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.

393 lines
9.2 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: I E N U M I D L . C P P
  7. //
  8. // Contents: IEnumIDList implementation for CUPnPDeviceFolderEnum
  9. //
  10. // Notes:
  11. //
  12. // Author: jeffspr 07 Sep 1999
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "tfind.h"
  18. #include "upscmn.h" // UPNP Shell common fns
  19. //+---------------------------------------------------------------------------
  20. //
  21. // Member: CUPnPDeviceFolderEnum::CUPnPDeviceFolderEnum
  22. //
  23. // Purpose: Constructor for the enumerator
  24. //
  25. // Arguments:
  26. // (none)
  27. //
  28. // Returns:
  29. //
  30. // Author: jeffspr 18 Mar 1998
  31. //
  32. // Notes:
  33. //
  34. CUPnPDeviceFolderEnum::CUPnPDeviceFolderEnum()
  35. {
  36. m_cDevices = 0;
  37. m_pidlFolder = NULL;
  38. m_dwFlags = 0;
  39. m_fFirstEnumeration = TRUE;
  40. m_psf = NULL;
  41. }
  42. //+---------------------------------------------------------------------------
  43. //
  44. // Function: CUPnPDeviceFolderEnum
  45. //
  46. // Purpose: Destructor for the enumerator. Standard cleanup.
  47. //
  48. // Arguments:
  49. // (none)
  50. //
  51. // Returns:
  52. //
  53. // Author: jeffspr 18 Mar 1998
  54. //
  55. // Notes:
  56. //
  57. CUPnPDeviceFolderEnum::~CUPnPDeviceFolderEnum()
  58. {
  59. if (m_pidlFolder)
  60. FreeIDL(m_pidlFolder);
  61. m_psf->Release();
  62. }
  63. //+---------------------------------------------------------------------------
  64. //
  65. // Function: CUPnPDeviceFolderEnum::Initialize
  66. //
  67. // Purpose: Initialization for the enumerator object
  68. //
  69. // Arguments:
  70. // pidlFolder [in] Pidl for the folder itself
  71. // psf [in] pointer to our folder object
  72. //
  73. // Returns:
  74. //
  75. // Author: jeffspr 18 Mar 1998
  76. //
  77. // Notes:
  78. //
  79. VOID CUPnPDeviceFolderEnum::Initialize(
  80. LPITEMIDLIST pidlFolder,
  81. CUPnPDeviceFolder * psf)
  82. {
  83. m_pidlFolder = (pidlFolder) ? CloneIDL (pidlFolder) : NULL;
  84. m_psf = psf;
  85. m_psf->AddRef();
  86. (VOID)HrStartSearch();
  87. }
  88. //+---------------------------------------------------------------------------
  89. //
  90. // Member: CUPnPDeviceFolderEnum::CreateInstance
  91. //
  92. // Purpose: Create an instance of the CUPnPDeviceFolderEnum object, and
  93. // returns the requested interface
  94. //
  95. // Arguments:
  96. // riid [in] Interface requested
  97. // ppv [out] Pointer to receive the requested interface
  98. //
  99. // Returns: Standard OLE HRESULT
  100. //
  101. // Author: jeffspr 5 Nov 1997
  102. //
  103. // Notes:
  104. //
  105. HRESULT CUPnPDeviceFolderEnum::CreateInstance(
  106. REFIID riid,
  107. void** ppv)
  108. {
  109. HRESULT hr = E_OUTOFMEMORY;
  110. CUPnPDeviceFolderEnum * pObj = NULL;
  111. TraceTag(ttidShellFolderIface, "OBJ: CCFE - IEnumIDList::CreateInstance");
  112. pObj = new CComObject <CUPnPDeviceFolderEnum>;
  113. if (pObj)
  114. {
  115. // Do the standard CComCreator::CreateInstance stuff.
  116. //
  117. pObj->SetVoid (NULL);
  118. pObj->InternalFinalConstructAddRef ();
  119. hr = pObj->FinalConstruct ();
  120. pObj->InternalFinalConstructRelease ();
  121. if (SUCCEEDED(hr))
  122. {
  123. hr = pObj->QueryInterface (riid, ppv);
  124. }
  125. if (FAILED(hr))
  126. {
  127. delete pObj;
  128. }
  129. }
  130. TraceHr(ttidError, FAL, hr, FALSE, "CUPnPDeviceFolderEnum::CreateInstance");
  131. return hr;
  132. }
  133. //+---------------------------------------------------------------------------
  134. //
  135. // Member: CUPnPDeviceFolderEnum::Next
  136. //
  137. // Purpose: Retrieves the specified number of item identifiers in the
  138. // enumeration sequence and advances the current position
  139. // by the number of items retrieved.
  140. //
  141. // Arguments:
  142. // celt [] Max number requested
  143. // rgelt [] Array to fill
  144. // pceltFetched [] Return count for # filled.
  145. //
  146. // Returns: S_OK if successful, S_FALSE if there are no more items
  147. // in the enumeration sequence, or an OLE-defined error value
  148. // otherwise.
  149. //
  150. // Author: jeffspr 5 Nov 1997
  151. //
  152. // Notes:
  153. //
  154. STDMETHODIMP CUPnPDeviceFolderEnum::Next(
  155. ULONG celt,
  156. LPITEMIDLIST * rgelt,
  157. ULONG * pceltFetched)
  158. {
  159. HRESULT hr = S_OK;
  160. TraceTag(ttidShellFolderIface, "OBJ: CCFE - IEnumIDList::Next");
  161. Assert(celt >= 1);
  162. Assert(rgelt);
  163. Assert(pceltFetched || (celt == 1));
  164. // If the caller asks for the fetch count, zero it out for now.
  165. //
  166. if (pceltFetched)
  167. {
  168. *pceltFetched = 0;
  169. }
  170. // Init the output list pointer
  171. //
  172. *rgelt = NULL;
  173. BOOL fExist = TRUE;
  174. ULONG celtFetched = 0;
  175. FolderDeviceNode * pCurrentNode;
  176. LPITEMIDLIST pidl;
  177. // build a list of devices currently in our folder list
  178. if (m_fFirstEnumeration)
  179. {
  180. BuildCurrentDeviceList();
  181. // get the first node
  182. fExist = m_CListDevices.FFirst(&pCurrentNode);
  183. if (fExist)
  184. {
  185. hr = m_psf->HrMakeUPnPDevicePidl(pCurrentNode, &pidl);
  186. if (SUCCEEDED(hr))
  187. {
  188. rgelt[celtFetched] = pidl;
  189. celtFetched++;
  190. }
  191. }
  192. m_fFirstEnumeration = FALSE;
  193. }
  194. while ((celtFetched < celt) && fExist)
  195. {
  196. // move to the next node
  197. fExist = m_CListDevices.FNext(&pCurrentNode);
  198. if (fExist)
  199. {
  200. hr = m_psf->HrMakeUPnPDevicePidl(pCurrentNode, &pidl);
  201. if (SUCCEEDED(hr))
  202. {
  203. rgelt[celtFetched] = pidl;
  204. celtFetched++;
  205. }
  206. else
  207. {
  208. break;
  209. }
  210. }
  211. }
  212. if (pceltFetched)
  213. {
  214. *pceltFetched = celtFetched;
  215. }
  216. if ((hr == S_OK) &&
  217. ((celtFetched == 0) || (celtFetched < celt)))
  218. {
  219. // done enumerating existing elements
  220. hr = S_FALSE;
  221. }
  222. TraceHr(ttidError, FAL, hr, (S_FALSE == hr), "CUPnPDeviceFolderEnum::Next");
  223. return hr;
  224. }
  225. //+---------------------------------------------------------------------------
  226. //
  227. // Member: CUPnPDeviceFolderEnum::Skip
  228. //
  229. // Purpose: Skips over the specified number of elements in the
  230. // enumeration sequence.
  231. //
  232. // Arguments:
  233. // celt [in] Number of item identifiers to skip.
  234. //
  235. // Returns: Returns S_OK if successful, or an OLE-defined error
  236. // value otherwise.
  237. //
  238. // Author: jeffspr 5 Nov 1997
  239. //
  240. // Notes:
  241. //
  242. STDMETHODIMP CUPnPDeviceFolderEnum::Skip(
  243. ULONG celt)
  244. {
  245. HRESULT hr = S_OK;
  246. TraceTag(ttidShellFolderIface, "OBJ: CCFE - IEnumIDList::Skip");
  247. NYI("CUPnPDeviceFolderEnum::Skip");
  248. // Currently, do nothing
  249. //
  250. TraceHr(ttidError, FAL, hr, FALSE, "CUPnPDeviceFolderEnum::Skip");
  251. return S_OK;
  252. }
  253. //+---------------------------------------------------------------------------
  254. //
  255. // Member: CUPnPDeviceFolderEnum::Reset
  256. //
  257. // Purpose: Returns to the beginning of the enumeration sequence. For us,
  258. // this means do all of the actual enumeration
  259. //
  260. // Arguments:
  261. // (none)
  262. //
  263. // Returns: Returns S_OK if successful, or an OLE-defined error
  264. // value otherwise.
  265. //
  266. // Author: jeffspr 5 Nov 1997
  267. //
  268. // Notes:
  269. //
  270. STDMETHODIMP CUPnPDeviceFolderEnum::Reset()
  271. {
  272. HRESULT hr = S_OK;
  273. TraceTag(ttidShellFolderIface, "OBJ: CCFE - IEnumIDList::Reset");
  274. // per RaymondC: I don't think the shell calls Reset.
  275. // It just creates a new enumerator.
  276. TraceHr(ttidError, FAL, hr, FALSE, "CUPnPDeviceFolderEnum::Reset");
  277. return hr;
  278. }
  279. //+---------------------------------------------------------------------------
  280. //
  281. // Member: CUPnPDeviceFolderEnum::Clone
  282. //
  283. // Purpose: Creates a new item enumeration object with the same contents
  284. // and state as the current one.
  285. //
  286. // Arguments:
  287. // ppenum [out] Return a clone of the current internal PIDL
  288. //
  289. // Returns: Returns S_OK if successful, or an OLE-defined error
  290. // value otherwise.
  291. //
  292. // Author: jeffspr 5 Nov 1997
  293. //
  294. // Notes:
  295. //
  296. STDMETHODIMP CUPnPDeviceFolderEnum::Clone(
  297. IEnumIDList ** ppenum)
  298. {
  299. NYI("CUPnPDeviceFolderEnum::Clone");
  300. TraceTag(ttidShellFolderIface, "OBJ: CCFE - IEnumIDList::Clone");
  301. *ppenum = NULL;
  302. return E_NOTIMPL;
  303. }
  304. //+---------------------------------------------------------------------------
  305. //
  306. // Member: CUPnPDeviceFolderEnum::BuildCurrentDeviceList
  307. //
  308. // Purpose: Walk through the global list of discovered devices
  309. // and create an internal list for enumeration
  310. //
  311. // Arguments:
  312. //
  313. // Returns:
  314. //
  315. // Author: tongl 18 Feb 2000
  316. //
  317. // Notes:
  318. //
  319. VOID CUPnPDeviceFolderEnum::BuildCurrentDeviceList()
  320. {
  321. // The list should not be there yet as this is the first enumeration
  322. Assert(!m_cDevices);
  323. EnterCriticalSection(&g_csFolderDeviceList);
  324. FolderDeviceNode * pCurrentNode = NULL;
  325. BOOL fReturn = g_CListFolderDeviceNode.FFirst(&pCurrentNode);
  326. while (fReturn)
  327. {
  328. if (!pCurrentNode->fDeleted)
  329. {
  330. m_CListDevices.FAdd(pCurrentNode);
  331. m_cDevices++;
  332. }
  333. // move to the next node
  334. fReturn = g_CListFolderDeviceNode.FNext(&pCurrentNode);
  335. }
  336. LeaveCriticalSection(&g_csFolderDeviceList);
  337. }