diff options
| author | Gangzheng Tong <tonggangzheng@gmail.com> | 2025-09-08 10:24:05 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-08 17:24:05 +0000 |
| commit | 3aff764c2b5d613f766538d27e0b9f448e7ed5ca (patch) | |
| tree | 0d21cd8486bb8914a933cd58841e4c9bb246df70 /source/core | |
| parent | 8b512c49d163af1df33e940acc3c4a230f0d00b7 (diff) | |
Use wide char version of Windows API (#8390)
This PR modernizes the Windows-specific code by replacing ANSI Windows
API functions with their Unicode (wide character) counterparts. This
change ensures proper handling of Unicode file paths and strings on
Windows systems.
### File Operations (`source/core/slang-io.cpp`)
- `DeleteFileA` → `DeleteFileW`
- `GetTempPathA` → `GetTempPathW`
- `GetTempFileNameA` → `GetTempFileNameW`
- `RemoveDirectoryA` → `RemoveDirectoryW`
- `SHFileOperationA` → `SHFileOperationW`
- `GetModuleFileNameA` → `GetModuleFileNameW` with UTF-8 conversion
### Platform Operations (`source/core/slang-platform.cpp`)
- `GetModuleHandleExA` → `GetModuleHandleExW`
- `LoadLibraryExA` → `LoadLibraryExW`
- `LoadLibraryA` → `LoadLibraryW`
- `OutputDebugStringA` → `OutputDebugStringW`
### Runtime and Tools
- `MessageBoxA` → `MessageBoxW` in slang-rt
- `GetCurrentDirectoryA` → `GetCurrentDirectoryW` in slang-fiddle
- String literal conversion to wide strings in vk-pipeline-create
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Gangzheng Tong <gtong-nv@users.noreply.github.com>
Co-authored-by: slangbot <ellieh+slangbot@nvidia.com>
Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com>
Diffstat (limited to 'source/core')
| -rw-r--r-- | source/core/slang-io.cpp | 69 | ||||
| -rw-r--r-- | source/core/slang-platform.cpp | 17 |
2 files changed, 55 insertions, 31 deletions
diff --git a/source/core/slang-io.cpp b/source/core/slang-io.cpp index 0720e788f..36c8c560d 100644 --- a/source/core/slang-io.cpp +++ b/source/core/slang-io.cpp @@ -48,8 +48,9 @@ namespace Slang /* static */ SlangResult File::remove(const String& fileName) { #ifdef _WIN32 - // https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-deletefilea - if (DeleteFileA(fileName.getBuffer())) + + // https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-deletefilew + if (DeleteFileW(fileName.toWString())) { return SLANG_OK; } @@ -77,10 +78,10 @@ namespace Slang int count = MAX_PATH + 1; while (true) { - char* chars = tempPath.prepareForAppend(count); + wchar_t* wideChars = (wchar_t*)_alloca(count * sizeof(wchar_t)); // Gets the temp path env string (no guarantee it's a valid path). - // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha - DWORD ret = ::GetTempPathA(count - 1, chars); + // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppathw + DWORD ret = ::GetTempPathW(count - 1, wideChars); if (ret == 0) { return SLANG_FAIL; @@ -90,7 +91,7 @@ namespace Slang count = ret + 1; continue; } - tempPath.appendInPlace(chars, count); + tempPath = String::fromWString(wideChars); break; } } @@ -104,19 +105,18 @@ namespace Slang String tempFileName; { - int count = MAX_PATH + 1; - char* chars = tempFileName.prepareForAppend(count); + wchar_t wideChars[MAX_PATH + 1]; - // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettempfilenamea + // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettempfilenamew // Generates a temporary file name. // Will create a file with this name. - DWORD ret = ::GetTempFileNameA(tempPath.getBuffer(), prefix.getBuffer(), 0, chars); + DWORD ret = ::GetTempFileNameW(tempPath.toWString(), prefix.toWString(), 0, wideChars); if (ret == 0) { return SLANG_FAIL; } - tempFileName.appendInPlace(chars, ::strlen(chars)); + tempFileName = String::fromWString(wideChars); } SLANG_ASSERT(File::exists(tempFileName)); @@ -768,8 +768,8 @@ SlangResult Path::remove(const String& path) { case SLANG_PATH_TYPE_FILE: { - // https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-deletefilea - if (DeleteFileA(path.getBuffer())) + // https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-deletefilew + if (DeleteFileW(path.toWString())) { return SLANG_OK; } @@ -777,8 +777,8 @@ SlangResult Path::remove(const String& path) } case SLANG_PATH_TYPE_DIRECTORY: { - // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-removedirectorya - if (RemoveDirectoryA(path.getBuffer())) + // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-removedirectoryw + if (RemoveDirectoryW(path.toWString())) { return SLANG_OK; } @@ -810,20 +810,26 @@ SlangResult Path::remove(const String& path) // Path::remove() doesn't support remove a non-empty directory, so we need to implement // a simple function to remove the directory recursively. #ifdef _WIN32 - // https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shfileoperationa + // https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shfileoperationw // Note: the fromPath requires a double-null-terminated string. - String newPath = path; - newPath.append('\0'); - SHFILEOPSTRUCTA file_op = { + // Convert to wide string first, then manually create double-null-terminated buffer + auto widePath = path.toWString(); + Index widePathLen = wcslen(widePath); + wchar_t* doubleNullPath = (wchar_t*)_alloca((widePathLen + 2) * sizeof(wchar_t)); + wcscpy(doubleNullPath, widePath); + doubleNullPath[widePathLen] = L'\0'; // First null terminator + doubleNullPath[widePathLen + 1] = L'\0'; // Second null terminator for SHFileOperationW + + SHFILEOPSTRUCTW file_op = { NULL, FO_DELETE, - newPath.begin(), + doubleNullPath, nullptr, FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT, false, 0, nullptr}; - int ret = SHFileOperationA(&file_op); + int ret = SHFileOperationW(&file_op); if (ret) { return SLANG_FAIL; @@ -973,13 +979,28 @@ static SlangResult _calcExectuablePath(char* outPath, size_t* ioSize) SLANG_ASSERT(bufferSize > 0); #if SLANG_WINDOWS_FAMILY - // https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-getmodulefilenamea + // https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-getmodulefilenamew - DWORD res = ::GetModuleFileNameA(::GetModuleHandle(nullptr), outPath, DWORD(bufferSize)); + // Use wide character version and convert back to UTF-8 + wchar_t* widePath = (wchar_t*)_alloca(bufferSize * sizeof(wchar_t)); + DWORD res = ::GetModuleFileNameW(::GetModuleHandle(nullptr), widePath, DWORD(bufferSize)); // If it fits it's the size not including terminator. So must be less than bufferSize if (res < bufferSize) { - return SLANG_OK; + // Convert back to UTF-8 + int utf8Len = WideCharToMultiByte( + CP_UTF8, + 0, + widePath, + -1, + outPath, + (int)bufferSize, + nullptr, + nullptr); + if (utf8Len > 0) + { + return SLANG_OK; + } } return SLANG_E_BUFFER_TOO_SMALL; #elif SLANG_LINUX_FAMILY diff --git a/source/core/slang-platform.cpp b/source/core/slang-platform.cpp index 25e6bc6f0..75c1b96cd 100644 --- a/source/core/slang-platform.cpp +++ b/source/core/slang-platform.cpp @@ -122,7 +122,7 @@ SLANG_COMPILE_TIME_ASSERT(E_OUTOFMEMORY == SLANG_E_OUT_OF_MEMORY); handleOut = nullptr; if (!platformFileName || strlen(platformFileName) == 0) { - if (!GetModuleHandleExA(0, nullptr, (HMODULE*)&handleOut)) + if (!GetModuleHandleExW(0, nullptr, (HMODULE*)&handleOut)) return SLANG_FAIL; return SLANG_OK; } @@ -131,12 +131,14 @@ SLANG_COMPILE_TIME_ASSERT(E_OUTOFMEMORY == SLANG_E_OUT_OF_MEMORY); // First attempt tries on the directories explicitly specified with AddDllDirectory(), // If it failed to find one, we will search over all PATH. // Windows API made two approaches mutually exclusive and we need to try two times. - // https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexa - HMODULE h = LoadLibraryExA(platformFileName, nullptr, LOAD_LIBRARY_SEARCH_USER_DIRS); - // If LoadLibraryExA failed, try again with LoadLibraryA. - // https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-loadlibrarya + // https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw + String platformFileNameStr(platformFileName); + HMODULE h = + LoadLibraryExW(platformFileNameStr.toWString(), nullptr, LOAD_LIBRARY_SEARCH_USER_DIRS); + // If LoadLibraryExW failed, try again with LoadLibraryW. + // https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-loadlibraryw if (!h) - h = LoadLibraryA(platformFileName); + h = LoadLibraryW(platformFileNameStr.toWString()); // If still not found, return an error. if (!h) { @@ -356,7 +358,8 @@ static const PlatformFlags s_familyFlags[int(PlatformFamily::CountOf)] = { /* static */ SlangResult PlatformUtil::outputDebugMessage([[maybe_unused]] const char* text) { #ifdef _WIN32 - OutputDebugStringA(text); + String textStr(text); + OutputDebugStringW(textStr.toWString()); return SLANG_OK; #else return SLANG_E_NOT_AVAILABLE; |
