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.

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