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.

559 lines
16 KiB

  1. // This is a part of the Microsoft Management Console.
  2. // Copyright (C) Microsoft Corporation, 1995 - 1999
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Management Console and related
  7. // electronic documentation provided with the interfaces.
  8. #include "stdafx.h"
  9. #ifdef _DEBUG
  10. #undef THIS_FILE
  11. static char THIS_FILE[] = __FILE__;
  12. #endif
  13. ///////////////////////////////////////////////////////////////////////////////
  14. // Sample code to show how to Create DataObjects
  15. // Minimal error checking for clarity
  16. ///////////////////////////////////////////////////////////////////////////////
  17. // Snap-in NodeType in both GUID format and string format
  18. // Note - Typically there is a node type for each different object, sample
  19. // only uses one node type.
  20. unsigned int CDataObject::m_cfNodeType = 0;
  21. unsigned int CDataObject::m_cfNodeID = 0;
  22. unsigned int CDataObject::m_cfCoClass = 0;
  23. unsigned int CDataObject::m_cfNodeTypeString = 0;
  24. unsigned int CDataObject::m_cfDisplayName = 0;
  25. unsigned int CDataObject::m_cfInternal = 0;
  26. unsigned int CDataObject::m_cfObjInMultiSel = 0;
  27. unsigned int CDataObject::m_cfIsMultiSel = 0;
  28. unsigned int CDataObject::m_cfPreloads = 0;
  29. // The only additional clipboard format supported is to get the workstation name.
  30. unsigned int CDataObject::m_cfSelectedCA_InstallType = 0;
  31. unsigned int CDataObject::m_cfSelectedCA_CommonName = 0;
  32. unsigned int CDataObject::m_cfSelectedCA_SanitizedName= 0;
  33. unsigned int CDataObject::m_cfSelectedCA_MachineName = 0;
  34. /////////////////////////////////////////////////////////////////////////////
  35. // CDataObject implementations
  36. CDataObject::CDataObject()
  37. {
  38. USES_CONVERSION;
  39. m_cfNodeType = RegisterClipboardFormat(CCF_NODETYPE);
  40. m_cfNodeID = RegisterClipboardFormat(CCF_COLUMN_SET_ID);
  41. m_cfCoClass = RegisterClipboardFormat(CCF_SNAPIN_CLASSID);
  42. m_cfNodeTypeString = RegisterClipboardFormat(CCF_SZNODETYPE);
  43. m_cfDisplayName = RegisterClipboardFormat(CCF_DISPLAY_NAME);
  44. m_cfInternal = RegisterClipboardFormat(SNAPIN_INTERNAL);
  45. m_cfObjInMultiSel = RegisterClipboardFormat(CCF_OBJECT_TYPES_IN_MULTI_SELECT);
  46. m_cfIsMultiSel = RegisterClipboardFormat(CCF_MMC_MULTISELECT_DATAOBJECT);
  47. m_cfPreloads = RegisterClipboardFormat(CCF_SNAPIN_PRELOADS);
  48. m_cfSelectedCA_InstallType = RegisterClipboardFormat(SNAPIN_CA_INSTALL_TYPE);
  49. m_cfSelectedCA_CommonName = RegisterClipboardFormat(SNAPIN_CA_COMMON_NAME);
  50. m_cfSelectedCA_MachineName = RegisterClipboardFormat(SNAPIN_CA_MACHINE_NAME);
  51. m_cfSelectedCA_SanitizedName = RegisterClipboardFormat(SNAPIN_CA_SANITIZED_NAME);
  52. m_pComponentData = NULL;
  53. #ifdef _DEBUG
  54. dbg_refCount = 0;
  55. #endif
  56. m_cbMultiSelData = 0;
  57. m_bMultiSelDobj = FALSE;
  58. m_dwViewID = -1;
  59. }
  60. STDMETHODIMP CDataObject::QueryGetData(LPFORMATETC lpFormatetc)
  61. {
  62. HRESULT hr = S_FALSE;
  63. if ( lpFormatetc )
  64. {
  65. const CLIPFORMAT cf = lpFormatetc->cfFormat;
  66. if ( cf == m_cfIsMultiSel )
  67. {
  68. hr = S_FALSE; // always return this; MMC returns S_OK if ptr to SI_MS_DO
  69. // hr = (m_bMultiSelDobj ? S_OK : S_FALSE);
  70. }
  71. else if ( cf == m_cfNodeType ||
  72. cf == m_cfNodeID ||
  73. cf == m_cfCoClass ||
  74. cf == m_cfNodeTypeString ||
  75. cf == m_cfDisplayName ||
  76. cf == m_cfObjInMultiSel ||
  77. cf == m_cfInternal ||
  78. cf == m_cfPreloads ||
  79. cf == m_cfSelectedCA_SanitizedName ||
  80. cf == m_cfSelectedCA_MachineName ||
  81. cf == m_cfSelectedCA_CommonName ||
  82. cf == m_cfSelectedCA_InstallType
  83. )
  84. {
  85. hr = S_OK;
  86. }
  87. }
  88. return hr;
  89. }
  90. STDMETHODIMP CDataObject::GetData(LPFORMATETC lpFormatetc, LPSTGMEDIUM lpMedium)
  91. {
  92. HRESULT hr = DV_E_CLIPFORMAT;
  93. const CLIPFORMAT cf = lpFormatetc->cfFormat;
  94. if (cf == m_cfObjInMultiSel)
  95. {
  96. hr = CreateObjInMultiSel(lpMedium);
  97. }
  98. else if (cf == m_cfNodeID)
  99. {
  100. hr = CreateNodeIDData(lpMedium);
  101. }
  102. return hr;
  103. }
  104. STDMETHODIMP CDataObject::GetDataHere(LPFORMATETC lpFormatetc, LPSTGMEDIUM lpMedium)
  105. {
  106. HRESULT hr = DV_E_CLIPFORMAT;
  107. // Based on the CLIPFORMAT write data to the stream
  108. const CLIPFORMAT cf = lpFormatetc->cfFormat;
  109. if (cf == m_cfNodeType)
  110. {
  111. hr = CreateNodeTypeData(lpMedium);
  112. }
  113. else if (cf == m_cfCoClass)
  114. {
  115. hr = CreateCoClassID(lpMedium);
  116. }
  117. else if(cf == m_cfNodeTypeString)
  118. {
  119. hr = CreateNodeTypeStringData(lpMedium);
  120. }
  121. else if (cf == m_cfDisplayName)
  122. {
  123. hr = CreateDisplayName(lpMedium);
  124. }
  125. else if (cf == m_cfInternal)
  126. {
  127. hr = CreateInternal(lpMedium);
  128. }
  129. else if (cf == m_cfPreloads)
  130. {
  131. hr = CreatePreloadsData(lpMedium);
  132. }
  133. else if (cf == m_cfSelectedCA_CommonName)
  134. {
  135. hr = CreateSelectedCA_CommonName(lpMedium);
  136. }
  137. else if (cf == m_cfSelectedCA_SanitizedName)
  138. {
  139. hr = CreateSelectedCA_SanitizedName(lpMedium);
  140. }
  141. else if (cf == m_cfSelectedCA_MachineName)
  142. {
  143. hr = CreateSelectedCA_MachineName(lpMedium);
  144. }
  145. else if (cf == m_cfSelectedCA_InstallType)
  146. {
  147. hr = CreateSelectedCA_InstallType(lpMedium);
  148. }
  149. return hr;
  150. }
  151. STDMETHODIMP CDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC* ppEnumFormatEtc)
  152. {
  153. return E_NOTIMPL;
  154. }
  155. /////////////////////////////////////////////////////////////////////////////
  156. // CDataObject creation members
  157. HRESULT CDataObject::Create(const void* pBuffer, int len, LPSTGMEDIUM lpMedium)
  158. {
  159. HRESULT hr = DV_E_TYMED;
  160. // Do some simple validation
  161. if (pBuffer == NULL || lpMedium == NULL)
  162. return E_POINTER;
  163. // Make sure the type medium is HGLOBAL
  164. if (lpMedium->tymed == TYMED_HGLOBAL)
  165. {
  166. // Create the stream on the hGlobal passed in
  167. LPSTREAM lpStream;
  168. hr = CreateStreamOnHGlobal(lpMedium->hGlobal, FALSE, &lpStream);
  169. if (SUCCEEDED(hr))
  170. {
  171. ULONG written;
  172. if (NULL == lpMedium->hGlobal)
  173. {
  174. // always return a valid hGlobal for the caller
  175. hr = GetHGlobalFromStream(lpStream, &lpMedium->hGlobal);
  176. if (hr != S_OK)
  177. goto err;
  178. }
  179. // Write to the stream the number of bytes
  180. hr = lpStream->Write(pBuffer, len, &written);
  181. // Because we told CreateStreamOnHGlobal with 'FALSE',
  182. // only the stream is released here.
  183. // Note - the caller (i.e. snap-in, object) will free the HGLOBAL
  184. // at the correct time. This is according to the IDataObject specification.
  185. lpStream->Release();
  186. }
  187. }
  188. err:
  189. return hr;
  190. }
  191. HRESULT CDataObject::CreateVariableLen(const void* pBuffer, int len, LPSTGMEDIUM lpMedium)
  192. {
  193. HRESULT hr = DV_E_TYMED;
  194. BYTE* pb;
  195. // Do some simple validation
  196. if (pBuffer == NULL || lpMedium == NULL)
  197. {
  198. hr = E_POINTER;
  199. _JumpError(hr, Ret, "Invalid args");
  200. }
  201. // Make sure the type medium is HGLOBAL
  202. lpMedium->tymed = TYMED_HGLOBAL;
  203. lpMedium->hGlobal = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, (len));
  204. _JumpIfOutOfMemory(hr, Ret, lpMedium->hGlobal);
  205. pb = reinterpret_cast<BYTE*>(::GlobalLock(lpMedium->hGlobal));
  206. CopyMemory(pb, pBuffer, len);
  207. ::GlobalUnlock(lpMedium->hGlobal);
  208. hr = S_OK;
  209. Ret:
  210. return hr;
  211. }
  212. const GUID* FolderTypeToNodeGUID(DATA_OBJECT_TYPES type, CFolder* pFolder)
  213. {
  214. const GUID* pcObjectType = NULL;
  215. if (pFolder == NULL)
  216. {
  217. pcObjectType = &cNodeTypeMachineInstance;
  218. }
  219. else if (type == CCT_SCOPE)
  220. {
  221. switch (pFolder->GetType())
  222. {
  223. case SERVER_INSTANCE:
  224. pcObjectType = &cNodeTypeServerInstance;
  225. break;
  226. case SERVERFUNC_CRL_PUBLICATION:
  227. pcObjectType = &cNodeTypeCRLPublication;
  228. break;
  229. case SERVERFUNC_ISSUED_CERTIFICATES:
  230. pcObjectType = &cNodeTypeIssuedCerts;
  231. break;
  232. case SERVERFUNC_PENDING_CERTIFICATES:
  233. pcObjectType = &cNodeTypePendingCerts;
  234. break;
  235. case SERVERFUNC_FAILED_CERTIFICATES:
  236. pcObjectType = &cNodeTypeFailedCerts;
  237. break;
  238. case SERVERFUNC_ALIEN_CERTIFICATES:
  239. pcObjectType = &cNodeTypeAlienCerts;
  240. break;
  241. default:
  242. ASSERT(0);
  243. pcObjectType = &cNodeTypeDynamic;
  244. break;
  245. }
  246. }
  247. else if (type == CCT_RESULT)
  248. {
  249. // RESULT_DATA* pData = reinterpret_cast<RESULT_DATA*>(m_internal.m_cookie);
  250. pcObjectType = &cObjectTypeResultItem;
  251. }
  252. else
  253. {
  254. ASSERT(0);
  255. }
  256. return pcObjectType;
  257. }
  258. HRESULT CDataObject::CreateNodeIDData(LPSTGMEDIUM lpMedium)
  259. {
  260. // Create the node type object in GUID format
  261. const GUID* pFolderGuid = NULL;
  262. PBYTE pbWritePtr;
  263. // Instance guid, node guid, dwViewIndex
  264. #define CDO_CNID_SIZE ( (2*sizeof(GUID))+ sizeof(DWORD) + FIELD_OFFSET(SNodeID2, id) )
  265. BYTE bSNodeID2[CDO_CNID_SIZE];
  266. ZeroMemory(&bSNodeID2, CDO_CNID_SIZE);
  267. SNodeID2* psColID = (SNodeID2*)bSNodeID2;
  268. pFolderGuid = FolderTypeToNodeGUID(m_internal.m_type, reinterpret_cast<CFolder*>(m_internal.m_cookie));
  269. if (pFolderGuid == NULL)
  270. return E_FAIL;
  271. if (m_pComponentData == NULL)
  272. return E_FAIL;
  273. // node ID is {GUIDInstance|GUIDNode}
  274. psColID->cBytes = 2*sizeof(GUID) + sizeof(DWORD);
  275. pbWritePtr = psColID->id;
  276. CopyMemory(pbWritePtr, &m_pComponentData->m_guidInstance, sizeof(GUID));
  277. pbWritePtr += sizeof(GUID);
  278. CopyMemory(pbWritePtr, pFolderGuid, sizeof(GUID));
  279. pbWritePtr += sizeof(GUID);
  280. // ASSERT(m_dwViewID != -1);
  281. // UNDONE UNDONE: MMC will soon call for this data through IComponent, not IComponentData
  282. // this will allow us to set this as we desire
  283. *(DWORD*)pbWritePtr = m_dwViewID;
  284. // copy structure only
  285. return CreateVariableLen(reinterpret_cast<const void*>(psColID), CDO_CNID_SIZE, lpMedium);
  286. }
  287. HRESULT CDataObject::CreateObjInMultiSel(LPSTGMEDIUM lpMedium)
  288. {
  289. HRESULT hr;
  290. ASSERT(m_cbMultiSelData != 0);
  291. ASSERT(m_internal.m_cookie == MMC_MULTI_SELECT_COOKIE);
  292. if (m_internal.m_cookie != MMC_MULTI_SELECT_COOKIE)
  293. return E_FAIL;
  294. // copy guid + len
  295. hr = CreateVariableLen(&m_sGuidObjTypes, m_cbMultiSelData, lpMedium);
  296. //Ret:
  297. return hr;
  298. }
  299. HRESULT CDataObject::CreateNodeTypeData(LPSTGMEDIUM lpMedium)
  300. {
  301. // Create the node type object in GUID format
  302. const GUID* pcObjectType = NULL;
  303. pcObjectType = FolderTypeToNodeGUID(m_internal.m_type, reinterpret_cast<CFolder*>(m_internal.m_cookie));
  304. if (pcObjectType == NULL)
  305. return E_FAIL;
  306. return Create(reinterpret_cast<const void*>(pcObjectType), sizeof(GUID),
  307. lpMedium);
  308. }
  309. HRESULT CDataObject::CreateNodeTypeStringData(LPSTGMEDIUM lpMedium)
  310. {
  311. // Create the node type object in GUID string format
  312. const WCHAR* cszObjectType = NULL;
  313. if (m_internal.m_cookie == NULL)
  314. {
  315. cszObjectType = cszNodeTypeMachineInstance;
  316. }
  317. else if (m_internal.m_type == CCT_SCOPE)
  318. {
  319. CFolder* pFolder = reinterpret_cast<CFolder*>(m_internal.m_cookie);
  320. ASSERT(pFolder != NULL);
  321. if (pFolder == NULL)
  322. return E_UNEXPECTED;
  323. switch (pFolder->GetType())
  324. {
  325. case SERVER_INSTANCE:
  326. cszObjectType = cszNodeTypeServerInstance;
  327. break;
  328. case SERVERFUNC_CRL_PUBLICATION:
  329. cszObjectType = cszNodeTypeCRLPublication;
  330. break;
  331. case SERVERFUNC_ISSUED_CERTIFICATES:
  332. cszObjectType = cszNodeTypeIssuedCerts;
  333. break;
  334. case SERVERFUNC_PENDING_CERTIFICATES:
  335. cszObjectType = cszNodeTypePendingCerts;
  336. break;
  337. case SERVERFUNC_FAILED_CERTIFICATES:
  338. cszObjectType = cszNodeTypeFailedCerts;
  339. break;
  340. default:
  341. ASSERT(0);
  342. cszObjectType = cszNodeTypeDynamic;
  343. break;
  344. }
  345. }
  346. else if (m_internal.m_type == CCT_RESULT)
  347. {
  348. // RESULT_DATA* pData = reinterpret_cast<RESULT_DATA*>(m_internal.m_cookie);
  349. cszObjectType = cszObjectTypeResultItem;
  350. }
  351. else
  352. return E_UNEXPECTED;
  353. return Create(cszObjectType, ((wcslen(cszObjectType)+1) * sizeof(WCHAR)), lpMedium);
  354. }
  355. HRESULT CDataObject::CreateDisplayName(LPSTGMEDIUM lpMedium)
  356. {
  357. // This is the display named used in the scope pane and snap-in manager
  358. // Load the name to display
  359. // Note - if this is not provided, the console will used the snap-in name
  360. CString strFormat, strMachine, strFinished;
  361. strFormat.LoadString(IDS_NODENAME_FORMAT);
  362. if (NULL == m_pComponentData)
  363. return E_POINTER;
  364. if (m_pComponentData->m_pCertMachine->m_strMachineName.IsEmpty())
  365. strMachine.LoadString(IDS_LOCALMACHINE);
  366. else
  367. strMachine = m_pComponentData->m_pCertMachine->m_strMachineName;
  368. strFinished.Format(strFormat, strMachine);
  369. return Create(strFinished, ((strFinished.GetLength()+1)* sizeof(WCHAR)), lpMedium);
  370. }
  371. HRESULT CDataObject::CreateInternal(LPSTGMEDIUM lpMedium)
  372. {
  373. return Create(&m_internal, sizeof(INTERNAL), lpMedium);
  374. }
  375. HRESULT CDataObject::CreateSelectedCA_CommonName(LPSTGMEDIUM lpMedium)
  376. {
  377. CertSvrCA* pCA = NULL;
  378. CFolder* pFolder = GetParentFolder(&m_internal);
  379. ASSERT(pFolder != NULL);
  380. if (pFolder == NULL)
  381. return E_UNEXPECTED;
  382. pCA = pFolder->GetCA();
  383. ASSERT(pCA != NULL);
  384. ASSERT(pCA->m_strCommonName.GetLength() != 0);
  385. // Add 1 for the NULL and calculate the bytes for the stream
  386. return Create(pCA->m_strCommonName, ((pCA->m_strCommonName.GetLength()+1)*sizeof(WCHAR)), lpMedium);
  387. }
  388. HRESULT CDataObject::CreateSelectedCA_SanitizedName(LPSTGMEDIUM lpMedium)
  389. {
  390. CertSvrCA* pCA = NULL;
  391. CFolder* pFolder = GetParentFolder(&m_internal);
  392. ASSERT(pFolder != NULL);
  393. if (pFolder == NULL)
  394. return E_UNEXPECTED;
  395. pCA = pFolder->GetCA();
  396. ASSERT(pCA != NULL);
  397. ASSERT(pCA->m_strSanitizedName.GetLength() != 0);
  398. // Add 1 for the NULL and calculate the bytes for the stream
  399. return Create(pCA->m_strSanitizedName, ((pCA->m_strSanitizedName.GetLength()+1)* sizeof(WCHAR)), lpMedium);
  400. }
  401. HRESULT CDataObject::CreateSelectedCA_MachineName(LPSTGMEDIUM lpMedium)
  402. {
  403. CertSvrCA* pCA = NULL;
  404. CFolder* pFolder = GetParentFolder(&m_internal);
  405. ASSERT(pFolder != NULL);
  406. if (pFolder == NULL)
  407. return E_UNEXPECTED;
  408. pCA = pFolder->GetCA();
  409. ASSERT(pCA != NULL);
  410. // Add 1 for the NULL and calculate the bytes for the stream
  411. return Create(pCA->m_strServer, ((pCA->m_strServer.GetLength()+1)* sizeof(WCHAR)), lpMedium);
  412. }
  413. HRESULT CDataObject::CreateSelectedCA_InstallType(LPSTGMEDIUM lpMedium)
  414. {
  415. CertSvrCA* pCA = NULL;
  416. CFolder* pFolder = GetParentFolder(&m_internal);
  417. ASSERT(pFolder != NULL);
  418. if (pFolder == NULL)
  419. return E_UNEXPECTED;
  420. pCA = pFolder->GetCA();
  421. ASSERT(pCA != NULL);
  422. DWORD dwFlags[2] =
  423. {
  424. (DWORD) pCA->GetCAType(),
  425. (DWORD) pCA->FIsAdvancedServer(),
  426. };
  427. return Create(&dwFlags, sizeof(dwFlags), lpMedium);
  428. }
  429. HRESULT CDataObject::CreateCoClassID(LPSTGMEDIUM lpMedium)
  430. {
  431. // Create the CoClass information
  432. return Create(reinterpret_cast<const void*>(&m_internal.m_clsid), sizeof(CLSID), lpMedium);
  433. }
  434. HRESULT CDataObject::CreatePreloadsData(LPSTGMEDIUM lpMedium)
  435. {
  436. BOOL bPreload = TRUE;
  437. return Create((LPVOID)&bPreload, sizeof(bPreload), lpMedium);
  438. }