From 53a63187fe6a9808c25b2ea9f1f92fd12bc5e7f3 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Mon, 8 Apr 2019 22:25:27 -0400 Subject: [PATCH] Add partial Unicode handling of filenames on Windows. --- dep/osdialog | 2 +- src/asset.cpp | 24 +++++++++++++++++++----- src/main.cpp | 2 +- src/system.cpp | 22 +++++++++++++++------- 4 files changed, 36 insertions(+), 14 deletions(-) diff --git a/dep/osdialog b/dep/osdialog index e76001ce..724b4287 160000 --- a/dep/osdialog +++ b/dep/osdialog @@ -1 +1 @@ -Subproject commit e76001cea2ae805f6315bb916d902272736913a4 +Subproject commit 724b4287eae674779855adaf250b9ae2ebe85f72 diff --git a/src/asset.cpp b/src/asset.cpp index f2bbaa01..6cdd9ebd 100644 --- a/src/asset.cpp +++ b/src/asset.cpp @@ -43,10 +43,18 @@ void init() { systemDir = resourcesBuf; #endif #if defined ARCH_WIN - char moduleBuf[MAX_PATH]; - DWORD length = GetModuleFileName(NULL, moduleBuf, sizeof(moduleBuf)); + // Get path to executable + wchar_t moduleBufW[MAX_PATH]; + DWORD length = GetModuleFileNameW(NULL, moduleBufW, LENGTHOF(moduleBufW)); assert(length > 0); - PathRemoveFileSpec(moduleBuf); + // Get folder of executable + PathRemoveFileSpecW(moduleBufW); + // Convert to short path to avoid Unicode + wchar_t moduleBufShortW[MAX_PATH]; + GetShortPathNameW(moduleBufW, moduleBufShortW, LENGTHOF(moduleBufShortW)); + // Convert to UTF-8. + char moduleBuf[MAX_PATH]; + WideCharToMultiByte(CP_UTF8, 0, moduleBufShortW, -1, moduleBuf, sizeof(moduleBuf), NULL, NULL); systemDir = moduleBuf; #endif #if defined ARCH_LIN @@ -64,9 +72,15 @@ void init() { else { #if defined ARCH_WIN // Get "My Documents" folder + wchar_t documentsBufW[MAX_PATH] = L"."; + HRESULT result = SHGetFolderPathW(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, documentsBufW); + // assert(result == S_OK); + // Convert to short path to avoid Unicode + wchar_t documentsBufShortW[MAX_PATH]; + GetShortPathNameW(documentsBufW, documentsBufShortW, LENGTHOF(documentsBufShortW)); + // Convert to UTF-8. char documentsBuf[MAX_PATH]; - HRESULT result = SHGetFolderPath(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, documentsBuf); - assert(result == S_OK); + WideCharToMultiByte(CP_UTF8, 0, documentsBufShortW, -1, documentsBuf, sizeof(documentsBuf), NULL, NULL); userDir = documentsBuf; userDir += "/Rack"; #endif diff --git a/src/main.cpp b/src/main.cpp index 8c2603da..ecc9c4d2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,7 +48,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 = CreateMutex(NULL, true, app::APP_NAME); + HANDLE instanceMutex = CreateMutexA(NULL, true, app::APP_NAME); 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/system.cpp b/src/system.cpp index 64abb763..533a87ae 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -85,7 +85,9 @@ void copyFile(const std::string &srcPath, const std::string &destPath) { void createDirectory(const std::string &path) { #if defined ARCH_WIN - CreateDirectory(path.c_str(), NULL); + wchar_t pathW[MAX_PATH]; + MultiByteToWideChar(CP_UTF8, 0, path.c_str(), -1, pathW, LENGTHOF(pathW)); + CreateDirectoryW(pathW, NULL); #else mkdir(path.c_str(), 0755); #endif @@ -160,7 +162,9 @@ void openBrowser(const std::string &url) { std::system(command.c_str()); #endif #if defined ARCH_WIN - ShellExecute(NULL, "open", url.c_str(), NULL, NULL, SW_SHOWNORMAL); + wchar_t urlW[1024]; + MultiByteToWideChar(CP_UTF8, 0, url.c_str(), -1, urlW, LENGTHOF(urlW)); + ShellExecuteW(NULL, L"open", urlW, NULL, NULL, SW_SHOWNORMAL); #endif } @@ -170,21 +174,25 @@ void openFolder(const std::string &path) { (void) std::system(command.c_str()); #endif #if defined ARCH_WIN - ShellExecute(NULL, "explorer", path.c_str(), NULL, NULL, SW_SHOWNORMAL); + wchar_t pathW[MAX_PATH]; + MultiByteToWideChar(CP_UTF8, 0, path.c_str(), -1, pathW, LENGTHOF(pathW)); + ShellExecuteW(NULL, L"explorer", pathW, NULL, NULL, SW_SHOWNORMAL); #endif } void runProcessAsync(const std::string &path) { #if defined ARCH_WIN - STARTUPINFO startupInfo; + STARTUPINFOW startupInfo; PROCESS_INFORMATION processInfo; std::memset(&startupInfo, 0, sizeof(startupInfo)); startupInfo.cb = sizeof(startupInfo); std::memset(&processInfo, 0, sizeof(processInfo)); - CreateProcessA(path.c_str(), NULL, + wchar_t pathW[MAX_PATH]; + MultiByteToWideChar(CP_UTF8, 0, path.c_str(), -1, pathW, LENGTHOF(pathW)); + CreateProcessW(pathW, NULL, NULL, NULL, false, 0, NULL, NULL, &startupInfo, &processInfo); #endif @@ -197,10 +205,10 @@ std::string getOperatingSystemInfo() { uname(&u); return string::f("%s %s %s %s", u.sysname, u.release, u.version, u.machine); #elif defined ARCH_WIN - OSVERSIONINFOA info; + OSVERSIONINFOW info; ZeroMemory(&info, sizeof(info)); info.dwOSVersionInfoSize = sizeof(info); - GetVersionExA(&info); + GetVersionExW(&info); return string::f("Windows %u.%u", info.dwMajorVersion, info.dwMinorVersion); #endif }