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.

422 lines
12 KiB

  1. // This is a part of the Microsoft Management Console.
  2. // Copyright 1995 - 1997 Microsoft Corporation
  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. #include "Service.h"
  10. #include "CSnapin.h"
  11. #include "DataObj.h"
  12. #ifdef _DEBUG
  13. #define new DEBUG_NEW
  14. #undef THIS_FILE
  15. static char THIS_FILE[] = __FILE__;
  16. #endif
  17. ///////////////////////////////////////////////////////////////////////////////
  18. // Sample code to show how to Create DataObjects
  19. // Minimal error checking for clarity
  20. ///////////////////////////////////////////////////////////////////////////////
  21. // Snap-in NodeType in both GUID format and string format
  22. // Note - Typically there is a node type for each different object, sample
  23. // only uses one node type.
  24. unsigned int CDataObject::m_cfNodeType = 0;
  25. unsigned int CDataObject::m_cfNodeTypeString = 0;
  26. unsigned int CDataObject::m_cfDisplayName = 0;
  27. unsigned int CDataObject::m_cfCoClass = 0;
  28. unsigned int CDataObject::m_cfNodeID = 0;
  29. unsigned int CDataObject::m_cfInternal = 0;
  30. unsigned int CDataObject::m_cfMultiSel = 0;
  31. // Extension information
  32. // The only additional clipboard format supported is to get the workstation name.
  33. unsigned int CDataObject::m_cfWorkstation = 0;
  34. /////////////////////////////////////////////////////////////////////////////
  35. // CDataObject implementations
  36. CDataObject::CDataObject()
  37. {
  38. USES_CONVERSION;
  39. m_cfNodeType = RegisterClipboardFormat(W2T(CCF_NODETYPE));
  40. m_cfNodeTypeString = RegisterClipboardFormat(W2T(CCF_SZNODETYPE));
  41. m_cfDisplayName = RegisterClipboardFormat(W2T(CCF_DISPLAY_NAME));
  42. m_cfCoClass = RegisterClipboardFormat(W2T(CCF_SNAPIN_CLASSID));
  43. m_cfMultiSel = RegisterClipboardFormat(W2T(CCF_OBJECT_TYPES_IN_MULTI_SELECT));
  44. m_cfNodeID = RegisterClipboardFormat(W2T(CCF_NODEID));
  45. #ifdef UNICODE
  46. m_cfInternal = RegisterClipboardFormat(W2T((LPTSTR)SNAPIN_INTERNAL));
  47. m_cfWorkstation = RegisterClipboardFormat(W2T((LPTSTR)SNAPIN_WORKSTATION));
  48. #else
  49. m_cfInternal = RegisterClipboardFormat(W2T(SNAPIN_INTERNAL));
  50. m_cfWorkstation = RegisterClipboardFormat(W2T(SNAPIN_WORKSTATION));
  51. #endif //UNICODE
  52. #ifdef _DEBUG
  53. m_ComponentData = NULL;
  54. dbg_refCount = 0;
  55. #endif
  56. m_pbMultiSelData = 0;
  57. m_cbMultiSelData = 0;
  58. m_bMultiSelDobj = FALSE;
  59. }
  60. STDMETHODIMP CDataObject::GetData(LPFORMATETC lpFormatetc, LPSTGMEDIUM lpMedium)
  61. {
  62. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  63. HRESULT hr = DV_E_CLIPFORMAT;
  64. const CLIPFORMAT cf = lpFormatetc->cfFormat;
  65. if (cf == m_cfMultiSel)
  66. {
  67. ASSERT(m_internal.m_cookie == MMC_MULTI_SELECT_COOKIE);
  68. if (m_internal.m_cookie != MMC_MULTI_SELECT_COOKIE)
  69. return E_FAIL;
  70. //return CreateMultiSelData(lpMedium);
  71. ASSERT(m_pbMultiSelData != 0);
  72. ASSERT(m_cbMultiSelData != 0);
  73. lpMedium->tymed = TYMED_HGLOBAL;
  74. lpMedium->hGlobal = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE,
  75. (m_cbMultiSelData + sizeof(DWORD)));
  76. if (lpMedium->hGlobal == NULL)
  77. return STG_E_MEDIUMFULL;
  78. BYTE* pb = reinterpret_cast<BYTE*>(::GlobalLock(lpMedium->hGlobal));
  79. *((DWORD*)pb) = m_cbMultiSelData / sizeof(GUID);
  80. pb += sizeof(DWORD);
  81. CopyMemory(pb, m_pbMultiSelData, m_cbMultiSelData);
  82. ::GlobalUnlock(lpMedium->hGlobal);
  83. hr = S_OK;
  84. }
  85. #ifdef RECURSIVE_NODE_EXPANSION
  86. else if (cf == m_cfNodeID)
  87. {
  88. // Create the node type object in GUID format
  89. BYTE byData[256] = {0};
  90. SNodeID* pData = reinterpret_cast<SNodeID*>(byData);
  91. LPCTSTR pszText;
  92. if (m_internal.m_cookie == NULL)
  93. {
  94. return (E_FAIL);
  95. }
  96. else if (m_internal.m_type == CCT_SCOPE)
  97. {
  98. CFolder* pFolder = reinterpret_cast<CFolder*>(m_internal.m_cookie);
  99. ASSERT(pFolder != NULL);
  100. if (pFolder == NULL)
  101. return E_UNEXPECTED;
  102. switch (pFolder->GetType())
  103. {
  104. // save the user node as a custom node ID
  105. case USER:
  106. pszText = _T("___Custom ID for User Data node___");
  107. break;
  108. // save the company node as a string
  109. case COMPANY:
  110. return (E_FAIL);
  111. break;
  112. // truncate anything below a virtual node
  113. case VIRTUAL:
  114. pszText = _T("");
  115. break;
  116. case EXT_USER:
  117. case EXT_COMPANY:
  118. case EXT_VIRTUAL:
  119. default:
  120. return (E_FAIL);
  121. break;
  122. }
  123. }
  124. else if (m_internal.m_type == CCT_RESULT)
  125. {
  126. return (E_FAIL);
  127. }
  128. _tcscpy ((LPTSTR) pData->id, pszText);
  129. pData->cBytes = _tcslen ((LPTSTR) pData->id) * sizeof (TCHAR);
  130. int cb = pData->cBytes + sizeof (pData->cBytes);
  131. lpMedium->tymed = TYMED_HGLOBAL;
  132. lpMedium->hGlobal = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, cb);
  133. if (lpMedium->hGlobal == NULL)
  134. return STG_E_MEDIUMFULL;
  135. BYTE* pb = reinterpret_cast<BYTE*>(::GlobalLock(lpMedium->hGlobal));
  136. CopyMemory(pb, pData, cb);
  137. ::GlobalUnlock(lpMedium->hGlobal);
  138. hr = S_OK;
  139. }
  140. #endif /* RECURSIVE_NODE_EXPANSION */
  141. return hr;
  142. }
  143. STDMETHODIMP CDataObject::GetDataHere(LPFORMATETC lpFormatetc, LPSTGMEDIUM lpMedium)
  144. {
  145. HRESULT hr = DV_E_CLIPFORMAT;
  146. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  147. // Based on the CLIPFORMAT write data to the stream
  148. const CLIPFORMAT cf = lpFormatetc->cfFormat;
  149. if (cf == m_cfNodeType)
  150. {
  151. hr = CreateNodeTypeData(lpMedium);
  152. }
  153. else if (cf == m_cfCoClass)
  154. {
  155. hr = CreateCoClassID(lpMedium);
  156. }
  157. else if(cf == m_cfNodeTypeString)
  158. {
  159. hr = CreateNodeTypeStringData(lpMedium);
  160. }
  161. else if (cf == m_cfDisplayName)
  162. {
  163. hr = CreateDisplayName(lpMedium);
  164. }
  165. else if (cf == m_cfInternal)
  166. {
  167. hr = CreateInternal(lpMedium);
  168. }
  169. else if (cf == m_cfWorkstation)
  170. {
  171. hr = CreateWorkstationName(lpMedium);
  172. }
  173. return hr;
  174. }
  175. STDMETHODIMP CDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC* ppEnumFormatEtc)
  176. {
  177. return E_NOTIMPL;
  178. }
  179. /////////////////////////////////////////////////////////////////////////////
  180. // CDataObject creation members
  181. HRESULT CDataObject::Create(const void* pBuffer, int len, LPSTGMEDIUM lpMedium)
  182. {
  183. HRESULT hr = DV_E_TYMED;
  184. // Do some simple validation
  185. if (pBuffer == NULL || lpMedium == NULL)
  186. return E_POINTER;
  187. // Make sure the type medium is HGLOBAL
  188. if (lpMedium->tymed == TYMED_HGLOBAL)
  189. {
  190. // Create the stream on the hGlobal passed in
  191. LPSTREAM lpStream;
  192. hr = CreateStreamOnHGlobal(lpMedium->hGlobal, FALSE, &lpStream);
  193. if (SUCCEEDED(hr))
  194. {
  195. // Write to the stream the number of bytes
  196. unsigned long written;
  197. hr = lpStream->Write(pBuffer, len, &written);
  198. // Because we told CreateStreamOnHGlobal with 'FALSE',
  199. // only the stream is released here.
  200. // Note - the caller (i.e. snap-in, object) will free the HGLOBAL
  201. // at the correct time. This is according to the IDataObject specification.
  202. lpStream->Release();
  203. }
  204. }
  205. return hr;
  206. }
  207. HRESULT CDataObject::CreateMultiSelData(LPSTGMEDIUM lpMedium)
  208. {
  209. ASSERT(m_internal.m_cookie == MMC_MULTI_SELECT_COOKIE);
  210. ASSERT(m_pbMultiSelData != 0);
  211. ASSERT(m_cbMultiSelData != 0);
  212. return Create(reinterpret_cast<const void*>(m_pbMultiSelData),
  213. m_cbMultiSelData, lpMedium);
  214. }
  215. HRESULT CDataObject::CreateNodeTypeData(LPSTGMEDIUM lpMedium)
  216. {
  217. // Create the node type object in GUID format
  218. const GUID* pcObjectType = NULL;
  219. if (m_internal.m_cookie == NULL)
  220. {
  221. pcObjectType = &cNodeTypeStatic;
  222. }
  223. else if (m_internal.m_type == CCT_SCOPE)
  224. {
  225. CFolder* pFolder = reinterpret_cast<CFolder*>(m_internal.m_cookie);
  226. ASSERT(pFolder != NULL);
  227. if (pFolder == NULL)
  228. return E_UNEXPECTED;
  229. switch (pFolder->GetType())
  230. {
  231. case COMPANY:
  232. pcObjectType = &cNodeTypeCompany;
  233. break;
  234. case USER:
  235. pcObjectType = &cNodeTypeUser;
  236. break;
  237. case EXT_COMPANY:
  238. pcObjectType = &cNodeTypeExtCompany;
  239. break;
  240. case EXT_USER:
  241. pcObjectType = &cNodeTypeExtUser;
  242. break;
  243. case VIRTUAL:
  244. case EXT_VIRTUAL:
  245. pcObjectType = &cNodeTypeExtUser;
  246. break;
  247. default:
  248. pcObjectType = &cNodeTypeDynamic;
  249. break;
  250. }
  251. }
  252. else if (m_internal.m_type == CCT_RESULT)
  253. {
  254. // RESULT_DATA* pData = reinterpret_cast<RESULT_DATA*>(m_internal.m_cookie);
  255. pcObjectType = &cObjectTypeResultItem;
  256. }
  257. return Create(reinterpret_cast<const void*>(pcObjectType), sizeof(GUID),
  258. lpMedium);
  259. }
  260. HRESULT CDataObject::CreateNodeTypeStringData(LPSTGMEDIUM lpMedium)
  261. {
  262. // Create the node type object in GUID string format
  263. const WCHAR* cszObjectType = NULL;
  264. if (m_internal.m_cookie == NULL)
  265. {
  266. cszObjectType = cszNodeTypeStatic;
  267. }
  268. else if (m_internal.m_type == CCT_SCOPE)
  269. {
  270. CFolder* pFolder = reinterpret_cast<CFolder*>(m_internal.m_cookie);
  271. ASSERT(pFolder != NULL);
  272. if (pFolder == NULL)
  273. return E_UNEXPECTED;
  274. switch (pFolder->GetType())
  275. {
  276. case COMPANY:
  277. cszObjectType = cszNodeTypeCompany;
  278. break;
  279. case USER:
  280. cszObjectType = cszNodeTypeUser;
  281. break;
  282. case EXT_COMPANY:
  283. cszObjectType = cszNodeTypeExtCompany;
  284. break;
  285. case EXT_USER:
  286. cszObjectType = cszNodeTypeExtUser;
  287. break;
  288. default:
  289. cszObjectType = cszNodeTypeDynamic;
  290. break;
  291. }
  292. }
  293. else if (m_internal.m_type == CCT_RESULT)
  294. {
  295. // RESULT_DATA* pData = reinterpret_cast<RESULT_DATA*>(m_internal.m_cookie);
  296. cszObjectType = cszObjectTypeResultItem;
  297. }
  298. return Create(cszObjectType, ((wcslen(cszObjectType)+1) * sizeof(WCHAR)), lpMedium);
  299. }
  300. HRESULT CDataObject::CreateDisplayName(LPSTGMEDIUM lpMedium)
  301. {
  302. // This is the display named used in the scope pane and snap-in manager
  303. // Load the name from resource
  304. // Note - if this is not provided, the console will used the snap-in name
  305. CString szDispName;
  306. szDispName.LoadString(IDS_NODENAME);
  307. USES_CONVERSION;
  308. #ifdef UNICODE
  309. return Create(szDispName, ((szDispName.GetLength()+1) * sizeof(WCHAR)), lpMedium);
  310. #else
  311. return Create(T2W(szDispName), ((szDispName.GetLength()+1) * sizeof(WCHAR)), lpMedium);
  312. #endif
  313. }
  314. HRESULT CDataObject::CreateInternal(LPSTGMEDIUM lpMedium)
  315. {
  316. return Create(&m_internal, sizeof(INTERNAL), lpMedium);
  317. }
  318. HRESULT CDataObject::CreateWorkstationName(LPSTGMEDIUM lpMedium)
  319. {
  320. TCHAR pzName[MAX_COMPUTERNAME_LENGTH+1] = {0};
  321. DWORD len = MAX_COMPUTERNAME_LENGTH+1;
  322. if (GetComputerName(pzName, &len) == FALSE)
  323. return E_FAIL;
  324. // Add 1 for the NULL and calculate the bytes for the stream
  325. //#ifdef UNICODE
  326. USES_CONVERSION;
  327. return Create(T2W(pzName), ((len+1)* sizeof(WCHAR)), lpMedium);
  328. //#else
  329. // return Create(pzName, ((len+1)* sizeof(WCHAR)), lpMedium);
  330. //#endif
  331. }
  332. HRESULT CDataObject::CreateCoClassID(LPSTGMEDIUM lpMedium)
  333. {
  334. // Create the CoClass information
  335. return Create(reinterpret_cast<const void*>(&m_internal.m_clsid), sizeof(CLSID), lpMedium);
  336. }