/*++ Copyright (c) 2000 Microsoft Corporation Module Name: MechWarrior2.cpp Abstract: This shim fixes a problem with MW2 expecting BitBlt to return a specific value, contrary to the published documentation. It also fixes a situation in which a thread calls "SuspendThread" on itself, killing itself. Notes: This shim is specific to Mechwarrior, though potentially some of this could be applied to other apps that use the AIL32 libraries. History: 05/16/2000 dmunsil Created --*/ #include "precomp.h" #include #include #include IMPLEMENT_SHIM_BEGIN(MechWarrior2) #include "ShimHookMacro.h" APIHOOK_ENUM_BEGIN APIHOOK_ENUM_ENTRY(BitBlt) APIHOOK_ENUM_ENTRY(SuspendThread) APIHOOK_ENUM_ENTRY(ResumeThread) APIHOOK_ENUM_END DWORD dwGetThreadID(HANDLE hThread) { THREAD_BASIC_INFORMATION ThreadBasicInfo; NTSTATUS Status; TEB teb; Status = NtQueryInformationThread( hThread, ThreadBasicInformation, &ThreadBasicInfo, sizeof(ThreadBasicInfo), NULL ); if (!NT_SUCCESS(Status)) { DPFN( eDbgLevelError, "NtQueryInfomationThread failed\n"); return 0; } return (DWORD)ThreadBasicInfo.ClientId.UniqueThread; } /*++ Return what Mechwarrior is expecting from BitBlt --*/ BOOL APIHOOK(BitBlt)( HDC hdcDest, // handle to destination DC int nXDest, // x-coord of destination upper-left corner int nYDest, // y-coord of destination upper-left corner int nWidth, // width of destination rectangle int nHeight, // height of destination rectangle HDC hdcSrc, // handle to source DC int nXSrc, // x-coordinate of source upper-left corner int nYSrc, // y-coordinate of source upper-left corner DWORD dwRop // raster operation code ) { BOOL bRet; bRet = ORIGINAL_API(BitBlt)( hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop ); if (bRet) { bRet = 0x1e0; // this is what MechWarrior expects to be returned. } return bRet; } /*++ Disallow suspending self --*/ DWORD APIHOOK(SuspendThread)( HANDLE hThread // handle to the thread ) { // if we're trying to suspend our own thread, refuse if (dwGetThreadID(hThread) != dwGetThreadID(GetCurrentThread())) { return ORIGINAL_API(SuspendThread)(hThread); } else { return 0; } } /*++ Disallow resuming self, for same reason --*/ DWORD APIHOOK(ResumeThread)( HANDLE hThread // handle to the thread ) { // if we're trying to resume our own thread, refuse if (dwGetThreadID(hThread) != dwGetThreadID(GetCurrentThread())) { return ORIGINAL_API(SuspendThread)(hThread); } else { return 0; } } /*++ Register hooked functions --*/ HOOK_BEGIN APIHOOK_ENTRY(GDI32.DLL, BitBlt ) APIHOOK_ENTRY(Kernel32.DLL, SuspendThread ) APIHOOK_ENTRY(Kernel32.DLL, ResumeThread ) HOOK_END IMPLEMENT_SHIM_END