windows-nt/Source/XPSP1/NT/base/cluster/clusexts/leaks/leaks.c

769 lines
18 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
leaks.c
Abstract:
A filter DLL for trying to detect memory, event, registry, and
token handle leaks.
Author:
Charlie Wickham/Rod Gamache
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#define _ADVAPI32_
#define _KERNEL32_
#include <windows.h>
#include <stdio.h>
#include "clusrtl.h"
#include "leaks.h"
HINSTANCE Kernel32Handle;
HINSTANCE Advapi32Handle;
FARPROC SystemLocalAlloc;
FARPROC SystemLocalFree;
FARPROC SystemCreateEventA;
FARPROC SystemCreateEventW;
FARPROC SystemRegOpenKeyA;
FARPROC SystemRegOpenKeyW;
FARPROC SystemRegOpenKeyExA;
FARPROC SystemRegOpenKeyExW;
FARPROC SystemRegCreateKeyA;
FARPROC SystemRegCreateKeyW;
FARPROC SystemRegCreateKeyExA;
FARPROC SystemRegCreateKeyExW;
FARPROC SystemRegCloseKey;
FARPROC SystemOpenProcessToken;
FARPROC SystemOpenThreadToken;
FARPROC SystemDuplicateToken;
FARPROC SystemDuplicateTokenEx;
FARPROC SystemCloseHandle;
#define SetSystemPointer( _h, _n ) \
System##_n = GetProcAddress( _h, #_n );
BOOL LeaksVerbose = FALSE;
HANDLE_TABLE HandleTable[ MAX_HANDLE / HANDLE_DELTA ];
BOOLEAN
WINAPI
LeaksDllEntry(
IN HINSTANCE DllHandle,
IN DWORD Reason,
IN LPVOID Reserved
)
/*++
Routine Description:
Main DLL entrypoint
Arguments:
DllHandle - Supplies the DLL handle.
Reason - Supplies the call reason
Return Value:
TRUE if successful
FALSE if unsuccessful
--*/
{
if (Reason == DLL_PROCESS_ATTACH) {
DisableThreadLibraryCalls(DllHandle);
ClRtlInitialize( TRUE, NULL );
//
// get pointers to the real functions
//
Kernel32Handle = LoadLibrary( "kernel32.dll" );
Advapi32Handle = LoadLibrary( "advapi32.dll" );
SetSystemPointer( Kernel32Handle, LocalAlloc );
SetSystemPointer( Kernel32Handle, LocalFree );
SetSystemPointer( Kernel32Handle, CreateEventA );
SetSystemPointer( Kernel32Handle, CreateEventW );
SetSystemPointer( Advapi32Handle, RegOpenKeyA );
SetSystemPointer( Advapi32Handle, RegOpenKeyW );
SetSystemPointer( Advapi32Handle, RegOpenKeyExA );
SetSystemPointer( Advapi32Handle, RegOpenKeyExW );
SetSystemPointer( Advapi32Handle, RegCreateKeyA );
SetSystemPointer( Advapi32Handle, RegCreateKeyW );
SetSystemPointer( Advapi32Handle, RegCreateKeyExA );
SetSystemPointer( Advapi32Handle, RegCreateKeyExW );
SetSystemPointer( Advapi32Handle, RegCloseKey );
SetSystemPointer( Advapi32Handle, OpenProcessToken );
SetSystemPointer( Advapi32Handle, OpenThreadToken );
SetSystemPointer( Advapi32Handle, DuplicateToken );
SetSystemPointer( Advapi32Handle, DuplicateTokenEx );
SetSystemPointer( Kernel32Handle, CloseHandle );
}
return(TRUE);
}
HLOCAL
WINAPI
LEAKS_LocalAlloc(
UINT uFlags,
SIZE_T uBytes
)
{
HLOCAL memory;
PMEM_HDR memHdr;
PVOID callersAddress;
PVOID callersCaller;
RtlGetCallersAddress(
&callersAddress,
&callersCaller );
memHdr = (PVOID)(*SystemLocalAlloc)( uFlags, uBytes + sizeof(MEM_HDR) );
if ( !memHdr ) {
return NULL;
}
memHdr->Signature = HEAP_SIGNATURE_ALLOC;
memHdr->CallersAddress = callersAddress;
memHdr->CallersCaller = callersCaller;
return(memHdr+1);
}
HLOCAL
WINAPI
LEAKS_LocalFree(
HLOCAL hMem
)
{
PMEM_HDR memHdr = hMem;
PVOID callersAddress;
PVOID callersCaller;
CHAR buf[128];
if ( memHdr ) {
--memHdr;
if ( memHdr->Signature == HEAP_SIGNATURE_FREE ) {
sprintf( buf, "Freeing %p a 2nd time!\n", memHdr );
OutputDebugString( buf );
DebugBreak();
} else if ( memHdr->Signature == HEAP_SIGNATURE_ALLOC ) {
RtlGetCallersAddress(&callersAddress,
&callersCaller );
memHdr->Signature = HEAP_SIGNATURE_FREE;
memHdr->CallersAddress = callersAddress;
memHdr->CallersCaller = callersCaller;
} else {
memHdr++;
}
} else {
#if 0
sprintf( buf, "Passing NULL to LocalFree, tsk, tsk, tsk!!\n" );
OutputDebugString( buf );
DebugBreak();
#endif
}
return( (HLOCAL)(*SystemLocalFree)(memHdr) );
}
HANDLE
WINAPI
LEAKS_CreateEventA(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCSTR lpName
)
{
HANDLE handle;
PVOID callersAddress;
PVOID callersCaller;
handle = (HANDLE)(*SystemCreateEventA)(
lpEventAttributes,
bManualReset,
bInitialState,
lpName
);
if ( handle != NULL ) {
SetHandleTable( handle, TRUE, LeaksEvent );
}
if ( LeaksVerbose ) {
ClRtlLogPrint(LOG_NOISE, "[LEAKS] CreateEventA returns handle %1!X!, called from %2!X! and %3!X!\n",
handle,
callersAddress,
callersCaller );
}
return(handle);
} // CreateEventA
HANDLE
WINAPI
LEAKS_CreateEventW(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCWSTR lpName
)
{
HANDLE handle;
PVOID callersAddress;
PVOID callersCaller;
handle = (HANDLE)(*SystemCreateEventW)(
lpEventAttributes,
bManualReset,
bInitialState,
lpName
);
if ( handle != NULL ) {
SetHandleTable( handle, TRUE, LeaksEvent );
}
if ( LeaksVerbose ) {
ClRtlLogPrint(LOG_NOISE,"[LEAKS] CreateEventW returns handle %1!X!, called from %2!X! and %3!X!\n",
handle,
callersAddress,
callersCaller );
}
return(handle);
} // CreateEventW
LONG
APIENTRY
LEAKS_RegOpenKeyA(
HKEY hKey,
LPCSTR lpSubKey,
PHKEY phkResult
)
{
LONG status;
PVOID callersAddress;
PVOID callersCaller;
status = (LONG)(*SystemRegOpenKeyA)(
hKey,
lpSubKey,
phkResult
);
if ( status == ERROR_SUCCESS ) {
SetHandleTable( *phkResult, TRUE, LeaksRegistry );
}
if ( LeaksVerbose ) {
ClRtlLogPrint(LOG_NOISE,"[LEAKS] RegOpenKeyA returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
*phkResult,
status,
callersAddress,
callersCaller );
}
return(status);
} // RegOpenKeyA
LONG
APIENTRY
LEAKS_RegOpenKeyW(
HKEY hKey,
LPCWSTR lpSubKey,
PHKEY phkResult
)
{
LONG status;
PVOID callersAddress;
PVOID callersCaller;
status = (LONG)(*SystemRegOpenKeyW)(
hKey,
lpSubKey,
phkResult
);
if ( status == ERROR_SUCCESS ) {
SetHandleTable( *phkResult, TRUE, LeaksRegistry );
}
if ( LeaksVerbose ) {
ClRtlLogPrint(LOG_NOISE, "[LEAKS] RegOpenKeyW returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
*phkResult,
status,
callersAddress,
callersCaller );
}
return(status);
} // RegOpenKeyW
LONG
APIENTRY
LEAKS_RegOpenKeyExA(
HKEY hKey,
LPCSTR lpSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult
)
{
LONG status;
PVOID callersAddress;
PVOID callersCaller;
status = (LONG)(*SystemRegOpenKeyExA)(
hKey,
lpSubKey,
ulOptions,
samDesired,
phkResult
);
if ( status == ERROR_SUCCESS ) {
SetHandleTable( *phkResult, TRUE, LeaksRegistry );
}
if ( LeaksVerbose ) {
ClRtlLogPrint(LOG_NOISE, "[LEAKS] RegOpenKeyExA returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
*phkResult,
status,
callersAddress,
callersCaller );
}
return(status);
} // RegOpenKeyExA
LONG
APIENTRY
LEAKS_RegOpenKeyExW(
HKEY hKey,
LPCWSTR lpSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult
)
{
LONG status;
PVOID callersAddress;
PVOID callersCaller;
status = (LONG)(*SystemRegOpenKeyExW)(
hKey,
lpSubKey,
ulOptions,
samDesired,
phkResult
);
if ( status == ERROR_SUCCESS ) {
SetHandleTable( *phkResult, TRUE, LeaksRegistry );
}
if ( LeaksVerbose ) {
ClRtlLogPrint(LOG_NOISE, "[LEAKS] RegOpenKeyExW returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
*phkResult,
status,
callersAddress,
callersCaller );
}
return(status);
} // RegOpenKeyExW
LONG
APIENTRY
LEAKS_RegCreateKeyA(
HKEY hKey,
LPCSTR lpSubKey,
PHKEY phkResult
)
{
LONG status;
PVOID callersAddress;
PVOID callersCaller;
status = (LONG)(*SystemRegCreateKeyA)(
hKey,
lpSubKey,
phkResult
);
if ( status == ERROR_SUCCESS ) {
SetHandleTable( *phkResult, TRUE, LeaksRegistry );
}
if ( LeaksVerbose ) {
ClRtlLogPrint(LOG_NOISE, "[LEAKS] RegCreateKeyA returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
*phkResult,
status,
callersAddress,
callersCaller );
}
return(status);
} // RegCreateKeyA
LONG
APIENTRY
LEAKS_RegCreateKeyW(
HKEY hKey,
LPCWSTR lpSubKey,
PHKEY phkResult
)
{
LONG status;
PVOID callersAddress;
PVOID callersCaller;
status = (LONG)(*SystemRegCreateKeyW)(
hKey,
lpSubKey,
phkResult
);
if ( status == ERROR_SUCCESS ) {
SetHandleTable( *phkResult, TRUE, LeaksRegistry );
}
if ( LeaksVerbose ) {
ClRtlLogPrint(LOG_NOISE, "[LEAKS] RegCreateKeyW returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
*phkResult,
status,
callersAddress,
callersCaller );
}
return(status);
} // RegCreateKeyW
LONG
APIENTRY
LEAKS_RegCreateKeyExA(
HKEY hKey,
LPCSTR lpSubKey,
DWORD Reserved,
LPSTR lpClass,
DWORD dwOptions,
REGSAM samDesired,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
PHKEY phkResult,
LPDWORD lpdwDisposition
)
{
LONG status;
PVOID callersAddress;
PVOID callersCaller;
status = (LONG)(*SystemRegCreateKeyExA)(hKey,
lpSubKey,
Reserved,
lpClass,
dwOptions,
samDesired,
lpSecurityAttributes,
phkResult,
lpdwDisposition
);
if ( status == ERROR_SUCCESS ) {
SetHandleTable( *phkResult, TRUE, LeaksRegistry );
}
if ( LeaksVerbose ) {
ClRtlLogPrint(LOG_NOISE, "[LEAKS] RegCreateKeyExA returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
*phkResult,
status,
callersAddress,
callersCaller );
}
return(status);
} // RegCreateKeyExA
LONG
APIENTRY
LEAKS_RegCreateKeyExW(
HKEY hKey,
LPCWSTR lpSubKey,
DWORD Reserved,
LPWSTR lpClass,
DWORD dwOptions,
REGSAM samDesired,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
PHKEY phkResult,
LPDWORD lpdwDisposition
)
{
LONG status;
PVOID callersAddress;
PVOID callersCaller;
status = (LONG)(*SystemRegCreateKeyExW)(
hKey,
lpSubKey,
Reserved,
lpClass,
dwOptions,
samDesired,
lpSecurityAttributes,
phkResult,
lpdwDisposition
);
if ( status == ERROR_SUCCESS ) {
SetHandleTable( *phkResult, TRUE, LeaksRegistry );
}
if ( LeaksVerbose ) {
ClRtlLogPrint(LOG_NOISE, "[LEAKS] RegCreateKeyExW returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
*phkResult,
status,
callersAddress,
callersCaller );
}
return(status);
} // RegCreateKeyExW
LONG
APIENTRY
LEAKS_RegCloseKey(
HKEY hKey
)
{
LONG status;
PVOID callersAddress;
PVOID callersCaller;
status = (LONG)(*SystemRegCloseKey)( hKey );
if ( status == ERROR_SUCCESS ) {
SetHandleTable( hKey, FALSE, LeaksRegistry );
}
if ( LeaksVerbose ) {
ClRtlLogPrint(LOG_NOISE, "[LEAKS] RegCloseKey for key %1!X! returns status %2!u!, called from %3!X! and %4!X!\n",
hKey,
status,
callersAddress,
callersCaller );
}
return(status);
} // RegCloseKey
BOOL
WINAPI
LEAKS_CloseHandle(
IN OUT HANDLE hObject
)
{
PVOID callersAddress;
PVOID callersCaller;
if ( HandleTable[ HINDEX( hObject )].InUse ) {
RtlGetCallersAddress(&callersAddress,
&callersCaller );
HandleTable[ HINDEX( hObject )].InUse = FALSE;
HandleTable[ HINDEX( hObject )].Caller = callersAddress;
HandleTable[ HINDEX( hObject )].CallersCaller = callersCaller;
if ( LeaksVerbose ) {
ClRtlLogPrint(LOG_NOISE, "[LEAKS] CloseHandle for handle %1!X!, called from %2!X! and %3!X!\n",
hObject,
callersAddress,
callersCaller );
}
}
return (BOOL)(*SystemCloseHandle)( hObject );
}
BOOL
WINAPI
LEAKS_OpenProcessToken (
IN HANDLE ProcessHandle,
IN DWORD DesiredAccess,
OUT PHANDLE TokenHandle
)
{
BOOL status;
PVOID callersAddress;
PVOID callersCaller;
status = (BOOL)(*SystemOpenProcessToken)(ProcessHandle,
DesiredAccess,
TokenHandle);
if ( status ) {
SetHandleTable( *TokenHandle, TRUE, LeaksToken );
}
if ( LeaksVerbose ) {
ClRtlLogPrint(LOG_NOISE, "[LEAKS] OpenProcessToken returns handle %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
*TokenHandle,
status,
callersAddress,
callersCaller );
}
return(status);
}
BOOL
WINAPI
LEAKS_OpenThreadToken (
IN HANDLE ThreadHandle,
IN DWORD DesiredAccess,
IN BOOL OpenAsSelf,
OUT PHANDLE TokenHandle
)
{
BOOL status;
PVOID callersAddress;
PVOID callersCaller;
status = (BOOL)(*SystemOpenThreadToken)(ThreadHandle,
DesiredAccess,
OpenAsSelf,
TokenHandle);
if ( status ) {
SetHandleTable( *TokenHandle, TRUE, LeaksToken );
}
if ( LeaksVerbose ) {
ClRtlLogPrint(LOG_NOISE, "[LEAKS] OpenThreadToken returns handle %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
*TokenHandle,
status,
callersAddress,
callersCaller );
}
return(status);
}
BOOL
WINAPI
LEAKS_DuplicateToken(
IN HANDLE ExistingTokenHandle,
IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
OUT PHANDLE DuplicateTokenHandle
)
{
BOOL status;
PVOID callersAddress;
PVOID callersCaller;
status = (BOOL)(*SystemDuplicateToken)(ExistingTokenHandle,
ImpersonationLevel,
DuplicateTokenHandle);
if ( status ) {
SetHandleTable( *DuplicateTokenHandle, TRUE, LeaksToken );
}
if ( LeaksVerbose ) {
ClRtlLogPrint(LOG_NOISE, "[LEAKS] DuplicateToken returns handle %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
*DuplicateTokenHandle,
status,
callersAddress,
callersCaller );
}
return(status);
}
BOOL
WINAPI
LEAKS_DuplicateTokenEx(
IN HANDLE hExistingToken,
IN DWORD dwDesiredAccess,
IN LPSECURITY_ATTRIBUTES lpTokenAttributes,
IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
IN TOKEN_TYPE TokenType,
OUT PHANDLE phNewToken)
{
BOOL status;
PVOID callersAddress;
PVOID callersCaller;
status = (BOOL)(*SystemDuplicateTokenEx)(hExistingToken,
dwDesiredAccess,
lpTokenAttributes,
ImpersonationLevel,
TokenType,
phNewToken);
if ( status ) {
SetHandleTable( *phNewToken, TRUE, LeaksToken );
}
if ( LeaksVerbose ) {
ClRtlLogPrint(LOG_NOISE, "[LEAKS] DuplicateTokenEx returns handle %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
*phNewToken,
status,
callersAddress,
callersCaller );
}
return(status);
}