stdenum.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 9k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //=--------------------------------------------------------------------------=
  2. // StandardEnum.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright  1995  Microsoft Corporation.  All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. // implementation of a generic enumerator object.
  13. //
  14. #include "priv.h"
  15. #include "stdenum.h"
  16. #define RETURN_ON_NULLALLOC(p) if ((p)==NULL) return E_OUTOFMEMORY
  17. // Used by creators of CStandardEnum
  18. //
  19. void WINAPI CopyAndAddRefObject
  20. (
  21.     void       *pDest,      // dest
  22.     const void *pSource,    // src
  23.     DWORD       dwSize      // size, ignored, since it's always 4
  24. )
  25. {
  26.     IUnknown *pUnk = *((IUnknown **)pSource);
  27.     *((IUnknown **)pDest) = pUnk;
  28.     pUnk->AddRef();
  29.     return;
  30. }
  31. //=--------------------------------------------------------------------------=
  32. // CStandardEnum::CStandardEnum
  33. //=--------------------------------------------------------------------------=
  34. // create the object and initialize the refcount
  35. //
  36. // Parameters:
  37. //    REFCLSID        - [in] type of enumerator that we are
  38. //    int             - [in] number of elements in the enumeration
  39. //    int             - [in] size of each element
  40. //    void *          - [in] pointer to element data
  41. //    void (WINAPI *pfnCopyElement)(void *, const void *, DWORD)
  42. //                    - [in] copying function
  43. //
  44. // Notes:
  45. //
  46. #pragma warning(disable:4355)  // using 'this' in constructor
  47. CStandardEnum::CStandardEnum
  48. (
  49.     REFCLSID rclsid,
  50.     BOOL fMembersAreInterfaces,
  51.     int      cElements,
  52.     int      cbElementSize,
  53.     void    *rgElements,
  54.     void (WINAPI *pfnCopyElement)(void *, const void *, DWORD)
  55. )
  56. : m_cRef(1),
  57.   m_iid(rclsid),
  58.   m_cElements(cElements),
  59.   m_cbElementSize(cbElementSize),
  60.   m_iCurrent(0),
  61.   m_rgElements(rgElements),
  62.   m_pfnCopyElement(pfnCopyElement),
  63.   m_fMembersAreInterfaces(fMembersAreInterfaces)
  64. {
  65.     m_pEnumClonedFrom = NULL;
  66.     if(m_fMembersAreInterfaces)
  67.     {
  68.         if(m_rgElements)
  69.         {
  70.             int i;
  71.             for(i=0; i<m_cElements; i++)
  72.             {
  73.                 LPUNKNOWN *ppunk = (IUnknown **)GetNthElement(i);
  74.                 (*ppunk)->AddRef();
  75.             }
  76.         }
  77.     }
  78. }
  79. #pragma warning(default:4355)  // using 'this' in constructor
  80. //=--------------------------------------------------------------------------=
  81. // CStandardEnum::CStandardEnum
  82. //=--------------------------------------------------------------------------=
  83. // "it is not death, but dying, which is terrible."
  84. //    - Henry Fielding (1707-54)
  85. //
  86. // Notes:
  87. //
  88. CStandardEnum::~CStandardEnum ()
  89. {
  90.     // if we're a cloned object, then just release our parent object and
  91.     // we're done. otherwise, free up the allocated memory we were given
  92.     //
  93.     if (m_pEnumClonedFrom)
  94.     {
  95.         m_pEnumClonedFrom->Release();
  96.     }
  97.     else
  98.     {
  99.         if (m_rgElements)
  100.         {
  101.             if(m_fMembersAreInterfaces)
  102.             {
  103.                 int i;
  104.                 for(i=0; i<m_cElements; i++)
  105.                 {
  106.                     LPUNKNOWN *ppunk = (IUnknown **)GetNthElement(i);
  107.                     (*ppunk)->Release();
  108.                 }
  109.             }
  110.             GlobalFree(m_rgElements);
  111.         }
  112.     }
  113. }
  114. //=--------------------------------------------------------------------------=
  115. // CStandardEnum::InternalQueryInterface
  116. //=--------------------------------------------------------------------------=
  117. // we support our internal iid, and that's all
  118. //
  119. // Parameters:
  120. //    REFIID        - [in]  interface they want
  121. //    void **       - [out] where they want to put the resulting object ptr.
  122. //
  123. // Output:
  124. //    HRESULT       - S_OK, E_NOINTERFACE
  125. //
  126. // Notes:
  127. //
  128. HRESULT CStandardEnum::QueryInterface
  129. (
  130.     REFIID riid,
  131.     void **ppvObjOut
  132. )
  133. {
  134.     *ppvObjOut = NULL;
  135.     if (IsEqualIID(riid, m_iid))
  136.     {
  137.         *ppvObjOut = (IEnumGeneric *)this;
  138.     }
  139.     else if (IsEqualIID(riid, IID_IUnknown))
  140.     {
  141.         *ppvObjOut = (IUnknown *)this;
  142.     }
  143.     if (*ppvObjOut)
  144.     {
  145.         AddRef();
  146.         return S_OK;
  147.     }
  148.     else
  149.     {
  150.         return E_NOINTERFACE;
  151.     }
  152. }
  153. ULONG CStandardEnum::AddRef(void)
  154. {
  155.     return ++m_cRef;
  156. }
  157. ULONG CStandardEnum::Release(void)
  158. {
  159.     int n = --m_cRef;
  160.     if (n == 0)
  161.         delete this;
  162.     return(n);
  163. }
  164. //=--------------------------------------------------------------------------=
  165. // CStandardEnum::Next
  166. //=--------------------------------------------------------------------------=
  167. // returns the next dude in our iteration
  168. //
  169. // Parameters:
  170. //    unsigned long     - [in]  count of elements requested
  171. //    void    *         - [out] array of slots to put values in.
  172. //    unsigned long *   - [out] actual number fetched
  173. //
  174. // Output:
  175. //    HRESULT           - S_OK, E_INVALIDARG, S_FALSE
  176. //
  177. // Notes:
  178. //
  179. STDMETHODIMP CStandardEnum::Next
  180. (
  181.     unsigned long  cElm,
  182.     void          *rgDest,
  183.     unsigned long *pcElmOut
  184. )
  185. {
  186.     unsigned long cElementsFetched = 0;
  187.     void         *pElementDest = rgDest;
  188.     const void   *pElementSrc = GetNthElement(m_iCurrent);
  189.     while (cElementsFetched < cElm) {
  190.         // if we hit EOF, break out
  191.         //
  192.         if (m_iCurrent >= m_cElements)
  193.             break;
  194.         // copy the element out for them
  195.         //
  196.         m_pfnCopyElement(pElementDest, pElementSrc, m_cbElementSize);
  197.         // increase the counters
  198.         //
  199.         pElementDest = (LPBYTE)pElementDest + m_cbElementSize;
  200.         pElementSrc  = (const BYTE *)pElementSrc + m_cbElementSize;
  201.         m_iCurrent++;
  202.         cElementsFetched++;
  203.     }
  204.     if (pcElmOut)
  205.         *pcElmOut = cElementsFetched;
  206.     return (cElementsFetched < cElm)? S_FALSE : S_OK;
  207. }
  208. //=--------------------------------------------------------------------------=
  209. // CStandardEnum::Skip
  210. //=--------------------------------------------------------------------------=
  211. // skips the requested number of rows.
  212. //
  213. // Parameters:
  214. //    unsigned long     - [in] number to skip
  215. //
  216. // Output:
  217. //    HRESULT           - S_OK, S_FALSE
  218. //
  219. // Notes:
  220. //
  221. STDMETHODIMP CStandardEnum::Skip
  222. (
  223.     unsigned long cSkip
  224. )
  225. {
  226.     // handle running off the end
  227.     //
  228.     if (m_iCurrent + (int)cSkip > m_cElements) {
  229.         m_iCurrent = m_cElements;
  230.         return S_FALSE;
  231.     }
  232.     m_iCurrent += cSkip;
  233.     return S_OK;
  234. }
  235. //=--------------------------------------------------------------------------=
  236. // CStandardEnum::Reset
  237. //=--------------------------------------------------------------------------=
  238. // reset the counter.
  239. //
  240. // Output:
  241. //    HRESULT        - S_OK
  242. //
  243. // Notes:
  244. //
  245. STDMETHODIMP CStandardEnum::Reset
  246. (
  247.     void
  248. )
  249. {
  250.     m_iCurrent = 0;
  251.     return S_OK;
  252. }
  253. //=--------------------------------------------------------------------------=
  254. // CStandardEnum::Clone
  255. //=--------------------------------------------------------------------------=
  256. // clones the object and gives the new one the same position
  257. //
  258. // Parameters:
  259. //    IEnumVARIANT **    - [out] where to put the new object.
  260. //
  261. // Output;
  262. //    HRESULT            - S_OK, E_OUTOFMEMORY
  263. //
  264. // Notes:
  265. //
  266. STDMETHODIMP CStandardEnum::Clone
  267. (
  268.     IEnumGeneric **ppEnumClone
  269. )
  270. {
  271.     CStandardEnum *pNewEnum;
  272.     pNewEnum = new CStandardEnum(m_iid, m_fMembersAreInterfaces, m_cElements, 
  273.                                  m_cbElementSize, m_rgElements, m_pfnCopyElement);
  274.     RETURN_ON_NULLALLOC(pNewEnum);
  275.     // The clone has the same current position as we do
  276.     pNewEnum->m_iCurrent = m_iCurrent;
  277.     // hold on to who we were cloned from so m_rgElements stays alive, and we don't
  278.     // have to copy it.
  279.     //
  280.     pNewEnum->m_pEnumClonedFrom = this;
  281.     // AddRef() ourselves on their behalf.
  282.     //
  283.     AddRef();
  284.     return S_OK;
  285. }
  286. // Helper function for creating IConnectionPoint enumerators
  287. //
  288. HRESULT CreateInstance_IEnumConnectionPoints(LPENUMCONNECTIONPOINTS * ppEnum, DWORD count, ...)
  289. {
  290.     DWORD  countTemp;
  291.     IConnectionPoint **rgCPs;
  292.     if (NULL == ppEnum)
  293.         return E_POINTER;
  294.     ASSERT(count > 0);
  295.     // GlobalAlloc an array of connection points [since our standard enum
  296.     // assumes this and GlobalFree's it later]
  297.     //
  298.     rgCPs = (LPCONNECTIONPOINT*)GlobalAlloc(GPTR, SIZEOF(LPCONNECTIONPOINT) * count);
  299.     if (NULL == rgCPs)
  300.         return E_OUTOFMEMORY;
  301.     va_list ArgList;
  302.     va_start(ArgList, count);
  303.     IConnectionPoint **prgCPs = rgCPs;
  304.     countTemp = count;
  305.     while (countTemp)
  306.     {
  307.         IConnectionPoint *pArg = va_arg(ArgList, IConnectionPoint*);
  308.         *prgCPs = pArg;
  309.         prgCPs++;
  310.         countTemp--;
  311.     }
  312.     va_end(ArgList);
  313.     *ppEnum = (IEnumConnectionPoints *)(IEnumGeneric *) new CStandardEnum(IID_IEnumConnectionPoints,
  314.                                 TRUE, count, SIZEOF(LPCONNECTIONPOINT), (LPVOID)rgCPs,
  315.                                 CopyAndAddRefObject);
  316.     if (!*ppEnum)
  317.     {
  318.         GlobalFree(rgCPs);
  319.         return E_OUTOFMEMORY;
  320.     }
  321.     return S_OK;
  322. }