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.

1122 lines
27 KiB

  1. #include "precomp.h"
  2. #include "arrtempl.h" // for CDeleteMe
  3. #include "md5wbem.h" // for MD5
  4. #include "winmgmt.h"
  5. #include "wbemdelta.h"
  6. #include <tchar.h>
  7. #include <vector>
  8. #include <map>
  9. CPerfLib::CPerfLib(TCHAR * SvcName):
  10. m_wstrServiceName(NULL),
  11. m_wstrFull(NULL),
  12. m_hKey(NULL),
  13. m_bOK(FALSE),
  14. m_pwcsLibrary(NULL),
  15. m_pwcsOpenProc(NULL),
  16. m_pwcsCollectProc(NULL),
  17. m_pwcsCloseProc(NULL)
  18. {
  19. if (SvcName)
  20. {
  21. DWORD dwLen = _tcslen(SvcName);
  22. DWORD dwLenPrefix = _tcslen(_T("SYSTEM\\CurrentControlSet\\Services\\"));
  23. TCHAR * pStart = SvcName+dwLenPrefix;
  24. TCHAR * pNameEnd = _tcschr(pStart,_T('\\'));
  25. if (pNameEnd)
  26. {
  27. ULONG_PTR NameLength = (ULONG_PTR)pNameEnd-(ULONG_PTR)pStart;
  28. NameLength/=sizeof(TCHAR);
  29. m_wstrServiceName = new TCHAR[NameLength+1];
  30. if (!m_wstrServiceName)
  31. {
  32. return; // OUT_OF_MEMORY
  33. }
  34. m_wstrServiceName[NameLength]=0;
  35. memcpy(m_wstrServiceName,pStart,NameLength*sizeof(TCHAR));
  36. m_wstrFull = new TCHAR[dwLen+1];
  37. if (m_wstrFull)
  38. {
  39. lstrcpy(m_wstrFull, SvcName);
  40. m_hKey = NULL;
  41. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  42. m_wstrFull,
  43. NULL,
  44. KEY_READ,
  45. &m_hKey))
  46. {
  47. m_pwcsLibrary = NULL;
  48. m_pwcsOpenProc = NULL;
  49. m_pwcsCollectProc = NULL;
  50. m_pwcsCloseProc = NULL;
  51. m_bOK = TRUE;
  52. }
  53. }
  54. }
  55. }
  56. }
  57. CPerfLib::~CPerfLib()
  58. {
  59. if (m_wstrServiceName)
  60. delete [] m_wstrServiceName;
  61. if (m_wstrFull)
  62. delete [] m_wstrFull;
  63. if (m_pwcsLibrary)
  64. delete [] m_pwcsLibrary;
  65. if (m_pwcsOpenProc)
  66. delete [] m_pwcsOpenProc; // not needed as a member
  67. if (m_pwcsCollectProc)
  68. delete [] m_pwcsCollectProc; // not needed as a member
  69. if (m_pwcsCloseProc)
  70. delete [] m_pwcsCloseProc; // not needed as a member
  71. if (m_hKey)
  72. RegCloseKey(m_hKey);
  73. }
  74. HRESULT CPerfLib::GetFileSignature( CheckLibStruct * pCheckLib )
  75. {
  76. HRESULT hr = WBEM_S_NO_ERROR;
  77. if (!pCheckLib){
  78. return WBEM_E_INVALID_PARAMETER;
  79. }
  80. // Get the current library's file time
  81. // ===================================
  82. HANDLE hFile = NULL;
  83. DWORD dwRet = 0;
  84. WCHAR wszFullPath[MAX_PATH];
  85. WCHAR* pwcsTemp = NULL;
  86. if ( 0 != SearchPathW( NULL, m_pwcsLibrary, NULL, MAX_PATH, wszFullPath, &pwcsTemp ) )
  87. {
  88. hFile = CreateFileW( wszFullPath, GENERIC_READ,FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  89. if ( INVALID_HANDLE_VALUE != hFile )
  90. {
  91. DWORD dwFileSizeLow = 0;
  92. DWORD dwFileSizeHigh = 0;
  93. __int32 nFileSize = 0;
  94. DWORD dwNumRead = 0;
  95. BYTE* aBuffer = NULL;
  96. dwFileSizeLow = GetFileSize( hFile, &dwFileSizeHigh );
  97. nFileSize = ( dwFileSizeHigh << 32 ) + dwFileSizeLow;
  98. FILETIME ft;
  99. if (GetFileTime(hFile,&ft,NULL,NULL))
  100. {
  101. HANDLE hFileMap = NULL;
  102. hFileMap = CreateFileMapping(hFile,NULL,PAGE_READONLY,dwFileSizeHigh,dwFileSizeLow,NULL);
  103. if (hFileMap)
  104. {
  105. aBuffer = (BYTE *)MapViewOfFile(hFileMap,
  106. FILE_MAP_READ,
  107. 0,0,0);
  108. if (aBuffer)
  109. {
  110. //
  111. // do the real work
  112. //
  113. MD5 md5;
  114. BYTE aSignature[16];
  115. md5.Transform( aBuffer, nFileSize, aSignature );
  116. // return our data
  117. memcpy(pCheckLib->Signature,aSignature,sizeof(aSignature));
  118. pCheckLib->FileTime = ft;
  119. pCheckLib->FileSize = nFileSize;
  120. UnmapViewOfFile(aBuffer);
  121. }
  122. else
  123. {
  124. hr = WBEM_E_OUT_OF_MEMORY;
  125. }
  126. CloseHandle(hFileMap);
  127. }
  128. else
  129. {
  130. hr = WBEM_E_OUT_OF_MEMORY;
  131. }
  132. /*
  133. aBuffer = new BYTE[nFileSize];
  134. CDeleteMe<BYTE> dmBuffer( aBuffer );
  135. if ( NULL != aBuffer )
  136. {
  137. if ( ReadFile( hFile, aBuffer, nFileSize, &dwNumRead, FALSE ) )
  138. {
  139. MD5 md5;
  140. BYTE aSignature[16];
  141. md5.Transform( aBuffer, dwNumRead, aSignature );
  142. // return our data
  143. memcpy(pCheckLib->Signature,aSignature,sizeof(aSignature));
  144. pCheckLib->FileTime = ft;
  145. pCheckLib->FileSize = nFileSize;
  146. }
  147. else
  148. {
  149. hr = WBEM_E_TOO_MUCH_DATA;
  150. }
  151. }
  152. else
  153. {
  154. hr = WBEM_E_OUT_OF_MEMORY;
  155. }
  156. */
  157. }
  158. else
  159. {
  160. hr = WBEM_E_FAILED;
  161. }
  162. CloseHandle( hFile );
  163. }
  164. else
  165. {
  166. hr = WBEM_E_FAILED;
  167. }
  168. }
  169. else
  170. {
  171. hr = WBEM_E_NOT_FOUND;
  172. }
  173. return hr;
  174. }
  175. LONG
  176. GetBinary(HKEY hKey, TCHAR * Value, BYTE ** ppBuff, DWORD * pdwSize)
  177. {
  178. LONG lRet;
  179. DWORD dwType;
  180. DWORD dwSize = 0;
  181. // null Value is allowed
  182. if (!ppBuff || !pdwSize)
  183. return ERROR_INVALID_PARAMETER;
  184. lRet = RegQueryValueEx(hKey,
  185. Value,
  186. NULL,
  187. &dwType,
  188. NULL,
  189. &dwSize);
  190. if ((ERROR_SUCCESS == lRet) &&
  191. (REG_BINARY == dwType))
  192. {
  193. *pdwSize = dwSize;
  194. if (dwSize > 0)
  195. {
  196. *ppBuff = new BYTE[dwSize];
  197. if (*ppBuff){
  198. lRet = RegQueryValueEx(hKey,
  199. Value,
  200. NULL,
  201. &dwType,
  202. (BYTE *)(*ppBuff),
  203. &dwSize);
  204. } else {
  205. lRet = ERROR_OUTOFMEMORY;
  206. }
  207. }
  208. }
  209. else
  210. {
  211. lRet = ERROR_INVALID_PARAMETER;
  212. }
  213. return lRet;
  214. }
  215. LONG
  216. GetDWORD(HKEY hKey, TCHAR * Value ,DWORD * pDword)
  217. {
  218. LONG lRet;
  219. DWORD dwType = 0;
  220. DWORD dwSize = sizeof(DWORD);
  221. if (!pDword)
  222. return ERROR_INVALID_PARAMETER;
  223. lRet = RegQueryValueEx(hKey,
  224. Value,
  225. NULL,
  226. &dwType,
  227. (BYTE *)pDword,
  228. &dwSize);
  229. if ((REG_DWORD == dwType) &&
  230. (ERROR_SUCCESS == lRet))
  231. return lRet;
  232. else
  233. return ERROR_INVALID_PARAMETER;
  234. }
  235. LONG
  236. GetStr(HKEY hKey, TCHAR * Value ,TCHAR ** ppStr)
  237. {
  238. LONG lRet;
  239. DWORD dwType;
  240. DWORD dwSize = 0;
  241. if (!ppStr)
  242. return ERROR_INVALID_PARAMETER;
  243. lRet = RegQueryValueEx(hKey,
  244. Value,
  245. NULL,
  246. &dwType,
  247. NULL,
  248. &dwSize);
  249. if ((ERROR_SUCCESS == lRet) &&
  250. ((REG_SZ == dwType) || (REG_EXPAND_SZ == dwType)))
  251. {
  252. if (dwSize > 0)
  253. {
  254. TCHAR * pString = new TCHAR[dwSize];
  255. if (pString)
  256. {
  257. lRet = RegQueryValueEx(hKey,
  258. Value,
  259. NULL,
  260. &dwType,
  261. (BYTE *)(pString),
  262. &dwSize);
  263. if (ERROR_SUCCESS == lRet)
  264. {
  265. if (REG_EXPAND_SZ == dwType)
  266. {
  267. TCHAR * pExpanded = new TCHAR[dwSize + MAX_PATH];
  268. if (pExpanded)
  269. {
  270. if(ExpandEnvironmentStrings(pString,pExpanded,(dwSize + MAX_PATH)))
  271. {
  272. *ppStr = pExpanded;
  273. delete [] pString;
  274. }
  275. else
  276. {
  277. delete [] pString;
  278. lRet = ERROR_OUTOFMEMORY;
  279. }
  280. }
  281. else
  282. {
  283. delete [] pString;
  284. lRet = ERROR_OUTOFMEMORY;
  285. }
  286. }
  287. else
  288. {
  289. *ppStr = pString;
  290. }
  291. }
  292. else
  293. {
  294. goto empty_string;
  295. }
  296. }
  297. else
  298. {
  299. lRet = ERROR_OUTOFMEMORY;
  300. }
  301. }
  302. else // empty string
  303. {
  304. empty_string:
  305. *ppStr = new TCHAR[sizeof(_T(""))];
  306. if (*ppStr) {
  307. lstrcpy(*ppStr,_T(""));
  308. } else {
  309. lRet = ERROR_OUTOFMEMORY;
  310. }
  311. }
  312. }
  313. else
  314. {
  315. lRet = ERROR_INVALID_PARAMETER;
  316. }
  317. return lRet;
  318. }
  319. int CPerfLib::CheckFileSignature(HKEY hKey)
  320. {
  321. int hr = Perf_SeemsNew;
  322. int nRet = 0;
  323. BYTE cCurrentMD5[16];
  324. BYTE* cStoredMD5 = NULL;
  325. // Get the stored file signature
  326. // =============================
  327. CheckLibStruct StoredLibStruct;
  328. int nRet1;
  329. int nRet2;
  330. int nRet3;
  331. DWORD dwSize;
  332. nRet1 = GetBinary( hKey, ADAP_PERFLIB_SIGNATURE, (PBYTE*)&cStoredMD5, &dwSize );
  333. CDeleteMe<BYTE> dmStoredMD5( cStoredMD5 );
  334. if (cStoredMD5 && (dwSize == sizeof(StoredLibStruct.Signature)))
  335. {
  336. memcpy(&StoredLibStruct.Signature,cStoredMD5,sizeof(StoredLibStruct.Signature));
  337. BYTE * pFileTime = NULL;
  338. nRet2 = GetBinary( hKey, ADAP_PERFLIB_TIME, (PBYTE*)&pFileTime, &dwSize );
  339. CDeleteMe<BYTE> dmFileTime( pFileTime );
  340. if (pFileTime)
  341. {
  342. memcpy(&StoredLibStruct.FileTime,pFileTime,sizeof(FILETIME));
  343. }
  344. nRet3 = GetDWORD(hKey, ADAP_PERFLIB_SIZE,&StoredLibStruct.FileSize);
  345. if((ERROR_SUCCESS == nRet1) &&
  346. (ERROR_SUCCESS == nRet2) &&
  347. (ERROR_SUCCESS == nRet3))
  348. {
  349. // Get the current library's signature
  350. // ===================================
  351. CheckLibStruct CurrentLibStruct;
  352. memset(&CurrentLibStruct,0,sizeof(CheckLibStruct));
  353. if (SUCCEEDED(GetFileSignature( &CurrentLibStruct )))
  354. {
  355. if ( (StoredLibStruct.FileSize == CurrentLibStruct.FileSize) &&
  356. (0 == memcmp( &StoredLibStruct.Signature, &CurrentLibStruct.Signature, sizeof(CurrentLibStruct.Signature) )) &&
  357. (0 == memcmp( &StoredLibStruct.FileTime, &CurrentLibStruct.FileTime, sizeof(FILETIME))) )
  358. {
  359. hr = Perf_NotChanged;
  360. }
  361. else
  362. {
  363. hr = Perf_SeemsNew;
  364. //DBG_PRINTFA((pBuff,"no FileSize or Signature or FIleSuze\n"));
  365. }
  366. }
  367. else
  368. {
  369. hr = Perf_SeemsNew;
  370. //DBG_PRINTFA((pBuff,"no GetFileSignature\n"));
  371. }
  372. }
  373. else
  374. {
  375. hr = Perf_SeemsNew;
  376. //DBG_PRINTFA((pBuff,"no triple regkey\n"));
  377. }
  378. }
  379. else
  380. {
  381. //DBG_PRINTFA((pBuff,"no ADAP_PERFLIB_SIGNATURE\n"));
  382. }
  383. return hr;
  384. }
  385. int
  386. CPerfLib::VerifyLoaded()
  387. {
  388. int hr = Perf_Invalid;
  389. LONG lRet;
  390. {
  391. DWORD dwFirstCtr = 0,
  392. dwLastCtr = 0;
  393. TCHAR * wszObjList = NULL;
  394. if ( ( ERROR_SUCCESS == GetStr( GetHKey(), L"Object List", &wszObjList )) ||
  395. ( ( ERROR_SUCCESS == GetDWORD( GetHKey(), L"First Counter", &dwFirstCtr )) &&
  396. ( ERROR_SUCCESS == GetDWORD( GetHKey(), L"Last Counter", &dwLastCtr ))))
  397. {
  398. hr = InitializeEntryPoints(GetHKey());
  399. if (wszObjList)
  400. {
  401. delete [] wszObjList;
  402. }
  403. } else { // more special cases
  404. if ( (0 == _tcsicmp(m_wstrServiceName,_T("TCPIP"))) ||
  405. (0 == _tcsicmp(m_wstrServiceName,_T("TAPISRV"))) ||
  406. (0 == _tcsicmp(m_wstrServiceName,_T("PERFOS" ))) ||
  407. (0 == _tcsicmp(m_wstrServiceName,_T("PERFPROC"))) ||
  408. (0 == _tcsicmp(m_wstrServiceName,_T("PERFDISK"))) ||
  409. (0 == _tcsicmp(m_wstrServiceName,_T("PERFNET"))) ||
  410. (0 == _tcsicmp(m_wstrServiceName,_T("SPOOLER"))) ||
  411. (0 == _tcsicmp(m_wstrServiceName,_T("MSFTPSvc"))) ||
  412. (0 == _tcsicmp(m_wstrServiceName,_T("RemoteAccess"))) ||
  413. (0 == _tcsicmp(m_wstrServiceName,_T("WINS"))) ||
  414. (0 == _tcsicmp(m_wstrServiceName,_T("MacSrv"))) ||
  415. (0 == _tcsicmp(m_wstrServiceName,_T("AppleTalk"))) ||
  416. (0 == _tcsicmp(m_wstrServiceName,_T("NM"))) ||
  417. (0 == _tcsicmp(m_wstrServiceName,_T("RSVP"))) )
  418. {
  419. hr = InitializeEntryPoints(GetHKey());
  420. }
  421. }
  422. }
  423. return hr;
  424. }
  425. int
  426. CPerfLib::InitializeEntryPoints(HKEY hKey)
  427. {
  428. int hr = Perf_SeemsNew;
  429. // see if someone disabled this library
  430. DWORD dwDisable = 0;
  431. if ( ERROR_SUCCESS == GetDWORD( hKey, _T("Disable Performance Counters"), &dwDisable ) &&
  432. (dwDisable != 0) )
  433. {
  434. hr = Perf_Disabled;
  435. }
  436. if ((ERROR_SUCCESS == GetDWORD( hKey, _T("WbemAdapStatus"), &dwDisable))
  437. && (0xFFFFFFFF == dwDisable))
  438. {
  439. hr = Perf_Disabled;
  440. }
  441. // the perflib is OK for the world, see if it os OK for US
  442. if (SUCCEEDED(hr)){
  443. if (!(( ERROR_SUCCESS == GetStr( hKey, _T("Library"), &m_pwcsLibrary ) ) &&
  444. ( ERROR_SUCCESS == GetStr( hKey, _T("Open"), &m_pwcsOpenProc ) )&&
  445. ( ERROR_SUCCESS == GetStr( hKey, _T("Collect"), &m_pwcsCollectProc ) ) &&
  446. ( ERROR_SUCCESS == GetStr( hKey, _T("Close"), &m_pwcsCloseProc ) ) ))
  447. {
  448. hr = Perf_Invalid;
  449. }
  450. else
  451. {
  452. hr = Perf_SetupOK;
  453. }
  454. }
  455. return hr;
  456. }
  457. int
  458. CPerfLib::VerifyLoadable()
  459. {
  460. if (!m_bOK)
  461. return Perf_Invalid;
  462. int hr;
  463. hr = VerifyLoaded();
  464. if ( Perf_SetupOK == hr )
  465. {
  466. hr = CheckFileSignature(GetHKey());
  467. }
  468. return hr;
  469. }
  470. TCHAR * g_ExcludeList[] = {
  471. _T("WMIAPRPL")
  472. };
  473. //
  474. //
  475. // GetListofSvcs
  476. //
  477. ////////////////////////////////////////////////////////////
  478. HRESULT
  479. GetListOfSvcs(LIST_ENTRY * pListServices)
  480. {
  481. LONG lRet;
  482. HKEY hKey;
  483. HRESULT hRes = WBEM_NO_ERROR;
  484. lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  485. SVC_KEY,
  486. 0,KEY_READ,
  487. &hKey);
  488. if (ERROR_SUCCESS == lRet)
  489. {
  490. DWORD dwIndex = 0;
  491. TCHAR KeyName[MAX_PATH];
  492. TCHAR * pKeyName = KeyName;
  493. DWORD dwKeyNameSize = (sizeof(KeyName)/sizeof(TCHAR));
  494. FILETIME FileTime;
  495. while (ERROR_SUCCESS == lRet)
  496. {
  497. if (pKeyName != KeyName)
  498. {
  499. delete [] pKeyName;
  500. pKeyName = KeyName;
  501. }
  502. dwKeyNameSize = (sizeof(KeyName)/sizeof(TCHAR));
  503. lRet = RegEnumKeyEx(hKey,
  504. dwIndex,
  505. pKeyName,
  506. &dwKeyNameSize,
  507. NULL,NULL,NULL,
  508. &FileTime);
  509. if (ERROR_INSUFFICIENT_BUFFER == lRet)
  510. {
  511. pKeyName = new TCHAR[dwKeyNameSize];
  512. if (pKeyName)
  513. {
  514. lRet = RegEnumKeyEx(hKey,
  515. dwIndex,
  516. pKeyName,
  517. &dwKeyNameSize,
  518. NULL,NULL,NULL,
  519. &FileTime);
  520. }
  521. else
  522. {
  523. lRet = ERROR_OUTOFMEMORY;
  524. }
  525. }
  526. if (ERROR_SUCCESS == lRet)
  527. {
  528. dwIndex++;
  529. DWORD i;
  530. DWORD NumExcluded = sizeof(g_ExcludeList)/sizeof(TCHAR *);
  531. for (i=0; i<NumExcluded; i++)
  532. {
  533. if (0 == _tcsicmp(g_ExcludeList[i],pKeyName)){
  534. break;
  535. }
  536. }
  537. // if we pass all the Excluded Array then we are OK to add
  538. if (i == NumExcluded)
  539. {
  540. DWORD dwSize = _tcslen(pKeyName);
  541. LinkString * pLinkString = (LinkString *)new BYTE[sizeof(LinkString) + dwSize*sizeof(TCHAR)];
  542. if (pLinkString)
  543. {
  544. pLinkString->Size = dwSize;
  545. _tcscpy(pLinkString->pString,pKeyName);
  546. InsertTailList(pListServices,&pLinkString->Entry);
  547. }
  548. else
  549. {
  550. lRet = ERROR_OUTOFMEMORY;
  551. }
  552. }
  553. }
  554. //
  555. // the lack of the else case here will prevent the loop
  556. // from completing if only one key is BAD
  557. //
  558. }
  559. if (pKeyName != KeyName)
  560. {
  561. delete [] pKeyName;
  562. pKeyName = KeyName;
  563. }
  564. if (ERROR_NO_MORE_ITEMS != lRet)
  565. {
  566. hRes = WBEM_E_FAILED;
  567. }
  568. RegCloseKey(hKey);
  569. }
  570. else
  571. {
  572. hRes = WBEM_E_FAILED;
  573. }
  574. return hRes;
  575. }
  576. //
  577. //
  578. // GetSvcWithPerf
  579. //
  580. ///////////////////////////////////////////////////////////
  581. #define FIXED_SIZE (sizeof(_T("System\\CurrentControlSet\\Services\\%s\\Performance")))
  582. HRESULT
  583. GetSvcWithPerf(/*IN OUT*/ LIST_ENTRY * pListHead)
  584. {
  585. TCHAR KeyPath[MAX_PATH+1];
  586. TCHAR * pKeyPath = KeyPath;
  587. LIST_ENTRY LocalListHead;
  588. InitializeListHead(&LocalListHead);
  589. // now change the head to the list
  590. // assume the list is NOT EMPTY
  591. LIST_ENTRY * pEntry = pListHead->Flink; // point to the first item
  592. RemoveEntryList(pListHead); // remove the head
  593. InitializeListHead(pListHead); // clear the head
  594. InsertTailList(pEntry,&LocalListHead); // put in the same place the New Local head
  595. HRESULT hRes = WBEM_NO_ERROR;
  596. DWORD i;
  597. for (pEntry = LocalListHead.Flink;
  598. pEntry != &LocalListHead;
  599. pEntry = pEntry->Flink)
  600. {
  601. LinkString * pLinkString = (LinkString *) pEntry;
  602. if ((FIXED_SIZE + pLinkString->Size) < MAX_PATH )
  603. {
  604. _stprintf(KeyPath,_T("System\\CurrentControlSet\\Services\\%s\\Performance"),pLinkString->pString);
  605. }
  606. else
  607. {
  608. if (pKeyPath != KeyPath && pKeyPath)
  609. {
  610. delete [] pKeyPath;
  611. }
  612. pKeyPath = new TCHAR[1 + FIXED_SIZE + pLinkString->Size];
  613. if (pKeyPath)
  614. {
  615. _stprintf(pKeyPath,_T("System\\CurrentControlSet\\Services\\%s\\Performance"),pLinkString->pString);
  616. }
  617. else
  618. {
  619. hRes = WBEM_E_OUT_OF_MEMORY;
  620. break;
  621. }
  622. }
  623. LONG lRes;
  624. HKEY hKey;
  625. lRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  626. pKeyPath,
  627. NULL,KEY_READ,
  628. &hKey);
  629. if (ERROR_SUCCESS == lRes)
  630. {
  631. DWORD nSize = _tcslen(pKeyPath);
  632. LinkString * pLinkString2 = (LinkString *)new BYTE[sizeof(LinkString) + nSize*sizeof(TCHAR)];
  633. if (pLinkString2)
  634. {
  635. pLinkString2->Size = nSize;
  636. _tcscpy(pLinkString2->pString,pKeyPath);
  637. InsertTailList(pListHead,&pLinkString2->Entry);
  638. }
  639. else
  640. {
  641. lRes = ERROR_OUTOFMEMORY;
  642. }
  643. RegCloseKey(hKey);
  644. }
  645. }
  646. for (pEntry = LocalListHead.Flink;
  647. pEntry != &LocalListHead;
  648. pEntry = pEntry->Flink)
  649. {
  650. BYTE * pByte = (BYTE *)pEntry;
  651. RemoveEntryList(pEntry);
  652. pEntry = pEntry->Flink;
  653. delete [] pByte;
  654. };
  655. if (pKeyPath != KeyPath)
  656. {
  657. delete [] pKeyPath;
  658. }
  659. return hRes;
  660. }
  661. //
  662. //
  663. // Known Service implementation
  664. //
  665. ///////////////////////////////////////////////////////////
  666. bool
  667. WCmp::operator()(WString pFirst,WString pSec) const
  668. {
  669. if (!pFirst || !pSec)
  670. return false;
  671. int res = _wcsicmp(pFirst,pSec);
  672. return (res<0);
  673. }
  674. CSvcs::CSvcs():
  675. m_cRef(1)
  676. {
  677. }
  678. CSvcs::~CSvcs()
  679. {
  680. }
  681. DWORD
  682. CSvcs::Add(WCHAR * pService)
  683. {
  684. if (pService)
  685. {
  686. try
  687. {
  688. MapSvc::iterator it = m_SetServices.find(pService);
  689. if (it == m_SetServices.end()) // not in the std::map
  690. {
  691. m_SetServices[pService] = true; // add to the map
  692. }
  693. return 0;
  694. }
  695. catch (CX_MemoryException)
  696. {
  697. return ERROR_OUTOFMEMORY;
  698. }
  699. }
  700. else
  701. return ERROR_INVALID_PARAMETER;
  702. }
  703. BOOL
  704. CSvcs::Find(WCHAR * pService)
  705. {
  706. if (pService)
  707. {
  708. MapSvc::iterator it = m_SetServices.find(pService);
  709. if (it != m_SetServices.end())
  710. {
  711. return TRUE;
  712. }
  713. }
  714. return FALSE;
  715. }
  716. DWORD
  717. CSvcs::Load()
  718. {
  719. // get the MULTI_SZ key
  720. LONG lRet;
  721. HKEY hKey;
  722. lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  723. WBEM_REG_WINMGMT,
  724. NULL,
  725. KEY_READ,
  726. &hKey);
  727. if (ERROR_SUCCESS == lRet)
  728. {
  729. DWORD dwSize = 0;
  730. DWORD dwType = REG_MULTI_SZ;
  731. lRet = RegQueryValueEx(hKey,
  732. KNOWN_SERVICES,
  733. NULL,
  734. &dwType,
  735. NULL,
  736. &dwSize);
  737. if (ERROR_SUCCESS == lRet && (dwSize > 0))
  738. {
  739. TCHAR * pStr = new TCHAR[dwSize];
  740. if (pStr)
  741. {
  742. CDeleteMe<TCHAR> cdm(pStr);
  743. lRet = RegQueryValueEx(hKey,
  744. KNOWN_SERVICES,
  745. NULL,
  746. &dwType,
  747. (BYTE *)pStr,
  748. &dwSize);
  749. if ((ERROR_SUCCESS == lRet) &&
  750. (REG_MULTI_SZ == dwType))
  751. {
  752. DWORD dwLen = 0;
  753. while(dwLen = lstrlen(pStr))
  754. {
  755. try
  756. {
  757. m_SetServices[pStr] = true;
  758. }
  759. catch (CX_MemoryException)
  760. {
  761. lRet = ERROR_OUTOFMEMORY;
  762. break;
  763. }
  764. pStr += (dwLen+1);
  765. }
  766. }
  767. }
  768. else
  769. {
  770. lRet = ERROR_OUTOFMEMORY;
  771. }
  772. }
  773. RegCloseKey(hKey);
  774. }
  775. return lRet;
  776. }
  777. // already in winmgmt.h
  778. /*
  779. #define FULL_DREDGE 2
  780. #define PARTIAL_DREDGE 1
  781. #define NO_DREDGE 0
  782. */
  783. //
  784. //
  785. // DeltaDredge
  786. //
  787. // both params are unused
  788. // operation
  789. // reads a registry key containing the known Services
  790. // enumerates the registry keys, and figure-out which ones
  791. // are the one with "performance" subkey
  792. //
  793. ///////////////////////////////////////////////////////////
  794. DWORD WINAPI
  795. DeltaDredge(DWORD dwNumServicesArgs,
  796. LPWSTR *lpServiceArgVectors)
  797. {
  798. DWORD bDredge = NO_DREDGE;
  799. CSvcs KnownSvc;
  800. if (ERROR_SUCCESS == KnownSvc.Load())
  801. {
  802. LIST_ENTRY ListServices;
  803. InitializeListHead(&ListServices);
  804. HRESULT hRes;
  805. hRes = GetListOfSvcs(&ListServices);
  806. if (SUCCEEDED(hRes))
  807. {
  808. hRes = GetSvcWithPerf(&ListServices);
  809. if (SUCCEEDED(hRes))
  810. {
  811. DWORD Status = 0;
  812. try
  813. {
  814. CSvcs OKServices; // this constructor throws
  815. LIST_ENTRY * pListEntry;
  816. DWORD i=0;
  817. for (pListEntry = ListServices.Flink;
  818. pListEntry != &ListServices;
  819. pListEntry = pListEntry->Flink)
  820. {
  821. LinkString * pLString = (LinkString *)pListEntry;
  822. CPerfLib PerfLib(pLString->pString);
  823. if (!PerfLib.IsOK())
  824. {
  825. continue;
  826. }
  827. int PerfStatus = PerfLib.VerifyLoadable();
  828. #ifdef DEBUG_ADAP
  829. DBG_PRINTFA((pBuff,"%d Service %S status %d\n",i,pLString->pString,PerfStatus));
  830. #endif
  831. switch (PerfStatus)
  832. {
  833. case CPerfLib::Perf_Invalid:
  834. case CPerfLib::Perf_Disabled:
  835. //
  836. // nothing to do with an invalid library
  837. // or with a disabled library
  838. //
  839. #ifdef DEBUG_ADAP
  840. DBG_PRINTFA((pBuff,"Invalid or Disabled Service %S\n",PerfLib.GetServiceName()));
  841. #endif
  842. DEBUGTRACE((LOG_WMIADAP,"Invalid registration or Disabled Service %S\n",PerfLib.GetServiceName()));
  843. break;
  844. case CPerfLib::Perf_NotChanged:
  845. //
  846. // this is what we want to hear
  847. //
  848. OKServices.Add(PerfLib.GetServiceName());
  849. break;
  850. case CPerfLib::Perf_SeemsNew:
  851. //
  852. // now we have to do a dredge
  853. //
  854. #ifdef DEBUG_ADAP
  855. DBG_PRINTFA((pBuff,"NewOrChanged Service %S\n",PerfLib.GetServiceName()));
  856. #endif
  857. DEBUGTRACE((LOG_WMIADAP,"NewOrChanged Service %S\n",PerfLib.GetServiceName()));
  858. bDredge = PARTIAL_DREDGE;
  859. break;
  860. default:
  861. //
  862. // never here
  863. //
  864. break;
  865. }
  866. i++;
  867. }
  868. if (NO_DREDGE == bDredge)
  869. {
  870. //
  871. // if here, someone might have changed the registry directly
  872. //
  873. if (OKServices.GetMap().size() != KnownSvc.GetMap().size())
  874. {
  875. #ifdef DEBUG_ADAP
  876. DBG_PRINTFA((pBuff,"Registry-listed Services and KnownSvcs are not of the same size\n"));
  877. #endif
  878. ERRORTRACE((LOG_WMIADAP,"Registry-listed Services and KnownSvcs are not of the same size\n"));
  879. bDredge = PARTIAL_DREDGE;
  880. }
  881. else // same size -> are they the same ?
  882. {
  883. MapSvc::iterator it1 = OKServices.GetMap().begin();
  884. MapSvc::iterator it2 = KnownSvc.GetMap().begin();
  885. while (it1 != OKServices.GetMap().end())
  886. {
  887. #ifdef DEBUG_ADAP
  888. DBG_PRINTFA((pBuff," %S =?= %S \n",(const WCHAR *)(*it1).first,(const WCHAR *)(*it2).first));
  889. #endif
  890. if (0 != _wcsicmp((*it1).first,(*it2).first))
  891. {
  892. bDredge = PARTIAL_DREDGE;
  893. break;
  894. }
  895. ++it1;
  896. ++it2;
  897. }
  898. }
  899. }
  900. }
  901. catch (CX_MemoryException & )
  902. {
  903. bDredge = PARTIAL_DREDGE;
  904. }
  905. }
  906. }
  907. LIST_ENTRY * pListEntry;
  908. for (pListEntry = ListServices.Flink;
  909. pListEntry != &ListServices;
  910. )
  911. {
  912. BYTE * pByte = (BYTE *)pListEntry;
  913. RemoveEntryList(pListEntry);
  914. pListEntry = pListEntry->Flink;
  915. delete [] pByte;
  916. }
  917. }
  918. else
  919. {
  920. //
  921. // There is no valid KNOWN_SERVICES key --- FULL Dredge
  922. //
  923. bDredge = FULL_DREDGE;
  924. }
  925. return bDredge;
  926. }
  927. DWORD WINAPI
  928. DeltaDredge2(DWORD dwNumServicesArgs,
  929. LPWSTR *lpServiceArgVectors)
  930. {
  931. DWORD bDredge = FULL_DREDGE;
  932. // check the MULTI_SZ key
  933. LONG lRet;
  934. HKEY hKey;
  935. lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  936. WBEM_REG_WINMGMT,
  937. NULL,
  938. KEY_READ,
  939. &hKey);
  940. if (ERROR_SUCCESS == lRet)
  941. {
  942. DWORD dwSize = 0;
  943. DWORD dwType = REG_MULTI_SZ;
  944. lRet = RegQueryValueEx(hKey,
  945. KNOWN_SERVICES,
  946. NULL,
  947. &dwType,
  948. NULL,
  949. &dwSize);
  950. if (ERROR_SUCCESS == lRet && (dwSize > 2)) // empty MULTI_SZ is 2 bytes
  951. {
  952. bDredge = NO_DREDGE;
  953. }
  954. RegCloseKey(hKey);
  955. }
  956. return bDredge;
  957. }