Fix steamshim on OS X and Windows

This commit is contained in:
Mathew Velasquez 2016-02-29 04:03:36 -05:00
parent 546f29f42e
commit 6f3d70e6e4
3 changed files with 65 additions and 20 deletions

View file

@ -65,12 +65,11 @@ static void closePipe(PipeType fd)
CloseHandle(fd); CloseHandle(fd);
} /* closePipe */ } /* 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); const DWORD rc = GetEnvironmentVariableA(key, buf, buflen);
/* rc doesn't count null char, hence "<". */ /* rc doesn't count null char, hence "<". */
return ((rc > 0) && (rc < buflen)) ? NULL : buf; return ((rc > 0) && (rc < buflen)) ? buf : NULL;
} /* getEnvVar */ } /* getEnvVar */
#else #else
@ -157,21 +156,14 @@ static inline int writeBye(void)
static int initPipes(void) static int initPipes(void)
{ {
char buf[64]; char buf[64];
unsigned long long val;
if (!getEnvVar("STEAMSHIM_READHANDLE", buf, sizeof (buf))) if (!getEnvVar("STEAMSHIM_READHANDLE", buf, sizeof (buf)))
return 0; return 0;
else if ((val = strtoull(buf, 0, 10)) == 0) GPipeRead = (PipeType) strtoull(buf, 0, 10);
return 0;
else
GPipeRead = (PipeType) val;
if (!getEnvVar("STEAMSHIM_WRITEHANDLE", buf, sizeof (buf))) if (!getEnvVar("STEAMSHIM_WRITEHANDLE", buf, sizeof (buf)))
return 0; return 0;
else if ((val = strtoull(buf, 0, 10)) == 0) GPipeWrite = (PipeType) strtoull(buf, 0, 10);
return 0;
else
GPipeWrite = (PipeType) val;
return ((GPipeRead != NULLPIPE) && (GPipeWrite != NULLPIPE)); return ((GPipeRead != NULLPIPE) && (GPipeWrite != NULLPIPE));
} /* initPipes */ } /* initPipes */

View file

@ -4,7 +4,7 @@ GAME_LAUNCH_NAME ?= oneshot
CXX ?= clang++ CXX ?= clang++
WINDRES ?= windres WINDRES ?= windres
HOST ?= linux64 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) ifeq ($(HOST),w32)
FLAGS += -L$(STEAMWORKS)/redistributable_bin -mwindows FLAGS += -L$(STEAMWORKS)/redistributable_bin -mwindows

View file

@ -9,18 +9,21 @@
typedef PROCESS_INFORMATION ProcessType; typedef PROCESS_INFORMATION ProcessType;
typedef HANDLE PipeType; typedef HANDLE PipeType;
#define NULLPIPE NULL #define NULLPIPE NULL
#define LLUFMT "%I64u"
#else #else
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <signal.h> #include <signal.h>
#include <fcntl.h>
typedef pid_t ProcessType; typedef pid_t ProcessType;
typedef int PipeType; typedef int PipeType;
#define NULLPIPE -1 #define NULLPIPE -1
#define LLUFMT "%llu"
#endif #endif
#include <stdlib.h>
#include "steam/steam_api.h" #include "steam/steam_api.h"
@ -99,11 +102,57 @@ static bool setEnvVar(const char *key, const char *val)
return (SetEnvironmentVariableA(key, val) != 0); return (SetEnvironmentVariableA(key, val) != 0);
} // setEnvVar } // 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) static bool launchChild(ProcessType *pid)
{ {
return (CreateProcessW(TEXT(".\\") TEXT(GAME_LAUNCH_NAME) TEXT(".exe"), STARTUPINFOW si;
GetCommandLineW(), NULL, NULL, TRUE, 0, NULL, memset(&si, 0, sizeof(si));
NULL, NULL, pid) != 0); return CreateProcessW(TEXT(".\\" GAME_LAUNCH_NAME ".exe"),
genCommandLine(), NULL, NULL, TRUE, 0, NULL,
NULL, &si, pid);
} // launchChild } // launchChild
static int closeProcess(ProcessType *pid) static int closeProcess(ProcessType *pid)
@ -153,6 +202,8 @@ static bool createPipes(PipeType *pPipeParentRead, PipeType *pPipeParentWrite,
int fds[2]; int fds[2];
if (pipe(fds) == -1) if (pipe(fds) == -1)
return 0; return 0;
fcntl(fds[0], F_SETFL, 0);
fcntl(fds[1], F_SETFL, 0);
*pPipeParentRead = fds[0]; *pPipeParentRead = fds[0];
*pPipeChildWrite = fds[1]; *pPipeChildWrite = fds[1];
@ -163,6 +214,8 @@ static bool createPipes(PipeType *pPipeParentRead, PipeType *pPipeParentWrite,
return 0; return 0;
} // if } // if
fcntl(fds[0], F_SETFL, 0);
fcntl(fds[1], F_SETFL, 0);
*pPipeChildRead = fds[0]; *pPipeChildRead = fds[0];
*pPipeParentWrite = fds[1]; *pPipeParentWrite = fds[1];
@ -337,7 +390,7 @@ static bool writeAchievementGet(PipeType fd, const char *name, const int status,
{ {
uint8 buf[256]; uint8 buf[256];
uint8 *ptr = buf+1; 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) SHIMEVENT_GETACHIEVEMENT;
*(ptr++) = (uint8) status; *(ptr++) = (uint8) status;
memcpy(ptr, &time, sizeof (time)); memcpy(ptr, &time, sizeof (time));
@ -601,11 +654,11 @@ static void processCommands(PipeType pipeParentRead, PipeType pipeParentWrite)
static bool setEnvironmentVars(PipeType pipeChildRead, PipeType pipeChildWrite) static bool setEnvironmentVars(PipeType pipeChildRead, PipeType pipeChildWrite)
{ {
char buf[64]; 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)) if (!setEnvVar("STEAMSHIM_READHANDLE", buf))
return false; 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)) if (!setEnvVar("STEAMSHIM_WRITEHANDLE", buf))
return false; return false;