diff --git a/Readme_experimental_steamclient.txt b/Readme_experimental_steamclient.txt new file mode 100644 index 0000000..247ccd2 --- /dev/null +++ b/Readme_experimental_steamclient.txt @@ -0,0 +1,4 @@ +This is a build of the experimental version of my emu in steamclient mode with an included loader. See both the regular and experimental readmes for how to configure it. +Note that all emu config files should be put beside the steamclient dll. You do not need to put a steam_interfaces.txt file for the steamclient version of the emu. + +To use the loader, put both steamclient dlls and the loader in a folder and edit the config file. Make sure you put the right appid in the ini file. diff --git a/build_win_release.bat b/build_win_release.bat index 895303a..ac30a9e 100755 --- a/build_win_release.bat +++ b/build_win_release.bat @@ -2,6 +2,7 @@ cd /d "%~dp0" del /Q /S release\* rmdir /S /Q release\experimental +rmdir /S /Q release\experimental_steamclient rmdir /S /Q release\lobby_connect rmdir /S /Q release mkdir release @@ -18,5 +19,6 @@ cl /LD /DEMU_RELEASE_BUILD /DNDEBUG /I%PROTOBUF_X64_DIRECTORY%\include\ dll/*.cp copy Readme_release.txt release\Readme.txt xcopy /s files_example\* release\ call build_win_release_experimental.bat +call build_win_release_experimental_steamclient.bat call build_win_lobby_connect.bat call build_win_find_interfaces.bat diff --git a/build_win_release_experimental_steamclient.bat b/build_win_release_experimental_steamclient.bat new file mode 100644 index 0000000..1a1312e --- /dev/null +++ b/build_win_release_experimental_steamclient.bat @@ -0,0 +1,16 @@ +@echo off +cd /d "%~dp0" +mkdir release\experimental_steamclient +del /Q release\experimental_steamclient\* +call build_set_protobuf_directories.bat +"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto +call build_env_x86.bat +cl dll/rtlgenrandom.c dll/rtlgenrandom.def +cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DSTEAMCLIENT_DLL /DCONTROLLER_SUPPORT /DNDEBUG /I%PROTOBUF_X86_DIRECTORY%\include\ dll/*.cpp dll/*.cc detours/*.cpp controller/gamepad.c "%PROTOBUF_X86_LIBRARY%" Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\experimental_steamclient\steamclient.dll +"%PROTOC_X64_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto +cl steamclient_loader/*.cpp advapi32.lib user32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\experimental_steamclient\steamclient_loader.exe +copy steamclient_loader\ColdClientLoader.ini release\experimental_steamclient\ +call build_env_x64.bat +cl dll/rtlgenrandom.c dll/rtlgenrandom.def +cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DSTEAMCLIENT_DLL /DCONTROLLER_SUPPORT /DNDEBUG /I%PROTOBUF_X64_DIRECTORY%\include\ dll/*.cpp dll/*.cc detours/*.cpp controller/gamepad.c "%PROTOBUF_X64_LIBRARY%" Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\experimental_steamclient\steamclient64.dll +copy Readme_experimental_steamclient.txt release\experimental_steamclient\Readme.txt diff --git a/steamclient_loader/ColdClientLoader.cpp b/steamclient_loader/ColdClientLoader.cpp new file mode 100644 index 0000000..a43363b --- /dev/null +++ b/steamclient_loader/ColdClientLoader.cpp @@ -0,0 +1,216 @@ +// My own modified version of ColdClientLoader originally written by Rat431 + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files +#include +// C RunTime Header Files +#include +#include +#include +#include + +bool IsNotRelativePathOrRemoveFileName(CHAR* output, bool Remove) +{ + int LG = lstrlenA(output); + for (int i = LG; i > 0; i--) { + if (output[i] == '\\') { + if(Remove) + RtlFillMemory(&output[i], LG - i, NULL); + return true; + } + } + return false; +} + +int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) +{ + CHAR CurrentDirectory[MAX_PATH] = { 0 }; + CHAR Client64Path[MAX_PATH] = { 0 }; + CHAR ClientPath[MAX_PATH] = { 0 }; + CHAR ExeFile[MAX_PATH] = { 0 }; + CHAR ExeRunDir[MAX_PATH] = { 0 }; + CHAR ExeCommandLine[300] = { 0 }; + CHAR AppId[128] = { 0 }; + + STARTUPINFOA info = { sizeof(info) }; + PROCESS_INFORMATION processInfo; + + int Length = GetModuleFileNameA(GetModuleHandleA(NULL), CurrentDirectory, sizeof(CurrentDirectory)) + 1; + for (int i = Length; i > 0; i--) { + if (CurrentDirectory[i] == '\\') { + lstrcpyA(&CurrentDirectory[i + 1], "ColdClientLoader.ini"); + break; + } + } + if (GetFileAttributesA(CurrentDirectory) == INVALID_FILE_ATTRIBUTES) { + MessageBoxA(NULL, "Couldn't find the configuration file(ColdClientLoader.ini).", "ColdClientLoader", MB_ICONERROR); + ExitProcess(NULL); + } + + GetPrivateProfileStringA("SteamClient", "SteamClient64Dll", "", Client64Path, MAX_PATH, CurrentDirectory); + GetPrivateProfileStringA("SteamClient", "SteamClientDll", "", ClientPath, MAX_PATH, CurrentDirectory); + GetPrivateProfileStringA("SteamClient", "Exe", NULL, ExeFile, MAX_PATH, CurrentDirectory); + GetPrivateProfileStringA("SteamClient", "ExeRunDir", NULL, ExeRunDir, MAX_PATH, CurrentDirectory); + GetPrivateProfileStringA("SteamClient", "ExeCommandLine", NULL, ExeCommandLine, 300, CurrentDirectory); + GetPrivateProfileStringA("SteamClient", "AppId", NULL, AppId, sizeof(AppId), CurrentDirectory); + + if (AppId[0]) { + SetEnvironmentVariableA("SteamAppId", AppId); + SetEnvironmentVariableA("SteamGameId", AppId); + } + + CHAR TMP[MAX_PATH] = { 0 }; + if (!IsNotRelativePathOrRemoveFileName(Client64Path, false)) { + ZeroMemory(TMP, sizeof(TMP)); + lstrcpyA(TMP, Client64Path); + ZeroMemory(Client64Path, sizeof(Client64Path)); + GetFullPathNameA(TMP, MAX_PATH, Client64Path, NULL); + } + if (!IsNotRelativePathOrRemoveFileName(ClientPath, false)) { + ZeroMemory(TMP, sizeof(TMP)); + lstrcpyA(TMP, ClientPath); + ZeroMemory(ClientPath, sizeof(ClientPath)); + GetFullPathNameA(TMP, MAX_PATH, ClientPath, NULL); + } + if (!IsNotRelativePathOrRemoveFileName(ExeFile, false)) { + ZeroMemory(TMP, sizeof(TMP)); + lstrcpyA(TMP, ExeFile); + ZeroMemory(ExeFile, sizeof(ExeFile)); + GetFullPathNameA(TMP, MAX_PATH, ExeFile, NULL); + } + if (!IsNotRelativePathOrRemoveFileName(ExeRunDir, false)) { + ZeroMemory(TMP, sizeof(TMP)); + lstrcpyA(TMP, ExeRunDir); + ZeroMemory(ExeRunDir, sizeof(ExeRunDir)); + GetFullPathNameA(TMP, MAX_PATH, ExeRunDir, NULL); + } + + if (GetFileAttributesA(Client64Path) == INVALID_FILE_ATTRIBUTES) { + MessageBoxA(NULL, "Couldn't find the requested SteamClient64Dll.", "ColdClientLoader", MB_ICONERROR); + ExitProcess(NULL); + } + + if (GetFileAttributesA(ClientPath) == INVALID_FILE_ATTRIBUTES) { + MessageBoxA(NULL, "Couldn't find the requested SteamClientDll.", "ColdClientLoader", MB_ICONERROR); + ExitProcess(NULL); + } + + if (GetFileAttributesA(ExeFile) == INVALID_FILE_ATTRIBUTES) { + MessageBoxA(NULL, "Couldn't find the requested Exe file.", "ColdClientLoader", MB_ICONERROR); + ExitProcess(NULL); + } + + if (ExeFile[0] != NULL && CreateProcessA(ExeFile, ExeCommandLine, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, ExeRunDir, &info, &processInfo)) + { + + } + else + { + MessageBoxA(NULL, "Unable to load the requested EXE file.", "ColdClientLoader", MB_ICONERROR); + ExitProcess(NULL); + } + HKEY Registrykey; + // Declare some variables to be used for Steam registry. + DWORD UserId = 0x03100004771F810D & 0xffffffff; + DWORD ProcessID = GetCurrentProcessId(); + + if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Valve\\Steam\\ActiveProcess", 0, KEY_ALL_ACCESS, &Registrykey) != ERROR_SUCCESS) + { + if (RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Valve\\Steam\\ActiveProcess", 0, 0, REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, NULL, &Registrykey, NULL) != ERROR_SUCCESS) + { + MessageBoxA(NULL, "Unable to patch Steam process informations on the Windows registry.", "ColdClientLoader", MB_ICONERROR); + TerminateProcess(processInfo.hProcess, NULL); + ExitProcess(NULL); + } + else + { + + // Set values to Windows registry. + RegSetValueExA(Registrykey, "ActiveUser", NULL, REG_DWORD, (LPBYTE)& UserId, sizeof(DWORD)); + RegSetValueExA(Registrykey, "pid", NULL, REG_DWORD, (LPBYTE)& ProcessID, sizeof(DWORD)); + + { + // Before saving to the registry check again if the path was valid and if the file exist + if (GetFileAttributesA(ClientPath) != INVALID_FILE_ATTRIBUTES) { + RegSetValueExA(Registrykey, "SteamClientDll", NULL, REG_SZ, (LPBYTE)ClientPath, (DWORD)lstrlenA(ClientPath) + 1); + } + else { + RegSetValueExA(Registrykey, "SteamClientDll", NULL, REG_SZ, (LPBYTE)"", (DWORD)lstrlenA(ClientPath) + 1); + } + if (GetFileAttributesA(Client64Path) != INVALID_FILE_ATTRIBUTES) { + RegSetValueExA(Registrykey, "SteamClientDll64", NULL, REG_SZ, (LPBYTE)Client64Path, (DWORD)lstrlenA(Client64Path) + 1); + } + else { + RegSetValueExA(Registrykey, "SteamClientDll64", NULL, REG_SZ, (LPBYTE)"", (DWORD)lstrlenA(Client64Path) + 1); + } + } + RegSetValueExA(Registrykey, "Universe", NULL, REG_SZ, (LPBYTE)"Public", (DWORD)lstrlenA("Public") + 1); + + // Close the HKEY Handle. + RegCloseKey(Registrykey); + + ResumeThread(processInfo.hThread); + WaitForSingleObject(processInfo.hThread, INFINITE); + CloseHandle(processInfo.hProcess); + CloseHandle(processInfo.hThread); + ExitProcess(NULL); + } + } + else + { + DWORD keyType = REG_SZ; + CHAR OrgSteamCDir[MAX_PATH] = { 0 }; + CHAR OrgSteamCDir64[MAX_PATH] = { 0 }; + DWORD Size1 = MAX_PATH; + DWORD Size2 = MAX_PATH; + + // Get original values to restore later. + RegQueryValueExA(Registrykey, "SteamClientDll", 0, &keyType, (LPBYTE)& OrgSteamCDir, &Size1); + RegQueryValueExA(Registrykey, "SteamClientDll64", 0, &keyType, (LPBYTE)& OrgSteamCDir64, &Size2); + + // Set values to Windows registry. + RegSetValueExA(Registrykey, "ActiveUser", NULL, REG_DWORD, (LPBYTE)& UserId, sizeof(DWORD)); + RegSetValueExA(Registrykey, "pid", NULL, REG_DWORD, (LPBYTE)& ProcessID, sizeof(DWORD)); + + + { + // Before saving to the registry check again if the path was valid and if the file exist + if (GetFileAttributesA(ClientPath) != INVALID_FILE_ATTRIBUTES) { + RegSetValueExA(Registrykey, "SteamClientDll", NULL, REG_SZ, (LPBYTE)ClientPath, (DWORD)lstrlenA(ClientPath) + 1); + } + else { + RegSetValueExA(Registrykey, "SteamClientDll", NULL, REG_SZ, (LPBYTE)"", (DWORD)lstrlenA(ClientPath) + 1); + } + if (GetFileAttributesA(Client64Path) != INVALID_FILE_ATTRIBUTES) { + RegSetValueExA(Registrykey, "SteamClientDll64", NULL, REG_SZ, (LPBYTE)Client64Path, (DWORD)lstrlenA(Client64Path) + 1); + } + else { + RegSetValueExA(Registrykey, "SteamClientDll64", NULL, REG_SZ, (LPBYTE)"", (DWORD)lstrlenA(Client64Path) + 1); + } + } + RegSetValueExA(Registrykey, "Universe", NULL, REG_SZ, (LPBYTE)"Public", (DWORD)lstrlenA("Public") + 1); + + // Close the HKEY Handle. + RegCloseKey(Registrykey); + + ResumeThread(processInfo.hThread); + WaitForSingleObject(processInfo.hThread, INFINITE); + CloseHandle(processInfo.hProcess); + CloseHandle(processInfo.hThread); + + if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Valve\\Steam\\ActiveProcess", 0, KEY_ALL_ACCESS, &Registrykey) == ERROR_SUCCESS) + { + // Restore the values. + RegSetValueExA(Registrykey, "SteamClientDll", NULL, REG_SZ, (LPBYTE)OrgSteamCDir, (DWORD)lstrlenA(OrgSteamCDir) + 1); + RegSetValueExA(Registrykey, "SteamClientDll64", NULL, REG_SZ, (LPBYTE)OrgSteamCDir64, (DWORD)lstrlenA(OrgSteamCDir64) + 1); + + // Close the HKEY Handle. + RegCloseKey(Registrykey); + } + ExitProcess(NULL); + } + + + return 1; +} diff --git a/steamclient_loader/ColdClientLoader.ini b/steamclient_loader/ColdClientLoader.ini new file mode 100644 index 0000000..bc65aa2 --- /dev/null +++ b/steamclient_loader/ColdClientLoader.ini @@ -0,0 +1,10 @@ +#My own modified version of ColdClientLoader originally by Rat431 +[SteamClient] +Exe=game.exe +ExeRunDir=. +ExeCommandLine= +#IMPORTANT: +AppId= + +SteamClientDll=steamclient.dll +SteamClient64Dll=steamclient64.dll