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

Windows Kernel

Development Platform:

Visual C++

  1. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  2. //
  3. // enum.cpp 
  4. //
  5. //   The enumerator object for the cdf viewer.
  6. //
  7. //   History:
  8. //
  9. //       3/16/97  edwardp   Created.
  10. //
  11. ////////////////////////////////////////////////////////////////////////////////
  12. //
  13. // Includes
  14. //
  15. #include "stdinc.h"
  16. #include "cdfidl.h"
  17. #include "xmlutil.h"
  18. #include "enum.h"
  19. #include "dll.h"
  20. //
  21. // Constructor and destructor.
  22. //
  23. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  24. //
  25. // *** CCdfEnum::CCdfView ***
  26. //
  27. //    Constructor.
  28. //
  29. ////////////////////////////////////////////////////////////////////////////////
  30. CCdfEnum::CCdfEnum (
  31.     IXMLElementCollection* pIXMLElementCollection,
  32.     DWORD fEnumerateFlags,
  33.     PCDFITEMIDLIST pcdfidlFolder
  34. )
  35. : m_cRef(1),
  36.   m_fEnumerate(fEnumerateFlags)
  37. {
  38.     //
  39.     // Zero inited memory.
  40.     //
  41.     ASSERT(NULL == m_pIXMLElementCollection);
  42.     ASSERT(0 == m_nCurrentItem);
  43.     if (pIXMLElementCollection)
  44.     {
  45.         pIXMLElementCollection->AddRef();
  46.         m_pIXMLElementCollection = pIXMLElementCollection;
  47.     }
  48.     m_pcdfidlFolder = (PCDFITEMIDLIST)ILClone((LPITEMIDLIST)pcdfidlFolder);
  49.     
  50.     //
  51.     // Don't allow the dll to be unloaded.
  52.     //
  53.     TraceMsg(TF_OBJECTS, "+ IEnumIDList");
  54.     DllAddRef();
  55. }
  56. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  57. //
  58. // *** CCdfView::~CCdfView **
  59. //
  60. //    Destructor.
  61. //
  62. ////////////////////////////////////////////////////////////////////////////////
  63. CCdfEnum::~CCdfEnum(
  64.     void
  65. )
  66. {
  67.     if (m_pIXMLElementCollection)
  68.         m_pIXMLElementCollection->Release();
  69.     TraceMsg(TF_OBJECTS, "- IEnumIDList");
  70.     if (m_pcdfidlFolder)
  71.         ILFree((LPITEMIDLIST)m_pcdfidlFolder);
  72.     DllRelease();
  73. }
  74. //
  75. // IUnknown methods.
  76. //
  77. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  78. //
  79. // *** CCdfView::CCdfEnum ***
  80. //
  81. //    Cdf view QI.
  82. //
  83. ////////////////////////////////////////////////////////////////////////////////
  84. STDMETHODIMP
  85. CCdfEnum::QueryInterface (
  86.     REFIID riid,
  87.     void **ppv
  88. )
  89. {
  90.     ASSERT(ppv);
  91.     HRESULT hr;
  92.     if (IID_IUnknown == riid || IID_IEnumIDList == riid)
  93.     {
  94.         AddRef();
  95.         *ppv = (IEnumIDList*)this;
  96.         hr = S_OK;
  97.     }
  98.     else
  99.     {
  100.         *ppv = NULL;
  101.         hr = E_NOINTERFACE;
  102.     }
  103.     ASSERT((SUCCEEDED(hr) && *ppv) || (FAILED(hr) && NULL == *ppv));
  104.     return hr;
  105. }
  106. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  107. //
  108. // *** CCdfEnum::AddRef ***
  109. //
  110. //    Cdf view AddRef.
  111. //
  112. ////////////////////////////////////////////////////////////////////////////////
  113. STDMETHODIMP_(ULONG)
  114. CCdfEnum::AddRef (
  115.     void
  116. )
  117. {
  118.     ASSERT(m_cRef != 0);
  119.     ASSERT(m_cRef < (ULONG)-1);
  120.     return ++m_cRef;
  121. }
  122. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  123. //
  124. // *** CCdfEnum::Release ***
  125. //
  126. //    Cdf view Release.
  127. //
  128. ////////////////////////////////////////////////////////////////////////////////
  129. STDMETHODIMP_(ULONG)
  130. CCdfEnum::Release (
  131.     void
  132. )
  133. {
  134.     ASSERT (m_cRef != 0);
  135.     ULONG cRef = --m_cRef;
  136.     
  137.     if (0 == cRef)
  138.         delete this;
  139.     return cRef;
  140. }
  141. //
  142. // IEnumIDList methods.
  143. //
  144. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  145. //
  146. // *** CCdfEnum::Next ***
  147. //
  148. //
  149. // Description:
  150. //     Returns the next n item id lists associated with this enumerator.
  151. //
  152. // Parameters:
  153. //     [in]  celt         - Number of item id lists to return.
  154. //     [Out] rgelt        - A pointer to an array of item id list pointers that
  155. //                          will receive the id item lists.
  156. //     [Out] pceltFetched - A pointer to a ULONG that receives a count of the
  157. //                          number of id lists fetched.
  158. //
  159. // Return:
  160. //     S_OK if celt items where fetched.
  161. //     S_FALSE if celt items where not fetched.
  162. //
  163. // Comments:
  164. //     
  165. //
  166. ////////////////////////////////////////////////////////////////////////////////
  167. STDMETHODIMP
  168. CCdfEnum::Next(
  169.     ULONG celt,
  170.     LPITEMIDLIST *rgelt,
  171.     ULONG* pceltFetched)
  172. {
  173.     ASSERT(rgelt || 0 == celt);
  174.     ASSERT(pceltFetched || 1 == celt);
  175.     //
  176.     // pceltFetched can be NULL if and only if celt is 1.
  177.     //
  178.     ULONG lFetched;
  179.     if (1 == celt && NULL == pceltFetched)
  180.         pceltFetched = &lFetched;
  181.     for (*pceltFetched = 0; *pceltFetched < celt; (*pceltFetched)++)
  182.     {
  183.         if (NULL == (rgelt[*pceltFetched] = NextCdfidl()))
  184.             break;
  185.         ASSERT(CDFIDL_IsValid((PCDFITEMIDLIST)rgelt[*pceltFetched]));
  186.     }
  187.     return (*pceltFetched == celt) ? S_OK : S_FALSE;
  188. }
  189. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  190. //
  191. // *** CCdfEnum::Skip ***
  192. //
  193. //   Shell doesn't call this member.
  194. //
  195. ////////////////////////////////////////////////////////////////////////////////
  196. STDMETHODIMP
  197. CCdfEnum::Skip(
  198.     ULONG celt)
  199. {
  200.     return E_NOTIMPL;
  201. }
  202. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  203. //
  204. // *** CCdfEnum::Reset ***
  205. //
  206. //   Set the current item to the index of the first item in CFolderItems.
  207. //
  208. ////////////////////////////////////////////////////////////////////////////////
  209. STDMETHODIMP
  210. CCdfEnum::Reset(
  211.     void
  212. )
  213. {
  214.     m_nCurrentItem = 0;
  215.     m_fReturnedFolderPidl = FALSE;
  216.     return S_OK;
  217. }
  218. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  219. //
  220. // *** CCdfEnum::Clone ***
  221. //
  222. //   Shell doesn't call this method.
  223. //
  224. ////////////////////////////////////////////////////////////////////////////////
  225. STDMETHODIMP
  226. CCdfEnum::Clone(
  227.     IEnumIDList **ppenum
  228. )
  229. {
  230.     return E_NOTIMPL;
  231. }
  232. //
  233. // Helper functions.
  234. //
  235. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  236. //
  237. // *** CCdfEnum::NextCdfidl ***
  238. //
  239. //
  240. // Description:
  241. //     Returns a cdf item idl list for the next cdf item in the collection
  242. //
  243. // Parameters:
  244. //     None.
  245. //
  246. // Return:
  247. //     A pointer to a new cdf item id list.
  248. //     NULL if there aren't any more items or if there isn't enough memory to
  249. //     allocated an id list for the item.
  250. //
  251. // Comments:
  252. //     The caller is responsible for freeing the returned item id list.
  253. //
  254. ////////////////////////////////////////////////////////////////////////////////
  255. LPITEMIDLIST
  256. CCdfEnum::NextCdfidl(
  257.     void
  258. )
  259. {
  260.     PCDFITEMIDLIST pcdfidlNew = NULL;
  261.     IXMLElement* pIXMLElement;
  262.     ULONG        nIndex;
  263.     //the first item in the enum is the folder's link (if it has one)
  264.     if (!m_fReturnedFolderPidl && m_pIXMLElementCollection)
  265.     {
  266.         IXMLElement *pIXMLElementChild;
  267.         XML_GetElementByIndex(m_pIXMLElementCollection, 0, &pIXMLElementChild);
  268.         if (pIXMLElementChild)
  269.         {
  270.             pIXMLElementChild->get_parent(&pIXMLElement);
  271.             if (pIXMLElement)
  272.             {
  273.                 BSTR bstr = XML_GetAttribute(pIXMLElement, XML_HREF);
  274.                 if (bstr)
  275.                 {
  276.                     if (*bstr)
  277.                         pcdfidlNew = CDFIDL_CreateFolderPidl(m_pcdfidlFolder);
  278.                     SysFreeString(bstr);
  279.                 }
  280.                 
  281.                 //get_parent doesn't addref???
  282.                 pIXMLElement->Release();
  283.             }
  284.             pIXMLElementChild->Release();
  285.         }
  286.         m_fReturnedFolderPidl = TRUE;
  287.     }
  288.     if (!pcdfidlNew)
  289.     {
  290.         HRESULT hr = GetNextCdfElement(&pIXMLElement, &nIndex);
  291.         if (SUCCEEDED(hr))
  292.         {
  293.             ASSERT(pIXMLElement);
  294.             pcdfidlNew = CDFIDL_CreateFromXMLElement(pIXMLElement, nIndex);
  295.             pIXMLElement->Release();
  296.         }
  297.     }
  298.     
  299.     ASSERT(CDFIDL_IsValid(pcdfidlNew) || NULL == pcdfidlNew);
  300.     return (LPITEMIDLIST)pcdfidlNew;
  301. }
  302. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  303. //
  304. // *** CCdfEnum::GetNextCdfElement ***
  305. //
  306. //
  307. // Description:
  308. //     Get the IXMLElement pointer and index for the next cdf item in the
  309. //     collection.
  310. //
  311. // Parameters:
  312. //     [Out] ppIXMLElement - A pointer that recieves the xml element.
  313. //     [Out] pnIndex       - The object model index of the xml element.
  314. //
  315. // Return:
  316. //     S_OK if the element was found.
  317. //     E_FAIL otherwise.
  318. //
  319. // Comments:
  320. //
  321. //
  322. ////////////////////////////////////////////////////////////////////////////////
  323. HRESULT
  324. CCdfEnum::GetNextCdfElement(
  325.     IXMLElement** ppIXMLElement,
  326.     ULONG* pnIndex
  327. )
  328. {
  329.     ASSERT(ppIXMLElement);
  330.     HRESULT hr;
  331.     if (m_pIXMLElementCollection)
  332.     {
  333.         IXMLElement* pIXMLElement;
  334.         hr = XML_GetElementByIndex(m_pIXMLElementCollection,
  335.                                    m_nCurrentItem++, &pIXMLElement);
  336.         if (SUCCEEDED(hr))
  337.         {
  338.             ASSERT(pIXMLElement)
  339.             if (IsCorrectType(pIXMLElement))
  340.             {
  341.                 pIXMLElement->AddRef();
  342.                 *ppIXMLElement = pIXMLElement;
  343.                 *pnIndex = m_nCurrentItem - 1;
  344.             }
  345.             else
  346.             {
  347.                 hr = GetNextCdfElement(ppIXMLElement, pnIndex);
  348.             }
  349.             pIXMLElement->Release();
  350.         }
  351.     }
  352.     else
  353.     {
  354.         hr = E_FAIL;
  355.     }
  356.     ASSERT(SUCCEEDED(hr) && *ppIXMLElement || FAILED(hr));
  357.     return hr;
  358. }
  359. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  360. //
  361. // *** CCdfEnum::IsCorrectType ***
  362. //
  363. //
  364. // Description:
  365. //     Determines if the given xml element is a cdf element and if it should
  366. //     be returned accroding to the folder non-folder enumrator flags.
  367. //
  368. // Parameters:
  369. //     [In]  pIXMLElement - The xml element to check.
  370. //
  371. // Return:
  372. //     TRUE if the lement is cdf displayable and the correct type for this
  373. //     enumerator.
  374. //     FALSE if the given element should not be enumerated.
  375. //
  376. // Comments:
  377. //     Id list enumerators are created with a combination of SHCONTF_FOLDERS,
  378. //     SHCONTF_NONFOLDERS and SHCONTF_INCLUDEHIDDEN flags.
  379. //
  380. ////////////////////////////////////////////////////////////////////////////////
  381. inline BOOL
  382. CCdfEnum::IsCorrectType(
  383.     IXMLElement* pIXMLElement
  384. )
  385. {
  386.     return (XML_IsCdfDisplayable(pIXMLElement) &&
  387.             (XML_IsFolder(pIXMLElement) ? (m_fEnumerate & SHCONTF_FOLDERS) :
  388.                                           (m_fEnumerate & SHCONTF_NONFOLDERS)));
  389. }