442 lines
12 KiB
C
442 lines
12 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 <assert.h>
|
||
#include "pdhitype.h"
|
||
#include "pdhidef.h"
|
||
#include "pdhmsg.h"
|
||
#include "strings.h"
|
||
#include "pdhp.h"
|
||
|
||
HANDLE ThisDLLHandle = NULL;
|
||
WCHAR szStaticLocalMachineName[MAX_PATH] = {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;
|
||
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 (szReturnString, 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;
|
||
|
||
if ((hReturn = RegisterEventSourceW (
|
||
NULL, // on the local machine
|
||
cszAppShortName // for the PDH.DLL
|
||
)) != NULL) {
|
||
*phEventLogHandle = hReturn;
|
||
bReturn = TRUE;
|
||
} else {
|
||
bReturn = FALSE;
|
||
}
|
||
return bReturn;
|
||
}
|
||
|
||
STATIC_BOOL
|
||
PdhiGetRegistryDefaults ()
|
||
{
|
||
DWORD dwStatus;
|
||
DWORD dwType, dwSize, dwValue;
|
||
|
||
HKEY hKeyPDH;
|
||
|
||
// 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;
|
||
|
||
// close the registry key
|
||
RegCloseKey (hKeyPDH);
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
STATIC_BOOL
|
||
PdhiCloseEventLog (
|
||
HANDLE * phEventLogHandle
|
||
)
|
||
{
|
||
BOOL bReturn;
|
||
|
||
if (*phEventLogHandle != NULL) {
|
||
bReturn = DeregisterEventSource (*phEventLogHandle);
|
||
*phEventLogHandle = NULL;
|
||
} else {
|
||
// it's already closed so that's OK
|
||
bReturn = TRUE;
|
||
}
|
||
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;
|
||
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;}
|
||
|
||
dwAclSize = sizeof (ACL) +
|
||
(3 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (ULONG))) +
|
||
GetLengthSid(AuthenticatedUsers) +
|
||
GetLengthSid(BuiltInAdministrators) +
|
||
GetLengthSid(NetworkService);
|
||
|
||
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, SYNCHRONIZE | GENERIC_READ, AuthenticatedUsers );
|
||
if( !bResult ){goto cleanup;}
|
||
|
||
bResult = AddAccessAllowedAce(Acl, ACL_REVISION, MUTEX_ALL_ACCESS , NetworkService );
|
||
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);
|
||
}
|
||
G_FREE(SD);
|
||
|
||
return hr;
|
||
}
|
||
|
||
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
|
||
memset (&os, 0, sizeof(os));
|
||
os.dwOSVersionInfoSize = sizeof(os);
|
||
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
|
||
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 = (sizeof(szStaticLocalMachineName) / sizeof(WCHAR)) - 2;
|
||
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();
|
||
assert (hPdhHeap != NULL);
|
||
}
|
||
|
||
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);
|
||
assert (bStatus);
|
||
hPdhDataMutex = NULL;
|
||
}
|
||
if (hPdhContextMutex != NULL) {
|
||
bStatus = CloseHandle (hPdhContextMutex);
|
||
assert (bStatus);
|
||
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);
|
||
}
|