diff --git a/compile.mk b/compile.mk index 96ea4b8d..8c3e4d7d 100644 --- a/compile.mk +++ b/compile.mk @@ -34,6 +34,7 @@ endif ifdef ARCH_WIN FLAGS += -DARCH_WIN FLAGS += -D_USE_MATH_DEFINES + FLAGS += -municode CXXFLAGS += -Wsuggest-override endif diff --git a/include/common.hpp b/include/common.hpp index d49446e9..cc1594e4 100644 --- a/include/common.hpp +++ b/include/common.hpp @@ -164,3 +164,23 @@ struct Exception : std::runtime_error { } // namespace rack + + +#if defined ARCH_WIN +// Windows C standard functions are ASCII-8 instead of UTF-8, so redirect these functions to wrappers which convert to UTF-8 +#define fopen fopen_utf8 +#define remove remove_utf8 +#define rename rename_utf8 + +extern "C" { +FILE* fopen_utf8(const char* filename, const char* mode); +int remove_utf8(const char* path); +int rename_utf8(const char* oldname, const char* newname); +} + +namespace std { + using ::fopen_utf8; + using ::remove_utf8; + using ::rename_utf8; +} +#endif diff --git a/src/common.cpp b/src/common.cpp new file mode 100644 index 00000000..9639844a --- /dev/null +++ b/src/common.cpp @@ -0,0 +1,39 @@ +#include + + +#if defined ARCH_WIN +#include + +static wchar_t* utf8_to_w(const char* str) { + int len = MultiByteToWideChar(CP_UTF8, 0, str, -1, 0, 0); + wchar_t* strW = (wchar_t*) malloc(len * sizeof(wchar_t)); + MultiByteToWideChar(CP_UTF8, 0, str, -1, strW, len); + return strW; +} + +FILE* fopen_utf8(const char* filename, const char* mode) { + wchar_t* filenameW = utf8_to_w(filename); + wchar_t* modeW = utf8_to_w(mode); + FILE* file = _wfopen(filenameW, modeW); + free(filenameW); + free(modeW); + return file; +} + +int remove_utf8(const char* path) { + wchar_t* pathW = utf8_to_w(path); + int ret = _wremove(pathW); + free(pathW); + return ret; +} + +int rename_utf8(const char* oldname, const char* newname) { + wchar_t* oldnameW = utf8_to_w(oldname); + wchar_t* newnameW = utf8_to_w(newname); + int ret = _wrename(oldnameW, newnameW); + free(oldnameW); + free(newnameW); + return ret; +} + +#endif diff --git a/src/main.cpp b/src/main.cpp index 6cd1dd07..8d723fc7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -58,7 +58,7 @@ int main(int argc, char* argv[]) { #if defined ARCH_WIN // Windows global mutex to prevent multiple instances // Handle will be closed by Windows when the process ends - HANDLE instanceMutex = CreateMutexA(NULL, true, app::APP_NAME.c_str()); + HANDLE instanceMutex = CreateMutexW(NULL, true, string::toWstring(app::APP_NAME).c_str()); if (GetLastError() == ERROR_ALREADY_EXISTS) { osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Rack is already running. Multiple Rack instances are not supported."); exit(1); diff --git a/src/plugin.cpp b/src/plugin.cpp index 0ed8931b..ecb1e063 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -23,7 +23,6 @@ #if defined ARCH_WIN #include #include - #define mkdir(_dir, _perms) _mkdir(_dir) #else #include #endif @@ -65,7 +64,8 @@ static InitCallback loadLibrary(Plugin* plugin) { // Load dynamic/shared library #if defined ARCH_WIN SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); - HINSTANCE handle = LoadLibrary(libraryFilename.c_str()); + std::wstring libraryFilenameW = string::toWstring(libraryFilename); + HINSTANCE handle = LoadLibraryW(libraryFilenameW.c_str()); SetErrorMode(0); if (!handle) { int error = GetLastError(); @@ -207,7 +207,7 @@ void init() { loadPlugin(""); // Get user plugins directory - mkdir(asset::pluginsPath.c_str(), 0755); + system::createDirectory(asset::pluginsPath); // Extract packages and load plugins extractPackages(asset::pluginsPath); diff --git a/src/system.cpp b/src/system.cpp index 84460c39..53eba432 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -130,7 +130,7 @@ void copyFile(const std::string& srcPath, const std::string& destPath) { void createDirectory(const std::string& path) { #if defined ARCH_WIN std::wstring pathW = string::toWstring(path); - CreateDirectoryW(pathW.c_str(), NULL); + _wmkdir(pathW.c_str()); #else mkdir(path.c_str(), 0755); #endif @@ -148,7 +148,12 @@ void createDirectories(const std::string& path) { void removeDirectory(const std::string& path) { +#if defined ARCH_WIN + std::wstring pathW = string::toWstring(path); + _wrmdir(pathW.c_str()); +#else rmdir(path.c_str()); +#endif }