Source code of Windows XP (NT5)
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.

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