fix: use wide-char Windows APIs for non-ASCII filenames

This commit is contained in:
2026-09-15 14:01:49 +02:00
parent fd34aa1956
commit e72df334ef
2 changed files with 183 additions and 41 deletions
+46 -1
View File
@@ -13,7 +13,7 @@
#ifdef _WIN32
#include <direct.h>
#include <windows.h>
#define MKDIR(path) _mkdir(path)
#include <wchar.h>
#define PROGRAM_NAME "funpack.exe"
#else
#include <time.h>
@@ -21,6 +21,42 @@
#define PROGRAM_NAME "funpack"
#endif
#ifdef _WIN32
static wchar_t *utf8_to_wide(const char *s)
{
int wlen = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0);
wchar_t *w;
if (wlen <= 0)
return NULL;
w = malloc((size_t)wlen * sizeof(wchar_t));
if (!w)
return NULL;
MultiByteToWideChar(CP_UTF8, 0, s, -1, w, wlen);
return w;
}
static int win_mkdir(const char *path)
{
wchar_t *wpath = utf8_to_wide(path);
int ok;
if (!wpath)
return -1;
ok = CreateDirectoryW(wpath, NULL);
free(wpath);
if (ok)
return 0;
if (GetLastError() == ERROR_ALREADY_EXISTS) {
errno = EEXIST;
return -1;
}
errno = 0;
return -1;
}
#define MKDIR(path) win_mkdir(path)
#endif
static double now_seconds(void)
{
#ifdef _WIN32
@@ -168,6 +204,9 @@ static int extract_entry(const char *out_dir, const fpk_entry_t *entry,
{
char *full_path = join_path(out_dir, entry->path);
FILE *fp;
#ifdef _WIN32
wchar_t *wpath;
#endif
if (strchr(entry->path, '/') != NULL) {
char *dir_part = dup_str(full_path);
@@ -182,7 +221,13 @@ static int extract_entry(const char *out_dir, const fpk_entry_t *entry,
free(dir_part);
}
#ifdef _WIN32
wpath = utf8_to_wide(full_path);
fp = wpath ? _wfopen(wpath, L"wb") : NULL;
free(wpath);
#else
fp = fopen(full_path, "wb");
#endif
if (!fp) {
fprintf(stderr, "funpack: cannot create: %s\n", full_path);
free(full_path);