From 14a22dbc6d23bc761c3e642bab6badbfe48a6d5b Mon Sep 17 00:00:00 2001 From: Alex0vSky <52796897+Alex0vSky@users.noreply.github.com> Date: Fri, 22 Sep 2023 16:44:45 +0300 Subject: [PATCH 1/9] optimize off --- include/gmock-win32.h | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/include/gmock-win32.h b/include/gmock-win32.h index efacfdd..0bbc1a5 100644 --- a/include/gmock-win32.h +++ b/include/gmock-win32.h @@ -55,8 +55,16 @@ struct mock_module_##func \ #define MOCK_MODULE_FUNC0_CDECL_CONV(m, ...) MOCK_MODULE_FUNC0_CALLCONV(__cdecl, m, __VA_ARGS__) #define MOCK_MODULE_FUNC1_(tn, constness, ct, func, ...) \ +_Pragma( "optimize( \"\", off )" ) \ struct mock_module_##func \ { \ + static void hideCodeFromOptimizer() { \ + if (!mock_module_##func::oldFn_) \ + mockModule_patchModuleFunc( \ + &::func \ + , reinterpret_cast< void* >( &mock_module_##func::stub ) \ + , &mock_module_##func::oldFn_); \ + } \ GMOCK_RESULT_(tn, __VA_ARGS__) ct func( \ GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1) constness \ { \ @@ -85,7 +93,8 @@ struct mock_module_##func \ gmock_a1); \ } \ static void* oldFn_; \ -}; void* mock_module_##func::oldFn_ = nullptr; +}; void* mock_module_##func::oldFn_ = nullptr; \ +_Pragma( "optimize( \"\", on )" ) #define MOCK_MODULE_FUNC1(m, ...) MOCK_MODULE_FUNC1_(, , , m, __VA_ARGS__) #define MOCK_MODULE_FUNC1_CALLCONV(ct, m, ...) MOCK_MODULE_FUNC1_(, , ct, m, __VA_ARGS__) @@ -815,11 +824,7 @@ void mockModule_patchModuleFunc (void*, void*, void**); void mockModule_restoreModuleFunc (void*, void*, void**); #define EXPECT_MODULE_FUNC_CALL(func, ...) \ - if (!mock_module_##func::oldFn_) \ - { \ - mockModule_patchModuleFunc(&func, reinterpret_cast< void* >( \ - &mock_module_##func::stub), &mock_module_##func::oldFn_); \ - } \ + mock_module_##func::hideCodeFromOptimizer( ); \ EXPECT_CALL(mock_module_##func::instance(), func(__VA_ARGS__)) #define ON_MODULE_FUNC_CALL(func, ...) \ From 62e3ef08fec80141eec223b7a80a50e334ffb61c Mon Sep 17 00:00:00 2001 From: Alex0vSky <52796897+Alex0vSky@users.noreply.github.com> Date: Thu, 28 Sep 2023 18:38:33 +0300 Subject: [PATCH 2/9] change name, separate global function --- include/gmock-win32.h | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/include/gmock-win32.h b/include/gmock-win32.h index 0bbc1a5..0ea7a2d 100644 --- a/include/gmock-win32.h +++ b/include/gmock-win32.h @@ -54,16 +54,21 @@ struct mock_module_##func \ #define MOCK_MODULE_FUNC0_STDCALL_CONV(m, ...) MOCK_MODULE_FUNC0_CALLCONV(__stdcall, m, __VA_ARGS__) #define MOCK_MODULE_FUNC0_CDECL_CONV(m, ...) MOCK_MODULE_FUNC0_CALLCONV(__cdecl, m, __VA_ARGS__) +template +static void patchModuleFunc_(void* mock_module_func_oldFn, TFunc func, TStub stub) { + if (!mock_module_func_oldFn) + mockModule_patchModuleFunc( + func + , reinterpret_cast< void* >( stub ) + , &mock_module_func_oldFn); +} + #define MOCK_MODULE_FUNC1_(tn, constness, ct, func, ...) \ _Pragma( "optimize( \"\", off )" ) \ struct mock_module_##func \ { \ - static void hideCodeFromOptimizer() { \ - if (!mock_module_##func::oldFn_) \ - mockModule_patchModuleFunc( \ - &::func \ - , reinterpret_cast< void* >( &mock_module_##func::stub ) \ - , &mock_module_##func::oldFn_); \ + static void patchModuleFunc() { \ + ::patchModuleFunc_( mock_module_##func::oldFn_, &::func, mock_module_##func::stub ); \ } \ GMOCK_RESULT_(tn, __VA_ARGS__) ct func( \ GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1) constness \ @@ -824,7 +829,7 @@ void mockModule_patchModuleFunc (void*, void*, void**); void mockModule_restoreModuleFunc (void*, void*, void**); #define EXPECT_MODULE_FUNC_CALL(func, ...) \ - mock_module_##func::hideCodeFromOptimizer( ); \ + mock_module_##func::patchModuleFunc( ); \ EXPECT_CALL(mock_module_##func::instance(), func(__VA_ARGS__)) #define ON_MODULE_FUNC_CALL(func, ...) \ From cc1814e843ac8849d0b5d61e56dcd5c18abf80b4 Mon Sep 17 00:00:00 2001 From: Alex0vSky <52796897+Alex0vSky@users.noreply.github.com> Date: Thu, 28 Sep 2023 20:28:45 +0300 Subject: [PATCH 3/9] Avoided duplicating code in mock_module_##func --- include/gmock-win32.h | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/include/gmock-win32.h b/include/gmock-win32.h index 0ea7a2d..b62f1aa 100644 --- a/include/gmock-win32.h +++ b/include/gmock-win32.h @@ -54,22 +54,9 @@ struct mock_module_##func \ #define MOCK_MODULE_FUNC0_STDCALL_CONV(m, ...) MOCK_MODULE_FUNC0_CALLCONV(__stdcall, m, __VA_ARGS__) #define MOCK_MODULE_FUNC0_CDECL_CONV(m, ...) MOCK_MODULE_FUNC0_CALLCONV(__cdecl, m, __VA_ARGS__) -template -static void patchModuleFunc_(void* mock_module_func_oldFn, TFunc func, TStub stub) { - if (!mock_module_func_oldFn) - mockModule_patchModuleFunc( - func - , reinterpret_cast< void* >( stub ) - , &mock_module_func_oldFn); -} - #define MOCK_MODULE_FUNC1_(tn, constness, ct, func, ...) \ -_Pragma( "optimize( \"\", off )" ) \ struct mock_module_##func \ { \ - static void patchModuleFunc() { \ - ::patchModuleFunc_( mock_module_##func::oldFn_, &::func, mock_module_##func::stub ); \ - } \ GMOCK_RESULT_(tn, __VA_ARGS__) ct func( \ GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1) constness \ { \ @@ -98,8 +85,7 @@ struct mock_module_##func \ gmock_a1); \ } \ static void* oldFn_; \ -}; void* mock_module_##func::oldFn_ = nullptr; \ -_Pragma( "optimize( \"\", on )" ) +}; void* mock_module_##func::oldFn_ = nullptr; #define MOCK_MODULE_FUNC1(m, ...) MOCK_MODULE_FUNC1_(, , , m, __VA_ARGS__) #define MOCK_MODULE_FUNC1_CALLCONV(ct, m, ...) MOCK_MODULE_FUNC1_(, , ct, m, __VA_ARGS__) @@ -822,14 +808,31 @@ struct mock_module_##func \ #define MOCK_MODULE_FUNC_OVERLOAD(name, ...) MOCK_MODULE_UNITE(MOCK_MODULE_OVERLOAD(name, MOCK_MODULE_NBARG(__VA_ARGS__)), (__VA_ARGS__)) #define MOCK_MODULE_FUNC(r, m, ...) MOCK_MODULE_OVERLOAD(MOCK_MODULE_FUNC, MOCK_MODULE_NBARG(__VA_ARGS__))##(m, r(__VA_ARGS__)) -#define MOCK_STDCALL_FUNC(r, m, ...) MOCK_MODULE_OVERLOAD(MOCK_MODULE_FUNC, MOCK_MODULE_NBARG(__VA_ARGS__)##_STDCALL_CONV)##(m, r(__VA_ARGS__)) +#define MOCK_STDCALL_FUNC(r, m, ...) \ + MOCK_MODULE_OVERLOAD(MOCK_MODULE_FUNC, MOCK_MODULE_NBARG(__VA_ARGS__)##_STDCALL_CONV)##(m, r(__VA_ARGS__)) \ + _Pragma( "optimize( \"\", off )" ) \ + static void patchModuleFunc_##m() { \ + ::patchModuleFunc_( mock_module_##m::oldFn_, &::m, mock_module_##m::stub ); \ + } \ + _Pragma( "optimize( \"\", on )" ) + +// Hidden from optimizer +template +static void patchModuleFunc_(void* mock_module_func_oldFn, TFunc func, TStub stub) { + if (!mock_module_func_oldFn) + mockModule_patchModuleFunc( + func + , reinterpret_cast< void* >( stub ) + , &mock_module_func_oldFn); +} + #define MOCK_CDECL_FUNC(r, m, ...) MOCK_MODULE_OVERLOAD(MOCK_MODULE_FUNC, MOCK_MODULE_NBARG(__VA_ARGS__)##__CDECL_CONV)##(m, r(__VA_ARGS__)) void mockModule_patchModuleFunc (void*, void*, void**); void mockModule_restoreModuleFunc (void*, void*, void**); #define EXPECT_MODULE_FUNC_CALL(func, ...) \ - mock_module_##func::patchModuleFunc( ); \ + patchModuleFunc_##func( ); \ EXPECT_CALL(mock_module_##func::instance(), func(__VA_ARGS__)) #define ON_MODULE_FUNC_CALL(func, ...) \ From 7237d29e7dc0e6ce3432c894ef2bce8e3100fb71 Mon Sep 17 00:00:00 2001 From: Alex0vSky <52796897+Alex0vSky@users.noreply.github.com> Date: Thu, 28 Sep 2023 20:30:32 +0300 Subject: [PATCH 4/9] Avoid code duplication in mock_module_##func From a34e101125eaa9db66ed6e6a9e59e21a80c8ada1 Mon Sep 17 00:00:00 2001 From: Alex0vSky <52796897+Alex0vSky@users.noreply.github.com> Date: Fri, 29 Sep 2023 20:01:19 +0300 Subject: [PATCH 5/9] Avoid using winApi directly in core --- src/gmock-win32.cpp | 62 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/src/gmock-win32.cpp b/src/gmock-win32.cpp index 1575765..d05df4b 100644 --- a/src/gmock-win32.cpp +++ b/src/gmock-win32.cpp @@ -21,6 +21,40 @@ do { \ namespace { + typedef DWORD (WINAPI *pfnGetLastError_t)( VOID ); + pfnGetLastError_t g_pfnGetLastError = nullptr; + + typedef HANDLE (WINAPI *pfnGetCurrentProcess_t)( VOID ); + pfnGetCurrentProcess_t g_pfnGetCurrentProcess = nullptr; + + typedef BOOL (WINAPI *pfnWriteProcessMemory_t)(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesWritten); + pfnWriteProcessMemory_t g_pfnWriteProcessMemory = nullptr; + + typedef BOOL (WINAPI *pfnVirtualProtect_t)(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); + pfnVirtualProtect_t g_pfnVirtualProtect = nullptr; + + typedef HMODULE (WINAPI *pfnGetModuleHandleA_t)(LPCSTR lpModuleName); + pfnGetModuleHandleA_t g_pfnGetModuleHandleA = nullptr; + + typedef PVOID(__stdcall *pfnImageDirectoryEntryToDataEx_t)(PVOID Base, BOOLEAN MappedAsImage, USHORT DirectoryEntry, PULONG Size, PIMAGE_SECTION_HEADER *FoundHeader); + pfnImageDirectoryEntryToDataEx_t g_pfnImageDirectoryEntryToDataEx = nullptr; + + static bool g_bInit = false; + void init() { + HMODULE module; + module = LoadLibraryA( "kernel32.dll" ); + g_pfnGetLastError = (pfnGetLastError_t)GetProcAddress( module, "GetLastError" ); + g_pfnGetCurrentProcess = (pfnGetCurrentProcess_t)GetProcAddress( module, "GetCurrentProcess" ); + g_pfnWriteProcessMemory = (pfnWriteProcessMemory_t)GetProcAddress( module, "WriteProcessMemory" ); + g_pfnVirtualProtect = (pfnVirtualProtect_t)GetProcAddress( module, "VirtualProtect" ); + // Doesnt matter wchar_t or char, GetModuleHandleW or GetModuleHandleA + g_pfnGetModuleHandleA = (pfnGetModuleHandleA_t)GetProcAddress( module, "GetModuleHandleA" ); + module = LoadLibraryA( "dbghelp.dll" ); + ImageDirectoryEntryToDataEx; + g_pfnImageDirectoryEntryToDataEx = (pfnImageDirectoryEntryToDataEx_t)GetProcAddress( module, "ImageDirectoryEntryToDataEx" ); + g_bInit = true; + } + LONG WINAPI InvalidReadExceptionFilter(PEXCEPTION_POINTERS /*pep*/) { return EXCEPTION_EXECUTE_HANDLER; @@ -40,7 +74,7 @@ namespace { __try { *resultDescriptor = reinterpret_cast< PIMAGE_IMPORT_DESCRIPTOR >( - ::ImageDirectoryEntryToDataEx( + g_pfnImageDirectoryEntryToDataEx( base, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize, &pFoundHeader)); } __except (InvalidReadExceptionFilter(GetExceptionInformation())) @@ -50,7 +84,7 @@ namespace { } return *resultDescriptor ? - S_OK : HRESULT_FROM_WIN32(::GetLastError()); + S_OK : HRESULT_FROM_WIN32(g_pfnGetLastError()); } HRESULT writeProcessMemory( @@ -59,26 +93,26 @@ namespace { if (!address || !buffer) return E_INVALIDARG; - const auto processHandle = ::GetCurrentProcess(); + const auto processHandle = g_pfnGetCurrentProcess(); - if (::WriteProcessMemory(processHandle, address, buffer, size, nullptr) == 0 - && (ERROR_NOACCESS == ::GetLastError())) + if (g_pfnWriteProcessMemory(processHandle, address, buffer, size, nullptr) == 0 + && (ERROR_NOACCESS == g_pfnGetLastError())) { DWORD oldProtect{ }; - if (::VirtualProtect(address, size, PAGE_WRITECOPY, &oldProtect)) + if (g_pfnVirtualProtect(address, size, PAGE_WRITECOPY, &oldProtect)) { std::shared_ptr< void > finalAction(nullptr, [&](auto&&...) { - ::VirtualProtect(address, size, oldProtect, &oldProtect); + g_pfnVirtualProtect(address, size, oldProtect, &oldProtect); }); - if (!::WriteProcessMemory(processHandle, address, buffer, size, nullptr)) - return HRESULT_FROM_WIN32(::GetLastError()); + if (!g_pfnWriteProcessMemory(processHandle, address, buffer, size, nullptr)) + return HRESULT_FROM_WIN32(g_pfnGetLastError()); return S_OK; } else { - return HRESULT_FROM_WIN32(::GetLastError()); + return HRESULT_FROM_WIN32(g_pfnGetLastError()); } } else @@ -134,7 +168,7 @@ namespace { LPVOID* ppfn = nullptr; RETURN_IF_FAILED( - findImportProc(::GetModuleHandle(nullptr), funcAddr, &ppfn)); + findImportProc(g_pfnGetModuleHandleA(nullptr), funcAddr, &ppfn)); RETURN_IF_FAILED( writeProcessMemory(ppfn, &newFunc, sizeof(ppfn))); @@ -152,7 +186,7 @@ namespace { LPVOID* ppfn = nullptr; RETURN_IF_FAILED( - findImportProc(::GetModuleHandle(nullptr), stubFunc, &ppfn)); + findImportProc(g_pfnGetModuleHandleA(nullptr), stubFunc, &ppfn)); return writeProcessMemory(ppfn, &origFunc, sizeof(ppfn)); } @@ -162,6 +196,8 @@ namespace { void mockModule_patchModuleFunc( void* funcAddr, void* newFunc, void** oldFunc) { + if ( !g_bInit ) + init( ); if (FAILED(patchImportFunc(funcAddr, newFunc, oldFunc))) throw std::runtime_error{ "failed to patch module function" }; } @@ -169,6 +205,8 @@ void mockModule_patchModuleFunc( void mockModule_restoreModuleFunc( void* origFunc, void* stubFunc, void** oldFunc) { + if ( !g_bInit ) + init( ); if (FAILED(restoreImportFunc(origFunc, stubFunc))) throw std::runtime_error{ "failed to restore module function" }; From 3f81885a4dde1d0dba85d8c3c6e726c28bd3f923 Mon Sep 17 00:00:00 2001 From: Alex0vSky <52796897+Alex0vSky@users.noreply.github.com> Date: Mon, 2 Oct 2023 13:28:33 +0300 Subject: [PATCH 6/9] add error check to initialize --- src/gmock-win32.cpp | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/gmock-win32.cpp b/src/gmock-win32.cpp index d05df4b..8acbfa9 100644 --- a/src/gmock-win32.cpp +++ b/src/gmock-win32.cpp @@ -40,19 +40,35 @@ namespace { pfnImageDirectoryEntryToDataEx_t g_pfnImageDirectoryEntryToDataEx = nullptr; static bool g_bInit = false; - void init() { + bool init() { HMODULE module; module = LoadLibraryA( "kernel32.dll" ); + if ( !module ) + return false; g_pfnGetLastError = (pfnGetLastError_t)GetProcAddress( module, "GetLastError" ); + if ( !g_pfnGetLastError ) + return false; g_pfnGetCurrentProcess = (pfnGetCurrentProcess_t)GetProcAddress( module, "GetCurrentProcess" ); + if ( !g_pfnGetCurrentProcess ) + return false; g_pfnWriteProcessMemory = (pfnWriteProcessMemory_t)GetProcAddress( module, "WriteProcessMemory" ); + if ( !g_pfnWriteProcessMemory ) + return false; g_pfnVirtualProtect = (pfnVirtualProtect_t)GetProcAddress( module, "VirtualProtect" ); + if ( !g_pfnVirtualProtect ) + return false; // Doesnt matter wchar_t or char, GetModuleHandleW or GetModuleHandleA g_pfnGetModuleHandleA = (pfnGetModuleHandleA_t)GetProcAddress( module, "GetModuleHandleA" ); + if ( !g_pfnGetModuleHandleA ) + return false; module = LoadLibraryA( "dbghelp.dll" ); - ImageDirectoryEntryToDataEx; + if ( !module ) + return false; g_pfnImageDirectoryEntryToDataEx = (pfnImageDirectoryEntryToDataEx_t)GetProcAddress( module, "ImageDirectoryEntryToDataEx" ); + if ( g_pfnImageDirectoryEntryToDataEx ) + return false; g_bInit = true; + return true; } LONG WINAPI InvalidReadExceptionFilter(PEXCEPTION_POINTERS /*pep*/) @@ -197,7 +213,8 @@ void mockModule_patchModuleFunc( void* funcAddr, void* newFunc, void** oldFunc) { if ( !g_bInit ) - init( ); + if ( !init( ) ) + throw std::runtime_error{ "failed to initialize patcher" }; if (FAILED(patchImportFunc(funcAddr, newFunc, oldFunc))) throw std::runtime_error{ "failed to patch module function" }; } @@ -206,7 +223,8 @@ void mockModule_restoreModuleFunc( void* origFunc, void* stubFunc, void** oldFunc) { if ( !g_bInit ) - init( ); + if ( !init( ) ) + throw std::runtime_error{ "failed to initialize patcher" }; if (FAILED(restoreImportFunc(origFunc, stubFunc))) throw std::runtime_error{ "failed to restore module function" }; From d40a50cfe81b43d4178ce30af2b53e8ff886baaa Mon Sep 17 00:00:00 2001 From: Alex0vSky <52796897+Alex0vSky@users.noreply.github.com> Date: Mon, 2 Oct 2023 13:41:48 +0300 Subject: [PATCH 7/9] correct optimization directive, remove useless static --- include/gmock-win32.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/gmock-win32.h b/include/gmock-win32.h index b62f1aa..fa7e28a 100644 --- a/include/gmock-win32.h +++ b/include/gmock-win32.h @@ -810,15 +810,15 @@ struct mock_module_##func \ #define MOCK_STDCALL_FUNC(r, m, ...) \ MOCK_MODULE_OVERLOAD(MOCK_MODULE_FUNC, MOCK_MODULE_NBARG(__VA_ARGS__)##_STDCALL_CONV)##(m, r(__VA_ARGS__)) \ - _Pragma( "optimize( \"\", off )" ) \ + __pragma(optimize("", on)) \ static void patchModuleFunc_##m() { \ ::patchModuleFunc_( mock_module_##m::oldFn_, &::m, mock_module_##m::stub ); \ } \ - _Pragma( "optimize( \"\", on )" ) + __pragma(optimize("", off)) // Hidden from optimizer template -static void patchModuleFunc_(void* mock_module_func_oldFn, TFunc func, TStub stub) { +void patchModuleFunc_(void* mock_module_func_oldFn, TFunc func, TStub stub) { if (!mock_module_func_oldFn) mockModule_patchModuleFunc( func From e5a4077410f31f2442122559f0e63e07360adc1e Mon Sep 17 00:00:00 2001 From: Alex0vSky <52796897+Alex0vSky@users.noreply.github.com> Date: Mon, 2 Oct 2023 18:29:20 +0300 Subject: [PATCH 8/9] fix bug, keep init order --- src/gmock-win32.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gmock-win32.cpp b/src/gmock-win32.cpp index 8acbfa9..0905fb0 100644 --- a/src/gmock-win32.cpp +++ b/src/gmock-win32.cpp @@ -65,7 +65,7 @@ namespace { if ( !module ) return false; g_pfnImageDirectoryEntryToDataEx = (pfnImageDirectoryEntryToDataEx_t)GetProcAddress( module, "ImageDirectoryEntryToDataEx" ); - if ( g_pfnImageDirectoryEntryToDataEx ) + if ( !g_pfnImageDirectoryEntryToDataEx ) return false; g_bInit = true; return true; @@ -223,8 +223,7 @@ void mockModule_restoreModuleFunc( void* origFunc, void* stubFunc, void** oldFunc) { if ( !g_bInit ) - if ( !init( ) ) - throw std::runtime_error{ "failed to initialize patcher" }; + throw std::runtime_error{ "failed in initialization order" }; if (FAILED(restoreImportFunc(origFunc, stubFunc))) throw std::runtime_error{ "failed to restore module function" }; From f7e026a4d95a491291f7678f612b166cc5128003 Mon Sep 17 00:00:00 2001 From: Alex0vSky <52796897+Alex0vSky@users.noreply.github.com> Date: Mon, 2 Oct 2023 18:35:44 +0300 Subject: [PATCH 9/9] fix --- src/gmock-win32.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gmock-win32.cpp b/src/gmock-win32.cpp index 9cf5753..ced86e2 100644 --- a/src/gmock-win32.cpp +++ b/src/gmock-win32.cpp @@ -65,7 +65,7 @@ namespace { if ( !module ) return false; g_pfnImageDirectoryEntryToDataEx = (pfnImageDirectoryEntryToDataEx_t)GetProcAddress( module, "ImageDirectoryEntryToDataEx" ); - if ( g_pfnImageDirectoryEntryToDataEx ) + if ( !g_pfnImageDirectoryEntryToDataEx ) return false; g_bInit = true; return true; @@ -223,8 +223,7 @@ void mockModule_restoreModuleFunc( void* origFunc, void* stubFunc, void** oldFunc) { if ( !g_bInit ) - if ( !init( ) ) - throw std::runtime_error{ "failed to initialize patcher" }; + throw std::runtime_error{ "failed in initialization order" }; if (FAILED(restoreImportFunc(origFunc, stubFunc))) throw std::runtime_error{ "failed to restore module function" };