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.

848 lines
25 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // DS Administration MMC snapin.
  4. //
  5. // Microsoft Windows
  6. // Copyright (C) Microsoft Corporation, 1992 - 1999
  7. //
  8. // File: DataObj.cpp
  9. //
  10. // Contents: Data Object implementation.
  11. //
  12. // Classes: CDSDataObject
  13. //
  14. // History: 02-Oct-96 WayneSc Created
  15. // 06-Feb-97 EricB - added Property Page Data support
  16. //-----------------------------------------------------------------------------
  17. #include "stdafx.h"
  18. #include "resource.h"
  19. #include "DSdirect.h"
  20. #include "DataObj.h"
  21. #include "dssnap.h"
  22. #include <lm.h>
  23. #ifdef _DEBUG
  24. #define new DEBUG_NEW
  25. #undef THIS_FILE
  26. static char THIS_FILE[] = __FILE__;
  27. #endif
  28. //+----------------------------------------------------------------------------
  29. // MMC's clipboard formats:
  30. //-----------------------------------------------------------------------------
  31. // Snap-in NodeType in both GUID format and string format
  32. CLIPFORMAT CDSDataObject::m_cfNodeType =
  33. (CLIPFORMAT)RegisterClipboardFormat(CCF_NODETYPE);
  34. CLIPFORMAT CDSDataObject::m_cfNodeTypeString =
  35. (CLIPFORMAT)RegisterClipboardFormat(CCF_SZNODETYPE);
  36. CLIPFORMAT CDSDataObject::m_cfDisplayName =
  37. (CLIPFORMAT)RegisterClipboardFormat(CCF_DISPLAY_NAME);
  38. CLIPFORMAT CDSDataObject::m_cfCoClass =
  39. (CLIPFORMAT)RegisterClipboardFormat(CCF_SNAPIN_CLASSID);
  40. CLIPFORMAT CDSDataObject::m_cfpMultiSelDataObj =
  41. (CLIPFORMAT)RegisterClipboardFormat(CCF_MMC_MULTISELECT_DATAOBJECT);
  42. CLIPFORMAT CDSDataObject::m_cfMultiObjTypes =
  43. (CLIPFORMAT)RegisterClipboardFormat(CCF_OBJECT_TYPES_IN_MULTI_SELECT);
  44. CLIPFORMAT CDSDataObject::m_cfMultiSelDataObjs =
  45. (CLIPFORMAT)RegisterClipboardFormat(CCF_MULTI_SELECT_SNAPINS);
  46. CLIPFORMAT CDSDataObject::m_cfPreload =
  47. (CLIPFORMAT)RegisterClipboardFormat(CCF_SNAPIN_PRELOADS);
  48. //+----------------------------------------------------------------------------
  49. // Our clipboard formats:
  50. //-----------------------------------------------------------------------------
  51. CLIPFORMAT CDSDataObject::m_cfInternal =
  52. (CLIPFORMAT)RegisterClipboardFormat(SNAPIN_INTERNAL);
  53. CLIPFORMAT CDSDataObject::m_cfDsObjectNames =
  54. (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSOBJECTNAMES);
  55. CLIPFORMAT CDSDataObject::m_cfDsDisplaySpecOptions =
  56. (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DS_DISPLAY_SPEC_OPTIONS);
  57. CLIPFORMAT CDSDataObject::m_cfDsSchemaPath =
  58. (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DS_SCHEMA_PATH);
  59. CLIPFORMAT CDSDataObject::m_cfPropSheetCfg =
  60. (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DS_PROPSHEETCONFIG);
  61. CLIPFORMAT CDSDataObject::m_cfParentHwnd =
  62. (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DS_PARENTHWND);
  63. CLIPFORMAT CDSDataObject::m_cfComponentData =
  64. (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DS_COMPDATA);
  65. CLIPFORMAT CDSDataObject::m_cfColumnID =
  66. (CLIPFORMAT)RegisterClipboardFormat(CCF_COLUMN_SET_ID);
  67. CLIPFORMAT CDSDataObject::m_cfMultiSelectProppage =
  68. (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DS_MULTISELECTPROPPAGE);
  69. //+----------------------------------------------------------------------------
  70. // CDSDataObject implementation
  71. //-----------------------------------------------------------------------------
  72. //+----------------------------------------------------------------------------
  73. //
  74. // Method: CDSDataObject::IDataObject::GetData
  75. //
  76. // Synopsis: Returns data, in this case the Prop Page format data.
  77. //
  78. //-----------------------------------------------------------------------------
  79. STDMETHODIMP
  80. CDSDataObject::GetData(FORMATETC * pFormatEtc, STGMEDIUM * pMedium)
  81. {
  82. //TRACE(_T("xx.%03x> CDSDataObject(0x%x)::GetData\n"),
  83. // GetCurrentThreadId(), this);
  84. HRESULT hr = S_OK;
  85. if (IsBadWritePtr(pMedium, sizeof(STGMEDIUM)))
  86. {
  87. return E_INVALIDARG;
  88. }
  89. if (!(pFormatEtc->tymed & TYMED_HGLOBAL))
  90. {
  91. return DV_E_TYMED;
  92. }
  93. pMedium->pUnkForRelease = NULL;
  94. pMedium->tymed = TYMED_HGLOBAL;
  95. if (pFormatEtc->cfFormat == m_cfDsObjectNames)
  96. {
  97. DWORD dwCachedBytes = 0;
  98. LPDSOBJECTNAMES pObjectNames = GetDsObjectNames(dwCachedBytes);
  99. if (pObjectNames)
  100. {
  101. // make a deep copy of the cached data
  102. pMedium->hGlobal = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
  103. m_nDSObjCachedBytes);
  104. if (pMedium->hGlobal == NULL)
  105. {
  106. return E_OUTOFMEMORY;
  107. }
  108. memcpy(pMedium->hGlobal, pObjectNames, dwCachedBytes);
  109. }
  110. else
  111. {
  112. return E_OUTOFMEMORY;
  113. }
  114. }
  115. else if (pFormatEtc->cfFormat == m_cfDsDisplaySpecOptions)
  116. {
  117. //
  118. // Get the DSDISPLAYSPECOPTIONS structure.
  119. // Use the value cached in the component data.
  120. //
  121. if (m_pDsComponentData != NULL)
  122. {
  123. PDSDISPLAYSPECOPTIONS pDsDisplaySpecOptions = m_pDsComponentData->GetDsDisplaySpecOptions();
  124. pMedium->hGlobal = (HGLOBAL)pDsDisplaySpecOptions;
  125. if (pDsDisplaySpecOptions == NULL)
  126. return E_OUTOFMEMORY;
  127. }
  128. else
  129. {
  130. return E_FAIL;
  131. }
  132. }
  133. else if (pFormatEtc->cfFormat == m_cfDsSchemaPath)
  134. {
  135. ASSERT(m_pDsComponentData);
  136. LPCWSTR lpszSchemaNamingCtx = m_pDsComponentData->GetBasePathsInfo()->GetSchemaNamingContext();
  137. size_t nSchemaNamingCtxLen = wcslen(lpszSchemaNamingCtx);
  138. if (nSchemaNamingCtxLen == 0)
  139. {
  140. return E_FAIL;
  141. }
  142. PWSTR pwzSchemaPath = (PWSTR)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
  143. (nSchemaNamingCtxLen +1) * sizeof(WCHAR));
  144. if (pwzSchemaPath == NULL)
  145. {
  146. return STG_E_MEDIUMFULL;
  147. }
  148. wcscpy(pwzSchemaPath, lpszSchemaNamingCtx);
  149. pMedium->hGlobal = pwzSchemaPath;
  150. }
  151. else if (pFormatEtc->cfFormat == m_cfPropSheetCfg)
  152. {
  153. // Return the property sheet notification handle.
  154. //
  155. PPROPSHEETCFG pSheetCfg;
  156. pSheetCfg = (PPROPSHEETCFG)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
  157. sizeof(PROPSHEETCFG));
  158. if (pSheetCfg == NULL)
  159. {
  160. return STG_E_MEDIUMFULL;
  161. }
  162. pSheetCfg->lNotifyHandle = m_lNotifyHandle;
  163. pSheetCfg->hwndParentSheet = m_hwndParentSheet;
  164. pSheetCfg->hwndHidden = m_pDsComponentData->GetHiddenWindow();
  165. pSheetCfg->wParamSheetClose = reinterpret_cast<WPARAM>(m_internal.m_cookie);
  166. pMedium->hGlobal = (HGLOBAL)pSheetCfg;
  167. }
  168. else if (pFormatEtc->cfFormat == m_cfParentHwnd)
  169. {
  170. // return the HWND of the MMC frame window
  171. HWND* pHWndMain = (HWND*)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
  172. sizeof(HWND));
  173. m_pDsComponentData->m_pFrame->GetMainWindow(pHWndMain);
  174. pMedium->hGlobal = (HGLOBAL)pHWndMain;
  175. }
  176. else if (pFormatEtc->cfFormat == m_cfComponentData)
  177. {
  178. // return the m_pDsComponentData the data object is bound to
  179. CDSComponentData** ppCD = (CDSComponentData**)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
  180. sizeof(CDSComponentData*));
  181. if (ppCD != NULL)
  182. {
  183. *ppCD = m_pDsComponentData;
  184. pMedium->hGlobal = (HGLOBAL)ppCD;
  185. }
  186. else
  187. {
  188. return STG_E_MEDIUMFULL;
  189. }
  190. }
  191. else if (pFormatEtc->cfFormat == m_cfMultiSelectProppage)
  192. {
  193. if (m_szUniqueID == _T(""))
  194. {
  195. return E_FAIL;
  196. }
  197. UINT nLength = m_szUniqueID.GetLength();
  198. PWSTR pszGuidString = (PWSTR)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
  199. (nLength +1) * sizeof(WCHAR));
  200. if (pszGuidString == NULL)
  201. {
  202. return STG_E_MEDIUMFULL;
  203. }
  204. wcscpy(pszGuidString, m_szUniqueID);
  205. pMedium->hGlobal = pszGuidString;
  206. }
  207. else if (pFormatEtc->cfFormat == m_cfMultiObjTypes)
  208. {
  209. hr = CreateMultiSelectObject(pMedium);
  210. }
  211. else if (pFormatEtc->cfFormat == m_cfInternal)
  212. {
  213. hr = CreateInternal(pMedium);
  214. }
  215. else if (pFormatEtc->cfFormat == m_cfColumnID)
  216. {
  217. hr = CreateColumnID(pMedium);
  218. }
  219. else
  220. {
  221. return DV_E_FORMATETC;
  222. }
  223. pMedium->tymed = TYMED_HGLOBAL;
  224. pMedium->pUnkForRelease = NULL;
  225. return hr;
  226. }
  227. //+----------------------------------------------------------------------------
  228. //
  229. // Method: CDSDataObject::IDataObject::GetDataHere
  230. //
  231. // Synopsis: Returns data in callers storage medium
  232. //
  233. //-----------------------------------------------------------------------------
  234. STDMETHODIMP
  235. CDSDataObject::GetDataHere(LPFORMATETC lpFormatetc, LPSTGMEDIUM lpMedium)
  236. {
  237. HRESULT hr = DV_E_CLIPFORMAT;
  238. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  239. // Based on the CLIPFORMAT write data to the stream
  240. const CLIPFORMAT cf = lpFormatetc->cfFormat;
  241. if(cf == m_cfNodeType)
  242. {
  243. hr = CreateNodeTypeData(lpMedium);
  244. }
  245. else if(cf == m_cfNodeTypeString)
  246. {
  247. hr = CreateNodeTypeStringData(lpMedium);
  248. }
  249. else if (cf == m_cfDisplayName)
  250. {
  251. hr = CreateDisplayName(lpMedium);
  252. }
  253. else if (cf == m_cfCoClass)
  254. {
  255. hr = CreateCoClassID(lpMedium);
  256. }
  257. else if (cf == m_cfPreload)
  258. {
  259. // MMC notify the snapin before loading with the MMCN_PRELOAD notify message
  260. BOOL bPreload = TRUE;
  261. hr = Create(&bPreload, sizeof(BOOL), lpMedium);
  262. }
  263. return hr;
  264. }
  265. //+----------------------------------------------------------------------------
  266. //
  267. // Method: CDSDataObject::IDataObject::SetData
  268. //
  269. // Synopsis: Allows the caller to set data object values.
  270. //
  271. //-----------------------------------------------------------------------------
  272. STDMETHODIMP CDSDataObject::SetData(FORMATETC * pFormatEtc, STGMEDIUM * pMedium,
  273. BOOL fRelease)
  274. {
  275. HRESULT hr = S_OK;
  276. if (pFormatEtc->cfFormat == m_cfPropSheetCfg)
  277. {
  278. if (!(pFormatEtc->tymed & TYMED_HGLOBAL))
  279. {
  280. return DV_E_TYMED;
  281. }
  282. PPROPSHEETCFG pSheetCfg = (PPROPSHEETCFG)pMedium->hGlobal;
  283. if ( NULL != pSheetCfg->lNotifyHandle)
  284. {
  285. m_lNotifyHandle = pSheetCfg->lNotifyHandle;
  286. }
  287. if (NULL != pSheetCfg->hwndParentSheet)
  288. {
  289. m_hwndParentSheet = pSheetCfg->hwndParentSheet;
  290. }
  291. if (fRelease)
  292. {
  293. GlobalFree(pMedium->hGlobal);
  294. }
  295. return S_OK;
  296. }
  297. else if (pFormatEtc->cfFormat == m_cfMultiSelectProppage)
  298. {
  299. if (!(pFormatEtc->tymed & TYMED_HGLOBAL))
  300. {
  301. return DV_E_TYMED;
  302. }
  303. PWSTR pszGuidString = (PWSTR)pMedium->hGlobal;
  304. if (pszGuidString == NULL)
  305. {
  306. ASSERT(FALSE);
  307. return E_FAIL;
  308. }
  309. m_szUniqueID = pszGuidString;
  310. }
  311. else
  312. {
  313. return DV_E_FORMATETC;
  314. }
  315. return hr;
  316. }
  317. //+----------------------------------------------------------------------------
  318. //
  319. // Method: CDSDataObject::IDataObject::EnumFormatEtc
  320. //
  321. // Synopsis:
  322. //
  323. //-----------------------------------------------------------------------------
  324. STDMETHODIMP CDSDataObject::EnumFormatEtc(DWORD, LPENUMFORMATETC*)
  325. {
  326. return E_NOTIMPL;
  327. }
  328. //+----------------------------------------------------------------------------
  329. //
  330. // Method: CDSDataObject::Create
  331. //
  332. // Synopsis:
  333. //
  334. //-----------------------------------------------------------------------------
  335. HRESULT
  336. CDSDataObject::Create(const void * pBuffer, int len, LPSTGMEDIUM pMedium)
  337. {
  338. HRESULT hr = DV_E_TYMED;
  339. // Do some simple validation
  340. if (pBuffer == NULL || pMedium == NULL)
  341. return E_POINTER;
  342. // Make sure the type medium is HGLOBAL
  343. if (pMedium->tymed == TYMED_HGLOBAL)
  344. {
  345. // Create the stream on the hGlobal passed in
  346. LPSTREAM lpStream;
  347. hr = CreateStreamOnHGlobal(pMedium->hGlobal, FALSE, &lpStream);
  348. if (SUCCEEDED(hr))
  349. {
  350. // Write to the stream the number of bytes
  351. unsigned long written;
  352. hr = lpStream->Write(pBuffer, len, &written);
  353. // Because we told CreateStreamOnHGlobal with 'FALSE',
  354. // only the stream is released here.
  355. // Note - the caller (i.e. snap-in, object) will free the HGLOBAL
  356. // at the correct time. This is according to the IDataObject specification.
  357. lpStream->Release();
  358. }
  359. }
  360. return hr;
  361. }
  362. //+----------------------------------------------------------------------------
  363. //
  364. // Method: CDSDataObject::CreateNodeTypeData
  365. //
  366. // Synopsis: Create the node type object in GUID format
  367. //
  368. //-----------------------------------------------------------------------------
  369. HRESULT
  370. CDSDataObject::CreateNodeTypeData(LPSTGMEDIUM lpMedium)
  371. {
  372. TRACE(_T("xx.%03x> GetDataHere on Node Type\n"), GetCurrentThreadId());
  373. GUID* pGuid = m_internal.m_cookie->GetGUID();
  374. return Create(pGuid, sizeof(GUID), lpMedium);
  375. }
  376. //+----------------------------------------------------------------------------
  377. //
  378. // Method: CDSDataObject::CreateNodeTypeStringData
  379. //
  380. // Synopsis: Create the node type object in GUID string format
  381. //
  382. //-----------------------------------------------------------------------------
  383. HRESULT
  384. CDSDataObject::CreateNodeTypeStringData(LPSTGMEDIUM lpMedium)
  385. {
  386. TRACE(_T("xx.%03x> GetDataHere on Node Type String\n"), GetCurrentThreadId());
  387. GUID* pGuid = m_internal.m_cookie->GetGUID();
  388. CString strGUID;
  389. WCHAR * szGUID;
  390. StringFromCLSID(*pGuid, &szGUID);
  391. strGUID = szGUID;
  392. return Create (strGUID, strGUID.GetLength()+ sizeof(wchar_t),
  393. lpMedium);
  394. }
  395. //+----------------------------------------------------------------------------
  396. //
  397. // Method: CDSDataObject::CreateDisplayName
  398. //
  399. // Synopsis: This is the display named used in the scope pane and snap-in
  400. // manager.
  401. //
  402. //-----------------------------------------------------------------------------
  403. HRESULT
  404. CDSDataObject::CreateDisplayName(LPSTGMEDIUM lpMedium)
  405. {
  406. TRACE(_T("xx.%03x> GetDataHere on Display Name\n"), GetCurrentThreadId());
  407. // Load the name from resource
  408. // Note - if this is not provided, the console will used the snap-in name
  409. CString szDispName;
  410. szDispName.LoadString( ResourceIDForSnapinType[ m_internal.m_snapintype ]);
  411. return Create(szDispName, ((szDispName.GetLength()+1) * sizeof(wchar_t)), lpMedium);
  412. }
  413. //+----------------------------------------------------------------------------
  414. //
  415. // Method: CDSDataObject::CreateMultiSelectObject
  416. //
  417. // Synopsis: this is to create the list of types selected
  418. //
  419. //-----------------------------------------------------------------------------
  420. HRESULT
  421. CDSDataObject::CreateMultiSelectObject(LPSTGMEDIUM lpMedium)
  422. {
  423. TRACE(_T("xx.%03x> GetDataHere on MultiSelectObject\n"), GetCurrentThreadId());
  424. CUINode** cookieArray = NULL;
  425. cookieArray = (CUINode**) GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
  426. m_internal.m_cookie_count*sizeof(CUINode*));
  427. if (!cookieArray) {
  428. return E_OUTOFMEMORY;
  429. }
  430. for (UINT k=0; k<m_internal.m_cookie_count; k++)
  431. {
  432. if (k==0)
  433. cookieArray[k] = m_internal.m_cookie;
  434. else
  435. cookieArray[k] = m_internal.m_p_cookies[k-1];
  436. }
  437. BOOL* bDuplicateArr = NULL;
  438. bDuplicateArr = (BOOL*)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
  439. m_internal.m_cookie_count*sizeof(BOOL));
  440. if (!bDuplicateArr) {
  441. if (cookieArray)
  442. GlobalFree (cookieArray);
  443. return E_OUTOFMEMORY;
  444. }
  445. //ZeroMemory(bDuplicateArr, m_internal.m_cookie_count*sizeof(BOOL));
  446. UINT cCount = 0;
  447. for (UINT index=0; index<m_internal.m_cookie_count; index++)
  448. {
  449. for (UINT j=0; j<index;j++)
  450. {
  451. GUID Guid1 = *(cookieArray[index]->GetGUID());
  452. GUID Guid2 = *(cookieArray[j]->GetGUID());
  453. if (IsEqualGUID (Guid1, Guid2))
  454. {
  455. bDuplicateArr[index] = TRUE;
  456. break; //repeated GUID
  457. }
  458. }
  459. if (!bDuplicateArr[index])
  460. cCount++;
  461. }
  462. UINT size = sizeof(SMMCObjectTypes) + (cCount - 1) *
  463. sizeof(GUID);
  464. void * pTmp = ::GlobalAlloc(GPTR, size);
  465. if (!pTmp) {
  466. if (cookieArray) {
  467. GlobalFree (cookieArray);
  468. }
  469. if (bDuplicateArr) {
  470. GlobalFree (bDuplicateArr);
  471. }
  472. return E_OUTOFMEMORY;
  473. }
  474. SMMCObjectTypes* pdata = reinterpret_cast<SMMCObjectTypes*>(pTmp);
  475. pdata->count = cCount;
  476. UINT i = 0;
  477. for (index=0; index<m_internal.m_cookie_count; index++)
  478. {
  479. if (!bDuplicateArr[index])
  480. pdata->guid[i++] = *(cookieArray[index]->GetGUID());
  481. }
  482. ASSERT(i == cCount);
  483. lpMedium->hGlobal = pTmp;
  484. GlobalFree (cookieArray);
  485. GlobalFree (bDuplicateArr);
  486. return S_OK;
  487. }
  488. //+----------------------------------------------------------------------------
  489. //
  490. // Method: CDSDataObject::CreateInternal
  491. //
  492. // Synopsis:
  493. //
  494. //-----------------------------------------------------------------------------
  495. HRESULT
  496. CDSDataObject::CreateInternal(LPSTGMEDIUM lpMedium)
  497. {
  498. HRESULT hr = S_OK;
  499. INTERNAL * pInt = NULL;
  500. void * pBuf = NULL;
  501. UINT size = sizeof(INTERNAL);
  502. size += sizeof(CUINode *) * (m_internal.m_cookie_count - 1);
  503. pBuf = GlobalAlloc (GPTR, size);
  504. pInt = (INTERNAL *) pBuf;
  505. lpMedium->hGlobal = pBuf;
  506. if (pInt != NULL &&
  507. m_internal.m_cookie_count > 1)
  508. {
  509. // copy the data
  510. pInt->m_type = m_internal.m_type;
  511. pInt->m_cookie = m_internal.m_cookie;
  512. pInt->m_snapintype = m_internal.m_snapintype;
  513. pInt->m_cookie_count = m_internal.m_cookie_count;
  514. pInt->m_p_cookies = (CUINode **) ((BYTE *)pInt + sizeof(INTERNAL));
  515. memcpy (pInt->m_p_cookies, m_internal.m_p_cookies,
  516. sizeof(CUINode *) * (m_internal.m_cookie_count - 1));
  517. hr = Create(pBuf, size, lpMedium);
  518. }
  519. else
  520. {
  521. hr = Create(&m_internal, sizeof(INTERNAL), lpMedium);
  522. }
  523. return hr;
  524. }
  525. //+----------------------------------------------------------------------------
  526. //
  527. // Method: CDSDataObject::CreateCoClassID
  528. //
  529. // Synopsis:
  530. //
  531. //-----------------------------------------------------------------------------
  532. HRESULT
  533. CDSDataObject::CreateCoClassID(LPSTGMEDIUM lpMedium)
  534. {
  535. TRACE(_T("xx.%03x> GetDataHere on CoClass\n"), GetCurrentThreadId());
  536. CLSID CoClassID;
  537. switch (m_internal.m_snapintype) {
  538. case SNAPINTYPE_DS:
  539. CoClassID = CLSID_DSSnapin;
  540. break;
  541. case SNAPINTYPE_SITE:
  542. CoClassID = CLSID_SiteSnapin;
  543. break;
  544. default:
  545. memset (&CoClassID,0,sizeof(CLSID));
  546. }
  547. return Create(&CoClassID, sizeof(CLSID), lpMedium);
  548. }
  549. //+----------------------------------------------------------------------------
  550. //
  551. // Method: CDSDataObject::CreateColumnID
  552. //
  553. // Synopsis:
  554. //
  555. //-----------------------------------------------------------------------------
  556. HRESULT
  557. CDSDataObject::CreateColumnID(LPSTGMEDIUM lpMedium)
  558. {
  559. // build the column id
  560. CDSColumnSet* pColumnSet = (m_internal.m_cookie)->GetColumnSet(m_pDsComponentData);
  561. if (pColumnSet == NULL)
  562. return DV_E_TYMED;
  563. LPCWSTR lpszID = pColumnSet->GetColumnID();
  564. size_t iLen = wcslen(lpszID);
  565. // allocate enough memory for the struct and the string for the column id
  566. SColumnSetID* pColumnID = (SColumnSetID*)malloc(sizeof(SColumnSetID) + (iLen * sizeof(WCHAR)));
  567. if (pColumnID != NULL)
  568. {
  569. memset(pColumnID, 0, sizeof(SColumnSetID) + (iLen * sizeof(WCHAR)));
  570. pColumnID->cBytes = static_cast<ULONG>(iLen * sizeof(WCHAR));
  571. memcpy(pColumnID->id, lpszID, (iLen * sizeof(WCHAR)));
  572. // copy the column id to global memory
  573. size_t cb = sizeof(SColumnSetID) + (iLen * sizeof(WCHAR));
  574. lpMedium->tymed = TYMED_HGLOBAL;
  575. lpMedium->hGlobal = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, cb);
  576. if (lpMedium->hGlobal == NULL)
  577. return STG_E_MEDIUMFULL;
  578. BYTE* pb = reinterpret_cast<BYTE*>(::GlobalLock(lpMedium->hGlobal));
  579. memcpy(pb, pColumnID, cb);
  580. ::GlobalUnlock(lpMedium->hGlobal);
  581. free(pColumnID);
  582. }
  583. return S_OK;
  584. }
  585. LPDSOBJECTNAMES CDSDataObject::GetDsObjectNames(DWORD& dwCachedBytes)
  586. {
  587. if (!m_pDSObjCached)
  588. {
  589. HRESULT hr = CreateDsObjectNamesCached();
  590. if (FAILED(hr))
  591. {
  592. TRACE(L"Failed to create the cached DSOBJECTNAMES: hr = 0x%x\n", hr);
  593. return 0;
  594. }
  595. }
  596. dwCachedBytes = m_nDSObjCachedBytes;
  597. return m_pDSObjCached;
  598. }
  599. HRESULT CDSDataObject::CreateDsObjectNamesCached()
  600. {
  601. if (m_pDSObjCached != NULL)
  602. {
  603. ::free(m_pDSObjCached);
  604. m_pDSObjCached = NULL;
  605. m_nDSObjCachedBytes = 0;
  606. }
  607. // figure out how much storage we need
  608. DWORD cbStorage = 0;
  609. INT cbStruct = sizeof(DSOBJECTNAMES) +
  610. ((m_internal.m_cookie_count - 1) * sizeof(DSOBJECT));
  611. CString strPath;
  612. CString strClass;
  613. CUINode* pNode = 0;
  614. CDSCookie * pCookie = 0;
  615. //
  616. // this loop is to calc how much storage we need.
  617. //
  618. for (UINT index = 0; index < m_internal.m_cookie_count; index++)
  619. {
  620. if (index == 0)
  621. {
  622. pNode = m_internal.m_cookie;
  623. }
  624. else
  625. {
  626. pNode = m_internal.m_p_cookies[index - 1];
  627. }
  628. pCookie = NULL;
  629. if (IS_CLASS(pNode, DS_UI_NODE))
  630. {
  631. pCookie = GetDSCookieFromUINode(pNode);
  632. }
  633. //
  634. // All the nodes must be of type CDSUINode or else we fail
  635. //
  636. if (pCookie == NULL)
  637. {
  638. return E_FAIL;
  639. }
  640. m_pDsComponentData->GetBasePathsInfo()->ComposeADsIPath(strPath, pCookie->GetPath());
  641. strClass = pCookie->GetClass();
  642. if (_wcsicmp(strClass, L"Unknown") == 0)
  643. {
  644. strClass = L"";
  645. }
  646. cbStorage += (strPath.GetLength() + 1 + strClass.GetLength() + 1) * sizeof(TCHAR);
  647. }
  648. //
  649. // Allocate the needed storage
  650. //
  651. m_pDSObjCached = (LPDSOBJECTNAMES)malloc(cbStruct + cbStorage);
  652. if (m_pDSObjCached == NULL)
  653. {
  654. return STG_E_MEDIUMFULL;
  655. }
  656. m_nDSObjCachedBytes = cbStruct + cbStorage;
  657. switch (m_internal.m_snapintype)
  658. {
  659. case SNAPINTYPE_DS:
  660. m_pDSObjCached->clsidNamespace = CLSID_DSSnapin;
  661. break;
  662. case SNAPINTYPE_SITE:
  663. m_pDSObjCached->clsidNamespace = CLSID_SiteSnapin;
  664. break;
  665. default:
  666. memset (&m_pDSObjCached->clsidNamespace, 0, sizeof(CLSID));
  667. }
  668. m_pDSObjCached->cItems = m_internal.m_cookie_count;
  669. DWORD NextOffset = cbStruct;
  670. for (index = 0; index < m_internal.m_cookie_count; index++)
  671. {
  672. if (index == 0)
  673. {
  674. pNode = m_internal.m_cookie;
  675. }
  676. else
  677. {
  678. pNode = m_internal.m_p_cookies[index - 1];
  679. }
  680. pCookie = NULL;
  681. if (IS_CLASS(pNode, DS_UI_NODE))
  682. {
  683. pCookie = GetDSCookieFromUINode(pNode);
  684. }
  685. //
  686. // All nodes must be of type CDSUINode or else we fail
  687. //
  688. if (pCookie == NULL)
  689. {
  690. return E_FAIL;
  691. }
  692. //
  693. // Set the data from the node and node data
  694. //
  695. m_pDSObjCached->aObjects[index].dwFlags = pNode->IsContainer() ? DSOBJECT_ISCONTAINER : 0;
  696. m_pDSObjCached->aObjects[index].dwProviderFlags = (m_pDsComponentData->IsAdvancedView()) ?
  697. DSPROVIDER_ADVANCED : 0;
  698. m_pDsComponentData->GetBasePathsInfo()->ComposeADsIPath(strPath, pCookie->GetPath());
  699. strClass = pCookie->GetClass();
  700. if (_wcsicmp(strClass, L"Unknown") == 0)
  701. {
  702. strClass = L"";
  703. }
  704. m_pDSObjCached->aObjects[index].offsetName = NextOffset;
  705. m_pDSObjCached->aObjects[index].offsetClass = NextOffset +
  706. (strPath.GetLength() + 1) * sizeof(TCHAR);
  707. _tcscpy((LPTSTR)((BYTE *)m_pDSObjCached + NextOffset), strPath);
  708. NextOffset += (strPath.GetLength() + 1) * sizeof(TCHAR);
  709. _tcscpy((LPTSTR)((BYTE *)m_pDSObjCached + NextOffset), strClass);
  710. NextOffset += (strClass.GetLength() + 1) * sizeof(TCHAR);
  711. }
  712. return S_OK;
  713. }
  714. //+----------------------------------------------------------------------------
  715. //
  716. // Method: CDSDataObject::AddCookie
  717. //
  718. // Synopsis: adds a cookie to the data object. if this is
  719. // the first cookie it goes in m_cookie, else it
  720. // goes into the cookie list m_p_cookies.
  721. //
  722. //-----------------------------------------------------------------------------
  723. void
  724. CDSDataObject::AddCookie(CUINode* pUINode)
  725. {
  726. const UINT MEM_CHUNK_SIZE = 10;
  727. void * pTMP = NULL;
  728. if (m_internal.m_cookie) { // already have a cookie
  729. if ((m_internal.m_cookie_count - 1) % MEM_CHUNK_SIZE == 0) {
  730. if (m_internal.m_p_cookies) {
  731. pTMP = realloc (m_internal.m_p_cookies,
  732. (m_internal.m_cookie_count - 1 +
  733. MEM_CHUNK_SIZE) * sizeof (CUINode *));
  734. } else {
  735. pTMP = malloc (MEM_CHUNK_SIZE * sizeof (CUINode *));
  736. }
  737. if (pTMP == NULL) {
  738. TRACE(_T("CDataObject::AddCookie - malloc/realloc failed.."));
  739. ASSERT (pTMP != NULL);
  740. }
  741. m_internal.m_p_cookies = (CUINode **)pTMP;
  742. }
  743. (*(m_internal.m_p_cookies + m_internal.m_cookie_count - 1)) = pUINode;
  744. m_internal.m_cookie_count++;
  745. } else {
  746. m_internal.m_cookie = pUINode;
  747. m_internal.m_cookie_count = 1;
  748. }
  749. }