You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
5.3 KiB
197 lines
5.3 KiB
/*==========================================================================
|
|
*
|
|
* Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: dibpatch.c
|
|
* Content: Code to patch the DIB engine to correct problems with using
|
|
* the VRAM bit to disable the video card's accelerator.
|
|
*
|
|
*@@BEGIN_MSINTERNAL
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 13-Sep-96 colinmc initial implementation
|
|
* 31-jan-97 colinmc Bug 5457: Fixed Win16 lock problem causing hang
|
|
* with mutliple AMovie instances on old cards
|
|
*@@END_MSINTERNAL
|
|
*
|
|
***************************************************************************/
|
|
#include "ddraw16.h"
|
|
|
|
extern UINT FAR PASCAL AllocCStoDSAlias(UINT);
|
|
|
|
#define DIBENGMODULE "DIBENG"
|
|
#define EXTTEXTOUTENTRYPOINT "DIB_EXTTEXTOUTEXT"
|
|
#define EXTTEXTOUTPATCHOFFSET 136
|
|
|
|
char szExtTextOutMagic[] = "\x74\x0a\xf7\x86\x60\xff\x00\x80";
|
|
char szExtTextOutPatch[] = "\x90\x90\x90\x90\x90\x90\x90\x90";
|
|
|
|
LPVOID GetModifiableCodeAddress(LPCSTR lpszModuleName, LPCSTR lpszEntryPointName)
|
|
{
|
|
HMODULE hModule;
|
|
FARPROC fpEntryPoint;
|
|
LPVOID lpCodeAddress;
|
|
|
|
hModule = GetModuleHandle(lpszModuleName);
|
|
if (NULL == hModule)
|
|
{
|
|
DPF(0, "DIB Engine not loaded");
|
|
return NULL;
|
|
}
|
|
|
|
fpEntryPoint = GetProcAddress(hModule, lpszEntryPointName);
|
|
if (NULL == fpEntryPoint)
|
|
{
|
|
DPF(0, "Could not locate DIB engine's ExtTextOut entry point");
|
|
return FALSE;
|
|
}
|
|
|
|
lpCodeAddress = (LPVOID)MAKELP(AllocCStoDSAlias(SELECTOROF(fpEntryPoint)), OFFSETOF(fpEntryPoint));
|
|
if (NULL == lpCodeAddress)
|
|
{
|
|
DPF(0, "Could not allocate data segment alias for code segment");
|
|
return FALSE;
|
|
}
|
|
|
|
return lpCodeAddress;
|
|
}
|
|
|
|
#define FREEMODIFIABLECODEADDRESS(lpCodeAddress) FreeSelector(SELECTOROF(lpCodeAddress))
|
|
|
|
BOOL ValidateDIBEngine(void)
|
|
{
|
|
LPBYTE lpCodeAddress;
|
|
LPBYTE lpMagicAddress;
|
|
BOOL fDIBEngineOK;
|
|
|
|
/*
|
|
* Get a pointer to the ExtTextOut code.
|
|
*/
|
|
lpCodeAddress = (LPBYTE)GetModifiableCodeAddress(DIBENGMODULE, EXTTEXTOUTENTRYPOINT);
|
|
if (NULL == lpCodeAddress)
|
|
return FALSE;
|
|
|
|
/*
|
|
* Move to the patch address.
|
|
*/
|
|
lpMagicAddress = lpCodeAddress + EXTTEXTOUTPATCHOFFSET;
|
|
|
|
/*
|
|
* Verify that the data at the patch address is the stuff we want to replace.
|
|
*/
|
|
fDIBEngineOK = (!_fmemcmp(lpMagicAddress, szExtTextOutMagic, sizeof(szExtTextOutMagic) - 1));
|
|
if (!fDIBEngineOK)
|
|
{
|
|
/*
|
|
* Couldn't find the signature bytes we are looking for. This might be because we
|
|
* already patched it. So check for the no-ops.
|
|
*/
|
|
fDIBEngineOK = (!_fmemcmp(lpMagicAddress, szExtTextOutPatch, sizeof(szExtTextOutPatch) - 1));
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
if (!fDIBEngineOK)
|
|
DPF(2, "DIB Engine does not match magic or patch - different version?");
|
|
#endif
|
|
|
|
FREEMODIFIABLECODEADDRESS(lpMagicAddress);
|
|
|
|
return fDIBEngineOK;
|
|
}
|
|
|
|
BOOL PatchDIBEngineExtTextOut(BOOL fPatch)
|
|
{
|
|
LPBYTE lpCodeAddress;
|
|
LPBYTE lpMagicAddress;
|
|
|
|
/*
|
|
* Get a pointer to the ExtTextOut code.
|
|
*/
|
|
lpCodeAddress = (LPBYTE)GetModifiableCodeAddress(DIBENGMODULE, EXTTEXTOUTENTRYPOINT);
|
|
if (NULL == lpCodeAddress)
|
|
return FALSE;
|
|
|
|
/*
|
|
* Move to the patch address.
|
|
*/
|
|
lpMagicAddress = lpCodeAddress + EXTTEXTOUTPATCHOFFSET;
|
|
|
|
if (fPatch)
|
|
{
|
|
/*
|
|
* Don't do anything if its already patched.
|
|
*/
|
|
if (_fmemcmp(lpMagicAddress, szExtTextOutPatch, sizeof(szExtTextOutPatch) - 1))
|
|
{
|
|
/*
|
|
* Be very sure we know we are dealing with a DIB engine we can handle.
|
|
*/
|
|
if (_fmemcmp(lpMagicAddress, szExtTextOutMagic, sizeof(szExtTextOutMagic) - 1))
|
|
{
|
|
DPF(1, "Unknown DIB Engine. not fixing up");
|
|
FREEMODIFIABLECODEADDRESS(lpMagicAddress);
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Replace the offending code with NOPs.
|
|
*/
|
|
_fmemcpy(lpMagicAddress, szExtTextOutPatch, sizeof(szExtTextOutPatch) - 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Don't do anything if its already unpatched.
|
|
*/
|
|
if (!_fmemcmp(lpMagicAddress, szExtTextOutMagic, sizeof(szExtTextOutMagic) - 1))
|
|
{
|
|
/*
|
|
* Be very sure we know we are dealing with a DIB engine we can handle.
|
|
*/
|
|
if (_fmemcmp(lpMagicAddress, szExtTextOutPatch, sizeof(szExtTextOutPatch) - 1))
|
|
{
|
|
DPF(1, "Unknown DIB Engine. not fixing up");
|
|
FREEMODIFIABLECODEADDRESS(lpMagicAddress);
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Put the original code back.
|
|
*/
|
|
_fmemcpy(lpMagicAddress, szExtTextOutMagic, sizeof(szExtTextOutMagic) - 1);
|
|
}
|
|
}
|
|
|
|
FREEMODIFIABLECODEADDRESS(lpMagicAddress);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL DDAPI DD16_FixupDIBEngine(void)
|
|
{
|
|
/*
|
|
* Is this Win 4.1 (or higher)
|
|
*/
|
|
OSVERSIONINFO ver = {sizeof(OSVERSIONINFO)};
|
|
GetVersionEx(&ver);
|
|
|
|
if (ver.dwMajorVersion > 4 ||
|
|
(ver.dwMajorVersion == 4 && ver.dwMinorVersion >= 10))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* Is this a DIB engine version we can work with?
|
|
*/
|
|
if( !ValidateDIBEngine() )
|
|
return FALSE;
|
|
|
|
/*
|
|
* It is the correct version. So fix it up. Currently all this
|
|
* involves is patching the ExtTextOut routine.
|
|
*/
|
|
return PatchDIBEngineExtTextOut(TRUE);
|
|
}
|