mirror of
https://github.com/FunkyFr3sh/cnc-ddraw.git
synced 2025-03-15 06:04:49 +01:00
sync with master
This commit is contained in:
parent
c9229738ec
commit
0a779ac4fe
16
Makefile
16
Makefile
@ -1,7 +1,9 @@
|
||||
CC=gcc
|
||||
WINDRES=windres
|
||||
CFLAGS=-Iinc -Wall -Wl,--enable-stdcall-fixup -s
|
||||
LIBS=-lgdi32 -lwinmm
|
||||
-include config.mk
|
||||
|
||||
WINDRES ?= windres
|
||||
LDFLAGS = -Iinc -Wall -Wl,--enable-stdcall-fixup -s
|
||||
CFLAGS = -std=c99
|
||||
LIBS = -lgdi32 -lwinmm
|
||||
|
||||
FILES = src/debug.c \
|
||||
src/main.c \
|
||||
@ -21,8 +23,8 @@ FILES = src/debug.c \
|
||||
|
||||
all:
|
||||
$(WINDRES) -J rc ddraw.rc ddraw.rc.o
|
||||
$(CC) $(CFLAGS) -shared -o ddraw.dll $(FILES) ddraw.def ddraw.rc.o $(LIBS)
|
||||
# $(CC) $(CFLAGS) -nostdlib -shared -o ddraw.dll $(FILES) ddraw.def ddraw.rc.o $(LIBS) -lkernel32 -luser32 -lmsvcrt
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -shared -o ddraw.dll $(FILES) ddraw.def ddraw.rc.o $(LIBS)
|
||||
# $(CC) $(CFLAGS) $(LDFLAGS) -nostdlib -shared -o ddraw.dll $(FILES) ddraw.def ddraw.rc.o $(LIBS) -lkernel32 -luser32 -lmsvcrt
|
||||
|
||||
clean:
|
||||
rm -f ddraw.dll
|
||||
$(RM) ddraw.dll ddraw.rc.o
|
||||
|
@ -13,6 +13,19 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\clipper.c" />
|
||||
<ClCompile Include="src\debug.c" />
|
||||
<ClCompile Include="src\detours\creatwth.cpp" />
|
||||
<ClCompile Include="src\detours\detours.cpp" />
|
||||
<ClCompile Include="src\detours\disasm.cpp" />
|
||||
<ClCompile Include="src\detours\disolarm.cpp" />
|
||||
<ClCompile Include="src\detours\disolarm64.cpp" />
|
||||
<ClCompile Include="src\detours\disolia64.cpp" />
|
||||
<ClCompile Include="src\detours\disolx64.cpp" />
|
||||
<ClCompile Include="src\detours\disolx86.cpp" />
|
||||
<ClCompile Include="src\detours\image.cpp" />
|
||||
<ClCompile Include="src\detours\modules.cpp" />
|
||||
<ClCompile Include="src\detours\uimports.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dinput.c" />
|
||||
<ClCompile Include="src\hook.c" />
|
||||
<ClCompile Include="src\lodepng.c" />
|
||||
@ -99,7 +112,7 @@
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<AdditionalIncludeDirectories>inc</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>inc;src\detours</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@ -124,7 +137,7 @@ if exist "$(LocalDebuggerCommand)" if exist "$(LocalDebuggerWorkingDirectory)"
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<AdditionalIncludeDirectories>inc</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>inc;src\detours</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -13,6 +13,9 @@
|
||||
<UniqueIdentifier>{9b152f9d-a092-42a9-ac47-0594f135a640}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\detours">
|
||||
<UniqueIdentifier>{af194dd7-3316-4887-93d6-9f2af2135f94}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\clipper.c">
|
||||
@ -60,6 +63,39 @@
|
||||
<ClCompile Include="src\hook.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\detours\disolx64.cpp">
|
||||
<Filter>Source Files\detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\detours\disolx86.cpp">
|
||||
<Filter>Source Files\detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\detours\image.cpp">
|
||||
<Filter>Source Files\detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\detours\modules.cpp">
|
||||
<Filter>Source Files\detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\detours\uimports.cpp">
|
||||
<Filter>Source Files\detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\detours\creatwth.cpp">
|
||||
<Filter>Source Files\detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\detours\detours.cpp">
|
||||
<Filter>Source Files\detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\detours\disasm.cpp">
|
||||
<Filter>Source Files\detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\detours\disolarm.cpp">
|
||||
<Filter>Source Files\detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\detours\disolarm64.cpp">
|
||||
<Filter>Source Files\detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\detours\disolia64.cpp">
|
||||
<Filter>Source Files\detours</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="inc\clipper.h">
|
||||
|
2
ddraw.rc
2
ddraw.rc
@ -4,7 +4,7 @@
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 3
|
||||
#define VERSION_BUILD 4
|
||||
#define VERSION_REVISION 1
|
||||
#define VERSION_REVISION 3
|
||||
|
||||
#define VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION
|
||||
#define VERSION_STRING ver_str(VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION)
|
||||
|
@ -8,6 +8,7 @@ double CounterStop();
|
||||
void DebugPrint(const char *format, ...);
|
||||
void DrawFrameInfoStart();
|
||||
void DrawFrameInfoEnd();
|
||||
int dprintf(const char *fmt, ...);
|
||||
|
||||
extern double DebugFrameTime;
|
||||
extern DWORD DebugFrameCount;
|
||||
@ -24,6 +25,8 @@ extern DWORD DebugFrameCount;
|
||||
|
||||
#ifdef _DEBUG_S
|
||||
#define printf(format, ...) DebugPrint("xDBG " format, ##__VA_ARGS__)
|
||||
#else
|
||||
#define printf(format, ...) dprintf(format, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
typedef HFONT(__stdcall* CREATEFONTINDIRECTA)(CONST LOGFONT*);
|
||||
|
||||
typedef BOOL (WINAPI* GETCURSORPOSPROC)(LPPOINT);
|
||||
typedef BOOL(WINAPI* CLIPCURSORPROC)(const RECT*);
|
||||
typedef int (WINAPI* SHOWCURSORPROC)(BOOL);
|
||||
@ -45,11 +47,13 @@ extern ENABLEWINDOWPROC real_EnableWindow;
|
||||
extern CREATEWINDOWEXAPROC real_CreateWindowExA;
|
||||
extern DESTROYWINDOWPROC real_DestroyWindow;
|
||||
|
||||
extern int HookingMethod;
|
||||
extern BOOL Hook_Active;
|
||||
|
||||
void Hook_Init();
|
||||
void Hook_Exit();
|
||||
void Hook_PatchIAT(HMODULE hMod, char *moduleName, char *functionName, PROC newFunction);
|
||||
PROC Hook_HotPatch(PROC function, PROC newFunction);
|
||||
void Hook_TryHotPatch(char *moduleName, char *functionName, PROC newFunction, PROC *function);
|
||||
void Hook_Create(char *moduleName, char *functionName, PROC newFunction, PROC *function);
|
||||
void Hook_Revert(char *moduleName, char *functionName, PROC newFunction, PROC *function);
|
||||
|
||||
#endif
|
||||
|
@ -122,14 +122,12 @@ typedef struct IDirectDrawImpl
|
||||
BOOL handlemouse;
|
||||
char shader[MAX_PATH];
|
||||
BOOL wine;
|
||||
LONG minimized;
|
||||
BOOL altenter;
|
||||
BOOL hidecursor;
|
||||
BOOL accurateTimers;
|
||||
int bnetHack;
|
||||
BOOL bnetActive;
|
||||
BOOL bnetD3d9Fullscreen;
|
||||
BOOL hotPatch;
|
||||
SpeedLimiter ticksLimiter;
|
||||
SpeedLimiter flipLimiter;
|
||||
SpeedLimiter fpsLimiter;
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
HRESULT __stdcall ddraw_clipper_QueryInterface(IDirectDrawClipperImpl *This, REFIID riid, void **obj)
|
||||
{
|
||||
printf("DirectDrawClipper::QueryInterface(This=%p, riid=%08X, obj=%p) ???\n", This, (unsigned int)riid, obj);
|
||||
printf("??? DirectDrawClipper::QueryInterface(This=%p, riid=%08X, obj=%p)\n", This, (unsigned int)riid, obj);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -52,37 +52,37 @@ ULONG __stdcall ddraw_clipper_Release(IDirectDrawClipperImpl *This)
|
||||
|
||||
HRESULT __stdcall ddraw_clipper_GetClipList(IDirectDrawClipperImpl *This, LPRECT a, LPRGNDATA b, LPDWORD c)
|
||||
{
|
||||
printf("IDirectDrawClipper::GetClipList(This=%p, ...) ???\n", This);
|
||||
printf("??? IDirectDrawClipper::GetClipList(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_clipper_GetHWnd(IDirectDrawClipperImpl *This, HWND FAR *a)
|
||||
{
|
||||
printf("IDirectDrawClipper::GetHWnd(This=%p, ...) ???\n", This);
|
||||
printf("??? IDirectDrawClipper::GetHWnd(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_clipper_Initialize(IDirectDrawClipperImpl *This, LPDIRECTDRAW a, DWORD b)
|
||||
{
|
||||
printf("IDirectDrawClipper::Initialize(This=%p, ...) ???\n", This);
|
||||
printf("??? IDirectDrawClipper::Initialize(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_clipper_IsClipListChanged(IDirectDrawClipperImpl *This, BOOL FAR *a)
|
||||
{
|
||||
printf("IDirectDrawClipper::IsClipListChanged(This=%p, ...) ???\n", This);
|
||||
printf("??? IDirectDrawClipper::IsClipListChanged(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_clipper_SetClipList(IDirectDrawClipperImpl *This, LPRGNDATA a, DWORD b)
|
||||
{
|
||||
printf("IDirectDrawClipper::SetClipList(This=%p, ...) ???\n", This);
|
||||
printf("??? IDirectDrawClipper::SetClipList(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_clipper_SetHWnd(IDirectDrawClipperImpl *This, DWORD a, HWND b)
|
||||
{
|
||||
printf("IDirectDrawClipper::SetHWnd(This=%p, ...) ???\n", This);
|
||||
printf("??? IDirectDrawClipper::SetHWnd(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
|
30
src/debug.c
30
src/debug.c
@ -35,6 +35,36 @@ void DebugPrint(const char *format, ...)
|
||||
OutputDebugStringA(buffer);
|
||||
}
|
||||
|
||||
int dprintf(const char *fmt, ...)
|
||||
{
|
||||
static CRITICAL_SECTION cs;
|
||||
static BOOL initialized;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
initialized = TRUE;
|
||||
InitializeCriticalSection(&cs);
|
||||
}
|
||||
|
||||
EnterCriticalSection(&cs);
|
||||
|
||||
va_list args;
|
||||
int ret;
|
||||
|
||||
SYSTEMTIME st;
|
||||
GetLocalTime(&st);
|
||||
|
||||
fprintf(stdout, "[%lu] %02d:%02d:%02d.%03d ", GetCurrentThreadId(), st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
|
||||
|
||||
va_start(args, fmt);
|
||||
ret = vfprintf(stdout, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
LeaveCriticalSection(&cs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DrawFrameInfoStart()
|
||||
{
|
||||
static DWORD tick_fps = 0;
|
||||
|
115
src/detours/CREDITS.TXT
Normal file
115
src/detours/CREDITS.TXT
Normal file
@ -0,0 +1,115 @@
|
||||
==============================================================================
|
||||
The following individuals have helped identify specific bugs and improvements
|
||||
in Detours. The entire Detours community has benefited from their help.
|
||||
==============================================================================
|
||||
|
||||
* Jay Krell: Identified issue with VirtualSize == 0 files created in
|
||||
NT 3.1 images. (Build_339)
|
||||
|
||||
* Igor Odnovorov: Identified an issue with the placement of the trampoline
|
||||
region when a function is detoured twice and the second
|
||||
trampoline region is outside of the +/- 2GB range of
|
||||
the target. (Build_337)
|
||||
|
||||
* Jay Krell: Identified need for some programs to enumerate the
|
||||
address of IAT entries. (Build_336)
|
||||
|
||||
* Calvin Hsia: Identified need for some program to change the excluded
|
||||
system region. (Build_336)
|
||||
|
||||
* Adam Smith: Identified error in failure handling when VirtualProect
|
||||
cannot make pages executable because the Prohibit
|
||||
Dynamic Code Generation mitigation policy has been
|
||||
applied to a process. (Build_335)
|
||||
|
||||
* Ben Faull: Identified fix to detour_alloc_region_from_lo and
|
||||
detour_alloc_region_from_hi that preserves ASLR entropy.
|
||||
(Build_334)
|
||||
|
||||
* Shaoxiang Su: Reported errors building with Visual Studio 2015.
|
||||
(Build_332)
|
||||
|
||||
* Jay Krell: Identified and resolved significant gaps in the X86, X64
|
||||
and IA64 disassemblers for instruction found in code,
|
||||
but seldom found in function prologues. (Build_331)
|
||||
|
||||
* Allan Murphy: Identify error in rep and jmp ds: encodings. (Build_331)
|
||||
|
||||
* Philip Bacon: Identified incorrect entry point return for pure
|
||||
resource-only binaries. (Build_330)
|
||||
|
||||
* Jay Krell: Identified failure in DetourAttachEx to update nAlign.
|
||||
(Build_330)
|
||||
|
||||
* Sumit Sarin: Helped debug error with packed binaries.
|
||||
(Build_329)
|
||||
|
||||
* Nitya Kumar Sharma: Reported bug in DetourAfterWithDll for 32/64 agnostic
|
||||
EXEs.
|
||||
(Build_327)
|
||||
|
||||
* Richard Black: Identified a large number of typos in documentation.
|
||||
(Build_326)
|
||||
|
||||
* Michael Bilodeau: Identified bug in DetourUpdateProcessWithDll when the
|
||||
target process contains a Detours payload *after* all
|
||||
valid PE binaries.
|
||||
(Build_324)
|
||||
|
||||
* Meera Jindal: Reported bug in identification of target address in
|
||||
DetourCopyInstruction for jmp[] and call[] on x86 & x64,
|
||||
the ff15 and ff25 opcodes.
|
||||
(Build_323)
|
||||
|
||||
* Ken Johnson: Assistance with SAL 2.0 annotations.
|
||||
(Build_319)
|
||||
|
||||
* Nick Wood: Identified bug in DetourFindFunction on ARM.
|
||||
(Build_314)
|
||||
|
||||
* Mark Russinovich: Helped debug DetourCreateProcessWithDllEx.
|
||||
(Build_314)
|
||||
|
||||
* John Lin: Implementation idea for DetoursCreateProcessWithDllEx.
|
||||
(Build_314)
|
||||
|
||||
* Andrew Zawadowskiy Reported an improper memory page permissions
|
||||
vulnerability in Detours 2.1. (Vulnerability does not
|
||||
exist in versions later than Detours 2.1.)
|
||||
(Build_223)
|
||||
|
||||
* Nightxie: Identified bug in detour_alloc_round_up_to_region.
|
||||
(Build_310)
|
||||
|
||||
* Diana Milirud: Identified bug in B* instructions on ARM.
|
||||
(Build_309)
|
||||
|
||||
* Juan Carlos Identified correct MSIL entry point for unsigned MSIL.
|
||||
Luciani: (Build_308)
|
||||
|
||||
* Lee Hunt Suggested improvements in algorithm for allocation of
|
||||
Lawrence Landauer trampoline regions on x64 to avoid collisions with
|
||||
Joe Laughlin: system DLLs.
|
||||
(Build_307)
|
||||
|
||||
* Tyler Sims Identified bug in handling of "anycpu" MSIL binaries
|
||||
Darren Kennedy: on x64.
|
||||
(Build_307)
|
||||
|
||||
* Andre Vachon: Help with optimized binaries.
|
||||
(Build 301)
|
||||
|
||||
* Chris Mann: Identified fix not forward ported from 2.2 to 3.0.
|
||||
(Build_301)
|
||||
|
||||
* Mark Irving: Identified bug with EXEs missing second import table.
|
||||
(Build_300)
|
||||
|
||||
* Ben Schwarz: Identified bug in handling of multi-byte NOPs.
|
||||
(Build_300)
|
||||
|
||||
* Aaron Giles Coded initial ARM/Thumb2 disassembler.
|
||||
Jared Henderson: (Build_300)
|
||||
|
||||
* Doug Brubacher: Coded initial x86 disassembler.
|
||||
(Build_100)
|
23
src/detours/LICENSE.md
Normal file
23
src/detours/LICENSE.md
Normal file
@ -0,0 +1,23 @@
|
||||
# Copyright (c) Microsoft Corporation
|
||||
|
||||
All rights reserved.
|
||||
|
||||
# MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
48
src/detours/README.md
Normal file
48
src/detours/README.md
Normal file
@ -0,0 +1,48 @@
|
||||
# Microsoft Research Detours Package
|
||||
|
||||
Detours is a software package for monitoring and instrumenting API calls on Windows. Detours
|
||||
has been used by many ISVs and is also used by product teams at Microsoft. Detours is now available under
|
||||
a standard open source license (MIT). This simplifies licensing for programmers using Detours
|
||||
and allows the community to support Detours using open source tools and processes.
|
||||
|
||||
Detours is compatible with the Windows NT family of
|
||||
operating systems: Windows NT, Windows XP, Windows Server 2003, Windows 7,
|
||||
Windows 8, and Windows 10. It cannot be used by Window Store apps
|
||||
because Detours requires APIs not available to those applications.
|
||||
This repo contains the source code for version 4.0.1 of Detours.
|
||||
|
||||
For technical documentation on Detours, see the [Detours Wiki](https://github.com/microsoft/Detours/wiki).
|
||||
For directions on how to build and run samples, see the
|
||||
samples [README.txt](https://github.com/Microsoft/Detours/blob/master/samples/README.TXT) file.
|
||||
|
||||
## Contributing
|
||||
|
||||
The [`Detours`](https://github.com/microsoft/detours) repository is where development is done.
|
||||
Here are some ways you can participate in the project:
|
||||
|
||||
* [Answer questions](https://github.com/microsoft/detours/issues) about using Detours.
|
||||
* [Improve the Wiki](https://github.com/microsoft/detours/wiki).
|
||||
* [Submit bugs](https://github.com/microsoft/detours/issues) and help us verify fixes and changes as they are checked in.
|
||||
* Review [source code changes](https://github.com/microsoft/detours/pulls).
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
||||
## Issues, questions, and feedback
|
||||
|
||||
* Open an issue on [GitHub Issues](https://github.com/Microsoft/detours/issues).
|
||||
|
||||
## Mailing list for announcements
|
||||
|
||||
The detours-announce mailing list is a low-traffic email list for important announcements
|
||||
about the project, such as the availability of new versions of Detours. To join it, send
|
||||
an email to listserv@lists.research.microsoft.com with a
|
||||
message body containing only the text SUBSCRIBE DETOURS-ANNOUNCE.
|
||||
To leave it, send an email to listserv@lists.research.microsoft.com with a
|
||||
message body containing only the text UNSUBSCRIBE DETOURS-ANNOUNCE.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Licensed under the [MIT](LICENSE.md) License.
|
1586
src/detours/creatwth.cpp
Normal file
1586
src/detours/creatwth.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2489
src/detours/detours.cpp
Normal file
2489
src/detours/detours.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1080
src/detours/detours.h
Normal file
1080
src/detours/detours.h
Normal file
File diff suppressed because it is too large
Load Diff
27
src/detours/detver.h
Normal file
27
src/detours/detver.h
Normal file
@ -0,0 +1,27 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Common version parameters.
|
||||
//
|
||||
// Microsoft Research Detours Package, Version 4.0.1
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
|
||||
#define _USING_V110_SDK71_ 1
|
||||
#include "winver.h"
|
||||
#if 0
|
||||
#include <windows.h>
|
||||
#include <detours.h>
|
||||
#else
|
||||
#ifndef DETOURS_STRINGIFY
|
||||
#define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x)
|
||||
#define DETOURS_STRINGIFY_(x) #x
|
||||
#endif
|
||||
|
||||
#define VER_FILEFLAGSMASK 0x3fL
|
||||
#define VER_FILEFLAGS 0x0L
|
||||
#define VER_FILEOS 0x00040004L
|
||||
#define VER_FILETYPE 0x00000002L
|
||||
#define VER_FILESUBTYPE 0x00000000L
|
||||
#endif
|
||||
#define VER_DETOURS_BITS DETOUR_STRINGIFY(DETOURS_BITS)
|
4344
src/detours/disasm.cpp
Normal file
4344
src/detours/disasm.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2
src/detours/disolarm.cpp
Normal file
2
src/detours/disolarm.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#define DETOURS_ARM_OFFLINE_LIBRARY
|
||||
#include "disasm.cpp"
|
2
src/detours/disolarm64.cpp
Normal file
2
src/detours/disolarm64.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#define DETOURS_ARM64_OFFLINE_LIBRARY
|
||||
#include "disasm.cpp"
|
2
src/detours/disolia64.cpp
Normal file
2
src/detours/disolia64.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#define DETOURS_IA64_OFFLINE_LIBRARY
|
||||
#include "disasm.cpp"
|
2
src/detours/disolx64.cpp
Normal file
2
src/detours/disolx64.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#define DETOURS_X64_OFFLINE_LIBRARY
|
||||
#include "disasm.cpp"
|
2
src/detours/disolx86.cpp
Normal file
2
src/detours/disolx86.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#define DETOURS_X86_OFFLINE_LIBRARY
|
||||
#include "disasm.cpp"
|
2247
src/detours/image.cpp
Normal file
2247
src/detours/image.cpp
Normal file
File diff suppressed because it is too large
Load Diff
929
src/detours/modules.cpp
Normal file
929
src/detours/modules.cpp
Normal file
@ -0,0 +1,929 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Module Enumeration Functions (modules.cpp of detours.lib)
|
||||
//
|
||||
// Microsoft Research Detours Package, Version 4.0.1
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Module enumeration functions.
|
||||
//
|
||||
|
||||
#define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1
|
||||
|
||||
#pragma warning(disable:4068) // unknown pragma (suppress)
|
||||
|
||||
#if _MSC_VER >= 1900
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4091) // empty typedef
|
||||
#endif
|
||||
|
||||
#define _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE 1
|
||||
#include <windows.h>
|
||||
#if (_MSC_VER < 1310)
|
||||
#else
|
||||
#pragma warning(push)
|
||||
#if _MSC_VER > 1400
|
||||
#pragma warning(disable:6102 6103) // /analyze warnings
|
||||
#endif
|
||||
#include <strsafe.h>
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
// #define DETOUR_DEBUG 1
|
||||
#define DETOURS_INTERNAL
|
||||
#include "detours.h"
|
||||
|
||||
#if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH
|
||||
#error detours.h version mismatch
|
||||
#endif
|
||||
|
||||
#if _MSC_VER >= 1900
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#define CLR_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]
|
||||
#define IAT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT]
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
const GUID DETOUR_EXE_RESTORE_GUID = {
|
||||
0x2ed7a3ff, 0x3339, 0x4a8d,
|
||||
{ 0x80, 0x5c, 0xd4, 0x98, 0x15, 0x3f, 0xc2, 0x8f }};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
PDETOUR_SYM_INFO DetourLoadImageHlp(VOID)
|
||||
{
|
||||
static DETOUR_SYM_INFO symInfo;
|
||||
static PDETOUR_SYM_INFO pSymInfo = NULL;
|
||||
static BOOL failed = false;
|
||||
|
||||
if (failed) {
|
||||
return NULL;
|
||||
}
|
||||
if (pSymInfo != NULL) {
|
||||
return pSymInfo;
|
||||
}
|
||||
|
||||
ZeroMemory(&symInfo, sizeof(symInfo));
|
||||
// Create a real handle to the process.
|
||||
#if 0
|
||||
DuplicateHandle(GetCurrentProcess(),
|
||||
GetCurrentProcess(),
|
||||
GetCurrentProcess(),
|
||||
&symInfo.hProcess,
|
||||
0,
|
||||
FALSE,
|
||||
DUPLICATE_SAME_ACCESS);
|
||||
#else
|
||||
symInfo.hProcess = GetCurrentProcess();
|
||||
#endif
|
||||
|
||||
symInfo.hDbgHelp = LoadLibraryExW(L"dbghelp.dll", NULL, 0);
|
||||
if (symInfo.hDbgHelp == NULL) {
|
||||
abort:
|
||||
failed = true;
|
||||
if (symInfo.hDbgHelp != NULL) {
|
||||
FreeLibrary(symInfo.hDbgHelp);
|
||||
}
|
||||
symInfo.pfImagehlpApiVersionEx = NULL;
|
||||
symInfo.pfSymInitialize = NULL;
|
||||
symInfo.pfSymSetOptions = NULL;
|
||||
symInfo.pfSymGetOptions = NULL;
|
||||
symInfo.pfSymLoadModule64 = NULL;
|
||||
symInfo.pfSymGetModuleInfo64 = NULL;
|
||||
symInfo.pfSymFromName = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
symInfo.pfImagehlpApiVersionEx
|
||||
= (PF_ImagehlpApiVersionEx)GetProcAddress(symInfo.hDbgHelp,
|
||||
"ImagehlpApiVersionEx");
|
||||
symInfo.pfSymInitialize
|
||||
= (PF_SymInitialize)GetProcAddress(symInfo.hDbgHelp, "SymInitialize");
|
||||
symInfo.pfSymSetOptions
|
||||
= (PF_SymSetOptions)GetProcAddress(symInfo.hDbgHelp, "SymSetOptions");
|
||||
symInfo.pfSymGetOptions
|
||||
= (PF_SymGetOptions)GetProcAddress(symInfo.hDbgHelp, "SymGetOptions");
|
||||
symInfo.pfSymLoadModule64
|
||||
= (PF_SymLoadModule64)GetProcAddress(symInfo.hDbgHelp, "SymLoadModule64");
|
||||
symInfo.pfSymGetModuleInfo64
|
||||
= (PF_SymGetModuleInfo64)GetProcAddress(symInfo.hDbgHelp, "SymGetModuleInfo64");
|
||||
symInfo.pfSymFromName
|
||||
= (PF_SymFromName)GetProcAddress(symInfo.hDbgHelp, "SymFromName");
|
||||
|
||||
API_VERSION av;
|
||||
ZeroMemory(&av, sizeof(av));
|
||||
av.MajorVersion = API_VERSION_NUMBER;
|
||||
|
||||
if (symInfo.pfImagehlpApiVersionEx == NULL ||
|
||||
symInfo.pfSymInitialize == NULL ||
|
||||
symInfo.pfSymLoadModule64 == NULL ||
|
||||
symInfo.pfSymGetModuleInfo64 == NULL ||
|
||||
symInfo.pfSymFromName == NULL) {
|
||||
goto abort;
|
||||
}
|
||||
|
||||
symInfo.pfImagehlpApiVersionEx(&av);
|
||||
if (av.MajorVersion < API_VERSION_NUMBER) {
|
||||
goto abort;
|
||||
}
|
||||
|
||||
if (!symInfo.pfSymInitialize(symInfo.hProcess, NULL, FALSE)) {
|
||||
// We won't retry the initialize if it fails.
|
||||
goto abort;
|
||||
}
|
||||
|
||||
if (symInfo.pfSymGetOptions != NULL && symInfo.pfSymSetOptions != NULL) {
|
||||
DWORD dw = symInfo.pfSymGetOptions();
|
||||
|
||||
dw &= ~(SYMOPT_CASE_INSENSITIVE |
|
||||
SYMOPT_UNDNAME |
|
||||
SYMOPT_DEFERRED_LOADS |
|
||||
0);
|
||||
dw |= (
|
||||
#if defined(SYMOPT_EXACT_SYMBOLS)
|
||||
SYMOPT_EXACT_SYMBOLS |
|
||||
#endif
|
||||
#if defined(SYMOPT_NO_UNQUALIFIED_LOADS)
|
||||
SYMOPT_NO_UNQUALIFIED_LOADS |
|
||||
#endif
|
||||
SYMOPT_DEFERRED_LOADS |
|
||||
#if defined(SYMOPT_FAIL_CRITICAL_ERRORS)
|
||||
SYMOPT_FAIL_CRITICAL_ERRORS |
|
||||
#endif
|
||||
#if defined(SYMOPT_INCLUDE_32BIT_MODULES)
|
||||
SYMOPT_INCLUDE_32BIT_MODULES |
|
||||
#endif
|
||||
0);
|
||||
symInfo.pfSymSetOptions(dw);
|
||||
}
|
||||
|
||||
pSymInfo = &symInfo;
|
||||
return pSymInfo;
|
||||
}
|
||||
|
||||
PVOID WINAPI DetourFindFunction(_In_ PCSTR pszModule,
|
||||
_In_ PCSTR pszFunction)
|
||||
{
|
||||
/////////////////////////////////////////////// First, try GetProcAddress.
|
||||
//
|
||||
#pragma prefast(suppress:28752, "We don't do the unicode conversion for LoadLibraryExA.")
|
||||
HMODULE hModule = LoadLibraryExA(pszModule, NULL, 0);
|
||||
if (hModule == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PBYTE pbCode = (PBYTE)GetProcAddress(hModule, pszFunction);
|
||||
if (pbCode) {
|
||||
return pbCode;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////// Then try ImageHelp.
|
||||
//
|
||||
DETOUR_TRACE(("DetourFindFunction(%hs, %hs)\n", pszModule, pszFunction));
|
||||
PDETOUR_SYM_INFO pSymInfo = DetourLoadImageHlp();
|
||||
if (pSymInfo == NULL) {
|
||||
DETOUR_TRACE(("DetourLoadImageHlp failed: %d\n",
|
||||
GetLastError()));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pSymInfo->pfSymLoadModule64(pSymInfo->hProcess, NULL,
|
||||
(PCHAR)pszModule, NULL,
|
||||
(DWORD64)hModule, 0) == 0) {
|
||||
if (ERROR_SUCCESS != GetLastError()) {
|
||||
DETOUR_TRACE(("SymLoadModule64(%p) failed: %d\n",
|
||||
pSymInfo->hProcess, GetLastError()));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT hrRet;
|
||||
CHAR szFullName[512];
|
||||
IMAGEHLP_MODULE64 modinfo;
|
||||
ZeroMemory(&modinfo, sizeof(modinfo));
|
||||
modinfo.SizeOfStruct = sizeof(modinfo);
|
||||
if (!pSymInfo->pfSymGetModuleInfo64(pSymInfo->hProcess, (DWORD64)hModule, &modinfo)) {
|
||||
DETOUR_TRACE(("SymGetModuleInfo64(%p, %p) failed: %d\n",
|
||||
pSymInfo->hProcess, hModule, GetLastError()));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hrRet = StringCchCopyA(szFullName, sizeof(szFullName)/sizeof(CHAR), modinfo.ModuleName);
|
||||
if (FAILED(hrRet)) {
|
||||
DETOUR_TRACE(("StringCchCopyA failed: %08x\n", hrRet));
|
||||
return NULL;
|
||||
}
|
||||
hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), "!");
|
||||
if (FAILED(hrRet)) {
|
||||
DETOUR_TRACE(("StringCchCatA failed: %08x\n", hrRet));
|
||||
return NULL;
|
||||
}
|
||||
hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), pszFunction);
|
||||
if (FAILED(hrRet)) {
|
||||
DETOUR_TRACE(("StringCchCatA failed: %08x\n", hrRet));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct CFullSymbol : SYMBOL_INFO {
|
||||
CHAR szRestOfName[512];
|
||||
} symbol;
|
||||
ZeroMemory(&symbol, sizeof(symbol));
|
||||
//symbol.ModBase = (ULONG64)hModule;
|
||||
symbol.SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
#ifdef DBHLPAPI
|
||||
symbol.MaxNameLen = sizeof(symbol.szRestOfName)/sizeof(symbol.szRestOfName[0]);
|
||||
#else
|
||||
symbol.MaxNameLength = sizeof(symbol.szRestOfName)/sizeof(symbol.szRestOfName[0]);
|
||||
#endif
|
||||
|
||||
if (!pSymInfo->pfSymFromName(pSymInfo->hProcess, szFullName, &symbol)) {
|
||||
DETOUR_TRACE(("SymFromName(%hs) failed: %d\n", szFullName, GetLastError()));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(DETOURS_IA64)
|
||||
// On the IA64, we get a raw code pointer from the symbol engine
|
||||
// and have to convert it to a wrapped [code pointer, global pointer].
|
||||
//
|
||||
PPLABEL_DESCRIPTOR pldEntry = (PPLABEL_DESCRIPTOR)DetourGetEntryPoint(hModule);
|
||||
PPLABEL_DESCRIPTOR pldSymbol = new PLABEL_DESCRIPTOR;
|
||||
|
||||
pldSymbol->EntryPoint = symbol.Address;
|
||||
pldSymbol->GlobalPointer = pldEntry->GlobalPointer;
|
||||
return (PBYTE)pldSymbol;
|
||||
#elif defined(DETOURS_ARM)
|
||||
// On the ARM, we get a raw code pointer, which we must convert into a
|
||||
// valied Thumb2 function pointer.
|
||||
return DETOURS_PBYTE_TO_PFUNC(symbol.Address);
|
||||
#else
|
||||
return (PBYTE)symbol.Address;
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////// Module Image Functions.
|
||||
//
|
||||
|
||||
HMODULE WINAPI DetourEnumerateModules(_In_opt_ HMODULE hModuleLast)
|
||||
{
|
||||
PBYTE pbLast = (PBYTE)hModuleLast + MM_ALLOCATION_GRANULARITY;
|
||||
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
ZeroMemory(&mbi, sizeof(mbi));
|
||||
|
||||
// Find the next memory region that contains a mapped PE image.
|
||||
//
|
||||
for (;; pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) {
|
||||
if (VirtualQuery(pbLast, &mbi, sizeof(mbi)) <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Skip uncommitted regions and guard pages.
|
||||
//
|
||||
if ((mbi.State != MEM_COMMIT) ||
|
||||
((mbi.Protect & 0xff) == PAGE_NOACCESS) ||
|
||||
(mbi.Protect & PAGE_GUARD)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
__try {
|
||||
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pbLast;
|
||||
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE ||
|
||||
(DWORD)pDosHeader->e_lfanew > mbi.RegionSize ||
|
||||
(DWORD)pDosHeader->e_lfanew < sizeof(*pDosHeader)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
|
||||
pDosHeader->e_lfanew);
|
||||
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return (HMODULE)pDosHeader;
|
||||
}
|
||||
#pragma prefast(suppress:28940, "A bad pointer means this probably isn't a PE header.")
|
||||
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
|
||||
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PVOID WINAPI DetourGetEntryPoint(_In_opt_ HMODULE hModule)
|
||||
{
|
||||
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
|
||||
if (hModule == NULL) {
|
||||
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
|
||||
}
|
||||
|
||||
__try {
|
||||
#pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
|
||||
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||
SetLastError(ERROR_BAD_EXE_FORMAT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
|
||||
pDosHeader->e_lfanew);
|
||||
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
|
||||
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
|
||||
return NULL;
|
||||
}
|
||||
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
|
||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PDETOUR_CLR_HEADER pClrHeader = NULL;
|
||||
if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
|
||||
if (((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.VirtualAddress != 0 &&
|
||||
((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.Size != 0) {
|
||||
pClrHeader = (PDETOUR_CLR_HEADER)
|
||||
(((PBYTE)pDosHeader)
|
||||
+ ((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.VirtualAddress);
|
||||
}
|
||||
}
|
||||
else if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
|
||||
if (((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.VirtualAddress != 0 &&
|
||||
((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.Size != 0) {
|
||||
pClrHeader = (PDETOUR_CLR_HEADER)
|
||||
(((PBYTE)pDosHeader)
|
||||
+ ((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.VirtualAddress);
|
||||
}
|
||||
}
|
||||
|
||||
if (pClrHeader != NULL) {
|
||||
// For MSIL assemblies, we want to use the _Cor entry points.
|
||||
|
||||
HMODULE hClr = GetModuleHandleW(L"MSCOREE.DLL");
|
||||
if (hClr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SetLastError(NO_ERROR);
|
||||
return GetProcAddress(hClr, "_CorExeMain");
|
||||
}
|
||||
|
||||
SetLastError(NO_ERROR);
|
||||
|
||||
// Pure resource DLLs have neither an entry point nor CLR information
|
||||
// so handle them by returning NULL (LastError is NO_ERROR)
|
||||
if (pNtHeader->OptionalHeader.AddressOfEntryPoint == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ((PBYTE)pDosHeader) +
|
||||
pNtHeader->OptionalHeader.AddressOfEntryPoint;
|
||||
}
|
||||
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
|
||||
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
|
||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ULONG WINAPI DetourGetModuleSize(_In_opt_ HMODULE hModule)
|
||||
{
|
||||
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
|
||||
if (hModule == NULL) {
|
||||
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
|
||||
}
|
||||
|
||||
__try {
|
||||
#pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
|
||||
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||
SetLastError(ERROR_BAD_EXE_FORMAT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
|
||||
pDosHeader->e_lfanew);
|
||||
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
|
||||
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
|
||||
return NULL;
|
||||
}
|
||||
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
|
||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
||||
return NULL;
|
||||
}
|
||||
SetLastError(NO_ERROR);
|
||||
|
||||
return (pNtHeader->OptionalHeader.SizeOfImage);
|
||||
}
|
||||
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
|
||||
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
|
||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HMODULE WINAPI DetourGetContainingModule(_In_ PVOID pvAddr)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
ZeroMemory(&mbi, sizeof(mbi));
|
||||
|
||||
__try {
|
||||
if (VirtualQuery(pvAddr, &mbi, sizeof(mbi)) <= 0) {
|
||||
SetLastError(ERROR_BAD_EXE_FORMAT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Skip uncommitted regions and guard pages.
|
||||
//
|
||||
if ((mbi.State != MEM_COMMIT) ||
|
||||
((mbi.Protect & 0xff) == PAGE_NOACCESS) ||
|
||||
(mbi.Protect & PAGE_GUARD)) {
|
||||
SetLastError(ERROR_BAD_EXE_FORMAT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mbi.AllocationBase;
|
||||
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||
SetLastError(ERROR_BAD_EXE_FORMAT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
|
||||
pDosHeader->e_lfanew);
|
||||
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
|
||||
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
|
||||
return NULL;
|
||||
}
|
||||
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
|
||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
||||
return NULL;
|
||||
}
|
||||
SetLastError(NO_ERROR);
|
||||
|
||||
return (HMODULE)pDosHeader;
|
||||
}
|
||||
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
|
||||
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
|
||||
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline PBYTE RvaAdjust(_Pre_notnull_ PIMAGE_DOS_HEADER pDosHeader, _In_ DWORD raddr)
|
||||
{
|
||||
if (raddr != NULL) {
|
||||
return ((PBYTE)pDosHeader) + raddr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL WINAPI DetourEnumerateExports(_In_ HMODULE hModule,
|
||||
_In_opt_ PVOID pContext,
|
||||
_In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport)
|
||||
{
|
||||
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
|
||||
if (hModule == NULL) {
|
||||
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
|
||||
}
|
||||
|
||||
__try {
|
||||
#pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
|
||||
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||
SetLastError(ERROR_BAD_EXE_FORMAT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
|
||||
pDosHeader->e_lfanew);
|
||||
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
|
||||
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
|
||||
return FALSE;
|
||||
}
|
||||
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
|
||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PIMAGE_EXPORT_DIRECTORY pExportDir
|
||||
= (PIMAGE_EXPORT_DIRECTORY)
|
||||
RvaAdjust(pDosHeader,
|
||||
pNtHeader->OptionalHeader
|
||||
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
||||
|
||||
if (pExportDir == NULL) {
|
||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PBYTE pExportDirEnd = (PBYTE)pExportDir + pNtHeader->OptionalHeader
|
||||
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
|
||||
PDWORD pdwFunctions = (PDWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfFunctions);
|
||||
PDWORD pdwNames = (PDWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfNames);
|
||||
PWORD pwOrdinals = (PWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfNameOrdinals);
|
||||
|
||||
for (DWORD nFunc = 0; nFunc < pExportDir->NumberOfFunctions; nFunc++) {
|
||||
PBYTE pbCode = (pdwFunctions != NULL)
|
||||
? (PBYTE)RvaAdjust(pDosHeader, pdwFunctions[nFunc]) : NULL;
|
||||
PCHAR pszName = NULL;
|
||||
|
||||
// if the pointer is in the export region, then it is a forwarder.
|
||||
if (pbCode > (PBYTE)pExportDir && pbCode < pExportDirEnd) {
|
||||
pbCode = NULL;
|
||||
}
|
||||
|
||||
for (DWORD n = 0; n < pExportDir->NumberOfNames; n++) {
|
||||
if (pwOrdinals[n] == nFunc) {
|
||||
pszName = (pdwNames != NULL)
|
||||
? (PCHAR)RvaAdjust(pDosHeader, pdwNames[n]) : NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ULONG nOrdinal = pExportDir->Base + nFunc;
|
||||
|
||||
if (!pfExport(pContext, nOrdinal, pszName, pbCode)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
SetLastError(NO_ERROR);
|
||||
return TRUE;
|
||||
}
|
||||
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
|
||||
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
|
||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL WINAPI DetourEnumerateImportsEx(_In_opt_ HMODULE hModule,
|
||||
_In_opt_ PVOID pContext,
|
||||
_In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile,
|
||||
_In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK_EX pfImportFunc)
|
||||
{
|
||||
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
|
||||
if (hModule == NULL) {
|
||||
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
|
||||
}
|
||||
|
||||
__try {
|
||||
#pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
|
||||
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||
SetLastError(ERROR_BAD_EXE_FORMAT);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
|
||||
pDosHeader->e_lfanew);
|
||||
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
|
||||
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
|
||||
return FALSE;
|
||||
}
|
||||
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
|
||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PIMAGE_IMPORT_DESCRIPTOR iidp
|
||||
= (PIMAGE_IMPORT_DESCRIPTOR)
|
||||
RvaAdjust(pDosHeader,
|
||||
pNtHeader->OptionalHeader
|
||||
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
|
||||
|
||||
if (iidp == NULL) {
|
||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (; iidp->OriginalFirstThunk != 0; iidp++) {
|
||||
|
||||
PCSTR pszName = (PCHAR)RvaAdjust(pDosHeader, iidp->Name);
|
||||
if (pszName == NULL) {
|
||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PIMAGE_THUNK_DATA pThunks = (PIMAGE_THUNK_DATA)
|
||||
RvaAdjust(pDosHeader, iidp->OriginalFirstThunk);
|
||||
PVOID * pAddrs = (PVOID *)
|
||||
RvaAdjust(pDosHeader, iidp->FirstThunk);
|
||||
|
||||
HMODULE hFile = DetourGetContainingModule(pAddrs[0]);
|
||||
|
||||
if (pfImportFile != NULL) {
|
||||
if (!pfImportFile(pContext, hFile, pszName)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD nNames = 0;
|
||||
if (pThunks) {
|
||||
for (; pThunks[nNames].u1.Ordinal; nNames++) {
|
||||
DWORD nOrdinal = 0;
|
||||
PCSTR pszFunc = NULL;
|
||||
|
||||
if (IMAGE_SNAP_BY_ORDINAL(pThunks[nNames].u1.Ordinal)) {
|
||||
nOrdinal = (DWORD)IMAGE_ORDINAL(pThunks[nNames].u1.Ordinal);
|
||||
}
|
||||
else {
|
||||
pszFunc = (PCSTR)RvaAdjust(pDosHeader,
|
||||
(DWORD)pThunks[nNames].u1.AddressOfData + 2);
|
||||
}
|
||||
|
||||
if (pfImportFunc != NULL) {
|
||||
if (!pfImportFunc(pContext,
|
||||
nOrdinal,
|
||||
pszFunc,
|
||||
&pAddrs[nNames])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pfImportFunc != NULL) {
|
||||
pfImportFunc(pContext, 0, NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pfImportFile != NULL) {
|
||||
pfImportFile(pContext, NULL, NULL);
|
||||
}
|
||||
SetLastError(NO_ERROR);
|
||||
return TRUE;
|
||||
}
|
||||
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
|
||||
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
|
||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Context for DetourEnumerateImportsThunk, which adapts "regular" callbacks for use with "Ex".
|
||||
struct _DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT
|
||||
{
|
||||
PVOID pContext;
|
||||
PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc;
|
||||
};
|
||||
|
||||
// Callback for DetourEnumerateImportsEx that adapts DetourEnumerateImportsEx
|
||||
// for use with a DetourEnumerateImports callback -- derefence the IAT and pass the value on.
|
||||
|
||||
static
|
||||
BOOL
|
||||
CALLBACK
|
||||
DetourEnumerateImportsThunk(_In_ PVOID VoidContext,
|
||||
_In_ DWORD nOrdinal,
|
||||
_In_opt_ PCSTR pszFunc,
|
||||
_In_opt_ PVOID* ppvFunc)
|
||||
{
|
||||
_DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT const * const
|
||||
pContext = (_DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT*)VoidContext;
|
||||
return pContext->pfImportFunc(pContext->pContext, nOrdinal, pszFunc, ppvFunc ? *ppvFunc : NULL);
|
||||
}
|
||||
|
||||
BOOL WINAPI DetourEnumerateImports(_In_opt_ HMODULE hModule,
|
||||
_In_opt_ PVOID pContext,
|
||||
_In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile,
|
||||
_In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc)
|
||||
{
|
||||
_DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT const context = { pContext, pfImportFunc };
|
||||
|
||||
return DetourEnumerateImportsEx(hModule,
|
||||
(PVOID)&context,
|
||||
pfImportFile,
|
||||
&DetourEnumerateImportsThunk);
|
||||
}
|
||||
|
||||
static PDETOUR_LOADED_BINARY WINAPI GetPayloadSectionFromModule(HMODULE hModule)
|
||||
{
|
||||
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
|
||||
if (hModule == NULL) {
|
||||
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
|
||||
}
|
||||
|
||||
__try {
|
||||
#pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
|
||||
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||
SetLastError(ERROR_BAD_EXE_FORMAT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
|
||||
pDosHeader->e_lfanew);
|
||||
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
|
||||
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
|
||||
return NULL;
|
||||
}
|
||||
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
|
||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PIMAGE_SECTION_HEADER pSectionHeaders
|
||||
= (PIMAGE_SECTION_HEADER)((PBYTE)pNtHeader
|
||||
+ sizeof(pNtHeader->Signature)
|
||||
+ sizeof(pNtHeader->FileHeader)
|
||||
+ pNtHeader->FileHeader.SizeOfOptionalHeader);
|
||||
|
||||
for (DWORD n = 0; n < pNtHeader->FileHeader.NumberOfSections; n++) {
|
||||
if (strcmp((PCHAR)pSectionHeaders[n].Name, ".detour") == 0) {
|
||||
if (pSectionHeaders[n].VirtualAddress == 0 ||
|
||||
pSectionHeaders[n].SizeOfRawData == 0) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
PBYTE pbData = (PBYTE)pDosHeader + pSectionHeaders[n].VirtualAddress;
|
||||
DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pbData;
|
||||
if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
|
||||
pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (pHeader->nDataOffset == 0) {
|
||||
pHeader->nDataOffset = pHeader->cbHeaderSize;
|
||||
}
|
||||
SetLastError(NO_ERROR);
|
||||
return (PBYTE)pHeader;
|
||||
}
|
||||
}
|
||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
||||
return NULL;
|
||||
}
|
||||
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
|
||||
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
|
||||
SetLastError(ERROR_EXE_MARKED_INVALID);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule)
|
||||
{
|
||||
PDETOUR_LOADED_BINARY pBinary = GetPayloadSectionFromModule(hModule);
|
||||
if (pBinary == NULL) {
|
||||
// Error set by GetPayloadSectionFromModule.
|
||||
return 0;
|
||||
}
|
||||
|
||||
__try {
|
||||
DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pBinary;
|
||||
if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
|
||||
pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
|
||||
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return 0;
|
||||
}
|
||||
SetLastError(NO_ERROR);
|
||||
return pHeader->cbDataSize;
|
||||
}
|
||||
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
|
||||
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
_Writable_bytes_(*pcbData)
|
||||
_Readable_bytes_(*pcbData)
|
||||
_Success_(return != NULL)
|
||||
PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule,
|
||||
_In_ REFGUID rguid,
|
||||
_Out_ DWORD *pcbData)
|
||||
{
|
||||
PBYTE pbData = NULL;
|
||||
if (pcbData) {
|
||||
*pcbData = 0;
|
||||
}
|
||||
|
||||
PDETOUR_LOADED_BINARY pBinary = GetPayloadSectionFromModule(hModule);
|
||||
if (pBinary == NULL) {
|
||||
// Error set by GetPayloadSectionFromModule.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__try {
|
||||
DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pBinary;
|
||||
if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
|
||||
pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
|
||||
|
||||
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PBYTE pbBeg = ((PBYTE)pHeader) + pHeader->nDataOffset;
|
||||
PBYTE pbEnd = ((PBYTE)pHeader) + pHeader->cbDataSize;
|
||||
|
||||
for (pbData = pbBeg; pbData < pbEnd;) {
|
||||
DETOUR_SECTION_RECORD *pSection = (DETOUR_SECTION_RECORD *)pbData;
|
||||
|
||||
if (pSection->guid.Data1 == rguid.Data1 &&
|
||||
pSection->guid.Data2 == rguid.Data2 &&
|
||||
pSection->guid.Data3 == rguid.Data3 &&
|
||||
pSection->guid.Data4[0] == rguid.Data4[0] &&
|
||||
pSection->guid.Data4[1] == rguid.Data4[1] &&
|
||||
pSection->guid.Data4[2] == rguid.Data4[2] &&
|
||||
pSection->guid.Data4[3] == rguid.Data4[3] &&
|
||||
pSection->guid.Data4[4] == rguid.Data4[4] &&
|
||||
pSection->guid.Data4[5] == rguid.Data4[5] &&
|
||||
pSection->guid.Data4[6] == rguid.Data4[6] &&
|
||||
pSection->guid.Data4[7] == rguid.Data4[7]) {
|
||||
|
||||
if (pcbData) {
|
||||
*pcbData = pSection->cbBytes - sizeof(*pSection);
|
||||
SetLastError(NO_ERROR);
|
||||
return (PBYTE)(pSection + 1);
|
||||
}
|
||||
}
|
||||
|
||||
pbData = (PBYTE)pSection + pSection->cbBytes;
|
||||
}
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return NULL;
|
||||
}
|
||||
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
|
||||
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
_Writable_bytes_(*pcbData)
|
||||
_Readable_bytes_(*pcbData)
|
||||
_Success_(return != NULL)
|
||||
PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
|
||||
_Out_ DWORD * pcbData)
|
||||
{
|
||||
for (HMODULE hMod = NULL; (hMod = DetourEnumerateModules(hMod)) != NULL;) {
|
||||
PVOID pvData;
|
||||
|
||||
pvData = DetourFindPayload(hMod, rguid, pcbData);
|
||||
if (pvData != NULL) {
|
||||
return pvData;
|
||||
}
|
||||
}
|
||||
SetLastError(ERROR_MOD_NOT_FOUND);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
|
||||
_In_ DWORD cbData)
|
||||
{
|
||||
PDETOUR_EXE_RESTORE pder = (PDETOUR_EXE_RESTORE)pvData;
|
||||
|
||||
if (pder->cb != sizeof(*pder) || pder->cb > cbData) {
|
||||
SetLastError(ERROR_BAD_EXE_FORMAT);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD dwPermIdh = ~0u;
|
||||
DWORD dwPermInh = ~0u;
|
||||
DWORD dwPermClr = ~0u;
|
||||
DWORD dwIgnore;
|
||||
BOOL fSucceeded = FALSE;
|
||||
BOOL fUpdated32To64 = FALSE;
|
||||
|
||||
if (pder->pclr != NULL && pder->clr.Flags != ((PDETOUR_CLR_HEADER)pder->pclr)->Flags) {
|
||||
// If we had to promote the 32/64-bit agnostic IL to 64-bit, we can't restore
|
||||
// that.
|
||||
fUpdated32To64 = TRUE;
|
||||
}
|
||||
|
||||
if (DetourVirtualProtectSameExecute(pder->pidh, pder->cbidh,
|
||||
PAGE_EXECUTE_READWRITE, &dwPermIdh)) {
|
||||
if (DetourVirtualProtectSameExecute(pder->pinh, pder->cbinh,
|
||||
PAGE_EXECUTE_READWRITE, &dwPermInh)) {
|
||||
|
||||
CopyMemory(pder->pidh, &pder->idh, pder->cbidh);
|
||||
CopyMemory(pder->pinh, &pder->inh, pder->cbinh);
|
||||
|
||||
if (pder->pclr != NULL && !fUpdated32To64) {
|
||||
if (DetourVirtualProtectSameExecute(pder->pclr, pder->cbclr,
|
||||
PAGE_EXECUTE_READWRITE, &dwPermClr)) {
|
||||
CopyMemory(pder->pclr, &pder->clr, pder->cbclr);
|
||||
VirtualProtect(pder->pclr, pder->cbclr, dwPermClr, &dwIgnore);
|
||||
fSucceeded = TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fSucceeded = TRUE;
|
||||
}
|
||||
VirtualProtect(pder->pinh, pder->cbinh, dwPermInh, &dwIgnore);
|
||||
}
|
||||
VirtualProtect(pder->pidh, pder->cbidh, dwPermIdh, &dwIgnore);
|
||||
}
|
||||
return fSucceeded;
|
||||
}
|
||||
|
||||
BOOL WINAPI DetourRestoreAfterWith()
|
||||
{
|
||||
PVOID pvData;
|
||||
DWORD cbData;
|
||||
|
||||
pvData = DetourFindPayloadEx(DETOUR_EXE_RESTORE_GUID, &cbData);
|
||||
|
||||
if (pvData != NULL && cbData != 0) {
|
||||
return DetourRestoreAfterWithEx(pvData, cbData);
|
||||
}
|
||||
SetLastError(ERROR_MOD_NOT_FOUND);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// End of File
|
269
src/detours/uimports.cpp
Normal file
269
src/detours/uimports.cpp
Normal file
@ -0,0 +1,269 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Add DLLs to a module import table (uimports.cpp of detours.lib)
|
||||
//
|
||||
// Microsoft Research Detours Package, Version 4.0.1
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Note that this file is included into creatwth.cpp one or more times
|
||||
// (once for each supported module format).
|
||||
//
|
||||
|
||||
#if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH
|
||||
#error detours.h version mismatch
|
||||
#endif
|
||||
|
||||
// UpdateImports32 aka UpdateImports64
|
||||
static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||
HMODULE hModule,
|
||||
__in_ecount(nDlls) LPCSTR *plpDlls,
|
||||
DWORD nDlls)
|
||||
{
|
||||
BOOL fSucceeded = FALSE;
|
||||
DWORD cbNew = 0;
|
||||
|
||||
BYTE * pbNew = NULL;
|
||||
DWORD i;
|
||||
SIZE_T cbRead;
|
||||
DWORD n;
|
||||
|
||||
PBYTE pbModule = (PBYTE)hModule;
|
||||
|
||||
IMAGE_DOS_HEADER idh;
|
||||
ZeroMemory(&idh, sizeof(idh));
|
||||
if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), &cbRead)
|
||||
|| cbRead < sizeof(idh)) {
|
||||
|
||||
DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %d\n",
|
||||
pbModule, pbModule + sizeof(idh), GetLastError()));
|
||||
|
||||
finish:
|
||||
if (pbNew != NULL) {
|
||||
delete[] pbNew;
|
||||
pbNew = NULL;
|
||||
}
|
||||
return fSucceeded;
|
||||
}
|
||||
|
||||
IMAGE_NT_HEADERS_XX inh;
|
||||
ZeroMemory(&inh, sizeof(inh));
|
||||
|
||||
if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), &cbRead)
|
||||
|| cbRead < sizeof(inh)) {
|
||||
DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %d\n",
|
||||
pbModule + idh.e_lfanew,
|
||||
pbModule + idh.e_lfanew + sizeof(inh),
|
||||
GetLastError()));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (inh.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC_XX) {
|
||||
DETOUR_TRACE(("Wrong size image (%04x != %04x).\n",
|
||||
inh.OptionalHeader.Magic, IMAGE_NT_OPTIONAL_HDR_MAGIC_XX));
|
||||
SetLastError(ERROR_INVALID_BLOCK);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
// Zero out the bound table so loader doesn't use it instead of our new table.
|
||||
inh.BOUND_DIRECTORY.VirtualAddress = 0;
|
||||
inh.BOUND_DIRECTORY.Size = 0;
|
||||
|
||||
// Find the size of the mapped file.
|
||||
DWORD dwSec = idh.e_lfanew +
|
||||
FIELD_OFFSET(IMAGE_NT_HEADERS_XX, OptionalHeader) +
|
||||
inh.FileHeader.SizeOfOptionalHeader;
|
||||
|
||||
for (i = 0; i < inh.FileHeader.NumberOfSections; i++) {
|
||||
IMAGE_SECTION_HEADER ish;
|
||||
ZeroMemory(&ish, sizeof(ish));
|
||||
|
||||
if (!ReadProcessMemory(hProcess, pbModule + dwSec + sizeof(ish) * i, &ish,
|
||||
sizeof(ish), &cbRead)
|
||||
|| cbRead < sizeof(ish)) {
|
||||
|
||||
DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %d\n",
|
||||
pbModule + dwSec + sizeof(ish) * i,
|
||||
pbModule + dwSec + sizeof(ish) * (i + 1),
|
||||
GetLastError()));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
DETOUR_TRACE(("ish[%d] : va=%08x sr=%d\n", i, ish.VirtualAddress, ish.SizeOfRawData));
|
||||
|
||||
// If the file didn't have an IAT_DIRECTORY, we assign it...
|
||||
if (inh.IAT_DIRECTORY.VirtualAddress == 0 &&
|
||||
inh.IMPORT_DIRECTORY.VirtualAddress >= ish.VirtualAddress &&
|
||||
inh.IMPORT_DIRECTORY.VirtualAddress < ish.VirtualAddress + ish.SizeOfRawData) {
|
||||
|
||||
inh.IAT_DIRECTORY.VirtualAddress = ish.VirtualAddress;
|
||||
inh.IAT_DIRECTORY.Size = ish.SizeOfRawData;
|
||||
}
|
||||
}
|
||||
|
||||
DETOUR_TRACE((" Imports: %p..%p\n",
|
||||
(DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
|
||||
(DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress +
|
||||
inh.IMPORT_DIRECTORY.Size));
|
||||
|
||||
DWORD nOldDlls = inh.IMPORT_DIRECTORY.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);
|
||||
DWORD obRem = sizeof(IMAGE_IMPORT_DESCRIPTOR) * nDlls;
|
||||
DWORD obOld = obRem + sizeof(IMAGE_IMPORT_DESCRIPTOR) * nOldDlls;
|
||||
DWORD obTab = PadToDwordPtr(obOld);
|
||||
DWORD obDll = obTab + sizeof(DWORD_XX) * 4 * nDlls;
|
||||
DWORD obStr = obDll;
|
||||
cbNew = obStr;
|
||||
for (n = 0; n < nDlls; n++) {
|
||||
cbNew += PadToDword((DWORD)strlen(plpDlls[n]) + 1);
|
||||
}
|
||||
|
||||
_Analysis_assume_(cbNew >
|
||||
sizeof(IMAGE_IMPORT_DESCRIPTOR) * (nDlls + nOldDlls)
|
||||
+ sizeof(DWORD_XX) * 4 * nDlls);
|
||||
pbNew = new BYTE [cbNew];
|
||||
if (pbNew == NULL) {
|
||||
DETOUR_TRACE(("new BYTE [cbNew] failed.\n"));
|
||||
goto finish;
|
||||
}
|
||||
ZeroMemory(pbNew, cbNew);
|
||||
|
||||
PBYTE pbBase = pbModule;
|
||||
PBYTE pbNext = pbBase
|
||||
+ inh.OptionalHeader.BaseOfCode
|
||||
+ inh.OptionalHeader.SizeOfCode
|
||||
+ inh.OptionalHeader.SizeOfInitializedData
|
||||
+ inh.OptionalHeader.SizeOfUninitializedData;
|
||||
if (pbBase < pbNext) {
|
||||
pbBase = pbNext;
|
||||
}
|
||||
DETOUR_TRACE(("pbBase = %p\n", pbBase));
|
||||
|
||||
PBYTE pbNewIid = FindAndAllocateNearBase(hProcess, pbModule, pbBase, cbNew);
|
||||
if (pbNewIid == NULL) {
|
||||
DETOUR_TRACE(("FindAndAllocateNearBase failed.\n"));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
PIMAGE_IMPORT_DESCRIPTOR piid = (PIMAGE_IMPORT_DESCRIPTOR)pbNew;
|
||||
DWORD_XX *pt;
|
||||
|
||||
DWORD obBase = (DWORD)(pbNewIid - pbModule);
|
||||
DWORD dwProtect = 0;
|
||||
|
||||
if (inh.IMPORT_DIRECTORY.VirtualAddress != 0) {
|
||||
// Read the old import directory if it exists.
|
||||
DETOUR_TRACE(("IMPORT_DIRECTORY perms=%x\n", dwProtect));
|
||||
|
||||
if (!ReadProcessMemory(hProcess,
|
||||
pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
|
||||
&piid[nDlls],
|
||||
nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR), &cbRead)
|
||||
|| cbRead < nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR)) {
|
||||
|
||||
DETOUR_TRACE(("ReadProcessMemory(imports) failed: %d\n", GetLastError()));
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
for (n = 0; n < nDlls; n++) {
|
||||
HRESULT hrRet = StringCchCopyA((char*)pbNew + obStr, cbNew - obStr, plpDlls[n]);
|
||||
if (FAILED(hrRet)) {
|
||||
DETOUR_TRACE(("StringCchCopyA failed: %d\n", GetLastError()));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
// After copying the string, we patch up the size "??" bits if any.
|
||||
hrRet = ReplaceOptionalSizeA((char*)pbNew + obStr,
|
||||
cbNew - obStr,
|
||||
DETOURS_STRINGIFY(DETOURS_BITS_XX));
|
||||
if (FAILED(hrRet)) {
|
||||
DETOUR_TRACE(("ReplaceOptionalSizeA failed: %d\n", GetLastError()));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
DWORD nOffset = obTab + (sizeof(DWORD_XX) * (4 * n));
|
||||
piid[n].OriginalFirstThunk = obBase + nOffset;
|
||||
pt = ((DWORD_XX*)(pbNew + nOffset));
|
||||
pt[0] = IMAGE_ORDINAL_FLAG_XX + 1;
|
||||
pt[1] = 0;
|
||||
|
||||
nOffset = obTab + (sizeof(DWORD_XX) * ((4 * n) + 2));
|
||||
piid[n].FirstThunk = obBase + nOffset;
|
||||
pt = ((DWORD_XX*)(pbNew + nOffset));
|
||||
pt[0] = IMAGE_ORDINAL_FLAG_XX + 1;
|
||||
pt[1] = 0;
|
||||
piid[n].TimeDateStamp = 0;
|
||||
piid[n].ForwarderChain = 0;
|
||||
piid[n].Name = obBase + obStr;
|
||||
|
||||
obStr += PadToDword((DWORD)strlen(plpDlls[n]) + 1);
|
||||
}
|
||||
_Analysis_assume_(obStr <= cbNew);
|
||||
|
||||
#if 0
|
||||
for (i = 0; i < nDlls + nOldDlls; i++) {
|
||||
DETOUR_TRACE(("%8d. Look=%08x Time=%08x Fore=%08x Name=%08x Addr=%08x\n",
|
||||
i,
|
||||
piid[i].OriginalFirstThunk,
|
||||
piid[i].TimeDateStamp,
|
||||
piid[i].ForwarderChain,
|
||||
piid[i].Name,
|
||||
piid[i].FirstThunk));
|
||||
if (piid[i].OriginalFirstThunk == 0 && piid[i].FirstThunk == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!WriteProcessMemory(hProcess, pbNewIid, pbNew, obStr, NULL)) {
|
||||
DETOUR_TRACE(("WriteProcessMemory(iid) failed: %d\n", GetLastError()));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
DETOUR_TRACE(("obBaseBef = %08x..%08x\n",
|
||||
inh.IMPORT_DIRECTORY.VirtualAddress,
|
||||
inh.IMPORT_DIRECTORY.VirtualAddress + inh.IMPORT_DIRECTORY.Size));
|
||||
DETOUR_TRACE(("obBaseAft = %08x..%08x\n", obBase, obBase + obStr));
|
||||
|
||||
// If the file doesn't have an IAT_DIRECTORY, we create it...
|
||||
if (inh.IAT_DIRECTORY.VirtualAddress == 0) {
|
||||
inh.IAT_DIRECTORY.VirtualAddress = obBase;
|
||||
inh.IAT_DIRECTORY.Size = cbNew;
|
||||
}
|
||||
|
||||
inh.IMPORT_DIRECTORY.VirtualAddress = obBase;
|
||||
inh.IMPORT_DIRECTORY.Size = cbNew;
|
||||
|
||||
/////////////////////// Update the NT header for the new import directory.
|
||||
//
|
||||
if (!DetourVirtualProtectSameExecuteEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
|
||||
PAGE_EXECUTE_READWRITE, &dwProtect)) {
|
||||
DETOUR_TRACE(("VirtualProtectEx(inh) write failed: %d\n", GetLastError()));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
inh.OptionalHeader.CheckSum = 0;
|
||||
|
||||
if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
|
||||
DETOUR_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError()));
|
||||
goto finish;
|
||||
}
|
||||
DETOUR_TRACE(("WriteProcessMemory(idh:%p..%p)\n", pbModule, pbModule + sizeof(idh)));
|
||||
|
||||
if (!WriteProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) {
|
||||
DETOUR_TRACE(("WriteProcessMemory(inh) failed: %d\n", GetLastError()));
|
||||
goto finish;
|
||||
}
|
||||
DETOUR_TRACE(("WriteProcessMemory(inh:%p..%p)\n",
|
||||
pbModule + idh.e_lfanew,
|
||||
pbModule + idh.e_lfanew + sizeof(inh)));
|
||||
|
||||
if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
|
||||
dwProtect, &dwProtect)) {
|
||||
DETOUR_TRACE(("VirtualProtectEx(idh) restore failed: %d\n", GetLastError()));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
fSucceeded = TRUE;
|
||||
goto finish;
|
||||
}
|
47
src/dinput.c
47
src/dinput.c
@ -2,13 +2,13 @@
|
||||
#include <dinput.h>
|
||||
#include "hook.h"
|
||||
|
||||
typedef HRESULT (WINAPI *DInputCreateA)(HINSTANCE, DWORD, LPDIRECTINPUTA*, LPUNKNOWN);
|
||||
typedef HRESULT (WINAPI *DICreateDevice)(IDirectInputA*, REFGUID, LPDIRECTINPUTDEVICEA *, LPUNKNOWN);
|
||||
typedef HRESULT (WINAPI *DIDSetCooperativeLevel)(IDirectInputDeviceA *, HWND, DWORD);
|
||||
typedef HRESULT (WINAPI *DIRECTINPUTCREATEAPROC)(HINSTANCE, DWORD, LPDIRECTINPUTA*, LPUNKNOWN);
|
||||
typedef HRESULT (WINAPI *DICREATEDEVICEPROC)(IDirectInputA*, REFGUID, LPDIRECTINPUTDEVICEA *, LPUNKNOWN);
|
||||
typedef HRESULT (WINAPI *DIDSETCOOPERATIVELEVELPROC)(IDirectInputDeviceA *, HWND, DWORD);
|
||||
|
||||
static DInputCreateA DInputCreateA_;
|
||||
static DICreateDevice DICreateDevice_;
|
||||
static DIDSetCooperativeLevel DIDSetCooperativeLevel_;
|
||||
static DIRECTINPUTCREATEAPROC DInputCreateA;
|
||||
static DICREATEDEVICEPROC DICreateDevice;
|
||||
static DIDSETCOOPERATIVELEVELPROC DIDSetCooperativeLevel;
|
||||
|
||||
static PROC HookFunc(PROC *orgFunc, PROC newFunc)
|
||||
{
|
||||
@ -27,17 +27,17 @@ static PROC HookFunc(PROC *orgFunc, PROC newFunc)
|
||||
|
||||
static HRESULT WINAPI fake_DIDSetCooperativeLevel(IDirectInputDeviceA *This, HWND hwnd, DWORD dwFlags)
|
||||
{
|
||||
return DIDSetCooperativeLevel_(This, hwnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
|
||||
return DIDSetCooperativeLevel(This, hwnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI fake_DICreateDevice(IDirectInputA *This, REFGUID rguid, LPDIRECTINPUTDEVICEA * lplpDIDevice, LPUNKNOWN pUnkOuter)
|
||||
{
|
||||
HRESULT result = DICreateDevice_(This, rguid, lplpDIDevice, pUnkOuter);
|
||||
HRESULT result = DICreateDevice(This, rguid, lplpDIDevice, pUnkOuter);
|
||||
|
||||
if (SUCCEEDED(result) && !DIDSetCooperativeLevel_)
|
||||
if (SUCCEEDED(result) && !DIDSetCooperativeLevel)
|
||||
{
|
||||
DIDSetCooperativeLevel_ =
|
||||
(DIDSetCooperativeLevel)HookFunc(
|
||||
DIDSetCooperativeLevel =
|
||||
(DIDSETCOOPERATIVELEVELPROC)HookFunc(
|
||||
(PROC *)&(*lplpDIDevice)->lpVtbl->SetCooperativeLevel, (PROC)fake_DIDSetCooperativeLevel);
|
||||
}
|
||||
|
||||
@ -46,22 +46,33 @@ static HRESULT WINAPI fake_DICreateDevice(IDirectInputA *This, REFGUID rguid, LP
|
||||
|
||||
static HRESULT WINAPI fake_DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA* lplpDirectInput, LPUNKNOWN punkOuter)
|
||||
{
|
||||
DInputCreateA_ = (DInputCreateA)GetProcAddress(GetModuleHandle("dinput.dll"), "DirectInputCreateA");
|
||||
if (!DInputCreateA_)
|
||||
DInputCreateA =
|
||||
(DIRECTINPUTCREATEAPROC)GetProcAddress(GetModuleHandle("dinput.dll"), "DirectInputCreateA");
|
||||
|
||||
if (!DInputCreateA)
|
||||
return DIERR_GENERIC;
|
||||
|
||||
HRESULT result = DInputCreateA_(hinst, dwVersion, lplpDirectInput, punkOuter);
|
||||
HRESULT result = DInputCreateA(hinst, dwVersion, lplpDirectInput, punkOuter);
|
||||
|
||||
if (SUCCEEDED(result) && !DICreateDevice_)
|
||||
if (SUCCEEDED(result) && !DICreateDevice)
|
||||
{
|
||||
DICreateDevice_ =
|
||||
(DICreateDevice)HookFunc((PROC *)&(*lplpDirectInput)->lpVtbl->CreateDevice, (PROC)fake_DICreateDevice);
|
||||
DICreateDevice =
|
||||
(DICREATEDEVICEPROC)HookFunc((PROC *)&(*lplpDirectInput)->lpVtbl->CreateDevice, (PROC)fake_DICreateDevice);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void dinput_init()
|
||||
void DInput_Hook()
|
||||
{
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "dinput.dll", "DirectInputCreateA", (PROC)fake_DirectInputCreateA);
|
||||
}
|
||||
|
||||
void DInput_UnHook()
|
||||
{
|
||||
Hook_PatchIAT(
|
||||
GetModuleHandle(NULL),
|
||||
"dinput.dll",
|
||||
"DirectInputCreateA",
|
||||
(PROC)GetProcAddress(GetModuleHandle("dinput.dll"), "DirectInputCreateA"));
|
||||
}
|
||||
|
163
src/hook.c
163
src/hook.c
@ -4,7 +4,12 @@
|
||||
#include "mouse.h"
|
||||
#include "hook.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "detours.h"
|
||||
#endif
|
||||
|
||||
BOOL Hook_Active;
|
||||
int HookingMethod = 1;
|
||||
GETCURSORPOSPROC real_GetCursorPos = GetCursorPos;
|
||||
CLIPCURSORPROC real_ClipCursor = ClipCursor;
|
||||
SHOWCURSORPROC real_ShowCursor = ShowCursor;
|
||||
@ -86,78 +91,41 @@ void Hook_PatchIAT(HMODULE hMod, char *moduleName, char *functionName, PROC newF
|
||||
}
|
||||
}
|
||||
|
||||
PROC Hook_HotPatch(PROC function, PROC newFunction)
|
||||
void Hook_Create(char *moduleName, char *functionName, PROC newFunction, PROC *function)
|
||||
{
|
||||
PROC result = function;
|
||||
|
||||
if (!function)
|
||||
return result;
|
||||
|
||||
unsigned short *bytes = (unsigned short *)function;
|
||||
|
||||
if (*bytes == 0x25FF) // JMP DWORD PTR
|
||||
#ifdef _MSC_VER
|
||||
if (HookingMethod == 2)
|
||||
{
|
||||
char *address = (char *)function;
|
||||
DWORD oldProtect;
|
||||
|
||||
if (VirtualProtect(address, 8, PAGE_EXECUTE_READWRITE, &oldProtect))
|
||||
{
|
||||
if (memcmp(address + 6, (const char[]) { 0xCC, 0xCC }, 2) == 0 ||
|
||||
memcmp(address + 6, (const char[]) { 0x90, 0x90 }, 2) == 0)
|
||||
{
|
||||
memmove(address + 2, address, 6);
|
||||
*((WORD *)(&address[0])) = 0xFF8B; // mov edi, edi
|
||||
}
|
||||
|
||||
VirtualProtect(address, 8, oldProtect, &oldProtect);
|
||||
}
|
||||
DetourTransactionBegin();
|
||||
DetourUpdateThread(GetCurrentThread());
|
||||
DetourAttach((PVOID *)function, (PVOID)newFunction);
|
||||
DetourTransactionCommit();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (*bytes == 0xFF8B) // mov edi, edi
|
||||
{
|
||||
char *address = ((char *)function) - 5;
|
||||
DWORD oldProtect;
|
||||
|
||||
if (VirtualProtect(address, 7, PAGE_EXECUTE_READWRITE, &oldProtect))
|
||||
{
|
||||
if (memcmp(address, (const char[]) { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }, 5) == 0 ||
|
||||
memcmp(address, (const char[]) { 0x90, 0x90, 0x90, 0x90, 0x90 }, 5) == 0)
|
||||
{
|
||||
address[0] = 0xE9; // long jump
|
||||
*((DWORD *)(&address[1])) = ((char *)newFunction) - address - 5;
|
||||
*((WORD *)(&address[5])) = 0xF9EB; // short jump to our long jump
|
||||
|
||||
result = (PROC)(((char *)function) + 2);
|
||||
}
|
||||
|
||||
VirtualProtect(address, 7, oldProtect, &oldProtect);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
if (HookingMethod == 1)
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), moduleName, functionName, newFunction);
|
||||
}
|
||||
|
||||
void Hook_TryHotPatch(char *moduleName, char *functionName, PROC newFunction, PROC *function)
|
||||
void Hook_Revert(char *moduleName, char *functionName, PROC newFunction, PROC *function)
|
||||
{
|
||||
FARPROC org = GetProcAddress(GetModuleHandle(moduleName), functionName);
|
||||
if (ddraw->hotPatch && org)
|
||||
#ifdef _MSC_VER
|
||||
if (HookingMethod == 2)
|
||||
{
|
||||
*function = Hook_HotPatch(org, newFunction);
|
||||
|
||||
if (*function == org) // hotpatch failed...
|
||||
{
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), moduleName, functionName, newFunction);
|
||||
|
||||
if (ddraw->bnetHack)
|
||||
Hook_PatchIAT(GetModuleHandle("storm.dll"), moduleName, functionName, newFunction);
|
||||
}
|
||||
DetourTransactionBegin();
|
||||
DetourUpdateThread(GetCurrentThread());
|
||||
DetourDetach((PVOID *)function, (PVOID)newFunction);
|
||||
DetourTransactionCommit();
|
||||
}
|
||||
else
|
||||
{
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), moduleName, functionName, newFunction);
|
||||
#endif
|
||||
|
||||
if (ddraw->bnetHack)
|
||||
Hook_PatchIAT(GetModuleHandle("storm.dll"), moduleName, functionName, newFunction);
|
||||
if (HookingMethod == 1)
|
||||
{
|
||||
Hook_PatchIAT(
|
||||
GetModuleHandle(NULL),
|
||||
moduleName,
|
||||
functionName,
|
||||
GetProcAddress(GetModuleHandle(moduleName), functionName));
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,27 +135,54 @@ void Hook_Init()
|
||||
{
|
||||
Hook_Active = TRUE;
|
||||
|
||||
Hook_TryHotPatch("user32.dll", "GetCursorPos", (PROC)fake_GetCursorPos, (PROC *)&real_GetCursorPos);
|
||||
Hook_TryHotPatch("user32.dll", "ClipCursor", (PROC)fake_ClipCursor, (PROC *)&real_ClipCursor);
|
||||
Hook_TryHotPatch("user32.dll", "ShowCursor", (PROC)fake_ShowCursor, (PROC *)&real_ShowCursor);
|
||||
Hook_TryHotPatch("user32.dll", "SetCursor", (PROC)fake_SetCursor, (PROC *)&real_SetCursor);
|
||||
Hook_TryHotPatch("user32.dll", "GetWindowRect", (PROC)fake_GetWindowRect, (PROC *)&real_GetWindowRect);
|
||||
Hook_TryHotPatch("user32.dll", "GetClientRect", (PROC)fake_GetClientRect, (PROC *)&real_GetClientRect);
|
||||
Hook_TryHotPatch("user32.dll", "ClientToScreen", (PROC)fake_ClientToScreen, (PROC *)&real_ClientToScreen);
|
||||
Hook_TryHotPatch("user32.dll", "ScreenToClient", (PROC)fake_ScreenToClient, (PROC *)&real_ScreenToClient);
|
||||
Hook_TryHotPatch("user32.dll", "SetCursorPos", (PROC)fake_SetCursorPos, (PROC *)&real_SetCursorPos);
|
||||
Hook_TryHotPatch("user32.dll", "GetClipCursor", (PROC)fake_GetClipCursor, (PROC *)&real_GetClipCursor);
|
||||
Hook_TryHotPatch("user32.dll", "WindowFromPoint", (PROC)fake_WindowFromPoint, (PROC *)&real_WindowFromPoint);
|
||||
Hook_TryHotPatch("user32.dll", "GetCursorInfo", (PROC)fake_GetCursorInfo, (PROC *)&real_GetCursorInfo);
|
||||
Hook_TryHotPatch("user32.dll", "GetSystemMetrics", (PROC)fake_GetSystemMetrics, (PROC *)&real_GetSystemMetrics);
|
||||
Hook_TryHotPatch("user32.dll", "SetWindowPos", (PROC)fake_SetWindowPos, (PROC *)&real_SetWindowPos);
|
||||
Hook_TryHotPatch("user32.dll", "MoveWindow", (PROC)fake_MoveWindow, (PROC *)&real_MoveWindow);
|
||||
Hook_TryHotPatch("user32.dll", "SendMessageA", (PROC)fake_SendMessageA, (PROC *)&real_SendMessageA);
|
||||
Hook_TryHotPatch("user32.dll", "SetWindowLongA", (PROC)fake_SetWindowLongA, (PROC *)&real_SetWindowLongA);
|
||||
Hook_TryHotPatch("user32.dll", "EnableWindow", (PROC)fake_EnableWindow, (PROC *)&real_EnableWindow);
|
||||
Hook_TryHotPatch("user32.dll", "CreateWindowExA", (PROC)fake_CreateWindowExA, (PROC *)&real_CreateWindowExA);
|
||||
Hook_TryHotPatch("user32.dll", "DestroyWindow", (PROC)fake_DestroyWindow, (PROC *)&real_DestroyWindow);
|
||||
|
||||
//Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "GetCursorPos", (PROC)fake_GetCursorPos);
|
||||
Hook_Create("user32.dll", "GetCursorPos", (PROC)fake_GetCursorPos, (PROC *)&real_GetCursorPos);
|
||||
Hook_Create("user32.dll", "ClipCursor", (PROC)fake_ClipCursor, (PROC *)&real_ClipCursor);
|
||||
Hook_Create("user32.dll", "ShowCursor", (PROC)fake_ShowCursor, (PROC *)&real_ShowCursor);
|
||||
Hook_Create("user32.dll", "SetCursor", (PROC)fake_SetCursor, (PROC *)&real_SetCursor);
|
||||
Hook_Create("user32.dll", "GetWindowRect", (PROC)fake_GetWindowRect, (PROC *)&real_GetWindowRect);
|
||||
Hook_Create("user32.dll", "GetClientRect", (PROC)fake_GetClientRect, (PROC *)&real_GetClientRect);
|
||||
Hook_Create("user32.dll", "ClientToScreen", (PROC)fake_ClientToScreen, (PROC *)&real_ClientToScreen);
|
||||
Hook_Create("user32.dll", "ScreenToClient", (PROC)fake_ScreenToClient, (PROC *)&real_ScreenToClient);
|
||||
Hook_Create("user32.dll", "SetCursorPos", (PROC)fake_SetCursorPos, (PROC *)&real_SetCursorPos);
|
||||
Hook_Create("user32.dll", "GetClipCursor", (PROC)fake_GetClipCursor, (PROC *)&real_GetClipCursor);
|
||||
Hook_Create("user32.dll", "WindowFromPoint", (PROC)fake_WindowFromPoint, (PROC *)&real_WindowFromPoint);
|
||||
Hook_Create("user32.dll", "GetCursorInfo", (PROC)fake_GetCursorInfo, (PROC *)&real_GetCursorInfo);
|
||||
Hook_Create("user32.dll", "GetSystemMetrics", (PROC)fake_GetSystemMetrics, (PROC *)&real_GetSystemMetrics);
|
||||
Hook_Create("user32.dll", "SetWindowPos", (PROC)fake_SetWindowPos, (PROC *)&real_SetWindowPos);
|
||||
Hook_Create("user32.dll", "MoveWindow", (PROC)fake_MoveWindow, (PROC *)&real_MoveWindow);
|
||||
Hook_Create("user32.dll", "SendMessageA", (PROC)fake_SendMessageA, (PROC *)&real_SendMessageA);
|
||||
Hook_Create("user32.dll", "SetWindowLongA", (PROC)fake_SetWindowLongA, (PROC *)&real_SetWindowLongA);
|
||||
Hook_Create("user32.dll", "EnableWindow", (PROC)fake_EnableWindow, (PROC *)&real_EnableWindow);
|
||||
Hook_Create("user32.dll", "CreateWindowExA", (PROC)fake_CreateWindowExA, (PROC *)&real_CreateWindowExA);
|
||||
Hook_Create("user32.dll", "DestroyWindow", (PROC)fake_DestroyWindow, (PROC *)&real_DestroyWindow);
|
||||
}
|
||||
}
|
||||
|
||||
void Hook_Exit()
|
||||
{
|
||||
if (Hook_Active)
|
||||
{
|
||||
Hook_Active = FALSE;
|
||||
|
||||
Hook_Revert("user32.dll", "GetCursorPos", (PROC)fake_GetCursorPos, (PROC *)&real_GetCursorPos);
|
||||
Hook_Revert("user32.dll", "ClipCursor", (PROC)fake_ClipCursor, (PROC *)&real_ClipCursor);
|
||||
Hook_Revert("user32.dll", "ShowCursor", (PROC)fake_ShowCursor, (PROC *)&real_ShowCursor);
|
||||
Hook_Revert("user32.dll", "SetCursor", (PROC)fake_SetCursor, (PROC *)&real_SetCursor);
|
||||
Hook_Revert("user32.dll", "GetWindowRect", (PROC)fake_GetWindowRect, (PROC *)&real_GetWindowRect);
|
||||
Hook_Revert("user32.dll", "GetClientRect", (PROC)fake_GetClientRect, (PROC *)&real_GetClientRect);
|
||||
Hook_Revert("user32.dll", "ClientToScreen", (PROC)fake_ClientToScreen, (PROC *)&real_ClientToScreen);
|
||||
Hook_Revert("user32.dll", "ScreenToClient", (PROC)fake_ScreenToClient, (PROC *)&real_ScreenToClient);
|
||||
Hook_Revert("user32.dll", "SetCursorPos", (PROC)fake_SetCursorPos, (PROC *)&real_SetCursorPos);
|
||||
Hook_Revert("user32.dll", "GetClipCursor", (PROC)fake_GetClipCursor, (PROC *)&real_GetClipCursor);
|
||||
Hook_Revert("user32.dll", "WindowFromPoint", (PROC)fake_WindowFromPoint, (PROC *)&real_WindowFromPoint);
|
||||
Hook_Revert("user32.dll", "GetCursorInfo", (PROC)fake_GetCursorInfo, (PROC *)&real_GetCursorInfo);
|
||||
Hook_Revert("user32.dll", "GetSystemMetrics", (PROC)fake_GetSystemMetrics, (PROC *)&real_GetSystemMetrics);
|
||||
Hook_Revert("user32.dll", "SetWindowPos", (PROC)fake_SetWindowPos, (PROC *)&real_SetWindowPos);
|
||||
Hook_Revert("user32.dll", "MoveWindow", (PROC)fake_MoveWindow, (PROC *)&real_MoveWindow);
|
||||
Hook_Revert("user32.dll", "SendMessageA", (PROC)fake_SendMessageA, (PROC *)&real_SendMessageA);
|
||||
Hook_Revert("user32.dll", "SetWindowLongA", (PROC)fake_SetWindowLongA, (PROC *)&real_SetWindowLongA);
|
||||
Hook_Revert("user32.dll", "EnableWindow", (PROC)fake_EnableWindow, (PROC *)&real_EnableWindow);
|
||||
Hook_Revert("user32.dll", "CreateWindowExA", (PROC)fake_CreateWindowExA, (PROC *)&real_CreateWindowExA);
|
||||
Hook_Revert("user32.dll", "DestroyWindow", (PROC)fake_DestroyWindow, (PROC *)&real_DestroyWindow);
|
||||
}
|
||||
}
|
||||
|
65
src/main.c
65
src/main.c
@ -36,7 +36,8 @@
|
||||
BOOL screenshot(struct IDirectDrawSurfaceImpl *);
|
||||
void Settings_Load();
|
||||
void Settings_Save(RECT *lpRect, int windowState);
|
||||
void dinput_init();
|
||||
void DInput_Hook();
|
||||
void DInput_UnHook();
|
||||
|
||||
IDirectDrawImpl *ddraw = NULL;
|
||||
|
||||
@ -55,6 +56,33 @@ BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
{
|
||||
char buf[1024];
|
||||
if (GetEnvironmentVariable("__COMPAT_LAYER", buf, sizeof(buf)))
|
||||
{
|
||||
char *s = strtok(buf, " ");
|
||||
while (s)
|
||||
{
|
||||
if (strcmpi(s, "WIN95") == 0 || strcmpi(s, "WIN98") == 0 || strcmpi(s, "NT4SP5") == 0)
|
||||
{
|
||||
char mes[128] = { 0 };
|
||||
|
||||
_snprintf(
|
||||
mes,
|
||||
sizeof(mes),
|
||||
"Please disable the '%s' compatibility mode for all game executables and "
|
||||
"then try to start the game again.",
|
||||
s);
|
||||
|
||||
MessageBoxA(NULL, mes, "Compatibility modes detected - cnc-ddraw", MB_OK);
|
||||
|
||||
//return FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
s = strtok(NULL, " ");
|
||||
}
|
||||
}
|
||||
|
||||
printf("cnc-ddraw DLL_PROCESS_ATTACH\n");
|
||||
|
||||
//SetProcessPriorityBoost(GetCurrentProcess(), TRUE);
|
||||
@ -88,7 +116,7 @@ BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
|
||||
}
|
||||
|
||||
timeBeginPeriod(1);
|
||||
dinput_init();
|
||||
DInput_Hook();
|
||||
break;
|
||||
}
|
||||
case DLL_PROCESS_DETACH:
|
||||
@ -98,6 +126,8 @@ BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
|
||||
Settings_Save(&WindowRect, WindowState);
|
||||
|
||||
timeEndPeriod(1);
|
||||
Hook_Exit();
|
||||
DInput_UnHook();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -278,14 +308,14 @@ void UpdateBnetPos(int newX, int newY)
|
||||
|
||||
HRESULT __stdcall ddraw_Compact(IDirectDrawImpl *This)
|
||||
{
|
||||
printf("DirectDraw::Compact(This=%p) ???\n", This);
|
||||
printf("??? DirectDraw::Compact(This=%p)\n", This);
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_DuplicateSurface(IDirectDrawImpl *This, LPDIRECTDRAWSURFACE src, LPDIRECTDRAWSURFACE *dest)
|
||||
{
|
||||
printf("DirectDraw::DuplicateSurface(This=%p, ...) ???\n", This);
|
||||
printf("??? DirectDraw::DuplicateSurface(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
@ -430,13 +460,13 @@ HRESULT __stdcall ddraw_EnumDisplayModes(IDirectDrawImpl *This, DWORD dwFlags, L
|
||||
|
||||
HRESULT __stdcall ddraw_EnumSurfaces(IDirectDrawImpl *This, DWORD a, LPDDSURFACEDESC b, LPVOID c, LPDDENUMSURFACESCALLBACK d)
|
||||
{
|
||||
printf("DirectDraw::EnumSurfaces(This=%p, ...) ???\n", This);
|
||||
printf("??? DirectDraw::EnumSurfaces(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_FlipToGDISurface(IDirectDrawImpl *This)
|
||||
{
|
||||
printf("DirectDraw::FlipToGDISurface(This=%p) ???\n", This);
|
||||
printf("??? DirectDraw::FlipToGDISurface(This=%p)\n", This);
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
@ -473,44 +503,44 @@ HRESULT __stdcall ddraw_GetCaps(IDirectDrawImpl *This, LPDDCAPS lpDDDriverCaps,
|
||||
|
||||
HRESULT __stdcall ddraw_GetDisplayMode(IDirectDrawImpl *This, LPDDSURFACEDESC a)
|
||||
{
|
||||
printf("DirectDraw::GetDisplayMode(This=%p, ...) ???\n", This);
|
||||
printf("??? DirectDraw::GetDisplayMode(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_GetFourCCCodes(IDirectDrawImpl *This, LPDWORD a, LPDWORD b)
|
||||
{
|
||||
printf("DirectDraw::GetFourCCCodes(This=%p, ...) ???\n", This);
|
||||
printf("??? DirectDraw::GetFourCCCodes(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_GetGDISurface(IDirectDrawImpl *This, LPDIRECTDRAWSURFACE *a)
|
||||
{
|
||||
printf("DirectDraw::GetGDISurface(This=%p, ...) ???\n", This);
|
||||
printf("??? DirectDraw::GetGDISurface(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_GetMonitorFrequency(IDirectDrawImpl *This, LPDWORD a)
|
||||
{
|
||||
printf("DirectDraw::GetMonitorFrequency(This=%p, ...) ???\n", This);
|
||||
printf("??? DirectDraw::GetMonitorFrequency(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_GetScanLine(IDirectDrawImpl *This, LPDWORD a)
|
||||
{
|
||||
printf("DirectDraw::GetScanLine(This=%p, ...) ???\n", This);
|
||||
printf("??? DirectDraw::GetScanLine(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_GetVerticalBlankStatus(IDirectDrawImpl *This, LPBOOL lpbIsInVB)
|
||||
{
|
||||
printf("DirectDraw::GetVerticalBlankStatus(This=%p, ...) ???\n", This);
|
||||
printf("??? DirectDraw::GetVerticalBlankStatus(This=%p, ...)\n", This);
|
||||
*lpbIsInVB = TRUE;
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_Initialize(IDirectDrawImpl *This, GUID *a)
|
||||
{
|
||||
printf("DirectDraw::Initialize(This=%p, ...) ???\n", This);
|
||||
printf("??? DirectDraw::Initialize(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
@ -893,8 +923,6 @@ HRESULT __stdcall ddraw_SetDisplayMode(IDirectDrawImpl *This, DWORD width, DWORD
|
||||
RedrawWindow(This->hWnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE);
|
||||
}
|
||||
|
||||
InterlockedExchange(&ddraw->minimized, FALSE);
|
||||
|
||||
if(This->render.thread == NULL)
|
||||
{
|
||||
InterlockedExchange(&ddraw->render.paletteUpdated, TRUE);
|
||||
@ -975,6 +1003,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
case WM_NCLBUTTONUP:
|
||||
case WM_NCACTIVATE:
|
||||
case WM_NCPAINT:
|
||||
case WM_NCHITTEST:
|
||||
{
|
||||
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
@ -1289,8 +1318,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
mouse_lock();
|
||||
}
|
||||
|
||||
InterlockedExchange(&ddraw->minimized, FALSE);
|
||||
}
|
||||
|
||||
if (!ddraw->handlemouse)
|
||||
@ -1314,8 +1341,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
ShowWindow(ddraw->hWnd, SW_MINIMIZE);
|
||||
ChangeDisplaySettings(&ddraw->mode, CDS_FULLSCREEN);
|
||||
}
|
||||
|
||||
InterlockedExchange(&ddraw->minimized, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1541,7 +1566,7 @@ HRESULT __stdcall ddraw_SetCooperativeLevel(IDirectDrawImpl *This, HWND hWnd, DW
|
||||
HRESULT __stdcall ddraw_WaitForVerticalBlank(IDirectDrawImpl *This, DWORD a, HANDLE b)
|
||||
{
|
||||
#if _DEBUG_X
|
||||
printf("DirectDraw::WaitForVerticalBlank(This=%p, ...) ???\n", This);
|
||||
printf("??? DirectDraw::WaitForVerticalBlank(This=%p, ...)\n", This);
|
||||
#endif
|
||||
return DD_OK;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ HRESULT __stdcall ddraw_palette_SetEntries(IDirectDrawPaletteImpl *This, DWORD d
|
||||
|
||||
HRESULT __stdcall ddraw_palette_QueryInterface(IDirectDrawPaletteImpl *This, REFIID riid, void **obj)
|
||||
{
|
||||
printf("DirectDrawPalette::QueryInterface(This=%p, riid=%08X, obj=%p) ???\n", This, (unsigned int)riid, obj);
|
||||
printf("??? DirectDrawPalette::QueryInterface(This=%p, riid=%08X, obj=%p)\n", This, (unsigned int)riid, obj);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -105,13 +105,13 @@ ULONG __stdcall ddraw_palette_Release(IDirectDrawPaletteImpl *This)
|
||||
|
||||
HRESULT __stdcall ddraw_palette_GetCaps(IDirectDrawPaletteImpl *This, LPDWORD caps)
|
||||
{
|
||||
printf("DirectDrawPalette::GetCaps(This=%p, caps=%p) ???\n", This, caps);
|
||||
printf("??? DirectDrawPalette::GetCaps(This=%p, caps=%p)\n", This, caps);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_palette_Initialize(IDirectDrawPaletteImpl *This, LPDIRECTDRAW lpDD, DWORD dw, LPPALETTEENTRY paent)
|
||||
{
|
||||
printf("DirectDrawPalette::Initialize(This=%p, ...) ???\n", This);
|
||||
printf("??? DirectDrawPalette::Initialize(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ static GLuint FrameBufferTexId;
|
||||
static GLuint ScaleVBOs[3], ScaleVAO;
|
||||
static BOOL UseOpenGL;
|
||||
static BOOL AdjustAlignment;
|
||||
static BOOL UseBilinear;
|
||||
static BOOL FilterBilinear;
|
||||
|
||||
static HGLRC CreateContext(HDC hdc);
|
||||
static void SetMaxFPS();
|
||||
@ -178,7 +178,7 @@ static void BuildPrograms()
|
||||
else
|
||||
OpenGL_GotVersion3 = FALSE;
|
||||
|
||||
UseBilinear = strstr(ddraw->shader, "\\bilinear.glsl") != 0;
|
||||
FilterBilinear = strstr(ddraw->shader, "bilinear.glsl") != 0;
|
||||
}
|
||||
|
||||
if (OpenGL_GotVersion2 && !MainProgram)
|
||||
@ -488,8 +488,8 @@ static void InitScaleProgram()
|
||||
|
||||
glGenTextures(1, &FrameBufferTexId);
|
||||
glBindTexture(GL_TEXTURE_2D, FrameBufferTexId);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, UseBilinear ? GL_LINEAR : GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, UseBilinear ? GL_LINEAR : GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, FilterBilinear ? GL_LINEAR : GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, FilterBilinear ? GL_LINEAR : GL_NEAREST);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, SurfaceTexWidth, SurfaceTexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FrameBufferTexId, 0);
|
||||
|
@ -304,12 +304,6 @@ DWORD WINAPI render_d3d9_main(void)
|
||||
|
||||
while (ddraw->render.run && WaitForSingleObject(ddraw->render.sem, 200) != WAIT_FAILED)
|
||||
{
|
||||
if (InterlockedExchangeAdd(&ddraw->minimized, 0))
|
||||
{
|
||||
Sleep(500);
|
||||
continue;
|
||||
}
|
||||
|
||||
#if _DEBUG
|
||||
DrawFrameInfoStart();
|
||||
#endif
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "main.h"
|
||||
#include "opengl.h"
|
||||
#include "render_d3d9.h"
|
||||
#include "hook.h"
|
||||
|
||||
static char SettingsIniPath[MAX_PATH];
|
||||
static char ProcessFileName[96];
|
||||
@ -41,7 +42,6 @@ void Settings_Load()
|
||||
ddraw->noactivateapp = GetBool("noactivateapp", FALSE);
|
||||
ddraw->vhack = GetBool("vhack", FALSE);
|
||||
ddraw->accurateTimers = GetBool("accuratetimers", FALSE);
|
||||
ddraw->hotPatch = GetBool("hotpatch", FALSE);
|
||||
ddraw->bnetHack = GetBool("bnetHack", TRUE);
|
||||
|
||||
WindowRect.right = GetInt("width", 0);
|
||||
@ -49,6 +49,10 @@ void Settings_Load()
|
||||
WindowRect.left = GetInt("posX", -32000);
|
||||
WindowRect.top = GetInt("posY", -32000);
|
||||
|
||||
#ifndef _DEBUG
|
||||
HookingMethod = GetInt("hook", 1);
|
||||
#endif
|
||||
|
||||
ddraw->render.maxfps = GetInt("maxfps", 125);
|
||||
|
||||
if (ddraw->accurateTimers || ddraw->vsync)
|
||||
@ -276,9 +280,9 @@ static void CreateSettingsIni()
|
||||
"; Force CPU0 affinity, avoids crashes/freezing, *might* have a performance impact\n"
|
||||
"singlecpu=true\n"
|
||||
"\n"
|
||||
"; Use hotpatching rather than IAT hooking\n"
|
||||
"; Windows API Hooking, Possible values: 0 = disabled, 1 = IAT Hooking, 2 = Microsoft Detours\n"
|
||||
"; Note: Can be used to fix issues related to new features added by cnc-ddraw such as windowed mode or stretching\n"
|
||||
"hotpatch=false\n"
|
||||
"hook=1\n"
|
||||
"\n"
|
||||
"; Workaround for battle.net on Diablo and Warcraft 2 BNE\n"
|
||||
"bnetHack=true\n"
|
||||
@ -323,6 +327,9 @@ static void CreateSettingsIni()
|
||||
"[olwin]\n"
|
||||
"noactivateapp=true\n"
|
||||
"maxgameticks=60\n"
|
||||
"hook=2\n"
|
||||
"handlemouse=false\n"
|
||||
"renderer=gdi\n"
|
||||
"\n"
|
||||
"; Dark Reign: The Future of War\n"
|
||||
"[DKReign]\n"
|
||||
@ -356,8 +363,9 @@ static void CreateSettingsIni()
|
||||
"maxfps=59\n"
|
||||
"accuratetimers=true\n"
|
||||
"\n"
|
||||
"; Command & Conquer: Tiberian Sun\n"
|
||||
"; Command & Conquer: Tiberian Sun / Command & Conquer: Red Alert 2\n"
|
||||
"[game]\n"
|
||||
"checkfile=.\\blowfish.dll\n"
|
||||
"noactivateapp=true\n"
|
||||
"handlemouse=false\n"
|
||||
"maxfps=60\n"
|
||||
@ -398,6 +406,11 @@ static void CreateSettingsIni()
|
||||
"handlemouse=false\n"
|
||||
"maxfps=60\n"
|
||||
"\n"
|
||||
"; Command & Conquer: Red Alert 2: Yuri's Revenge - XWIS\n"
|
||||
"[Yuri's Revenge]\n"
|
||||
"noactivateapp=true\n"
|
||||
"handlemouse=false\n"
|
||||
"maxfps=60\n"
|
||||
"; Diablo\n"
|
||||
"[Diablo]\n"
|
||||
"bnetHack=true\n"
|
||||
@ -416,7 +429,17 @@ static DWORD GetString(LPCSTR key, LPCSTR defaultValue, LPSTR outString, DWORD o
|
||||
{
|
||||
DWORD s = GetPrivateProfileStringA(ProcessFileName, key, "", outString, outSize, SettingsIniPath);
|
||||
if (s > 0)
|
||||
return s;
|
||||
{
|
||||
char buf[MAX_PATH] = { 0 };
|
||||
|
||||
if (GetPrivateProfileStringA(ProcessFileName, "checkfile", "", buf, sizeof(buf), SettingsIniPath) > 0)
|
||||
{
|
||||
if (GetFileAttributes(buf) != INVALID_FILE_ATTRIBUTES)
|
||||
return s;
|
||||
}
|
||||
else
|
||||
return s;
|
||||
}
|
||||
|
||||
return GetPrivateProfileStringA("ddraw", key, defaultValue, outString, outSize, SettingsIniPath);
|
||||
}
|
||||
|
@ -34,11 +34,11 @@ void *pvBmpBits;
|
||||
|
||||
HRESULT __stdcall ddraw_surface_QueryInterface(IDirectDrawSurfaceImpl *This, REFIID riid, void **obj)
|
||||
{
|
||||
printf("DirectDrawSurface::QueryInterface(This=%p, riid=%08X, obj=%p) ???\n", This, (unsigned int)riid, obj);
|
||||
printf("??? DirectDrawSurface::QueryInterface(This=%p, riid=%08X, obj=%p)\n", This, (unsigned int)riid, obj);
|
||||
|
||||
if (riid && !IsEqualGUID(&IID_IDirectDrawSurface, riid))
|
||||
{
|
||||
printf(" IID_IDirectDrawSurfaceX\n");
|
||||
printf(" GUID = %08X\n", ((GUID *)riid)->Data1);
|
||||
|
||||
IDirectDrawSurface_AddRef(This);
|
||||
}
|
||||
@ -95,14 +95,14 @@ ULONG __stdcall ddraw_surface_Release(IDirectDrawSurfaceImpl *This)
|
||||
|
||||
HRESULT __stdcall ddraw_surface_AddAttachedSurface(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWSURFACE lpDDSurface)
|
||||
{
|
||||
printf("DirectDrawSurface::AddAttachedSurface(This=%p, lpDDSurface=%p) ???\n", This, lpDDSurface);
|
||||
printf("??? DirectDrawSurface::AddAttachedSurface(This=%p, lpDDSurface=%p)\n", This, lpDDSurface);
|
||||
IDirectDrawSurface_AddRef(lpDDSurface);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_surface_AddOverlayDirtyRect(IDirectDrawSurfaceImpl *This, LPRECT a)
|
||||
{
|
||||
printf("DirectDrawSurface::AddOverlayDirtyRect(This=%p, ...) ???\n", This);
|
||||
printf("??? DirectDrawSurface::AddOverlayDirtyRect(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
@ -213,8 +213,18 @@ HRESULT __stdcall ddraw_surface_Blt(IDirectDrawSurfaceImpl *This, LPRECT lpDestR
|
||||
|
||||
if (Source)
|
||||
{
|
||||
if (dwFlags & DDBLT_KEYSRC)
|
||||
if ((dwFlags & DDBLT_KEYSRC) || (dwFlags & DDBLT_KEYSRCOVERRIDE))
|
||||
{
|
||||
DDCOLORKEY colorKey;
|
||||
|
||||
colorKey.dwColorSpaceLowValue =
|
||||
(dwFlags & DDBLT_KEYSRCOVERRIDE) ?
|
||||
lpDDBltFx->ddckSrcColorkey.dwColorSpaceLowValue : Source->colorKey.dwColorSpaceLowValue;
|
||||
|
||||
colorKey.dwColorSpaceHighValue =
|
||||
(dwFlags & DDBLT_KEYSRCOVERRIDE) ?
|
||||
lpDDBltFx->ddckSrcColorkey.dwColorSpaceHighValue : Source->colorKey.dwColorSpaceHighValue;
|
||||
|
||||
if (!isStretchBlt)
|
||||
{
|
||||
int width = dst_w > src_w ? src_w : dst_w;
|
||||
@ -232,7 +242,7 @@ HRESULT __stdcall ddraw_surface_Blt(IDirectDrawSurfaceImpl *This, LPRECT lpDestR
|
||||
{
|
||||
unsigned char c = ((unsigned char *)Source->surface)[x1 + src_x + ysrc];
|
||||
|
||||
if (c != Source->colorKey.dwColorSpaceLowValue)
|
||||
if (c < colorKey.dwColorSpaceLowValue || c > colorKey.dwColorSpaceHighValue)
|
||||
{
|
||||
((unsigned char *)This->surface)[x1 + dst_x + ydst] = c;
|
||||
}
|
||||
@ -251,7 +261,7 @@ HRESULT __stdcall ddraw_surface_Blt(IDirectDrawSurfaceImpl *This, LPRECT lpDestR
|
||||
{
|
||||
unsigned short c = ((unsigned short *)Source->surface)[x1 + src_x + ysrc];
|
||||
|
||||
if (c != Source->colorKey.dwColorSpaceLowValue)
|
||||
if (c < colorKey.dwColorSpaceLowValue || c > colorKey.dwColorSpaceHighValue)
|
||||
{
|
||||
((unsigned short *)This->surface)[x1 + dst_x + ydst] = c;
|
||||
}
|
||||
@ -261,7 +271,7 @@ HRESULT __stdcall ddraw_surface_Blt(IDirectDrawSurfaceImpl *This, LPRECT lpDestR
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" DDBLT_KEYSRC does not support stretching");
|
||||
printf(" DDBLT_KEYSRC / DDBLT_KEYSRCOVERRIDE does not support stretching");
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -478,7 +488,7 @@ HRESULT __stdcall ddraw_surface_Blt(IDirectDrawSurfaceImpl *This, LPRECT lpDestR
|
||||
|
||||
HRESULT __stdcall ddraw_surface_BltBatch(IDirectDrawSurfaceImpl *This, LPDDBLTBATCH a, DWORD b, DWORD c)
|
||||
{
|
||||
printf("IDirectDrawSurface::BltBatch(This=%p, ...) ???\n", This);
|
||||
printf("??? IDirectDrawSurface::BltBatch(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
@ -548,7 +558,7 @@ HRESULT __stdcall ddraw_surface_BltFast(IDirectDrawSurfaceImpl *This, DWORD dst_
|
||||
{
|
||||
unsigned char c = ((unsigned char *)Source->surface)[x1 + src_x + ysrc];
|
||||
|
||||
if (c != Source->colorKey.dwColorSpaceLowValue)
|
||||
if (c < Source->colorKey.dwColorSpaceLowValue || c > Source->colorKey.dwColorSpaceHighValue)
|
||||
{
|
||||
((unsigned char *)This->surface)[x1 + dst_x + ydst] = c;
|
||||
}
|
||||
@ -567,7 +577,7 @@ HRESULT __stdcall ddraw_surface_BltFast(IDirectDrawSurfaceImpl *This, DWORD dst_
|
||||
{
|
||||
unsigned short c = ((unsigned short *)Source->surface)[x1 + src_x + ysrc];
|
||||
|
||||
if (c != Source->colorKey.dwColorSpaceLowValue)
|
||||
if (c < Source->colorKey.dwColorSpaceLowValue || c > Source->colorKey.dwColorSpaceHighValue)
|
||||
{
|
||||
((unsigned short *)This->surface)[x1 + dst_x + ydst] = c;
|
||||
}
|
||||
@ -667,7 +677,7 @@ HRESULT __stdcall ddraw_surface_EnumAttachedSurfaces(IDirectDrawSurfaceImpl *Thi
|
||||
|
||||
HRESULT __stdcall ddraw_surface_EnumOverlayZOrders(IDirectDrawSurfaceImpl *This, DWORD a, LPVOID b, LPDDENUMSURFACESCALLBACK c)
|
||||
{
|
||||
printf("IDirectDrawSurface::EnumOverlayZOrders(This=%p, ...) ???\n", This);
|
||||
printf("??? IDirectDrawSurface::EnumOverlayZOrders(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
@ -743,7 +753,7 @@ HRESULT __stdcall ddraw_surface_Flip(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWS
|
||||
|
||||
HRESULT __stdcall ddraw_surface_GetAttachedSurface(IDirectDrawSurfaceImpl *This, LPDDSCAPS lpDdsCaps, LPDIRECTDRAWSURFACE FAR *surface)
|
||||
{
|
||||
printf("IDirectDrawSurface::GetAttachedSurface(This=%p, dwCaps=%08X, surface=%p) ???\n", This, lpDdsCaps->dwCaps, surface);
|
||||
printf("??? IDirectDrawSurface::GetAttachedSurface(This=%p, dwCaps=%08X, surface=%p)\n", This, lpDdsCaps->dwCaps, surface);
|
||||
|
||||
if ((This->caps & DDSCAPS_PRIMARYSURFACE) && (This->caps & DDSCAPS_FLIP) && (lpDdsCaps->dwCaps & DDSCAPS_BACKBUFFER))
|
||||
{
|
||||
@ -757,7 +767,7 @@ HRESULT __stdcall ddraw_surface_GetAttachedSurface(IDirectDrawSurfaceImpl *This,
|
||||
HRESULT __stdcall ddraw_surface_GetBltStatus(IDirectDrawSurfaceImpl *This, DWORD a)
|
||||
{
|
||||
#if _DEBUG_X
|
||||
printf("IDirectDrawSurface::GetBltStatus(This=%p, ...) ???\n", This);
|
||||
printf("??? IDirectDrawSurface::GetBltStatus(This=%p, ...)\n", This);
|
||||
#endif
|
||||
return DD_OK;
|
||||
}
|
||||
@ -772,7 +782,7 @@ HRESULT __stdcall ddraw_surface_GetCaps(IDirectDrawSurfaceImpl *This, LPDDSCAPS
|
||||
HRESULT __stdcall ddraw_surface_GetClipper(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWCLIPPER FAR *a)
|
||||
{
|
||||
#if _DEBUG_X
|
||||
printf("IDirectDrawSurface::GetClipper(This=%p, ...) ???\n", This);
|
||||
printf("??? IDirectDrawSurface::GetClipper(This=%p, ...)\n", This);
|
||||
#endif
|
||||
return DD_OK;
|
||||
}
|
||||
@ -780,7 +790,7 @@ HRESULT __stdcall ddraw_surface_GetClipper(IDirectDrawSurfaceImpl *This, LPDIREC
|
||||
HRESULT __stdcall ddraw_surface_GetColorKey(IDirectDrawSurfaceImpl *This, DWORD flags, LPDDCOLORKEY colorKey)
|
||||
{
|
||||
#if _DEBUG_X
|
||||
printf("DirectDrawSurface::GetColorKey(This=%p, flags=0x%08X, colorKey=%p) ???\n", This, flags, colorKey);
|
||||
printf("??? DirectDrawSurface::GetColorKey(This=%p, flags=0x%08X, colorKey=%p)\n", This, flags, colorKey);
|
||||
#endif
|
||||
|
||||
if (colorKey)
|
||||
@ -799,7 +809,7 @@ HRESULT __stdcall ddraw_surface_GetDC(IDirectDrawSurfaceImpl *This, HDC FAR *a)
|
||||
#endif
|
||||
if (This->width % 4)
|
||||
{
|
||||
printf(" GetDC: width=%d height=%d ???\n", This->width, This->height);
|
||||
printf(" GetDC: width=%d height=%d\n", This->width, This->height);
|
||||
}
|
||||
|
||||
RGBQUAD *data =
|
||||
@ -817,14 +827,14 @@ HRESULT __stdcall ddraw_surface_GetDC(IDirectDrawSurfaceImpl *This, HDC FAR *a)
|
||||
HRESULT __stdcall ddraw_surface_GetFlipStatus(IDirectDrawSurfaceImpl *This, DWORD a)
|
||||
{
|
||||
#if _DEBUG_X
|
||||
printf("IDirectDrawSurface::GetFlipStatus(This=%p, ...) ???\n", This);
|
||||
printf("??? IDirectDrawSurface::GetFlipStatus(This=%p, ...)\n", This);
|
||||
#endif
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_surface_GetOverlayPosition(IDirectDrawSurfaceImpl *This, LPLONG a, LPLONG b)
|
||||
{
|
||||
printf("IDirectDrawSurface::GetOverlayPosition(This=%p, ...) ???\n", This);
|
||||
printf("??? IDirectDrawSurface::GetOverlayPosition(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
@ -868,7 +878,7 @@ HRESULT __stdcall ddraw_surface_GetPixelFormat(IDirectDrawSurfaceImpl *This, LPD
|
||||
|
||||
HRESULT __stdcall ddraw_surface_Initialize(IDirectDrawSurfaceImpl *This, LPDIRECTDRAW a, LPDDSURFACEDESC b)
|
||||
{
|
||||
printf("IDirectDrawSurface::Initialize(This=%p, ...) ???\n", This);
|
||||
printf("??? IDirectDrawSurface::Initialize(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
@ -921,21 +931,21 @@ HRESULT __stdcall ddraw_surface_ReleaseDC(IDirectDrawSurfaceImpl *This, HDC a)
|
||||
HRESULT __stdcall ddraw_surface_Restore(IDirectDrawSurfaceImpl *This)
|
||||
{
|
||||
#if _DEBUG_X
|
||||
printf("DirectDrawSurface::Restore(This=%p) ???\n", This);
|
||||
printf("??? DirectDrawSurface::Restore(This=%p)\n", This);
|
||||
#endif
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_surface_SetClipper(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWCLIPPER a)
|
||||
{
|
||||
printf("DirectDrawSurface::SetClipper(This=%p, ...) ???\n", This);
|
||||
printf("??? DirectDrawSurface::SetClipper(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_surface_SetColorKey(IDirectDrawSurfaceImpl *This, DWORD flags, LPDDCOLORKEY colorKey)
|
||||
{
|
||||
#if _DEBUG_X
|
||||
printf("DirectDrawSurface::SetColorKey(This=%p, flags=0x%08X, colorKey=%p) ???\n", This, flags, colorKey);
|
||||
printf("??? DirectDrawSurface::SetColorKey(This=%p, flags=0x%08X, colorKey=%p)\n", This, flags, colorKey);
|
||||
|
||||
if (colorKey)
|
||||
{
|
||||
@ -955,7 +965,7 @@ HRESULT __stdcall ddraw_surface_SetColorKey(IDirectDrawSurfaceImpl *This, DWORD
|
||||
|
||||
HRESULT __stdcall ddraw_surface_SetOverlayPosition(IDirectDrawSurfaceImpl *This, LONG a, LONG b)
|
||||
{
|
||||
printf("DirectDrawSurface::SetOverlayPosition(This=%p, ...) ???\n", This);
|
||||
printf("??? DirectDrawSurface::SetOverlayPosition(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
@ -1060,19 +1070,19 @@ HRESULT __stdcall ddraw_surface_Unlock(IDirectDrawSurfaceImpl *This, LPVOID lpRe
|
||||
|
||||
HRESULT __stdcall ddraw_surface_UpdateOverlay(IDirectDrawSurfaceImpl *This, LPRECT a, LPDIRECTDRAWSURFACE b, LPRECT c, DWORD d, LPDDOVERLAYFX e)
|
||||
{
|
||||
printf("DirectDrawSurface::UpdateOverlay(This=%p, ...) ???\n", This);
|
||||
printf("??? DirectDrawSurface::UpdateOverlay(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_surface_UpdateOverlayDisplay(IDirectDrawSurfaceImpl *This, DWORD a)
|
||||
{
|
||||
printf("DirectDrawSurface::UpdateOverlayDisplay(This=%p, ...) ???\n", This);
|
||||
printf("??? DirectDrawSurface::UpdateOverlayDisplay(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall ddraw_surface_UpdateOverlayZOrder(IDirectDrawSurfaceImpl *This, DWORD a, LPDIRECTDRAWSURFACE b)
|
||||
{
|
||||
printf("DirectDrawSurface::UpdateOverlayZOrder(This=%p, ...) ???\n", This);
|
||||
printf("??? DirectDrawSurface::UpdateOverlayZOrder(This=%p, ...)\n", This);
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user