├── DynamicPatcher.cpp ├── DynamicPatcher.h ├── DynamicPatcher2010.sln ├── DynamicPatcher2010.vcxproj ├── DynamicPatcher2010.vcxproj.filters ├── DynamicPatcher2012.sln ├── DynamicPatcher2012.vcxproj ├── DynamicPatcher2012.vcxproj.filters ├── DynamicPatcherInjector.cpp ├── DynamicPatcherInjector.dpconf ├── DynamicPatcherInjector2010.vcxproj ├── DynamicPatcherInjector2012.vcxproj ├── DynamicPatcherInjectorDLL.cpp ├── DynamicPatcherInjectorDLL2010.vcxproj ├── DynamicPatcherInjectorDLL2012.vcxproj ├── README.md ├── Test ├── Test_Dll2010.vcxproj ├── Test_Dll2012.vcxproj ├── Test_Inject │ └── Test_Inject.cpp ├── Test_Inject2010.vcxproj ├── Test_Inject2012.vcxproj ├── Test_Injected │ └── Test_Injected.cpp ├── Test_Injected2010.vcxproj ├── Test_Injected2012.vcxproj ├── Test_Lib2010.vcxproj ├── Test_Lib2012.vcxproj ├── Test_LibDll │ ├── Test_UseLibDll.cpp │ ├── dll.cpp │ ├── lib1.cpp │ └── lib2.cpp ├── Test_LibDll2010.sln ├── Test_LibDll2012.sln ├── Test_Particles │ ├── Test_Particles.cpp │ ├── Test_Particles.fx │ ├── Test_Particles.h │ └── Test_ParticlesObj.cpp ├── Test_Particles2010.vcxproj ├── Test_Particles2010.vcxproj.filters ├── Test_Particles2012.vcxproj ├── Test_Particles2012.vcxproj.filters ├── Test_Simple │ └── Test_Simple.cpp ├── Test_Simple2010.vcxproj ├── Test_Simple2012.vcxproj ├── Test_UseLibDll2010.vcxproj └── Test_UseLibDll2012.vcxproj ├── bin ├── DynamicPatcher-1.0.0.zip └── DynamicPatcher-1.1.0.zip ├── disasm-lib ├── cpu.c ├── cpu.h ├── disasm.c ├── disasm.h ├── disasm_x86.c ├── disasm_x86.h ├── disasm_x86_tables.h ├── misc.c └── misc.h ├── disasm2010.vcxproj ├── disasm2010.vcxproj.filters ├── disasm2012.vcxproj ├── disasm2012.vcxproj.filters ├── dpBinary.cpp ├── dpBuilder.cpp ├── dpConfig.cpp ├── dpContext.cpp ├── dpFoundation.cpp ├── dpInternal.h ├── dpLoader.cpp ├── dpPatcher.cpp ├── dpVS2012 ├── dpVS │ ├── AssemblyInfo.cs │ ├── Connect.cs │ ├── dpVS - For Testing.AddIn │ ├── dpVS.AddIn │ └── dpVS.csproj └── dpVSHelper │ ├── AssemblyInfo.cpp │ ├── Stdafx.cpp │ ├── Stdafx.h │ ├── app.ico │ ├── app.rc │ ├── dpVSHelper.cpp │ ├── dpVSHelper.h │ ├── dpVSHelper.vcxproj │ ├── dpVSHelper.vcxproj.filters │ └── resource.h ├── old ├── DynamicObjLoader.cpp ├── DynamicObjLoader.h └── Test │ ├── Test.sln │ ├── Test1 │ ├── Test1.cpp │ ├── Test1.h │ ├── Test1.vcxproj │ ├── Test1.vcxproj.filters │ └── Test1Obj.cpp │ ├── Test2 │ ├── Test2.cpp │ ├── Test2.fx │ ├── Test2.h │ ├── Test2.vcxproj │ ├── Test2.vcxproj.filters │ ├── Test2Obj.cpp │ ├── stdafx.cpp │ ├── stdafx.h │ └── targetver.h │ └── Test3 │ ├── Test3.cpp │ ├── Test3.vcxproj │ └── Test3.vcxproj.filters └── package.bat /DynamicPatcher.h: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicPatcher 4 | 5 | #ifndef DynamicPatcher_h 6 | #define DynamicPatcher_h 7 | 8 | #ifndef dpDisable 9 | 10 | // this option makes dpGetUnpatched() work. and makes dependency for disasm. 11 | // dpGetUnpatched() returns the function that behaves as old (before patch) function. 12 | #define dpWithTDisasm 13 | 14 | #if _MSC_VER>=1600 // dpPatchByFile() require C++11 15 | # define dpWithStdFunction 16 | #endif // _MSC_VER>=1600 17 | 18 | #ifdef _M_X64 19 | # define dpLibArch "64" 20 | #else // _M_X64 21 | # define dpLibArch 22 | #endif //_M_X64 23 | #ifdef _DEBUG 24 | # define dpLibConfig "d" 25 | #else // _DEBUG 26 | # define dpLibConfig 27 | #endif //_DEBUG 28 | 29 | 30 | #if defined(dpDLLImpl) 31 | # define dpAPI dpDLLExport 32 | #elif defined(dpLinkStatic) 33 | # define dpAPI 34 | # pragma comment(lib,"DynamicPatchers" dpLibConfig dpLibArch ".lib") 35 | #elif !defined(dpNoLib) 36 | # define dpAPI dpDLLImport 37 | # pragma comment(lib,"DynamicPatcher" dpLibArch ".lib") 38 | #else 39 | # define dpAPI 40 | #endif // dpDLL_Impl 41 | #ifdef dpWithStdFunction 42 | # include 43 | #endif // dpWithStdFunction 44 | 45 | #define dpDLLExport __declspec(dllexport) 46 | #define dpDLLImport __declspec(dllimport) 47 | #define dpCLinkage extern "C" 48 | 49 | #define dpPatch dpDLLExport 50 | #define dpNoInline __declspec(noinline) 51 | #define dpScope(...) __VA_ARGS__ 52 | #define dpOnLoad(...) dpCLinkage static void dpOnLoadHandler() { __VA_ARGS__ } __declspec(selectany) void *_dpOnLoadHandler =dpOnLoadHandler; 53 | #define dpOnUnload(...) dpCLinkage static void dpOnUnloadHandler(){ __VA_ARGS__ } __declspec(selectany) void *_dpOnUnloadHandler=dpOnUnloadHandler; 54 | 55 | enum dpSymbolFlags { 56 | dpE_Code = 0x1, // code 57 | dpE_IData = 0x2, // initialized data 58 | dpE_UData = 0x4, // uninitialized data 59 | dpE_Read = 0x8, // readable 60 | dpE_Write = 0x10, // writable 61 | dpE_Execute = 0x20, // executable 62 | dpE_Shared = 0x40, // shared 63 | dpE_Export = 0x80, // dllexport 64 | dpE_Handler = 0x100, // dpOnLoad, dpOnUnload, etc 65 | }; 66 | #define dpIsFunction(flag) ((flag&dpE_Code)!=0) 67 | #define dpIsExportFunction(flag) ((flag&(dpE_Code|dpE_Export|dpE_Handler))==(dpE_Code|dpE_Export)) 68 | 69 | struct dpSymbolS 70 | { 71 | const char *name; 72 | void *address; 73 | int flags; 74 | }; 75 | 76 | 77 | enum dpLogLevel { 78 | dpE_LogError = 0x1, 79 | dpE_LogWarning = 0x2, 80 | dpE_LogInfo = 0x4, 81 | dpE_LogDetail = 0x8, 82 | 83 | dpE_LogAll = dpE_LogError|dpE_LogWarning|dpE_LogInfo|dpE_LogDetail, 84 | dpE_LogSimple = dpE_LogError|dpE_LogWarning|dpE_LogInfo, 85 | dpE_LogNone = 0, 86 | }; 87 | enum dpSystemFlags { 88 | dpE_SysPatchExports = 0x1, // patch exported (dllexport==dpPatch) functions automatically when modules are loaded 89 | dpE_SysDelayedLink = 0x2, 90 | dpE_SysLoadConfig = 0x4, 91 | dpE_SysOpenConsole = 0x8, 92 | 93 | dpE_SysDefault = dpE_SysPatchExports|dpE_SysDelayedLink|dpE_SysLoadConfig, 94 | }; 95 | 96 | struct dpConfig 97 | { 98 | int log_flags; // combination of dpLogLevel 99 | int sys_flags; // combination of dpSystemFlags 100 | int vc_ver; // VisualC++ version to use to build. 2008/2010/2012 101 | const char *configfile; 102 | unsigned long long starttime; 103 | 104 | dpConfig(int log=dpE_LogSimple, int f=dpE_SysDefault, const char *config=NULL) 105 | : log_flags(log), sys_flags(f), configfile(config), vc_ver(0), starttime() 106 | { 107 | #if _MSC_VER==1500 108 | vc_ver = 2008; 109 | #elif _MSC_VER==1600 110 | vc_ver = 2010; 111 | #elif _MSC_VER==1700 112 | vc_ver = 2012; 113 | #elif _MSC_VER==1800 114 | vc_ver = 2013; 115 | #endif 116 | } 117 | }; 118 | 119 | class dpContext; 120 | 121 | dpAPI bool dpInitialize(const dpConfig &conf=dpConfig()); 122 | dpAPI bool dpFinalize(); 123 | 124 | dpAPI dpContext* dpGetDefaultContext(); 125 | dpAPI dpContext* dpCreateContext(); 126 | dpAPI void dpDeleteContext(dpContext *ctx); 127 | dpAPI void dpSetCurrentContext(dpContext *ctx); // current context is thread local 128 | dpAPI dpContext* dpGetCurrentContext(); // default is dpGetDefaultContext() 129 | 130 | dpAPI size_t dpLoad(const char *path); // path to .obj .lib .dll .exe. accepts wildcard (ex: x64/Debug/*.obj) 131 | dpAPI bool dpLoadObj(const char *path); // load as .obj regardless file extension 132 | dpAPI bool dpLoadLib(const char *path); // load as .lib regardless file extension 133 | dpAPI bool dpLoadDll(const char *path); // load as .dll regardless file extension 134 | dpAPI bool dpUnload(const char *path); 135 | dpAPI bool dpLink(); // must be called after dpLoad*()s & dpUnload()s. onload handler is called in this. 136 | dpAPI size_t dpLoadMapFiles(); // load symbol info from .map files. this function will reduce link time for .obj files drastically. 137 | // .map files should be placed on same directory of .exe or .dll with same name. 138 | // ex) c:/foo/bar.exe -> c:/foo/bar.map 139 | // .map files will be generated if linker option /map is specified. 140 | 141 | dpAPI size_t dpPatchByFile(const char *filename, const char *filter_regex); // ex: dpPatchByFile("MyClass.obj", "MyClass::.*") 142 | #ifdef dpWithStdFunction 143 | dpAPI size_t dpPatchByFile(const char *filename, const std::function &condition); 144 | #endif // dpWithStdFunction 145 | dpAPI bool dpPatchNameToName(const char *target_name, const char *hook_name); 146 | dpAPI bool dpPatchAddressToName(const char *target_name, void *hook_addr); 147 | dpAPI bool dpPatchAddressToAddress(void *target, void *hook_addr); 148 | dpAPI bool dpPatchByAddress(void *hook_addr); // patches the host symbol that have same name of hook 149 | dpAPI bool dpUnpatchByAddress(void *target_or_hook_addr); 150 | dpAPI void dpUnpatchAll(); 151 | dpAPI void* dpGetUnpatched(void *target_or_hook_addr); 152 | dpAPI void dpAddForceHostSymbolPattern(const char *pattern); 153 | 154 | dpAPI void dpAddModulePath(const char *path); // accepts wildcard. affects auto build and dpReload() 155 | dpAPI void dpAddSourcePath(const char *path); // 156 | dpAPI void dpAddPreloadPath(const char *path); // 157 | dpAPI void dpAddMSBuildCommand(const char *msbuild_option); // add msbuild command that will be called by auto build thread 158 | dpAPI void dpAddCLBuildCommand(const char *cl_option); // add cl command that will be called by auto build thread 159 | dpAPI void dpAddBuildCommand(const char *any_command); // add arbitrary command that will be called by auto build thread 160 | dpAPI bool dpStartAutoBuild(); 161 | dpAPI bool dpStopAutoBuild(); 162 | dpAPI bool dpStartPreload(); 163 | dpAPI bool dpStopPreload(); 164 | dpAPI void dpUpdate(); // reloads and links modified modules. 165 | 166 | dpAPI void dpPrint(const char* fmt, ...); 167 | dpAPI bool dpDemangle(const char *mangled, char *demangled, size_t buflen); 168 | dpAPI const char* dpGetVCVarsPath(); 169 | 170 | #else // dpDisable 171 | 172 | #define dpPatch 173 | #define dpNoInline 174 | #define dpScope(...) 175 | #define dpOnLoad(...) 176 | #define dpOnUnload(...) 177 | 178 | #define dpInitialize(...) 179 | #define dpFinalize(...) 180 | 181 | #define dpGetDefaultContext(...) 182 | #define dpCreateContext(...) 183 | #define dpDeleteContext(...) 184 | #define dpSetCurrentContext(...) 185 | #define dpGetCurrentContext(...) 186 | 187 | #define dpLoad(...) 188 | #define dpLoadObj(...) 189 | #define dpLoadLib(...) 190 | #define dpLoadDll(...) 191 | #define dpUnload(...) 192 | #define dpLink(...) 193 | #define dpLoadMapFiles(...) 194 | #define dpPatchByFile(...) 195 | #define dpPatchNameToName(...) 196 | #define dpPatchAddressToName(...) 197 | #define dpPatchAddressToAddress(...) 198 | #define dpPatchByAddress(...) 199 | #define dpUnpatchByAddress(...) 200 | #define dpUnpatchAll(...) 201 | #define dpGetUnpatched(...) 202 | #define dpAddForceHostSymbolPattern(...) 203 | 204 | #define dpAddModulePath(...) 205 | #define dpAddSourcePath(...) 206 | #define dpAddPreloadPath(...) 207 | #define dpAddMSBuildCommand(...) 208 | #define dpAddCLBuildCommand(...) 209 | #define dpAddBuildCommand(...) 210 | #define dpStartAutoBuild(...) 211 | #define dpStopAutoBuild(...) 212 | #define dpStartPreload(...) 213 | #define dpStopPreload(...) 214 | #define dpUpdate(...) 215 | 216 | #define dpPrint(...) 217 | #define dpDemangle(...) 218 | #define dpGetVCVarsPath(...) 219 | 220 | #endif // dpDisable 221 | 222 | #endif // DynamicPatcher_h 223 | -------------------------------------------------------------------------------- /DynamicPatcher2010.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /DynamicPatcher2012.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /DynamicPatcherInjector.cpp: -------------------------------------------------------------------------------- 1 | #include "windows.h" 2 | #include 3 | 4 | #ifdef _M_IX64 5 | # define InjectorDLL "DynamicPatcherInjectorDLL64.dll" 6 | # define PatcherDLL "DynamicPatcher64.dll" 7 | #else // _M_IX86 8 | # define InjectorDLL "DynamicPatcherInjectorDLL.dll" 9 | # define PatcherDLL "DynamicPatcher.dll" 10 | #endif // _M_IX64 11 | 12 | bool InjectDLL(HANDLE hProcess, const char* dllname) 13 | { 14 | SIZE_T bytesRet = 0; 15 | DWORD oldProtect = 0; 16 | LPVOID remote_addr = NULL; 17 | HANDLE hThread = NULL; 18 | size_t len = strlen(dllname) + 1; 19 | 20 | remote_addr = ::VirtualAllocEx(hProcess, 0, 1024, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE); 21 | if(remote_addr==NULL) { return false; } 22 | ::VirtualProtectEx(hProcess, remote_addr, len, PAGE_EXECUTE_READWRITE, &oldProtect); 23 | ::WriteProcessMemory(hProcess, remote_addr, dllname, len, &bytesRet); 24 | ::VirtualProtectEx(hProcess, remote_addr, len, oldProtect, &oldProtect); 25 | 26 | hThread = ::CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)((void*)&LoadLibraryA), remote_addr, 0, NULL); 27 | ::WaitForSingleObject(hThread, INFINITE); 28 | ::VirtualFreeEx(hProcess, remote_addr, 0, MEM_RELEASE); 29 | return true; 30 | } 31 | 32 | int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE prev, LPWSTR cmd, int show) 33 | { 34 | std::wstring exe_path = __wargv[1]; 35 | const char dll_path[MAX_PATH] = InjectorDLL; 36 | 37 | DWORD flags = NORMAL_PRIORITY_CLASS; 38 | if(__argc>=3 && wcscmp(__wargv[2], L"/suspended")==0) { 39 | flags |= CREATE_SUSPENDED; 40 | } 41 | 42 | STARTUPINFOW si; 43 | PROCESS_INFORMATION pi; 44 | ::ZeroMemory(&si, sizeof(si)); 45 | ::ZeroMemory(&pi, sizeof(pi)); 46 | si.cb = sizeof(si); 47 | BOOL ret = ::CreateProcessW(nullptr, (wchar_t*)exe_path.c_str(), nullptr, nullptr, FALSE, 48 | flags, nullptr, nullptr, &si, &pi); 49 | if(ret) { 50 | InjectDLL(pi.hProcess, dll_path); 51 | return pi.dwProcessId; 52 | } 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /DynamicPatcherInjector.dpconf: -------------------------------------------------------------------------------- 1 | load: "_tmp\Test_Inject_Win32Debug\Test_Inject.obj" 2 | source path: "Test_Injected" 3 | msbuild command: "Test_Injected.vcxproj /target:ClCompile /m /p:Configuration=Debug;Platform=Win32" 4 | vc ver: 2010 5 | -------------------------------------------------------------------------------- /DynamicPatcherInjector2010.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | {7986011C-5076-4506-AB77-7272257885FD} 28 | Win32Proj 29 | DynamicPatcherInjector 30 | DynamicPatcherInjector 31 | 32 | 33 | 34 | Application 35 | true 36 | Unicode 37 | 38 | 39 | Application 40 | true 41 | Unicode 42 | 43 | 44 | Application 45 | false 46 | true 47 | Unicode 48 | 49 | 50 | Application 51 | false 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | external;$(DXSDK_DIR)include;$(IncludePath) 73 | external\lib\win32;$(DXSDK_DIR)lib\x86;$(LibraryPath) 74 | $(ProjectName) 75 | $(ProjectDir)\ 76 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 77 | false 78 | 79 | 80 | external;$(DXSDK_DIR)include;$(IncludePath) 81 | external\lib\win64;$(DXSDK_DIR)lib\x86;$(LibraryPath) 82 | $(ProjectName)64 83 | $(ProjectDir)\ 84 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 85 | false 86 | 87 | 88 | external;$(DXSDK_DIR)include;$(IncludePath) 89 | external\lib\win32;$(DXSDK_DIR)lib\x86;$(LibraryPath) 90 | $(ProjectName) 91 | $(ProjectDir)\ 92 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 93 | false 94 | 95 | 96 | external;$(DXSDK_DIR)include;$(IncludePath) 97 | external\lib\win64;$(DXSDK_DIR)lib\x86;$(LibraryPath) 98 | $(ProjectName)64 99 | $(ProjectDir)\ 100 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 101 | false 102 | 103 | 104 | 105 | NotUsing 106 | /MP %(AdditionalOptions) 107 | false 108 | MultiThreadedDebug 109 | Fast 110 | ProgramDatabase 111 | dpNoLib;_UNICODE;UNICODE;%(PreprocessorDefinitions) 112 | 113 | 114 | Console 115 | false 116 | true 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | NotUsing 126 | /MP %(AdditionalOptions) 127 | false 128 | MultiThreadedDebug 129 | Fast 130 | ProgramDatabase 131 | dpNoLib;_UNICODE;UNICODE;%(PreprocessorDefinitions) 132 | 133 | 134 | Console 135 | false 136 | true 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | NotUsing 146 | /MP %(AdditionalOptions) 147 | MultiThreaded 148 | false 149 | Fast 150 | dpNoLib;_UNICODE;UNICODE;%(PreprocessorDefinitions) 151 | 152 | 153 | Console 154 | false 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | NotUsing 164 | /MP %(AdditionalOptions) 165 | MultiThreaded 166 | false 167 | Fast 168 | dpNoLib;_UNICODE;UNICODE;%(PreprocessorDefinitions) 169 | 170 | 171 | Console 172 | false 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /DynamicPatcherInjectorDLL.cpp: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicPatcher 4 | 5 | #include 6 | 7 | #include "DynamicPatcher.h" 8 | dpAPI void dpBeginPeriodicUpdate(); 9 | dpAPI void dpEndPeriodicUpdate(); 10 | 11 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 12 | { 13 | if(fdwReason==DLL_PROCESS_ATTACH) { 14 | dpBeginPeriodicUpdate(); 15 | } 16 | else if(fdwReason==DLL_PROCESS_DETACH) { 17 | dpEndPeriodicUpdate(); 18 | } 19 | return TRUE; 20 | } 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DynamicPatcher 2 | ================ 3 | Runtime C++ Editing library. 4 | compile .cpps, load and link .objs (or .libs, .dlls), and update functions at runtime. 5 | 6 | ##demo movie 7 | [![DynamicPatcher demo](http://img.youtube.com/vi/rL1LZjrhJbw/0.jpg)](http://www.youtube.com/watch?v=rL1LZjrhJbw) 8 | 9 | 10 | ##detailed description 11 | (japanese) http://www.slideshare.net/i-saint/runtime-cediting 12 | (japanese) http://i-saint.hatenablog.com/entry/2013/06/06/212515 13 | 14 | ##example 15 | ```c++ 16 | #include // Sleep() 17 | #include 18 | #include "DynamicPatcher.h" 19 | 20 | // dpPatch をつけておくとロード時に同名の関数を自動的に更新する。 21 | // (dpPatch は単なる dllexport。.obj に情報が残るいい指定方法が他に見当たらなかったので仕方なく…。 22 | // この自動ロードは dpInitialize() のオプションで切ることも可能) 23 | dpPatch void MaybeOverridden() 24 | { 25 | // ここを書き換えるとリアルタイムに挙動が変わる 26 | puts("MaybeOverridden()\n"); 27 | } 28 | 29 | // CRT の関数を差し替える例。今回の犠牲者は puts() 30 | int puts_hook(const char *s) 31 | { 32 | typedef int (*puts_t)(const char *s); 33 | puts_t orig_puts = (puts_t)dpGetUnpatched(&puts); // hook 前の関数を取得 34 | orig_puts("puts_hook()"); 35 | return orig_puts(s); 36 | } 37 | 38 | // dpOnLoad() の中身はロード時に自動的に実行される。アンロード時に実行される dpOnUnload() も記述可能 39 | dpOnLoad( 40 | // dpPatch による自動差し替えを使わない場合、on load 時とかに手動で差し替える必要がある。 41 | // 元関数と新しい関数の名前が違うケースでは手動指定するしかない。 42 | dpPatchAddressToAddress(&puts, &puts_hook); // puts() を puts_hook() に差し替える 43 | ) 44 | 45 | int main() 46 | { 47 | dpInitialize(); 48 | dpAddSourcePath("."); // このディレクトリのファイルに変更があったらビルドコマンドを呼ぶ 49 | dpAddModulePath("example.obj"); // ビルドが終わったらこのファイルをロードする 50 | // cl.exe でコンパイル。msbuild や任意のコマンドも指定可能。 51 | // 実運用の際は msbuild を使うか、自動ビルドは使用せすユーザー制御になると思われる。 52 | // (dpStartAutoBuild() を呼ばなかった場合、dpUpdate() はロード済み or module path にあるモジュールに更新があればそれをリロードする) 53 | dpAddCLBuildCommand("example.cpp /c /Zi"); 54 | dpStartAutoBuild(); // 自動ビルド開始 55 | 56 | for(;;) { 57 | MaybeOverridden(); 58 | ::Sleep(2000); 59 | dpUpdate(); 60 | } 61 | 62 | dpFinalize(); 63 | } 64 | 65 | // cl /Zi example.cpp && ./example 66 | ``` 67 | 68 | ##license 69 | CC BY 70 | 71 | ##thanks 72 | DynamicPatcher contains a disassembler (tDisasm) by Matt Conover. 73 | [Runtime-Compiled C++](http://runtimecompiledcplusplus.blogspot.com/) 74 | [Mhook](http://codefromthe70s.org/mhook23.aspx) 75 | [PE/COFF file format](http://www.skyfree.org/linux/references/coff.pdf) 76 | [lib file format](http://hp.vector.co.jp/authors/VA050396/tech_04.html) 77 | 78 | [Riot Games](http://www.riotgames.com/) used this library! 79 | -------------------------------------------------------------------------------- /Test/Test_Dll2010.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | {0E8C293B-618B-428B-B1AC-502544B732FB} 26 | Win32Proj 27 | Test_Dll 28 | Test_Dll 29 | 30 | 31 | 32 | DynamicLibrary 33 | true 34 | Unicode 35 | 36 | 37 | DynamicLibrary 38 | true 39 | Unicode 40 | 41 | 42 | DynamicLibrary 43 | false 44 | false 45 | Unicode 46 | 47 | 48 | DynamicLibrary 49 | false 50 | false 51 | Unicode 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | ..;$(IncludePath) 71 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 72 | $(ProjectName) 73 | $(ProjectDir) 74 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 75 | false 76 | 77 | 78 | ..;$(IncludePath) 79 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 80 | $(ProjectName) 81 | $(ProjectDir) 82 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 83 | false 84 | 85 | 86 | ..;$(IncludePath) 87 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 88 | $(ProjectName) 89 | $(ProjectDir) 90 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 91 | false 92 | 93 | 94 | ..;$(IncludePath) 95 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 96 | $(ProjectName) 97 | $(ProjectDir) 98 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 99 | false 100 | 101 | 102 | 103 | NotUsing 104 | false 105 | MultiThreadedDebug 106 | Fast 107 | ProgramDatabase 108 | true 109 | 110 | 111 | Console 112 | false 113 | true 114 | false 115 | true 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | NotUsing 125 | false 126 | MultiThreadedDebug 127 | Fast 128 | ProgramDatabase 129 | true 130 | 131 | 132 | Console 133 | false 134 | true 135 | false 136 | true 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | NotUsing 146 | MultiThreaded 147 | false 148 | Fast 149 | true 150 | 151 | 152 | Console 153 | false 154 | true 155 | false 156 | true 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | NotUsing 166 | MultiThreaded 167 | false 168 | Fast 169 | true 170 | 171 | 172 | Console 173 | false 174 | true 175 | false 176 | true 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /Test/Test_Dll2012.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | {0E8C293B-618B-428B-B1AC-502544B732FB} 26 | Win32Proj 27 | Test_Dll 28 | Test_Dll 29 | 30 | 31 | 32 | DynamicLibrary 33 | true 34 | Unicode 35 | v110 36 | 37 | 38 | DynamicLibrary 39 | true 40 | Unicode 41 | v110 42 | 43 | 44 | DynamicLibrary 45 | false 46 | false 47 | Unicode 48 | v110 49 | 50 | 51 | DynamicLibrary 52 | false 53 | false 54 | Unicode 55 | v110 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | ..;$(IncludePath) 75 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 76 | $(ProjectName) 77 | $(ProjectDir) 78 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 79 | false 80 | 81 | 82 | ..;$(IncludePath) 83 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 84 | $(ProjectName) 85 | $(ProjectDir) 86 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 87 | false 88 | 89 | 90 | ..;$(IncludePath) 91 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 92 | $(ProjectName) 93 | $(ProjectDir) 94 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 95 | false 96 | 97 | 98 | ..;$(IncludePath) 99 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 100 | $(ProjectName) 101 | $(ProjectDir) 102 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 103 | false 104 | 105 | 106 | 107 | NotUsing 108 | false 109 | MultiThreadedDebug 110 | Fast 111 | ProgramDatabase 112 | true 113 | 114 | 115 | Console 116 | false 117 | true 118 | false 119 | true 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | NotUsing 129 | false 130 | MultiThreadedDebug 131 | Fast 132 | ProgramDatabase 133 | true 134 | 135 | 136 | Console 137 | false 138 | true 139 | false 140 | true 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | NotUsing 150 | MultiThreaded 151 | false 152 | Fast 153 | true 154 | 155 | 156 | Console 157 | false 158 | true 159 | false 160 | true 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | NotUsing 170 | MultiThreaded 171 | false 172 | Fast 173 | true 174 | 175 | 176 | Console 177 | false 178 | true 179 | false 180 | true 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /Test/Test_Inject/Test_Inject.cpp: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicPatcher 4 | 5 | #include 6 | 7 | #define dpNoLib 8 | #include "DynamicPatcher.h" 9 | 10 | #ifdef _M_X64 11 | # define dpPlatform "x64" 12 | #else 13 | # define dpPlatform "Win32" 14 | #endif 15 | #ifdef _DEBUG 16 | # define dpConfiguration "Debug" 17 | #else 18 | # define dpConfiguration "Release" 19 | #endif 20 | #define dpObjDir "_tmp/Test_Inject_" dpPlatform dpConfiguration 21 | 22 | 23 | dpNoInline bool GetEndFlag() 24 | { 25 | return false; 26 | } 27 | 28 | dpNoInline void Test_ThisMaybeOverridden() 29 | { 30 | printf("Test_Inject.cpp: Overridden!\n"); 31 | dpUpdate(); 32 | } 33 | 34 | 35 | dpOnLoad( 36 | dpPrint("loaded: Test_Inject.cpp\n"); 37 | 38 | dpAddModulePath(dpObjDir"/*.obj"); 39 | dpAddSourcePath("Test_Inject"); 40 | dpAddMSBuildCommand("Test_Inject.vcxproj /target:ClCompile /m /p:Configuration="dpConfiguration";Platform="dpPlatform); 41 | dpStartAutoBuild(); 42 | 43 | dpPatchByAddress(&Test_ThisMaybeOverridden); 44 | dpPatchByAddress(&GetEndFlag); 45 | ) 46 | 47 | dpOnUnload( 48 | printf("unloaded: Test_Inject.cpp\n"); 49 | ) 50 | -------------------------------------------------------------------------------- /Test/Test_Inject2010.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | {8CA885E0-BF97-4FB3-82AD-DBE0FF0E4538} 29 | Win32Proj 30 | Test_Inject 31 | Test_Inject 32 | 33 | 34 | 35 | StaticLibrary 36 | true 37 | Unicode 38 | 39 | 40 | StaticLibrary 41 | true 42 | Unicode 43 | 44 | 45 | StaticLibrary 46 | false 47 | false 48 | Unicode 49 | 50 | 51 | StaticLibrary 52 | false 53 | false 54 | Unicode 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | ..;$(IncludePath) 74 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 75 | $(ProjectName) 76 | $(ProjectDir) 77 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 78 | false 79 | 80 | 81 | ..;$(IncludePath) 82 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 83 | $(ProjectName) 84 | $(ProjectDir) 85 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 86 | false 87 | 88 | 89 | ..;$(IncludePath) 90 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 91 | $(ProjectName) 92 | $(ProjectDir) 93 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 94 | false 95 | 96 | 97 | ..;$(IncludePath) 98 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 99 | $(ProjectName) 100 | $(ProjectDir) 101 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 102 | false 103 | 104 | 105 | 106 | NotUsing 107 | false 108 | MultiThreadedDebug 109 | Fast 110 | ProgramDatabase 111 | true 112 | 113 | 114 | Console 115 | false 116 | true 117 | false 118 | true 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | NotUsing 128 | false 129 | MultiThreadedDebug 130 | Fast 131 | ProgramDatabase 132 | true 133 | 134 | 135 | Console 136 | false 137 | true 138 | false 139 | true 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | NotUsing 149 | MultiThreaded 150 | false 151 | Fast 152 | true 153 | 154 | 155 | Console 156 | false 157 | true 158 | false 159 | true 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | NotUsing 169 | MultiThreaded 170 | false 171 | Fast 172 | true 173 | 174 | 175 | Console 176 | false 177 | true 178 | false 179 | true 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | -------------------------------------------------------------------------------- /Test/Test_Injected/Test_Injected.cpp: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicPatcher 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "DynamicPatcher.h" 13 | 14 | 15 | dpNoInline bool GetEndFlag() 16 | { 17 | return false; 18 | } 19 | 20 | dpNoInline void Test_ThisMaybeOverridden() 21 | { 22 | printf("Test_ThisMaybeOverridden()\n"); 23 | } 24 | 25 | int main(int argc, char *argv[]) 26 | { 27 | printf("DynamicPatcher Test_Injected\n"); 28 | { 29 | while(!GetEndFlag()) { 30 | Test_ThisMaybeOverridden(); 31 | ::Sleep(3000); 32 | } 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /Test/Test_Injected2010.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | {4256E731-91A4-44B7-993C-13CA2CFDF71B} 26 | Win32Proj 27 | Test_Injected 28 | Test_Injected 29 | 30 | 31 | 32 | Application 33 | true 34 | Unicode 35 | 36 | 37 | Application 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | false 44 | false 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | false 51 | Unicode 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | ..;$(IncludePath) 71 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 72 | $(ProjectName) 73 | $(ProjectDir) 74 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 75 | false 76 | 77 | 78 | ..;$(IncludePath) 79 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 80 | $(ProjectName) 81 | $(ProjectDir) 82 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 83 | false 84 | 85 | 86 | ..;$(IncludePath) 87 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 88 | $(ProjectName) 89 | $(ProjectDir) 90 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 91 | false 92 | 93 | 94 | ..;$(IncludePath) 95 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 96 | $(ProjectName) 97 | $(ProjectDir) 98 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 99 | false 100 | 101 | 102 | 103 | NotUsing 104 | false 105 | MultiThreadedDebug 106 | Fast 107 | ProgramDatabase 108 | true 109 | 110 | 111 | Console 112 | false 113 | true 114 | false 115 | true 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | NotUsing 125 | false 126 | MultiThreadedDebug 127 | Fast 128 | ProgramDatabase 129 | true 130 | 131 | 132 | Console 133 | false 134 | true 135 | false 136 | true 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | NotUsing 146 | MultiThreaded 147 | false 148 | Fast 149 | true 150 | 151 | 152 | Console 153 | false 154 | true 155 | false 156 | true 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | NotUsing 166 | MultiThreaded 167 | false 168 | Fast 169 | true 170 | 171 | 172 | Console 173 | false 174 | true 175 | false 176 | true 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /Test/Test_Lib2010.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {78800EB9-3249-4A82-9074-3D68A2E56C60} 27 | Win32Proj 28 | Test_Lib 29 | Test_Lib 30 | 31 | 32 | 33 | StaticLibrary 34 | true 35 | Unicode 36 | 37 | 38 | StaticLibrary 39 | true 40 | Unicode 41 | 42 | 43 | StaticLibrary 44 | false 45 | false 46 | Unicode 47 | 48 | 49 | StaticLibrary 50 | false 51 | false 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | ..;$(IncludePath) 72 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 73 | $(ProjectName) 74 | $(ProjectDir) 75 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 76 | false 77 | 78 | 79 | ..;$(IncludePath) 80 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 81 | $(ProjectName) 82 | $(ProjectDir) 83 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 84 | false 85 | 86 | 87 | ..;$(IncludePath) 88 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 89 | $(ProjectName) 90 | $(ProjectDir) 91 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 92 | false 93 | 94 | 95 | ..;$(IncludePath) 96 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 97 | $(ProjectName) 98 | $(ProjectDir) 99 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 100 | false 101 | 102 | 103 | 104 | NotUsing 105 | false 106 | MultiThreadedDebug 107 | Fast 108 | ProgramDatabase 109 | true 110 | 111 | 112 | Console 113 | false 114 | true 115 | false 116 | true 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | NotUsing 126 | false 127 | MultiThreadedDebug 128 | Fast 129 | ProgramDatabase 130 | true 131 | 132 | 133 | Console 134 | false 135 | true 136 | false 137 | true 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | NotUsing 147 | MultiThreaded 148 | false 149 | Fast 150 | true 151 | 152 | 153 | Console 154 | false 155 | true 156 | false 157 | true 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | NotUsing 167 | MultiThreaded 168 | false 169 | Fast 170 | true 171 | 172 | 173 | Console 174 | false 175 | true 176 | false 177 | true 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /Test/Test_LibDll/Test_UseLibDll.cpp: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicPatcher 4 | 5 | #include 6 | 7 | //#define dpDisable 8 | //#define dpLinkStatic 9 | #define dpLinkDynamic 10 | #include "DynamicPatcher.h" 11 | 12 | #ifdef _M_X64 13 | # define dpPlatform "x64" 14 | #else 15 | # define dpPlatform "Win32" 16 | #endif 17 | #ifdef _DEBUG 18 | # define dpConfiguration "Debug" 19 | #else 20 | # define dpConfiguration "Release" 21 | #endif 22 | 23 | dpScope( 24 | dpContext *g_dp_context; 25 | ) 26 | 27 | dpNoInline void OverriddenByLib1() 28 | { 29 | printf("this will be overridden by lib1\n"); 30 | } 31 | 32 | dpNoInline void OverriddenByLib2() 33 | { 34 | printf("this will be overridden by lib2\n"); 35 | } 36 | 37 | dpNoInline void OverriddenByDll() 38 | { 39 | printf("this will be overridden by dll\n"); 40 | } 41 | 42 | 43 | int main(int argc, char *argv[]) 44 | { 45 | dpInitialize(); 46 | dpScope(g_dp_context=dpCreateContext()); 47 | dpSetCurrentContext(g_dp_context); 48 | 49 | dpAddModulePath("Test_Dll.dll"); 50 | dpAddModulePath("Test_Lib.lib"); 51 | dpAddSourcePath("Test_LibDll"); 52 | dpAddMSBuildCommand("Test_Lib.vcxproj /target:Build /m /p:Configuration="dpConfiguration";Platform="dpPlatform); 53 | dpAddMSBuildCommand("Test_Dll.vcxproj /target:Build /m /p:Configuration="dpConfiguration";Platform="dpPlatform); 54 | dpStartAutoBuild(); 55 | 56 | // fail test 57 | //dpLoadLib("Test_Dll.dll"); 58 | //dpLoadDll("Test_Lib.lib"); 59 | 60 | printf("DynamicPatcher Test_UseLibDll\n"); 61 | for(;;) { 62 | OverriddenByLib1(); 63 | OverriddenByLib2(); 64 | OverriddenByDll(); 65 | ::Sleep(3000); 66 | dpUpdate(); 67 | } 68 | dpScope(dpDeleteContext(g_dp_context)); 69 | dpFinalize(); 70 | } 71 | -------------------------------------------------------------------------------- /Test/Test_LibDll/dll.cpp: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicPatcher 4 | 5 | #include 6 | #include "DynamicPatcher.h" 7 | 8 | dpPatch void OverriddenByDll() 9 | { 10 | printf("OverriddenByDll(): overridden!\n"); 11 | typedef void (*OrigT)(); 12 | OrigT f = (OrigT)dpGetUnpatched(&OverriddenByDll); 13 | f(); 14 | } 15 | -------------------------------------------------------------------------------- /Test/Test_LibDll/lib1.cpp: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicPatcher 4 | 5 | #include 6 | #include "DynamicPatcher.h" 7 | 8 | dpPatch void OverriddenByLib1() 9 | { 10 | printf("OverriddenByLib1(): overridden!\n"); 11 | } 12 | -------------------------------------------------------------------------------- /Test/Test_LibDll/lib2.cpp: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicPatcher 4 | 5 | #include 6 | #include "DynamicPatcher.h" 7 | 8 | dpPatch void OverriddenByLib2() 9 | { 10 | printf("OverriddenByLib2(): overridden!\n"); 11 | } 12 | -------------------------------------------------------------------------------- /Test/Test_LibDll2010.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test_Dll", "Test_Dll2010.vcxproj", "{0E8C293B-618B-428B-B1AC-502544B732FB}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test_Lib", "Test_Lib2010.vcxproj", "{78800EB9-3249-4A82-9074-3D68A2E56C60}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Release|Win32 = Release|Win32 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {0E8C293B-618B-428B-B1AC-502544B732FB}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {0E8C293B-618B-428B-B1AC-502544B732FB}.Debug|Win32.Build.0 = Debug|Win32 18 | {0E8C293B-618B-428B-B1AC-502544B732FB}.Debug|x64.ActiveCfg = Debug|x64 19 | {0E8C293B-618B-428B-B1AC-502544B732FB}.Debug|x64.Build.0 = Debug|x64 20 | {0E8C293B-618B-428B-B1AC-502544B732FB}.Release|Win32.ActiveCfg = Release|Win32 21 | {0E8C293B-618B-428B-B1AC-502544B732FB}.Release|Win32.Build.0 = Release|Win32 22 | {0E8C293B-618B-428B-B1AC-502544B732FB}.Release|x64.ActiveCfg = Release|x64 23 | {0E8C293B-618B-428B-B1AC-502544B732FB}.Release|x64.Build.0 = Release|x64 24 | {78800EB9-3249-4A82-9074-3D68A2E56C60}.Debug|Win32.ActiveCfg = Debug|Win32 25 | {78800EB9-3249-4A82-9074-3D68A2E56C60}.Debug|Win32.Build.0 = Debug|Win32 26 | {78800EB9-3249-4A82-9074-3D68A2E56C60}.Debug|x64.ActiveCfg = Debug|x64 27 | {78800EB9-3249-4A82-9074-3D68A2E56C60}.Debug|x64.Build.0 = Debug|x64 28 | {78800EB9-3249-4A82-9074-3D68A2E56C60}.Release|Win32.ActiveCfg = Release|Win32 29 | {78800EB9-3249-4A82-9074-3D68A2E56C60}.Release|Win32.Build.0 = Release|Win32 30 | {78800EB9-3249-4A82-9074-3D68A2E56C60}.Release|x64.ActiveCfg = Release|x64 31 | {78800EB9-3249-4A82-9074-3D68A2E56C60}.Release|x64.Build.0 = Release|x64 32 | EndGlobalSection 33 | GlobalSection(SolutionProperties) = preSolution 34 | HideSolutionNode = FALSE 35 | EndGlobalSection 36 | EndGlobal 37 | -------------------------------------------------------------------------------- /Test/Test_LibDll2012.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test_Dll", "Test_Dll2012.vcxproj", "{0E8C293B-618B-428B-B1AC-502544B732FB}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test_Lib", "Test_Lib2012.vcxproj", "{78800EB9-3249-4A82-9074-3D68A2E56C60}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Release|Win32 = Release|Win32 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {0E8C293B-618B-428B-B1AC-502544B732FB}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {0E8C293B-618B-428B-B1AC-502544B732FB}.Debug|Win32.Build.0 = Debug|Win32 18 | {0E8C293B-618B-428B-B1AC-502544B732FB}.Debug|x64.ActiveCfg = Debug|x64 19 | {0E8C293B-618B-428B-B1AC-502544B732FB}.Debug|x64.Build.0 = Debug|x64 20 | {0E8C293B-618B-428B-B1AC-502544B732FB}.Release|Win32.ActiveCfg = Release|Win32 21 | {0E8C293B-618B-428B-B1AC-502544B732FB}.Release|Win32.Build.0 = Release|Win32 22 | {0E8C293B-618B-428B-B1AC-502544B732FB}.Release|x64.ActiveCfg = Release|x64 23 | {0E8C293B-618B-428B-B1AC-502544B732FB}.Release|x64.Build.0 = Release|x64 24 | {78800EB9-3249-4A82-9074-3D68A2E56C60}.Debug|Win32.ActiveCfg = Debug|Win32 25 | {78800EB9-3249-4A82-9074-3D68A2E56C60}.Debug|Win32.Build.0 = Debug|Win32 26 | {78800EB9-3249-4A82-9074-3D68A2E56C60}.Debug|x64.ActiveCfg = Debug|x64 27 | {78800EB9-3249-4A82-9074-3D68A2E56C60}.Debug|x64.Build.0 = Debug|x64 28 | {78800EB9-3249-4A82-9074-3D68A2E56C60}.Release|Win32.ActiveCfg = Release|Win32 29 | {78800EB9-3249-4A82-9074-3D68A2E56C60}.Release|Win32.Build.0 = Release|Win32 30 | {78800EB9-3249-4A82-9074-3D68A2E56C60}.Release|x64.ActiveCfg = Release|x64 31 | {78800EB9-3249-4A82-9074-3D68A2E56C60}.Release|x64.Build.0 = Release|x64 32 | EndGlobalSection 33 | GlobalSection(SolutionProperties) = preSolution 34 | HideSolutionNode = FALSE 35 | EndGlobalSection 36 | EndGlobal 37 | -------------------------------------------------------------------------------- /Test/Test_Particles/Test_Particles.fx: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------- 2 | // File: Tutorial07.fx 3 | // 4 | // Copyright (c) Microsoft Corporation. All rights reserved. 5 | //-------------------------------------------------------------------------------------- 6 | 7 | cbuffer cbChangesEveryFrame : register( b0 ) 8 | { 9 | matrix g_ViewProjection; 10 | float4 g_CameraPos; 11 | 12 | float4 g_LightPos; 13 | float4 g_LightColor; 14 | 15 | float4 g_MeshColor; 16 | float g_MeshShininess; 17 | }; 18 | 19 | 20 | //-------------------------------------------------------------------------------------- 21 | struct VS_INPUT 22 | { 23 | float3 Pos : POSITION; 24 | float3 Normal : NORMAL; 25 | float3 InstancePos : INSTANCE_POSITION; 26 | }; 27 | 28 | struct PS_INPUT 29 | { 30 | float4 Pos : SV_POSITION; 31 | float3 LsPos : TEXCOORD0; 32 | float4 Color : TEXCOORD1; 33 | float3 Normal : NORMAL; 34 | }; 35 | 36 | 37 | //-------------------------------------------------------------------------------------- 38 | // Vertex Shader 39 | //-------------------------------------------------------------------------------------- 40 | PS_INPUT VS( VS_INPUT input ) 41 | { 42 | float3 LsPos3 = (input.Pos * float3(0.05f, 0.05f, 0.05f)) + input.InstancePos; 43 | PS_INPUT output = (PS_INPUT)0; 44 | output.LsPos = LsPos3; 45 | output.Pos = mul(float4(LsPos3, 1.0f), g_ViewProjection); 46 | output.Color = float4(0.8f, 0.8f, 0.8f, 1.0f); 47 | output.Normal = input.Normal; 48 | 49 | return output; 50 | } 51 | 52 | 53 | //-------------------------------------------------------------------------------------- 54 | // Pixel Shader 55 | //-------------------------------------------------------------------------------------- 56 | float4 PS( PS_INPUT input) : SV_Target 57 | { 58 | float3 FragPos = input.LsPos.xyz; 59 | float3 LightPos = g_LightPos.xyz; 60 | float3 LightColor = g_LightColor.rgb; 61 | float3 LightDiff = LightPos - FragPos; 62 | float LightDist2 = dot(LightDiff, LightDiff); 63 | float LightDist = sqrt(LightDist2); 64 | float3 LightDir = LightDiff / LightDist; 65 | 66 | float3 Albedo = input.Color.rgb; 67 | float Shininess = g_MeshShininess; 68 | float3 Normal = input.Normal.xyz; 69 | float3 EyePos = g_CameraPos.xyz; 70 | float3 EyeDir = normalize(EyePos - FragPos); 71 | 72 | float3 h = normalize(EyeDir + LightDir); 73 | float nh = max(dot(Normal, h), 0.0); 74 | float Specular = pow(nh, Shininess); 75 | float Intensity = max(dot(Normal, LightDir), 0.0); 76 | 77 | float4 Result = float4(0.0, 0.0, 0.0, 1.0); 78 | Result.rgb += LightColor * (Albedo * Intensity); 79 | Result.rgb += LightColor * Specular; 80 | 81 | return Result; 82 | } 83 | -------------------------------------------------------------------------------- /Test/Test_Particles/Test_Particles.h: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicPatcher 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "DynamicPatcher.h" 12 | 13 | #define MAX_PARTICLES 6144 14 | 15 | struct Particle 16 | { 17 | XMFLOAT3 position; 18 | XMFLOAT3 velocity; 19 | float radius; 20 | }; 21 | extern int g_num_particles; 22 | extern float g_pradius; 23 | extern float g_accel; 24 | extern float g_deccel; 25 | extern float g_gravity; 26 | extern XMFLOAT3 g_gravity_center; 27 | extern Particle g_particles[MAX_PARTICLES]; 28 | extern int g_num_particles; 29 | 30 | dpPatch void InitializeParticles(); 31 | dpPatch void FinalizeParticles(); 32 | dpPatch void UpdateParticles(); 33 | float GenRand(); 34 | 35 | -------------------------------------------------------------------------------- /Test/Test_Particles/Test_ParticlesObj.cpp: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicPatcher 4 | 5 | #include "Test_Particles.h" 6 | #include 7 | 8 | #pragma warning(disable:4018) 9 | 10 | inline XMFLOAT3& operator+=(XMFLOAT3 &l, const XMFLOAT3 &r) { l.x+=r.x; l.y+=r.y; l.z+=r.z; return l; } 11 | inline XMFLOAT3& operator*=(XMFLOAT3 &l, float r) { l.x*=r; l.y*=r; l.z*=r; return l; } 12 | inline XMFLOAT3 operator-(const XMFLOAT3 &l, const XMFLOAT3 &r) { return XMFLOAT3(l.x-r.x, l.y-r.y, l.z-r.z); } 13 | inline XMFLOAT3 operator*(const XMFLOAT3 &l, float r) { return XMFLOAT3(l.x*r, l.y*r, l.z*r); } 14 | inline XMFLOAT3 operator/(const XMFLOAT3 &l, float r) { return XMFLOAT3(l.x/r, l.y/r, l.z/r); } 15 | 16 | inline float Dot(const XMFLOAT3 a, const XMFLOAT3 b) 17 | { 18 | return a.x*b.x + a.y*b.y + a.z*b.z; 19 | } 20 | 21 | inline float Len(const XMFLOAT3 a) 22 | { 23 | return sqrt(Dot(a, a)); 24 | } 25 | 26 | inline XMFLOAT3 Normalize(XMFLOAT3 a) 27 | { 28 | return a / Len(a); 29 | } 30 | 31 | float GetParticleRadius() 32 | { 33 | return g_pradius; 34 | } 35 | 36 | dpPatch void SetParticleRadius(float r) 37 | { 38 | g_pradius = r; 39 | Particle *particles = g_particles; 40 | size_t num_particles = _countof(g_particles); 41 | for(size_t i=0; i(0.0f, d) * -0.2f; 112 | } 113 | 114 | // 速度を適用 115 | #pragma omp parallel for 116 | for(int ri=0; ri 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Test/Test_Particles2012.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Test/Test_Simple/Test_Simple.cpp: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicPatcher 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | //#define dpDisable 13 | //#define dpLinkStatic 14 | #include "DynamicPatcher.h" 15 | 16 | #ifdef _M_X64 17 | # define dpPlatform "x64" 18 | #else 19 | # define dpPlatform "Win32" 20 | #endif 21 | #ifdef _DEBUG 22 | # define dpConfiguration "Debug" 23 | #else 24 | # define dpConfiguration "Release" 25 | #endif 26 | #define dpObjDir "_tmp/Test_Simple_" dpPlatform dpConfiguration 27 | 28 | // __declspec(dllexport) がついてる関数や class には export 属性が .obj にも残る。 29 | // これを利用し、export 属性が付いているものはロードされた時自動的に patch する。 30 | // ( dpPatch == __declspec(dllexport) ) 31 | 32 | dpScope( 33 | int puts_hook(const char *s) 34 | { 35 | typedef int (*puts_t)(const char *s); 36 | puts_t orig_puts = (puts_t)dpGetUnpatched(&puts); 37 | orig_puts("puts_hook()"); 38 | return orig_puts(s); 39 | } 40 | ) 41 | 42 | class dpPatch Test 43 | { 44 | public: 45 | Test() : m_end_flag(false) {} 46 | virtual ~Test() {} 47 | 48 | dpNoInline virtual void doSomething() 49 | { 50 | puts("Test::doSomething()"); 51 | printf("Test::s_value: %d\n", s_value); 52 | //m_end_flag = true; 53 | } 54 | 55 | bool getEndFlag() const { return m_end_flag; } 56 | 57 | private: 58 | static int s_value; 59 | static const int s_cvalue; 60 | bool m_end_flag; 61 | }; 62 | int Test::s_value = 42; 63 | const int Test::s_cvalue = 42; 64 | 65 | dpNoInline void Test_ThisMaybeOverridden() 66 | { 67 | printf("Test_ThisMaybeOverridden()\n"); 68 | } 69 | 70 | int main(int argc, char *argv[]) 71 | { 72 | dpInitialize(dpE_LogAll); 73 | dpAddModulePath(dpObjDir"/*.obj"); 74 | dpAddSourcePath("Test_Simple"); 75 | dpAddMSBuildCommand("Test_Simple.vcxproj /target:ClCompile /m /p:Configuration="dpConfiguration";Platform="dpPlatform); 76 | dpStartAutoBuild(); 77 | 78 | printf("DynamicPatcher Test_Simple\n"); 79 | { 80 | Test test; 81 | while(!test.getEndFlag()) { 82 | test.doSomething(); 83 | 84 | ::Sleep(1000); 85 | dpUpdate(); 86 | } 87 | } 88 | dpFinalize(); 89 | } 90 | 91 | #ifdef dpWithTDisasm 92 | dpOnLoad( 93 | dpPatchAddressToAddress(&puts, &puts_hook); 94 | ) 95 | #endif // dpWithTDisasm 96 | 97 | dpOnUnload( 98 | printf("unloaded.\n"); 99 | ) 100 | -------------------------------------------------------------------------------- /Test/Test_Simple2010.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | {315A0660-7223-41CF-839C-69CF731F8F43} 26 | Win32Proj 27 | Test_Simple 28 | Test_Simple 29 | 30 | 31 | 32 | Application 33 | true 34 | Unicode 35 | 36 | 37 | Application 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | false 44 | false 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | false 51 | Unicode 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | ..;$(IncludePath) 71 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 72 | $(ProjectName) 73 | $(ProjectDir) 74 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 75 | false 76 | 77 | 78 | ..;$(IncludePath) 79 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 80 | $(ProjectName) 81 | $(ProjectDir) 82 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 83 | false 84 | 85 | 86 | ..;$(IncludePath) 87 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 88 | $(ProjectName) 89 | $(ProjectDir) 90 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 91 | false 92 | 93 | 94 | ..;$(IncludePath) 95 | ..;$(DXSDK_DIR)lib\x86;$(LibraryPath) 96 | $(ProjectName) 97 | $(ProjectDir) 98 | _tmp\$(ProjectName)_$(Platform)$(Configuration)\ 99 | false 100 | 101 | 102 | 103 | NotUsing 104 | false 105 | MultiThreadedDebug 106 | Fast 107 | ProgramDatabase 108 | true 109 | 110 | 111 | Console 112 | false 113 | true 114 | false 115 | true 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | NotUsing 125 | false 126 | MultiThreadedDebug 127 | Fast 128 | ProgramDatabase 129 | true 130 | 131 | 132 | Console 133 | false 134 | true 135 | false 136 | true 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | NotUsing 146 | MultiThreaded 147 | false 148 | Fast 149 | true 150 | 151 | 152 | Console 153 | false 154 | true 155 | false 156 | true 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | NotUsing 166 | MultiThreaded 167 | false 168 | Fast 169 | true 170 | 171 | 172 | Console 173 | false 174 | true 175 | false 176 | true 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /bin/DynamicPatcher-1.0.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-saint/DynamicPatcher/683057ddabe61a638124c11c993f8ae381930b18/bin/DynamicPatcher-1.0.0.zip -------------------------------------------------------------------------------- /bin/DynamicPatcher-1.1.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-saint/DynamicPatcher/683057ddabe61a638124c11c993f8ae381930b18/bin/DynamicPatcher-1.1.0.zip -------------------------------------------------------------------------------- /disasm-lib/cpu.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2003, Matt Conover (mconover@gmail.com) 2 | #include "cpu.h" 3 | #include 4 | 5 | // NOTE: this assumes default scenarios (i.e., we assume CS/DS/ES/SS and flat 6 | // and all have a base of 0 and limit of 0xffffffff, we don't try to verify 7 | // that in the GDT) 8 | // 9 | // TODO: use inline assembly to get selector for segment 10 | // Segment = x86 segment register (SEG_ES = 0, SEG_CS = 1, ...) 11 | BYTE *GetAbsoluteAddressFromSegment(BYTE Segment, DWORD Offset) 12 | { 13 | switch (Segment) 14 | { 15 | // Windows uses a flat address space (except FS for x86 and GS for x64) 16 | case 0: // SEG_ES 17 | case 1: // SEG_CS 18 | case 2: // SEG_SS 19 | case 3: // SEG_DS 20 | return (BYTE *)(DWORD_PTR)Offset; 21 | case 4: // SEG_FS 22 | case 5: // SEG_GS 23 | return (BYTE *)(DWORD_PTR)Offset; 24 | // Note: we're really supposed to do this, but get_teb is not implemented 25 | // in this bastardized version of the disassembler. 26 | // return (BYTE *)get_teb() + Offset; 27 | default: 28 | assert(0); 29 | return (BYTE *)(DWORD_PTR)Offset; 30 | } 31 | } 32 | 33 | // This is an GDT/LDT selector (pGDT+Selector) 34 | BYTE *GetAbsoluteAddressFromSelector(WORD Selector, DWORD Offset) 35 | { 36 | DESCRIPTOR_ENTRY Entry; 37 | GATE_ENTRY *Gate; 38 | ULONG_PTR Base; 39 | 40 | assert(Selector < 0x10000); 41 | if (!GetThreadSelectorEntry(GetCurrentThread(), Selector, (LDT_ENTRY *)&Entry)) return NULL; 42 | if (!Entry.Present) return NULL; 43 | if (Entry.System) 44 | { 45 | Base = 0; 46 | #ifdef _WIN64 47 | Base |= (ULONG_PTR)Entry.HighOffset64 << 32; 48 | #endif 49 | Base |= Entry.BaseHi << 24; 50 | Base |= Entry.BaseMid << 16; 51 | Base |= Entry.BaseLow; 52 | } 53 | else 54 | { 55 | switch (Entry.Type) 56 | { 57 | case 1: // 16-bit TSS (available) 58 | case 2: // LDT 59 | case 3: // 16-bit TSS (busy) 60 | case 9: // 32-bit TSS (available) 61 | case 11: // 32-bit TSS (busy) 62 | Base = 0; 63 | #ifdef _WIN64 64 | Base |= (ULONG_PTR)Entry.HighOffset64 << 32; 65 | #endif 66 | Base |= Entry.BaseHi << 24; 67 | Base |= Entry.BaseMid << 16; 68 | Base |= Entry.BaseLow; 69 | break; 70 | 71 | case 4: // 16-bit call gate 72 | case 5: // task gate 73 | case 6: // 16-bit interrupt gate 74 | case 7: // 16-bit task gate 75 | case 12: // 32-bit call gate 76 | case 14: // 32-bit interrupt gate 77 | case 15: // 32-bit trap gate 78 | Gate = (GATE_ENTRY *)&Entry; 79 | #ifdef _WIN64 80 | Base = ((ULONG_PTR)Gate->HighOffset64 << 32) | (Gate->HighOffset << 16) | Gate->LowOffset; 81 | #else 82 | Base = (Gate->HighOffset << 16) | Gate->LowOffset; 83 | #endif 84 | assert(!Offset); Offset = 0; 85 | break; 86 | default: 87 | assert(0); 88 | return NULL; 89 | } 90 | } 91 | return (BYTE *)Base + Offset; 92 | } 93 | 94 | -------------------------------------------------------------------------------- /disasm-lib/cpu.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2003, Matt Conover (mconover@gmail.com) 2 | #ifndef CPU_H 3 | #define CPU_H 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | #pragma pack(push,1) 8 | 9 | #include 10 | #include "misc.h" 11 | 12 | //////////////////////////////////////////////////////// 13 | // System descriptors 14 | //////////////////////////////////////////////////////// 15 | 16 | #define GDT_NULL 0 17 | #define GDT_R0_CODE 0x08 18 | #define GDT_R0_DATA 0x10 19 | #define GDT_R3_CODE 0x18 20 | #define GDT_R3_DATA 0x20 21 | #define GDT_TSS 0x28 22 | #define GDT_PCR 0x30 23 | #define GDT_R3_TEB 0x38 24 | #define GDT_VDM 0x40 25 | #define GDT_LDT 0x48 26 | #define GDT_DOUBLEFAULT_TSS 0x50 27 | #define GDT_NMI_TSS 0x58 28 | 29 | // 16-bit GDT entries: 30 | // TODO: #define GDT_ABIOS_UNKNOWN 0x60 (22F30-32F2F) 31 | #define GDT_ABIOS_VIDEO 0x68 32 | #define GDT_ABIOS_GDT 0x70 // descriptor describing ABIOS GDT itself 33 | #define GDT_ABIOS_NTOS 0x78 // first 64K of NTOSKRNL 34 | #define GDT_ABIOS_CDA 0xE8 // common data area 35 | #define GDT_ABIOS_CODE 0xF0 // KiI386AbiosCall 36 | #define GDT_ABIOS_STACK 0xF8 37 | 38 | #define SELECTOR_RPL_MASK 0x03 // bits 0-1 39 | #define SELECTOR_LDT 0x04 // bit 2 40 | 41 | // for data selectors 42 | #define DATA_ACCESS_MASK (1<<0) 43 | #define DATA_WRITE_ENABLE_MASK (1<<1) 44 | #define DATA_EXPAND_DOWN_MASK (1<<2) 45 | 46 | // for code selectors 47 | #define CODE_ACCESS_MASK (1<<0) 48 | #define CODE_READ_MASK (1<<1) 49 | #define CODE_CONFORMING_MASK (1<<2) 50 | #define CODE_FLAG (1<<3) 51 | 52 | #define TASK_GATE 5 53 | #define INTERRUPT_GATE 6 54 | #define TRAP_GATE 7 55 | 56 | typedef struct _IDT_ENTRY 57 | { 58 | USHORT LowOffset; 59 | USHORT Selector; 60 | UCHAR Ignored : 5; 61 | UCHAR Zero : 3; 62 | UCHAR Type : 3; 63 | UCHAR Is32Bit : 1; 64 | UCHAR Ignored2 : 1; 65 | UCHAR DPL : 2; 66 | UCHAR Present : 1; 67 | USHORT HighOffset; 68 | #ifdef _WIN64 69 | ULONG HighOffset64; 70 | ULONG Reserved; 71 | #endif 72 | } IDT_ENTRY, TRAP_GATE_ENTRY; 73 | 74 | typedef struct _CALL_GATE_ENTRY 75 | { 76 | USHORT LowOffset; 77 | USHORT Selector; 78 | UCHAR ParameterCount: 4; 79 | UCHAR Ignored : 3; 80 | UCHAR Type : 5; 81 | UCHAR DPL : 2; 82 | UCHAR Present : 1; 83 | USHORT HighOffset; 84 | #ifdef _WIN64 85 | ULONG HighOffset64; 86 | ULONG Reserved; 87 | #endif 88 | } CALL_GATE_ENTRY; 89 | 90 | typedef struct _TASK_GATE_ENTRY 91 | { 92 | USHORT Ignored; 93 | USHORT Selector; 94 | UCHAR Ignored2 : 5; 95 | UCHAR Zero : 3; 96 | UCHAR Type : 5; 97 | UCHAR DPL : 2; 98 | UCHAR Present : 1; 99 | USHORT Ignored3; 100 | } TASK_GATE_ENTRY; 101 | 102 | typedef struct _DESCRIPTOR_ENTRY 103 | { 104 | USHORT LimitLow; 105 | USHORT BaseLow; 106 | UCHAR BaseMid; 107 | UCHAR Type : 4; // 10EWA (code), E=ExpandDown, W=Writable, A=Accessed 108 | // 11CRA (data), C=Conforming, R=Readable, A=Accessed 109 | UCHAR System : 1; // if 1 then it is a gate or LDT 110 | UCHAR DPL : 2; // descriptor privilege level; 111 | // for data selectors, MAX(CPL, RPL) must be <= DPL to access (or else GP# fault) 112 | // for non-conforming code selectors (without callgate), MAX(CPL, RPL) must be <= DPL to access (or else GP# fault) 113 | // for conforming code selectors, MAX(CPL, RPL) must be >= DPL (i.e., CPL 0-2 cannot access if DPL is 3) 114 | // for non-conforming code selectors (with call gate), DPL indicates lowest privilege allowed to access gate 115 | UCHAR Present : 1; 116 | UCHAR LimitHigh : 4; 117 | UCHAR Available: 1; // aka AVL 118 | UCHAR Reserved : 1; 119 | UCHAR Is32Bit : 1; // aka B flag 120 | UCHAR Granularity : 1; // aka G flag 121 | UCHAR BaseHi : 8; 122 | #ifdef _WIN64 123 | ULONG HighOffset64; 124 | ULONG Reserved2; 125 | #endif 126 | } DESCRIPTOR_ENTRY; 127 | 128 | typedef struct _GATE_ENTRY 129 | { 130 | USHORT LowOffset; 131 | UCHAR Skip; 132 | UCHAR Type : 5; 133 | UCHAR DPL : 2; 134 | UCHAR Present : 1; 135 | USHORT HighOffset; 136 | #ifdef _WIN64 137 | ULONG HighOffset64; 138 | ULONG Reserved; 139 | #endif 140 | } GATE_ENTRY; 141 | 142 | // TODO: update for X64 143 | typedef struct _PTE_ENTRY 144 | { 145 | ULONG Present : 1; 146 | ULONG Write : 1; 147 | ULONG Owner : 1; // E.g., user mode or supervisor mode 148 | ULONG WriteThrough : 1; 149 | ULONG CacheDisable : 1; 150 | ULONG Accessed : 1; 151 | ULONG Dirty : 1; 152 | ULONG PAT : 1; 153 | ULONG Global : 1; 154 | ULONG CopyOnWrite : 1; 155 | ULONG Prototype : 1; 156 | ULONG Transition : 1; 157 | ULONG Address : 20; 158 | } PTE_ENTRY; 159 | 160 | // TODO: update for X64 161 | typedef struct _PDE_ENTRY 162 | { 163 | ULONG Present : 1; 164 | ULONG Write : 1; 165 | ULONG Owner : 1; 166 | ULONG WriteThrough : 1; 167 | ULONG CacheDisable : 1; 168 | ULONG Accessed : 1; 169 | ULONG Reserved1 : 1; 170 | ULONG PageSize : 1; 171 | ULONG Global : 1; 172 | ULONG Reserved : 3; 173 | ULONG Address : 20; 174 | } PDE_ENTRY; 175 | 176 | // TODO: update for X64 177 | typedef struct _IO_ACCESS_MAP 178 | { 179 | UCHAR DirectionMap[32]; 180 | UCHAR IoMap[8196]; 181 | } IO_ACCESS_MAP; 182 | 183 | #define MIN_TSS_SIZE FIELD_OFFSET(TSS_ENTRY, IoMaps) 184 | // TODO: update for X64 185 | typedef struct _TSS_ENTRY 186 | { 187 | USHORT Backlink; 188 | USHORT Reserved0; 189 | ULONG Esp0; 190 | USHORT Ss0; 191 | USHORT Reserved1; 192 | ULONG NotUsed1[4]; 193 | ULONG CR3; 194 | ULONG Eip; 195 | ULONG NotUsed2[9]; 196 | USHORT Es; 197 | USHORT Reserved2; 198 | USHORT Cs; 199 | USHORT Reserved3; 200 | USHORT Ss; 201 | USHORT Reserved4; 202 | USHORT Ds; 203 | USHORT Reserved5; 204 | USHORT Fs; 205 | USHORT Reserved6; 206 | USHORT Gs; 207 | USHORT Reserved7; 208 | USHORT LDT; 209 | USHORT Reserved8; 210 | USHORT Flags; 211 | USHORT IoMapBase; 212 | IO_ACCESS_MAP IoMaps[1]; 213 | UCHAR IntDirectionMap[32]; 214 | } TSS_ENTRY; 215 | 216 | // TODO: update for X64 217 | typedef struct _TSS16_ENTRY 218 | { 219 | USHORT Backlink; 220 | USHORT Sp0; 221 | USHORT Ss0; 222 | USHORT Sp1; 223 | USHORT Ss1; 224 | USHORT Sp2; 225 | USHORT Ss3; 226 | USHORT Ip; 227 | USHORT Flags; 228 | USHORT Ax; 229 | USHORT Cx; 230 | USHORT Dx; 231 | USHORT Bx; 232 | USHORT Sp; 233 | USHORT Bp; 234 | USHORT Si; 235 | USHORT Di; 236 | USHORT Es; 237 | USHORT Cs; 238 | USHORT Ss; 239 | USHORT Ds; 240 | USHORT LDT; 241 | } TSS16_ENTRY; 242 | 243 | // TODO: update for X64 244 | typedef struct _GDT_ENTRY 245 | { 246 | USHORT LimitLow; 247 | USHORT BaseLow; 248 | union { 249 | struct { 250 | UCHAR BaseMid; 251 | UCHAR Flags1; 252 | UCHAR Flags2; 253 | UCHAR BaseHi; 254 | } Bytes; 255 | struct { 256 | ULONG BaseMid : 8; 257 | ULONG Type : 5; 258 | ULONG Dpl : 2; 259 | ULONG Pres : 1; 260 | ULONG LimitHi : 4; 261 | ULONG Sys : 1; 262 | ULONG Reserved_0 : 1; 263 | ULONG Default_Big : 1; 264 | ULONG Granularity : 1; 265 | ULONG BaseHi : 8; 266 | } Bits; 267 | } HighWord; 268 | } GDT_ENTRY; 269 | 270 | BYTE *GetAbsoluteAddressFromSegment(BYTE Segment, DWORD Offset); 271 | BYTE *GetAbsoluteAddressFromSelector(WORD Selector, DWORD Offset); 272 | 273 | #pragma pack(pop) 274 | #ifdef __cplusplus 275 | } 276 | #endif 277 | #endif // CPU_H -------------------------------------------------------------------------------- /disasm-lib/disasm.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2004, Matt Conover (mconover@gmail.com) 2 | #undef NDEBUG 3 | #include 4 | #include 5 | #include "disasm.h" 6 | 7 | #ifdef NO_SANITY_CHECKS 8 | #define NDEBUG 9 | #undef assert 10 | #define assert(x) 11 | #endif 12 | 13 | ////////////////////////////////////////////////////////////////////// 14 | // Global variables 15 | ////////////////////////////////////////////////////////////////////// 16 | 17 | ARCHITECTURE_FORMAT SupportedArchitectures[] = 18 | { 19 | { ARCH_X86, &X86 }, 20 | { ARCH_X86_16, &X86 }, 21 | { ARCH_X64, &X86 }, 22 | { ARCH_UNKNOWN, NULL } 23 | }; 24 | 25 | typedef struct _DISASM_ARG_INFO 26 | { 27 | INSTRUCTION *MatchedInstruction; 28 | BOOL MatchPrefix; 29 | U8 *Opcode; 30 | U32 OpcodeLength; 31 | INSTRUCTION_TYPE InstructionType; 32 | U32 Count; 33 | } DISASM_ARG_INFO; 34 | 35 | ////////////////////////////////////////////////////////////////////// 36 | // Function prototypes 37 | ////////////////////////////////////////////////////////////////////// 38 | 39 | BOOL InitInstruction(INSTRUCTION *Instruction, DISASSEMBLER *Disassembler); 40 | struct _ARCHITECTURE_FORMAT *GetArchitectureFormat(ARCHITECTURE_TYPE Type); 41 | 42 | ////////////////////////////////////////////////////////////////////// 43 | // Disassembler setup 44 | ////////////////////////////////////////////////////////////////////// 45 | 46 | BOOL InitDisassembler(DISASSEMBLER *Disassembler, ARCHITECTURE_TYPE Architecture) 47 | { 48 | ARCHITECTURE_FORMAT *ArchFormat; 49 | 50 | memset(Disassembler, 0, sizeof(DISASSEMBLER)); 51 | Disassembler->Initialized = DISASSEMBLER_INITIALIZED; 52 | 53 | ArchFormat = GetArchitectureFormat(Architecture); 54 | if (!ArchFormat) { assert(0); return FALSE; } 55 | Disassembler->ArchType = ArchFormat->Type; 56 | Disassembler->Functions = ArchFormat->Functions; 57 | return TRUE; 58 | } 59 | 60 | void CloseDisassembler(DISASSEMBLER *Disassembler) 61 | { 62 | memset(Disassembler, 0, sizeof(DISASSEMBLER)); 63 | } 64 | 65 | ////////////////////////////////////////////////////////////////////// 66 | // Instruction setup 67 | ////////////////////////////////////////////////////////////////////// 68 | 69 | BOOL InitInstruction(INSTRUCTION *Instruction, DISASSEMBLER *Disassembler) 70 | { 71 | memset(Instruction, 0, sizeof(INSTRUCTION)); 72 | Instruction->Initialized = INSTRUCTION_INITIALIZED; 73 | Instruction->Disassembler = Disassembler; 74 | memset(Instruction->String, ' ', MAX_OPCODE_DESCRIPTION-1); 75 | Instruction->String[MAX_OPCODE_DESCRIPTION-1] = '\0'; 76 | return TRUE; 77 | } 78 | 79 | // If Decode = FALSE, only the following fields are valid: 80 | // Instruction->Length, Instruction->Address, Instruction->Prefixes, Instruction->PrefixCount, 81 | // Instruction->OpcodeBytes, Instruction->Instruction->OpcodeLength, Instruction->Groups, 82 | // Instruction->Type, Instruction->OperandCount 83 | // 84 | // If Disassemble = TRUE, then Instruction->String is valid (also requires Decode = TRUE) 85 | // 86 | // WARNING: This will overwrite the previously obtained instruction 87 | INSTRUCTION *GetInstruction(DISASSEMBLER *Disassembler, U64 VirtualAddress, U8 *Address, U32 Flags) 88 | { 89 | if (Disassembler->Initialized != DISASSEMBLER_INITIALIZED) { assert(0); return NULL; } 90 | assert(Address); 91 | InitInstruction(&Disassembler->Instruction, Disassembler); 92 | Disassembler->Instruction.Address = Address; 93 | Disassembler->Instruction.VirtualAddressDelta = VirtualAddress - (U64)Address; 94 | if (!Disassembler->Functions->GetInstruction(&Disassembler->Instruction, Address, Flags)) 95 | { 96 | assert(Disassembler->Instruction.Address == Address); 97 | assert(Disassembler->Instruction.Length < MAX_INSTRUCTION_LENGTH); 98 | 99 | // Save the address that failed, in case the lower-level disassembler didn't 100 | Disassembler->Instruction.Address = Address; 101 | Disassembler->Instruction.ErrorOccurred = TRUE; 102 | return NULL; 103 | } 104 | return &Disassembler->Instruction; 105 | } 106 | 107 | /////////////////////////////////////////////////////////////////////////// 108 | // Miscellaneous 109 | /////////////////////////////////////////////////////////////////////////// 110 | 111 | static ARCHITECTURE_FORMAT *GetArchitectureFormat(ARCHITECTURE_TYPE Type) 112 | { 113 | ARCHITECTURE_FORMAT *Format; 114 | for (Format = SupportedArchitectures; Format->Type != ARCH_UNKNOWN; Format++) 115 | { 116 | if (Format->Type == Type) return Format; 117 | } 118 | 119 | assert(0); 120 | return NULL; 121 | } 122 | 123 | -------------------------------------------------------------------------------- /disasm-lib/misc.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2002, Matt Conover (mconover@gmail.com) 2 | #include "misc.h" 3 | 4 | BOOL IsHexChar(BYTE ch) 5 | { 6 | switch (ch) 7 | { 8 | case '0': case '1': case '2': case '3': 9 | case '4': case '5': case '6': case '7': 10 | case '8': case '9': 11 | case 'A': case 'a': case 'B': case 'b': 12 | case 'C': case 'c': case 'D': case 'd': 13 | case 'E': case 'e': case 'F': case 'f': 14 | return TRUE; 15 | default: 16 | return FALSE; 17 | } 18 | } 19 | 20 | // NOTE: caller must free the buffer returned 21 | BYTE *HexToBinary(char *Input, DWORD InputLength, DWORD *OutputLength) 22 | { 23 | DWORD i, j, ByteCount = 0; 24 | char temp_byte[3]; 25 | BYTE *p, *ByteString = NULL; 26 | 27 | if (!InputLength || !OutputLength) return NULL; 28 | else *OutputLength = 0; 29 | 30 | while (*Input && isspace(*Input)) { Input++; InputLength--; } 31 | if (!*Input) return NULL; 32 | if (Input[0] == '\"') { Input++; InputLength--; } 33 | p = (BYTE *)strchr(Input, '\"'); 34 | if (p) InputLength--; 35 | 36 | if (InputLength > 2 && Input[2] == ' ') // assume spaces 37 | { 38 | for (i = 0; i < InputLength; i += 3) 39 | { 40 | while (i < InputLength && isspace(Input[i])) i++; // skip over extra space, \r, and \n 41 | if (i >= InputLength) break; 42 | 43 | if (!IsHexChar(Input[i])) 44 | { 45 | //fprintf(stderr, "ERROR: invalid hex character at offset %lu (0x%04x)\n", i, i); 46 | goto abort; 47 | } 48 | 49 | if (i+1 >= InputLength || !Input[i+1]) 50 | { 51 | //fprintf(stderr, "ERROR: hex string terminates unexpectedly at offset %lu (0x%04x)\n", i+1, i+1); 52 | goto abort; 53 | } 54 | 55 | if (i+2 < InputLength && Input[i+2] && !isspace(Input[i+2])) 56 | { 57 | //fprintf(stderr, "ERROR: Hex string is malformed at offset %lu (0x%04x)\n", i, i); 58 | //fprintf(stderr, "Found '%c' (0x%02x) instead of space\n", Input[i+2], Input[i+2]); 59 | goto abort; 60 | } 61 | 62 | ByteCount++; 63 | } 64 | 65 | if (!ByteCount) 66 | { 67 | //fprintf(stderr, "Error: no input (byte count = 0)\n"); 68 | goto abort; 69 | } 70 | 71 | ByteString = malloc(ByteCount+1); 72 | if (!ByteString) 73 | { 74 | //fprintf(stderr, "ERROR: failed to allocate %lu bytes\n", ByteCount); 75 | goto abort; 76 | } 77 | 78 | memset(ByteString, 0, ByteCount+1); 79 | for (i = 0, j = 0; j < ByteCount; i += 3, j++) 80 | { 81 | while (isspace(Input[i])) i++; // skip over extra space, \r, and \n 82 | temp_byte[0] = Input[i]; 83 | temp_byte[1] = Input[i+1]; 84 | temp_byte[2] = 0; 85 | ByteString[j] = (BYTE)strtoul(temp_byte, NULL, 16); 86 | } 87 | } 88 | else if (InputLength > 2 && Input[0] == '\\') 89 | { 90 | for (i = 0; i < InputLength; i += 2) 91 | { 92 | if (Input[i] != '\\' || (Input[i+1] != 'x' && Input[i+1] != '0')) 93 | { 94 | //fprintf(stderr, "ERROR: invalid hex character at offset %lu (0x%04x)\n", i, i); 95 | goto abort; 96 | } 97 | i += 2; 98 | 99 | if (!IsHexChar(Input[i])) 100 | { 101 | //fprintf(stderr, "ERROR: invalid hex character at offset %lu (0x%04x)\n", i, i); 102 | goto abort; 103 | } 104 | if (i+1 >= InputLength || !Input[i+1]) 105 | { 106 | //fprintf(stderr, "ERROR: hex string terminates unexpectedly at offset %lu (0x%04x)\n", i+1, i+1); 107 | goto abort; 108 | } 109 | 110 | ByteCount++; 111 | } 112 | 113 | if (!ByteCount) 114 | { 115 | //fprintf(stderr, "Error: no input (byte count = 0)\n"); 116 | goto abort; 117 | } 118 | 119 | ByteString = malloc(ByteCount+1); 120 | if (!ByteString) 121 | { 122 | //fprintf(stderr, "ERROR: failed to allocate %lu bytes\n", ByteCount); 123 | goto abort; 124 | } 125 | 126 | memset(ByteString, 0, ByteCount+1); 127 | for (i = j = 0; j < ByteCount; i += 2, j++) 128 | { 129 | i += 2; 130 | temp_byte[0] = Input[i]; 131 | temp_byte[1] = Input[i+1]; 132 | temp_byte[2] = 0; 133 | ByteString[j] = (BYTE)strtoul(temp_byte, NULL, 16); 134 | } 135 | } 136 | else // assume it is a hex string with no spaces with 2 bytes per character 137 | { 138 | for (i = 0; i < InputLength; i += 2) 139 | { 140 | if (!IsHexChar(Input[i])) 141 | { 142 | //fprintf(stderr, "ERROR: invalid hex character at offset %lu (0x%04x)\n", i, i); 143 | goto abort; 144 | } 145 | if (i+1 >= InputLength || !Input[i+1]) 146 | { 147 | //fprintf(stderr, "ERROR: hex string terminates unexpectedly at offset %lu (0x%04x)\n", i+1, i+1); 148 | goto abort; 149 | } 150 | 151 | ByteCount++; 152 | } 153 | 154 | if (!ByteCount) 155 | { 156 | //fprintf(stderr, "Error: no input (byte count = 0)\n"); 157 | goto abort; 158 | } 159 | 160 | ByteString = malloc(ByteCount+1); 161 | if (!ByteString) 162 | { 163 | //fprintf(stderr, "ERROR: failed to allocate %lu bytes\n", ByteCount); 164 | goto abort; 165 | } 166 | 167 | memset(ByteString, 0, ByteCount+1); 168 | for (i = 0, j = 0; j < ByteCount; i += 2, j++) 169 | { 170 | temp_byte[0] = Input[i]; 171 | temp_byte[1] = Input[i+1]; 172 | temp_byte[2] = 0; 173 | ByteString[j] = (BYTE)strtoul(temp_byte, NULL, 16); 174 | } 175 | } 176 | 177 | *OutputLength = ByteCount; 178 | return ByteString; 179 | 180 | abort: 181 | if (OutputLength) *OutputLength = 0; 182 | if (ByteString) free(ByteString); 183 | return NULL; 184 | } 185 | 186 | -------------------------------------------------------------------------------- /disasm-lib/misc.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2002, Matt Conover (mconover@gmail.com) 2 | #ifndef MISC_H 3 | #define MISC_H 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) 14 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) 15 | 16 | // NOTE: start is inclusive, end is exclusive (as in start <= x < end) 17 | #define IS_IN_RANGE(x, s, e) \ 18 | ( \ 19 | ((ULONG_PTR)(x) == (ULONG_PTR)(s) && (ULONG_PTR)(x) == (ULONG_PTR)(e)) || \ 20 | ((ULONG_PTR)(x) >= (ULONG_PTR)(s) && (ULONG_PTR)(x) < (ULONG_PTR)(e)) \ 21 | ) 22 | 23 | #if _MSC_VER >= 1400 24 | #pragma warning(disable:4996) 25 | #endif 26 | 27 | #if defined(_WIN64) 28 | #define VALID_ADDRESS_MAX 0x7FFEFFFFFFFFFFFF // Win64 specific 29 | typedef unsigned __int64 ULONG_PTR, *PULONG_PTR; 30 | #else 31 | #define VALID_ADDRESS_MAX 0x7FFEFFFF // Win32 specific 32 | typedef unsigned long ULONG_PTR, *PULONG_PTR; 33 | #endif 34 | 35 | #ifndef DECLSPEC_ALIGN 36 | #if (_MSC_VER >= 1300) && !defined(MIDL_PASS) 37 | #define DECLSPEC_ALIGN(x) __declspec(align(x)) 38 | #else 39 | #define DECLSPEC_ALIGN(x) 40 | #endif 41 | #endif 42 | 43 | #define VALID_ADDRESS_MIN 0x10000 // Win32 specific 44 | #define IS_VALID_ADDRESS(a) IS_IN_RANGE(a, VALID_ADDRESS_MIN, VALID_ADDRESS_MAX+1) 45 | 46 | BOOL IsHexChar(BYTE ch); 47 | BYTE *HexToBinary(char *Input, DWORD InputLength, DWORD *OutputLength); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | #endif // MISC_H 53 | -------------------------------------------------------------------------------- /disasm2010.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | disasm-lib 6 | 7 | 8 | disasm-lib 9 | 10 | 11 | disasm-lib 12 | 13 | 14 | disasm-lib 15 | 16 | 17 | 18 | 19 | disasm-lib 20 | 21 | 22 | disasm-lib 23 | 24 | 25 | disasm-lib 26 | 27 | 28 | disasm-lib 29 | 30 | 31 | disasm-lib 32 | 33 | 34 | 35 | 36 | {350a6ebe-5c55-4219-b806-031e7e991abf} 37 | 38 | 39 | -------------------------------------------------------------------------------- /disasm2012.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | disasm-lib 6 | 7 | 8 | disasm-lib 9 | 10 | 11 | disasm-lib 12 | 13 | 14 | disasm-lib 15 | 16 | 17 | 18 | 19 | disasm-lib 20 | 21 | 22 | disasm-lib 23 | 24 | 25 | disasm-lib 26 | 27 | 28 | disasm-lib 29 | 30 | 31 | disasm-lib 32 | 33 | 34 | 35 | 36 | {350a6ebe-5c55-4219-b806-031e7e991abf} 37 | 38 | 39 | -------------------------------------------------------------------------------- /dpConfig.cpp: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicPatcher 4 | 5 | #include "DynamicPatcher.h" 6 | #include "dpInternal.h" 7 | 8 | static dpConfig g_dpConfig; 9 | dpConfig& dpGetConfig() { return g_dpConfig; } 10 | 11 | dpConfigFile::dpConfigFile() 12 | : log_flags(-1), sys_flags(-1), vc_ver(-1) 13 | { 14 | } 15 | 16 | bool dpConfigFile::copy(const char *name) 17 | { 18 | return ::CopyFileA(config_path.c_str(), name, FALSE)==TRUE; 19 | } 20 | 21 | bool dpConfigFile::load() 22 | { 23 | char dll_path[MAX_PATH]; 24 | char exe_path[MAX_PATH]; 25 | std::string dll_dir, exe_file, exe; 26 | dpGetMainModulePath(exe_path, _countof(exe_path)); 27 | dpGetCurrentModulePath(dll_path, _countof(dll_path)); 28 | dpSeparateDirFile(dll_path, &dll_dir, nullptr); 29 | dpSeparateDirFile(exe_path, nullptr, &exe_file); 30 | dpSeparateFileExt(exe_file.c_str(), &exe, nullptr); 31 | 32 | std::string conf = dll_dir; 33 | conf += exe; 34 | conf += "dpconf"; 35 | return load(conf.c_str()); 36 | } 37 | 38 | bool dpConfigFile::load(const wchar_t *path) 39 | { 40 | size_t len = wcstombs(nullptr, path, 0); 41 | char *mbs = (char*)alloca(len+1); 42 | wcstombs(mbs, path, len); 43 | mbs[len] = '\0'; 44 | return load(mbs); 45 | } 46 | 47 | 48 | bool dpConfigFile::load(const char *path) 49 | { 50 | if(FILE *f=fopen(path, "rb")) { 51 | char line[1024]; 52 | char opt[MAX_PATH]; 53 | int iv; 54 | while(fgets(line, _countof(line), f)) { 55 | if(line[0]=='/') { continue; } 56 | else if(sscanf(line, "log flags: %x", &iv)) { log_flags=iv; } 57 | else if(sscanf(line, "sys flags: %x", &iv)) { sys_flags=iv; } 58 | else if(sscanf(line, "vc ver: %d", &iv)) { vc_ver=iv; } 59 | else if(sscanf(line, "load: \"%[^\"]\"", opt)) { loads.push_back(opt); } 60 | else if(sscanf(line, "source path: \"%[^\"]\"", opt)) { source_paths.push_back(opt); } 61 | else if(sscanf(line, "module path: \"%[^\"]\"", opt)) { module_paths.push_back(opt); } 62 | else if(sscanf(line, "preload path: \"%[^\"]\"", opt)) { preload_paths.push_back(opt); } 63 | else if(sscanf(line, "msbuild command: \"%[^\"]\"", opt)) { msbuild_commands.push_back(opt); } 64 | else if(sscanf(line, "build command: \"%[^\"]\"", opt)) { build_commands.push_back(opt); } 65 | else if(sscanf(line, "force host symbol pattern: \"%[^\"]\"", opt)) { force_host_symbol_patterns.push_back(opt); } 66 | } 67 | fclose(f); 68 | config_path = path; 69 | return true; 70 | } 71 | return false; 72 | } 73 | -------------------------------------------------------------------------------- /dpContext.cpp: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicPatcher 4 | 5 | #include "DynamicPatcher.h" 6 | #include "dpInternal.h" 7 | 8 | dpContext::dpContext() 9 | { 10 | m_builder = new dpBuilder(this); 11 | m_patcher = new dpPatcher(this); 12 | m_loader = new dpLoader(this); 13 | } 14 | 15 | dpContext::~dpContext() 16 | { 17 | m_builder->stopAutoBuild(); 18 | m_builder->stopPreload(); 19 | // バイナリ unload 時に適切に unpatch するには patcher より先に loader を破棄する必要がある 20 | delete m_loader; m_loader=nullptr; 21 | delete m_patcher; m_patcher=nullptr; 22 | delete m_builder; m_builder=nullptr; 23 | } 24 | 25 | dpBuilder* dpContext::getBuilder() { return m_builder; } 26 | dpPatcher* dpContext::getPatcher() { return m_patcher; } 27 | dpLoader* dpContext::getLoader() { return m_loader; } 28 | 29 | size_t dpContext::load(const char *path) 30 | { 31 | size_t ret = 0; 32 | dpGlob(path, [&](const std::string &p){ 33 | if(m_loader->load(p.c_str())) { ++ret; } 34 | }); 35 | return ret; 36 | } 37 | 38 | size_t dpContext::patchByFile(const char *filename, const char *filter_regex) 39 | { 40 | if(dpBinary *bin=m_loader->findBinary(filename)) { 41 | std::regex reg(filter_regex); 42 | m_patcher->patchByBinary(bin, 43 | [&](const dpSymbolS &sym){ 44 | return std::regex_search(sym.name, reg); 45 | }); 46 | return true; 47 | } 48 | return false; 49 | } 50 | 51 | size_t dpContext::patchByFile(const char *filename, const std::function &condition) 52 | { 53 | if(dpBinary *bin=m_loader->findBinary(filename)) { 54 | m_patcher->patchByBinary(bin, condition); 55 | return true; 56 | } 57 | return false; 58 | } 59 | 60 | bool dpContext::patchNameToName(const char *target_name, const char *hook_name) 61 | { 62 | dpSymbol *target = m_loader->findHostSymbolByName(target_name); 63 | dpSymbol *hook = m_loader->findSymbolByName(hook_name); 64 | if(target && hook) { 65 | return m_patcher->patch(target, hook)!=nullptr; 66 | } 67 | return false; 68 | } 69 | 70 | bool dpContext::patchAddressToName(const char *target_name, void *hook_addr) 71 | { 72 | dpSymbol *target = m_loader->findHostSymbolByName(target_name); 73 | dpSymbol *hook = m_loader->findSymbolByAddress(hook_addr); 74 | if(target && hook) { 75 | return m_patcher->patch(target, hook)!=nullptr; 76 | } 77 | return false; 78 | } 79 | 80 | bool dpContext::patchAddressToAddress(void *target_addr, void *hook_addr) 81 | { 82 | dpSymbol *target = m_loader->findHostSymbolByAddress(target_addr); 83 | dpSymbol *hook = m_loader->findSymbolByAddress(hook_addr); 84 | if(target && hook) { 85 | return m_patcher->patch(target, hook)!=nullptr; 86 | } 87 | return false; 88 | } 89 | 90 | bool dpContext::patchByAddress(void *hook_addr) 91 | { 92 | if(dpSymbol *hook=m_loader->findSymbolByAddress(hook_addr)) { 93 | if(dpSymbol *target=m_loader->findHostSymbolByName(hook->name)) { 94 | return m_patcher->patch(target, hook)!=nullptr; 95 | } 96 | } 97 | return false; 98 | } 99 | 100 | bool dpContext::unpatchByAddress(void *target_or_hook_addr) 101 | { 102 | return m_patcher->unpatchByAddress(target_or_hook_addr); 103 | } 104 | 105 | void dpContext::unpatchAll() 106 | { 107 | return m_patcher->unpatchAll(); 108 | } 109 | 110 | void* dpContext::getUnpatched(void *target) 111 | { 112 | #ifdef dpWithTDisasm 113 | if(dpPatchData *pd = m_patcher->findPatchByAddress(target)) { 114 | return pd->unpatched; 115 | } 116 | #endif // dpWithTDisasm 117 | return nullptr; 118 | } 119 | 120 | void dpContext::addForceHostSymbolPattern(const char *pattern) 121 | { 122 | m_loader->addForceHostSymbolPattern(pattern); 123 | } 124 | -------------------------------------------------------------------------------- /dpPatcher.cpp: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicPatcher 4 | 5 | #include "DynamicPatcher.h" 6 | #include "dpInternal.h" 7 | #include 8 | #ifdef dpWithTDisasm 9 | #include "disasm-lib/disasm.h" 10 | #endif // dpWithTDisasm 11 | 12 | static size_t dpCopyInstructions(void *dst, void *src, size_t minlen) 13 | { 14 | #ifdef dpWithTDisasm 15 | 16 | size_t len = 0; 17 | #ifdef _M_X64 18 | ARCHITECTURE_TYPE arch = ARCH_X64; 19 | #elif defined _M_IX86 20 | ARCHITECTURE_TYPE arch = ARCH_X86; 21 | #endif 22 | DISASSEMBLER dis; 23 | if(InitDisassembler(&dis, arch)) { 24 | INSTRUCTION* pins = NULL; 25 | U8* pLoc = (U8*)src; 26 | U8* pDst = (U8*)dst; 27 | DWORD dwFlags = DISASM_SUPPRESSERRORS; 28 | 29 | while( lenType == ITYPE_RET ) { break; } 33 | 34 | //// todo: call or jmp 35 | //if(pins->Type == ITYPE_BRANCH ) break; 36 | //if(pins->Type == ITYPE_BRANCHCC) break; 37 | //if(pins->Type == ITYPE_CALL ) break; 38 | //if(pins->Type == ITYPE_CALLCC ) break; 39 | 40 | switch(pLoc[0]) { 41 | // call & jmp 42 | case 0xE8: 43 | case 0xE9: 44 | { 45 | int rva = *(int*)(pLoc+1); 46 | pDst[0] = pLoc[0]; 47 | *(DWORD*)(pDst+1) = (DWORD)((ptrdiff_t)(pLoc+rva)-(ptrdiff_t)(pDst)); 48 | } 49 | break; 50 | default: 51 | memcpy(pDst, pLoc, pins->Length); 52 | break; 53 | } 54 | 55 | len += pins->Length; 56 | pLoc += pins->Length; 57 | pDst += pins->Length; 58 | } 59 | 60 | CloseDisassembler(&dis); 61 | } 62 | return len; 63 | 64 | #else // dpWithTDisasm 65 | 66 | memcpy(dst, src, minlen); 67 | return minlen; 68 | 69 | #endif // dpWithTDisasm 70 | } 71 | 72 | static BYTE* dpAddJumpInstruction(BYTE* from, BYTE* to) 73 | { 74 | // 距離が 32bit に収まる範囲であれば、0xe9 RVA 75 | // そうでない場合、0xff 0x25 [メモリアドレス] + 対象アドレス 76 | // の形式で jmp する必要がある。 77 | BYTE* jump_from = from + 5; 78 | size_t distance = jump_from > to ? jump_from - to : to - jump_from; 79 | if (distance <= 0x7fff0000) { 80 | from[0] = 0xe9; 81 | from += 1; 82 | *((DWORD*)from) = (DWORD)(to - jump_from); 83 | from += 4; 84 | } 85 | else { 86 | from[0] = 0xff; 87 | from[1] = 0x25; 88 | from += 2; 89 | #ifdef _M_IX86 90 | *((DWORD*)from) = (DWORD)(from + 4); 91 | #elif defined(_M_X64) 92 | *((DWORD*)from) = (DWORD)0; 93 | #endif 94 | from += 4; 95 | *((DWORD_PTR*)from) = (DWORD_PTR)(to); 96 | from += 8; 97 | } 98 | return from; 99 | } 100 | 101 | void dpPatcher::patchImpl(dpPatchData &pi) 102 | { 103 | // 元コードの退避先 104 | BYTE *hook = (BYTE*)pi.hook->address; 105 | BYTE *target = (BYTE*)pi.target->address; 106 | BYTE *unpatched = (BYTE*)m_talloc.allocate(target); 107 | DWORD old; 108 | ::VirtualProtect(target, 32, PAGE_EXECUTE_READWRITE, &old); 109 | HANDLE proc = ::GetCurrentProcess(); 110 | 111 | // 元のコードをコピー & 最後にコピー本へ jmp するコードを付加 (==これを call すれば上書き前の動作をするハズ) 112 | size_t stab_size = dpCopyInstructions(unpatched, target, 5); 113 | dpAddJumpInstruction(unpatched+stab_size, target+stab_size); 114 | 115 | // 距離が 32bit に収まらない場合、長距離 jmp で飛ぶコードを挟む。 116 | // (長距離 jmp は 14byte 必要なので直接書き込もうとすると容量が足りない可能性が出てくる) 117 | DWORD_PTR dwDistance = hook < target ? target - hook : hook - target; 118 | if(dwDistance > 0x7fff0000) { 119 | BYTE *trampoline = (BYTE*)m_talloc.allocate(target); 120 | dpAddJumpInstruction(trampoline, hook); 121 | dpAddJumpInstruction(target, trampoline); 122 | ::FlushInstructionCache(proc, trampoline, 32); 123 | ::FlushInstructionCache(proc, target, 32); 124 | pi.trampoline = trampoline; 125 | } 126 | else { 127 | dpAddJumpInstruction(target, hook); 128 | ::FlushInstructionCache(proc, target, 32); 129 | } 130 | ::VirtualProtect(target, 32, old, &old); 131 | 132 | pi.unpatched = unpatched; 133 | pi.unpatched_size = stab_size; 134 | 135 | if((dpGetConfig().log_flags&dpE_LogDetail)!=0) { // たぶん demangle はそこそこでかい処理なので early out 136 | char demangled[512]; 137 | dpDemangle(pi.target->name, demangled, sizeof(demangled)); 138 | dpPrintDetail("patch 0x%p -> 0x%p (\"%s\" : \"%s\")\n", pi.target->address, pi.hook->address, demangled, pi.target->name); 139 | } 140 | } 141 | 142 | void dpPatcher::unpatchImpl(const dpPatchData &pi) 143 | { 144 | DWORD old; 145 | ::VirtualProtect(pi.target->address, 32, PAGE_EXECUTE_READWRITE, &old); 146 | dpCopyInstructions(pi.target->address, pi.unpatched, pi.unpatched_size); 147 | ::VirtualProtect(pi.target->address, 32, old, &old); 148 | m_talloc.deallocate(pi.unpatched); 149 | m_talloc.deallocate(pi.trampoline); 150 | 151 | if((dpGetConfig().log_flags&dpE_LogDetail)!=0) { 152 | char demangled[512]; 153 | dpDemangle(pi.target->name, demangled, sizeof(demangled)); 154 | dpPrintDetail("unpatch 0x%p (\"%s\" : \"%s\")\n", pi.target->address, demangled, pi.target->name); 155 | } 156 | } 157 | 158 | 159 | dpPatcher::dpPatcher(dpContext *ctx) 160 | : m_context(ctx) 161 | { 162 | } 163 | 164 | dpPatcher::~dpPatcher() 165 | { 166 | unpatchAll(); 167 | } 168 | 169 | void* dpPatcher::patchByBinary(dpBinary *obj, const std::function &condition) 170 | { 171 | obj->eachSymbols([&](dpSymbol *sym){ 172 | if(dpIsFunction(sym->flags) && condition(sym->simplify())) { 173 | sym->partialLink(); 174 | patch(dpGetLoader()->findHostSymbolByName(sym->name), sym); 175 | } 176 | }); 177 | return nullptr; 178 | } 179 | 180 | void* dpPatcher::patch(dpSymbol *target, dpSymbol *hook) 181 | { 182 | if(!target || !hook) { return nullptr; } 183 | if(dpIsLinkFailed(target->flags) || dpIsLinkFailed(hook->flags)) { return nullptr; } 184 | if(dpGetLoader()->doesForceHostSymbol(target->name)) { return nullptr; } 185 | 186 | unpatchByAddress(target->address); 187 | 188 | dpPatchData pd; 189 | pd.target = target; 190 | pd.hook = hook; 191 | patchImpl(pd); 192 | m_patches.insert(pd); 193 | return pd.unpatched; 194 | } 195 | 196 | 197 | size_t dpPatcher::unpatchByBinary(dpBinary *obj) 198 | { 199 | size_t n = 0; 200 | obj->eachSymbols([&](dpSymbol *sym){ 201 | if(dpIsFunction(sym->flags) && unpatchByAddress(sym->address)) { 202 | ++n; 203 | } 204 | }); 205 | return n; 206 | } 207 | 208 | bool dpPatcher::unpatchByAddress(void *addr) 209 | { 210 | auto p = findPatchByAddressImpl(addr); 211 | if(p!=m_patches.end()) { 212 | unpatchImpl(*p); 213 | m_patches.erase(p); 214 | return true; 215 | } 216 | return false; 217 | } 218 | 219 | void dpPatcher::unpatchAll() 220 | { 221 | dpEach(m_patches, [&](const dpPatchData &p){ 222 | unpatchImpl(p); 223 | }); 224 | m_patches.clear(); 225 | } 226 | 227 | dpPatchData* dpPatcher::findPatchByName(const char *name) 228 | { 229 | auto p = findPatchByNameImpl(name); 230 | return p==m_patches.end() ? nullptr : const_cast(&*p); 231 | } 232 | 233 | dpPatchData* dpPatcher::findPatchByAddress(void *addr) 234 | { 235 | auto p = findPatchByAddressImpl(addr); 236 | return p==m_patches.end() ? nullptr : const_cast(&*p); 237 | } 238 | 239 | dpPatcher::patch_cont::iterator dpPatcher::findPatchByNameImpl(const char *name) 240 | { 241 | return dpFind(m_patches, [=](const dpPatchData &pat){ 242 | return strcmp(pat.target->name, name)==0; 243 | }); 244 | } 245 | 246 | dpPatcher::patch_cont::iterator dpPatcher::findPatchByAddressImpl(void *addr) 247 | { 248 | return dpFind(m_patches, [=](const dpPatchData &pat){ 249 | return pat.target->address==addr || pat.hook->address==addr; 250 | }); 251 | } 252 | -------------------------------------------------------------------------------- /dpVS2012/dpVS/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // 5 | // アセンブリに関する一般情報は以下の属性セットをとおして制御されます。 6 | // アセンブリに関連付けられている情報を変更するには、 7 | // これらの属性値を変更してください。 8 | // 9 | [assembly: AssemblyTitle("")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("")] 14 | [assembly: AssemblyCopyright("")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // 19 | // アセンブリのバージョン情報は、以下の 4 つの値で構成されています: 20 | // 21 | // Major Version 22 | // Minor Version 23 | // Revision 24 | // Build Number 25 | // 26 | // すべての値を指定するか、下のように '*' を使ってリビジョンおよびビルド番号を 27 | // 既定値にすることができます: 28 | 29 | [assembly: AssemblyVersion("1.0.*")] 30 | 31 | // 32 | // アセンブリに署名するには、使用するキーを指定しなければなりません。アセンブリ署名に関する 33 | // 詳細については、Microsoft .NET Framework ドキュメントを参照してください。 34 | // 35 | // 下の属性を使用して、署名に使用されるキーを制御します。 36 | // 37 | // メモ: 38 | // (*) キーが指定されないと、アセンブリは署名されません。 39 | // (*) KeyName は、コンピューターにインストールされている暗号サービス プロバイダー (CSP) を 40 | // 表します。 41 | // (*) キー ファイルおよびキー名の属性が共に指定されている場合は、 42 | // 以下の処理が行われます: 43 | // (1) KeyName が CSP に見つかった場合、そのキーが使われます。 44 | // (2) KeyName が存在せず、KeyFile が存在する場合、 45 | // ファイルにあるキーが CSP にインストールされ、使われます。 46 | // (*) 遅延署名は高度なオプションです - Microsoft .NET Framework 47 | // ドキュメントを参照してください。 48 | // 49 | [assembly: AssemblyDelaySign(false)] 50 | [assembly: AssemblyKeyFile("")] 51 | [assembly: AssemblyKeyName("")] 52 | -------------------------------------------------------------------------------- /dpVS2012/dpVS/Connect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Extensibility; 3 | using EnvDTE; 4 | using EnvDTE80; 5 | using Microsoft.VisualStudio.CommandBars; 6 | using System.Resources; 7 | using System.Reflection; 8 | using System.Globalization; 9 | 10 | using System.Runtime.InteropServices; 11 | using Microsoft.VisualStudio; 12 | using Microsoft.VisualStudio.VCProjectEngine; 13 | using Microsoft.VisualStudio.Shell; 14 | using Microsoft.VisualStudio.Shell.Interop; 15 | using Microsoft.VisualStudio.Debugger.Interop; 16 | 17 | 18 | namespace dpVS 19 | { 20 | /// アドインを実装するためのオブジェクトです。 21 | /// 22 | public class Connect : IDTExtensibility2, IDTCommandTarget 23 | { 24 | /// アドイン オブジェクトのコンストラクターを実装します。初期化コードをこのメソッド内に配置してください。 25 | public Connect() 26 | { 27 | } 28 | 29 | /// IDTExtensibility2 インターフェイスの OnConnection メソッドを実装します。アドインが読み込まれる際に通知を受けます。 30 | /// ホスト アプリケーションのルート オブジェクトです。 31 | /// アドインの読み込み状態を説明します。 32 | /// このアドインを表すオブジェクトです。 33 | /// 34 | public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom) 35 | { 36 | _applicationObject = (DTE2)application; 37 | _addInInstance = (AddIn)addInInst; 38 | if(connectMode == ext_ConnectMode.ext_cm_UISetup) 39 | { 40 | object []contextGUIDS = new object[] { }; 41 | Commands2 commands = (Commands2)_applicationObject.Commands; 42 | string toolsMenuName = "Tools"; 43 | 44 | //コマンドを [ツール] メニューに配置します。 45 | //メイン メニュー項目のすべてを保持するトップレベル コマンド バーである、MenuBar コマンド バーを検索します: 46 | Microsoft.VisualStudio.CommandBars.CommandBar menuBarCommandBar = ((Microsoft.VisualStudio.CommandBars.CommandBars)_applicationObject.CommandBars)["MenuBar"]; 47 | 48 | //MenuBar コマンド バーで [ツール] コマンド バーを検索します: 49 | CommandBarControl toolsControl = menuBarCommandBar.Controls[toolsMenuName]; 50 | CommandBarPopup toolsPopup = (CommandBarPopup)toolsControl; 51 | 52 | //アドインによって処理する複数のコマンドを追加する場合、この try ブロックおよび catch ブロックを重複できます。 53 | // ただし、新しいコマンド名を含めるために QueryStatus メソッドおよび Exec メソッドの更新も実行してください。 54 | try 55 | { 56 | //コマンド コレクションにコマンドを追加します: 57 | Command command = commands.AddNamedCommand2(_addInInstance, "dpVS", "dpVS", "Executes the command for dpVS", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported+(int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton); 58 | 59 | //コマンドのコントロールを [ツール] メニューに追加します: 60 | if((command != null) && (toolsPopup != null)) 61 | { 62 | command.AddControl(toolsPopup.CommandBar, 1); 63 | } 64 | } 65 | catch(System.ArgumentException) 66 | { 67 | //同じ名前のコマンドが既に存在しているため、例外が発生した可能性があります。 68 | // その場合、コマンドを再作成する必要はありません。 例外を 69 | // 無視しても安全です。 70 | } 71 | } 72 | } 73 | 74 | /// IDTExtensibility2 インターフェイスの OnDisconnection メソッドを実装します。アドインがアンロードされる際に通知を受けます。 75 | /// アドインのアンロード状態を説明します。 76 | /// ホスト アプリケーション固有のパラメーターの配列です。 77 | /// 78 | public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom) 79 | { 80 | } 81 | 82 | /// IDTExtensibility2 インターフェイスの OnAddInsUpdate メソッドを実装します。アドインのコレクションが変更されたときに通知を受けます。 83 | /// ホスト アプリケーション固有のパラメーターの配列です。 84 | /// 85 | public void OnAddInsUpdate(ref Array custom) 86 | { 87 | } 88 | 89 | /// IDTExtensibility2 インターフェイスの OnStartupComplete メソッドを実装します。ホスト アプリケーションが読み込みを終了したときに通知を受けます。 90 | /// ホスト アプリケーション固有のパラメーターの配列です。 91 | /// 92 | public void OnStartupComplete(ref Array custom) 93 | { 94 | } 95 | 96 | /// IDTExtensibility2 インターフェイスの OnBeginShutdown メソッドを実装します。ホスト アプリケーションがアンロードされる際に通知を受けます。 97 | /// ホスト アプリケーション固有のパラメーターの配列です。 98 | /// 99 | public void OnBeginShutdown(ref Array custom) 100 | { 101 | } 102 | 103 | /// IDTCommandTarget インターフェイスの QueryStatus メソッドを実装します。これは、コマンドの可用性が更新されたときに呼び出されます。 104 | /// 状態を決定するためのコマンド名です。 105 | /// コマンドに必要なテキストです。 106 | /// ユーザー インターフェイス内のコマンドの状態です。 107 | /// neededText パラメーターから要求されたテキストです。 108 | /// 109 | public void QueryStatus(string commandName, vsCommandStatusTextWanted neededText, ref vsCommandStatus status, ref object commandText) 110 | { 111 | if(neededText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone) 112 | { 113 | if(commandName == "dpVS.Connect.dpVS") 114 | { 115 | status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported|vsCommandStatus.vsCommandStatusEnabled; 116 | return; 117 | } 118 | } 119 | } 120 | 121 | /// IDTCommandTarget インターフェイスの Exec メソッドを実装します。これは、コマンドが実行されるときに呼び出されます。 122 | /// 実行するコマンド名です。 123 | /// コマンドの実行方法を説明します。 124 | /// 呼び出し元からコマンド ハンドラーへ渡されたパラメーターです。 125 | /// コマンド ハンドラーから呼び出し元へ渡されたパラメーターです。 126 | /// コマンドが処理されたかどうかを呼び出し元に通知します。 127 | /// 128 | public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled) 129 | { 130 | handled = false; 131 | if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault) 132 | { 133 | if(commandName == "dpVS.Connect.dpVS") 134 | { 135 | handled = true; 136 | LaunchAndDoInject(); 137 | return; 138 | } 139 | } 140 | } 141 | 142 | public bool LaunchAndDoInject() 143 | { 144 | IVsOutputWindowPane output = (IVsOutputWindowPane)Package.GetGlobalService(typeof(SVsGeneralOutputWindowPane)); 145 | 146 | String exepath = ""; 147 | String workdir = ""; 148 | String environment = ""; 149 | String addindir = ""; 150 | Solution sln = _applicationObject.Solution; 151 | String startup = (String)((Array)sln.SolutionBuild.StartupProjects).GetValue(0); 152 | foreach (EnvDTE.Project project in sln.Projects) 153 | { 154 | if (project.UniqueName == startup) 155 | { 156 | VCProject vcproj = (VCProject)project.Object; 157 | if (vcproj == null) 158 | { 159 | // this is not a visual c++ project 160 | continue; 161 | } 162 | IVCCollection cfgs = vcproj.Configurations; 163 | VCConfiguration cfg = cfgs.Item(1); 164 | exepath = cfg.Evaluate("$(LocalDebuggerCommand)"); 165 | workdir = cfg.Evaluate("$(LocalDebuggerWorkingDirectory)"); 166 | environment = cfg.Evaluate("$(LocalDebuggerEnvironment)"); 167 | addindir = cfg.Evaluate("$(USERPROFILE)\\Documents\\Visual Studio 2012\\Addins"); 168 | output.OutputString(exepath); 169 | } 170 | } 171 | 172 | uint pid = dpVSHelper.ExecuteSuspended(exepath, addindir, environment); 173 | if (pid != 0) 174 | { 175 | VsDebugTargetProcessInfo[] res = new VsDebugTargetProcessInfo[1]; 176 | VsDebugTargetInfo4[] info = new VsDebugTargetInfo4[1]; 177 | info[0].bstrExe = exepath; 178 | info[0].dlo = (uint)DEBUG_LAUNCH_OPERATION.DLO_AlreadyRunning; 179 | //info[0].dlo = (uint)_DEBUG_LAUNCH_OPERATION4.DLO_AttachToSuspendedLaunchProcess; // somehow this makes debugger not work 180 | info[0].dwProcessId = pid; 181 | info[0].LaunchFlags = (uint)__VSDBGLAUNCHFLAGS.DBGLAUNCH_StopDebuggingOnEnd | (uint)__VSDBGLAUNCHFLAGS.DBGLAUNCH_DetachOnStop; 182 | 183 | Guid guidDbgEngine = VSConstants.DebugEnginesGuids.ManagedAndNative_guid; 184 | IntPtr pGuids = Marshal.AllocCoTaskMem(Marshal.SizeOf(guidDbgEngine)); 185 | Marshal.StructureToPtr(guidDbgEngine, pGuids, false); 186 | info[0].pDebugEngines = pGuids; 187 | info[0].dwDebugEngineCount = 1; 188 | 189 | IVsDebugger4 idbg = (IVsDebugger4)Package.GetGlobalService(typeof(SVsShellDebugger)); 190 | idbg.LaunchDebugTargets4(1, info, res); 191 | 192 | dpVSHelper.Resume(pid); 193 | } 194 | 195 | return true; 196 | } 197 | 198 | 199 | private DTE2 _applicationObject; 200 | private AddIn _addInInstance; 201 | } 202 | } -------------------------------------------------------------------------------- /dpVS2012/dpVS/dpVS - For Testing.AddIn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-saint/DynamicPatcher/683057ddabe61a638124c11c993f8ae381930b18/dpVS2012/dpVS/dpVS - For Testing.AddIn -------------------------------------------------------------------------------- /dpVS2012/dpVS/dpVS.AddIn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-saint/DynamicPatcher/683057ddabe61a638124c11c993f8ae381930b18/dpVS2012/dpVS/dpVS.AddIn -------------------------------------------------------------------------------- /dpVS2012/dpVS/dpVS.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30424 7 | 2.0 8 | {54C786E5-FD14-4036-92AE-E9F25B71534B} 9 | Library 10 | 11 | 12 | false 13 | dpVS 14 | .\bin\ 15 | v4.5 16 | 17 | 18 | 19 | true 20 | false 21 | .\bin\Debug\ 22 | false 23 | DEBUG;TRACE 24 | 4 25 | false 26 | false 27 | bpVS.xml 28 | 29 | 30 | false 31 | true 32 | .\bin\Release\ 33 | false 34 | TRACE 35 | 4 36 | false 37 | false 38 | bpVS.xml 39 | 40 | 41 | dpVS 42 | 43 | 44 | 45 | False 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | True 55 | 56 | 57 | True 58 | 59 | 60 | 61 | 62 | True 63 | 64 | 65 | True 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Code 76 | 77 | 78 | Code 79 | 80 | 81 | 82 | 83 | {80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2} 84 | 8 85 | 0 86 | 0 87 | primary 88 | False 89 | False 90 | 91 | 92 | {26AD1324-4B7C-44BC-84F8-B86AED45729F} 93 | 10 94 | 0 95 | 0 96 | primary 97 | False 98 | False 99 | 100 | 101 | {1A31287A-4D7D-413E-8E32-3B374931BD89} 102 | 8 103 | 0 104 | 0 105 | primary 106 | False 107 | False 108 | 109 | 110 | {2CE2370E-D744-4936-A090-3FFFE667B0E1} 111 | 9 112 | 0 113 | 0 114 | primary 115 | False 116 | False 117 | 118 | 119 | {1CBA492E-7263-47BB-87FE-639000619B15} 120 | 8 121 | 0 122 | 0 123 | primary 124 | False 125 | False 126 | 127 | 128 | {00020430-0000-0000-C000-000000000046} 129 | 2 130 | 0 131 | 0 132 | primary 133 | False 134 | False 135 | 136 | 137 | 138 | 139 | 140 | bpVS - For Testing.AddIn 141 | 142 | 143 | 144 | 145 | {465dc4db-5219-4fef-a7ca-945bd2dd6639} 146 | dpVSHelper 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /dpVS2012/dpVSHelper/AssemblyInfo.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-saint/DynamicPatcher/683057ddabe61a638124c11c993f8ae381930b18/dpVS2012/dpVSHelper/AssemblyInfo.cpp -------------------------------------------------------------------------------- /dpVS2012/dpVSHelper/Stdafx.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-saint/DynamicPatcher/683057ddabe61a638124c11c993f8ae381930b18/dpVS2012/dpVSHelper/Stdafx.cpp -------------------------------------------------------------------------------- /dpVS2012/dpVSHelper/Stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-saint/DynamicPatcher/683057ddabe61a638124c11c993f8ae381930b18/dpVS2012/dpVSHelper/Stdafx.h -------------------------------------------------------------------------------- /dpVS2012/dpVSHelper/app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-saint/DynamicPatcher/683057ddabe61a638124c11c993f8ae381930b18/dpVS2012/dpVSHelper/app.ico -------------------------------------------------------------------------------- /dpVS2012/dpVSHelper/app.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-saint/DynamicPatcher/683057ddabe61a638124c11c993f8ae381930b18/dpVS2012/dpVSHelper/app.rc -------------------------------------------------------------------------------- /dpVS2012/dpVSHelper/dpVSHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "dpVSHelper.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #pragma comment(lib, "dbghelp.lib") 8 | #pragma comment(lib, "psapi.lib") 9 | 10 | #ifdef _M_IX64 11 | # define InjectorExecutable "DynamicPatcherInjector64.exe" 12 | #else // _M_IX64 13 | # define InjectorExecutable "DynamicPatcherInjector.exe" 14 | #endif // _M_IX64 15 | 16 | 17 | DWORD dpVSHelper::ExecuteSuspended( String^ _path_to_exe, String^ _addin_dir, String^ _environment ) 18 | { 19 | IntPtr path_to_exe = Marshal::StringToHGlobalAnsi(_path_to_exe); 20 | IntPtr addin_dir = Marshal::StringToHGlobalAnsi(_addin_dir); 21 | IntPtr environment = Marshal::StringToHGlobalAnsi(_environment); 22 | 23 | char injector[MAX_PATH]; 24 | sprintf(injector, "%s\\%s", (const char*)addin_dir.ToPointer(), InjectorExecutable); 25 | 26 | char command[4096]; 27 | sprintf(command, "\"%s\" \"%s\" /suspended", injector, (const char*)path_to_exe.ToPointer()); 28 | 29 | STARTUPINFOA si; 30 | PROCESS_INFORMATION pi; 31 | ::ZeroMemory(&si, sizeof(si)); 32 | ::ZeroMemory(&pi, sizeof(pi)); 33 | si.cb = sizeof(si); 34 | BOOL ret = ::CreateProcessA(nullptr, command, nullptr, nullptr, FALSE, 35 | NORMAL_PRIORITY_CLASS, nullptr, (const char*)addin_dir.ToPointer(), &si, &pi); 36 | if(ret) { 37 | DWORD ret; 38 | ::WaitForSingleObject(pi.hProcess, INFINITE); 39 | ::GetExitCodeProcess(pi.hProcess, &ret); 40 | return ret; 41 | } 42 | return 0; 43 | } 44 | 45 | // F: [](DWORD thread_id)->void 46 | template 47 | inline void EnumerateThreads(DWORD pid, const F &f) 48 | { 49 | HANDLE ss = ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 50 | if(ss!=INVALID_HANDLE_VALUE) { 51 | THREADENTRY32 te; 52 | te.dwSize = sizeof(te); 53 | if(::Thread32First(ss, &te)) { 54 | do { 55 | if(te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID)+sizeof(te.th32OwnerProcessID) && 56 | te.th32OwnerProcessID==pid) 57 | { 58 | f(te.th32ThreadID); 59 | } 60 | te.dwSize = sizeof(te); 61 | } while(::Thread32Next(ss, &te)); 62 | } 63 | ::CloseHandle(ss); 64 | } 65 | } 66 | 67 | bool dpVSHelper::Resume( DWORD pid ) 68 | { 69 | bool r = false; 70 | EnumerateThreads(pid, [&](DWORD thread_id){ 71 | if(HANDLE hthread = ::OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id)) { 72 | DWORD ret = ::ResumeThread(hthread); 73 | if(ret!=DWORD(-1)) { r=true; } 74 | ::CloseHandle(hthread); 75 | } 76 | }); 77 | return r; 78 | } 79 | -------------------------------------------------------------------------------- /dpVS2012/dpVSHelper/dpVSHelper.h: -------------------------------------------------------------------------------- 1 | // dpVSHelper.h 2 | 3 | #pragma once 4 | #include 5 | 6 | using namespace System; 7 | using namespace System::Runtime::InteropServices; 8 | 9 | public ref class dpVSHelper 10 | { 11 | public: 12 | static DWORD ExecuteSuspended(String^ path_to_exe, String^ work_dir, String^ environment); 13 | static bool Resume(DWORD pid); 14 | }; 15 | -------------------------------------------------------------------------------- /dpVS2012/dpVSHelper/dpVSHelper.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {465DC4DB-5219-4FEF-A7CA-945BD2DD6639} 15 | v4.5 16 | ManagedCProj 17 | dpVSHelper 18 | 19 | 20 | 21 | DynamicLibrary 22 | true 23 | v110 24 | true 25 | Unicode 26 | 27 | 28 | DynamicLibrary 29 | false 30 | v110 31 | true 32 | Unicode 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | true 46 | 47 | 48 | false 49 | 50 | 51 | 52 | Level3 53 | Disabled 54 | WIN32;_DEBUG;%(PreprocessorDefinitions) 55 | Use 56 | 57 | 58 | true 59 | 60 | 61 | 62 | 63 | 64 | Level3 65 | WIN32;NDEBUG;%(PreprocessorDefinitions) 66 | Use 67 | 68 | 69 | true 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | Create 88 | Create 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /dpVS2012/dpVSHelper/dpVSHelper.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | ヘッダー ファイル 20 | 21 | 22 | ヘッダー ファイル 23 | 24 | 25 | ヘッダー ファイル 26 | 27 | 28 | 29 | 30 | ソース ファイル 31 | 32 | 33 | ソース ファイル 34 | 35 | 36 | ソース ファイル 37 | 38 | 39 | 40 | 41 | リソース ファイル 42 | 43 | 44 | 45 | 46 | リソース ファイル 47 | 48 | 49 | -------------------------------------------------------------------------------- /dpVS2012/dpVSHelper/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by app.rc 4 | -------------------------------------------------------------------------------- /old/DynamicObjLoader.h: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicObjLoader 4 | 5 | // .obj ファイルを実行時にロード&リンクして実行可能にします。 6 | // 具体的な使い方はテストを参照。 7 | // DOL_StaticLink を define すると全て通常通り static link されるので、 8 | // 開発用ビルド構成でのみ .obj ロードを使う、という使い方が可能です。 9 | // 10 | // ロードされる .obj には以下のような制限があります。 11 | // 12 | // ・/GL (プログラム全体の最適化あり) でコンパイルされた .obj は読めない 13 | // リンク時関数 inline 展開実現のためにフォーマットが変わるらしいため 14 | // ・exe 本体のデバッグ情報 (.pdb) が必要 15 | // .obj から exe や dll の関数をリンクする際、文字列から関数のアドレスを取れないといけないため 16 | // ・exe 本体がリンクしていない外部 dll の関数や .lib の関数は呼べない 17 | // 超頑張って .lib を読めば対応できそうだが… 18 | // ・obj <-> exe 間で参照されるシンボルは、inline 展開や最適化で消えないように注意が必要 19 | // DOL_Fixate で対処可能。 20 | // ・virtual 関数を使う場合、RTTI を無効にしておく必要がある 21 | // RTTI の有無で vtable の内容が変わってしまうため。 22 | // .obj だけ RTTI 無効でコンパイルされていればよく、.exe は RTTI 有効でビルドされていても問題ない。 23 | // ・.obj から関数を引っ張ってくる際、mangling 後の関数名を指定する必要がある 24 | // とりあえず DOL_Export をつければ解決できる。(C linkage にする対応方法。これだと名前の頭に "_" をつけるだけで済む) 25 | // ・.obj 側のコードはデバッガでは逆アセンブルモードでしか追えない 26 | // デバッグ情報はロードしていないため。これは解決困難で諦めモード。 27 | // ・.obj 内の global オブジェクトのコンストラクタ/デストラクタは呼ばれない 28 | // デストラクタは atexit() に登録されるため、.obj リロードで終了時クラッシュを招く。なので意図的に対応していない。 29 | // DOL_OnLoad / DOL_OnUnload で代替する想定。 30 | 31 | #ifndef DynamicObjLoader_h 32 | #define DynamicObjLoader_h 33 | 34 | #include 35 | 36 | //// 全部 static link するオプション。Master ビルド用。 37 | //#define DOL_StaticLink 38 | 39 | // 一応非 Windows でもビルドエラーにはならないようにしておく 40 | #if !defined(_WIN32) && !defined(DOL_StaticLink) 41 | # define DOL_StaticLink 42 | #endif 43 | 44 | 45 | #ifndef DOL_StaticLink 46 | 47 | #ifdef _WIN64 48 | # define DOL_Symbol_Prefix 49 | #else // _WIN64 50 | # define DOL_Symbol_Prefix "_" 51 | #endif // _WIN64 52 | 53 | #if defined(_CPPRTTI) && !defined(DOL_DisableWarning_RTTI) 54 | # pragma message("DOL warning: RTTI が有効なため .obj 側の virtual 関数を正常に呼べません。この警告を無効にするには DOL_DisableWarning_RTTI を define します。\n") 55 | #endif // _CPPRTTI 56 | 57 | 58 | // obj 側で使います。親 process から参照されるシンボルにつけます。(mangling 問題解決のため) 59 | #define DOL_Export extern "C" 60 | 61 | // obj, exe 両方で使います。 62 | // obj から exe の関数などを参照する場合、それが inline 展開や最適化で消えてたりするとクラッシュします。 63 | // 以下のマクロをつけておくと消えるのが抑止され、安全になります。 64 | // また、obj で実装する class にもつけないと必要なシンボルが欠けることがあるようです。(詳細不詳。デストラクタ ("vector deleting destructor") で現象を確認) 65 | #define DOL_Fixate __declspec(dllexport) 66 | 67 | // obj 側で使います。 68 | // 動的にロードされる .obj だと明示します。DOL_Load() でディレクトリ指定した場合、これが定義されている .obj モジュールをディレクトリから探してロードします。 69 | #define DOL_Module DOL_Export __declspec(selectany) int DOL_ModuleMarker=0; 70 | 71 | // obj 側で使います。引数には処理内容を書きます。このブロックはロード時に自動的に実行されます。 72 | // DOL_OnUnload() と併せて、serialize/deserialize などに用います。 73 | #define DOL_OnLoad(...) DOL_Export static void DOL_OnLoadHandler() { __VA_ARGS__ }; __declspec(selectany) void *_DOL_OnLoadHandler=DOL_OnLoadHandler; 74 | 75 | // obj 側で使います。引数には処理内容を書きます。このブロックはアンロード時に自動的に実行されます。 76 | #define DOL_OnUnload(...) DOL_Export static void DOL_OnUnloadHandler() { __VA_ARGS__ }; __declspec(selectany) void *_DOL_OnUnloadHandler=DOL_OnUnloadHandler; 77 | 78 | // exe 側で使います。obj から import する関数/メンバ関数/変数を宣言します。 79 | // obj から import してくるものは exe 側では実際にはポインタなので、複数 cpp に定義があるとリンクエラーになってしまいます。 80 | // 定義 (DOL_ImportFunction/Variable) は一箇所だけにして、他は宣言を見るだけにする必要があります。 81 | // DOL_DeclareMemberFunction は class 宣言の中に書きます。 82 | #define DOL_DeclareFunction(ret, name, arg) extern ret (*name)arg 83 | #define DOL_DeclareVariable(type, name) extern DOL_Variable name 84 | #define DOL_DeclareMemberFunction(Ret, Name, Args)\ 85 | Ret Name##Impl Args;\ 86 | Ret Name Args; 87 | 88 | // obj 側で使います。メンバ関数を定義します。 89 | #define DOL_DefineMemberFunction(Ret, Class, Name, Args)\ 90 | DOL_Export Ret (Class::*g_##Class##_##Name)Args = &Class::Name##Impl;\ 91 | Ret Class::Name##Impl Args 92 | 93 | // exe 側で使います。.obj から import する関数/変数を定義します。 94 | // 変数は実際には void* を cast operator をかまして返すオブジェクトなので若干注意が必要です。 95 | // 例えば int の変数を printf で出力する場合、明示的に int に cast しないと意図した結果になりません。 96 | #define DOL_ImportFunction(ret, name, arg) ret (*name)arg=NULL; DOL_FunctionLink g_dol_link_##name##(name, DOL_Symbol_Prefix #name) 97 | #define DOL_ImportVariable(type, name) DOL_Variable name; DOL_VariableLink g_dol_link_##name##(name, DOL_Symbol_Prefix #name) 98 | #define DOL_ImportMemberFunction(Ret, Class, Name, Args, ArgNames)\ 99 | DOL_ImportVariable(Ret (Class::*)Args, g_##Class##_##Name);\ 100 | Ret Class::Name Args { return (this->*g_##Class##_##Name)ArgNames; } 101 | 102 | 103 | 104 | 105 | // 以下 exe 側で使う API 106 | 107 | // .obj をロードします。 108 | // path はファイル (.obj) でもディレクトリでもよく、ディレクトリの場合 .obj を探してロードします (サブディレクトリ含む)。 109 | // ディレクトリ指定の場合、DOL_Module が定義されている .obj しか読み込みませんが、ファイル指定の場合そうでなくても読み込みます。 110 | // ロードが終わった後は DOL_Link() でリンクする必要があります。 111 | void DOL_Load(const char *path); 112 | 113 | // リンクを行います。 必要なものを全てロードした後に 1 度これを呼ぶ必要があります。 114 | // .obj に DOL_OnLoad() のブロックがある場合、このタイミングで呼ばれます。 115 | void DOL_Link(); 116 | 117 | // 更新された .obj があればそれをリロードし、再リンクします。 118 | // .cpp の再コンパイルは別のスレッドで自動的に行われますが、.obj のリロードは勝手にやると問題が起きるので、 119 | // これを呼んでユーザー側で適切なタイミングで行う必要があります。 120 | // 再コンパイルが行われていなかった場合なにもしないので、毎フレーム呼んでも大丈夫です。 121 | void DOL_Update(); 122 | 123 | // .obj をアンロードします。 124 | // 対象 .obj に DOL_OnUnload() のブロックがある場合、このタイミングで呼ばれます。 125 | void DOL_Unload(const char *path); 126 | // 全 .obj をアンロードします。 127 | void DOL_UnloadAll(); 128 | 129 | // 自動ビルド (.cpp の変更を検出したら自動的にビルド開始) を開始します。 130 | void DOL_StartAutoRecompile(const char *build_options, bool create_console_window); 131 | // 自動ビルド用の監視ディレクトリ。このディレクトリ以下のファイルの変更を検出したらビルドが始まります。 132 | void DOL_AddSourceDirectory(const char *path); 133 | 134 | 135 | void DOL_EvalSetCompileOption(const char *includes); 136 | void DOL_EvalSetGlobalContext(const char *source); 137 | 138 | __declspec(noinline) void* _DOL_GetEsp(); 139 | void _DOL_Eval(const char *file, int line, const char *function, void *esp, const char *source); 140 | #ifdef _WIN64 141 | # define DOL_Eval(src) _DOL_Eval(__FILE__, __LINE__, __FUNCTION__, _DOL_GetEsp(), src) 142 | #else // _WIN64 143 | # define DOL_Eval(src) _DOL_Eval(__FILE__, __LINE__, __FUNCTION__, _AddressOfReturnAddress(), src) 144 | #endif // _WIN64 145 | 146 | 147 | // 以下内部実装用 148 | 149 | template 150 | class DOL_Variable 151 | { 152 | public: 153 | DOL_Variable() : m_sym(NULL) {} 154 | DOL_Variable& operator=(const DOL_Variable &o) { (T&)(*this)=(T&)o; } 155 | void*& get() { return m_sym; } 156 | operator T&() const { return *reinterpret_cast(m_sym); } 157 | T* operator&() const { return reinterpret_cast(m_sym); } 158 | private: 159 | mutable void *m_sym; 160 | }; 161 | 162 | void DOL_LinkSymbol(const char *name, void *&target); 163 | 164 | class DOL_FunctionLink 165 | { 166 | public: 167 | template 168 | DOL_FunctionLink(FuncPtr &v, const char *name) { DOL_LinkSymbol(name, (void*&)v); } 169 | }; 170 | 171 | class DOL_VariableLink 172 | { 173 | public: 174 | template 175 | DOL_VariableLink(DOL_Variable &v, const char *name) { DOL_LinkSymbol(name, v.get()); } 176 | }; 177 | 178 | 179 | #else // DOL_StaticLink 180 | 181 | 182 | #define DOL_Export 183 | #define DOL_Fixate 184 | #define DOL_Module 185 | #define DOL_OnLoad(...) 186 | #define DOL_OnUnload(...) 187 | #define DOL_DeclareFunction(ret, name, arg) ret name arg 188 | #define DOL_DeclareVariable(type, name) extern type name 189 | #define DOL_DeclareMemberFunction(Ret, Name, Args) Ret Name Args 190 | #define DOL_DefineMemberFunction(Ret, Class, Name, Args) Ret Class::Name Args 191 | #define DOL_ImportFunction(ret, name, arg) ret name arg 192 | #define DOL_ImportVariable(type, name) extern type name 193 | #define DOL_ImportMemberFunction(Ret, Class, Name, Args, ArgNames) 194 | 195 | #define DOL_Load(path) 196 | #define DOL_Update() 197 | #define DOL_Unload(path) 198 | #define DOL_UnloadAll() 199 | #define DOL_Link() 200 | 201 | #define DOL_StartAutoRecompile(...) 202 | #define DOL_AddSourceDirectory(...) 203 | 204 | #define DOL_EvalSetGlobalContext(...) 205 | #define DOL_Eval(...) 206 | 207 | 208 | #endif // DOL_StaticLink 209 | 210 | #endif // DynamicObjLoader_h 211 | -------------------------------------------------------------------------------- /old/Test/Test.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test1", "Test1\Test1.vcxproj", "{7CCD61E5-5F56-4050-BACC-1467972D2247}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test2", "Test2\Test2.vcxproj", "{D29C6982-A589-4081-89B1-91E78D7C41E2}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test3", "Test3\Test3.vcxproj", "{2EB11313-236B-4F74-8F89-4B5F21BAF953}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Win32 = Debug|Win32 13 | Debug|x64 = Debug|x64 14 | Profile|Win32 = Profile|Win32 15 | Profile|x64 = Profile|x64 16 | Release|Win32 = Release|Win32 17 | Release|x64 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {7CCD61E5-5F56-4050-BACC-1467972D2247}.Debug|Win32.ActiveCfg = Debug|Win32 21 | {7CCD61E5-5F56-4050-BACC-1467972D2247}.Debug|Win32.Build.0 = Debug|Win32 22 | {7CCD61E5-5F56-4050-BACC-1467972D2247}.Debug|x64.ActiveCfg = Debug|x64 23 | {7CCD61E5-5F56-4050-BACC-1467972D2247}.Debug|x64.Build.0 = Debug|x64 24 | {7CCD61E5-5F56-4050-BACC-1467972D2247}.Profile|Win32.ActiveCfg = Release|x64 25 | {7CCD61E5-5F56-4050-BACC-1467972D2247}.Profile|x64.ActiveCfg = Release|x64 26 | {7CCD61E5-5F56-4050-BACC-1467972D2247}.Profile|x64.Build.0 = Release|x64 27 | {7CCD61E5-5F56-4050-BACC-1467972D2247}.Release|Win32.ActiveCfg = Release|Win32 28 | {7CCD61E5-5F56-4050-BACC-1467972D2247}.Release|Win32.Build.0 = Release|Win32 29 | {7CCD61E5-5F56-4050-BACC-1467972D2247}.Release|x64.ActiveCfg = Release|x64 30 | {7CCD61E5-5F56-4050-BACC-1467972D2247}.Release|x64.Build.0 = Release|x64 31 | {D29C6982-A589-4081-89B1-91E78D7C41E2}.Debug|Win32.ActiveCfg = Debug|Win32 32 | {D29C6982-A589-4081-89B1-91E78D7C41E2}.Debug|Win32.Build.0 = Debug|Win32 33 | {D29C6982-A589-4081-89B1-91E78D7C41E2}.Debug|x64.ActiveCfg = Debug|x64 34 | {D29C6982-A589-4081-89B1-91E78D7C41E2}.Debug|x64.Build.0 = Debug|x64 35 | {D29C6982-A589-4081-89B1-91E78D7C41E2}.Profile|Win32.ActiveCfg = Profile|Win32 36 | {D29C6982-A589-4081-89B1-91E78D7C41E2}.Profile|Win32.Build.0 = Profile|Win32 37 | {D29C6982-A589-4081-89B1-91E78D7C41E2}.Profile|x64.ActiveCfg = Profile|x64 38 | {D29C6982-A589-4081-89B1-91E78D7C41E2}.Profile|x64.Build.0 = Profile|x64 39 | {D29C6982-A589-4081-89B1-91E78D7C41E2}.Release|Win32.ActiveCfg = Release|Win32 40 | {D29C6982-A589-4081-89B1-91E78D7C41E2}.Release|Win32.Build.0 = Release|Win32 41 | {D29C6982-A589-4081-89B1-91E78D7C41E2}.Release|x64.ActiveCfg = Release|x64 42 | {D29C6982-A589-4081-89B1-91E78D7C41E2}.Release|x64.Build.0 = Release|x64 43 | {2EB11313-236B-4F74-8F89-4B5F21BAF953}.Debug|Win32.ActiveCfg = Debug|Win32 44 | {2EB11313-236B-4F74-8F89-4B5F21BAF953}.Debug|Win32.Build.0 = Debug|Win32 45 | {2EB11313-236B-4F74-8F89-4B5F21BAF953}.Debug|x64.ActiveCfg = Debug|x64 46 | {2EB11313-236B-4F74-8F89-4B5F21BAF953}.Debug|x64.Build.0 = Debug|x64 47 | {2EB11313-236B-4F74-8F89-4B5F21BAF953}.Profile|Win32.ActiveCfg = Release|x64 48 | {2EB11313-236B-4F74-8F89-4B5F21BAF953}.Profile|x64.ActiveCfg = Release|x64 49 | {2EB11313-236B-4F74-8F89-4B5F21BAF953}.Profile|x64.Build.0 = Release|x64 50 | {2EB11313-236B-4F74-8F89-4B5F21BAF953}.Release|Win32.ActiveCfg = Release|Win32 51 | {2EB11313-236B-4F74-8F89-4B5F21BAF953}.Release|Win32.Build.0 = Release|Win32 52 | {2EB11313-236B-4F74-8F89-4B5F21BAF953}.Release|x64.ActiveCfg = Release|x64 53 | {2EB11313-236B-4F74-8F89-4B5F21BAF953}.Release|x64.Build.0 = Release|x64 54 | EndGlobalSection 55 | GlobalSection(SolutionProperties) = preSolution 56 | HideSolutionNode = FALSE 57 | EndGlobalSection 58 | EndGlobal 59 | -------------------------------------------------------------------------------- /old/Test/Test1/Test1.cpp: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicObjLoader 4 | 5 | #include "stdafx.h" 6 | #include 7 | #include "DynamicObjLoader.h" 8 | #include "Test1.h" 9 | #pragma warning(disable: 4996) // _s じゃない CRT 関数使うとでるやつ 10 | 11 | 12 | #define istPrint(...) DebugPrint(__VA_ARGS__) 13 | 14 | template 15 | inline int istvsprintf(char (&buf)[N], const char *format, va_list vl) 16 | { 17 | return _vsnprintf(buf, N, format, vl); 18 | } 19 | 20 | static const int DPRINTF_MES_LENGTH = 4096; 21 | void DebugPrintV(const char* fmt, va_list vl) 22 | { 23 | char buf[DPRINTF_MES_LENGTH]; 24 | istvsprintf(buf, fmt, vl); 25 | ::OutputDebugStringA(buf); 26 | } 27 | 28 | void DebugPrint(const char* fmt, ...) 29 | { 30 | va_list vl; 31 | va_start(vl, fmt); 32 | DebugPrintV(fmt, vl); 33 | va_end(vl); 34 | } 35 | 36 | 37 | 38 | // .obj から呼ぶ関数。最適化で消えないように DOL_Fixate つけておく 39 | DOL_Fixate void FuncInExe() 40 | { 41 | istPrint("FuncInExe()\n"); 42 | } 43 | 44 | 45 | void Hoge::DoSomething() 46 | { 47 | istPrint("Hoge::DoSomething()\n"); 48 | } 49 | 50 | 51 | DOL_ImportMemberFunction(int, Hoge, MemFnTest, (int i), (i)); 52 | DOL_ImportFunction(float, FloatAdd, (float, float)); 53 | DOL_ImportFunction(void, CallExternalFunc, ()); 54 | DOL_ImportFunction(void, CallExeFunc, ()); 55 | DOL_ImportFunction(void, IHogeReceiver, (IHoge*)); 56 | DOL_ImportFunction(IHoge*, CreateObjHoge, ()); 57 | DOL_ImportVariable(int, g_test); 58 | 59 | int main(int argc, _TCHAR* argv[]) 60 | { 61 | DOL_AddSourceDirectory(".\\"); 62 | #ifdef _WIN64 63 | DOL_StartAutoRecompile("/m /p:Configuration=Release;Platform=x64", true); 64 | DOL_Load("x64\\Release"); 65 | #else // _WIN64 66 | DOL_StartAutoRecompile("/m /p:Configuration=Release;Platform=Win32", true); 67 | DOL_Load("Release"); 68 | #endif // _WIN64 69 | DOL_Link(); 70 | 71 | for(;;) { 72 | g_test += 10; 73 | istPrint("g_test: %d\n", (int)g_test); 74 | istPrint("%.2f\n", FloatAdd(1.0f, 2.0f)); 75 | CallExternalFunc(); 76 | CallExeFunc(); 77 | { 78 | Hoge hoge; 79 | IHogeReceiver(&hoge); 80 | istPrint("ret: %d\n", hoge.MemFnTest(2)); 81 | } 82 | { 83 | IHoge *hoge = CreateObjHoge(); 84 | hoge->DoSomething(); 85 | delete hoge; 86 | } 87 | 88 | ::Sleep(5000); 89 | DOL_Update(); 90 | } 91 | 92 | DOL_UnloadAll(); 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /old/Test/Test1/Test1.h: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicObjLoader 4 | 5 | #ifndef Test1_h 6 | #define Test1_h 7 | 8 | 9 | class DOL_Fixate IHoge 10 | { 11 | public: 12 | virtual ~IHoge() {} 13 | virtual void DoSomething()=0; 14 | }; 15 | 16 | class Hoge : public IHoge 17 | { 18 | public: 19 | virtual void DoSomething(); 20 | DOL_DeclareMemberFunction(int, MemFnTest, (int)); 21 | }; 22 | 23 | #endif // Test1_h 24 | -------------------------------------------------------------------------------- /old/Test/Test1/Test1.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {7CCD61E5-5F56-4050-BACC-1467972D2247} 23 | Win32Proj 24 | Test1 25 | 26 | 27 | 28 | Application 29 | true 30 | Unicode 31 | 32 | 33 | Application 34 | true 35 | Unicode 36 | 37 | 38 | Application 39 | false 40 | false 41 | Unicode 42 | 43 | 44 | Application 45 | false 46 | false 47 | Unicode 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | true 67 | ..\..;$(CG_INC_PATH);$(DXSDK_DIR)include;$(IncludePath) 68 | $(CG_LIB_PATH);$(DXSDK_DIR)lib\x86;$(LibraryPath) 69 | 70 | 71 | true 72 | ..\..;$(CG_INC_PATH);$(DXSDK_DIR)include;$(IncludePath) 73 | $(CG_LIB_PATH);$(DXSDK_DIR)lib\x86;$(LibraryPath) 74 | 75 | 76 | false 77 | ..\..;$(CG_INC_PATH);$(DXSDK_DIR)include;$(IncludePath) 78 | $(CG_LIB_PATH);$(DXSDK_DIR)lib\x86;$(LibraryPath) 79 | 80 | 81 | false 82 | ..\..;$(CG_INC_PATH);$(DXSDK_DIR)include;$(IncludePath) 83 | $(CG_LIB_PATH);$(DXSDK_DIR)lib\x86;$(LibraryPath) 84 | 85 | 86 | 87 | NotUsing 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | false 92 | 93 | 94 | Console 95 | true 96 | 97 | 98 | 99 | 100 | NotUsing 101 | Level3 102 | Disabled 103 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | false 105 | 106 | 107 | Console 108 | true 109 | 110 | 111 | 112 | 113 | Level3 114 | NotUsing 115 | MaxSpeed 116 | true 117 | true 118 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 119 | false 120 | false 121 | 122 | 123 | Console 124 | true 125 | true 126 | true 127 | 128 | 129 | 130 | 131 | Level3 132 | NotUsing 133 | MaxSpeed 134 | true 135 | true 136 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 137 | false 138 | false 139 | 140 | 141 | Console 142 | true 143 | true 144 | true 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | NotUsing 154 | NotUsing 155 | NotUsing 156 | NotUsing 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /old/Test/Test1/Test1.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Test1 6 | 7 | 8 | DynamicObjLoader 9 | 10 | 11 | 12 | 13 | Test1 14 | 15 | 16 | Test1 17 | 18 | 19 | DynamicObjLoader 20 | 21 | 22 | 23 | 24 | {cec1ea66-648c-473f-a8c5-0b4e4a7f6a64} 25 | 26 | 27 | {88b61b2c-e193-4f16-86dd-6cdb5d55644f} 28 | 29 | 30 | -------------------------------------------------------------------------------- /old/Test/Test1/Test1Obj.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | #include 4 | #include "DynamicObjLoader.h" 5 | #include "Test1.h" 6 | 7 | DOL_Module 8 | 9 | DOL_Export int g_test = 100; 10 | DOL_Export int g_test2 = 200; 11 | DOL_Export int g_test3 = 300; 12 | 13 | DOL_Export float FloatAdd(float a, float b) 14 | { 15 | return a+b; 16 | } 17 | 18 | DOL_Export void CallExternalFunc() 19 | { 20 | OutputDebugStringA("CallExternalFunc()\n"); 21 | } 22 | 23 | void FuncInExe(); 24 | DOL_Export void CallExeFunc() 25 | { 26 | return FuncInExe(); 27 | } 28 | 29 | 30 | class DOL_Fixate ObjHoge : public IHoge 31 | { 32 | public: 33 | ObjHoge() 34 | { 35 | OutputDebugStringA("ObjHoge::ObjHoge()\n"); 36 | } 37 | 38 | virtual ~ObjHoge() 39 | { 40 | OutputDebugStringA("ObjHoge::~ObjHoge()\n"); 41 | } 42 | 43 | virtual void DoSomething() 44 | { 45 | OutputDebugStringA("ObjHoge::DoSomething()\n"); 46 | } 47 | }; 48 | 49 | DOL_Export void IHogeReceiver(IHoge *hoge) 50 | { 51 | hoge->DoSomething(); 52 | } 53 | 54 | DOL_Export IHoge* CreateObjHoge() 55 | { 56 | return new ObjHoge(); 57 | } 58 | 59 | 60 | DOL_DefineMemberFunction(int, Hoge, MemFnTest, (int i)) 61 | { 62 | OutputDebugStringA("Hoge::MemFnTest()\n"); 63 | return i*2; 64 | } 65 | 66 | DOL_OnLoad( 67 | OutputDebugStringA("DOL_OnLoad Test\n"); 68 | ) 69 | 70 | DOL_OnUnload( 71 | OutputDebugStringA("DOL_OnUnload Test\n"); 72 | ) 73 | -------------------------------------------------------------------------------- /old/Test/Test2/Test2.fx: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------- 2 | // File: Tutorial07.fx 3 | // 4 | // Copyright (c) Microsoft Corporation. All rights reserved. 5 | //-------------------------------------------------------------------------------------- 6 | 7 | cbuffer cbChangesEveryFrame : register( b0 ) 8 | { 9 | matrix g_ViewProjection; 10 | float4 g_CameraPos; 11 | 12 | float4 g_LightPos; 13 | float4 g_LightColor; 14 | 15 | float4 g_MeshColor; 16 | float g_MeshShininess; 17 | }; 18 | 19 | 20 | //-------------------------------------------------------------------------------------- 21 | struct VS_INPUT 22 | { 23 | float3 Pos : POSITION; 24 | float3 Normal : NORMAL; 25 | float3 InstancePos : INSTANCE_POSITION; 26 | }; 27 | 28 | struct PS_INPUT 29 | { 30 | float4 Pos : SV_POSITION; 31 | float3 LsPos : TEXCOORD0; 32 | float4 Color : TEXCOORD1; 33 | float3 Normal : NORMAL; 34 | }; 35 | 36 | 37 | //-------------------------------------------------------------------------------------- 38 | // Vertex Shader 39 | //-------------------------------------------------------------------------------------- 40 | PS_INPUT VS( VS_INPUT input ) 41 | { 42 | float3 LsPos3 = (input.Pos * float3(0.05f, 0.05f, 0.05f)) + input.InstancePos; 43 | PS_INPUT output = (PS_INPUT)0; 44 | output.LsPos = LsPos3; 45 | output.Pos = mul(float4(LsPos3, 1.0f), g_ViewProjection); 46 | output.Color = float4(0.8f, 0.8f, 0.8f, 1.0f); 47 | output.Normal = input.Normal; 48 | 49 | return output; 50 | } 51 | 52 | 53 | //-------------------------------------------------------------------------------------- 54 | // Pixel Shader 55 | //-------------------------------------------------------------------------------------- 56 | float4 PS( PS_INPUT input) : SV_Target 57 | { 58 | float3 FragPos = input.LsPos.xyz; 59 | float3 LightPos = g_LightPos.xyz; 60 | float3 LightColor = g_LightColor.rgb; 61 | float3 LightDiff = LightPos - FragPos; 62 | float LightDist2 = dot(LightDiff, LightDiff); 63 | float LightDist = sqrt(LightDist2); 64 | float3 LightDir = LightDiff / LightDist; 65 | 66 | float3 Albedo = input.Color.rgb; 67 | float Shininess = g_MeshShininess; 68 | float3 Normal = input.Normal.xyz; 69 | float3 EyePos = g_CameraPos.xyz; 70 | float3 EyeDir = normalize(EyePos - FragPos); 71 | 72 | float3 h = normalize(EyeDir + LightDir); 73 | float nh = max(dot(Normal, h), 0.0); 74 | float Specular = pow(nh, Shininess); 75 | float Intensity = max(dot(Normal, LightDir), 0.0); 76 | 77 | float4 Result = float4(0.0, 0.0, 0.0, 1.0); 78 | Result.rgb += LightColor * (Albedo * Intensity); 79 | Result.rgb += LightColor * Specular; 80 | 81 | return Result; 82 | } 83 | -------------------------------------------------------------------------------- /old/Test/Test2/Test2.h: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicObjLoader 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "DynamicObjLoader.h" 12 | 13 | #define MAX_PARTICLES 2048 14 | 15 | struct Particle 16 | { 17 | XMFLOAT3 position; 18 | XMFLOAT3 velocity; 19 | float radius; 20 | }; 21 | extern Particle g_particles[MAX_PARTICLES]; 22 | 23 | DOL_Fixate float GenRand(); 24 | -------------------------------------------------------------------------------- /old/Test/Test2/Test2.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {065ca4d8-e5f3-4356-8075-31598e5a2e0a} 6 | 7 | 8 | {fdfff9df-2da0-42e9-9eac-d2276a1eedac} 9 | 10 | 11 | {2c3d4c8c-5d1a-459a-a05a-a4e4b608a44e} 12 | fx;fxh;hlsl 13 | 14 | 15 | 16 | 17 | Test2 18 | 19 | 20 | Test2 21 | 22 | 23 | DynamicObjLoader 24 | 25 | 26 | 27 | 28 | Test2\Shaders 29 | 30 | 31 | 32 | 33 | Test2 34 | 35 | 36 | DynamicObjLoader 37 | 38 | 39 | -------------------------------------------------------------------------------- /old/Test/Test2/Test2Obj.cpp: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicObjLoader 4 | 5 | #include "stdafx.h" 6 | #include "Test2.h" 7 | #include 8 | 9 | DOL_Module 10 | 11 | inline XMFLOAT3& operator+=(XMFLOAT3 &l, const XMFLOAT3 &r) { l.x+=r.x; l.y+=r.y; l.z+=r.z; return l; } 12 | inline XMFLOAT3& operator*=(XMFLOAT3 &l, float r) { l.x*=r; l.y*=r; l.z*=r; return l; } 13 | inline XMFLOAT3 operator-(const XMFLOAT3 &l, const XMFLOAT3 &r) { return XMFLOAT3(l.x-r.x, l.y-r.y, l.z-r.z); } 14 | inline XMFLOAT3 operator*(const XMFLOAT3 &l, float r) { return XMFLOAT3(l.x*r, l.y*r, l.z*r); } 15 | inline XMFLOAT3 operator/(const XMFLOAT3 &l, float r) { return XMFLOAT3(l.x/r, l.y/r, l.z/r); } 16 | 17 | inline float Dot(const XMFLOAT3 a, const XMFLOAT3 b) 18 | { 19 | return a.x*b.x + a.y*b.y + a.z*b.z; 20 | } 21 | 22 | inline float Len(const XMFLOAT3 a) 23 | { 24 | return sqrt(Dot(a, a)); 25 | } 26 | 27 | inline XMFLOAT3 Normalize(XMFLOAT3 a) 28 | { 29 | return a / Len(a); 30 | } 31 | 32 | DOL_Export void InitializeParticles(Particle *particles, size_t num_particles) 33 | { 34 | for(size_t i=0; i(0.0f, d) * -0.2f; 79 | } 80 | 81 | // 速度を適用 82 | for(size_t ri=0; ri 11 | #include 12 | 13 | 14 | 15 | // TODO: プログラムに必要な追加ヘッダーをここで参照してください。 16 | -------------------------------------------------------------------------------- /old/Test/Test2/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // SDKDDKVer.h をインクルードすると、利用できる最も上位の Windows プラットフォームが定義されます。 4 | 5 | // 以前の Windows プラットフォーム用にアプリケーションをビルドする場合は、WinSDKVer.h をインクルードし、 6 | // SDKDDKVer.h をインクルードする前に、サポート対象とするプラットフォームを示すように _WIN32_WINNT マクロを設定します。 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /old/Test/Test3/Test3.cpp: -------------------------------------------------------------------------------- 1 | // created by i-saint 2 | // distributed under Creative Commons Attribution (CC BY) license. 3 | // https://github.com/i-saint/DynamicObjLoader 4 | 5 | #include 6 | #include 7 | #include "../../DynamicObjLoader.h" 8 | 9 | class Hoge 10 | { 11 | public: 12 | Hoge() { printf("Hoge::Hoge()\n"); } 13 | ~Hoge() { printf("Hoge::~Hoge()\n"); } 14 | void ExecHoge() { printf("Hoge::ExecHoge()\n"); } 15 | }; 16 | 17 | class Hage 18 | { 19 | public: 20 | Hage() { printf("Hage::Hage()\n"); } 21 | ~Hage() { printf("Hage::~Hage()\n"); } 22 | void ExecHage() { printf("Hage::ExecHage()\n"); } 23 | }; 24 | 25 | 26 | void* Create(const std::string &name) 27 | { 28 | volatile void *obj = NULL; 29 | std::string source = "obj = new "+name+"();"; 30 | DOL_Eval(source.c_str()); 31 | return (void*)obj; 32 | } 33 | 34 | void Delete(void *_obj, const std::string &name) 35 | { 36 | volatile void *obj = _obj; 37 | std::string source = "delete reinterpret_cast<"+name+"*>(obj);"; 38 | DOL_Eval(source.c_str()); 39 | } 40 | 41 | void CallMemberFunction(void *_obj, const std::string &type, const std::string &func) 42 | { 43 | volatile void *obj = _obj; 44 | std::string source = "reinterpret_cast<"+type+"*>(obj)->"+func+"();"; 45 | DOL_Eval(source.c_str()); 46 | } 47 | 48 | void TestReflection() 49 | { 50 | { 51 | void *obj = Create("Hoge"); 52 | CallMemberFunction(obj, "Hoge", "ExecHoge"); 53 | Delete(obj, "Hoge"); 54 | } 55 | { 56 | void *obj = Create("Hage"); 57 | CallMemberFunction(obj, "Hage", "ExecHage"); 58 | Delete(obj, "Hage"); 59 | } 60 | } 61 | 62 | 63 | void TestLocalVariable() 64 | { 65 | volatile int hoge = 10; // volatile: 最適化で消えるの防止 66 | volatile double hage = 1.0; 67 | DOL_Eval("printf(\"%d %lf\\n\", hoge, hage);"); 68 | DOL_Eval("hoge+=10;"); 69 | DOL_Eval("hage*=2.0;"); 70 | DOL_Eval("printf(\"%d %lf\\n\", hoge, hage);"); 71 | 72 | void *obj = NULL; 73 | DOL_Eval("obj = new Hoge();"); 74 | 75 | printf("%d %lf\n", hoge, hage); 76 | } 77 | 78 | int main(int argc, char* argv[]) 79 | { 80 | DOL_EvalSetCompileOption("/EHsc"); 81 | 82 | TestLocalVariable(); 83 | TestReflection(); 84 | 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /old/Test/Test3/Test3.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {2EB11313-236B-4F74-8F89-4B5F21BAF953} 23 | Win32Proj 24 | Test1 25 | 26 | 27 | 28 | Application 29 | true 30 | Unicode 31 | 32 | 33 | Application 34 | true 35 | Unicode 36 | 37 | 38 | Application 39 | false 40 | false 41 | Unicode 42 | 43 | 44 | Application 45 | false 46 | false 47 | Unicode 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | true 67 | ..\..;$(CG_INC_PATH);$(DXSDK_DIR)include;$(IncludePath) 68 | $(CG_LIB_PATH);$(DXSDK_DIR)lib\x86;$(LibraryPath) 69 | 70 | 71 | true 72 | ..\..;$(CG_INC_PATH);$(DXSDK_DIR)include;$(IncludePath) 73 | $(CG_LIB_PATH);$(DXSDK_DIR)lib\x86;$(LibraryPath) 74 | 75 | 76 | false 77 | ..\..;$(CG_INC_PATH);$(DXSDK_DIR)include;$(IncludePath) 78 | $(CG_LIB_PATH);$(DXSDK_DIR)lib\x86;$(LibraryPath) 79 | 80 | 81 | false 82 | ..\..;$(CG_INC_PATH);$(DXSDK_DIR)include;$(IncludePath) 83 | $(CG_LIB_PATH);$(DXSDK_DIR)lib\x86;$(LibraryPath) 84 | 85 | 86 | 87 | Use 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | false 92 | 93 | 94 | Console 95 | true 96 | 97 | 98 | 99 | 100 | Use 101 | Level3 102 | Disabled 103 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | false 105 | 106 | 107 | Console 108 | true 109 | 110 | 111 | 112 | 113 | Level3 114 | Use 115 | MaxSpeed 116 | true 117 | true 118 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 119 | false 120 | false 121 | 122 | 123 | Console 124 | true 125 | true 126 | false 127 | 128 | 129 | 130 | 131 | Level3 132 | Use 133 | MaxSpeed 134 | true 135 | true 136 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 137 | false 138 | false 139 | 140 | 141 | Console 142 | true 143 | true 144 | false 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | NotUsing 153 | NotUsing 154 | NotUsing 155 | NotUsing 156 | 157 | 158 | NotUsing 159 | NotUsing 160 | NotUsing 161 | NotUsing 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /old/Test/Test3/Test3.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | DynamicObjLoader 6 | 7 | 8 | 9 | 10 | DynamicObjLoader 11 | 12 | 13 | Test3 14 | 15 | 16 | 17 | 18 | {88b61b2c-e193-4f16-86dd-6cdb5d55644f} 19 | 20 | 21 | {cec1ea66-648c-473f-a8c5-0b4e4a7f6a64} 22 | 23 | 24 | -------------------------------------------------------------------------------- /package.bat: -------------------------------------------------------------------------------- 1 | copy DynamicPatcher.h bin 2 | copy DynamicPatcher*.dll bin 3 | copy DynamicPatcher*.lib bin 4 | copy DynamicPatcherInjector*.dll bin 5 | copy DynamicPatcherInjector*.exe bin 6 | --------------------------------------------------------------------------------