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.

2010 lines
69 KiB

  1. /*++
  2. Copyright (C) 1999-2001 Microsoft Corporation
  3. Module Name:
  4. ADAPPERF.CPP
  5. Abstract:
  6. History:
  7. --*/
  8. #include "precomp.h"
  9. #include <stdio.h>
  10. #include <wbemcli.h>
  11. #include <cominit.h>
  12. #include <WinMgmtR.h>
  13. #include "ntreg.h"
  14. #include "adapperf.h"
  15. #include "adaputil.h"
  16. #define PL_TIMEOUT 100000 // The timeout value for waiting on a function mutex
  17. #define GUARD_BLOCK "WMIADAP_WMIADAP_WMIADAP_WMIADAP_WMIADAP_WMIADAP_WMIADAP_WMIADAP"
  18. BYTE CAdapSafeBuffer::s_pGuardBytes[] = GUARD_BLOCK;
  19. ////////////////////////////////////////////////////////////////////////////////////////////
  20. //
  21. // CAdapSafeDataBlock
  22. //
  23. ////////////////////////////////////////////////////////////////////////////////////////////
  24. CAdapSafeBuffer::CAdapSafeBuffer( WString wstrServiceName )
  25. ////////////////////////////////////////////////////////////////////////////////////////////
  26. //
  27. // Constructor
  28. //
  29. ////////////////////////////////////////////////////////////////////////////////////////////
  30. : m_dwGuardSize ( 0 ),
  31. m_hPerfLibHeap ( NULL ),
  32. m_pRawBuffer ( NULL ),
  33. m_pSafeBuffer ( NULL ),
  34. m_dwSafeBufferSize ( 0 ),
  35. m_pCurrentPtr ( NULL ),
  36. m_dwNumObjects ( 0 ),
  37. m_wstrServiceName ( wstrServiceName )
  38. {
  39. // Initialize the guard byte pattern
  40. // =================================
  41. m_dwGuardSize = sizeof( GUARD_BLOCK );
  42. // Create the private heap
  43. // =======================
  44. m_hPerfLibHeap = HeapCreate( 0, 0x100000, 0 );
  45. // If the private heap could not be created, then use the process heap
  46. // ===================================================================
  47. if ( NULL == m_hPerfLibHeap )
  48. {
  49. m_hPerfLibHeap = GetProcessHeap();
  50. }
  51. }
  52. CAdapSafeBuffer::~CAdapSafeBuffer()
  53. ////////////////////////////////////////////////////////////////////////////////////////////
  54. //
  55. // Destructor
  56. //
  57. ////////////////////////////////////////////////////////////////////////////////////////////
  58. {
  59. // Deallocate the raw buffer
  60. // =========================
  61. if ( NULL != m_pRawBuffer )
  62. {
  63. HeapFree( m_hPerfLibHeap, 0, m_pRawBuffer );
  64. }
  65. // Destroy the private heap
  66. // ========================
  67. if ( ( NULL != m_hPerfLibHeap ) && ( GetProcessHeap() != m_hPerfLibHeap ) )
  68. {
  69. HeapDestroy( m_hPerfLibHeap );
  70. }
  71. }
  72. HRESULT CAdapSafeBuffer::SetSize( DWORD dwNumBytes )
  73. ////////////////////////////////////////////////////////////////////////////////////////////
  74. //
  75. // Sets the size of the safe buffer. Memory is actually allocated for the raw buffer, and
  76. // the safe buffer just sits in the raw buffer between the set of guard bytes
  77. //
  78. // Parameters:
  79. // dwNumBytes - the number of bytes requested for the safe buffer
  80. //
  81. ////////////////////////////////////////////////////////////////////////////////////////////
  82. {
  83. HRESULT hr = WBEM_NO_ERROR;
  84. DWORD dwRawBufferSize = 0;
  85. // Check for roll-over
  86. // ===================
  87. if ( dwNumBytes > ( 0xFFFFFFFF - ( 2 * m_dwGuardSize ) ) )
  88. {
  89. hr = WBEM_E_OUT_OF_MEMORY;
  90. }
  91. if ( SUCCEEDED ( hr ) )
  92. {
  93. // Set the total size of the buffer
  94. // ================================
  95. m_dwSafeBufferSize = dwNumBytes;
  96. dwRawBufferSize = dwNumBytes + ( 2 * m_dwGuardSize );
  97. // Allocate the memory
  98. // ===================
  99. if ( NULL == m_pRawBuffer )
  100. {
  101. // First time allocation
  102. // =====================
  103. m_pRawBuffer = (BYTE*) HeapAlloc( m_hPerfLibHeap,
  104. HEAP_ZERO_MEMORY,
  105. dwRawBufferSize );
  106. }
  107. else
  108. {
  109. BYTE * pTmp = (BYTE *)HeapReAlloc( m_hPerfLibHeap,
  110. HEAP_ZERO_MEMORY,
  111. m_pRawBuffer,
  112. dwRawBufferSize );
  113. if (pTmp)
  114. {
  115. m_pRawBuffer = pTmp;
  116. }
  117. else
  118. {
  119. HeapFree(m_hPerfLibHeap,0,m_pRawBuffer);
  120. m_pRawBuffer = NULL;
  121. }
  122. }
  123. if ( NULL != m_pRawBuffer )
  124. {
  125. // Set the safe buffer pointer
  126. // ===========================
  127. m_pSafeBuffer = m_pRawBuffer + m_dwGuardSize;
  128. // Set the prefix guard bytes
  129. // =========================
  130. memcpy( m_pRawBuffer, s_pGuardBytes, m_dwGuardSize );
  131. // Set the suffix guard bytes
  132. // ==========================
  133. memcpy( m_pSafeBuffer + m_dwSafeBufferSize, s_pGuardBytes, m_dwGuardSize );
  134. }
  135. else
  136. {
  137. m_pSafeBuffer = NULL;
  138. m_pCurrentPtr = NULL;
  139. m_dwSafeBufferSize = 0;
  140. hr = WBEM_E_OUT_OF_MEMORY;
  141. }
  142. }
  143. return hr;
  144. }
  145. HRESULT CAdapSafeBuffer::Validate(BOOL * pSentToEventLog)
  146. ////////////////////////////////////////////////////////////////////////////////////////////
  147. //
  148. // Validate will compare the size of the pointer displacement matches the byte size
  149. // returned from the collection, validates the guard bytes and walks the blob, verifying
  150. // that all of the pointers are within the boundary of the blob
  151. //
  152. ////////////////////////////////////////////////////////////////////////////////////////////
  153. {
  154. HRESULT hr = WBEM_NO_ERROR;
  155. try
  156. {
  157. PERF_OBJECT_TYPE* pObject = (PERF_OBJECT_TYPE*) m_pSafeBuffer;
  158. // Validate that if we have objects, then we have mass
  159. // ===================================================
  160. if ( ( 0 < m_dwNumObjects ) && ( 0 == m_dwDataBlobSize ) )
  161. {
  162. hr = WBEM_E_FAILED;
  163. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  164. WBEM_MC_ADAP_BLOB_HAS_NO_SIZE,
  165. (LPCWSTR)m_wstrServiceName );
  166. if (pSentToEventLog) {
  167. *pSentToEventLog = TRUE;
  168. }
  169. }
  170. // Validate that that number of bytes returned is the same as the pointer displacement
  171. // ===================================================================================
  172. if ( SUCCEEDED( hr ) && ( ( m_pCurrentPtr - m_pSafeBuffer ) != m_dwDataBlobSize ) )
  173. {
  174. hr = WBEM_E_FAILED;
  175. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  176. WBEM_MC_ADAP_BAD_PERFLIB_INVALID_DATA,
  177. (LPCWSTR)m_wstrServiceName, CHex( hr ) );
  178. if (pSentToEventLog) {
  179. *pSentToEventLog = TRUE;
  180. }
  181. }
  182. if ( SUCCEEDED ( hr ) )
  183. {
  184. // Validate the guard bytes
  185. // ========================
  186. if ( 0 != memcmp( m_pRawBuffer, s_pGuardBytes, m_dwGuardSize) )
  187. {
  188. hr = WBEM_E_FAILED;
  189. CAdapUtility::NTLogEvent( EVENTLOG_ERROR_TYPE,
  190. WBEM_MC_ADAP_BAD_PERFLIB_MEMORY,
  191. (LPCWSTR)m_wstrServiceName, CHex( hr ) );
  192. if (pSentToEventLog) {
  193. *pSentToEventLog = TRUE;
  194. }
  195. }
  196. else
  197. {
  198. if ( 0 != memcmp( m_pSafeBuffer + m_dwSafeBufferSize, s_pGuardBytes, m_dwGuardSize) )
  199. {
  200. hr = WBEM_E_FAILED;
  201. CAdapUtility::NTLogEvent( EVENTLOG_ERROR_TYPE,
  202. WBEM_MC_ADAP_BAD_PERFLIB_MEMORY,
  203. (LPCWSTR)m_wstrServiceName, CHex( hr ) );
  204. if (pSentToEventLog) {
  205. *pSentToEventLog = TRUE;
  206. }
  207. }
  208. }
  209. }
  210. // Validate the blob
  211. // =================
  212. if ( SUCCEEDED( hr ) )
  213. {
  214. for ( int nObject = 0; SUCCEEDED( hr ) && nObject < m_dwNumObjects; nObject++ )
  215. {
  216. PERF_COUNTER_DEFINITION* pCtr = NULL;
  217. DWORD dwCtrBlockSize = 0;
  218. // Validate the object pointer
  219. // ===========================
  220. hr = ValidateSafePointer( (BYTE*) pObject );
  221. if ( SUCCEEDED( hr ) )
  222. {
  223. // Validate the counter definitions
  224. // ================================
  225. if ( 0 == pObject->HeaderLength )
  226. {
  227. hr = WBEM_E_FAILED;
  228. }
  229. else
  230. {
  231. pCtr = ( PERF_COUNTER_DEFINITION* ) ( ( ( BYTE* ) pObject ) + pObject->HeaderLength );
  232. }
  233. }
  234. for( int nCtr = 0; SUCCEEDED( hr ) && nCtr < pObject->NumCounters; nCtr++)
  235. {
  236. hr = ValidateSafePointer( ( BYTE* ) pCtr );
  237. if ( SUCCEEDED( hr ) )
  238. {
  239. dwCtrBlockSize += pCtr->CounterSize;
  240. if ( nCtr < ( pObject->NumCounters - 1 ) )
  241. {
  242. if ( 0 == pCtr->ByteLength )
  243. {
  244. hr = WBEM_E_FAILED;
  245. }
  246. else
  247. {
  248. pCtr = ( PERF_COUNTER_DEFINITION* ) ( ( ( BYTE* ) pCtr ) + pCtr->ByteLength );
  249. }
  250. }
  251. }
  252. }
  253. // Validate the data
  254. // =================
  255. if ( pObject->NumInstances >= 0 )
  256. {
  257. // Blob has instances
  258. // ==================
  259. PERF_INSTANCE_DEFINITION* pInstance = NULL;
  260. if ( 0 == pObject->DefinitionLength )
  261. {
  262. hr = WBEM_E_FAILED;
  263. }
  264. else
  265. {
  266. pInstance = ( PERF_INSTANCE_DEFINITION* ) ( ( ( BYTE* ) pObject ) + pObject->DefinitionLength );
  267. }
  268. // Validate the instances
  269. // ======================
  270. for ( int nInst = 0; SUCCEEDED( hr ) && nInst < pObject->NumInstances; nInst++ )
  271. {
  272. hr = ValidateSafePointer( ( BYTE* ) pInstance );
  273. if ( SUCCEEDED( hr ) )
  274. {
  275. PERF_COUNTER_BLOCK* pCounterBlock = NULL;
  276. // Validate the counter blocks
  277. // ===========================
  278. if ( 0 == pInstance->ByteLength )
  279. {
  280. hr = WBEM_E_FAILED;
  281. }
  282. else
  283. {
  284. pCounterBlock = ( PERF_COUNTER_BLOCK* ) ( ( ( BYTE* ) pInstance ) + pInstance->ByteLength );
  285. hr = ValidateSafePointer( ( BYTE* ) pCounterBlock );
  286. }
  287. if ( SUCCEEDED( hr ) )
  288. {
  289. // Is the counter block the same size as the aggregation of the counter sizes?
  290. // ===========================================================================
  291. if ( ( nInst < pObject->NumInstances - 1 ) && SUCCEEDED( hr ) )
  292. {
  293. pInstance = ( PERF_INSTANCE_DEFINITION* ) ( ( ( BYTE* ) pCounterBlock ) + pCounterBlock->ByteLength );
  294. hr = ValidateSafePointer( (BYTE*) pInstance );
  295. }
  296. //
  297. // validate the size of the last object against
  298. // the 'aperture' of the buffer
  299. //
  300. /*
  301. if (SUCCEEDED(hr) && (nInst == (pObject->NumInstances - 1)))
  302. {
  303. BYTE * pLast = ( ( ( BYTE* ) pCounterBlock ) + pCounterBlock->ByteLength );
  304. // now pLast is 1 byte over the "end" of the buffer
  305. if (pLast > m_pCurrentPtr)
  306. {
  307. hr = WBEM_E_FAILED;
  308. }
  309. }
  310. */
  311. }
  312. }
  313. }
  314. }
  315. else
  316. {
  317. // Blob is a singleton. Validate the counter blocks
  318. // ================================================
  319. if ( 0 == pObject->DefinitionLength )
  320. {
  321. hr = WBEM_E_FAILED;
  322. }
  323. else
  324. {
  325. PERF_COUNTER_BLOCK* pCounterBlock = ( PERF_COUNTER_BLOCK* ) ( ( ( BYTE* ) pObject ) + pObject->DefinitionLength );
  326. hr = ValidateSafePointer( ( BYTE* ) pCounterBlock );
  327. }
  328. }
  329. // Get the next object as long as one exists
  330. // =========================================
  331. if ( nObject < ( m_dwNumObjects - 1 ) )
  332. {
  333. pObject = (PERF_OBJECT_TYPE*)((BYTE*)pObject + pObject->TotalByteLength);
  334. hr = ValidateSafePointer( ( BYTE* ) pObject );
  335. }
  336. }
  337. }
  338. }
  339. catch(...)
  340. {
  341. hr = WBEM_E_FAILED;
  342. }
  343. return hr;
  344. }
  345. HRESULT CAdapSafeBuffer::ValidateSafePointer( BYTE* pPtr )
  346. ////////////////////////////////////////////////////////////////////////////////////////////
  347. //
  348. // Verifys that the pointer is within the blob. The blob occupies the memory starting at
  349. // the beginning of the safe buffer, and termintes at an offset equal to m_dwDataBlobSize
  350. //
  351. // Parameters:
  352. // pPtr - a pointer to be verified
  353. //
  354. ////////////////////////////////////////////////////////////////////////////////////////////
  355. {
  356. HRESULT hr = WBEM_NO_ERROR;
  357. // NOTE: The upper limit of the safe buffer is 1 byte less the blob pointer plus the blob size since
  358. // the first byte of the blob is also the first byte. Imagine he case with a blob of size 1.
  359. // =================================================================================================
  360. if ( ( pPtr < m_pSafeBuffer ) || ( pPtr > ( m_pSafeBuffer + m_dwDataBlobSize - 1 ) ) )
  361. {
  362. hr = WBEM_E_FAILED;
  363. }
  364. if ( FAILED ( hr ) )
  365. {
  366. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  367. WBEM_MC_ADAP_BAD_PERFLIB_INVALID_DATA,
  368. (LPCWSTR)m_wstrServiceName, CHex( hr ) );
  369. }
  370. return hr;
  371. }
  372. HRESULT CAdapSafeBuffer::CopyData( BYTE** ppData, DWORD* pdwNumBytes, DWORD* pdwNumObjects )
  373. ////////////////////////////////////////////////////////////////////////////////////////////
  374. //
  375. // Copies the blob data from the private heap into the process heap. The method will
  376. // allocate memory in the process heap.
  377. //
  378. // Parameters:
  379. // ppData - a pointer to an unallocated byte array
  380. //
  381. ////////////////////////////////////////////////////////////////////////////////////////////
  382. {
  383. if (NULL == ppData || NULL == pdwNumBytes || NULL == pdwNumObjects) return WBEM_E_INVALID_PARAMETER;
  384. HRESULT hr = WBEM_NO_ERROR;
  385. *ppData = new BYTE[m_dwDataBlobSize];
  386. if ( NULL == *ppData )
  387. {
  388. hr = WBEM_E_OUT_OF_MEMORY;
  389. }
  390. else
  391. {
  392. memcpy( *ppData, m_pSafeBuffer, m_dwDataBlobSize );
  393. }
  394. *pdwNumBytes = m_dwDataBlobSize;
  395. *pdwNumObjects = m_dwNumObjects;
  396. return hr;
  397. }
  398. ////////////////////////////////////////////////////////////////////////////////////////////
  399. //
  400. // CAdapPerfLib
  401. //
  402. ////////////////////////////////////////////////////////////////////////////////////////////
  403. CAdapPerfLib::CAdapPerfLib( LPCWSTR pwcsServiceName, DWORD * pLoadStatus )
  404. ////////////////////////////////////////////////////////////////////////////////////////////
  405. //
  406. // Constructor
  407. //
  408. // Initializes all member variables, sets the library and function names, opens the library,
  409. // sets the entry point addresses, creates the perflib processing mutex, and opens the
  410. // processing thread.
  411. //
  412. // Parameters:
  413. // pwcsServiceName - A Unicode string specifying the name of the perflib service.
  414. //
  415. ////////////////////////////////////////////////////////////////////////////////////////////
  416. : m_wstrServiceName( pwcsServiceName ),
  417. m_pfnOpenProc( NULL ),
  418. m_pfnCollectProc( NULL ),
  419. m_pfnCloseProc( NULL ),
  420. m_pwcsLibrary( NULL ),
  421. m_pwcsOpenProc( NULL ),
  422. m_pwcsCollectProc( NULL ),
  423. m_pwcsCloseProc( NULL ),
  424. m_hLib( NULL ),
  425. m_fOpen( FALSE ),
  426. m_dwStatus( 0 ),
  427. m_pPerfThread( NULL ),
  428. m_hPLMutex( NULL ),
  429. m_fOK( FALSE ),
  430. m_EventLogCalled( FALSE ),
  431. m_CollectOK( TRUE ),
  432. m_dwFirstCtr(2),
  433. m_dwLastCtr(CPerfNameDb::GetSystemReservedHigh())
  434. {
  435. DEBUGTRACE( ( LOG_WMIADAP, "Constructing the %S performance library wrapper.\n", pwcsServiceName ) );
  436. HRESULT hr = WBEM_NO_ERROR;
  437. // Verify that the perflib is loaded
  438. // Initialize the performance library name and entry point names
  439. // =============================================================
  440. hr = VerifyLoaded();
  441. if (FAILED(hr))
  442. {
  443. ERRORTRACE( ( LOG_WMIADAP, "VerifyLoaded for %S hr = %08x.\n", pwcsServiceName, hr ) );
  444. }
  445. // Set the processing status information for this attempt
  446. // ======================================================
  447. if ( SUCCEEDED ( hr ) )
  448. {
  449. if (pLoadStatus)
  450. {
  451. (*pLoadStatus) |= EX_STATUS_LOADABLE;
  452. }
  453. hr = BeginProcessingStatus();
  454. if ( hr == WBEM_S_ALREADY_EXISTS )
  455. {
  456. SetStatus( ADAP_PERFLIB_PREVIOUSLY_PROCESSED );
  457. }
  458. }
  459. m_fOK = SUCCEEDED( hr );
  460. if ( !m_fOK )
  461. {
  462. ERRORTRACE( ( LOG_WMIADAP, "Construction of the %S perflib wrapper failed hr = %08x.\n", pwcsServiceName, hr ) );
  463. }
  464. }
  465. CAdapPerfLib::~CAdapPerfLib( void )
  466. ////////////////////////////////////////////////////////////////////////////////////////////
  467. //
  468. // Destructor
  469. //
  470. ////////////////////////////////////////////////////////////////////////////////////////////
  471. {
  472. DEBUGTRACE( ( LOG_WMIADAP, "Destructing the %S performance library wrapper.\n", (LPWSTR)m_wstrServiceName) );
  473. delete m_pPerfThread;
  474. // Delete the library and entry point names
  475. // ========================================
  476. delete [] m_pwcsLibrary;
  477. delete [] m_pwcsOpenProc;
  478. delete [] m_pwcsCollectProc;
  479. delete [] m_pwcsCloseProc;
  480. // Free the library
  481. // ================
  482. if ( NULL != m_hLib )
  483. {
  484. try
  485. {
  486. FreeLibrary( m_hLib );
  487. }
  488. catch (...)
  489. {
  490. ERRORTRACE(( LOG_WMIADAP,"FreeLibrary for Service %S threw an exception",(LPWSTR)m_wstrServiceName) );
  491. }
  492. DEBUGTRACE( ( LOG_WMIADAP, "Library for Service %S Freed.\n",(LPWSTR)m_wstrServiceName ) );
  493. }
  494. }
  495. HRESULT CAdapPerfLib::VerifyLoaded()
  496. {
  497. HRESULT hr = WBEM_E_FAILED;
  498. WString wszRegPath = L"SYSTEM\\CurrentControlSet\\Services\\";
  499. wszRegPath += m_wstrServiceName;
  500. wszRegPath += L"\\Performance";
  501. CNTRegistry reg;
  502. int nRet = 0;
  503. nRet = reg.Open( HKEY_LOCAL_MACHINE, wszRegPath );
  504. switch( nRet )
  505. {
  506. case CNTRegistry::no_error:
  507. {
  508. DWORD dwFirstCtr = 0;
  509. DWORD dwLastCtr = 0;
  510. WCHAR* wszObjList = NULL;
  511. if ( ( ( reg.GetDWORD( L"First Counter", &dwFirstCtr ) == CNTRegistry::no_error ) &&
  512. ( reg.GetDWORD( L"Last Counter", &dwLastCtr ) == CNTRegistry::no_error ) ) ||
  513. ( reg.GetStr( L"Object List", &wszObjList ) == CNTRegistry::no_error ))
  514. {
  515. hr = InitializeEntryPoints(reg,wszRegPath);
  516. if (wszObjList)
  517. {
  518. delete [] wszObjList;
  519. }
  520. if (dwFirstCtr && dwLastCtr)
  521. {
  522. m_dwFirstCtr = dwFirstCtr;
  523. m_dwLastCtr = dwLastCtr;
  524. }
  525. }
  526. else // more special cases
  527. {
  528. if ( m_wstrServiceName.EqualNoCase( L"TCPIP" ) ||
  529. m_wstrServiceName.EqualNoCase( L"TAPISRV") ||
  530. m_wstrServiceName.EqualNoCase( L"PERFOS" ) ||
  531. m_wstrServiceName.EqualNoCase( L"PERFPROC" ) ||
  532. m_wstrServiceName.EqualNoCase( L"PERFDISK" ) ||
  533. m_wstrServiceName.EqualNoCase( L"PERFNET" ) ||
  534. m_wstrServiceName.EqualNoCase( L"SPOOLER" ) ||
  535. m_wstrServiceName.EqualNoCase( L"MSFTPSvc" ) ||
  536. m_wstrServiceName.EqualNoCase( L"RemoteAccess" ) ||
  537. m_wstrServiceName.EqualNoCase( L"WINS" ) ||
  538. m_wstrServiceName.EqualNoCase( L"MacSrv" ) ||
  539. m_wstrServiceName.EqualNoCase( L"AppleTalk" ) ||
  540. m_wstrServiceName.EqualNoCase( L"NM" ) ||
  541. m_wstrServiceName.EqualNoCase( L"RSVP" ) )
  542. {
  543. hr = InitializeEntryPoints(reg,wszRegPath);
  544. }
  545. else
  546. {
  547. hr = WBEM_E_FAILED;
  548. }
  549. }
  550. }break;
  551. case CNTRegistry::not_found:
  552. {
  553. // This shouldn't happen since this is how a perflib is defined
  554. hr = WBEM_E_FAILED;
  555. }break;
  556. case CNTRegistry::access_denied:
  557. {
  558. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  559. WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
  560. (LPWSTR)wszRegPath, nRet );
  561. }break;
  562. }
  563. return hr;
  564. }
  565. HRESULT CAdapPerfLib::InitializeEntryPoints(CNTRegistry & reg,WString & wszRegPath){
  566. HRESULT hr = WBEM_S_NO_ERROR;
  567. // see if someone disabled this library
  568. DWORD dwDisable = 0;
  569. if ( CNTRegistry::no_error == reg.GetDWORD( L"Disable Performance Counters", &dwDisable ) &&
  570. (dwDisable != 0) )
  571. {
  572. hr = WBEM_E_FAILED;
  573. }
  574. else
  575. {
  576. hr = WBEM_S_NO_ERROR;
  577. }
  578. // the perflib is OK for the world, see if it os OK for US
  579. if (SUCCEEDED(hr)){
  580. if (!(( reg.GetStr( L"Library", &m_pwcsLibrary ) == CNTRegistry::no_error ) &&
  581. ( reg.GetStr( L"Open", &m_pwcsOpenProc ) == CNTRegistry::no_error)&&
  582. ( reg.GetStr( L"Collect", &m_pwcsCollectProc ) == CNTRegistry::no_error) &&
  583. ( reg.GetStr( L"Close", &m_pwcsCloseProc ) == CNTRegistry::no_error ) ))
  584. {
  585. WString wstrPath(wszRegPath);
  586. if (m_pwcsLibrary == NULL){
  587. wstrPath += L"\\Library";
  588. } else if (m_pwcsCollectProc == NULL) {
  589. wstrPath += L"\\Collect";
  590. }
  591. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  592. WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
  593. (LPWSTR)wstrPath, CHex( WBEM_E_NOT_AVAILABLE ) );
  594. hr = WBEM_E_FAILED;
  595. } else {
  596. hr = WBEM_S_NO_ERROR;
  597. }
  598. }
  599. return hr;
  600. }
  601. HRESULT CAdapPerfLib::Initialize()
  602. {
  603. // Load the perflib and initialize the procedure addresses
  604. // =======================================================
  605. HRESULT hr = Load();
  606. // Initialize the named function mutex (see WbemPerf for syntax of Mutex name)
  607. // ===========================================================================
  608. if ( SUCCEEDED( hr ) )
  609. {
  610. size_t cchSizeTmp = m_wstrServiceName.Length() + 256;
  611. WCHAR* wcsMutexName = new WCHAR[cchSizeTmp];
  612. if (NULL == wcsMutexName) return WBEM_E_OUT_OF_MEMORY;
  613. CDeleteMe<WCHAR> dmMutexName( wcsMutexName );
  614. StringCchPrintfW( wcsMutexName, cchSizeTmp, L"Global\\%s_Perf_Library_Lock_PID_%x", (WCHAR *)m_wstrServiceName, GetCurrentProcessId() );
  615. m_hPLMutex = CreateMutexW( 0, FALSE, wcsMutexName);
  616. if ( NULL == m_hPLMutex )
  617. {
  618. hr = WBEM_E_FAILED;
  619. }
  620. }
  621. // Create the worker thread
  622. // ========================
  623. if ( SUCCEEDED( hr ) )
  624. {
  625. m_pPerfThread = new CPerfThread( this );
  626. if ( ( NULL == m_pPerfThread) || ( !m_pPerfThread->IsOk() ) )
  627. {
  628. hr = WBEM_E_FAILED;
  629. }
  630. else
  631. {
  632. hr = m_pPerfThread->Open( this );
  633. }
  634. }
  635. if ( FAILED( hr ) )
  636. {
  637. SetStatus( ADAP_PERFLIB_IS_INACTIVE );
  638. }
  639. return hr;
  640. }
  641. HRESULT CAdapPerfLib::GetFileSignature( CheckLibStruct * pCheckLib )
  642. {
  643. HRESULT hr = WBEM_S_NO_ERROR;
  644. if (!pCheckLib){
  645. return WBEM_E_INVALID_PARAMETER;
  646. }
  647. // Get the current library's file time
  648. // ===================================
  649. HANDLE hFile = NULL;
  650. DWORD dwRet = 0;
  651. WCHAR wszFullPath[MAX_PATH];
  652. WCHAR* pwcsTemp = NULL;
  653. if ( 0 != SearchPathW( NULL, m_pwcsLibrary, NULL, MAX_PATH, wszFullPath, &pwcsTemp ) )
  654. {
  655. // Use GetFileAttributes to validate the path.
  656. DWORD dwAttributes = GetFileAttributesW(wszFullPath);
  657. if (dwAttributes == 0xFFFFFFFF) return WBEM_E_FAILED;
  658. // create mask of the attributes that would make an existing file invalid for use
  659. DWORD dwMask = FILE_ATTRIBUTE_DEVICE |
  660. FILE_ATTRIBUTE_DIRECTORY |
  661. FILE_ATTRIBUTE_OFFLINE |
  662. FILE_ATTRIBUTE_READONLY |
  663. FILE_ATTRIBUTE_REPARSE_POINT |
  664. FILE_ATTRIBUTE_SPARSE_FILE |
  665. FILE_ATTRIBUTE_SYSTEM |
  666. FILE_ATTRIBUTE_TEMPORARY;
  667. if (dwAttributes & dwMask) return WBEM_E_FAILED;
  668. hFile = CreateFileW( wszFullPath,
  669. GENERIC_READ,
  670. FILE_SHARE_READ,
  671. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  672. if ( INVALID_HANDLE_VALUE != hFile )
  673. {
  674. OnDelete<HANDLE,BOOL(*)(HANDLE),CloseHandle> CloseMe(hFile);
  675. DWORD dwFileSizeLow = 0;
  676. DWORD dwFileSizeHigh = 0;
  677. __int32 nFileSize = 0;
  678. DWORD dwNumRead = 0;
  679. BYTE* aBuffer = NULL;
  680. dwFileSizeLow = GetFileSize( hFile, &dwFileSizeHigh );
  681. nFileSize = ( dwFileSizeHigh << 32 ) + dwFileSizeLow;
  682. FILETIME ft;
  683. if (GetFileTime(hFile,&ft,NULL,NULL))
  684. {
  685. aBuffer = new BYTE[nFileSize];
  686. CDeleteMe<BYTE> dmBuffer( aBuffer );
  687. if ( NULL != aBuffer )
  688. {
  689. if ( ReadFile( hFile, aBuffer, nFileSize, &dwNumRead, FALSE ) )
  690. {
  691. MD5 md5;
  692. BYTE aSignature[16];
  693. md5.Transform( aBuffer, dwNumRead, aSignature );
  694. // return our data
  695. memcpy(pCheckLib->Signature,aSignature,sizeof(aSignature));
  696. pCheckLib->FileTime = ft;
  697. pCheckLib->FileSize = nFileSize;
  698. }
  699. else
  700. {
  701. hr = WBEM_E_TOO_MUCH_DATA;
  702. }
  703. }
  704. else
  705. {
  706. hr = WBEM_E_OUT_OF_MEMORY;
  707. }
  708. }
  709. else
  710. {
  711. hr = WBEM_E_FAILED;
  712. }
  713. }
  714. else
  715. {
  716. ERRORTRACE((LOG_WMIADAP,"GetFileSignature for %S err %d\n",wszFullPath,GetLastError()));
  717. hr = WBEM_E_FAILED;
  718. }
  719. }
  720. else
  721. {
  722. hr = WBEM_E_NOT_FOUND;
  723. }
  724. return hr;
  725. }
  726. HRESULT CAdapPerfLib::SetFileSignature()
  727. {
  728. HRESULT hr = WBEM_S_NO_ERROR;
  729. CNTRegistry reg;
  730. int nRet = 0;
  731. CheckLibStruct CheckLib;
  732. // Clear the signature buffer
  733. // ==========================
  734. memset( &CheckLib, 0, sizeof(CheckLib) );
  735. // Get the current file time stamp
  736. // ===============================
  737. hr = GetFileSignature( &CheckLib );
  738. // And write it into the registry key
  739. // ==================================
  740. if ( SUCCEEDED( hr ) )
  741. {
  742. WString wstr;
  743. try
  744. {
  745. wstr = L"SYSTEM\\CurrentControlSet\\Services\\";
  746. wstr += m_wstrServiceName;
  747. wstr += L"\\Performance";
  748. }
  749. catch(...)
  750. {
  751. hr = WBEM_E_OUT_OF_MEMORY;
  752. }
  753. if ( SUCCEEDED( hr ) )
  754. {
  755. nRet = reg.Open( HKEY_LOCAL_MACHINE , wstr );
  756. switch ( nRet )
  757. {
  758. case CNTRegistry::no_error:
  759. {
  760. }break;
  761. case CNTRegistry::access_denied:
  762. {
  763. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  764. WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
  765. (LPCWSTR)wstr, nRet );
  766. }
  767. default:
  768. hr = WBEM_E_FAILED;
  769. }
  770. }
  771. if ( SUCCEEDED( hr ) )
  772. {
  773. int nRet1 = reg.SetBinary( ADAP_PERFLIB_SIGNATURE, (PBYTE)&CheckLib.Signature, sizeof( BYTE[16] ) );
  774. int nRet2 = reg.SetBinary( ADAP_PERFLIB_TIME, (PBYTE)&CheckLib.FileTime, sizeof( FILETIME ) );
  775. int nRet3 = reg.SetDWORD( ADAP_PERFLIB_SIZE, CheckLib.FileSize );
  776. if ( (CNTRegistry::no_error == nRet1) &&
  777. (CNTRegistry::no_error == nRet2) &&
  778. (CNTRegistry::no_error == nRet3))
  779. {
  780. // everything OK
  781. }
  782. else if ((CNTRegistry::access_denied == nRet1) ||
  783. (CNTRegistry::access_denied == nRet2) ||
  784. (CNTRegistry::access_denied == nRet3))
  785. {
  786. WString wstrPath = wstr;
  787. wstrPath += ADAP_PERFLIB_SIGNATURE;
  788. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  789. WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
  790. (LPCWSTR)wstrPath, CNTRegistry::access_denied );
  791. }
  792. else
  793. {
  794. hr = WBEM_E_FAILED;
  795. }
  796. }
  797. }
  798. return hr;
  799. }
  800. HRESULT CAdapPerfLib::CheckFileSignature()
  801. {
  802. HRESULT hr = WBEM_S_SAME;
  803. CNTRegistry reg;
  804. int nRet = 0;
  805. BYTE cCurrentMD5[16];
  806. BYTE* cStoredMD5 = NULL;
  807. // Set the performance key path
  808. // ============================
  809. WString wstr;
  810. try
  811. {
  812. wstr = L"SYSTEM\\CurrentControlSet\\Services\\";
  813. wstr += m_wstrServiceName;
  814. wstr += L"\\Performance";
  815. }
  816. catch(...)
  817. {
  818. hr = WBEM_E_OUT_OF_MEMORY;
  819. }
  820. if ( SUCCEEDED( hr ) )
  821. {
  822. // Open the performance key
  823. // ========================
  824. nRet = reg.Open( HKEY_LOCAL_MACHINE , wstr );
  825. switch ( nRet )
  826. {
  827. case CNTRegistry::no_error:
  828. {
  829. }break;
  830. case CNTRegistry::access_denied:
  831. {
  832. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  833. WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
  834. (LPCWSTR)wstr, nRet );
  835. hr = WBEM_E_FAILED;
  836. }break;
  837. default:
  838. {
  839. hr = WBEM_E_FAILED;
  840. }break;
  841. }
  842. }
  843. if ( SUCCEEDED( hr ) )
  844. {
  845. // Get the stored file signature
  846. // =============================
  847. CheckLibStruct StoredLibStruct;
  848. int nRet1;
  849. int nRet2;
  850. int nRet3;
  851. DWORD dwSizeBlob;
  852. nRet1 = reg.GetBinary( ADAP_PERFLIB_SIGNATURE, (PBYTE*)&cStoredMD5,&dwSizeBlob);
  853. CDeleteMe<BYTE> dmStoredMD5( cStoredMD5 );
  854. if (cStoredMD5)
  855. {
  856. if ( sizeof(cCurrentMD5) == dwSizeBlob)
  857. {
  858. memcpy(&StoredLibStruct.Signature,cStoredMD5,sizeof(StoredLibStruct.Signature));
  859. }
  860. else
  861. {
  862. nRet1 = CNTRegistry::failed;
  863. }
  864. }
  865. BYTE * pFileTime = NULL;
  866. nRet2 = reg.GetBinary( ADAP_PERFLIB_TIME, (PBYTE*)&pFileTime,&dwSizeBlob);
  867. CDeleteMe<BYTE> dmFileTime( pFileTime );
  868. if (pFileTime)
  869. {
  870. if (sizeof(FILETIME) == dwSizeBlob )
  871. {
  872. memcpy(&StoredLibStruct.FileTime,pFileTime,sizeof(FILETIME));
  873. }
  874. else
  875. {
  876. nRet2 = CNTRegistry::failed;
  877. }
  878. }
  879. nRet3 = reg.GetDWORD(ADAP_PERFLIB_SIZE,&StoredLibStruct.FileSize);
  880. if ((CNTRegistry::access_denied == nRet1) ||
  881. (CNTRegistry::access_denied == nRet2) ||
  882. (CNTRegistry::access_denied == nRet3))
  883. {
  884. WString wstrPath = wstr;
  885. wstrPath += ADAP_PERFLIB_SIGNATURE;
  886. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  887. WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
  888. (LPCWSTR)wstrPath, nRet );
  889. hr = WBEM_E_FAILED;
  890. }
  891. else if ((CNTRegistry::not_found == nRet1) ||
  892. (CNTRegistry::not_found == nRet2) ||
  893. (CNTRegistry::not_found == nRet3))
  894. {
  895. hr = WBEM_S_FALSE;
  896. }
  897. else if((CNTRegistry::out_of_memory == nRet1) ||
  898. (CNTRegistry::out_of_memory == nRet2) ||
  899. (CNTRegistry::out_of_memory == nRet3) ||
  900. (CNTRegistry::failed == nRet1) ||
  901. (CNTRegistry::failed == nRet2) ||
  902. (CNTRegistry::failed == nRet3))
  903. {
  904. hr = WBEM_E_FAILED;
  905. }
  906. if ( SUCCEEDED( hr ) && ( WBEM_S_FALSE != hr ) )
  907. {
  908. // Get the current library's signature
  909. // ===================================
  910. CheckLibStruct CurrentLibStruct;
  911. memset(&CurrentLibStruct,0,sizeof(CheckLibStruct));
  912. hr = GetFileSignature( &CurrentLibStruct );
  913. if ( SUCCEEDED( hr ) )
  914. {
  915. if ( (StoredLibStruct.FileSize == CurrentLibStruct.FileSize) &&
  916. (0 == memcmp( &StoredLibStruct.Signature, &CurrentLibStruct.Signature, sizeof(CurrentLibStruct.Signature) )) &&
  917. (0 == memcmp( &StoredLibStruct.FileTime, &CurrentLibStruct.FileTime, sizeof(FILETIME))) )
  918. {
  919. hr = WBEM_S_ALREADY_EXISTS;
  920. }
  921. else
  922. {
  923. hr = WBEM_S_FALSE;
  924. }
  925. }
  926. }
  927. }
  928. return hr;
  929. }
  930. HRESULT CAdapPerfLib::BeginProcessingStatus()
  931. ////////////////////////////////////////////////////////////////////////////////////////////
  932. //
  933. // Opens the registry key, reads the ADAP_PERFLIB_STATUS_KEY, and processes the value as
  934. // follows:
  935. //
  936. // ADAP_PERFLIB_OK: The perflib has been successfully accessed before. Set
  937. // the status flag to ADAP_PERFLIB_PROCESSING
  938. //
  939. // ADAP_PERFLIB_PROCESSING: The perflib caused the process to fail. It is corrupt,
  940. // set the status flag to ADAP_PERFLIB_CORRUPT.
  941. //
  942. // ADAP_PERFLIB_CORRUPT: The perflib is known to be corrupt. Status flag retains
  943. // its value.
  944. //
  945. // No Value: The perflib has not been accessed before. Set the
  946. // status flag to ADAP_PERFLIB_PROCESSING.
  947. //
  948. ////////////////////////////////////////////////////////////////////////////////////////////
  949. {
  950. DEBUGTRACE( ( LOG_WMIADAP, "CAdapPerfLib::BeginProcessingStatus()...\n") );
  951. HRESULT hr = WBEM_S_NO_ERROR;
  952. CNTRegistry reg;
  953. // Set the registry path
  954. // =====================
  955. WString wstr;
  956. try
  957. {
  958. wstr = L"SYSTEM\\CurrentControlSet\\Services\\";
  959. wstr += m_wstrServiceName;
  960. wstr += L"\\Performance";
  961. }
  962. catch(...)
  963. {
  964. hr = WBEM_E_OUT_OF_MEMORY;
  965. }
  966. if ( SUCCEEDED( hr ) )
  967. {
  968. // Open the services key
  969. // =====================
  970. int nRet = reg.Open( HKEY_LOCAL_MACHINE, wstr );
  971. switch ( nRet )
  972. {
  973. case CNTRegistry::access_denied:
  974. {
  975. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  976. WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
  977. (LPCWSTR)wstr, nRet );
  978. } break;
  979. case CNTRegistry::no_error:
  980. {
  981. DWORD dwVal;
  982. // Check perflib status
  983. // ====================
  984. hr = CheckFileSignature();
  985. if ( SUCCEEDED( hr ) )
  986. {
  987. if ( WBEM_S_FALSE == hr )
  988. {
  989. // We've got a new perflib, reset the status
  990. // =========================================
  991. hr = SetFileSignature();
  992. if ( SUCCEEDED( hr ) )
  993. {
  994. hr = reg.SetDWORD( ADAP_PERFLIB_STATUS_KEY, ADAP_PERFLIB_PROCESSING );
  995. }
  996. }
  997. else // WBEM_S_ALREADY_EXISTS
  998. {
  999. // It's the same perflib, check the status
  1000. // =======================================
  1001. nRet = reg.GetDWORD( ADAP_PERFLIB_STATUS_KEY, &dwVal );
  1002. if ( nRet == CNTRegistry::no_error )
  1003. {
  1004. switch ( dwVal )
  1005. {
  1006. case ADAP_PERFLIB_OK: // 0
  1007. case ADAP_PERFLIB_PROCESSING: // 1
  1008. case ADAP_PERFLIB_BOOBOO: // 2
  1009. {
  1010. // So far, perflib has behaved within reason. Set it to processing state
  1011. // =====================================================================
  1012. reg.SetDWORD( ADAP_PERFLIB_STATUS_KEY, dwVal + 1 );
  1013. //ERRORTRACE( ( LOG_WMIADAP, "Performance library %S status %d\n",(LPWSTR)m_wstrServiceName,dwVal + 1));
  1014. }break;
  1015. case ADAP_PERFLIB_LASTCHANCE: // 3
  1016. {
  1017. // Perflib failed in the last access attempt before processing ended. Set as bad perflib
  1018. // =====================================================================================
  1019. reg.SetDWORD( ADAP_PERFLIB_STATUS_KEY, ADAP_PERFLIB_CORRUPT );
  1020. ERRORTRACE( ( LOG_WMIADAP, "Performance library %S status was left in the \"Processing\" state.\n",(LPWSTR)m_pwcsLibrary) );
  1021. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  1022. WBEM_MC_ADAP_BAD_PERFLIB_BAD_LIBRARY,
  1023. m_pwcsLibrary, CHex( (DWORD)-1 ) );
  1024. hr = WBEM_E_FAILED;
  1025. }break;
  1026. case ADAP_PERFLIB_CORRUPT: // -1
  1027. {
  1028. // Sign of a bad perflib. Do not open
  1029. // ==================================
  1030. ERRORTRACE( ( LOG_WMIADAP, "Performance library for %S has previously been disabled.\n",(LPWSTR)m_wstrServiceName) );
  1031. //CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_BAD_PERFLIB_BAD_LIBRARY, m_pwcsLibrary, CHex( ADAP_PERFLIB_CORRUPT ) );
  1032. hr = WBEM_E_FAILED;
  1033. }break;
  1034. }
  1035. }
  1036. else if ( nRet == CNTRegistry::not_found )
  1037. {
  1038. // The status does not exist
  1039. // =========================
  1040. hr = reg.SetDWORD( ADAP_PERFLIB_STATUS_KEY, ADAP_PERFLIB_PROCESSING );
  1041. }
  1042. }
  1043. } else {
  1044. DEBUGTRACE( ( LOG_WMIADAP, "CheckFileSignature for %S %08x\n",(LPWSTR)m_wstrServiceName,hr ) );
  1045. }
  1046. }break;
  1047. default:
  1048. {
  1049. hr = WBEM_E_FAILED;
  1050. }break;
  1051. }
  1052. }
  1053. return hr;
  1054. }
  1055. HRESULT CAdapPerfLib::EndProcessingStatus()
  1056. ////////////////////////////////////////////////////////////////////////////////////////////
  1057. //
  1058. // Opens the service registry key, reads the ADAP_PERFLIB_STATUS_KEY, and processes the
  1059. // value as follows:
  1060. //
  1061. // ADAP_PERFLIB_PROCESSING: Valid state. Set status flag to ADAP_PERFLIB_OK.
  1062. //
  1063. // ADAP_PERFLIB_CORRUPT: Valid state (may have been set during processing).
  1064. // Leave status flag as is.
  1065. //
  1066. // ADAP_PERFLIB_OK: Invalid state. Return an error and log an event.
  1067. //
  1068. // No Value: Invalid state. Return an error and log an event.
  1069. //
  1070. ////////////////////////////////////////////////////////////////////////////////////////////
  1071. {
  1072. DEBUGTRACE( ( LOG_WMIADAP, "CAdapPerfLib::EndProcessingStatus()...\n") );
  1073. HRESULT hr = WBEM_S_NO_ERROR;
  1074. CNTRegistry reg;
  1075. WString wstr;
  1076. try
  1077. {
  1078. wstr = L"SYSTEM\\CurrentControlSet\\Services\\";
  1079. wstr += m_wstrServiceName;
  1080. wstr += L"\\Performance";
  1081. }
  1082. catch(...)
  1083. {
  1084. hr = WBEM_E_OUT_OF_MEMORY;
  1085. }
  1086. if (SUCCEEDED(hr)){
  1087. // Open the services key
  1088. // =====================
  1089. int nRet = reg.Open( HKEY_LOCAL_MACHINE, wstr );
  1090. if ( CNTRegistry::access_denied == nRet )
  1091. {
  1092. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  1093. WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
  1094. (LPCWSTR)wstr, nRet );
  1095. hr = WBEM_E_FAILED;
  1096. }
  1097. else if ( CNTRegistry::no_error == nRet )
  1098. {
  1099. DWORD dwVal = 0;
  1100. // Check perflib status
  1101. // ====================
  1102. if ( CheckStatus( ADAP_PERFLIB_FAILED ) )
  1103. {
  1104. // If we have a failure, then immediately mark the perflib as corrupt
  1105. // ==================================================================
  1106. hr = reg.SetDWORD( ADAP_PERFLIB_STATUS_KEY, ADAP_PERFLIB_CORRUPT );
  1107. if (!m_EventLogCalled){
  1108. m_EventLogCalled = TRUE;
  1109. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_BAD_PERFLIB_EXCEPTION, (LPCWSTR)m_wstrServiceName, CHex( hr ) );
  1110. }
  1111. }
  1112. else if ( reg.GetDWORD( ADAP_PERFLIB_STATUS_KEY, &dwVal) == CNTRegistry::no_error )
  1113. {
  1114. switch ( dwVal )
  1115. {
  1116. case ADAP_PERFLIB_PROCESSING:
  1117. case ADAP_PERFLIB_BOOBOO:
  1118. case ADAP_PERFLIB_LASTCHANCE:
  1119. {
  1120. // Perflib is in expected state, reset as long as nothing bad has happened
  1121. // =======================================================================
  1122. hr = reg.SetDWORD( ADAP_PERFLIB_STATUS_KEY, ADAP_PERFLIB_OK );
  1123. //ERRORTRACE( ( LOG_WMIADAP, "Performance library %S EndProcessing\n",(LPWSTR)m_wstrServiceName) );
  1124. }break;
  1125. case ADAP_PERFLIB_CORRUPT:
  1126. {
  1127. // Valid state. Leave as is.
  1128. // ==========================
  1129. ERRORTRACE( ( LOG_WMIADAP, "Performance library for %S: status is corrupt.\n",(LPWSTR)m_wstrServiceName) );
  1130. hr = WBEM_E_FAILED;
  1131. }break;
  1132. case ADAP_PERFLIB_OK:
  1133. {
  1134. if (CheckStatus(ADAP_PERFLIB_IS_INACTIVE))
  1135. {
  1136. hr = reg.SetDWORD( ADAP_PERFLIB_STATUS_KEY, ADAP_PERFLIB_OK );
  1137. }
  1138. else
  1139. {
  1140. // Invalid state
  1141. ERRORTRACE( ( LOG_WMIADAP, "Performance library %S: status is still ADAP_PERFLIB_OK.\n",(LPWSTR)m_wstrServiceName) );
  1142. hr = WBEM_E_FAILED;
  1143. }
  1144. }break;
  1145. default:
  1146. {
  1147. // Really bad state
  1148. // ================
  1149. ERRORTRACE( ( LOG_WMIADAP, "Performance library %S: status is in an unknown state.\n",(LPWSTR)m_wstrServiceName) );
  1150. hr = WBEM_E_FAILED;
  1151. }
  1152. }
  1153. }
  1154. else
  1155. {
  1156. // There is no status key. Something wacky has happened
  1157. // ====================================================
  1158. hr = WBEM_E_FAILED;
  1159. }
  1160. }
  1161. }
  1162. return hr;
  1163. }
  1164. HRESULT CAdapPerfLib::Load()
  1165. ////////////////////////////////////////////////////////////////////////////////////////////
  1166. //
  1167. // Loads the library and resolves the addresses for the Open, Collect and Close entry
  1168. // points.
  1169. //
  1170. ////////////////////////////////////////////////////////////////////////////////////////////
  1171. {
  1172. // Redundant, but it's a failsafe in case some perflib shuts this off on us
  1173. // during processing
  1174. // ========================================================================
  1175. SetErrorMode( SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX );
  1176. HRESULT hr = WBEM_S_NO_ERROR;
  1177. // Free the library if it has been previously loaded
  1178. // =================================================
  1179. if ( NULL != m_hLib )
  1180. {
  1181. try
  1182. {
  1183. FreeLibrary( m_hLib );
  1184. }
  1185. catch (...)
  1186. {
  1187. hr = WBEM_E_CRITICAL_ERROR;
  1188. }
  1189. }
  1190. // Load the predefined library
  1191. // ===========================
  1192. if ( SUCCEEDED( hr ) )
  1193. {
  1194. try
  1195. {
  1196. m_hLib = LoadLibraryExW( m_pwcsLibrary, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
  1197. }
  1198. catch(...)
  1199. {
  1200. hr = WBEM_E_CRITICAL_ERROR;
  1201. }
  1202. }
  1203. if ( SUCCEEDED( hr ) && ( NULL != m_hLib ) )
  1204. {
  1205. DEBUGTRACE( ( LOG_WMIADAP, "** %S Library Loaded.\n", m_wstrServiceName ) );
  1206. char szName[256];
  1207. DWORD Last1 = 0;
  1208. DWORD Last2 = 0;
  1209. DWORD Last3 = 0;
  1210. // Get the entry point addresses. No Wide version of GetProcAddress? sigh...
  1211. // ==========================================================================
  1212. if ( NULL != m_pwcsOpenProc )
  1213. {
  1214. if (0 != WideCharToMultiByte( CP_ACP, 0L, m_pwcsOpenProc, lstrlenW( m_pwcsOpenProc ) + 1,
  1215. szName, sizeof(szName), NULL, NULL ))
  1216. {
  1217. m_pfnOpenProc = (PM_OPEN_PROC*) GetProcAddress( m_hLib, szName );
  1218. }
  1219. Last1 = GetLastError();
  1220. }
  1221. if (0 != WideCharToMultiByte( CP_ACP, 0L, m_pwcsCollectProc, lstrlenW( m_pwcsCollectProc ) + 1,
  1222. szName, sizeof(szName), NULL, NULL ))
  1223. {
  1224. m_pfnCollectProc = (PM_COLLECT_PROC*) GetProcAddress( m_hLib, szName );
  1225. }
  1226. Last2 = GetLastError();
  1227. if ( NULL != m_pwcsCloseProc )
  1228. {
  1229. if (0 != WideCharToMultiByte( CP_ACP, 0L, m_pwcsCloseProc, lstrlenW( m_pwcsCloseProc ) + 1,
  1230. szName, sizeof(szName), NULL, NULL ))
  1231. {
  1232. m_pfnCloseProc = (PM_CLOSE_PROC*) GetProcAddress( m_hLib, szName );
  1233. }
  1234. Last3 = GetLastError();
  1235. }
  1236. if ( ( ( ( NULL != m_pwcsOpenProc ) && ( NULL != m_pfnOpenProc) ) || ( NULL == m_pwcsOpenProc ) ) &&
  1237. ( NULL != m_pfnCollectProc ) &&
  1238. ( ( ( NULL != m_pwcsCloseProc ) && ( NULL != m_pfnCloseProc ) ) || ( NULL == m_pwcsCloseProc ) ) )
  1239. {
  1240. hr = WBEM_S_NO_ERROR;
  1241. }
  1242. else
  1243. {
  1244. ERRORTRACE( ( LOG_WMIADAP, "A performance library function in %S failed to load.\n",(LPWSTR)m_wstrServiceName) );
  1245. WString wstr;
  1246. wstr += L"HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\";
  1247. wstr += m_wstrServiceName;
  1248. if ( ( NULL != m_pwcsOpenProc ) && ( NULL == m_pfnOpenProc ) )
  1249. {
  1250. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  1251. WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
  1252. (LPCWSTR)wstr, Last1 );
  1253. }
  1254. else if ( NULL == m_pfnCollectProc )
  1255. {
  1256. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  1257. WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
  1258. (LPCWSTR)wstr, Last2 );
  1259. }
  1260. else if (( NULL != m_pwcsCloseProc ) && ( NULL == m_pfnCloseProc ))
  1261. {
  1262. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  1263. WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
  1264. (LPCWSTR)wstr, Last3 );
  1265. }
  1266. SetStatus( ADAP_PERFLIB_FAILED );
  1267. hr = WBEM_E_FAILED;
  1268. }
  1269. }
  1270. else
  1271. {
  1272. // If the library fails to load, then send an event, but do not charge a strike
  1273. // ============================================================================
  1274. ERRORTRACE( ( LOG_WMIADAP, "The performance library for %S failed to load.\n",(LPWSTR)m_wstrServiceName ) );
  1275. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_BAD_PERFLIB_BAD_LIBRARY, m_pwcsLibrary, CHex( hr ) );
  1276. hr = WBEM_E_FAILED;
  1277. }
  1278. return hr;
  1279. }
  1280. HRESULT CAdapPerfLib::GetBlob( PERF_OBJECT_TYPE** ppPerfBlock, DWORD* pdwNumBytes, DWORD* pdwNumObjects, BOOL fCostly )
  1281. {
  1282. HRESULT hr = WBEM_S_NO_ERROR;
  1283. if ( m_fOpen )
  1284. {
  1285. hr = m_pPerfThread->GetPerfBlock( this, ppPerfBlock, pdwNumBytes, pdwNumObjects, fCostly );
  1286. }
  1287. if ( FAILED( hr ) )
  1288. {
  1289. if (!m_EventLogCalled){
  1290. //
  1291. //
  1292. //WBEM_MC_ADAP_BAD_PERFLIB_BAD_RETURN
  1293. //
  1294. m_EventLogCalled = TRUE;
  1295. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_BAD_PERFLIB_BAD_RETURN , (LPCWSTR)m_wstrServiceName, CHex( hr ) );
  1296. }
  1297. }
  1298. return hr;
  1299. }
  1300. HRESULT CAdapPerfLib::Close()
  1301. {
  1302. HRESULT hr = WBEM_S_NO_ERROR;
  1303. if ( m_fOpen )
  1304. {
  1305. m_pPerfThread->Close( this );
  1306. }
  1307. return hr;
  1308. }
  1309. HRESULT CAdapPerfLib::Cleanup()
  1310. {
  1311. HRESULT hr = WBEM_S_NO_ERROR;
  1312. // Terminate the worker thread
  1313. // ===========================
  1314. if ( NULL != m_pPerfThread )
  1315. m_pPerfThread->Shutdown();
  1316. // Adjust the status
  1317. // =================
  1318. EndProcessingStatus();
  1319. return hr;
  1320. }
  1321. HRESULT CAdapPerfLib::_Open( void )
  1322. ////////////////////////////////////////////////////////////////////////////////////////////
  1323. //
  1324. // Wraps a call to the perflib's open function. Fetches and passes an exports parameter
  1325. // to the open function if it exists.
  1326. //
  1327. // Note: We should use the named mutex to guard around the calls to Open/Collect/Close
  1328. //
  1329. ////////////////////////////////////////////////////////////////////////////////////////////
  1330. {
  1331. HRESULT hr = WBEM_S_NO_ERROR;
  1332. // Check to ensure that the library has not yet been opened
  1333. // ========================================================
  1334. if ( ( !m_fOpen ) && SUCCEEDED ( hr ) )
  1335. {
  1336. CNTRegistry reg; // The registry wrapper class
  1337. // Build the service path
  1338. // ======================
  1339. WString wstr = L"SYSTEM\\CurrentControlSet\\Services\\";
  1340. wstr += m_wstrServiceName;
  1341. // Open the registry
  1342. // =================
  1343. if ( reg.Open( HKEY_LOCAL_MACHINE, wstr ) == CNTRegistry::no_error )
  1344. {
  1345. WCHAR* pwcsExports = NULL;
  1346. // Get Exports if they are available.
  1347. // ==============================================================
  1348. if ( reg.MoveToSubkey( L"Linkage" ) == CNTRegistry::no_error )
  1349. {
  1350. DWORD dwNumBytes = 0;
  1351. if (CNTRegistry::no_error != reg.GetMultiStr( L"Export", &pwcsExports, dwNumBytes ))
  1352. {
  1353. if ( ERROR_FILE_NOT_FOUND == reg.GetLastError())
  1354. {
  1355. // Linkage with no Export, that is OK
  1356. }
  1357. else
  1358. {
  1359. ERRORTRACE((LOG_WMIADAP,"Serivce %S has a non MSDN compliant or invalid Linkage Key\n",(WCHAR *)m_wstrServiceName));
  1360. if (CNTRegistry::no_error != reg.GetStr( L"Export", &pwcsExports))
  1361. {
  1362. pwcsExports = new WCHAR[2];
  1363. if (pwcsExports)
  1364. {
  1365. pwcsExports[0] = 0;
  1366. pwcsExports[1] = 0;
  1367. }
  1368. }
  1369. }
  1370. }
  1371. }
  1372. // Call the Open function for the perflib
  1373. // ======================================
  1374. switch ( WaitForSingleObject( m_hPLMutex, PL_TIMEOUT ) )
  1375. {
  1376. case WAIT_OBJECT_0:
  1377. {
  1378. try
  1379. {
  1380. if ( NULL != m_pfnOpenProc )
  1381. {
  1382. LONG lRes = m_pfnOpenProc( pwcsExports );
  1383. if (lRes == ERROR_SUCCESS )
  1384. {
  1385. hr = WBEM_S_NO_ERROR;
  1386. m_fOpen = TRUE;
  1387. }
  1388. else
  1389. {
  1390. SetStatus( ADAP_PERFLIB_IS_INACTIVE );
  1391. hr = WBEM_E_NOT_AVAILABLE;
  1392. }
  1393. DEBUGTRACE( ( LOG_WMIADAP, "Open called for %S returned %d\n", (LPCWSTR)m_wstrServiceName, lRes ) );
  1394. }
  1395. else
  1396. {
  1397. hr = WBEM_S_NO_ERROR;
  1398. m_fOpen = TRUE;
  1399. }
  1400. }
  1401. catch (...)
  1402. {
  1403. SetStatus( ADAP_PERFLIB_FAILED );
  1404. hr = WBEM_E_FAILED;
  1405. ERRORTRACE( ( LOG_WMIADAP, "Perflib Open function has thrown an exception in %S.\n",(LPWSTR)m_wstrServiceName) );
  1406. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_BAD_PERFLIB_EXCEPTION, (LPCWSTR)m_wstrServiceName, CHex( hr ) );
  1407. }
  1408. } break;
  1409. case WAIT_TIMEOUT:
  1410. {
  1411. hr = WBEM_E_NOT_AVAILABLE;
  1412. ERRORTRACE( ( LOG_WMIADAP, "Perflib access mutex timed out in %S.\n",(LPWSTR)m_wstrServiceName) );
  1413. }break;
  1414. case WAIT_ABANDONED:
  1415. {
  1416. hr = WBEM_E_FAILED;
  1417. ERRORTRACE( ( LOG_WMIADAP, "Perflib access mutex was abandoned in %S.\n",(LPWSTR)m_wstrServiceName) );
  1418. }break;
  1419. default:
  1420. {
  1421. hr = WBEM_E_FAILED;
  1422. ERRORTRACE( ( LOG_WMIADAP, "Unknown error with perflib access mutex in %S.\n",(LPWSTR)m_wstrServiceName) );
  1423. }
  1424. } // switch
  1425. ReleaseMutex( m_hPLMutex );
  1426. if ( NULL != pwcsExports )
  1427. {
  1428. delete [] pwcsExports;
  1429. }
  1430. } // IF reg.Open
  1431. else
  1432. {
  1433. hr = WBEM_E_FAILED;
  1434. ERRORTRACE( ( LOG_WMIADAP, "Could not open the %S registry key.\n", wstr ) );
  1435. }
  1436. }
  1437. else
  1438. {
  1439. ERRORTRACE( ( LOG_WMIADAP, "Performance library %S has not been loaded.\n",(LPWSTR)m_wstrServiceName) );
  1440. }
  1441. return hr;
  1442. }
  1443. HRESULT CAdapPerfLib::_GetPerfBlock( PERF_OBJECT_TYPE** ppData, DWORD* pdwBytes, DWORD* pdwNumObjTypes, BOOL fCostly )
  1444. ////////////////////////////////////////////////////////////////////////////////////////////
  1445. //
  1446. // Wraps a call to the perflib's collect function. Will create progressively larger buffers
  1447. // in a private heap to attempt to fetch the performance data block.
  1448. //
  1449. // Parameters:
  1450. // ppData - a pointer to a buffer pointer for the data blob
  1451. // pdwBytes - a pointer to the byte-size of the data blob
  1452. // pdwNumObjTypes - a pointer to the number of objects in the data blob
  1453. // fCostly - a flag to determine what type of data to collect (costly or global)
  1454. //
  1455. // NOTE: This should always return perf object type data, since we cannot specify a
  1456. // foreign computer, which would cause the collect function to return a PERF_DATA_BLOCK
  1457. // structure.
  1458. //
  1459. ////////////////////////////////////////////////////////////////////////////////////////////
  1460. {
  1461. HRESULT hr = WBEM_S_NO_ERROR;
  1462. CAdapSafeBuffer SafeBuffer( m_wstrServiceName ); // The safe buffer
  1463. DWORD dwNumBytes = 0; // Byte counter for the buffer size
  1464. DWORD dwError = ERROR_MORE_DATA; // The return value for the collect function
  1465. DWORD Increment = 0x10000;
  1466. // this is a workaround for perfproc.dll
  1467. if (0 == wbem_wcsicmp(m_wstrServiceName,L"perfproc"))
  1468. {
  1469. Increment = 0x100000;
  1470. }
  1471. // Verify provider status
  1472. // ======================
  1473. if ( m_fOpen )
  1474. {
  1475. // Sets the data-to-fetch parameter
  1476. // ================================
  1477. WCHAR* pwcsValue = ( fCostly ? L"Costly" : L"Global" );
  1478. // Start buffer at 64k (the guarded (safe) buffer is 2 * GUARD_BLOCK bytes smaller)
  1479. // ==================================================================================
  1480. dwNumBytes = Increment;
  1481. // Repeatedly attempt to collect the data until successful (buffer is sufficiently
  1482. // large), or the attempt fails for a reason other than buffer size
  1483. // ===============================================================================
  1484. while ( (ERROR_MORE_DATA == dwError ) && ( SUCCEEDED( hr ) ) )
  1485. {
  1486. // Allocate a raw buffer of size dwNumBytes
  1487. // ========================================
  1488. if (dwNumBytes > s_MaxSizeCollect)
  1489. {
  1490. ERRORTRACE((LOG_WMIADAP,"Library %S: Collect function requires more than 0x%08x bytes to complete",(WCHAR *)m_wstrServiceName,s_MaxSizeCollect));
  1491. m_CollectOK = FALSE;
  1492. hr = WBEM_E_QUOTA_VIOLATION;
  1493. break;
  1494. }
  1495. hr = SafeBuffer.SetSize( dwNumBytes );
  1496. if (FAILED(hr)) break;
  1497. // Collect the data from the perflib
  1498. // =================================
  1499. switch ( WaitForSingleObject( m_hPLMutex, PL_TIMEOUT ) )
  1500. {
  1501. case WAIT_OBJECT_0:
  1502. {
  1503. try
  1504. {
  1505. dwError = m_pfnCollectProc( pwcsValue,
  1506. SafeBuffer.GetSafeBufferPtrPtr(),
  1507. SafeBuffer.GetDataBlobSizePtr(),
  1508. SafeBuffer.GetNumObjTypesPtr() );
  1509. DEBUGTRACE( ( LOG_WMIADAP, "Collect called for %S returned %d\n", (LPCWSTR)m_wstrServiceName, dwError ) );
  1510. }
  1511. catch (...)
  1512. {
  1513. SetStatus( ADAP_PERFLIB_FAILED );
  1514. hr = WBEM_E_FAILED;
  1515. ERRORTRACE( ( LOG_WMIADAP, "Perflib Collection function has thrown an exception in %S.\n",(LPCWSTR)m_wstrServiceName) );
  1516. if (!m_EventLogCalled){
  1517. m_EventLogCalled = TRUE;
  1518. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_BAD_PERFLIB_EXCEPTION, (LPCWSTR)m_wstrServiceName, CHex( dwError ) );
  1519. }
  1520. }
  1521. }break;
  1522. case WAIT_TIMEOUT:
  1523. {
  1524. hr = WBEM_E_NOT_AVAILABLE;
  1525. ERRORTRACE( ( LOG_WMIADAP, "Perflib access mutex timed out in %S.\n",(LPCWSTR)m_wstrServiceName) );
  1526. }break;
  1527. case WAIT_ABANDONED:
  1528. {
  1529. hr = WBEM_E_FAILED;
  1530. ERRORTRACE( ( LOG_WMIADAP, "Perflib access mutex was abandoned in %S.\n",(LPCWSTR)m_wstrServiceName) );
  1531. }break;
  1532. default:
  1533. {
  1534. hr = WBEM_E_FAILED;
  1535. ERRORTRACE( ( LOG_WMIADAP, "Unknown error with perflib access mutex in %S.\n",(LPCWSTR)m_wstrServiceName) );
  1536. }
  1537. } // switch
  1538. ReleaseMutex( m_hPLMutex );
  1539. if ( SUCCEEDED( hr ) )
  1540. {
  1541. switch (dwError)
  1542. {
  1543. case ERROR_SUCCESS:
  1544. {
  1545. //
  1546. // the Validate function can call ReportEvent
  1547. // by itself, and we don't want to bother user too much
  1548. //
  1549. hr = SafeBuffer.Validate(&m_EventLogCalled);
  1550. if ( SUCCEEDED( hr ) )
  1551. {
  1552. hr = SafeBuffer.CopyData( (BYTE**) ppData, pdwBytes, pdwNumObjTypes );
  1553. }
  1554. else
  1555. {
  1556. // Catastrophic error has occured
  1557. // ==============================
  1558. SetStatus( ADAP_PERFLIB_FAILED );
  1559. if (!m_EventLogCalled)
  1560. {
  1561. m_EventLogCalled = TRUE;
  1562. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  1563. WBEM_MC_ADAP_BAD_PERFLIB_INVALID_DATA,
  1564. (LPCWSTR)m_wstrServiceName,
  1565. CHex(hr));
  1566. }
  1567. }
  1568. } break;
  1569. case ERROR_MORE_DATA:
  1570. {
  1571. dwNumBytes += Increment;
  1572. } break;
  1573. default:
  1574. {
  1575. hr = WBEM_E_FAILED;
  1576. m_CollectOK = FALSE;
  1577. ERRORTRACE( ( LOG_WMIADAP, "Perflib Collection function has returned an unknown error(%d) in %S.\n", dwError,(LPCWSTR)m_wstrServiceName ) );
  1578. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_BAD_PERFLIB_BAD_RETURN, (LPCWSTR)m_wstrServiceName, CHex( dwError ) );
  1579. }
  1580. } // switch
  1581. } // IF SUCCEEDED()
  1582. } // WHILE
  1583. // Clean up the buffer
  1584. // ===================
  1585. } // IF CheckStatus
  1586. else
  1587. {
  1588. ERRORTRACE( ( LOG_WMIADAP, "Performance library %S has not been loaded.\n",(LPCWSTR)m_wstrServiceName) );
  1589. }
  1590. return hr;
  1591. }
  1592. HRESULT CAdapPerfLib::_Close( void )
  1593. ////////////////////////////////////////////////////////////////////////////////////////////
  1594. //
  1595. // Wraps a call to the perflib's close function.
  1596. //
  1597. ////////////////////////////////////////////////////////////////////////////////////////////
  1598. {
  1599. HRESULT hr = WBEM_S_NO_ERROR;
  1600. // Verify that the perflib is actually open
  1601. // ========================================
  1602. if ( m_fOpen )
  1603. {
  1604. // Get the mutex
  1605. // =============
  1606. switch ( WaitForSingleObject( m_hPLMutex, PL_TIMEOUT ) )
  1607. {
  1608. case WAIT_OBJECT_0:
  1609. {
  1610. try
  1611. {
  1612. // And call the function
  1613. // =====================
  1614. if ( NULL != m_pfnCloseProc )
  1615. {
  1616. LONG lRet = m_pfnCloseProc();
  1617. DEBUGTRACE( ( LOG_WMIADAP, "Close called for %S returned %d\n", (LPCWSTR)m_wstrServiceName, lRet ) );
  1618. }
  1619. m_fOpen = FALSE;
  1620. }
  1621. catch (...)
  1622. {
  1623. // Ooops... something blew, return error code
  1624. // ==========================================
  1625. SetStatus( ADAP_PERFLIB_FAILED );
  1626. hr = WBEM_E_FAILED;
  1627. ERRORTRACE( ( LOG_WMIADAP, "Perflib Close function has thrown an exception in %S.\n",(LPCWSTR)m_wstrServiceName) );
  1628. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_BAD_PERFLIB_EXCEPTION, (LPCWSTR)m_wstrServiceName, CHex( hr ) );
  1629. }
  1630. }break;
  1631. case WAIT_TIMEOUT:
  1632. {
  1633. hr = WBEM_E_NOT_AVAILABLE;
  1634. ERRORTRACE( ( LOG_WMIADAP, "Perflib access mutex timed out in %S.\n",(LPCWSTR)m_wstrServiceName) );
  1635. }break;
  1636. case WAIT_ABANDONED:
  1637. {
  1638. hr = WBEM_E_FAILED;
  1639. ERRORTRACE( ( LOG_WMIADAP, "Perflib access mutex was abandoned in %S.\n",(LPCWSTR)m_wstrServiceName) );
  1640. }break;
  1641. default:
  1642. {
  1643. hr = WBEM_E_FAILED;
  1644. ERRORTRACE( ( LOG_WMIADAP, "Unknown error with perflib access mutex in %S.\n",(LPCWSTR)m_wstrServiceName) );
  1645. } }
  1646. ReleaseMutex( m_hPLMutex );
  1647. }
  1648. return hr;
  1649. }
  1650. HRESULT CAdapPerfLib::SetStatus(DWORD dwStatus)
  1651. {
  1652. HRESULT hr = WBEM_NO_ERROR;
  1653. m_dwStatus |= dwStatus;
  1654. return hr;
  1655. }
  1656. HRESULT CAdapPerfLib::ClearStatus(DWORD dwStatus)
  1657. {
  1658. HRESULT hr = WBEM_NO_ERROR;
  1659. m_dwStatus &= ~dwStatus;
  1660. return hr;
  1661. }
  1662. BOOL CAdapPerfLib::CheckStatus(DWORD dwStatus)
  1663. {
  1664. return ((m_dwStatus & dwStatus) == dwStatus);
  1665. }