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

293 lines
7.4 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
IgnoreLoadLibrary.cpp
Abstract:
This shim allows the user to specified a list of libraries it tries to ignore and
optionally the return values of the LoadLibrary call. Some apps try to load libraries
they don't use but expect the LoadLibrary call to succeed.
Use ; as the delimeter of the item and optionally use : to specify the return value.
If you don't specify a return value we'll make the return value NULL.
Eg:
video_3dfx.dll;video_3dfx
helper32.dll:1234;helper.dll
Notes:
This is a general purpose shim.
History:
04/13/2000 a-jamd Created
10/11/2000 maonis Added support for specifying return values and renamed it from
FailLoadLibrary to IgnoreLoadLibrary.
11/16/2000 linstev Added SetErrorMode emulation
--*/
#include "precomp.h"
IMPLEMENT_SHIM_BEGIN(IgnoreLoadLibrary)
#include "ShimHookMacro.h"
// Globals are zero initialized by default. see c++ spec 3.6.2.
CString * g_csIgnoreLib;
int g_csIgnoreLibCount;
DWORD * g_rgReturnValues;
APIHOOK_ENUM_BEGIN
APIHOOK_ENUM_ENTRY(LoadLibraryA)
APIHOOK_ENUM_ENTRY(LoadLibraryExA)
APIHOOK_ENUM_ENTRY(LoadLibraryW)
APIHOOK_ENUM_ENTRY(LoadLibraryExW)
APIHOOK_ENUM_END
/*++
This function parses the COMMAND_LINE for the libraries you wish to ignore.
--*/
BOOL ParseCommandLine(LPCSTR lpszCommandLine)
{
CSTRING_TRY
{
DPF(g_szModuleName, eDbgLevelInfo, "[ParseCommandLine] CommandLine(%s)\n", lpszCommandLine);
CString csCl(lpszCommandLine);
CStringParser csParser(csCl, L" ;");
g_csIgnoreLibCount = csParser.GetCount();
g_csIgnoreLib = csParser.ReleaseArgv();
g_rgReturnValues = (DWORD *)malloc(sizeof(*g_rgReturnValues) * g_csIgnoreLibCount);
if (g_csIgnoreLibCount && !g_rgReturnValues)
{
return FALSE;
}
// Iterate over all strings looking for a return value
for (int i = 0; i < g_csIgnoreLibCount; ++i)
{
CStringToken csIgnore(g_csIgnoreLib[i], L":");
CString csLib;
CString csValue;
csIgnore.GetToken(csLib);
csIgnore.GetToken(csValue);
if (!csValue.IsEmpty())
{
WCHAR *unused;
g_csIgnoreLib[i] = csLib;
g_rgReturnValues[i] = wcstol(csValue, &unused, 10);
}
DPF(g_szModuleName, eDbgLevelInfo, "[ParseCommandLine] library (%S) return value(%d)\n", g_csIgnoreLib[i].Get(), g_rgReturnValues[i]);
}
return TRUE;
}
CSTRING_CATCH
{
// Do nothing.
}
return FALSE;
}
/*++
These stub functions break into LoadLibrary and check to see if lpLibFileName equals
one of the specified dll's. If so return the specified return value. If not call LoadLibrary on it.
--*/
HINSTANCE
APIHOOK(LoadLibraryA)(LPCSTR lpLibFileName)
{
CSTRING_TRY
{
CString csFilePath(lpLibFileName);
CString csFileName;
csFilePath.GetLastPathComponent(csFileName);
for (int i = 0; i < g_csIgnoreLibCount; i++)
{
if (g_csIgnoreLib[i].CompareNoCase(csFileName) == 0)
{
LOG(g_szModuleName,eDbgLevelError, "[LoadLibraryA] Caught attempt loading %s, return %d\n", g_csIgnoreLib[i].Get(), g_rgReturnValues[i]);
return (HINSTANCE) g_rgReturnValues[i];
}
}
}
CSTRING_CATCH
{
// Do Nothing
}
DPF(g_szModuleName, eDbgLevelSpew, "LoadLibraryA Allow(%s)", lpLibFileName);
UINT uLastMode;
HINSTANCE hRet;
uLastMode = SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
hRet = ORIGINAL_API(LoadLibraryA)(lpLibFileName);
SetErrorMode(uLastMode);
return hRet;
}
HINSTANCE
APIHOOK(LoadLibraryExA)(
LPCSTR lpLibFileName,
HANDLE hFile,
DWORD dwFlags
)
{
CSTRING_TRY
{
CString csFilePath(lpLibFileName);
CString csFileName;
csFilePath.GetLastPathComponent(csFileName);
for (int i = 0; i < g_csIgnoreLibCount; i++)
{
if (g_csIgnoreLib[i].CompareNoCase(csFileName) == 0)
{
LOG(g_szModuleName,eDbgLevelError, "[LoadLibraryExA] Caught attempt loading %s, return %d\n", g_csIgnoreLib[i].Get(), g_rgReturnValues[i]);
return (HINSTANCE) g_rgReturnValues[i];
}
}
}
CSTRING_CATCH
{
// Do Nothing
}
DPF(g_szModuleName, eDbgLevelSpew, "LoadLibraryExA Allow(%s)", lpLibFileName);
UINT uLastMode;
HINSTANCE hRet;
uLastMode = SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
hRet = ORIGINAL_API(LoadLibraryExA)(lpLibFileName, hFile, dwFlags);
SetErrorMode(uLastMode);
return hRet;
}
HINSTANCE
APIHOOK(LoadLibraryW)(LPCWSTR lpLibFileName)
{
CSTRING_TRY
{
CString csFilePath(lpLibFileName);
CString csFileName;
csFilePath.GetLastPathComponent(csFileName);
for (int i = 0; i < g_csIgnoreLibCount; i++)
{
if (g_csIgnoreLib[i].CompareNoCase(csFileName) == 0)
{
LOG(g_szModuleName,eDbgLevelError, "[LoadLibraryW] Caught attempt loading %s, return %d\n", g_csIgnoreLib[i].Get(), g_rgReturnValues[i]);
return (HINSTANCE) g_rgReturnValues[i];
}
}
}
CSTRING_CATCH
{
// Do Nothing
}
DPF(g_szModuleName, eDbgLevelSpew,"LoadLibraryW Allow(%S)", lpLibFileName);
UINT uLastMode;
HINSTANCE hRet;
uLastMode = SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
hRet = ORIGINAL_API(LoadLibraryW)(lpLibFileName);
SetErrorMode(uLastMode);
return hRet;
}
HINSTANCE
APIHOOK(LoadLibraryExW)(
LPCWSTR lpLibFileName,
HANDLE hFile,
DWORD dwFlags
)
{
CSTRING_TRY
{
CString csFilePath(lpLibFileName);
CString csFileName;
csFilePath.GetLastPathComponent(csFileName);
for (int i = 0; i < g_csIgnoreLibCount; i++)
{
if (g_csIgnoreLib[i].CompareNoCase(csFileName) == 0)
{
LOG(g_szModuleName,eDbgLevelError, "[LoadLibraryExW] Caught attempt loading %s, return %d\n", g_csIgnoreLib[i].Get(), g_rgReturnValues[i]);
return (HINSTANCE) g_rgReturnValues[i];
}
}
}
CSTRING_CATCH
{
// Do Nothing
}
DPF(g_szModuleName, eDbgLevelSpew,"APIHook_LoadLibraryExW Allow(%S)", lpLibFileName);
UINT uLastMode;
HINSTANCE hRet;
uLastMode = SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
hRet = ORIGINAL_API(LoadLibraryExW)(lpLibFileName, hFile, dwFlags);
SetErrorMode(uLastMode);
return hRet;
}
/*++
Register hooked functions
--*/
BOOL
NOTIFY_FUNCTION(
DWORD fdwReason)
{
if (fdwReason == DLL_PROCESS_ATTACH)
{
ParseCommandLine(COMMAND_LINE);
}
return TRUE;
}
HOOK_BEGIN
CALL_NOTIFY_FUNCTION
APIHOOK_ENTRY(KERNEL32.DLL, LoadLibraryA)
APIHOOK_ENTRY(KERNEL32.DLL, LoadLibraryExA)
APIHOOK_ENTRY(KERNEL32.DLL, LoadLibraryW)
APIHOOK_ENTRY(KERNEL32.DLL, LoadLibraryExW)
HOOK_END
IMPLEMENT_SHIM_END