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.

451 lines
12 KiB

  1. /*++
  2. 1998 Seagate Software, Inc. All rights reserved.
  3. Module Name:
  4. MsDatObj.cpp
  5. Abstract:
  6. Implementation of IDataObject interface for Multi-Select
  7. Allows MMC to get a list of Node Types
  8. Author:
  9. Art Bragg 28-Aug-1997
  10. Revision History:
  11. --*/
  12. /////////////////////////////////////////////////////////////////////////////
  13. //
  14. //
  15. /////////////////////////////////////////////////////////////////////////////
  16. #include "stdafx.h"
  17. #include "msdatobj.h"
  18. #define BUMP_SIZE 20
  19. // Declare Snap-in NodeType formats:
  20. UINT CMsDataObject::m_cfObjectTypes = RegisterClipboardFormat(CCF_OBJECT_TYPES_IN_MULTI_SELECT);
  21. HRESULT
  22. CMsDataObject::FinalConstruct(
  23. void
  24. )
  25. /*++
  26. Routine Description:
  27. Called during initial CMsDataObject construction to initialize members.
  28. Arguments:
  29. none.
  30. Return Value:
  31. S_OK - Initialized correctly.
  32. E_xxxxxxxxxxx - Failure occurred.
  33. --*/
  34. {
  35. HRESULT hr = S_OK;
  36. WsbTraceIn( L"CMsDataObject::FinalConstruct", L"" );
  37. try {
  38. m_Count = 0;
  39. // Allocate initial array of GUIDs
  40. m_pGUIDArray = (GUID *) malloc (BUMP_SIZE * sizeof(GUID));
  41. WsbAffirm ((m_pGUIDArray != NULL), E_OUTOFMEMORY);
  42. ZeroMemory (m_pGUIDArray, (BUMP_SIZE * sizeof(GUID)));
  43. m_pUnkNodeArray = (IUnknown **) malloc( BUMP_SIZE * sizeof(IUnknown*) );
  44. WsbAffirm ((m_pGUIDArray != NULL), E_OUTOFMEMORY);
  45. ZeroMemory (m_pGUIDArray, (BUMP_SIZE * sizeof(IUnknown*)));
  46. m_pObjectIdArray = (GUID *) malloc (BUMP_SIZE * sizeof(GUID));
  47. WsbAffirm ((m_pObjectIdArray != NULL), E_OUTOFMEMORY);
  48. ZeroMemory (m_pObjectIdArray, (BUMP_SIZE * sizeof(GUID)));
  49. m_ArraySize = BUMP_SIZE;
  50. WsbAffirmHr (CComObjectRoot::FinalConstruct( ));
  51. } WsbCatch (hr);
  52. WsbTraceOut( L"CMsDataObject::FinalConstruct", L"hr = <%ls>", WsbHrAsString( hr ) );
  53. return( hr );
  54. }
  55. void
  56. CMsDataObject::FinalRelease(
  57. void
  58. )
  59. /*++
  60. Routine Description:
  61. Called on final release in order to clean up all members.
  62. Arguments:
  63. none.
  64. Return Value:
  65. none.
  66. --*/
  67. {
  68. WsbTraceIn( L"CMsDataObject::FinalRelease", L"" );
  69. // Clean up array of GUIDs
  70. free( m_pGUIDArray );
  71. for( DWORD i = 0; i < m_Count; i++ ) {
  72. m_pUnkNodeArray[i]->Release();
  73. }
  74. free( m_pUnkNodeArray );
  75. WsbTraceOut( L"CMsDataObject::FinalRelease", L"" );
  76. }
  77. // IDataObject
  78. STDMETHODIMP
  79. CMsDataObject::GetDataHere(
  80. LPFORMATETC lpFormatetc,
  81. LPSTGMEDIUM /*lpMedium*/
  82. )
  83. /*++
  84. Routine Description:
  85. Retrieve information FROM the dataobject and put INTO lpMedium.
  86. Arguments:
  87. lpFormatetc - Format to retreive.
  88. lpMedium - Storage to put information into.
  89. Return Value:
  90. S_OK - Storage filled in.
  91. E_xxxxxxxxxxx - Failure occurred.
  92. --*/
  93. {
  94. WsbTraceIn( L"CMsDataObject::GetDataHere", L"lpFormatetc->cfFormat = <%ls>", RsClipFormatAsString( lpFormatetc->cfFormat ) );
  95. HRESULT hr = E_NOTIMPL;
  96. WsbTraceOut( L"CMsDataObject::GetDataHere", L"hr = <%ls>", WsbHrAsString( hr ) );
  97. return( hr );
  98. }
  99. STDMETHODIMP
  100. CMsDataObject::SetData(
  101. LPFORMATETC lpFormatetc,
  102. LPSTGMEDIUM /*lpMedium*/,
  103. BOOL /*fRelease*/
  104. )
  105. {
  106. WsbTraceIn( L"CMsDataObject::SetData", L"lpFormatetc->cfFormat = <%ls>", RsClipFormatAsString( lpFormatetc->cfFormat ) );
  107. HRESULT hr = E_NOTIMPL;
  108. WsbTraceOut( L"CMsDataObject::SetData", L"hr = <%ls>", WsbHrAsString( hr ) );
  109. return( hr );
  110. }
  111. ///////////////////////////////////////////////////////////////////////
  112. // Note - CMsDataObject does not implement these
  113. ///////////////////////////////////////////////////////////////////////
  114. STDMETHODIMP
  115. CMsDataObject::GetData(
  116. LPFORMATETC lpFormatetcIn,
  117. LPSTGMEDIUM lpMedium
  118. )
  119. {
  120. WsbTraceIn( L"CMsDataObject::GetData", L"lpFormatetc->cfFormat = <%ls>", RsClipFormatAsString( lpFormatetcIn->cfFormat ) );
  121. HRESULT hr = S_OK;
  122. lpMedium->tymed = TYMED_NULL;
  123. lpMedium->hGlobal = NULL;
  124. lpMedium->pUnkForRelease = NULL;
  125. try {
  126. //
  127. // Don't need to throw error if not a format we don't understand -
  128. // which is currently only CCF_OBJECT_TYPES_IN_MULTI_SELECT
  129. //
  130. if( lpFormatetcIn->cfFormat == m_cfObjectTypes ) {
  131. //
  132. // Check to make sure there is data to transfer
  133. //
  134. WsbAffirm( ( lpFormatetcIn->tymed & TYMED_HGLOBAL ), DV_E_TYMED );
  135. //
  136. // m_ppDataObjects m_count
  137. //
  138. UINT datasize = sizeof(DWORD) + ( sizeof(GUID) * m_Count );
  139. lpMedium->hGlobal = ::GlobalAlloc( GPTR, datasize );
  140. WsbAffirmAlloc( lpMedium->hGlobal );
  141. //
  142. // Put the count in the allocated memory
  143. //
  144. BYTE* pb = reinterpret_cast<BYTE*>(lpMedium->hGlobal);
  145. *((DWORD*)lpMedium->hGlobal) = m_Count;
  146. //
  147. // Copy the GUIDs to the allocated memory
  148. //
  149. if( m_Count > 0 ) {
  150. pb += sizeof(DWORD);
  151. CopyMemory(pb, m_pGUIDArray, m_Count * sizeof(GUID));
  152. }
  153. lpMedium->tymed = TYMED_HGLOBAL;
  154. } else {
  155. hr = DATA_E_FORMATETC;
  156. }
  157. } WsbCatch( hr );
  158. WsbTraceOut( L"CMsDataObject::GetData", L"hr = <%ls>", WsbHrAsString( hr ) );
  159. return( hr );
  160. }
  161. STDMETHODIMP CMsDataObject::EnumFormatEtc(DWORD /*dwDirection*/, LPENUMFORMATETC* /*ppEnumFormatEtc*/)
  162. {
  163. WsbTraceIn( L"CMsDataObject::EnumFormatEtc", L"" );
  164. HRESULT hr = E_NOTIMPL;
  165. WsbTraceOut( L"CMsDataObject::EnumFormatEtc", L"hr = <%ls>", WsbHrAsString( hr ) );
  166. return( hr );
  167. }
  168. HRESULT CMsDataObject::RetrieveMultiSelectData (LPSTGMEDIUM lpMedium)
  169. {
  170. WsbTraceIn( L"CMsDataObject::RetrieveMultiSelectData", L"" );
  171. HRESULT hr = S_OK;
  172. try {
  173. WsbAffirm( lpMedium != NULL, E_POINTER);
  174. WsbAffirm( lpMedium->tymed == TYMED_HGLOBAL, E_FAIL );
  175. // Create the stream on the hGlobal passed in. When we write to the stream,
  176. // it simultaneously writes to the hGlobal the same information.
  177. LPSTREAM lpStream;
  178. WsbAffirmHr( CreateStreamOnHGlobal(lpMedium->hGlobal, FALSE, &lpStream ));
  179. // Write 'len' number of bytes from pBuffer into the stream. When we write
  180. // to the stream, it simultaneously writes to the global memory we
  181. // associated it with above.
  182. ULONG numBytesWritten;
  183. // Write the count first
  184. WsbAffirmHr( lpStream->Write(&m_Count, sizeof (m_Count), &numBytesWritten ));
  185. // Write the GUID array
  186. WsbAffirmHr( lpStream->Write(m_pGUIDArray, m_Count * sizeof (GUID), &numBytesWritten ));
  187. // Because we told CreateStreamOnHGlobal with 'FALSE', only the stream is released here.
  188. // Note - the caller (i.e. snap-in, object) will free the HGLOBAL
  189. // at the correct time. This is according to the IDataObject specification.
  190. lpStream->Release();
  191. } WsbCatch( hr );
  192. WsbTraceOut( L"CMsDataObject::RetrieveMultiSelectData", L"hr = <%ls>", WsbHrAsString( hr ) );
  193. return hr;
  194. }
  195. // Data setting method
  196. // Note that we keep the node array seperate from the GUID array because
  197. // the GetData interface memory copies the GUID array to the stream.
  198. STDMETHODIMP
  199. CMsDataObject::AddNode (ISakNode *pNode )
  200. {
  201. WsbTraceIn( L"CMsDataObject::AddNode", L"pNode = <0x%p>", pNode );
  202. HRESULT hr = S_OK;
  203. GUID thisGUID;
  204. GUID objectId;
  205. GUID * pGUIDArray = 0,
  206. * pObjectIdArray = 0;
  207. IUnknown ** pUnkNodeArray = 0;
  208. try {
  209. //
  210. // Get the object type GUID
  211. //
  212. WsbAffirmHr( pNode->GetNodeType( &thisGUID ) );
  213. //
  214. // Get the unique ID for the engine object (i.e. FsaResource)
  215. //
  216. WsbAffirmHr( pNode->GetObjectId( &objectId ) );
  217. //
  218. // Reallocate if we need to
  219. //
  220. if( m_Count >= m_ArraySize ) {
  221. //
  222. // Allocate new buffer
  223. //
  224. m_ArraySize += BUMP_SIZE;
  225. pGUIDArray = (GUID *) malloc( m_ArraySize * sizeof( GUID ) );
  226. WsbAffirmAlloc( pGUIDArray );
  227. pUnkNodeArray = (IUnknown **) malloc( m_ArraySize * sizeof( IUnknown* ) );
  228. WsbAffirmAlloc( pUnkNodeArray );
  229. pObjectIdArray = (GUID *) malloc( m_ArraySize * sizeof( GUID ) );
  230. WsbAffirmAlloc( pObjectIdArray );
  231. //
  232. // copy over old buffer and free
  233. //
  234. memcpy( pGUIDArray, m_pGUIDArray, m_Count * sizeof( GUID ) );
  235. memcpy( pUnkNodeArray, m_pUnkNodeArray, m_Count * sizeof( IUnknown* ) );
  236. memcpy( pObjectIdArray, m_pObjectIdArray, m_Count * sizeof( GUID ) );
  237. free( m_pGUIDArray );
  238. free( m_pUnkNodeArray );
  239. free( m_pObjectIdArray );
  240. m_pGUIDArray = pGUIDArray;
  241. m_pUnkNodeArray = pUnkNodeArray;
  242. m_pObjectIdArray = pObjectIdArray;
  243. pGUIDArray = 0;
  244. pUnkNodeArray = 0;
  245. pObjectIdArray = 0;
  246. }
  247. //
  248. // Put the GUID in the array
  249. //
  250. m_pGUIDArray[ m_Count ] = thisGUID;
  251. //
  252. // Put the objectId in the array
  253. //
  254. m_pObjectIdArray[ m_Count ] = objectId;
  255. //
  256. // Put the unknown pointer (the Cookie) in the array
  257. //
  258. CComPtr<IUnknown> pUnkNode;
  259. WsbAffirmHr( RsQueryInterface( pNode, IUnknown, pUnkNode ) );
  260. pUnkNode.CopyTo( &m_pUnkNodeArray[ m_Count ] );
  261. m_Count++;
  262. } WsbCatch( hr );
  263. if( pGUIDArray ) free( pGUIDArray );
  264. if( pObjectIdArray ) free( pObjectIdArray );
  265. if( pUnkNodeArray ) free( pUnkNodeArray );
  266. WsbTraceOut( L"CMsDataObject::AddNode", L"hr = <%ls>", WsbHrAsString( hr ) );
  267. return( hr );
  268. }
  269. STDMETHODIMP
  270. CMsDataObject::GetNodeEnumerator( IEnumUnknown **ppEnum )
  271. {
  272. WsbTraceIn( L"CMsDataObject::GetNodeEnumerator", L"ppEnum = <0x%p>", ppEnum );
  273. HRESULT hr = S_OK;
  274. CEnumUnknown * pEnum = 0;
  275. try {
  276. WsbAffirmPointer( ppEnum );
  277. *ppEnum = 0;
  278. //
  279. // New an ATL enumerator
  280. //
  281. pEnum = new CEnumUnknown;
  282. WsbAffirm( 0 != pEnum, E_OUTOFMEMORY );
  283. //
  284. // Initialize it to copy the current node interface pointers
  285. //
  286. WsbAffirmHr( pEnum->FinalConstruct() );
  287. WsbAffirmHr( pEnum->Init( &m_pUnkNodeArray[0], &m_pUnkNodeArray[m_Count], NULL, AtlFlagCopy ) );
  288. WsbAffirmHr( pEnum->QueryInterface( IID_IEnumUnknown, (void**)ppEnum ) );
  289. } WsbCatchAndDo( hr,
  290. if( pEnum ) delete pEnum;
  291. );
  292. WsbTraceOut( L"CMsDataObject::GetNodeEnumerator", L"hr = <%ls>, *ppEnum = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)ppEnum ) );
  293. return( hr );
  294. }
  295. STDMETHODIMP
  296. CMsDataObject::GetObjectIdEnumerator( IEnumGUID ** ppEnum )
  297. {
  298. WsbTraceIn( L"CMsDataObject::GetObjectIdEnumerator", L"ppEnum = <0x%p>", ppEnum );
  299. HRESULT hr = S_OK;
  300. CEnumGUID * pEnum = 0;
  301. try {
  302. WsbAffirmPointer( ppEnum );
  303. *ppEnum = 0;
  304. //
  305. // New an ATL enumerator
  306. //
  307. pEnum = new CEnumGUID;
  308. WsbAffirm( 0 != pEnum, E_OUTOFMEMORY );
  309. //
  310. // Initialize it to copy the current node interface pointers
  311. //
  312. WsbAffirmHr( pEnum->FinalConstruct() );
  313. WsbAffirmHr( pEnum->Init( &m_pObjectIdArray[0], &m_pObjectIdArray[m_Count], NULL, AtlFlagCopy ) );
  314. WsbAffirmHr( pEnum->QueryInterface( IID_IEnumGUID, (void**)ppEnum ) );
  315. } WsbCatchAndDo( hr,
  316. if( pEnum ) delete pEnum;
  317. );
  318. WsbTraceOut( L"CMsDataObject::GetObjectIdEnumerator", L"hr = <%ls>, *ppEnum = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)ppEnum ) );
  319. return( hr );
  320. }