Handle file paths in a clean way

Belated birthday present for @mewmew

Functions for gettings paths have sensible names
It's using snprintf for safe? string concat
Paths don't use \ as path reporator, or magic marker
Drop code for copying pre 1.09 save games from the windows folder
This commit is contained in:
Anders Jenbo 2019-09-26 06:26:37 +02:00
commit 06bcd3c3f9
11 changed files with 67 additions and 242 deletions

View file

@ -825,7 +825,10 @@ SMemReAlloc(
#define SLOG_FILE -4
#define SLOG_EXCEPTION -5
void GetBasePath(char *buffer, size_t size);
void GetPrefPath(char *buffer, size_t size);
bool getIniValue(const char *sectionName, const char *keyName, char *string, int stringSize, int *dataSize = NULL);
void setIniValue(const char *sectionName, const char *keyName, char *value, int len = 0);
BOOL STORMAPI SRegLoadData(const char *keyname, const char *valuename, int size, LPBYTE lpData, BYTE flags, LPDWORD lpcbData);
BOOL STORMAPI SRegLoadString(const char *keyname, const char *valuename, BYTE flags, char *buffer, unsigned int buffersize);
BOOL STORMAPI SRegLoadValue(const char *keyname, const char *valuename, BYTE flags, int *value);

View file

@ -1,4 +1,5 @@
#include "diablo.h"
#include "../3rdParty/Storm/Source/storm.h"
DEVILUTION_BEGIN_NAMESPACE
@ -126,10 +127,12 @@ BYTE *CaptureEnc(BYTE *src, BYTE *dst, int width)
HANDLE CaptureFile(char *dst_path)
{
int len = GetModuleFileNameA(ghInst, dst_path, MAX_PATH);
char path[MAX_PATH];
GetPrefPath(dst_path, MAX_PATH);
for (int i = 0; i <= 99; i++) {
sprintf(&dst_path[len], "screen%02d.PCX", i);
snprintf(dst_path, MAX_PATH, "%sscreen%02d.PCX", path, i);
FILE *file = fopen(dst_path, "r");
if (file == NULL) {

View file

@ -232,16 +232,13 @@ void free_game()
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HINSTANCE hInst;
int nData;
char szFileName[MAX_PATH];
hInst = hInstance;
ghInst = hInst;
ghInst = hInstance;
if (ReadOnlyTest()) {
if (!GetModuleFileName(ghInst, szFileName, sizeof(szFileName)))
szFileName[0] = '\0';
GetPrefPath(szFileName, sizeof(szFileName));
DirErrorDlg(szFileName);
}
@ -846,25 +843,18 @@ BOOL PressSysKey(int wParam)
void diablo_hotkey_msg(DWORD dwMsg)
{
char *s;
char szFileName[MAX_PATH];
char szMsg[MAX_SEND_STR_LEN];
if (gbMaxPlayers == 1) {
return;
}
if (GetModuleFileName(ghInst, szFileName, sizeof(szFileName)) == 0) {
app_fatal("Can't get program name");
}
s = strrchr(szFileName, '\\');
if (s != NULL) {
*s = '\0';
}
strcat(szFileName, "\\Diablo.ini");
/// ASSERT: assert(dwMsg < sizeof(spszMsgTbl) / sizeof(spszMsgTbl[0]));
GetPrivateProfileString("NetMsg", spszMsgHotKeyTbl[dwMsg], spszMsgTbl[dwMsg], szMsg, sizeof(szMsg), szFileName);
if (!getIniValue("NetMsg", spszMsgHotKeyTbl[dwMsg], szMsg, MAX_SEND_STR_LEN)) {
snprintf(szMsg, MAX_SEND_STR_LEN, "%s", spszMsgTbl[dwMsg]);
setIniValue("NetMsg", spszMsgHotKeyTbl[dwMsg], szMsg);
}
NetSendCmdString(-1, szMsg);
}

View file

@ -112,14 +112,14 @@ void init_archives()
HANDLE init_test_access(char *mpq_path, char *mpq_name, char *reg_loc, int flags, int fs)
{
char Buffer[2][MAX_PATH];
char *sdlPath;
HANDLE archive;
GetCurrentDirectory(MAX_PATH, Buffer[0]); // Package
GetModuleFileName(NULL, Buffer[1], MAX_PATH); // Preferences
GetBasePath(Buffer[0], MAX_PATH);
GetPrefPath(Buffer[1], MAX_PATH);
for (int i = 0; i < 2; i++) {
strcpy(mpq_path, Buffer[i]);
strcat(mpq_path, mpq_name);
snprintf(mpq_path, MAX_PATH, "%s%s", Buffer[i], mpq_name);
if (SFileOpenArchive(mpq_path, 0, flags, &archive)) {
SFileSetBasePath(Buffer[i]);
return archive;

View file

@ -47,9 +47,10 @@ void __cdecl dumphist(const char *pszFmt, ...)
va_start(va, pszFmt);
char dumpHistPath[MAX_PATH] = {};
if (sgpHistFile == NULL && GetWindowsDirectory(dumpHistPath, sizeof(dumpHistPath))) {
strcat(dumpHistPath, "\\dumphist.txt");
char path[MAX_PATH], dumpHistPath[MAX_PATH];
if (sgpHistFile == NULL) {
GetPrefPath(path, MAX_PATH);
snprintf(dumpHistPath, MAX_PATH, "%sdumphist.txt", path);
sgpHistFile = fopen(dumpHistPath, "wb");
if (sgpHistFile == NULL) {
return;

View file

@ -17,19 +17,12 @@ BOOL gbValidSaveFile;
void pfile_init_save_directory()
{
DWORD len;
char Buffer[MAX_PATH];
len = GetWindowsDirectory(Buffer, sizeof(Buffer));
if (len) {
pfile_check_available_space(Buffer);
len = GetModuleFileName(ghInst, Buffer, sizeof(Buffer));
}
pfile_check_available_space(Buffer);
GetPrefPath(Buffer, MAX_PATH);
if (!len)
app_fatal("Unable to initialize save directory");
else
pfile_check_available_space(Buffer);
pfile_check_available_space(Buffer);
}
void pfile_check_available_space(char *pszDir)
@ -117,32 +110,22 @@ BOOL pfile_open_archive(BOOL update, DWORD save_num)
void pfile_get_save_path(char *pszBuf, DWORD dwBufSize, DWORD save_num)
{
DWORD plen;
char *s;
char path[MAX_PATH];
#ifdef SPAWN
const char *fmt = "\\share_%d.sv";
const char *fmt = "%sshare_%d.sv";
if (gbMaxPlayers <= 1)
fmt = "\\spawn%d.sv";
fmt = "%sspawn%d.sv";
#else
const char *fmt = "\\multi_%d.sv";
const char *fmt = "%smulti_%d.sv";
if (gbMaxPlayers <= 1)
fmt = "\\single_%d.sv";
fmt = "%ssingle_%d.sv";
#endif
// BUGFIX: ignores dwBufSize and uses MAX_PATH instead
plen = GetModuleFileName(ghInst, pszBuf, MAX_PATH);
s = strrchr(pszBuf, '\\');
if (s)
*s = '\0';
if (!plen)
app_fatal("Unable to get save directory");
sprintf(path, fmt, save_num);
strcat(pszBuf, path);
GetPrefPath(path, MAX_PATH);
snprintf(pszBuf, MAX_PATH, fmt, path, save_num);
}
void pfile_flush(BOOL is_single_player, DWORD save_num)
@ -250,36 +233,6 @@ BOOL __stdcall pfile_ui_set_hero_infos(BOOL(__stdcall *ui_add_hero_info)(_uihero
BOOL showFixedMsg;
memset(hero_names, 0, sizeof(hero_names));
if (gbMaxPlayers > 1) {
for (i = 0, save_num = 0; i < MAX_CHARACTERS && save_num < MAX_CHARACTERS; i++) {
struct _OFSTRUCT ReOpenBuff;
const char *s;
GetSaveDirectory(FileName, sizeof(FileName), i);
s = strrchr(FileName, '\\') + 1;
if (s == (const char *)1)
continue;
if (OpenFile(FileName, &ReOpenBuff, OF_EXIST) == HFILE_ERROR)
continue;
if (!SRegLoadString("Diablo\\Converted", s, 0, NewFileName, sizeof(NewFileName))) {
while (save_num < MAX_CHARACTERS) {
pfile_get_save_path(NewFileName, sizeof(NewFileName), save_num++);
if (OpenFile(NewFileName, &ReOpenBuff, OF_EXIST) == HFILE_ERROR) {
if (CopyFile(FileName, NewFileName, TRUE)) {
DWORD attrib;
SRegSaveString("Diablo\\Converted", s, 0, NewFileName);
attrib = GetFileAttributes(NewFileName);
if (attrib != INVALID_FILE_ATTRIBUTES) {
attrib &= ~(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
SetFileAttributes(NewFileName, attrib);
}
}
break;
}
}
}
}
}
showFixedMsg = TRUE;
for (i = 0; i < MAX_CHARACTERS; i++) {
@ -300,41 +253,6 @@ BOOL __stdcall pfile_ui_set_hero_infos(BOOL(__stdcall *ui_add_hero_info)(_uihero
return TRUE;
}
char *GetSaveDirectory(char *dst, int dst_size, DWORD save_num)
{
DWORD dirLen;
char FileName[MAX_PATH];
const char *savename;
// BUGFIX: ignores dst_size and uses MAX_PATH instead
if (gbMaxPlayers > 1) {
#ifdef SPAWN
savename = "\\slinfo_%d.drv";
#else
savename = "\\dlinfo_%d.drv";
#endif
dirLen = GetWindowsDirectory(dst, MAX_PATH);
} else {
char *s;
#ifdef SPAWN
savename = "\\spawn_%d.sv";
#else
savename = "\\single_%d.sv";
#endif
dirLen = GetModuleFileName(ghInst, dst, MAX_PATH);
s = strrchr(dst, '\\');
if (s)
*s = '\0';
}
if (!dirLen)
app_fatal("Unable to get save directory");
sprintf(FileName, savename, save_num);
strcat(dst, FileName);
return dst;
}
BOOL pfile_read_hero(HANDLE archive, PkPlayerStruct *pPack)
{
HANDLE file;

View file

@ -1,28 +1,24 @@
#include "diablo.h"
#include "../3rdParty/Storm/Source/storm.h"
DEVILUTION_BEGIN_NAMESPACE
BOOL ReadOnlyTest()
{
char *c;
FILE *f;
char Filename[MAX_PATH];
BOOL ret = FALSE;
char path[MAX_PATH], Filename[MAX_PATH];
if (GetModuleFileName(ghInst, Filename, sizeof(Filename))) {
c = strrchr(Filename, '\\');
if (c) {
strcpy(c + 1, "Diablo1ReadOnlyTest.foo");
f = fopen(Filename, "wt");
if (f) {
fclose(f);
remove(Filename);
} else {
ret = TRUE;
}
}
GetPrefPath(path, MAX_PATH);
snprintf(Filename, DVL_MAX_PATH, "%sDiablo1ReadOnlyTest.foo", path);
f = fopen(Filename, "wt");
if (f) {
fclose(f);
remove(Filename);
return FALSE;
}
return ret;
return TRUE;
}
DEVILUTION_END_NAMESPACE

View file

@ -65,7 +65,7 @@ typedef LONG_PTR LRESULT;
//
typedef void *HANDLE;
typedef HANDLE HWND, HGDIOBJ, HMODULE, HDC, HRGN, HINSTANCE, HPALETTE, HFILE, HCURSOR;
typedef HANDLE HWND, HGDIOBJ, HMODULE, HDC, HRGN, HINSTANCE, HPALETTE, HCURSOR;
typedef LONG LCID;
@ -348,15 +348,6 @@ typedef struct _IMAGE_DOS_HEADER {
LONG e_lfanew;
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
typedef struct _OFSTRUCT {
BYTE cBytes;
BYTE fFixedDisk;
WORD nErrCode;
WORD Reserved1;
WORD Reserved2;
CHAR szPathName[DVL_OFS_MAXPATHNAME];
} OFSTRUCT, *LPOFSTRUCT, *POFSTRUCT;
typedef struct _OSVERSIONINFOA {
DWORD dwOSVersionInfoSize;
DWORD dwMajorVersion;
@ -388,8 +379,6 @@ void lstrcpynA(LPSTR lpString1, LPCSTR lpString2, int iMaxLength);
LPVOID VirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
BOOL VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType);
DWORD WINAPI GetPrivateProfileStringA(LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpDefault, LPSTR lpReturnedString,
DWORD nSize, LPCSTR lpFileName);
int MessageBoxA(HWND hWnd, const char *Text, const char *Title, UINT Flags);
typedef LONG LSTATUS, HKEY, REGSAM, PHKEY;
@ -411,17 +400,11 @@ HANDLE WINAPI CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShar
WINBOOL WINAPI ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped);
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh);
UINT WINAPI GetWindowsDirectoryA(LPSTR lpBuffer, UINT uSize);
DWORD GetCurrentDirectory(DWORD nBufferLength, LPTSTR lpBuffer);
DWORD GetLogicalDriveStringsA(DWORD nBufferLength, LPSTR lpBuffer);
UINT GetDriveTypeA(LPCSTR lpRootPathName);
WINBOOL WINAPI GetDiskFreeSpaceA(LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector,
LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters);
DWORD WINAPI GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize);
WINBOOL WINAPI GetComputerNameA(LPSTR lpBuffer, LPDWORD nSize);
WINBOOL WINAPI DeleteFileA(LPCSTR lpFileName);
WINBOOL WINAPI CopyFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, WINBOOL bFailIfExists);
HFILE WINAPI OpenFile(LPCSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle);
typedef struct _CONTEXT {
@ -545,7 +528,6 @@ extern BOOL __cdecl LoadArtWithPal(char *pszFile, void **pBuffer, int frames, DW
constexpr auto DVL_WM_ACTIVATEAPP = 0x001C;
constexpr auto DVL_WM_SYSKEYUP = 0x0105;
const auto DVL_HFILE_ERROR = (HFILE)-1;
constexpr auto DVL_DRIVE_CDROM = 5;
constexpr auto DVL_WM_DESTROY = 0x0002;
constexpr auto DVL_HORZRES = 8;

View file

@ -5,7 +5,6 @@
#define INVALID_HANDLE_VALUE ((HANDLE)-1)
#define INVALID_HANDLE ((HANDLE)-1)
#define HFILE_ERROR DVL_HFILE_ERROR
//
// Intrinsics
@ -98,7 +97,6 @@
#define SECTION_ALL_ACCESS \
(STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_WRITE | SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_EXTEND_SIZE)
#define GetPrivateProfileString GetPrivateProfileStringA
#define MessageBox MessageBoxA
#define HKEY_CURRENT_USER 1
@ -112,14 +110,10 @@
#define SetFileAttributes SetFileAttributesA
#define FindFirstFile FindFirstFileA
#define CreateFile CreateFileA
#define GetWindowsDirectory GetWindowsDirectoryA
#define GetLogicalDriveStrings GetLogicalDriveStringsA
#define GetDriveType GetDriveTypeA
#define GetDiskFreeSpace GetDiskFreeSpaceA
#define GetModuleFileName GetModuleFileNameA
#define GetComputerName GetComputerNameA
#define DeleteFile DeleteFileA
#define CopyFile CopyFileA
#define GWL_STYLE (-16)
@ -199,8 +193,6 @@
#define SWP_NOSIZE 0x0004
#define SWP_NOZORDER 0x0001
#define OF_EXIST 1
#define MAKEINTRESOURCE DVL_MAKEINTRESOURCE
#define _finddata_t DVL_finddata_t

View file

@ -97,22 +97,6 @@ WINBOOL FindClose(HANDLE hFindFile)
return true;
}
/**
* @brief Normally this would get the Windows install, but Diablo uses it to find the old save game folder
*/
UINT GetWindowsDirectoryA(LPSTR lpBuffer, UINT uSize)
{
char *name = SDL_GetPrefPath("diasurgical", "devilution");
strncpy(lpBuffer, name, uSize);
SDL_free(name);
DWORD len = strlen(lpBuffer);
lpBuffer[len - 1] = '\0';
return len - 1;
}
WINBOOL GetDiskFreeSpaceA(LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector,
LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters)
{
@ -123,22 +107,6 @@ WINBOOL GetDiskFreeSpaceA(LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LP
return true;
}
/**
* @brief Used for getting save path, by removing up to and including the last "\"
*/
DWORD GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize)
{
char *name = SDL_GetPrefPath("diasurgical", "devilution");
strncpy(lpFilename, name, nSize);
SDL_free(name);
DWORD len = strlen(lpFilename);
lpFilename[len - 1] = '\\';
return len;
}
WINBOOL GetComputerNameA(LPSTR lpBuffer, LPDWORD nSize)
{
DUMMY();
@ -147,26 +115,6 @@ WINBOOL GetComputerNameA(LPSTR lpBuffer, LPDWORD nSize)
return true;
}
DWORD GetCurrentDirectory(DWORD nBufferLength, LPTSTR lpBuffer)
{
char *base_path = SDL_GetBasePath();
if (base_path == NULL) {
SDL_Log(SDL_GetError());
base_path = SDL_strdup("./");
}
eprintf("BasePath: %s\n", base_path);
strncpy(lpBuffer, base_path, nBufferLength);
SDL_free(base_path);
return strlen(lpBuffer);
}
DWORD GetLogicalDriveStringsA(DWORD nBufferLength, LPSTR lpBuffer)
{
return 0;
}
UINT GetDriveTypeA(LPCSTR lpRootPathName)
{
return DVL_DRIVE_CDROM;
@ -190,18 +138,6 @@ WINBOOL DeleteFileA(LPCSTR lpFileName)
return true;
}
WINBOOL CopyFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, WINBOOL bFailIfExists)
{
UNIMPLEMENTED();
return true;
}
HFILE OpenFile(LPCSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle)
{
DUMMY();
return DVL_HFILE_ERROR;
}
HWND SetCapture(HWND hWnd)
{
DUMMY_ONCE();
@ -468,16 +404,6 @@ void lstrcpynA(LPSTR lpString1, LPCSTR lpString2, int iMaxLength)
strncpy(lpString1, lpString2, iMaxLength);
}
DWORD GetPrivateProfileStringA(LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpDefault, LPSTR lpReturnedString,
DWORD nSize, LPCSTR lpFileName)
{
if (!SRegLoadString(lpAppName, lpKeyName, 0, lpReturnedString, nSize)) {
strncpy(lpReturnedString, lpDefault, nSize);
SRegSaveString(lpAppName, lpKeyName, 0, lpReturnedString);
}
return 0; // dummy return value
}
int MessageBoxA(HWND hWnd, const char *Text, const char *Title, UINT Flags)
{
Uint32 SDLFlags = 0;

View file

@ -21,17 +21,31 @@ bool directFileAccess = false;
static std::string getIniPath()
{
char path[DVL_MAX_PATH];
int len = GetModuleFileNameA(ghInst, path, DVL_MAX_PATH);
path[len - 1] = '/';
strcat(path, "diablo.ini");
char path[DVL_MAX_PATH], file_path[DVL_MAX_PATH];
return path;
GetPrefPath(path, DVL_MAX_PATH);
snprintf(file_path, DVL_MAX_PATH, "%sdiablo.ini", path);
return file_path;
}
static radon::File ini(getIniPath());
static Mix_Chunk *SFileChunk;
void GetBasePath(char *buffer, size_t size)
{
char *path = SDL_GetBasePath();
snprintf(buffer, size, "%s", path);
SDL_free(path);
}
void GetPrefPath(char *buffer, size_t size)
{
char *path = SDL_GetPrefPath("diasurgical", "devilution");
snprintf(buffer, size, "%s", path);
SDL_free(path);
}
void TranslateFileName(char *dst, int dstLen, const char *src)
{
for (int i = 0; i < dstLen; i++) {
@ -346,7 +360,7 @@ void *SMemReAlloc(void *location, unsigned int amount, char *logfilename, int lo
UNIMPLEMENTED();
}
bool getIniValue(const char *sectionName, const char *keyName, char *string, int stringSize, int *dataSize = NULL)
bool getIniValue(const char *sectionName, const char *keyName, char *string, int stringSize, int *dataSize)
{
radon::Section *section = ini.getSection(sectionName);
if (!section)
@ -366,7 +380,7 @@ bool getIniValue(const char *sectionName, const char *keyName, char *string, int
return true;
}
void setIniValue(const char *sectionName, const char *keyName, char *value, int len = 0)
void setIniValue(const char *sectionName, const char *keyName, char *value, int len)
{
radon::Section *section = ini.getSection(sectionName);
if (!section) {