Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

449 lines
10 KiB

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