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.

574 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(IN 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; // Placement new can't fail with OUTOFMEMORY.
  72. Assert(pPlacement == m_pConFoldPidl);
  73. return S_OK;
  74. }
  75. template <class T>
  76. HRESULT CPConFoldPidl<T>::SHAlloc(IN 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; // Placement new can't fail with OUTOFMEMORY.
  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(IN 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; // Placement new can't fail with OUTOFMEMORY.
  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(IN 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; // Placement new can't fail with OUTOFMEMORY
  200. Assert(pPlacement == m_pConFoldPidl);
  201. if (!m_pConFoldPidl->IsPidlOfThisType())
  202. {
  203. ::SHFree(pPlacement);
  204. m_pConFoldPidl = NULL;
  205. return E_INVALIDARG;
  206. }
  207. }
  208. else // We'll have to convert:
  209. {
  210. TraceTag(ttidShellFolderIface, "InitializeFromItemIDList: Converting PIDL from type %d to %d", pidlType, PIDL_VERSION);
  211. switch (PIDL_VERSION)
  212. {
  213. case PIDL_TYPE_UNKNOWN: // This is what we are
  214. {
  215. switch (pidlType)
  216. {
  217. // This is what we're getting
  218. case PIDL_TYPE_UNKNOWN:
  219. AssertSz(FALSE, "PIDL is already of this type.");
  220. break;
  221. case PIDL_TYPE_V1:
  222. case PIDL_TYPE_V2:
  223. case PIDL_TYPE_98:
  224. case PIDL_TYPE_FOLDER:
  225. default:
  226. AssertSz(FALSE, "Can't upgrade PIDL to UNKNOWN type");
  227. hr = E_INVALIDARG;
  228. break;
  229. }
  230. }
  231. break;
  232. case PIDL_TYPE_V1: // This is what we are
  233. {
  234. switch (pidlType)
  235. {
  236. // This is what we're getting
  237. case PIDL_TYPE_V1:
  238. AssertSz(FALSE, "PIDL is already of this type.");
  239. break;
  240. case PIDL_TYPE_UNKNOWN:
  241. case PIDL_TYPE_V2:
  242. case PIDL_TYPE_98:
  243. case PIDL_TYPE_FOLDER:
  244. default:
  245. AssertSz(FALSE, "Can't upgrade PIDL to PIDL_V1 type");
  246. hr = E_INVALIDARG;
  247. break;
  248. }
  249. }
  250. break;
  251. case PIDL_TYPE_FOLDER: // This is what we are
  252. {
  253. switch (pidlType)
  254. {
  255. // This is what we're getting
  256. case PIDL_TYPE_FOLDER:
  257. AssertSz(FALSE, "PIDL is already of this type.");
  258. break;
  259. case PIDL_TYPE_V1:
  260. case PIDL_TYPE_98:
  261. case PIDL_TYPE_UNKNOWN:
  262. case PIDL_TYPE_V2:
  263. default:
  264. AssertSz(FALSE, "Can't upgrade PIDL to PIDL_TYPE_FOLDER type");
  265. hr = E_INVALIDARG;
  266. break;
  267. }
  268. }
  269. break;
  270. case PIDL_TYPE_98: // This is what we are
  271. {
  272. switch (pidlType)
  273. {
  274. // This is what we're getting
  275. case PIDL_TYPE_98:
  276. AssertSz(FALSE, "PIDL is already of this type.");
  277. break;
  278. case PIDL_TYPE_V1:
  279. case PIDL_TYPE_V2:
  280. case PIDL_TYPE_UNKNOWN:
  281. case PIDL_TYPE_FOLDER:
  282. default:
  283. AssertSz(FALSE, "Can't upgrade PIDL to PIDL_TYPE_98 type");
  284. hr = E_INVALIDARG;
  285. break;
  286. }
  287. }
  288. break;
  289. case PIDL_TYPE_V2: // This is what we are
  290. {
  291. switch (pidlType)
  292. {
  293. // This is what we're getting
  294. case PIDL_TYPE_V2:
  295. AssertSz(FALSE, "PIDL is already of this type.");
  296. break;
  297. case PIDL_TYPE_V1:
  298. {
  299. // Do the convert.
  300. cfpv1 = const_cast<ConFoldPidl_v1 *>(reinterpret_cast<const ConFoldPidl_v1 *>(pItemIdList));
  301. if (!cfpv1->IsPidlOfThisType())
  302. {
  303. return E_INVALIDARG;
  304. }
  305. dwPidlSize = cfpv1->iCB + CBCONFOLDPIDLV2_MIN - CBCONFOLDPIDLV1_MIN;
  306. dwPidlSize += sizeof(WCHAR); // Adding NULL for PhoneOrHostAddress in bData
  307. pPlacement = reinterpret_cast<UNALIGNED T*>(::ILCreate(dwPidlSize + sizeof(USHORT))); // Terminating 0
  308. if (!pPlacement)
  309. {
  310. return E_OUTOFMEMORY;
  311. }
  312. TraceTag(ttidShellFolderIface, "InitializeFromItemIDList: Original: 0x%08x New:0x%08x", pItemIdList, pPlacement);
  313. // Basically call the constructor
  314. // Semantic equivalent to m_pConFoldPidl = pPlacement;
  315. // m_pConFoldPidl::T();
  316. m_pConFoldPidl = new( pPlacement ) T; // Placement new can't fail with OUTOFMEMORY
  317. Assert(pPlacement == m_pConFoldPidl);
  318. Assert(sizeof(ConFoldPidlBase) <= cfpv1->iCB );
  319. // Copy the ConFoldPidlBase data
  320. CopyMemory(m_pConFoldPidl, cfpv1, sizeof(ConFoldPidlBase));
  321. // I know we're already a ConFoldPidl_v2 - but this is a template, so we'll have to cast
  322. // to get it to compile. This code path is dead for non-v2 classes though.
  323. cfpv2 = reinterpret_cast<ConFoldPidl_v2 *>(m_pConFoldPidl);
  324. // Copy the bData member (everything but ConFoldPidlBase in this case)
  325. CopyMemory(cfpv2->bData, cfpv1->bData, cfpv1->iCB - sizeof(ConFoldPidlBase));
  326. // Force update the version number and byte count
  327. cfpv2->iCB = (WORD)dwPidlSize;
  328. const_cast<DWORD&>(cfpv2->dwVersion) = PIDL_TYPE_V2;
  329. if (NCM_LAN == cfpv2->ncm)
  330. {
  331. cfpv2->ncsm = NCSM_LAN;
  332. }
  333. else
  334. {
  335. cfpv2->ncsm = NCSM_NONE;
  336. }
  337. cfpv2->ulStrPhoneOrHostAddressPos = cfpv2->ulPersistBufPos + cfpv2->ulPersistBufSize;
  338. LPWSTR pszPhoneOrHostAddress = cfpv2->PszGetPhoneOrHostAddressPointer();
  339. *pszPhoneOrHostAddress = L'\0';
  340. cfpv2->ulStrPhoneOrHostAddressSize = sizeof(WCHAR); // Size of NULL
  341. // Don't forget to terminate the list!
  342. //
  343. LPITEMIDLIST pidlTerminate;
  344. pidlTerminate = ILNext( reinterpret_cast<LPCITEMIDLIST>( m_pConFoldPidl ) );
  345. pidlTerminate->mkid.cb = 0;
  346. #ifdef DBG_VALIDATE_PIDLS
  347. Assert(IsValidConFoldPIDL());
  348. #endif
  349. Assert(m_pConFoldPidl->IsPidlOfThisType());
  350. if (!m_pConFoldPidl->IsPidlOfThisType())
  351. {
  352. ::SHFree(m_pConFoldPidl);
  353. m_pConFoldPidl = NULL;
  354. return E_FAIL;
  355. }
  356. }
  357. break;
  358. case PIDL_TYPE_98:
  359. {
  360. cfpv98 = const_cast<ConFoldPidl98 *>(reinterpret_cast<const ConFoldPidl98 *>(pItemIdList));
  361. if (!cfpv98->IsPidlOfThisType())
  362. {
  363. return E_INVALIDARG;
  364. }
  365. WCHAR szName[MAX_PATH];
  366. mbstowcs(szName, cfpv98->szaName, MAX_PATH);
  367. ConnListEntry cle;
  368. PCONFOLDPIDL pidlv2;
  369. HRESULT hrTmp = g_ccl.HrFindConnectionByName(szName, cle);
  370. if (hrTmp != S_OK)
  371. {
  372. return E_FAIL;
  373. }
  374. cle.ccfe.ConvertToPidl(pidlv2);
  375. LPITEMIDLIST pIdl = pidlv2.TearOffItemIdList();
  376. m_pConFoldPidl = reinterpret_cast<T *>(pIdl);
  377. LPITEMIDLIST pidlTerminate;
  378. pidlTerminate = ILNext( reinterpret_cast<LPCITEMIDLIST>( m_pConFoldPidl ) );
  379. pidlTerminate->mkid.cb = 0;
  380. #ifdef DBG_VALIDATE_PIDLS
  381. Assert(IsValidConFoldPIDL());
  382. #endif
  383. Assert(m_pConFoldPidl->IsPidlOfThisType());
  384. if (!m_pConFoldPidl->IsPidlOfThisType())
  385. {
  386. ::SHFree(m_pConFoldPidl);
  387. m_pConFoldPidl = NULL;
  388. return E_FAIL;
  389. }
  390. }
  391. break;
  392. case PIDL_TYPE_FOLDER:
  393. AssertSz(FALSE, "Can't upgrade PIDL to PIDL_V2 type");
  394. case PIDL_TYPE_UNKNOWN:
  395. default:
  396. hr = E_INVALIDARG;
  397. break;
  398. }
  399. }
  400. break;
  401. default:
  402. AssertSz(FALSE, "Can't upgrade PIDL");
  403. hr = E_INVALIDARG;
  404. break;
  405. }
  406. }
  407. if ( FAILED(hr) )
  408. {
  409. ::SHFree(m_pConFoldPidl);
  410. m_pConFoldPidl = NULL;
  411. }
  412. else
  413. {
  414. Assert(m_pConFoldPidl->IsPidlOfThisType());
  415. }
  416. return hr;
  417. }
  418. template <class T>
  419. CPConFoldPidl<T>::CPConFoldPidl()
  420. {
  421. m_pConFoldPidl = NULL;
  422. }
  423. template <class T>
  424. CPConFoldPidl<T>::CPConFoldPidl(IN const CPConFoldPidl& PConFoldPidl) throw (HRESULT)
  425. {
  426. m_pConFoldPidl = NULL;
  427. HRESULT hr = InitializeFromItemIDList(reinterpret_cast<LPCITEMIDLIST>(PConFoldPidl.m_pConFoldPidl));
  428. if (FAILED(hr))
  429. {
  430. throw hr;
  431. }
  432. }
  433. template <class T>
  434. CPConFoldPidl<T>::~CPConFoldPidl()
  435. {
  436. FreePIDLIfRequired();
  437. m_pConFoldPidl = NULL;
  438. }
  439. template <class T>
  440. CPConFoldPidl<T>& CPConFoldPidl<T>::operator =(IN const CPConFoldPidl<T>& PConFoldPidl) throw (HRESULT)
  441. {
  442. FreePIDLIfRequired();
  443. if (PConFoldPidl.m_pConFoldPidl)
  444. {
  445. HRESULT hr = InitializeFromItemIDList(reinterpret_cast<LPCITEMIDLIST>(PConFoldPidl.m_pConFoldPidl));
  446. if (FAILED(hr))
  447. {
  448. throw hr;
  449. }
  450. }
  451. else
  452. {
  453. m_pConFoldPidl = NULL;
  454. }
  455. return *this;
  456. }
  457. template <class T>
  458. inline BOOL CPConFoldPidl<T>::empty() const
  459. {
  460. return (m_pConFoldPidl == NULL);
  461. }
  462. template <class T>
  463. HRESULT CPConFoldPidl<T>::ConvertToConFoldEntry(OUT CConFoldEntry& cfe) const
  464. {
  465. Assert(m_pConFoldPidl);
  466. if (!m_pConFoldPidl)
  467. {
  468. return E_UNEXPECTED;
  469. }
  470. return m_pConFoldPidl->ConvertToConFoldEntry(cfe);
  471. }
  472. template <class T>
  473. HRESULT CPConFoldPidl<T>::Swop(OUT CPConFoldPidl<T>& cfe)
  474. {
  475. UNALIGNED T* pTemp = m_pConFoldPidl;
  476. m_pConFoldPidl = cfe.m_pConFoldPidl;
  477. cfe.m_pConFoldPidl = pTemp;
  478. return S_OK;
  479. }
  480. template CPConFoldPidl<ConFoldPidl_v1>;
  481. template CPConFoldPidl<ConFoldPidl_v2 >;
  482. template CPConFoldPidl<ConFoldPidlFolder>;
  483. template CPConFoldPidl<ConFoldPidl98>;