diff --git a/steamshim/steamshim_child.c b/steamshim/steamshim_child.c index 4c089d7..eb2fd3c 100644 --- a/steamshim/steamshim_child.c +++ b/steamshim/steamshim_child.c @@ -65,12 +65,11 @@ static void closePipe(PipeType fd) CloseHandle(fd); } /* closePipe */ -static char *getEnvVar(const char *key, char *buf, const size_t _buflen) +static char *getEnvVar(const char *key, char *buf, const size_t buflen) { - const DWORD buflen = (DWORD) _buflen; const DWORD rc = GetEnvironmentVariableA(key, buf, buflen); /* rc doesn't count null char, hence "<". */ - return ((rc > 0) && (rc < buflen)) ? NULL : buf; + return ((rc > 0) && (rc < buflen)) ? buf : NULL; } /* getEnvVar */ #else @@ -157,21 +156,14 @@ static inline int writeBye(void) static int initPipes(void) { char buf[64]; - unsigned long long val; if (!getEnvVar("STEAMSHIM_READHANDLE", buf, sizeof (buf))) return 0; - else if ((val = strtoull(buf, 0, 10)) == 0) - return 0; - else - GPipeRead = (PipeType) val; + GPipeRead = (PipeType) strtoull(buf, 0, 10); if (!getEnvVar("STEAMSHIM_WRITEHANDLE", buf, sizeof (buf))) return 0; - else if ((val = strtoull(buf, 0, 10)) == 0) - return 0; - else - GPipeWrite = (PipeType) val; + GPipeWrite = (PipeType) strtoull(buf, 0, 10); return ((GPipeRead != NULLPIPE) && (GPipeWrite != NULLPIPE)); } /* initPipes */ diff --git a/steamshim_parent/Makefile b/steamshim_parent/Makefile index ca8201a..fd4bad3 100644 --- a/steamshim_parent/Makefile +++ b/steamshim_parent/Makefile @@ -4,7 +4,7 @@ GAME_LAUNCH_NAME ?= oneshot CXX ?= clang++ WINDRES ?= windres HOST ?= linux64 -FLAGS := -I$(STEAMWORKS)/public -DGAME_LAUNCH_NAME=\"$(GAME_LAUNCH_NAME)\" +FLAGS := -I$(STEAMWORKS)/public -DGAME_LAUNCH_NAME=\"$(GAME_LAUNCH_NAME)\" -Wall ifeq ($(HOST),w32) FLAGS += -L$(STEAMWORKS)/redistributable_bin -mwindows diff --git a/steamshim_parent/steamshim_parent.cpp b/steamshim_parent/steamshim_parent.cpp index 4fe85d6..d6550bb 100644 --- a/steamshim_parent/steamshim_parent.cpp +++ b/steamshim_parent/steamshim_parent.cpp @@ -9,18 +9,21 @@ typedef PROCESS_INFORMATION ProcessType; typedef HANDLE PipeType; #define NULLPIPE NULL +#define LLUFMT "%I64u" #else #include -#include #include #include #include #include #include +#include typedef pid_t ProcessType; typedef int PipeType; #define NULLPIPE -1 +#define LLUFMT "%llu" #endif +#include #include "steam/steam_api.h" @@ -99,11 +102,57 @@ static bool setEnvVar(const char *key, const char *val) return (SetEnvironmentVariableA(key, val) != 0); } // setEnvVar +static LPWSTR genCommandLine() +{ + // Construct a command line with the appropriate filename + LPWSTR cmdline = GetCommandLineW(); + + // Find the index of the first argument after 0 + int iFirstArg = -1; + bool quote = false; + bool whitespace = false; + for (int i = 0; cmdline[i]; ++i) + { + if (cmdline[i] == '"' && (i == 0 || cmdline[i-1] != '\\')) + { + quote = !quote; + whitespace = false; + } + else if (!quote && (cmdline[i] == ' ' || cmdline[i] == '\t')) + { + whitespace = true; + } + else + { + if (whitespace) + { + iFirstArg = i; + break; + } + whitespace = false; + } + } + + // If it doesn't exist, that must mean there are no arguments, + // so just return GAME_LAUNCH_NAME + if (iFirstArg == -1) + return _wcsdup(TEXT("\".\\" GAME_LAUNCH_NAME ".exe\"")); + + // Create the new string + // (`".\.exe" ` == +9 + LPWSTR newcmdline = (LPWSTR)malloc(sizeof(TEXT(GAME_LAUNCH_NAME)) + + sizeof(WCHAR) * (wcslen(cmdline) - iFirstArg + 9)); + wsprintf(newcmdline, TEXT("\".\\" GAME_LAUNCH_NAME ".exe\" %s"), cmdline + iFirstArg); + return newcmdline; +} + static bool launchChild(ProcessType *pid) { - return (CreateProcessW(TEXT(".\\") TEXT(GAME_LAUNCH_NAME) TEXT(".exe"), - GetCommandLineW(), NULL, NULL, TRUE, 0, NULL, - NULL, NULL, pid) != 0); + STARTUPINFOW si; + memset(&si, 0, sizeof(si)); + return CreateProcessW(TEXT(".\\" GAME_LAUNCH_NAME ".exe"), + genCommandLine(), NULL, NULL, TRUE, 0, NULL, + NULL, &si, pid); } // launchChild static int closeProcess(ProcessType *pid) @@ -153,6 +202,8 @@ static bool createPipes(PipeType *pPipeParentRead, PipeType *pPipeParentWrite, int fds[2]; if (pipe(fds) == -1) return 0; + fcntl(fds[0], F_SETFL, 0); + fcntl(fds[1], F_SETFL, 0); *pPipeParentRead = fds[0]; *pPipeChildWrite = fds[1]; @@ -163,6 +214,8 @@ static bool createPipes(PipeType *pPipeParentRead, PipeType *pPipeParentWrite, return 0; } // if + fcntl(fds[0], F_SETFL, 0); + fcntl(fds[1], F_SETFL, 0); *pPipeChildRead = fds[0]; *pPipeParentWrite = fds[1]; @@ -337,7 +390,7 @@ static bool writeAchievementGet(PipeType fd, const char *name, const int status, { uint8 buf[256]; uint8 *ptr = buf+1; - dbgpipe("Parent sending SHIMEVENT_GETACHIEVEMENT('%s', status %d, time %llu).\n", name, status, (unsigned long long) time); + dbgpipe("Parent sending SHIMEVENT_GETACHIEVEMENT('%s', status %d, time " LLUFMT ").\n", name, status, (unsigned long long) time); *(ptr++) = (uint8) SHIMEVENT_GETACHIEVEMENT; *(ptr++) = (uint8) status; memcpy(ptr, &time, sizeof (time)); @@ -601,11 +654,11 @@ static void processCommands(PipeType pipeParentRead, PipeType pipeParentWrite) static bool setEnvironmentVars(PipeType pipeChildRead, PipeType pipeChildWrite) { char buf[64]; - snprintf(buf, sizeof (buf), "%llu", (unsigned long long) pipeChildRead); + snprintf(buf, sizeof (buf), LLUFMT, (unsigned long long) pipeChildRead); if (!setEnvVar("STEAMSHIM_READHANDLE", buf)) return false; - snprintf(buf, sizeof (buf), "%llu", (unsigned long long) pipeChildWrite); + snprintf(buf, sizeof (buf), LLUFMT, (unsigned long long) pipeChildWrite); if (!setEnvVar("STEAMSHIM_WRITEHANDLE", buf)) return false;