Leaked source code of windows server 2003
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.

521 lines
12 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: P I D L . C P P
  7. //
  8. // Contents: PIDL utility routines. This stuff is mainly copied from the
  9. // existing Namespace extension samples and real code, since
  10. // everyone and their gramma uses this stuff.
  11. //
  12. // Notes:
  13. //
  14. // Author: jeffspr 1 Oct 1997
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "pch.h"
  18. #pragma hdrstop
  19. #include "shlobj.h"
  20. #include "shlobjp.h"
  21. #include "pidlutil.h"
  22. #if DBG
  23. //+---------------------------------------------------------------------------
  24. //
  25. // Function: ILNext
  26. //
  27. // Purpose: Return the next PIDL in the list
  28. //
  29. // Arguments:
  30. // pidl []
  31. //
  32. // Returns:
  33. //
  34. // Author: jeffspr 1 Oct 1997 (from brianwen)
  35. //
  36. // Notes:
  37. //
  38. LPITEMIDLIST ILNext(LPCITEMIDLIST pidl)
  39. {
  40. if (pidl)
  41. {
  42. pidl = (LPITEMIDLIST) ((BYTE *)pidl + pidl->mkid.cb);
  43. }
  44. return (LPITEMIDLIST)pidl;
  45. }
  46. //+---------------------------------------------------------------------------
  47. //
  48. // Function: ILIsEmpty
  49. //
  50. // Purpose: Is this PIDL empty
  51. //
  52. // Arguments:
  53. // pidl []
  54. //
  55. // Returns:
  56. //
  57. // Author: jeffspr 1 Oct 1997 (from brianwen)
  58. //
  59. // Notes:
  60. //
  61. BOOL ILIsEmpty(LPCITEMIDLIST pidl)
  62. {
  63. return (!pidl || !pidl->mkid.cb);
  64. }
  65. #endif // #if DBG
  66. //+---------------------------------------------------------------------------
  67. //
  68. // Function: ILCreate
  69. //
  70. // Purpose: Create a PIDL
  71. //
  72. // Arguments:
  73. // cbSize []
  74. //
  75. // Returns:
  76. //
  77. // Author: jeffspr 1 Oct 1997 (from brianwen)
  78. //
  79. // Notes:
  80. //
  81. LPITEMIDLIST ILCreate(DWORD dwSize)
  82. {
  83. LPITEMIDLIST pidl = (LPITEMIDLIST) SHAlloc(dwSize);
  84. return pidl;
  85. }
  86. VOID FreeIDL(LPITEMIDLIST pidl)
  87. {
  88. Assert(pidl);
  89. SHFree(pidl);
  90. }
  91. //+---------------------------------------------------------------------------
  92. //
  93. // Function: ILIsSingleID
  94. //
  95. // Purpose: Returns TRUE if the idlist has just one ID in it.
  96. //
  97. // Arguments:
  98. // pidl []
  99. //
  100. // Returns:
  101. //
  102. // Author: jeffspr 1 Oct 1997 (from brianwen)
  103. //
  104. // Notes:
  105. //
  106. BOOL ILIsSingleID(LPCITEMIDLIST pidl)
  107. {
  108. if (pidl == NULL)
  109. return FALSE;
  110. return (pidl->mkid.cb == 0 || ILNext(pidl)->mkid.cb == 0);
  111. }
  112. //+---------------------------------------------------------------------------
  113. //
  114. // Function: ILGetCID
  115. //
  116. // Purpose: Returns the number of ID's in the list.
  117. //
  118. // Arguments:
  119. // pidl []
  120. //
  121. // Returns:
  122. //
  123. // Author: jeffspr 1 Oct 1997 (from brianwen)
  124. //
  125. // Notes:
  126. //
  127. UINT ILGetCID(LPCITEMIDLIST pidl)
  128. {
  129. UINT cid = 0;
  130. while (!ILIsEmpty(pidl))
  131. {
  132. ++ cid;
  133. pidl = ILNext(pidl);
  134. }
  135. return cid;
  136. }
  137. //+---------------------------------------------------------------------------
  138. //
  139. // Function: ILGetSizeCID
  140. //
  141. // Purpose: Get the length of the first cid items in a pidl.
  142. //
  143. // Arguments:
  144. // pidl []
  145. // cid []
  146. //
  147. // Returns:
  148. //
  149. // Author: jeffspr 1 Oct 1997 (from brianwen)
  150. //
  151. // Notes:
  152. //
  153. UINT ILGetSizeCID(LPCITEMIDLIST pidl, UINT cid)
  154. {
  155. UINT cbTotal = 0;
  156. if (pidl)
  157. {
  158. cbTotal += sizeof(pidl->mkid.cb); // Null terminator
  159. while (cid && !ILIsEmpty(pidl))
  160. {
  161. cbTotal += pidl->mkid.cb;
  162. pidl = ILNext(pidl);
  163. -- cid;
  164. }
  165. }
  166. return cbTotal;
  167. }
  168. //+---------------------------------------------------------------------------
  169. //
  170. // Function: CloneIDLFirstCID
  171. //
  172. // Purpose: Make a new list consisting of only the first cid items on
  173. // an existing list.
  174. //
  175. // Arguments:
  176. // pidl []
  177. // cid []
  178. //
  179. // Returns:
  180. //
  181. // Author: jeffspr 1 Oct 1997 (from brianwen)
  182. //
  183. // Notes:
  184. //
  185. LPITEMIDLIST CloneIDLFirstCID(LPCITEMIDLIST pidl, UINT cid)
  186. {
  187. Assert((INT)cid >= 0);
  188. UINT cb = ILGetSizeCID(pidl, cid);
  189. LPITEMIDLIST pidlRet = (LPITEMIDLIST) SHAlloc(cb);
  190. if (pidlRet)
  191. {
  192. // Notes: no need to zero-init.
  193. // Also, do not copy the NULL terminator.
  194. memcpy (pidlRet, pidl, cb - sizeof(pidl->mkid.cb));
  195. LPITEMIDLIST pidlTerm = pidlRet;
  196. // Cannot test for NULL terminator, we have not terminated
  197. // the list yet.
  198. //
  199. while (cid)
  200. {
  201. pidlTerm = ILNext(pidlTerm);
  202. -- cid;
  203. }
  204. pidlTerm->mkid.cb = 0;
  205. }
  206. return pidlRet;
  207. }
  208. //+---------------------------------------------------------------------------
  209. //
  210. // Function: ILSkipCID
  211. //
  212. // Purpose: Skips the first cid items in a pidl.
  213. //
  214. // Arguments:
  215. // pidl []
  216. // cid []
  217. //
  218. // Returns:
  219. //
  220. // Author: jeffspr 1 Oct 1997 (from brianwen)
  221. //
  222. // Notes:
  223. //
  224. LPITEMIDLIST ILSkipCID(LPCITEMIDLIST pidl, UINT cid)
  225. {
  226. Assert((INT)cid >= 0);
  227. while (cid && !ILIsEmpty(pidl))
  228. {
  229. pidl = ILNext(pidl);
  230. -- cid;
  231. }
  232. return (LPITEMIDLIST)pidl;
  233. }
  234. #if 0
  235. BOOL ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
  236. {
  237. if (FSetupGlobalShellFolders())
  238. {
  239. LPSHELLFOLDER psfDesktop = (LPSHELLFOLDER) PvGlobGet (ipsfDesktop);
  240. if (psfDesktop)
  241. {
  242. VERIFYPTR(pidl1, FALSE);
  243. VERIFYPTR(pidl2, FALSE);
  244. return psfDesktop->CompareIDs(0, pidl1, pidl2) == ResultFromShort(0);
  245. }
  246. }
  247. return FALSE;
  248. }
  249. #endif
  250. //+---------------------------------------------------------------------------
  251. //
  252. // Function: CloneIDL
  253. //
  254. // Purpose: Clone an IDL (return a duplicate)
  255. //
  256. // Arguments:
  257. // pidl []
  258. //
  259. // Returns:
  260. //
  261. // Author: jeffspr 1 Oct 1997 (from brianwen)
  262. //
  263. // Notes:
  264. //
  265. LPITEMIDLIST CloneIDL(LPCITEMIDLIST pidl)
  266. {
  267. UINT cb = 0;
  268. LPITEMIDLIST pidlRet = NULL;
  269. if (pidl)
  270. {
  271. cb = ILGetSize(pidl);
  272. pidlRet = (LPITEMIDLIST) SHAlloc(cb);
  273. if (pidlRet)
  274. {
  275. memcpy(pidlRet, pidl, cb);
  276. }
  277. }
  278. return pidlRet;
  279. }
  280. //+---------------------------------------------------------------------------
  281. //
  282. // Function: CloneRgIDL
  283. //
  284. // Purpose: Clone a pidl array
  285. //
  286. // Arguments:
  287. // rgpidl [in] PIDL array to clone
  288. // cidl [in] Count of the pidl array
  289. // fUseCache [in] If TRUE, generate the returned IDL from the cache
  290. // fAllowNonCacheItems [in] Use old version of pidl if cached version non available
  291. // pppidl [out] Return pointer for pidl array
  292. //
  293. // Returns:
  294. //
  295. // Author: jeffspr 22 Oct 1997
  296. //
  297. // Notes:
  298. //
  299. /*
  300. HRESULT HrCloneRgIDL(
  301. LPCITEMIDLIST * rgpidl,
  302. ULONG cidl,
  303. BOOL fUseCache,
  304. BOOL fAllowNonCacheItems,
  305. LPITEMIDLIST ** pppidl,
  306. ULONG * pcidl)
  307. {
  308. HRESULT hr = NOERROR;
  309. LPITEMIDLIST * rgpidlReturn = NULL;
  310. ULONG irg = 0;
  311. ULONG cidlCopied = 0;
  312. Assert(pppidl);
  313. Assert(pcidl);
  314. Assert(rgpidl);
  315. if (!rgpidl || !cidl)
  316. {
  317. hr = E_INVALIDARG;
  318. goto Exit;
  319. }
  320. else
  321. {
  322. // Alloc the return buffer
  323. //
  324. rgpidlReturn = (LPITEMIDLIST *) SHAlloc(cidl * sizeof(LPITEMIDLIST));
  325. if (!rgpidlReturn)
  326. {
  327. hr = E_OUTOFMEMORY;
  328. goto Exit;
  329. }
  330. else
  331. {
  332. // Clone all elements within the passed in PIDL array
  333. //
  334. for (irg = 0; irg < cidl; irg++)
  335. {
  336. if (rgpidl[irg])
  337. {
  338. if (fUseCache)
  339. {
  340. PCONNLISTENTRY pcle = NULL;
  341. PCONFOLDPIDL pcfp = (PCONFOLDPIDL) rgpidl[irg];
  342. hr = g_ccl.HrFindConnectionByGuid(&(pcfp->guidId), &pcle);
  343. if (hr == S_OK)
  344. {
  345. Assert(pcle);
  346. Assert(pcle->pccfe);
  347. // Copy to the return pidl array.
  348. hr = HrConFoldEntryToPidl(pcle->pccfe, &(rgpidlReturn[cidlCopied++]));
  349. if (FAILED(hr))
  350. goto Exit;
  351. }
  352. else
  353. {
  354. TraceTag(ttidShellFolder, "HrCloneRgIDL: Connection find returned: 0x%08x", hr);
  355. if (hr == S_FALSE)
  356. {
  357. if (fAllowNonCacheItems)
  358. {
  359. TraceTag(ttidShellFolder, "HrCloneRgIDL: Connection not found in cache, "
  360. "using non-cache item");
  361. rgpidlReturn[cidlCopied++] = CloneIDL((LPITEMIDLIST)rgpidl[irg]);
  362. if (!rgpidlReturn[irg])
  363. {
  364. hr = E_OUTOFMEMORY;
  365. goto Exit;
  366. }
  367. }
  368. else
  369. {
  370. TraceTag(ttidShellFolder, "HrCloneRgIDL: Connection not found in cache. "
  371. "Dropping item from array");
  372. }
  373. }
  374. else
  375. {
  376. AssertSz(FALSE, "HrCloneRgIDL: Connection find HR_FAILED");
  377. }
  378. }
  379. }
  380. else
  381. {
  382. // Clone this element in the PIDL array
  383. //
  384. rgpidlReturn[cidlCopied++] = CloneIDL ((LPITEMIDLIST) rgpidl[irg]);
  385. if (!rgpidlReturn[irg])
  386. {
  387. hr = E_OUTOFMEMORY;
  388. goto Exit;
  389. }
  390. }
  391. }
  392. else
  393. {
  394. // Make sure that we don't try to delete bogus data later.
  395. //
  396. rgpidlReturn[cidlCopied++] = NULL;
  397. AssertSz(FALSE, "Bogus element in the rgpidl in HrCloneRgIDL");
  398. hr = E_INVALIDARG;
  399. goto Exit;
  400. }
  401. }
  402. }
  403. }
  404. Exit:
  405. if (FAILED(hr))
  406. {
  407. // Free the already-allocated IDLISTs
  408. //
  409. ULONG irgT = 0;
  410. for (irgT = 0; irgT < irg; irgT++)
  411. {
  412. if (rgpidlReturn[irgT])
  413. {
  414. FreeIDL(rgpidlReturn[irgT]);
  415. }
  416. }
  417. SHFree(rgpidlReturn);
  418. *pppidl = NULL;
  419. }
  420. else
  421. {
  422. // Fill in the return var.
  423. //
  424. *pppidl = rgpidlReturn;
  425. *pcidl = cidlCopied;
  426. }
  427. TraceHr(ttidError, FAL, hr, FALSE, "HrCloneRgIDL");
  428. return hr;
  429. } // CloneRgIDL
  430. */
  431. //+---------------------------------------------------------------------------
  432. //
  433. // Function: FreeRgIDL
  434. //
  435. // Purpose: Free a PIDL array
  436. //
  437. // Arguments:
  438. // cidl [in] Size of PIDL array
  439. // apidl [in] Pointer to the array itself.
  440. //
  441. // Returns:
  442. //
  443. // Author: jeffspr 27 Oct 1997
  444. //
  445. // Notes:
  446. //
  447. VOID FreeRgIDL(
  448. UINT cidl,
  449. LPITEMIDLIST * apidl)
  450. {
  451. if (apidl)
  452. {
  453. for (UINT i = 0; i < cidl; i++)
  454. {
  455. FreeIDL(apidl[i]);
  456. }
  457. SHFree(apidl);
  458. }
  459. }