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.

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