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.

1455 lines
48 KiB

  1. /*++
  2. Copyright (C) 1999-2001 Microsoft Corporation
  3. Module Name:
  4. ADAPREG.CPP
  5. Abstract:
  6. History:
  7. --*/
  8. #include "precomp.h"
  9. #include <stdio.h>
  10. #include <wtypes.h>
  11. #include <oleauto.h>
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #include <time.h>
  15. #include <malloc.h>
  16. #include <process.h>
  17. #include <arrtempl.h>
  18. #include <cominit.h>
  19. #include <winmgmtr.h>
  20. #include <wbemcli.h>
  21. #include <throttle.h>
  22. #include <psapi.h>
  23. #include "adapreg.h"
  24. #include "perflibschema.h"
  25. #include "WMIBroker.h"
  26. #include "adaputil.h"
  27. #include "adapperf.h"
  28. #include "ntreg.h"
  29. #include "winuser.h"
  30. // globals
  31. DWORD CAdapPerfLib::s_MaxSizeCollect = 64*1024*1024;
  32. // Performance library processing list
  33. // ===================================
  34. CPerfLibList g_PerfLibList;
  35. HANDLE g_hAbort = NULL;
  36. /////////////////////////////////////////////////////////////////////////////
  37. //
  38. // returns the PID (the first found if many are there) if success
  39. // returns ZERO if fails
  40. //
  41. /////////////////////////////////////////////////////////////////////////////
  42. #define MAX_ITERATION 8
  43. #define MAX_MODULE (1024)
  44. DWORD GetExecPid()
  45. {
  46. DWORD ThisProc = 0;
  47. LONG lRet = 0;
  48. HKEY hKey;
  49. lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  50. L"Software\\Microsoft\\WBEM\\CIMOM",
  51. NULL,
  52. KEY_READ,
  53. &hKey);
  54. if (ERROR_SUCCESS == lRet)
  55. {
  56. DWORD dwType;
  57. DWORD dwSize = sizeof(DWORD);
  58. RegQueryValueEx(hKey,
  59. L"ProcessID",
  60. NULL,
  61. &dwType,
  62. (BYTE*)&ThisProc,
  63. &dwSize);
  64. RegCloseKey(hKey);
  65. }
  66. return ThisProc;
  67. }
  68. void DoResyncPerf( BOOL bDelta, BOOL bThrottle )
  69. {
  70. DEBUGTRACE((LOG_WINMGMT,"ADAP Resync has started\n"));
  71. g_hAbort = CreateEventW( NULL, TRUE, FALSE, L"ADAP_ABORT");
  72. CCloseMe cmAbort( g_hAbort );
  73. if ( NULL != g_hAbort )
  74. {
  75. HRESULT hr = WBEM_S_NO_ERROR;
  76. CAdapRegPerf regPerf(!bDelta);
  77. // Process each perflib that is registered on the system
  78. // =====================================================
  79. hr = regPerf.Initialize( bDelta, bThrottle );
  80. if ( SUCCEEDED( hr ) )
  81. {
  82. hr = regPerf.Dredge( bDelta, bThrottle );
  83. }
  84. if ( FAILED( hr ) )
  85. {
  86. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_PROCESSING_FAILURE, CHex( hr ) );
  87. }
  88. }
  89. DEBUGTRACE((LOG_WINMGMT,"ADAP Resync has completed\n"));
  90. return;
  91. }
  92. void DoClearADAP()
  93. {
  94. DEBUGTRACE((LOG_WINMGMT,"ADAP registry reset has started\n"));
  95. CAdapRegPerf regPerf(FALSE);
  96. regPerf.Clean();
  97. DEBUGTRACE((LOG_WINMGMT,"ADAP registry reset has completed\n"));
  98. return;
  99. }
  100. HRESULT DoReverseAdapterMaintenance( BOOL bThrottle );
  101. /*
  102. {
  103. ERRORTRACE((LOG_WMIADAP,"DoReverseAdapterDredge called"));
  104. return WBEM_NO_ERROR;
  105. };
  106. */
  107. /*
  108. ->Revision: 0x1
  109. ->Sbz1 : 0x0
  110. ->Control : 0x8004
  111. SE_DACL_PRESENT
  112. SE_SELF_RELATIVE
  113. ->Owner : S-1-5-32-544
  114. ->Group : S-1-5-18
  115. ->Dacl :
  116. ->Dacl : ->AclRevision: 0x2
  117. ->Dacl : ->Sbz1 : 0x0
  118. ->Dacl : ->AclSize : 0x44
  119. ->Dacl : ->AceCount : 0x2
  120. ->Dacl : ->Sbz2 : 0x0
  121. ->Dacl : ->Ace[0]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
  122. ->Dacl : ->Ace[0]: ->AceFlags: 0x0
  123. ->Dacl : ->Ace[0]: ->AceSize: 0x14
  124. ->Dacl : ->Ace[0]: ->Mask : 0x001f0003
  125. ->Dacl : ->Ace[0]: ->SID: S-1-5-18
  126. ->Dacl : ->Ace[1]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
  127. ->Dacl : ->Ace[1]: ->AceFlags: 0x0
  128. ->Dacl : ->Ace[1]: ->AceSize: 0x18
  129. ->Dacl : ->Ace[1]: ->Mask : 0x001f0003
  130. ->Dacl : ->Ace[1]: ->SID: S-1-5-32-544
  131. */
  132. DWORD g_PreCompSD[] = {
  133. 0x80040001 , 0x00000058 , 0x00000068 , 0x00000000,
  134. 0x00000014 , 0x00440002 , 0x00000002 , 0x00140000,
  135. 0x001f0003 , 0x00000101 , 0x05000000 , 0x00000012,
  136. 0x00180000 , 0x001f0003 , 0x00000201 , 0x05000000,
  137. 0x00000020 , 0x00000220 , 0x00b70000 , 0x00000000,
  138. 0x01190000 , 0x00010002 , 0x00000201 , 0x05000000,
  139. 0x00000020 , 0x00000220 , 0x00000101 , 0x05000000,
  140. 0x00000012 , 0x00000069 , 0x00000000 , 0x00000000
  141. };
  142. //
  143. // Build a SD with owner == ProcessSid
  144. // group == ProcessSid
  145. // DACL
  146. // ACE[0] MUTEX_ALL_ACCESS System
  147. // ACE[1] MUTEX_ALL_ACCESS Administators
  148. ///////////////////////////////////////////////////////////////////
  149. VOID * CreateSD(/* in */ DWORD AccessMask,
  150. /* out */ DWORD &SizeSd )
  151. {
  152. SizeSd = 0;
  153. HANDLE hToken;
  154. if (FALSE == OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&hToken)) return NULL;
  155. OnDelete<HANDLE,BOOL(*)(HANDLE),CloseHandle> CloseToken(hToken);
  156. DWORD dwSize = sizeof(TOKEN_USER)+sizeof(SID)+(SID_MAX_SUB_AUTHORITIES*sizeof(DWORD));
  157. TOKEN_USER * pToken_User = (TOKEN_USER *)LocalAlloc(LPTR,dwSize);
  158. if (NULL == pToken_User) return NULL;
  159. OnDelete<HLOCAL,HLOCAL(*)(HLOCAL),LocalFree> FreeMe1(pToken_User);
  160. if (FALSE == GetTokenInformation(hToken,TokenUser,pToken_User,dwSize,&dwSize)) return NULL;
  161. SID_IDENTIFIER_AUTHORITY ntifs = SECURITY_NT_AUTHORITY;
  162. PSID SystemSid = NULL;
  163. if (FALSE == AllocateAndInitializeSid( &ntifs ,
  164. 1,
  165. SECURITY_LOCAL_SYSTEM_RID,0,0,0,0,0,0,0,
  166. &SystemSid)) return NULL;
  167. OnDelete<PSID,PVOID(*)(PSID),FreeSid> FreeSid1(SystemSid);
  168. PSID AdministratorsSid = NULL;
  169. if (FALSE == AllocateAndInitializeSid(&ntifs,
  170. 2,
  171. SECURITY_BUILTIN_DOMAIN_RID,
  172. DOMAIN_ALIAS_RID_ADMINS,0,0,0,0,0,0,
  173. &AdministratorsSid)) return NULL;
  174. OnDelete<PSID,PVOID(*)(PSID),FreeSid> FreeSid2(AdministratorsSid);
  175. PSID pSIDUser = pToken_User->User.Sid;
  176. dwSize = GetLengthSid(pSIDUser);
  177. DWORD dwSids = 2; // System and Administrators
  178. DWORD ACLLength = (ULONG) sizeof(ACL) +
  179. (dwSids * ((ULONG) sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG))) + GetLengthSid(SystemSid) + GetLengthSid(AdministratorsSid);
  180. DWORD dwSizeSD = sizeof(SECURITY_DESCRIPTOR_RELATIVE) + dwSize + dwSize + ACLLength;
  181. SECURITY_DESCRIPTOR_RELATIVE * pLocalSD = (SECURITY_DESCRIPTOR_RELATIVE *)LocalAlloc(LPTR,dwSizeSD);
  182. if (NULL == pLocalSD) return NULL;
  183. OnDeleteIf<HLOCAL,HLOCAL(*)(HLOCAL),LocalFree> FreeMeSD(pLocalSD);
  184. memset(pLocalSD,0,sizeof(SECURITY_DESCRIPTOR_RELATIVE));
  185. pLocalSD->Revision = SECURITY_DESCRIPTOR_REVISION;
  186. pLocalSD->Control = SE_DACL_PRESENT|SE_SELF_RELATIVE;
  187. //SetSecurityDescriptorOwner(pLocalSD,pSIDUser,FALSE);
  188. memcpy((BYTE*)pLocalSD+sizeof(SECURITY_DESCRIPTOR_RELATIVE),pSIDUser,dwSize);
  189. pLocalSD->Owner = (DWORD)sizeof(SECURITY_DESCRIPTOR_RELATIVE);
  190. //SetSecurityDescriptorGroup(pLocalSD,pSIDUser,FALSE);
  191. memcpy((BYTE*)pLocalSD+sizeof(SECURITY_DESCRIPTOR_RELATIVE)+dwSize,pSIDUser,dwSize);
  192. pLocalSD->Group = (DWORD)(sizeof(SECURITY_DESCRIPTOR_RELATIVE)+dwSize);
  193. PACL pDacl = (PACL)LocalAlloc(LPTR,ACLLength);
  194. if (NULL == pDacl) return NULL;
  195. OnDelete<HLOCAL,HLOCAL(*)(HLOCAL),LocalFree> FreeMe3(pDacl);
  196. if (FALSE == InitializeAcl( pDacl,ACLLength,ACL_REVISION)) return NULL;
  197. if (FALSE == AddAccessAllowedAceEx (pDacl,ACL_REVISION,0,AccessMask,SystemSid)) return NULL;
  198. if (FALSE == AddAccessAllowedAceEx (pDacl,ACL_REVISION,0,AccessMask,AdministratorsSid)) return NULL;
  199. //bRet = SetSecurityDescriptorDacl(pLocalSD,TRUE,pDacl,FALSE);
  200. memcpy((BYTE*)pLocalSD+sizeof(SECURITY_DESCRIPTOR_RELATIVE)+dwSize+dwSize,pDacl,ACLLength);
  201. pLocalSD->Dacl = (DWORD)(sizeof(SECURITY_DESCRIPTOR_RELATIVE)+dwSize+dwSize);
  202. if (false == RtlValidRelativeSecurityDescriptor(pLocalSD,
  203. dwSizeSD,
  204. OWNER_SECURITY_INFORMATION|
  205. GROUP_SECURITY_INFORMATION|
  206. DACL_SECURITY_INFORMATION)) return NULL;
  207. FreeMeSD.dismiss();
  208. SizeSd = dwSizeSD;
  209. return pLocalSD;
  210. };
  211. ///////////////////////////////////////////////////////////////////////////////
  212. //
  213. // Entry Point
  214. // ===========
  215. //
  216. ///////////////////////////////////////////////////////////////////////////////
  217. int WINAPI WinMain(
  218. HINSTANCE hInstance, // handle to current instance
  219. HINSTANCE hPrevInstance, // handle to previous instance
  220. LPSTR szCmdLine, // command line
  221. int nCmdShow // show state
  222. )
  223. {
  224. try
  225. {
  226. if (CStaticCritSec::anyFailure()) return 0;
  227. // Ensure that we are NT5 or better
  228. // ================================
  229. OSVERSIONINFO OSVer;
  230. OSVer.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
  231. if ( GetVersionEx( &OSVer ) )
  232. {
  233. if ( ! ( ( VER_PLATFORM_WIN32_NT == OSVer.dwPlatformId ) && ( 5 <= OSVer.dwMajorVersion ) ) )
  234. return 0;
  235. }
  236. else
  237. {
  238. return 0;
  239. }
  240. // To avoid messy dialog boxes...
  241. // ==============================
  242. SetErrorMode( SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX );
  243. // Initialize COM.
  244. RETURN_ON_ERR(CoInitializeEx(NULL,COINIT_MULTITHREADED));
  245. OnDelete0<void(*)(void),CoUninitialize> CoUninit;
  246. RETURN_ON_ERR(CoInitializeSecurity( NULL, -1, NULL, NULL,
  247. RPC_C_AUTHN_LEVEL_DEFAULT,
  248. RPC_C_IMP_LEVEL_IDENTIFY,
  249. NULL,
  250. EOAC_NONE|EOAC_SECURE_REFS , NULL ));
  251. // get some value from registry
  252. CNTRegistry reg;
  253. if ( CNTRegistry::no_error == reg.Open( HKEY_LOCAL_MACHINE, WBEM_REG_WINMGMT) )
  254. {
  255. reg.GetDWORD( ADAP_KEY_MAX_COLLECT, &CAdapPerfLib::s_MaxSizeCollect);
  256. }
  257. // Get the Winmgmt service PID
  258. // ===========================
  259. DWORD dwPID = GetExecPid();
  260. // The semaphore is used so that no more that two copies are running at any time.
  261. // ==============================================================================
  262. WCHAR wszObjName[256];
  263. HANDLE hSemaphore;
  264. DWORD SizeSd;
  265. void * pSecDesSem = CreateSD(SEMAPHORE_ALL_ACCESS,SizeSd);
  266. OnDelete<HLOCAL,HLOCAL(*)(HLOCAL),LocalFree> FreeMeSem(pSecDesSem);
  267. SECURITY_ATTRIBUTES sa;
  268. sa.nLength = (pSecDesSem) ? SizeSd : sizeof(g_PreCompSD);
  269. sa.lpSecurityDescriptor = (pSecDesSem) ? pSecDesSem : g_PreCompSD;
  270. sa.bInheritHandle = FALSE;
  271. StringCchPrintfW(wszObjName, 256, L"Global\\WMI_SysEvent_Semaphore_%d", dwPID);
  272. hSemaphore = CreateSemaphoreW(&sa, 2, 2, wszObjName);
  273. if(hSemaphore == NULL)
  274. {
  275. DEBUGTRACE((LOG_WMIADAP,"WMI_SysEvent_Semaphore semaphore creation failed %d\n",GetLastError()));
  276. return 0;
  277. }
  278. CCloseMe cm1(hSemaphore);
  279. DWORD dwRet = WaitForSingleObject(hSemaphore, 0);
  280. if(dwRet != WAIT_OBJECT_0)
  281. return 0;
  282. // The mutex makes sure that multiple copies are sequential.
  283. // =========================================================
  284. void * pSecDesMut = CreateSD(MUTEX_ALL_ACCESS,SizeSd);
  285. OnDelete<HLOCAL,HLOCAL(*)(HLOCAL),LocalFree> FreeMeMut(pSecDesMut);
  286. sa.nLength = (pSecDesMut) ? SizeSd : sizeof(g_PreCompSD);
  287. sa.lpSecurityDescriptor = (pSecDesMut) ? pSecDesSem : g_PreCompSD;
  288. sa.bInheritHandle = FALSE;
  289. HANDLE hMutex;
  290. hMutex = CreateMutexW( &sa, FALSE, L"Global\\ADAP_WMI_ENTRY" );
  291. if(hMutex == NULL)
  292. {
  293. DEBUGTRACE((LOG_WMIADAP,"ADAP_WMI_ENTRY mutex creation failed %d\n",GetLastError()));
  294. return 0;
  295. }
  296. CCloseMe cm2(hMutex);
  297. switch ( WaitForSingleObject( hMutex, 400000) )
  298. {
  299. case WAIT_ABANDONED:
  300. case WAIT_OBJECT_0:
  301. {
  302. BOOL bThrottle = FALSE;
  303. BOOL bFull = FALSE;
  304. BOOL bDelta = FALSE;
  305. BOOL bReverse = FALSE;
  306. BOOL bClear = FALSE;
  307. if (szCmdLine)
  308. {
  309. while (*szCmdLine)
  310. {
  311. while(*szCmdLine && isspace((UCHAR)*szCmdLine)){
  312. szCmdLine++;
  313. };
  314. if (*szCmdLine == '-' || *szCmdLine == '/')
  315. {
  316. szCmdLine++;
  317. if (toupper((UCHAR)*szCmdLine) == 'T'){
  318. bThrottle = TRUE;
  319. } else if (toupper((UCHAR)*szCmdLine) == 'R') {
  320. bReverse = TRUE;
  321. } else if (toupper((UCHAR)*szCmdLine) == 'F') {
  322. bFull = TRUE;
  323. } else if (toupper((UCHAR)*szCmdLine) == 'D') {
  324. bDelta = TRUE;
  325. } else if (toupper((UCHAR)*szCmdLine) == 'C') {
  326. bClear = TRUE;
  327. }
  328. }
  329. // move to the next white space
  330. while(*szCmdLine && !isspace(*szCmdLine)){
  331. szCmdLine++;
  332. }
  333. }
  334. }
  335. if (bClear) // ClearADAP and/or ReverseAdap
  336. {
  337. DoClearADAP();
  338. if (bReverse)
  339. DoReverseAdapterMaintenance( bThrottle );
  340. }
  341. else
  342. {
  343. if (!bFull && !bDelta && !bReverse)
  344. {
  345. // no options, use Delta NO-THROTTLE
  346. DoResyncPerf(TRUE,FALSE);
  347. }
  348. else
  349. {
  350. if (bFull) {
  351. DoResyncPerf(FALSE,bThrottle);
  352. }
  353. if (bDelta && !bFull) {
  354. DoResyncPerf(TRUE,bThrottle);
  355. }
  356. if (bReverse)
  357. DoReverseAdapterMaintenance( bThrottle );
  358. }
  359. }
  360. ReleaseMutex( hMutex );
  361. }break;
  362. }
  363. long l;
  364. ReleaseSemaphore(hSemaphore, 1, &l);
  365. }
  366. catch(...)
  367. {
  368. // <Gasp> We have been betrayed... try to write something to the error log
  369. // =======================================================================
  370. CriticalFailADAPTrace( "An unhandled exception has been thrown in the main thread." );
  371. }
  372. return 0;
  373. }
  374. ////////////////////////////////////////////////////////////////////////////////
  375. //
  376. // CPerfLibList
  377. //
  378. ////////////////////////////////////////////////////////////////////////////////
  379. HRESULT CPerfLibList::AddPerfLib( WCHAR* wszPerfLib )
  380. {
  381. HRESULT hr = WBEM_S_NO_ERROR;
  382. CInCritSec ics( &m_csPerfLibList );
  383. try
  384. {
  385. // Compute the size of the new buffer
  386. // ==================================
  387. DWORD dwListSize = 0;
  388. if ( NULL != m_wszPerfLibList )
  389. {
  390. dwListSize += wcslen( m_wszPerfLibList );
  391. dwListSize += wcslen( ADAP_EVENT_MESSAGE_DELIM );
  392. }
  393. if ( NULL != wszPerfLib )
  394. {
  395. dwListSize += wcslen( wszPerfLib );
  396. }
  397. // Create the new buffer, and initialize the content
  398. // =================================================
  399. size_t cchSizeTmp = dwListSize + 1;
  400. WCHAR* wszNew = new WCHAR[cchSizeTmp];
  401. if (NULL == wszNew) return WBEM_E_OUT_OF_MEMORY;
  402. // Copy the old buffer if required
  403. // ===============================
  404. if ( NULL != m_wszPerfLibList )
  405. {
  406. StringCchPrintfW( wszNew, cchSizeTmp, L"%s%s%s", m_wszPerfLibList, ADAP_EVENT_MESSAGE_DELIM, wszPerfLib );
  407. delete [] m_wszPerfLibList;
  408. }
  409. else
  410. {
  411. StringCchCopyW(wszNew, cchSizeTmp, wszPerfLib);
  412. }
  413. // And assign it to the static member
  414. // ==================================
  415. m_wszPerfLibList = wszNew;
  416. }
  417. catch(...)
  418. {
  419. hr = WBEM_E_FAILED;
  420. }
  421. return hr;
  422. }
  423. HRESULT CPerfLibList::HandleFailure()
  424. {
  425. HRESULT hr = WBEM_S_NO_ERROR;
  426. CInCritSec ics( &m_csPerfLibList );
  427. try
  428. {
  429. char szMessage[ADAP_EVENT_MESSAGE_LENGTH];
  430. DWORD dwMessageLen = strlen( ADAP_EVENT_MESSAGE_PREFIX );
  431. if ( NULL != m_wszPerfLibList )
  432. {
  433. dwMessageLen += wcslen( m_wszPerfLibList );
  434. }
  435. StringCchPrintfA(szMessage,ADAP_EVENT_MESSAGE_LENGTH,
  436. "%s%S\n", ADAP_EVENT_MESSAGE_PREFIX, (NULL != m_wszPerfLibList) ? m_wszPerfLibList : L"<NULL>" );
  437. CriticalFailADAPTrace( szMessage );
  438. }
  439. catch(...)
  440. {
  441. hr = WBEM_E_FAILED;
  442. }
  443. return hr;
  444. }
  445. ////////////////////////////////////////////////////////////////////////////////
  446. //
  447. // Static Members
  448. //
  449. ////////////////////////////////////////////////////////////////////////////////
  450. LONG CAdapRegPerf::AdapUnhandledExceptionFilter( LPEXCEPTION_POINTERS lpexpExceptionInfo )
  451. {
  452. g_PerfLibList.HandleFailure();
  453. return EXCEPTION_CONTINUE_SEARCH;
  454. }
  455. ////////////////////////////////////////////////////////////////////////////////
  456. //
  457. // CAdapRegPerf
  458. //
  459. ////////////////////////////////////////////////////////////////////////////////
  460. CAdapRegPerf::CAdapRegPerf(BOOL bFull)
  461. : m_pLocaleCache( NULL ),
  462. m_fQuit( FALSE ),
  463. m_dwPID( 0 ),
  464. m_pADAPStatus( NULL ),
  465. m_pRootDefault( NULL ),
  466. m_hRegChangeEvent( NULL ),
  467. m_hPerflibKey( NULL ),
  468. m_pKnownSvcs(NULL),
  469. m_bFull(bFull)
  470. {
  471. for ( DWORD dwType = 0; dwType < WMI_ADAP_NUM_TYPES; dwType++ )
  472. m_apMasterClassList[dwType] = NULL;
  473. }
  474. CAdapRegPerf::~CAdapRegPerf()
  475. {
  476. // Status: COMPLETE
  477. // ================
  478. SetADAPStatus( eADAPStatusFinished);
  479. //
  480. // Add TimeStamp to registry if FULL
  481. //
  482. if (m_bFull)
  483. {
  484. FILETIME FileTime;
  485. GetSystemTimeAsFileTime(&FileTime);
  486. LONG lRet;
  487. HKEY hKey;
  488. lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  489. L"Software\\Microsoft\\WBEM\\CIMOM",
  490. NULL,
  491. KEY_WRITE,
  492. &hKey);
  493. if (ERROR_SUCCESS == lRet)
  494. {
  495. RegSetValueEx(hKey,
  496. ADAP_TIMESTAMP_FULL,
  497. NULL,
  498. REG_BINARY,
  499. (BYTE*)&FileTime,
  500. sizeof(FILETIME));
  501. RegCloseKey(hKey);
  502. }
  503. }
  504. if (m_pKnownSvcs)
  505. {
  506. m_pKnownSvcs->Save();
  507. m_pKnownSvcs->Release();
  508. }
  509. // Cleanup
  510. // =======
  511. for ( DWORD dwType = 0; dwType < WMI_ADAP_NUM_TYPES; dwType++ )
  512. {
  513. if ( NULL != m_apMasterClassList[dwType] )
  514. {
  515. m_apMasterClassList[dwType]->Release();
  516. }
  517. }
  518. if ( NULL != m_pLocaleCache )
  519. {
  520. m_pLocaleCache->Release();
  521. }
  522. if ( NULL != m_pRootDefault )
  523. {
  524. m_pRootDefault->Release();
  525. }
  526. if ( NULL != m_pADAPStatus )
  527. {
  528. m_pADAPStatus->Release();
  529. }
  530. if ( NULL != m_hPerflibKey )
  531. {
  532. RegCloseKey( m_hPerflibKey );
  533. }
  534. if ( NULL != m_hRegChangeEvent )
  535. {
  536. CloseHandle( m_hRegChangeEvent );
  537. }
  538. SetEvent( m_hTerminationEvent );
  539. }
  540. HRESULT CAdapRegPerf::Initialize(BOOL bDelta, BOOL bThrottle)
  541. ///////////////////////////////////////////////////////////////////////////////
  542. //
  543. // Initialize is responsible for setting up the dredging environment. The
  544. // unhandled exception filter is set to handle any exceptions throw and not
  545. // handled by perforance libraries. The termination event is a signal used
  546. // to identify when the process is being abnormally terminated. The
  547. // GoGershwin thread is suitably named since it is something to watch over
  548. // over the main process. The locale cache is a cache of all locales
  549. // available in the performance domain (enumeration of the names' database
  550. // subkeys). The master class lists for both the cooked and the raw classes
  551. // represent the state of the performance objects in WMI.
  552. //
  553. // Parameters:
  554. // none
  555. //
  556. ///////////////////////////////////////////////////////////////////////////////
  557. {
  558. HRESULT hr = WBEM_NO_ERROR;
  559. // Initialize the root\default pointer. This will be used to track our status
  560. // ==========================================================================
  561. GetADAPStatusObject();
  562. // Set the filter for handling unhandled exceptions thrown in threads generated by the perflibs
  563. // ============================================================================================
  564. SetUnhandledExceptionFilter( CAdapRegPerf::AdapUnhandledExceptionFilter );
  565. // ADAP termination event
  566. // ======================
  567. m_hTerminationEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
  568. if ( NULL == m_hTerminationEvent )
  569. {
  570. hr = WBEM_E_FAILED;
  571. }
  572. // Open the registry key to be monitored
  573. // =====================================
  574. if ( SUCCEEDED( hr ) )
  575. {
  576. if ( ERROR_SUCCESS != RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Perflib"), 0, KEY_NOTIFY, &m_hPerflibKey ) )
  577. {
  578. hr = WBEM_E_FAILED;
  579. }
  580. }
  581. // Create the registry change event
  582. // ================================
  583. if ( SUCCEEDED( hr ) )
  584. {
  585. m_hRegChangeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  586. if ( NULL == m_hRegChangeEvent )
  587. {
  588. hr = WBEM_E_FAILED;
  589. }
  590. }
  591. // Create the names' database change notification
  592. // ==============================================
  593. // Note that we are only looking for subkeys being added or deleted. We do
  594. // not want to monitor the registry values since the status and signature
  595. // values may be changing throughout the course of the dredge, and we do
  596. // not want to cause a re-cache unless a performance library is added
  597. // (i.e. a performance subkey is added
  598. if ( SUCCEEDED( hr ) )
  599. {
  600. if ( ERROR_SUCCESS != RegNotifyChangeKeyValue( m_hPerflibKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, m_hRegChangeEvent, TRUE ) )
  601. {
  602. hr = WBEM_E_FAILED;
  603. }
  604. }
  605. // Get the WinMgmt Service PID
  606. // ===========================
  607. if ( SUCCEEDED( hr ) )
  608. {
  609. m_dwPID = GetExecPid();
  610. }
  611. // Create the "Someone to watch over me" thread
  612. // ============================================
  613. if ( SUCCEEDED( hr ) )
  614. {
  615. UINT nThreadID = 0;
  616. m_hSyncThread = ( HANDLE ) _beginthreadex( NULL, 0, CAdapRegPerf::GoGershwin, (void*) this, 0, &nThreadID );
  617. DEBUGTRACE ( ( LOG_WMIADAP, "The Monitor thread ID is 0x%x\n", nThreadID ) );
  618. if ( (HANDLE)-1 == m_hSyncThread )
  619. {
  620. hr = WBEM_E_FAILED;
  621. }
  622. }
  623. // Set up the locale cache
  624. // =======================
  625. if ( SUCCEEDED( hr ) )
  626. {
  627. m_pLocaleCache = new CLocaleCache( );
  628. if ( NULL == m_pLocaleCache )
  629. {
  630. hr = WBEM_E_OUT_OF_MEMORY;
  631. }
  632. else
  633. {
  634. hr = m_pLocaleCache->Initialize();
  635. }
  636. }
  637. //
  638. //
  639. m_pKnownSvcs = new CKnownSvcs(KNOWN_SERVICES);
  640. if (m_pKnownSvcs)
  641. m_pKnownSvcs->Load();
  642. // Set up the master class lists for the raw classes
  643. // =================================================
  644. if ( SUCCEEDED( hr ) )
  645. {
  646. m_apMasterClassList[WMI_ADAP_RAW_CLASS] = new CMasterClassList( m_pLocaleCache, m_pKnownSvcs );
  647. if ( NULL != m_apMasterClassList[WMI_ADAP_RAW_CLASS] )
  648. {
  649. hr = m_apMasterClassList[WMI_ADAP_RAW_CLASS]->BuildList( ADAP_PERF_RAW_BASE_CLASS, bDelta, bThrottle );
  650. }
  651. else
  652. {
  653. hr = WBEM_E_OUT_OF_MEMORY;
  654. }
  655. }
  656. // Set up the master class lists for the cooked classes
  657. // ====================================================
  658. if ( SUCCEEDED( hr ) )
  659. {
  660. m_apMasterClassList[WMI_ADAP_COOKED_CLASS] = new CMasterClassList( m_pLocaleCache, m_pKnownSvcs );
  661. if ( NULL != m_apMasterClassList[WMI_ADAP_COOKED_CLASS] )
  662. {
  663. m_apMasterClassList[WMI_ADAP_COOKED_CLASS]->BuildList( ADAP_PERF_COOKED_BASE_CLASS, bDelta, bThrottle );
  664. }
  665. else
  666. {
  667. hr = WBEM_E_OUT_OF_MEMORY;
  668. }
  669. }
  670. #ifdef _DUMP_LIST
  671. m_apMasterClassList[WMI_ADAP_RAW_CLASS]->Dump();
  672. m_apMasterClassList[WMI_ADAP_COOKED_CLASS]->Dump();
  673. #endif
  674. return hr;
  675. }
  676. HRESULT CAdapRegPerf::Dredge( BOOL bDelta, BOOL bThrottle )
  677. ///////////////////////////////////////////////////////////////////////////////
  678. //
  679. // This is the entry point method which dredges the registry for performance
  680. // counters and registers the classes in WMI. This method enumerates all of
  681. // the service keys looking for 'Performance' subkeys which indicate
  682. // performance libraries. If a library is discovered, then it is sent to
  683. // the ProcessLibrary method for, you guessed it, processing.
  684. //
  685. // Parameters:
  686. // none
  687. //
  688. ///////////////////////////////////////////////////////////////////////////////
  689. {
  690. HRESULT hr = WBEM_S_NO_ERROR;
  691. WString wstrServiceKey,
  692. wstrPerformanceKey;
  693. if ( SUCCEEDED( hr ) )
  694. {
  695. // Status: PROCESSING
  696. // ==================
  697. SetADAPStatus( eADAPStatusProcessLibs);
  698. // Open the services key
  699. // =====================
  700. long lError = Open( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services" );
  701. if ( CNTRegistry::no_error == lError )
  702. {
  703. // Iterate through the services list
  704. // =================================
  705. DWORD dwIndex = 0;
  706. DWORD dwBuffSize = 0;
  707. wmilib::auto_buffer<WCHAR> pwcsServiceName;
  708. while ( ( CNTRegistry::no_error == lError ) && ( !m_fQuit ) )
  709. {
  710. // Reset the processing status
  711. // ===========================
  712. hr = WBEM_NO_ERROR;
  713. if ( WAIT_OBJECT_0 == WaitForSingleObject( m_hRegChangeEvent, 0 ) )
  714. {
  715. m_pLocaleCache->Reset();
  716. dwIndex = 0;
  717. // Reset the event and reset the change notification
  718. ResetEvent( m_hRegChangeEvent );
  719. RegNotifyChangeKeyValue( m_hPerflibKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, m_hRegChangeEvent, TRUE );
  720. }
  721. // For each service name, we will check for a performance
  722. // key and if it exists, we will process the library
  723. // ======================================================
  724. lError = Enum( dwIndex, pwcsServiceName , dwBuffSize );
  725. if (bThrottle)
  726. {
  727. HRESULT hrThr = Throttle(THROTTLE_USER|THROTTLE_IO,
  728. ADAP_IDLE_USER,
  729. ADAP_IDLE_IO,
  730. ADAP_LOOP_SLEEP,
  731. ADAP_MAX_WAIT);
  732. if (THROTTLE_FORCE_EXIT == hrThr)
  733. {
  734. //OutputDebugStringA("(ADAP) Unthrottle command received\n");
  735. bThrottle = FALSE;
  736. UNICODE_STRING BaseUnicodeCommandLine = NtCurrentPeb()->ProcessParameters->CommandLine;
  737. WCHAR * pT = wcschr(BaseUnicodeCommandLine.Buffer,L't');
  738. if (0 == pT)
  739. pT = wcschr(BaseUnicodeCommandLine.Buffer,L'T');
  740. if (pT)
  741. {
  742. *pT = L' ';
  743. pT--;
  744. *pT = L' ';
  745. }
  746. }
  747. }
  748. if ( CNTRegistry::no_error == lError )
  749. {
  750. try
  751. {
  752. // Create the perfomance key path
  753. // ==============================
  754. wstrServiceKey = L"SYSTEM\\CurrentControlSet\\Services\\";
  755. wstrServiceKey += pwcsServiceName.get();
  756. wstrPerformanceKey = wstrServiceKey;
  757. wstrPerformanceKey += L"\\Performance";
  758. }
  759. catch( ... )
  760. {
  761. hr = WBEM_E_OUT_OF_MEMORY;
  762. }
  763. if ( SUCCEEDED( hr ) )
  764. {
  765. CNTRegistry reg;
  766. // Atempt to open the performance registry key for the service
  767. // ===========================================================
  768. long lPerfError = reg.Open( HKEY_LOCAL_MACHINE, wstrPerformanceKey );
  769. if ( CNTRegistry::no_error == lPerfError )
  770. {
  771. // If we can open it, then we have found a perflib! Process it
  772. // unless it is the reverse provider perflib
  773. // =============================================================
  774. if ( 0 != wbem_wcsicmp( pwcsServiceName.get(), WMI_ADAP_REVERSE_PERFLIB ) )
  775. {
  776. hr = ProcessLibrary( pwcsServiceName.get(), bDelta );
  777. }
  778. }
  779. else if ( CNTRegistry::access_denied == lPerfError )
  780. {
  781. ServiceRec * pSvcRec = NULL;
  782. if (0 == m_pKnownSvcs->Get(pwcsServiceName.get(),&pSvcRec))
  783. {
  784. if (!pSvcRec->IsELCalled())
  785. {
  786. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  787. WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
  788. (LPCWSTR)wstrPerformanceKey, L"Access Denied" );
  789. pSvcRec->SetELCalled();
  790. }
  791. }
  792. }
  793. else
  794. {
  795. // Otherwise, it is not a perflib service
  796. // ======================================
  797. }
  798. }
  799. }
  800. else if ( CNTRegistry::no_more_items != lError )
  801. {
  802. if ( CNTRegistry::out_of_memory == lError )
  803. {
  804. hr = WBEM_E_OUT_OF_MEMORY;
  805. }
  806. else
  807. {
  808. hr = WBEM_E_FAILED;
  809. }
  810. }
  811. dwIndex++;
  812. }
  813. }
  814. else if ( CNTRegistry::access_denied == lError )
  815. {
  816. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE, L"SYSTEM\\CurrentControlSet\\Services\\", L"Access Denied" );
  817. hr = WBEM_E_FAILED;
  818. }
  819. else
  820. {
  821. hr = WBEM_E_FAILED;
  822. }
  823. // Now that we have a master class list that contains updated
  824. // data from all of the perflibs, commit any changes to WMI
  825. // ==========================================================
  826. if ( SUCCEEDED ( hr ) && ( !m_fQuit ) )
  827. {
  828. // Status: COMMIT
  829. // ==============
  830. SetADAPStatus( eADAPStatusCommit );
  831. for ( DWORD dwType = 0; dwType < WMI_ADAP_NUM_TYPES; dwType++ )
  832. {
  833. m_apMasterClassList[dwType]->Commit(bThrottle);
  834. }
  835. }
  836. }
  837. if ( SUCCEEDED( hr ) )
  838. {
  839. DEBUGTRACE( ( LOG_WMIADAP, "CAdapRegPerf::Dredge() for %S succeeded.\n", (WCHAR *)wstrServiceKey ) );
  840. }
  841. else
  842. {
  843. ERRORTRACE( ( LOG_WMIADAP, "CAdapRegPerf::Dredge() failed: %X.\n", hr ) );
  844. }
  845. return hr;
  846. }
  847. HRESULT CAdapRegPerf::Clean()
  848. ////////////////////////////////////////////////////////////////////////////////
  849. //
  850. // This method enumerates all of the keys from the
  851. // HLM\System\CurrentControlSet\Services and searches for a performance subkey.
  852. // If a performance subkey is discovered, then any information that was placed
  853. // in the key by ADAP is deleted.
  854. //
  855. // Parameters:
  856. // none
  857. //
  858. ////////////////////////////////////////////////////////////////////////////////
  859. {
  860. HRESULT hr = WBEM_S_NO_ERROR;
  861. WString wstrServiceKey, // The path to the service key
  862. wstrPerformanceKey; // The path to the performance subkey
  863. CNTRegistry regOuter; // The registry object for the services enumeration
  864. // Open the services key
  865. // =====================
  866. long lError = regOuter.Open( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services" );
  867. if ( CNTRegistry::no_error == lError )
  868. {
  869. // Iterate through the services list
  870. // =================================
  871. DWORD dwIndex = 0;
  872. DWORD dwBuffSize = 0;
  873. wmilib::auto_buffer<WCHAR> pwcsServiceName;
  874. while ( CNTRegistry::no_error == lError )
  875. {
  876. // Reset the processing status
  877. // ===========================
  878. hr = WBEM_NO_ERROR;
  879. // For each service name, we will check for a performance
  880. // key and if it exists, we will process the library
  881. // ======================================================
  882. lError = regOuter.Enum( dwIndex, pwcsServiceName , dwBuffSize );
  883. if ( CNTRegistry::no_error == lError )
  884. {
  885. try
  886. {
  887. // Create the perfomance key path
  888. // ==============================
  889. wstrServiceKey = L"SYSTEM\\CurrentControlSet\\Services\\";
  890. wstrServiceKey += pwcsServiceName.get();
  891. wstrPerformanceKey = wstrServiceKey;
  892. wstrPerformanceKey += L"\\Performance";
  893. }
  894. catch( ... )
  895. {
  896. hr = WBEM_E_OUT_OF_MEMORY;
  897. }
  898. if ( SUCCEEDED( hr ) )
  899. {
  900. CNTRegistry regInner; // The registry object for the performance subkey
  901. // Atempt to open the performance registry key for the service
  902. // ===========================================================
  903. long lPerfError = regInner.Open( HKEY_LOCAL_MACHINE, wstrPerformanceKey );
  904. if ( CNTRegistry::no_error == lPerfError )
  905. {
  906. // If we can open it, then we have found a perflib! Clean it!
  907. // =============================================================
  908. regInner.DeleteValue( ADAP_PERFLIB_STATUS_KEY );
  909. regInner.DeleteValue( ADAP_PERFLIB_SIGNATURE );
  910. regInner.DeleteValue( ADAP_PERFLIB_SIZE );
  911. regInner.DeleteValue( ADAP_PERFLIB_TIME );
  912. }
  913. else if ( CNTRegistry::access_denied == lPerfError )
  914. {
  915. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
  916. WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
  917. (LPCWSTR)wstrPerformanceKey, L"Access Denied" );
  918. }
  919. else
  920. {
  921. // Otherwise, it is not a perflib service
  922. // ======================================
  923. }
  924. }
  925. }
  926. else if ( CNTRegistry::no_more_items != lError )
  927. {
  928. if ( CNTRegistry::out_of_memory == lError )
  929. {
  930. hr = WBEM_E_OUT_OF_MEMORY;
  931. }
  932. else
  933. {
  934. hr = WBEM_E_FAILED;
  935. }
  936. }
  937. dwIndex++;
  938. }
  939. }
  940. else if ( CNTRegistry::access_denied == lError )
  941. {
  942. CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE, L"SYSTEM\\CurrentControlSet\\Services\\", L"Access Denied" );
  943. hr = WBEM_E_FAILED;
  944. }
  945. else
  946. {
  947. hr = WBEM_E_FAILED;
  948. }
  949. if ( SUCCEEDED( hr ) )
  950. {
  951. DEBUGTRACE( ( LOG_WMIADAP, "CAdapRegPerf::Clean() succeeded.\n" ) );
  952. }
  953. else
  954. {
  955. ERRORTRACE( ( LOG_WMIADAP, "CAdapRegPerf::Clean() failed: %X.\n", hr ) );
  956. }
  957. return hr;
  958. }
  959. HRESULT CAdapRegPerf::ProcessLibrary( WCHAR* pwcsServiceName, BOOL bDelta )
  960. ///////////////////////////////////////////////////////////////////////////////
  961. //
  962. // Once a performance library has been discovered, then it's schema must be
  963. // retrieved and the performance library's class list compared to what is
  964. // already in the WMI repository. The comparison is achieved in the "Merge"
  965. // method of the master class list which extracts any classes from the perf
  966. // lib's class list that are not already in the master class list. The
  967. // comparison occurs for both the raw and the cooked classes.
  968. //
  969. // Parameters:
  970. // pwcsServiceName - The name of the service to be processed
  971. //
  972. ///////////////////////////////////////////////////////////////////////////////
  973. {
  974. HRESULT hr = WBEM_NO_ERROR;
  975. try
  976. {
  977. // Add the name of the performance library to the perflib list
  978. // ===========================================================
  979. // The list is used for book keeping purposses to track processing
  980. // in the event of a perflib failure
  981. g_PerfLibList.AddPerfLib( pwcsServiceName );
  982. // Construct and initialize the schema for the perflib
  983. // ===================================================
  984. DWORD LoadStatus = EX_STATUS_UNLOADED;
  985. CPerfLibSchema Schema( pwcsServiceName, m_pLocaleCache );
  986. hr = Schema.Initialize( bDelta, &LoadStatus);
  987. DEBUGTRACE(( LOG_WMIADAP,"CPerfLibSchema::Initialize for %S hr %08x\n",pwcsServiceName,hr));
  988. if ( !bDelta || ( bDelta && ( hr != WBEM_S_ALREADY_EXISTS ) ) )
  989. {
  990. // Update raw and cooked classes
  991. // =============================
  992. for ( DWORD dwType = 0; ( dwType < WMI_ADAP_NUM_TYPES ) && SUCCEEDED( hr ); dwType++ )
  993. {
  994. // Get the class list for classes from the perflib's schema
  995. // ========================================================
  996. CClassList* pClassList = NULL;
  997. hr = Schema.GetClassList( dwType, &pClassList );
  998. CAdapReleaseMe rmClassList( pClassList );
  999. DEBUGTRACE(( LOG_WMIADAP,"GetClassList for %S hr %08x\n",pwcsServiceName,hr));
  1000. if ( SUCCEEDED( hr ) )
  1001. {
  1002. // Merge the raw classes obtained from the perflib into the master class list
  1003. // ==========================================================================
  1004. hr = m_apMasterClassList[dwType]->Merge( pClassList, bDelta );
  1005. DEBUGTRACE(( LOG_WMIADAP,"m_apMasterClassList[%d]->Merge for %S hr %08x\n",dwType,pwcsServiceName,hr));
  1006. }
  1007. //if (bDelta && FAILED(hr)){
  1008. // // the class was not in the repository if we are here
  1009. // LoadStatus = EX_STATUS_UNLOADED;
  1010. //}
  1011. }
  1012. };
  1013. if (FAILED(hr) && (LoadStatus != EX_STATUS_LOADABLE))
  1014. {
  1015. for ( DWORD dwType = 0; ( dwType < WMI_ADAP_NUM_TYPES ) ; dwType++ )
  1016. {
  1017. DEBUGTRACE((LOG_WMIADAP,"ProcessLibrary ForceStatus for %S hr = %08x\n",pwcsServiceName,hr));
  1018. DWORD NewStatus = ADAP_OBJECT_IS_DELETED;
  1019. if (LoadStatus == EX_STATUS_UNLOADED)
  1020. {
  1021. NewStatus |= ADAP_OBJECT_IS_TO_BE_CLEARED;
  1022. }
  1023. m_apMasterClassList[dwType]->ForceStatus(pwcsServiceName,TRUE,NewStatus);
  1024. }
  1025. }
  1026. }
  1027. catch(...)
  1028. {
  1029. hr = WBEM_E_OUT_OF_MEMORY;
  1030. }
  1031. return hr;
  1032. }
  1033. unsigned int CAdapRegPerf::GoGershwin( void* pParam )
  1034. ///////////////////////////////////////////////////////////////////////////////
  1035. //
  1036. // The monitoring thread entry point
  1037. //
  1038. ///////////////////////////////////////////////////////////////////////////////
  1039. {
  1040. HRESULT hr = WBEM_S_NO_ERROR;
  1041. try
  1042. {
  1043. CAdapRegPerf* pThis = (CAdapRegPerf*)pParam;
  1044. HANDLE ahHandles[2];
  1045. // If we don't have an initialized PID, then find one from WMI
  1046. // ===========================================================
  1047. if ( 0 == pThis->m_dwPID )
  1048. {
  1049. pThis->m_dwPID = GetExecPid();
  1050. }
  1051. // Get the process handle and wait for a signal
  1052. // ============================================
  1053. if ( SUCCEEDED( hr ) && ( 0 != pThis->m_dwPID ) )
  1054. {
  1055. ahHandles[0] = OpenProcess( SYNCHRONIZE, FALSE, pThis->m_dwPID );
  1056. CCloseMe cmProcess( ahHandles[0] );
  1057. ahHandles[1] = pThis->m_hTerminationEvent;
  1058. DWORD dwRet = WaitForMultipleObjects( 2, ahHandles, FALSE, INFINITE );
  1059. switch ( dwRet )
  1060. {
  1061. case WAIT_FAILED: // Something is wierd
  1062. case WAIT_OBJECT_0: // The service process
  1063. {
  1064. pThis->m_fQuit = TRUE; // Set the termination flag
  1065. } break;
  1066. case ( WAIT_OBJECT_0 + 1 ): // The completion event
  1067. {
  1068. // continue
  1069. }break;
  1070. }
  1071. }
  1072. }
  1073. catch(...)
  1074. {
  1075. // <Gasp> We have been betrayed... try to write something to the error log
  1076. // =======================================================================
  1077. CriticalFailADAPTrace( "An unhandled exception has been thrown in the WMI monitoring thread." );
  1078. }
  1079. return 0;
  1080. }
  1081. HRESULT CAdapRegPerf::GetADAPStatusObject( void )
  1082. {
  1083. IWbemLocator* pLocator = NULL;
  1084. HRESULT hr = CoCreateInstance( CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator,
  1085. (void**) &pLocator );
  1086. CReleaseMe rm( pLocator );
  1087. if ( SUCCEEDED( hr ) )
  1088. {
  1089. BSTR bstrNameSpace = SysAllocString( L"root\\default" );
  1090. BSTR bstrInstancePath = SysAllocString( L"__ADAPStatus=@" );
  1091. CSysFreeMe sfm1( bstrNameSpace );
  1092. CSysFreeMe sfm2( bstrInstancePath );
  1093. if ( NULL != bstrNameSpace && NULL != bstrInstancePath )
  1094. {
  1095. // Connect to Root\default and get hold of the status object
  1096. hr = pLocator->ConnectServer( bstrNameSpace, // NameSpace Name
  1097. NULL, // UserName
  1098. NULL, // Password
  1099. NULL, // Locale
  1100. 0L, // Security Flags
  1101. NULL, // Authority
  1102. NULL, // Wbem Context
  1103. &m_pRootDefault // Namespace
  1104. );
  1105. if ( SUCCEEDED( hr ) )
  1106. {
  1107. // Set Interface security
  1108. hr = WbemSetProxyBlanket( m_pRootDefault, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
  1109. RPC_C_AUTHN_LEVEL_PKT,RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
  1110. if ( SUCCEEDED( hr ) )
  1111. {
  1112. hr = m_pRootDefault->GetObject( bstrInstancePath, 0L, NULL, &m_pADAPStatus, NULL );
  1113. if ( SUCCEEDED( hr ) )
  1114. {
  1115. SetADAPStatus( eADAPStatusRunning );
  1116. }
  1117. }
  1118. }
  1119. }
  1120. else
  1121. {
  1122. hr = WBEM_E_OUT_OF_MEMORY;
  1123. }
  1124. } // IF got locator
  1125. return hr;
  1126. }
  1127. // Gets the time in the popular DMTF format
  1128. void CAdapRegPerf::GetTime( LPWSTR Buff, size_t cchBuffSize )
  1129. {
  1130. SYSTEMTIME st;
  1131. int Bias=0;
  1132. char cOffsetSign = '+';
  1133. GetLocalTime( &st );
  1134. TIME_ZONE_INFORMATION ZoneInformation;
  1135. DWORD dwRet = GetTimeZoneInformation(&ZoneInformation);
  1136. if(dwRet != TIME_ZONE_ID_UNKNOWN)
  1137. Bias = -ZoneInformation.Bias;
  1138. if(Bias < 0)
  1139. {
  1140. cOffsetSign = '-';
  1141. Bias = -Bias;
  1142. }
  1143. StringCchPrintfW(Buff,cchBuffSize, L"%4d%02d%02d%02d%02d%02d.%06d%c%03d",
  1144. st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute,
  1145. st.wSecond, st.wMilliseconds*1000, cOffsetSign, Bias);
  1146. }
  1147. // Sets the status back in WMI
  1148. void CAdapRegPerf::SetADAPStatus( eADAPStatus status )
  1149. {
  1150. HRESULT hr = E_FAIL;
  1151. // Make sure we've got both our pointers
  1152. if ( NULL != m_pRootDefault && NULL != m_pADAPStatus )
  1153. {
  1154. // We only need 25 characters for this
  1155. WCHAR wcsTime[32];
  1156. _variant_t var;
  1157. // legacy fastprox behavior
  1158. WCHAR pNum[16];
  1159. StringCchPrintfW(pNum,16,L"%u",status);
  1160. var = pNum;
  1161. hr = m_pADAPStatus->Put( L"Status", 0L, &var, 0 );//CIM_UINT32 );
  1162. if ( SUCCEEDED( hr ) )
  1163. {
  1164. // Set the time property if necessary
  1165. if ( status == eADAPStatusRunning || status == eADAPStatusFinished )
  1166. {
  1167. GetTime( wcsTime, 32 );
  1168. // This can fail
  1169. try
  1170. {
  1171. var = wcsTime;
  1172. }
  1173. catch(...)
  1174. {
  1175. hr = WBEM_E_OUT_OF_MEMORY;
  1176. }
  1177. if ( SUCCEEDED( hr ) )
  1178. {
  1179. hr = ( status == eADAPStatusRunning ?
  1180. m_pADAPStatus->Put( L"LastStartTime", 0L, &var, CIM_DATETIME ) :
  1181. m_pADAPStatus->Put( L"LastStopTime", 0L, &var, CIM_DATETIME ) );
  1182. }
  1183. }
  1184. if ( SUCCEEDED( hr ) )
  1185. {
  1186. hr = m_pRootDefault->PutInstance( m_pADAPStatus, 0L, NULL, NULL );
  1187. }
  1188. } // Set the Status property
  1189. } // Make sure we've got both pointers
  1190. }