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

376 lines
9.7 KiB
C++

/*
Copyright (c) 2001 Microsoft Corporation
Module Name:
SMSDeadlock.cpp
Abstract:
SMS experiences a deadlock due to its loading a module that tries to take
MFC42's AfxResourceLock during DllMain when the LoaderLock is held.
MFC42's established locking-order is FIRST take the AfxResourceLock, and
SECONDLY take the loader lock.
This shim tries to right the order of lock-taking by taking the
AfxResourceLock prior to allowing LoadLibrary and FreeLibrary calls.
Thus the order of lock acquisition is righted.
DLL's for which LoadLibrary takes the Afx lock are specified on the
command line and separated by semi-colons. A blank command line indicates
that ALL modules should take the lock.
NOTE: Every module in a process (including system) should be shimmed by
this shim. The dlls specified in the command line are the TARGETS of
LoadLibrary for which we should take the AfxResource lock. To actually
make that switch no matter who calls LoadLibrary, we must shim all
modules.
History:
09/26/2002 astritz Created
*/
#include "precomp.h"
IMPLEMENT_SHIM_BEGIN(SMSDeadlock)
#include "ShimHookMacro.h"
typedef void (AFXAPI * _pfn_AfxLockGlobals)(int nLockType);
typedef void (AFXAPI * _pfn_AfxUnlockGlobals)(int nLockType);
_pfn_AfxLockGlobals g_pfnAfxLockGlobals = NULL;
_pfn_AfxUnlockGlobals g_pfnAfxUnlockGlobals = NULL;
CString * g_csLockLib = NULL;
int g_csLockLibCount = NULL;
APIHOOK_ENUM_BEGIN
APIHOOK_ENUM_ENTRY(LoadLibraryA)
APIHOOK_ENUM_ENTRY(LoadLibraryExA)
APIHOOK_ENUM_ENTRY(LoadLibraryW)
APIHOOK_ENUM_ENTRY(LoadLibraryExW)
APIHOOK_ENUM_ENTRY(FreeLibrary)
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_csLockLibCount = csParser.GetCount();
g_csLockLib = csParser.ReleaseArgv();
return TRUE;
}
CSTRING_CATCH
{
// Do nothing.
}
return FALSE;
}
HINSTANCE
APIHOOK(LoadLibraryA)(
LPCSTR lpLibFileName
)
{
HINSTANCE hRet;
BOOL bTakeLock = FALSE;
if( g_pfnAfxLockGlobals && g_pfnAfxUnlockGlobals ) {
if( g_csLockLibCount == 0 ) {
bTakeLock = TRUE;
} else {
CSTRING_TRY
{
CString csFilePath(lpLibFileName);
CString csFileName;
csFilePath.GetLastPathComponent(csFileName);
for (int i = 0; i < g_csLockLibCount; i++)
{
if (g_csLockLib[i].CompareNoCase(csFileName) == 0)
{
LOG(g_szModuleName,eDbgLevelError, "[LoadLibraryA] Caught attempt loading %ls, taking AfxResourceLock.", g_csLockLib[i].Get());
bTakeLock = TRUE;
break;
}
}
}
CSTRING_CATCH
{
// Do Nothing
}
}
}
if( bTakeLock ) {
(*g_pfnAfxLockGlobals)(0);
}
hRet = ORIGINAL_API(LoadLibraryA)(lpLibFileName);
if( bTakeLock ) {
(*g_pfnAfxUnlockGlobals)(0);
}
return hRet;
}
HINSTANCE
APIHOOK(LoadLibraryW)(
LPCWSTR lpLibFileName
)
{
HINSTANCE hRet;
BOOL bTakeLock = FALSE;
if( g_pfnAfxLockGlobals && g_pfnAfxUnlockGlobals ) {
if( g_csLockLibCount == 0 ) {
bTakeLock = TRUE;
} else {
CSTRING_TRY
{
CString csFilePath(lpLibFileName);
CString csFileName;
csFilePath.GetLastPathComponent(csFileName);
for (int i = 0; i < g_csLockLibCount; i++)
{
if (g_csLockLib[i].CompareNoCase(csFileName) == 0)
{
LOG(g_szModuleName,eDbgLevelError, "[LoadLibraryW] Caught attempt loading %ls, taking AfxResourceLock.", g_csLockLib[i].Get());
bTakeLock = TRUE;
break;
}
}
}
CSTRING_CATCH
{
// Do Nothing
}
}
}
if( bTakeLock ) {
(*g_pfnAfxLockGlobals)(0);
}
hRet = ORIGINAL_API(LoadLibraryW)(lpLibFileName);
if( bTakeLock ) {
(*g_pfnAfxUnlockGlobals)(0);
}
return hRet;
}
HINSTANCE
APIHOOK(LoadLibraryExA)(
LPCSTR lpLibFileName,
HANDLE hFile,
DWORD dwFlags
)
{
HINSTANCE hRet;
BOOL bTakeLock = FALSE;
if( g_pfnAfxLockGlobals && g_pfnAfxUnlockGlobals ) {
if( g_csLockLibCount == 0 ) {
bTakeLock = TRUE;
} else {
CSTRING_TRY
{
CString csFilePath(lpLibFileName);
CString csFileName;
csFilePath.GetLastPathComponent(csFileName);
for (int i = 0; i < g_csLockLibCount; i++)
{
if (g_csLockLib[i].CompareNoCase(csFileName) == 0)
{
LOG(g_szModuleName,eDbgLevelError, "[LoadLibraryExA] Caught attempt loading %ls, taking AfxResourceLock.", g_csLockLib[i].Get());
bTakeLock = TRUE;
break;
}
}
}
CSTRING_CATCH
{
// Do Nothing
}
}
}
if( bTakeLock ) {
(*g_pfnAfxLockGlobals)(0);
}
hRet = ORIGINAL_API(LoadLibraryExA)(lpLibFileName, hFile, dwFlags);
if( bTakeLock ) {
(*g_pfnAfxUnlockGlobals)(0);
}
return hRet;
}
HINSTANCE
APIHOOK(LoadLibraryExW)(
LPCWSTR lpLibFileName,
HANDLE hFile,
DWORD dwFlags
)
{
HINSTANCE hRet;
BOOL bTakeLock = FALSE;
if( g_pfnAfxLockGlobals && g_pfnAfxUnlockGlobals ) {
if( g_csLockLibCount == 0 ) {
bTakeLock = TRUE;
} else {
CSTRING_TRY
{
CString csFilePath(lpLibFileName);
CString csFileName;
csFilePath.GetLastPathComponent(csFileName);
for (int i = 0; i < g_csLockLibCount; i++)
{
if (g_csLockLib[i].CompareNoCase(csFileName) == 0)
{
LOG(g_szModuleName,eDbgLevelError, "[LoadLibraryExW] Caught attempt loading %ls, taking AfxResourceLock.", g_csLockLib[i].Get());
bTakeLock = TRUE;
break;
}
}
}
CSTRING_CATCH
{
// Do Nothing
}
}
}
if( bTakeLock ) {
(*g_pfnAfxLockGlobals)(0);
}
hRet = ORIGINAL_API(LoadLibraryExW)(lpLibFileName, hFile, dwFlags);
if( bTakeLock ) {
(*g_pfnAfxUnlockGlobals)(0);
}
return hRet;
}
BOOL
APIHOOK(FreeLibrary)(
HMODULE hModule
)
{
BOOL bTakeLock = FALSE;
BOOL bRet;
if( g_pfnAfxLockGlobals && g_pfnAfxUnlockGlobals ) {
if( g_csLockLibCount == 0 ) {
bTakeLock = TRUE;
} else {
WCHAR wszModule[MAX_PATH];
if( GetModuleFileNameW(hModule, wszModule, MAX_PATH) ) {
CSTRING_TRY
{
CString csFilePath(wszModule);
CString csFileName;
csFilePath.GetLastPathComponent(csFileName);
for (int i = 0; i < g_csLockLibCount; i++)
{
if (g_csLockLib[i].CompareNoCase(csFileName) == 0)
{
LOG(g_szModuleName,eDbgLevelError, "[FreeLibrary] Caught attempt freeing %ls, taking AfxResourceLock.", g_csLockLib[i].Get());
bTakeLock = TRUE;
break;
}
}
}
CSTRING_CATCH
{
// Do Nothing
}
}
}
}
if( bTakeLock ) {
(*g_pfnAfxLockGlobals)(0);
}
bRet = ORIGINAL_API(FreeLibrary)(hModule);
if( bTakeLock ) {
(*g_pfnAfxUnlockGlobals)(0);
}
return bRet;
}
/*++
Register hooked functions
--*/
BOOL
NOTIFY_FUNCTION(
DWORD fdwReason
)
{
if( fdwReason == DLL_PROCESS_ATTACH )
{
ParseCommandLine(COMMAND_LINE);
}
else if( fdwReason == SHIM_STATIC_DLLS_INITIALIZED )
{
HMODULE hMod = LoadLibraryW(L"MFC42.DLL");
if( NULL != hMod )
{
g_pfnAfxLockGlobals = (_pfn_AfxLockGlobals)GetProcAddress(hMod, (LPCSTR)1196);
g_pfnAfxUnlockGlobals = (_pfn_AfxUnlockGlobals)GetProcAddress(hMod, (LPCSTR)1569);
}
}
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)
APIHOOK_ENTRY(KERNEL32.DLL, FreeLibrary)
HOOK_END
IMPLEMENT_SHIM_END