├── trashim ├── trashim.def ├── stdafx.h ├── stdafx.cpp ├── targetver.h ├── trashim.cpp ├── resource.h ├── TRAWindowed.h ├── ShimDirect3DDevice9.cpp ├── dllmain.cpp ├── trashim.vcxproj.filters ├── trashim.rc ├── ShimDirect3D9.h ├── ShimDirect3D9.cpp ├── trashim.vcxproj ├── TRAWindowed.cpp └── ShimDirect3DDevice9.h ├── Detours ├── detours.lib └── include │ ├── detver.h │ └── detours.h ├── LICENSE ├── trashim.sln ├── README.md ├── .gitattributes └── .gitignore /trashim/trashim.def: -------------------------------------------------------------------------------- 1 | LIBRARY 2 | EXPORTS 3 | Direct3DCreate9 @36 -------------------------------------------------------------------------------- /trashim/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chreden/trawindowed/HEAD/trashim/stdafx.h -------------------------------------------------------------------------------- /Detours/detours.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chreden/trawindowed/HEAD/Detours/detours.lib -------------------------------------------------------------------------------- /trashim/stdafx.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chreden/trawindowed/HEAD/trashim/stdafx.cpp -------------------------------------------------------------------------------- /trashim/targetver.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chreden/trawindowed/HEAD/trashim/targetver.h -------------------------------------------------------------------------------- /trashim/trashim.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chreden/trawindowed/HEAD/trashim/trashim.cpp -------------------------------------------------------------------------------- /trashim/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by trashim.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /trashim/TRAWindowed.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace trashim 6 | { 7 | // Enables windowed mode for Tomb Raider Legend and Anniversary. 8 | void initialise_shim(HWND window, uint32_t back_buffer_width, uint32_t back_buffer_height, uint32_t display_width, uint32_t display_height, bool vsync, uint32_t framerate); 9 | 10 | // Sleeps for the appropriate amount of time to emulate a fullscreen fixed framerate. 11 | // If vsync is disabled, this will immediately return. 12 | void wait_for_frame(); 13 | 14 | void start_fps_emulation(); 15 | } -------------------------------------------------------------------------------- /Detours/include/detver.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Common version parameters. 4 | // 5 | // Microsoft Research Detours Package, Version 3.0 Build_343. 6 | // 7 | // Copyright (c) Microsoft Corporation. All rights reserved. 8 | // 9 | 10 | #define _USING_V110_SDK71_ 1 11 | #include "winver.h" 12 | #if 0 13 | #include 14 | #include 15 | #else 16 | #ifndef DETOURS_STRINGIFY 17 | #define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x) 18 | #define DETOURS_STRINGIFY_(x) #x 19 | #endif 20 | 21 | #define VER_FILEFLAGSMASK 0x3fL 22 | #define VER_FILEFLAGS 0x0L 23 | #define VER_FILEOS 0x00040004L 24 | #define VER_FILETYPE 0x00000002L 25 | #define VER_FILESUBTYPE 0x00000000L 26 | #endif 27 | #define VER_DETOURS_BITS DETOUR_STRINGIFY(DETOURS_BITS) 28 | -------------------------------------------------------------------------------- /trashim/ShimDirect3DDevice9.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "ShimDirect3DDevice9.h" 3 | #include "TRAWindowed.h" 4 | 5 | namespace 6 | { 7 | void* source = nullptr; 8 | } 9 | 10 | HRESULT ShimDirect3DDevice9::TestCooperativeLevel(THIS) 11 | { 12 | void* caller = nullptr; 13 | __asm 14 | { 15 | mov eax, dword ptr[ebp] 16 | mov caller, eax 17 | } 18 | 19 | if (!source) 20 | { 21 | source = caller; 22 | } 23 | 24 | if (caller == source) 25 | { 26 | trashim::wait_for_frame(); 27 | } 28 | return _device->TestCooperativeLevel(); 29 | } 30 | 31 | HRESULT ShimDirect3DDevice9::Clear(THIS_ DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) 32 | { 33 | if (Color) 34 | { 35 | trashim::start_fps_emulation(); 36 | } 37 | return _device->Clear(Count, pRects, Flags, Color, Z, Stencil); 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 chreden 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /trashim/dllmain.cpp: -------------------------------------------------------------------------------- 1 | // dllmain.cpp : Defines the entry point for the DLL application. 2 | #include "stdafx.h" 3 | #include "ShimDirect3D9.h" 4 | 5 | extern "C" 6 | { 7 | IDirect3D9 * WINAPI Direct3DCreate9(UINT SDKVersion) 8 | { 9 | // Get System32 directory 10 | TCHAR windir[MAX_PATH]; 11 | GetWindowsDirectory(windir, MAX_PATH); 12 | LPWSTR dllpath = lstrcat(windir, L"\\System32\\d3d9.dll"); 13 | 14 | // Load the real d3d9 dll. 15 | HMODULE mod = LoadLibraryEx(dllpath, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); 16 | FARPROC proc = GetProcAddress(mod, "Direct3DCreate9"); 17 | 18 | // Get the real d3d9 create. 19 | typedef IDirect3D9* (WINAPI *func)(UINT); 20 | return new ShimDirect3D9(((func)proc)(SDKVersion)); 21 | } 22 | } 23 | 24 | BOOL APIENTRY DllMain( HMODULE hModule, 25 | DWORD ul_reason_for_call, 26 | LPVOID lpReserved 27 | ) 28 | { 29 | switch (ul_reason_for_call) 30 | { 31 | case DLL_PROCESS_ATTACH: 32 | case DLL_THREAD_ATTACH: 33 | case DLL_THREAD_DETACH: 34 | case DLL_PROCESS_DETACH: 35 | break; 36 | } 37 | return TRUE; 38 | } 39 | -------------------------------------------------------------------------------- /trashim.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31624.102 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "trashim", "trashim\trashim.vcxproj", "{902D877C-E320-422C-8F01-87AE5D36713D}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E84511A9-7A9B-478A-83AF-AEC8E9149DDE}" 9 | ProjectSection(SolutionItems) = preProject 10 | README.md = README.md 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|x64 = Debug|x64 16 | Debug|x86 = Debug|x86 17 | Release|x64 = Release|x64 18 | Release|x86 = Release|x86 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {902D877C-E320-422C-8F01-87AE5D36713D}.Debug|x64.ActiveCfg = Debug|x64 22 | {902D877C-E320-422C-8F01-87AE5D36713D}.Debug|x64.Build.0 = Debug|x64 23 | {902D877C-E320-422C-8F01-87AE5D36713D}.Debug|x86.ActiveCfg = Debug|Win32 24 | {902D877C-E320-422C-8F01-87AE5D36713D}.Debug|x86.Build.0 = Debug|Win32 25 | {902D877C-E320-422C-8F01-87AE5D36713D}.Release|x64.ActiveCfg = Release|x64 26 | {902D877C-E320-422C-8F01-87AE5D36713D}.Release|x64.Build.0 = Release|x64 27 | {902D877C-E320-422C-8F01-87AE5D36713D}.Release|x86.ActiveCfg = Release|Win32 28 | {902D877C-E320-422C-8F01-87AE5D36713D}.Release|x86.Build.0 = Release|Win32 29 | EndGlobalSection 30 | GlobalSection(SolutionProperties) = preSolution 31 | HideSolutionNode = FALSE 32 | EndGlobalSection 33 | GlobalSection(ExtensibilityGlobals) = postSolution 34 | SolutionGuid = {4B8DC21D-54F9-4A53-BEF6-E2F5154247A8} 35 | EndGlobalSection 36 | EndGlobal 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TRAWindowed - Tomb Raider Windowed 2 | This is a custom d3d9.dll that enables more display modes for the three second era Tomb Raider games. This allows you to play the game in "windowed mode", as well as "borderless-window mode" 3 | 4 | ## Supported Games 5 | * Tomb Raider: Legend 6 | * Tomb Raider: Anniversary 7 | * Tomb Raider: Underworld 8 | 9 | ## How to use 10 | ### Installation 11 | 1. Download the latest dll from the [release page](https://github.com/chreden/trawindowed/releases/) 12 | 2. Navigate to your Tomb Raider game directory 13 | 3. Place the d3d9.dll in the same folder as the Tomb Raider game binary (exe file) 14 | 15 | ### Switch display modes 16 | 1. Start the game 17 | 2. Press F6 to switch between bordered and borderless windowed mode. 18 | 19 | ### Center the window 20 | 1. Start the game 21 | 2. Press Shift + F6 to center the window on the monitor the window is currently on. 22 | 23 | ### Toggle Always on Top 24 | 1. Start the game 25 | 2. Press F7 to toggle always on top 26 | 27 | ### Toggle mouse capture 28 | 1. Start the game 29 | 2. Press F8 to toggle mouse capture. 30 | 31 | This can be useful if you want to interact with the TRAE Menu Hook. 32 | 33 | ### Command Line Arguments 34 | These can all be added via the "Launch Options" in Steam. 35 | 36 | - Passing `-borderless` to the game exe will launch the game in borderless window mode (as if you had started the game and pressed the toggle button). 37 | - Passing `-camerafix` to the game exe will fix an issue with the camera (if it gets stuck looking down). 38 | - Passing `-autocenter` to the game exe will start the window in the center of the primary display. Underworld may need to be manually centered. 39 | - Passing `-disableaspectfix` to the game exe will stop the TRU aspect ratio being calculated based on the window size and will use the game setting instead. 40 | - Passing `-ontop` to the game exe will start the window on top. 41 | - Passing `-nomousecapture` will start the game without forcing mouse capture. 42 | 43 | ## Information for developers 44 | ### Build 45 | You need Visual Studio to compile the dll. Just import the ```trashim.sln``` project file. Before you start the build you have to change the active configuration to "Release" and "Win32" as target platform. 46 | 47 | After the build is completed the final ```d3d9.dll``` will be located in the ```Release``` folder. -------------------------------------------------------------------------------- /trashim/trashim.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | 58 | 59 | Source Files 60 | 61 | 62 | 63 | 64 | Resource Files 65 | 66 | 67 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /trashim/trashim.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include "resource.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | #include "winres.h" 11 | 12 | ///////////////////////////////////////////////////////////////////////////// 13 | #undef APSTUDIO_READONLY_SYMBOLS 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | // English (United Kingdom) resources 17 | 18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) 19 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK 20 | #pragma code_page(1252) 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // Version 51 | // 52 | 53 | VS_VERSION_INFO VERSIONINFO 54 | FILEVERSION 1,9,0,0 55 | PRODUCTVERSION 1,9,0,0 56 | FILEFLAGSMASK 0x3fL 57 | #ifdef _DEBUG 58 | FILEFLAGS 0x1L 59 | #else 60 | FILEFLAGS 0x0L 61 | #endif 62 | FILEOS 0x40004L 63 | FILETYPE 0x2L 64 | FILESUBTYPE 0x0L 65 | BEGIN 66 | BLOCK "StringFileInfo" 67 | BEGIN 68 | BLOCK "080904b0" 69 | BEGIN 70 | VALUE "CompanyName", "https://github.com/chreden/trawindowed" 71 | VALUE "FileDescription", "Windowed DLL for TR LAU" 72 | VALUE "FileVersion", "1.9.0.0" 73 | VALUE "InternalName", "d3d9.dll" 74 | VALUE "LegalCopyright", "Copyright (C) chreden 2025" 75 | VALUE "OriginalFilename", "d3d9.dll" 76 | VALUE "ProductName", "chreden/trawindowed" 77 | VALUE "ProductVersion", "1.9.0.0" 78 | END 79 | END 80 | BLOCK "VarFileInfo" 81 | BEGIN 82 | VALUE "Translation", 0x809, 1200 83 | END 84 | END 85 | 86 | #endif // English (United Kingdom) resources 87 | ///////////////////////////////////////////////////////////////////////////// 88 | 89 | 90 | 91 | #ifndef APSTUDIO_INVOKED 92 | ///////////////////////////////////////////////////////////////////////////// 93 | // 94 | // Generated from the TEXTINCLUDE 3 resource. 95 | // 96 | 97 | 98 | ///////////////////////////////////////////////////////////////////////////// 99 | #endif // not APSTUDIO_INVOKED 100 | 101 | -------------------------------------------------------------------------------- /trashim/ShimDirect3D9.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | struct ShimDirect3D9 : IDirect3D9 8 | { 9 | CComPtr _d3d9; 10 | uint32_t _ref{ 1 }; 11 | 12 | ShimDirect3D9(IDirect3D9* d3d9) 13 | : _d3d9(d3d9) 14 | { 15 | } 16 | 17 | /*** IUnknown methods ***/ 18 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) 19 | { 20 | return _d3d9->QueryInterface(riid, ppvObj); 21 | } 22 | 23 | STDMETHOD_(ULONG, AddRef)(THIS) 24 | { 25 | InterlockedIncrement(&_ref); 26 | return _ref; 27 | } 28 | 29 | STDMETHOD_(ULONG, Release)(THIS) 30 | { 31 | ULONG ulRefCount = InterlockedDecrement(&_ref); 32 | if (0 == _ref) 33 | { 34 | delete this; 35 | } 36 | return ulRefCount; 37 | } 38 | 39 | /*** IDirect3D9 methods ***/ 40 | STDMETHOD(RegisterSoftwareDevice)(THIS_ void* pInitializeFunction) 41 | { 42 | return _d3d9->RegisterSoftwareDevice(pInitializeFunction); 43 | } 44 | 45 | STDMETHOD_(UINT, GetAdapterCount)(THIS) 46 | { 47 | return _d3d9->GetAdapterCount(); 48 | } 49 | 50 | STDMETHOD(GetAdapterIdentifier)(THIS_ UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier) 51 | { 52 | return _d3d9->GetAdapterIdentifier(Adapter, Flags, pIdentifier); 53 | } 54 | 55 | STDMETHOD_(UINT, GetAdapterModeCount)(THIS_ UINT Adapter, D3DFORMAT Format); 56 | STDMETHOD(EnumAdapterModes)(THIS_ UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode); 57 | 58 | STDMETHOD(GetAdapterDisplayMode)(THIS_ UINT Adapter, D3DDISPLAYMODE* pMode) 59 | { 60 | return _d3d9->GetAdapterDisplayMode(Adapter, pMode); 61 | } 62 | 63 | STDMETHOD(CheckDeviceType)(THIS_ UINT Adapter, D3DDEVTYPE DevType, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, BOOL bWindowed) 64 | { 65 | return _d3d9->CheckDeviceType(Adapter, DevType, AdapterFormat, BackBufferFormat, bWindowed); 66 | } 67 | 68 | STDMETHOD(CheckDeviceFormat)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) 69 | { 70 | return _d3d9->CheckDeviceFormat(Adapter, DeviceType, AdapterFormat, Usage, RType, CheckFormat); 71 | } 72 | 73 | STDMETHOD(CheckDeviceMultiSampleType)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) 74 | { 75 | return _d3d9->CheckDeviceMultiSampleType(Adapter, DeviceType, SurfaceFormat, Windowed, MultiSampleType, pQualityLevels); 76 | } 77 | 78 | STDMETHOD(CheckDepthStencilMatch)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) 79 | { 80 | return _d3d9->CheckDepthStencilMatch(Adapter, DeviceType, AdapterFormat, RenderTargetFormat, DepthStencilFormat); 81 | } 82 | 83 | STDMETHOD(CheckDeviceFormatConversion)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat) 84 | { 85 | return _d3d9->CheckDeviceFormatConversion(Adapter, DeviceType, SourceFormat, TargetFormat); 86 | } 87 | 88 | STDMETHOD(GetDeviceCaps)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) 89 | { 90 | return _d3d9->GetDeviceCaps(Adapter, DeviceType, pCaps); 91 | } 92 | 93 | STDMETHOD_(HMONITOR, GetAdapterMonitor)(THIS_ UINT Adapter) 94 | { 95 | return _d3d9->GetAdapterMonitor(Adapter); 96 | } 97 | 98 | STDMETHOD(CreateDevice)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface); 99 | }; 100 | -------------------------------------------------------------------------------- /trashim/ShimDirect3D9.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "ShimDirect3D9.h" 3 | #include "ShimDirect3DDevice9.h" 4 | #include "TRAWindowed.h" 5 | #include 6 | #include 7 | #include 8 | 9 | namespace 10 | { 11 | struct Resolution 12 | { 13 | UINT width; 14 | UINT height; 15 | auto operator<=>(const Resolution&) const = default; 16 | }; 17 | } 18 | 19 | template <> 20 | struct std::hash 21 | { 22 | std::size_t operator()(const Resolution& res) const noexcept 23 | { 24 | std::size_t h1 = std::hash{}(res.width); 25 | std::size_t h2 = std::hash{}(res.height); 26 | return h1 ^ (h2 << 1); 27 | } 28 | }; 29 | 30 | namespace 31 | { 32 | std::unordered_map> adapter_display_modes; 33 | 34 | const std::vector wanted_refresh_rates{ 20, 40, 60, 100, 144 }; 35 | 36 | std::vector store_display_modes(IDirect3D9& d3d9, UINT adapter, D3DFORMAT format) 37 | { 38 | auto found = adapter_display_modes.find(adapter); 39 | if (adapter_display_modes.find(adapter) != adapter_display_modes.end()) 40 | { 41 | return found->second; 42 | } 43 | 44 | std::unordered_map> framerates; 45 | for (uint32_t i = 0; i < d3d9.GetAdapterModeCount(adapter, format); ++i) 46 | { 47 | D3DDISPLAYMODE mode{}; 48 | d3d9.EnumAdapterModes(adapter, format, i, &mode); 49 | framerates[{mode.Width, mode.Height}].insert(mode.RefreshRate); 50 | } 51 | 52 | for (auto& resolution : framerates) 53 | { 54 | for (const auto& rate : wanted_refresh_rates) 55 | { 56 | resolution.second.insert(rate); 57 | } 58 | } 59 | 60 | std::vector modes; 61 | for (const auto& resolution : framerates) 62 | { 63 | for (const auto& rate : resolution.second) 64 | { 65 | modes.push_back( 66 | { 67 | resolution.first.width, 68 | resolution.first.height, 69 | rate, 70 | format 71 | }); 72 | } 73 | } 74 | 75 | adapter_display_modes[adapter] = modes; 76 | return modes; 77 | } 78 | } 79 | 80 | HRESULT ShimDirect3D9::CreateDevice(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface) 81 | { 82 | D3DDISPLAYMODE mode; 83 | _d3d9->GetAdapterDisplayMode(Adapter, &mode); 84 | 85 | if (hFocusWindow) 86 | { 87 | trashim::initialise_shim(hFocusWindow, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight, mode.Width, mode.Height, pPresentationParameters->PresentationInterval != D3DPRESENT_INTERVAL_IMMEDIATE, pPresentationParameters->FullScreen_RefreshRateInHz); 88 | } 89 | 90 | pPresentationParameters->Windowed = TRUE; 91 | pPresentationParameters->FullScreen_RefreshRateInHz = 0; 92 | pPresentationParameters->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; 93 | 94 | IDirect3DDevice9* device = nullptr; 95 | HRESULT hr = _d3d9->CreateDevice(Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, &device); 96 | *ppReturnedDeviceInterface = new ShimDirect3DDevice9(device); 97 | return hr; 98 | } 99 | 100 | UINT ShimDirect3D9::GetAdapterModeCount(UINT Adapter, D3DFORMAT Format) 101 | { 102 | auto modes = store_display_modes(*_d3d9, Adapter, Format); 103 | return modes.size(); 104 | } 105 | 106 | HRESULT ShimDirect3D9::EnumAdapterModes(UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) 107 | { 108 | auto modes = store_display_modes(*_d3d9, Adapter, Format); 109 | *pMode = modes[Mode]; 110 | return D3D_OK; 111 | } 112 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /trashim/trashim.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {902D877C-E320-422C-8F01-87AE5D36713D} 24 | Win32Proj 25 | trashim 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | d3d9 76 | 77 | 78 | true 79 | d3d9 80 | 81 | 82 | false 83 | d3d9 84 | 85 | 86 | false 87 | d3d9 88 | 89 | 90 | 91 | Use 92 | Level3 93 | Disabled 94 | false 95 | WIN32;_DEBUG;TRASHIM_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 96 | true 97 | $(SolutionDir)/detours/include 98 | stdcpplatest 99 | 100 | 101 | Windows 102 | true 103 | detours.lib;%(AdditionalDependencies) 104 | trashim.def 105 | $(SolutionDir)/detours 106 | 107 | 108 | 109 | 110 | Use 111 | Level3 112 | Disabled 113 | false 114 | _DEBUG;TRASHIM_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 115 | true 116 | $(SolutionDir)/detours/include 117 | 118 | 119 | Windows 120 | true 121 | detours.lib;%(AdditionalDependencies) 122 | trashim.def 123 | $(SolutionDir)/detours 124 | 125 | 126 | 127 | 128 | Use 129 | Level3 130 | MaxSpeed 131 | true 132 | true 133 | false 134 | WIN32;NDEBUG;TRASHIM_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 135 | true 136 | MultiThreadedDLL 137 | $(SolutionDir)/detours/include 138 | stdcpplatest 139 | 140 | 141 | Windows 142 | true 143 | true 144 | true 145 | detours.lib;%(AdditionalDependencies) 146 | trashim.def 147 | $(SolutionDir)/detours 148 | 149 | 150 | 151 | 152 | Use 153 | Level3 154 | MaxSpeed 155 | true 156 | true 157 | false 158 | NDEBUG;TRASHIM_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 159 | true 160 | MultiThreadedDLL 161 | $(SolutionDir)/detours/include 162 | 163 | 164 | Windows 165 | true 166 | true 167 | true 168 | detours.lib;%(AdditionalDependencies) 169 | trashim.def 170 | $(SolutionDir)/detours 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | Create 188 | Create 189 | Create 190 | Create 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /trashim/TRAWindowed.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "TRAWindowed.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace trashim 11 | { 12 | namespace 13 | { 14 | // Whether or not to capture the mouse when the cursor is moved (apply a clip rectangle). 15 | // This is disabled when the window has lost focus. 16 | bool mouse_captured{ false }; 17 | bool capture_allowed{ true }; 18 | bool camera_fix{ false }; 19 | 20 | // Style used to toggle on and off the bordered windowed mode. 21 | const LONG_PTR windowed_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; 22 | 23 | HWND game_window{ nullptr }; 24 | WNDPROC original_wndproc{ nullptr }; 25 | 26 | uint32_t window_width{ 0u }; 27 | uint32_t window_height{ 0u }; 28 | 29 | // The width and height of the display adapter - the game is expecting the mouse to be moving around an 30 | // area of these dimensions, so if we are playing in a window smaller than this size the distance the 31 | // cursor has moved has to be scaled appropriately. e.g - 1920x1080 window on a 2560x1440 display requires 32 | // a scaling factor of 1.3333x1.3333, otherwise the mouse will move too slowly. 33 | // The game also regularly sets the cursor to the centre of the display adapter - and believes that the 34 | // cursor is at that position. We therefore have to lie to the game and report all movement as relative to 35 | // the centre of the display adapter, regardless of the position and size of the window. 36 | uint32_t device_width{ 0u }; 37 | uint32_t device_height{ 0u }; 38 | 39 | uint32_t last_cursor_x{ 0u }; 40 | uint32_t last_cursor_y{ 0u }; 41 | 42 | // Framerate management 43 | 44 | // The number of nanoseconds between each frame. 45 | uint32_t desired_frame_interval{ 0u }; 46 | int64_t timer_frequency{ 0ll }; 47 | int64_t timer_previous{ 0ll }; 48 | bool vsync_enabled{ false }; 49 | bool frame_timer_enabled{ false }; 50 | 51 | // Real versions of the functions that are detoured. They are called directly by the shim dll when appropriate 52 | BOOL(WINAPI * RealGetCursorPos)(LPPOINT) = GetCursorPos; 53 | BOOL(WINAPI * RealSetCursorPos)(int, int) = SetCursorPos; 54 | BOOL(WINAPI * RealClipCursor)(const RECT*) = ClipCursor; 55 | 56 | // Stops the game from doing any cursor clipping - we do this ourselves based on whether 57 | // we are currently capturing the mouse. 58 | BOOL WINAPI FixedClipCursor(const RECT* rect) 59 | { 60 | return TRUE; 61 | } 62 | 63 | // Just adds a conversion from screen space into client space - the game does not do this 64 | // as it is not expecting there to be a difference. 65 | BOOL WINAPI FixedGetCursorPos(LPPOINT output) 66 | { 67 | auto result = RealGetCursorPos(output); 68 | if (!camera_fix) 69 | { 70 | ScreenToClient(game_window, output); 71 | } 72 | return result; 73 | } 74 | 75 | // Version of SetCursorPos that also does cursor clipping - but based on the position of the window 76 | // as well as the size. Only clips when the game has focus. 77 | BOOL WINAPI FixedSetCursorPos(int x, int y) 78 | { 79 | if (mouse_captured) 80 | { 81 | RECT cr; 82 | GetClientRect(game_window, &cr); 83 | 84 | POINT pt{ 0,0 }; 85 | ClientToScreen(game_window, &pt); 86 | 87 | cr.left += pt.x; 88 | cr.right += pt.x; 89 | cr.top += pt.y; 90 | cr.bottom += pt.y; 91 | 92 | RealClipCursor(&cr); 93 | } 94 | 95 | return TRUE; 96 | } 97 | 98 | // Resize the window to have the desired client area, taking in to account whether the border 99 | // is currently active or not. 100 | void resize_window(uint32_t desired_width, uint32_t desired_height) 101 | { 102 | RECT rect{ 0, 0, static_cast(desired_width), static_cast(desired_height) }; 103 | LONG_PTR style = GetWindowLongPtr(game_window, GWL_STYLE); 104 | AdjustWindowRect(&rect, style, false); 105 | SetWindowPos(game_window, nullptr, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_SHOWWINDOW | SWP_NOMOVE); 106 | } 107 | 108 | // Creates an adjusted LPARAM for WM_MOUSEMOVE based on where the game thinks the cursor should be, 109 | // where we know it was and where it has moved to. 110 | // x, y: The client space coordinates of the mouse cursor. 111 | LPARAM move_mouse(int32_t x, int32_t y) 112 | { 113 | // Find how far the mouse has moved since the last time we saw it, based on our last 114 | // recorded client space position. 115 | int32_t diff_x = x - last_cursor_x; 116 | int32_t diff_y = y - last_cursor_y; 117 | 118 | // Apply the scaling required to translate window cursor movement into device cursor movement. 119 | float scale_x = static_cast(device_width) / window_width; 120 | float scale_y = static_cast(device_height) / window_height; 121 | 122 | diff_x = static_cast(diff_x * scale_x); 123 | diff_y = static_cast(diff_y * scale_y); 124 | 125 | // The game expects the cursor to be in the centre of the device, so report all cursor positions 126 | // as relative to that coordinate. 127 | auto new_x = device_width / 2 + diff_x; 128 | auto new_y = device_height / 2 + diff_y; 129 | 130 | // Set the cursor position to the centre of the actual client (so user can click and 131 | // still be in the window). 132 | POINT pt = { static_cast(window_width / 2), static_cast(window_height / 2) }; 133 | 134 | // Store client space coordinates for comparison next time (before we make them screen space). 135 | last_cursor_x = pt.x; 136 | last_cursor_y = pt.y; 137 | 138 | // Pin the mouse in the centre of the client space. 139 | ClientToScreen(game_window, &pt); 140 | RealSetCursorPos(pt.x, pt.y); 141 | 142 | return MAKELPARAM(new_x, new_y); 143 | } 144 | 145 | void hide_cursor() 146 | { 147 | while (ShowCursor(false) >= 0) {} 148 | } 149 | 150 | void show_cursor() 151 | { 152 | while (ShowCursor(true) < 0) {} 153 | } 154 | 155 | void capture_mouse() 156 | { 157 | // Allow the user to give control 158 | if (!mouse_captured && capture_allowed) 159 | { 160 | mouse_captured = true; 161 | hide_cursor(); 162 | } 163 | } 164 | 165 | void centre_window() 166 | { 167 | RECT rect{ 0, 0, static_cast(window_width), static_cast(window_height) }; 168 | LONG_PTR style = GetWindowLongPtr(game_window, GWL_STYLE); 169 | AdjustWindowRect(&rect, style, false); 170 | 171 | const HMONITOR monitor = MonitorFromWindow(game_window, MONITOR_DEFAULTTOPRIMARY); 172 | MONITORINFO info{ .cbSize = sizeof(MONITORINFO) }; 173 | GetMonitorInfo(monitor, &info); 174 | 175 | const LONG screen_width = info.rcMonitor.right - info.rcMonitor.left; 176 | const LONG screen_height = info.rcMonitor.bottom - info.rcMonitor.top; 177 | const LONG width = rect.right - rect.left; 178 | const LONG height = rect.bottom - rect.top; 179 | 180 | const LONG x = info.rcMonitor.left + (screen_width / 2) - (width / 2); 181 | const LONG y = info.rcMonitor.top + (screen_height / 2) - (height / 2); 182 | SetWindowPos(game_window, nullptr, x, y, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE); 183 | } 184 | 185 | void release_mouse() 186 | { 187 | mouse_captured = false; 188 | RealClipCursor(nullptr); 189 | show_cursor(); 190 | } 191 | 192 | void toggle_border() 193 | { 194 | auto style = GetWindowLongPtr(game_window, GWL_STYLE); 195 | SetWindowLongPtr(game_window, GWL_STYLE, style & windowed_style ? (style & ~windowed_style) : (style | windowed_style)); 196 | resize_window(window_width, window_height); 197 | } 198 | 199 | void toggle_on_top() 200 | { 201 | const auto style = GetWindowLongPtr(game_window, GWL_EXSTYLE); 202 | if (style & WS_EX_TOPMOST) 203 | { 204 | SetWindowPos(game_window, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); 205 | BringWindowToTop(game_window); 206 | } 207 | else 208 | { 209 | SetWindowPos(game_window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); 210 | } 211 | } 212 | 213 | void toggle_capture() 214 | { 215 | capture_allowed = !capture_allowed; 216 | if (capture_allowed) 217 | { 218 | capture_mouse(); 219 | } 220 | else 221 | { 222 | release_mouse(); 223 | } 224 | } 225 | 226 | void initialise_timer() 227 | { 228 | LARGE_INTEGER frequency; 229 | QueryPerformanceFrequency(&frequency); 230 | timer_frequency = frequency.QuadPart; 231 | 232 | LARGE_INTEGER counter; 233 | QueryPerformanceCounter(&counter); 234 | timer_previous = counter.QuadPart; 235 | } 236 | 237 | void update_timer() 238 | { 239 | LARGE_INTEGER current_time; 240 | QueryPerformanceCounter(¤t_time); 241 | timer_previous = current_time.QuadPart; 242 | } 243 | 244 | LRESULT CALLBACK subclass_wndproc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) 245 | { 246 | switch (msg) 247 | { 248 | case WM_KEYDOWN: 249 | { 250 | if (wParam == VK_F6) 251 | { 252 | if (GetKeyState(VK_SHIFT) & 0x8000) 253 | { 254 | centre_window(); 255 | } 256 | else 257 | { 258 | toggle_border(); 259 | } 260 | } 261 | else if (wParam == VK_F7) 262 | { 263 | toggle_on_top(); 264 | } 265 | else if (wParam == VK_F8) 266 | { 267 | toggle_capture(); 268 | } 269 | break; 270 | } 271 | case WM_SETFOCUS: 272 | { 273 | capture_mouse(); 274 | break; 275 | } 276 | case WM_KILLFOCUS: 277 | { 278 | release_mouse(); 279 | break; 280 | } 281 | case WM_LBUTTONDOWN: 282 | { 283 | capture_mouse(); 284 | break; 285 | } 286 | case WM_MOUSEMOVE: 287 | { 288 | if (mouse_captured) 289 | { 290 | int32_t x = GET_X_LPARAM(lParam); 291 | int32_t y = GET_Y_LPARAM(lParam); 292 | lParam = move_mouse(x, y); 293 | break; 294 | } 295 | else 296 | { 297 | // Don't let the game handle this message - everything would go very badly wrong. 298 | return DefWindowProc(window, msg, wParam, lParam); 299 | } 300 | } 301 | } 302 | return CallWindowProc(original_wndproc, window, msg, wParam, lParam); 303 | } 304 | 305 | bool is_arg_present(const wchar_t* arg) 306 | { 307 | int number_of_arguments = 0; 308 | const auto args = CommandLineToArgvW(GetCommandLine(), &number_of_arguments); 309 | return args != nullptr && std::any_of(args, args + number_of_arguments, [arg](auto str) { return wcsstr(str, arg) != nullptr; }); 310 | } 311 | 312 | bool should_start_borderless() 313 | { 314 | return is_arg_present(L"-borderless"); 315 | } 316 | 317 | bool is_camera_fix_enabled() 318 | { 319 | return is_arg_present(L"-camerafix"); 320 | } 321 | 322 | bool is_centering_enabled() 323 | { 324 | return is_arg_present(L"-autocenter"); 325 | } 326 | 327 | bool is_aspect_fix_disabled() 328 | { 329 | return is_arg_present(L"-disableaspectfix"); 330 | } 331 | 332 | void apply_aspect_ratio() 333 | { 334 | wchar_t path[MAX_PATH]; 335 | if (!is_aspect_fix_disabled() && 336 | 0 != GetModuleFileName(NULL, path, MAX_PATH) && 337 | std::wstring(path).contains(L"tru.exe")) 338 | { 339 | // Some sort of graphics related struct pointer - at 0x170 offset is the aspect ratio x 10000. 340 | char* ptr = *reinterpret_cast(0x00ad75e4); 341 | int* aspect_ratio = reinterpret_cast(ptr + 0x170); 342 | *aspect_ratio = (static_cast(window_width) / static_cast(window_height)) * 10000; 343 | } 344 | } 345 | 346 | bool should_start_ontop() 347 | { 348 | return is_arg_present(L"-ontop"); 349 | } 350 | 351 | bool should_start_without_mouse_capture() 352 | { 353 | return is_arg_present(L"-nomousecapture"); 354 | } 355 | } 356 | 357 | void initialise_shim(HWND window, uint32_t back_buffer_width, uint32_t back_buffer_height, uint32_t display_width, uint32_t display_height, bool vsync, uint32_t framerate) 358 | { 359 | // Only set the windowed style the first time the window is seen. 360 | bool need_auto_centering = false; 361 | if (!game_window) 362 | { 363 | camera_fix = is_camera_fix_enabled(); 364 | 365 | game_window = window; 366 | SetWindowLongPtr(game_window, GWL_STYLE, windowed_style); 367 | if (should_start_borderless()) 368 | { 369 | toggle_border(); 370 | } 371 | 372 | if (!should_start_ontop()) 373 | { 374 | toggle_on_top(); 375 | } 376 | 377 | if (!should_start_without_mouse_capture()) 378 | { 379 | capture_mouse(); 380 | } 381 | 382 | need_auto_centering = is_centering_enabled(); 383 | 384 | original_wndproc = (WNDPROC)SetWindowLongPtr(window, GWLP_WNDPROC, (LONG_PTR)subclass_wndproc); 385 | 386 | // If our window is already the foreground window, hide the cursor now. 387 | if (GetForegroundWindow() == game_window) 388 | { 389 | hide_cursor(); 390 | } 391 | 392 | // Only detour the first time. 393 | DetourTransactionBegin(); 394 | DetourUpdateThread(GetCurrentThread()); 395 | DetourAttach(&(PVOID&)RealGetCursorPos, FixedGetCursorPos); 396 | DetourAttach(&(PVOID&)RealSetCursorPos, FixedSetCursorPos); 397 | DetourAttach(&(PVOID&)RealClipCursor, FixedClipCursor); 398 | DetourTransactionCommit(); 399 | 400 | // Create the framerate timer. 401 | initialise_timer(); 402 | } 403 | 404 | device_width = display_width; 405 | device_height = display_height; 406 | window_width = back_buffer_width; 407 | window_height = back_buffer_height; 408 | desired_frame_interval = 1.0f / framerate * 1e7; 409 | vsync_enabled = vsync; 410 | resize_window(window_width, window_height); 411 | initialise_timer(); 412 | apply_aspect_ratio(); 413 | 414 | if (need_auto_centering) 415 | { 416 | centre_window(); 417 | } 418 | } 419 | 420 | uint64_t get_frame_difference() 421 | { 422 | LARGE_INTEGER current_time; 423 | QueryPerformanceCounter(¤t_time); 424 | int64_t difference = current_time.QuadPart - timer_previous; 425 | return (static_cast(difference) / timer_frequency) * 1e7; 426 | } 427 | 428 | void wait_for_frame() 429 | { 430 | // Only perform fixed framerate emulation when vsync is enabled. 431 | if (!vsync_enabled || !frame_timer_enabled) 432 | { 433 | return; 434 | } 435 | 436 | while (get_frame_difference() < desired_frame_interval) 437 | { 438 | // Busy wait. 439 | } 440 | 441 | update_timer(); 442 | } 443 | 444 | void start_fps_emulation() 445 | { 446 | frame_timer_enabled = true; 447 | } 448 | } -------------------------------------------------------------------------------- /trashim/ShimDirect3DDevice9.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | struct ShimDirect3DDevice9 : IDirect3DDevice9 8 | { 9 | CComPtr _device; 10 | uint32_t _ref{ 1 }; 11 | 12 | ShimDirect3DDevice9(IDirect3DDevice9* device) 13 | : _device(device) 14 | { 15 | } 16 | 17 | /*** IUnknown methods ***/ 18 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) 19 | { 20 | return _device->QueryInterface(riid, ppvObj); 21 | } 22 | 23 | STDMETHOD_(ULONG, AddRef)(THIS) 24 | { 25 | InterlockedIncrement(&_ref); 26 | return _ref; 27 | } 28 | 29 | STDMETHOD_(ULONG, Release)(THIS) 30 | { 31 | ULONG ulRefCount = InterlockedDecrement(&_ref); 32 | if (0 == _ref) 33 | { 34 | delete this; 35 | } 36 | return ulRefCount; 37 | } 38 | 39 | STDMETHOD(TestCooperativeLevel)(THIS); 40 | 41 | STDMETHOD_(UINT, GetAvailableTextureMem)(THIS) 42 | { 43 | return _device->GetAvailableTextureMem(); 44 | } 45 | 46 | STDMETHOD(EvictManagedResources)(THIS) 47 | { 48 | return _device->EvictManagedResources(); 49 | } 50 | 51 | STDMETHOD(GetDirect3D)(THIS_ IDirect3D9** ppD3D9) 52 | { 53 | return _device->GetDirect3D(ppD3D9); 54 | } 55 | 56 | STDMETHOD(GetDeviceCaps)(THIS_ D3DCAPS9* pCaps) 57 | { 58 | return _device->GetDeviceCaps(pCaps); 59 | } 60 | 61 | STDMETHOD(GetDisplayMode)(THIS_ UINT iSwapChain, D3DDISPLAYMODE* pMode) 62 | { 63 | return _device->GetDisplayMode(iSwapChain, pMode); 64 | } 65 | 66 | STDMETHOD(GetCreationParameters)(THIS_ D3DDEVICE_CREATION_PARAMETERS *pParameters) 67 | { 68 | return _device->GetCreationParameters(pParameters); 69 | } 70 | 71 | STDMETHOD(SetCursorProperties)(THIS_ UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9* pCursorBitmap) 72 | { 73 | return _device->SetCursorProperties(XHotSpot, YHotSpot, pCursorBitmap); 74 | } 75 | 76 | STDMETHOD_(void, SetCursorPosition)(THIS_ int X, int Y, DWORD Flags) 77 | { 78 | return _device->SetCursorPosition(X, Y, Flags); 79 | } 80 | 81 | STDMETHOD_(BOOL, ShowCursor)(THIS_ BOOL bShow) 82 | { 83 | return _device->ShowCursor(bShow); 84 | } 85 | 86 | STDMETHOD(CreateAdditionalSwapChain)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain9** pSwapChain) 87 | { 88 | return _device->CreateAdditionalSwapChain(pPresentationParameters, pSwapChain); 89 | } 90 | 91 | STDMETHOD(GetSwapChain)(THIS_ UINT iSwapChain, IDirect3DSwapChain9** pSwapChain) 92 | { 93 | return _device->GetSwapChain(iSwapChain, pSwapChain); 94 | } 95 | 96 | STDMETHOD_(UINT, GetNumberOfSwapChains)(THIS) 97 | { 98 | return _device->GetNumberOfSwapChains(); 99 | } 100 | 101 | STDMETHOD(Reset)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters) 102 | { 103 | return _device->Reset(pPresentationParameters); 104 | } 105 | 106 | STDMETHOD(Present)(THIS_ CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) 107 | { 108 | return _device->Present(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); 109 | } 110 | 111 | STDMETHOD(GetBackBuffer)(THIS_ UINT iSwapChain, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer) 112 | { 113 | return _device->GetBackBuffer(iSwapChain, iBackBuffer, Type, ppBackBuffer); 114 | } 115 | 116 | STDMETHOD(GetRasterStatus)(THIS_ UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) 117 | { 118 | return _device->GetRasterStatus(iSwapChain, pRasterStatus); 119 | } 120 | 121 | STDMETHOD(SetDialogBoxMode)(THIS_ BOOL bEnableDialogs) 122 | { 123 | return _device->SetDialogBoxMode(bEnableDialogs); 124 | } 125 | 126 | STDMETHOD_(void, SetGammaRamp)(THIS_ UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) 127 | { 128 | return _device->SetGammaRamp(iSwapChain, Flags, pRamp); 129 | } 130 | 131 | STDMETHOD_(void, GetGammaRamp)(THIS_ UINT iSwapChain, D3DGAMMARAMP* pRamp) 132 | { 133 | return _device->GetGammaRamp(iSwapChain, pRamp); 134 | } 135 | 136 | STDMETHOD(CreateTexture)(THIS_ UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9** ppTexture, HANDLE* pSharedHandle) 137 | { 138 | return _device->CreateTexture(Width, Height, Levels, Usage, Format, Pool, ppTexture, pSharedHandle); 139 | } 140 | 141 | STDMETHOD(CreateVolumeTexture)(THIS_ UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle) 142 | { 143 | return _device->CreateVolumeTexture(Width, Height, Depth, Levels, Usage, Format, Pool, ppVolumeTexture, pSharedHandle); 144 | } 145 | 146 | STDMETHOD(CreateCubeTexture)(THIS_ UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture9** ppCubeTexture, HANDLE* pSharedHandle) 147 | { 148 | return _device->CreateCubeTexture(EdgeLength, Levels, Usage, Format, Pool, ppCubeTexture, pSharedHandle); 149 | } 150 | 151 | STDMETHOD(CreateVertexBuffer)(THIS_ UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle) 152 | { 153 | return _device->CreateVertexBuffer(Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle); 154 | } 155 | 156 | STDMETHOD(CreateIndexBuffer)(THIS_ UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle) 157 | { 158 | return _device->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, pSharedHandle); 159 | } 160 | 161 | STDMETHOD(CreateRenderTarget)(THIS_ UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) 162 | { 163 | return _device->CreateRenderTarget(Width, Height, Format, MultiSample, MultisampleQuality, Lockable, ppSurface, pSharedHandle); 164 | } 165 | 166 | STDMETHOD(CreateDepthStencilSurface)(THIS_ UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) 167 | { 168 | return _device->CreateDepthStencilSurface(Width, Height, Format, MultiSample, MultisampleQuality, Discard, ppSurface, pSharedHandle); 169 | } 170 | 171 | STDMETHOD(UpdateSurface)(THIS_ IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestinationSurface, CONST POINT* pDestPoint) 172 | { 173 | return _device->UpdateSurface(pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint); 174 | } 175 | 176 | STDMETHOD(UpdateTexture)(THIS_ IDirect3DBaseTexture9* pSourceTexture, IDirect3DBaseTexture9* pDestinationTexture) 177 | { 178 | return _device->UpdateTexture(pSourceTexture, pDestinationTexture); 179 | } 180 | 181 | STDMETHOD(GetRenderTargetData)(THIS_ IDirect3DSurface9* pRenderTarget, IDirect3DSurface9* pDestSurface) 182 | { 183 | return _device->GetRenderTargetData(pRenderTarget, pDestSurface); 184 | } 185 | 186 | STDMETHOD(GetFrontBufferData)(THIS_ UINT iSwapChain, IDirect3DSurface9* pDestSurface) 187 | { 188 | return _device->GetFrontBufferData(iSwapChain, pDestSurface); 189 | } 190 | 191 | STDMETHOD(StretchRect)(THIS_ IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestSurface, CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) 192 | { 193 | return _device->StretchRect(pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter); 194 | } 195 | 196 | STDMETHOD(ColorFill)(THIS_ IDirect3DSurface9* pSurface, CONST RECT* pRect, D3DCOLOR color) 197 | { 198 | return _device->ColorFill(pSurface, pRect, color); 199 | } 200 | 201 | STDMETHOD(CreateOffscreenPlainSurface)(THIS_ UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) 202 | { 203 | return _device->CreateOffscreenPlainSurface(Width, Height, Format, Pool, ppSurface, pSharedHandle); 204 | } 205 | 206 | STDMETHOD(SetRenderTarget)(THIS_ DWORD RenderTargetIndex, IDirect3DSurface9* pRenderTarget) 207 | { 208 | return _device->SetRenderTarget(RenderTargetIndex, pRenderTarget); 209 | } 210 | 211 | STDMETHOD(GetRenderTarget)(THIS_ DWORD RenderTargetIndex, IDirect3DSurface9** ppRenderTarget) 212 | { 213 | return _device->GetRenderTarget(RenderTargetIndex, ppRenderTarget); 214 | } 215 | 216 | STDMETHOD(SetDepthStencilSurface)(THIS_ IDirect3DSurface9* pNewZStencil) 217 | { 218 | return _device->SetDepthStencilSurface(pNewZStencil); 219 | } 220 | 221 | STDMETHOD(GetDepthStencilSurface)(THIS_ IDirect3DSurface9** ppZStencilSurface) 222 | { 223 | return _device->GetDepthStencilSurface(ppZStencilSurface); 224 | } 225 | 226 | STDMETHOD(BeginScene)(THIS) 227 | { 228 | return _device->BeginScene(); 229 | } 230 | 231 | STDMETHOD(EndScene)(THIS) 232 | { 233 | return _device->EndScene(); 234 | } 235 | 236 | STDMETHOD(Clear)(THIS_ DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil); 237 | 238 | STDMETHOD(SetTransform)(THIS_ D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) 239 | { 240 | return _device->SetTransform(State, pMatrix); 241 | } 242 | 243 | STDMETHOD(GetTransform)(THIS_ D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) 244 | { 245 | return _device->GetTransform(State, pMatrix); 246 | } 247 | 248 | STDMETHOD(MultiplyTransform)(THIS_ D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) 249 | { 250 | return _device->MultiplyTransform(State, pMatrix); 251 | } 252 | 253 | STDMETHOD(SetViewport)(THIS_ CONST D3DVIEWPORT9* pViewport) 254 | { 255 | return _device->SetViewport(pViewport); 256 | } 257 | 258 | STDMETHOD(GetViewport)(THIS_ D3DVIEWPORT9* pViewport) 259 | { 260 | return _device->GetViewport(pViewport); 261 | } 262 | 263 | STDMETHOD(SetMaterial)(THIS_ CONST D3DMATERIAL9* pMaterial) 264 | { 265 | return _device->SetMaterial(pMaterial); 266 | } 267 | 268 | STDMETHOD(GetMaterial)(THIS_ D3DMATERIAL9* pMaterial) 269 | { 270 | return _device->GetMaterial(pMaterial); 271 | } 272 | 273 | STDMETHOD(SetLight)(THIS_ DWORD Index, CONST D3DLIGHT9* light) 274 | { 275 | return _device->SetLight(Index, light); 276 | } 277 | 278 | STDMETHOD(GetLight)(THIS_ DWORD Index, D3DLIGHT9* light) 279 | { 280 | return _device->GetLight(Index, light); 281 | } 282 | 283 | STDMETHOD(LightEnable)(THIS_ DWORD Index, BOOL Enable) 284 | { 285 | return _device->LightEnable(Index, Enable); 286 | } 287 | 288 | STDMETHOD(GetLightEnable)(THIS_ DWORD Index, BOOL* pEnable) 289 | { 290 | return _device->GetLightEnable(Index, pEnable); 291 | } 292 | 293 | STDMETHOD(SetClipPlane)(THIS_ DWORD Index, CONST float* pPlane) 294 | { 295 | return _device->SetClipPlane(Index, pPlane); 296 | } 297 | 298 | STDMETHOD(GetClipPlane)(THIS_ DWORD Index, float* pPlane) 299 | { 300 | return _device->GetClipPlane(Index, pPlane); 301 | } 302 | 303 | STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE State, DWORD Value) 304 | { 305 | return _device->SetRenderState(State, Value); 306 | } 307 | 308 | STDMETHOD(GetRenderState)(THIS_ D3DRENDERSTATETYPE State, DWORD* pValue) 309 | { 310 | return _device->GetRenderState(State, pValue); 311 | } 312 | 313 | STDMETHOD(CreateStateBlock)(THIS_ D3DSTATEBLOCKTYPE Type, IDirect3DStateBlock9** ppSB) 314 | { 315 | return _device->CreateStateBlock(Type, ppSB); 316 | } 317 | 318 | STDMETHOD(BeginStateBlock)(THIS) 319 | { 320 | return _device->BeginStateBlock(); 321 | } 322 | 323 | STDMETHOD(EndStateBlock)(THIS_ IDirect3DStateBlock9** ppSB) 324 | { 325 | return _device->EndStateBlock(ppSB); 326 | } 327 | 328 | STDMETHOD(SetClipStatus)(THIS_ CONST D3DCLIPSTATUS9* pClipStatus) 329 | { 330 | return _device->SetClipStatus(pClipStatus); 331 | } 332 | 333 | STDMETHOD(GetClipStatus)(THIS_ D3DCLIPSTATUS9* pClipStatus) 334 | { 335 | return _device->GetClipStatus(pClipStatus); 336 | } 337 | 338 | STDMETHOD(GetTexture)(THIS_ DWORD Stage, IDirect3DBaseTexture9** ppTexture) 339 | { 340 | return _device->GetTexture(Stage, ppTexture); 341 | } 342 | 343 | STDMETHOD(SetTexture)(THIS_ DWORD Stage, IDirect3DBaseTexture9* pTexture) 344 | { 345 | return _device->SetTexture(Stage, pTexture); 346 | } 347 | 348 | STDMETHOD(GetTextureStageState)(THIS_ DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) 349 | { 350 | return _device->GetTextureStageState(Stage, Type, pValue); 351 | } 352 | 353 | STDMETHOD(SetTextureStageState)(THIS_ DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) 354 | { 355 | return _device->SetTextureStageState(Stage, Type, Value); 356 | } 357 | 358 | STDMETHOD(GetSamplerState)(THIS_ DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD* pValue) 359 | { 360 | return _device->GetSamplerState(Sampler, Type, pValue); 361 | } 362 | 363 | STDMETHOD(SetSamplerState)(THIS_ DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) 364 | { 365 | return _device->SetSamplerState(Sampler, Type, Value); 366 | } 367 | 368 | STDMETHOD(ValidateDevice)(THIS_ DWORD* pNumPasses) 369 | { 370 | return _device->ValidateDevice(pNumPasses); 371 | } 372 | 373 | STDMETHOD(SetPaletteEntries)(THIS_ UINT PaletteNumber, CONST PALETTEENTRY* pEntries) 374 | { 375 | return _device->SetPaletteEntries(PaletteNumber, pEntries); 376 | } 377 | 378 | STDMETHOD(GetPaletteEntries)(THIS_ UINT PaletteNumber, PALETTEENTRY* pEntries) 379 | { 380 | return _device->GetPaletteEntries(PaletteNumber, pEntries); 381 | } 382 | 383 | STDMETHOD(SetCurrentTexturePalette)(THIS_ UINT PaletteNumber) 384 | { 385 | return _device->SetCurrentTexturePalette(PaletteNumber); 386 | } 387 | 388 | STDMETHOD(GetCurrentTexturePalette)(THIS_ UINT *PaletteNumber) 389 | { 390 | return _device->GetCurrentTexturePalette(PaletteNumber); 391 | } 392 | 393 | STDMETHOD(SetScissorRect)(THIS_ CONST RECT* pRect) 394 | { 395 | return _device->SetScissorRect(pRect); 396 | } 397 | 398 | STDMETHOD(GetScissorRect)(THIS_ RECT* pRect) 399 | { 400 | return _device->GetScissorRect(pRect); 401 | } 402 | 403 | STDMETHOD(SetSoftwareVertexProcessing)(THIS_ BOOL bSoftware) 404 | { 405 | return _device->SetSoftwareVertexProcessing(bSoftware); 406 | } 407 | 408 | STDMETHOD_(BOOL, GetSoftwareVertexProcessing)(THIS) 409 | { 410 | return _device->GetSoftwareVertexProcessing(); 411 | } 412 | 413 | STDMETHOD(SetNPatchMode)(THIS_ float nSegments) 414 | { 415 | return _device->SetNPatchMode(nSegments); 416 | } 417 | 418 | STDMETHOD_(float, GetNPatchMode)(THIS) 419 | { 420 | return _device->GetNPatchMode(); 421 | } 422 | 423 | STDMETHOD(DrawPrimitive)(THIS_ D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) 424 | { 425 | return _device->DrawPrimitive(PrimitiveType, StartVertex, PrimitiveCount); 426 | } 427 | 428 | STDMETHOD(DrawIndexedPrimitive)(THIS_ D3DPRIMITIVETYPE PrimitiveType, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT primCount) 429 | { 430 | return _device->DrawIndexedPrimitive(PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount); 431 | } 432 | 433 | STDMETHOD(DrawPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) 434 | { 435 | return _device->DrawPrimitiveUP(PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride); 436 | } 437 | 438 | STDMETHOD(DrawIndexedPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertices, UINT PrimitiveCount, CONST void* pIndexData, D3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) 439 | { 440 | return _device->DrawIndexedPrimitiveUP(PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride); 441 | } 442 | 443 | STDMETHOD(ProcessVertices)(THIS_ UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9* pDestBuffer, IDirect3DVertexDeclaration9* pVertexDecl, DWORD Flags) 444 | { 445 | return _device->ProcessVertices(SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags); 446 | } 447 | 448 | STDMETHOD(CreateVertexDeclaration)(THIS_ CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl) 449 | { 450 | return _device->CreateVertexDeclaration(pVertexElements, ppDecl); 451 | } 452 | 453 | STDMETHOD(SetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9* pDecl) 454 | { 455 | return _device->SetVertexDeclaration(pDecl); 456 | } 457 | 458 | STDMETHOD(GetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9** ppDecl) 459 | { 460 | return _device->GetVertexDeclaration(ppDecl); 461 | } 462 | 463 | STDMETHOD(SetFVF)(THIS_ DWORD FVF) 464 | { 465 | return _device->SetFVF(FVF); 466 | } 467 | 468 | STDMETHOD(GetFVF)(THIS_ DWORD* pFVF) 469 | { 470 | return _device->GetFVF(pFVF); 471 | } 472 | 473 | STDMETHOD(CreateVertexShader)(THIS_ CONST DWORD* pFunction, IDirect3DVertexShader9** ppShader) 474 | { 475 | return _device->CreateVertexShader(pFunction, ppShader); 476 | } 477 | 478 | STDMETHOD(SetVertexShader)(THIS_ IDirect3DVertexShader9* pShader) 479 | { 480 | return _device->SetVertexShader(pShader); 481 | } 482 | 483 | STDMETHOD(GetVertexShader)(THIS_ IDirect3DVertexShader9** ppShader) 484 | { 485 | return _device->GetVertexShader(ppShader); 486 | } 487 | 488 | STDMETHOD(SetVertexShaderConstantF)(THIS_ UINT StartRegister, CONST float* pConstantData, UINT Vector4fCount) 489 | { 490 | return _device->SetVertexShaderConstantF(StartRegister, pConstantData, Vector4fCount); 491 | } 492 | 493 | STDMETHOD(GetVertexShaderConstantF)(THIS_ UINT StartRegister, float* pConstantData, UINT Vector4fCount) 494 | { 495 | return _device->GetVertexShaderConstantF(StartRegister, pConstantData, Vector4fCount); 496 | } 497 | 498 | STDMETHOD(SetVertexShaderConstantI)(THIS_ UINT StartRegister, CONST int* pConstantData, UINT Vector4iCount) 499 | { 500 | return _device->SetVertexShaderConstantI(StartRegister, pConstantData, Vector4iCount); 501 | } 502 | 503 | STDMETHOD(GetVertexShaderConstantI)(THIS_ UINT StartRegister, int* pConstantData, UINT Vector4iCount) 504 | { 505 | return _device->GetVertexShaderConstantI(StartRegister, pConstantData, Vector4iCount); 506 | } 507 | 508 | STDMETHOD(SetVertexShaderConstantB)(THIS_ UINT StartRegister, CONST BOOL* pConstantData, UINT BoolCount) 509 | { 510 | return _device->SetVertexShaderConstantB(StartRegister, pConstantData, BoolCount); 511 | } 512 | 513 | STDMETHOD(GetVertexShaderConstantB)(THIS_ UINT StartRegister, BOOL* pConstantData, UINT BoolCount) 514 | { 515 | return _device->GetVertexShaderConstantB(StartRegister, pConstantData, BoolCount); 516 | } 517 | 518 | STDMETHOD(SetStreamSource)(THIS_ UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInBytes, UINT Stride) 519 | { 520 | return _device->SetStreamSource(StreamNumber, pStreamData, OffsetInBytes, Stride); 521 | } 522 | 523 | STDMETHOD(GetStreamSource)(THIS_ UINT StreamNumber, IDirect3DVertexBuffer9** ppStreamData, UINT* pOffsetInBytes, UINT* pStride) 524 | { 525 | return _device->GetStreamSource(StreamNumber, ppStreamData, pOffsetInBytes, pStride); 526 | } 527 | 528 | STDMETHOD(SetStreamSourceFreq)(THIS_ UINT StreamNumber, UINT Setting) 529 | { 530 | return _device->SetStreamSourceFreq(StreamNumber, Setting); 531 | } 532 | 533 | STDMETHOD(GetStreamSourceFreq)(THIS_ UINT StreamNumber, UINT* pSetting) 534 | { 535 | return _device->GetStreamSourceFreq(StreamNumber, pSetting); 536 | } 537 | 538 | STDMETHOD(SetIndices)(THIS_ IDirect3DIndexBuffer9* pIndexData) 539 | { 540 | return _device->SetIndices(pIndexData); 541 | } 542 | 543 | STDMETHOD(GetIndices)(THIS_ IDirect3DIndexBuffer9** ppIndexData) 544 | { 545 | return _device->GetIndices(ppIndexData); 546 | } 547 | 548 | STDMETHOD(CreatePixelShader)(THIS_ CONST DWORD* pFunction, IDirect3DPixelShader9** ppShader) 549 | { 550 | return _device->CreatePixelShader(pFunction, ppShader); 551 | } 552 | 553 | STDMETHOD(SetPixelShader)(THIS_ IDirect3DPixelShader9* pShader) 554 | { 555 | return _device->SetPixelShader(pShader); 556 | } 557 | 558 | STDMETHOD(GetPixelShader)(THIS_ IDirect3DPixelShader9** ppShader) 559 | { 560 | return _device->GetPixelShader(ppShader); 561 | } 562 | 563 | STDMETHOD(SetPixelShaderConstantF)(THIS_ UINT StartRegister, CONST float* pConstantData, UINT Vector4fCount) 564 | { 565 | return _device->SetPixelShaderConstantF(StartRegister, pConstantData, Vector4fCount); 566 | } 567 | 568 | STDMETHOD(GetPixelShaderConstantF)(THIS_ UINT StartRegister, float* pConstantData, UINT Vector4fCount) 569 | { 570 | return _device->GetPixelShaderConstantF(StartRegister, pConstantData, Vector4fCount); 571 | } 572 | 573 | STDMETHOD(SetPixelShaderConstantI)(THIS_ UINT StartRegister, CONST int* pConstantData, UINT Vector4iCount) 574 | { 575 | return _device->SetPixelShaderConstantI(StartRegister, pConstantData, Vector4iCount); 576 | } 577 | 578 | STDMETHOD(GetPixelShaderConstantI)(THIS_ UINT StartRegister, int* pConstantData, UINT Vector4iCount) 579 | { 580 | return _device->GetPixelShaderConstantI(StartRegister, pConstantData, Vector4iCount); 581 | } 582 | 583 | STDMETHOD(SetPixelShaderConstantB)(THIS_ UINT StartRegister, CONST BOOL* pConstantData, UINT BoolCount) 584 | { 585 | return _device->SetPixelShaderConstantB(StartRegister, pConstantData, BoolCount); 586 | } 587 | 588 | STDMETHOD(GetPixelShaderConstantB)(THIS_ UINT StartRegister, BOOL* pConstantData, UINT BoolCount) 589 | { 590 | return _device->GetPixelShaderConstantB(StartRegister, pConstantData, BoolCount); 591 | } 592 | 593 | STDMETHOD(DrawRectPatch)(THIS_ UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) 594 | { 595 | return _device->DrawRectPatch(Handle, pNumSegs, pRectPatchInfo); 596 | } 597 | 598 | STDMETHOD(DrawTriPatch)(THIS_ UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) 599 | { 600 | return _device->DrawTriPatch(Handle, pNumSegs, pTriPatchInfo); 601 | } 602 | 603 | STDMETHOD(DeletePatch)(THIS_ UINT Handle) 604 | { 605 | return _device->DeletePatch(Handle); 606 | } 607 | 608 | STDMETHOD(CreateQuery)(THIS_ D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery) 609 | { 610 | return _device->CreateQuery(Type, ppQuery); 611 | } 612 | 613 | }; 614 | 615 | -------------------------------------------------------------------------------- /Detours/include/detours.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Core Detours Functionality (detours.h of detours.lib) 4 | // 5 | // Microsoft Research Detours Package, Version 3.0 Build_343. 6 | // 7 | // Copyright (c) Microsoft Corporation. All rights reserved. 8 | // 9 | 10 | #pragma once 11 | #ifndef _DETOURS_H_ 12 | #define _DETOURS_H_ 13 | 14 | #define DETOURS_VERSION 30001 // 3.00.01 15 | 16 | ////////////////////////////////////////////////////////////////////////////// 17 | // 18 | 19 | #undef DETOURS_X64 20 | #undef DETOURS_X86 21 | #undef DETOURS_IA64 22 | #undef DETOURS_ARM 23 | #undef DETOURS_ARM64 24 | #undef DETOURS_BITS 25 | #undef DETOURS_32BIT 26 | #undef DETOURS_64BIT 27 | 28 | #if defined(_X86_) 29 | #define DETOURS_X86 30 | #define DETOURS_OPTION_BITS 64 31 | 32 | #elif defined(_AMD64_) 33 | #define DETOURS_X64 34 | #define DETOURS_OPTION_BITS 32 35 | 36 | #elif defined(_IA64_) 37 | #define DETOURS_IA64 38 | #define DETOURS_OPTION_BITS 32 39 | 40 | #elif defined(_ARM_) 41 | #define DETOURS_ARM 42 | 43 | #elif defined(_ARM64_) 44 | #define DETOURS_ARM64 45 | 46 | #else 47 | #error Unknown architecture (x86, amd64, ia64, arm, arm64) 48 | #endif 49 | 50 | #ifdef _WIN64 51 | #undef DETOURS_32BIT 52 | #define DETOURS_64BIT 1 53 | #define DETOURS_BITS 64 54 | // If all 64bit kernels can run one and only one 32bit architecture. 55 | //#define DETOURS_OPTION_BITS 32 56 | #else 57 | #define DETOURS_32BIT 1 58 | #undef DETOURS_64BIT 59 | #define DETOURS_BITS 32 60 | // If all 64bit kernels can run one and only one 32bit architecture. 61 | //#define DETOURS_OPTION_BITS 32 62 | #endif 63 | 64 | #define VER_DETOURS_BITS DETOUR_STRINGIFY(DETOURS_BITS) 65 | 66 | ////////////////////////////////////////////////////////////////////////////// 67 | // 68 | 69 | #if (_MSC_VER < 1299) 70 | typedef LONG LONG_PTR; 71 | typedef ULONG ULONG_PTR; 72 | #endif 73 | 74 | ///////////////////////////////////////////////// SAL 2.0 Annotations w/o SAL. 75 | // 76 | // These definitions are include so that Detours will build even if the 77 | // compiler doesn't have full SAL 2.0 support. 78 | // 79 | #ifndef DETOURS_DONT_REMOVE_SAL_20 80 | 81 | #ifdef DETOURS_TEST_REMOVE_SAL_20 82 | #undef _Analysis_assume_ 83 | #undef _Benign_race_begin_ 84 | #undef _Benign_race_end_ 85 | #undef _Field_range_ 86 | #undef _Field_size_ 87 | #undef _In_ 88 | #undef _In_bytecount_ 89 | #undef _In_count_ 90 | #undef _In_opt_ 91 | #undef _In_opt_bytecount_ 92 | #undef _In_opt_count_ 93 | #undef _In_opt_z_ 94 | #undef _In_range_ 95 | #undef _In_reads_ 96 | #undef _In_reads_bytes_ 97 | #undef _In_reads_opt_ 98 | #undef _In_reads_opt_bytes_ 99 | #undef _In_reads_or_z_ 100 | #undef _In_z_ 101 | #undef _Inout_ 102 | #undef _Inout_opt_ 103 | #undef _Inout_z_count_ 104 | #undef _Out_ 105 | #undef _Out_opt_ 106 | #undef _Out_writes_ 107 | #undef _Outptr_result_maybenull_ 108 | #undef _Readable_bytes_ 109 | #undef _Success_ 110 | #undef _Writable_bytes_ 111 | #undef _Pre_notnull_ 112 | #endif 113 | 114 | #if defined(_Deref_out_opt_z_) && !defined(_Outptr_result_maybenull_) 115 | #define _Outptr_result_maybenull_ _Deref_out_opt_z_ 116 | #endif 117 | 118 | #if defined(_In_count_) && !defined(_In_reads_) 119 | #define _In_reads_(x) _In_count_(x) 120 | #endif 121 | 122 | #if defined(_In_opt_count_) && !defined(_In_reads_opt_) 123 | #define _In_reads_opt_(x) _In_opt_count_(x) 124 | #endif 125 | 126 | #if defined(_In_opt_bytecount_) && !defined(_In_reads_opt_bytes_) 127 | #define _In_reads_opt_bytes_(x) _In_opt_bytecount_(x) 128 | #endif 129 | 130 | #if defined(_In_bytecount_) && !defined(_In_reads_bytes_) 131 | #define _In_reads_bytes_(x) _In_bytecount_(x) 132 | #endif 133 | 134 | #ifndef _In_ 135 | #define _In_ 136 | #endif 137 | 138 | #ifndef _In_bytecount_ 139 | #define _In_bytecount_(x) 140 | #endif 141 | 142 | #ifndef _In_count_ 143 | #define _In_count_(x) 144 | #endif 145 | 146 | #ifndef _In_opt_ 147 | #define _In_opt_ 148 | #endif 149 | 150 | #ifndef _In_opt_bytecount_ 151 | #define _In_opt_bytecount_(x) 152 | #endif 153 | 154 | #ifndef _In_opt_count_ 155 | #define _In_opt_count_(x) 156 | #endif 157 | 158 | #ifndef _In_opt_z_ 159 | #define _In_opt_z_ 160 | #endif 161 | 162 | #ifndef _In_range_ 163 | #define _In_range_(x,y) 164 | #endif 165 | 166 | #ifndef _In_reads_ 167 | #define _In_reads_(x) 168 | #endif 169 | 170 | #ifndef _In_reads_bytes_ 171 | #define _In_reads_bytes_(x) 172 | #endif 173 | 174 | #ifndef _In_reads_opt_ 175 | #define _In_reads_opt_(x) 176 | #endif 177 | 178 | #ifndef _In_reads_opt_bytes_ 179 | #define _In_reads_opt_bytes_(x) 180 | #endif 181 | 182 | #ifndef _In_reads_or_z_ 183 | #define _In_reads_or_z_ 184 | #endif 185 | 186 | #ifndef _In_z_ 187 | #define _In_z_ 188 | #endif 189 | 190 | #ifndef _Inout_ 191 | #define _Inout_ 192 | #endif 193 | 194 | #ifndef _Inout_opt_ 195 | #define _Inout_opt_ 196 | #endif 197 | 198 | #ifndef _Inout_z_count_ 199 | #define _Inout_z_count_(x) 200 | #endif 201 | 202 | #ifndef _Out_ 203 | #define _Out_ 204 | #endif 205 | 206 | #ifndef _Out_opt_ 207 | #define _Out_opt_ 208 | #endif 209 | 210 | #ifndef _Out_writes_ 211 | #define _Out_writes_(x) 212 | #endif 213 | 214 | #ifndef _Outptr_result_maybenull_ 215 | #define _Outptr_result_maybenull_ 216 | #endif 217 | 218 | #ifndef _Writable_bytes_ 219 | #define _Writable_bytes_(x) 220 | #endif 221 | 222 | #ifndef _Readable_bytes_ 223 | #define _Readable_bytes_(x) 224 | #endif 225 | 226 | #ifndef _Success_ 227 | #define _Success_(x) 228 | #endif 229 | 230 | #ifndef _Pre_notnull_ 231 | #define _Pre_notnull_ 232 | #endif 233 | 234 | #ifdef DETOURS_INTERNAL 235 | 236 | #pragma warning(disable:4615) // unknown warning type (suppress with older compilers) 237 | 238 | #ifndef _Benign_race_begin_ 239 | #define _Benign_race_begin_ 240 | #endif 241 | 242 | #ifndef _Benign_race_end_ 243 | #define _Benign_race_end_ 244 | #endif 245 | 246 | #ifndef _Field_size_ 247 | #define _Field_size_(x) 248 | #endif 249 | 250 | #ifndef _Field_range_ 251 | #define _Field_range_(x,y) 252 | #endif 253 | 254 | #ifndef _Analysis_assume_ 255 | #define _Analysis_assume_(x) 256 | #endif 257 | 258 | #endif // DETOURS_INTERNAL 259 | #endif // DETOURS_DONT_REMOVE_SAL_20 260 | 261 | ////////////////////////////////////////////////////////////////////////////// 262 | // 263 | #ifndef GUID_DEFINED 264 | #define GUID_DEFINED 265 | typedef struct _GUID 266 | { 267 | DWORD Data1; 268 | WORD Data2; 269 | WORD Data3; 270 | BYTE Data4[ 8 ]; 271 | } GUID; 272 | 273 | #ifdef INITGUID 274 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ 275 | const GUID name \ 276 | = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } 277 | #else 278 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ 279 | const GUID name 280 | #endif // INITGUID 281 | #endif // !GUID_DEFINED 282 | 283 | #if defined(__cplusplus) 284 | #ifndef _REFGUID_DEFINED 285 | #define _REFGUID_DEFINED 286 | #define REFGUID const GUID & 287 | #endif // !_REFGUID_DEFINED 288 | #else // !__cplusplus 289 | #ifndef _REFGUID_DEFINED 290 | #define _REFGUID_DEFINED 291 | #define REFGUID const GUID * const 292 | #endif // !_REFGUID_DEFINED 293 | #endif // !__cplusplus 294 | 295 | #ifndef ARRAYSIZE 296 | #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0])) 297 | #endif 298 | 299 | // 300 | ////////////////////////////////////////////////////////////////////////////// 301 | 302 | #ifdef __cplusplus 303 | extern "C" { 304 | #endif // __cplusplus 305 | 306 | /////////////////////////////////////////////////// Instruction Target Macros. 307 | // 308 | #define DETOUR_INSTRUCTION_TARGET_NONE ((PVOID)0) 309 | #define DETOUR_INSTRUCTION_TARGET_DYNAMIC ((PVOID)(LONG_PTR)-1) 310 | #define DETOUR_SECTION_HEADER_SIGNATURE 0x00727444 // "Dtr\0" 311 | 312 | extern const GUID DETOUR_EXE_RESTORE_GUID; 313 | extern const GUID DETOUR_EXE_HELPER_GUID; 314 | 315 | #define DETOUR_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr! 316 | typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE; 317 | 318 | /////////////////////////////////////////////////////////// Binary Structures. 319 | // 320 | #pragma pack(push, 8) 321 | typedef struct _DETOUR_SECTION_HEADER 322 | { 323 | DWORD cbHeaderSize; 324 | DWORD nSignature; 325 | DWORD nDataOffset; 326 | DWORD cbDataSize; 327 | 328 | DWORD nOriginalImportVirtualAddress; 329 | DWORD nOriginalImportSize; 330 | DWORD nOriginalBoundImportVirtualAddress; 331 | DWORD nOriginalBoundImportSize; 332 | 333 | DWORD nOriginalIatVirtualAddress; 334 | DWORD nOriginalIatSize; 335 | DWORD nOriginalSizeOfImage; 336 | DWORD cbPrePE; 337 | 338 | DWORD nOriginalClrFlags; 339 | DWORD reserved1; 340 | DWORD reserved2; 341 | DWORD reserved3; 342 | 343 | // Followed by cbPrePE bytes of data. 344 | } DETOUR_SECTION_HEADER, *PDETOUR_SECTION_HEADER; 345 | 346 | typedef struct _DETOUR_SECTION_RECORD 347 | { 348 | DWORD cbBytes; 349 | DWORD nReserved; 350 | GUID guid; 351 | } DETOUR_SECTION_RECORD, *PDETOUR_SECTION_RECORD; 352 | 353 | typedef struct _DETOUR_CLR_HEADER 354 | { 355 | // Header versioning 356 | ULONG cb; 357 | USHORT MajorRuntimeVersion; 358 | USHORT MinorRuntimeVersion; 359 | 360 | // Symbol table and startup information 361 | IMAGE_DATA_DIRECTORY MetaData; 362 | ULONG Flags; 363 | 364 | // Followed by the rest of the IMAGE_COR20_HEADER 365 | } DETOUR_CLR_HEADER, *PDETOUR_CLR_HEADER; 366 | 367 | typedef struct _DETOUR_EXE_RESTORE 368 | { 369 | DWORD cb; 370 | DWORD cbidh; 371 | DWORD cbinh; 372 | DWORD cbclr; 373 | 374 | PBYTE pidh; 375 | PBYTE pinh; 376 | PBYTE pclr; 377 | 378 | IMAGE_DOS_HEADER idh; 379 | union { 380 | IMAGE_NT_HEADERS inh; 381 | IMAGE_NT_HEADERS32 inh32; 382 | IMAGE_NT_HEADERS64 inh64; 383 | BYTE raw[sizeof(IMAGE_NT_HEADERS64) + 384 | sizeof(IMAGE_SECTION_HEADER) * 32]; 385 | }; 386 | DETOUR_CLR_HEADER clr; 387 | 388 | } DETOUR_EXE_RESTORE, *PDETOUR_EXE_RESTORE; 389 | 390 | typedef struct _DETOUR_EXE_HELPER 391 | { 392 | DWORD cb; 393 | DWORD pid; 394 | DWORD nDlls; 395 | CHAR rDlls[4]; 396 | } DETOUR_EXE_HELPER, *PDETOUR_EXE_HELPER; 397 | 398 | #pragma pack(pop) 399 | 400 | #define DETOUR_SECTION_HEADER_DECLARE(cbSectionSize) \ 401 | { \ 402 | sizeof(DETOUR_SECTION_HEADER),\ 403 | DETOUR_SECTION_HEADER_SIGNATURE,\ 404 | sizeof(DETOUR_SECTION_HEADER),\ 405 | (cbSectionSize),\ 406 | \ 407 | 0,\ 408 | 0,\ 409 | 0,\ 410 | 0,\ 411 | \ 412 | 0,\ 413 | 0,\ 414 | 0,\ 415 | 0,\ 416 | } 417 | 418 | /////////////////////////////////////////////////////////////// Helper Macros. 419 | // 420 | #define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x) 421 | #define DETOURS_STRINGIFY_(x) #x 422 | 423 | ///////////////////////////////////////////////////////////// Binary Typedefs. 424 | // 425 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_BYWAY_CALLBACK)( 426 | _In_opt_ PVOID pContext, 427 | _In_opt_ LPCSTR pszFile, 428 | _Outptr_result_maybenull_ LPCSTR *ppszOutFile); 429 | 430 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_FILE_CALLBACK)( 431 | _In_opt_ PVOID pContext, 432 | _In_ LPCSTR pszOrigFile, 433 | _In_ LPCSTR pszFile, 434 | _Outptr_result_maybenull_ LPCSTR *ppszOutFile); 435 | 436 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_SYMBOL_CALLBACK)( 437 | _In_opt_ PVOID pContext, 438 | _In_ ULONG nOrigOrdinal, 439 | _In_ ULONG nOrdinal, 440 | _Out_ ULONG *pnOutOrdinal, 441 | _In_opt_ LPCSTR pszOrigSymbol, 442 | _In_opt_ LPCSTR pszSymbol, 443 | _Outptr_result_maybenull_ LPCSTR *ppszOutSymbol); 444 | 445 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_COMMIT_CALLBACK)( 446 | _In_opt_ PVOID pContext); 447 | 448 | typedef BOOL (CALLBACK *PF_DETOUR_ENUMERATE_EXPORT_CALLBACK)(_In_opt_ PVOID pContext, 449 | _In_ ULONG nOrdinal, 450 | _In_opt_ LPCSTR pszName, 451 | _In_opt_ PVOID pCode); 452 | 453 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FILE_CALLBACK)(_In_opt_ PVOID pContext, 454 | _In_opt_ HMODULE hModule, 455 | _In_opt_ LPCSTR pszFile); 456 | 457 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK)(_In_opt_ PVOID pContext, 458 | _In_ DWORD nOrdinal, 459 | _In_opt_ LPCSTR pszFunc, 460 | _In_opt_ PVOID pvFunc); 461 | 462 | // Same as PF_DETOUR_IMPORT_FUNC_CALLBACK but extra indirection on last parameter. 463 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK_EX)(_In_opt_ PVOID pContext, 464 | _In_ DWORD nOrdinal, 465 | _In_opt_ LPCSTR pszFunc, 466 | _In_opt_ PVOID* ppvFunc); 467 | 468 | typedef VOID * PDETOUR_BINARY; 469 | typedef VOID * PDETOUR_LOADED_BINARY; 470 | 471 | //////////////////////////////////////////////////////////// Transaction APIs. 472 | // 473 | LONG WINAPI DetourTransactionBegin(VOID); 474 | LONG WINAPI DetourTransactionAbort(VOID); 475 | LONG WINAPI DetourTransactionCommit(VOID); 476 | LONG WINAPI DetourTransactionCommitEx(_Out_opt_ PVOID **pppFailedPointer); 477 | 478 | LONG WINAPI DetourUpdateThread(_In_ HANDLE hThread); 479 | 480 | LONG WINAPI DetourAttach(_Inout_ PVOID *ppPointer, 481 | _In_ PVOID pDetour); 482 | 483 | LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer, 484 | _In_ PVOID pDetour, 485 | _Out_opt_ PDETOUR_TRAMPOLINE *ppRealTrampoline, 486 | _Out_opt_ PVOID *ppRealTarget, 487 | _Out_opt_ PVOID *ppRealDetour); 488 | 489 | LONG WINAPI DetourDetach(_Inout_ PVOID *ppPointer, 490 | _In_ PVOID pDetour); 491 | 492 | BOOL WINAPI DetourSetIgnoreTooSmall(_In_ BOOL fIgnore); 493 | BOOL WINAPI DetourSetRetainRegions(_In_ BOOL fRetain); 494 | PVOID WINAPI DetourSetSystemRegionLowerBound(_In_ PVOID pSystemRegionLowerBound); 495 | PVOID WINAPI DetourSetSystemRegionUpperBound(_In_ PVOID pSystemRegionUpperBound); 496 | 497 | ////////////////////////////////////////////////////////////// Code Functions. 498 | // 499 | PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule, 500 | _In_ LPCSTR pszFunction); 501 | PVOID WINAPI DetourCodeFromPointer(_In_ PVOID pPointer, 502 | _Out_opt_ PVOID *ppGlobals); 503 | PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst, 504 | _Inout_opt_ PVOID *ppDstPool, 505 | _In_ PVOID pSrc, 506 | _Out_opt_ PVOID *ppTarget, 507 | _Out_opt_ LONG *plExtra); 508 | BOOL WINAPI DetourSetCodeModule(_In_ HMODULE hModule, 509 | _In_ BOOL fLimitReferencesToModule); 510 | 511 | ///////////////////////////////////////////////////// Loaded Binary Functions. 512 | // 513 | HMODULE WINAPI DetourGetContainingModule(_In_ PVOID pvAddr); 514 | HMODULE WINAPI DetourEnumerateModules(_In_opt_ HMODULE hModuleLast); 515 | PVOID WINAPI DetourGetEntryPoint(_In_opt_ HMODULE hModule); 516 | ULONG WINAPI DetourGetModuleSize(_In_opt_ HMODULE hModule); 517 | BOOL WINAPI DetourEnumerateExports(_In_ HMODULE hModule, 518 | _In_opt_ PVOID pContext, 519 | _In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport); 520 | BOOL WINAPI DetourEnumerateImports(_In_opt_ HMODULE hModule, 521 | _In_opt_ PVOID pContext, 522 | _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, 523 | _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc); 524 | 525 | BOOL WINAPI DetourEnumerateImportsEx(_In_opt_ HMODULE hModule, 526 | _In_opt_ PVOID pContext, 527 | _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, 528 | _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK_EX pfImportFuncEx); 529 | 530 | _Writable_bytes_(*pcbData) 531 | _Readable_bytes_(*pcbData) 532 | _Success_(return != NULL) 533 | PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule, 534 | _In_ REFGUID rguid, 535 | _Out_ DWORD *pcbData); 536 | 537 | _Writable_bytes_(*pcbData) 538 | _Readable_bytes_(*pcbData) 539 | _Success_(return != NULL) 540 | PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid, 541 | _Out_ DWORD * pcbData); 542 | 543 | DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule); 544 | 545 | ///////////////////////////////////////////////// Persistent Binary Functions. 546 | // 547 | 548 | PDETOUR_BINARY WINAPI DetourBinaryOpen(_In_ HANDLE hFile); 549 | 550 | _Writable_bytes_(*pcbData) 551 | _Readable_bytes_(*pcbData) 552 | _Success_(return != NULL) 553 | PVOID WINAPI DetourBinaryEnumeratePayloads(_In_ PDETOUR_BINARY pBinary, 554 | _Out_opt_ GUID *pGuid, 555 | _Out_ DWORD *pcbData, 556 | _Inout_ DWORD *pnIterator); 557 | 558 | _Writable_bytes_(*pcbData) 559 | _Readable_bytes_(*pcbData) 560 | _Success_(return != NULL) 561 | PVOID WINAPI DetourBinaryFindPayload(_In_ PDETOUR_BINARY pBinary, 562 | _In_ REFGUID rguid, 563 | _Out_ DWORD *pcbData); 564 | 565 | PVOID WINAPI DetourBinarySetPayload(_In_ PDETOUR_BINARY pBinary, 566 | _In_ REFGUID rguid, 567 | _In_reads_opt_(cbData) PVOID pData, 568 | _In_ DWORD cbData); 569 | BOOL WINAPI DetourBinaryDeletePayload(_In_ PDETOUR_BINARY pBinary, _In_ REFGUID rguid); 570 | BOOL WINAPI DetourBinaryPurgePayloads(_In_ PDETOUR_BINARY pBinary); 571 | BOOL WINAPI DetourBinaryResetImports(_In_ PDETOUR_BINARY pBinary); 572 | BOOL WINAPI DetourBinaryEditImports(_In_ PDETOUR_BINARY pBinary, 573 | _In_opt_ PVOID pContext, 574 | _In_opt_ PF_DETOUR_BINARY_BYWAY_CALLBACK pfByway, 575 | _In_opt_ PF_DETOUR_BINARY_FILE_CALLBACK pfFile, 576 | _In_opt_ PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbol, 577 | _In_opt_ PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommit); 578 | BOOL WINAPI DetourBinaryWrite(_In_ PDETOUR_BINARY pBinary, _In_ HANDLE hFile); 579 | BOOL WINAPI DetourBinaryClose(_In_ PDETOUR_BINARY pBinary); 580 | 581 | /////////////////////////////////////////////////// Create Process & Load Dll. 582 | // 583 | typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEA)( 584 | _In_opt_ LPCSTR lpApplicationName, 585 | _Inout_opt_ LPSTR lpCommandLine, 586 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 587 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 588 | _In_ BOOL bInheritHandles, 589 | _In_ DWORD dwCreationFlags, 590 | _In_opt_ LPVOID lpEnvironment, 591 | _In_opt_ LPCSTR lpCurrentDirectory, 592 | _In_ LPSTARTUPINFOA lpStartupInfo, 593 | _Out_ LPPROCESS_INFORMATION lpProcessInformation); 594 | 595 | typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEW)( 596 | _In_opt_ LPCWSTR lpApplicationName, 597 | _Inout_opt_ LPWSTR lpCommandLine, 598 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 599 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 600 | _In_ BOOL bInheritHandles, 601 | _In_ DWORD dwCreationFlags, 602 | _In_opt_ LPVOID lpEnvironment, 603 | _In_opt_ LPCWSTR lpCurrentDirectory, 604 | _In_ LPSTARTUPINFOW lpStartupInfo, 605 | _Out_ LPPROCESS_INFORMATION lpProcessInformation); 606 | 607 | BOOL WINAPI DetourCreateProcessWithDllA(_In_opt_ LPCSTR lpApplicationName, 608 | _Inout_opt_ LPSTR lpCommandLine, 609 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 610 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 611 | _In_ BOOL bInheritHandles, 612 | _In_ DWORD dwCreationFlags, 613 | _In_opt_ LPVOID lpEnvironment, 614 | _In_opt_ LPCSTR lpCurrentDirectory, 615 | _In_ LPSTARTUPINFOA lpStartupInfo, 616 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 617 | _In_ LPCSTR lpDllName, 618 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 619 | 620 | BOOL WINAPI DetourCreateProcessWithDllW(_In_opt_ LPCWSTR lpApplicationName, 621 | _Inout_opt_ LPWSTR lpCommandLine, 622 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 623 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 624 | _In_ BOOL bInheritHandles, 625 | _In_ DWORD dwCreationFlags, 626 | _In_opt_ LPVOID lpEnvironment, 627 | _In_opt_ LPCWSTR lpCurrentDirectory, 628 | _In_ LPSTARTUPINFOW lpStartupInfo, 629 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 630 | _In_ LPCSTR lpDllName, 631 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 632 | 633 | #ifdef UNICODE 634 | #define DetourCreateProcessWithDll DetourCreateProcessWithDllW 635 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEW 636 | #else 637 | #define DetourCreateProcessWithDll DetourCreateProcessWithDllA 638 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEA 639 | #endif // !UNICODE 640 | 641 | BOOL WINAPI DetourCreateProcessWithDllExA(_In_opt_ LPCSTR lpApplicationName, 642 | _Inout_opt_ LPSTR lpCommandLine, 643 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 644 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 645 | _In_ BOOL bInheritHandles, 646 | _In_ DWORD dwCreationFlags, 647 | _In_opt_ LPVOID lpEnvironment, 648 | _In_opt_ LPCSTR lpCurrentDirectory, 649 | _In_ LPSTARTUPINFOA lpStartupInfo, 650 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 651 | _In_ LPCSTR lpDllName, 652 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 653 | 654 | BOOL WINAPI DetourCreateProcessWithDllExW(_In_opt_ LPCWSTR lpApplicationName, 655 | _Inout_opt_ LPWSTR lpCommandLine, 656 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 657 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 658 | _In_ BOOL bInheritHandles, 659 | _In_ DWORD dwCreationFlags, 660 | _In_opt_ LPVOID lpEnvironment, 661 | _In_opt_ LPCWSTR lpCurrentDirectory, 662 | _In_ LPSTARTUPINFOW lpStartupInfo, 663 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 664 | _In_ LPCSTR lpDllName, 665 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 666 | 667 | #ifdef UNICODE 668 | #define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExW 669 | #else 670 | #define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExA 671 | #endif // !UNICODE 672 | 673 | BOOL WINAPI DetourCreateProcessWithDllsA(_In_opt_ LPCSTR lpApplicationName, 674 | _Inout_opt_ LPSTR lpCommandLine, 675 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 676 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 677 | _In_ BOOL bInheritHandles, 678 | _In_ DWORD dwCreationFlags, 679 | _In_opt_ LPVOID lpEnvironment, 680 | _In_opt_ LPCSTR lpCurrentDirectory, 681 | _In_ LPSTARTUPINFOA lpStartupInfo, 682 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 683 | _In_ DWORD nDlls, 684 | _In_reads_(nDlls) LPCSTR *rlpDlls, 685 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 686 | 687 | BOOL WINAPI DetourCreateProcessWithDllsW(_In_opt_ LPCWSTR lpApplicationName, 688 | _Inout_opt_ LPWSTR lpCommandLine, 689 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 690 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 691 | _In_ BOOL bInheritHandles, 692 | _In_ DWORD dwCreationFlags, 693 | _In_opt_ LPVOID lpEnvironment, 694 | _In_opt_ LPCWSTR lpCurrentDirectory, 695 | _In_ LPSTARTUPINFOW lpStartupInfo, 696 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 697 | _In_ DWORD nDlls, 698 | _In_reads_(nDlls) LPCSTR *rlpDlls, 699 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 700 | 701 | #ifdef UNICODE 702 | #define DetourCreateProcessWithDlls DetourCreateProcessWithDllsW 703 | #else 704 | #define DetourCreateProcessWithDlls DetourCreateProcessWithDllsA 705 | #endif // !UNICODE 706 | 707 | BOOL WINAPI DetourProcessViaHelperA(_In_ DWORD dwTargetPid, 708 | _In_ LPCSTR lpDllName, 709 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 710 | 711 | BOOL WINAPI DetourProcessViaHelperW(_In_ DWORD dwTargetPid, 712 | _In_ LPCSTR lpDllName, 713 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 714 | 715 | #ifdef UNICODE 716 | #define DetourProcessViaHelper DetourProcessViaHelperW 717 | #else 718 | #define DetourProcessViaHelper DetourProcessViaHelperA 719 | #endif // !UNICODE 720 | 721 | BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid, 722 | _In_ DWORD nDlls, 723 | _In_reads_(nDlls) LPCSTR *rlpDlls, 724 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 725 | 726 | BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid, 727 | _In_ DWORD nDlls, 728 | _In_reads_(nDlls) LPCSTR *rlpDlls, 729 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 730 | 731 | #ifdef UNICODE 732 | #define DetourProcessViaHelperDlls DetourProcessViaHelperDllsW 733 | #else 734 | #define DetourProcessViaHelperDlls DetourProcessViaHelperDllsA 735 | #endif // !UNICODE 736 | 737 | BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess, 738 | _In_reads_(nDlls) LPCSTR *rlpDlls, 739 | _In_ DWORD nDlls); 740 | 741 | BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess, 742 | _In_ HMODULE hImage, 743 | _In_ BOOL bIs32Bit, 744 | _In_reads_(nDlls) LPCSTR *rlpDlls, 745 | _In_ DWORD nDlls); 746 | 747 | BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, 748 | _In_ REFGUID rguid, 749 | _In_reads_bytes_(cbData) PVOID pvData, 750 | _In_ DWORD cbData); 751 | BOOL WINAPI DetourRestoreAfterWith(VOID); 752 | BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData, 753 | _In_ DWORD cbData); 754 | BOOL WINAPI DetourIsHelperProcess(VOID); 755 | VOID CALLBACK DetourFinishHelperProcess(_In_ HWND, 756 | _In_ HINSTANCE, 757 | _In_ LPSTR, 758 | _In_ INT); 759 | 760 | // 761 | ////////////////////////////////////////////////////////////////////////////// 762 | #ifdef __cplusplus 763 | } 764 | #endif // __cplusplus 765 | 766 | //////////////////////////////////////////////// Detours Internal Definitions. 767 | // 768 | #ifdef __cplusplus 769 | #ifdef DETOURS_INTERNAL 770 | 771 | #define NOTHROW 772 | // #define NOTHROW (nothrow) 773 | 774 | ////////////////////////////////////////////////////////////////////////////// 775 | // 776 | #if (_MSC_VER < 1299) 777 | #include 778 | typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64; 779 | typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64; 780 | typedef IMAGEHLP_SYMBOL SYMBOL_INFO; 781 | typedef PIMAGEHLP_SYMBOL PSYMBOL_INFO; 782 | 783 | static inline 784 | LONG InterlockedCompareExchange(_Inout_ LONG *ptr, _In_ LONG nval, _In_ LONG oval) 785 | { 786 | return (LONG)::InterlockedCompareExchange((PVOID*)ptr, (PVOID)nval, (PVOID)oval); 787 | } 788 | #else 789 | #pragma warning(push) 790 | #pragma warning(disable:4091) // empty typedef 791 | #include 792 | #pragma warning(pop) 793 | #endif 794 | 795 | #ifdef IMAGEAPI // defined by DBGHELP.H 796 | typedef LPAPI_VERSION (NTAPI *PF_ImagehlpApiVersionEx)(_In_ LPAPI_VERSION AppVersion); 797 | 798 | typedef BOOL (NTAPI *PF_SymInitialize)(_In_ HANDLE hProcess, 799 | _In_opt_ LPCSTR UserSearchPath, 800 | _In_ BOOL fInvadeProcess); 801 | typedef DWORD (NTAPI *PF_SymSetOptions)(_In_ DWORD SymOptions); 802 | typedef DWORD (NTAPI *PF_SymGetOptions)(VOID); 803 | typedef DWORD64 (NTAPI *PF_SymLoadModule64)(_In_ HANDLE hProcess, 804 | _In_opt_ HANDLE hFile, 805 | _In_ LPSTR ImageName, 806 | _In_opt_ LPSTR ModuleName, 807 | _In_ DWORD64 BaseOfDll, 808 | _In_opt_ DWORD SizeOfDll); 809 | typedef BOOL (NTAPI *PF_SymGetModuleInfo64)(_In_ HANDLE hProcess, 810 | _In_ DWORD64 qwAddr, 811 | _Out_ PIMAGEHLP_MODULE64 ModuleInfo); 812 | typedef BOOL (NTAPI *PF_SymFromName)(_In_ HANDLE hProcess, 813 | _In_ LPSTR Name, 814 | _Out_ PSYMBOL_INFO Symbol); 815 | 816 | typedef struct _DETOUR_SYM_INFO 817 | { 818 | HANDLE hProcess; 819 | HMODULE hDbgHelp; 820 | PF_ImagehlpApiVersionEx pfImagehlpApiVersionEx; 821 | PF_SymInitialize pfSymInitialize; 822 | PF_SymSetOptions pfSymSetOptions; 823 | PF_SymGetOptions pfSymGetOptions; 824 | PF_SymLoadModule64 pfSymLoadModule64; 825 | PF_SymGetModuleInfo64 pfSymGetModuleInfo64; 826 | PF_SymFromName pfSymFromName; 827 | } DETOUR_SYM_INFO, *PDETOUR_SYM_INFO; 828 | 829 | PDETOUR_SYM_INFO DetourLoadImageHlp(VOID); 830 | 831 | #endif // IMAGEAPI 832 | 833 | #if defined(_INC_STDIO) && !defined(_CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS) 834 | #error detours.h must be included before stdio.h (or at least define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS earlier) 835 | #endif 836 | #define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1 837 | 838 | #ifndef DETOUR_TRACE 839 | #if DETOUR_DEBUG 840 | #define DETOUR_TRACE(x) printf x 841 | #define DETOUR_BREAK() __debugbreak() 842 | #include 843 | #include 844 | #else 845 | #define DETOUR_TRACE(x) 846 | #define DETOUR_BREAK() 847 | #endif 848 | #endif 849 | 850 | #if 1 || defined(DETOURS_IA64) 851 | 852 | // 853 | // IA64 instructions are 41 bits, 3 per bundle, plus 5 bit bundle template => 128 bits per bundle. 854 | // 855 | 856 | #define DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE (3) 857 | 858 | #define DETOUR_IA64_TEMPLATE_OFFSET (0) 859 | #define DETOUR_IA64_TEMPLATE_SIZE (5) 860 | 861 | #define DETOUR_IA64_INSTRUCTION_SIZE (41) 862 | #define DETOUR_IA64_INSTRUCTION0_OFFSET (DETOUR_IA64_TEMPLATE_SIZE) 863 | #define DETOUR_IA64_INSTRUCTION1_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE) 864 | #define DETOUR_IA64_INSTRUCTION2_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE + DETOUR_IA64_INSTRUCTION_SIZE) 865 | 866 | C_ASSERT(DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE * DETOUR_IA64_INSTRUCTION_SIZE == 128); 867 | 868 | __declspec(align(16)) struct DETOUR_IA64_BUNDLE 869 | { 870 | public: 871 | union 872 | { 873 | BYTE data[16]; 874 | UINT64 wide[2]; 875 | }; 876 | 877 | enum { 878 | A_UNIT = 1u, 879 | I_UNIT = 2u, 880 | M_UNIT = 3u, 881 | B_UNIT = 4u, 882 | F_UNIT = 5u, 883 | L_UNIT = 6u, 884 | X_UNIT = 7u, 885 | }; 886 | struct DETOUR_IA64_METADATA 887 | { 888 | ULONG nTemplate : 8; // Instruction template. 889 | ULONG nUnit0 : 4; // Unit for slot 0 890 | ULONG nUnit1 : 4; // Unit for slot 1 891 | ULONG nUnit2 : 4; // Unit for slot 2 892 | }; 893 | 894 | protected: 895 | static const DETOUR_IA64_METADATA s_rceCopyTable[33]; 896 | 897 | UINT RelocateBundle(_Inout_ DETOUR_IA64_BUNDLE* pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const; 898 | 899 | bool RelocateInstruction(_Inout_ DETOUR_IA64_BUNDLE* pDst, 900 | _In_ BYTE slot, 901 | _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const; 902 | 903 | // 120 112 104 96 88 80 72 64 56 48 40 32 24 16 8 0 904 | // f. e. d. c. b. a. 9. 8. 7. 6. 5. 4. 3. 2. 1. 0. 905 | 906 | // 00 907 | // f.e. d.c. b.a. 9.8. 7.6. 5.4. 3.2. 1.0. 908 | // 0000 0000 0000 0000 0000 0000 0000 001f : Template [4..0] 909 | // 0000 0000 0000 0000 0000 03ff ffff ffe0 : Zero [ 41.. 5] 910 | // 0000 0000 0000 0000 0000 3c00 0000 0000 : Zero [ 45.. 42] 911 | // 0000 0000 0007 ffff ffff c000 0000 0000 : One [ 82.. 46] 912 | // 0000 0000 0078 0000 0000 0000 0000 0000 : One [ 86.. 83] 913 | // 0fff ffff ff80 0000 0000 0000 0000 0000 : Two [123.. 87] 914 | // f000 0000 0000 0000 0000 0000 0000 0000 : Two [127..124] 915 | BYTE GetTemplate() const; 916 | // Get 4 bit opcodes. 917 | BYTE GetInst0() const; 918 | BYTE GetInst1() const; 919 | BYTE GetInst2() const; 920 | BYTE GetUnit(BYTE slot) const; 921 | BYTE GetUnit0() const; 922 | BYTE GetUnit1() const; 923 | BYTE GetUnit2() const; 924 | // Get 37 bit data. 925 | UINT64 GetData0() const; 926 | UINT64 GetData1() const; 927 | UINT64 GetData2() const; 928 | 929 | // Get/set the full 41 bit instructions. 930 | UINT64 GetInstruction(BYTE slot) const; 931 | UINT64 GetInstruction0() const; 932 | UINT64 GetInstruction1() const; 933 | UINT64 GetInstruction2() const; 934 | void SetInstruction(BYTE slot, UINT64 instruction); 935 | void SetInstruction0(UINT64 instruction); 936 | void SetInstruction1(UINT64 instruction); 937 | void SetInstruction2(UINT64 instruction); 938 | 939 | // Get/set bitfields. 940 | static UINT64 GetBits(UINT64 Value, UINT64 Offset, UINT64 Count); 941 | static UINT64 SetBits(UINT64 Value, UINT64 Offset, UINT64 Count, UINT64 Field); 942 | 943 | // Get specific read-only fields. 944 | static UINT64 GetOpcode(UINT64 instruction); // 4bit opcode 945 | static UINT64 GetX(UINT64 instruction); // 1bit opcode extension 946 | static UINT64 GetX3(UINT64 instruction); // 3bit opcode extension 947 | static UINT64 GetX6(UINT64 instruction); // 6bit opcode extension 948 | 949 | // Get/set specific fields. 950 | static UINT64 GetImm7a(UINT64 instruction); 951 | static UINT64 SetImm7a(UINT64 instruction, UINT64 imm7a); 952 | static UINT64 GetImm13c(UINT64 instruction); 953 | static UINT64 SetImm13c(UINT64 instruction, UINT64 imm13c); 954 | static UINT64 GetSignBit(UINT64 instruction); 955 | static UINT64 SetSignBit(UINT64 instruction, UINT64 signBit); 956 | static UINT64 GetImm20a(UINT64 instruction); 957 | static UINT64 SetImm20a(UINT64 instruction, UINT64 imm20a); 958 | static UINT64 GetImm20b(UINT64 instruction); 959 | static UINT64 SetImm20b(UINT64 instruction, UINT64 imm20b); 960 | 961 | static UINT64 SignExtend(UINT64 Value, UINT64 Offset); 962 | 963 | BOOL IsMovlGp() const; 964 | 965 | VOID SetInst(BYTE Slot, BYTE nInst); 966 | VOID SetInst0(BYTE nInst); 967 | VOID SetInst1(BYTE nInst); 968 | VOID SetInst2(BYTE nInst); 969 | VOID SetData(BYTE Slot, UINT64 nData); 970 | VOID SetData0(UINT64 nData); 971 | VOID SetData1(UINT64 nData); 972 | VOID SetData2(UINT64 nData); 973 | BOOL SetNop(BYTE Slot); 974 | BOOL SetNop0(); 975 | BOOL SetNop1(); 976 | BOOL SetNop2(); 977 | 978 | public: 979 | BOOL IsBrl() const; 980 | VOID SetBrl(); 981 | VOID SetBrl(UINT64 target); 982 | UINT64 GetBrlTarget() const; 983 | VOID SetBrlTarget(UINT64 target); 984 | VOID SetBrlImm(UINT64 imm); 985 | UINT64 GetBrlImm() const; 986 | 987 | UINT64 GetMovlGp() const; 988 | VOID SetMovlGp(UINT64 gp); 989 | 990 | VOID SetStop(); 991 | 992 | UINT Copy(_Out_ DETOUR_IA64_BUNDLE *pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra = NULL) const; 993 | }; 994 | #endif // DETOURS_IA64 995 | 996 | #ifdef DETOURS_ARM 997 | 998 | #define DETOURS_PFUNC_TO_PBYTE(p) ((PBYTE)(((ULONG_PTR)(p)) & ~(ULONG_PTR)1)) 999 | #define DETOURS_PBYTE_TO_PFUNC(p) ((PBYTE)(((ULONG_PTR)(p)) | (ULONG_PTR)1)) 1000 | 1001 | #endif // DETOURS_ARM 1002 | 1003 | ////////////////////////////////////////////////////////////////////////////// 1004 | 1005 | #ifdef __cplusplus 1006 | extern "C" { 1007 | #endif // __cplusplus 1008 | 1009 | #define DETOUR_OFFLINE_LIBRARY(x) \ 1010 | PVOID WINAPI DetourCopyInstruction##x(_In_opt_ PVOID pDst, \ 1011 | _Inout_opt_ PVOID *ppDstPool, \ 1012 | _In_ PVOID pSrc, \ 1013 | _Out_opt_ PVOID *ppTarget, \ 1014 | _Out_opt_ LONG *plExtra); \ 1015 | \ 1016 | BOOL WINAPI DetourSetCodeModule##x(_In_ HMODULE hModule, \ 1017 | _In_ BOOL fLimitReferencesToModule); \ 1018 | 1019 | DETOUR_OFFLINE_LIBRARY(X86) 1020 | DETOUR_OFFLINE_LIBRARY(X64) 1021 | DETOUR_OFFLINE_LIBRARY(ARM) 1022 | DETOUR_OFFLINE_LIBRARY(ARM64) 1023 | DETOUR_OFFLINE_LIBRARY(IA64) 1024 | 1025 | #undef DETOUR_OFFLINE_LIBRARY 1026 | 1027 | ////////////////////////////////////////////////////////////////////////////// 1028 | // 1029 | // Helpers for manipulating page protection. 1030 | // 1031 | 1032 | _Success_(return != FALSE) 1033 | BOOL WINAPI DetourVirtualProtectSameExecuteEx(_In_ HANDLE hProcess, 1034 | _In_ PVOID pAddress, 1035 | _In_ SIZE_T nSize, 1036 | _In_ DWORD dwNewProtect, 1037 | _Out_ PDWORD pdwOldProtect); 1038 | 1039 | _Success_(return != FALSE) 1040 | BOOL WINAPI DetourVirtualProtectSameExecute(_In_ PVOID pAddress, 1041 | _In_ SIZE_T nSize, 1042 | _In_ DWORD dwNewProtect, 1043 | _Out_ PDWORD pdwOldProtect); 1044 | #ifdef __cplusplus 1045 | } 1046 | #endif // __cplusplus 1047 | 1048 | ////////////////////////////////////////////////////////////////////////////// 1049 | 1050 | #define MM_ALLOCATION_GRANULARITY 0x10000 1051 | 1052 | ////////////////////////////////////////////////////////////////////////////// 1053 | 1054 | #endif // DETOURS_INTERNAL 1055 | #endif // __cplusplus 1056 | 1057 | #endif // _DETOURS_H_ 1058 | // 1059 | //////////////////////////////////////////////////////////////// End of File. 1060 | --------------------------------------------------------------------------------