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.

553 lines
12 KiB

  1. /**************************************************************************
  2. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3. ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  4. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5. PARTICULAR PURPOSE.
  6. Copyright 1998 Microsoft Corporation. All Rights Reserved.
  7. **************************************************************************/
  8. /**************************************************************************
  9. File: PidlMgr.cpp
  10. Description: Implements CPidlMgr.
  11. **************************************************************************/
  12. /**************************************************************************
  13. #include statements
  14. **************************************************************************/
  15. #include "PidlMgr.h"
  16. #include "ShlFldr.h"
  17. #include "Guid.h"
  18. #include "resource.h"
  19. /**************************************************************************
  20. CPidlMgr::CPidlMgr
  21. **************************************************************************/
  22. CPidlMgr::CPidlMgr()
  23. {
  24. g_DllRefCount++;
  25. //get the shell's IMalloc pointer
  26. //we'll keep this until we get destroyed
  27. if(FAILED(SHGetMalloc(&m_pMalloc)))
  28. {
  29. delete this;
  30. }
  31. }
  32. /**************************************************************************
  33. CPidlMgr::~CPidlMgr
  34. **************************************************************************/
  35. CPidlMgr::~CPidlMgr()
  36. {
  37. if(m_pMalloc)
  38. m_pMalloc->Release();
  39. g_DllRefCount--;
  40. }
  41. /**************************************************************************
  42. CPidlMgr::Create()
  43. Creates a new PIDL
  44. **************************************************************************/
  45. LPITEMIDLIST CPidlMgr::Create(VOID)
  46. {
  47. LPITEMIDLIST pidlOut;
  48. USHORT uSize;
  49. pidlOut = NULL;
  50. /*
  51. Calculate the size. This consists of the ITEMIDLIST plus the size of our
  52. private PIDL structure.
  53. */
  54. uSize = sizeof(ITEMIDLIST) + sizeof(PIDLDATA);
  55. /*
  56. Allocate the memory, adding an additional ITEMIDLIST for the NULL terminating
  57. ID List.
  58. */
  59. pidlOut = (LPITEMIDLIST)m_pMalloc->Alloc(uSize + sizeof(ITEMIDLIST));
  60. if(pidlOut)
  61. {
  62. LPITEMIDLIST pidlTemp = pidlOut;
  63. //set the size of this item
  64. pidlTemp->mkid.cb = uSize;
  65. //set the NULL terminator to 0
  66. pidlTemp = GetNextItem(pidlTemp);
  67. pidlTemp->mkid.cb = 0;
  68. pidlTemp->mkid.abID[0] = 0;
  69. }
  70. return pidlOut;
  71. }
  72. /**************************************************************************
  73. CPidlMgr::Delete()
  74. Deletes a PIDL
  75. **************************************************************************/
  76. VOID CPidlMgr::Delete(LPITEMIDLIST pidl)
  77. {
  78. m_pMalloc->Free(pidl);
  79. }
  80. /**************************************************************************
  81. CPidlMgr::GetNextItem()
  82. **************************************************************************/
  83. LPITEMIDLIST CPidlMgr::GetNextItem(LPCITEMIDLIST pidl)
  84. {
  85. if(pidl)
  86. {
  87. return (LPITEMIDLIST)(LPBYTE)(((LPBYTE)pidl) + pidl->mkid.cb);
  88. }
  89. else
  90. return NULL;
  91. }
  92. /**************************************************************************
  93. CPidlMgr::GetSize()
  94. **************************************************************************/
  95. UINT CPidlMgr::GetSize(LPCITEMIDLIST pidl)
  96. {
  97. UINT cbTotal = 0;
  98. LPITEMIDLIST pidlTemp = (LPITEMIDLIST)pidl;
  99. if(pidlTemp)
  100. {
  101. while(pidlTemp->mkid.cb)
  102. {
  103. cbTotal += pidlTemp->mkid.cb;
  104. pidlTemp = GetNextItem(pidlTemp);
  105. }
  106. //add the size of the NULL terminating ITEMIDLIST
  107. cbTotal += sizeof(ITEMIDLIST);
  108. }
  109. return cbTotal;
  110. }
  111. /**************************************************************************
  112. CPidlMgr::GetLastItem()
  113. Gets the last item in the list
  114. **************************************************************************/
  115. LPITEMIDLIST CPidlMgr::GetLastItem(LPCITEMIDLIST pidl)
  116. {
  117. LPITEMIDLIST pidlLast = NULL;
  118. //get the PIDL of the last item in the list
  119. while(pidl && pidl->mkid.cb)
  120. {
  121. pidlLast = (LPITEMIDLIST)pidl;
  122. pidl = GetNextItem(pidl);
  123. }
  124. return pidlLast;
  125. }
  126. /**************************************************************************
  127. CPidlMgr::Copy()
  128. **************************************************************************/
  129. LPITEMIDLIST CPidlMgr::Copy(LPCITEMIDLIST pidlSource)
  130. {
  131. LPITEMIDLIST pidlTarget = NULL;
  132. UINT cbSource = 0;
  133. if(NULL == pidlSource)
  134. return NULL;
  135. // Allocate the new pidl
  136. cbSource = GetSize(pidlSource);
  137. pidlTarget = (LPITEMIDLIST)m_pMalloc->Alloc(cbSource);
  138. if(!pidlTarget)
  139. return NULL;
  140. // Copy the source to the target
  141. CopyMemory(pidlTarget, pidlSource, cbSource);
  142. return pidlTarget;
  143. }
  144. /**************************************************************************
  145. CPidlMgr::CopySingleItem()
  146. **************************************************************************/
  147. LPITEMIDLIST CPidlMgr::CopySingleItem(LPCITEMIDLIST pidlSource)
  148. {
  149. LPITEMIDLIST pidlTarget = NULL;
  150. UINT cbSource = 0;
  151. if(NULL == pidlSource)
  152. return NULL;
  153. // Allocate the new pidl
  154. cbSource = pidlSource->mkid.cb;
  155. pidlTarget = (LPITEMIDLIST)m_pMalloc->Alloc(cbSource + sizeof(ITEMIDLIST));
  156. if(!pidlTarget)
  157. return NULL;
  158. // Copy the source to the target
  159. ZeroMemory(pidlTarget, cbSource + sizeof(ITEMIDLIST));
  160. CopyMemory(pidlTarget, pidlSource, cbSource);
  161. return pidlTarget;
  162. }
  163. /**************************************************************************
  164. CPidlMgr::GetDataPointer()
  165. **************************************************************************/
  166. inline LPPIDLDATA CPidlMgr::GetDataPointer(LPCITEMIDLIST pidl)
  167. {
  168. if(!pidl)
  169. return NULL;
  170. return (LPPIDLDATA)(pidl->mkid.abID);
  171. }
  172. /**************************************************************************
  173. CPidlMgr::Concatenate()
  174. Create a new PIDL by combining two existing PIDLs.
  175. **************************************************************************/
  176. LPITEMIDLIST CPidlMgr::Concatenate(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
  177. {
  178. LPITEMIDLIST pidlNew;
  179. UINT cb1 = 0,
  180. cb2 = 0;
  181. //are both of these NULL?
  182. if(!pidl1 && !pidl2)
  183. return NULL;
  184. //if pidl1 is NULL, just return a copy of pidl2
  185. if(!pidl1)
  186. {
  187. pidlNew = Copy(pidl2);
  188. return pidlNew;
  189. }
  190. //if pidl2 is NULL, just return a copy of pidl1
  191. if(!pidl2)
  192. {
  193. pidlNew = Copy(pidl1);
  194. return pidlNew;
  195. }
  196. cb1 = GetSize(pidl1) - sizeof(ITEMIDLIST);
  197. cb2 = GetSize(pidl2);
  198. //create the new PIDL
  199. pidlNew = (LPITEMIDLIST)m_pMalloc->Alloc(cb1 + cb2);
  200. if(pidlNew)
  201. {
  202. //copy the first PIDL
  203. CopyMemory(pidlNew, pidl1, cb1);
  204. //copy the second PIDL
  205. CopyMemory(((LPBYTE)pidlNew) + cb1, pidl2, cb2);
  206. }
  207. return pidlNew;
  208. }
  209. /**************************************************************************
  210. CPidlMgr::CreateFolderPidl()
  211. Create a new folder PIDL.
  212. **************************************************************************/
  213. LPITEMIDLIST CPidlMgr::CreateFolderPidl(LPCTSTR pszName)
  214. {
  215. LPITEMIDLIST pidl = Create();
  216. LPPIDLDATA pData = GetDataPointer(pidl);
  217. if(pData)
  218. {
  219. pData->fFolder = TRUE;
  220. lstrcpyn(pData->szName, pszName, MAX_NAME);
  221. pData->szData[0] = 0;
  222. }
  223. return pidl;
  224. }
  225. /**************************************************************************
  226. CPidlMgr::CreateItemPidl()
  227. Create a new item PIDL.
  228. **************************************************************************/
  229. LPITEMIDLIST CPidlMgr::CreateItemPidl( LPCTSTR pszName,
  230. LPCTSTR pszData)
  231. {
  232. LPITEMIDLIST pidl = Create();
  233. LPPIDLDATA pData = GetDataPointer(pidl);
  234. if(pData)
  235. {
  236. pData->fFolder = FALSE;
  237. lstrcpyn(pData->szName, pszName, MAX_NAME);
  238. lstrcpyn(pData->szData, pszData, MAX_DATA);
  239. }
  240. return pidl;
  241. }
  242. /**************************************************************************
  243. CPidlMgr::SetDataPidl()
  244. Set a data in the PIDL.
  245. **************************************************************************/
  246. LPITEMIDLIST CPidlMgr::SetDataPidl(LPITEMIDLIST pidl, LPPIDLDATA pSourceData, PIDLDATATYPE pidldatatype)
  247. {
  248. if (!pidl)
  249. pidl = Create();
  250. LPPIDLDATA pData = GetDataPointer(pidl);
  251. if(pData)
  252. {
  253. if (pidldatatype & FOLDER)
  254. pData->fFolder = pSourceData->fFolder;
  255. if (pidldatatype & NAME)
  256. lstrcpyn(pData->szName, pSourceData->szName, MAX_NAME);
  257. if (pidldatatype & DATA)
  258. lstrcpyn(pData->szData, pSourceData->szData, MAX_DATA);
  259. if (pidldatatype & ICON)
  260. pData->iIcon = pSourceData->iIcon;
  261. if (pidldatatype & URL)
  262. lstrcpyn(pData->szUrl, pSourceData->szUrl, MAX_DATA);
  263. }
  264. return pidl;
  265. }
  266. /**************************************************************************
  267. CPidlMgr::GetName()
  268. Gets the name for this item
  269. **************************************************************************/
  270. int CPidlMgr::GetName(LPCITEMIDLIST pidl, LPTSTR pszText, DWORD dwSize)
  271. {
  272. if(!IsBadWritePtr(pszText, dwSize))
  273. {
  274. *pszText = 0;
  275. LPPIDLDATA pData = GetDataPointer(pidl);
  276. if(pData)
  277. {
  278. lstrcpyn(pszText, pData->szName, dwSize);
  279. return lstrlen(pszText);
  280. }
  281. }
  282. return 0;
  283. }
  284. /**************************************************************************
  285. CPidlMgr::GetRelativeName()
  286. Gets the full name for this item
  287. **************************************************************************/
  288. int CPidlMgr::GetRelativeName(LPCITEMIDLIST pidl, LPTSTR pszText, DWORD dwSize)
  289. {
  290. if(!IsBadWritePtr(pszText, dwSize))
  291. {
  292. LPITEMIDLIST pidlTemp;
  293. *pszText = 0;
  294. //walk the list, getting the name for each item
  295. pidlTemp = (LPITEMIDLIST)pidl;
  296. while(pidlTemp && pidlTemp->mkid.cb)
  297. {
  298. LPTSTR pszCurrent = pszText + lstrlen(pszText);
  299. dwSize -= GetName(pidlTemp, pszCurrent, dwSize);
  300. pidlTemp = GetNextItem(pidlTemp);
  301. //don't add a backslash to the last item
  302. if(pidlTemp && pidlTemp->mkid.cb)
  303. {
  304. SmartAppendBackslash(pszCurrent);
  305. }
  306. }
  307. return lstrlen(pszText);
  308. }
  309. return 0;
  310. }
  311. /**************************************************************************
  312. CPidlMgr::GetData()
  313. Gets the data for this item
  314. **************************************************************************/
  315. int CPidlMgr::GetData(LPCITEMIDLIST pidl, LPTSTR pszText, DWORD dwSize)
  316. {
  317. if(!IsBadWritePtr(pszText, dwSize))
  318. {
  319. *pszText = 0;
  320. LPPIDLDATA pData = GetDataPointer(pidl);
  321. if(pData)
  322. {
  323. lstrcpyn(pszText, pData->szData, dwSize);
  324. return lstrlen(pszText);
  325. }
  326. }
  327. return 0;
  328. }
  329. /**************************************************************************
  330. CPidlMgr::IsFolder()
  331. Determines if the item is a folder
  332. **************************************************************************/
  333. BOOL CPidlMgr::IsFolder(LPCITEMIDLIST pidl)
  334. {
  335. LPPIDLDATA pData = GetDataPointer(pidl);
  336. if(pData)
  337. {
  338. return pData->fFolder;
  339. }
  340. return FALSE;
  341. }
  342. /**************************************************************************
  343. CPidlMgr::SetData()
  344. **************************************************************************/
  345. int CPidlMgr::SetData(LPCITEMIDLIST pidl, LPCTSTR pszData)
  346. {
  347. LPPIDLDATA pData = GetDataPointer(pidl);
  348. if(pData)
  349. {
  350. lstrcpyn(pData->szData, pszData, MAX_DATA);
  351. return lstrlen(pData->szData);
  352. }
  353. return 0;
  354. }
  355. /**************************************************************************
  356. CPidlMgr::GetIcon()
  357. Determines if the item is a folder
  358. **************************************************************************/
  359. int CPidlMgr::GetIcon(LPCITEMIDLIST pidl)
  360. {
  361. LPPIDLDATA pData = GetDataPointer(pidl);
  362. if(pData)
  363. {
  364. return pData->iIcon;
  365. }
  366. return FALSE;
  367. }
  368. /**************************************************************************
  369. CPidlMgr::GetUrl()
  370. Gets the data for this item
  371. **************************************************************************/
  372. int CPidlMgr::GetUrl(LPCITEMIDLIST pidl, LPTSTR pszText, DWORD dwSize)
  373. {
  374. if(!IsBadWritePtr(pszText, dwSize))
  375. {
  376. *pszText = 0;
  377. LPPIDLDATA pData = GetDataPointer(pidl);
  378. if(pData)
  379. {
  380. lstrcpyn(pszText, pData->szUrl, dwSize);
  381. return lstrlen(pszText);
  382. }
  383. }
  384. return 0;
  385. }