|
|
/*++
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); }
|