windows-nt/Source/XPSP1/NT/windows/appcompat/shims/general/ignorefreelibrary.cpp
2020-09-26 16:20:57 +08:00

144 lines
2.7 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
IgnoreFreeLibrary.cpp
Abstract:
Some applications free DLLs before they're actually ready to. When this occurs,
if the offending application attempts to make a call to an exported function,
the call fails. This results in an access violation.
This shim takes a command line of ; delimited DLL names. For each DLL on the command
line, a call to FreeLibrary for the specified DLL will be ignored.
Example:
xanim.dll
video_3dfx.dll;glide.dll
Notes:
This is a general purpose shim.
History:
10/31/2000 rparsons Created
--*/
#include "precomp.h"
IMPLEMENT_SHIM_BEGIN(IgnoreFreeLibrary)
#include "ShimHookMacro.h"
APIHOOK_ENUM_BEGIN
APIHOOK_ENUM_ENTRY(FreeLibrary)
APIHOOK_ENUM_END
#define MAX_FILES 64
int g_nLibraryCountFreeLibrary = 0;
CString * g_rgLibrariesToIgnoreFreeLibrary = NULL;
/*++
Hook the call to FreeLibrary. Determine if the file name that corresponds to this
module should be ignored.
--*/
BOOL
APIHOOK(FreeLibrary)(
HMODULE hModule
)
{
CSTRING_TRY
{
CString csModule;
csModule.GetModuleFileNameW(hModule);
CString csFileName;
csModule.GetLastPathComponent(csFileName);
for (int i = 0; i < g_nLibraryCountFreeLibrary; ++i)
{
if (csFileName.CompareNoCase(g_rgLibrariesToIgnoreFreeLibrary[i]) == 0)
{
DPFN( eDbgLevelInfo, "Caught attempt freeing %S\n", csModule.Get());
return TRUE;
}
}
}
CSTRING_CATCH
{
// Do Nothing
}
return ORIGINAL_API(FreeLibrary)(hModule);
}
/*++
This function parses the COMMAND_LINE for the libraries that should
have their FreeLibrary call ignored.
--*/
BOOL ParseCommandLine()
{
CSTRING_TRY
{
CString csCl(COMMAND_LINE);
CStringParser csParser(csCl, L";");
g_nLibraryCountFreeLibrary = csParser.GetCount();
g_rgLibrariesToIgnoreFreeLibrary = csParser.ReleaseArgv();
}
CSTRING_CATCH
{
return FALSE;
}
for (int i = 0; i < g_nLibraryCountFreeLibrary; ++i) {
DPFN( eDbgLevelInfo, "Library %d: name: --%S--\n", i, g_rgLibrariesToIgnoreFreeLibrary[i].Get());
}
return TRUE;
}
BOOL
NOTIFY_FUNCTION(
DWORD fdwReason
)
{
if (fdwReason == DLL_PROCESS_ATTACH) {
return ParseCommandLine();
}
return TRUE;
}
/*++
Register hooked functions
--*/
HOOK_BEGIN
CALL_NOTIFY_FUNCTION
APIHOOK_ENTRY(KERNEL32.DLL, FreeLibrary)
HOOK_END
IMPLEMENT_SHIM_END