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.

494 lines
13 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 CConnectionFolderEnum
  9. //
  10. // Notes:
  11. //
  12. // Author: jeffspr 22 Sep 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "foldinc.h" // Standard shell\folder includes
  18. #include "ncnetcon.h"
  19. #include "webview.h"
  20. //+---------------------------------------------------------------------------
  21. //
  22. // Member: CConnectionFolderEnum::CConnectionFolderEnum
  23. //
  24. // Purpose: Constructor for the enumerator
  25. //
  26. // Arguments:
  27. // (none)
  28. //
  29. // Returns:
  30. //
  31. // Author: jeffspr 18 Mar 1998
  32. //
  33. // Notes:
  34. //
  35. CConnectionFolderEnum::CConnectionFolderEnum()
  36. {
  37. TraceFileFunc(ttidShellFolderIface);
  38. m_pidlFolder.Clear();
  39. m_dwFlags = 0;
  40. m_fTray = FALSE;
  41. m_dwEnumerationType = CFCOPT_ENUMALL; // all connection types
  42. }
  43. //+---------------------------------------------------------------------------
  44. //
  45. // Function: CConnectionFolderEnum
  46. //
  47. // Purpose: Destructor for the enumerator. Standard cleanup.
  48. //
  49. // Arguments:
  50. // (none)
  51. //
  52. // Returns:
  53. //
  54. // Author: jeffspr 18 Mar 1998
  55. //
  56. // Notes:
  57. //
  58. CConnectionFolderEnum::~CConnectionFolderEnum()
  59. {
  60. TraceFileFunc(ttidShellFolderIface);
  61. m_pidlFolder.Clear();
  62. }
  63. //+---------------------------------------------------------------------------
  64. //
  65. // Function: CConnectionFolderEnum::PidlInitialize
  66. //
  67. // Purpose: Initialization for the enumerator object
  68. //
  69. // Arguments:
  70. // fTray [in] Are we owned by the tray
  71. // pidlFolder [in] Pidl for the folder itself
  72. // dwEnumerationType [in] Enumeration type (inbound/outbound/all)
  73. //
  74. // Returns:
  75. //
  76. // Author: jeffspr 18 Mar 1998
  77. //
  78. // Notes:
  79. //
  80. VOID CConnectionFolderEnum::PidlInitialize(
  81. BOOL fTray,
  82. const PCONFOLDPIDLFOLDER& pidlFolder,
  83. DWORD dwEnumerationType)
  84. {
  85. TraceFileFunc(ttidShellFolderIface);
  86. NETCFG_TRY
  87. m_fTray = fTray;
  88. m_pidlFolder = pidlFolder;
  89. m_dwEnumerationType = dwEnumerationType;
  90. NETCFG_CATCH_AND_RETHROW
  91. }
  92. //+---------------------------------------------------------------------------
  93. //
  94. // Member: CConnectionFolderEnum::CreateInstance
  95. //
  96. // Purpose: Create an instance of the CConnectionFolderEnum object, and
  97. // returns the requested interface
  98. //
  99. // Arguments:
  100. // riid [in] Interface requested
  101. // ppv [out] Pointer to receive the requested interface
  102. //
  103. // Returns: Standard OLE HRESULT
  104. //
  105. // Author: jeffspr 5 Nov 1997
  106. //
  107. // Notes:
  108. //
  109. HRESULT CConnectionFolderEnum::CreateInstance(
  110. REFIID riid,
  111. void** ppv)
  112. {
  113. TraceFileFunc(ttidShellFolderIface);
  114. HRESULT hr = E_OUTOFMEMORY;
  115. CConnectionFolderEnum * pObj = NULL;
  116. pObj = new CComObject <CConnectionFolderEnum>;
  117. if (pObj)
  118. {
  119. // Do the standard CComCreator::CreateInstance stuff.
  120. //
  121. pObj->SetVoid (NULL);
  122. pObj->InternalFinalConstructAddRef ();
  123. hr = pObj->FinalConstruct ();
  124. pObj->InternalFinalConstructRelease ();
  125. if (SUCCEEDED(hr))
  126. {
  127. hr = pObj->QueryInterface (riid, ppv);
  128. }
  129. if (FAILED(hr))
  130. {
  131. delete pObj;
  132. }
  133. }
  134. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionFolderEnum::CreateInstance");
  135. return hr;
  136. }
  137. //+---------------------------------------------------------------------------
  138. //
  139. // Member: CConnectionFolderEnum::Next
  140. //
  141. // Purpose: Retrieves the specified number of item identifiers in the
  142. // enumeration sequence and advances the current position
  143. // by the number of items retrieved.
  144. //
  145. // Arguments:
  146. // celt [] Max number requested
  147. // rgelt [] Array to fill
  148. // pceltFetched [] Return count for # filled.
  149. //
  150. // Returns: S_OK if successful, S_FALSE if there are no more items
  151. // in the enumeration sequence, or an OLE-defined error value
  152. // otherwise.
  153. //
  154. // Author: jeffspr 5 Nov 1997
  155. //
  156. // Notes:
  157. //
  158. STDMETHODIMP CConnectionFolderEnum::Next(
  159. ULONG celt,
  160. LPITEMIDLIST * rgelt,
  161. ULONG * pceltFetched)
  162. {
  163. TraceFileFunc(ttidShellFolderIface);
  164. HRESULT hr = S_OK;
  165. Assert(celt >= 1);
  166. Assert(rgelt);
  167. Assert(pceltFetched || (celt == 1));
  168. // If the caller asks for the fetch count, zero it out for now.
  169. //
  170. if (pceltFetched)
  171. {
  172. *pceltFetched = 0;
  173. }
  174. // Init the output list pointer
  175. //
  176. *rgelt = NULL;
  177. // If there's not currently a list, build one.
  178. //
  179. if (m_apidl.empty())
  180. {
  181. hr = Reset();
  182. // This will have returned either S_FALSE (no wizard? weird!), an
  183. // error (meaning creating the wizard failed), or S_OK, meaning
  184. // that (at least) the wizard creation succeeded. Enum of the connections
  185. // failing will get filtered by Reset().
  186. }
  187. if (SUCCEEDED(hr))
  188. {
  189. // If there are NOW items in the list
  190. //
  191. if (!m_apidl.empty() )
  192. {
  193. BOOL fMatchFound = FALSE;
  194. // Check that we've set the current pointer to at least the root
  195. //
  196. // Normalize the return code
  197. hr = S_OK;
  198. while ((S_OK == hr) && !fMatchFound)
  199. {
  200. // If there are no remaining entries, return S_FALSE.
  201. //
  202. if ( m_iterPidlCurrent == m_apidl.end() )
  203. {
  204. hr = S_FALSE;
  205. }
  206. else
  207. {
  208. const PCONFOLDPIDL& pcfp = *m_iterPidlCurrent;
  209. // Else, Return the first entry, then increment the current
  210. // pointer
  211. //
  212. Assert(!pcfp.empty());
  213. // Check to see if we want to return this type, based on
  214. // the enumeration type & connection type. The wizard
  215. // should always be included.
  216. //
  217. if ( WIZARD_NOT_WIZARD != pcfp->wizWizard )
  218. {
  219. if (HrIsWebViewEnabled() == S_OK)
  220. {
  221. m_iterPidlCurrent++; // skip over this item
  222. continue;
  223. }
  224. else
  225. {
  226. fMatchFound = TRUE;
  227. }
  228. }
  229. else
  230. {
  231. switch(m_dwEnumerationType)
  232. {
  233. case CFCOPT_ENUMALL:
  234. fMatchFound = TRUE;
  235. break;
  236. case CFCOPT_ENUMINCOMING:
  237. fMatchFound = (pcfp->dwCharacteristics & NCCF_INCOMING_ONLY);
  238. break;
  239. case CFCOPT_ENUMOUTGOING:
  240. fMatchFound = !(pcfp->dwCharacteristics & NCCF_INCOMING_ONLY);
  241. break;
  242. }
  243. }
  244. // If we've found one that needn't be filtered out,
  245. // then fill in the return param, etc.
  246. //
  247. if (fMatchFound)
  248. {
  249. // Copy the pidl for return
  250. //
  251. rgelt[0] = m_iterPidlCurrent->TearOffItemIdList();
  252. if (!rgelt[0])
  253. {
  254. hr = E_OUTOFMEMORY;
  255. }
  256. else
  257. {
  258. // If they requested a return count, fill it in.
  259. //
  260. if (pceltFetched)
  261. {
  262. *pceltFetched = 1;
  263. }
  264. // ISSUE:
  265. // IsValidPIDL is debug code. However, we're doing this in release mode until we
  266. // find the bug from NTRAID#NTBUG9-125787-2000/07/26-deonb.
  267. #ifdef DBG_VALIDATE_PIDLS
  268. if (!IsValidPIDL(rgelt[0]))
  269. {
  270. return E_ABORT;
  271. }
  272. #endif
  273. }
  274. }
  275. // Move the pointer to the next pidl in the list.
  276. //
  277. m_iterPidlCurrent++;
  278. }
  279. }
  280. }
  281. else
  282. {
  283. // There are no items in the list, return S_FALSE
  284. //
  285. hr = S_FALSE;
  286. }
  287. }
  288. #ifdef DBG
  289. if (pceltFetched)
  290. {
  291. TraceTag(ttidShellFolderIface, "IEnumIDList::Next generated PIDL: 0x%08x", rgelt[0]);
  292. }
  293. #endif
  294. TraceHr(ttidError, FAL, hr, (S_FALSE == hr), "CConnectionFolderEnum::Next");
  295. return hr;
  296. }
  297. //+---------------------------------------------------------------------------
  298. //
  299. // Member: CConnectionFolderEnum::Skip
  300. //
  301. // Purpose: Skips over the specified number of elements in the
  302. // enumeration sequence.
  303. //
  304. // Arguments:
  305. // celt [in] Number of item identifiers to skip.
  306. //
  307. // Returns: Returns S_OK if successful, or an OLE-defined error
  308. // value otherwise.
  309. //
  310. // Author: jeffspr 5 Nov 1997
  311. //
  312. // Notes:
  313. //
  314. STDMETHODIMP CConnectionFolderEnum::Skip(
  315. ULONG celt)
  316. {
  317. TraceFileFunc(ttidShellFolderIface);
  318. HRESULT hr = S_OK;
  319. NYI("CConnectionFolderEnum::Skip");
  320. // Currently, do nothing
  321. //
  322. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionFolderEnum::Skip");
  323. return S_OK;
  324. }
  325. //+---------------------------------------------------------------------------
  326. //
  327. // Member: CConnectionFolderEnum::Reset
  328. //
  329. // Purpose: Returns to the beginning of the enumeration sequence. For us,
  330. // this means do all of the actual enumeration
  331. //
  332. // Arguments:
  333. // (none)
  334. //
  335. // Returns: Returns S_OK if successful, or an OLE-defined error
  336. // value otherwise.
  337. //
  338. // Author: jeffspr 5 Nov 1997
  339. //
  340. // Notes:
  341. //
  342. STDMETHODIMP CConnectionFolderEnum::Reset()
  343. {
  344. TraceFileFunc(ttidShellFolderIface);
  345. HRESULT hr = S_OK;
  346. // If there's already a list, free it and rebuild.
  347. //
  348. if (!m_apidl.empty())
  349. {
  350. m_apidl.clear();
  351. m_iterPidlCurrent = m_apidl.end();
  352. }
  353. // Yes, I know that the code below looks strange, as both cases do the same thing,
  354. // but it makes it a bit easier to debug, and it makes the comments more obvious.
  355. //
  356. hr = HrRetrieveConManEntries();
  357. if (SUCCEEDED(hr))
  358. {
  359. // Normalize the return code. HrRetrieveConManEntries... may have returned
  360. // S_FALSE, meaning that there we no connections (fine).
  361. //
  362. hr = S_OK;
  363. m_iterPidlCurrent = m_apidl.begin();
  364. }
  365. else
  366. {
  367. // Actually, we're still going to return noerror here after tracing the problem,
  368. // as we don't want to keep the enumerator from returning an error
  369. // if the wizard is present (no connections, but hey, better than nothing).
  370. //
  371. TraceHr(ttidError, FAL, hr, FALSE,
  372. "CConnectionsFolderEnum failed in call to HrRetrieveConManEntries");
  373. hr = S_FALSE;
  374. }
  375. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionFolderEnum::Reset");
  376. return hr;
  377. }
  378. //+---------------------------------------------------------------------------
  379. //
  380. // Member: CConnectionFolderEnum::Clone
  381. //
  382. // Purpose: Creates a new item enumeration object with the same contents
  383. // and state as the current one.
  384. //
  385. // Arguments:
  386. // ppenum [out] Return a clone of the current internal PIDL
  387. //
  388. // Returns: Returns S_OK if successful, or an OLE-defined error
  389. // value otherwise.
  390. //
  391. // Author: jeffspr 5 Nov 1997
  392. //
  393. // Notes:
  394. //
  395. STDMETHODIMP CConnectionFolderEnum::Clone(
  396. IEnumIDList ** ppenum)
  397. {
  398. TraceFileFunc(ttidShellFolderIface);
  399. NYI("CConnectionFolderEnum::Clone");
  400. *ppenum = NULL;
  401. return E_NOTIMPL;
  402. }
  403. //+---------------------------------------------------------------------------
  404. //
  405. // Member: CConnectionFolderEnum::HrRetrieveConManEntries
  406. //
  407. // Purpose: Enumerate all connections from the ConnectionManagers, and
  408. // add them to our IDL.
  409. //
  410. // Arguments:
  411. // (none)
  412. //
  413. // Returns:
  414. //
  415. // Author: jeffspr 8 Oct 1997
  416. //
  417. // Notes:
  418. //
  419. HRESULT CConnectionFolderEnum::HrRetrieveConManEntries()
  420. {
  421. TraceFileFunc(ttidShellFolderIface);
  422. HRESULT hr = S_OK;
  423. NETCFG_TRY
  424. PCONFOLDPIDLVEC apidlNew;
  425. hr = g_ccl.HrRetrieveConManEntries(apidlNew);
  426. if (SUCCEEDED(hr))
  427. {
  428. m_apidl.clear();
  429. m_apidl = apidlNew;
  430. }
  431. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionFolder::HrRetrieveConManEntries");
  432. NETCFG_CATCH(hr)
  433. return hr;
  434. }