diff --git a/DDraw/DDraw.vcxproj b/DDraw/DDraw.vcxproj index 2a72068..4687b24 100644 --- a/DDraw/DDraw.vcxproj +++ b/DDraw/DDraw.vcxproj @@ -150,6 +150,7 @@ copy /y "$(TargetPath)" "D:\Steam\steamapps\common\Grand Theft Auto Vice City\dd + @@ -157,6 +158,7 @@ copy /y "$(TargetPath)" "D:\Steam\steamapps\common\Grand Theft Auto Vice City\dd + diff --git a/DDraw/DDraw.vcxproj.filters b/DDraw/DDraw.vcxproj.filters index 92dd8dc..6915b57 100644 --- a/DDraw/DDraw.vcxproj.filters +++ b/DDraw/DDraw.vcxproj.filters @@ -18,11 +18,17 @@ Source Files + + Source Files + Header Files + + Header Files + diff --git a/DDraw/dllmain.cpp b/DDraw/dllmain.cpp index 0d89180..d3dce2c 100644 --- a/DDraw/dllmain.cpp +++ b/DDraw/dllmain.cpp @@ -7,6 +7,7 @@ #include #include #include "MemoryMgr.h" +#include "Patterns.h" #pragma comment(lib, "shlwapi.lib") @@ -173,8 +174,10 @@ void InjectHooks() } -static VOID (WINAPI* pOrgGetStartupInfoA)(LPSTARTUPINFOA); -VOID WINAPI GetStartupInfoA_Hook(LPSTARTUPINFOA lpStartupInfo) +static bool FixRwcseg_Patterns(); +static bool rwcsegUnprotected = false; + +static void ProcHook() { static bool bPatched = false; if ( !bPatched ) @@ -182,24 +185,44 @@ VOID WINAPI GetStartupInfoA_Hook(LPSTARTUPINFOA lpStartupInfo) bPatched = true; InjectHooks(); + + if ( !rwcsegUnprotected ) + { + rwcsegUnprotected = FixRwcseg_Patterns(); + } } +} + +static VOID (WINAPI* pOrgGetStartupInfoA)(LPSTARTUPINFOA); +VOID WINAPI GetStartupInfoA_Hook(LPSTARTUPINFOA lpStartupInfo) +{ + ProcHook(); pOrgGetStartupInfoA(lpStartupInfo); } -void PatchIAT() +static uint8_t orgCode[5]; +static decltype(SystemParametersInfoA)* pOrgSystemParametersInfoA; +BOOL WINAPI SystemParametersInfoA_OverwritingHook( UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni ) +{ + ProcHook(); + Memory::VP::Patch( pOrgSystemParametersInfoA, { orgCode[0], orgCode[1], orgCode[2], orgCode[3], orgCode[4] } ); + return pOrgSystemParametersInfoA( uiAction, uiParam, pvParam, fWinIni ); +} + +static bool FixRwcseg_Header() { HINSTANCE hInstance = GetModuleHandle(nullptr); - IMAGE_NT_HEADERS* ntHeader = (IMAGE_NT_HEADERS*)((DWORD)hInstance + ((IMAGE_DOS_HEADER*)hInstance)->e_lfanew); + PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)hInstance + ((PIMAGE_DOS_HEADER)hInstance)->e_lfanew); // Give _rwcseg proper access rights - IMAGE_SECTION_HEADER* pSection = IMAGE_FIRST_SECTION(ntHeader); + PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(ntHeader); for ( SIZE_T i = 0, j = ntHeader->FileHeader.NumberOfSections; i < j; i++, pSection++ ) { if ( *(uint64_t*)(pSection->Name) == 0x006765736377725F ) // _rwcseg { DWORD dwProtect; - VirtualProtect((LPVOID)((ptrdiff_t)hInstance + pSection->VirtualAddress), pSection->Misc.VirtualSize, PAGE_EXECUTE_READ, &dwProtect); + VirtualProtect((LPVOID)((DWORD_PTR)hInstance + pSection->VirtualAddress), pSection->Misc.VirtualSize, PAGE_EXECUTE_READ, &dwProtect); DWORD Characteristics = pSection->Characteristics; if ( (Characteristics & IMAGE_SCN_CNT_CODE) == 0 ) @@ -218,39 +241,88 @@ void PatchIAT() Memory::VP::Patch( &ntHeader->OptionalHeader.SizeOfUninitializedData, ntHeader->OptionalHeader.SizeOfUninitializedData - pSection->Misc.VirtualSize ); } Memory::VP::Patch( &pSection->Characteristics, Characteristics ); - break; + return true; } } + return false; +} + +static bool FixRwcseg_Patterns() +{ + using namespace hook; + + auto begin = pattern( "55 8B EC 50 53 51 52 8B 5D 14 8B 4D 10 8B 45 0C 8B 55 08" ).count_hint(1000); + auto end = pattern( "9B D9 3D ? ? ? ? 81 25 ? ? ? ? FF FC FF FF 83 0D ? ? ? ? 3F" ).count_hint(1000); + + if ( begin.count_hint(1).size() == 1 && end.count_hint(1).size() == 1 ) + { + const ptrdiff_t size = (intptr_t)end.get_first( 24 ) - (intptr_t)begin.get_first(); + if ( size > 0 ) + { + DWORD dwProtect; + VirtualProtect( begin.get_first(), size, PAGE_EXECUTE_READ, &dwProtect ); + return true; + } + } + return false; +} + +static bool PatchIAT() +{ + HINSTANCE hInstance = GetModuleHandle(nullptr); + PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)hInstance + ((PIMAGE_DOS_HEADER)hInstance)->e_lfanew); // Find IAT - IMAGE_IMPORT_DESCRIPTOR* pImports = (IMAGE_IMPORT_DESCRIPTOR*)((DWORD)hInstance + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); + PIMAGE_IMPORT_DESCRIPTOR pImports = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)hInstance + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); // Find kernel32.dll for ( ; pImports->Name != 0; pImports++ ) { - if ( !_stricmp((const char*)((DWORD)hInstance + pImports->Name), "KERNEL32.DLL") ) + if ( !_stricmp((const char*)((DWORD_PTR)hInstance + pImports->Name), "KERNEL32.DLL") ) { - IMAGE_IMPORT_BY_NAME** pFunctions = (IMAGE_IMPORT_BY_NAME**)((DWORD)hInstance + pImports->OriginalFirstThunk); + if ( pImports->OriginalFirstThunk == 0 ) return false; + + PIMAGE_IMPORT_BY_NAME* pFunctions = (PIMAGE_IMPORT_BY_NAME*)((DWORD_PTR)hInstance + pImports->OriginalFirstThunk); // kernel32.dll found, find GetStartupInfoA for ( ptrdiff_t j = 0; pFunctions[j] != nullptr; j++ ) { - if ( !strcmp((const char*)((DWORD)hInstance + pFunctions[j]->Name), "GetStartupInfoA") ) + if ( !strcmp((const char*)((DWORD_PTR)hInstance + pFunctions[j]->Name), "GetStartupInfoA") ) { // Overwrite the address with the address to a custom GetStartupInfoA DWORD dwProtect[2]; - DWORD_PTR* pAddress = &((DWORD_PTR*)((DWORD)hInstance + pImports->FirstThunk))[j]; + DWORD_PTR* pAddress = &((DWORD_PTR*)((DWORD_PTR)hInstance + pImports->FirstThunk))[j]; - VirtualProtect(pAddress, sizeof(DWORD), PAGE_EXECUTE_READWRITE, &dwProtect[0]); + VirtualProtect(pAddress, sizeof(DWORD_PTR), PAGE_EXECUTE_READWRITE, &dwProtect[0]); pOrgGetStartupInfoA = **(VOID(WINAPI**)(LPSTARTUPINFOA))pAddress; - *pAddress = (DWORD)GetStartupInfoA_Hook; - VirtualProtect(pAddress, sizeof(DWORD), dwProtect[0], &dwProtect[1]); + *pAddress = (DWORD_PTR)GetStartupInfoA_Hook; + VirtualProtect(pAddress, sizeof(DWORD_PTR), dwProtect[0], &dwProtect[1]); - return; + return true; } } } } + return false; +} + +static bool PatchIAT_ByPointers() +{ + pOrgSystemParametersInfoA = SystemParametersInfoA; + memcpy( orgCode, pOrgSystemParametersInfoA, sizeof(orgCode) ); + Memory::VP::InjectHook( pOrgSystemParametersInfoA, SystemParametersInfoA_OverwritingHook, PATCH_JUMP ); + return true; +} + +static void ApplyDDrawHooks() +{ + rwcsegUnprotected = FixRwcseg_Header(); + + bool getStartupInfoHooked = PatchIAT(); + if ( !getStartupInfoHooked ) + { + PatchIAT_ByPointers(); + } } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) @@ -260,9 +332,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) if ( fdwReason == DLL_PROCESS_ATTACH ) { - DisableThreadLibraryCalls(hinstDLL); - - PatchIAT(); + ApplyDDrawHooks(); } return TRUE;