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.

275 lines
8.5 KiB

  1. //==============================================================;
  2. //
  3. // This source code is only intended as a supplement to existing Microsoft documentation.
  4. //
  5. //
  6. //
  7. //
  8. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  9. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  10. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  11. // PURPOSE.
  12. //
  13. // Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  14. //
  15. //
  16. //
  17. //==============================================================;
  18. #include "DataObj.h"
  19. #include "guids.h"
  20. #include "DeleBase.h"
  21. #include "Space.h"
  22. //
  23. // This is the minimum set of clipboard formats we must implement.
  24. // MMC uses these to get necessary information from our snapin about
  25. // our nodes.
  26. //
  27. // we need to do this to get around MMC.IDL - it explicitly defines
  28. // the clipboard formats as WCHAR types...
  29. #define _T_CCF_DISPLAY_NAME _T("CCF_DISPLAY_NAME")
  30. #define _T_CCF_NODETYPE _T("CCF_NODETYPE")
  31. #define _T_CCF_SZNODETYPE _T("CCF_SZNODETYPE")
  32. #define _T_CCF_SNAPIN_CLASSID _T("CCF_SNAPIN_CLASSID")
  33. #define _T_CCF_OBJECT_TYPES_IN_MULTI_SELECT _T("CCF_OBJECT_TYPES_IN_MULTI_SELECT")
  34. #define _T_CCF_INTERNAL_SNAPIN _T("{2479DB32-5276-11d2-94F5-00C04FB92EC2}")
  35. // These are the clipboard formats that we must supply at a minimum.
  36. // mmc.h actually defined these. We can make up our own to use for
  37. // other reasons. We don't need any others at this time.
  38. UINT CDataObject::s_cfDisplayName = RegisterClipboardFormat(_T_CCF_DISPLAY_NAME);
  39. UINT CDataObject::s_cfNodeType = RegisterClipboardFormat(_T_CCF_NODETYPE);
  40. UINT CDataObject::s_cfSZNodeType = RegisterClipboardFormat(_T_CCF_SZNODETYPE);
  41. UINT CDataObject::s_cfSnapinClsid = RegisterClipboardFormat(_T_CCF_SNAPIN_CLASSID);
  42. UINT CDataObject::s_cfInternal = RegisterClipboardFormat(_T_CCF_INTERNAL_SNAPIN);
  43. //We must also supply a data object for CCF_OBJECT_TYPES_IN_MULTI_SELECT
  44. UINT CDataObject::s_cfMultiSelect = RegisterClipboardFormat(_T_CCF_OBJECT_TYPES_IN_MULTI_SELECT);
  45. CDataObject::CDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES context)
  46. : m_lCookie(cookie), m_context(context), m_cref(0)
  47. {
  48. //Do the following if the data object is a multiselection data object
  49. if ( MMC_MULTI_SELECT_COOKIE == m_lCookie ) {
  50. pCookies = new MMC_COOKIE[MAX_COOKIES];
  51. for (int n = 0; n < MAX_COOKIES; n++) {
  52. pCookies[n] = NULL;
  53. }
  54. }
  55. }
  56. CDataObject::~CDataObject()
  57. {
  58. //Do the following if the data object is a multiselection data object
  59. if ( MMC_MULTI_SELECT_COOKIE == m_lCookie )
  60. delete [] pCookies;
  61. }
  62. ///////////////////////
  63. // IUnknown implementation
  64. ///////////////////////
  65. STDMETHODIMP CDataObject::QueryInterface(REFIID riid, LPVOID *ppv)
  66. {
  67. if (!ppv)
  68. return E_FAIL;
  69. *ppv = NULL;
  70. if (IsEqualIID(riid, IID_IUnknown))
  71. *ppv = static_cast<IDataObject *>(this);
  72. else if (IsEqualIID(riid, IID_IDataObject))
  73. *ppv = static_cast<IDataObject *>(this);
  74. if (*ppv)
  75. {
  76. reinterpret_cast<IUnknown *>(*ppv)->AddRef();
  77. return S_OK;
  78. }
  79. return E_NOINTERFACE;
  80. }
  81. STDMETHODIMP_(ULONG) CDataObject::AddRef()
  82. {
  83. return InterlockedIncrement((LONG *)&m_cref);
  84. }
  85. STDMETHODIMP_(ULONG) CDataObject::Release()
  86. {
  87. if (InterlockedDecrement((LONG *)&m_cref) == 0)
  88. {
  89. delete this;
  90. return 0;
  91. }
  92. return m_cref;
  93. }
  94. /////////////////////////////////////////////////////////////////////////////
  95. // IDataObject implementation
  96. //
  97. HRESULT CDataObject::GetDataHere(
  98. FORMATETC *pFormatEtc, // [in] Pointer to the FORMATETC structure
  99. STGMEDIUM *pMedium // [out] Pointer to the STGMEDIUM structure
  100. )
  101. {
  102. const CLIPFORMAT cf = pFormatEtc->cfFormat;
  103. IStream *pStream = NULL;
  104. CDelegationBase *base = GetBaseNodeObject();
  105. HRESULT hr = CreateStreamOnHGlobal( pMedium->hGlobal, FALSE, &pStream );
  106. if ( FAILED(hr) )
  107. return hr; // Minimal error checking
  108. hr = DV_E_FORMATETC; // Unknown format
  109. if (cf == s_cfDisplayName) {
  110. const _TCHAR *pszName = base->GetDisplayName();
  111. MAKE_WIDEPTR_FROMTSTR(wszName, pszName);
  112. // get length of original string and convert it accordingly
  113. ULONG ulSizeofName = lstrlen(pszName);
  114. ulSizeofName++; // Count null character
  115. ulSizeofName *= sizeof(WCHAR);
  116. hr = pStream->Write(wszName, ulSizeofName, NULL);
  117. } else if (cf == s_cfNodeType) {
  118. const GUID *pGUID = (const GUID *)&base->getNodeType();
  119. hr = pStream->Write(pGUID, sizeof(GUID), NULL);
  120. } else if (cf == s_cfSZNodeType) {
  121. LPOLESTR szGuid;
  122. hr = StringFromCLSID(base->getNodeType(), &szGuid);
  123. if (SUCCEEDED(hr)) {
  124. hr = pStream->Write(szGuid, wcslen(szGuid), NULL);
  125. CoTaskMemFree(szGuid);
  126. }
  127. } else if (cf == s_cfSnapinClsid) {
  128. const GUID *pGUID = NULL;
  129. pGUID = &CLSID_CComponentData;
  130. hr = pStream->Write(pGUID, sizeof(GUID), NULL);
  131. } else if (cf == s_cfInternal) {
  132. // we are being asked to get our this pointer from the IDataObject interface
  133. // only our own snap-in objects will know how to do this.
  134. CDataObject *pThis = this;
  135. hr = pStream->Write( &pThis, sizeof(CDataObject*), NULL );
  136. }
  137. pStream->Release();
  138. return hr;
  139. }
  140. HRESULT CDataObject::GetData (LPFORMATETC lpFormatetcIn, LPSTGMEDIUM lpMedium)
  141. {
  142. HRESULT hr = S_FALSE;
  143. const CLIPFORMAT cf = lpFormatetcIn->cfFormat;
  144. CDelegationBase *base = GetBaseNodeObject();
  145. if (cf == s_cfMultiSelect) {
  146. // MMC requires support for this format to load any extensions
  147. // that extend the selected result items
  148. BYTE byData[256] = {0};
  149. SMMCObjectTypes* pData = reinterpret_cast<SMMCObjectTypes*>(byData);
  150. //We need the node type GUID of the selected items.
  151. //from CRocket::thisGuid
  152. GUID guid = { 0x29743811, 0x4c4b, 0x11d2, { 0x89, 0xd8, 0x0, 0x0, 0x21, 0x47, 0x31, 0x28 } };
  153. //Enter data required for the SMMCObjectTypes structure
  154. //count specifies the number of unique node types in the multiselection
  155. //Here, all CRocket items are of the same node type, so count == 1.
  156. pData->count = 1;
  157. pData->guid[0] = guid;
  158. // Calculate the size of SMMCObjectTypes.
  159. int cb = sizeof(GUID)*(pData->count) + sizeof (SMMCObjectTypes);
  160. //Fill out parameters
  161. lpMedium->tymed = TYMED_HGLOBAL;
  162. lpMedium->hGlobal = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, cb);
  163. if (lpMedium->hGlobal == NULL)
  164. return STG_E_MEDIUMFULL;
  165. BYTE* pb = reinterpret_cast<BYTE*>(::GlobalLock(lpMedium->hGlobal));
  166. CopyMemory(pb, pData, cb);
  167. ::GlobalUnlock(lpMedium->hGlobal);
  168. hr = S_OK;
  169. }
  170. return hr;
  171. }
  172. /////////////////////////////////////////////////////////////////////////////
  173. // Global helper functions to help work with dataobjects and
  174. // clipboard formats
  175. //---------------------------------------------------------------------------
  176. // Returns the current object based on the s_cfInternal clipboard format
  177. //
  178. CDataObject* GetOurDataObject (
  179. LPDATAOBJECT lpDataObject // [in] IComponent pointer
  180. )
  181. {
  182. HRESULT hr = S_OK;
  183. CDataObject *pSDO = NULL;
  184. // check to see if the data object is a special data object.
  185. if ( IS_SPECIAL_DATAOBJECT (lpDataObject) )
  186. {
  187. //Code for handling a special data object goes here.
  188. //Note that the MMC SDK samples do not handle
  189. //special data objects, so we exit if we get one.
  190. return NULL;
  191. }
  192. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  193. FORMATETC formatetc = { CDataObject::s_cfInternal, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  194. // Allocate memory for the stream
  195. stgmedium.hGlobal = GlobalAlloc( GMEM_SHARE, sizeof(CDataObject *));
  196. if (!stgmedium.hGlobal) {
  197. hr = E_OUTOFMEMORY;
  198. }
  199. if SUCCEEDED(hr)
  200. // Attempt to get data from the object
  201. hr = lpDataObject->GetDataHere( &formatetc, &stgmedium );
  202. // stgmedium now has the data we need
  203. if (SUCCEEDED(hr)) {
  204. pSDO = *(CDataObject **)(stgmedium.hGlobal);
  205. }
  206. // if we have memory free it
  207. if (stgmedium.hGlobal)
  208. GlobalFree(stgmedium.hGlobal);
  209. return pSDO;
  210. } // end GetOurDataObject()