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.

550 lines
14 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997-2001.
  5. //
  6. // File: DataObj.cpp
  7. //
  8. // Contents: Implementation of data object classes: CCertTemplatesDataObject
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. USE_HANDLE_MACROS("CERTTMPL(dataobj.cpp)")
  13. #include "compdata.h"
  14. #include "dataobj.h"
  15. #include "uuids.h"
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. #include "stddtobj.cpp"
  22. // IDataObject interface implementation
  23. CCertTemplatesDataObject::CCertTemplatesDataObject()
  24. : m_pCookie (0),
  25. m_objecttype (CERTTMPL_SNAPIN),
  26. m_dataobjecttype (CCT_UNINITIALIZED),
  27. m_pbMultiSelData(NULL),
  28. m_cbMultiSelData(0),
  29. m_bMultiSelDobj(false),
  30. m_iCurr(0)
  31. {
  32. }
  33. HRESULT CCertTemplatesDataObject::GetDataHere(
  34. FORMATETC __RPC_FAR *pFormatEtcIn,
  35. STGMEDIUM __RPC_FAR *pMedium)
  36. {
  37. const CLIPFORMAT cf=pFormatEtcIn->cfFormat;
  38. if (cf == m_CFNodeType)
  39. {
  40. if ( IsValidObjectType (m_pCookie->m_objecttype) )
  41. {
  42. const GUID* pguid = GetObjectTypeGUID( m_pCookie->m_objecttype );
  43. stream_ptr s(pMedium);
  44. return s.Write(pguid, sizeof(GUID));
  45. }
  46. else
  47. return E_UNEXPECTED;
  48. }
  49. else if (cf == m_CFSnapInCLSID)
  50. {
  51. stream_ptr s(pMedium);
  52. return s.Write(&m_SnapInCLSID, sizeof(GUID));
  53. }
  54. else if (cf == m_CFNodeTypeString)
  55. {
  56. if ( IsValidObjectType (m_pCookie->m_objecttype) )
  57. {
  58. const BSTR strGUID = GetObjectTypeString( m_pCookie->m_objecttype );
  59. stream_ptr s(pMedium);
  60. return s.Write(strGUID);
  61. }
  62. else
  63. return E_UNEXPECTED;
  64. }
  65. else if (cf == m_CFDisplayName)
  66. {
  67. return PutDisplayName(pMedium);
  68. }
  69. else if (cf == m_CFDataObjectType)
  70. {
  71. stream_ptr s(pMedium);
  72. return s.Write(&m_dataobjecttype, sizeof(m_dataobjecttype));
  73. }
  74. else if (cf == m_CFRawCookie)
  75. {
  76. stream_ptr s(pMedium);
  77. if ( m_pCookie )
  78. {
  79. // CODEWORK This cast ensures that the data format is
  80. // always a CCookie*, even for derived subclasses
  81. if ( ((CCertTmplCookie*) MMC_MULTI_SELECT_COOKIE) == m_pCookie ||
  82. IsValidObjectType (m_pCookie->m_objecttype) )
  83. {
  84. CCookie* pcookie = (CCookie*) m_pCookie;
  85. return s.Write(reinterpret_cast<PBYTE>(&pcookie), sizeof(m_pCookie));
  86. }
  87. else
  88. return E_UNEXPECTED;
  89. }
  90. }
  91. else if ( cf == m_CFMultiSel )
  92. {
  93. return CreateMultiSelectObject (pMedium);
  94. }
  95. else if (cf == m_CFSnapinPreloads)
  96. {
  97. stream_ptr s(pMedium);
  98. // If this is TRUE, then the next time this snapin is loaded, it will
  99. // be preloaded to give us the opportunity to change the root node
  100. // name before the user sees it.
  101. BOOL x = 1;
  102. return s.Write (reinterpret_cast<PBYTE>(&x), sizeof (BOOL));
  103. }
  104. return DV_E_FORMATETC;
  105. }
  106. HRESULT CCertTemplatesDataObject::Initialize(
  107. CCertTmplCookie* pcookie,
  108. DATA_OBJECT_TYPES type,
  109. CCertTmplComponentData& refComponentData)
  110. {
  111. if ( !pcookie || m_pCookie )
  112. {
  113. ASSERT(FALSE);
  114. return S_OK; // Initialize must not fail
  115. }
  116. m_dataobjecttype = type;
  117. m_pCookie = pcookie;
  118. if ( ((CCertTmplCookie*) MMC_MULTI_SELECT_COOKIE) != m_pCookie )
  119. ((CRefcountedObject*)m_pCookie)->AddRef();
  120. VERIFY( SUCCEEDED(refComponentData.GetClassID(&m_SnapInCLSID)) );
  121. return S_OK;
  122. }
  123. CCertTemplatesDataObject::~CCertTemplatesDataObject()
  124. {
  125. if ( ((CCertTmplCookie*) MMC_MULTI_SELECT_COOKIE) != m_pCookie &&
  126. m_pCookie && IsValidObjectType (m_pCookie->m_objecttype) )
  127. {
  128. ((CRefcountedObject*)m_pCookie)->Release();
  129. }
  130. if (m_pbMultiSelData)
  131. delete m_pbMultiSelData;
  132. for (int i=0; i < m_rgCookies.GetSize(); ++i)
  133. {
  134. m_rgCookies[i]->Release();
  135. m_rgCookies[i] = 0;
  136. }
  137. }
  138. void CCertTemplatesDataObject::AddCookie(CCertTmplCookie* pCookie)
  139. {
  140. m_rgCookies.Add(pCookie);
  141. pCookie->AddRef();
  142. }
  143. HRESULT CCertTemplatesDataObject::PutDisplayName(STGMEDIUM* pMedium)
  144. // Writes the "friendly name" to the provided storage medium
  145. // Returns the result of the write operation
  146. {
  147. AFX_MANAGE_STATE (AfxGetStaticModuleState ());
  148. CString strDomainName = m_pCookie->GetManagedDomainDNSName();
  149. stream_ptr s (pMedium);
  150. CString snapinName;
  151. snapinName.FormatMessage (IDS_CERTTMPL_ROOT_NODE_NAME, strDomainName);
  152. return s.Write ((PCWSTR) snapinName);
  153. }
  154. // Register the clipboard formats
  155. CLIPFORMAT CCertTemplatesDataObject::m_CFDisplayName =
  156. (CLIPFORMAT)RegisterClipboardFormat(CCF_DISPLAY_NAME);
  157. CLIPFORMAT CDataObject::m_CFRawCookie =
  158. (CLIPFORMAT)RegisterClipboardFormat(L"CERTTMPL_SNAPIN_RAW_COOKIE");
  159. CLIPFORMAT CCertTemplatesDataObject::m_CFMultiSel =
  160. (CLIPFORMAT)RegisterClipboardFormat(CCF_OBJECT_TYPES_IN_MULTI_SELECT);
  161. CLIPFORMAT CCertTemplatesDataObject::m_CFMultiSelDobj =
  162. (CLIPFORMAT)RegisterClipboardFormat(CCF_MMC_MULTISELECT_DATAOBJECT);
  163. CLIPFORMAT CCertTemplatesDataObject::m_CFMultiSelDataObjs =
  164. (CLIPFORMAT)RegisterClipboardFormat(CCF_MULTI_SELECT_SNAPINS);
  165. CLIPFORMAT CCertTemplatesDataObject::m_CFDsObjectNames =
  166. (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSOBJECTNAMES);
  167. void CCertTemplatesDataObject::SetMultiSelData(BYTE* pbMultiSelData, UINT cbMultiSelData)
  168. {
  169. m_pbMultiSelData = pbMultiSelData;
  170. m_cbMultiSelData = cbMultiSelData;
  171. }
  172. ///////////////////////////////////////////////////////////////////////////////
  173. ///////////////////////////////////////////////////////////////////////////////
  174. STDMETHODIMP CCertTmplComponentData::QueryDataObject (
  175. MMC_COOKIE cookie,
  176. DATA_OBJECT_TYPES type,
  177. LPDATAOBJECT* ppDataObject)
  178. {
  179. if ( MMC_MULTI_SELECT_COOKIE == cookie )
  180. {
  181. return QueryMultiSelectDataObject (cookie, type, ppDataObject);
  182. }
  183. CCertTmplCookie* pUseThisCookie =
  184. (CCertTmplCookie*) ActiveBaseCookie (
  185. reinterpret_cast<CCookie*> (cookie));
  186. CComObject<CCertTemplatesDataObject>* pDataObject = 0;
  187. HRESULT hRes = CComObject<CCertTemplatesDataObject>::CreateInstance(&pDataObject);
  188. if ( FAILED(hRes) )
  189. return hRes;
  190. HRESULT hr = pDataObject->Initialize (
  191. pUseThisCookie,
  192. type,
  193. *this);
  194. if ( FAILED(hr) )
  195. {
  196. delete pDataObject;
  197. return hr;
  198. }
  199. pDataObject->AddRef();
  200. *ppDataObject = pDataObject;
  201. return hr;
  202. }
  203. typedef CArray<GUID, const GUID&> CGUIDArray;
  204. void GuidArray_Add(CGUIDArray& rgGuids, const GUID& guid)
  205. {
  206. for (INT_PTR i=rgGuids.GetUpperBound(); i >= 0; --i)
  207. {
  208. if (rgGuids[i] == guid)
  209. break;
  210. }
  211. if (i < 0)
  212. rgGuids.Add(guid);
  213. }
  214. HRESULT CCertTmplComponentData::QueryMultiSelectDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type,
  215. LPDATAOBJECT* ppDataObject)
  216. {
  217. ASSERT(ppDataObject != NULL);
  218. if (ppDataObject == NULL)
  219. return E_POINTER;
  220. HRESULT hr = S_OK;
  221. CGUIDArray rgGuids;
  222. // Determine the items selected
  223. ASSERT(m_pResultData != NULL);
  224. RESULTDATAITEM rdi;
  225. ZeroMemory(&rdi, sizeof(rdi));
  226. rdi.mask = RDI_STATE;
  227. rdi.nIndex = -1;
  228. rdi.nState = TVIS_SELECTED;
  229. CCookiePtrArray rgCookiesSelected;
  230. while (m_pResultData->GetNextItem (&rdi) == S_OK)
  231. {
  232. const GUID* pguid;
  233. CCertTmplCookie* pCookie = reinterpret_cast <CCertTmplCookie*> (rdi.lParam);
  234. if ( pCookie )
  235. {
  236. rgCookiesSelected.Add (pCookie);
  237. switch (pCookie->m_objecttype)
  238. {
  239. case CERTTMPL_CERT_TEMPLATE:
  240. pguid = &NODEID_CertTmpl_CERT_TEMPLATE;
  241. break;
  242. default:
  243. ASSERT (0);
  244. continue;
  245. }
  246. }
  247. else
  248. {
  249. hr = E_INVALIDARG;
  250. break;
  251. }
  252. GuidArray_Add(rgGuids, *pguid);
  253. }
  254. CComObject<CCertTemplatesDataObject>* pObject;
  255. CComObject<CCertTemplatesDataObject>::CreateInstance(&pObject);
  256. ASSERT(pObject != NULL);
  257. // Save cookie and type for delayed rendering
  258. pObject->Initialize ((CCertTmplCookie*) cookie,
  259. type,
  260. *this);
  261. pObject->SetMultiSelDobj();
  262. // Store the coclass with the data object
  263. UINT cb = (UINT)(rgGuids.GetSize() * sizeof(GUID));
  264. GUID* pGuid = new GUID[(UINT)rgGuids.GetSize()];
  265. CopyMemory(pGuid, rgGuids.GetData(), cb);
  266. pObject->SetMultiSelData((BYTE*)pGuid, cb);
  267. for (int i=0; i < rgCookiesSelected.GetSize(); ++i)
  268. {
  269. pObject->AddCookie(rgCookiesSelected[i]);
  270. }
  271. return pObject->QueryInterface(
  272. IID_PPV_ARG (IDataObject, ppDataObject));
  273. }
  274. //+--------------------------------------------------------------------------
  275. //
  276. // Member: CDataObject::Create
  277. //
  278. // Synopsis: Fill the hGlobal in [lpmedium] with the data in pBuffer
  279. //
  280. // Arguments: [pBuffer] - [in] the data to be written
  281. // [len] - [in] the length of that data
  282. // [pMedium] - [in,out] where to store the data
  283. // History:
  284. //
  285. //---------------------------------------------------------------------------
  286. HRESULT CCertTemplatesDataObject::Create (const void* pBuffer, int len, LPSTGMEDIUM pMedium)
  287. {
  288. HRESULT hr = DV_E_TYMED;
  289. //
  290. // Do some simple validation
  291. //
  292. if (pBuffer == NULL || pMedium == NULL)
  293. return E_POINTER;
  294. //
  295. // Make sure the type medium is HGLOBAL
  296. //
  297. if (pMedium->tymed == TYMED_HGLOBAL) {
  298. //
  299. // Create the stream on the hGlobal passed in
  300. //
  301. LPSTREAM lpStream = 0;
  302. hr = CreateStreamOnHGlobal(pMedium->hGlobal, FALSE, &lpStream);
  303. ASSERT (SUCCEEDED (hr));
  304. if (SUCCEEDED(hr))
  305. {
  306. //
  307. // Write to the stream the number of bytes
  308. //
  309. ULONG written = 0;
  310. hr = lpStream->Write(pBuffer, len, &written);
  311. ASSERT (SUCCEEDED (hr));
  312. //
  313. // Because we told CreateStreamOnHGlobal with 'FALSE',
  314. // only the stream is released here.
  315. // Note - the caller (i.e. snap-in, object) will free the HGLOBAL
  316. // at the correct time. This is according to the IDataObject specification.
  317. //
  318. lpStream->Release();
  319. }
  320. }
  321. return hr;
  322. }
  323. //+----------------------------------------------------------------------------
  324. //
  325. // Method: CCertTemplatesDataObject::CreateMultiSelectObject
  326. //
  327. // Synopsis: this is to create the list of types selected
  328. //
  329. //-----------------------------------------------------------------------------
  330. HRESULT CCertTemplatesDataObject::CreateMultiSelectObject(LPSTGMEDIUM pMedium)
  331. {
  332. ASSERT(m_pbMultiSelData != 0);
  333. ASSERT(m_cbMultiSelData != 0);
  334. pMedium->tymed = TYMED_HGLOBAL;
  335. pMedium->hGlobal = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE,
  336. (m_cbMultiSelData + sizeof(DWORD)));
  337. if (pMedium->hGlobal == NULL)
  338. return STG_E_MEDIUMFULL;
  339. BYTE* pb = reinterpret_cast<BYTE*>(::GlobalLock(pMedium->hGlobal));
  340. *((DWORD*)pb) = m_cbMultiSelData / sizeof(GUID);
  341. pb += sizeof(DWORD);
  342. CopyMemory(pb, m_pbMultiSelData, m_cbMultiSelData);
  343. ::GlobalUnlock(pMedium->hGlobal);
  344. return S_OK;
  345. }
  346. LPDATAOBJECT ExtractMultiSelect (LPDATAOBJECT lpDataObject)
  347. {
  348. if (lpDataObject == NULL)
  349. return NULL;
  350. SMMCDataObjects * pDO = NULL;
  351. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  352. FORMATETC formatetc = { CCertTemplatesDataObject::m_CFMultiSelDataObjs, NULL,
  353. DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  354. if ( FAILED (lpDataObject->GetData (&formatetc, &stgmedium)) )
  355. {
  356. return NULL;
  357. }
  358. else
  359. {
  360. pDO = reinterpret_cast<SMMCDataObjects*>(stgmedium.hGlobal);
  361. return pDO->lpDataObject[0]; //assume that ours is the 1st
  362. }
  363. }
  364. STDMETHODIMP CCertTemplatesDataObject::GetData(LPFORMATETC lpFormatetc, LPSTGMEDIUM pMedium)
  365. {
  366. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  367. HRESULT hr = DV_E_CLIPFORMAT;
  368. if (lpFormatetc->cfFormat == m_CFMultiSel)
  369. {
  370. ASSERT(((CCertTmplCookie*) MMC_MULTI_SELECT_COOKIE) == m_pCookie);
  371. if ( ((CCertTmplCookie*) MMC_MULTI_SELECT_COOKIE) != m_pCookie )
  372. return E_FAIL;
  373. hr = CreateMultiSelectObject (pMedium);
  374. }
  375. else if ( lpFormatetc->cfFormat == m_CFDsObjectNames )
  376. {
  377. switch (m_pCookie->m_objecttype)
  378. {
  379. case CERTTMPL_CERT_TEMPLATE:
  380. {
  381. CCertTemplate* pCertTemplate = dynamic_cast <CCertTemplate*> (m_pCookie);
  382. ASSERT (pCertTemplate);
  383. if ( pCertTemplate )
  384. {
  385. // figure out how much storage we need
  386. CString adsiPath;
  387. adsiPath = pCertTemplate->GetLDAPPath ();
  388. int cbPath = sizeof (WCHAR) * (adsiPath.GetLength() + 1);
  389. int cbClass = sizeof (WCHAR) * (pCertTemplate->GetClass ().GetLength() + 1);;
  390. int cbStruct = sizeof(DSOBJECTNAMES); //contains already a DSOBJECT embedded struct
  391. LPDSOBJECTNAMES pDSObj = 0;
  392. pDSObj = (LPDSOBJECTNAMES)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
  393. cbStruct + cbPath + cbClass);
  394. if ( pDSObj )
  395. {
  396. // write the info
  397. pDSObj->clsidNamespace = CLSID_CertTemplatesSnapin;
  398. pDSObj->cItems = 1;
  399. pDSObj->aObjects[0].dwFlags = 0;
  400. pDSObj->aObjects[0].dwProviderFlags = 0;
  401. pDSObj->aObjects[0].offsetName = cbStruct;
  402. pDSObj->aObjects[0].offsetClass = cbStruct + cbPath;
  403. wcscpy((LPWSTR)((BYTE *)pDSObj + (pDSObj->aObjects[0].offsetName)),
  404. (LPCWSTR) adsiPath);
  405. wcscpy((LPWSTR)((BYTE *)pDSObj + (pDSObj->aObjects[0].offsetClass)),
  406. (LPCWSTR) pCertTemplate->GetClass ());
  407. pMedium->hGlobal = (HGLOBAL)pDSObj;
  408. pMedium->tymed = TYMED_HGLOBAL;
  409. pMedium->pUnkForRelease = NULL;
  410. hr = S_OK;
  411. }
  412. else
  413. hr = STG_E_MEDIUMFULL;
  414. }
  415. }
  416. break;
  417. default:
  418. break;
  419. }
  420. }
  421. return hr;
  422. }
  423. STDMETHODIMP CCertTemplatesDataObject::Next(ULONG celt, MMC_COOKIE* rgelt, ULONG *pceltFetched)
  424. {
  425. HRESULT hr = S_OK;
  426. if ((rgelt == NULL) ||
  427. ((celt > 1) && (pceltFetched == NULL)))
  428. {
  429. hr = E_INVALIDARG;
  430. return hr;
  431. }
  432. ULONG celtTemp = (ULONG)(m_rgCookies.GetSize() - m_iCurr);
  433. celtTemp = (celt < celtTemp) ? celt : celtTemp;
  434. if (pceltFetched)
  435. *pceltFetched = celtTemp;
  436. if (celtTemp == 0)
  437. return S_FALSE;
  438. for (ULONG i=0; i < celtTemp; ++i)
  439. {
  440. rgelt[i] = reinterpret_cast<MMC_COOKIE>(m_rgCookies[m_iCurr++]);
  441. }
  442. return (celtTemp < celt) ? S_FALSE : S_OK;
  443. }
  444. STDMETHODIMP CCertTemplatesDataObject::Skip(ULONG celt)
  445. {
  446. ULONG celtTemp = (ULONG)(m_rgCookies.GetSize() - m_iCurr);
  447. celtTemp = (celt < celtTemp) ? celt : celtTemp;
  448. m_iCurr += celtTemp;
  449. return (celtTemp < celt) ? S_FALSE : S_OK;
  450. }
  451. STDMETHODIMP CCertTemplatesDataObject::Reset(void)
  452. {
  453. m_iCurr = 0;
  454. return S_OK;
  455. }