Change the current working directory before writing save games.

We can't rely on the game.dll being unicode conformant. Work around
that by changing the current working directory before calling into
the game.dll, pass a non unicode string to it and chang back after
we return.
This commit is contained in:
Yamagi Burmeister 2018-02-05 17:21:55 +01:00
parent 3634ed7013
commit 6b13d77c36
4 changed files with 115 additions and 10 deletions

View file

@ -521,3 +521,27 @@ Sys_LoadLibrary(const char *path, const char *sym, void **handle)
return entry;
}
/* ================================================================ */
void
Sys_GetWorkDir(char *buffer, size_t len)
{
if (getcwd(buffer, len) != 0)
{
return;
}
buffer[0] = '\0';
}
qboolean
Sys_SetWorkDir(char *path)
{
if (chdir(path) == 0)
{
return true;
}
return false;
}

View file

@ -579,6 +579,37 @@ Sys_LoadLibrary(const char *path, const char *sym, void **handle)
/* ======================================================================= */
void
Sys_GetWorkDir(char *buffer, size_t len)
{
WCHAR wbuffer[MAX_OSPATH];
if (GetCurrentDirectoryW(sizeof(wbuffer), wbuffer) != 0)
{
WideCharToMultiByte(CP_UTF8, 0, wbuffer, -1, buffer, len, NULL, NULL);
return;
}
buffer[0] = '\0';
}
qboolean
Sys_SetWorkDir(char *path)
{
WCHAR wpath[MAX_OSPATH];
MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, sizeof(wpath));
if (SetCurrentDirectoryW(wpath) != 0)
{
return true;
}
return false;
}
/* ======================================================================= */
// This one is Windows specific.
void

View file

@ -787,10 +787,10 @@ void Sys_Nanosleep(int);
void *Sys_GetProcAddress(void *handle, const char *sym);
void Sys_FreeLibrary(void *handle);
void *Sys_LoadLibrary(const char *path, const char *sym, void **handle);
// TODO: Use generic functions instead
void *Sys_GetGameAPI(void *parms);
void Sys_UnloadGame(void);
void Sys_GetWorkDir(char *buffer, size_t len);
qboolean Sys_SetWorkDir(char *path);
// Windows only (system.c)
#ifdef _WIN32

View file

@ -162,6 +162,7 @@ void
SV_WriteLevelFile(void)
{
char name[MAX_OSPATH];
char workdir[MAX_OSPATH];
FILE *f;
Com_DPrintf("SV_WriteLevelFile()\n");
@ -180,15 +181,28 @@ SV_WriteLevelFile(void)
CM_WritePortalState(f);
fclose(f);
Com_sprintf(name, sizeof(name), "%s/save/current/%s.sav",
FS_Gamedir(), sv.name);
Com_sprintf(name, sizeof(name), "%s/save/current", FS_Gamedir());
Sys_GetWorkDir(workdir, sizeof(workdir));
Sys_Mkdir(name);
if (!Sys_SetWorkDir(name))
{
Com_Printf("Couldn't change to %s\n", name);
Sys_SetWorkDir(workdir);
return;
}
Com_sprintf(name, sizeof(name), "%s.sav", sv.name);
ge->WriteLevel(name);
Sys_SetWorkDir(workdir);
}
void
SV_ReadLevelFile(void)
{
char name[MAX_OSPATH];
char workdir[MAX_OSPATH];
fileHandle_t f;
Com_DPrintf("SV_ReadLevelFile()\n");
@ -206,9 +220,20 @@ SV_ReadLevelFile(void)
CM_ReadPortalState(f);
FS_FCloseFile(f);
Com_sprintf(name, sizeof(name), "%s/save/current/%s.sav",
FS_Gamedir(), sv.name);
Com_sprintf(name, sizeof(name), "%s/save/current", FS_Gamedir());
Sys_GetWorkDir(workdir, sizeof(workdir));
if (!Sys_SetWorkDir(name))
{
Com_Printf("Couldn't change to %s\n", name);
Sys_SetWorkDir(workdir);
return;
}
Com_sprintf(name, sizeof(name), "%s.sav", sv.name);
ge->ReadLevel(name);
Sys_SetWorkDir(workdir);
}
void
@ -217,6 +242,7 @@ SV_WriteServerFile(qboolean autosave)
FILE *f;
cvar_t *var;
char name[MAX_OSPATH], string[128];
char workdir[MAX_OSPATH];
char comment[32];
time_t aclock;
struct tm *newtime;
@ -285,8 +311,20 @@ SV_WriteServerFile(qboolean autosave)
fclose(f);
/* write game state */
Com_sprintf(name, sizeof(name), "%s/save/current/game.ssv", FS_Gamedir());
ge->WriteGame(name, autosave);
Com_sprintf(name, sizeof(name), "%s/save/current", FS_Gamedir());
Sys_GetWorkDir(workdir, sizeof(workdir));
Sys_Mkdir(name);
if (!Sys_SetWorkDir(name))
{
Com_Printf("Couldn't change to %s\n", name);
Sys_SetWorkDir(workdir);
return;
}
ge->WriteGame("game.ssv", autosave);
Sys_SetWorkDir(workdir);
}
void
@ -294,6 +332,7 @@ SV_ReadServerFile(void)
{
fileHandle_t f;
char name[MAX_OSPATH], string[128];
char workdir[MAX_OSPATH];
char comment[32];
char mapcmd[MAX_TOKEN_CHARS];
@ -338,8 +377,19 @@ SV_ReadServerFile(void)
strcpy(svs.mapcmd, mapcmd);
/* read game state */
Com_sprintf(name, sizeof(name), "%s/save/current/game.ssv", FS_Gamedir());
ge->ReadGame(name);
Com_sprintf(name, sizeof(name), "%s/save/current", FS_Gamedir());
Sys_GetWorkDir(workdir, sizeof(workdir));
if (!Sys_SetWorkDir(name))
{
Com_Printf("Couldn't change to %s\n", name);
Sys_SetWorkDir(workdir);
return;
}
ge->ReadGame("game.ssv");
Sys_SetWorkDir(workdir);
}
void