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.

425 lines
12 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1998 **/
  4. /**********************************************************************/
  5. /*
  6. dataobj.cpp
  7. Implementation for data objects in the MMC
  8. FILE HISTORY:
  9. */
  10. #include "stdafx.h"
  11. #include "dataobj.h"
  12. #include "extract.h"
  13. #ifdef _DEBUG
  14. #define new DEBUG_NEW
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. ///////////////////////////////////////////////////////////////////////////////
  19. // Sample code to show how to Create DataObjects
  20. // Minimal error checking for clarity
  21. // Internal private format
  22. const wchar_t* SNAPIN_INTERNAL = L"SNAPIN_INTERNAL";
  23. ///////////////////////////////////////////////////////////////////////////////
  24. // Snap-in NodeType in both GUID format and string format
  25. // Note - Typically there is a node type for each different object, sample
  26. // only uses one node type.
  27. // MMC required clipboard formats
  28. unsigned int CDataObject::m_cfNodeType = RegisterClipboardFormat(CCF_NODETYPE);
  29. unsigned int CDataObject::m_cfNodeTypeString = RegisterClipboardFormat(CCF_SZNODETYPE);
  30. unsigned int CDataObject::m_cfDisplayName = RegisterClipboardFormat(CCF_DISPLAY_NAME);
  31. unsigned int CDataObject::m_cfCoClass = RegisterClipboardFormat(CCF_SNAPIN_CLASSID);
  32. unsigned int CDataObject::m_cfMultiSel = RegisterClipboardFormat(CCF_OBJECT_TYPES_IN_MULTI_SELECT);
  33. unsigned int CDataObject::m_cfMultiSelDobj = RegisterClipboardFormat(CCF_MMC_MULTISELECT_DATAOBJECT);
  34. unsigned int CDataObject::m_cfDynamicExtension = RegisterClipboardFormat(CCF_MMC_DYNAMIC_EXTENSIONS);
  35. unsigned int CDataObject::m_cfNodeId2 = RegisterClipboardFormat(CCF_NODEID2);
  36. // snpain specific clipboard formats
  37. unsigned int CDataObject::m_cfInternal = RegisterClipboardFormat(SNAPIN_INTERNAL);
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CDataObject implementations
  40. DEBUG_DECLARE_INSTANCE_COUNTER(CDataObject);
  41. IMPLEMENT_ADDREF_RELEASE(CDataObject)
  42. STDMETHODIMP CDataObject::QueryInterface(REFIID riid, LPVOID *ppv)
  43. {
  44. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  45. // Is the pointer bad?
  46. if (ppv == NULL)
  47. return E_INVALIDARG;
  48. // Place NULL in *ppv in case of failure
  49. *ppv = NULL;
  50. // This is the non-delegating IUnknown implementation
  51. if (riid == IID_IUnknown)
  52. *ppv = (LPVOID) this;
  53. else if (riid == IID_IDataObject)
  54. *ppv = (IDataObject *) this;
  55. else if (m_spUnknownInner)
  56. {
  57. // blind aggregation, we don't know what we're aggregating
  58. // with, so just pass it down.
  59. return m_spUnknownInner->QueryInterface(riid, ppv);
  60. }
  61. // If we're going to return an interface, AddRef it first
  62. if (*ppv)
  63. {
  64. ((LPUNKNOWN) *ppv)->AddRef();
  65. return hrOK;
  66. }
  67. else
  68. return E_NOINTERFACE;
  69. }
  70. STDMETHODIMP CDataObject::GetDataHere(LPFORMATETC lpFormatetc, LPSTGMEDIUM lpMedium)
  71. {
  72. HRESULT hr = DV_E_CLIPFORMAT;
  73. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  74. // Based on the CLIPFORMAT write data to the stream
  75. const CLIPFORMAT cf = lpFormatetc->cfFormat;
  76. if(cf == m_cfNodeType)
  77. {
  78. hr = CreateNodeTypeData(lpMedium);
  79. }
  80. else if (cf == m_cfCoClass)
  81. {
  82. hr = CreateCoClassID(lpMedium);
  83. }
  84. else if(cf == m_cfNodeTypeString)
  85. {
  86. hr = CreateNodeTypeStringData(lpMedium);
  87. }
  88. else if (cf == m_cfDisplayName)
  89. {
  90. hr = CreateDisplayName(lpMedium);
  91. }
  92. else if (cf == m_cfInternal)
  93. {
  94. hr = CreateInternal(lpMedium);
  95. }
  96. else
  97. {
  98. //
  99. // Call the derived class and see if it can handle
  100. // this clipboard format
  101. //
  102. hr = GetMoreDataHere(lpFormatetc, lpMedium);
  103. }
  104. return hr;
  105. }
  106. STDMETHODIMP CDataObject::GetData(LPFORMATETC lpFormatetcIn, LPSTGMEDIUM lpMedium)
  107. {
  108. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  109. HRESULT hr = DV_E_CLIPFORMAT;
  110. if (lpFormatetcIn->cfFormat == m_cfMultiSel)
  111. {
  112. ASSERT(m_internal.m_cookie == MMC_MULTI_SELECT_COOKIE);
  113. if (m_internal.m_cookie != MMC_MULTI_SELECT_COOKIE)
  114. return E_FAIL;
  115. //return CreateMultiSelData(lpMedium);
  116. ASSERT(m_pbMultiSelData != 0);
  117. ASSERT(m_cbMultiSelData != 0);
  118. lpMedium->tymed = TYMED_HGLOBAL;
  119. lpMedium->hGlobal = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE,
  120. (m_cbMultiSelData + sizeof(DWORD)));
  121. if (lpMedium->hGlobal == NULL)
  122. return STG_E_MEDIUMFULL;
  123. BYTE* pb = reinterpret_cast<BYTE*>(::GlobalLock(lpMedium->hGlobal));
  124. *((DWORD*)pb) = m_cbMultiSelData / sizeof(GUID);
  125. pb += sizeof(DWORD);
  126. CopyMemory(pb, m_pbMultiSelData, m_cbMultiSelData);
  127. ::GlobalUnlock(lpMedium->hGlobal);
  128. hr = S_OK;
  129. }
  130. else
  131. if (lpFormatetcIn->cfFormat == m_cfDynamicExtension)
  132. {
  133. if (m_pDynExt)
  134. {
  135. // get the data...
  136. m_pDynExt->BuildMMCObjectTypes(&lpMedium->hGlobal);
  137. if (lpMedium->hGlobal == NULL)
  138. return STG_E_MEDIUMFULL;
  139. hr = S_OK;
  140. }
  141. }
  142. else
  143. if (lpFormatetcIn->cfFormat == m_cfNodeId2)
  144. {
  145. hr = CreateNodeId2(lpMedium);
  146. }
  147. return hr;
  148. }
  149. STDMETHODIMP CDataObject::QueryGetData(LPFORMATETC lpFormatEtc)
  150. {
  151. HRESULT hr = E_INVALIDARG;
  152. if (lpFormatEtc == NULL)
  153. return DV_E_FORMATETC;
  154. if (lpFormatEtc->lindex != -1)
  155. return DV_E_LINDEX;
  156. if (lpFormatEtc->tymed != TYMED_HGLOBAL)
  157. return DV_E_TYMED;
  158. if (!(lpFormatEtc->dwAspect & DVASPECT_CONTENT))
  159. return DV_E_DVASPECT;
  160. // these are our supported clipboard formats. If it isn't one
  161. // of these then return invalid.
  162. if ( (lpFormatEtc->cfFormat == m_cfNodeType) ||
  163. (lpFormatEtc->cfFormat == m_cfNodeTypeString) ||
  164. (lpFormatEtc->cfFormat == m_cfDisplayName) ||
  165. (lpFormatEtc->cfFormat == m_cfCoClass) ||
  166. (lpFormatEtc->cfFormat == m_cfInternal) ||
  167. (lpFormatEtc->cfFormat == m_cfNodeId2) ||
  168. (lpFormatEtc->cfFormat == m_cfDynamicExtension) )
  169. {
  170. hr = S_OK;
  171. }
  172. else if ((lpFormatEtc->cfFormat == m_cfMultiSel) ||
  173. (lpFormatEtc->cfFormat == m_cfMultiSelDobj))
  174. {
  175. // Support multi-selection format only if this
  176. // is a multi-select data object
  177. if (m_bMultiSelDobj)
  178. hr = S_OK;
  179. }
  180. else
  181. hr = QueryGetMoreData(lpFormatEtc);
  182. #ifdef DEBUG
  183. TCHAR buf[2000];
  184. ::GetClipboardFormatName(lpFormatEtc->cfFormat, buf, sizeof(buf));
  185. Trace2("CDataObject::QueryGetData - query format %s returning %lx\n", buf, hr);
  186. #endif
  187. return hr;
  188. }
  189. // Note - Sample does not implement these
  190. STDMETHODIMP CDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC* ppEnumFormatEtc)
  191. {
  192. return E_NOTIMPL;
  193. }
  194. STDMETHODIMP CDataObject::GetCanonicalFormatEtc(LPFORMATETC lpFormatEtcIn, LPFORMATETC lpFormatEtcOut)
  195. {
  196. return E_NOTIMPL;
  197. }
  198. STDMETHODIMP CDataObject::SetData(LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpMedium, BOOL bRelease)
  199. {
  200. return E_NOTIMPL;
  201. }
  202. STDMETHODIMP CDataObject::DAdvise(LPFORMATETC lpFormatEc, DWORD advf,
  203. LPADVISESINK pAdvSink, LPDWORD pdwConn)
  204. {
  205. return E_NOTIMPL;
  206. }
  207. STDMETHODIMP CDataObject::DUnadvise(DWORD dwConnection)
  208. {
  209. return E_NOTIMPL;
  210. }
  211. STDMETHODIMP CDataObject::EnumDAdvise(LPENUMSTATDATA *ppEnumAdvise)
  212. {
  213. return E_NOTIMPL;
  214. }
  215. /////////////////////////////////////////////////////////////////////////////
  216. // CDataObject creation members
  217. HRESULT CDataObject::Create(const void* pBuffer, int len, LPSTGMEDIUM lpMedium)
  218. {
  219. HRESULT hr = DV_E_TYMED;
  220. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  221. // Do some simple validation
  222. if (pBuffer == NULL || lpMedium == NULL)
  223. return E_POINTER;
  224. // Make sure the type medium is HGLOBAL
  225. if (lpMedium->tymed == TYMED_HGLOBAL)
  226. {
  227. // Create the stream on the hGlobal passed in
  228. LPSTREAM lpStream;
  229. hr = CreateStreamOnHGlobal(lpMedium->hGlobal, FALSE, &lpStream);
  230. if (SUCCEEDED(hr))
  231. {
  232. // Write to the stream the number of bytes
  233. unsigned long written;
  234. hr = lpStream->Write(pBuffer, len, &written);
  235. // Because we told CreateStreamOnHGlobal with 'FALSE',
  236. // only the stream is released here.
  237. // Note - the caller (i.e. snap-in, object) will free the HGLOBAL
  238. // at the correct time. This is according to the IDataObject specification.
  239. lpStream->Release();
  240. }
  241. }
  242. return hr;
  243. }
  244. HRESULT CDataObject::CreateNodeTypeData(LPSTGMEDIUM lpMedium)
  245. {
  246. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  247. // Create the node type object in GUID format
  248. SPITFSNode spNode;
  249. spNode = GetDataFromComponentData();
  250. const GUID* pNodeType = spNode->GetNodeType();
  251. return Create(reinterpret_cast<const void*>(pNodeType), sizeof(GUID), lpMedium);
  252. }
  253. HRESULT CDataObject::CreateNodeTypeStringData(LPSTGMEDIUM lpMedium)
  254. {
  255. // Create the node type object in GUID string format
  256. OLECHAR szNodeType[128];
  257. SPITFSNode spNode;
  258. spNode = GetDataFromComponentData();
  259. const GUID* pNodeType = spNode->GetNodeType();
  260. ::StringFromGUID2(*pNodeType,szNodeType,128);
  261. return Create(szNodeType, ((wcslen(szNodeType)+1) * sizeof(wchar_t)), lpMedium);
  262. }
  263. HRESULT CDataObject::CreateDisplayName(LPSTGMEDIUM lpMedium)
  264. {
  265. // This is the display named used in the scope pane and snap-in manager
  266. CString szDispName;
  267. SPITFSNode spNode;
  268. spNode = GetDataFromComponentData();
  269. szDispName = spNode->GetString(-1);
  270. return Create(szDispName, ((szDispName.GetLength()+1) * sizeof(wchar_t)), lpMedium);
  271. }
  272. HRESULT CDataObject::CreateInternal(LPSTGMEDIUM lpMedium)
  273. {
  274. return Create(&m_internal, sizeof(INTERNAL), lpMedium);
  275. }
  276. HRESULT CDataObject::CreateCoClassID(LPSTGMEDIUM lpMedium)
  277. {
  278. // Create the CoClass information
  279. return Create(reinterpret_cast<const void*>(&m_internal.m_clsid), sizeof(CLSID), lpMedium);
  280. }
  281. HRESULT CDataObject::CreateMultiSelData(LPSTGMEDIUM lpMedium)
  282. {
  283. Assert(m_internal.m_cookie == MMC_MULTI_SELECT_COOKIE);
  284. Assert(m_pbMultiSelData != 0);
  285. Assert(m_cbMultiSelData != 0);
  286. return Create(reinterpret_cast<const void*>(m_pbMultiSelData),
  287. m_cbMultiSelData, lpMedium);
  288. }
  289. HRESULT CDataObject::CreateNodeId2(LPSTGMEDIUM lpMedium)
  290. {
  291. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  292. HRESULT hr = hrOK;
  293. // Create the node type object in GUID format
  294. SPITFSNode spNode;
  295. spNode = GetDataFromComponentData();
  296. SPITFSNodeHandler spHandler;
  297. spNode->GetHandler(&spHandler);
  298. if (spHandler)
  299. {
  300. CComBSTR bstrId;
  301. DWORD dwFlags = 0;
  302. hr = spHandler->CreateNodeId2(spNode, &bstrId, &dwFlags);
  303. if (SUCCEEDED(hr) && hr != S_FALSE && bstrId.Length() > 0)
  304. {
  305. int nSize = sizeof(SNodeID2) + (bstrId.Length() * sizeof(TCHAR));
  306. lpMedium->tymed = TYMED_HGLOBAL;
  307. lpMedium->hGlobal = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, nSize);
  308. if (lpMedium->hGlobal == NULL)
  309. {
  310. hr = STG_E_MEDIUMFULL;
  311. }
  312. else
  313. {
  314. SNodeID2 * pNodeId = reinterpret_cast<SNodeID2*>(::GlobalLock(lpMedium->hGlobal));
  315. ::ZeroMemory(pNodeId, nSize);
  316. pNodeId->cBytes = bstrId.Length() * sizeof(TCHAR);
  317. pNodeId->dwFlags = dwFlags;
  318. _tcscpy((LPTSTR) pNodeId->id, bstrId);
  319. ::GlobalUnlock(lpMedium->hGlobal);
  320. }
  321. }
  322. }
  323. else
  324. {
  325. hr = E_UNEXPECTED;
  326. }
  327. return hr;
  328. }
  329. ITFSNode* CDataObject::GetDataFromComponentData()
  330. {
  331. SPITFSNodeMgr spNodeMgr;
  332. SPITFSNode spNode;
  333. Assert(m_spTFSComponentData);
  334. m_spTFSComponentData->GetNodeMgr(&spNodeMgr);
  335. spNodeMgr->FindNode(m_internal.m_cookie, &spNode);
  336. return spNode.Transfer();
  337. }