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.

567 lines
18 KiB

  1. // ****************************************************************************
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2000.
  5. //
  6. // File: C F P I D L _ T E M P L A T E S . C P P
  7. //
  8. // Contents: Connections Folder template structures.
  9. //
  10. // Author: deonb 12 Jan 2001
  11. //
  12. // ****************************************************************************
  13. #include "pch.h"
  14. #pragma hdrstop
  15. #include "ncperms.h"
  16. #include "ncras.h"
  17. #include "foldinc.h" // Standard shell\folder includes
  18. #include "ncnetcon.h"
  19. template <class T>
  20. HRESULT CPConFoldPidl<T>::FreePIDLIfRequired()
  21. {
  22. if ( m_pConFoldPidl )
  23. {
  24. FreeIDL(reinterpret_cast<LPITEMIDLIST>(m_pConFoldPidl));
  25. m_pConFoldPidl = NULL;
  26. return S_OK;
  27. }
  28. else
  29. {
  30. return S_FALSE;
  31. }
  32. }
  33. template <class T>
  34. HRESULT CPConFoldPidl<T>::Clear()
  35. {
  36. FreePIDLIfRequired();
  37. return S_OK;
  38. }
  39. template <class T>
  40. T& CPConFoldPidl<T>::operator *()
  41. {
  42. return (*m_pConFoldPidl);
  43. }
  44. template <class T>
  45. UNALIGNED T* CPConFoldPidl<T>::operator->()
  46. {
  47. return m_pConFoldPidl;
  48. }
  49. template <class T>
  50. const UNALIGNED T* CPConFoldPidl<T>::operator->() const
  51. {
  52. return m_pConFoldPidl;
  53. }
  54. template <class T>
  55. HRESULT CPConFoldPidl<T>::ILCreate(const DWORD dwSize)
  56. {
  57. Assert(dwSize >= sizeof(T));
  58. FreePIDLIfRequired();
  59. // Just call the constructor on T (placement form of new doesn't allocate any more memory).
  60. LPVOID pPlacement = ::ILCreate(dwSize);
  61. if (!pPlacement)
  62. {
  63. return E_OUTOFMEMORY;
  64. }
  65. #if DBG
  66. ZeroMemory(pPlacement, dwSize);
  67. #endif
  68. // Basically call the constructor
  69. // Semantic equivalent to m_pConFoldPidl = pPlacement;
  70. // m_pConFoldPidl::T();
  71. m_pConFoldPidl = new( pPlacement ) T;
  72. Assert(pPlacement == m_pConFoldPidl);
  73. return S_OK;
  74. }
  75. template <class T>
  76. HRESULT CPConFoldPidl<T>::SHAlloc(const SIZE_T cb)
  77. {
  78. FreePIDLIfRequired();
  79. LPVOID pPlacement = reinterpret_cast<UNALIGNED T*>(::SHAlloc(cb));
  80. if (!pPlacement)
  81. {
  82. return E_OUTOFMEMORY;
  83. }
  84. // Basically call the constructor
  85. // Semantic equivalent to m_pConFoldPidl = pPlacement;
  86. // m_pConFoldPidl::T();
  87. m_pConFoldPidl = new( pPlacement ) T;
  88. Assert(pPlacement == m_pConFoldPidl);
  89. if (m_pConFoldPidl)
  90. {
  91. return S_OK;
  92. }
  93. else
  94. {
  95. return E_OUTOFMEMORY;
  96. }
  97. }
  98. template <class T>
  99. HRESULT CPConFoldPidl<T>::ILClone(const CPConFoldPidl<T>& PConFoldPidl)
  100. {
  101. C_ASSERT(PIDL_VERSION == T::CONNECTIONS_FOLDER_IDL_VERSION);
  102. FreePIDLIfRequired();
  103. LPVOID pPlacement = reinterpret_cast<UNALIGNED T*>(::ILClone(reinterpret_cast<LPITEMIDLIST>(PConFoldPidl.m_pConFoldPidl)));
  104. if (!pPlacement)
  105. {
  106. return E_OUTOFMEMORY;
  107. }
  108. // Basically call the constructor
  109. // Semantic equivalent to m_pConFoldPidl = pPlacement;
  110. // m_pConFoldPidl::T();
  111. m_pConFoldPidl = new( pPlacement ) T;
  112. Assert(pPlacement == m_pConFoldPidl);
  113. if (m_pConFoldPidl)
  114. {
  115. Assert(m_pConFoldPidl->IsPidlOfThisType());
  116. return S_OK;
  117. }
  118. else
  119. {
  120. return E_OUTOFMEMORY;
  121. }
  122. }
  123. template <class T>
  124. LPITEMIDLIST CPConFoldPidl<T>::TearOffItemIdList() const
  125. {
  126. TraceFileFunc(ttidConFoldEntry);
  127. Assert(m_pConFoldPidl);
  128. Assert( m_pConFoldPidl->IsPidlOfThisType() );
  129. LPITEMIDLIST retList = ::ILClone(reinterpret_cast<LPITEMIDLIST>(m_pConFoldPidl));
  130. #ifdef DBG_VALIDATE_PIDLS
  131. Assert(IsValidPIDL(retList));
  132. #endif
  133. return retList;
  134. }
  135. template <class T>
  136. LPITEMIDLIST CPConFoldPidl<T>::Detach()
  137. {
  138. TraceFileFunc(ttidConFoldEntry);
  139. Assert(m_pConFoldPidl);
  140. Assert( m_pConFoldPidl->IsPidlOfThisType() );
  141. LPITEMIDLIST retList = reinterpret_cast<LPITEMIDLIST>(m_pConFoldPidl);
  142. #ifdef DBG_VALIDATE_PIDLS
  143. Assert(IsValidPIDL(retList));
  144. #endif
  145. m_pConFoldPidl = NULL;
  146. return retList;
  147. }
  148. template <class T>
  149. LPCITEMIDLIST CPConFoldPidl<T>::GetItemIdList() const
  150. {
  151. TraceFileFunc(ttidConFoldEntry);
  152. Assert(m_pConFoldPidl);
  153. Assert( m_pConFoldPidl->IsPidlOfThisType() );
  154. LPCITEMIDLIST tmpItemIdList = reinterpret_cast<LPCITEMIDLIST>(m_pConFoldPidl);
  155. #ifdef DBG_VALIDATE_PIDLS
  156. Assert(IsValidPIDL(tmpItemIdList));
  157. #endif
  158. return tmpItemIdList;
  159. }
  160. #ifdef DBG_VALIDATE_PIDLS
  161. template <class T>
  162. BOOL CPConFoldPidl<T>::IsValidConFoldPIDL() const
  163. {
  164. return IsValidPIDL(reinterpret_cast<LPCITEMIDLIST>(m_pConFoldPidl));
  165. }
  166. #endif
  167. template <class T>
  168. HRESULT CPConFoldPidl<T>::InitializeFromItemIDList(LPCITEMIDLIST pItemIdList)
  169. {
  170. DWORD dwPidlSize = 0;
  171. UNALIGNED ConFoldPidl_v1 * cfpv1 = NULL;
  172. UNALIGNED ConFoldPidl_v2 * cfpv2 = NULL;
  173. UNALIGNED ConFoldPidl98 * cfpv98 = NULL;
  174. LPVOID pPlacement = NULL;
  175. HRESULT hr = S_OK;
  176. Assert(pItemIdList);
  177. #ifdef DBG_VALIDATE_PIDLS
  178. if (!IsValidPIDL(pItemIdList))
  179. {
  180. TraceError("Invalid PIDL passed to InitializeFromItemIDList", E_INVALIDARG);
  181. }
  182. #endif
  183. Clear();
  184. CONFOLDPIDLTYPE pidlType = GetPidlType(pItemIdList);
  185. if ( (PIDL_TYPE_UNKNOWN == pidlType) && (PIDL_VERSION == PIDL_TYPE_FOLDER) )
  186. {
  187. pidlType = PIDL_TYPE_FOLDER; // Give it the benefit of the doubt
  188. }
  189. if (pidlType == PIDL_VERSION)
  190. {
  191. pPlacement = reinterpret_cast<UNALIGNED T*>(::ILClone(pItemIdList));
  192. if (!pPlacement)
  193. {
  194. return E_OUTOFMEMORY;
  195. }
  196. // Basically call the constructor
  197. // Semantic equivalent to m_pConFoldPidl = pPlacement;
  198. // m_pConFoldPidl::T();
  199. m_pConFoldPidl = new( pPlacement ) T;
  200. Assert(pPlacement == m_pConFoldPidl);
  201. }
  202. else // We'll have to convert:
  203. {
  204. TraceTag(ttidShellFolderIface, "InitializeFromItemIDList: Converting PIDL from type %d to %d", pidlType, PIDL_VERSION);
  205. switch (PIDL_VERSION)
  206. {
  207. case PIDL_TYPE_UNKNOWN: // This is what we are
  208. {
  209. switch (pidlType)
  210. {
  211. // This is what we're getting
  212. case PIDL_TYPE_UNKNOWN:
  213. AssertSz(FALSE, "PIDL is already of this type.");
  214. break;
  215. case PIDL_TYPE_V1:
  216. case PIDL_TYPE_V2:
  217. case PIDL_TYPE_98:
  218. case PIDL_TYPE_FOLDER:
  219. default:
  220. AssertSz(FALSE, "Can't upgrade PIDL to UNKNOWN type");
  221. hr = E_INVALIDARG;
  222. break;
  223. }
  224. }
  225. break;
  226. case PIDL_TYPE_V1: // This is what we are
  227. {
  228. switch (pidlType)
  229. {
  230. // This is what we're getting
  231. case PIDL_TYPE_V1:
  232. AssertSz(FALSE, "PIDL is already of this type.");
  233. break;
  234. case PIDL_TYPE_UNKNOWN:
  235. case PIDL_TYPE_V2:
  236. case PIDL_TYPE_98:
  237. case PIDL_TYPE_FOLDER:
  238. default:
  239. AssertSz(FALSE, "Can't upgrade PIDL to PIDL_V1 type");
  240. hr = E_INVALIDARG;
  241. break;
  242. }
  243. }
  244. break;
  245. case PIDL_TYPE_FOLDER: // This is what we are
  246. {
  247. switch (pidlType)
  248. {
  249. // This is what we're getting
  250. case PIDL_TYPE_FOLDER:
  251. AssertSz(FALSE, "PIDL is already of this type.");
  252. break;
  253. case PIDL_TYPE_V1:
  254. case PIDL_TYPE_98:
  255. case PIDL_TYPE_UNKNOWN:
  256. case PIDL_TYPE_V2:
  257. default:
  258. AssertSz(FALSE, "Can't upgrade PIDL to PIDL_TYPE_FOLDER type");
  259. hr = E_INVALIDARG;
  260. break;
  261. }
  262. }
  263. break;
  264. case PIDL_TYPE_98: // This is what we are
  265. {
  266. switch (pidlType)
  267. {
  268. // This is what we're getting
  269. case PIDL_TYPE_98:
  270. AssertSz(FALSE, "PIDL is already of this type.");
  271. break;
  272. case PIDL_TYPE_V1:
  273. case PIDL_TYPE_V2:
  274. case PIDL_TYPE_UNKNOWN:
  275. case PIDL_TYPE_FOLDER:
  276. default:
  277. AssertSz(FALSE, "Can't upgrade PIDL to PIDL_TYPE_98 type");
  278. hr = E_INVALIDARG;
  279. break;
  280. }
  281. }
  282. break;
  283. case PIDL_TYPE_V2: // This is what we are
  284. {
  285. switch (pidlType)
  286. {
  287. // This is what we're getting
  288. case PIDL_TYPE_V2:
  289. AssertSz(FALSE, "PIDL is already of this type.");
  290. break;
  291. case PIDL_TYPE_V1:
  292. {
  293. // Do the convert.
  294. cfpv1 = const_cast<ConFoldPidl_v1 *>(reinterpret_cast<const ConFoldPidl_v1 *>(pItemIdList));
  295. Assert(cfpv1->IsPidlOfThisType());
  296. if (!cfpv1->IsPidlOfThisType())
  297. {
  298. return E_INVALIDARG;
  299. }
  300. dwPidlSize = cfpv1->iCB + CBCONFOLDPIDLV2_MIN - CBCONFOLDPIDLV1_MIN;
  301. dwPidlSize += sizeof(WCHAR); // Adding NULL for PhoneOrHostAddress in bData
  302. pPlacement = reinterpret_cast<UNALIGNED T*>(::ILCreate(dwPidlSize + sizeof(USHORT))); // Terminating 0
  303. if (!pPlacement)
  304. {
  305. return E_OUTOFMEMORY;
  306. }
  307. TraceTag(ttidShellFolderIface, "InitializeFromItemIDList: Original: 0x%08x New:0x%08x", pItemIdList, pPlacement);
  308. // Basically call the constructor
  309. // Semantic equivalent to m_pConFoldPidl = pPlacement;
  310. // m_pConFoldPidl::T();
  311. m_pConFoldPidl = new( pPlacement ) T;
  312. Assert(pPlacement == m_pConFoldPidl);
  313. Assert(sizeof(ConFoldPidlBase) <= cfpv1->iCB );
  314. // Copy the ConFoldPidlBase data
  315. CopyMemory(m_pConFoldPidl, cfpv1, sizeof(ConFoldPidlBase));
  316. // I know we're already a ConFoldPidl_v2 - but this is a template, so we'll have to cast
  317. // to get it to compile. This code path is dead for non-v2 classes though.
  318. cfpv2 = reinterpret_cast<ConFoldPidl_v2 *>(m_pConFoldPidl);
  319. // Copy the bData member (everything but ConFoldPidlBase in this case)
  320. CopyMemory(cfpv2->bData, cfpv1->bData, cfpv1->iCB - sizeof(ConFoldPidlBase));
  321. // Force update the version number and byte count
  322. cfpv2->iCB = dwPidlSize;
  323. const_cast<DWORD&>(cfpv2->dwVersion) = PIDL_TYPE_V2;
  324. if (NCM_LAN == cfpv2->ncm)
  325. {
  326. cfpv2->ncsm = NCSM_LAN;
  327. }
  328. else
  329. {
  330. cfpv2->ncsm = NCSM_NONE;
  331. }
  332. cfpv2->ulStrPhoneOrHostAddressPos = cfpv2->ulPersistBufPos + cfpv2->ulPersistBufSize;
  333. LPWSTR pszPhoneOrHostAddress = cfpv2->PszGetPhoneOrHostAddressPointer();
  334. *pszPhoneOrHostAddress = L'\0';
  335. cfpv2->ulStrPhoneOrHostAddressSize = sizeof(WCHAR); // Size of NULL
  336. // Don't forget to terminate the list!
  337. //
  338. LPITEMIDLIST pidlTerminate;
  339. pidlTerminate = ILNext( reinterpret_cast<LPCITEMIDLIST>( m_pConFoldPidl ) );
  340. pidlTerminate->mkid.cb = 0;
  341. #ifdef DBG_VALIDATE_PIDLS
  342. Assert(IsValidConFoldPIDL());
  343. #endif
  344. Assert(m_pConFoldPidl->IsPidlOfThisType());
  345. if (!m_pConFoldPidl->IsPidlOfThisType())
  346. {
  347. ::SHFree(m_pConFoldPidl);
  348. m_pConFoldPidl = NULL;
  349. return E_FAIL;
  350. }
  351. }
  352. break;
  353. case PIDL_TYPE_98:
  354. {
  355. cfpv98 = const_cast<ConFoldPidl98 *>(reinterpret_cast<const ConFoldPidl98 *>(pItemIdList));
  356. Assert(cfpv98->IsPidlOfThisType());
  357. if (!cfpv98->IsPidlOfThisType())
  358. {
  359. return E_INVALIDARG;
  360. }
  361. WCHAR szName[MAX_PATH];
  362. mbstowcs(szName, cfpv98->szaName, MAX_PATH);
  363. ConnListEntry cle;
  364. PCONFOLDPIDL pidlv2;
  365. HRESULT hrTmp = g_ccl.HrFindConnectionByName(szName, cle);
  366. if (hrTmp != S_OK)
  367. {
  368. return E_FAIL;
  369. }
  370. cle.ccfe.ConvertToPidl(pidlv2);
  371. LPITEMIDLIST pIdl = pidlv2.TearOffItemIdList();
  372. m_pConFoldPidl = reinterpret_cast<T *>(pIdl);
  373. LPITEMIDLIST pidlTerminate;
  374. pidlTerminate = ILNext( reinterpret_cast<LPCITEMIDLIST>( m_pConFoldPidl ) );
  375. pidlTerminate->mkid.cb = 0;
  376. #ifdef DBG_VALIDATE_PIDLS
  377. Assert(IsValidConFoldPIDL());
  378. #endif
  379. Assert(m_pConFoldPidl->IsPidlOfThisType());
  380. if (!m_pConFoldPidl->IsPidlOfThisType())
  381. {
  382. ::SHFree(m_pConFoldPidl);
  383. m_pConFoldPidl = NULL;
  384. return E_FAIL;
  385. }
  386. }
  387. break;
  388. case PIDL_TYPE_FOLDER:
  389. AssertSz(FALSE, "Can't upgrade PIDL to PIDL_V2 type");
  390. case PIDL_TYPE_UNKNOWN:
  391. default:
  392. hr = E_INVALIDARG;
  393. break;
  394. }
  395. }
  396. break;
  397. default:
  398. AssertSz(FALSE, "Can't upgrade PIDL");
  399. hr = E_INVALIDARG;
  400. break;
  401. }
  402. }
  403. if ( FAILED(hr) )
  404. {
  405. ::SHFree(m_pConFoldPidl);
  406. m_pConFoldPidl = NULL;
  407. }
  408. else
  409. {
  410. Assert(m_pConFoldPidl->IsPidlOfThisType());
  411. }
  412. return hr;
  413. }
  414. template <class T>
  415. CPConFoldPidl<T>::CPConFoldPidl()
  416. {
  417. m_pConFoldPidl = NULL;
  418. }
  419. template <class T>
  420. CPConFoldPidl<T>::CPConFoldPidl(const CPConFoldPidl& PConFoldPidl)
  421. {
  422. m_pConFoldPidl = NULL;
  423. HRESULT hr = InitializeFromItemIDList(reinterpret_cast<LPCITEMIDLIST>(PConFoldPidl.m_pConFoldPidl));
  424. if (FAILED(hr))
  425. {
  426. throw hr;
  427. }
  428. }
  429. template <class T>
  430. CPConFoldPidl<T>::~CPConFoldPidl()
  431. {
  432. FreePIDLIfRequired();
  433. m_pConFoldPidl = NULL;
  434. }
  435. template <class T>
  436. CPConFoldPidl<T>& CPConFoldPidl<T>::operator =(const CPConFoldPidl<T>& PConFoldPidl)
  437. {
  438. FreePIDLIfRequired();
  439. if (PConFoldPidl.m_pConFoldPidl)
  440. {
  441. HRESULT hr = InitializeFromItemIDList(reinterpret_cast<LPCITEMIDLIST>(PConFoldPidl.m_pConFoldPidl));
  442. if (FAILED(hr))
  443. {
  444. throw hr;
  445. }
  446. }
  447. else
  448. {
  449. m_pConFoldPidl = NULL;
  450. }
  451. return *this;
  452. }
  453. template <class T>
  454. inline BOOL CPConFoldPidl<T>::empty() const
  455. {
  456. return (m_pConFoldPidl == NULL);
  457. }
  458. template <class T>
  459. HRESULT CPConFoldPidl<T>::ConvertToConFoldEntry(OUT CConFoldEntry& cfe) const
  460. {
  461. Assert(m_pConFoldPidl);
  462. if (!m_pConFoldPidl)
  463. {
  464. return E_UNEXPECTED;
  465. }
  466. return m_pConFoldPidl->ConvertToConFoldEntry(cfe);
  467. }
  468. template <class T>
  469. HRESULT CPConFoldPidl<T>::Swop(OUT CPConFoldPidl<T>& cfe)
  470. {
  471. UNALIGNED T* pTemp = m_pConFoldPidl;
  472. m_pConFoldPidl = cfe.m_pConFoldPidl;
  473. cfe.m_pConFoldPidl = pTemp;
  474. return S_OK;
  475. }
  476. template CPConFoldPidl<ConFoldPidl_v1>;
  477. template CPConFoldPidl<ConFoldPidl_v2 >;
  478. template CPConFoldPidl<ConFoldPidlFolder>;
  479. template CPConFoldPidl<ConFoldPidl98>;