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.

1200 lines
27 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. History:
  6. --*/
  7. #include "precomp.h"
  8. #include <wbemint.h>
  9. #include <wbemutil.h>
  10. #include <md5wbem.h>
  11. #include <arrtempl.h>
  12. #include "smrtmrsh.h"
  13. #include "buffer.h"
  14. static DWORD g_dwSignature = 0xabcdefab;
  15. static WORD g_dwVersion = 0;
  16. enum { e_ClassIdNone=0,
  17. e_ClassIdHash,
  18. e_ClassIdHashAndPath } ClassIdType_e;
  19. enum { e_DataPartial=0,
  20. e_DataFull } DataType_e;
  21. /****
  22. Packed Object Format
  23. - 4 byte magic number
  24. - 2 byte version number
  25. - 1 byte class id type
  26. - 4 byte class id len
  27. - N byte class id
  28. - 1 byte data type
  29. - 4 byte data len
  30. - N byte data
  31. *****/
  32. #define HDRSIZE 16 // size of msg w/o variable length data.
  33. #define HASHSIZE 16
  34. /**************************************************************************
  35. CWbemObjectWrapper - smooths out differences between Nova and Whistler
  36. ***************************************************************************/
  37. class CWbemObjectWrapper
  38. {
  39. CWbemPtr<_IWmiObject> m_pWmiObj;
  40. CWbemPtr<IWbemObjectAccess> m_pObjAccess;
  41. // CWbemPtr<IWbemObjectInternals> m_pObjInt;
  42. public:
  43. HRESULT SetPointer( IWbemClassObject* pObj )
  44. {
  45. HRESULT hr;
  46. hr = pObj->QueryInterface( IID__IWmiObject, (void**)&m_pWmiObj );
  47. if ( FAILED(hr) )
  48. {
  49. hr = pObj->QueryInterface( IID_IWbemObjectAccess,
  50. (void**)&m_pObjAccess );
  51. if ( SUCCEEDED(hr) )
  52. {
  53. // hr = pObj->QueryInterface( IID_IWbemObjectInternals,
  54. // (void**)&m_pObjInt );
  55. }
  56. }
  57. return hr;
  58. }
  59. operator IWbemObjectAccess* ()
  60. {
  61. IWbemObjectAccess* pAccess;
  62. if ( m_pWmiObj != NULL )
  63. {
  64. pAccess = m_pWmiObj;
  65. }
  66. else
  67. {
  68. pAccess = m_pObjAccess;
  69. }
  70. return pAccess;
  71. }
  72. BOOL IsValid()
  73. {
  74. return m_pWmiObj != NULL || m_pObjAccess != NULL;
  75. }
  76. HRESULT SetObjectParts( LPVOID pMem,
  77. DWORD dwDestBufSize,
  78. DWORD dwParts )
  79. {
  80. HRESULT hr;
  81. if ( m_pWmiObj != NULL )
  82. {
  83. hr = m_pWmiObj->SetObjectParts( pMem, dwDestBufSize, dwParts );
  84. }
  85. else
  86. {
  87. hr = WBEM_E_NOT_SUPPORTED;
  88. }
  89. return hr;
  90. }
  91. HRESULT GetObjectParts( LPVOID pDestination,
  92. DWORD dwDestBufSize,
  93. DWORD dwParts,
  94. DWORD *pdwUsed )
  95. {
  96. HRESULT hr;
  97. if ( m_pWmiObj != NULL )
  98. {
  99. hr = m_pWmiObj->GetObjectParts( pDestination,
  100. dwDestBufSize,
  101. dwParts,
  102. pdwUsed );
  103. }
  104. else
  105. {
  106. hr = WBEM_E_NOT_SUPPORTED;
  107. }
  108. return hr;
  109. }
  110. HRESULT MergeClassPart( IWbemClassObject* pObj )
  111. {
  112. HRESULT hr;
  113. if ( m_pWmiObj != NULL )
  114. {
  115. hr = m_pWmiObj->MergeClassPart( pObj );
  116. }
  117. else
  118. {
  119. hr = WBEM_E_NOT_SUPPORTED;
  120. }
  121. return hr;
  122. }
  123. };
  124. HRESULT GetClassPath( IWbemClassObject* pObj,
  125. LPCWSTR wszNamespace,
  126. PBYTE pBuff,
  127. ULONG cBuff,
  128. ULONG* pcUsed )
  129. {
  130. HRESULT hr;
  131. *pcUsed = 0;
  132. CPropVar vNamespace, vClass;
  133. //
  134. // before trying to optimize the property access, realize that
  135. // class objects do not support handle access to the __Namespace prop.
  136. //
  137. hr = pObj->Get( L"__NAMESPACE", 0, &vNamespace, NULL, NULL );
  138. if ( FAILED(hr) )
  139. {
  140. return hr;
  141. }
  142. hr = pObj->Get( L"__CLASS", 0, &vClass, NULL, NULL );
  143. if ( FAILED(hr) )
  144. {
  145. return hr;
  146. }
  147. if ( V_VT(&vNamespace) == VT_BSTR )
  148. {
  149. wszNamespace = V_BSTR(&vNamespace);
  150. }
  151. if ( wszNamespace == NULL )
  152. {
  153. return WBEM_E_NOT_SUPPORTED;
  154. }
  155. if ( V_VT(&vClass) != VT_BSTR )
  156. {
  157. return WBEM_E_CRITICAL_ERROR;
  158. }
  159. ULONG cNamespace = wcslen(wszNamespace)*2;
  160. ULONG cClass = wcslen(V_BSTR(&vClass))*2;
  161. //
  162. // add 4 for the two null terminators
  163. //
  164. *pcUsed = cNamespace + cClass + 4;
  165. if ( cBuff < *pcUsed )
  166. {
  167. return WBEM_E_BUFFER_TOO_SMALL;
  168. }
  169. ULONG iBuff = 0;
  170. memcpy( pBuff+iBuff, wszNamespace, cNamespace );
  171. iBuff += cNamespace;
  172. *(WCHAR*)(pBuff+iBuff) = ':';
  173. iBuff+= 2;
  174. memcpy( pBuff+iBuff, V_BSTR(&vClass), cClass );
  175. iBuff += cClass;
  176. *(WCHAR*)(pBuff+iBuff) = '\0';
  177. iBuff+= 2;
  178. _DBG_ASSERT( iBuff == *pcUsed );
  179. return hr;
  180. }
  181. HRESULT GetClassPartHash( CWbemObjectWrapper& rWrap,
  182. PBYTE pClassPartHash,
  183. ULONG cClassPartHash )
  184. {
  185. HRESULT hr;
  186. //
  187. // Too bad we have to perform a copy here, but no other way. This
  188. // function requires the passed in buffer be big enough to hold both
  189. // the class part and the hash. This is not really too limiting because
  190. // in most cases where this function is used, the caller already has
  191. // enough memory allocated to use here as a workarea.
  192. //
  193. DWORD dwSize;
  194. if ( cClassPartHash >= HASHSIZE )
  195. {
  196. hr = rWrap.GetObjectParts( pClassPartHash+HASHSIZE,
  197. cClassPartHash-HASHSIZE,
  198. WBEM_OBJ_CLASS_PART,
  199. &dwSize );
  200. if ( SUCCEEDED(hr) )
  201. {
  202. MD5::Transform( pClassPartHash+HASHSIZE, dwSize, pClassPartHash );
  203. }
  204. }
  205. else
  206. {
  207. hr = WBEM_E_BUFFER_TOO_SMALL;
  208. }
  209. return hr;
  210. }
  211. /***************************************************************************
  212. CSmartObjectMarshaler
  213. ****************************************************************************/
  214. HRESULT CSmartObjectMarshaler::GetMaxMarshalSize( IWbemClassObject* pObj,
  215. LPCWSTR wszNamespace,
  216. DWORD dwFlags,
  217. ULONG* pulSize )
  218. {
  219. HRESULT hr;
  220. if ( pObj == NULL || wszNamespace == NULL )
  221. {
  222. return WBEM_E_INVALID_PARAMETER;
  223. }
  224. CWbemPtr<IMarshal> pMrsh;
  225. hr = pObj->QueryInterface( IID_IMarshal, (void**)&pMrsh );
  226. if ( FAILED(hr) )
  227. {
  228. return hr;
  229. }
  230. //
  231. // user is requesting the required size to pack object. For now,
  232. // we always use the size of the entire object blob. However, the
  233. // actual size of the object may be much smaller.
  234. //
  235. DWORD dwSize;
  236. hr = pMrsh->GetMarshalSizeMax( IID_IWbemClassObject,
  237. pObj,
  238. MSHCTX_INPROC,
  239. NULL,
  240. 0,
  241. &dwSize );
  242. if ( FAILED(hr) )
  243. {
  244. return hr;
  245. }
  246. *pulSize = dwSize + HDRSIZE + HASHSIZE;
  247. if ( dwFlags == WMIMSG_FLAG_MRSH_PARTIAL )
  248. {
  249. hr = GetClassPath( pObj, wszNamespace, NULL, 0, &dwSize );
  250. if ( hr == WBEM_E_BUFFER_TOO_SMALL )
  251. {
  252. *pulSize += dwSize;
  253. hr = WBEM_S_NO_ERROR;
  254. }
  255. else
  256. {
  257. _DBG_ASSERT( FAILED(hr) );
  258. }
  259. }
  260. return hr;
  261. }
  262. HRESULT CSmartObjectMarshaler::InternalPack( IWbemClassObject* pObj,
  263. LPCWSTR wszNamespace,
  264. DWORD dwFlags,
  265. ULONG cBuff,
  266. BYTE* pBuff,
  267. ULONG* pcUsed )
  268. {
  269. HRESULT hr;
  270. *pcUsed = 0;
  271. //
  272. // make sure we have enough room for at least the header data.
  273. //
  274. if ( cBuff < HDRSIZE )
  275. {
  276. return WBEM_E_BUFFER_TOO_SMALL;
  277. }
  278. ULONG iBuff = 0;
  279. memcpy( pBuff + iBuff, &g_dwSignature, 4 );
  280. iBuff += 4;
  281. memcpy( pBuff + iBuff, &g_dwVersion, 2 );
  282. iBuff += 2;
  283. //
  284. // write class information
  285. //
  286. DWORD dwSize;
  287. BOOL bPartialData;
  288. CWbemObjectWrapper ObjWrap;
  289. PBYTE pClassPartHash = NULL;
  290. if ( dwFlags == WMIMSG_FLAG_MRSH_FULL_ONCE )
  291. {
  292. hr = ObjWrap.SetPointer( pObj );
  293. if ( FAILED(hr) )
  294. {
  295. return hr;
  296. }
  297. //
  298. // send class part hash for class info
  299. //
  300. *(pBuff+iBuff) = char(e_ClassIdHash);
  301. iBuff++;
  302. dwSize = HASHSIZE;
  303. memcpy( pBuff+iBuff, &dwSize, 4 );
  304. iBuff += 4;
  305. hr = GetClassPartHash( ObjWrap, pBuff+iBuff, cBuff-iBuff );
  306. if ( FAILED(hr) )
  307. {
  308. return hr;
  309. }
  310. pClassPartHash = pBuff+iBuff;
  311. iBuff += HASHSIZE;
  312. //
  313. // see if we've sent the class part before
  314. //
  315. CInCritSec ics( &m_cs );
  316. bPartialData = m_SentMap[pClassPartHash];
  317. }
  318. else if ( dwFlags == WMIMSG_FLAG_MRSH_PARTIAL )
  319. {
  320. hr = ObjWrap.SetPointer( pObj );
  321. if ( FAILED(hr) )
  322. {
  323. return hr;
  324. }
  325. //
  326. // send class path and class part hash for class info
  327. //
  328. *(pBuff+iBuff) = char(e_ClassIdHashAndPath);
  329. iBuff++;
  330. PBYTE pLen = pBuff+iBuff;
  331. iBuff+= 4; // leave room for class info size
  332. hr = GetClassPartHash( ObjWrap, pBuff+iBuff, cBuff-iBuff );
  333. if ( FAILED(hr) )
  334. {
  335. return hr;
  336. }
  337. iBuff += HASHSIZE;
  338. hr = GetClassPath( pObj,
  339. wszNamespace,
  340. pBuff+iBuff,
  341. cBuff-iBuff,
  342. &dwSize );
  343. if ( FAILED(hr) )
  344. {
  345. return hr;
  346. }
  347. iBuff += dwSize;
  348. dwSize += HASHSIZE; // size if both hash and path
  349. memcpy( pLen, &dwSize, 4 );
  350. bPartialData = TRUE;
  351. }
  352. else if ( dwFlags == WMIMSG_FLAG_MRSH_FULL )
  353. {
  354. //
  355. // no class information
  356. //
  357. *(pBuff+iBuff) = char(e_ClassIdNone);
  358. iBuff++;
  359. memset( pBuff + iBuff, 0, 4 );
  360. iBuff += 4;
  361. bPartialData = FALSE;
  362. }
  363. else
  364. {
  365. return WBEM_E_INVALID_PARAMETER;
  366. }
  367. //
  368. // write data
  369. //
  370. if ( bPartialData )
  371. {
  372. *(pBuff+iBuff) = char(e_DataPartial);
  373. iBuff++;
  374. PBYTE pLen = pBuff+iBuff;
  375. iBuff += 4; // fill in length afterwords.
  376. //
  377. // now get instance part
  378. //
  379. _DBG_ASSERT( ObjWrap.IsValid() );
  380. hr = ObjWrap.GetObjectParts( pBuff+iBuff,
  381. cBuff-iBuff,
  382. WBEM_OBJ_DECORATION_PART |
  383. WBEM_OBJ_INSTANCE_PART,
  384. &dwSize );
  385. if ( FAILED(hr) )
  386. {
  387. return hr;
  388. }
  389. iBuff += dwSize;
  390. //
  391. // go back and set length ..
  392. //
  393. memcpy( pLen, &dwSize, 4 );
  394. }
  395. else
  396. {
  397. *(pBuff+iBuff) = char(e_DataFull);
  398. iBuff++;
  399. PBYTE pLen = pBuff+iBuff;
  400. iBuff += 4; // fill in length afterwords.
  401. //
  402. // for now, use MarshalInterface() to marshal object. The reason
  403. // for this is because SetObjectMemory() has a bug where
  404. // it assumes ownership of the memory ( even though the client
  405. // doesn't have access to the allocator used to free it ).
  406. //
  407. CBuffer Strm( pBuff+iBuff, cBuff-iBuff, FALSE );
  408. CWbemPtr<IMarshal> pMrsh;
  409. hr = pObj->QueryInterface( IID_IMarshal, (void**)&pMrsh );
  410. if ( FAILED(hr) )
  411. {
  412. return hr;
  413. }
  414. hr = pMrsh->MarshalInterface( &Strm,
  415. IID_IWbemClassObject,
  416. pObj,
  417. MSHCTX_INPROC,
  418. NULL,
  419. 0 );
  420. if ( FAILED(hr) )
  421. {
  422. return hr;
  423. }
  424. //
  425. // check if we read more data than we can fit into our buffer. We
  426. // can tell this if the buffer is no longer the one we passed in.
  427. //
  428. if ( Strm.GetRawData() != pBuff+iBuff )
  429. {
  430. return WBEM_E_BUFFER_TOO_SMALL;
  431. }
  432. dwSize = Strm.GetIndex();
  433. iBuff += dwSize;
  434. //
  435. // go back and set length of the data.
  436. //
  437. memcpy( pLen, &dwSize, 4 );
  438. if ( dwFlags == WMIMSG_FLAG_MRSH_FULL_ONCE )
  439. {
  440. //
  441. // mark that we've successfully packed the class part once.
  442. //
  443. _DBG_ASSERT( pClassPartHash != NULL );
  444. CInCritSec ics(&m_cs);
  445. m_SentMap[pClassPartHash] = TRUE;
  446. }
  447. }
  448. *pcUsed = iBuff;
  449. return WBEM_S_NO_ERROR;
  450. }
  451. STDMETHODIMP CSmartObjectMarshaler::Pack( IWbemClassObject* pObj,
  452. LPCWSTR wszNamespace,
  453. DWORD dwFlags,
  454. ULONG cBuff,
  455. BYTE* pBuff,
  456. ULONG* pcUsed )
  457. {
  458. HRESULT hr;
  459. ENTER_API_CALL
  460. hr = InternalPack( pObj, wszNamespace, dwFlags, cBuff, pBuff, pcUsed );
  461. if ( hr == WBEM_E_BUFFER_TOO_SMALL )
  462. {
  463. HRESULT hr2;
  464. hr2 = GetMaxMarshalSize( pObj, wszNamespace, dwFlags, pcUsed );
  465. if ( FAILED(hr2) )
  466. {
  467. hr = hr2;
  468. }
  469. }
  470. EXIT_API_CALL
  471. return hr;
  472. }
  473. STDMETHODIMP CSmartObjectMarshaler::Flush()
  474. {
  475. CInCritSec ics(&m_cs);
  476. m_SentMap.clear();
  477. return S_OK;
  478. }
  479. /***************************************************************************
  480. CSmartObjectUnmarshaler
  481. ****************************************************************************/
  482. HRESULT CSmartObjectUnmarshaler::EnsureInitialized()
  483. {
  484. HRESULT hr;
  485. CInCritSec ics( &m_cs );
  486. if ( m_pEmptyClass != NULL )
  487. {
  488. return WBEM_S_NO_ERROR;
  489. }
  490. //
  491. // allocate a template class object which we can use for spawning
  492. // 'empty' instances from.
  493. //
  494. CWbemPtr<IWbemClassObject> pEmptyClass;
  495. hr = CoCreateInstance( CLSID_WbemClassObject,
  496. NULL,
  497. CLSCTX_INPROC,
  498. IID_IWbemClassObject,
  499. (void**)&pEmptyClass );
  500. if ( FAILED(hr) )
  501. {
  502. return hr;
  503. }
  504. VARIANT vName;
  505. V_VT(&vName) = VT_BSTR;
  506. V_BSTR(&vName) = L"__DummyClass";
  507. hr = pEmptyClass->Put( L"__CLASS", 0, &vName, NULL );
  508. if ( FAILED(hr) )
  509. {
  510. return hr;
  511. }
  512. //
  513. // allocate a locator to access namespaces for obtaining class definitions.
  514. //
  515. CWbemPtr<IWbemLocator> pLocator;
  516. hr = CoCreateInstance( CLSID_WbemLocator,
  517. NULL,
  518. CLSCTX_INPROC,
  519. IID_IWbemLocator,
  520. (void**)&pLocator );
  521. if ( FAILED(hr) )
  522. {
  523. return hr;
  524. }
  525. //
  526. // Allocate a full object unmarshaler. This is used to create classes
  527. // or instances that were sent in full.
  528. //
  529. hr = CoCreateInstance( CLSID_WbemClassObjectProxy,
  530. NULL,
  531. CLSCTX_INPROC,
  532. IID_IMarshal,
  533. (void**)&m_pUnmrsh );
  534. if ( FAILED(hr) )
  535. {
  536. return hr;
  537. }
  538. m_pEmptyClass = pEmptyClass;
  539. m_pLocator = pLocator;
  540. return WBEM_S_NO_ERROR;
  541. }
  542. void CSmartObjectUnmarshaler::MakeRoomInCache( DWORD dwSize )
  543. {
  544. while ( !m_Cache.empty() && dwSize + m_ulCacheSize > m_ulMaxCacheSize )
  545. {
  546. DWORD dwLeastRecentTime = 0xffffffff;
  547. ClassPartMap::iterator it, itLeastRecent;
  548. for( it = m_Cache.begin(); it != m_Cache.end(); it++ )
  549. {
  550. CacheRecord& rCurrent = it->second;
  551. if ( rCurrent.m_dwLastUsedTime <= dwLeastRecentTime )
  552. {
  553. itLeastRecent = it;
  554. dwLeastRecentTime = rCurrent.m_dwLastUsedTime;
  555. }
  556. }
  557. _DBG_ASSERT( m_ulCacheSize >= itLeastRecent->second.m_dwClassSize );
  558. m_ulCacheSize -= itLeastRecent->second.m_dwClassSize;
  559. m_Cache.erase( itLeastRecent );
  560. }
  561. }
  562. HRESULT CSmartObjectUnmarshaler::CacheClassPart( PBYTE pClassHash,
  563. DWORD dwSize,
  564. IWbemClassObject* pClassPart )
  565. {
  566. HRESULT hr;
  567. CInCritSec ics(&m_cs);
  568. ClassPartMap::iterator it = m_Cache.find( pClassHash );
  569. if ( it == m_Cache.end() )
  570. {
  571. MakeRoomInCache( dwSize );
  572. if ( dwSize + m_ulCacheSize < m_ulMaxCacheSize )
  573. {
  574. //
  575. // create the record and add to cache.
  576. //
  577. CacheRecord Record;
  578. Record.m_dwClassSize = dwSize;
  579. Record.m_pClassPart = pClassPart;
  580. Record.m_dwLastUsedTime = GetTickCount();
  581. m_Cache[pClassHash] = Record;
  582. m_ulCacheSize += dwSize;
  583. hr = WBEM_S_NO_ERROR;
  584. }
  585. else
  586. {
  587. //
  588. // the class part size is too big to store in the cache.
  589. //
  590. hr = WBEM_S_FALSE;
  591. }
  592. }
  593. else
  594. {
  595. //
  596. // already in the cache.
  597. //
  598. hr = WBEM_S_NO_ERROR;
  599. }
  600. return hr;
  601. }
  602. HRESULT CSmartObjectUnmarshaler::FindClassPart( PBYTE pClassPartHash,
  603. LPCWSTR wszClassPath,
  604. IWbemClassObject** ppClassPart)
  605. {
  606. HRESULT hr;
  607. //
  608. // first try the cache ...
  609. //
  610. ClassPartMap::iterator it;
  611. {
  612. CInCritSec ics(&m_cs);
  613. it = m_Cache.find( pClassPartHash );
  614. if ( it != m_Cache.end() )
  615. {
  616. it->second.m_dwLastUsedTime = GetTickCount();
  617. *ppClassPart = it->second.m_pClassPart;
  618. (*ppClassPart)->AddRef();
  619. // DEBUGTRACE((LOG_ESS,
  620. // "MRSH: Cache Hit !!! %d bytes saved in transmission\n",
  621. // it->second.m_dwClassSize ));
  622. return WBEM_S_NO_ERROR;
  623. }
  624. }
  625. //
  626. // expensive route ... fetch the class object from wmi
  627. //
  628. if ( wszClassPath == NULL )
  629. {
  630. //
  631. // there's nothing we can do.
  632. //
  633. return WBEM_E_NOT_FOUND;
  634. }
  635. CWbemPtr<IWbemServices> pSvc;
  636. CWbemBSTR bsNamespace = wszClassPath;
  637. WCHAR* pch = wcschr( bsNamespace, ':' );
  638. if ( pch == NULL )
  639. {
  640. return WBEM_E_INVALID_OBJECT_PATH;
  641. }
  642. *pch++ = '\0';
  643. hr = m_pLocator->ConnectServer( bsNamespace, NULL, NULL,
  644. NULL, 0, NULL, NULL, &pSvc );
  645. if ( FAILED(hr) )
  646. {
  647. return hr;
  648. }
  649. CWbemBSTR bsRelpath = pch;
  650. CWbemPtr<IWbemClassObject> pClass;
  651. hr = pSvc->GetObject( bsRelpath, 0, NULL, &pClass, NULL );
  652. if ( FAILED(hr) )
  653. {
  654. return hr;
  655. }
  656. CWbemPtr<IWbemClassObject> pClassPart;
  657. hr = pClass->SpawnInstance( 0, &pClassPart );
  658. if ( FAILED(hr) )
  659. {
  660. return hr;
  661. }
  662. //
  663. // now we have to verify that hash of the class part and the
  664. // hash sent in the message are the same.
  665. //
  666. CWbemObjectWrapper ObjWrap;
  667. hr = ObjWrap.SetPointer( pClassPart );
  668. if ( FAILED(hr) )
  669. {
  670. return hr;
  671. }
  672. DWORD dwSize;
  673. hr = ObjWrap.GetObjectParts( NULL, 0, WBEM_OBJ_CLASS_PART, &dwSize );
  674. if ( hr != WBEM_E_BUFFER_TOO_SMALL )
  675. {
  676. _DBG_ASSERT( FAILED(hr) );
  677. return hr;
  678. }
  679. PBYTE pBuff = new BYTE[dwSize+HASHSIZE];
  680. if ( pBuff == NULL )
  681. {
  682. return WBEM_E_OUT_OF_MEMORY;
  683. }
  684. CVectorDeleteMe<BYTE> tdm( pBuff );
  685. hr = GetClassPartHash( ObjWrap, pBuff, dwSize+HASHSIZE );
  686. if ( FAILED(hr) )
  687. {
  688. return hr;
  689. }
  690. if ( memcmp( pBuff, pClassPartHash, HASHSIZE ) == 0 )
  691. {
  692. //
  693. // things look good so cache the class part.
  694. //
  695. hr = CacheClassPart( pClassPartHash, dwSize, pClassPart );
  696. if ( FAILED(hr) )
  697. {
  698. return hr;
  699. }
  700. *ppClassPart = pClassPart;
  701. (*ppClassPart)->AddRef();
  702. }
  703. else
  704. {
  705. //
  706. // class parts don't match up, nothing else we can do.
  707. //
  708. hr = WBEM_E_NOT_FOUND;
  709. }
  710. return hr;
  711. }
  712. STDMETHODIMP CSmartObjectUnmarshaler::Unpack( ULONG cBuff,
  713. PBYTE pBuff,
  714. DWORD dwFlags,
  715. IWbemClassObject** ppObj,
  716. ULONG* pcUsed )
  717. {
  718. HRESULT hr;
  719. ENTER_API_CALL
  720. *pcUsed = 0;
  721. *ppObj = NULL;
  722. hr = EnsureInitialized();
  723. if ( FAILED(hr) )
  724. {
  725. return hr;
  726. }
  727. if ( cBuff < HDRSIZE )
  728. {
  729. return WMIMSG_E_INVALIDMESSAGE;
  730. }
  731. //
  732. // verify signature and version info
  733. //
  734. DWORD dw;
  735. ULONG iBuff = 0;
  736. memcpy( &dw, pBuff + iBuff, 4 );
  737. iBuff += 6; // version info is not currently used;
  738. if ( dw != g_dwSignature )
  739. {
  740. return WMIMSG_E_INVALIDMESSAGE;
  741. }
  742. //
  743. // obtain the class id type
  744. //
  745. char chClassIdType = *(pBuff + iBuff);
  746. iBuff++;
  747. memcpy( &dw, pBuff + iBuff, 4 );
  748. iBuff += 4;
  749. if ( cBuff - iBuff - 5 < dw ) // 5 is for what's left in the hdr to read
  750. {
  751. return WMIMSG_E_INVALIDMESSAGE;
  752. }
  753. //
  754. // obtain the class information associated with the data
  755. //
  756. PBYTE pClassPartHash = NULL;
  757. LPCWSTR wszClassPath = NULL;
  758. if ( chClassIdType == e_ClassIdHash )
  759. {
  760. pClassPartHash = pBuff+iBuff;
  761. }
  762. else if ( chClassIdType == e_ClassIdHashAndPath )
  763. {
  764. pClassPartHash = pBuff+iBuff;
  765. wszClassPath = LPWSTR(pBuff+iBuff+HASHSIZE);
  766. if ( *(WCHAR*)(pBuff+iBuff+dw-2) != '\0' )
  767. {
  768. return WMIMSG_E_INVALIDMESSAGE;
  769. }
  770. }
  771. else if ( chClassIdType == e_ClassIdNone )
  772. {
  773. if ( dw != 0 )
  774. {
  775. return WMIMSG_E_INVALIDMESSAGE;
  776. }
  777. }
  778. else
  779. {
  780. return WMIMSG_E_INVALIDMESSAGE;
  781. }
  782. iBuff += dw;
  783. //
  784. // get data part info
  785. //
  786. char chDataType = *(pBuff+iBuff);
  787. iBuff++;
  788. memcpy( &dw, pBuff+iBuff, 4 );
  789. iBuff += 4;
  790. if ( dw > cBuff-iBuff )
  791. {
  792. return WMIMSG_E_INVALIDMESSAGE;
  793. }
  794. CWbemPtr<IWbemClassObject> pObj;
  795. if ( chDataType == e_DataFull )
  796. {
  797. CBuffer Strm( pBuff+iBuff, cBuff-iBuff, FALSE );
  798. hr = m_pUnmrsh->UnmarshalInterface( &Strm,
  799. IID_IWbemClassObject,
  800. (void**)&pObj );
  801. if ( FAILED(hr) )
  802. {
  803. return WMIMSG_E_INVALIDMESSAGE;
  804. }
  805. dw = Strm.GetIndex();
  806. //
  807. // if there is an associated hash we need to store the class part
  808. // of the unmarshaled object in our cache.
  809. //
  810. if ( pClassPartHash != NULL )
  811. {
  812. //
  813. // create an empty version of the instance to store in the
  814. // cache. All we're interested in storing is the class part.
  815. //
  816. CWbemPtr<IWbemClassObject> pClassPart;
  817. hr = pObj->SpawnInstance( 0, &pClassPart );
  818. if ( FAILED(hr) )
  819. {
  820. return hr;
  821. }
  822. CWbemObjectWrapper ObjWrap;
  823. hr = ObjWrap.SetPointer( pClassPart );
  824. if ( FAILED(hr) )
  825. {
  826. return hr;
  827. }
  828. DWORD dwSize;
  829. hr = ObjWrap.GetObjectParts( NULL,
  830. 0,
  831. WBEM_OBJ_CLASS_PART,
  832. &dwSize );
  833. if ( hr != WBEM_E_BUFFER_TOO_SMALL )
  834. {
  835. _DBG_ASSERT( FAILED(hr) );
  836. return hr;
  837. }
  838. hr = CacheClassPart( pClassPartHash, dwSize, pClassPart );
  839. if ( FAILED(hr) )
  840. {
  841. return hr;
  842. }
  843. }
  844. }
  845. else if ( chDataType == e_DataPartial )
  846. {
  847. CWbemPtr<IWbemClassObject> pClassPart;
  848. _DBG_ASSERT( pClassPartHash != NULL );
  849. hr = FindClassPart( pClassPartHash, wszClassPath, &pClassPart );
  850. if ( FAILED(hr) )
  851. {
  852. return hr;
  853. }
  854. hr = m_pEmptyClass->SpawnInstance( 0, &pObj );
  855. if ( FAILED(hr) )
  856. {
  857. return hr;
  858. }
  859. CWbemObjectWrapper ObjWrap;
  860. hr = ObjWrap.SetPointer( pObj );
  861. if ( FAILED(hr) )
  862. {
  863. return hr;
  864. }
  865. //
  866. // aquires ownership of the memory -- must be CoTaskMemAlloc-ed
  867. // kind of unfortunate - but the memory has to be allocated and
  868. // copied sometime so guess its not that big of a deal.
  869. //
  870. PVOID pInstData = CoTaskMemAlloc( dw );
  871. if ( NULL == pInstData )
  872. {
  873. return WBEM_E_OUT_OF_MEMORY;
  874. }
  875. memcpy( pInstData, pBuff+iBuff, dw );
  876. hr = ObjWrap.SetObjectParts( pInstData,
  877. dw,
  878. WBEM_OBJ_DECORATION_PART |
  879. WBEM_OBJ_INSTANCE_PART );
  880. if ( FAILED(hr) )
  881. {
  882. CoTaskMemFree( pInstData );
  883. return hr;
  884. }
  885. hr = ObjWrap.MergeClassPart( pClassPart );
  886. if ( FAILED(hr) )
  887. {
  888. return hr;
  889. }
  890. }
  891. else
  892. {
  893. return WMIMSG_E_INVALIDMESSAGE;
  894. }
  895. iBuff += dw; // advance the index to account for the data part
  896. pObj->AddRef();
  897. *ppObj = pObj;
  898. *pcUsed = iBuff;
  899. EXIT_API_CALL
  900. return WBEM_S_NO_ERROR;
  901. }
  902. STDMETHODIMP CSmartObjectUnmarshaler::Flush()
  903. {
  904. CInCritSec ics(&m_cs);
  905. m_Cache.clear();
  906. return S_OK;
  907. }