├── src ├── UniversalInjectorFramework │ ├── pch.cpp │ ├── proxies │ │ ├── d3d11.h │ │ ├── d3d8.h │ │ ├── d3d9.h │ │ ├── dxgi.h │ │ ├── winmm.h │ │ ├── version.h │ │ ├── d3dx9_43.h │ │ ├── opengl32.h │ │ ├── d3dcompiler_43.h │ │ ├── d3dcompiler_47.h │ │ ├── d3d8.def │ │ ├── version.def │ │ ├── d3dcompiler_43.def │ │ ├── dxgi.def │ │ ├── d3d9.def │ │ ├── d3d8.cpp │ │ ├── d3dcompiler_47.def │ │ ├── d3d11.def │ │ ├── version.cpp │ │ ├── dxgi.cpp │ │ ├── d3dcompiler_43.cpp │ │ ├── d3d9.cpp │ │ ├── d3dcompiler_47.cpp │ │ ├── winmm.def │ │ └── d3d11.cpp │ ├── libraries.h │ ├── dllmain64.asm │ ├── dllmain32.asm │ ├── features │ │ ├── start_suspended.h │ │ ├── allocate_console.h │ │ ├── tunnel_decoder.h │ │ ├── custom_feature.h │ │ ├── character_substitution.h │ │ ├── locale_emulator.h │ │ ├── start_suspended.cpp │ │ ├── window_manager.h │ │ ├── file_monitor.h │ │ ├── memory_patcher.h │ │ ├── play_timer.h │ │ ├── _feature_base.cpp │ │ ├── font_manager.h │ │ ├── _feature_base.h │ │ ├── custom_feature.cpp │ │ ├── allocate_console.cpp │ │ ├── tunnel_decoder.cpp │ │ ├── memory_patcher.cpp │ │ ├── play_timer.cpp │ │ ├── text_processor.h │ │ ├── character_substitution.cpp │ │ ├── window_manager.cpp │ │ ├── file_monitor.cpp │ │ └── locale_emulator.cpp │ ├── config.h │ ├── pch.h │ ├── function_traits.h │ ├── encoding.h │ ├── hooks.h │ ├── libraries.cpp │ ├── injector.h │ ├── config.cpp │ ├── utils.h │ ├── dllmain.cpp │ ├── ansi.h │ ├── encoding.cpp │ ├── utils.cpp │ ├── injector.cpp │ ├── hooks.cpp │ └── UniversalInjectorFramework.vcxproj.filters ├── Detours │ ├── disolarm.cpp │ ├── disolia64.cpp │ ├── disolx64.cpp │ ├── disolx86.cpp │ ├── disolarm64.cpp │ ├── detver.h │ ├── LICENSE.md │ ├── Detours.vcxproj.filters │ ├── Detours.vcxproj │ └── uimports.cpp ├── ProxyGenerator │ ├── ProxyGenerator.vcxproj.filters │ ├── ProxyGenerator.vcxproj │ └── main.cpp ├── .gitignore └── UniversalInjectorFramework.sln └── .github └── ISSUE_TEMPLATE ├── feature_request.md ├── bug_report.md └── help-request.md /src/UniversalInjectorFramework/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | -------------------------------------------------------------------------------- /src/Detours/disolarm.cpp: -------------------------------------------------------------------------------- 1 | #define DETOURS_ARM_OFFLINE_LIBRARY 2 | #include "disasm.cpp" 3 | -------------------------------------------------------------------------------- /src/Detours/disolia64.cpp: -------------------------------------------------------------------------------- 1 | #define DETOURS_IA64_OFFLINE_LIBRARY 2 | #include "disasm.cpp" 3 | -------------------------------------------------------------------------------- /src/Detours/disolx64.cpp: -------------------------------------------------------------------------------- 1 | #define DETOURS_X64_OFFLINE_LIBRARY 2 | #include "disasm.cpp" 3 | -------------------------------------------------------------------------------- /src/Detours/disolx86.cpp: -------------------------------------------------------------------------------- 1 | #define DETOURS_X86_OFFLINE_LIBRARY 2 | #include "disasm.cpp" 3 | -------------------------------------------------------------------------------- /src/Detours/disolarm64.cpp: -------------------------------------------------------------------------------- 1 | #define DETOURS_ARM64_OFFLINE_LIBRARY 2 | #include "disasm.cpp" 3 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/d3d11.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | bool load_library_d3d11(); 4 | bool unload_library_d3d11(); 5 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/d3d8.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | bool load_library_d3d8(); 4 | bool unload_library_d3d8(); 5 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/d3d9.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | bool load_library_d3d9(); 4 | bool unload_library_d3d9(); 5 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/dxgi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | bool load_library_dxgi(); 4 | bool unload_library_dxgi(); 5 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/winmm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | bool load_library_winmm(); 4 | bool unload_library_winmm(); 5 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/version.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | bool load_library_version(); 4 | bool unload_library_version(); 5 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/libraries.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace uif::libraries 4 | { 5 | void load(); 6 | void unload(); 7 | } 8 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/d3dx9_43.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | bool load_library_d3dx9_43(); 4 | bool unload_library_d3dx9_43(); 5 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/opengl32.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | bool load_library_opengl32(); 4 | bool unload_library_opengl32(); 5 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/d3dcompiler_43.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | bool load_library_d3dcompiler_43(); 4 | bool unload_library_d3dcompiler_43(); 5 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/d3dcompiler_47.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | bool load_library_d3dcompiler_47(); 4 | bool unload_library_d3dcompiler_47(); 5 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/dllmain64.asm: -------------------------------------------------------------------------------- 1 | .CODE 2 | ALIGN 16 3 | EXTERN Attach : PROC 4 | EXTERN EntryPoint : QWORD 5 | 6 | EntryPointHook PROC 7 | call Attach 8 | jmp EntryPoint 9 | EntryPointHook ENDP 10 | 11 | END -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/dllmain32.asm: -------------------------------------------------------------------------------- 1 | .686P 2 | .MODEL FLAT, C 3 | 4 | .CODE 5 | ALIGN 8 6 | EXTERN Attach : PROC 7 | EXTERN EntryPoint : DWORD 8 | 9 | EntryPointHook PROC 10 | call Attach 11 | jmp EntryPoint 12 | EntryPointHook ENDP 13 | 14 | END -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/d3d8.def: -------------------------------------------------------------------------------- 1 | LIBRARY d3d8 2 | EXPORTS 3 | Direct3D8EnableMaximizedWindowedModeShim=lib_d3d8_Direct3D8EnableMaximizedWindowedModeShim @1 4 | ValidatePixelShader=lib_d3d8_ValidatePixelShader @2 5 | ValidateVertexShader=lib_d3d8_ValidateVertexShader @3 6 | DebugSetMute=lib_d3d8_DebugSetMute @4 7 | Direct3DCreate8=lib_d3d8_Direct3DCreate8 @5 8 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/start_suspended.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "_feature_base.h" 3 | 4 | namespace uif::features 5 | { 6 | class start_suspended final : public feature_base 7 | { 8 | public: 9 | explicit start_suspended(uif::injector& injector) : feature_base(injector, "start_suspended") {} 10 | void initialize() override; 11 | void finalize() override; 12 | }; 13 | } -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/allocate_console.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "_feature_base.h" 3 | 4 | namespace uif::features 5 | { 6 | class allocate_console final : public feature_base 7 | { 8 | public: 9 | explicit allocate_console(uif::injector& injector) : feature_base(injector, "allocate_console") {} 10 | void initialize() override; 11 | void finalize() override; 12 | }; 13 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Use case** 11 | Please explain what you are trying to achieve. 12 | 13 | **Feature description** 14 | Please describe what new functionality you would like to see in UIF and how it would help you with the issue above. 15 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/tunnel_decoder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "_feature_base.h" 3 | 4 | namespace uif::features { 5 | 6 | class tunnel_decoder : public feature_base 7 | { 8 | public: 9 | explicit tunnel_decoder(uif::injector& injector) : feature_base(injector, "tunnel_decoder") {} 10 | void initialize() override; 11 | void finalize() override; 12 | 13 | std::wstring mapping{}; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "json.hpp" 4 | 5 | namespace uif 6 | { 7 | class config 8 | { 9 | public: 10 | static bool try_load_json(const std::string& path, nlohmann::json& config); 11 | static bool try_load_bson(const std::string& path, nlohmann::json& config); 12 | 13 | private: 14 | static std::ifstream try_find_file(const std::string& path, std::ios::openmode mode); 15 | }; 16 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Only use this if you believe there is an issue with UIF itself. 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **Expected behavior** 14 | A clear and concise description of what you expected to happen. 15 | 16 | **UIF config** 17 | Please upload your `uif_config.json` 18 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/custom_feature.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "_feature_base.h" 3 | 4 | namespace uif::features 5 | { 6 | class custom_feature final : public feature_base 7 | { 8 | public: 9 | explicit custom_feature(uif::injector& injector) : feature_base(injector, "custom_feature") {} 10 | void initialize() override; 11 | void finalize() override; 12 | 13 | bool overwrite_exit_code = false; 14 | UINT exit_code = 0; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN 4 | #define NOMINMAX 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "../Detours/detours.h" 21 | #include "json.hpp" 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/help-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Help request 3 | about: Use this if you need help using UIF. 4 | title: '' 5 | labels: help 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Description** 11 | Please describe what you are trying to achieve and what you already tried. 12 | 13 | **UIF config** 14 | Please upload your `uif_config.json` 15 | 16 |
17 | Console output 18 |
19 | Paste your console output here.
20 | 
21 |
22 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/character_substitution.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "_feature_base.h" 3 | 4 | namespace uif::features 5 | { 6 | class character_substitution final : public feature_base 7 | { 8 | public: 9 | explicit character_substitution(uif::injector& injector) : feature_base(injector, "character_substitution") {} 10 | void initialize() override; 11 | void finalize() override; 12 | 13 | void substitute(wchar_t* text, int length) const; 14 | void substitute(std::wstring& text) const; 15 | 16 | std::map substitutions; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/locale_emulator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "_feature_base.h" 3 | 4 | struct ML_PROCESS_INFORMATION; 5 | 6 | namespace uif::features 7 | { 8 | class locale_emulator final : public feature_base 9 | { 10 | public: 11 | explicit locale_emulator(uif::injector& injector) : feature_base(injector, "locale_emulator") {} 12 | void initialize() override; 13 | void finalize() override; 14 | 15 | private: 16 | bool wait_for_exit = false; 17 | ULONG codepage = 0; 18 | ULONG locale = 0; 19 | ULONG charset = 0; 20 | std::string timezone{}; 21 | 22 | bool relaunch(ML_PROCESS_INFORMATION* pProcessInfo) const; 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/function_traits.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // function_traits implementation adapted from 4 | // https://devblogs.microsoft.com/oldnewthing/20200713-00/?p=103978 5 | template struct function_traits; 6 | 7 | template 8 | struct function_traits 9 | { 10 | using pointer = TReturn(*)(TArgs...); 11 | using return_type = TReturn; 12 | static constexpr size_t arg_count = sizeof...(TArgs); 13 | }; 14 | 15 | template 16 | struct function_traits 17 | { 18 | using pointer = TReturn(*)(); 19 | using return_type = TReturn; 20 | static constexpr size_t arg_count = 0; 21 | }; 22 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/start_suspended.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "start_suspended.h" 3 | 4 | #include "config.h" 5 | #include "hooks.h" 6 | 7 | void uif::features::start_suspended::initialize() 8 | { 9 | std::cout << "Starting in suspended mode" << std::endl; 10 | 11 | const int waitTime = config().value("wait_time", -1); 12 | if(waitTime > 0) 13 | { 14 | std::cout << "Waiting for " << waitTime << " ms" << std::endl; 15 | Sleep(waitTime); 16 | } 17 | 18 | 19 | if(config().value("wait_for_input", false) == true) 20 | { 21 | std::cout << "Waiting for input. Please press enter." << std::endl; 22 | std::cin.get(); 23 | } 24 | } 25 | 26 | void uif::features::start_suspended::finalize() 27 | { 28 | } -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/window_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "features/_feature_base.h" 6 | 7 | namespace uif::features { 8 | class window_manager : public feature_base 9 | { 10 | public: 11 | window_manager(uif::injector& injector) : feature_base(injector, "window_manager") {} 12 | 13 | void initialize() override; 14 | void finalize() override; 15 | 16 | [[nodiscard]] std::wstring process_title(const std::string& title) const; 17 | void process_title(std::wstring& title) const; 18 | 19 | protected: 20 | void process_title_no_normalize(std::wstring& title) const; 21 | 22 | bool overwrite_title = false; 23 | std::wstring overwrite_title_value{}; 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/encoding.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | constexpr int CP_SHIFTJIS = 932; 6 | 7 | namespace encoding 8 | { 9 | std::wstring to_widechar(const std::string& text, int codepage); 10 | std::string to_multibyte(const std::wstring& text, int codepage); 11 | 12 | std::wstring shiftjis_to_utf16(const std::string& shift_jis); 13 | std::string utf16_to_shiftjis(const std::wstring& utf16); 14 | std::wstring utf8_to_utf16(const std::string& utf8); 15 | std::string utf16_to_utf8(const std::wstring& utf16); 16 | 17 | void print_bytes(const std::string& str); 18 | void print_bytes(const std::wstring& str); 19 | 20 | std::wstring decode_shiftjis_tunnel(const char* text, int count, const std::wstring& mapping); 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/ProxyGenerator/ProxyGenerator.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/file_monitor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "features/_feature_base.h" 5 | 6 | namespace uif::features { 7 | class file_monitor : public feature_base 8 | { 9 | public: 10 | file_monitor(uif::injector& injector) : feature_base(injector, "file_monitor") {} 11 | 12 | void initialize() override; 13 | void finalize() override; 14 | 15 | struct file_action 16 | { 17 | std::wregex path_pattern; 18 | std::wstring redirect_path; 19 | DWORD accessFilter; 20 | bool breakpoint; 21 | bool log; 22 | }; 23 | 24 | file_action* get_action(std::wstring path, DWORD desiredAccess); 25 | 26 | bool log_all = false; 27 | std::vector actions; 28 | 29 | private: 30 | static std::wregex build_path_pattern(const std::wstring& path); 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /src/Detours/detver.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Common version parameters. 4 | // 5 | // Microsoft Research Detours Package, Version 4.0.1 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 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/memory_patcher.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "_feature_base.h" 3 | 4 | namespace uif::features { 5 | 6 | class memory_patcher : public feature_base 7 | { 8 | public: 9 | explicit memory_patcher(uif::injector& injector) : feature_base(injector, "memory_patcher") {} 10 | void initialize() override; 11 | void finalize() override; 12 | 13 | private: 14 | struct patch_entry 15 | { 16 | size_t length; 17 | void* address; 18 | void* patch_value; 19 | void* original_value; 20 | 21 | patch_entry(size_t length, void* address, void* patch_value, void* original_value) 22 | : length(length), 23 | address(address), 24 | patch_value(patch_value), 25 | original_value(original_value) 26 | { 27 | } 28 | }; 29 | 30 | std::vector patches; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/play_timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "_feature_base.h" 3 | 4 | namespace uif::features 5 | { 6 | class play_timer final : public feature_base 7 | { 8 | public: 9 | explicit play_timer(uif::injector& injector) : feature_base(injector, "play_timer") {} 10 | void initialize() override; 11 | void finalize() override; 12 | 13 | private: 14 | long long start_time = -1; 15 | long long end_time = -1; 16 | std::string save_file_path; 17 | 18 | bool auto_save_enable = false; 19 | long long auto_save_interval = -1; 20 | std::thread auto_save_thread; 21 | std::mutex auto_save_mutex; 22 | std::condition_variable auto_save_stop_signal; 23 | 24 | void auto_save_start(); 25 | void auto_save_stop(); 26 | void write_save_file() const; 27 | 28 | static long long epoch_time(); 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/_feature_base.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "_feature_base.h" 3 | 4 | #include "ansi.h" 5 | #include "injector.h" 6 | 7 | using namespace uif::ansi; 8 | 9 | uif::features::feature_base::feature_base(uif::injector& injector, std::string name) : 10 | _injector(injector), 11 | _config(_injector.config()[name]), 12 | _name(std::move(name)) 13 | { 14 | } 15 | 16 | bool uif::features::feature_base::try_init() 17 | { 18 | _enabled = pre_init(); 19 | if(_enabled) initialize(); 20 | return _enabled; 21 | } 22 | 23 | bool uif::features::feature_base::pre_init() 24 | { 25 | if (config().is_boolean()) return config().get(); 26 | if (!config().is_object()) return false; 27 | _debug = config().value("debug", false); 28 | return config().value("enable", false); 29 | } 30 | 31 | std::ostream& uif::features::operator<<(std::ostream& os, const feature_base& feature) 32 | { 33 | return os << white("[") << white(feature.name()) << white("]"); 34 | } 35 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/font_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "_feature_base.h" 3 | 4 | #include 5 | 6 | namespace uif::features 7 | { 8 | struct enum_fonts_settings 9 | { 10 | BYTE filterPitchAndFamilyValue; 11 | BYTE filterCharSetValue; 12 | BYTE spoofCharSetValue; 13 | 14 | bool filterPitchAndFamily; 15 | bool filterCharSet; 16 | bool spoofCharSet; 17 | }; 18 | 19 | struct create_font_settings 20 | { 21 | std::string overrideFaceValueA; 22 | std::wstring overrideFaceValueW; 23 | BYTE overrideCharSetValue; 24 | 25 | bool overrideFace; 26 | bool overrideCharSet; 27 | }; 28 | 29 | class font_manager : public feature_base 30 | { 31 | public: 32 | font_manager(uif::injector& injector) : feature_base(injector, "font_manager") { } 33 | void initialize() override; 34 | void finalize() override; 35 | 36 | bool spoof_enumeration = false; 37 | bool spoof_creation = false; 38 | 39 | enum_fonts_settings enum_fonts_settings{}; 40 | create_font_settings create_font_settings{}; 41 | }; 42 | } -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/version.def: -------------------------------------------------------------------------------- 1 | LIBRARY version 2 | EXPORTS 3 | GetFileVersionInfoA=lib_version_GetFileVersionInfoA @1 4 | GetFileVersionInfoByHandle=lib_version_GetFileVersionInfoByHandle @2 5 | GetFileVersionInfoExA=lib_version_GetFileVersionInfoExA @3 6 | GetFileVersionInfoExW=lib_version_GetFileVersionInfoExW @4 7 | GetFileVersionInfoSizeA=lib_version_GetFileVersionInfoSizeA @5 8 | GetFileVersionInfoSizeExA=lib_version_GetFileVersionInfoSizeExA @6 9 | GetFileVersionInfoSizeExW=lib_version_GetFileVersionInfoSizeExW @7 10 | GetFileVersionInfoSizeW=lib_version_GetFileVersionInfoSizeW @8 11 | GetFileVersionInfoW=lib_version_GetFileVersionInfoW @9 12 | VerFindFileA=lib_version_VerFindFileA @10 13 | VerFindFileW=lib_version_VerFindFileW @11 14 | VerInstallFileA=lib_version_VerInstallFileA @12 15 | VerInstallFileW=lib_version_VerInstallFileW @13 16 | VerLanguageNameA=lib_version_VerLanguageNameA @14 17 | VerLanguageNameW=lib_version_VerLanguageNameW @15 18 | VerQueryValueA=lib_version_VerQueryValueA @16 19 | VerQueryValueW=lib_version_VerQueryValueW @17 20 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/d3dcompiler_43.def: -------------------------------------------------------------------------------- 1 | LIBRARY d3dcompiler_43 2 | EXPORTS 3 | D3DAssemble=lib_d3dcompiler_43_D3DAssemble @1 4 | DebugSetMute=lib_d3dcompiler_43_DebugSetMute @2 5 | D3DCompile=lib_d3dcompiler_43_D3DCompile @3 6 | D3DCompressShaders=lib_d3dcompiler_43_D3DCompressShaders @4 7 | D3DCreateBlob=lib_d3dcompiler_43_D3DCreateBlob @5 8 | D3DDecompressShaders=lib_d3dcompiler_43_D3DDecompressShaders @6 9 | D3DDisassemble10Effect=lib_d3dcompiler_43_D3DDisassemble10Effect @7 10 | D3DDisassemble=lib_d3dcompiler_43_D3DDisassemble @8 11 | D3DGetBlobPart=lib_d3dcompiler_43_D3DGetBlobPart @9 12 | D3DGetDebugInfo=lib_d3dcompiler_43_D3DGetDebugInfo @10 13 | D3DGetInputAndOutputSignatureBlob=lib_d3dcompiler_43_D3DGetInputAndOutputSignatureBlob @11 14 | D3DGetInputSignatureBlob=lib_d3dcompiler_43_D3DGetInputSignatureBlob @12 15 | D3DGetOutputSignatureBlob=lib_d3dcompiler_43_D3DGetOutputSignatureBlob @13 16 | D3DPreprocess=lib_d3dcompiler_43_D3DPreprocess @14 17 | D3DReflect=lib_d3dcompiler_43_D3DReflect @15 18 | D3DReturnFailure1=lib_d3dcompiler_43_D3DReturnFailure1 @16 19 | D3DStripShader=lib_d3dcompiler_43_D3DStripShader @17 20 | -------------------------------------------------------------------------------- /src/Detours/LICENSE.md: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation 2 | 3 | All rights reserved. 4 | 5 | # MIT License 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | this software and associated documentation files (the "Software"), to deal in 9 | the Software without restriction, including without limitation the rights to 10 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11 | of the Software, and to permit persons to whom the Software is furnished to do 12 | so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/dxgi.def: -------------------------------------------------------------------------------- 1 | LIBRARY dxgi 2 | EXPORTS 3 | ApplyCompatResolutionQuirking=lib_dxgi_ApplyCompatResolutionQuirking @1 4 | CompatString=lib_dxgi_CompatString @2 5 | CompatValue=lib_dxgi_CompatValue @3 6 | DXGIDumpJournal=lib_dxgi_DXGIDumpJournal @4 7 | PIXBeginCapture=lib_dxgi_PIXBeginCapture @5 8 | PIXEndCapture=lib_dxgi_PIXEndCapture @6 9 | PIXGetCaptureState=lib_dxgi_PIXGetCaptureState @7 10 | SetAppCompatStringPointer=lib_dxgi_SetAppCompatStringPointer @8 11 | UpdateHMDEmulationStatus=lib_dxgi_UpdateHMDEmulationStatus @9 12 | CreateDXGIFactory1=lib_dxgi_CreateDXGIFactory1 @10 13 | CreateDXGIFactory2=lib_dxgi_CreateDXGIFactory2 @11 14 | CreateDXGIFactory=lib_dxgi_CreateDXGIFactory @12 15 | DXGID3D10CreateDevice=lib_dxgi_DXGID3D10CreateDevice @13 16 | DXGID3D10CreateLayeredDevice=lib_dxgi_DXGID3D10CreateLayeredDevice @14 17 | DXGID3D10GetLayeredDeviceSize=lib_dxgi_DXGID3D10GetLayeredDeviceSize @15 18 | DXGID3D10RegisterLayers=lib_dxgi_DXGID3D10RegisterLayers @16 19 | DXGIDeclareAdapterRemovalSupport=lib_dxgi_DXGIDeclareAdapterRemovalSupport @17 20 | DXGIGetDebugInterface1=lib_dxgi_DXGIGetDebugInterface1 @18 21 | DXGIReportAdapterConfiguration=lib_dxgi_DXGIReportAdapterConfiguration @19 22 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/d3d9.def: -------------------------------------------------------------------------------- 1 | LIBRARY d3d9 2 | EXPORTS 3 | Ordinal16=lib_d3d9_Ordinal16 @16 NONAME 4 | Ordinal17=lib_d3d9_Ordinal17 @17 NONAME 5 | Ordinal18=lib_d3d9_Ordinal18 @18 NONAME 6 | Ordinal19=lib_d3d9_Ordinal19 @19 NONAME 7 | Direct3DCreate9On12=lib_d3d9_Direct3DCreate9On12 @20 8 | Direct3DCreate9On12Ex=lib_d3d9_Direct3DCreate9On12Ex @21 9 | Ordinal22=lib_d3d9_Ordinal22 @22 NONAME 10 | Ordinal23=lib_d3d9_Ordinal23 @23 NONAME 11 | Direct3DShaderValidatorCreate9=lib_d3d9_Direct3DShaderValidatorCreate9 @24 12 | PSGPError=lib_d3d9_PSGPError @25 13 | PSGPSampleTexture=lib_d3d9_PSGPSampleTexture @26 14 | D3DPERF_BeginEvent=lib_d3d9_D3DPERF_BeginEvent @27 15 | D3DPERF_EndEvent=lib_d3d9_D3DPERF_EndEvent @28 16 | D3DPERF_GetStatus=lib_d3d9_D3DPERF_GetStatus @29 17 | D3DPERF_QueryRepeatFrame=lib_d3d9_D3DPERF_QueryRepeatFrame @30 18 | D3DPERF_SetMarker=lib_d3d9_D3DPERF_SetMarker @31 19 | D3DPERF_SetOptions=lib_d3d9_D3DPERF_SetOptions @32 20 | D3DPERF_SetRegion=lib_d3d9_D3DPERF_SetRegion @33 21 | DebugSetLevel=lib_d3d9_DebugSetLevel @34 22 | DebugSetMute=lib_d3d9_DebugSetMute @35 23 | Direct3D9EnableMaximizedWindowedModeShim=lib_d3d9_Direct3D9EnableMaximizedWindowedModeShim @36 24 | Direct3DCreate9=lib_d3d9_Direct3DCreate9 @37 25 | Direct3DCreate9Ex=lib_d3d9_Direct3DCreate9Ex @38 26 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/_feature_base.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace uif 4 | { 5 | class injector; 6 | class config; 7 | } 8 | 9 | namespace uif::features 10 | { 11 | class feature_base 12 | { 13 | public: 14 | explicit feature_base(injector& injector, std::string name); 15 | explicit feature_base(feature_base&) = delete; 16 | explicit feature_base(feature_base&&) = delete; 17 | virtual ~feature_base() = default; 18 | 19 | feature_base& operator=(const feature_base&) = delete; 20 | feature_base& operator=(const feature_base&&) = delete; 21 | 22 | bool try_init(); 23 | 24 | virtual bool pre_init(); 25 | virtual void initialize() = 0; 26 | virtual void finalize() = 0; 27 | 28 | [[nodiscard]] injector& injector() const { return _injector; } 29 | [[nodiscard]] nlohmann::json& config() const { return _config; } 30 | [[nodiscard]] const std::string& name() const { return _name; } 31 | [[nodiscard]] bool is_enabled() const { return _enabled; } 32 | [[nodiscard]] bool is_debugging_enabled() const { return _debug; } 33 | 34 | private: 35 | uif::injector& _injector; 36 | nlohmann::json& _config; 37 | const std::string _name; 38 | 39 | protected: 40 | bool _enabled = false; 41 | bool _debug = false; 42 | }; 43 | 44 | extern std::ostream& operator<<(std::ostream& os, const feature_base& feature); 45 | } 46 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/hooks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "features/_feature_base.h" 3 | 4 | #include 5 | 6 | namespace uif::hooks { 7 | bool hook_import(const features::feature_base* feature, const char* importName, void* hookFunction); 8 | bool unhook_import(const features::feature_base* feature, const char* importName, void* hookFunction); 9 | 10 | bool hook_function(const features::feature_base* feature, void*& targetFunction, void* hookFunction, const std::string& functionName = ""); 11 | bool unhook_function(const features::feature_base* feature, void*& targetFunction, void* hookFunction, const std::string& functionName = ""); 12 | 13 | template 14 | bool hook_function(const features::feature_base* feature, TTarget& targetFunction, TDetour hookFunction, const std::string& functionName = "") 15 | { 16 | return hook_function(feature, *reinterpret_cast(&targetFunction), *reinterpret_cast(&hookFunction), functionName); 17 | } 18 | 19 | template 20 | bool unhook_function(const features::feature_base* feature, TTarget& targetFunction, TDetour hookFunction, const std::string& functionName = "") 21 | { 22 | return unhook_function(feature, *reinterpret_cast(&targetFunction), *reinterpret_cast(&hookFunction), functionName); 23 | } 24 | } -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/d3d8.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #ifdef UIF_LIB_D3D8 4 | 5 | #include "injector.h" 6 | 7 | struct { 8 | HMODULE dll; 9 | FARPROC Direct3D8EnableMaximizedWindowedModeShim; 10 | FARPROC ValidatePixelShader; 11 | FARPROC ValidateVertexShader; 12 | FARPROC DebugSetMute; 13 | FARPROC Direct3DCreate8; 14 | } d3d8; 15 | 16 | void lib_d3d8_Direct3D8EnableMaximizedWindowedModeShim() { d3d8.Direct3D8EnableMaximizedWindowedModeShim(); } 17 | void lib_d3d8_ValidatePixelShader() { d3d8.ValidatePixelShader(); } 18 | void lib_d3d8_ValidateVertexShader() { d3d8.ValidateVertexShader(); } 19 | void lib_d3d8_DebugSetMute() { d3d8.DebugSetMute(); } 20 | void lib_d3d8_Direct3DCreate8() { d3d8.Direct3DCreate8(); } 21 | 22 | bool load_library_d3d8() { 23 | d3d8.dll = uif::injector::instance().load_real_library("d3d8.dll"); 24 | d3d8.Direct3D8EnableMaximizedWindowedModeShim = GetProcAddress(d3d8.dll, "Direct3D8EnableMaximizedWindowedModeShim"); 25 | d3d8.ValidatePixelShader = GetProcAddress(d3d8.dll, "ValidatePixelShader"); 26 | d3d8.ValidateVertexShader = GetProcAddress(d3d8.dll, "ValidateVertexShader"); 27 | d3d8.DebugSetMute = GetProcAddress(d3d8.dll, "DebugSetMute"); 28 | d3d8.Direct3DCreate8 = GetProcAddress(d3d8.dll, "Direct3DCreate8"); 29 | return true; 30 | } 31 | 32 | bool unload_library_d3d8() { 33 | FreeLibrary(d3d8.dll); 34 | d3d8.dll = nullptr; 35 | return true; 36 | } 37 | 38 | #else 39 | 40 | bool load_library_d3d8() { 41 | return false; 42 | } 43 | 44 | bool unload_library_d3d8() { 45 | return false; 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/libraries.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "proxies/d3d8.h" 4 | #include "proxies/d3d9.h" 5 | #include "proxies/d3d11.h" 6 | #include "proxies/d3dcompiler_43.h" 7 | #include "proxies/d3dcompiler_47.h" 8 | #include "proxies/d3dx9_43.h" 9 | #include "proxies/dxgi.h" 10 | #include "proxies/opengl32.h" 11 | #include "proxies/version.h" 12 | #include "proxies/winmm.h" 13 | 14 | namespace uif::libraries 15 | { 16 | void load() 17 | { 18 | int loaded = false; 19 | 20 | loaded += load_library_d3d8(); 21 | loaded += load_library_d3d9(); 22 | loaded += load_library_d3d11(); 23 | loaded += load_library_d3dcompiler_43(); 24 | loaded += load_library_d3dcompiler_47(); 25 | loaded += load_library_d3dx9_43(); 26 | loaded += load_library_dxgi(); 27 | loaded += load_library_opengl32(); 28 | loaded += load_library_version(); 29 | loaded += load_library_winmm(); 30 | 31 | if (!loaded) 32 | { 33 | std::cout << "No library loaded" << std::endl; 34 | } 35 | } 36 | 37 | void unload() 38 | { 39 | int loaded = false; 40 | 41 | loaded += unload_library_d3d8(); 42 | loaded += unload_library_d3d9(); 43 | loaded += unload_library_d3d11(); 44 | loaded += unload_library_d3dcompiler_43(); 45 | loaded += unload_library_d3dcompiler_47(); 46 | loaded += unload_library_d3dx9_43(); 47 | loaded += unload_library_dxgi(); 48 | loaded += unload_library_opengl32(); 49 | loaded += unload_library_version(); 50 | loaded += unload_library_winmm(); 51 | 52 | if (!loaded) 53 | { 54 | std::cout << "No library unloaded" << std::endl; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/injector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "config.h" 3 | #include "features/_feature_base.h" 4 | 5 | namespace uif 6 | { 7 | class injector 8 | { 9 | public: 10 | static injector& instance(); 11 | injector(); 12 | nlohmann::json& config(); 13 | void attach(); 14 | void detach(); 15 | template T& feature() const; 16 | template T* try_get_feature() const; 17 | 18 | HMODULE load_real_library(const std::string& dllName); 19 | 20 | HMODULE game_module; 21 | std::vector additional_modules{}; 22 | 23 | template 24 | void initialize_feature() 25 | { 26 | features::feature_base* feature = new T(*this); 27 | if(feature->try_init()) 28 | { 29 | features.push_back(feature); 30 | } 31 | else 32 | { 33 | delete feature; 34 | } 35 | } 36 | 37 | private: 38 | nlohmann::json _config; 39 | std::vector features; 40 | bool enabled = false; 41 | bool attached = false; 42 | }; 43 | 44 | template 45 | T& injector::feature() const 46 | { 47 | for (auto* feature : features) 48 | { 49 | T* casted = dynamic_cast(feature); 50 | if (casted != nullptr) 51 | { 52 | T& reference = *casted; 53 | return reference; 54 | } 55 | } 56 | 57 | throw std::runtime_error(std::string("no matching feature found for type ") + typeid(T).name()); 58 | } 59 | 60 | template 61 | T* injector::try_get_feature() const 62 | { 63 | for (auto* feature : features) 64 | { 65 | T* casted = dynamic_cast(feature); 66 | if (casted != nullptr) 67 | { 68 | return casted; 69 | } 70 | } 71 | return nullptr; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/custom_feature.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "custom_feature.h" 3 | 4 | #include "ansi.h" 5 | #include "config.h" 6 | #include "encoding.h" 7 | #include "hooks.h" 8 | #include "injector.h" 9 | #include "utils.h" 10 | 11 | #pragma region Hooks 12 | 13 | static void WINAPI ExitProcessHook(UINT uExitCode) 14 | { 15 | // Get the feature implementation 16 | const auto& feature = uif::injector::instance().feature(); 17 | 18 | if (feature.overwrite_exit_code) 19 | uExitCode = feature.exit_code; 20 | 21 | // Call the real ExitProcess function 22 | ExitProcess(uExitCode); 23 | } 24 | 25 | #pragma endregion 26 | 27 | void uif::features::custom_feature::initialize() 28 | { 29 | // By default, this function is only executed if the 30 | // key "/custom_feature/enable" is set to true in the 31 | // config file. You can change this behavior by over- 32 | // writing the pre_init function in feature_base. 33 | 34 | // Use this function to read the configuration, set up 35 | // your feature and install necessary hooks. You can 36 | // access the "/custom_feature" config object with the 37 | // config() function. 38 | 39 | // This example implementation reads an integer value 40 | // from the config key "/custom_feature/exit_code" and 41 | // uses it when the ExitProcess function is called, 42 | // overwriting the actual exit code in the process. 43 | 44 | if(config().contains("exit_code")) 45 | { 46 | overwrite_exit_code = true; 47 | exit_code = config()["exit_code"].get(); 48 | } 49 | 50 | hooks::hook_import(this, "ExitProcess", ExitProcessHook); 51 | } 52 | 53 | void uif::features::custom_feature::finalize() 54 | { 55 | // Uninstall all of your hooks in here 56 | 57 | hooks::unhook_import(this, "ExitProcess", ExitProcessHook); 58 | } 59 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/allocate_console.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "allocate_console.h" 3 | 4 | #include "ansi.h" 5 | #include "config.h" 6 | #include "hooks.h" 7 | #include "injector.h" 8 | #include "utils.h" 9 | 10 | using namespace uif::ansi; 11 | 12 | static void alloc_console() 13 | { 14 | if(GetConsoleWindow()) return; 15 | 16 | // try to reuse the existing console 17 | if(!AttachConsole(ATTACH_PARENT_PROCESS)) 18 | { 19 | if(!AllocConsole()) 20 | { 21 | uif::utils::fail(std::string("Failed to allocate console: ") + std::to_string(GetLastError())); 22 | } 23 | } 24 | 25 | SetConsoleOutputCP(65001); 26 | 27 | FILE* _; 28 | freopen_s(&_, "CONOUT$", "w", stdout); 29 | freopen_s(&_, "CONOUT$", "w", stderr); 30 | freopen_s(&_, "CONIN$", "r", stdin); 31 | 32 | std::cout.clear(); 33 | std::clog.clear(); 34 | std::cerr.clear(); 35 | std::cin.clear(); 36 | } 37 | 38 | static void focus_console() 39 | { 40 | auto* const window = GetConsoleWindow(); 41 | if(window == nullptr) return; 42 | SetForegroundWindow(window); 43 | } 44 | 45 | static bool enable_vt_mode() 46 | { 47 | const auto hOut = GetStdHandle(STD_OUTPUT_HANDLE); 48 | if(hOut == INVALID_HANDLE_VALUE) 49 | return false; 50 | 51 | DWORD dwMode = 0; 52 | if(!GetConsoleMode(hOut, &dwMode)) 53 | return false; 54 | 55 | dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; 56 | return SetConsoleMode(hOut, dwMode); 57 | } 58 | 59 | void uif::features::allocate_console::initialize() 60 | { 61 | alloc_console(); 62 | enable_vt_mode(); 63 | setlocale(LC_ALL, "en_US.UTF-8"); // NOLINT(concurrency-mt-unsafe) 64 | 65 | std::cout << cyan("Universal Injector Framework") << ", created by " << yellow("AtomCrafty") << ", 2021\n"; 66 | std::cout << "Loaded configuration:\n" << std::setw(4) << injector().config() << std::endl; 67 | } 68 | 69 | void uif::features::allocate_console::finalize() 70 | { 71 | } -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/d3dcompiler_47.def: -------------------------------------------------------------------------------- 1 | LIBRARY d3dcompiler_47 2 | EXPORTS 3 | D3DAssemble=lib_d3dcompiler_47_D3DAssemble @1 4 | DebugSetMute=lib_d3dcompiler_47_DebugSetMute @2 5 | D3DCompile2=lib_d3dcompiler_47_D3DCompile2 @3 6 | D3DCompile=lib_d3dcompiler_47_D3DCompile @4 7 | D3DCompileFromFile=lib_d3dcompiler_47_D3DCompileFromFile @5 8 | D3DCompressShaders=lib_d3dcompiler_47_D3DCompressShaders @6 9 | D3DCreateBlob=lib_d3dcompiler_47_D3DCreateBlob @7 10 | D3DCreateFunctionLinkingGraph=lib_d3dcompiler_47_D3DCreateFunctionLinkingGraph @8 11 | D3DCreateLinker=lib_d3dcompiler_47_D3DCreateLinker @9 12 | D3DDecompressShaders=lib_d3dcompiler_47_D3DDecompressShaders @10 13 | D3DDisassemble10Effect=lib_d3dcompiler_47_D3DDisassemble10Effect @11 14 | D3DDisassemble11Trace=lib_d3dcompiler_47_D3DDisassemble11Trace @12 15 | D3DDisassemble=lib_d3dcompiler_47_D3DDisassemble @13 16 | D3DDisassembleRegion=lib_d3dcompiler_47_D3DDisassembleRegion @14 17 | D3DGetBlobPart=lib_d3dcompiler_47_D3DGetBlobPart @15 18 | D3DGetDebugInfo=lib_d3dcompiler_47_D3DGetDebugInfo @16 19 | D3DGetInputAndOutputSignatureBlob=lib_d3dcompiler_47_D3DGetInputAndOutputSignatureBlob @17 20 | D3DGetInputSignatureBlob=lib_d3dcompiler_47_D3DGetInputSignatureBlob @18 21 | D3DGetOutputSignatureBlob=lib_d3dcompiler_47_D3DGetOutputSignatureBlob @19 22 | D3DGetTraceInstructionOffsets=lib_d3dcompiler_47_D3DGetTraceInstructionOffsets @20 23 | D3DLoadModule=lib_d3dcompiler_47_D3DLoadModule @21 24 | D3DPreprocess=lib_d3dcompiler_47_D3DPreprocess @22 25 | D3DReadFileToBlob=lib_d3dcompiler_47_D3DReadFileToBlob @23 26 | D3DReflect=lib_d3dcompiler_47_D3DReflect @24 27 | D3DReflectLibrary=lib_d3dcompiler_47_D3DReflectLibrary @25 28 | D3DReturnFailure1=lib_d3dcompiler_47_D3DReturnFailure1 @26 29 | D3DSetBlobPart=lib_d3dcompiler_47_D3DSetBlobPart @27 30 | D3DStripShader=lib_d3dcompiler_47_D3DStripShader @28 31 | D3DWriteBlobToFile=lib_d3dcompiler_47_D3DWriteBlobToFile @29 32 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/config.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "config.h" 3 | 4 | #include 5 | 6 | #include "utils.h" 7 | 8 | namespace uif 9 | { 10 | bool config::try_load_json(const std::string& path, nlohmann::json& config) 11 | { 12 | try 13 | { 14 | std::ifstream ifs = try_find_file(path, std::ios::in); 15 | if (!ifs.is_open()) 16 | return false; 17 | 18 | ifs >> config; 19 | return true; 20 | } 21 | catch (nlohmann::json::parse_error& error) 22 | { 23 | utils::fail(std::string("Failed to parse config file.\n\n") + error.what()); 24 | } 25 | } 26 | 27 | bool config::try_load_bson(const std::string& path, nlohmann::json& config) 28 | { 29 | try 30 | { 31 | std::ifstream ifs = try_find_file(path, std::ios::in | std::ios::binary); 32 | 33 | if (!ifs.is_open()) 34 | return false; 35 | 36 | ifs.seekg(0, std::ios::end); 37 | std::streampos size = ifs.tellg(); 38 | ifs.seekg(0, std::ios::beg); 39 | 40 | std::vector bytes{}; 41 | bytes.reserve(size); 42 | 43 | ifs.unsetf(std::ios::skipws); 44 | bytes.insert(bytes.begin(), std::istream_iterator(ifs), std::istream_iterator()); 45 | 46 | for (uint8_t& byte : bytes) 47 | { 48 | byte ^= 0xff; 49 | } 50 | 51 | config = nlohmann::json::from_bson(bytes); 52 | return true; 53 | } 54 | catch (nlohmann::json::parse_error& error) 55 | { 56 | utils::fail(std::string("Failed to parse config file.\n\n") + error.what()); 57 | } 58 | } 59 | 60 | std::ifstream config::try_find_file(const std::string& path, std::ios::openmode mode) 61 | { 62 | std::filesystem::path dir = utils::get_dll_path().parent_path(); 63 | 64 | std::ifstream ifs; 65 | while (true) 66 | { 67 | ifs.open(dir / path, mode); 68 | if (ifs.is_open()) { 69 | return ifs; 70 | } 71 | 72 | std::filesystem::path parent = dir.parent_path(); 73 | 74 | if (parent.empty() || parent == dir) 75 | { 76 | return ifs; 77 | } 78 | 79 | dir = parent; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Detours/Detours.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;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 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifndef DEBUG_LOG 6 | #define DEBUG_LOG 1 7 | #endif 8 | 9 | #ifndef DEBUG_NOTIFY 10 | #define DEBUG_NOTIFY 1 11 | #endif 12 | 13 | namespace uif::utils { 14 | bool file_exists(const wchar_t* path); 15 | bool file_create_new(const wchar_t* path, const char* content, size_t length); 16 | std::filesystem::path get_dll_path(); 17 | std::string get_module_name(HMODULE hModule); 18 | std::string get_last_error_message(DWORD error = 0); 19 | void normalize(std::wstring& text); 20 | std::wstring normalize(const std::string& text); 21 | WORD set_console_color(WORD color); 22 | void print_colored(const char* text, WORD color); 23 | void patch_memory(void* address, const void* data, size_t size, void* oldDataBuffer); 24 | void patch_address(void** patchAddress, void* patchValue); 25 | void* parse_address(const nlohmann::json& json); 26 | void* parse_address(const std::string& string); 27 | [[noreturn]] void fail(const std::string& reason); 28 | 29 | inline void debug_notify(const char* caption, const char* message, UINT type = MB_OK | MB_ICONINFORMATION) 30 | { 31 | #if DEBUG_NOTIFY 32 | MessageBoxA(nullptr, message, caption, type); 33 | #endif 34 | } 35 | 36 | static void debug_log_write(HANDLE file, const char* text) 37 | { 38 | const DWORD length = strlen(text); 39 | DWORD written = 0; 40 | const auto success = WriteFile(file, text, length, &written, nullptr); 41 | 42 | if (!success || written != length) 43 | fail("Failed to write to log file"); 44 | } 45 | 46 | inline void debug_log(const char* message, bool terminate = true) 47 | { 48 | #if DEBUG_LOG 49 | const auto file = CreateFileA("uif_log.log", FILE_APPEND_DATA, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); 50 | if (file == INVALID_HANDLE_VALUE) 51 | fail("Failed to open log file"); 52 | 53 | debug_log_write(file, message); 54 | if (terminate) debug_log_write(file, "\n"); 55 | 56 | CloseHandle(file); 57 | #endif 58 | } 59 | 60 | inline void debug_log_clear() 61 | { 62 | #if DEBUG_LOG 63 | DeleteFileA("uif_log.log"); 64 | #endif 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "injector.h" 4 | #include "utils.h" 5 | 6 | extern "C" { 7 | void* EntryPoint; 8 | void EntryPointHook(); 9 | bool IsHooked = false; 10 | void Detach() { uif::injector::instance().detach(); } 11 | void Attach() 12 | { 13 | uif::utils::debug_log("Attach: run"); 14 | if (IsHooked) 15 | { 16 | uif::utils::debug_log("Attach: unhook"); 17 | DetourTransactionBegin(); 18 | DetourDetach(&EntryPoint, EntryPointHook); 19 | DetourTransactionCommit(); 20 | } 21 | uif::injector::instance().attach(); 22 | } 23 | } 24 | 25 | void InstallDelayedAttachHook() 26 | { 27 | uif::utils::debug_log("InstallDelayedAttachHook: start"); 28 | 29 | if(uif::injector::instance().config().value("/injector/inject_directly"_json_pointer, false)) 30 | { 31 | uif::utils::debug_log("InstallDelayedAttachHook: direct attach"); 32 | Attach(); 33 | return; 34 | } 35 | 36 | const auto targetModuleName = uif::injector::instance().config().value("/injector/target_module"_json_pointer, ""); 37 | if (targetModuleName.empty()) 38 | { 39 | EntryPoint = DetourGetEntryPoint(nullptr); 40 | uif::utils::debug_log("InstallDelayedAttachHook: no target module specified"); 41 | } 42 | else 43 | { 44 | const auto handle = GetModuleHandleA(targetModuleName.c_str()); 45 | uif::utils::debug_log("InstallDelayedAttachHook: target module is ", false); 46 | uif::utils::debug_log(targetModuleName.c_str()); 47 | if (!handle) uif::utils::fail("Target module is not loaded"); 48 | EntryPoint = DetourGetEntryPoint(handle); 49 | } 50 | 51 | if (*static_cast(EntryPoint) == 0xCC) 52 | { 53 | Attach(); 54 | return; 55 | } 56 | 57 | uif::utils::debug_log("InstallDelayedAttachHook: transaction"); 58 | IsHooked = true; 59 | DetourTransactionBegin(); 60 | DetourAttach(&EntryPoint, EntryPointHook); 61 | DetourTransactionCommit(); 62 | uif::utils::debug_log("InstallDelayedAttachHook: end"); 63 | } 64 | 65 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 66 | { 67 | switch (ul_reason_for_call) 68 | { 69 | case DLL_PROCESS_ATTACH: 70 | DisableThreadLibraryCalls(hModule); 71 | uif::utils::debug_log_clear(); 72 | uif::utils::debug_log("DllMain: attach"); 73 | InstallDelayedAttachHook(); 74 | break; 75 | 76 | case DLL_PROCESS_DETACH: 77 | uif::utils::debug_log("DllMain: detach"); 78 | Detach(); 79 | break; 80 | 81 | default: 82 | uif::utils::debug_log("DllMain: default"); 83 | break; 84 | } 85 | return TRUE; 86 | } 87 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/tunnel_decoder.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "tunnel_decoder.h" 3 | 4 | #include "ansi.h" 5 | #include "config.h" 6 | #include "encoding.h" 7 | #include "hooks.h" 8 | #include "injector.h" 9 | 10 | using namespace uif::ansi; 11 | 12 | BOOL __stdcall TextOutAHook(HDC hdc, int x, int y, LPCSTR lpString, int c) 13 | { 14 | const auto& decoder = uif::injector::instance().feature(); 15 | const auto& decoded = encoding::decode_shiftjis_tunnel(lpString, c, decoder.mapping); 16 | 17 | return TextOutW(hdc, x, y, decoded.c_str(), static_cast(decoded.length())); 18 | } 19 | 20 | int __stdcall MultiByteToWideCharHook(UINT CodePage, DWORD dwFlags, LPCCH lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar) 21 | { 22 | const auto& decoder = uif::injector::instance().feature(); 23 | const auto& decoded = encoding::decode_shiftjis_tunnel(lpMultiByteStr, cbMultiByte, decoder.mapping); 24 | 25 | const int decodedCount = static_cast(cbMultiByte < 0 ? decoded.length() + 1 : decoded.length()); 26 | if (decodedCount > cchWideChar) 27 | return 0; 28 | 29 | wcscpy_s(lpWideCharStr, cchWideChar, decoded.c_str()); 30 | return decodedCount; 31 | } 32 | 33 | int __stdcall GetTextExtentPoint32AHook(HDC hdc, LPCSTR lpString, int c, LPSIZE psizl) 34 | { 35 | const auto& decoder = uif::injector::instance().feature(); 36 | const auto& decoded = encoding::decode_shiftjis_tunnel(lpString, c, decoder.mapping); 37 | 38 | return GetTextExtentPoint32W(hdc, decoded.c_str(), static_cast(decoded.size()), psizl); 39 | } 40 | 41 | int __stdcall IsDBCSLeadByteExHook(UINT CodePage, BYTE TestChar) 42 | { 43 | return IsDBCSLeadByteEx(932, TestChar); 44 | } 45 | 46 | int __stdcall IsDBCSLeadByteHook(BYTE TestChar) 47 | { 48 | return IsDBCSLeadByteEx(932, TestChar); 49 | } 50 | 51 | void uif::features::tunnel_decoder::initialize() 52 | { 53 | if (!config()["mapping"].is_string()) 54 | { 55 | std::cout << *this << dark_red(" Error:") << " no mapping specified, disabling tunnel decoder\n"; 56 | _enabled = false; 57 | return; 58 | } 59 | 60 | mapping = encoding::utf8_to_utf16(config()["mapping"].get()); 61 | std::cout << *this << " Loaded " << mapping.length() << " mapping characters\n"; 62 | 63 | hooks::hook_import(this, "TextOutA", TextOutAHook); 64 | hooks::hook_import(this, "MultiByteToWideChar", MultiByteToWideCharHook); 65 | hooks::hook_import(this, "GetTextExtentPoint32A", GetTextExtentPoint32AHook); 66 | hooks::hook_import(this, "IsDBCSLeadByteEx", IsDBCSLeadByteExHook); 67 | hooks::hook_import(this, "IsDBCSLeadByte", IsDBCSLeadByteHook); 68 | } 69 | 70 | void uif::features::tunnel_decoder::finalize() 71 | { 72 | hooks::unhook_import(this, "TextOutA", TextOutAHook); 73 | hooks::unhook_import(this, "MultiByteToWideChar", MultiByteToWideCharHook); 74 | hooks::unhook_import(this, "GetTextExtentPoint32A", GetTextExtentPoint32AHook); 75 | hooks::unhook_import(this, "IsDBCSLeadByteEx", IsDBCSLeadByteExHook); 76 | hooks::unhook_import(this, "IsDBCSLeadByte", IsDBCSLeadByteHook); 77 | } -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/ansi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef UIF_ANSI_COLOR 4 | #define UIF_ANSI_COLOR 1 5 | #endif 6 | 7 | namespace uif::ansi 8 | { 9 | enum class color : char 10 | { 11 | none = -1, 12 | 13 | dark_black = 0, 14 | dark_red = 1, 15 | dark_green = 2, 16 | dark_yellow = 3, 17 | dark_blue = 4, 18 | dark_magenta = 5, 19 | dark_cyan = 6, 20 | dark_white = 7, 21 | 22 | black = 8, 23 | red = 9, 24 | green = 10, 25 | yellow = 11, 26 | blue = 12, 27 | magenta = 13, 28 | cyan = 14, 29 | white = 15 30 | }; 31 | 32 | static const char* fg_ansi_codes[] = { 33 | "\33[30m", "\33[31m", "\33[32m", "\33[33m", 34 | "\33[34m", "\33[35m", "\33[36m", "\33[37m", 35 | "\33[30;1m", "\33[31;1m", "\33[32;1m", "\33[33;1m", 36 | "\33[34;1m", "\33[35;1m", "\33[36;1m", "\33[37;1m", 37 | }; 38 | 39 | static const char* bg_ansi_codes[] = { 40 | "\33[40m", "\33[41m", "\33[42m", "\33[43m", 41 | "\33[44m", "\33[45m", "\33[46m", "\33[47m", 42 | "\33[40;1m", "\33[41;1m", "\33[42;1m", "\33[43;1m", 43 | "\33[44;1m", "\33[45;1m", "\33[46;1m", "\33[47;1m", 44 | }; 45 | 46 | template 47 | struct colored_thing { T thing; }; 48 | 49 | #if UIF_ANSI_COLOR 50 | #define COLOR_TEMPLATES(col) \ 51 | template colored_thing col(T t) { return { t }; } \ 52 | template colored_thing col ##_bg(T t) { return { t }; } 53 | #else 54 | #define COLOR_TEMPLATES(col) \ 55 | template T col(T t) { return t; } \ 56 | template T col ##_bg(T t) { return t; } 57 | #endif 58 | 59 | COLOR_TEMPLATES(black); 60 | COLOR_TEMPLATES(red); 61 | COLOR_TEMPLATES(green); 62 | COLOR_TEMPLATES(yellow); 63 | COLOR_TEMPLATES(blue); 64 | COLOR_TEMPLATES(magenta); 65 | COLOR_TEMPLATES(cyan); 66 | COLOR_TEMPLATES(white); 67 | 68 | COLOR_TEMPLATES(dark_black); 69 | COLOR_TEMPLATES(dark_red); 70 | COLOR_TEMPLATES(dark_green); 71 | COLOR_TEMPLATES(dark_yellow); 72 | COLOR_TEMPLATES(dark_blue); 73 | COLOR_TEMPLATES(dark_magenta); 74 | COLOR_TEMPLATES(dark_cyan); 75 | COLOR_TEMPLATES(dark_white); 76 | 77 | template 78 | std::ostream& operator<<(std::ostream& os, const colored_thing colored) 79 | { 80 | if(fg != color::none) 81 | os << fg_ansi_codes[static_cast(fg)]; 82 | 83 | if(bg != color::none) 84 | os << bg_ansi_codes[static_cast(bg)]; 85 | 86 | os << colored.thing; 87 | 88 | if(fg != color::none || bg != color::none) 89 | os << "\033[0m"; 90 | 91 | return os; 92 | } 93 | 94 | template 95 | std::wostream& operator<<(std::wostream& os, const colored_thing colored) 96 | { 97 | if(fg != color::none) 98 | os << fg_ansi_codes[static_cast(fg)]; 99 | 100 | if(bg != color::none) 101 | os << bg_ansi_codes[static_cast(bg)]; 102 | 103 | os << colored.thing; 104 | 105 | if(fg != color::none || bg != color::none) 106 | os << "\033[0m"; 107 | 108 | return os; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/memory_patcher.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "memory_patcher.h" 3 | 4 | #include "ansi.h" 5 | #include "config.h" 6 | #include "hooks.h" 7 | #include "utils.h" 8 | 9 | using namespace uif::ansi; 10 | 11 | void uif::features::memory_patcher::initialize() 12 | { 13 | if(!config().contains("patches")) 14 | { 15 | std::cout << *this << dark_yellow(" Warning:") << " no patches specified\n"; 16 | return; 17 | } 18 | 19 | auto& patchTable = config()["patches"]; 20 | 21 | if(!patchTable.is_object()) { 22 | std::cout << *this << dark_red(" Error:") << " expected object\n"; 23 | return; 24 | } 25 | 26 | for(const auto& it : patchTable.items()) 27 | { 28 | void* address = utils::parse_address(it.key()); 29 | 30 | if(address == nullptr) 31 | continue; 32 | 33 | const auto& bytesJson = it.value(); 34 | 35 | if(!bytesJson.is_string()) 36 | { 37 | std::cout << *this << dark_red(" Error:") << " expected string\n"; 38 | continue; 39 | } 40 | 41 | const auto& bytesString = bytesJson.get(); 42 | if(bytesString.length() == 0) 43 | { 44 | std::cout << *this << dark_yellow(" Warning:") << " empty patch\n"; 45 | continue; 46 | } 47 | 48 | if(bytesString.length() % 3 != 2) 49 | { 50 | std::cout << *this << dark_yellow(" Warning:") << " malformed patch bytes\n"; 51 | continue; 52 | } 53 | 54 | const size_t length = (bytesString.length() + 1) / 3; 55 | char* newBytes = new char[length * 2]; 56 | char* oldBytes = newBytes + length; 57 | 58 | bool valid = true; 59 | 60 | for(size_t i = 0; i < length; ++i) 61 | { 62 | // every third character must be a space or the null terminator 63 | const char space = bytesString[3 * i + 2]; 64 | if(space && space != ' ') 65 | { 66 | valid = false; 67 | break; 68 | } 69 | 70 | const char hi = bytesString[3 * i + 0]; 71 | const char lo = bytesString[3 * i + 1]; 72 | char value = 0; 73 | 74 | if(hi >= 'a' && hi <= 'f') value |= (0xA + hi - 'a') << 4; 75 | else if(hi >= 'A' && hi <= 'F') value |= (0xA + hi - 'A') << 4; 76 | else if(hi >= '0' && hi <= '9') value |= (0x0 + hi - '0') << 4; 77 | else 78 | { 79 | valid = false; 80 | break; 81 | } 82 | 83 | if(lo >= 'a' && lo <= 'f') value |= (0xA + lo - 'a') << 0; 84 | else if(lo >= 'A' && lo <= 'F') value |= (0xA + lo - 'A') << 0; 85 | else if(lo >= '0' && lo <= '9') value |= (0x0 + lo - '0') << 0; 86 | else 87 | { 88 | valid = false; 89 | break; 90 | } 91 | 92 | newBytes[i] = value; 93 | } 94 | 95 | if(!valid) 96 | { 97 | std::cout << *this << dark_yellow(" Warning:") << " malformed patch bytes\n"; 98 | delete[] newBytes; 99 | delete[] oldBytes; 100 | continue; 101 | } 102 | 103 | patches.emplace_back(length, address, newBytes, oldBytes); 104 | } 105 | 106 | for(const auto& patch : patches) 107 | { 108 | if(_debug) 109 | { 110 | std::cout << *this << " Patching " << patch.length << " bytes at " << blue(patch.address) << "\n"; 111 | } 112 | 113 | utils::patch_memory(patch.address, patch.patch_value, patch.length, patch.original_value); 114 | } 115 | } 116 | 117 | void uif::features::memory_patcher::finalize() 118 | { 119 | for(const auto& patch : patches) 120 | { 121 | utils::patch_memory(patch.address, patch.original_value, patch.length, nullptr); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/d3d11.def: -------------------------------------------------------------------------------- 1 | LIBRARY d3d11 2 | EXPORTS 3 | D3D11CreateDeviceForD3D12=lib_d3d11_D3D11CreateDeviceForD3D12 @1 4 | D3DKMTCloseAdapter=lib_d3d11_D3DKMTCloseAdapter @2 5 | D3DKMTDestroyAllocation=lib_d3d11_D3DKMTDestroyAllocation @3 6 | D3DKMTDestroyContext=lib_d3d11_D3DKMTDestroyContext @4 7 | D3DKMTDestroyDevice=lib_d3d11_D3DKMTDestroyDevice @5 8 | D3DKMTDestroySynchronizationObject=lib_d3d11_D3DKMTDestroySynchronizationObject @6 9 | D3DKMTPresent=lib_d3d11_D3DKMTPresent @7 10 | D3DKMTQueryAdapterInfo=lib_d3d11_D3DKMTQueryAdapterInfo @8 11 | D3DKMTSetDisplayPrivateDriverFormat=lib_d3d11_D3DKMTSetDisplayPrivateDriverFormat @9 12 | D3DKMTSignalSynchronizationObject=lib_d3d11_D3DKMTSignalSynchronizationObject @10 13 | D3DKMTUnlock=lib_d3d11_D3DKMTUnlock @11 14 | D3DKMTWaitForSynchronizationObject=lib_d3d11_D3DKMTWaitForSynchronizationObject @12 15 | EnableFeatureLevelUpgrade=lib_d3d11_EnableFeatureLevelUpgrade @13 16 | OpenAdapter10=lib_d3d11_OpenAdapter10 @14 17 | OpenAdapter10_2=lib_d3d11_OpenAdapter10_2 @15 18 | CreateDirect3D11DeviceFromDXGIDevice=lib_d3d11_CreateDirect3D11DeviceFromDXGIDevice @16 19 | CreateDirect3D11SurfaceFromDXGISurface=lib_d3d11_CreateDirect3D11SurfaceFromDXGISurface @17 20 | D3D11CoreCreateDevice=lib_d3d11_D3D11CoreCreateDevice @18 21 | D3D11CoreCreateLayeredDevice=lib_d3d11_D3D11CoreCreateLayeredDevice @19 22 | D3D11CoreGetLayeredDeviceSize=lib_d3d11_D3D11CoreGetLayeredDeviceSize @20 23 | D3D11CoreRegisterLayers=lib_d3d11_D3D11CoreRegisterLayers @21 24 | D3D11CreateDevice=lib_d3d11_D3D11CreateDevice @22 25 | D3D11CreateDeviceAndSwapChain=lib_d3d11_D3D11CreateDeviceAndSwapChain @23 26 | D3D11On12CreateDevice=lib_d3d11_D3D11On12CreateDevice @24 27 | D3DKMTCreateAllocation=lib_d3d11_D3DKMTCreateAllocation @25 28 | D3DKMTCreateContext=lib_d3d11_D3DKMTCreateContext @26 29 | D3DKMTCreateDevice=lib_d3d11_D3DKMTCreateDevice @27 30 | D3DKMTCreateSynchronizationObject=lib_d3d11_D3DKMTCreateSynchronizationObject @28 31 | D3DKMTEscape=lib_d3d11_D3DKMTEscape @29 32 | D3DKMTGetContextSchedulingPriority=lib_d3d11_D3DKMTGetContextSchedulingPriority @30 33 | D3DKMTGetDeviceState=lib_d3d11_D3DKMTGetDeviceState @31 34 | D3DKMTGetDisplayModeList=lib_d3d11_D3DKMTGetDisplayModeList @32 35 | D3DKMTGetMultisampleMethodList=lib_d3d11_D3DKMTGetMultisampleMethodList @33 36 | D3DKMTGetRuntimeData=lib_d3d11_D3DKMTGetRuntimeData @34 37 | D3DKMTGetSharedPrimaryHandle=lib_d3d11_D3DKMTGetSharedPrimaryHandle @35 38 | D3DKMTLock=lib_d3d11_D3DKMTLock @36 39 | D3DKMTOpenAdapterFromHdc=lib_d3d11_D3DKMTOpenAdapterFromHdc @37 40 | D3DKMTOpenResource=lib_d3d11_D3DKMTOpenResource @38 41 | D3DKMTQueryAllocationResidency=lib_d3d11_D3DKMTQueryAllocationResidency @39 42 | D3DKMTQueryResourceInfo=lib_d3d11_D3DKMTQueryResourceInfo @40 43 | D3DKMTRender=lib_d3d11_D3DKMTRender @41 44 | D3DKMTSetAllocationPriority=lib_d3d11_D3DKMTSetAllocationPriority @42 45 | D3DKMTSetContextSchedulingPriority=lib_d3d11_D3DKMTSetContextSchedulingPriority @43 46 | D3DKMTSetDisplayMode=lib_d3d11_D3DKMTSetDisplayMode @44 47 | D3DKMTSetGammaRamp=lib_d3d11_D3DKMTSetGammaRamp @45 48 | D3DKMTSetVidPnSourceOwner=lib_d3d11_D3DKMTSetVidPnSourceOwner @46 49 | D3DKMTWaitForVerticalBlankEvent=lib_d3d11_D3DKMTWaitForVerticalBlankEvent @47 50 | D3DPerformance_BeginEvent=lib_d3d11_D3DPerformance_BeginEvent @48 51 | D3DPerformance_EndEvent=lib_d3d11_D3DPerformance_EndEvent @49 52 | D3DPerformance_GetStatus=lib_d3d11_D3DPerformance_GetStatus @50 53 | D3DPerformance_SetMarker=lib_d3d11_D3DPerformance_SetMarker @51 54 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/play_timer.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "play_timer.h" 3 | 4 | #include "config.h" 5 | #include "hooks.h" 6 | 7 | using json = nlohmann::json; 8 | 9 | void uif::features::play_timer::initialize() 10 | { 11 | start_time = epoch_time(); 12 | save_file_path = config().value("save_file_path", "play_timer.json"); 13 | 14 | auto_save_enable = config().value("auto_save/enable"_json_pointer, false); 15 | if(auto_save_enable) { 16 | auto_save_interval = config().value("auto_save/interval"_json_pointer, 60); 17 | auto_save_start(); 18 | } 19 | } 20 | 21 | void uif::features::play_timer::finalize() 22 | { 23 | auto_save_stop(); 24 | end_time = epoch_time(); 25 | write_save_file(); 26 | } 27 | 28 | void uif::features::play_timer::auto_save_start() 29 | { 30 | auto_save_enable = true; 31 | auto_save_thread = std::thread([this]() 32 | { 33 | while(auto_save_enable) { 34 | write_save_file(); 35 | std::unique_lock lk(auto_save_mutex); 36 | auto_save_stop_signal.wait_for(lk, std::chrono::seconds(auto_save_interval)); 37 | } 38 | }); 39 | } 40 | 41 | void uif::features::play_timer::auto_save_stop() 42 | { 43 | if(auto_save_enable) { 44 | auto_save_enable = false; 45 | { 46 | std::lock_guard _(auto_save_mutex); 47 | auto_save_stop_signal.notify_one(); 48 | } 49 | auto_save_thread.join(); 50 | } 51 | } 52 | 53 | void uif::features::play_timer::write_save_file() const 54 | { 55 | std::cout << "Writing play timer save file..." << std::endl; 56 | json data; 57 | std::ifstream in; 58 | in.open(save_file_path); 59 | if(in.is_open()) 60 | { 61 | try 62 | { 63 | in >> data; 64 | } 65 | catch(nlohmann::json::parse_error& error) 66 | { 67 | std::cout << "Failed to read play timer save file (" << save_file_path << "): " << error.what() << std::endl; 68 | } 69 | in.close(); 70 | } 71 | else 72 | { 73 | data = json({}); 74 | } 75 | 76 | if(!data.contains("times")) 77 | { 78 | data["times"] = json::array(); 79 | } 80 | 81 | const bool was_active = data.value("active", false); 82 | if(was_active && data["active_start"] != start_time) 83 | { 84 | std::cout << "Found stale active marker. The app didn't exit properly last time." << std::endl; 85 | data["times"].emplace_back(json({ 86 | { "start", data["active_start"] }, 87 | { "end", data["active_ping"] } 88 | })); 89 | } 90 | 91 | const bool is_active = end_time == -1; 92 | if(is_active) 93 | { 94 | data["active"] = true; 95 | data["active_start"] = start_time; 96 | data["active_ping"] = epoch_time(); 97 | } 98 | else 99 | { 100 | data.erase("active"); 101 | data.erase("active_start"); 102 | data.erase("active_ping"); 103 | data["times"].emplace_back(json({ 104 | { "start", start_time }, 105 | { "end", end_time }, 106 | { "duration", end_time - start_time } 107 | })); 108 | } 109 | 110 | long long total_time = 0; 111 | for(auto time_entry : data["times"]) 112 | { 113 | long long duration = time_entry["duration"]; 114 | total_time += duration; 115 | } 116 | data["total_time"] = total_time; 117 | 118 | std::ofstream out; 119 | out.open(save_file_path); 120 | if(!out.is_open()) 121 | { 122 | std::cout << "Failed to write play timer save file (" << save_file_path << ")" << std::endl; 123 | return; 124 | } 125 | out << std::setw(4) << data; 126 | out.close(); 127 | } 128 | 129 | long long uif::features::play_timer::epoch_time() 130 | { 131 | const auto duration = std::chrono::system_clock::now().time_since_epoch(); 132 | return std::chrono::duration_cast(duration).count(); 133 | } 134 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/encoding.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "encoding.h" 4 | 5 | using string = std::string; 6 | using wstring = std::wstring; 7 | 8 | namespace encoding 9 | { 10 | wstring to_widechar(const string& text, int codepage) { 11 | const int numBytes = static_cast(text.length()); 12 | const int numChars = MultiByteToWideChar(codepage, 0, text.c_str(), numBytes, nullptr, 0); 13 | 14 | wstring result; 15 | result.resize(numChars); 16 | MultiByteToWideChar(codepage, 0, text.c_str(), numBytes, result.data(), numChars); 17 | 18 | return result; 19 | } 20 | 21 | string to_multibyte(const wstring& text, int codepage) { 22 | const int numChars = text.length(); 23 | const int numBytes = WideCharToMultiByte(codepage, 0, text.c_str(), numChars, nullptr, 0, nullptr, nullptr); 24 | 25 | string result; 26 | result.resize(numBytes); 27 | WideCharToMultiByte(codepage, 0, text.c_str(), numChars, result.data(), numBytes, nullptr, nullptr); 28 | 29 | return result; 30 | } 31 | 32 | wstring shiftjis_to_utf16(const string& shift_jis) 33 | { 34 | return to_widechar(shift_jis, CP_SHIFTJIS); 35 | } 36 | 37 | string utf16_to_shiftjis(const wstring& utf16) 38 | { 39 | return to_multibyte(utf16, CP_SHIFTJIS); 40 | } 41 | 42 | wstring utf8_to_utf16(const string& utf8) 43 | { 44 | return to_widechar(utf8, CP_UTF8); 45 | } 46 | 47 | string utf16_to_utf8(const wstring& utf16) 48 | { 49 | return to_multibyte(utf16, CP_UTF8); 50 | } 51 | 52 | // shift-jis tunnel decoder logic courtesy of https://github.com/arcusmaximus 53 | std::wstring decode_shiftjis_tunnel(const char* text, int count, const std::wstring& mapping) 54 | { 55 | std::wstring result; 56 | if (text == nullptr) 57 | return result; 58 | 59 | if (count < 0) 60 | count = strlen(text); 61 | 62 | int charIdx = 0; 63 | while (charIdx < count) 64 | { 65 | const BYTE highByte = text[charIdx++]; 66 | BYTE lowByte = 0; 67 | 68 | if ((highByte >= 0x81 && highByte < 0xA0) || (highByte >= 0xE0 && highByte < 0xFD)) 69 | { 70 | const int highIdx = highByte < 0xA0 ? highByte - 0x81 : 0x1F + (highByte - 0xE0); 71 | 72 | lowByte = text[charIdx++]; 73 | if (lowByte == 0) 74 | break; 75 | 76 | if (lowByte < 0x40) 77 | { 78 | int lowIdx = lowByte; 79 | if (lowIdx > ',') 80 | lowIdx--; 81 | if (lowIdx > ' ') 82 | lowIdx--; 83 | if (lowIdx > '\r') 84 | lowIdx--; 85 | if (lowIdx > '\n') 86 | lowIdx--; 87 | if (lowIdx > '\t') 88 | lowIdx--; 89 | 90 | lowIdx--; 91 | 92 | const size_t index = highIdx * 0x3A + lowIdx; 93 | 94 | if (index < mapping.length()) 95 | result += mapping[index]; 96 | else 97 | std::cout << " No mapping defined for tunnel index " << index << '\n'; 98 | 99 | continue; 100 | } 101 | } 102 | 103 | const int charLength = lowByte == 0 ? 1 : 2; 104 | wchar_t wc; 105 | MultiByteToWideChar(CP_SHIFTJIS, 0, text + charIdx - charLength, charLength, &wc, 1); 106 | result += wc; 107 | } 108 | 109 | assert(charIdx == count); 110 | 111 | return result; 112 | } 113 | 114 | void print_bytes(const string& str) 115 | { 116 | for (const auto c : str) 117 | { 118 | std::cout << std::setw(2) << std::hex << (static_cast(c) & 0xFF) << ' '; 119 | } 120 | std::cout << std::endl; 121 | } 122 | 123 | void print_bytes(const wstring& str) 124 | { 125 | for (const auto c : str) 126 | { 127 | std::cout << std::setw(2) << std::hex << (static_cast(c) & 0xFF) << (static_cast(c) >> 8 & 0xFF) << ' '; 128 | } 129 | std::cout << std::endl; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/version.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #ifdef UIF_LIB_VERSION 4 | 5 | #include "injector.h" 6 | 7 | struct { 8 | HMODULE dll; 9 | FARPROC GetFileVersionInfoA; 10 | FARPROC GetFileVersionInfoByHandle; 11 | FARPROC GetFileVersionInfoExA; 12 | FARPROC GetFileVersionInfoExW; 13 | FARPROC GetFileVersionInfoSizeA; 14 | FARPROC GetFileVersionInfoSizeExA; 15 | FARPROC GetFileVersionInfoSizeExW; 16 | FARPROC GetFileVersionInfoSizeW; 17 | FARPROC GetFileVersionInfoW; 18 | FARPROC VerFindFileA; 19 | FARPROC VerFindFileW; 20 | FARPROC VerInstallFileA; 21 | FARPROC VerInstallFileW; 22 | FARPROC VerLanguageNameA; 23 | FARPROC VerLanguageNameW; 24 | FARPROC VerQueryValueA; 25 | FARPROC VerQueryValueW; 26 | } version; 27 | 28 | void lib_version_GetFileVersionInfoA() { version.GetFileVersionInfoA(); } 29 | void lib_version_GetFileVersionInfoByHandle() { version.GetFileVersionInfoByHandle(); } 30 | void lib_version_GetFileVersionInfoExA() { version.GetFileVersionInfoExA(); } 31 | void lib_version_GetFileVersionInfoExW() { version.GetFileVersionInfoExW(); } 32 | void lib_version_GetFileVersionInfoSizeA() { version.GetFileVersionInfoSizeA(); } 33 | void lib_version_GetFileVersionInfoSizeExA() { version.GetFileVersionInfoSizeExA(); } 34 | void lib_version_GetFileVersionInfoSizeExW() { version.GetFileVersionInfoSizeExW(); } 35 | void lib_version_GetFileVersionInfoSizeW() { version.GetFileVersionInfoSizeW(); } 36 | void lib_version_GetFileVersionInfoW() { version.GetFileVersionInfoW(); } 37 | void lib_version_VerFindFileA() { version.VerFindFileA(); } 38 | void lib_version_VerFindFileW() { version.VerFindFileW(); } 39 | void lib_version_VerInstallFileA() { version.VerInstallFileA(); } 40 | void lib_version_VerInstallFileW() { version.VerInstallFileW(); } 41 | void lib_version_VerLanguageNameA() { version.VerLanguageNameA(); } 42 | void lib_version_VerLanguageNameW() { version.VerLanguageNameW(); } 43 | void lib_version_VerQueryValueA() { version.VerQueryValueA(); } 44 | void lib_version_VerQueryValueW() { version.VerQueryValueW(); } 45 | 46 | bool load_library_version() { 47 | version.dll = uif::injector::instance().load_real_library("version.dll"); 48 | version.GetFileVersionInfoA = GetProcAddress(version.dll, "GetFileVersionInfoA"); 49 | version.GetFileVersionInfoByHandle = GetProcAddress(version.dll, "GetFileVersionInfoByHandle"); 50 | version.GetFileVersionInfoExA = GetProcAddress(version.dll, "GetFileVersionInfoExA"); 51 | version.GetFileVersionInfoExW = GetProcAddress(version.dll, "GetFileVersionInfoExW"); 52 | version.GetFileVersionInfoSizeA = GetProcAddress(version.dll, "GetFileVersionInfoSizeA"); 53 | version.GetFileVersionInfoSizeExA = GetProcAddress(version.dll, "GetFileVersionInfoSizeExA"); 54 | version.GetFileVersionInfoSizeExW = GetProcAddress(version.dll, "GetFileVersionInfoSizeExW"); 55 | version.GetFileVersionInfoSizeW = GetProcAddress(version.dll, "GetFileVersionInfoSizeW"); 56 | version.GetFileVersionInfoW = GetProcAddress(version.dll, "GetFileVersionInfoW"); 57 | version.VerFindFileA = GetProcAddress(version.dll, "VerFindFileA"); 58 | version.VerFindFileW = GetProcAddress(version.dll, "VerFindFileW"); 59 | version.VerInstallFileA = GetProcAddress(version.dll, "VerInstallFileA"); 60 | version.VerInstallFileW = GetProcAddress(version.dll, "VerInstallFileW"); 61 | version.VerLanguageNameA = GetProcAddress(version.dll, "VerLanguageNameA"); 62 | version.VerLanguageNameW = GetProcAddress(version.dll, "VerLanguageNameW"); 63 | version.VerQueryValueA = GetProcAddress(version.dll, "VerQueryValueA"); 64 | version.VerQueryValueW = GetProcAddress(version.dll, "VerQueryValueW"); 65 | return true; 66 | } 67 | 68 | bool unload_library_version() { 69 | FreeLibrary(version.dll); 70 | version.dll = nullptr; 71 | return true; 72 | } 73 | 74 | #else 75 | 76 | bool load_library_version() { 77 | return false; 78 | } 79 | 80 | bool unload_library_version() { 81 | return false; 82 | } 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/text_processor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "_feature_base.h" 5 | 6 | namespace uif::features 7 | { 8 | class text_processor final : public feature_base 9 | { 10 | public: 11 | explicit text_processor(uif::injector& injector) : feature_base(injector, "text_processor") {} 12 | void initialize() override; 13 | void finalize() override; 14 | 15 | enum class api 16 | { 17 | IsDBCSLeadByte, 18 | IsDBCSLeadByteEx, 19 | MultiByteToWideChar, 20 | 21 | GetGlyphOutlineA, 22 | GetGlyphOutlineW, 23 | GetTextExtentExPointA, 24 | GetTextExtentExPointW, 25 | GetTextExtentPoint32A, 26 | GetTextExtentPoint32W, 27 | GetTextExtentPointA, 28 | GetTextExtentPointW, 29 | TextOutA, 30 | TextOutW, 31 | ExtTextOutA, 32 | ExtTextOutW, 33 | 34 | AppendMenuA, 35 | AppendMenuW, 36 | InsertMenuA, 37 | InsertMenuW, 38 | InsertMenuItemA, 39 | InsertMenuItemW, 40 | ModifyMenuA, 41 | ModifyMenuW, 42 | SetMenuItemInfoA, 43 | SetMenuItemInfoW, 44 | 45 | SetDlgItemTextA, 46 | SetDlgItemTextW, 47 | 48 | DrawTextA, 49 | DrawTextW, 50 | DrawTextExA, 51 | DrawTextExW, 52 | GrayStringA, 53 | GrayStringW, 54 | TabbedTextOutA, 55 | TabbedTextOutW, 56 | 57 | MessageBoxA, 58 | MessageBoxW, 59 | MessageBoxExA, 60 | MessageBoxExW, 61 | MessageBoxIndirectA, 62 | MessageBoxIndirectW, 63 | 64 | DefWindowProcA, 65 | DefWindowProcW, 66 | DefDlgProcA, 67 | DefDlgProcW, 68 | 69 | NCCREATE, 70 | SETTEXT, 71 | 72 | N 73 | }; 74 | 75 | static constexpr size_t api_count = static_cast(api::N); 76 | typedef std::bitset api_mask; 77 | 78 | struct api_descriptor 79 | { 80 | api api; 81 | const char* name; 82 | void* hook; 83 | UINT msg; 84 | bool needs_conversion; 85 | }; 86 | 87 | struct api_set 88 | { 89 | std::string name; 90 | api_mask mask; 91 | }; 92 | 93 | class processing_rule 94 | { 95 | public: 96 | api_mask mask{}; 97 | 98 | explicit processing_rule(const api_mask& mask) 99 | : mask(mask) 100 | { } 101 | 102 | bool applies_to_api(api api) const 103 | { 104 | return mask.test(static_cast(api)); 105 | } 106 | 107 | virtual bool process(std::wstring& value) = 0; 108 | virtual ~processing_rule() = default; 109 | 110 | processing_rule() = default; 111 | processing_rule(const processing_rule&) = delete; 112 | processing_rule(const processing_rule&&) = delete; 113 | processing_rule& operator=(processing_rule const&) = delete; 114 | processing_rule& operator=(processing_rule const&&) = delete; 115 | }; 116 | 117 | static const std::array api_descriptors; 118 | static const std::vector default_api_sets; 119 | 120 | int conversion_codepage; 121 | bool use_tunnel_decoder; 122 | std::wstring tunnel_mapping{}; 123 | 124 | api_mask enabled_apis{}; 125 | std::vector custom_api_sets; 126 | std::vector rules{}; 127 | 128 | bool is_api_enabled(api api) const; 129 | bool enable_api(api api); 130 | bool disable_api(api api); 131 | void set_enabled_apis(api_mask mask); 132 | 133 | std::wstring convert(const std::string& value, api api) const; 134 | std::wstring convert(const std::wstring& value, api api) const; 135 | std::wstring process(const std::string& value, api api) const; 136 | std::wstring process(const std::wstring& value, api api) const; 137 | std::optional process(const char* value, api api) const; 138 | std::optional process(const wchar_t* value, api api) const; 139 | 140 | private: 141 | static std::vector parse_strings(const nlohmann::basic_json<>& value); 142 | processing_rule* parse_rule(const nlohmann::basic_json<>& rule) const; 143 | api_mask parse_mask(const nlohmann::basic_json<>& value); 144 | void parse_mask(const nlohmann::basic_json<>& value, api_mask& mask); 145 | }; 146 | } -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/character_substitution.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "character_substitution.h" 3 | 4 | #include "config.h" 5 | #include "encoding.h" 6 | #include "hooks.h" 7 | #include "injector.h" 8 | 9 | #pragma region Hooks 10 | 11 | static BOOL __stdcall TextOutWHook(HDC hdc, int x, int y, LPCWSTR lpString, int c) { 12 | const auto& subst = uif::injector::instance().feature(); 13 | 14 | std::wstring s = lpString; 15 | subst.substitute(s); 16 | 17 | if(subst.is_debugging_enabled()) 18 | { 19 | std::wcout << lpString << L" => " << s << L"\n"; 20 | } 21 | 22 | return TextOutW(hdc, x, y, s.c_str(), c); 23 | } 24 | 25 | static BOOL __stdcall TextOutAHook(HDC hdc, int x, int y, LPCSTR lpString, int c) { 26 | std::string truncated = lpString; 27 | truncated.resize(c); 28 | const auto s = encoding::shiftjis_to_utf16(truncated); 29 | return TextOutWHook(hdc, x, y, s.c_str(), static_cast(s.length())); 30 | } 31 | 32 | static DWORD __stdcall GetGlyphOutlineWHook(HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, DWORD cjBuffer, LPVOID pvBuffer, MAT2* lpmat2) 33 | { 34 | //std::wcout << std::setw(4) << std::hex << uChar << std::dec << std::setw(0) << ' ' << *reinterpret_cast(&uChar) << '\n'; 35 | 36 | const auto& subst = uif::injector::instance().feature(); 37 | const auto& map = subst.substitutions; 38 | 39 | const auto wChar = static_cast(uChar); 40 | 41 | const auto it = map.find(wChar); 42 | if(it != map.end()) 43 | { 44 | uChar = it->second; 45 | } 46 | 47 | return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cjBuffer, pvBuffer, lpmat2); 48 | } 49 | 50 | static DWORD __stdcall GetGlyphOutlineAHook(HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, DWORD cjBuffer, LPVOID pvBuffer, MAT2* lpmat2) 51 | { 52 | char a[3] = { 0 }; 53 | if(uChar < 0x100) 54 | { 55 | a[0] = static_cast(uChar); 56 | } 57 | else 58 | { 59 | a[0] = static_cast(uChar >> 8); 60 | a[1] = static_cast(uChar); 61 | } 62 | 63 | const auto s = encoding::shiftjis_to_utf16(a); 64 | 65 | return GetGlyphOutlineWHook(hdc, s[0], fuFormat, lpgm, cjBuffer, pvBuffer, lpmat2); 66 | } 67 | 68 | #pragma endregion 69 | 70 | void uif::features::character_substitution::initialize() 71 | { 72 | substitutions = std::map(); 73 | 74 | const std::string source = config().value("source_characters", ""); 75 | const std::string target = config().value("target_characters", ""); 76 | 77 | const std::wstring wsource = encoding::utf8_to_utf16(source); 78 | const std::wstring wtarget = encoding::utf8_to_utf16(target); 79 | 80 | const size_t substCount = std::min(wsource.length(), wtarget.length()); 81 | for(size_t i = 0; i < substCount; i++) 82 | { 83 | substitutions[wsource[i]] = wtarget[i]; 84 | } 85 | 86 | std::cout << *this << " Loaded " << substCount << " substitution characters\n"; 87 | 88 | hooks::hook_import(this, "TextOutA", TextOutAHook); 89 | hooks::hook_import(this, "TextOutW", TextOutWHook); 90 | hooks::hook_import(this, "GetGlyphOutlineA", GetGlyphOutlineAHook); 91 | hooks::hook_import(this, "GetGlyphOutlineW", GetGlyphOutlineWHook); 92 | } 93 | 94 | void uif::features::character_substitution::finalize() 95 | { 96 | hooks::unhook_import(this, "TextOutA", TextOutAHook); 97 | hooks::unhook_import(this, "TextOutW", TextOutWHook); 98 | hooks::unhook_import(this, "GetGlyphOutlineA", GetGlyphOutlineAHook); 99 | hooks::unhook_import(this, "GetGlyphOutlineW", GetGlyphOutlineWHook); 100 | } 101 | 102 | void uif::features::character_substitution::substitute(wchar_t* text, int length) const 103 | { 104 | if (!is_enabled()) return; 105 | 106 | for (int i = 0; i < length; ++i) 107 | { 108 | const wchar_t ch = text[i]; 109 | if (ch == 0) break; 110 | 111 | const auto it = substitutions.find(ch); 112 | if (it != substitutions.end()) 113 | { 114 | text[i] = it->second; 115 | } 116 | } 117 | } 118 | 119 | void uif::features::character_substitution::substitute(std::wstring& text) const 120 | { 121 | substitute(text.data(), static_cast(text.length())); 122 | } 123 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/dxgi.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #ifdef UIF_LIB_DXGI 4 | 5 | #include "injector.h" 6 | 7 | struct { 8 | HMODULE dll; 9 | FARPROC ApplyCompatResolutionQuirking; 10 | FARPROC CompatString; 11 | FARPROC CompatValue; 12 | FARPROC DXGIDumpJournal; 13 | FARPROC PIXBeginCapture; 14 | FARPROC PIXEndCapture; 15 | FARPROC PIXGetCaptureState; 16 | FARPROC SetAppCompatStringPointer; 17 | FARPROC UpdateHMDEmulationStatus; 18 | FARPROC CreateDXGIFactory1; 19 | FARPROC CreateDXGIFactory2; 20 | FARPROC CreateDXGIFactory; 21 | FARPROC DXGID3D10CreateDevice; 22 | FARPROC DXGID3D10CreateLayeredDevice; 23 | FARPROC DXGID3D10GetLayeredDeviceSize; 24 | FARPROC DXGID3D10RegisterLayers; 25 | FARPROC DXGIDeclareAdapterRemovalSupport; 26 | FARPROC DXGIGetDebugInterface1; 27 | FARPROC DXGIReportAdapterConfiguration; 28 | } dxgi; 29 | 30 | void lib_dxgi_ApplyCompatResolutionQuirking() { dxgi.ApplyCompatResolutionQuirking(); } 31 | void lib_dxgi_CompatString() { dxgi.CompatString(); } 32 | void lib_dxgi_CompatValue() { dxgi.CompatValue(); } 33 | void lib_dxgi_DXGIDumpJournal() { dxgi.DXGIDumpJournal(); } 34 | void lib_dxgi_PIXBeginCapture() { dxgi.PIXBeginCapture(); } 35 | void lib_dxgi_PIXEndCapture() { dxgi.PIXEndCapture(); } 36 | void lib_dxgi_PIXGetCaptureState() { dxgi.PIXGetCaptureState(); } 37 | void lib_dxgi_SetAppCompatStringPointer() { dxgi.SetAppCompatStringPointer(); } 38 | void lib_dxgi_UpdateHMDEmulationStatus() { dxgi.UpdateHMDEmulationStatus(); } 39 | void lib_dxgi_CreateDXGIFactory1() { dxgi.CreateDXGIFactory1(); } 40 | void lib_dxgi_CreateDXGIFactory2() { dxgi.CreateDXGIFactory2(); } 41 | void lib_dxgi_CreateDXGIFactory() { dxgi.CreateDXGIFactory(); } 42 | void lib_dxgi_DXGID3D10CreateDevice() { dxgi.DXGID3D10CreateDevice(); } 43 | void lib_dxgi_DXGID3D10CreateLayeredDevice() { dxgi.DXGID3D10CreateLayeredDevice(); } 44 | void lib_dxgi_DXGID3D10GetLayeredDeviceSize() { dxgi.DXGID3D10GetLayeredDeviceSize(); } 45 | void lib_dxgi_DXGID3D10RegisterLayers() { dxgi.DXGID3D10RegisterLayers(); } 46 | void lib_dxgi_DXGIDeclareAdapterRemovalSupport() { dxgi.DXGIDeclareAdapterRemovalSupport(); } 47 | void lib_dxgi_DXGIGetDebugInterface1() { dxgi.DXGIGetDebugInterface1(); } 48 | void lib_dxgi_DXGIReportAdapterConfiguration() { dxgi.DXGIReportAdapterConfiguration(); } 49 | 50 | bool load_library_dxgi() { 51 | dxgi.dll = uif::injector::instance().load_real_library("dxgi.dll"); 52 | dxgi.ApplyCompatResolutionQuirking = GetProcAddress(dxgi.dll, "ApplyCompatResolutionQuirking"); 53 | dxgi.CompatString = GetProcAddress(dxgi.dll, "CompatString"); 54 | dxgi.CompatValue = GetProcAddress(dxgi.dll, "CompatValue"); 55 | dxgi.DXGIDumpJournal = GetProcAddress(dxgi.dll, "DXGIDumpJournal"); 56 | dxgi.PIXBeginCapture = GetProcAddress(dxgi.dll, "PIXBeginCapture"); 57 | dxgi.PIXEndCapture = GetProcAddress(dxgi.dll, "PIXEndCapture"); 58 | dxgi.PIXGetCaptureState = GetProcAddress(dxgi.dll, "PIXGetCaptureState"); 59 | dxgi.SetAppCompatStringPointer = GetProcAddress(dxgi.dll, "SetAppCompatStringPointer"); 60 | dxgi.UpdateHMDEmulationStatus = GetProcAddress(dxgi.dll, "UpdateHMDEmulationStatus"); 61 | dxgi.CreateDXGIFactory1 = GetProcAddress(dxgi.dll, "CreateDXGIFactory1"); 62 | dxgi.CreateDXGIFactory2 = GetProcAddress(dxgi.dll, "CreateDXGIFactory2"); 63 | dxgi.CreateDXGIFactory = GetProcAddress(dxgi.dll, "CreateDXGIFactory"); 64 | dxgi.DXGID3D10CreateDevice = GetProcAddress(dxgi.dll, "DXGID3D10CreateDevice"); 65 | dxgi.DXGID3D10CreateLayeredDevice = GetProcAddress(dxgi.dll, "DXGID3D10CreateLayeredDevice"); 66 | dxgi.DXGID3D10GetLayeredDeviceSize = GetProcAddress(dxgi.dll, "DXGID3D10GetLayeredDeviceSize"); 67 | dxgi.DXGID3D10RegisterLayers = GetProcAddress(dxgi.dll, "DXGID3D10RegisterLayers"); 68 | dxgi.DXGIDeclareAdapterRemovalSupport = GetProcAddress(dxgi.dll, "DXGIDeclareAdapterRemovalSupport"); 69 | dxgi.DXGIGetDebugInterface1 = GetProcAddress(dxgi.dll, "DXGIGetDebugInterface1"); 70 | dxgi.DXGIReportAdapterConfiguration = GetProcAddress(dxgi.dll, "DXGIReportAdapterConfiguration"); 71 | return true; 72 | } 73 | 74 | bool unload_library_dxgi() { 75 | FreeLibrary(dxgi.dll); 76 | dxgi.dll = nullptr; 77 | return true; 78 | } 79 | 80 | #else 81 | 82 | bool load_library_dxgi() { 83 | return false; 84 | } 85 | 86 | bool unload_library_dxgi() { 87 | return false; 88 | } 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/d3dcompiler_43.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #ifdef UIF_LIB_D3DCOMPILER_43 4 | 5 | #include "injector.h" 6 | 7 | struct { 8 | HMODULE dll; 9 | FARPROC D3DAssemble; 10 | FARPROC DebugSetMute; 11 | FARPROC D3DCompile; 12 | FARPROC D3DCompressShaders; 13 | FARPROC D3DCreateBlob; 14 | FARPROC D3DDecompressShaders; 15 | FARPROC D3DDisassemble10Effect; 16 | FARPROC D3DDisassemble; 17 | FARPROC D3DGetBlobPart; 18 | FARPROC D3DGetDebugInfo; 19 | FARPROC D3DGetInputAndOutputSignatureBlob; 20 | FARPROC D3DGetInputSignatureBlob; 21 | FARPROC D3DGetOutputSignatureBlob; 22 | FARPROC D3DPreprocess; 23 | FARPROC D3DReflect; 24 | FARPROC D3DReturnFailure1; 25 | FARPROC D3DStripShader; 26 | } d3dcompiler_43; 27 | 28 | void lib_d3dcompiler_43_D3DAssemble() { d3dcompiler_43.D3DAssemble(); } 29 | void lib_d3dcompiler_43_DebugSetMute() { d3dcompiler_43.DebugSetMute(); } 30 | void lib_d3dcompiler_43_D3DCompile() { d3dcompiler_43.D3DCompile(); } 31 | void lib_d3dcompiler_43_D3DCompressShaders() { d3dcompiler_43.D3DCompressShaders(); } 32 | void lib_d3dcompiler_43_D3DCreateBlob() { d3dcompiler_43.D3DCreateBlob(); } 33 | void lib_d3dcompiler_43_D3DDecompressShaders() { d3dcompiler_43.D3DDecompressShaders(); } 34 | void lib_d3dcompiler_43_D3DDisassemble10Effect() { d3dcompiler_43.D3DDisassemble10Effect(); } 35 | void lib_d3dcompiler_43_D3DDisassemble() { d3dcompiler_43.D3DDisassemble(); } 36 | void lib_d3dcompiler_43_D3DGetBlobPart() { d3dcompiler_43.D3DGetBlobPart(); } 37 | void lib_d3dcompiler_43_D3DGetDebugInfo() { d3dcompiler_43.D3DGetDebugInfo(); } 38 | void lib_d3dcompiler_43_D3DGetInputAndOutputSignatureBlob() { d3dcompiler_43.D3DGetInputAndOutputSignatureBlob(); } 39 | void lib_d3dcompiler_43_D3DGetInputSignatureBlob() { d3dcompiler_43.D3DGetInputSignatureBlob(); } 40 | void lib_d3dcompiler_43_D3DGetOutputSignatureBlob() { d3dcompiler_43.D3DGetOutputSignatureBlob(); } 41 | void lib_d3dcompiler_43_D3DPreprocess() { d3dcompiler_43.D3DPreprocess(); } 42 | void lib_d3dcompiler_43_D3DReflect() { d3dcompiler_43.D3DReflect(); } 43 | void lib_d3dcompiler_43_D3DReturnFailure1() { d3dcompiler_43.D3DReturnFailure1(); } 44 | void lib_d3dcompiler_43_D3DStripShader() { d3dcompiler_43.D3DStripShader(); } 45 | 46 | bool load_library_d3dcompiler_43() { 47 | d3dcompiler_43.dll = uif::injector::instance().load_real_library("d3dcompiler_43.dll"); 48 | d3dcompiler_43.D3DAssemble = GetProcAddress(d3dcompiler_43.dll, "D3DAssemble"); 49 | d3dcompiler_43.DebugSetMute = GetProcAddress(d3dcompiler_43.dll, "DebugSetMute"); 50 | d3dcompiler_43.D3DCompile = GetProcAddress(d3dcompiler_43.dll, "D3DCompile"); 51 | d3dcompiler_43.D3DCompressShaders = GetProcAddress(d3dcompiler_43.dll, "D3DCompressShaders"); 52 | d3dcompiler_43.D3DCreateBlob = GetProcAddress(d3dcompiler_43.dll, "D3DCreateBlob"); 53 | d3dcompiler_43.D3DDecompressShaders = GetProcAddress(d3dcompiler_43.dll, "D3DDecompressShaders"); 54 | d3dcompiler_43.D3DDisassemble10Effect = GetProcAddress(d3dcompiler_43.dll, "D3DDisassemble10Effect"); 55 | d3dcompiler_43.D3DDisassemble = GetProcAddress(d3dcompiler_43.dll, "D3DDisassemble"); 56 | d3dcompiler_43.D3DGetBlobPart = GetProcAddress(d3dcompiler_43.dll, "D3DGetBlobPart"); 57 | d3dcompiler_43.D3DGetDebugInfo = GetProcAddress(d3dcompiler_43.dll, "D3DGetDebugInfo"); 58 | d3dcompiler_43.D3DGetInputAndOutputSignatureBlob = GetProcAddress(d3dcompiler_43.dll, "D3DGetInputAndOutputSignatureBlob"); 59 | d3dcompiler_43.D3DGetInputSignatureBlob = GetProcAddress(d3dcompiler_43.dll, "D3DGetInputSignatureBlob"); 60 | d3dcompiler_43.D3DGetOutputSignatureBlob = GetProcAddress(d3dcompiler_43.dll, "D3DGetOutputSignatureBlob"); 61 | d3dcompiler_43.D3DPreprocess = GetProcAddress(d3dcompiler_43.dll, "D3DPreprocess"); 62 | d3dcompiler_43.D3DReflect = GetProcAddress(d3dcompiler_43.dll, "D3DReflect"); 63 | d3dcompiler_43.D3DReturnFailure1 = GetProcAddress(d3dcompiler_43.dll, "D3DReturnFailure1"); 64 | d3dcompiler_43.D3DStripShader = GetProcAddress(d3dcompiler_43.dll, "D3DStripShader"); 65 | return true; 66 | } 67 | 68 | bool unload_library_d3dcompiler_43() { 69 | FreeLibrary(d3dcompiler_43.dll); 70 | d3dcompiler_43.dll = nullptr; 71 | return true; 72 | } 73 | 74 | #else 75 | 76 | bool load_library_d3dcompiler_43() { 77 | return false; 78 | } 79 | 80 | bool unload_library_d3dcompiler_43() { 81 | return false; 82 | } 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/d3d9.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #ifdef UIF_LIB_D3D9 4 | 5 | #include "injector.h" 6 | 7 | struct { 8 | HMODULE dll; 9 | FARPROC Ordinal16; 10 | FARPROC Ordinal17; 11 | FARPROC Ordinal18; 12 | FARPROC Ordinal19; 13 | FARPROC Direct3DCreate9On12; 14 | FARPROC Direct3DCreate9On12Ex; 15 | FARPROC Ordinal22; 16 | FARPROC Ordinal23; 17 | FARPROC Direct3DShaderValidatorCreate9; 18 | FARPROC PSGPError; 19 | FARPROC PSGPSampleTexture; 20 | FARPROC D3DPERF_BeginEvent; 21 | FARPROC D3DPERF_EndEvent; 22 | FARPROC D3DPERF_GetStatus; 23 | FARPROC D3DPERF_QueryRepeatFrame; 24 | FARPROC D3DPERF_SetMarker; 25 | FARPROC D3DPERF_SetOptions; 26 | FARPROC D3DPERF_SetRegion; 27 | FARPROC DebugSetLevel; 28 | FARPROC DebugSetMute; 29 | FARPROC Direct3D9EnableMaximizedWindowedModeShim; 30 | FARPROC Direct3DCreate9; 31 | FARPROC Direct3DCreate9Ex; 32 | } d3d9; 33 | 34 | void lib_d3d9_Ordinal16() { d3d9.Ordinal16(); } 35 | void lib_d3d9_Ordinal17() { d3d9.Ordinal17(); } 36 | void lib_d3d9_Ordinal18() { d3d9.Ordinal18(); } 37 | void lib_d3d9_Ordinal19() { d3d9.Ordinal19(); } 38 | void lib_d3d9_Direct3DCreate9On12() { d3d9.Direct3DCreate9On12(); } 39 | void lib_d3d9_Direct3DCreate9On12Ex() { d3d9.Direct3DCreate9On12Ex(); } 40 | void lib_d3d9_Ordinal22() { d3d9.Ordinal22(); } 41 | void lib_d3d9_Ordinal23() { d3d9.Ordinal23(); } 42 | void lib_d3d9_Direct3DShaderValidatorCreate9() { d3d9.Direct3DShaderValidatorCreate9(); } 43 | void lib_d3d9_PSGPError() { d3d9.PSGPError(); } 44 | void lib_d3d9_PSGPSampleTexture() { d3d9.PSGPSampleTexture(); } 45 | void lib_d3d9_D3DPERF_BeginEvent() { d3d9.D3DPERF_BeginEvent(); } 46 | void lib_d3d9_D3DPERF_EndEvent() { d3d9.D3DPERF_EndEvent(); } 47 | void lib_d3d9_D3DPERF_GetStatus() { d3d9.D3DPERF_GetStatus(); } 48 | void lib_d3d9_D3DPERF_QueryRepeatFrame() { d3d9.D3DPERF_QueryRepeatFrame(); } 49 | void lib_d3d9_D3DPERF_SetMarker() { d3d9.D3DPERF_SetMarker(); } 50 | void lib_d3d9_D3DPERF_SetOptions() { d3d9.D3DPERF_SetOptions(); } 51 | void lib_d3d9_D3DPERF_SetRegion() { d3d9.D3DPERF_SetRegion(); } 52 | void lib_d3d9_DebugSetLevel() { d3d9.DebugSetLevel(); } 53 | void lib_d3d9_DebugSetMute() { d3d9.DebugSetMute(); } 54 | void lib_d3d9_Direct3D9EnableMaximizedWindowedModeShim() { d3d9.Direct3D9EnableMaximizedWindowedModeShim(); } 55 | void lib_d3d9_Direct3DCreate9() { d3d9.Direct3DCreate9(); } 56 | void lib_d3d9_Direct3DCreate9Ex() { d3d9.Direct3DCreate9Ex(); } 57 | 58 | bool load_library_d3d9() { 59 | d3d9.dll = uif::injector::instance().load_real_library("d3d9.dll"); 60 | d3d9.Ordinal16 = GetProcAddress(d3d9.dll, MAKEINTRESOURCEA(16)); 61 | d3d9.Ordinal17 = GetProcAddress(d3d9.dll, MAKEINTRESOURCEA(17)); 62 | d3d9.Ordinal18 = GetProcAddress(d3d9.dll, MAKEINTRESOURCEA(18)); 63 | d3d9.Ordinal19 = GetProcAddress(d3d9.dll, MAKEINTRESOURCEA(19)); 64 | d3d9.Direct3DCreate9On12 = GetProcAddress(d3d9.dll, "Direct3DCreate9On12"); 65 | d3d9.Direct3DCreate9On12Ex = GetProcAddress(d3d9.dll, "Direct3DCreate9On12Ex"); 66 | d3d9.Ordinal22 = GetProcAddress(d3d9.dll, MAKEINTRESOURCEA(22)); 67 | d3d9.Ordinal23 = GetProcAddress(d3d9.dll, MAKEINTRESOURCEA(23)); 68 | d3d9.Direct3DShaderValidatorCreate9 = GetProcAddress(d3d9.dll, "Direct3DShaderValidatorCreate9"); 69 | d3d9.PSGPError = GetProcAddress(d3d9.dll, "PSGPError"); 70 | d3d9.PSGPSampleTexture = GetProcAddress(d3d9.dll, "PSGPSampleTexture"); 71 | d3d9.D3DPERF_BeginEvent = GetProcAddress(d3d9.dll, "D3DPERF_BeginEvent"); 72 | d3d9.D3DPERF_EndEvent = GetProcAddress(d3d9.dll, "D3DPERF_EndEvent"); 73 | d3d9.D3DPERF_GetStatus = GetProcAddress(d3d9.dll, "D3DPERF_GetStatus"); 74 | d3d9.D3DPERF_QueryRepeatFrame = GetProcAddress(d3d9.dll, "D3DPERF_QueryRepeatFrame"); 75 | d3d9.D3DPERF_SetMarker = GetProcAddress(d3d9.dll, "D3DPERF_SetMarker"); 76 | d3d9.D3DPERF_SetOptions = GetProcAddress(d3d9.dll, "D3DPERF_SetOptions"); 77 | d3d9.D3DPERF_SetRegion = GetProcAddress(d3d9.dll, "D3DPERF_SetRegion"); 78 | d3d9.DebugSetLevel = GetProcAddress(d3d9.dll, "DebugSetLevel"); 79 | d3d9.DebugSetMute = GetProcAddress(d3d9.dll, "DebugSetMute"); 80 | d3d9.Direct3D9EnableMaximizedWindowedModeShim = GetProcAddress(d3d9.dll, "Direct3D9EnableMaximizedWindowedModeShim"); 81 | d3d9.Direct3DCreate9 = GetProcAddress(d3d9.dll, "Direct3DCreate9"); 82 | d3d9.Direct3DCreate9Ex = GetProcAddress(d3d9.dll, "Direct3DCreate9Ex"); 83 | return true; 84 | } 85 | 86 | bool unload_library_d3d9() { 87 | FreeLibrary(d3d9.dll); 88 | d3d9.dll = nullptr; 89 | return true; 90 | } 91 | 92 | #else 93 | 94 | bool load_library_d3d9() { 95 | return false; 96 | } 97 | 98 | bool unload_library_d3d9() { 99 | return false; 100 | } 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/window_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "window_manager.h" 3 | 4 | #include "ansi.h" 5 | #include "config.h" 6 | #include "encoding.h" 7 | #include "hooks.h" 8 | #include "injector.h" 9 | #include "utils.h" 10 | 11 | using namespace uif::ansi; 12 | 13 | #pragma region Hooks 14 | 15 | static LRESULT WINAPI DefWindowProcWHook(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) 16 | { 17 | switch (Msg) 18 | { 19 | case WM_NCCREATE: 20 | { 21 | CREATESTRUCTW paramsW{}; 22 | memcpy(¶msW, reinterpret_cast(lParam), sizeof(CREATESTRUCTW)); 23 | 24 | const auto& windowMgr = uif::injector::instance().feature(); 25 | std::wstring windowTitle = paramsW.lpszName; 26 | windowMgr.process_title(windowTitle); 27 | paramsW.lpszName = windowTitle.c_str(); 28 | 29 | return DefWindowProcW(hWnd, Msg, wParam, reinterpret_cast(¶msW)); 30 | } 31 | 32 | case WM_SETTEXT: 33 | { 34 | const auto& windowMgr = uif::injector::instance().feature(); 35 | std::wstring windowTitle = reinterpret_cast(lParam); 36 | windowMgr.process_title(windowTitle); 37 | return DefWindowProcW(hWnd, Msg, wParam, reinterpret_cast(windowTitle.c_str())); 38 | } 39 | 40 | default: 41 | return DefWindowProcW(hWnd, Msg, wParam, lParam); 42 | } 43 | } 44 | 45 | static LRESULT WINAPI DefWindowProcAHook(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) 46 | { 47 | switch (Msg) 48 | { 49 | case WM_NCCREATE: 50 | { 51 | const auto* paramsA = reinterpret_cast(lParam); 52 | CREATESTRUCTW paramsW{}; 53 | memcpy(¶msW, paramsA, sizeof(CREATESTRUCTW)); 54 | 55 | const auto className = encoding::shiftjis_to_utf16(paramsA->lpszClass); 56 | paramsW.lpszClass = className.c_str(); 57 | 58 | const auto& windowMgr = uif::injector::instance().feature(); 59 | const auto windowTitle = windowMgr.process_title(paramsA->lpszName); 60 | paramsW.lpszName = windowTitle.c_str(); 61 | 62 | return DefWindowProcW(hWnd, Msg, wParam, reinterpret_cast(¶msW)); 63 | } 64 | 65 | case WM_SETTEXT: 66 | { 67 | const auto& windowMgr = uif::injector::instance().feature(); 68 | const auto windowTitle = windowMgr.process_title(reinterpret_cast(lParam)); 69 | return DefWindowProcW(hWnd, Msg, wParam, reinterpret_cast(windowTitle.c_str())); 70 | } 71 | 72 | default: 73 | return DefWindowProcA(hWnd, Msg, wParam, lParam); 74 | } 75 | } 76 | 77 | #pragma endregion 78 | 79 | static BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) 80 | { 81 | auto* windows = reinterpret_cast*>(lParam); 82 | 83 | DWORD windowProcessId = 0; 84 | GetWindowThreadProcessId(hWnd, &windowProcessId); 85 | if (windowProcessId == GetCurrentProcessId()) 86 | windows->push_back(hWnd); 87 | 88 | return TRUE; 89 | } 90 | 91 | void uif::features::window_manager::initialize() 92 | { 93 | if (config().contains("overwrite_title")) 94 | { 95 | overwrite_title = true; 96 | overwrite_title_value = encoding::utf8_to_utf16(config().value("overwrite_title", "")); 97 | } 98 | 99 | if (config().value("process_existing_windows", false)) 100 | { 101 | std::vector windows{}; 102 | EnumWindows(EnumWindowsProc, reinterpret_cast(&windows)); 103 | 104 | for (const auto window : windows) 105 | { 106 | std::string title; 107 | title.resize(1024); 108 | title.resize(GetWindowTextA(window, title.data(), static_cast(title.length()))); 109 | std::wstring processed = process_title(title); 110 | DefWindowProcW(window, WM_SETTEXT, 0, reinterpret_cast(processed.c_str())); 111 | } 112 | } 113 | 114 | hooks::hook_import(this, "DefWindowProcA", DefWindowProcAHook); 115 | hooks::hook_import(this, "DefWindowProcW", DefWindowProcWHook); 116 | } 117 | 118 | void uif::features::window_manager::finalize() 119 | { 120 | hooks::unhook_import(this, "DefWindowProcA", DefWindowProcAHook); 121 | hooks::unhook_import(this, "DefWindowProcW", DefWindowProcWHook); 122 | } 123 | 124 | std::wstring uif::features::window_manager::process_title(const std::string& title) const 125 | { 126 | auto wide = utils::normalize(title); 127 | process_title_no_normalize(wide); 128 | return wide; 129 | } 130 | 131 | void uif::features::window_manager::process_title(std::wstring& title) const 132 | { 133 | utils::normalize(title); 134 | process_title_no_normalize(title); 135 | } 136 | 137 | void uif::features::window_manager::process_title_no_normalize(std::wstring& title) const 138 | { 139 | if (overwrite_title) 140 | title.assign(overwrite_title_value); 141 | } 142 | -------------------------------------------------------------------------------- /src/ProxyGenerator/ProxyGenerator.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 | 23 | 24 | 25 | 26 | {962a7719-2381-40d0-8214-377689f9429a} 27 | 28 | 29 | 30 | 16.0 31 | Win32Proj 32 | {024cf2e7-6985-4536-b063-55822e5f2696} 33 | ProxyGenerator 34 | 10.0 35 | 36 | 37 | 38 | Application 39 | true 40 | v143 41 | Unicode 42 | 43 | 44 | Application 45 | false 46 | v143 47 | true 48 | Unicode 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | true 59 | 60 | 61 | false 62 | 63 | 64 | 65 | 66 | Level3 67 | true 68 | true 69 | stdcpp17 70 | 71 | 72 | Console 73 | true 74 | 75 | 76 | 77 | 78 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 79 | 80 | 81 | 82 | 83 | true 84 | true 85 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 86 | 87 | 88 | true 89 | true 90 | 91 | 92 | 93 | 94 | WIN32;%(PreprocessorDefinitions) 95 | 96 | 97 | 98 | $(SolutionDir)Build\$(ProjectName)\$(Platform)\$(Configuration)\ 99 | $(SolutionDir)Build\$(ProjectName)\$(Platform)\$(Configuration)\obj\ 100 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)$(ProjectName); 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /src/ProxyGenerator/main.cpp: -------------------------------------------------------------------------------- 1 | #define WIN32_LEAN_AND_MEAN 2 | #include "Windows.h" 3 | #include "../Detours/detours.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | HMODULE load_library(const char* name) 11 | { 12 | const auto module = LoadLibraryExA(name, nullptr, DONT_RESOLVE_DLL_REFERENCES); 13 | return module; 14 | } 15 | 16 | struct export_symbol 17 | { 18 | const unsigned long ordinal; 19 | const std::string name; 20 | const std::string safe_name; 21 | const bool has_name; 22 | }; 23 | 24 | std::string get_safe_name(std::string name) 25 | { 26 | for (char& ch : name) 27 | { 28 | if (!IsCharAlphaNumericA(ch)) 29 | { 30 | ch = '_'; 31 | } 32 | } 33 | 34 | return name; 35 | } 36 | 37 | std::vector enumerate_exports(HMODULE moduleHandle) 38 | { 39 | std::vector symbols; 40 | 41 | // Microsoft documentation states that "When you specify ordinal values, they must be 42 | // in the range 1 through N, where N is the number of functions exported by the DLL." 43 | // This, however, is incorrect, and many system DLLs do not follow the rule. 44 | auto enum_proc = [](PVOID pContext, ULONG nOrdinal, LPCSTR pszName, PVOID pCode) -> BOOL 45 | { 46 | auto* symbols = static_cast*>(pContext); 47 | if(pszName) 48 | { 49 | symbols->push_back({ nOrdinal, pszName, get_safe_name(pszName), true}); 50 | } 51 | else 52 | { 53 | const std::string dummyName = "Ordinal" + std::to_string(nOrdinal); 54 | symbols->push_back({ nOrdinal, dummyName, dummyName, false }); 55 | } 56 | return true; 57 | }; 58 | 59 | DetourEnumerateExports(moduleHandle, &symbols, enum_proc); 60 | return symbols; 61 | } 62 | 63 | bool generate_module_definition(const std::string& dllName, const std::vector& exports) 64 | { 65 | std::ofstream file; 66 | file.open(dllName + ".def"); 67 | if(!file.is_open()) 68 | return false; 69 | 70 | file << "LIBRARY " << dllName << "\n"; 71 | file << "EXPORTS\n"; 72 | 73 | for(const auto& symbol : exports) 74 | { 75 | file << '\t' << symbol.name << "=lib_" << dllName << '_' << symbol.safe_name << " @" << symbol.ordinal << (symbol.has_name ? "\n" : " NONAME\n"); 76 | } 77 | 78 | return true; 79 | } 80 | 81 | bool generate_cpp_file(const std::string& dllName, const std::vector& exports) 82 | { 83 | std::string ucName{ dllName }; 84 | CharUpperA(&ucName[0]); 85 | 86 | std::ofstream file; 87 | file.open(dllName + ".cpp"); 88 | if(!file.is_open()) 89 | return false; 90 | 91 | file << "#include \"pch.h\"\n\n"; 92 | file << "#ifdef UIF_LIB_" << ucName << "\n\n"; 93 | file << "#include \"injector.h\"\n\n"; 94 | file << "struct {\n"; 95 | file << "\tHMODULE dll;\n"; 96 | 97 | for(const auto& symbol : exports) 98 | { 99 | file << "\tFARPROC " << symbol.safe_name << ";\n"; 100 | } 101 | 102 | file << "} " << dllName << ";\n\n"; 103 | 104 | for(const auto& symbol : exports) 105 | { 106 | file << "void lib_" << dllName << '_' << symbol.safe_name << "() { " << dllName << '.' << symbol.safe_name << "(); }\n"; 107 | } 108 | 109 | file << "\nbool load_library_" << dllName << "() {\n"; 110 | file << '\t' << dllName << ".dll = uif::injector::instance().load_real_library(\"" << dllName << ".dll\");\n"; 111 | 112 | for(const auto& symbol : exports) 113 | { 114 | file << '\t' << dllName << '.' << symbol.safe_name << " = GetProcAddress(" << dllName << ".dll, "; 115 | if(symbol.has_name) 116 | { 117 | file << '"' << symbol.safe_name << "\");\n"; 118 | } 119 | else 120 | { 121 | file << "MAKEINTRESOURCEA(" << symbol.ordinal << "));\n"; 122 | } 123 | } 124 | 125 | file << "\treturn true;\n"; 126 | file << "}\n\n"; 127 | file << "bool unload_library_" << dllName << "() {\n"; 128 | file << "\tFreeLibrary(" << dllName << ".dll);\n"; 129 | file << "\t" << dllName << ".dll = nullptr;\n"; 130 | file << "\treturn true;\n"; 131 | file << "}\n\n"; 132 | file << "#else\n\n"; 133 | file << "bool load_library_" << dllName << "() {\n"; 134 | file << "\treturn false;\n"; 135 | file << "}\n\n"; 136 | file << "bool unload_library_" << dllName << "() {\n"; 137 | file << "\treturn false;\n"; 138 | file << "}\n\n"; 139 | file << "#endif\n"; 140 | 141 | return true; 142 | } 143 | 144 | bool generate_header_file(const std::string& dllName, const std::vector& exports) 145 | { 146 | std::ofstream file; 147 | file.open(dllName + ".h"); 148 | if(!file.is_open()) 149 | return false; 150 | 151 | file << "#pragma once\n\n"; 152 | file << "bool load_library_" << dllName << "();\n"; 153 | file << "bool unload_library_" << dllName << "();\n"; 154 | 155 | return true; 156 | } 157 | 158 | bool generate_files(const std::string& dllPath, const std::vector& exports) 159 | { 160 | const auto startIndex = dllPath.find_last_of("\\/") + 1; 161 | auto endIndex = dllPath.find_last_of('.'); 162 | if(endIndex == std::string::npos) endIndex = dllPath.length(); 163 | 164 | const std::string dllName = get_safe_name(dllPath.substr(startIndex, endIndex - startIndex)); 165 | 166 | if(!generate_module_definition(dllName, exports)) 167 | return false; 168 | 169 | if(!generate_cpp_file(dllName, exports)) 170 | return false; 171 | 172 | if(!generate_header_file(dllName, exports)) 173 | return false; 174 | 175 | return true; 176 | } 177 | 178 | int main(int argc, const char** argv) 179 | { 180 | if(argc < 2) 181 | { 182 | std::cout << "Usage: ProxyGenerator.exe \"path\\to\\library.dll\"\n"; 183 | std::cin.get(); 184 | return 1; 185 | } 186 | 187 | const auto dllPath = argv[1]; 188 | const auto hModule = load_library(dllPath); 189 | 190 | if(!hModule) 191 | { 192 | std::cout << "Unable to load " << dllPath << "\n"; 193 | return 1; 194 | } 195 | 196 | const auto exports = enumerate_exports(hModule); 197 | 198 | for(const auto& symbol : exports) { 199 | std::cout << symbol.ordinal << ": " << symbol.name << "\n"; 200 | } 201 | 202 | if(!generate_files(dllPath, exports)) 203 | { 204 | std::cout << "Failed to generate files\n"; 205 | return 1; 206 | } 207 | 208 | return 0; 209 | } 210 | 211 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "utils.h" 3 | 4 | #include 5 | #include 6 | 7 | #include "ansi.h" 8 | #include "encoding.h" 9 | #include "injector.h" 10 | #include "features/character_substitution.h" 11 | #include "features/tunnel_decoder.h" 12 | 13 | using namespace uif::ansi; 14 | 15 | namespace uif::utils 16 | { 17 | bool file_exists(const wchar_t* path) 18 | { 19 | const auto attributes = GetFileAttributes(path); 20 | return attributes != INVALID_FILE_ATTRIBUTES && 21 | !(attributes & FILE_ATTRIBUTE_DIRECTORY); 22 | } 23 | 24 | bool file_create_new(const wchar_t* path, const char* content, size_t length) 25 | { 26 | if(file_exists(path)) 27 | return false; 28 | 29 | auto* const handle = CreateFile(path, GENERIC_WRITE, NULL, nullptr, CREATE_ALWAYS, NULL, nullptr); 30 | while(length > 0) { 31 | DWORD written; 32 | if(!WriteFile(handle, content, static_cast(length), &written, nullptr)) 33 | return false; 34 | content += written; 35 | length -= written; 36 | } 37 | 38 | CloseHandle(handle); 39 | return true; 40 | } 41 | 42 | void patch_memory(void* address, const void* data, size_t size, void* oldDataBuffer) 43 | { 44 | DWORD origProtect; 45 | VirtualProtect(address, size, PAGE_READWRITE, &origProtect); 46 | if(oldDataBuffer) memcpy(oldDataBuffer, address, size); 47 | memcpy(address, data, size); 48 | VirtualProtect(address, size, origProtect, &origProtect); 49 | } 50 | 51 | void patch_address(void** patchAddress, void* patchValue) 52 | { 53 | DWORD origProtect; 54 | VirtualProtect(patchAddress, sizeof(patchValue), PAGE_READWRITE, &origProtect); 55 | *patchAddress = patchValue; 56 | VirtualProtect(patchAddress, sizeof(patchValue), origProtect, &origProtect); 57 | } 58 | 59 | void* parse_address(const nlohmann::json& json) 60 | { 61 | if(json.is_string()) 62 | return parse_address(json.get()); 63 | 64 | if(json.is_number_integer()) 65 | return GetModuleHandleA(nullptr) + json.get(); 66 | 67 | std::cout << white("[injector]") << dark_red(" Error:") << 68 | " Failed to parse address " << blue('<') << blue(json.type_name()) << blue('>') << ": invalid json type\n"; 69 | 70 | return nullptr; 71 | } 72 | 73 | void* parse_address(const std::string& string) 74 | { 75 | const bool isHex = string.ends_with('h') || string.ends_with('H'); 76 | const size_t offsetStartIndex = string.find_last_of('+') + 1; 77 | const std::string offsetString = string.substr(offsetStartIndex, string.length() - offsetStartIndex - isHex); 78 | 79 | uintptr_t address = std::stoul(offsetString, nullptr, isHex ? 16 : 10); 80 | 81 | if(offsetStartIndex != 0) 82 | { 83 | const std::string moduleName = string.substr(0, offsetStartIndex - 1); 84 | const HMODULE hModule = GetModuleHandleA(moduleName.c_str()); 85 | if(!hModule) 86 | { 87 | std::cout << white("[injector]") << dark_red(" Error:") << 88 | " Failed to parse address " << blue(string) << ": unable to resolve module " << yellow(moduleName) << '\n'; 89 | return nullptr; 90 | } 91 | 92 | address += reinterpret_cast(hModule); 93 | } 94 | else 95 | { 96 | address += reinterpret_cast(GetModuleHandleA(nullptr)); 97 | } 98 | 99 | return reinterpret_cast(address); 100 | } 101 | 102 | std::filesystem::path get_dll_path() 103 | { 104 | TCHAR path[MAX_PATH]; 105 | HMODULE hm = nullptr; 106 | 107 | GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | 108 | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, 109 | reinterpret_cast(&get_dll_path), &hm); 110 | 111 | GetModuleFileName(hm, path, MAX_PATH); 112 | 113 | return { path }; 114 | } 115 | 116 | std::string get_module_name(HMODULE hModule) 117 | { 118 | char dllNameBuffer[MAX_PATH]; 119 | if(GetModuleFileNameA(hModule, dllNameBuffer, MAX_PATH) == 0) 120 | return ""; 121 | const char* dllName = strrchr(dllNameBuffer, '\\'); 122 | if (dllName == nullptr) dllName = dllNameBuffer; 123 | else dllName++; 124 | return dllName; 125 | } 126 | 127 | // https://stackoverflow.com/a/17387176/7391324 128 | std::string get_last_error_message(DWORD error) 129 | { 130 | if (error == 0) error = GetLastError(); 131 | if (error == 0) return "No error"; 132 | 133 | LPSTR messageBuffer = nullptr; 134 | 135 | const size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 136 | nullptr, error, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), reinterpret_cast(&messageBuffer), 0, nullptr); 137 | 138 | std::string message(messageBuffer, size); 139 | message.erase(std::find_if(message.rbegin(), message.rend(), [](unsigned char ch) { return !std::isspace(ch) && ch != '.'; }).base(), message.end()); 140 | 141 | LocalFree(messageBuffer); 142 | 143 | return message; 144 | } 145 | 146 | void normalize(std::wstring& text) 147 | { 148 | const auto* substitution = injector::instance().try_get_feature(); 149 | 150 | if (substitution && substitution->is_enabled()) 151 | { 152 | substitution->substitute(text); 153 | } 154 | } 155 | 156 | std::wstring normalize(const std::string& text) 157 | { 158 | const auto* decoder = injector::instance().try_get_feature(); 159 | 160 | std::wstring wide; 161 | if (decoder && decoder->is_enabled()) 162 | { 163 | wide = encoding::decode_shiftjis_tunnel(text.c_str(), static_cast(text.length()), decoder->mapping); 164 | } 165 | else 166 | { 167 | wide = encoding::shiftjis_to_utf16(text); 168 | } 169 | 170 | normalize(wide); 171 | return wide; 172 | } 173 | 174 | WORD set_console_color(const WORD color) 175 | { 176 | CONSOLE_SCREEN_BUFFER_INFO info; 177 | auto* const hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 178 | GetConsoleScreenBufferInfo(hStdout, &info); 179 | SetConsoleTextAttribute(hStdout, color); 180 | return info.wAttributes; 181 | } 182 | 183 | void print_colored(const char* text, const WORD color) 184 | { 185 | const auto prev = set_console_color(color); 186 | std::cout << text; 187 | set_console_color(prev); 188 | } 189 | 190 | [[noreturn]] 191 | void fail(const std::string& reason) 192 | { 193 | MessageBoxA(nullptr, reason.c_str(), "Universal Injector", MB_OK | MB_ICONERROR); 194 | ExitProcess(-1); 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /src/Detours/Detours.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 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 16.0 38 | Win32Proj 39 | {962a7719-2381-40d0-8214-377689f9429a} 40 | Detours 41 | 10.0 42 | 43 | 44 | 45 | StaticLibrary 46 | true 47 | v143 48 | Unicode 49 | 50 | 51 | StaticLibrary 52 | false 53 | v143 54 | true 55 | Unicode 56 | 57 | 58 | StaticLibrary 59 | true 60 | v143 61 | Unicode 62 | 63 | 64 | StaticLibrary 65 | false 66 | v143 67 | true 68 | Unicode 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | $(SolutionDir)Build\$(ProjectName)\$(Platform)\$(Configuration)\ 90 | $(SolutionDir)Build\$(ProjectName)\$(Platform)\$(Configuration)\obj\ 91 | 92 | 93 | true 94 | 95 | 96 | false 97 | 98 | 99 | 100 | Level3 101 | true 102 | _DEBUG;_LIB;%(PreprocessorDefinitions) 103 | true 104 | 105 | 106 | 107 | 108 | true 109 | 110 | 111 | 112 | 113 | Level3 114 | true 115 | true 116 | true 117 | NDEBUG;_LIB;%(PreprocessorDefinitions) 118 | true 119 | 120 | 121 | 122 | 123 | true 124 | true 125 | true 126 | 127 | 128 | 129 | 130 | WIN32;%(PreprocessorDefinitions) 131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/d3dcompiler_47.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #ifdef UIF_LIB_D3DCOMPILER_47 4 | 5 | #include "injector.h" 6 | 7 | struct { 8 | HMODULE dll; 9 | FARPROC D3DAssemble; 10 | FARPROC DebugSetMute; 11 | FARPROC D3DCompile2; 12 | FARPROC D3DCompile; 13 | FARPROC D3DCompileFromFile; 14 | FARPROC D3DCompressShaders; 15 | FARPROC D3DCreateBlob; 16 | FARPROC D3DCreateFunctionLinkingGraph; 17 | FARPROC D3DCreateLinker; 18 | FARPROC D3DDecompressShaders; 19 | FARPROC D3DDisassemble10Effect; 20 | FARPROC D3DDisassemble11Trace; 21 | FARPROC D3DDisassemble; 22 | FARPROC D3DDisassembleRegion; 23 | FARPROC D3DGetBlobPart; 24 | FARPROC D3DGetDebugInfo; 25 | FARPROC D3DGetInputAndOutputSignatureBlob; 26 | FARPROC D3DGetInputSignatureBlob; 27 | FARPROC D3DGetOutputSignatureBlob; 28 | FARPROC D3DGetTraceInstructionOffsets; 29 | FARPROC D3DLoadModule; 30 | FARPROC D3DPreprocess; 31 | FARPROC D3DReadFileToBlob; 32 | FARPROC D3DReflect; 33 | FARPROC D3DReflectLibrary; 34 | FARPROC D3DReturnFailure1; 35 | FARPROC D3DSetBlobPart; 36 | FARPROC D3DStripShader; 37 | FARPROC D3DWriteBlobToFile; 38 | } d3dcompiler_47; 39 | 40 | void lib_d3dcompiler_47_D3DAssemble() { d3dcompiler_47.D3DAssemble(); } 41 | void lib_d3dcompiler_47_DebugSetMute() { d3dcompiler_47.DebugSetMute(); } 42 | void lib_d3dcompiler_47_D3DCompile2() { d3dcompiler_47.D3DCompile2(); } 43 | void lib_d3dcompiler_47_D3DCompile() { d3dcompiler_47.D3DCompile(); } 44 | void lib_d3dcompiler_47_D3DCompileFromFile() { d3dcompiler_47.D3DCompileFromFile(); } 45 | void lib_d3dcompiler_47_D3DCompressShaders() { d3dcompiler_47.D3DCompressShaders(); } 46 | void lib_d3dcompiler_47_D3DCreateBlob() { d3dcompiler_47.D3DCreateBlob(); } 47 | void lib_d3dcompiler_47_D3DCreateFunctionLinkingGraph() { d3dcompiler_47.D3DCreateFunctionLinkingGraph(); } 48 | void lib_d3dcompiler_47_D3DCreateLinker() { d3dcompiler_47.D3DCreateLinker(); } 49 | void lib_d3dcompiler_47_D3DDecompressShaders() { d3dcompiler_47.D3DDecompressShaders(); } 50 | void lib_d3dcompiler_47_D3DDisassemble10Effect() { d3dcompiler_47.D3DDisassemble10Effect(); } 51 | void lib_d3dcompiler_47_D3DDisassemble11Trace() { d3dcompiler_47.D3DDisassemble11Trace(); } 52 | void lib_d3dcompiler_47_D3DDisassemble() { d3dcompiler_47.D3DDisassemble(); } 53 | void lib_d3dcompiler_47_D3DDisassembleRegion() { d3dcompiler_47.D3DDisassembleRegion(); } 54 | void lib_d3dcompiler_47_D3DGetBlobPart() { d3dcompiler_47.D3DGetBlobPart(); } 55 | void lib_d3dcompiler_47_D3DGetDebugInfo() { d3dcompiler_47.D3DGetDebugInfo(); } 56 | void lib_d3dcompiler_47_D3DGetInputAndOutputSignatureBlob() { d3dcompiler_47.D3DGetInputAndOutputSignatureBlob(); } 57 | void lib_d3dcompiler_47_D3DGetInputSignatureBlob() { d3dcompiler_47.D3DGetInputSignatureBlob(); } 58 | void lib_d3dcompiler_47_D3DGetOutputSignatureBlob() { d3dcompiler_47.D3DGetOutputSignatureBlob(); } 59 | void lib_d3dcompiler_47_D3DGetTraceInstructionOffsets() { d3dcompiler_47.D3DGetTraceInstructionOffsets(); } 60 | void lib_d3dcompiler_47_D3DLoadModule() { d3dcompiler_47.D3DLoadModule(); } 61 | void lib_d3dcompiler_47_D3DPreprocess() { d3dcompiler_47.D3DPreprocess(); } 62 | void lib_d3dcompiler_47_D3DReadFileToBlob() { d3dcompiler_47.D3DReadFileToBlob(); } 63 | void lib_d3dcompiler_47_D3DReflect() { d3dcompiler_47.D3DReflect(); } 64 | void lib_d3dcompiler_47_D3DReflectLibrary() { d3dcompiler_47.D3DReflectLibrary(); } 65 | void lib_d3dcompiler_47_D3DReturnFailure1() { d3dcompiler_47.D3DReturnFailure1(); } 66 | void lib_d3dcompiler_47_D3DSetBlobPart() { d3dcompiler_47.D3DSetBlobPart(); } 67 | void lib_d3dcompiler_47_D3DStripShader() { d3dcompiler_47.D3DStripShader(); } 68 | void lib_d3dcompiler_47_D3DWriteBlobToFile() { d3dcompiler_47.D3DWriteBlobToFile(); } 69 | 70 | bool load_library_d3dcompiler_47() { 71 | d3dcompiler_47.dll = uif::injector::instance().load_real_library("d3dcompiler_47.dll"); 72 | d3dcompiler_47.D3DAssemble = GetProcAddress(d3dcompiler_47.dll, "D3DAssemble"); 73 | d3dcompiler_47.DebugSetMute = GetProcAddress(d3dcompiler_47.dll, "DebugSetMute"); 74 | d3dcompiler_47.D3DCompile2 = GetProcAddress(d3dcompiler_47.dll, "D3DCompile2"); 75 | d3dcompiler_47.D3DCompile = GetProcAddress(d3dcompiler_47.dll, "D3DCompile"); 76 | d3dcompiler_47.D3DCompileFromFile = GetProcAddress(d3dcompiler_47.dll, "D3DCompileFromFile"); 77 | d3dcompiler_47.D3DCompressShaders = GetProcAddress(d3dcompiler_47.dll, "D3DCompressShaders"); 78 | d3dcompiler_47.D3DCreateBlob = GetProcAddress(d3dcompiler_47.dll, "D3DCreateBlob"); 79 | d3dcompiler_47.D3DCreateFunctionLinkingGraph = GetProcAddress(d3dcompiler_47.dll, "D3DCreateFunctionLinkingGraph"); 80 | d3dcompiler_47.D3DCreateLinker = GetProcAddress(d3dcompiler_47.dll, "D3DCreateLinker"); 81 | d3dcompiler_47.D3DDecompressShaders = GetProcAddress(d3dcompiler_47.dll, "D3DDecompressShaders"); 82 | d3dcompiler_47.D3DDisassemble10Effect = GetProcAddress(d3dcompiler_47.dll, "D3DDisassemble10Effect"); 83 | d3dcompiler_47.D3DDisassemble11Trace = GetProcAddress(d3dcompiler_47.dll, "D3DDisassemble11Trace"); 84 | d3dcompiler_47.D3DDisassemble = GetProcAddress(d3dcompiler_47.dll, "D3DDisassemble"); 85 | d3dcompiler_47.D3DDisassembleRegion = GetProcAddress(d3dcompiler_47.dll, "D3DDisassembleRegion"); 86 | d3dcompiler_47.D3DGetBlobPart = GetProcAddress(d3dcompiler_47.dll, "D3DGetBlobPart"); 87 | d3dcompiler_47.D3DGetDebugInfo = GetProcAddress(d3dcompiler_47.dll, "D3DGetDebugInfo"); 88 | d3dcompiler_47.D3DGetInputAndOutputSignatureBlob = GetProcAddress(d3dcompiler_47.dll, "D3DGetInputAndOutputSignatureBlob"); 89 | d3dcompiler_47.D3DGetInputSignatureBlob = GetProcAddress(d3dcompiler_47.dll, "D3DGetInputSignatureBlob"); 90 | d3dcompiler_47.D3DGetOutputSignatureBlob = GetProcAddress(d3dcompiler_47.dll, "D3DGetOutputSignatureBlob"); 91 | d3dcompiler_47.D3DGetTraceInstructionOffsets = GetProcAddress(d3dcompiler_47.dll, "D3DGetTraceInstructionOffsets"); 92 | d3dcompiler_47.D3DLoadModule = GetProcAddress(d3dcompiler_47.dll, "D3DLoadModule"); 93 | d3dcompiler_47.D3DPreprocess = GetProcAddress(d3dcompiler_47.dll, "D3DPreprocess"); 94 | d3dcompiler_47.D3DReadFileToBlob = GetProcAddress(d3dcompiler_47.dll, "D3DReadFileToBlob"); 95 | d3dcompiler_47.D3DReflect = GetProcAddress(d3dcompiler_47.dll, "D3DReflect"); 96 | d3dcompiler_47.D3DReflectLibrary = GetProcAddress(d3dcompiler_47.dll, "D3DReflectLibrary"); 97 | d3dcompiler_47.D3DReturnFailure1 = GetProcAddress(d3dcompiler_47.dll, "D3DReturnFailure1"); 98 | d3dcompiler_47.D3DSetBlobPart = GetProcAddress(d3dcompiler_47.dll, "D3DSetBlobPart"); 99 | d3dcompiler_47.D3DStripShader = GetProcAddress(d3dcompiler_47.dll, "D3DStripShader"); 100 | d3dcompiler_47.D3DWriteBlobToFile = GetProcAddress(d3dcompiler_47.dll, "D3DWriteBlobToFile"); 101 | return true; 102 | } 103 | 104 | bool unload_library_d3dcompiler_47() { 105 | FreeLibrary(d3dcompiler_47.dll); 106 | d3dcompiler_47.dll = nullptr; 107 | return true; 108 | } 109 | 110 | #else 111 | 112 | bool load_library_d3dcompiler_47() { 113 | return false; 114 | } 115 | 116 | bool unload_library_d3dcompiler_47() { 117 | return false; 118 | } 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/file_monitor.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "file_monitor.h" 3 | 4 | #include "ansi.h" 5 | #include "config.h" 6 | #include "encoding.h" 7 | #include "hooks.h" 8 | #include "injector.h" 9 | 10 | using namespace uif::ansi; 11 | 12 | static const wchar_t* tryGetRelativePath(const wchar_t* path) 13 | { 14 | if(path[0] == '\0' || path[1] != ':') 15 | return path; 16 | 17 | wchar_t currentDirectory[MAX_PATH]; 18 | GetCurrentDirectoryW(MAX_PATH, currentDirectory); 19 | 20 | const wchar_t* cd = currentDirectory; 21 | const wchar_t* pp = path; 22 | while(true) 23 | { 24 | auto ca = static_cast(tolower(*cd)); 25 | auto cb = static_cast(tolower(*pp)); 26 | if(cb == '\0') return path; 27 | if(ca == '\0') return pp + 1; 28 | if(ca == L'\\') ca = L'/'; 29 | if(cb == L'\\') cb = L'/'; 30 | if(ca != cb) return path; 31 | cd++; 32 | pp++; 33 | } 34 | } 35 | 36 | HANDLE __stdcall CreateFileWHook( 37 | LPCWSTR lpFileName, 38 | DWORD dwDesiredAccess, 39 | DWORD dwShareMode, 40 | LPSECURITY_ATTRIBUTES lpSecurityAttributes, 41 | DWORD dwCreationDisposition, 42 | DWORD dwFlagsAndAttributes, 43 | HANDLE hTemplateFile) 44 | { 45 | auto& monitor = uif::injector::instance().feature(); 46 | std::wstring redirected; 47 | 48 | const auto* action = monitor.get_action(lpFileName, dwDesiredAccess); 49 | 50 | if(monitor.log_all || action && action->log) 51 | { 52 | std::cout << monitor << " Accessing "; 53 | std::wcout << yellow(tryGetRelativePath(lpFileName)); 54 | std::cout << " ["; 55 | if(dwDesiredAccess & GENERIC_READ) std::cout << 'R'; 56 | if(dwDesiredAccess & GENERIC_WRITE) std::cout << 'W'; 57 | if(dwDesiredAccess & GENERIC_EXECUTE) std::cout << 'X'; 58 | std::cout << "]\n"; 59 | } 60 | 61 | if(action) { 62 | if(action->breakpoint) 63 | { 64 | __debugbreak(); 65 | } 66 | 67 | if(!action->redirect_path.empty()) 68 | { 69 | std::cout << monitor; 70 | redirected = std::regex_replace(lpFileName, action->path_pattern, action->redirect_path); 71 | std::wcout << L" Redirecting " << yellow(tryGetRelativePath(lpFileName)) << L" to " << yellow(tryGetRelativePath(redirected.c_str())) << L'\n'; 72 | lpFileName = redirected.c_str(); 73 | } 74 | } 75 | 76 | return CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); 77 | } 78 | 79 | HANDLE __stdcall CreateFileAHook( 80 | LPCSTR lpFileName, 81 | DWORD dwDesiredAccess, 82 | DWORD dwShareMode, 83 | LPSECURITY_ATTRIBUTES lpSecurityAttributes, 84 | DWORD dwCreationDisposition, 85 | DWORD dwFlagsAndAttributes, 86 | HANDLE hTemplateFile) 87 | { 88 | wchar_t path[MAX_PATH]; 89 | MultiByteToWideChar(CP_ACP, 0, lpFileName, -1, path, MAX_PATH); 90 | return CreateFileWHook(path, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); 91 | } 92 | 93 | void uif::features::file_monitor::initialize() 94 | { 95 | log_all = config().value("log_all", false); 96 | 97 | if(config().contains("actions")) 98 | { 99 | const auto& actionArray = config()["actions"]; 100 | if(actionArray.is_array()) 101 | { 102 | for(auto& actionObject : actionArray) 103 | { 104 | if(!actionObject.is_object()) { 105 | std::cout << *this << dark_red(" Error:") << " expected object\n"; 106 | continue; 107 | } 108 | 109 | const auto& pattern = encoding::utf8_to_utf16(actionObject.value("pattern", "")); 110 | const auto& path = encoding::utf8_to_utf16(actionObject.value("path", "")); 111 | 112 | if(path.empty() && pattern.empty()) 113 | { 114 | std::cout << *this << dark_red(" Error:") << " no path or pattern specified\n"; 115 | continue; 116 | } 117 | 118 | if(!path.empty() && !pattern.empty()) 119 | { 120 | std::cout << *this << dark_yellow(" Warning:") << " both a path and a pattern specified. the pattern will be used\n"; 121 | } 122 | 123 | std::wregex regex = pattern.empty() ? build_path_pattern(path) : std::wregex(pattern); 124 | const auto& redirectPath = encoding::utf8_to_utf16(actionObject.value("redirect", "")); 125 | const auto& accessFilterString = actionObject.value("access", ""); 126 | const bool breakpoint = actionObject.value("breakpoint", false); 127 | const bool log = actionObject.value("log", false); 128 | 129 | DWORD accessFilter = 0; 130 | for(const char ch : accessFilterString) 131 | { 132 | switch(ch) 133 | { 134 | case 'r': 135 | case 'R': 136 | accessFilter |= GENERIC_READ; 137 | break; 138 | case 'w': 139 | case 'W': 140 | accessFilter |= GENERIC_WRITE; 141 | break; 142 | case 'x': 143 | case 'X': 144 | accessFilter |= GENERIC_EXECUTE; 145 | break; 146 | default: 147 | break; 148 | } 149 | } 150 | 151 | actions.push_back({ std::move(regex), redirectPath, accessFilter, breakpoint, log }); 152 | } 153 | } 154 | else 155 | { 156 | std::cout << *this << dark_red(" Error:") << " expected array\n"; 157 | } 158 | } 159 | 160 | if(actions.empty() && !log_all) 161 | { 162 | std::cout << *this << dark_yellow(" Warning:") << " no actions specified, disabling file monitor\n"; 163 | _enabled = false; 164 | return; 165 | } 166 | 167 | hooks::hook_import(this, "CreateFileA", CreateFileAHook); 168 | hooks::hook_import(this, "CreateFileW", CreateFileWHook); 169 | } 170 | 171 | void uif::features::file_monitor::finalize() 172 | { 173 | hooks::unhook_import(this, "CreateFileA", CreateFileAHook); 174 | hooks::unhook_import(this, "CreateFileW", CreateFileWHook); 175 | } 176 | 177 | std::wregex uif::features::file_monitor::build_path_pattern(const std::wstring& path) 178 | { 179 | std::wstring pattern = L"^.*("; 180 | for(const wchar_t c : path) 181 | { 182 | switch(c) 183 | { 184 | case L'.': 185 | case L'^': 186 | case L'$': 187 | case L'+': 188 | case L'-': 189 | case L'(': 190 | case L')': 191 | case L'[': 192 | case L']': 193 | case L'{': 194 | case L'}': 195 | case L'|': 196 | pattern += L'\\'; 197 | pattern += c; 198 | break; 199 | 200 | case L'\\': 201 | case L'/': 202 | pattern += L"\\/"; 203 | break; 204 | 205 | case '?': 206 | pattern += L"."; 207 | break; 208 | 209 | case '*': 210 | pattern += L".*"; 211 | break; 212 | 213 | default: 214 | pattern += c; 215 | break; 216 | } 217 | } 218 | 219 | pattern += L")$"; 220 | 221 | return std::wregex(pattern); 222 | } 223 | 224 | uif::features::file_monitor::file_action* uif::features::file_monitor::get_action(std::wstring path, DWORD desiredAccess) 225 | { 226 | std::ranges::replace(path, L'\\', L'/'); 227 | for(auto& action : actions) 228 | { 229 | if(std::regex_match(path, action.path_pattern)) 230 | { 231 | if(action.accessFilter && !(action.accessFilter & desiredAccess)) 232 | continue; 233 | return &action; 234 | } 235 | } 236 | return nullptr; 237 | } 238 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/injector.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "injector.h" 3 | 4 | #include "ansi.h" 5 | #include "libraries.h" 6 | #include "utils.h" 7 | 8 | #include "features/allocate_console.h" 9 | #include "features/text_processor.h" 10 | #include "features/start_suspended.h" 11 | #include "features/character_substitution.h" 12 | #include "features/custom_feature.h" 13 | #include "features/tunnel_decoder.h" 14 | #include "features/file_monitor.h" 15 | #include "features/font_manager.h" 16 | #include "features/locale_emulator.h" 17 | #include "features/memory_patcher.h" 18 | #include "features/play_timer.h" 19 | #include "features/window_manager.h" 20 | 21 | using namespace uif::ansi; 22 | 23 | namespace uif 24 | { 25 | injector& injector::instance() 26 | { 27 | static auto instance = new injector(); 28 | return *instance; 29 | } 30 | 31 | injector::injector() : game_module(GetModuleHandle(nullptr)) 32 | { 33 | if (config::try_load_json("uif_config.json", _config)) return; 34 | if (config::try_load_bson("uif_config.dat", _config)) return; 35 | 36 | utils::fail("Failed to find uif config file."); 37 | } 38 | 39 | nlohmann::json& injector::config() 40 | { 41 | return _config; 42 | } 43 | 44 | void injector::attach() 45 | { 46 | if(attached) return; 47 | attached = true; 48 | 49 | auto& injector_config = config()["injector"]; 50 | 51 | enabled = injector_config.value("enable", true); 52 | if(!enabled) { 53 | utils::debug_log("injector::attach: disabled"); 54 | libraries::load(); 55 | return; 56 | } 57 | 58 | utils::debug_log("injector::attach: enabled"); 59 | initialize_feature(); 60 | 61 | std::cout << white("[injector] ======================================================\n"); 62 | std::cout << white("[injector]") << " Injecting into module " << yellow(utils::get_module_name(game_module)) << " at address " << blue(game_module) << '\n'; 63 | 64 | if(injector_config.value("print_loaded_modules", false)) 65 | { 66 | std::cout << white("[injector]") << " Loaded modules:\n"; 67 | HMODULE hModule = nullptr; 68 | while((hModule = DetourEnumerateModules(hModule))) 69 | { 70 | std::cout << white("[injector] ") << blue(hModule) << ' ' << yellow(utils::get_module_name(hModule)) << '\n'; 71 | } 72 | } 73 | 74 | if(injector_config.contains("load_modules")) 75 | { 76 | auto& loadModules = injector_config["load_modules"]; 77 | 78 | if(loadModules.is_array()) { 79 | 80 | for(const auto& dllPathValue : loadModules) 81 | { 82 | if(!dllPathValue.is_string()) continue; 83 | 84 | std::string dllPath; 85 | dllPathValue.get_to(dllPath); 86 | 87 | auto handle = LoadLibraryA(dllPath.c_str()); 88 | 89 | if(!handle) { 90 | std::cout << white("[injector]") << dark_red(" Error:") << " Unable to locate dll " << yellow(dllPath) << " (" << GetLastError() << " - " << utils::get_last_error_message() << ")\n"; 91 | continue; 92 | } 93 | 94 | std::cout << white("[injector]") << " Loaded dll " << yellow(dllPath) << '\n'; 95 | 96 | additional_modules.push_back(handle); 97 | } 98 | } 99 | } 100 | 101 | if(injector_config.contains("hook_modules")) 102 | { 103 | auto& additionalHookModules = injector_config["hook_modules"]; 104 | 105 | if(additionalHookModules.is_array()) { 106 | 107 | for(const auto& moduleNameValue : additionalHookModules) 108 | { 109 | if(!moduleNameValue.is_string()) continue; 110 | 111 | std::string moduleName; 112 | moduleNameValue.get_to(moduleName); 113 | 114 | auto handle = GetModuleHandleA(moduleName.c_str()); 115 | 116 | if(!handle) { 117 | std::cout << white("[injector]") << dark_red(" Error:") << " Unable to locate additional module " << yellow(moduleName) << " (" << GetLastError() << " - " << utils::get_last_error_message() << ")\n"; 118 | continue; 119 | } 120 | 121 | additional_modules.push_back(handle); 122 | } 123 | } 124 | } 125 | 126 | if (injector_config.value("export_bson_config", false)) 127 | { 128 | injector_config.erase("export_bson_config"); 129 | std::vector bytes = nlohmann::json::to_bson(config()); 130 | 131 | for (uint8_t& byte : bytes) 132 | { 133 | byte ^= 0xff; 134 | } 135 | 136 | std::cout << white("[injector]") << " Exporting bson config\n"; 137 | 138 | std::ofstream ofs; 139 | ofs.open("uif_config.dat", std::ios::binary); 140 | ofs.write(reinterpret_cast(bytes.data()), bytes.size()); 141 | } 142 | 143 | libraries::load(); 144 | 145 | initialize_feature(); 146 | initialize_feature(); 147 | initialize_feature(); 148 | initialize_feature(); 149 | initialize_feature(); 150 | initialize_feature(); 151 | initialize_feature(); 152 | initialize_feature(); 153 | initialize_feature(); 154 | initialize_feature(); 155 | initialize_feature(); 156 | 157 | std::cout << white("[injector]") << green(" Initialization complete\n"); 158 | std::cout << white("[injector] ======================================================\n"); 159 | } 160 | 161 | void injector::detach() 162 | { 163 | if(!enabled) return; 164 | if(!attached) return; 165 | attached = false; 166 | 167 | std::cout << white("[injector] ======================================================\n"); 168 | std::cout << white("[injector]") << " Detaching...\n"; 169 | 170 | for(auto* feature : features) 171 | { 172 | feature->finalize(); 173 | delete feature; 174 | } 175 | features.clear(); 176 | 177 | libraries::unload(); 178 | 179 | std::cout << white("[injector]") << cyan(" Shutting down. Goodbye :)\n"); 180 | std::cout << white("[injector] ======================================================\n"); 181 | } 182 | 183 | HMODULE injector::load_real_library(const std::string& dllName) 184 | { 185 | std::string dllPath; 186 | 187 | if(config().contains("/injector/real_library_location"_json_pointer)) 188 | { 189 | const auto& value = config()["/injector/real_library_location"_json_pointer]; 190 | if(value.is_string()) 191 | { 192 | value.get_to(dllPath); 193 | } 194 | } 195 | 196 | if(dllPath.empty()) 197 | { 198 | char sysDir[MAX_PATH]; 199 | GetSystemDirectoryA(sysDir, MAX_PATH); 200 | dllPath = std::string(sysDir) + '\\' + dllName; 201 | } 202 | 203 | std::cout << white("[injector]") << " Loading original library from " << dllPath << "\n"; 204 | 205 | const auto result = LoadLibraryA(dllPath.c_str()); 206 | 207 | if(result == nullptr) 208 | { 209 | std::cout << white("[injector]") << red(" Error:") << " Failed to load original library\n"; 210 | const std::string error = "Unable to locate original library.\nPlease check the configuration file.\n\nPath: " + dllPath; 211 | MessageBoxA(nullptr, error.c_str(), "Universal Injector", MB_ICONERROR); 212 | ExitProcess(1); 213 | } 214 | 215 | return result; 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/features/locale_emulator.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "locale_emulator.h" 4 | 5 | #include "config.h" 6 | #include "hooks.h" 7 | #include "utils.h" 8 | 9 | #pragma region types 10 | 11 | typedef struct ML_PROCESS_INFORMATION : PROCESS_INFORMATION 12 | { 13 | PVOID FirstCallLdrLoadDll; 14 | 15 | } ML_PROCESS_INFORMATION, * PML_PROCESS_INFORMATION; 16 | 17 | typedef struct _TIME_FIELDS 18 | { 19 | SHORT Year; // range [1601...] 20 | SHORT Month; // range [1..12] 21 | SHORT Day; // range [1..31] 22 | SHORT Hour; // range [0..23] 23 | SHORT Minute; // range [0..59] 24 | SHORT Second; // range [0..59] 25 | SHORT Milliseconds;// range [0..999] 26 | SHORT Weekday; // range [0..6] == [Sunday..Saturday] 27 | } TIME_FIELDS, * PTIME_FIELDS; 28 | 29 | typedef struct _RTL_TIME_ZONE_INFORMATION 30 | { 31 | LONG Bias; 32 | WCHAR StandardName[32]; 33 | TIME_FIELDS StandardStart; 34 | LONG StandardBias; 35 | WCHAR DaylightName[32]; 36 | TIME_FIELDS DaylightStart; 37 | LONG DaylightBias; 38 | } RTL_TIME_ZONE_INFORMATION, * PRTL_TIME_ZONE_INFORMATION; 39 | 40 | typedef struct _REG_TZI_FORMAT 41 | { 42 | int Bias; 43 | int StandardBias; 44 | int DaylightBias; 45 | _SYSTEMTIME StandardDate; 46 | _SYSTEMTIME DaylightDate; 47 | } REG_TZI_FORMAT; 48 | 49 | typedef struct 50 | { 51 | USHORT Length; 52 | USHORT MaximumLength; 53 | union 54 | { 55 | PWSTR Buffer; 56 | ULONG64 Dummy; 57 | }; 58 | } UNICODE_STRING3264, * PUNICODE_STRING3264; 59 | 60 | typedef UNICODE_STRING3264 UNICODE_STRING64; 61 | typedef PUNICODE_STRING3264 PUNICODE_STRING64; 62 | 63 | typedef struct 64 | { 65 | ULONG64 Root; 66 | UNICODE_STRING64 SubKey; 67 | UNICODE_STRING64 ValueName; 68 | ULONG DataType; 69 | PVOID64 Data; 70 | ULONG64 DataSize; 71 | } REGISTRY_ENTRY64; 72 | 73 | typedef struct 74 | { 75 | REGISTRY_ENTRY64 Original; 76 | REGISTRY_ENTRY64 Redirected; 77 | } REGISTRY_REDIRECTION_ENTRY64, * PREGISTRY_REDIRECTION_ENTRY64; 78 | 79 | typedef struct 80 | { 81 | ULONG AnsiCodePage; 82 | ULONG OemCodePage; 83 | ULONG LocaleID; 84 | ULONG DefaultCharset; 85 | ULONG HookUILanguageApi; 86 | WCHAR DefaultFaceName[LF_FACESIZE]; 87 | RTL_TIME_ZONE_INFORMATION Timezone; 88 | ULONG64 NumberOfRegistryRedirectionEntries; 89 | REGISTRY_REDIRECTION_ENTRY64 RegistryReplacement[1]; 90 | } LOCALE_ENUMLATOR_ENVIRONMENT_BLOCK, * PLOCALE_ENUMLATOR_ENVIRONMENT_BLOCK, LEB, * PLEB; 91 | 92 | typedef DWORD(WINAPI* LeCreateProcess_t)( 93 | PLEB leb, 94 | PCWSTR applicationName, 95 | PCWSTR commandLine, 96 | PCWSTR currentDirectory, 97 | ULONG creationFlags, 98 | LPSTARTUPINFOW startupInfo, 99 | PML_PROCESS_INFORMATION processInformation, 100 | LPSECURITY_ATTRIBUTES processAttributes, 101 | LPSECURITY_ATTRIBUTES threadAttributes, 102 | PVOID environment, 103 | HANDLE token 104 | ); 105 | 106 | #pragma endregion 107 | 108 | // https://github.com/arcusmaximus/VNTranslationTools/blob/main/VNTextProxy/LocaleEmulator.cpp 109 | 110 | bool uif::features::locale_emulator::relaunch(ML_PROCESS_INFORMATION* pProcessInfo) const 111 | { 112 | std::cout << *this << " Attempting to relaunch with codepage " << codepage << "\n"; 113 | 114 | LEB leb{}; 115 | leb.AnsiCodePage = codepage; 116 | leb.OemCodePage = codepage; 117 | leb.LocaleID = locale; 118 | leb.DefaultCharset = charset; 119 | 120 | HKEY hTimeZone; 121 | const std::string key = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\" + timezone; 122 | if (RegOpenKeyA(HKEY_LOCAL_MACHINE, key.c_str(), &hTimeZone) == ERROR_SUCCESS) 123 | { 124 | DWORD bufferSize = sizeof leb.Timezone.StandardName; 125 | RegGetValue(hTimeZone, nullptr, L"Std", RRF_RT_REG_SZ, nullptr, leb.Timezone.StandardName, &bufferSize); 126 | 127 | bufferSize = sizeof leb.Timezone.DaylightName; 128 | RegGetValue(hTimeZone, nullptr, L"Dlt", RRF_RT_REG_SZ, nullptr, leb.Timezone.DaylightName, &bufferSize); 129 | 130 | REG_TZI_FORMAT timeZoneInfo; 131 | bufferSize = sizeof timeZoneInfo; 132 | RegGetValue(hTimeZone, nullptr, L"TZI", RRF_RT_REG_BINARY, nullptr, &timeZoneInfo, &bufferSize); 133 | leb.Timezone.Bias = timeZoneInfo.Bias; 134 | leb.Timezone.StandardBias = timeZoneInfo.StandardBias; 135 | leb.Timezone.DaylightBias = 0; 136 | 137 | RegCloseKey(hTimeZone); 138 | } 139 | else 140 | { 141 | std::cout << *this << " Error retrieving time zone information\n"; 142 | } 143 | 144 | wchar_t exePath[MAX_PATH]; 145 | GetModuleFileName(nullptr, exePath, std::size(exePath)); 146 | 147 | const wchar_t* commandLine = GetCommandLine(); 148 | 149 | wchar_t currentDirectory[MAX_PATH]; 150 | GetCurrentDirectory(std::size(currentDirectory), currentDirectory); 151 | 152 | STARTUPINFO startInfo{}; 153 | ML_PROCESS_INFORMATION processInfo{}; 154 | 155 | const HMODULE hLoader = LoadLibraryA("LoaderDll.dll"); 156 | if (hLoader == nullptr) 157 | { 158 | std::cout << *this << " Failed to load LoaderDll.dll\n"; 159 | return false; 160 | } 161 | 162 | const auto LeCreateProcess = reinterpret_cast(GetProcAddress(hLoader, "LeCreateProcess")); 163 | if (LeCreateProcess == nullptr) 164 | { 165 | std::cout << *this << " Failed to find function LeCreateProcess\n"; 166 | return false; 167 | } 168 | 169 | const auto result = LeCreateProcess( 170 | &leb, 171 | exePath, 172 | commandLine, 173 | currentDirectory, 174 | 0, 175 | &startInfo, 176 | pProcessInfo != nullptr ? pProcessInfo : &processInfo, 177 | nullptr, 178 | nullptr, 179 | nullptr, 180 | nullptr 181 | ); 182 | 183 | return result == ERROR_SUCCESS; 184 | } 185 | 186 | void uif::features::locale_emulator::initialize() 187 | { 188 | codepage = config().value("codepage", 932); 189 | locale = config().value("locale", 1041); 190 | charset = config().value("charset", SHIFTJIS_CHARSET); 191 | timezone = config().value("timezone", "Tokyo Standard Time"); 192 | wait_for_exit = config().value("wait_for_exit", false); 193 | 194 | if (GetACP() == codepage) 195 | { 196 | std::cout << *this << " Codepage " << codepage << " matches expectation\n"; 197 | return; 198 | } 199 | 200 | std::cout << *this << " Codepage " << GetACP() << " did not match expectation (" << codepage << ")\n"; 201 | 202 | Sleep(5000); 203 | 204 | ML_PROCESS_INFORMATION processInfo; 205 | if (!relaunch(&processInfo)) { 206 | std::cout << *this << " Failed to relaunch. Continuing with default locale\n"; 207 | return; 208 | } 209 | 210 | std::cout << *this << " Relaunch successful (child process " << processInfo.dwProcessId << ")\n"; 211 | 212 | if(wait_for_exit) 213 | { 214 | std::cout << *this << " Waiting for child process to end\n"; 215 | WaitForSingleObject(processInfo.hProcess, INFINITE); 216 | std::cout << *this << " Child process ended\n"; 217 | } 218 | 219 | std::cout << *this << " Terminating parent process\n"; 220 | 221 | ExitProcess(0); 222 | } 223 | 224 | void uif::features::locale_emulator::finalize() 225 | { 226 | } 227 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | Build/ 21 | UniversalInjectorFramework/Temp/ 22 | [Dd]ebug/ 23 | [Dd]ebugPublic/ 24 | [Rr]elease/ 25 | [Rr]eleases/ 26 | x64/ 27 | x86/ 28 | [Ww][Ii][Nn]32/ 29 | [Aa][Rr][Mm]/ 30 | [Aa][Rr][Mm]64/ 31 | bld/ 32 | [Bb]in/ 33 | [Oo]bj/ 34 | [Ll]og/ 35 | [Ll]ogs/ 36 | 37 | # Visual Studio 2015/2017 cache/options directory 38 | .vs/ 39 | # Uncomment if you have tasks that create the project's static files in wwwroot 40 | #wwwroot/ 41 | 42 | # Visual Studio 2017 auto generated files 43 | Generated\ Files/ 44 | 45 | # MSTest test Results 46 | [Tt]est[Rr]esult*/ 47 | [Bb]uild[Ll]og.* 48 | 49 | # NUnit 50 | *.VisualState.xml 51 | TestResult.xml 52 | nunit-*.xml 53 | 54 | # Build Results of an ATL Project 55 | [Dd]ebugPS/ 56 | [Rr]eleasePS/ 57 | dlldata.c 58 | 59 | # Benchmark Results 60 | BenchmarkDotNet.Artifacts/ 61 | 62 | # .NET Core 63 | project.lock.json 64 | project.fragment.lock.json 65 | artifacts/ 66 | 67 | # ASP.NET Scaffolding 68 | ScaffoldingReadMe.txt 69 | 70 | # StyleCop 71 | StyleCopReport.xml 72 | 73 | # Files built by Visual Studio 74 | *_i.c 75 | *_p.c 76 | *_h.h 77 | *.ilk 78 | *.meta 79 | *.obj 80 | *.iobj 81 | *.pch 82 | *.pdb 83 | *.ipdb 84 | *.pgc 85 | *.pgd 86 | *.rsp 87 | *.sbr 88 | *.tlb 89 | *.tli 90 | *.tlh 91 | *.tmp 92 | *.tmp_proj 93 | *_wpftmp.csproj 94 | *.log 95 | *.vspscc 96 | *.vssscc 97 | .builds 98 | *.pidb 99 | *.svclog 100 | *.scc 101 | 102 | # Chutzpah Test files 103 | _Chutzpah* 104 | 105 | # Visual C++ cache files 106 | ipch/ 107 | *.aps 108 | *.ncb 109 | *.opendb 110 | *.opensdf 111 | *.sdf 112 | *.cachefile 113 | *.VC.db 114 | *.VC.VC.opendb 115 | 116 | # Visual Studio profiler 117 | *.psess 118 | *.vsp 119 | *.vspx 120 | *.sap 121 | 122 | # Visual Studio Trace Files 123 | *.e2e 124 | 125 | # TFS 2012 Local Workspace 126 | $tf/ 127 | 128 | # Guidance Automation Toolkit 129 | *.gpState 130 | 131 | # ReSharper is a .NET coding add-in 132 | _ReSharper*/ 133 | *.[Rr]e[Ss]harper 134 | *.DotSettings.user 135 | 136 | # TeamCity is a build add-in 137 | _TeamCity* 138 | 139 | # DotCover is a Code Coverage Tool 140 | *.dotCover 141 | 142 | # AxoCover is a Code Coverage Tool 143 | .axoCover/* 144 | !.axoCover/settings.json 145 | 146 | # Coverlet is a free, cross platform Code Coverage Tool 147 | coverage*.json 148 | coverage*.xml 149 | coverage*.info 150 | 151 | # Visual Studio code coverage results 152 | *.coverage 153 | *.coveragexml 154 | 155 | # NCrunch 156 | _NCrunch_* 157 | .*crunch*.local.xml 158 | nCrunchTemp_* 159 | 160 | # MightyMoose 161 | *.mm.* 162 | AutoTest.Net/ 163 | 164 | # Web workbench (sass) 165 | .sass-cache/ 166 | 167 | # Installshield output folder 168 | [Ee]xpress/ 169 | 170 | # DocProject is a documentation generator add-in 171 | DocProject/buildhelp/ 172 | DocProject/Help/*.HxT 173 | DocProject/Help/*.HxC 174 | DocProject/Help/*.hhc 175 | DocProject/Help/*.hhk 176 | DocProject/Help/*.hhp 177 | DocProject/Help/Html2 178 | DocProject/Help/html 179 | 180 | # Click-Once directory 181 | publish/ 182 | 183 | # Publish Web Output 184 | *.[Pp]ublish.xml 185 | *.azurePubxml 186 | # Note: Comment the next line if you want to checkin your web deploy settings, 187 | # but database connection strings (with potential passwords) will be unencrypted 188 | *.pubxml 189 | *.publishproj 190 | 191 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 192 | # checkin your Azure Web App publish settings, but sensitive information contained 193 | # in these scripts will be unencrypted 194 | PublishScripts/ 195 | 196 | # NuGet Packages 197 | *.nupkg 198 | # NuGet Symbol Packages 199 | *.snupkg 200 | # The packages folder can be ignored because of Package Restore 201 | **/[Pp]ackages/* 202 | # except build/, which is used as an MSBuild target. 203 | !**/[Pp]ackages/build/ 204 | # Uncomment if necessary however generally it will be regenerated when needed 205 | #!**/[Pp]ackages/repositories.config 206 | # NuGet v3's project.json files produces more ignorable files 207 | *.nuget.props 208 | *.nuget.targets 209 | 210 | # Microsoft Azure Build Output 211 | csx/ 212 | *.build.csdef 213 | 214 | # Microsoft Azure Emulator 215 | ecf/ 216 | rcf/ 217 | 218 | # Windows Store app package directories and files 219 | AppPackages/ 220 | BundleArtifacts/ 221 | Package.StoreAssociation.xml 222 | _pkginfo.txt 223 | *.appx 224 | *.appxbundle 225 | *.appxupload 226 | 227 | # Visual Studio cache files 228 | # files ending in .cache can be ignored 229 | *.[Cc]ache 230 | # but keep track of directories ending in .cache 231 | !?*.[Cc]ache/ 232 | 233 | # Others 234 | ClientBin/ 235 | ~$* 236 | *~ 237 | *.dbmdl 238 | *.dbproj.schemaview 239 | *.jfm 240 | *.pfx 241 | *.publishsettings 242 | orleans.codegen.cs 243 | 244 | # Including strong name files can present a security risk 245 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 246 | #*.snk 247 | 248 | # Since there are multiple workflows, uncomment next line to ignore bower_components 249 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 250 | #bower_components/ 251 | 252 | # RIA/Silverlight projects 253 | Generated_Code/ 254 | 255 | # Backup & report files from converting an old project file 256 | # to a newer Visual Studio version. Backup files are not needed, 257 | # because we have git ;-) 258 | _UpgradeReport_Files/ 259 | Backup*/ 260 | UpgradeLog*.XML 261 | UpgradeLog*.htm 262 | ServiceFabricBackup/ 263 | *.rptproj.bak 264 | 265 | # SQL Server files 266 | *.mdf 267 | *.ldf 268 | *.ndf 269 | 270 | # Business Intelligence projects 271 | *.rdl.data 272 | *.bim.layout 273 | *.bim_*.settings 274 | *.rptproj.rsuser 275 | *- [Bb]ackup.rdl 276 | *- [Bb]ackup ([0-9]).rdl 277 | *- [Bb]ackup ([0-9][0-9]).rdl 278 | 279 | # Microsoft Fakes 280 | FakesAssemblies/ 281 | 282 | # GhostDoc plugin setting file 283 | *.GhostDoc.xml 284 | 285 | # Node.js Tools for Visual Studio 286 | .ntvs_analysis.dat 287 | node_modules/ 288 | 289 | # Visual Studio 6 build log 290 | *.plg 291 | 292 | # Visual Studio 6 workspace options file 293 | *.opt 294 | 295 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 296 | *.vbw 297 | 298 | # Visual Studio LightSwitch build output 299 | **/*.HTMLClient/GeneratedArtifacts 300 | **/*.DesktopClient/GeneratedArtifacts 301 | **/*.DesktopClient/ModelManifest.xml 302 | **/*.Server/GeneratedArtifacts 303 | **/*.Server/ModelManifest.xml 304 | _Pvt_Extensions 305 | 306 | # Paket dependency manager 307 | .paket/paket.exe 308 | paket-files/ 309 | 310 | # FAKE - F# Make 311 | .fake/ 312 | 313 | # CodeRush personal settings 314 | .cr/personal 315 | 316 | # Python Tools for Visual Studio (PTVS) 317 | __pycache__/ 318 | *.pyc 319 | 320 | # Cake - Uncomment if you are using it 321 | # tools/** 322 | # !tools/packages.config 323 | 324 | # Tabs Studio 325 | *.tss 326 | 327 | # Telerik's JustMock configuration file 328 | *.jmconfig 329 | 330 | # BizTalk build output 331 | *.btp.cs 332 | *.btm.cs 333 | *.odx.cs 334 | *.xsd.cs 335 | 336 | # OpenCover UI analysis results 337 | OpenCover/ 338 | 339 | # Azure Stream Analytics local run output 340 | ASALocalRun/ 341 | 342 | # MSBuild Binary and Structured Log 343 | *.binlog 344 | 345 | # NVidia Nsight GPU debugger configuration file 346 | *.nvuser 347 | 348 | # MFractors (Xamarin productivity tool) working folder 349 | .mfractor/ 350 | 351 | # Local History for Visual Studio 352 | .localhistory/ 353 | 354 | # BeatPulse healthcheck temp database 355 | healthchecksdb 356 | 357 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 358 | MigrationBackup/ 359 | 360 | # Ionide (cross platform F# VS Code tools) working folder 361 | .ionide/ 362 | 363 | # Fody - auto-generated XML schema 364 | FodyWeavers.xsd -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/hooks.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "hooks.h" 3 | 4 | #include "ansi.h" 5 | #include "utils.h" 6 | #include "injector.h" 7 | #include "features/_feature_base.h" 8 | 9 | using namespace uif::ansi; 10 | using namespace uif::utils; 11 | 12 | namespace uif::hooks 13 | { 14 | struct hooked_import_info 15 | { 16 | const features::feature_base* feature; 17 | void** originalFunctionPointer; 18 | }; 19 | 20 | struct hooked_function_info 21 | { 22 | const features::feature_base* feature; 23 | }; 24 | 25 | static std::unordered_map hooked_imports{}; 26 | static std::unordered_map hooked_functions{}; 27 | static std::unordered_map trampoline_mapping{}; 28 | 29 | struct hook_import_info 30 | { 31 | const features::feature_base* feature; 32 | const char* importName; 33 | void* hookFunction; 34 | HMODULE targetModule; 35 | bool success; 36 | bool found; 37 | bool foundAny; 38 | }; 39 | 40 | BOOL CALLBACK hook_import_enum_proc(PVOID pContext, DWORD nOrdinal, LPCSTR pszFunc, PVOID* ppvFunc) 41 | { 42 | if(ppvFunc == nullptr || pszFunc == nullptr) 43 | return true; 44 | 45 | auto* info = static_cast(pContext); 46 | 47 | info->foundAny = true; 48 | 49 | if(!strcmp(pszFunc, info->importName)) 50 | { 51 | info->found = true; 52 | auto [iterator, success] = hooked_imports.try_emplace(ppvFunc, hooked_import_info{ info->feature, ppvFunc }); 53 | if(!success) 54 | { 55 | std::cout << *info->feature << dark_yellow(" Warning:") << " Unable to hook import " << yellow(pszFunc) << " because it has already been hooked by feature " << iterator->second.feature->name() << '\n'; 56 | return false; 57 | } 58 | 59 | std::cout << *info->feature 60 | << " Hooking import " << yellow(pszFunc) 61 | << " in " << yellow(get_module_name(info->targetModule)) 62 | << " at " << blue(iterator->second.originalFunctionPointer) 63 | << green(" --> ") << blue(info->hookFunction) << '\n'; 64 | 65 | info->success = true; 66 | patch_address(ppvFunc, info->hookFunction); 67 | return false; 68 | } 69 | 70 | return true; 71 | } 72 | 73 | BOOL CALLBACK unhook_import_enum_proc(PVOID pContext, DWORD nOrdinal, LPCSTR pszFunc, PVOID* ppvFunc) 74 | { 75 | if(ppvFunc == nullptr || pszFunc == nullptr) 76 | return true; 77 | 78 | auto* info = static_cast(pContext); 79 | 80 | if(!strcmp(pszFunc, info->importName)) 81 | { 82 | info->found = true; 83 | const auto iterator = hooked_imports.find(ppvFunc); 84 | if(iterator == hooked_imports.end() || iterator->second.feature != info->feature) 85 | { 86 | std::cout << *info->feature << dark_yellow(" Warning:") << " Unable to unhook import " << yellow(pszFunc) << " because it has not been hooked by this feature\n"; 87 | return false; 88 | } 89 | 90 | std::cout << *info->feature 91 | << " Unhooking import " << yellow(pszFunc) 92 | << " in " << yellow(get_module_name(info->targetModule)) 93 | << " at " << blue(iterator->second.originalFunctionPointer) 94 | << red(" -/-> ") << blue(info->hookFunction) << '\n'; 95 | 96 | info->success = true; 97 | patch_address(ppvFunc, iterator->second.originalFunctionPointer); 98 | return false; 99 | } 100 | 101 | return true; 102 | } 103 | 104 | bool hook_import(const features::feature_base* feature, const char* importName, void* hookFunction) 105 | { 106 | hook_import_info info{ feature, importName, hookFunction, injector::instance().game_module, false, false, false }; 107 | 108 | DetourEnumerateImportsEx(injector::instance().game_module, &info, nullptr, hook_import_enum_proc); 109 | for(const auto module : injector::instance().additional_modules) 110 | { 111 | info.targetModule = module; 112 | DetourEnumerateImportsEx(module, &info, nullptr, hook_import_enum_proc); 113 | } 114 | 115 | if(!info.foundAny) 116 | { 117 | std::cout << *feature << red(" Unable to enumerate import address table\n"); 118 | std::cout << *feature << red(" This likely means the module had some sort of tamper protection applied to it\n"); 119 | } 120 | 121 | if(!info.found) 122 | { 123 | std::cout << *feature << black(" Unable to hook import ") << black(importName) << black(" because it does not exist\n"); 124 | } 125 | 126 | return info.success; 127 | } 128 | 129 | bool unhook_import(const features::feature_base* feature, const char* importName, void* hookFunction) 130 | { 131 | hook_import_info info{ feature, importName, hookFunction, injector::instance().game_module, false, false, false }; 132 | 133 | DetourEnumerateImportsEx(injector::instance().game_module, &info, nullptr, unhook_import_enum_proc); 134 | for(const auto module : injector::instance().additional_modules) 135 | { 136 | info.targetModule = module; 137 | DetourEnumerateImportsEx(module, &info, nullptr, unhook_import_enum_proc); 138 | } 139 | 140 | if(!info.found) 141 | { 142 | std::cout << *feature << black(" Unable to unhook import ") << black(importName) << black(" because it does not exist\n"); 143 | } 144 | 145 | return info.success; 146 | } 147 | 148 | bool hook_function(const features::feature_base* feature, void*& targetFunction, void* hookFunction, const std::string& functionName) 149 | { 150 | auto [iterator, emplaced] = hooked_functions.try_emplace(targetFunction, hooked_function_info{ feature }); 151 | if(!emplaced) 152 | { 153 | if(functionName.empty()) 154 | std::cout << *feature << dark_yellow(" Warning:") << " Unable to hook function at " << blue(targetFunction) << " because it has already been hooked by feature " << yellow(iterator->second.feature->name()) << '\n'; 155 | else 156 | std::cout << *feature << dark_yellow(" Warning:") << " Unable to hook " << yellow(functionName) << " at " << blue(targetFunction) << " because it has already been hooked by feature " << yellow(iterator->second.feature->name()) << '\n'; 157 | return false; 158 | } 159 | 160 | if(functionName.empty()) 161 | std::cout << *feature << " Hooking function at " << blue(targetFunction) << green(" --> ") << blue(hookFunction) << '\n'; 162 | else 163 | std::cout << *feature << " Hooking " << yellow(functionName) << " at " << blue(targetFunction) << green(" --> ") << blue(hookFunction) << '\n'; 164 | 165 | 166 | void* originalTargetFunction = targetFunction; 167 | DetourTransactionBegin(); 168 | DetourAttach(&targetFunction, hookFunction); 169 | DetourTransactionCommit(); 170 | trampoline_mapping.try_emplace(targetFunction, originalTargetFunction); 171 | 172 | return true; 173 | } 174 | 175 | bool unhook_function(const features::feature_base* feature, void*& targetFunction, void* hookFunction, const std::string& functionName) 176 | { 177 | const auto trampolineIterator = trampoline_mapping.find(targetFunction); 178 | bool failed = false; 179 | 180 | if(trampolineIterator == trampoline_mapping.end()) 181 | { 182 | failed = true; 183 | if (functionName.empty()) 184 | std::cout << *feature << dark_yellow(" Warning:") << " Unable to unhook function at " << blue(targetFunction) << " because no trampoline exists at this location\n"; 185 | else 186 | std::cout << *feature << dark_yellow(" Warning:") << " Unable to unhook " << yellow(functionName) << " at " << blue(targetFunction) << " because no trampoline exists at this location\n"; 187 | return false; 188 | } 189 | 190 | const auto originalTargetFunction = trampolineIterator->second; 191 | const auto functionIterator = hooked_functions.find(originalTargetFunction); 192 | 193 | if(functionIterator == hooked_functions.end() || functionIterator->second.feature != feature) 194 | { 195 | if(functionName.empty()) 196 | std::cout << *feature << dark_yellow(" Warning:") << " Unable to unhook function at " << blue(originalTargetFunction) << " because it has not been hooked by this feature\n"; 197 | else 198 | std::cout << *feature << dark_yellow(" Warning:") << " Unable to unhook " << yellow(functionName) << " at " << blue(originalTargetFunction) << " because it has not been hooked by this feature\n"; 199 | return false; 200 | } 201 | 202 | if(functionName.empty()) 203 | std::cout << *feature << " Unhooking function at " << blue(originalTargetFunction) << red(" -/-> ") << blue(hookFunction) << '\n'; 204 | else 205 | std::cout << *feature << " Unhooking " << yellow(functionName) << " at " << blue(originalTargetFunction) << red(" -/-> ") << blue(hookFunction) << '\n'; 206 | 207 | DetourTransactionBegin(); 208 | DetourDetach(&targetFunction, hookFunction); 209 | DetourTransactionCommit(); 210 | return true; 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/winmm.def: -------------------------------------------------------------------------------- 1 | LIBRARY winmm 2 | EXPORTS 3 | Ordinal2=lib_winmm_Ordinal2 @2 NONAME 4 | mciExecute=lib_winmm_mciExecute @3 5 | CloseDriver=lib_winmm_CloseDriver @4 6 | DefDriverProc=lib_winmm_DefDriverProc @5 7 | DriverCallback=lib_winmm_DriverCallback @6 8 | DrvGetModuleHandle=lib_winmm_DrvGetModuleHandle @7 9 | GetDriverModuleHandle=lib_winmm_GetDriverModuleHandle @8 10 | NotifyCallbackData=lib_winmm_NotifyCallbackData @9 11 | OpenDriver=lib_winmm_OpenDriver @10 12 | PlaySound=lib_winmm_PlaySound @11 13 | PlaySoundA=lib_winmm_PlaySoundA @12 14 | PlaySoundW=lib_winmm_PlaySoundW @13 15 | SendDriverMessage=lib_winmm_SendDriverMessage @14 16 | WOW32DriverCallback=lib_winmm_WOW32DriverCallback @15 17 | WOW32ResolveMultiMediaHandle=lib_winmm_WOW32ResolveMultiMediaHandle @16 18 | WOWAppExit=lib_winmm_WOWAppExit @17 19 | aux32Message=lib_winmm_aux32Message @18 20 | auxGetDevCapsA=lib_winmm_auxGetDevCapsA @19 21 | auxGetDevCapsW=lib_winmm_auxGetDevCapsW @20 22 | auxGetNumDevs=lib_winmm_auxGetNumDevs @21 23 | auxGetVolume=lib_winmm_auxGetVolume @22 24 | auxOutMessage=lib_winmm_auxOutMessage @23 25 | auxSetVolume=lib_winmm_auxSetVolume @24 26 | joy32Message=lib_winmm_joy32Message @25 27 | joyConfigChanged=lib_winmm_joyConfigChanged @26 28 | joyGetDevCapsA=lib_winmm_joyGetDevCapsA @27 29 | joyGetDevCapsW=lib_winmm_joyGetDevCapsW @28 30 | joyGetNumDevs=lib_winmm_joyGetNumDevs @29 31 | joyGetPos=lib_winmm_joyGetPos @30 32 | joyGetPosEx=lib_winmm_joyGetPosEx @31 33 | joyGetThreshold=lib_winmm_joyGetThreshold @32 34 | joyReleaseCapture=lib_winmm_joyReleaseCapture @33 35 | joySetCapture=lib_winmm_joySetCapture @34 36 | joySetThreshold=lib_winmm_joySetThreshold @35 37 | mci32Message=lib_winmm_mci32Message @36 38 | mciDriverNotify=lib_winmm_mciDriverNotify @37 39 | mciDriverYield=lib_winmm_mciDriverYield @38 40 | mciFreeCommandResource=lib_winmm_mciFreeCommandResource @39 41 | mciGetCreatorTask=lib_winmm_mciGetCreatorTask @40 42 | mciGetDeviceIDA=lib_winmm_mciGetDeviceIDA @41 43 | mciGetDeviceIDFromElementIDA=lib_winmm_mciGetDeviceIDFromElementIDA @42 44 | mciGetDeviceIDFromElementIDW=lib_winmm_mciGetDeviceIDFromElementIDW @43 45 | mciGetDeviceIDW=lib_winmm_mciGetDeviceIDW @44 46 | mciGetDriverData=lib_winmm_mciGetDriverData @45 47 | mciGetErrorStringA=lib_winmm_mciGetErrorStringA @46 48 | mciGetErrorStringW=lib_winmm_mciGetErrorStringW @47 49 | mciGetYieldProc=lib_winmm_mciGetYieldProc @48 50 | mciLoadCommandResource=lib_winmm_mciLoadCommandResource @49 51 | mciSendCommandA=lib_winmm_mciSendCommandA @50 52 | mciSendCommandW=lib_winmm_mciSendCommandW @51 53 | mciSendStringA=lib_winmm_mciSendStringA @52 54 | mciSendStringW=lib_winmm_mciSendStringW @53 55 | mciSetDriverData=lib_winmm_mciSetDriverData @54 56 | mciSetYieldProc=lib_winmm_mciSetYieldProc @55 57 | mid32Message=lib_winmm_mid32Message @56 58 | midiConnect=lib_winmm_midiConnect @57 59 | midiDisconnect=lib_winmm_midiDisconnect @58 60 | midiInAddBuffer=lib_winmm_midiInAddBuffer @59 61 | midiInClose=lib_winmm_midiInClose @60 62 | midiInGetDevCapsA=lib_winmm_midiInGetDevCapsA @61 63 | midiInGetDevCapsW=lib_winmm_midiInGetDevCapsW @62 64 | midiInGetErrorTextA=lib_winmm_midiInGetErrorTextA @63 65 | midiInGetErrorTextW=lib_winmm_midiInGetErrorTextW @64 66 | midiInGetID=lib_winmm_midiInGetID @65 67 | midiInGetNumDevs=lib_winmm_midiInGetNumDevs @66 68 | midiInMessage=lib_winmm_midiInMessage @67 69 | midiInOpen=lib_winmm_midiInOpen @68 70 | midiInPrepareHeader=lib_winmm_midiInPrepareHeader @69 71 | midiInReset=lib_winmm_midiInReset @70 72 | midiInStart=lib_winmm_midiInStart @71 73 | midiInStop=lib_winmm_midiInStop @72 74 | midiInUnprepareHeader=lib_winmm_midiInUnprepareHeader @73 75 | midiOutCacheDrumPatches=lib_winmm_midiOutCacheDrumPatches @74 76 | midiOutCachePatches=lib_winmm_midiOutCachePatches @75 77 | midiOutClose=lib_winmm_midiOutClose @76 78 | midiOutGetDevCapsA=lib_winmm_midiOutGetDevCapsA @77 79 | midiOutGetDevCapsW=lib_winmm_midiOutGetDevCapsW @78 80 | midiOutGetErrorTextA=lib_winmm_midiOutGetErrorTextA @79 81 | midiOutGetErrorTextW=lib_winmm_midiOutGetErrorTextW @80 82 | midiOutGetID=lib_winmm_midiOutGetID @81 83 | midiOutGetNumDevs=lib_winmm_midiOutGetNumDevs @82 84 | midiOutGetVolume=lib_winmm_midiOutGetVolume @83 85 | midiOutLongMsg=lib_winmm_midiOutLongMsg @84 86 | midiOutMessage=lib_winmm_midiOutMessage @85 87 | midiOutOpen=lib_winmm_midiOutOpen @86 88 | midiOutPrepareHeader=lib_winmm_midiOutPrepareHeader @87 89 | midiOutReset=lib_winmm_midiOutReset @88 90 | midiOutSetVolume=lib_winmm_midiOutSetVolume @89 91 | midiOutShortMsg=lib_winmm_midiOutShortMsg @90 92 | midiOutUnprepareHeader=lib_winmm_midiOutUnprepareHeader @91 93 | midiStreamClose=lib_winmm_midiStreamClose @92 94 | midiStreamOpen=lib_winmm_midiStreamOpen @93 95 | midiStreamOut=lib_winmm_midiStreamOut @94 96 | midiStreamPause=lib_winmm_midiStreamPause @95 97 | midiStreamPosition=lib_winmm_midiStreamPosition @96 98 | midiStreamProperty=lib_winmm_midiStreamProperty @97 99 | midiStreamRestart=lib_winmm_midiStreamRestart @98 100 | midiStreamStop=lib_winmm_midiStreamStop @99 101 | mixerClose=lib_winmm_mixerClose @100 102 | mixerGetControlDetailsA=lib_winmm_mixerGetControlDetailsA @101 103 | mixerGetControlDetailsW=lib_winmm_mixerGetControlDetailsW @102 104 | mixerGetDevCapsA=lib_winmm_mixerGetDevCapsA @103 105 | mixerGetDevCapsW=lib_winmm_mixerGetDevCapsW @104 106 | mixerGetID=lib_winmm_mixerGetID @105 107 | mixerGetLineControlsA=lib_winmm_mixerGetLineControlsA @106 108 | mixerGetLineControlsW=lib_winmm_mixerGetLineControlsW @107 109 | mixerGetLineInfoA=lib_winmm_mixerGetLineInfoA @108 110 | mixerGetLineInfoW=lib_winmm_mixerGetLineInfoW @109 111 | mixerGetNumDevs=lib_winmm_mixerGetNumDevs @110 112 | mixerMessage=lib_winmm_mixerMessage @111 113 | mixerOpen=lib_winmm_mixerOpen @112 114 | mixerSetControlDetails=lib_winmm_mixerSetControlDetails @113 115 | mmDrvInstall=lib_winmm_mmDrvInstall @114 116 | mmGetCurrentTask=lib_winmm_mmGetCurrentTask @115 117 | mmTaskBlock=lib_winmm_mmTaskBlock @116 118 | mmTaskCreate=lib_winmm_mmTaskCreate @117 119 | mmTaskSignal=lib_winmm_mmTaskSignal @118 120 | mmTaskYield=lib_winmm_mmTaskYield @119 121 | mmioAdvance=lib_winmm_mmioAdvance @120 122 | mmioAscend=lib_winmm_mmioAscend @121 123 | mmioClose=lib_winmm_mmioClose @122 124 | mmioCreateChunk=lib_winmm_mmioCreateChunk @123 125 | mmioDescend=lib_winmm_mmioDescend @124 126 | mmioFlush=lib_winmm_mmioFlush @125 127 | mmioGetInfo=lib_winmm_mmioGetInfo @126 128 | mmioInstallIOProcA=lib_winmm_mmioInstallIOProcA @127 129 | mmioInstallIOProcW=lib_winmm_mmioInstallIOProcW @128 130 | mmioOpenA=lib_winmm_mmioOpenA @129 131 | mmioOpenW=lib_winmm_mmioOpenW @130 132 | mmioRead=lib_winmm_mmioRead @131 133 | mmioRenameA=lib_winmm_mmioRenameA @132 134 | mmioRenameW=lib_winmm_mmioRenameW @133 135 | mmioSeek=lib_winmm_mmioSeek @134 136 | mmioSendMessage=lib_winmm_mmioSendMessage @135 137 | mmioSetBuffer=lib_winmm_mmioSetBuffer @136 138 | mmioSetInfo=lib_winmm_mmioSetInfo @137 139 | mmioStringToFOURCCA=lib_winmm_mmioStringToFOURCCA @138 140 | mmioStringToFOURCCW=lib_winmm_mmioStringToFOURCCW @139 141 | mmioWrite=lib_winmm_mmioWrite @140 142 | mmsystemGetVersion=lib_winmm_mmsystemGetVersion @141 143 | mod32Message=lib_winmm_mod32Message @142 144 | mxd32Message=lib_winmm_mxd32Message @143 145 | sndPlaySoundA=lib_winmm_sndPlaySoundA @144 146 | sndPlaySoundW=lib_winmm_sndPlaySoundW @145 147 | tid32Message=lib_winmm_tid32Message @146 148 | timeBeginPeriod=lib_winmm_timeBeginPeriod @147 149 | timeEndPeriod=lib_winmm_timeEndPeriod @148 150 | timeGetDevCaps=lib_winmm_timeGetDevCaps @149 151 | timeGetSystemTime=lib_winmm_timeGetSystemTime @150 152 | timeGetTime=lib_winmm_timeGetTime @151 153 | timeKillEvent=lib_winmm_timeKillEvent @152 154 | timeSetEvent=lib_winmm_timeSetEvent @153 155 | waveInAddBuffer=lib_winmm_waveInAddBuffer @154 156 | waveInClose=lib_winmm_waveInClose @155 157 | waveInGetDevCapsA=lib_winmm_waveInGetDevCapsA @156 158 | waveInGetDevCapsW=lib_winmm_waveInGetDevCapsW @157 159 | waveInGetErrorTextA=lib_winmm_waveInGetErrorTextA @158 160 | waveInGetErrorTextW=lib_winmm_waveInGetErrorTextW @159 161 | waveInGetID=lib_winmm_waveInGetID @160 162 | waveInGetNumDevs=lib_winmm_waveInGetNumDevs @161 163 | waveInGetPosition=lib_winmm_waveInGetPosition @162 164 | waveInMessage=lib_winmm_waveInMessage @163 165 | waveInOpen=lib_winmm_waveInOpen @164 166 | waveInPrepareHeader=lib_winmm_waveInPrepareHeader @165 167 | waveInReset=lib_winmm_waveInReset @166 168 | waveInStart=lib_winmm_waveInStart @167 169 | waveInStop=lib_winmm_waveInStop @168 170 | waveInUnprepareHeader=lib_winmm_waveInUnprepareHeader @169 171 | waveOutBreakLoop=lib_winmm_waveOutBreakLoop @170 172 | waveOutClose=lib_winmm_waveOutClose @171 173 | waveOutGetDevCapsA=lib_winmm_waveOutGetDevCapsA @172 174 | waveOutGetDevCapsW=lib_winmm_waveOutGetDevCapsW @173 175 | waveOutGetErrorTextA=lib_winmm_waveOutGetErrorTextA @174 176 | waveOutGetErrorTextW=lib_winmm_waveOutGetErrorTextW @175 177 | waveOutGetID=lib_winmm_waveOutGetID @176 178 | waveOutGetNumDevs=lib_winmm_waveOutGetNumDevs @177 179 | waveOutGetPitch=lib_winmm_waveOutGetPitch @178 180 | waveOutGetPlaybackRate=lib_winmm_waveOutGetPlaybackRate @179 181 | waveOutGetPosition=lib_winmm_waveOutGetPosition @180 182 | waveOutGetVolume=lib_winmm_waveOutGetVolume @181 183 | waveOutMessage=lib_winmm_waveOutMessage @182 184 | waveOutOpen=lib_winmm_waveOutOpen @183 185 | waveOutPause=lib_winmm_waveOutPause @184 186 | waveOutPrepareHeader=lib_winmm_waveOutPrepareHeader @185 187 | waveOutReset=lib_winmm_waveOutReset @186 188 | waveOutRestart=lib_winmm_waveOutRestart @187 189 | waveOutSetPitch=lib_winmm_waveOutSetPitch @188 190 | waveOutSetPlaybackRate=lib_winmm_waveOutSetPlaybackRate @189 191 | waveOutSetVolume=lib_winmm_waveOutSetVolume @190 192 | waveOutUnprepareHeader=lib_winmm_waveOutUnprepareHeader @191 193 | waveOutWrite=lib_winmm_waveOutWrite @192 194 | wid32Message=lib_winmm_wid32Message @193 195 | wod32Message=lib_winmm_wod32Message @194 196 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/UniversalInjectorFramework.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {a13f8962-c15c-4ad1-b8db-502d6776ef64} 14 | 15 | 16 | {b60d6976-4731-446c-bb27-26d4609a4f7c} 17 | 18 | 19 | {5cd8fe93-e08e-4fb4-94b3-46626e5d447b} 20 | 21 | 22 | {40b37917-c6a3-4c82-89b8-ffe84113fae2} 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files\features 49 | 50 | 51 | Header Files\features 52 | 53 | 54 | Header Files\features 55 | 56 | 57 | Header Files\features 58 | 59 | 60 | Header Files\proxies 61 | 62 | 63 | Header Files\proxies 64 | 65 | 66 | Header Files\features 67 | 68 | 69 | Header Files\proxies 70 | 71 | 72 | Header Files 73 | 74 | 75 | Header Files\proxies 76 | 77 | 78 | Header Files\proxies 79 | 80 | 81 | Header Files\proxies 82 | 83 | 84 | Header Files\features 85 | 86 | 87 | Header Files\features 88 | 89 | 90 | Header Files 91 | 92 | 93 | Header Files\features 94 | 95 | 96 | Header Files 97 | 98 | 99 | Header Files 100 | 101 | 102 | Header Files\features 103 | 104 | 105 | Header Files\proxies 106 | 107 | 108 | Header Files\proxies 109 | 110 | 111 | Header Files\features 112 | 113 | 114 | Header Files\features 115 | 116 | 117 | Header Files\proxies 118 | 119 | 120 | Header Files\features 121 | 122 | 123 | Header Files\proxies 124 | 125 | 126 | Header Files\features 127 | 128 | 129 | 130 | 131 | Source Files 132 | 133 | 134 | Source Files 135 | 136 | 137 | Source Files 138 | 139 | 140 | Source Files 141 | 142 | 143 | Source Files 144 | 145 | 146 | Source Files 147 | 148 | 149 | Source Files 150 | 151 | 152 | Source Files\features 153 | 154 | 155 | Source Files\features 156 | 157 | 158 | Source Files\features 159 | 160 | 161 | Source Files\features 162 | 163 | 164 | Source Files\proxies 165 | 166 | 167 | Source Files\proxies 168 | 169 | 170 | Source Files\features 171 | 172 | 173 | Source Files\proxies 174 | 175 | 176 | Source Files 177 | 178 | 179 | Source Files\proxies 180 | 181 | 182 | Source Files\proxies 183 | 184 | 185 | Source Files\proxies 186 | 187 | 188 | Source Files\features 189 | 190 | 191 | Source Files\features 192 | 193 | 194 | Source Files\features 195 | 196 | 197 | Source Files\features 198 | 199 | 200 | Source Files\proxies 201 | 202 | 203 | Source Files\proxies 204 | 205 | 206 | Source Files\features 207 | 208 | 209 | Source Files\features 210 | 211 | 212 | Source Files\proxies 213 | 214 | 215 | Source Files\features 216 | 217 | 218 | Source Files\proxies 219 | 220 | 221 | Source Files\features 222 | 223 | 224 | Source Files\features 225 | 226 | 227 | 228 | 229 | Source Files\proxies 230 | 231 | 232 | Source Files\proxies 233 | 234 | 235 | Source Files\proxies 236 | 237 | 238 | Source Files\proxies 239 | 240 | 241 | Source Files\proxies 242 | 243 | 244 | Source Files\proxies 245 | 246 | 247 | Source Files\proxies 248 | 249 | 250 | Source Files\proxies 251 | 252 | 253 | Source Files\proxies 254 | 255 | 256 | Source Files\proxies 257 | 258 | 259 | 260 | 261 | Source Files 262 | 263 | 264 | Source Files 265 | 266 | 267 | -------------------------------------------------------------------------------- /src/Detours/uimports.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Add DLLs to a module import table (uimports.cpp of detours.lib) 4 | // 5 | // Microsoft Research Detours Package, Version 4.0.1 6 | // 7 | // Copyright (c) Microsoft Corporation. All rights reserved. 8 | // 9 | // Note that this file is included into creatwth.cpp one or more times 10 | // (once for each supported module format). 11 | // 12 | 13 | #if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH 14 | #error detours.h version mismatch 15 | #endif 16 | 17 | // UpdateImports32 aka UpdateImports64 18 | static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess, 19 | HMODULE hModule, 20 | __in_ecount(nDlls) LPCSTR *plpDlls, 21 | DWORD nDlls) 22 | { 23 | BOOL fSucceeded = FALSE; 24 | DWORD cbNew = 0; 25 | 26 | BYTE * pbNew = NULL; 27 | DWORD i; 28 | SIZE_T cbRead; 29 | DWORD n; 30 | 31 | PBYTE pbModule = (PBYTE)hModule; 32 | 33 | IMAGE_DOS_HEADER idh; 34 | ZeroMemory(&idh, sizeof(idh)); 35 | if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), &cbRead) 36 | || cbRead < sizeof(idh)) { 37 | 38 | DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %d\n", 39 | pbModule, pbModule + sizeof(idh), GetLastError())); 40 | 41 | finish: 42 | if (pbNew != NULL) { 43 | delete[] pbNew; 44 | pbNew = NULL; 45 | } 46 | return fSucceeded; 47 | } 48 | 49 | IMAGE_NT_HEADERS_XX inh; 50 | ZeroMemory(&inh, sizeof(inh)); 51 | 52 | if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), &cbRead) 53 | || cbRead < sizeof(inh)) { 54 | DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %d\n", 55 | pbModule + idh.e_lfanew, 56 | pbModule + idh.e_lfanew + sizeof(inh), 57 | GetLastError())); 58 | goto finish; 59 | } 60 | 61 | if (inh.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC_XX) { 62 | DETOUR_TRACE(("Wrong size image (%04x != %04x).\n", 63 | inh.OptionalHeader.Magic, IMAGE_NT_OPTIONAL_HDR_MAGIC_XX)); 64 | SetLastError(ERROR_INVALID_BLOCK); 65 | goto finish; 66 | } 67 | 68 | // Zero out the bound table so loader doesn't use it instead of our new table. 69 | inh.BOUND_DIRECTORY.VirtualAddress = 0; 70 | inh.BOUND_DIRECTORY.Size = 0; 71 | 72 | // Find the size of the mapped file. 73 | DWORD dwSec = idh.e_lfanew + 74 | FIELD_OFFSET(IMAGE_NT_HEADERS_XX, OptionalHeader) + 75 | inh.FileHeader.SizeOfOptionalHeader; 76 | 77 | for (i = 0; i < inh.FileHeader.NumberOfSections; i++) { 78 | IMAGE_SECTION_HEADER ish; 79 | ZeroMemory(&ish, sizeof(ish)); 80 | 81 | if (!ReadProcessMemory(hProcess, pbModule + dwSec + sizeof(ish) * i, &ish, 82 | sizeof(ish), &cbRead) 83 | || cbRead < sizeof(ish)) { 84 | 85 | DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %d\n", 86 | pbModule + dwSec + sizeof(ish) * i, 87 | pbModule + dwSec + sizeof(ish) * (i + 1), 88 | GetLastError())); 89 | goto finish; 90 | } 91 | 92 | DETOUR_TRACE(("ish[%d] : va=%08x sr=%d\n", i, ish.VirtualAddress, ish.SizeOfRawData)); 93 | 94 | // If the file didn't have an IAT_DIRECTORY, we assign it... 95 | if (inh.IAT_DIRECTORY.VirtualAddress == 0 && 96 | inh.IMPORT_DIRECTORY.VirtualAddress >= ish.VirtualAddress && 97 | inh.IMPORT_DIRECTORY.VirtualAddress < ish.VirtualAddress + ish.SizeOfRawData) { 98 | 99 | inh.IAT_DIRECTORY.VirtualAddress = ish.VirtualAddress; 100 | inh.IAT_DIRECTORY.Size = ish.SizeOfRawData; 101 | } 102 | } 103 | 104 | DETOUR_TRACE((" Imports: %p..%p\n", 105 | (DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress, 106 | (DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress + 107 | inh.IMPORT_DIRECTORY.Size)); 108 | 109 | DWORD nOldDlls = inh.IMPORT_DIRECTORY.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR); 110 | DWORD obRem = sizeof(IMAGE_IMPORT_DESCRIPTOR) * nDlls; 111 | DWORD obOld = obRem + sizeof(IMAGE_IMPORT_DESCRIPTOR) * nOldDlls; 112 | DWORD obTab = PadToDwordPtr(obOld); 113 | DWORD obDll = obTab + sizeof(DWORD_XX) * 4 * nDlls; 114 | DWORD obStr = obDll; 115 | cbNew = obStr; 116 | for (n = 0; n < nDlls; n++) { 117 | cbNew += PadToDword((DWORD)strlen(plpDlls[n]) + 1); 118 | } 119 | 120 | _Analysis_assume_(cbNew > 121 | sizeof(IMAGE_IMPORT_DESCRIPTOR) * (nDlls + nOldDlls) 122 | + sizeof(DWORD_XX) * 4 * nDlls); 123 | pbNew = new BYTE [cbNew]; 124 | if (pbNew == NULL) { 125 | DETOUR_TRACE(("new BYTE [cbNew] failed.\n")); 126 | goto finish; 127 | } 128 | ZeroMemory(pbNew, cbNew); 129 | 130 | PBYTE pbBase = pbModule; 131 | PBYTE pbNext = pbBase 132 | + inh.OptionalHeader.BaseOfCode 133 | + inh.OptionalHeader.SizeOfCode 134 | + inh.OptionalHeader.SizeOfInitializedData 135 | + inh.OptionalHeader.SizeOfUninitializedData; 136 | if (pbBase < pbNext) { 137 | pbBase = pbNext; 138 | } 139 | DETOUR_TRACE(("pbBase = %p\n", pbBase)); 140 | 141 | PBYTE pbNewIid = FindAndAllocateNearBase(hProcess, pbBase, cbNew); 142 | if (pbNewIid == NULL) { 143 | DETOUR_TRACE(("FindAndAllocateNearBase failed.\n")); 144 | goto finish; 145 | } 146 | 147 | PIMAGE_IMPORT_DESCRIPTOR piid = (PIMAGE_IMPORT_DESCRIPTOR)pbNew; 148 | DWORD_XX *pt; 149 | 150 | DWORD obBase = (DWORD)(pbNewIid - pbModule); 151 | DWORD dwProtect = 0; 152 | 153 | if (inh.IMPORT_DIRECTORY.VirtualAddress != 0) { 154 | // Read the old import directory if it exists. 155 | DETOUR_TRACE(("IMPORT_DIRECTORY perms=%x\n", dwProtect)); 156 | 157 | if (!ReadProcessMemory(hProcess, 158 | pbModule + inh.IMPORT_DIRECTORY.VirtualAddress, 159 | &piid[nDlls], 160 | nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR), &cbRead) 161 | || cbRead < nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR)) { 162 | 163 | DETOUR_TRACE(("ReadProcessMemory(imports) failed: %d\n", GetLastError())); 164 | goto finish; 165 | } 166 | } 167 | 168 | for (n = 0; n < nDlls; n++) { 169 | HRESULT hrRet = StringCchCopyA((char*)pbNew + obStr, cbNew - obStr, plpDlls[n]); 170 | if (FAILED(hrRet)) { 171 | DETOUR_TRACE(("StringCchCopyA failed: %d\n", GetLastError())); 172 | goto finish; 173 | } 174 | 175 | // After copying the string, we patch up the size "??" bits if any. 176 | hrRet = ReplaceOptionalSizeA((char*)pbNew + obStr, 177 | cbNew - obStr, 178 | DETOURS_STRINGIFY(DETOURS_BITS_XX)); 179 | if (FAILED(hrRet)) { 180 | DETOUR_TRACE(("ReplaceOptionalSizeA failed: %d\n", GetLastError())); 181 | goto finish; 182 | } 183 | 184 | DWORD nOffset = obTab + (sizeof(DWORD_XX) * (4 * n)); 185 | piid[n].OriginalFirstThunk = obBase + nOffset; 186 | pt = ((DWORD_XX*)(pbNew + nOffset)); 187 | pt[0] = IMAGE_ORDINAL_FLAG_XX + 1; 188 | pt[1] = 0; 189 | 190 | nOffset = obTab + (sizeof(DWORD_XX) * ((4 * n) + 2)); 191 | piid[n].FirstThunk = obBase + nOffset; 192 | pt = ((DWORD_XX*)(pbNew + nOffset)); 193 | pt[0] = IMAGE_ORDINAL_FLAG_XX + 1; 194 | pt[1] = 0; 195 | piid[n].TimeDateStamp = 0; 196 | piid[n].ForwarderChain = 0; 197 | piid[n].Name = obBase + obStr; 198 | 199 | obStr += PadToDword((DWORD)strlen(plpDlls[n]) + 1); 200 | } 201 | _Analysis_assume_(obStr <= cbNew); 202 | 203 | #if 0 204 | for (i = 0; i < nDlls + nOldDlls; i++) { 205 | DETOUR_TRACE(("%8d. Look=%08x Time=%08x Fore=%08x Name=%08x Addr=%08x\n", 206 | i, 207 | piid[i].OriginalFirstThunk, 208 | piid[i].TimeDateStamp, 209 | piid[i].ForwarderChain, 210 | piid[i].Name, 211 | piid[i].FirstThunk)); 212 | if (piid[i].OriginalFirstThunk == 0 && piid[i].FirstThunk == 0) { 213 | break; 214 | } 215 | } 216 | #endif 217 | 218 | if (!WriteProcessMemory(hProcess, pbNewIid, pbNew, obStr, NULL)) { 219 | DETOUR_TRACE(("WriteProcessMemory(iid) failed: %d\n", GetLastError())); 220 | goto finish; 221 | } 222 | 223 | DETOUR_TRACE(("obBaseBef = %08x..%08x\n", 224 | inh.IMPORT_DIRECTORY.VirtualAddress, 225 | inh.IMPORT_DIRECTORY.VirtualAddress + inh.IMPORT_DIRECTORY.Size)); 226 | DETOUR_TRACE(("obBaseAft = %08x..%08x\n", obBase, obBase + obStr)); 227 | 228 | // If the file doesn't have an IAT_DIRECTORY, we create it... 229 | if (inh.IAT_DIRECTORY.VirtualAddress == 0) { 230 | inh.IAT_DIRECTORY.VirtualAddress = obBase; 231 | inh.IAT_DIRECTORY.Size = cbNew; 232 | } 233 | 234 | inh.IMPORT_DIRECTORY.VirtualAddress = obBase; 235 | inh.IMPORT_DIRECTORY.Size = cbNew; 236 | 237 | /////////////////////// Update the NT header for the new import directory. 238 | // 239 | if (!DetourVirtualProtectSameExecuteEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders, 240 | PAGE_EXECUTE_READWRITE, &dwProtect)) { 241 | DETOUR_TRACE(("VirtualProtectEx(inh) write failed: %d\n", GetLastError())); 242 | goto finish; 243 | } 244 | 245 | inh.OptionalHeader.CheckSum = 0; 246 | 247 | if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) { 248 | DETOUR_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError())); 249 | goto finish; 250 | } 251 | DETOUR_TRACE(("WriteProcessMemory(idh:%p..%p)\n", pbModule, pbModule + sizeof(idh))); 252 | 253 | if (!WriteProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) { 254 | DETOUR_TRACE(("WriteProcessMemory(inh) failed: %d\n", GetLastError())); 255 | goto finish; 256 | } 257 | DETOUR_TRACE(("WriteProcessMemory(inh:%p..%p)\n", 258 | pbModule + idh.e_lfanew, 259 | pbModule + idh.e_lfanew + sizeof(inh))); 260 | 261 | if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders, 262 | dwProtect, &dwProtect)) { 263 | DETOUR_TRACE(("VirtualProtectEx(idh) restore failed: %d\n", GetLastError())); 264 | goto finish; 265 | } 266 | 267 | fSucceeded = TRUE; 268 | goto finish; 269 | } 270 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31912.275 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UniversalInjectorFramework", "UniversalInjectorFramework\UniversalInjectorFramework.vcxproj", "{CBBF2C50-0662-4442-AD10-881D8E95DDA3}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Detours", "Detours\Detours.vcxproj", "{962A7719-2381-40D0-8214-377689F9429A}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProxyGenerator", "ProxyGenerator\ProxyGenerator.vcxproj", "{024CF2E7-6985-4536-B063-55822E5F2696}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | d3d11|x64 = d3d11|x64 15 | d3d11|x86 = d3d11|x86 16 | d3d8|x64 = d3d8|x64 17 | d3d8|x86 = d3d8|x86 18 | d3d9|x64 = d3d9|x64 19 | d3d9|x86 = d3d9|x86 20 | d3dcompiler_43|x64 = d3dcompiler_43|x64 21 | d3dcompiler_43|x86 = d3dcompiler_43|x86 22 | d3dcompiler_47|x64 = d3dcompiler_47|x64 23 | d3dcompiler_47|x86 = d3dcompiler_47|x86 24 | d3dx9_43|x64 = d3dx9_43|x64 25 | d3dx9_43|x86 = d3dx9_43|x86 26 | dxgi|x64 = dxgi|x64 27 | dxgi|x86 = dxgi|x86 28 | opengl32|x64 = opengl32|x64 29 | opengl32|x86 = opengl32|x86 30 | version|x64 = version|x64 31 | version|x86 = version|x86 32 | winmm|x64 = winmm|x64 33 | winmm|x86 = winmm|x86 34 | EndGlobalSection 35 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 36 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3d11|x64.ActiveCfg = d3d11|x64 37 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3d11|x64.Build.0 = d3d11|x64 38 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3d11|x86.ActiveCfg = d3d11|Win32 39 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3d11|x86.Build.0 = d3d11|Win32 40 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3d8|x64.ActiveCfg = d3d8|x64 41 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3d8|x64.Build.0 = d3d8|x64 42 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3d8|x86.ActiveCfg = d3d8|Win32 43 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3d8|x86.Build.0 = d3d8|Win32 44 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3d9|x64.ActiveCfg = d3d9|x64 45 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3d9|x64.Build.0 = d3d9|x64 46 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3d9|x86.ActiveCfg = d3d9|Win32 47 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3d9|x86.Build.0 = d3d9|Win32 48 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3dcompiler_43|x64.ActiveCfg = d3dcompiler_43|x64 49 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3dcompiler_43|x64.Build.0 = d3dcompiler_43|x64 50 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3dcompiler_43|x86.ActiveCfg = d3dcompiler_43|Win32 51 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3dcompiler_43|x86.Build.0 = d3dcompiler_43|Win32 52 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3dcompiler_47|x64.ActiveCfg = d3dcompiler_47|x64 53 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3dcompiler_47|x64.Build.0 = d3dcompiler_47|x64 54 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3dcompiler_47|x86.ActiveCfg = d3d9|Win32 55 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3dcompiler_47|x86.Build.0 = d3d9|Win32 56 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3dx9_43|x64.ActiveCfg = d3dx9_43|x64 57 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3dx9_43|x64.Build.0 = d3dx9_43|x64 58 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3dx9_43|x86.ActiveCfg = d3dx9_43|Win32 59 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.d3dx9_43|x86.Build.0 = d3dx9_43|Win32 60 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.dxgi|x64.ActiveCfg = dxgi|x64 61 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.dxgi|x64.Build.0 = dxgi|x64 62 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.dxgi|x86.ActiveCfg = d3d9|Win32 63 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.dxgi|x86.Build.0 = d3d9|Win32 64 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.opengl32|x64.ActiveCfg = opengl32|x64 65 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.opengl32|x64.Build.0 = opengl32|x64 66 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.opengl32|x86.ActiveCfg = opengl32|Win32 67 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.opengl32|x86.Build.0 = opengl32|Win32 68 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.version|x64.ActiveCfg = version|x64 69 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.version|x64.Build.0 = version|x64 70 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.version|x86.ActiveCfg = version|Win32 71 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.version|x86.Build.0 = version|Win32 72 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.winmm|x64.ActiveCfg = winmm|x64 73 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.winmm|x64.Build.0 = winmm|x64 74 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.winmm|x86.ActiveCfg = winmm|Win32 75 | {CBBF2C50-0662-4442-AD10-881D8E95DDA3}.winmm|x86.Build.0 = winmm|Win32 76 | {962A7719-2381-40D0-8214-377689F9429A}.d3d11|x64.ActiveCfg = Debug|x64 77 | {962A7719-2381-40D0-8214-377689F9429A}.d3d11|x64.Build.0 = Debug|x64 78 | {962A7719-2381-40D0-8214-377689F9429A}.d3d11|x86.ActiveCfg = Debug|Win32 79 | {962A7719-2381-40D0-8214-377689F9429A}.d3d11|x86.Build.0 = Debug|Win32 80 | {962A7719-2381-40D0-8214-377689F9429A}.d3d8|x64.ActiveCfg = Debug|x64 81 | {962A7719-2381-40D0-8214-377689F9429A}.d3d8|x64.Build.0 = Debug|x64 82 | {962A7719-2381-40D0-8214-377689F9429A}.d3d8|x86.ActiveCfg = Debug|Win32 83 | {962A7719-2381-40D0-8214-377689F9429A}.d3d8|x86.Build.0 = Debug|Win32 84 | {962A7719-2381-40D0-8214-377689F9429A}.d3d9|x64.ActiveCfg = Debug|x64 85 | {962A7719-2381-40D0-8214-377689F9429A}.d3d9|x64.Build.0 = Debug|x64 86 | {962A7719-2381-40D0-8214-377689F9429A}.d3d9|x86.ActiveCfg = Debug|Win32 87 | {962A7719-2381-40D0-8214-377689F9429A}.d3d9|x86.Build.0 = Debug|Win32 88 | {962A7719-2381-40D0-8214-377689F9429A}.d3dcompiler_43|x64.ActiveCfg = Debug|x64 89 | {962A7719-2381-40D0-8214-377689F9429A}.d3dcompiler_43|x64.Build.0 = Debug|x64 90 | {962A7719-2381-40D0-8214-377689F9429A}.d3dcompiler_43|x86.ActiveCfg = Debug|Win32 91 | {962A7719-2381-40D0-8214-377689F9429A}.d3dcompiler_43|x86.Build.0 = Debug|Win32 92 | {962A7719-2381-40D0-8214-377689F9429A}.d3dcompiler_47|x64.ActiveCfg = Debug|x64 93 | {962A7719-2381-40D0-8214-377689F9429A}.d3dcompiler_47|x64.Build.0 = Debug|x64 94 | {962A7719-2381-40D0-8214-377689F9429A}.d3dcompiler_47|x86.ActiveCfg = Debug|Win32 95 | {962A7719-2381-40D0-8214-377689F9429A}.d3dcompiler_47|x86.Build.0 = Debug|Win32 96 | {962A7719-2381-40D0-8214-377689F9429A}.d3dx9_43|x64.ActiveCfg = Debug|x64 97 | {962A7719-2381-40D0-8214-377689F9429A}.d3dx9_43|x86.ActiveCfg = Debug|Win32 98 | {962A7719-2381-40D0-8214-377689F9429A}.d3dx9_43|x86.Build.0 = Debug|Win32 99 | {962A7719-2381-40D0-8214-377689F9429A}.dxgi|x64.ActiveCfg = Debug|x64 100 | {962A7719-2381-40D0-8214-377689F9429A}.dxgi|x64.Build.0 = Debug|x64 101 | {962A7719-2381-40D0-8214-377689F9429A}.dxgi|x86.ActiveCfg = Debug|Win32 102 | {962A7719-2381-40D0-8214-377689F9429A}.dxgi|x86.Build.0 = Debug|Win32 103 | {962A7719-2381-40D0-8214-377689F9429A}.opengl32|x64.ActiveCfg = Debug|x64 104 | {962A7719-2381-40D0-8214-377689F9429A}.opengl32|x64.Build.0 = Debug|x64 105 | {962A7719-2381-40D0-8214-377689F9429A}.opengl32|x86.ActiveCfg = Debug|Win32 106 | {962A7719-2381-40D0-8214-377689F9429A}.opengl32|x86.Build.0 = Debug|Win32 107 | {962A7719-2381-40D0-8214-377689F9429A}.version|x64.ActiveCfg = Debug|x64 108 | {962A7719-2381-40D0-8214-377689F9429A}.version|x64.Build.0 = Debug|x64 109 | {962A7719-2381-40D0-8214-377689F9429A}.version|x86.ActiveCfg = Debug|Win32 110 | {962A7719-2381-40D0-8214-377689F9429A}.version|x86.Build.0 = Debug|Win32 111 | {962A7719-2381-40D0-8214-377689F9429A}.winmm|x64.ActiveCfg = Debug|x64 112 | {962A7719-2381-40D0-8214-377689F9429A}.winmm|x64.Build.0 = Debug|x64 113 | {962A7719-2381-40D0-8214-377689F9429A}.winmm|x86.ActiveCfg = Debug|Win32 114 | {962A7719-2381-40D0-8214-377689F9429A}.winmm|x86.Build.0 = Debug|Win32 115 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3d11|x64.ActiveCfg = Debug|x64 116 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3d11|x64.Build.0 = Debug|x64 117 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3d11|x86.ActiveCfg = Debug|Win32 118 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3d11|x86.Build.0 = Debug|Win32 119 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3d8|x64.ActiveCfg = Debug|x64 120 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3d8|x64.Build.0 = Debug|x64 121 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3d8|x86.ActiveCfg = Debug|Win32 122 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3d8|x86.Build.0 = Debug|Win32 123 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3d9|x64.ActiveCfg = Debug|x64 124 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3d9|x64.Build.0 = Debug|x64 125 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3d9|x86.ActiveCfg = Debug|Win32 126 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3d9|x86.Build.0 = Debug|Win32 127 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3dcompiler_43|x64.ActiveCfg = Debug|x64 128 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3dcompiler_43|x64.Build.0 = Debug|x64 129 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3dcompiler_43|x86.ActiveCfg = Debug|Win32 130 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3dcompiler_43|x86.Build.0 = Debug|Win32 131 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3dcompiler_47|x64.ActiveCfg = Debug|x64 132 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3dcompiler_47|x64.Build.0 = Debug|x64 133 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3dcompiler_47|x86.ActiveCfg = Debug|Win32 134 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3dcompiler_47|x86.Build.0 = Debug|Win32 135 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3dx9_43|x64.ActiveCfg = Debug|x64 136 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3dx9_43|x86.ActiveCfg = Debug|Win32 137 | {024CF2E7-6985-4536-B063-55822E5F2696}.d3dx9_43|x86.Build.0 = Debug|Win32 138 | {024CF2E7-6985-4536-B063-55822E5F2696}.dxgi|x64.ActiveCfg = Debug|x64 139 | {024CF2E7-6985-4536-B063-55822E5F2696}.dxgi|x64.Build.0 = Debug|x64 140 | {024CF2E7-6985-4536-B063-55822E5F2696}.dxgi|x86.ActiveCfg = Debug|Win32 141 | {024CF2E7-6985-4536-B063-55822E5F2696}.dxgi|x86.Build.0 = Debug|Win32 142 | {024CF2E7-6985-4536-B063-55822E5F2696}.opengl32|x64.ActiveCfg = Debug|x64 143 | {024CF2E7-6985-4536-B063-55822E5F2696}.opengl32|x64.Build.0 = Debug|x64 144 | {024CF2E7-6985-4536-B063-55822E5F2696}.opengl32|x86.ActiveCfg = Debug|Win32 145 | {024CF2E7-6985-4536-B063-55822E5F2696}.opengl32|x86.Build.0 = Debug|Win32 146 | {024CF2E7-6985-4536-B063-55822E5F2696}.version|x64.ActiveCfg = Debug|x64 147 | {024CF2E7-6985-4536-B063-55822E5F2696}.version|x64.Build.0 = Debug|x64 148 | {024CF2E7-6985-4536-B063-55822E5F2696}.version|x86.ActiveCfg = Debug|Win32 149 | {024CF2E7-6985-4536-B063-55822E5F2696}.version|x86.Build.0 = Debug|Win32 150 | {024CF2E7-6985-4536-B063-55822E5F2696}.winmm|x64.ActiveCfg = Debug|x64 151 | {024CF2E7-6985-4536-B063-55822E5F2696}.winmm|x64.Build.0 = Debug|x64 152 | {024CF2E7-6985-4536-B063-55822E5F2696}.winmm|x86.ActiveCfg = Debug|Win32 153 | {024CF2E7-6985-4536-B063-55822E5F2696}.winmm|x86.Build.0 = Debug|Win32 154 | EndGlobalSection 155 | GlobalSection(SolutionProperties) = preSolution 156 | HideSolutionNode = FALSE 157 | EndGlobalSection 158 | GlobalSection(ExtensibilityGlobals) = postSolution 159 | SolutionGuid = {9F840163-4FF0-4E8A-A78C-CA364B626FDB} 160 | EndGlobalSection 161 | EndGlobal 162 | -------------------------------------------------------------------------------- /src/UniversalInjectorFramework/proxies/d3d11.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #ifdef UIF_LIB_D3D11 4 | 5 | #include "injector.h" 6 | 7 | struct { 8 | HMODULE dll; 9 | FARPROC D3D11CreateDeviceForD3D12; 10 | FARPROC D3DKMTCloseAdapter; 11 | FARPROC D3DKMTDestroyAllocation; 12 | FARPROC D3DKMTDestroyContext; 13 | FARPROC D3DKMTDestroyDevice; 14 | FARPROC D3DKMTDestroySynchronizationObject; 15 | FARPROC D3DKMTPresent; 16 | FARPROC D3DKMTQueryAdapterInfo; 17 | FARPROC D3DKMTSetDisplayPrivateDriverFormat; 18 | FARPROC D3DKMTSignalSynchronizationObject; 19 | FARPROC D3DKMTUnlock; 20 | FARPROC D3DKMTWaitForSynchronizationObject; 21 | FARPROC EnableFeatureLevelUpgrade; 22 | FARPROC OpenAdapter10; 23 | FARPROC OpenAdapter10_2; 24 | FARPROC CreateDirect3D11DeviceFromDXGIDevice; 25 | FARPROC CreateDirect3D11SurfaceFromDXGISurface; 26 | FARPROC D3D11CoreCreateDevice; 27 | FARPROC D3D11CoreCreateLayeredDevice; 28 | FARPROC D3D11CoreGetLayeredDeviceSize; 29 | FARPROC D3D11CoreRegisterLayers; 30 | FARPROC D3D11CreateDevice; 31 | FARPROC D3D11CreateDeviceAndSwapChain; 32 | FARPROC D3D11On12CreateDevice; 33 | FARPROC D3DKMTCreateAllocation; 34 | FARPROC D3DKMTCreateContext; 35 | FARPROC D3DKMTCreateDevice; 36 | FARPROC D3DKMTCreateSynchronizationObject; 37 | FARPROC D3DKMTEscape; 38 | FARPROC D3DKMTGetContextSchedulingPriority; 39 | FARPROC D3DKMTGetDeviceState; 40 | FARPROC D3DKMTGetDisplayModeList; 41 | FARPROC D3DKMTGetMultisampleMethodList; 42 | FARPROC D3DKMTGetRuntimeData; 43 | FARPROC D3DKMTGetSharedPrimaryHandle; 44 | FARPROC D3DKMTLock; 45 | FARPROC D3DKMTOpenAdapterFromHdc; 46 | FARPROC D3DKMTOpenResource; 47 | FARPROC D3DKMTQueryAllocationResidency; 48 | FARPROC D3DKMTQueryResourceInfo; 49 | FARPROC D3DKMTRender; 50 | FARPROC D3DKMTSetAllocationPriority; 51 | FARPROC D3DKMTSetContextSchedulingPriority; 52 | FARPROC D3DKMTSetDisplayMode; 53 | FARPROC D3DKMTSetGammaRamp; 54 | FARPROC D3DKMTSetVidPnSourceOwner; 55 | FARPROC D3DKMTWaitForVerticalBlankEvent; 56 | FARPROC D3DPerformance_BeginEvent; 57 | FARPROC D3DPerformance_EndEvent; 58 | FARPROC D3DPerformance_GetStatus; 59 | FARPROC D3DPerformance_SetMarker; 60 | } d3d11; 61 | 62 | void lib_d3d11_D3D11CreateDeviceForD3D12() { d3d11.D3D11CreateDeviceForD3D12(); } 63 | void lib_d3d11_D3DKMTCloseAdapter() { d3d11.D3DKMTCloseAdapter(); } 64 | void lib_d3d11_D3DKMTDestroyAllocation() { d3d11.D3DKMTDestroyAllocation(); } 65 | void lib_d3d11_D3DKMTDestroyContext() { d3d11.D3DKMTDestroyContext(); } 66 | void lib_d3d11_D3DKMTDestroyDevice() { d3d11.D3DKMTDestroyDevice(); } 67 | void lib_d3d11_D3DKMTDestroySynchronizationObject() { d3d11.D3DKMTDestroySynchronizationObject(); } 68 | void lib_d3d11_D3DKMTPresent() { d3d11.D3DKMTPresent(); } 69 | void lib_d3d11_D3DKMTQueryAdapterInfo() { d3d11.D3DKMTQueryAdapterInfo(); } 70 | void lib_d3d11_D3DKMTSetDisplayPrivateDriverFormat() { d3d11.D3DKMTSetDisplayPrivateDriverFormat(); } 71 | void lib_d3d11_D3DKMTSignalSynchronizationObject() { d3d11.D3DKMTSignalSynchronizationObject(); } 72 | void lib_d3d11_D3DKMTUnlock() { d3d11.D3DKMTUnlock(); } 73 | void lib_d3d11_D3DKMTWaitForSynchronizationObject() { d3d11.D3DKMTWaitForSynchronizationObject(); } 74 | void lib_d3d11_EnableFeatureLevelUpgrade() { d3d11.EnableFeatureLevelUpgrade(); } 75 | void lib_d3d11_OpenAdapter10() { d3d11.OpenAdapter10(); } 76 | void lib_d3d11_OpenAdapter10_2() { d3d11.OpenAdapter10_2(); } 77 | void lib_d3d11_CreateDirect3D11DeviceFromDXGIDevice() { d3d11.CreateDirect3D11DeviceFromDXGIDevice(); } 78 | void lib_d3d11_CreateDirect3D11SurfaceFromDXGISurface() { d3d11.CreateDirect3D11SurfaceFromDXGISurface(); } 79 | void lib_d3d11_D3D11CoreCreateDevice() { d3d11.D3D11CoreCreateDevice(); } 80 | void lib_d3d11_D3D11CoreCreateLayeredDevice() { d3d11.D3D11CoreCreateLayeredDevice(); } 81 | void lib_d3d11_D3D11CoreGetLayeredDeviceSize() { d3d11.D3D11CoreGetLayeredDeviceSize(); } 82 | void lib_d3d11_D3D11CoreRegisterLayers() { d3d11.D3D11CoreRegisterLayers(); } 83 | void lib_d3d11_D3D11CreateDevice() { d3d11.D3D11CreateDevice(); } 84 | void lib_d3d11_D3D11CreateDeviceAndSwapChain() { d3d11.D3D11CreateDeviceAndSwapChain(); } 85 | void lib_d3d11_D3D11On12CreateDevice() { d3d11.D3D11On12CreateDevice(); } 86 | void lib_d3d11_D3DKMTCreateAllocation() { d3d11.D3DKMTCreateAllocation(); } 87 | void lib_d3d11_D3DKMTCreateContext() { d3d11.D3DKMTCreateContext(); } 88 | void lib_d3d11_D3DKMTCreateDevice() { d3d11.D3DKMTCreateDevice(); } 89 | void lib_d3d11_D3DKMTCreateSynchronizationObject() { d3d11.D3DKMTCreateSynchronizationObject(); } 90 | void lib_d3d11_D3DKMTEscape() { d3d11.D3DKMTEscape(); } 91 | void lib_d3d11_D3DKMTGetContextSchedulingPriority() { d3d11.D3DKMTGetContextSchedulingPriority(); } 92 | void lib_d3d11_D3DKMTGetDeviceState() { d3d11.D3DKMTGetDeviceState(); } 93 | void lib_d3d11_D3DKMTGetDisplayModeList() { d3d11.D3DKMTGetDisplayModeList(); } 94 | void lib_d3d11_D3DKMTGetMultisampleMethodList() { d3d11.D3DKMTGetMultisampleMethodList(); } 95 | void lib_d3d11_D3DKMTGetRuntimeData() { d3d11.D3DKMTGetRuntimeData(); } 96 | void lib_d3d11_D3DKMTGetSharedPrimaryHandle() { d3d11.D3DKMTGetSharedPrimaryHandle(); } 97 | void lib_d3d11_D3DKMTLock() { d3d11.D3DKMTLock(); } 98 | void lib_d3d11_D3DKMTOpenAdapterFromHdc() { d3d11.D3DKMTOpenAdapterFromHdc(); } 99 | void lib_d3d11_D3DKMTOpenResource() { d3d11.D3DKMTOpenResource(); } 100 | void lib_d3d11_D3DKMTQueryAllocationResidency() { d3d11.D3DKMTQueryAllocationResidency(); } 101 | void lib_d3d11_D3DKMTQueryResourceInfo() { d3d11.D3DKMTQueryResourceInfo(); } 102 | void lib_d3d11_D3DKMTRender() { d3d11.D3DKMTRender(); } 103 | void lib_d3d11_D3DKMTSetAllocationPriority() { d3d11.D3DKMTSetAllocationPriority(); } 104 | void lib_d3d11_D3DKMTSetContextSchedulingPriority() { d3d11.D3DKMTSetContextSchedulingPriority(); } 105 | void lib_d3d11_D3DKMTSetDisplayMode() { d3d11.D3DKMTSetDisplayMode(); } 106 | void lib_d3d11_D3DKMTSetGammaRamp() { d3d11.D3DKMTSetGammaRamp(); } 107 | void lib_d3d11_D3DKMTSetVidPnSourceOwner() { d3d11.D3DKMTSetVidPnSourceOwner(); } 108 | void lib_d3d11_D3DKMTWaitForVerticalBlankEvent() { d3d11.D3DKMTWaitForVerticalBlankEvent(); } 109 | void lib_d3d11_D3DPerformance_BeginEvent() { d3d11.D3DPerformance_BeginEvent(); } 110 | void lib_d3d11_D3DPerformance_EndEvent() { d3d11.D3DPerformance_EndEvent(); } 111 | void lib_d3d11_D3DPerformance_GetStatus() { d3d11.D3DPerformance_GetStatus(); } 112 | void lib_d3d11_D3DPerformance_SetMarker() { d3d11.D3DPerformance_SetMarker(); } 113 | 114 | bool load_library_d3d11() { 115 | d3d11.dll = uif::injector::instance().load_real_library("d3d11.dll"); 116 | d3d11.D3D11CreateDeviceForD3D12 = GetProcAddress(d3d11.dll, "D3D11CreateDeviceForD3D12"); 117 | d3d11.D3DKMTCloseAdapter = GetProcAddress(d3d11.dll, "D3DKMTCloseAdapter"); 118 | d3d11.D3DKMTDestroyAllocation = GetProcAddress(d3d11.dll, "D3DKMTDestroyAllocation"); 119 | d3d11.D3DKMTDestroyContext = GetProcAddress(d3d11.dll, "D3DKMTDestroyContext"); 120 | d3d11.D3DKMTDestroyDevice = GetProcAddress(d3d11.dll, "D3DKMTDestroyDevice"); 121 | d3d11.D3DKMTDestroySynchronizationObject = GetProcAddress(d3d11.dll, "D3DKMTDestroySynchronizationObject"); 122 | d3d11.D3DKMTPresent = GetProcAddress(d3d11.dll, "D3DKMTPresent"); 123 | d3d11.D3DKMTQueryAdapterInfo = GetProcAddress(d3d11.dll, "D3DKMTQueryAdapterInfo"); 124 | d3d11.D3DKMTSetDisplayPrivateDriverFormat = GetProcAddress(d3d11.dll, "D3DKMTSetDisplayPrivateDriverFormat"); 125 | d3d11.D3DKMTSignalSynchronizationObject = GetProcAddress(d3d11.dll, "D3DKMTSignalSynchronizationObject"); 126 | d3d11.D3DKMTUnlock = GetProcAddress(d3d11.dll, "D3DKMTUnlock"); 127 | d3d11.D3DKMTWaitForSynchronizationObject = GetProcAddress(d3d11.dll, "D3DKMTWaitForSynchronizationObject"); 128 | d3d11.EnableFeatureLevelUpgrade = GetProcAddress(d3d11.dll, "EnableFeatureLevelUpgrade"); 129 | d3d11.OpenAdapter10 = GetProcAddress(d3d11.dll, "OpenAdapter10"); 130 | d3d11.OpenAdapter10_2 = GetProcAddress(d3d11.dll, "OpenAdapter10_2"); 131 | d3d11.CreateDirect3D11DeviceFromDXGIDevice = GetProcAddress(d3d11.dll, "CreateDirect3D11DeviceFromDXGIDevice"); 132 | d3d11.CreateDirect3D11SurfaceFromDXGISurface = GetProcAddress(d3d11.dll, "CreateDirect3D11SurfaceFromDXGISurface"); 133 | d3d11.D3D11CoreCreateDevice = GetProcAddress(d3d11.dll, "D3D11CoreCreateDevice"); 134 | d3d11.D3D11CoreCreateLayeredDevice = GetProcAddress(d3d11.dll, "D3D11CoreCreateLayeredDevice"); 135 | d3d11.D3D11CoreGetLayeredDeviceSize = GetProcAddress(d3d11.dll, "D3D11CoreGetLayeredDeviceSize"); 136 | d3d11.D3D11CoreRegisterLayers = GetProcAddress(d3d11.dll, "D3D11CoreRegisterLayers"); 137 | d3d11.D3D11CreateDevice = GetProcAddress(d3d11.dll, "D3D11CreateDevice"); 138 | d3d11.D3D11CreateDeviceAndSwapChain = GetProcAddress(d3d11.dll, "D3D11CreateDeviceAndSwapChain"); 139 | d3d11.D3D11On12CreateDevice = GetProcAddress(d3d11.dll, "D3D11On12CreateDevice"); 140 | d3d11.D3DKMTCreateAllocation = GetProcAddress(d3d11.dll, "D3DKMTCreateAllocation"); 141 | d3d11.D3DKMTCreateContext = GetProcAddress(d3d11.dll, "D3DKMTCreateContext"); 142 | d3d11.D3DKMTCreateDevice = GetProcAddress(d3d11.dll, "D3DKMTCreateDevice"); 143 | d3d11.D3DKMTCreateSynchronizationObject = GetProcAddress(d3d11.dll, "D3DKMTCreateSynchronizationObject"); 144 | d3d11.D3DKMTEscape = GetProcAddress(d3d11.dll, "D3DKMTEscape"); 145 | d3d11.D3DKMTGetContextSchedulingPriority = GetProcAddress(d3d11.dll, "D3DKMTGetContextSchedulingPriority"); 146 | d3d11.D3DKMTGetDeviceState = GetProcAddress(d3d11.dll, "D3DKMTGetDeviceState"); 147 | d3d11.D3DKMTGetDisplayModeList = GetProcAddress(d3d11.dll, "D3DKMTGetDisplayModeList"); 148 | d3d11.D3DKMTGetMultisampleMethodList = GetProcAddress(d3d11.dll, "D3DKMTGetMultisampleMethodList"); 149 | d3d11.D3DKMTGetRuntimeData = GetProcAddress(d3d11.dll, "D3DKMTGetRuntimeData"); 150 | d3d11.D3DKMTGetSharedPrimaryHandle = GetProcAddress(d3d11.dll, "D3DKMTGetSharedPrimaryHandle"); 151 | d3d11.D3DKMTLock = GetProcAddress(d3d11.dll, "D3DKMTLock"); 152 | d3d11.D3DKMTOpenAdapterFromHdc = GetProcAddress(d3d11.dll, "D3DKMTOpenAdapterFromHdc"); 153 | d3d11.D3DKMTOpenResource = GetProcAddress(d3d11.dll, "D3DKMTOpenResource"); 154 | d3d11.D3DKMTQueryAllocationResidency = GetProcAddress(d3d11.dll, "D3DKMTQueryAllocationResidency"); 155 | d3d11.D3DKMTQueryResourceInfo = GetProcAddress(d3d11.dll, "D3DKMTQueryResourceInfo"); 156 | d3d11.D3DKMTRender = GetProcAddress(d3d11.dll, "D3DKMTRender"); 157 | d3d11.D3DKMTSetAllocationPriority = GetProcAddress(d3d11.dll, "D3DKMTSetAllocationPriority"); 158 | d3d11.D3DKMTSetContextSchedulingPriority = GetProcAddress(d3d11.dll, "D3DKMTSetContextSchedulingPriority"); 159 | d3d11.D3DKMTSetDisplayMode = GetProcAddress(d3d11.dll, "D3DKMTSetDisplayMode"); 160 | d3d11.D3DKMTSetGammaRamp = GetProcAddress(d3d11.dll, "D3DKMTSetGammaRamp"); 161 | d3d11.D3DKMTSetVidPnSourceOwner = GetProcAddress(d3d11.dll, "D3DKMTSetVidPnSourceOwner"); 162 | d3d11.D3DKMTWaitForVerticalBlankEvent = GetProcAddress(d3d11.dll, "D3DKMTWaitForVerticalBlankEvent"); 163 | d3d11.D3DPerformance_BeginEvent = GetProcAddress(d3d11.dll, "D3DPerformance_BeginEvent"); 164 | d3d11.D3DPerformance_EndEvent = GetProcAddress(d3d11.dll, "D3DPerformance_EndEvent"); 165 | d3d11.D3DPerformance_GetStatus = GetProcAddress(d3d11.dll, "D3DPerformance_GetStatus"); 166 | d3d11.D3DPerformance_SetMarker = GetProcAddress(d3d11.dll, "D3DPerformance_SetMarker"); 167 | return true; 168 | } 169 | 170 | bool unload_library_d3d11() { 171 | FreeLibrary(d3d11.dll); 172 | d3d11.dll = nullptr; 173 | return true; 174 | } 175 | 176 | #else 177 | 178 | bool load_library_d3d11() { 179 | return false; 180 | } 181 | 182 | bool unload_library_d3d11() { 183 | return false; 184 | } 185 | 186 | #endif 187 | --------------------------------------------------------------------------------