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.

1585 lines
46 KiB

  1. /*++
  2. Copyright (C) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. History:
  6. --*/
  7. ///////////////////////////////////////////////////////////////////////////////
  8. //
  9. // Cache.cpp
  10. //
  11. ///////////////////////////////////////////////////////////////////////////////
  12. #include "precomp.h"
  13. #include <winperf.h>
  14. #include <comdef.h>
  15. #include <algorithm>
  16. #include <wbemint.h>
  17. #include <sync.h> // for CInCritSec
  18. #include <autoptr.h>
  19. #include "Cache.h"
  20. #include "WMIObjCooker.h"
  21. #include "CookerUtils.h"
  22. ///////////////////////////////////////////////////////////////////////////////
  23. //
  24. // CProperty
  25. // =========
  26. //
  27. // The base property - used for raw properties and the base
  28. // class for the CookedProperty.
  29. //
  30. ///////////////////////////////////////////////////////////////////////////////
  31. CProperty::CProperty(LPWSTR wszName,
  32. long lHandle, CIMTYPE ct ) :
  33. #ifdef _VERBOSE
  34. m_wszName( NULL ),
  35. #endif
  36. m_lPropHandle( lHandle ),
  37. m_ct( ct )
  38. ///////////////////////////////////////////////////////////////////////////////
  39. //
  40. //
  41. //
  42. // Parameters:
  43. //
  44. //
  45. ///////////////////////////////////////////////////////////////////////////////
  46. {
  47. #ifdef _VERBOSE
  48. size_t length = wcslen( wszName ) + 1;
  49. m_wszName = new WCHAR[ length ];
  50. if (m_wszName)
  51. StringCchCopyW( m_wszName, length , wszName);
  52. #endif
  53. }
  54. CProperty::~CProperty()
  55. {
  56. #ifdef _VERBOSE
  57. delete [] m_wszName;
  58. #endif
  59. }
  60. #ifdef _VERBOSE
  61. LPWSTR CProperty::GetName()
  62. {
  63. return m_wszName?m_wszName:L"";
  64. }
  65. #endif
  66. CIMTYPE CProperty::GetType()
  67. {
  68. return m_ct;
  69. }
  70. long CProperty::GetHandle()
  71. {
  72. return m_lPropHandle;
  73. }
  74. ///////////////////////////////////////////////////////////////////////////////
  75. //
  76. // CCookingProperty
  77. // ================
  78. //
  79. // The cooked property - used to model the data required to
  80. // cook a property of a cooked class
  81. //
  82. ///////////////////////////////////////////////////////////////////////////////
  83. CCookingProperty::CCookingProperty( LPWSTR wszName,
  84. DWORD dwCounterType,
  85. long lPropHandle,
  86. CIMTYPE ct,
  87. DWORD dwReqProp,
  88. BOOL bUseWellKnownIfNeeded) :
  89. CProperty( wszName, lPropHandle, ct ),
  90. m_dwCounterType( dwCounterType ),
  91. m_dwReqProp(dwReqProp),
  92. m_nTimeFreq( 0 ),
  93. m_lScale(0), // 10^0 = 1
  94. m_pRawCounterProp( NULL ),
  95. m_pTimeProp( NULL ),
  96. m_pFrequencyProp( NULL ),
  97. m_pBaseProp( NULL ),
  98. m_nSampleWindow( 0 ),
  99. m_nTimeWindow( 0 ),
  100. m_bUseWellKnownIfNeeded(bUseWellKnownIfNeeded)
  101. ///////////////////////////////////////////////////////////////////////////////
  102. //
  103. // Constructor
  104. //
  105. // Parameters:
  106. // wszName - The property name
  107. // dwCounterType - The property's counter type
  108. // lPropHandle - The cooking property's WMI Access handle
  109. // ct - The CIM type of the property
  110. //
  111. ///////////////////////////////////////////////////////////////////////////////
  112. {}
  113. CCookingProperty::~CCookingProperty()
  114. {
  115. delete m_pRawCounterProp;
  116. delete m_pTimeProp;
  117. delete m_pFrequencyProp;
  118. delete m_pBaseProp;
  119. }
  120. //
  121. //
  122. //
  123. // Parameters:
  124. // pCookingClassAccess - The class definition for the cooking class
  125. //
  126. // Description:
  127. // For each property of the class to be cooked
  128. // we need to find the property of the Raw class needed in the formula
  129. // The 'Counter' qualifier is always needed,
  130. // but thereafter we might need the timestap, the base, the frequency, ecc, ecc
  131. // SOme of these are in the PropertyQualifierSet, but other can be defaulted in the
  132. // ClassQualifierSet
  133. //
  134. ///////////////////////////////////////////////////////////////////////////////
  135. WMISTATUS CCookingProperty::Initialize( IWbemQualifierSet* pCookingPropQualifierSet,
  136. IWbemObjectAccess* pRawAccess,
  137. IWbemQualifierSet* pCookingClassQSet)
  138. {
  139. WMISTATUS dwStatus = WBEM_NO_ERROR;
  140. _variant_t vVal;
  141. // Initialize the raw counter property ("Counter")
  142. // ===============================================
  143. dwStatus = pCookingPropQualifierSet->Get( WMI_COOKER_RAW_COUNTER, 0, &vVal, NULL );
  144. if ( SUCCEEDED( dwStatus ) && ( vVal.vt != VT_BSTR ) )
  145. {
  146. dwStatus = E_FAIL;
  147. }
  148. if ( SUCCEEDED( dwStatus ) )
  149. {
  150. // Get the raw data properties
  151. // ===========================
  152. CIMTYPE ct;
  153. long lHandle = 0;
  154. WCHAR* wszRawCounterName = vVal.bstrVal;
  155. // Get the raw counter property
  156. // ============================
  157. dwStatus = pRawAccess->GetPropertyHandle( wszRawCounterName, &ct, &lHandle );
  158. if ( SUCCEEDED( dwStatus ) )
  159. {
  160. m_pRawCounterProp = new CProperty( wszRawCounterName, lHandle, ct );
  161. if ( NULL == m_pRawCounterProp )
  162. {
  163. dwStatus = WBEM_E_OUT_OF_MEMORY;
  164. }
  165. }
  166. // Get the raw base property
  167. // =========================
  168. if ( SUCCEEDED( dwStatus ) )
  169. {
  170. _variant_t vProp;
  171. dwStatus = pCookingPropQualifierSet->Get( WMI_COOKER_RAW_BASE, 0, &vProp, NULL );
  172. if ( SUCCEEDED( dwStatus ) )
  173. {
  174. if ( vProp.vt == VT_BSTR )
  175. {
  176. dwStatus = pRawAccess->GetPropertyHandle( vProp.bstrVal, &ct, &lHandle );
  177. if ( SUCCEEDED( dwStatus ) )
  178. {
  179. m_pBaseProp = new CProperty( vProp.bstrVal, lHandle, ct );
  180. if ( NULL == m_pBaseProp )
  181. {
  182. dwStatus = WBEM_E_OUT_OF_MEMORY;
  183. }
  184. }
  185. }
  186. else
  187. {
  188. dwStatus = WBEM_E_TYPE_MISMATCH;
  189. }
  190. }
  191. else
  192. {
  193. // the property qualifier set failed, try the class one
  194. _variant_t varProp; // does not throw, simple container
  195. dwStatus = pCookingClassQSet->Get( WMI_COOKER_RAW_BASE, 0, &varProp, NULL );
  196. if ( SUCCEEDED( dwStatus ) )
  197. {
  198. if ( varProp.vt == VT_BSTR )
  199. {
  200. dwStatus = pRawAccess->GetPropertyHandle( varProp.bstrVal, &ct, &lHandle );
  201. if ( SUCCEEDED( dwStatus ) )
  202. {
  203. m_pBaseProp = new CProperty( varProp.bstrVal, lHandle, ct );
  204. if ( NULL == m_pBaseProp )
  205. {
  206. dwStatus = WBEM_E_OUT_OF_MEMORY;
  207. }
  208. }
  209. }
  210. else
  211. {
  212. dwStatus = WBEM_E_TYPE_MISMATCH;
  213. }
  214. }
  215. else
  216. {
  217. dwStatus = WBEM_NO_ERROR;
  218. }
  219. }
  220. //
  221. // no error so far, the BASE qulifier is REQUIRED, but none is found
  222. //
  223. if ( SUCCEEDED( dwStatus ) &&
  224. IsReq(REQ_BASE) &&
  225. (NULL == m_pBaseProp))
  226. {
  227. dwStatus = WBEM_E_INVALID_CLASS;
  228. }
  229. }
  230. // Get the raw timestamp property record
  231. // =====================================
  232. if ( SUCCEEDED( dwStatus ) )
  233. {
  234. _variant_t vProp2;
  235. dwStatus = pCookingPropQualifierSet->Get( WMI_COOKER_RAW_TIME, 0, &vProp2, NULL );
  236. if ( SUCCEEDED( dwStatus ) )
  237. {
  238. if ( vProp2.vt == VT_BSTR )
  239. {
  240. dwStatus = pRawAccess->GetPropertyHandle( vProp2.bstrVal, &ct, &lHandle );
  241. if ( SUCCEEDED( dwStatus ) )
  242. {
  243. m_pTimeProp = new CProperty( vProp2.bstrVal, lHandle, ct );
  244. if ( NULL == m_pTimeProp )
  245. {
  246. dwStatus = WBEM_E_OUT_OF_MEMORY;
  247. }
  248. }
  249. }
  250. else
  251. {
  252. dwStatus = WBEM_E_TYPE_MISMATCH;
  253. }
  254. }
  255. else
  256. {
  257. // the property qualifier set failed, try the class one
  258. //PERF_TIMER_TICK
  259. //PERF_TIMER_100NS
  260. //PERF_OBJECT_TIMER
  261. _variant_t varProp; // does not throw, simple container
  262. if (m_dwCounterType & PERF_OBJECT_TIMER)
  263. {
  264. dwStatus = pCookingClassQSet->Get( WMI_COOKER_RAW_TIME_OBJ, 0, &varProp, NULL );
  265. if (FAILED(dwStatus) && m_bUseWellKnownIfNeeded)
  266. {
  267. dwStatus = WBEM_NO_ERROR;
  268. varProp = WMI_COOKER_REQ_TIMESTAMP_PERFTIME;
  269. }
  270. }
  271. else if (m_dwCounterType & PERF_TIMER_100NS)
  272. {
  273. dwStatus = pCookingClassQSet->Get( WMI_COOKER_RAW_TIME_100NS, 0, &varProp, NULL );
  274. if (FAILED(dwStatus) && m_bUseWellKnownIfNeeded)
  275. {
  276. dwStatus = WBEM_NO_ERROR;
  277. varProp = WMI_COOKER_REQ_TIMESTAMP_SYS100NS;
  278. }
  279. } else
  280. {
  281. dwStatus = pCookingClassQSet->Get( WMI_COOKER_RAW_TIME_SYS, 0, &varProp, NULL );
  282. if (FAILED(dwStatus) && m_bUseWellKnownIfNeeded)
  283. {
  284. dwStatus = WBEM_NO_ERROR;
  285. varProp = WMI_COOKER_REQ_TIMESTAMP_OBJECT;
  286. }
  287. }
  288. if ( SUCCEEDED( dwStatus ) )
  289. {
  290. if ( varProp.vt == VT_BSTR )
  291. {
  292. dwStatus = pRawAccess->GetPropertyHandle( varProp.bstrVal, &ct, &lHandle );
  293. if ( SUCCEEDED( dwStatus ) )
  294. {
  295. m_pTimeProp = new CProperty( varProp.bstrVal, lHandle, ct );
  296. if ( NULL == m_pTimeProp )
  297. {
  298. dwStatus = WBEM_E_OUT_OF_MEMORY;
  299. }
  300. }
  301. }
  302. else
  303. {
  304. dwStatus = WBEM_E_TYPE_MISMATCH;
  305. }
  306. }
  307. else
  308. {
  309. dwStatus = WBEM_NO_ERROR;
  310. }
  311. }
  312. // get in cascade the frequency property
  313. if (SUCCEEDED(dwStatus))
  314. {
  315. _variant_t VarFreqName; // simple container, does not throw
  316. dwStatus = pCookingPropQualifierSet->Get( WMI_COOKER_RAW_FREQUENCY, 0, &VarFreqName, NULL );
  317. if (SUCCEEDED(dwStatus))
  318. {
  319. if (VarFreqName.vt == VT_BSTR)
  320. {
  321. dwStatus = pRawAccess->GetPropertyHandle( VarFreqName.bstrVal, &ct, &lHandle );
  322. if (SUCCEEDED(dwStatus))
  323. {
  324. m_pFrequencyProp = new CProperty( VarFreqName.bstrVal, lHandle, ct );
  325. if ( NULL == m_pFrequencyProp )
  326. {
  327. dwStatus = WBEM_E_OUT_OF_MEMORY;
  328. }
  329. }
  330. } else {
  331. dwStatus = WBEM_E_TYPE_MISMATCH;
  332. }
  333. }
  334. else
  335. {
  336. if (m_dwCounterType & PERF_OBJECT_TIMER)
  337. {
  338. dwStatus = pCookingClassQSet->Get( WMI_COOKER_RAW_FREQ_OBJ, 0, &VarFreqName, NULL );
  339. if (FAILED(dwStatus) && m_bUseWellKnownIfNeeded)
  340. {
  341. dwStatus = WBEM_NO_ERROR;
  342. VarFreqName = WMI_COOKER_REQ_FREQUENCY_PERFTIME;
  343. }
  344. }
  345. else if (m_dwCounterType & PERF_TIMER_100NS)
  346. {
  347. dwStatus = pCookingClassQSet->Get( WMI_COOKER_RAW_FREQ_100NS, 0, &VarFreqName, NULL );
  348. if (FAILED(dwStatus) && m_bUseWellKnownIfNeeded)
  349. {
  350. dwStatus = WBEM_NO_ERROR;
  351. VarFreqName = WMI_COOKER_REQ_FREQUENCY_SYS100NS;
  352. }
  353. } else
  354. {
  355. dwStatus = pCookingClassQSet->Get( WMI_COOKER_RAW_FREQ_SYS, 0, &VarFreqName, NULL );
  356. if (FAILED(dwStatus) && m_bUseWellKnownIfNeeded)
  357. {
  358. dwStatus = WBEM_NO_ERROR;
  359. VarFreqName = WMI_COOKER_REQ_FREQUENCY_OBJECT;
  360. }
  361. }
  362. if (SUCCEEDED(dwStatus))
  363. {
  364. if (VarFreqName.vt == VT_BSTR)
  365. {
  366. dwStatus = pRawAccess->GetPropertyHandle( VarFreqName.bstrVal, &ct, &lHandle );
  367. if (SUCCEEDED(dwStatus))
  368. {
  369. m_pFrequencyProp = new CProperty( VarFreqName.bstrVal, lHandle, ct );
  370. if ( NULL == m_pFrequencyProp )
  371. {
  372. dwStatus = WBEM_E_OUT_OF_MEMORY;
  373. }
  374. }
  375. } else {
  376. dwStatus = WBEM_E_TYPE_MISMATCH;
  377. }
  378. } else {
  379. dwStatus = WBEM_S_NO_ERROR;
  380. }
  381. }
  382. }
  383. }
  384. //
  385. // Get the Scale factor from ONLY the property Qualifier
  386. //
  387. if ( SUCCEEDED( dwStatus ) )
  388. {
  389. _variant_t VarScale; // does not throw, simple container
  390. dwStatus = pCookingPropQualifierSet->Get( WMI_COOKER_SCALE_FACT, 0, &VarScale, NULL );
  391. if ( SUCCEEDED( dwStatus ) && (V_VT(&VarScale) == VT_I4))
  392. {
  393. m_lScale = VarScale.intVal;
  394. }
  395. else
  396. {
  397. dwStatus = WBEM_S_NO_ERROR;
  398. }
  399. }
  400. // Get the Sample and Time windows value
  401. // =====================================
  402. if ( SUCCEEDED( dwStatus ) )
  403. {
  404. DWORD dwSampleStatus = WBEM_NO_ERROR,
  405. dwTimeStatus = WBEM_NO_ERROR;
  406. _variant_t vSampleProp; // does not throw, simple container
  407. _variant_t vTimeProp; // does not throw, simple container
  408. dwSampleStatus = pCookingPropQualifierSet->Get( WMI_COOKER_SAMPLE_WINDOW, 0, &vSampleProp, NULL );
  409. dwTimeStatus = pCookingPropQualifierSet->Get( WMI_COOKER_TIME_WINDOW, 0, &vTimeProp, NULL );
  410. if ( SUCCEEDED( dwSampleStatus ) && SUCCEEDED( dwTimeStatus ) )
  411. {
  412. dwStatus = WBEM_E_INVALID_PROPERTY;
  413. }
  414. else if ( SUCCEEDED( dwSampleStatus ) )
  415. {
  416. if ( vSampleProp.vt != VT_I4 )
  417. {
  418. dwStatus = E_FAIL;
  419. }
  420. else
  421. {
  422. m_nSampleWindow = vSampleProp.intVal;
  423. }
  424. }
  425. else if ( SUCCEEDED( dwTimeStatus ) )
  426. {
  427. if ( vTimeProp.vt != VT_I4 )
  428. dwStatus = E_FAIL;
  429. else
  430. m_nTimeWindow = vTimeProp.intVal;
  431. }
  432. else
  433. {
  434. m_nSampleWindow = WMI_DEFAULT_SAMPLE_WINDOW;
  435. }
  436. }
  437. }
  438. return dwStatus;
  439. }
  440. //
  441. // Description: the RawCooker could easily be a Singleton shared among
  442. // all the cooking properties, since it does not mantain state on behaf of the
  443. // Cooking property
  444. //
  445. ///////////////////////////////////////////////////////////////////
  446. WMISTATUS CCookingProperty::Cook( DWORD dwNumSamples, __int64* aRawCounter, __int64* aBaseCounter, __int64* aTimeStamp, __int64* pnResult )
  447. {
  448. WMISTATUS dwStatus = WBEM_NO_ERROR;
  449. dwStatus = m_Cooker.CookRawValues( m_dwCounterType,
  450. dwNumSamples,
  451. aTimeStamp,
  452. aRawCounter,
  453. aBaseCounter,
  454. m_nTimeFreq,
  455. m_lScale,
  456. pnResult );
  457. return dwStatus;
  458. }
  459. CProperty* CCookingProperty::GetRawCounterProperty()
  460. {
  461. return m_pRawCounterProp;
  462. }
  463. CProperty* CCookingProperty::GetBaseProperty()
  464. {
  465. return m_pBaseProp;
  466. }
  467. CProperty* CCookingProperty::GetTimeProperty()
  468. {
  469. return m_pTimeProp;
  470. }
  471. HRESULT
  472. CCookingProperty::SetFrequency(IWbemObjectAccess * pObjAcc)
  473. {
  474. if (m_nTimeFreq == 0)
  475. {
  476. // get the Frequency from the Raw Object
  477. if (m_pFrequencyProp)
  478. {
  479. __int64 lTmp;
  480. HRESULT hRes = GetPropValue(m_pFrequencyProp,pObjAcc,lTmp);
  481. if (SUCCEEDED(hRes)) m_nTimeFreq = lTmp;
  482. return hRes;
  483. }
  484. else if (!(m_dwReqProp & REQ_FREQ))
  485. {
  486. return WBEM_NO_ERROR;
  487. }
  488. else
  489. {
  490. LARGE_INTEGER li;
  491. if (QueryPerformanceFrequency(&li))
  492. {
  493. m_nTimeFreq = li.QuadPart;
  494. return WBEM_NO_ERROR;
  495. }
  496. else
  497. {
  498. return WBEM_E_INVALID_PARAMETER;
  499. }
  500. }
  501. }
  502. else
  503. {
  504. return WBEM_NO_ERROR;
  505. }
  506. }
  507. unsigned __int64 CCookingProperty::GetFrequency(void)
  508. {
  509. return m_nTimeFreq;
  510. }
  511. ///////////////////////////////////////////////////////////////////////////////
  512. //
  513. // CPropertySampleCache
  514. // ====================
  515. //
  516. // This class caches the sample data for a single property for a single
  517. // instance
  518. //
  519. ///////////////////////////////////////////////////////////////////////////////
  520. CPropertySampleCache::CPropertySampleCache():
  521. m_aRawCounterVals(NULL),
  522. m_aBaseCounterVals(NULL),
  523. m_aTimeStampVals(NULL),
  524. m_dwRefreshID(0)
  525. {
  526. }
  527. CPropertySampleCache::~CPropertySampleCache()
  528. {
  529. delete [] m_aRawCounterVals;
  530. delete [] m_aBaseCounterVals;
  531. delete [] m_aTimeStampVals;
  532. }
  533. WMISTATUS CPropertySampleCache::SetSampleInfo( DWORD dwNumActiveSamples, DWORD dwMinReqSamples )
  534. {
  535. WMISTATUS dwStatus = WBEM_NO_ERROR;
  536. m_dwNumSamples = 0;
  537. m_dwTotSamples = dwNumActiveSamples;
  538. m_aRawCounterVals = new __int64[dwNumActiveSamples];
  539. if (!m_aRawCounterVals)
  540. return WBEM_E_OUT_OF_MEMORY;
  541. memset( m_aRawCounterVals, 0, sizeof(__int64) * dwNumActiveSamples );
  542. m_aBaseCounterVals = new __int64[dwNumActiveSamples];
  543. if (!m_aBaseCounterVals)
  544. return WBEM_E_OUT_OF_MEMORY;
  545. memset( m_aBaseCounterVals, 0, sizeof(__int64) * dwNumActiveSamples );
  546. m_aTimeStampVals = new __int64[dwNumActiveSamples];
  547. if (!m_aTimeStampVals)
  548. return WBEM_E_OUT_OF_MEMORY;
  549. memset( m_aBaseCounterVals, 0, sizeof(__int64) * dwNumActiveSamples );
  550. return dwStatus;
  551. }
  552. WMISTATUS CPropertySampleCache::SetSampleData( DWORD dwRefreshID, __int64 nRawCounter, __int64 nRawBase, __int64 nTimeStamp )
  553. {
  554. WMISTATUS dwStatus = WBEM_NO_ERROR;
  555. if (dwRefreshID <= m_dwRefreshID)
  556. {
  557. return dwStatus;
  558. }
  559. else
  560. {
  561. m_dwRefreshID = dwRefreshID;
  562. }
  563. if ( m_dwNumSamples < m_dwTotSamples )
  564. {
  565. m_dwNumSamples++;
  566. }
  567. if ( m_dwTotSamples >= 2 )
  568. {
  569. for (LONG i = (LONG)(m_dwTotSamples-2); i>=0; i--)
  570. {
  571. m_aRawCounterVals[i+1] = m_aRawCounterVals[i];
  572. m_aBaseCounterVals[i+1] = m_aBaseCounterVals[i];
  573. m_aTimeStampVals[i+1] = m_aTimeStampVals[i];
  574. }
  575. }
  576. m_aRawCounterVals[0] = nRawCounter;
  577. m_aBaseCounterVals[0] = nRawBase;
  578. m_aTimeStampVals[0] = nTimeStamp;
  579. return dwStatus;
  580. }
  581. WMISTATUS CPropertySampleCache::GetData( DWORD* pdwNumSamples, __int64** paRawCounter, __int64** paBaseCounter, __int64** paTimeStamp )
  582. {
  583. WMISTATUS dwStatus = WBEM_NO_ERROR;
  584. *pdwNumSamples = m_dwNumSamples;
  585. *paRawCounter = m_aRawCounterVals;
  586. *paBaseCounter = m_aBaseCounterVals;
  587. *paTimeStamp = m_aTimeStampVals;
  588. return dwStatus;
  589. }
  590. ///////////////////////////////////////////////////////////////////////////////
  591. //
  592. // CCookingInstance
  593. // ================
  594. //
  595. // The cooking instance - used to model an instance of a cooked object. Each
  596. // property maintains a cache of values that will be used to compute the
  597. // final cooked value.
  598. //
  599. ///////////////////////////////////////////////////////////////////////////////
  600. CCookingInstance::CCookingInstance( IWbemObjectAccess *pCookingInstance, DWORD dwNumProps ) :
  601. m_wszKey( NULL ),
  602. m_aPropertySamples( NULL ),
  603. m_pCookingInstance( pCookingInstance ),
  604. m_pRawInstance( NULL ),
  605. m_dwNumProps( dwNumProps )
  606. ///////////////////////////////////////////////////////////////////////////////
  607. //
  608. //
  609. //
  610. // Parameters:
  611. //
  612. //
  613. ///////////////////////////////////////////////////////////////////////////////
  614. {
  615. if ( m_pCookingInstance )
  616. {
  617. m_pCookingInstance->AddRef();
  618. m_wszKey = ::GetKey( m_pCookingInstance );
  619. }
  620. if (dwNumProps)
  621. {
  622. // allocation checked in IsValid
  623. m_aPropertySamples = new CPropertySampleCache[dwNumProps];
  624. };
  625. }
  626. CCookingInstance::~CCookingInstance()
  627. {
  628. delete [] m_wszKey;
  629. if ( NULL != m_pCookingInstance )
  630. {
  631. m_pCookingInstance->Release();
  632. }
  633. delete [] m_aPropertySamples;
  634. if ( NULL != m_pRawInstance )
  635. {
  636. m_pRawInstance->Release();
  637. }
  638. }
  639. WMISTATUS CCookingInstance::InitProperty( DWORD dwProp, DWORD dwNumActiveSamples, DWORD dwMinReqSamples )
  640. {
  641. return m_aPropertySamples[dwProp].SetSampleInfo( dwNumActiveSamples, dwMinReqSamples );
  642. }
  643. WMISTATUS CCookingInstance::SetRawSourceInstance( IWbemObjectAccess* pRawSampleSource )
  644. {
  645. WMISTATUS dwStatus = WBEM_NO_ERROR;
  646. if ( NULL != m_pRawInstance )
  647. {
  648. m_pRawInstance->Release();
  649. }
  650. m_pRawInstance = pRawSampleSource;
  651. if ( NULL != m_pRawInstance )
  652. {
  653. m_pRawInstance->AddRef();
  654. }
  655. return dwStatus;
  656. }
  657. WMISTATUS CCookingInstance::GetRawSourceInstance( IWbemObjectAccess** ppRawSampleSource )
  658. {
  659. WMISTATUS dwStatus = WBEM_NO_ERROR;
  660. *ppRawSampleSource = m_pRawInstance;
  661. if ( NULL != m_pRawInstance )
  662. {
  663. m_pRawInstance->AddRef();
  664. }
  665. return dwStatus;
  666. }
  667. IWbemObjectAccess* CCookingInstance::GetInstance()
  668. {
  669. if ( NULL != m_pCookingInstance )
  670. m_pCookingInstance->AddRef();
  671. return m_pCookingInstance;
  672. }
  673. WMISTATUS CCookingInstance::AddSample( DWORD dwRefreshStamp, DWORD dwProp, __int64 nRawCounter, __int64 nRawBase, __int64 nTimeStamp )
  674. {
  675. return m_aPropertySamples[dwProp].SetSampleData( dwRefreshStamp, nRawCounter, nRawBase, nTimeStamp );
  676. }
  677. WMISTATUS CCookingInstance::Refresh( IWbemObjectAccess* pRawData, IWbemObjectAccess** ppCookedData )
  678. {
  679. WMISTATUS dwStatus = WBEM_NO_ERROR;
  680. return dwStatus;
  681. }
  682. WMISTATUS CCookingInstance::UpdateSamples()
  683. {
  684. WMISTATUS dwStatus = WBEM_NO_ERROR;
  685. return dwStatus;
  686. }
  687. WMISTATUS CCookingInstance::CookProperty( DWORD dwProp, CCookingProperty* pProperty )
  688. ///////////////////////////////////////////////////////////////////////////////
  689. //
  690. //
  691. //
  692. // Parameters:
  693. //
  694. //
  695. ///////////////////////////////////////////////////////////////////////////////
  696. {
  697. WMISTATUS dwStatus = WBEM_NO_ERROR;
  698. DWORD dwNumSamples = 0;
  699. __int64* aRawCounter;
  700. __int64* aBaseCounter;
  701. __int64* aTimeStamp;
  702. __int64 nResult = 0;
  703. long lHandle = pProperty->GetHandle();
  704. dwStatus = m_aPropertySamples[dwProp].GetData( &dwNumSamples, &aRawCounter, &aBaseCounter, &aTimeStamp );
  705. if ( SUCCEEDED( dwStatus ) )
  706. {
  707. #ifdef _VERBOSE
  708. {
  709. unsigned __int64 Freq = pProperty->GetFrequency();
  710. DbgPrintfA(0,"PropName %S sample %d\n"
  711. "Raw %I64d %I64d\n"
  712. "Base %I64d %I64d\n"
  713. "Time %I64d %I64d\n"
  714. "Freq %I64d\n",
  715. pProperty->GetName(),dwNumSamples,
  716. aRawCounter[0],aRawCounter[1],
  717. aBaseCounter[0],aBaseCounter[1],
  718. aTimeStamp[0],aTimeStamp[1],
  719. Freq);
  720. }
  721. #endif
  722. if (SUCCEEDED(dwStatus = pProperty->SetFrequency(m_pRawInstance))){
  723. dwStatus = pProperty->Cook( dwNumSamples, aRawCounter, aBaseCounter, aTimeStamp, &nResult );
  724. }
  725. #ifdef _VERBOSE
  726. DbgPrintfA(0,"Result %I64d dwStatus %08x\n",nResult,dwStatus);
  727. #endif
  728. };
  729. if ( SUCCEEDED( dwStatus ) )
  730. {
  731. switch ( pProperty->GetType() )
  732. {
  733. case CIM_UINT32:
  734. dwStatus = m_pCookingInstance->WriteDWORD( lHandle, (DWORD) nResult );
  735. break;
  736. case CIM_UINT64:
  737. dwStatus = m_pCookingInstance->WriteQWORD( lHandle, nResult );
  738. break;
  739. default:
  740. dwStatus = WBEM_E_TYPE_MISMATCH;
  741. }
  742. };
  743. return dwStatus;
  744. }
  745. /////////////////////////////////////////////////////////////////////////
  746. //
  747. //
  748. // CEnumeratorCache
  749. //
  750. //
  751. /////////////////////////////////////////////////////////////////////////
  752. CEnumeratorCache::CEnumeratorCache() :
  753. m_dwEnum( 0 )
  754. ///////////////////////////////////////////////////////////////////////////////
  755. //
  756. //
  757. //
  758. // Parameters:
  759. //
  760. //
  761. ///////////////////////////////////////////////////////////////////////////////
  762. {
  763. }
  764. CEnumeratorCache::~CEnumeratorCache()
  765. {
  766. CInCritSec ics(&m_cs);
  767. for (DWORD i=0;i<m_apEnumerators.size();i++)
  768. {
  769. CEnumeratorManager* pEnumMgr = m_apEnumerators[i];
  770. if (pEnumMgr) pEnumMgr->Release();
  771. }
  772. }
  773. WMISTATUS CEnumeratorCache::AddEnum( LPCWSTR wszCookingClass,
  774. IWbemClassObject* pCookedClass,
  775. IWbemClassObject* pRawClass,
  776. IWbemHiPerfEnum* pCookedEnum,
  777. IWbemHiPerfEnum* pRawEnum,
  778. long lIDRaw,
  779. DWORD* pdwID )
  780. ///////////////////////////////////////////////////////////////////////////////
  781. //
  782. //
  783. //
  784. // Parameters:
  785. //
  786. //
  787. ///////////////////////////////////////////////////////////////////////////////
  788. {
  789. WMISTATUS dwStatus = WBEM_NO_ERROR;
  790. CEnumeratorManager* pEnumMgr = new CEnumeratorManager( wszCookingClass, pCookedClass, pRawClass, pCookedEnum, pRawEnum, lIDRaw );
  791. if (NULL == pEnumMgr) return WBEM_E_OUT_OF_MEMORY;
  792. CInCritSec ics(&m_cs);
  793. if (SUCCEEDED(pEnumMgr->GetInithResult()))
  794. {
  795. DWORD i;
  796. for (i=0;i<m_apEnumerators.size();i++)
  797. {
  798. if(m_apEnumerators[i] == NULL)
  799. {
  800. m_apEnumerators[i] = pEnumMgr;
  801. if (pdwID)
  802. {
  803. *pdwID = i;
  804. }
  805. break;
  806. }
  807. }
  808. // we need to expand the array
  809. if (i == m_apEnumerators.size())
  810. {
  811. try
  812. {
  813. m_apEnumerators.push_back(pEnumMgr);
  814. if (pdwID)
  815. {
  816. *pdwID = m_apEnumerators.size()-1;
  817. }
  818. }
  819. catch (...)
  820. {
  821. pEnumMgr->Release();
  822. dwStatus = WBEM_E_OUT_OF_MEMORY;
  823. }
  824. }
  825. }
  826. else
  827. {
  828. dwStatus = pEnumMgr->GetInithResult();
  829. }
  830. return dwStatus;
  831. }
  832. WMISTATUS CEnumeratorCache::RemoveEnum( DWORD dwID , long * pRawId )
  833. ///////////////////////////////////////////////////////////////////////////////
  834. //
  835. //
  836. //
  837. // Parameters:
  838. //
  839. //
  840. ///////////////////////////////////////////////////////////////////////////////
  841. {
  842. WMISTATUS dwStatus = WBEM_NO_ERROR;
  843. CInCritSec ics(&m_cs);
  844. if ( dwID < m_apEnumerators.size() )
  845. {
  846. CEnumeratorManager* pEnumMgr = m_apEnumerators[dwID];
  847. m_apEnumerators[dwID] = NULL;
  848. if (pRawId) *pRawId = pEnumMgr->GetRawId();
  849. pEnumMgr->Release();
  850. }
  851. else
  852. {
  853. dwStatus = E_FAIL;
  854. }
  855. return dwStatus;
  856. }
  857. WMISTATUS CEnumeratorCache::Refresh(DWORD dwRefreshId)
  858. ///////////////////////////////////////////////////////////////////////////////
  859. //
  860. //
  861. //
  862. // Parameters:
  863. //
  864. //
  865. ///////////////////////////////////////////////////////////////////////////////
  866. {
  867. WMISTATUS dwStatus = WBEM_NO_ERROR;
  868. CEnumeratorManager** ppEnumMang = new CEnumeratorManager*[m_apEnumerators.size()];
  869. wmilib::auto_buffer<CEnumeratorManager*> rm_(ppEnumMang);
  870. if (!ppEnumMang)
  871. return WBEM_E_OUT_OF_MEMORY;
  872. memset(ppEnumMang,0,sizeof(CEnumeratorManager*)*m_apEnumerators.size());
  873. DWORD j=0;
  874. DWORD i=0;
  875. {
  876. CInCritSec ics(&m_cs);
  877. for (i=0;i<m_apEnumerators.size();i++)
  878. {
  879. CEnumeratorManager* pEnumMgr = m_apEnumerators[i];
  880. if (pEnumMgr)
  881. {
  882. pEnumMgr->AddRef();
  883. ppEnumMang[j] = pEnumMgr;
  884. j++;
  885. }
  886. }
  887. }
  888. for (i=0;i<j;i++)
  889. {
  890. dwStatus = ppEnumMang[i]->Refresh(dwRefreshId);
  891. if (FAILED(dwStatus))
  892. {
  893. break;
  894. }
  895. }
  896. for (i=0;i<j;i++)
  897. {
  898. ppEnumMang[i]->Release();
  899. }
  900. return dwStatus;
  901. }
  902. /////////////////////////////////////////////////////////////////////////
  903. //
  904. //
  905. // CEnumeratorManager
  906. //
  907. //
  908. /////////////////////////////////////////////////////////////////////////
  909. CEnumeratorManager::CEnumeratorManager( LPCWSTR wszCookingClass,
  910. IWbemClassObject* pCookedClass,
  911. IWbemClassObject* pRawClass,
  912. IWbemHiPerfEnum* pCookedEnum,
  913. IWbemHiPerfEnum* pRawEnum,
  914. long lRawID )
  915. : m_pCookedClass( pCookedClass ),
  916. m_pRawEnum(pRawEnum),
  917. m_pCookedEnum( pCookedEnum ),
  918. m_pCooker(NULL),
  919. m_lRawID(lRawID),
  920. m_dwSignature('mMnE'),
  921. m_cRef(1), //-------------- initial refcount
  922. m_dwVector(0),
  923. m_wszCookingClassName(NULL)
  924. {
  925. size_t length = wcslen( wszCookingClass ) + 1;
  926. m_wszCookingClassName = new WCHAR[ length];
  927. if ( NULL != m_wszCookingClassName )
  928. StringCchCopyW( m_wszCookingClassName, length, wszCookingClass );
  929. _DBG_ASSERT(m_pCookedClass);
  930. m_pCookedClass->AddRef();
  931. if ( NULL != m_pRawEnum )
  932. m_pRawEnum->AddRef();
  933. if ( NULL != m_pCookedEnum )
  934. m_pCookedEnum->AddRef();
  935. _DBG_ASSERT(pRawClass);
  936. m_IsSingleton = IsSingleton(pRawClass);
  937. m_InithRes = Initialize( pRawClass );
  938. }
  939. CEnumeratorManager::~CEnumeratorManager()
  940. {
  941. m_dwSignature = 'gmne';
  942. delete m_wszCookingClassName;
  943. // one reference is held by the CWMISimpleObjectCooker
  944. if (m_pCookedClass ) m_pCookedClass->Release();
  945. if (m_pRawEnum) m_pRawEnum->Release();
  946. if (m_pCookedEnum) m_pCookedEnum->Release();
  947. delete m_pCooker;
  948. #ifdef _VERBOSE
  949. DbgPrintfA(0,"~CEnumeratorManager %08x\n",this);
  950. #endif
  951. }
  952. LONG CEnumeratorManager::AddRef()
  953. {
  954. return InterlockedIncrement(&m_cRef);
  955. }
  956. LONG CEnumeratorManager::Release()
  957. {
  958. LONG lRet = InterlockedDecrement(&m_cRef);
  959. if (lRet == 0) delete this;
  960. return lRet;
  961. }
  962. //
  963. // called from the constructor
  964. //
  965. WMISTATUS CEnumeratorManager::Initialize( IWbemClassObject* pRawClass )
  966. {
  967. WMISTATUS dwStatus;
  968. HRESULT hr1,hr2;
  969. IWbemObjectAccess* pCookedAccess = NULL;
  970. IWbemObjectAccess* pRawAccess = NULL;
  971. hr1 = m_pCookedClass->QueryInterface( IID_IWbemObjectAccess, (void**)&pCookedAccess );
  972. CReleaseMe arCookedAccess( pCookedAccess );
  973. hr2 = pRawClass->QueryInterface( IID_IWbemObjectAccess, (void**)&pRawAccess );
  974. CReleaseMe arRawAccess( pRawAccess );
  975. if (SUCCEEDED(hr1) && SUCCEEDED(hr2))
  976. {
  977. m_pCooker = new CWMISimpleObjectCooker( m_wszCookingClassName,
  978. pCookedAccess, // acquired by CWMISimpleObjectCooker
  979. pRawAccess );
  980. }
  981. if (m_pCooker == NULL)
  982. {
  983. dwStatus = WBEM_E_OUT_OF_MEMORY;
  984. }
  985. else
  986. {
  987. dwStatus = m_pCooker->GetLastHR();
  988. }
  989. return dwStatus;
  990. }
  991. //
  992. // returns an hash-ed value of the __RELPATH in a ULONG_PTR with the lower bit stripped
  993. // the lower bit is used to flag the entry when updating the enumerators
  994. //
  995. /////////////////////////////////////////////////////////////////////////////
  996. ULONG_PTR hash_string (WCHAR * pKey)
  997. {
  998. ULONG_PTR acc = 0;
  999. ULONG_PTR i = 0;
  1000. WCHAR *this_char = pKey;
  1001. while (*this_char != NULL) {
  1002. acc ^= *(this_char++) << i;
  1003. i = (i + 1) % sizeof (void *);
  1004. }
  1005. return (acc<<1); // so we can save the LOWEST bit
  1006. }
  1007. //
  1008. // this function simply fills out an array of pointers to IWbemObejctAccess
  1009. // obtaining them from the RAW-Enumerator
  1010. // it also builds an array with hashes of the __RELPATHs of the instances
  1011. //
  1012. ///////////////////////////////////////////////////////////////
  1013. WMISTATUS
  1014. CEnumeratorManager::GetRawEnumObjects(std::vector<IWbemObjectAccess*, wbem_allocator<IWbemObjectAccess*> > & refArray,
  1015. std::vector<ULONG_PTR, wbem_allocator<ULONG_PTR> > & refObjHashKeys)
  1016. {
  1017. WMISTATUS dwStatus = WBEM_NO_ERROR;
  1018. DWORD dwRet = 0,
  1019. dwNumRawObjects = 0;
  1020. IWbemObjectAccess** apObjAccess = NULL;
  1021. dwStatus = m_pRawEnum->GetObjects( 0L, 0, apObjAccess, &dwRet);
  1022. if ( WBEM_E_BUFFER_TOO_SMALL == dwStatus )
  1023. {
  1024. // Set the buffer size
  1025. // ===================
  1026. dwNumRawObjects = dwRet;
  1027. wmilib::auto_buffer<IWbemObjectAccess*> apObjAccess( new IWbemObjectAccess*[dwNumRawObjects]);
  1028. if ( NULL != apObjAccess.get() )
  1029. {
  1030. memset( apObjAccess.get(), 0, dwNumRawObjects * sizeof(IWbemObjectAccess*));
  1031. dwStatus = m_pRawEnum->GetObjects( 0L, dwNumRawObjects, (IWbemObjectAccess **)apObjAccess.get(), &dwRet );
  1032. }
  1033. else
  1034. {
  1035. dwStatus = WBEM_E_OUT_OF_MEMORY;
  1036. }
  1037. if ( SUCCEEDED( dwStatus ) )
  1038. {
  1039. try
  1040. {
  1041. refArray.reserve(dwNumRawObjects);
  1042. refObjHashKeys.reserve(dwNumRawObjects);
  1043. }
  1044. catch (...)
  1045. {
  1046. dwStatus = WBEM_E_OUT_OF_MEMORY;
  1047. dwNumRawObjects = 0;
  1048. }
  1049. for (DWORD i=0;i<dwNumRawObjects;i++)
  1050. {
  1051. HRESULT hr1;
  1052. _variant_t VarKey; // does not throw, just container
  1053. hr1 = apObjAccess[i]->Get(L"__RELPATH",0,&VarKey,NULL,NULL);
  1054. if (SUCCEEDED(hr1))
  1055. {
  1056. DWORD Hash = hash_string(VarKey.bstrVal);
  1057. refObjHashKeys.push_back(Hash);
  1058. refArray.push_back(apObjAccess[i]);
  1059. }
  1060. else
  1061. {
  1062. // if we cannot give out the ownership of a pointer, release
  1063. apObjAccess[i]->Release();
  1064. }
  1065. }
  1066. }
  1067. }
  1068. return dwStatus;
  1069. }
  1070. //
  1071. // the problem that UpdateEnums and Refresh are trying to solve is the following:
  1072. // The Cooked enumerator needs 2 Raw values for calculating 1 value.
  1073. // the 2 values comes from two distinc enumeration
  1074. // the 2 distinct enumeration can give a different resultset
  1075. // OLD: A B C D E
  1076. // NEW: B C E F G
  1077. // we are adding to the "cooking cache" only the new objects,
  1078. // and we are removing the old ones
  1079. //
  1080. //////////////////////////////////////////////////////////////////////
  1081. WMISTATUS
  1082. CEnumeratorManager::UpdateEnums(
  1083. /*out*/ std::vector<ULONG_PTR, wbem_allocator<ULONG_PTR> > & apObjKeyHash)
  1084. {
  1085. // cyclic logic:
  1086. // we have a 'circular array' of std::vector
  1087. // and the m_dwVector is the index
  1088. // circular increment of the index will decide
  1089. // who is the New and who is the Old
  1090. std::vector<ULONG_PTR, wbem_allocator<ULONG_PTR> > & Old = m_Delta[m_dwVector];
  1091. m_dwVector = (m_dwVector+1)%2;
  1092. m_Delta[m_dwVector].clear();
  1093. m_Delta[m_dwVector] = apObjKeyHash;
  1094. std::vector<ULONG_PTR, wbem_allocator<ULONG_PTR> > & New = m_Delta[m_dwVector];
  1095. DWORD j,k;
  1096. for (j=0;j<New.size();j++)
  1097. {
  1098. BOOL bFound = FALSE;
  1099. for (k=0;k<Old.size();k++)
  1100. {
  1101. if (Old[k] == New[j])
  1102. {
  1103. Old[k] |= 1;
  1104. bFound = TRUE;
  1105. break;
  1106. }
  1107. }
  1108. if (!bFound)
  1109. {
  1110. New[j] |= 1; // ad the very NEW bit
  1111. }
  1112. }
  1113. return WBEM_S_NO_ERROR;
  1114. }
  1115. WMISTATUS CEnumeratorManager::Refresh( DWORD dwRefreshStamp )
  1116. {
  1117. WMISTATUS dwStatus = WBEM_NO_ERROR;
  1118. std::vector<IWbemObjectAccess*, wbem_allocator<IWbemObjectAccess*> > apObjAccess;
  1119. std::vector<ULONG_PTR, wbem_allocator<ULONG_PTR> > apObjHashKeys;
  1120. dwStatus = GetRawEnumObjects( apObjAccess, apObjHashKeys );
  1121. // calculate the Delta of the caches
  1122. if (SUCCEEDED(dwStatus))
  1123. {
  1124. dwStatus = UpdateEnums(apObjHashKeys);
  1125. }
  1126. std::vector<ULONG_PTR, wbem_allocator<ULONG_PTR> > & New = m_Delta[m_dwVector];
  1127. std::vector<ULONG_PTR, wbem_allocator<ULONG_PTR> > & Old = m_Delta[(m_dwVector-1)%2];
  1128. {
  1129. CInCritSec ics(&m_cs);
  1130. // Merge into the cache
  1131. if ( SUCCEEDED(dwStatus) )
  1132. {
  1133. //
  1134. // Elements in the New array with the bit set are really new
  1135. //
  1136. DWORD j;
  1137. for (j=0; j< New.size(); j++)
  1138. {
  1139. if (New[j] & 1) // test the very new BIT
  1140. {
  1141. EnumCookId thisEnumCookId;
  1142. dwStatus = InsertCookingRecord( apObjAccess[j], &thisEnumCookId, dwRefreshStamp );
  1143. if (SUCCEEDED(dwStatus))
  1144. {
  1145. try
  1146. {
  1147. m_mapID[New[j]] = thisEnumCookId;
  1148. }
  1149. catch (...)
  1150. {
  1151. break;
  1152. }
  1153. }
  1154. else
  1155. {
  1156. break;
  1157. }
  1158. //remove the bit
  1159. New[j] &= (~1);
  1160. }
  1161. }
  1162. for (j=0; j<Old.size(); j++)
  1163. {
  1164. if (Old[j] & 1)
  1165. {
  1166. Old[j] &= (~1); // remove the ALREADY_THERE bit
  1167. }
  1168. else
  1169. {
  1170. EnumCookId thisEnumCookId;
  1171. thisEnumCookId = m_mapID[Old[j]];
  1172. m_mapID.erase(Old[j]);
  1173. RemoveCookingRecord(&thisEnumCookId);
  1174. }
  1175. }
  1176. m_pCooker->Recalc(dwRefreshStamp);
  1177. }
  1178. }
  1179. // in any case ....
  1180. for (DWORD i=0;i<apObjAccess.size();i++)
  1181. {
  1182. apObjAccess[i]->Release();
  1183. };
  1184. return dwStatus;
  1185. }
  1186. WMISTATUS
  1187. CEnumeratorManager::InsertCookingRecord(
  1188. IWbemObjectAccess* pRawObject,
  1189. EnumCookId * pEnumCookId,
  1190. DWORD dwRefreshStamp)
  1191. ///////////////////////////////////////////////////////////////////////////////
  1192. //
  1193. //
  1194. //
  1195. // Parameters:
  1196. //
  1197. //
  1198. ///////////////////////////////////////////////////////////////////////////////
  1199. {
  1200. WMISTATUS dwStatus = WBEM_NO_ERROR;
  1201. if (!pRawObject || !pEnumCookId)
  1202. {
  1203. return WBEM_E_INVALID_PARAMETER;
  1204. }
  1205. IWbemObjectAccess* pCookedObject = NULL;
  1206. long lID = 0;
  1207. dwStatus = CreateCookingObject( pRawObject, &pCookedObject );
  1208. CReleaseMe rm1(pCookedObject);
  1209. if ( SUCCEEDED( dwStatus ) )
  1210. {
  1211. dwStatus = m_pCooker->SetCookedInstance( pCookedObject, &lID );
  1212. if ( SUCCEEDED( dwStatus ) )
  1213. {
  1214. dwStatus = m_pCooker->BeginCooking( lID, pRawObject,dwRefreshStamp);
  1215. }
  1216. }
  1217. if ( SUCCEEDED( dwStatus ) )
  1218. {
  1219. DWORD dwTarget;
  1220. long EnumId = lID;
  1221. dwStatus = m_pCookedEnum->AddObjects( 0L, 1, &EnumId, &pCookedObject );
  1222. if (SUCCEEDED(dwStatus))
  1223. {
  1224. pEnumCookId->CookId = lID;
  1225. pEnumCookId->EnumId = EnumId;
  1226. m_dwUsage++;
  1227. }
  1228. else
  1229. {
  1230. pEnumCookId->CookId = 0;
  1231. pEnumCookId->EnumId = 0;
  1232. }
  1233. }
  1234. return dwStatus;
  1235. }
  1236. WMISTATUS CEnumeratorManager::CreateCookingObject(
  1237. IWbemObjectAccess* pRawObject,
  1238. IWbemObjectAccess** ppCookedObject )
  1239. ///////////////////////////////////////////////////////////////////////////////
  1240. //
  1241. // Create a new instance of the cooked object and set the key(s) based on the
  1242. // raw object's key(s) value.
  1243. //
  1244. // Parameters:
  1245. //
  1246. // pRawObject - The new object's corresponding raw object
  1247. // ppCookedObject - The new cooked object
  1248. //
  1249. ///////////////////////////////////////////////////////////////////////////////
  1250. {
  1251. HRESULT hr = WBEM_E_FAILED;
  1252. IWbemClassObject * pCookedInst = NULL;
  1253. hr = m_pCookedClass->SpawnInstance(0,&pCookedInst);
  1254. CReleaseMe rm1(pCookedInst);
  1255. if (SUCCEEDED(hr) &&
  1256. !m_IsSingleton)
  1257. {
  1258. // get the 'list' of all the key property
  1259. // if you haven't got it in the past
  1260. if (m_pKeyProps.size() == 0)
  1261. {
  1262. hr = pRawObject->BeginEnumeration(WBEM_FLAG_KEYS_ONLY);
  1263. if (SUCCEEDED(hr))
  1264. {
  1265. BSTR bstrName;
  1266. while(WBEM_S_NO_ERROR == pRawObject->Next(0,&bstrName,NULL,NULL,NULL))
  1267. {
  1268. try
  1269. {
  1270. m_pKeyProps.push_back(bstrName);
  1271. }
  1272. catch (...)
  1273. {
  1274. hr = WBEM_E_OUT_OF_MEMORY;
  1275. };
  1276. SysFreeString(bstrName);
  1277. };
  1278. pRawObject->EndEnumeration();
  1279. }
  1280. }
  1281. // copy all the key properties from the Raw to the cooked instance
  1282. if (m_pKeyProps.size() > 0 && SUCCEEDED(hr))
  1283. {
  1284. for(int i=0;i<m_pKeyProps.size();i++)
  1285. {
  1286. // does not thorow, just a container
  1287. _variant_t VarVal;
  1288. CIMTYPE ct;
  1289. hr = pRawObject->Get(m_pKeyProps[i],0,&VarVal,&ct,NULL);
  1290. if (SUCCEEDED(hr))
  1291. {
  1292. hr = pCookedInst->Put(m_pKeyProps[i],0,&VarVal,0);
  1293. if (FAILED(hr))
  1294. {
  1295. break;
  1296. }
  1297. }
  1298. else
  1299. {
  1300. break;
  1301. }
  1302. VarVal.Clear();
  1303. }
  1304. } else {
  1305. hr = WBEM_E_INVALID_CLASS;
  1306. }
  1307. };
  1308. if (SUCCEEDED(hr)){
  1309. hr = pCookedInst->QueryInterface( IID_IWbemObjectAccess, (void**)ppCookedObject );
  1310. }
  1311. return hr;
  1312. }
  1313. WMISTATUS CEnumeratorManager::RemoveCookingRecord( EnumCookId * pEnumCookID )
  1314. ///////////////////////////////////////////////////////////////////////////////
  1315. //
  1316. //
  1317. //
  1318. // Parameters:
  1319. //
  1320. //
  1321. ///////////////////////////////////////////////////////////////////////////////
  1322. {
  1323. if (!pEnumCookID)
  1324. {
  1325. return WBEM_E_INVALID_PARAMETER;
  1326. }
  1327. WMISTATUS dwStatus = WBEM_NO_ERROR;
  1328. dwStatus = m_pCookedEnum->RemoveObjects( 0L, 1, &pEnumCookID->EnumId );
  1329. m_pCooker->StopCooking(pEnumCookID->CookId);
  1330. m_pCooker->Remove(pEnumCookID->CookId);
  1331. --m_dwUsage;
  1332. return dwStatus;
  1333. }