Skip to content

Commit 3aff764

Browse files
gtong-nvgithub-actions[bot]slangbot
authored
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>
1 parent 8b512c4 commit 3aff764

5 files changed

Lines changed: 64 additions & 37 deletions

File tree

source/core/slang-io.cpp

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@ namespace Slang
4848
/* static */ SlangResult File::remove(const String& fileName)
4949
{
5050
#ifdef _WIN32
51-
// https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-deletefilea
52-
if (DeleteFileA(fileName.getBuffer()))
51+
52+
// https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-deletefilew
53+
if (DeleteFileW(fileName.toWString()))
5354
{
5455
return SLANG_OK;
5556
}
@@ -77,10 +78,10 @@ namespace Slang
7778
int count = MAX_PATH + 1;
7879
while (true)
7980
{
80-
char* chars = tempPath.prepareForAppend(count);
81+
wchar_t* wideChars = (wchar_t*)_alloca(count * sizeof(wchar_t));
8182
// Gets the temp path env string (no guarantee it's a valid path).
82-
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha
83-
DWORD ret = ::GetTempPathA(count - 1, chars);
83+
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppathw
84+
DWORD ret = ::GetTempPathW(count - 1, wideChars);
8485
if (ret == 0)
8586
{
8687
return SLANG_FAIL;
@@ -90,7 +91,7 @@ namespace Slang
9091
count = ret + 1;
9192
continue;
9293
}
93-
tempPath.appendInPlace(chars, count);
94+
tempPath = String::fromWString(wideChars);
9495
break;
9596
}
9697
}
@@ -104,19 +105,18 @@ namespace Slang
104105
String tempFileName;
105106

106107
{
107-
int count = MAX_PATH + 1;
108-
char* chars = tempFileName.prepareForAppend(count);
108+
wchar_t wideChars[MAX_PATH + 1];
109109

110-
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettempfilenamea
110+
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettempfilenamew
111111
// Generates a temporary file name.
112112
// Will create a file with this name.
113-
DWORD ret = ::GetTempFileNameA(tempPath.getBuffer(), prefix.getBuffer(), 0, chars);
113+
DWORD ret = ::GetTempFileNameW(tempPath.toWString(), prefix.toWString(), 0, wideChars);
114114

115115
if (ret == 0)
116116
{
117117
return SLANG_FAIL;
118118
}
119-
tempFileName.appendInPlace(chars, ::strlen(chars));
119+
tempFileName = String::fromWString(wideChars);
120120
}
121121

122122
SLANG_ASSERT(File::exists(tempFileName));
@@ -768,17 +768,17 @@ SlangResult Path::remove(const String& path)
768768
{
769769
case SLANG_PATH_TYPE_FILE:
770770
{
771-
// https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-deletefilea
772-
if (DeleteFileA(path.getBuffer()))
771+
// https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-deletefilew
772+
if (DeleteFileW(path.toWString()))
773773
{
774774
return SLANG_OK;
775775
}
776776
break;
777777
}
778778
case SLANG_PATH_TYPE_DIRECTORY:
779779
{
780-
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-removedirectorya
781-
if (RemoveDirectoryA(path.getBuffer()))
780+
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-removedirectoryw
781+
if (RemoveDirectoryW(path.toWString()))
782782
{
783783
return SLANG_OK;
784784
}
@@ -810,20 +810,26 @@ SlangResult Path::remove(const String& path)
810810
// Path::remove() doesn't support remove a non-empty directory, so we need to implement
811811
// a simple function to remove the directory recursively.
812812
#ifdef _WIN32
813-
// https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shfileoperationa
813+
// https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shfileoperationw
814814
// Note: the fromPath requires a double-null-terminated string.
815-
String newPath = path;
816-
newPath.append('\0');
817-
SHFILEOPSTRUCTA file_op = {
815+
// Convert to wide string first, then manually create double-null-terminated buffer
816+
auto widePath = path.toWString();
817+
Index widePathLen = wcslen(widePath);
818+
wchar_t* doubleNullPath = (wchar_t*)_alloca((widePathLen + 2) * sizeof(wchar_t));
819+
wcscpy(doubleNullPath, widePath);
820+
doubleNullPath[widePathLen] = L'\0'; // First null terminator
821+
doubleNullPath[widePathLen + 1] = L'\0'; // Second null terminator for SHFileOperationW
822+
823+
SHFILEOPSTRUCTW file_op = {
818824
NULL,
819825
FO_DELETE,
820-
newPath.begin(),
826+
doubleNullPath,
821827
nullptr,
822828
FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT,
823829
false,
824830
0,
825831
nullptr};
826-
int ret = SHFileOperationA(&file_op);
832+
int ret = SHFileOperationW(&file_op);
827833
if (ret)
828834
{
829835
return SLANG_FAIL;
@@ -973,13 +979,28 @@ static SlangResult _calcExectuablePath(char* outPath, size_t* ioSize)
973979
SLANG_ASSERT(bufferSize > 0);
974980

975981
#if SLANG_WINDOWS_FAMILY
976-
// https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-getmodulefilenamea
982+
// https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-getmodulefilenamew
977983

978-
DWORD res = ::GetModuleFileNameA(::GetModuleHandle(nullptr), outPath, DWORD(bufferSize));
984+
// Use wide character version and convert back to UTF-8
985+
wchar_t* widePath = (wchar_t*)_alloca(bufferSize * sizeof(wchar_t));
986+
DWORD res = ::GetModuleFileNameW(::GetModuleHandle(nullptr), widePath, DWORD(bufferSize));
979987
// If it fits it's the size not including terminator. So must be less than bufferSize
980988
if (res < bufferSize)
981989
{
982-
return SLANG_OK;
990+
// Convert back to UTF-8
991+
int utf8Len = WideCharToMultiByte(
992+
CP_UTF8,
993+
0,
994+
widePath,
995+
-1,
996+
outPath,
997+
(int)bufferSize,
998+
nullptr,
999+
nullptr);
1000+
if (utf8Len > 0)
1001+
{
1002+
return SLANG_OK;
1003+
}
9831004
}
9841005
return SLANG_E_BUFFER_TOO_SMALL;
9851006
#elif SLANG_LINUX_FAMILY

source/core/slang-platform.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ SLANG_COMPILE_TIME_ASSERT(E_OUTOFMEMORY == SLANG_E_OUT_OF_MEMORY);
122122
handleOut = nullptr;
123123
if (!platformFileName || strlen(platformFileName) == 0)
124124
{
125-
if (!GetModuleHandleExA(0, nullptr, (HMODULE*)&handleOut))
125+
if (!GetModuleHandleExW(0, nullptr, (HMODULE*)&handleOut))
126126
return SLANG_FAIL;
127127
return SLANG_OK;
128128
}
@@ -131,12 +131,14 @@ SLANG_COMPILE_TIME_ASSERT(E_OUTOFMEMORY == SLANG_E_OUT_OF_MEMORY);
131131
// First attempt tries on the directories explicitly specified with AddDllDirectory(),
132132
// If it failed to find one, we will search over all PATH.
133133
// Windows API made two approaches mutually exclusive and we need to try two times.
134-
// https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexa
135-
HMODULE h = LoadLibraryExA(platformFileName, nullptr, LOAD_LIBRARY_SEARCH_USER_DIRS);
136-
// If LoadLibraryExA failed, try again with LoadLibraryA.
137-
// https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-loadlibrarya
134+
// https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw
135+
String platformFileNameStr(platformFileName);
136+
HMODULE h =
137+
LoadLibraryExW(platformFileNameStr.toWString(), nullptr, LOAD_LIBRARY_SEARCH_USER_DIRS);
138+
// If LoadLibraryExW failed, try again with LoadLibraryW.
139+
// https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-loadlibraryw
138140
if (!h)
139-
h = LoadLibraryA(platformFileName);
141+
h = LoadLibraryW(platformFileNameStr.toWString());
140142
// If still not found, return an error.
141143
if (!h)
142144
{
@@ -356,7 +358,8 @@ static const PlatformFlags s_familyFlags[int(PlatformFamily::CountOf)] = {
356358
/* static */ SlangResult PlatformUtil::outputDebugMessage([[maybe_unused]] const char* text)
357359
{
358360
#ifdef _WIN32
359-
OutputDebugStringA(text);
361+
String textStr(text);
362+
OutputDebugStringW(textStr.toWString());
360363
return SLANG_OK;
361364
#else
362365
return SLANG_E_NOT_AVAILABLE;

source/slang-rt/slang-rt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ extern "C"
1616
{
1717
fprintf(stderr, "%s", errorMessage.getBuffer());
1818
#if SLANG_WINDOWS_FAMILY
19-
MessageBoxA(0, errorMessage.getBuffer(), "Slang Runtime Error", MB_ICONERROR);
19+
MessageBoxW(0, errorMessage.toWString(), L"Slang Runtime Error", MB_ICONERROR);
2020
#endif
2121
abort();
2222
}

tools/slang-fiddle/slang-fiddle-main.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -425,9 +425,12 @@ int main(int argc, char const* const* argv)
425425
}
426426
fprintf(stderr, "\n");
427427

428-
char buffer[1024];
429-
GetCurrentDirectoryA(sizeof(buffer), buffer);
430-
fprintf(stderr, "cwd: %s\n", buffer);
428+
wchar_t wideBuffer[1024];
429+
GetCurrentDirectoryW(sizeof(wideBuffer) / sizeof(wideBuffer[0]), wideBuffer);
430+
431+
// Convert to UTF-8 using String::fromWString
432+
String currentDir = String::fromWString(wideBuffer);
433+
fprintf(stderr, "cwd: %s\n", currentDir.getBuffer());
431434
return 1;
432435
#endif
433436

tools/vk-pipeline-create/main.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,8 @@ void PipelineCreationReplay::initVulkanAPI(IDevice* device)
278278
vkAPI.device = (VkDevice)(handle.handles[2].value);
279279
vkAPI.instance = (VkInstance)(handle.handles[0].value);
280280
#if SLANG_WINDOWS_FAMILY
281-
auto dynamicLibraryName = "vulkan-1.dll";
282-
HMODULE module = ::LoadLibraryA(dynamicLibraryName);
281+
auto dynamicLibraryName = L"vulkan-1.dll";
282+
HMODULE module = ::LoadLibraryW(dynamicLibraryName);
283283
vkAPI.vulkanLibraryHandle = (void*)module;
284284
#define VK_API_GET_GLOBAL_PROC(x) vkAPI.x = (PFN_##x)GetProcAddress(module, #x);
285285
#else

0 commit comments

Comments
 (0)