From 5b55d448f7051f36c84cc340855f764b2a5e4cb4 Mon Sep 17 00:00:00 2001 From: otavepto Date: Sun, 17 Mar 2024 01:15:48 +0200 Subject: [PATCH] * new stub dll `GameOverlayRenderer` for the experiemntal steamclient setup * for windows build script: prevent permissive language extensions via the compiler flag `/permissive-` --- .github/workflows/build-win.yml | 4 +- CHANGELOG.md | 6 +- build_win.bat | 63 ++++++++-- .../game_overlay_renderer_lib.cpp | 109 ++++++++++++++++++ .../game_overlay_renderer_lib.h | 70 +++++++++++ post_build/README.experimental_steamclient.md | 27 ++++- .../win/ColdClientLoader.cpp | 30 ++++- .../win/ColdClientLoader.ini | 3 + 8 files changed, 296 insertions(+), 16 deletions(-) create mode 100644 game_overlay_renderer_lib/game_overlay_renderer_lib.cpp create mode 100644 game_overlay_renderer_lib/game_overlay_renderer_lib.h diff --git a/.github/workflows/build-win.yml b/.github/workflows/build-win.yml index 343ceb19..a953d216 100644 --- a/.github/workflows/build-win.yml +++ b/.github/workflows/build-win.yml @@ -148,7 +148,7 @@ jobs: - name: Build release mode shell: cmd working-directory: ${{ github.workspace }} - run: build_win.bat -verbose +exclient-extra-32 +exclient-extra-64 release + run: build_win.bat -verbose +exclient-extra-32 +exclient-extra-64 +lib-gameoverlay-32 +lib-gameoverlay-64 release ### package (release mode) - name: Package build (release) @@ -170,7 +170,7 @@ jobs: - name: Build debug mode shell: cmd working-directory: ${{ github.workspace }} - run: build_win.bat -verbose +exclient-extra-32 +exclient-extra-64 debug + run: build_win.bat -verbose +exclient-extra-32 +exclient-extra-64 +lib-gameoverlay-32 +lib-gameoverlay-64 debug ### package (debug mode) - name: Package build (debug) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ed7ea84..02b9ed5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,12 @@ the script will attempt to detect and use the built-in tool `sudo` if it was available * for windows: updated stub drm patterns and added a workaround for older variants, this increases the compatibility, but makes it easier to be detected -* added missing example file `disable_lobby_creation.txt` in `steam_settings` folder + updated release `README` +* new stub dll `GameOverlayRenderer` for the experiemntal steamclient setup, + some apps verify the existence of this dll, either on disk, or inside their memory space. + not recommended to ignore it * allow overlay invitations to obscure game input to be able to accept/reject the request +* added missing example file `disable_lobby_creation.txt` in `steam_settings` folder + updated release `README` +* for windows build script: prevent permissive language extensions via the compiler flag `/permissive-` --- diff --git a/build_win.bat b/build_win.bat index 3b56525a..1e1d9275 100644 --- a/build_win.bat +++ b/build_win.bat @@ -39,6 +39,9 @@ set /a BUILD_TOOL_LOBBY=1 set /a BUILD_LIB_NET_SOCKETS_32=0 set /a BUILD_LIB_NET_SOCKETS_64=0 +set /a BUILD_LIB_GAMEOVERLAY_32=0 +set /a BUILD_LIB_GAMEOVERLAY_64=0 + :: < 0: deduce, > 1: force set /a PARALLEL_THREADS_OVERRIDE=-1 @@ -85,6 +88,10 @@ set /a VERBOSE=0 set /a BUILD_LIB_NET_SOCKETS_32=1 ) else if "%~1"=="+lib-netsockets-64" ( set /a BUILD_LIB_NET_SOCKETS_64=1 + ) else if "%~1"=="+lib-gameoverlay-32" ( + set /a BUILD_LIB_GAMEOVERLAY_32=1 + ) else if "%~1"=="+lib-gameoverlay-64" ( + set /a BUILD_LIB_GAMEOVERLAY_64=1 ) else if "%~1"=="-j" ( call :get_parallel_threads_count %~2 || ( call :err_msg "Invalid arg after -j, expected a number" @@ -175,7 +182,7 @@ set "dos_stub_exe_64=%win_resources_src_dir%\file_dos_stub\file_dos_stub_64.exe" set "protoc_exe_32=%deps_dir%\protobuf\install32\bin\protoc.exe" set "protoc_exe_64=%deps_dir%\protobuf\install64\bin\protoc.exe" -set "common_compiler_args=/std:c++17 /MP%build_threads% /DYNAMICBASE /errorReport:none /nologo /utf-8 /Zc:char8_t- /EHsc /GF /GL- /GS" +set "common_compiler_args=/std:c++17 /permissive- /MP%build_threads% /DYNAMICBASE /errorReport:none /nologo /utf-8 /Zc:char8_t- /EHsc /GF /GL- /GS" set "common_compiler_args_32=%common_compiler_args%" set "common_compiler_args_64=%common_compiler_args%" @@ -391,6 +398,14 @@ if %BUILD_LIB_NET_SOCKETS_32% equ 1 ( echo: & echo: ) +:: gameoverlayrenderer lib (x32) +if %BUILD_LIB_GAMEOVERLAY_32% equ 1 ( + call :compile_gameoverlay_lib_32 || ( + set /a last_code+=1 + ) + echo: & echo: +) + endlocal & set /a last_code=%last_code% @@ -494,6 +509,14 @@ if %BUILD_LIB_NET_SOCKETS_64% equ 1 ( echo: & echo: ) +:: gameoverlayrenderer lib (x64) +if %BUILD_LIB_GAMEOVERLAY_64% equ 1 ( + call :compile_gameoverlay_lib_64 || ( + set /a last_code+=1 + ) + echo: & echo: +) + endlocal & set /a last_code=%last_code% @@ -577,7 +600,7 @@ endlocal & exit /b %_exit% :compile_experimentalclient_32 setlocal - echo // building lib steamclient.dll - 32 + echo // building experimental lib steamclient.dll - 32 set src_files="%win_resources_out_dir%\rsrc-client-32.res" %release_src% "%libs_dir%\detours\*.cpp" "controller\gamepad.c" "overlay_experimental\*.cpp" set extra_inc_dirs=%overlay_inc32% set extra_libs=%overlay_lib32% @@ -591,7 +614,7 @@ endlocal & exit /b %_exit% :compile_experimentalclient_ldr_32 setlocal - echo // building executable steamclient_loader_32.exe - 32 + echo // building experimental executable steamclient_loader_32.exe - 32 set src_files="%win_resources_out_dir%\rsrc-launcher-32.res" "%tools_src_dir%\steamclient_loader\win\*.cpp" "helpers\pe_helpers.cpp" "helpers\common_helpers.cpp" "helpers\dbg_log.cpp" set extra_inc_dirs=/I"%tools_src_dir%\steamclient_loader\win\extra_protection" /I"pe_helpers" set extra_libs="user32.lib" @@ -605,7 +628,7 @@ endlocal & exit /b %_exit% :compile_experimentalclient_extra_32 setlocal - echo // building library steamclient_extra.dll - 32 + echo // building experimental library steamclient_extra.dll - 32 set src_files="%win_resources_out_dir%\rsrc-client-32.res" "%tools_src_dir%\steamclient_loader\win\extra_protection\*.cpp" "helpers\pe_helpers.cpp" "helpers\common_helpers.cpp" "%libs_dir%\detours\*.cpp" set extra_inc_dirs=/I"%tools_src_dir%\steamclient_loader\win\extra_protection" /I"pe_helpers" call :build_for 1 0 "%steamclient_dir%\extra_dlls\steamclient_extra.dll" src_files extra_inc_dirs @@ -652,6 +675,19 @@ endlocal & exit /b %_exit% ) endlocal & exit /b %_exit% +:compile_gameoverlay_lib_32 + setlocal + echo // building experimental library GameOverlayRenderer.dll - 32 + set src_files="game_overlay_renderer_lib\game_overlay_renderer_lib.cpp" + set extra_inc_dirs=/I"game_overlay_renderer_lib" + call :build_for 1 0 "%steamclient_dir%\GameOverlayRenderer.dll" src_files extra_inc_dirs + set /a _exit=%errorlevel% + if %_exit% equ 0 ( + call :change_dos_stub 1 "%steamclient_dir%\GameOverlayRenderer.dll" + call "%signer_tool%" "%steamclient_dir%\GameOverlayRenderer.dll" + ) +endlocal & exit /b %_exit% + :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: x64 @@ -695,7 +731,7 @@ endlocal & exit /b %_exit% :compile_experimentalclient_64 setlocal - echo // building lib steamclient64.dll - 64 + echo // building experimental lib steamclient64.dll - 64 set src_files="%win_resources_out_dir%\rsrc-client-64.res" %release_src% "%libs_dir%\detours\*.cpp" "controller\gamepad.c" "overlay_experimental\*.cpp" set extra_inc_dirs=%overlay_inc64% set extra_libs=%overlay_lib64% @@ -709,7 +745,7 @@ endlocal & exit /b %_exit% :compile_experimentalclient_ldr_64 setlocal - echo // building executable steamclient_loader_64.exe - 64 + echo // building experimental executable steamclient_loader_64.exe - 64 set src_files="%win_resources_out_dir%\rsrc-launcher-64.res" "%tools_src_dir%\steamclient_loader\win\*.cpp" "helpers\pe_helpers.cpp" "helpers\common_helpers.cpp" "helpers\dbg_log.cpp" set extra_inc_dirs=/I"%tools_src_dir%\steamclient_loader\win\extra_protection" /I"pe_helpers" set extra_libs="user32.lib" @@ -723,7 +759,7 @@ endlocal & exit /b %_exit% :compile_experimentalclient_extra_64 setlocal - echo // building library steamclient_extra64.dll - 64 + echo // building experimental library steamclient_extra64.dll - 64 set src_files="%win_resources_out_dir%\rsrc-client-64.res" "%tools_src_dir%\steamclient_loader\win\extra_protection\*.cpp" "helpers\pe_helpers.cpp" "helpers\common_helpers.cpp" "%libs_dir%\detours\*.cpp" set extra_inc_dirs=/I"%tools_src_dir%\steamclient_loader\win\extra_protection" /I"pe_helpers" call :build_for 0 0 "%steamclient_dir%\extra_dlls\steamclient_extra64.dll" src_files extra_inc_dirs @@ -746,6 +782,19 @@ endlocal & exit /b %_exit% ) endlocal & exit /b %_exit% +:compile_gameoverlay_lib_64 + setlocal + echo // building experimental library GameOverlayRenderer64.dll - 64 + set src_files="game_overlay_renderer_lib\game_overlay_renderer_lib.cpp" + set extra_inc_dirs=/I"game_overlay_renderer_lib" + call :build_for 0 0 "%steamclient_dir%\GameOverlayRenderer64.dll" src_files extra_inc_dirs + set /a _exit=%errorlevel% + if %_exit% equ 0 ( + call :change_dos_stub 0 "%steamclient_dir%\GameOverlayRenderer64.dll" + call "%signer_tool%" "%steamclient_dir%\GameOverlayRenderer64.dll" + ) +endlocal & exit /b %_exit% + :err_msg diff --git a/game_overlay_renderer_lib/game_overlay_renderer_lib.cpp b/game_overlay_renderer_lib/game_overlay_renderer_lib.cpp new file mode 100644 index 00000000..14c17a43 --- /dev/null +++ b/game_overlay_renderer_lib/game_overlay_renderer_lib.cpp @@ -0,0 +1,109 @@ +#include "game_overlay_renderer_lib.h" + +static bool overlay_enabled = false; +static bool screenshots_hooked = false; + +static float scale_factor_x = 0.0f; +static float scale_factor_y = 0.0f; + +static int32 notification_inset_x = 0; +static int32 notification_inset_y = 0; + +static ENotificationPosition notification_position = ENotificationPosition::k_EPositionInvalid; + +S_API_EXPORT steam_bool S_CALLTYPE BOverlayNeedsPresent() +{ + return false; +} + + +S_API_EXPORT steam_bool S_CALLTYPE IsOverlayEnabled() +{ + return overlay_enabled; +} + + +S_API_EXPORT void S_CALLTYPE OverlayHookD3D3(void *param_1, void *param_2) +{ + +} + +S_API_EXPORT void S_CALLTYPE SetNotificationInset(int32 param_1, int32 param_2) +{ + if (param_1 >= 0 && param_2 >=0) { + notification_inset_x = param_1; + notification_inset_y = param_2; + } +} + +S_API_EXPORT void S_CALLTYPE SetNotificationPosition(ENotificationPosition param_1) +{ + switch (param_1) + { + case ENotificationPosition::k_EPositionTopLeft: + case ENotificationPosition::k_EPositionTopRight: + case ENotificationPosition::k_EPositionBottomLeft: + case ENotificationPosition::k_EPositionBottomRight: + notification_position = param_1; + break; + + default: break; + } +} + + +S_API_EXPORT steam_bool S_CALLTYPE SteamOverlayIsUsingGamepad() +{ + return false; +} + +S_API_EXPORT steam_bool S_CALLTYPE SteamOverlayIsUsingKeyboard() +{ + return false; +} + +S_API_EXPORT void S_CALLTYPE ValveHookScreenshots(bool param_1) +{ + screenshots_hooked = param_1; +} + +S_API_EXPORT steam_bool S_CALLTYPE ValveIsScreenshotsHooked() +{ + return screenshots_hooked; +} + +#if defined(__WINDOWS_32__) +void __stdcall VirtualFreeWrapper( + void *param_1, void *param_2, + void *stack_cleanup_1, void *stack_cleanup_2, void *stack_cleanup_3, void *stack_cleanup_4, void *stack_cleanup_5, + void *stack_cleanup_6, void *stack_cleanup_7, void *stack_cleanup_8, void *stack_cleanup_9 +) +{ + // https://stackoverflow.com/a/2805560 + #pragma comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__) +} +#endif // __WINDOWS_32__ + +S_API_EXPORT void S_CALLTYPE VulkanSteamOverlayGetScaleFactors(float *param_1, float *param_2) +{ + // the original function doesn't check for nullptr + if (param_1) *param_1 = 0.0f; + if (param_2) *param_2 = 0.0f; +} + +S_API_EXPORT void S_CALLTYPE VulkanSteamOverlayPresent( + void *param_1, int32 param_2, int32 param_3, void *param_4, void * param_5, + void *param_6, void *param_7, void *param_8, void *param_9, void *param_10 +) +{ + +} + + +S_API_EXPORT void S_CALLTYPE VulkanSteamOverlayProcessCapturedFrame( + bool param_1, int32 param_2, int32 param_3, int32 param_4, void *param_5, void *param_6, int32 param_7, + int32 param_8, int32 param_9, int32 param_10, int32 param_11, int16 param_12, int16 param_13, int16 param_14 +) +{ + +} diff --git a/game_overlay_renderer_lib/game_overlay_renderer_lib.h b/game_overlay_renderer_lib/game_overlay_renderer_lib.h new file mode 100644 index 00000000..ca77cdd0 --- /dev/null +++ b/game_overlay_renderer_lib/game_overlay_renderer_lib.h @@ -0,0 +1,70 @@ +// this library is sometimes needed because some apps (like appid 410900) will check +// for its existence inside their memory space during runtime, +// otherwise they'll trigger custom nagging stuff + +// notice how functions return a boolean result as uint32 not bool +// the return value is placed inside the entire 'eax' register, not just 'al' +// you have to disassem both 32-bit and 64-bit libraries to see this nonsense +// ex: 32-bit ValveIsScreenshotsHooked(): mov al, byte ptr ds:[0x7AF62DA1] +// 64-bit ValveIsScreenshotsHooked(): movzx eax, byte ptr ds:[0x00007FF8938F235D] + +#ifndef __GAME_OVERLAY_RENDERER_LIB_H__ +#define __GAME_OVERLAY_RENDERER_LIB_H__ + +#include "dll/common_includes.h" + + +S_API_EXPORT steam_bool S_CALLTYPE BOverlayNeedsPresent(); + +S_API_EXPORT steam_bool S_CALLTYPE IsOverlayEnabled(); + +S_API_EXPORT void S_CALLTYPE OverlayHookD3D3(void *param_1, void *param_2); + +S_API_EXPORT void S_CALLTYPE SetNotificationInset(int32 param_1, int32 param_2); + +S_API_EXPORT void S_CALLTYPE SetNotificationPosition(ENotificationPosition param_1); + +S_API_EXPORT steam_bool S_CALLTYPE SteamOverlayIsUsingGamepad(); + +S_API_EXPORT steam_bool S_CALLTYPE SteamOverlayIsUsingKeyboard(); + +S_API_EXPORT void S_CALLTYPE ValveHookScreenshots(bool param_1); + +S_API_EXPORT steam_bool S_CALLTYPE ValveIsScreenshotsHooked(); + +// only available for 32-bit lib on Windows +// the function takes 2 arguments, but they're expected to be at [esp] & [esp+4] +// notice how the top of the stack is not the return address, but param 1 +// this function might be designed to be invoked via a jmp instruction, +// at the end it does this: +// popad // pop all 8 general purpose registers +// popfd // pop flags register +// ret // regular return +// notice how it eventually deallocates 8+1 registers (4 bytes * 9), +// meaning that (4 bytes * 2 input params) + (4 bytes * 9) are deallocated from the stack + +// note: this is not marked S_API_EXPORT, because later we'll use a linker pragma +// to both export this function, and prevent __stdcall name mangling +#if defined(__WINDOWS_32__) +void __stdcall VirtualFreeWrapper( + void *param_1, void *param_2, + void *stack_cleanup_1, void *stack_cleanup_2, void *stack_cleanup_3, void *stack_cleanup_4, void *stack_cleanup_5, + void *stack_cleanup_6, void *stack_cleanup_7, void *stack_cleanup_8, void *stack_cleanup_9 +); +#endif // __WINDOWS_32__ + +S_API_EXPORT void S_CALLTYPE VulkanSteamOverlayGetScaleFactors(float *param_1, float *param_2); + +S_API_EXPORT void S_CALLTYPE VulkanSteamOverlayPresent( + void *param_1, int32 param_2, int32 param_3, void *param_4, void * param_5, + void *param_6, void *param_7, void *param_8, void *param_9, void *param_10 +); + + +S_API_EXPORT void S_CALLTYPE VulkanSteamOverlayProcessCapturedFrame( + bool param_1, int32 param_2, int32 param_3, int32 param_4, void *param_5, void *param_6, int32 param_7, + int32 param_8, int32 param_9, int32 param_10, int32 param_11, int16 param_12, int16 param_13, int16 param_14 +); + + +#endif // __GAME_OVERLAY_RENDERER_LIB_H__ diff --git a/post_build/README.experimental_steamclient.md b/post_build/README.experimental_steamclient.md index a72c4471..63e39f27 100644 --- a/post_build/README.experimental_steamclient.md +++ b/post_build/README.experimental_steamclient.md @@ -17,17 +17,26 @@ You do not need to create a `steam_interfaces.txt` file for the `steamclient` ve * `steamclient64.dll` * `ColdClientLoader.ini` * `steamclient_loader.exe` -2. Edit `ColdClientLoader.ini` and specify: + +2. While it is not mandatory, it is highly recommended to copy the relevant `GameOverlayRenderer` dll(s) + This is recommended because some apps check for the existence of this dll, either on disk, on inside their memory space, otherwise they'll trigger custom protection. + When in doubt, just copy both dlls. + * `GameOverlayRenderer.dll`: for 32-bit apps + * `GameOverlayRenderer64.dll`: for 64-bit apps + +3. Edit `ColdClientLoader.ini` and specify: * `AppId`: the app ID * `Exe`: the path to the game's executable/launcher, either full path or relative to this loader * `ExeRunDir` *(optional)*: generally this must be set to the folder containing the game's exe, if left empty then it will be automatically set to the folder containing the game's exe. * `ExeCommandLine` *(optional)*: additional args to pass to the exe, example: `-dx11 -windowed` - Optionally you can specify a different location for `steamclient(64).dll`: + Optionally you can specify a different location for `steamclient(64).dll`: * `SteamClientDll`: path to `steamclient.dll`, either full path or relative to this loader - * `SteamClient64Dll`: path to `steamclient(64).dll`, either full path or relative to this loader + * `SteamClient64Dll`: path to `steamclient64.dll`, either full path or relative to this loader * `ForceInjectSteamClient`: force inject `steamclient(64).dll` instead of letting the app load it automatically + * `ForceInjectGameOverlayRenderer`: force inject `GameOverlayRenderer(64).dll` instead of letting the app load it automatically. + These dlls are expected to be in the same folder of `steamclient(64).dll` * `ResumeByDebugger`: setting this to `1` or `y` or `true` will prevent the loader from calling `ResumeThread()` on the main thread after spawning the .exe, and it will display a mesage with the process ID (PID) so you attach your debugger on it. - Note that you have to resume the main thread from the debugger after attaching, also the entry breakpoint may not be set automatically, but you can do that manually. + Note that you have to resume the main thread from the debugger after attaching, also the entry breakpoint may not be set automatically, but you can do that manually. * `DllsToInjectFolder` *(optional)*: path to a folder containing dlls to force inject into the app upon start, the loader will attempt to detect the dll architecture (32 or 64 bit), if it didn't match the architecture of the exe, then it will ignored * `IgnoreInjectionError`: setting this to `1` or `y` or `true` will prevent the loader from displaying an error message when a dll injection fails @@ -59,4 +68,12 @@ Any .dll file not mentioned in this file will be loaded later, but in random ord --- ## `extra_dlls` -This folder contains an experimental dll which, when injected, will attempt to patch the Stub drm in meory, only for v3.1 +This folder contains an experimental dll which, when injected, will attempt to patch the Stub drm in memory, mainly for newer variants but it also works on some of the older ones. + +This isn't a complete solution, just a different method. + +--- + +## `GameOverlayRenderer` +Some apps verify the existence of this dll, either on disk, or inside their memory space, that's why this dll exists. +It is **NOT** recommended to ignore this dll. diff --git a/tools/steamclient_loader/win/ColdClientLoader.cpp b/tools/steamclient_loader/win/ColdClientLoader.cpp index 1849e625..bb85314b 100644 --- a/tools/steamclient_loader/win/ColdClientLoader.cpp +++ b/tools/steamclient_loader/win/ColdClientLoader.cpp @@ -79,7 +79,7 @@ static std::vector get_pe_header(const std::wstring &filepath) static std::vector collect_dlls_to_inject( const std::wstring &extra_dlls_folder, bool is_exe_32, - std::wstring &failed_dlls = std::wstring{}) + std::wstring &failed_dlls) { const auto load_order_file = std::filesystem::path(extra_dlls_folder) / "load_order.txt"; std::vector dlls_to_inject{}; @@ -361,6 +361,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance // dlls to inject std::wstring ForceInjectSteamClient = get_ini_value(L"Injection", L"ForceInjectSteamClient"); + std::wstring ForceInjectGameOverlayRenderer = get_ini_value(L"Injection", L"ForceInjectGameOverlayRenderer"); std::wstring DllsToInjectFolder = common_helpers::to_absolute( get_ini_value(L"Injection", L"DllsToInjectFolder"), pe_helpers::get_current_exe_path_w() @@ -374,6 +375,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance std::wstring ResumeByDebugger = get_ini_value(L"Debug", L"ResumeByDebugger"); to_bool_ini_val(ForceInjectSteamClient); + to_bool_ini_val(ForceInjectGameOverlayRenderer); to_bool_ini_val(IgnoreInjectionError); to_bool_ini_val(IgnoreLoaderArchDifference); to_bool_ini_val(ResumeByDebugger); @@ -388,6 +390,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance dbg_log::write(L"SteamClient::SteamClient64Dll: " + Client64Path); dbg_log::write(L"SteamClient::PersistentMode: " + PersistentMode); dbg_log::write(L"SteamClient::ForceInjectSteamClient: " + ForceInjectSteamClient); + dbg_log::write(L"SteamClient::ForceInjectGameOverlayRenderer: " + ForceInjectGameOverlayRenderer); dbg_log::write(L"Injection::DllsToInjectFolder: " + DllsToInjectFolder); dbg_log::write(L"Injection::IgnoreInjectionError: " + IgnoreInjectionError); dbg_log::write(L"Injection::IgnoreLoaderArchDifference: " + IgnoreLoaderArchDifference); @@ -487,6 +490,31 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance } } } + if (ForceInjectGameOverlayRenderer.size()) { + if (is_exe_32) { + std::wstring GameOverlayPath = common_helpers::to_absolute( + L"GameOverlayRenderer.dll", + std::filesystem::path(ClientPath).parent_path().wstring() + ); + if (!common_helpers::file_exist(GameOverlayPath)) { + dbg_log::write("Couldn't find GameOverlayRenderer.dll"); + MessageBoxA(NULL, "Couldn't find GameOverlayRenderer.dll.", "ColdClientLoader", MB_ICONERROR); + } else { + dlls_to_inject.insert(dlls_to_inject.begin(), GameOverlayPath); + } + } else { // 64 + std::wstring GameOverlay64Path = common_helpers::to_absolute( + L"GameOverlayRenderer64.dll", + std::filesystem::path(Client64Path).parent_path().wstring() + ); + if (!common_helpers::file_exist(GameOverlay64Path)) { + dbg_log::write("Couldn't find GameOverlayRenderer64.dll"); + MessageBoxA(NULL, "Couldn't find GameOverlayRenderer64.dll.", "ColdClientLoader", MB_ICONERROR); + } else { + dlls_to_inject.insert(dlls_to_inject.begin(), GameOverlay64Path); + } + } + } if (ForceInjectSteamClient.size()) { if (is_exe_32) { dlls_to_inject.insert(dlls_to_inject.begin(), ClientPath); diff --git a/tools/steamclient_loader/win/ColdClientLoader.ini b/tools/steamclient_loader/win/ColdClientLoader.ini index e4451568..3f7c26e2 100644 --- a/tools/steamclient_loader/win/ColdClientLoader.ini +++ b/tools/steamclient_loader/win/ColdClientLoader.ini @@ -18,6 +18,9 @@ SteamClient64Dll=steamclient64.dll # force inject steamclient dll instead of waiting for the app to load it ForceInjectSteamClient=0 +# force inject GameOverlayRenderer dll instead of waiting for the app to load it +ForceInjectGameOverlayRenderer=0 + # path to a folder containing some dlls to inject into the app upon start # this folder will be traversed recursively # additionally, inside this folder you can create a file called `load_order.txt` and