629 lines
21 KiB
C
629 lines
21 KiB
C
/*++
|
|
Copyright (c) 1995-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
dllinit.c
|
|
|
|
Abstract:
|
|
This module contians the DLL attach/detach event entry point for
|
|
the pdh.dll
|
|
|
|
Author:
|
|
Bob Watson (a-robw) Jul 95
|
|
|
|
Revision History:
|
|
--*/
|
|
|
|
#include <windows.h>
|
|
#include <wmistr.h>
|
|
#include <objbase.h>
|
|
#include <initguid.h>
|
|
#include <evntrace.h>
|
|
#include <wmiguid.h>
|
|
#include <wmium.h>
|
|
#include "strsafe.h"
|
|
#include "pdh.h"
|
|
#include "pdhp.h"
|
|
#include "pdhitype.h"
|
|
#define _INIT_PDH_DEBUGTRACE
|
|
#include "pdhidef.h"
|
|
#include "pdhmsg.h"
|
|
#include "strings.h"
|
|
|
|
#define PDH_DEFAULT_COLLECT_TIMEOUT 300 // 5 minutes
|
|
|
|
HANDLE ThisDLLHandle = NULL;
|
|
WCHAR szStaticLocalMachineName[MAX_COMPUTERNAME_LENGTH + 3] = {0};
|
|
HANDLE hPdhDataMutex = NULL;
|
|
HANDLE hPdhContextMutex = NULL;
|
|
HANDLE hPdhHeap = NULL;
|
|
HANDLE hEventLog = NULL;
|
|
|
|
LONGLONG llRemoteRetryTime = RETRY_TIME_INTERVAL;
|
|
BOOL bEnableRemotePdhAccess = TRUE;
|
|
DWORD dwPdhiLocalDefaultDataSource = DATA_SOURCE_REGISTRY;
|
|
LONG dwCurrentRealTimeDataSource = 0;
|
|
ULONGLONG ulPdhCollectTimeout = PDH_DEFAULT_COLLECT_TIMEOUT;
|
|
BOOL bProcessIsDetaching = FALSE;
|
|
|
|
LPWSTR
|
|
GetStringResource(
|
|
DWORD dwResId
|
|
)
|
|
{
|
|
LPWSTR szReturnString = NULL;
|
|
LPWSTR szTmpString = NULL;
|
|
DWORD dwStrLen = (2048 * sizeof(WCHAR));
|
|
|
|
szReturnString = (LPWSTR) G_ALLOC(dwStrLen);
|
|
if (szReturnString != NULL) {
|
|
dwStrLen /= sizeof(WCHAR);
|
|
dwStrLen = LoadStringW(ThisDLLHandle, (UINT) dwResId, szReturnString, dwStrLen);
|
|
if (dwStrLen > 0) {
|
|
// then realloc down to the size used
|
|
dwStrLen ++; // to include the NULL
|
|
dwStrLen *= sizeof(WCHAR);
|
|
szTmpString = szReturnString;
|
|
szReturnString = G_REALLOC(szTmpString, dwStrLen);
|
|
if (szReturnString == NULL) {
|
|
G_FREE(szTmpString);
|
|
szTmpString = NULL;
|
|
}
|
|
}
|
|
else {
|
|
// free the memory since the look up failed
|
|
G_FREE(szReturnString);
|
|
szReturnString = NULL;
|
|
}
|
|
} //else allocation failed
|
|
|
|
return szReturnString;
|
|
}
|
|
|
|
STATIC_BOOL
|
|
PdhiOpenEventLog(
|
|
HANDLE * phEventLogHandle
|
|
)
|
|
{
|
|
HANDLE hReturn;
|
|
BOOL bReturn = FALSE;
|
|
|
|
if ((hReturn = RegisterEventSourceW(NULL, cszAppShortName)) != NULL) {
|
|
* phEventLogHandle = hReturn;
|
|
bReturn = TRUE;
|
|
}
|
|
return bReturn;
|
|
}
|
|
|
|
STATIC_BOOL
|
|
PdhiGetRegistryDefaults()
|
|
{
|
|
DWORD dwStatus;
|
|
DWORD dwType, dwSize, dwValue;
|
|
|
|
HKEY hKeyPDH;
|
|
|
|
ulPdhCollectTimeout = ((ULONGLONG) PDH_DEFAULT_COLLECT_TIMEOUT) * ((ULONGLONG) 10000000);
|
|
// the local data source is not initialized so use it
|
|
dwStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE, cszPdhKey, 0L, KEY_READ, & hKeyPDH);
|
|
if (dwStatus == ERROR_SUCCESS) {
|
|
// get the default null data source
|
|
//
|
|
dwValue = 0;
|
|
dwType = 0;
|
|
dwSize = sizeof (dwValue);
|
|
dwStatus = RegQueryValueExW(hKeyPDH, cszDefaultNullDataSource, NULL, & dwType, (LPBYTE) & dwValue, & dwSize);
|
|
if (dwStatus != ERROR_SUCCESS || dwType != REG_DWORD) {
|
|
dwValue = DATA_SOURCE_REGISTRY;
|
|
}
|
|
else {
|
|
// check the value for validity
|
|
switch (dwValue) {
|
|
case DATA_SOURCE_WBEM:
|
|
case DATA_SOURCE_REGISTRY:
|
|
// this is OK
|
|
break;
|
|
|
|
case DATA_SOURCE_LOGFILE:
|
|
default:
|
|
// these are not OK so insert default
|
|
dwValue = DATA_SOURCE_REGISTRY;
|
|
break;
|
|
}
|
|
}
|
|
dwPdhiLocalDefaultDataSource = dwValue;
|
|
|
|
//
|
|
// get the retry timeout
|
|
//
|
|
dwValue = 0;
|
|
dwType = 0;
|
|
dwSize = sizeof (dwValue);
|
|
dwStatus = RegQueryValueExW(hKeyPDH, cszRemoteMachineRetryTime, NULL, & dwType, (LPBYTE) & dwValue, & dwSize);
|
|
if (dwStatus != ERROR_SUCCESS || dwType != REG_DWORD) {
|
|
dwValue = 0;
|
|
}
|
|
else {
|
|
// check the value for validity
|
|
// must be 30 seconds or more yet no more than an hour
|
|
if ((dwValue <= 30) || (dwValue > 3600)) {
|
|
dwValue = 0;
|
|
}
|
|
}
|
|
if (dwValue != 0) {
|
|
// convert to 100NS units
|
|
llRemoteRetryTime = dwValue * 10000000;
|
|
}
|
|
else {
|
|
// use default
|
|
llRemoteRetryTime = RETRY_TIME_INTERVAL;
|
|
}
|
|
|
|
// get the remote access mode
|
|
//
|
|
dwValue = 0;
|
|
dwType = 0;
|
|
dwSize = sizeof (dwValue);
|
|
dwStatus = RegQueryValueExW(hKeyPDH, cszEnableRemotePdhAccess, NULL, & dwType, (LPBYTE) & dwValue, & dwSize);
|
|
if (dwStatus != ERROR_SUCCESS || dwType != REG_DWORD) {
|
|
dwValue = TRUE;
|
|
}
|
|
else {
|
|
// check the value for validity
|
|
if (dwValue != 0) {
|
|
dwValue = TRUE;
|
|
}
|
|
}
|
|
bEnableRemotePdhAccess = (BOOL) dwValue;
|
|
|
|
// get RegQueryValueEx(HKEY_PERFORMANCE_DATA) elapsed time maximum
|
|
//
|
|
dwValue = 0;
|
|
dwType = 0;
|
|
dwSize = sizeof(dwValue);
|
|
dwStatus = RegQueryValueExW(hKeyPDH, cszCollectTimeout, NULL, & dwType, (LPBYTE) & dwValue, & dwSize);
|
|
if (dwStatus != ERROR_SUCCESS || dwType != REG_DWORD) {
|
|
dwValue = PDH_DEFAULT_COLLECT_TIMEOUT;
|
|
}
|
|
else if (dwValue < 30 || dwValue > 3600) {
|
|
// must between 30 seconds and 1 hour
|
|
//
|
|
dwValue = PDH_DEFAULT_COLLECT_TIMEOUT;
|
|
}
|
|
ulPdhCollectTimeout = ((ULONGLONG) dwValue) * ((ULONGLONG) 10000000);
|
|
|
|
// close the registry key
|
|
RegCloseKey(hKeyPDH);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
STATIC_BOOL
|
|
PdhiCloseEventLog(
|
|
HANDLE * phEventLogHandle
|
|
)
|
|
{
|
|
BOOL bReturn = TRUE;
|
|
|
|
if (* phEventLogHandle != NULL) {
|
|
bReturn = DeregisterEventSource(* phEventLogHandle);
|
|
* phEventLogHandle = NULL;
|
|
}
|
|
return bReturn;
|
|
}
|
|
|
|
HRESULT
|
|
PdhiPlaInitMutex()
|
|
{
|
|
HRESULT hr = ERROR_SUCCESS;
|
|
BOOL bResult = TRUE;
|
|
|
|
PSECURITY_DESCRIPTOR SD = NULL;
|
|
SECURITY_ATTRIBUTES sa;
|
|
PSID AuthenticatedUsers = NULL;
|
|
PSID BuiltInAdministrators = NULL;
|
|
PSID NetworkService = NULL;
|
|
PSID LoggingUsers = NULL;
|
|
DWORD dwAclSize;
|
|
ACL *Acl;
|
|
|
|
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
|
|
|
bResult = AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0,0,0,0,0,0,
|
|
&BuiltInAdministrators);
|
|
if( !bResult ){goto cleanup;}
|
|
|
|
bResult = AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
1,
|
|
SECURITY_AUTHENTICATED_USER_RID,
|
|
0,0,0,0,0,0,0,
|
|
&AuthenticatedUsers);
|
|
if( !bResult ){goto cleanup;}
|
|
|
|
bResult = AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
1,
|
|
SECURITY_NETWORK_SERVICE_RID,
|
|
0,0,0,0,0,0,0,
|
|
&NetworkService);
|
|
if( !bResult ){goto cleanup;}
|
|
|
|
bResult = AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
1,
|
|
DOMAIN_ALIAS_RID_LOGGING_USERS,
|
|
0,0,0,0,0,0,0,
|
|
&LoggingUsers);
|
|
if( !bResult ){goto cleanup;}
|
|
|
|
|
|
dwAclSize = sizeof (ACL) +
|
|
(4 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (ULONG))) +
|
|
GetLengthSid(AuthenticatedUsers) +
|
|
GetLengthSid(BuiltInAdministrators) +
|
|
GetLengthSid(NetworkService) +
|
|
GetLengthSid(LoggingUsers);
|
|
|
|
SD = (PSECURITY_DESCRIPTOR)G_ALLOC(SECURITY_DESCRIPTOR_MIN_LENGTH + dwAclSize);
|
|
if( NULL == SD ){ goto cleanup; }
|
|
|
|
ZeroMemory( SD, sizeof(SD) );
|
|
|
|
Acl = (ACL *)((BYTE *)SD + SECURITY_DESCRIPTOR_MIN_LENGTH);
|
|
|
|
bResult = InitializeAcl( Acl, dwAclSize, ACL_REVISION);
|
|
if( !bResult ){goto cleanup;}
|
|
|
|
bResult = AddAccessAllowedAce(Acl, ACL_REVISION, MUTEX_ALL_ACCESS, AuthenticatedUsers );
|
|
if( !bResult ){goto cleanup;}
|
|
|
|
bResult = AddAccessAllowedAce(Acl, ACL_REVISION, MUTEX_ALL_ACCESS , NetworkService );
|
|
if( !bResult ){goto cleanup;}
|
|
|
|
bResult = AddAccessAllowedAce(Acl, ACL_REVISION, MUTEX_ALL_ACCESS , LoggingUsers );
|
|
if( !bResult ){goto cleanup;}
|
|
|
|
bResult = AddAccessAllowedAce(Acl, ACL_REVISION, GENERIC_ALL, BuiltInAdministrators );
|
|
if( !bResult ){goto cleanup;}
|
|
|
|
bResult = InitializeSecurityDescriptor(SD, SECURITY_DESCRIPTOR_REVISION);
|
|
if( !bResult ){goto cleanup;}
|
|
|
|
bResult = SetSecurityDescriptorDacl(SD, TRUE, Acl, FALSE);
|
|
if( !bResult ){goto cleanup;}
|
|
|
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
sa.lpSecurityDescriptor = SD;
|
|
sa.bInheritHandle = FALSE;
|
|
|
|
hPdhPlaMutex = CreateMutexW( &sa, FALSE, PDH_PLA_MUTEX );
|
|
|
|
cleanup:
|
|
if( hPdhPlaMutex == NULL || !bResult ){
|
|
hr = GetLastError();
|
|
}
|
|
if( NULL != AuthenticatedUsers ){
|
|
FreeSid(AuthenticatedUsers);
|
|
}
|
|
if( NULL != BuiltInAdministrators){
|
|
FreeSid(BuiltInAdministrators);
|
|
}
|
|
if( NULL != NetworkService){
|
|
FreeSid(NetworkService);
|
|
}
|
|
if( NULL != LoggingUsers){
|
|
FreeSid(LoggingUsers);
|
|
}
|
|
G_FREE(SD);
|
|
|
|
return hr;
|
|
}
|
|
|
|
const LPCWSTR cszTraceLevel = L"DebugTraceLevel";
|
|
const LPCWSTR cszTraceFileValue = L"DebugTraceFile";
|
|
const LPCWSTR cszTraceLogName = L"PDH Debug Logger";
|
|
const LPCWSTR cszDefaultTraceFile = L"PdhDbg.Etl";
|
|
const LPCWSTR cszDefaultTraceFileName = L"C:\\PdhDbg.Etl";
|
|
|
|
TRACEHANDLE g_hTraceHandle = 0;
|
|
LONG g_lDbgStarted = 0;
|
|
|
|
DEFINE_GUID( /* 51af3adf-28b1-4ba5-b59a-3aeec16deb3c */
|
|
PdhDebugGuid,
|
|
0x51af3adf,
|
|
0x28b1,
|
|
0x4ba5,
|
|
0xb5, 0x9a, 0x3a, 0xee, 0xc1, 0x6d, 0xeb, 0x3c
|
|
);
|
|
|
|
PDH_FUNCTION
|
|
PdhDebugStartTrace()
|
|
{
|
|
DWORD status = ERROR_SUCCESS;
|
|
DWORD dwType = 0;
|
|
DWORD dwSize = 0;
|
|
DWORD dwTraceLevel = PDH_DBG_TRACE_NONE;
|
|
HKEY hKey = NULL;
|
|
TRACEHANDLE TraceHandle = 0;
|
|
LPWSTR szTraceFileName = NULL;
|
|
CHAR Buffer[SMALL_BUFFER_SIZE];
|
|
PCHAR ptr;
|
|
ULONG lFileNameSize = 0;
|
|
|
|
PEVENT_TRACE_PROPERTIES Properties;
|
|
|
|
if (InterlockedCompareExchange(& g_lDbgStarted, 1, 0) != 0) {
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
|
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\PDH",
|
|
0L,
|
|
KEY_READ,
|
|
& hKey);
|
|
if (status == ERROR_SUCCESS) {
|
|
dwSize = sizeof(DWORD);
|
|
dwType = 0;
|
|
status = RegQueryValueExW(hKey, cszTraceLevel, NULL, & dwType, (LPBYTE) & dwTraceLevel, & dwSize);
|
|
if ((status != ERROR_SUCCESS) || (dwType != REG_DWORD)) {
|
|
dwTraceLevel = PDH_DBG_TRACE_NONE;
|
|
}
|
|
}
|
|
|
|
if (dwTraceLevel == PDH_DBG_TRACE_NONE) goto Cleanup;
|
|
|
|
dwType = 0;
|
|
dwSize = 0;
|
|
status = RegQueryValueExW(hKey, cszTraceFileValue, NULL, & dwType, (LPBYTE) szTraceFileName, & dwSize);
|
|
while (status == ERROR_MORE_DATA) {
|
|
if (szTraceFileName != NULL) HeapFree(GetProcessHeap(), 0, szTraceFileName);
|
|
szTraceFileName = (LPWSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
|
|
status = RegQueryValueExW(hKey, cszTraceFileValue, NULL, & dwType, (LPBYTE) szTraceFileName, & dwSize);
|
|
}
|
|
if (status != ERROR_SUCCESS || dwType != REG_SZ) {
|
|
DWORD dwFileSize = MAX_PATH + lstrlenW(cszDefaultTraceFile) + 2;
|
|
|
|
if (szTraceFileName != NULL) HeapFree(GetProcessHeap(), 0, szTraceFileName);
|
|
szTraceFileName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR) * dwFileSize);
|
|
if (szTraceFileName == NULL) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (GetSystemWindowsDirectoryW(szTraceFileName, MAX_PATH) > 0) {
|
|
StringCchCatW(szTraceFileName, dwFileSize, L"\\");
|
|
StringCchCatW(szTraceFileName, dwFileSize, cszDefaultTraceFile);
|
|
}
|
|
else {
|
|
StringCchCopyW(szTraceFileName, MAX_PATH, cszDefaultTraceFileName);
|
|
}
|
|
}
|
|
lFileNameSize = sizeof(WCHAR) * (lstrlenW(szTraceFileName) + 1);
|
|
|
|
Properties = (PEVENT_TRACE_PROPERTIES) Buffer;
|
|
|
|
ZeroMemory(Buffer, SMALL_BUFFER_SIZE);
|
|
Properties->Wnode.BufferSize = SMALL_BUFFER_SIZE;
|
|
Properties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
|
|
Properties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
|
|
Properties->LogFileNameOffset = Properties->LoggerNameOffset + sizeof(cszTraceLogName);
|
|
ptr = (PCHAR) (((PCHAR) Buffer) + Properties->LoggerNameOffset);
|
|
RtlCopyMemory(ptr, cszTraceLogName, sizeof(cszTraceLogName));
|
|
ptr = (PCHAR) (((PCHAR) Buffer) + Properties->LogFileNameOffset);
|
|
RtlCopyMemory(ptr, szTraceFileName, lFileNameSize);
|
|
status = QueryTraceW(0, cszTraceLogName, Properties);
|
|
if (status == ERROR_SUCCESS) {
|
|
TraceHandle = (TRACEHANDLE) Properties->Wnode.HistoricalContext;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Reinitialize structure again for StartTrace()
|
|
//
|
|
ZeroMemory(Buffer, SMALL_BUFFER_SIZE);
|
|
Properties->Wnode.BufferSize = SMALL_BUFFER_SIZE;
|
|
Properties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
|
|
Properties->BufferSize = 64;
|
|
Properties->LogFileMode = EVENT_TRACE_FILE_MODE_SEQUENTIAL
|
|
| EVENT_TRACE_USE_PAGED_MEMORY
|
|
| EVENT_TRACE_FILE_MODE_APPEND;
|
|
Properties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
|
|
Properties->LogFileNameOffset = Properties->LoggerNameOffset + sizeof(cszTraceLogName);
|
|
ptr = (PCHAR) (((PCHAR) Buffer) + Properties->LoggerNameOffset);
|
|
RtlCopyMemory(ptr, cszTraceLogName, sizeof(cszTraceLogName));
|
|
ptr = (PCHAR) (((PCHAR) Buffer) + Properties->LogFileNameOffset);
|
|
RtlCopyMemory(ptr, szTraceFileName, lFileNameSize);
|
|
|
|
status = StartTraceW(& TraceHandle, cszTraceLogName, Properties);
|
|
if (status == ERROR_SUCCESS) {
|
|
g_hTraceHandle = TraceHandle;
|
|
}
|
|
else {
|
|
dwTraceLevel = PDH_DBG_TRACE_NONE;
|
|
TraceHandle = (TRACEHANDLE) 0;
|
|
}
|
|
|
|
Cleanup:
|
|
if (hKey != NULL && hKey != INVALID_HANDLE_VALUE) RegCloseKey(hKey);
|
|
if (szTraceFileName != NULL) HeapFree(GetProcessHeap(), 0, szTraceFileName);
|
|
g_dwDebugTraceLevel = dwTraceLevel;
|
|
g_hTraceHandle = TraceHandle;
|
|
return status;
|
|
}
|
|
|
|
VOID
|
|
PdhDbgTrace(
|
|
ULONG LineNumber,
|
|
ULONG ModuleNumber,
|
|
ULONG OptArgs,
|
|
ULONG Status,
|
|
...
|
|
)
|
|
{
|
|
ULONG ErrorCode;
|
|
struct _MY_EVENT {
|
|
EVENT_TRACE_HEADER Header;
|
|
MOF_FIELD MofField[MAX_MOF_FIELDS];
|
|
} MyEvent;
|
|
ULONG i;
|
|
va_list ArgList;
|
|
PVOID source;
|
|
SIZE_T len;
|
|
DWORD dwLastError;
|
|
|
|
dwLastError = GetLastError();
|
|
RtlZeroMemory(& MyEvent, sizeof(EVENT_TRACE_HEADER));
|
|
|
|
va_start(ArgList, Status);
|
|
for (i = 3; i < MAX_MOF_FIELDS; i ++) {
|
|
source = va_arg(ArgList, PVOID);
|
|
if (source == NULL) break;
|
|
len = va_arg(ArgList, SIZE_T);
|
|
if (len == 0) break;
|
|
MyEvent.MofField[i].DataPtr = (ULONGLONG) source;
|
|
MyEvent.MofField[i].Length = (ULONG) len;
|
|
}
|
|
va_end(ArgList);
|
|
|
|
MyEvent.Header.Class.Type = (UCHAR) ModuleNumber;
|
|
MyEvent.Header.Size = (USHORT) ( sizeof(EVENT_TRACE_HEADER)
|
|
+ (i * sizeof(MOF_FIELD)));
|
|
MyEvent.Header.Flags = WNODE_FLAG_TRACED_GUID |
|
|
WNODE_FLAG_USE_MOF_PTR |
|
|
WNODE_FLAG_USE_GUID_PTR;
|
|
MyEvent.Header.GuidPtr = (ULONGLONG) & PdhDebugGuid;
|
|
MyEvent.MofField[0].DataPtr = (ULONGLONG) & LineNumber;
|
|
MyEvent.MofField[0].Length = sizeof(LineNumber);
|
|
MyEvent.MofField[1].DataPtr = (ULONGLONG) & Status;
|
|
MyEvent.MofField[1].Length = sizeof(Status);
|
|
MyEvent.MofField[2].DataPtr = (ULONGLONG) & OptArgs;
|
|
MyEvent.MofField[2].Length = sizeof(OptArgs);
|
|
|
|
__try {
|
|
ErrorCode = TraceEvent(g_hTraceHandle, (PEVENT_TRACE_HEADER) & MyEvent);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
|
ErrorCode = GetLastError();
|
|
}
|
|
|
|
if (ErrorCode != ERROR_SUCCESS) {
|
|
DebugPrint((1, "ErrorCode = %d Module = %d Line = %d Status = 0X%08X\n",
|
|
ErrorCode, ModuleNumber, LineNumber, Status));
|
|
}
|
|
|
|
SetLastError(dwLastError);
|
|
}
|
|
|
|
BOOL
|
|
_stdcall
|
|
PdhDllInitRoutine(
|
|
IN HANDLE DLLHandle,
|
|
IN DWORD Reason,
|
|
IN LPVOID ReservedAndUnused
|
|
)
|
|
{
|
|
BOOL bStatus;
|
|
BOOL bReturn = TRUE;
|
|
OSVERSIONINFOW os;
|
|
ReservedAndUnused;
|
|
|
|
switch(Reason) {
|
|
case DLL_PROCESS_ATTACH:
|
|
bProcessIsDetaching = FALSE;
|
|
{
|
|
DWORD dwBufferLength = 0;
|
|
|
|
ThisDLLHandle = DLLHandle;
|
|
|
|
// make sure this is the correct operating system
|
|
ZeroMemory(& os, sizeof(OSVERSIONINFOW));
|
|
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
|
|
bReturn = GetVersionExW(& os);
|
|
if (bReturn) {
|
|
// check for windows NT v4.0
|
|
if (os.dwPlatformId != VER_PLATFORM_WIN32_NT) {
|
|
// not WINDOWS NT
|
|
bReturn = FALSE;
|
|
}
|
|
else if (os.dwMajorVersion < 4) {
|
|
// it's windows NT, but an old one
|
|
bReturn = FALSE;
|
|
}
|
|
}
|
|
else {
|
|
// unable to read version so give up
|
|
}
|
|
|
|
if (bReturn) {
|
|
// disable thread init calls
|
|
DisableThreadLibraryCalls(DLLHandle);
|
|
|
|
// initialize the event log so events can be reported
|
|
PdhDebugStartTrace();
|
|
bStatus = PdhiOpenEventLog(& hEventLog);
|
|
bStatus = PdhiGetRegistryDefaults();
|
|
|
|
// initialize the local computer name buffer
|
|
if (szStaticLocalMachineName[0] == 0) {
|
|
// initialize the computer name for this computer
|
|
szStaticLocalMachineName[0] = BACKSLASH_L;
|
|
szStaticLocalMachineName[1] = BACKSLASH_L;
|
|
dwBufferLength = MAX_COMPUTERNAME_LENGTH + 1;
|
|
GetComputerNameW(& szStaticLocalMachineName[2], & dwBufferLength);
|
|
}
|
|
hPdhDataMutex = CreateMutexW(NULL, FALSE, NULL);
|
|
hPdhContextMutex = CreateMutexW(NULL, FALSE, NULL);
|
|
hPdhHeap = HeapCreate(0, 0, 0);
|
|
if (hPdhHeap == NULL) {
|
|
// unable to create our own heap, so use the
|
|
// process heap
|
|
hPdhHeap = GetProcessHeap();
|
|
}
|
|
PdhiPlaInitMutex();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
// close all pending loggers
|
|
//
|
|
bProcessIsDetaching = (ReservedAndUnused != NULL) ? (TRUE) : (FALSE);
|
|
PdhiCloseAllLoggers();
|
|
|
|
// walk down query list and close (at least disconnect) queries.
|
|
PdhiQueryCleanup ();
|
|
FreeAllMachines(bProcessIsDetaching);
|
|
PdhiFreeAllWbemServers();
|
|
if (hPdhDataMutex != NULL) {
|
|
bStatus = CloseHandle(hPdhDataMutex);
|
|
hPdhDataMutex = NULL;
|
|
}
|
|
if (hPdhContextMutex != NULL) {
|
|
bStatus = CloseHandle(hPdhContextMutex);
|
|
hPdhContextMutex = NULL;
|
|
}
|
|
|
|
if (hPdhHeap != GetProcessHeap()) {
|
|
HeapDestroy(hPdhHeap);
|
|
hPdhHeap = NULL;
|
|
}
|
|
|
|
// lastly close the event log interface
|
|
bStatus = PdhiCloseEventLog(& hEventLog);
|
|
bReturn = TRUE;
|
|
break ;
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
case DLL_THREAD_DETACH:
|
|
bReturn = TRUE;
|
|
break;
|
|
}
|
|
|
|
return (bReturn);
|
|
}
|