Windows2003-3790/windows/appcompat/shims/general/heapdelaylocalfree.cpp
2020-09-30 16:53:55 +02:00

144 lines
3.0 KiB
C++

/*++
Copyright (c) 2000-2002 Microsoft Corporation
Module Name:
HeapDelayLocalFree.cpp
Abstract:
Delay calls to LocalFree.
History:
09/19/2000 robkenny
02/12/2002 robkenny Convert InitializeCriticalSection to InitializeCriticalSectionAndSpinCount
and checking return status to verify that critical section was
actually created.
Shim was deallocating memory in SHIM_PROCESS_DETACH, which can
cause the shim to crash when the process is exiting, since there
is not guarantee that the shim will not be called from other
libraries afterwards.
--*/
#include "precomp.h"
#include "CharVector.h"
IMPLEMENT_SHIM_BEGIN(HeapDelayLocalFree)
#include "ShimHookMacro.h"
APIHOOK_ENUM_BEGIN
APIHOOK_ENUM_ENTRY(LocalFree)
APIHOOK_ENUM_END
CRITICAL_SECTION g_CritSec;
static VectorT<HLOCAL> *g_DelayLocal = NULL;
static DWORD g_DelayBufferSize = 20;
HLOCAL
APIHOOK(LocalFree)(
HLOCAL hMem // handle to local memory object
)
{
if (hMem == NULL)
return NULL;
if (g_DelayLocal)
{
EnterCriticalSection(&g_CritSec);
// If the list is full
if (g_DelayLocal->Size() > 0 &&
g_DelayLocal->Size() >= g_DelayLocal->MaxSize())
{
HLOCAL & hDelayed = g_DelayLocal->Get(0);
#if DBG
DPFN(eDbgLevelInfo, "LocalFree(0x%08x).", hDelayed);
#endif
ORIGINAL_API(LocalFree)(hDelayed);
g_DelayLocal->Remove(0);
}
g_DelayLocal->Append(hMem);
#if DBG
DPFN(eDbgLevelInfo, "Delaying LocalFree(0x%08x).", hMem);
#endif
LeaveCriticalSection(&g_CritSec);
return NULL;
}
HLOCAL returnValue = ORIGINAL_API(LocalFree)(hMem);
return returnValue;
}
BOOL ParseCommandLine(const char * /*commandLine*/)
{
// Preallocate the event, prevents EnterCriticalSection
// from throwing an exception in low-memory situations.
if (!InitializeCriticalSectionAndSpinCount(&g_CritSec, 0x8000000))
{
return FALSE;
}
g_DelayLocal = new VectorT<HLOCAL>;
if (g_DelayLocal)
{
// If we cannot resize the array, stop now
if (!g_DelayLocal->Resize(g_DelayBufferSize))
{
delete g_DelayLocal;
g_DelayLocal = NULL;
// Turn off all hooks:
return FALSE;
}
}
return TRUE;
}
/*++
Register hooked functions
--*/
BOOL
NOTIFY_FUNCTION(
DWORD fdwReason
)
{
if (fdwReason == DLL_PROCESS_ATTACH)
{
return ParseCommandLine(COMMAND_LINE);
}
return TRUE;
}
/*++
Register hooked functions
--*/
HOOK_BEGIN
CALL_NOTIFY_FUNCTION
APIHOOK_ENTRY(KERNEL32.DLL, LocalFree)
HOOK_END
IMPLEMENT_SHIM_END