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.

628 lines
21 KiB

  1. /*++
  2. Copyright (c) 1995-1999 Microsoft Corporation
  3. Module Name:
  4. dllinit.c
  5. Abstract:
  6. This module contians the DLL attach/detach event entry point for
  7. the pdh.dll
  8. Author:
  9. Bob Watson (a-robw) Jul 95
  10. Revision History:
  11. --*/
  12. #include <windows.h>
  13. #include <wmistr.h>
  14. #include <objbase.h>
  15. #include <initguid.h>
  16. #include <evntrace.h>
  17. #include <wmiguid.h>
  18. #include <wmium.h>
  19. #include "strsafe.h"
  20. #include "pdh.h"
  21. #include "pdhp.h"
  22. #include "pdhitype.h"
  23. #define _INIT_PDH_DEBUGTRACE
  24. #include "pdhidef.h"
  25. #include "pdhmsg.h"
  26. #include "strings.h"
  27. #define PDH_DEFAULT_COLLECT_TIMEOUT 300 // 5 minutes
  28. HANDLE ThisDLLHandle = NULL;
  29. WCHAR szStaticLocalMachineName[MAX_COMPUTERNAME_LENGTH + 3] = {0};
  30. HANDLE hPdhDataMutex = NULL;
  31. HANDLE hPdhContextMutex = NULL;
  32. HANDLE hPdhHeap = NULL;
  33. HANDLE hEventLog = NULL;
  34. LONGLONG llRemoteRetryTime = RETRY_TIME_INTERVAL;
  35. BOOL bEnableRemotePdhAccess = TRUE;
  36. DWORD dwPdhiLocalDefaultDataSource = DATA_SOURCE_REGISTRY;
  37. LONG dwCurrentRealTimeDataSource = 0;
  38. ULONGLONG ulPdhCollectTimeout = PDH_DEFAULT_COLLECT_TIMEOUT;
  39. BOOL bProcessIsDetaching = FALSE;
  40. LPWSTR
  41. GetStringResource(
  42. DWORD dwResId
  43. )
  44. {
  45. LPWSTR szReturnString = NULL;
  46. LPWSTR szTmpString = NULL;
  47. DWORD dwStrLen = (2048 * sizeof(WCHAR));
  48. szReturnString = (LPWSTR) G_ALLOC(dwStrLen);
  49. if (szReturnString != NULL) {
  50. dwStrLen /= sizeof(WCHAR);
  51. dwStrLen = LoadStringW(ThisDLLHandle, (UINT) dwResId, szReturnString, dwStrLen);
  52. if (dwStrLen > 0) {
  53. // then realloc down to the size used
  54. dwStrLen ++; // to include the NULL
  55. dwStrLen *= sizeof(WCHAR);
  56. szTmpString = szReturnString;
  57. szReturnString = G_REALLOC(szTmpString, dwStrLen);
  58. if (szReturnString == NULL) {
  59. G_FREE(szTmpString);
  60. szTmpString = NULL;
  61. }
  62. }
  63. else {
  64. // free the memory since the look up failed
  65. G_FREE(szReturnString);
  66. szReturnString = NULL;
  67. }
  68. } //else allocation failed
  69. return szReturnString;
  70. }
  71. STATIC_BOOL
  72. PdhiOpenEventLog(
  73. HANDLE * phEventLogHandle
  74. )
  75. {
  76. HANDLE hReturn;
  77. BOOL bReturn = FALSE;
  78. if ((hReturn = RegisterEventSourceW(NULL, cszAppShortName)) != NULL) {
  79. * phEventLogHandle = hReturn;
  80. bReturn = TRUE;
  81. }
  82. return bReturn;
  83. }
  84. STATIC_BOOL
  85. PdhiGetRegistryDefaults()
  86. {
  87. DWORD dwStatus;
  88. DWORD dwType, dwSize, dwValue;
  89. HKEY hKeyPDH;
  90. ulPdhCollectTimeout = ((ULONGLONG) PDH_DEFAULT_COLLECT_TIMEOUT) * ((ULONGLONG) 10000000);
  91. // the local data source is not initialized so use it
  92. dwStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE, cszPdhKey, 0L, KEY_READ, & hKeyPDH);
  93. if (dwStatus == ERROR_SUCCESS) {
  94. // get the default null data source
  95. //
  96. dwValue = 0;
  97. dwType = 0;
  98. dwSize = sizeof (dwValue);
  99. dwStatus = RegQueryValueExW(hKeyPDH, cszDefaultNullDataSource, NULL, & dwType, (LPBYTE) & dwValue, & dwSize);
  100. if (dwStatus != ERROR_SUCCESS || dwType != REG_DWORD) {
  101. dwValue = DATA_SOURCE_REGISTRY;
  102. }
  103. else {
  104. // check the value for validity
  105. switch (dwValue) {
  106. case DATA_SOURCE_WBEM:
  107. case DATA_SOURCE_REGISTRY:
  108. // this is OK
  109. break;
  110. case DATA_SOURCE_LOGFILE:
  111. default:
  112. // these are not OK so insert default
  113. dwValue = DATA_SOURCE_REGISTRY;
  114. break;
  115. }
  116. }
  117. dwPdhiLocalDefaultDataSource = dwValue;
  118. //
  119. // get the retry timeout
  120. //
  121. dwValue = 0;
  122. dwType = 0;
  123. dwSize = sizeof (dwValue);
  124. dwStatus = RegQueryValueExW(hKeyPDH, cszRemoteMachineRetryTime, NULL, & dwType, (LPBYTE) & dwValue, & dwSize);
  125. if (dwStatus != ERROR_SUCCESS || dwType != REG_DWORD) {
  126. dwValue = 0;
  127. }
  128. else {
  129. // check the value for validity
  130. // must be 30 seconds or more yet no more than an hour
  131. if ((dwValue <= 30) || (dwValue > 3600)) {
  132. dwValue = 0;
  133. }
  134. }
  135. if (dwValue != 0) {
  136. // convert to 100NS units
  137. llRemoteRetryTime = dwValue * 10000000;
  138. }
  139. else {
  140. // use default
  141. llRemoteRetryTime = RETRY_TIME_INTERVAL;
  142. }
  143. // get the remote access mode
  144. //
  145. dwValue = 0;
  146. dwType = 0;
  147. dwSize = sizeof (dwValue);
  148. dwStatus = RegQueryValueExW(hKeyPDH, cszEnableRemotePdhAccess, NULL, & dwType, (LPBYTE) & dwValue, & dwSize);
  149. if (dwStatus != ERROR_SUCCESS || dwType != REG_DWORD) {
  150. dwValue = TRUE;
  151. }
  152. else {
  153. // check the value for validity
  154. if (dwValue != 0) {
  155. dwValue = TRUE;
  156. }
  157. }
  158. bEnableRemotePdhAccess = (BOOL) dwValue;
  159. // get RegQueryValueEx(HKEY_PERFORMANCE_DATA) elapsed time maximum
  160. //
  161. dwValue = 0;
  162. dwType = 0;
  163. dwSize = sizeof(dwValue);
  164. dwStatus = RegQueryValueExW(hKeyPDH, cszCollectTimeout, NULL, & dwType, (LPBYTE) & dwValue, & dwSize);
  165. if (dwStatus != ERROR_SUCCESS || dwType != REG_DWORD) {
  166. dwValue = PDH_DEFAULT_COLLECT_TIMEOUT;
  167. }
  168. else if (dwValue < 30 || dwValue > 3600) {
  169. // must between 30 seconds and 1 hour
  170. //
  171. dwValue = PDH_DEFAULT_COLLECT_TIMEOUT;
  172. }
  173. ulPdhCollectTimeout = ((ULONGLONG) dwValue) * ((ULONGLONG) 10000000);
  174. // close the registry key
  175. RegCloseKey(hKeyPDH);
  176. }
  177. return TRUE;
  178. }
  179. STATIC_BOOL
  180. PdhiCloseEventLog(
  181. HANDLE * phEventLogHandle
  182. )
  183. {
  184. BOOL bReturn = TRUE;
  185. if (* phEventLogHandle != NULL) {
  186. bReturn = DeregisterEventSource(* phEventLogHandle);
  187. * phEventLogHandle = NULL;
  188. }
  189. return bReturn;
  190. }
  191. HRESULT
  192. PdhiPlaInitMutex()
  193. {
  194. HRESULT hr = ERROR_SUCCESS;
  195. BOOL bResult = TRUE;
  196. PSECURITY_DESCRIPTOR SD = NULL;
  197. SECURITY_ATTRIBUTES sa;
  198. PSID AuthenticatedUsers = NULL;
  199. PSID BuiltInAdministrators = NULL;
  200. PSID NetworkService = NULL;
  201. PSID LoggingUsers = NULL;
  202. DWORD dwAclSize;
  203. ACL *Acl;
  204. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  205. bResult = AllocateAndInitializeSid(
  206. &NtAuthority,
  207. 2,
  208. SECURITY_BUILTIN_DOMAIN_RID,
  209. DOMAIN_ALIAS_RID_ADMINS,
  210. 0,0,0,0,0,0,
  211. &BuiltInAdministrators);
  212. if( !bResult ){goto cleanup;}
  213. bResult = AllocateAndInitializeSid(
  214. &NtAuthority,
  215. 1,
  216. SECURITY_AUTHENTICATED_USER_RID,
  217. 0,0,0,0,0,0,0,
  218. &AuthenticatedUsers);
  219. if( !bResult ){goto cleanup;}
  220. bResult = AllocateAndInitializeSid(
  221. &NtAuthority,
  222. 1,
  223. SECURITY_NETWORK_SERVICE_RID,
  224. 0,0,0,0,0,0,0,
  225. &NetworkService);
  226. if( !bResult ){goto cleanup;}
  227. bResult = AllocateAndInitializeSid(
  228. &NtAuthority,
  229. 1,
  230. DOMAIN_ALIAS_RID_LOGGING_USERS,
  231. 0,0,0,0,0,0,0,
  232. &LoggingUsers);
  233. if( !bResult ){goto cleanup;}
  234. dwAclSize = sizeof (ACL) +
  235. (4 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (ULONG))) +
  236. GetLengthSid(AuthenticatedUsers) +
  237. GetLengthSid(BuiltInAdministrators) +
  238. GetLengthSid(NetworkService) +
  239. GetLengthSid(LoggingUsers);
  240. SD = (PSECURITY_DESCRIPTOR)G_ALLOC(SECURITY_DESCRIPTOR_MIN_LENGTH + dwAclSize);
  241. if( NULL == SD ){ goto cleanup; }
  242. ZeroMemory( SD, sizeof(SD) );
  243. Acl = (ACL *)((BYTE *)SD + SECURITY_DESCRIPTOR_MIN_LENGTH);
  244. bResult = InitializeAcl( Acl, dwAclSize, ACL_REVISION);
  245. if( !bResult ){goto cleanup;}
  246. bResult = AddAccessAllowedAce(Acl, ACL_REVISION, MUTEX_ALL_ACCESS, AuthenticatedUsers );
  247. if( !bResult ){goto cleanup;}
  248. bResult = AddAccessAllowedAce(Acl, ACL_REVISION, MUTEX_ALL_ACCESS , NetworkService );
  249. if( !bResult ){goto cleanup;}
  250. bResult = AddAccessAllowedAce(Acl, ACL_REVISION, MUTEX_ALL_ACCESS , LoggingUsers );
  251. if( !bResult ){goto cleanup;}
  252. bResult = AddAccessAllowedAce(Acl, ACL_REVISION, GENERIC_ALL, BuiltInAdministrators );
  253. if( !bResult ){goto cleanup;}
  254. bResult = InitializeSecurityDescriptor(SD, SECURITY_DESCRIPTOR_REVISION);
  255. if( !bResult ){goto cleanup;}
  256. bResult = SetSecurityDescriptorDacl(SD, TRUE, Acl, FALSE);
  257. if( !bResult ){goto cleanup;}
  258. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  259. sa.lpSecurityDescriptor = SD;
  260. sa.bInheritHandle = FALSE;
  261. hPdhPlaMutex = CreateMutexW( &sa, FALSE, PDH_PLA_MUTEX );
  262. cleanup:
  263. if( hPdhPlaMutex == NULL || !bResult ){
  264. hr = GetLastError();
  265. }
  266. if( NULL != AuthenticatedUsers ){
  267. FreeSid(AuthenticatedUsers);
  268. }
  269. if( NULL != BuiltInAdministrators){
  270. FreeSid(BuiltInAdministrators);
  271. }
  272. if( NULL != NetworkService){
  273. FreeSid(NetworkService);
  274. }
  275. if( NULL != LoggingUsers){
  276. FreeSid(LoggingUsers);
  277. }
  278. G_FREE(SD);
  279. return hr;
  280. }
  281. const LPCWSTR cszTraceLevel = L"DebugTraceLevel";
  282. const LPCWSTR cszTraceFileValue = L"DebugTraceFile";
  283. const LPCWSTR cszTraceLogName = L"PDH Debug Logger";
  284. const LPCWSTR cszDefaultTraceFile = L"PdhDbg.Etl";
  285. const LPCWSTR cszDefaultTraceFileName = L"C:\\PdhDbg.Etl";
  286. TRACEHANDLE g_hTraceHandle = 0;
  287. LONG g_lDbgStarted = 0;
  288. DEFINE_GUID( /* 51af3adf-28b1-4ba5-b59a-3aeec16deb3c */
  289. PdhDebugGuid,
  290. 0x51af3adf,
  291. 0x28b1,
  292. 0x4ba5,
  293. 0xb5, 0x9a, 0x3a, 0xee, 0xc1, 0x6d, 0xeb, 0x3c
  294. );
  295. PDH_FUNCTION
  296. PdhDebugStartTrace()
  297. {
  298. DWORD status = ERROR_SUCCESS;
  299. DWORD dwType = 0;
  300. DWORD dwSize = 0;
  301. DWORD dwTraceLevel = PDH_DBG_TRACE_NONE;
  302. HKEY hKey = NULL;
  303. TRACEHANDLE TraceHandle = 0;
  304. LPWSTR szTraceFileName = NULL;
  305. CHAR Buffer[SMALL_BUFFER_SIZE];
  306. PCHAR ptr;
  307. ULONG lFileNameSize = 0;
  308. PEVENT_TRACE_PROPERTIES Properties;
  309. if (InterlockedCompareExchange(& g_lDbgStarted, 1, 0) != 0) {
  310. return ERROR_SUCCESS;
  311. }
  312. status = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  313. L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\PDH",
  314. 0L,
  315. KEY_READ,
  316. & hKey);
  317. if (status == ERROR_SUCCESS) {
  318. dwSize = sizeof(DWORD);
  319. dwType = 0;
  320. status = RegQueryValueExW(hKey, cszTraceLevel, NULL, & dwType, (LPBYTE) & dwTraceLevel, & dwSize);
  321. if ((status != ERROR_SUCCESS) || (dwType != REG_DWORD)) {
  322. dwTraceLevel = PDH_DBG_TRACE_NONE;
  323. }
  324. }
  325. if (dwTraceLevel == PDH_DBG_TRACE_NONE) goto Cleanup;
  326. dwType = 0;
  327. dwSize = 0;
  328. status = RegQueryValueExW(hKey, cszTraceFileValue, NULL, & dwType, (LPBYTE) szTraceFileName, & dwSize);
  329. while (status == ERROR_MORE_DATA) {
  330. if (szTraceFileName != NULL) HeapFree(GetProcessHeap(), 0, szTraceFileName);
  331. szTraceFileName = (LPWSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
  332. status = RegQueryValueExW(hKey, cszTraceFileValue, NULL, & dwType, (LPBYTE) szTraceFileName, & dwSize);
  333. }
  334. if (status != ERROR_SUCCESS || dwType != REG_SZ) {
  335. DWORD dwFileSize = MAX_PATH + lstrlenW(cszDefaultTraceFile) + 2;
  336. if (szTraceFileName != NULL) HeapFree(GetProcessHeap(), 0, szTraceFileName);
  337. szTraceFileName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR) * dwFileSize);
  338. if (szTraceFileName == NULL) {
  339. goto Cleanup;
  340. }
  341. if (GetSystemWindowsDirectoryW(szTraceFileName, MAX_PATH) > 0) {
  342. StringCchCatW(szTraceFileName, dwFileSize, L"\\");
  343. StringCchCatW(szTraceFileName, dwFileSize, cszDefaultTraceFile);
  344. }
  345. else {
  346. StringCchCopyW(szTraceFileName, MAX_PATH, cszDefaultTraceFileName);
  347. }
  348. }
  349. lFileNameSize = sizeof(WCHAR) * (lstrlenW(szTraceFileName) + 1);
  350. Properties = (PEVENT_TRACE_PROPERTIES) Buffer;
  351. ZeroMemory(Buffer, SMALL_BUFFER_SIZE);
  352. Properties->Wnode.BufferSize = SMALL_BUFFER_SIZE;
  353. Properties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  354. Properties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  355. Properties->LogFileNameOffset = Properties->LoggerNameOffset + sizeof(cszTraceLogName);
  356. ptr = (PCHAR) (((PCHAR) Buffer) + Properties->LoggerNameOffset);
  357. RtlCopyMemory(ptr, cszTraceLogName, sizeof(cszTraceLogName));
  358. ptr = (PCHAR) (((PCHAR) Buffer) + Properties->LogFileNameOffset);
  359. RtlCopyMemory(ptr, szTraceFileName, lFileNameSize);
  360. status = QueryTraceW(0, cszTraceLogName, Properties);
  361. if (status == ERROR_SUCCESS) {
  362. TraceHandle = (TRACEHANDLE) Properties->Wnode.HistoricalContext;
  363. goto Cleanup;
  364. }
  365. // Reinitialize structure again for StartTrace()
  366. //
  367. ZeroMemory(Buffer, SMALL_BUFFER_SIZE);
  368. Properties->Wnode.BufferSize = SMALL_BUFFER_SIZE;
  369. Properties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  370. Properties->BufferSize = 64;
  371. Properties->LogFileMode = EVENT_TRACE_FILE_MODE_SEQUENTIAL
  372. | EVENT_TRACE_USE_PAGED_MEMORY
  373. | EVENT_TRACE_FILE_MODE_APPEND;
  374. Properties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  375. Properties->LogFileNameOffset = Properties->LoggerNameOffset + sizeof(cszTraceLogName);
  376. ptr = (PCHAR) (((PCHAR) Buffer) + Properties->LoggerNameOffset);
  377. RtlCopyMemory(ptr, cszTraceLogName, sizeof(cszTraceLogName));
  378. ptr = (PCHAR) (((PCHAR) Buffer) + Properties->LogFileNameOffset);
  379. RtlCopyMemory(ptr, szTraceFileName, lFileNameSize);
  380. status = StartTraceW(& TraceHandle, cszTraceLogName, Properties);
  381. if (status == ERROR_SUCCESS) {
  382. g_hTraceHandle = TraceHandle;
  383. }
  384. else {
  385. dwTraceLevel = PDH_DBG_TRACE_NONE;
  386. TraceHandle = (TRACEHANDLE) 0;
  387. }
  388. Cleanup:
  389. if (hKey != NULL && hKey != INVALID_HANDLE_VALUE) RegCloseKey(hKey);
  390. if (szTraceFileName != NULL) HeapFree(GetProcessHeap(), 0, szTraceFileName);
  391. g_dwDebugTraceLevel = dwTraceLevel;
  392. g_hTraceHandle = TraceHandle;
  393. return status;
  394. }
  395. VOID
  396. PdhDbgTrace(
  397. ULONG LineNumber,
  398. ULONG ModuleNumber,
  399. ULONG OptArgs,
  400. ULONG Status,
  401. ...
  402. )
  403. {
  404. ULONG ErrorCode;
  405. struct _MY_EVENT {
  406. EVENT_TRACE_HEADER Header;
  407. MOF_FIELD MofField[MAX_MOF_FIELDS];
  408. } MyEvent;
  409. ULONG i;
  410. va_list ArgList;
  411. PVOID source;
  412. SIZE_T len;
  413. DWORD dwLastError;
  414. dwLastError = GetLastError();
  415. RtlZeroMemory(& MyEvent, sizeof(EVENT_TRACE_HEADER));
  416. va_start(ArgList, Status);
  417. for (i = 3; i < MAX_MOF_FIELDS; i ++) {
  418. source = va_arg(ArgList, PVOID);
  419. if (source == NULL) break;
  420. len = va_arg(ArgList, SIZE_T);
  421. if (len == 0) break;
  422. MyEvent.MofField[i].DataPtr = (ULONGLONG) source;
  423. MyEvent.MofField[i].Length = (ULONG) len;
  424. }
  425. va_end(ArgList);
  426. MyEvent.Header.Class.Type = (UCHAR) ModuleNumber;
  427. MyEvent.Header.Size = (USHORT) ( sizeof(EVENT_TRACE_HEADER)
  428. + (i * sizeof(MOF_FIELD)));
  429. MyEvent.Header.Flags = WNODE_FLAG_TRACED_GUID |
  430. WNODE_FLAG_USE_MOF_PTR |
  431. WNODE_FLAG_USE_GUID_PTR;
  432. MyEvent.Header.GuidPtr = (ULONGLONG) & PdhDebugGuid;
  433. MyEvent.MofField[0].DataPtr = (ULONGLONG) & LineNumber;
  434. MyEvent.MofField[0].Length = sizeof(LineNumber);
  435. MyEvent.MofField[1].DataPtr = (ULONGLONG) & Status;
  436. MyEvent.MofField[1].Length = sizeof(Status);
  437. MyEvent.MofField[2].DataPtr = (ULONGLONG) & OptArgs;
  438. MyEvent.MofField[2].Length = sizeof(OptArgs);
  439. __try {
  440. ErrorCode = TraceEvent(g_hTraceHandle, (PEVENT_TRACE_HEADER) & MyEvent);
  441. }
  442. __except (EXCEPTION_EXECUTE_HANDLER) {
  443. ErrorCode = GetLastError();
  444. }
  445. if (ErrorCode != ERROR_SUCCESS) {
  446. DebugPrint((1, "ErrorCode = %d Module = %d Line = %d Status = 0X%08X\n",
  447. ErrorCode, ModuleNumber, LineNumber, Status));
  448. }
  449. SetLastError(dwLastError);
  450. }
  451. BOOL
  452. _stdcall
  453. PdhDllInitRoutine(
  454. IN HANDLE DLLHandle,
  455. IN DWORD Reason,
  456. IN LPVOID ReservedAndUnused
  457. )
  458. {
  459. BOOL bStatus;
  460. BOOL bReturn = TRUE;
  461. OSVERSIONINFOW os;
  462. ReservedAndUnused;
  463. switch(Reason) {
  464. case DLL_PROCESS_ATTACH:
  465. bProcessIsDetaching = FALSE;
  466. {
  467. DWORD dwBufferLength = 0;
  468. ThisDLLHandle = DLLHandle;
  469. // make sure this is the correct operating system
  470. ZeroMemory(& os, sizeof(OSVERSIONINFOW));
  471. os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
  472. bReturn = GetVersionExW(& os);
  473. if (bReturn) {
  474. // check for windows NT v4.0
  475. if (os.dwPlatformId != VER_PLATFORM_WIN32_NT) {
  476. // not WINDOWS NT
  477. bReturn = FALSE;
  478. }
  479. else if (os.dwMajorVersion < 4) {
  480. // it's windows NT, but an old one
  481. bReturn = FALSE;
  482. }
  483. }
  484. else {
  485. // unable to read version so give up
  486. }
  487. if (bReturn) {
  488. // disable thread init calls
  489. DisableThreadLibraryCalls(DLLHandle);
  490. // initialize the event log so events can be reported
  491. PdhDebugStartTrace();
  492. bStatus = PdhiOpenEventLog(& hEventLog);
  493. bStatus = PdhiGetRegistryDefaults();
  494. // initialize the local computer name buffer
  495. if (szStaticLocalMachineName[0] == 0) {
  496. // initialize the computer name for this computer
  497. szStaticLocalMachineName[0] = BACKSLASH_L;
  498. szStaticLocalMachineName[1] = BACKSLASH_L;
  499. dwBufferLength = MAX_COMPUTERNAME_LENGTH + 1;
  500. GetComputerNameW(& szStaticLocalMachineName[2], & dwBufferLength);
  501. }
  502. hPdhDataMutex = CreateMutexW(NULL, FALSE, NULL);
  503. hPdhContextMutex = CreateMutexW(NULL, FALSE, NULL);
  504. hPdhHeap = HeapCreate(0, 0, 0);
  505. if (hPdhHeap == NULL) {
  506. // unable to create our own heap, so use the
  507. // process heap
  508. hPdhHeap = GetProcessHeap();
  509. }
  510. PdhiPlaInitMutex();
  511. }
  512. }
  513. break;
  514. case DLL_PROCESS_DETACH:
  515. // close all pending loggers
  516. //
  517. bProcessIsDetaching = (ReservedAndUnused != NULL) ? (TRUE) : (FALSE);
  518. PdhiCloseAllLoggers();
  519. // walk down query list and close (at least disconnect) queries.
  520. PdhiQueryCleanup ();
  521. FreeAllMachines(bProcessIsDetaching);
  522. PdhiFreeAllWbemServers();
  523. if (hPdhDataMutex != NULL) {
  524. bStatus = CloseHandle(hPdhDataMutex);
  525. hPdhDataMutex = NULL;
  526. }
  527. if (hPdhContextMutex != NULL) {
  528. bStatus = CloseHandle(hPdhContextMutex);
  529. hPdhContextMutex = NULL;
  530. }
  531. if (hPdhHeap != GetProcessHeap()) {
  532. HeapDestroy(hPdhHeap);
  533. hPdhHeap = NULL;
  534. }
  535. // lastly close the event log interface
  536. bStatus = PdhiCloseEventLog(& hEventLog);
  537. bReturn = TRUE;
  538. break ;
  539. case DLL_THREAD_ATTACH:
  540. case DLL_THREAD_DETACH:
  541. bReturn = TRUE;
  542. break;
  543. }
  544. return (bReturn);
  545. }