/* * Copyright (c) 2019, Valve Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* This is a stub steam.exe implementation for use inside Proton. It provides * a small subset of the actual Steam functionality for games that expect * Windows version of Steam running. */ #include #pragma push_macro("_WIN32") #pragma push_macro("__cdecl") #undef _WIN32 #undef __cdecl #include "steam_api.h" #pragma pop_macro("_WIN32") #pragma pop_macro("__cdecl") #include "wine/unicode.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(steam); EXTERN_C HANDLE CDECL __wine_make_process_system(void); static void set_active_process_pid(void) { DWORD pid = GetCurrentProcessId(); RegSetKeyValueA(HKEY_CURRENT_USER, "Software\\Valve\\Steam\\ActiveProcess", "pid", REG_DWORD, &pid, sizeof(pid)); } static DWORD WINAPI create_steam_window(void *arg) { static WNDCLASSEXW wndclass = { sizeof(WNDCLASSEXW) }; static const WCHAR class_nameW[] = {'v','g','u','i','P','o','p','u','p','W','i','n','d','o','w',0}; static const WCHAR steamW[] = {'S','t','e','a','m',0}; MSG msg; wndclass.lpfnWndProc = DefWindowProcW; wndclass.lpszClassName = class_nameW; RegisterClassExW(&wndclass); CreateWindowW(class_nameW, steamW, WS_POPUP, 40, 40, 400, 300, NULL, NULL, NULL, NULL); while (GetMessageW(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } static void setup_steam_registry(void) { const char *ui_lang; uint32 appid; char buf[256]; HKEY key; LSTATUS status; if (!SteamAPI_Init()) { WINE_ERR("SteamAPI_Init failed\n"); return; } ui_lang = SteamUtils()->GetSteamUILanguage(); WINE_TRACE("UI language: %s\n", wine_dbgstr_a(ui_lang)); RegSetKeyValueA(HKEY_CURRENT_USER, "Software\\Valve\\Steam", "language", REG_SZ, ui_lang, strlen(ui_lang) + 1); appid = SteamUtils()->GetAppID(); WINE_TRACE("appid: %u\n", appid); sprintf(buf, "Software\\Valve\\Steam\\Apps\\%u", appid); status = RegCreateKeyA(HKEY_CURRENT_USER, buf, &key); if (!status) { DWORD value; value = 1; RegSetKeyValueA(key, NULL, "Installed", REG_DWORD, &value, sizeof(value)); RegSetKeyValueA(key, NULL, "Running", REG_DWORD, &value, sizeof(value)); value = 0; RegSetKeyValueA(key, NULL, "Updating", REG_DWORD, &value, sizeof(value)); RegCloseKey(key); } else WINE_ERR("Could not create key: %u\n", status); SteamAPI_Shutdown(); } static int run_process(void) { WCHAR *cmdline = GetCommandLineW(); STARTUPINFOW si = { sizeof(si) }; PROCESS_INFORMATION pi; /* skip argv[0] */ if (*cmdline == '"') { cmdline = strchrW(cmdline + 1, '"'); if (cmdline) cmdline++; } else { cmdline = strchrW(cmdline, ' '); } if (!cmdline) { WINE_ERR("Invalid command\n"); return 1; } while (*cmdline == ' ') cmdline++; WINE_TRACE("Running command %s\n", wine_dbgstr_w(cmdline)); if (!CreateProcessW(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { WINE_ERR("Failed to create process %s: %u\n", wine_dbgstr_w(cmdline), GetLastError()); return 1; } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return 0; } int main(int argc, char *argv[]) { WINE_TRACE("\n"); CreateThread(NULL, 0, create_steam_window, NULL, 0, NULL); set_active_process_pid(); setup_steam_registry(); if (argc > 1) { int ret = run_process(); if (ret) return ret; } WaitForSingleObject(__wine_make_process_system(), INFINITE); return 0; }