Windows: Fix Unicode directory handling
Jeffrey Pfau jeffrey@endrift.com
Thu, 13 Oct 2016 13:42:12 -0700
2 files changed,
43 insertions(+),
16 deletions(-)
M
CHANGES
→
CHANGES
@@ -9,6 +9,7 @@ - GBA Memory: Fix misaligned BIOS reads
- GBA BIOS: Fix MidiKey2Freq BIOS reads - GBA BIOS: Fix invalid CpuSet not setting BIOS prefetch - GB MBC: Fix SRAM dangling pointer with RTC games + - Windows: Fix Unicode directory handling Misc: - SDL: Remove scancode key input - GBA Video: Clean up unused timers
M
src/platform/windows/vfs-w32.c
→
src/platform/windows/vfs-w32.c
@@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "util/vfs.h" #include "util/string.h" +#include <strsafe.h> static bool _vdwClose(struct VDir* vd); static void _vdwRewind(struct VDir* vd);@@ -20,7 +21,8 @@
struct VDirW32; struct VDirEntryW32 { struct VDirEntry d; - WIN32_FIND_DATA ffData; + WIN32_FIND_DATAW ffData; + char* utf8Name; }; struct VDirW32 {@@ -34,10 +36,11 @@ struct VDir* VDirOpen(const char* path) {
if (!path || !path[0]) { return 0; } - char name[MAX_PATH]; - _snprintf(name, sizeof(name), "%s\\*", path); - WIN32_FIND_DATA ffData; - HANDLE handle = FindFirstFile(name, &ffData); + wchar_t name[MAX_PATH + 1]; + MultiByteToWideChar(CP_UTF8, 0, path, -1, name, MAX_PATH); + StringCchCatNW(name, MAX_PATH, L"\\*", 2); + WIN32_FIND_DATAW ffData; + HANDLE handle = FindFirstFileW(name, &ffData); if (handle == INVALID_HANDLE_VALUE) { return 0; }@@ -67,6 +70,11 @@
bool _vdwClose(struct VDir* vd) { struct VDirW32* vdw = (struct VDirW32*) vd; FindClose(vdw->handle); + free(vdw->path); + if (vdw->vde.utf8Name) { + free(vdw->vde.utf8Name); + vdw->vde.utf8Name = NULL; + } free(vdw); return true; }@@ -74,14 +82,23 @@
void _vdwRewind(struct VDir* vd) { struct VDirW32* vdw = (struct VDirW32*) vd; FindClose(vdw->handle); - char name[MAX_PATH]; - _snprintf(name, sizeof(name), "%s\\*", vdw->path); - vdw->handle = FindFirstFile(name, &vdw->vde.ffData); + wchar_t name[MAX_PATH + 1]; + MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, vdw->path, -1, name, MAX_PATH); + StringCchCatNW(name, MAX_PATH, L"\\*", 2); + if (vdw->vde.utf8Name) { + free(vdw->vde.utf8Name); + vdw->vde.utf8Name = NULL; + } + vdw->handle = FindFirstFileW(name, &vdw->vde.ffData); } struct VDirEntry* _vdwListNext(struct VDir* vd) { struct VDirW32* vdw = (struct VDirW32*) vd; - if (FindNextFile(vdw->handle, &vdw->vde.ffData)) { + if (FindNextFileW(vdw->handle, &vdw->vde.ffData)) { + if (vdw->vde.utf8Name) { + free(vdw->vde.utf8Name); + vdw->vde.utf8Name = NULL; + } return &vdw->vde.d; }@@ -94,8 +111,9 @@ if (!path) {
return 0; } const char* dir = vdw->path; - char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + 2)); - sprintf(combined, "%s\\%s", dir, path); + size_t size = sizeof(char) * (strlen(path) + strlen(dir) + 2); + char* combined = malloc(size); + StringCbPrintf(combined, size, "%s\\%s", dir, path); struct VFile* file = VFileOpen(combined, mode); free(combined);@@ -108,8 +126,9 @@ if (!path) {
return 0; } const char* dir = vdw->path; - char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + 2)); - sprintf(combined, "%s\\%s", dir, path); + size_t size = sizeof(char) * (strlen(path) + strlen(dir) + 2); + char* combined = malloc(size); + StringCbPrintf(combined, size, "%s\\%s", dir, path); struct VDir* vd2 = VDirOpen(combined); if (!vd2) {@@ -125,8 +144,9 @@ if (!path) {
return 0; } const char* dir = vdw->path; - char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + 2)); - sprintf(combined, "%s\\%s", dir, path); + size_t size = sizeof(char) * (strlen(path) + strlen(dir) + 2); + char* combined = malloc(size); + StringCbPrintf(combined, size, "%s\\%s", dir, path); bool ret = DeleteFile(combined); free(combined);@@ -135,7 +155,13 @@ }
const char* _vdweName(struct VDirEntry* vde) { struct VDirEntryW32* vdwe = (struct VDirEntryW32*) vde; - return vdwe->ffData.cFileName; + if (vdwe->utf8Name) { + return vdwe->utf8Name; + } + size_t len = 4 * wcslen(vdwe->ffData.cFileName); + vdwe->utf8Name = malloc(len); + WideCharToMultiByte(CP_UTF8, 0, vdwe->ffData.cFileName, -1, vdwe->utf8Name, len - 1, NULL, NULL); + return vdwe->utf8Name; } static enum VFSType _vdweType(struct VDirEntry* vde) {