157 lines
3.1 KiB
C++
157 lines
3.1 KiB
C++
/*++
|
|
|
|
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 <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
|
|
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
|
|
|