From d5a3874c2fdbcbeb5a90bcbb9e106c3f5b6a9175 Mon Sep 17 00:00:00 2001 From: VDm Date: Sat, 8 Apr 2023 22:46:53 +0400 Subject: [PATCH] feat(util): update SFile with logging (Windows only) --- src/util/Filesystem.cpp | 34 +++++++++ src/util/Filesystem.hpp | 4 ++ src/util/SFile.cpp | 156 +++++++++++++++++----------------------- src/util/SFile.hpp | 5 +- 4 files changed, 104 insertions(+), 95 deletions(-) diff --git a/src/util/Filesystem.cpp b/src/util/Filesystem.cpp index 69193f2..15acad0 100644 --- a/src/util/Filesystem.cpp +++ b/src/util/Filesystem.cpp @@ -41,6 +41,40 @@ char* OsPathFindExtensionWithDot(char* pathName) { return result; } +void OsFileToNativeSlashes(char* path, size_t size) { +#ifdef WHOA_SYSTEM_WIN + OsFileToBackSlashes(path, size); +#else + OsFileToForwardSlashes(path, size); +#endif +} + +void OsFileToForwardSlashes(char* path, size_t size) { + if (!path) + return; + + for (size_t i = 0; i < size; ++i) { + if (!path[i]) + return; + + if (path[i] == '\\') + path[i] = '/'; + } +} + +void OsFileToBackSlashes(char* path, size_t size) { + if (!path) + return; + + for (size_t i = 0; i < size; ++i) { + if (!path[i]) + return; + + if (path[i] == '/') + path[i] = '\\'; + } +} + void OpenPatches(const std::string& language, const std::string& fileName) { std::string path("Data/" + language + "/"); std::string fullPath; diff --git a/src/util/Filesystem.hpp b/src/util/Filesystem.hpp index 8341006..9f4e867 100644 --- a/src/util/Filesystem.hpp +++ b/src/util/Filesystem.hpp @@ -10,6 +10,10 @@ void OsBuildFontFilePath(const char*, char*, size_t); char* OsPathFindExtensionWithDot(char*); +void OsFileToNativeSlashes(char* path, size_t size = (size_t) -1); +void OsFileToForwardSlashes(char* path, size_t size = (size_t) -1); +void OsFileToBackSlashes(char* path, size_t size = (size_t) -1); + void OpenArchives(); extern void* g_mpqHandle; diff --git a/src/util/SFile.cpp b/src/util/SFile.cpp index c52f56e..f4e920e 100644 --- a/src/util/SFile.cpp +++ b/src/util/SFile.cpp @@ -8,19 +8,20 @@ // TODO Proper implementation int32_t SFile::Close(SFile* file) { - SFileCloseFile(file->m_file); + SFileCloseFile(file->m_handle); delete file; return 1; } // TODO Proper implementation -size_t SFile::GetFileSize(SFile* file, size_t* filesizeHigh) { - DWORD highPart = 0; - DWORD lowPart = SFileGetFileSize(file->m_file, &highPart); +uint32_t SFile::GetFileSize(SFile* file, uint32_t* filesizeHigh) { + DWORD high = 0; + DWORD low = SFileGetFileSize(file->m_handle, &high); if (filesizeHigh) - *filesizeHigh = highPart; - return lowPart; + *filesizeHigh = high; + + return low; } int32_t SFile::IsStreamingMode() { @@ -30,73 +31,39 @@ int32_t SFile::IsStreamingMode() { // TODO Proper implementation int32_t SFile::Load(SArchive* archive, const char* filename, void** buffer, size_t* bytes, size_t extraBytes, uint32_t flags, SOVERLAPPED* overlapped) { - auto pathLen = SStrLen(filename); - - char archivePath[STORM_MAX_PATH] = { 0 }; - char localPath[STORM_MAX_PATH] = { 0 }; - char subPath[STORM_MAX_PATH] = { 0 }; - - bool containsPath = false; - - for (int32_t i = 0; i < pathLen; ++i) { - if (filename[i] == '/') { - containsPath = true; -#ifdef WHOA_SYSTEM_WIN - localPath[i] = '\\'; -#else - localPath[i] = '/'; -#endif - archivePath[i] = '\\'; - } else if (filename[i] == '\\') { - containsPath = true; -#ifdef WHOA_SYSTEM_WIN - localPath[i] = '\\'; -#else - localPath[i] = '/'; -#endif - archivePath[i] = '\\'; - } else { - localPath[i] = filename[i]; - archivePath[i] = filename[i]; - } - } - - if (!containsPath) { -#ifdef WHOA_SYSTEM_WIN - SStrCopy(subPath, "Data\\enGB\\", sizeof(subPath)); -#else - SStrCopy(subPath, "Data/enGB/", sizeof(subPath)); -#endif - strcat(subPath, filename); - } - - - HANDLE file; - if (!SFileOpenFileEx(nullptr, localPath, SFILE_OPEN_LOCAL_FILE, &file)) { - if (containsPath || !SFileOpenFileEx(nullptr, subPath, SFILE_OPEN_LOCAL_FILE, &file)) { - if (!SFileOpenFileEx(g_mpqHandle, archivePath, SFILE_OPEN_FROM_MPQ, &file)) - return 0; - } - } - - DWORD highPart = 0; - size_t size = SFileGetFileSize(file, &highPart); - size |= (highPart << 32); + if (!buffer || !filename) + return 0; + *buffer = nullptr; if (bytes) - *bytes = size; + *bytes = 0; + + SFile* file = nullptr; + if (!SFile::OpenEx(nullptr, filename, 0, &file)) + return 0; + + uint32_t high = 0; + uint64_t size = SFile::GetFileSize(file, &high); + size |= ((uint64_t) high << 32); char* data = (char*) SMemAlloc(size + extraBytes, __FILE__, __LINE__, 0); - SFileReadFile(file, data, size, &highPart, nullptr); + if (!SFile::Read(file, data, size, nullptr, nullptr, nullptr)) { + SMemFree(data, __FILE__, __LINE__, 0); + SFile::Close(file); + return 0; + } if (extraBytes) memset(data + size, 0, extraBytes); + if (bytes) + *bytes = size; + if (buffer) *buffer = data; - SFileCloseFile(file); + SFile::Close(file); return 1; } @@ -107,46 +74,51 @@ int32_t SFile::Open(const char* filename, SFile** file) { // TODO Proper implementation int32_t SFile::OpenEx(SArchive* archive, const char* filename, uint32_t flags, SFile** file) { - auto pathLen = SStrLen(filename); + if (!file || !filename) + return 0; - char archivePath[STORM_MAX_PATH] = { 0 }; - char localPath[STORM_MAX_PATH] = { 0 }; + *file = nullptr; - for (int32_t i = 0; i < pathLen; ++i) { - if (filename[i] == '/') { -#ifdef WHOA_SYSTEM_WIN - localPath[i] = '\\'; -#else - localPath[i] = '/'; -#endif - archivePath[i] = '\\'; - } else if (filename[i] == '\\') { -#ifdef WHOA_SYSTEM_WIN - localPath[i] = '\\'; -#else - localPath[i] = '/'; -#endif - archivePath[i] = '\\'; - } else { - localPath[i] = filename[i]; - archivePath[i] = filename[i]; - } - } + size_t length = SStrLen(filename); + // Overflow protection + if (length + 1 > STORM_MAX_PATH) + return 0; + + char nativePath[STORM_MAX_PATH] = { 0 }; + char backslashPath[STORM_MAX_PATH] = { 0 }; + + SStrCopy(nativePath, filename, STORM_MAX_PATH); + SStrCopy(backslashPath, filename, STORM_MAX_PATH); + + OsFileToNativeSlashes(nativePath); + OsFileToBackSlashes(backslashPath); + + char message[512] = { 0 }; HANDLE handle; bool local = true; - if (!SFileOpenFileEx(nullptr, localPath, SFILE_OPEN_LOCAL_FILE, &handle)) { + if (!SFileOpenFileEx(nullptr, nativePath, SFILE_OPEN_LOCAL_FILE, &handle)) { local = false; - if (!SFileOpenFileEx(g_mpqHandle, archivePath, SFILE_OPEN_FROM_MPQ, &handle)) { - *file = nullptr; + if (!SFileOpenFileEx(g_mpqHandle, backslashPath, SFILE_OPEN_FROM_MPQ, &handle)) { + SStrCopy(message, "[SFile] Unable to open: ", sizeof(message)); + strcat(message, filename); + strcat(message, "\n"); + OutputDebugStringA(message); return 0; } } - SFile* fileptr = new SFile; - fileptr->m_mpq = local ? nullptr : g_mpqHandle; - fileptr->m_file = handle; - *file = fileptr; + if (local) { + SStrCopy(message, "[SFile] Open (file system): ", sizeof(message)); + } else { + SStrCopy(message, "[SFile] Open (archive): ", sizeof(message)); + } + strcat(message, filename); + strcat(message, "\n"); + OutputDebugStringA(message); + + *file = new SFile; + (*file)->m_handle = handle; return 1; } @@ -154,7 +126,7 @@ int32_t SFile::OpenEx(SArchive* archive, const char* filename, uint32_t flags, S // TODO Proper implementation int32_t SFile::Read(SFile* file, void* buffer, size_t bytestoread, size_t* bytesread, SOVERLAPPED* overlapped, TASYNCPARAMBLOCK* asyncparam) { DWORD read = 0; - if (SFileReadFile(file->m_file, buffer, bytestoread, &read, nullptr)) { + if (SFileReadFile(file->m_handle, buffer, bytestoread, &read, nullptr)) { if (bytesread) *bytesread = read; return 1; diff --git a/src/util/SFile.hpp b/src/util/SFile.hpp index c877da2..92ce35f 100644 --- a/src/util/SFile.hpp +++ b/src/util/SFile.hpp @@ -12,7 +12,7 @@ class SFile { public: // Static functions static int32_t Close(SFile*); - static size_t GetFileSize(SFile*, size_t*); + static uint32_t GetFileSize(SFile*, uint32_t*); static int32_t IsStreamingMode(void); static int32_t Load(SArchive*, const char*, void**, size_t*, size_t, uint32_t, SOVERLAPPED*); static int32_t Open(const char*, SFile**); @@ -21,8 +21,7 @@ class SFile { static int32_t Unload(void*); // Member variables - void* m_mpq; - void* m_file; + void* m_handle; }; #endif