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.

854 lines
19 KiB

  1. /*++
  2. Copyright (C) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. Cache.h
  5. Abstract:
  6. Contains all caching classes and objects.
  7. History:
  8. a-dcrews 01-Mar-00 Created
  9. ivanbrug 23-Jun-2000 mostly rewritten
  10. --*/
  11. #ifndef _CACHE_H_
  12. #define _CACHE_H_
  13. #include <windows.h>
  14. #include <wbemcli.h>
  15. #include <wbemint.h>
  16. #include <wstlallc.h>
  17. #include "RawCooker.h"
  18. #include "CookerUtils.h"
  19. #include "DynArray.h"
  20. #include <wstring.h>
  21. #include <map>
  22. #include <vector>
  23. #include <functional>
  24. ///////////////////////////////////////////////////////////////////////////////
  25. //
  26. // Macro Definitions
  27. //
  28. ///////////////////////////////////////////////////////////////////////////////
  29. #define WMI_COOKER_CACHE_INCREMENT 8 // The cache size adjustment increment
  30. ///////////////////////////////////////////////////////////////////////////////
  31. //
  32. // CProperty
  33. // =========
  34. //
  35. // The base property - used for raw properties and the base
  36. // class for the CookedProperty.
  37. //
  38. ///////////////////////////////////////////////////////////////////////////////
  39. class CProperty
  40. {
  41. protected:
  42. LPWSTR m_wszName; // The property name
  43. long m_lPropHandle; // The property handle
  44. CIMTYPE m_ct;
  45. public:
  46. CProperty( LPWSTR wszName, long lHandle, CIMTYPE ct );
  47. ~CProperty();
  48. LPWSTR GetName();
  49. CIMTYPE GetType();
  50. long GetHandle();
  51. };
  52. ///////////////////////////////////////////////////////////////////////////////
  53. //
  54. // CCookingProperty
  55. // ================
  56. //
  57. // The cooked property - used to model the data required to
  58. // cook a property of a cooekd class
  59. //
  60. ///////////////////////////////////////////////////////////////////////////////
  61. class CCookingProperty : public CProperty
  62. {
  63. DWORD m_dwCounterType; // Counter type
  64. DWORD m_dwReqProp; // which property are needed to perform calculation
  65. CRawCooker m_Cooker; // The cooker object
  66. CProperty* m_pRawCounterProp; // The raw counter property
  67. CProperty* m_pTimeProp; // The raw time property
  68. CProperty* m_pFrequencyProp; // The raw frequency property
  69. CProperty* m_pBaseProp; // The raw base property OPTIONAL for most counters
  70. __int32 m_nSampleWindow; // The number of samples used for the computation
  71. __int32 m_nTimeWindow; // The period used for the samples
  72. unsigned __int64 m_nTimeFreq; // The timer frequency;
  73. long m_lScale; // The Scale factor (10 ^ (m_lScale))
  74. BOOL m_bUseWellKnownIfNeeded;
  75. public:
  76. CCookingProperty( LPWSTR wszName,
  77. DWORD dwCounterType,
  78. long lPropHandle,
  79. CIMTYPE ct,
  80. DWORD dwReqProp,
  81. BOOL bUseWellKnownIfNeeded);
  82. virtual ~CCookingProperty();
  83. WMISTATUS Initialize( IWbemQualifierSet* pCookingPropQualifierSet,
  84. IWbemObjectAccess* pRawAccess,
  85. IWbemQualifierSet* pCookingClassQSet);
  86. WMISTATUS Cook( DWORD dwNumSamples,
  87. __int64* aRawCounter,
  88. __int64* aBaseCounter,
  89. __int64* aTimeStamp,
  90. __int64* pnResult );
  91. CProperty* GetRawCounterProperty();
  92. CProperty* GetBaseProperty();
  93. CProperty* GetTimeProperty();
  94. HRESULT SetFrequency(IWbemObjectAccess * pObjAcc);
  95. unsigned __int64 GetFrequency(void);
  96. BOOL IsReq(DWORD ReqProp) { return (m_dwReqProp&ReqProp); };
  97. DWORD NumberOfActiveSamples() { return m_nSampleWindow; };
  98. DWORD MinSamplesRequired() { return m_nSampleWindow; };
  99. };
  100. ///////////////////////////////////////////////////////////////////////////////
  101. //
  102. // CPropertySampleCache
  103. // ====================
  104. //
  105. // For every property in each instance, we must maintain a history of
  106. // previous samples for the cooking. The type of cooking determines the
  107. // number of required samples
  108. //
  109. ///////////////////////////////////////////////////////////////////////////////
  110. class CPropertySampleCache
  111. {
  112. DWORD m_dwNumSamples; // The number of current samples
  113. DWORD m_dwTotSamples; // The size of the sample array
  114. DWORD m_dwRefreshID;
  115. __int64* m_aRawCounterVals; // The array of raw counter values
  116. __int64* m_aBaseCounterVals; // The array of base counter values
  117. __int64* m_aTimeStampVals; // The array of timestamp values
  118. public:
  119. CPropertySampleCache();
  120. ~CPropertySampleCache();
  121. WMISTATUS SetSampleInfo( DWORD dwNumActiveSamples, DWORD dwMinReqSamples );
  122. WMISTATUS SetSampleData( DWORD dwRefreshID, __int64 nRawCounter, __int64 nRawBase, __int64 nTimeStamp );
  123. WMISTATUS GetData( DWORD* pdwNumSamples, __int64** paRawCounter, __int64** paBaseCounter, __int64** paTimeStamp );
  124. };
  125. ///////////////////////////////////////////////////////////////////////////////
  126. //
  127. // CCookingInstance
  128. // ================
  129. //
  130. // The cooking instance - used to model an instance of a cooked object. Each
  131. // property maintains a cache of values that will be used to compute the
  132. // final cooked value.
  133. //
  134. ///////////////////////////////////////////////////////////////////////////////
  135. class CCookingInstance
  136. {
  137. LPWSTR m_wszKey; // The instance key
  138. IWbemObjectAccess* m_pCookingInstance; // Cooking instance data
  139. IWbemObjectAccess* m_pRawInstance; // Raw sample source
  140. CPropertySampleCache* m_aPropertySamples; // The cache of property samples for this instance
  141. DWORD m_dwNumProps;
  142. public:
  143. CCookingInstance( IWbemObjectAccess *pCookingInstance, DWORD dwNumProps );
  144. virtual ~CCookingInstance();
  145. WMISTATUS InitProperty( DWORD dwProp, DWORD dwNumActiveSamples, DWORD dwMinReqSamples );
  146. WMISTATUS SetRawSourceInstance( IWbemObjectAccess* pRawSampleSource );
  147. WMISTATUS GetRawSourceInstance( IWbemObjectAccess** ppRawSampleSource );
  148. WMISTATUS AddSample( DWORD dwRefresherInc, DWORD dwProp, __int64 nRawCounter, __int64 nRawBase, __int64 nTimeStamp );
  149. WMISTATUS GetCachedSamples( IWbemObjectAccess** ppOldSample, IWbemObjectAccess** ppNewSample );
  150. IWbemObjectAccess* GetInstance();
  151. WMISTATUS UpdateSamples();
  152. WMISTATUS CookProperty( DWORD dwProp, CCookingProperty* pProperty );
  153. LPWSTR GetKey() { return m_wszKey; }
  154. WMISTATUS Refresh( IWbemObjectAccess* pRawData, IWbemObjectAccess** ppCookedData );
  155. BOOL IsValid() {
  156. return (m_dwNumProps && m_aPropertySamples);
  157. };
  158. };
  159. ///////////////////////////////////////////////////////////////////////////////
  160. //
  161. // CRecord
  162. // =======
  163. //
  164. ///////////////////////////////////////////////////////////////////////////////
  165. template<class T>
  166. class CRecord
  167. {
  168. static long m_lRefIDGen; // The ID generator
  169. long m_lID; // Instance ID
  170. CRecord* m_pNext; // The next pointer in the list
  171. public:
  172. CRecord() : m_lID( m_lRefIDGen++ ), m_pNext( NULL ) {}
  173. virtual ~CRecord() {}
  174. void SetNext( CRecord* pRecord ) { m_pNext = pRecord; }
  175. void SetID( long lID ) { m_lID = lID; }
  176. CRecord* GetNext() { return m_pNext; }
  177. long GetID() { return m_lID; }
  178. virtual T* GetData() = 0;
  179. };
  180. ///////////////////////////////////////////////////////////////////////////////
  181. //
  182. // CUnkRecord
  183. // ==========
  184. //
  185. ///////////////////////////////////////////////////////////////////////////////
  186. template<class T>
  187. class CUnkRecord : public CRecord<T>
  188. {
  189. T* m_pUnk;
  190. public:
  191. CUnkRecord( T* pUnk ) : m_pUnk( pUnk ) {}
  192. ~CUnkRecord(){ if ( NULL != m_pUnk ) m_pUnk->Release(); }
  193. T* GetData(){ if ( NULL != m_pUnk ) m_pUnk->AddRef(); return m_pUnk; }
  194. };
  195. ///////////////////////////////////////////////////////////////////////////////
  196. //
  197. // CObjRecord
  198. // ==========
  199. //
  200. // A hidden class used by the cache to manage elements
  201. //
  202. ///////////////////////////////////////////////////////////////////////////////
  203. template<class T>
  204. class CObjRecord : public CRecord<T>
  205. {
  206. WCHAR* m_wszKey;
  207. T* m_pObj;
  208. public:
  209. CObjRecord( T* pObj, WCHAR* wszKey ) : m_pObj( pObj ), m_wszKey( NULL )
  210. {
  211. if ( NULL != wszKey )
  212. {
  213. m_wszKey = new WCHAR[ wcslen( wszKey ) + 1 ];
  214. wcscpy( m_wszKey, wszKey );
  215. }
  216. }
  217. ~CObjRecord()
  218. {
  219. if ( NULL != m_pObj ) delete m_pObj;
  220. if ( NULL != m_wszKey ) delete m_wszKey;
  221. }
  222. T* GetData(){ return m_pObj; }
  223. bool IsValueByKey( WCHAR* wszKey )
  224. {
  225. return ( 0 == _wcsicmp( m_wszKey, wszKey ) );
  226. }
  227. };
  228. ///////////////////////////////////////////////////////////////////////////////
  229. //
  230. // CCache
  231. // ======
  232. //
  233. // BT - base type
  234. // RT - record type
  235. //
  236. ///////////////////////////////////////////////////////////////////////////////
  237. template<class BT, class RT>
  238. class CCache
  239. {
  240. RT* m_pHead; // Head of list
  241. RT* m_pTail; // Tail of list
  242. RT* m_pEnumNode; // Enumerator pointer
  243. public:
  244. CCache();
  245. virtual ~CCache();
  246. WMISTATUS Add( BT* pData, WCHAR* wszKey, long* plID );
  247. WMISTATUS Remove( long lID );
  248. WMISTATUS RemoveAll();
  249. WMISTATUS GetData( long lID, BT** ppData );
  250. WMISTATUS BeginEnum();
  251. WMISTATUS Next( BT** ppData );
  252. WMISTATUS EndEnum();
  253. bool FindByKey( WCHAR* wszKey, BT* pData );
  254. };
  255. template<class T>
  256. long CRecord<T>::m_lRefIDGen = 0;
  257. template<class BT, class RT>
  258. CCache<BT,RT>::CCache() : m_pHead( NULL ), m_pTail( NULL ), m_pEnumNode( NULL )
  259. {
  260. }
  261. template<class BT, class RT>
  262. CCache<BT,RT>::~CCache()
  263. {
  264. RT* pNode = m_pHead;
  265. RT* pNext = NULL;
  266. while ( NULL != pNode )
  267. {
  268. pNext = (RT*)pNode->GetNext();
  269. delete pNode;
  270. pNode = pNext;
  271. }
  272. };
  273. template<class BT, class RT>
  274. WMISTATUS CCache<BT,RT>::Add( BT *pData, WCHAR* wszKey, long* plID )
  275. {
  276. WMISTATUS dwStatus = S_OK;
  277. if ( NULL == pData )
  278. {
  279. dwStatus = WBEM_E_INVALID_PARAMETER;
  280. }
  281. if ( SUCCEEDED( dwStatus ) )
  282. {
  283. RT* pNewRecord = new RT( pData, wszKey );
  284. if ( NULL != pNewRecord )
  285. {
  286. if ( NULL == m_pHead )
  287. {
  288. m_pHead = pNewRecord;
  289. m_pTail = pNewRecord;
  290. }
  291. else
  292. {
  293. m_pTail->SetNext( pNewRecord );
  294. m_pTail = pNewRecord;
  295. }
  296. *plID = pNewRecord->GetID();
  297. }
  298. else
  299. {
  300. dwStatus = WBEM_E_OUT_OF_MEMORY;
  301. }
  302. }
  303. return dwStatus;
  304. };
  305. template<class BT, class RT>
  306. WMISTATUS CCache<BT,RT>::Remove( long lID )
  307. {
  308. WMISTATUS dwStatus = S_FALSE;
  309. RT* pNode = m_pHead;
  310. RT* pNext = (RT*)pNode->GetNext();
  311. RT* pPrev = NULL;
  312. while ( NULL != pNode )
  313. {
  314. if ( pNode->GetID() == lID )
  315. {
  316. if ( NULL == pNext )
  317. m_pTail = pPrev;
  318. if ( NULL == pPrev )
  319. m_pHead = pNext;
  320. else
  321. pPrev->SetNext( pNext );
  322. delete pNode;
  323. dwStatus = S_OK;
  324. }
  325. pPrev = pNode;
  326. pNode = pNext;
  327. if ( NULL != pNode )
  328. pNext = (RT*)pNode->GetNext();
  329. }
  330. return dwStatus;
  331. };
  332. template<class BT, class RT>
  333. WMISTATUS CCache<BT,RT>::RemoveAll()
  334. {
  335. WMISTATUS dwStatus = S_FALSE;
  336. RT* pNode = m_pHead;
  337. RT* pNext = NULL;
  338. while ( NULL != pNode )
  339. {
  340. pNext = (RT*)pNode->GetNext();
  341. delete pNode;
  342. pNode = pNext;
  343. }
  344. m_pHead = m_pTail = NULL;
  345. return dwStatus;
  346. };
  347. template<class BT, class RT>
  348. WMISTATUS CCache<BT,RT>::GetData( long lID, BT** ppData )
  349. {
  350. WMISTATUS dwStatus = S_FALSE;
  351. RT* pNode = m_pHead;
  352. while ( NULL != pNode )
  353. {
  354. if ( pNode->GetID() == lID )
  355. {
  356. *ppData = pNode->GetData();
  357. dwStatus = S_OK;
  358. break;
  359. }
  360. else
  361. {
  362. pNode = (RT*)pNode->GetNext();
  363. }
  364. }
  365. return dwStatus;
  366. };
  367. template<class BT, class RT>
  368. WMISTATUS CCache<BT,RT>::BeginEnum()
  369. {
  370. WMISTATUS dwStatus = S_OK;
  371. m_pEnumNode = m_pHead;
  372. return dwStatus;
  373. };
  374. template<class BT, class RT>
  375. WMISTATUS CCache<BT,RT>::Next( BT** ppData )
  376. {
  377. WMISTATUS dwStatus = WBEM_S_FALSE;
  378. if ( NULL != m_pEnumNode )
  379. {
  380. *ppData = m_pEnumNode->GetData();
  381. m_pEnumNode = (RT*)m_pEnumNode->GetNext();
  382. dwStatus = S_OK;
  383. }
  384. return dwStatus;
  385. };
  386. template<class BT, class RT>
  387. WMISTATUS CCache<BT,RT>::EndEnum()
  388. {
  389. WMISTATUS dwStatus = S_OK;
  390. m_pEnumNode = NULL;
  391. return dwStatus;
  392. };
  393. template<class BT, class RT>
  394. bool CCache<BT,RT>::FindByKey( WCHAR* wszKey, BT* pData )
  395. {
  396. BT Data;
  397. bool bRet = FALSE;
  398. BeginEnum();
  399. while( WBEM_S_FALSE != Next( &Data ) )
  400. {
  401. if ( pData->IsValueByKey( wszKey ) )
  402. {
  403. *pData = Data;
  404. bRet = TRUE;
  405. break;
  406. }
  407. }
  408. EndEnum();
  409. return bRet;
  410. };
  411. ///////////////////////////////////////////////////////////////
  412. //
  413. // CInstanceCache
  414. // ==============
  415. //
  416. ///////////////////////////////////////////////////////////////
  417. class CInstanceCache : public CCache<CCookingInstance,CObjRecord<CCookingInstance> >
  418. {
  419. public:
  420. };
  421. ///////////////////////////////////////////////////////////////
  422. //
  423. // CEnumInstanceRecord
  424. // ===================
  425. //
  426. ///////////////////////////////////////////////////////////////
  427. class CInstanceRecord
  428. {
  429. long m_lID;
  430. LPWSTR m_wszName;
  431. public:
  432. CInstanceRecord( LPWSTR wszName, long lID );
  433. virtual ~CInstanceRecord();
  434. long GetID(){ return m_lID; }
  435. LPWSTR GetKey(){ return m_wszName; }
  436. };
  437. //
  438. // used to add/remove an instance from the coooker
  439. // and from the fastprox enumerator
  440. //
  441. typedef struct tagEnumCookId {
  442. long CookId;
  443. long EnumId;
  444. } EnumCookId;
  445. ///////////////////////////////////////////////////////////////
  446. //
  447. // CEnumeratorManager
  448. // ==================
  449. //
  450. ///////////////////////////////////////////////////////////////
  451. class CWMISimpleObjectCooker;
  452. class BstrAlloc : public wbem_allocator<WString>
  453. {
  454. };
  455. class CEnumeratorManager
  456. // Manages a single enumerator
  457. {
  458. DWORD m_dwSignature;
  459. LONG m_cRef;
  460. HRESULT m_InithRes;
  461. CRITICAL_SECTION m_cs;
  462. CWMISimpleObjectCooker* m_pCooker; // The class' cooker
  463. long m_lRawID; // RawID
  464. IWbemHiPerfEnum* m_pRawEnum; // The hiperf cooked enumerator
  465. IWbemHiPerfEnum* m_pCookedEnum; // The hiperf cooked enumerator
  466. IWbemClassObject* m_pCookedClass; // The class definition for the cooking class
  467. std::vector<WString,BstrAlloc> m_pKeyProps;
  468. WCHAR* m_wszCookingClassName;
  469. BOOL m_IsSingleton;
  470. // to keep track of the differences
  471. // between the raw enum and our enum
  472. DWORD m_dwUsage;
  473. std::map< ULONG_PTR , EnumCookId , std::less<ULONG_PTR> ,wbem_allocator<EnumCookId> > m_mapID;
  474. std::vector< ULONG_PTR , wbem_allocator<ULONG_PTR> > m_Delta[2];
  475. DWORD m_dwVector;
  476. // members
  477. WMISTATUS Initialize( IWbemClassObject* pRawClass );
  478. WMISTATUS CreateCookingObject( IWbemObjectAccess* pRawObject, IWbemObjectAccess** ppCookedObject );
  479. WMISTATUS InsertCookingRecord( IWbemObjectAccess* pRawObject, EnumCookId * pStruct, DWORD dwRefreshStamp );
  480. WMISTATUS RemoveCookingRecord( EnumCookId * pEnumCookId );
  481. WMISTATUS GetRawEnumObjects( std::vector<IWbemObjectAccess*, wbem_allocator<IWbemObjectAccess*> > & refArray,
  482. std::vector<ULONG_PTR, wbem_allocator<ULONG_PTR> > & refObjHashKeys);
  483. WMISTATUS SortRawArray(std::vector<IWbemObjectAccess*, wbem_allocator<IWbemObjectAccess*> > & refArray );
  484. WMISTATUS UpdateEnums(std::vector<ULONG_PTR, wbem_allocator<ULONG_PTR> > & apObjAccess);
  485. public:
  486. CEnumeratorManager( LPCWSTR wszCookingClass, IWbemClassObject* pCookedClass, IWbemClassObject* pRawClass, IWbemHiPerfEnum* pCookedEnum, IWbemHiPerfEnum* pRawEnum, long lRawID );
  487. virtual ~CEnumeratorManager();
  488. HRESULT GetInithResult(){ return m_InithRes; };
  489. WMISTATUS Refresh( DWORD dwRefreshStamp );
  490. long GetRawId(void){ return m_lRawID; };
  491. LONG AddRef();
  492. LONG Release();
  493. };
  494. ///////////////////////////////////////////////////////////////
  495. //
  496. // CEnumeratorCache
  497. // ================
  498. //
  499. ///////////////////////////////////////////////////////////////
  500. class CEnumeratorCache
  501. {
  502. DWORD m_dwRefreshStamp; // The refresh counter
  503. DWORD m_dwEnum; // The enumerator index
  504. std::vector<CEnumeratorManager*, wbem_allocator<CEnumeratorManager*> > m_apEnumerators;
  505. CRITICAL_SECTION m_cs;
  506. WMISTATUS Initialize();
  507. public:
  508. CEnumeratorCache();
  509. virtual ~CEnumeratorCache();
  510. WMISTATUS AddEnum(
  511. LPCWSTR wszCookingClass,
  512. IWbemClassObject* pCookedClass,
  513. IWbemClassObject* pRawClass,
  514. IWbemHiPerfEnum* pCookedEnum,
  515. IWbemHiPerfEnum* pRawEnum,
  516. long lID,
  517. DWORD* pdwID );
  518. WMISTATUS RemoveEnum( DWORD dwID , long * pRawId);
  519. WMISTATUS Refresh(DWORD dwRefreshStamp);
  520. };
  521. //
  522. // Simple Cache based on the std::map
  523. // It will use the ID semantics:
  524. // Insertion will return an ID that need to be
  525. // used for deletion
  526. // ids are unique for the lifetime of the Cache object
  527. //
  528. template <class T>
  529. class IdCache {
  530. private:
  531. std::map<DWORD, T> m_map;
  532. DWORD m_NextId;
  533. std::map<DWORD, T>::iterator m_it;
  534. CRITICAL_SECTION m_cs;
  535. public:
  536. IdCache():m_NextId(0){
  537. InitializeCriticalSection(&m_cs);
  538. };
  539. virtual ~IdCache(){
  540. DeleteCriticalSection(&m_cs);
  541. };
  542. void Lock(){
  543. EnterCriticalSection(&m_cs);
  544. }
  545. void Unlock(){
  546. LeaveCriticalSection(&m_cs);
  547. };
  548. // traditional interfaces
  549. HRESULT Add( DWORD * pId, T Elem);
  550. HRESULT GetData(DWORD Id, T * pElem);
  551. HRESULT Remove(DWORD Id, T * pRemovedElem);
  552. // before calling this, delete the elements !!!!
  553. HRESULT RemoveAll(void);
  554. // Enumerator Style
  555. HRESULT BeginEnum(void);
  556. HRESULT Next(T * pElem);
  557. HRESULT EndEnum(void);
  558. };
  559. template <class T>
  560. HRESULT
  561. IdCache<T>::Add( DWORD * pId, T Elem){
  562. HRESULT hr;
  563. Lock();
  564. if (pId) {
  565. std::map<DWORD, T>::iterator it = m_map.find(m_NextId);
  566. if (it != m_map.end()) {
  567. // should never happen
  568. hr = E_FAIL;
  569. } else {
  570. m_map[m_NextId] = Elem;
  571. *pId = m_NextId;
  572. InterlockedIncrement((PLONG)&m_NextId);
  573. hr = WBEM_S_NO_ERROR;
  574. }
  575. } else {
  576. hr = WBEM_E_INVALID_PARAMETER;
  577. }
  578. Unlock();
  579. return hr;
  580. }
  581. template <class T>
  582. HRESULT
  583. IdCache<T>::GetData(DWORD Id, T * pElem){
  584. HRESULT hr = WBEM_S_NO_ERROR;
  585. Lock();
  586. std::map<DWORD, T>::iterator it = m_map.find(Id);
  587. if (it != m_map.end()){
  588. *pElem = (*it).second;
  589. } else {
  590. hr = WBEM_E_NOT_FOUND;
  591. }
  592. Unlock();
  593. return hr;
  594. }
  595. template <class T>
  596. HRESULT
  597. IdCache<T>::Remove(DWORD Id, T * pRemovedElem){
  598. HRESULT hr = WBEM_S_NO_ERROR;
  599. Lock();
  600. if (pRemovedElem) {
  601. std::map<DWORD, T>::iterator it = m_map.find(Id);
  602. if (it != m_map.end()) {
  603. *pRemovedElem = (*it).second;
  604. m_map.erase(it);
  605. } else {
  606. hr = WBEM_E_NOT_FOUND;
  607. }
  608. } else {
  609. hr = WBEM_E_INVALID_PARAMETER;
  610. }
  611. Unlock();
  612. return hr;
  613. }
  614. //
  615. // DEVDEV Empty the cache before removing from std::map
  616. //
  617. template <class T>
  618. HRESULT
  619. IdCache<T>::RemoveAll(void){
  620. Lock();
  621. m_map.erase(m_map.begin(),m_map.end());
  622. Unlock();
  623. return WBEM_S_NO_ERROR;
  624. };
  625. //
  626. // DEVDEV Consider using Lock if no exception ....
  627. //
  628. template <class T>
  629. HRESULT
  630. IdCache<T>::BeginEnum(void){
  631. Lock();
  632. m_it = m_map.begin();
  633. return WBEM_S_NO_ERROR;
  634. }
  635. template <class T>
  636. HRESULT
  637. IdCache<T>::Next(T * pElem){
  638. HRESULT hr;
  639. if (pElem){
  640. if (m_it == m_map.end()){
  641. hr = WBEM_S_NO_MORE_DATA;
  642. } else {
  643. * pElem = (*m_it).second;
  644. ++m_it;
  645. hr = WBEM_S_NO_ERROR;
  646. }
  647. } else {
  648. hr = WBEM_E_INVALID_PARAMETER;
  649. }
  650. return hr;
  651. }
  652. template <class T>
  653. HRESULT
  654. IdCache<T>::EndEnum(void){
  655. Unlock();
  656. return WBEM_S_NO_ERROR;
  657. }
  658. #endif //_CACHE_H_