Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/Vulkan-Loader.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Naumov <andrew-naumov@yandex-team.ru>2022-02-14 14:21:43 +0300
committerCharles Giessen <46324611+charles-lunarg@users.noreply.github.com>2022-06-24 22:14:10 +0300
commit5249c8f8690d0e867f1c0ff16b428f07a805a4d2 (patch)
tree688558e1cdd269917f19a44d70b837f91f30bf43
parent865626abbafda93a236398ac35627407d62dbe6f (diff)
loader: Add unicode support
-rw-r--r--loader/allocation.h7
-rw-r--r--loader/get_environment.c40
-rw-r--r--loader/loader.c11
-rw-r--r--loader/loader_windows.c8
-rw-r--r--loader/stack_allocation.h41
-rw-r--r--loader/vk_loader_platform.h42
-rw-r--r--tests/framework/framework_config.h.in4
-rw-r--r--tests/framework/icd/CMakeLists.txt6
-rw-r--r--tests/framework/test_util.cpp97
-rw-r--r--tests/framework/test_util.h14
-rw-r--r--tests/loader_envvar_tests.cpp13
11 files changed, 222 insertions, 61 deletions
diff --git a/loader/allocation.h b/loader/allocation.h
index 3f272d925..6e2d7ef23 100644
--- a/loader/allocation.h
+++ b/loader/allocation.h
@@ -29,6 +29,7 @@
#pragma once
#include "loader_common.h"
+#include "stack_allocation.h"
void *loader_instance_heap_alloc(const struct loader_instance *instance, size_t size, VkSystemAllocationScope allocation_scope);
void *loader_instance_heap_calloc(const struct loader_instance *instance, size_t size, VkSystemAllocationScope allocation_scope);
@@ -59,9 +60,3 @@ void loader_free_with_instance_fallback(const VkAllocationCallbacks *pAllocator,
void *pMemory);
void *loader_realloc_with_instance_fallback(const VkAllocationCallbacks *pAllocator, const struct loader_instance *instance,
void *pMemory, size_t orig_size, size_t size, VkSystemAllocationScope allocation_scope);
-
-#if defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__) || defined(__QNXNTO__) || defined(__FreeBSD__)
-#define loader_stack_alloc(size) alloca(size)
-#elif defined(_WIN32)
-#define loader_stack_alloc(size) _alloca(size)
-#endif // defined(_WIN32)
diff --git a/loader/get_environment.c b/loader/get_environment.c
index a389a9333..424123895 100644
--- a/loader/get_environment.c
+++ b/loader/get_environment.c
@@ -106,22 +106,40 @@ bool is_high_integrity() {
}
char *loader_getenv(const char *name, const struct loader_instance *inst) {
- char *retVal;
- DWORD valSize;
-
- valSize = GetEnvironmentVariableA(name, NULL, 0);
+ int name_utf16_size = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0);
+ if (name_utf16_size <= 0) {
+ return NULL;
+ }
+ wchar_t *name_utf16 = (wchar_t *)loader_stack_alloc(name_utf16_size * sizeof(wchar_t));
+ if (MultiByteToWideChar(CP_UTF8, 0, name, -1, name_utf16, name_utf16_size) != name_utf16_size) {
+ return NULL;
+ }
- // valSize DOES include the null terminator, so for any set variable
+ DWORD val_size = GetEnvironmentVariableW(name_utf16, NULL, 0);
+ // val_size DOES include the null terminator, so for any set variable
// will always be at least 1. If it's 0, the variable wasn't set.
- if (valSize == 0) return NULL;
-
- retVal = loader_instance_heap_alloc(inst, valSize, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (val_size == 0) {
+ return NULL;
+ }
- if (NULL != retVal) {
- GetEnvironmentVariableA(name, retVal, valSize);
+ wchar_t *val = (wchar_t *)loader_stack_alloc(val_size * sizeof(wchar_t));
+ if (GetEnvironmentVariableW(name_utf16, val, val_size) != val_size - 1) {
+ return NULL;
}
- return retVal;
+ int val_utf8_size = WideCharToMultiByte(CP_UTF8, 0, val, -1, NULL, 0, NULL, NULL);
+ if (val_utf8_size <= 0) {
+ return NULL;
+ }
+ char *val_utf8 = (char *)loader_instance_heap_alloc(inst, val_utf8_size * sizeof(char), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (val_utf8 == NULL) {
+ return NULL;
+ }
+ if (WideCharToMultiByte(CP_UTF8, 0, val, -1, val_utf8, val_utf8_size, NULL, NULL) != val_utf8_size) {
+ loader_instance_heap_free(inst, val_utf8);
+ return NULL;
+ }
+ return val_utf8;
}
char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
diff --git a/loader/loader.c b/loader/loader.c
index fd59f199c..da63d0d72 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -1644,7 +1644,18 @@ static VkResult loader_get_json(const struct loader_instance *inst, const char *
*json = NULL;
+#if defined(_WIN32)
+ int filename_utf16_size = MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0);
+ if (filename_utf16_size > 0) {
+ wchar_t *filename_utf16 = (wchar_t *)loader_stack_alloc(filename_utf16_size * sizeof(wchar_t));
+ if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, filename_utf16, filename_utf16_size) == filename_utf16_size) {
+ file = _wfopen(filename_utf16, L"rb");
+ }
+ }
+#else
file = fopen(filename, "rb");
+#endif
+
if (!file) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to open JSON file %s", filename);
res = VK_ERROR_INITIALIZATION_FAILED;
diff --git a/loader/loader_windows.c b/loader/loader_windows.c
index cc469a4e0..c7fbab9c8 100644
--- a/loader/loader_windows.c
+++ b/loader/loader_windows.c
@@ -73,10 +73,10 @@ void windows_initialization(void) {
// and not after the first call that has been statically linked
LoadLibrary("gdi32.dll");
- TCHAR systemPath[MAX_PATH] = "";
- GetSystemDirectory(systemPath, MAX_PATH);
- StringCchCat(systemPath, MAX_PATH, TEXT("\\dxgi.dll"));
- HMODULE dxgi_module = LoadLibrary(systemPath);
+ wchar_t systemPath[MAX_PATH] = L"";
+ GetSystemDirectoryW(systemPath, MAX_PATH);
+ StringCchCatW(systemPath, MAX_PATH, L"\\dxgi.dll");
+ HMODULE dxgi_module = LoadLibraryW(systemPath);
fpCreateDXGIFactory1 = dxgi_module == NULL ? NULL : (PFN_CreateDXGIFactory1)GetProcAddress(dxgi_module, "CreateDXGIFactory1");
#if !defined(NDEBUG)
diff --git a/loader/stack_allocation.h b/loader/stack_allocation.h
new file mode 100644
index 000000000..0ddd5ca3c
--- /dev/null
+++ b/loader/stack_allocation.h
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright (c) 2014-2022 The Khronos Group Inc.
+ * Copyright (c) 2014-2022 Valve Corporation
+ * Copyright (c) 2014-2022 LunarG, Inc.
+ * Copyright (C) 2015 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Jon Ashburn <jon@lunarg.com>
+ * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
+ * Author: Chia-I Wu <olvaffe@gmail.com>
+ * Author: Chia-I Wu <olv@lunarg.com>
+ * Author: Mark Lobodzinski <mark@LunarG.com>
+ * Author: Lenny Komow <lenny@lunarg.com>
+ * Author: Charles Giessen <charles@lunarg.com>
+ */
+
+#pragma once
+
+#if defined(_WIN32)
+#include <malloc.h>
+#else
+#include <alloca.h>
+#endif
+
+#if defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__) || defined(__QNXNTO__) || defined(__FreeBSD__)
+#define loader_stack_alloc(size) alloca(size)
+#elif defined(_WIN32)
+#define loader_stack_alloc(size) _alloca(size)
+#endif // defined(_WIN32)
diff --git a/loader/vk_loader_platform.h b/loader/vk_loader_platform.h
index 62f74312e..993fe8306 100644
--- a/loader/vk_loader_platform.h
+++ b/loader/vk_loader_platform.h
@@ -76,6 +76,7 @@
#include "vk_loader_layer.h"
#include "vk_layer_dispatch_table.h"
#include "vk_loader_extensions.h"
+#include "stack_allocation.h"
#if defined(__GNUC__) && __GNUC__ >= 4
#define LOADER_EXPORT __attribute__((visibility("default")))
@@ -374,7 +375,15 @@ static inline const wchar_t *LoaderPnpILayerRegistryWide() {
// File IO
static bool loader_platform_file_exists(const char *path) {
- if ((_access(path, 0)) == -1)
+ int path_utf16_size = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
+ if (path_utf16_size <= 0) {
+ return false;
+ }
+ wchar_t *path_utf16 = (wchar_t *)loader_stack_alloc(path_utf16_size * sizeof(wchar_t));
+ if (MultiByteToWideChar(CP_UTF8, 0, path, -1, path_utf16, path_utf16_size) != path_utf16_size) {
+ return false;
+ }
+ if (_waccess(path_utf16, 0) == -1)
return false;
else
return true;
@@ -410,21 +419,40 @@ static inline char *loader_platform_dirname(char *path) {
}
static inline char *loader_platform_executable_path(char *buffer, size_t size) {
- DWORD ret = GetModuleFileName(NULL, buffer, (DWORD)size);
- if (ret == 0) return NULL;
- if (ret > size) return NULL;
- buffer[ret] = '\0';
+ wchar_t *buffer_utf16 = (wchar_t *)loader_stack_alloc(size * sizeof(wchar_t));
+ DWORD ret = GetModuleFileNameW(NULL, buffer_utf16, (DWORD)size);
+ if (ret == 0) {
+ return NULL;
+ }
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ return NULL;
+ }
+ int buffer_utf8_size = WideCharToMultiByte(CP_UTF8, 0, buffer_utf16, -1, NULL, 0, NULL, NULL);
+ if (buffer_utf8_size <= 0 || (size_t)buffer_utf8_size > size) {
+ return NULL;
+ }
+ if (WideCharToMultiByte(CP_UTF8, 0, buffer_utf16, -1, buffer, buffer_utf8_size, NULL, NULL) != buffer_utf8_size) {
+ return NULL;
+ }
return buffer;
}
// Dynamic Loading:
typedef HMODULE loader_platform_dl_handle;
static loader_platform_dl_handle loader_platform_open_library(const char *lib_path) {
+ int lib_path_utf16_size = MultiByteToWideChar(CP_UTF8, 0, lib_path, -1, NULL, 0);
+ if (lib_path_utf16_size <= 0) {
+ return NULL;
+ }
+ wchar_t *lib_path_utf16 = (wchar_t *)loader_stack_alloc(lib_path_utf16_size * sizeof(wchar_t));
+ if (MultiByteToWideChar(CP_UTF8, 0, lib_path, -1, lib_path_utf16, lib_path_utf16_size) != lib_path_utf16_size) {
+ return NULL;
+ }
// Try loading the library the original way first.
- loader_platform_dl_handle lib_handle = LoadLibrary(lib_path);
+ loader_platform_dl_handle lib_handle = LoadLibraryW(lib_path_utf16);
if (lib_handle == NULL && GetLastError() == ERROR_MOD_NOT_FOUND) {
// If that failed, then try loading it with broader search folders.
- lib_handle = LoadLibraryEx(lib_path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
+ lib_handle = LoadLibraryExW(lib_path_utf16, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
}
return lib_handle;
}
diff --git a/tests/framework/framework_config.h.in b/tests/framework/framework_config.h.in
index fca36cb57..4b956937b 100644
--- a/tests/framework/framework_config.h.in
+++ b/tests/framework/framework_config.h.in
@@ -41,6 +41,10 @@
#define TEST_ICD_PATH_VERSION_2 "$<TARGET_FILE:test_icd_version_2>"
+#define TEST_JSON_NAME_VERSION_2_UNICODE "\xf0\x9f\x8c\x8b"
+#define TEST_ICD_PATH_VERSION_2_UNICODE \
+ "$<TARGET_FILE_DIR:test_icd_version_2>/" TEST_JSON_NAME_VERSION_2_UNICODE "$<TARGET_FILE_SUFFIX:test_icd_version_2>"
+
// assumes version 2 exports
#define TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA "$<TARGET_FILE:test_icd_version_2_export_icd_gpdpa>"
diff --git a/tests/framework/icd/CMakeLists.txt b/tests/framework/icd/CMakeLists.txt
index 0ef56601d..9deb6d420 100644
--- a/tests/framework/icd/CMakeLists.txt
+++ b/tests/framework/icd/CMakeLists.txt
@@ -39,3 +39,9 @@ AddSharedLibrary(test_icd_version_2_export_icd_gpdpa DEF_FILE test_icd_2_gpdpa
AddSharedLibrary(test_icd_version_6 DEF_FILE test_icd_6
SOURCES test_icd.cpp
DEFINITIONS TEST_ICD_EXPORT_ICD_GPDPA=1 TEST_ICD_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES=1 ${TEST_ICD_VERSION_2_DEFINES})
+
+add_custom_command(TARGET test_icd_version_2 POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ "$<TARGET_FILE:test_icd_version_2>"
+ "$<TARGET_FILE_DIR:test_icd_version_2>/🌋${CMAKE_SHARED_LIBRARY_SUFFIX}"
+)
diff --git a/tests/framework/test_util.cpp b/tests/framework/test_util.cpp
index 6b796e7ce..1c27c0869 100644
--- a/tests/framework/test_util.cpp
+++ b/tests/framework/test_util.cpp
@@ -58,27 +58,24 @@ void print_error_message(LSTATUS status, const char* function_name, std::string
}
void set_env_var(std::string const& name, std::string const& value) {
- BOOL ret = SetEnvironmentVariableA(name.c_str(), value.c_str());
+ BOOL ret = SetEnvironmentVariableW(widen(name).c_str(), widen(value).c_str());
if (ret == 0) {
- print_error_message(ERROR_SETENV_FAILED, "SetEnvironmentVariableA");
+ print_error_message(ERROR_SETENV_FAILED, "SetEnvironmentVariableW");
}
}
-void remove_env_var(std::string const& name) { SetEnvironmentVariableA(name.c_str(), nullptr); }
-#define ENV_VAR_BUFFER_SIZE 4096
+void remove_env_var(std::string const& name) { SetEnvironmentVariableW(widen(name).c_str(), nullptr); }
std::string get_env_var(std::string const& name, bool report_failure) {
- std::string value;
- value.resize(ENV_VAR_BUFFER_SIZE);
- DWORD ret = GetEnvironmentVariable(name.c_str(), &value[0], ENV_VAR_BUFFER_SIZE);
- if (0 == ret) {
- if (report_failure) print_error_message(ERROR_ENVVAR_NOT_FOUND, "GetEnvironmentVariable");
- return std::string();
- } else if (ENV_VAR_BUFFER_SIZE < ret) {
- if (report_failure) std::cerr << "Not enough space to write environment variable" << name << "\n";
- return std::string();
- } else {
- value.resize(ret);
+ std::wstring name_utf16 = widen(name);
+ DWORD value_size = GetEnvironmentVariableW(name_utf16.c_str(), nullptr, 0);
+ if (0 == value_size) {
+ if (report_failure) print_error_message(ERROR_ENVVAR_NOT_FOUND, "GetEnvironmentVariableW");
+ return {};
}
- return value;
+ std::wstring value(value_size, L'\0');
+ if (GetEnvironmentVariableW(name_utf16.c_str(), &value[0], value_size) != value_size - 1) {
+ return {};
+ }
+ return narrow(value);
}
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
@@ -353,7 +350,7 @@ path& path::replace_filename(path const& replacement) {
// internal implementation helper for per-platform creating & destroying folders
int create_folder(path const& path) {
#if defined(WIN32)
- return _mkdir(path.c_str());
+ return _wmkdir(widen(path.str()).c_str());
#else
mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
return 0;
@@ -362,25 +359,27 @@ int create_folder(path const& path) {
int delete_folder_contents(path const& folder) {
#if defined(WIN32)
- if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(folder.c_str()) && GetLastError() == ERROR_FILE_NOT_FOUND) {
+ std::wstring folder_utf16 = widen(folder.str());
+ if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(folder_utf16.c_str()) && GetLastError() == ERROR_FILE_NOT_FOUND) {
// nothing to delete
return 0;
}
- std::string search_path = folder.str() + "/*.*";
+ std::wstring search_path = folder_utf16 + L"/*.*";
std::string s_p = folder.str() + "/";
- WIN32_FIND_DATA fd;
- HANDLE hFind = ::FindFirstFileA(search_path.c_str(), &fd);
+ WIN32_FIND_DATAW fd;
+ HANDLE hFind = ::FindFirstFileW(search_path.c_str(), &fd);
if (hFind != INVALID_HANDLE_VALUE) {
do {
+ std::string file_name_utf8 = narrow(fd.cFileName);
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- if (!string_eq(fd.cFileName, ".") && !string_eq(fd.cFileName, "..")) {
- delete_folder(s_p + fd.cFileName);
+ if (!string_eq(file_name_utf8.c_str(), ".") && !string_eq(file_name_utf8.c_str(), "..")) {
+ delete_folder(s_p + file_name_utf8);
}
} else {
- std::string child_name = s_p + fd.cFileName;
- DeleteFile(child_name.c_str());
+ std::string child_name = s_p + file_name_utf8;
+ DeleteFileW(widen(child_name).c_str());
}
- } while (::FindNextFile(hFind, &fd));
+ } while (::FindNextFileW(hFind, &fd));
::FindClose(hFind);
}
return 0;
@@ -417,13 +416,19 @@ int delete_folder(path const& folder) {
int ret = delete_folder_contents(folder);
if (ret != 0) return ret;
#if defined(WIN32)
- _rmdir(folder.c_str());
+ _wrmdir(widen(folder.str()).c_str());
return 0;
#else
return rmdir(folder.c_str());
#endif
}
+#if defined(WIN32)
+std::wstring native_path(const std::string& utf8) { return widen(utf8); }
+#else
+const std::string& native_path(const std::string& utf8) { return utf8; }
+#endif
+
FolderManager::FolderManager(path root_path, std::string name) : folder(root_path / name) {
delete_folder_contents(folder);
create_folder(folder);
@@ -447,7 +452,7 @@ path FolderManager::write_manifest(std::string const& name, std::string const& c
} else {
files.emplace_back(name);
}
- auto file = std::ofstream(out_path.str(), std::ios_base::trunc | std::ios_base::out);
+ auto file = std::ofstream(native_path(out_path.str()), std::ios_base::trunc | std::ios_base::out);
if (!file) {
std::cerr << "Failed to create manifest " << name << " at " << out_path.str() << "\n";
return out_path;
@@ -483,12 +488,12 @@ path FolderManager::copy_file(path const& file, std::string const& new_name) {
} else {
files.emplace_back(new_name);
}
- std::ifstream src(file.str(), std::ios::binary);
+ std::ifstream src(native_path(file.str()), std::ios::binary);
if (!src) {
std::cerr << "Failed to create file " << file.str() << " for copying from\n";
return new_filepath;
}
- std::ofstream dst(new_filepath.str(), std::ios::binary);
+ std::ofstream dst(native_path(new_filepath.str()), std::ios::binary);
if (!dst) {
std::cerr << "Failed to create file " << new_filepath.str() << " for copying to\n";
return new_filepath;
@@ -672,3 +677,35 @@ VkDeviceCreateInfo* DeviceCreateInfo::get() noexcept {
dev.pQueueCreateInfos = device_queue_infos.data();
return &dev;
}
+
+#if defined(WIN32)
+std::string narrow(const std::wstring& utf16) {
+ if (utf16.empty()) {
+ return {};
+ }
+ int size = WideCharToMultiByte(CP_UTF8, 0, utf16.data(), static_cast<int>(utf16.size()), nullptr, 0, nullptr, nullptr);
+ if (size <= 0) {
+ return {};
+ }
+ std::string utf8(size, '\0');
+ if (WideCharToMultiByte(CP_UTF8, 0, utf16.data(), static_cast<int>(utf16.size()), &utf8[0], size, nullptr, nullptr) != size) {
+ return {};
+ }
+ return utf8;
+}
+
+std::wstring widen(const std::string& utf8) {
+ if (utf8.empty()) {
+ return {};
+ }
+ int size = MultiByteToWideChar(CP_UTF8, 0, utf8.data(), static_cast<int>(utf8.size()), nullptr, 0);
+ if (size <= 0) {
+ return {};
+ }
+ std::wstring utf16(size, L'\0');
+ if (MultiByteToWideChar(CP_UTF8, 0, utf8.data(), static_cast<int>(utf8.size()), &utf16[0], size) != size) {
+ return {};
+ }
+ return utf16;
+}
+#endif
diff --git a/tests/framework/test_util.h b/tests/framework/test_util.h
index 376602414..d6fe16367 100644
--- a/tests/framework/test_util.h
+++ b/tests/framework/test_util.h
@@ -107,7 +107,6 @@
#if defined(WIN32)
void set_env_var(std::string const& name, std::string const& value);
void remove_env_var(std::string const& name);
-#define ENV_VAR_BUFFER_SIZE 4096
std::string get_env_var(std::string const& name, bool report_failure = true);
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
@@ -243,13 +242,22 @@ inline void copy_string_to_char_array(std::string const& src, char* dst, size_t
}
#if defined(WIN32)
+// Convert an UTF-16 wstring to an UTF-8 string
+std::string narrow(const std::wstring &utf16);
+// Convert an UTF-8 string to an UTF-16 wstring
+std::wstring widen(const std::string &utf8);
+#endif
+
+#if defined(WIN32)
typedef HMODULE loader_platform_dl_handle;
static loader_platform_dl_handle loader_platform_open_library(const char* lib_path) {
+ std::wstring lib_path_utf16 = widen(lib_path);
// Try loading the library the original way first.
- loader_platform_dl_handle lib_handle = LoadLibrary(lib_path);
+ loader_platform_dl_handle lib_handle = LoadLibraryW(lib_path_utf16.c_str());
if (lib_handle == nullptr && GetLastError() == ERROR_MOD_NOT_FOUND) {
// If that failed, then try loading it with broader search folders.
- lib_handle = LoadLibraryEx(lib_path, nullptr, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
+ lib_handle =
+ LoadLibraryExW(lib_path_utf16.c_str(), nullptr, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
}
return lib_handle;
}
diff --git a/tests/loader_envvar_tests.cpp b/tests/loader_envvar_tests.cpp
index 59e5a7020..fb36aa32b 100644
--- a/tests/loader_envvar_tests.cpp
+++ b/tests/loader_envvar_tests.cpp
@@ -90,6 +90,19 @@ TEST(EnvVarICDOverrideSetup, version_2_negotiate_interface_version_and_icd_gipa)
ASSERT_EQ(env.get_test_icd(0).called_vk_icd_gipa, CalledICDGIPA::vk_icd_gipa);
}
+// export vk_icdNegotiateLoaderICDInterfaceVersion and vk_icdGetInstanceProcAddr
+TEST(EnvVarICDOverrideSetup, version_2_negotiate_interface_version_and_icd_gipa_unicode) {
+ FrameworkEnvironment env{};
+ env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_UNICODE)
+ .set_discovery_type(ManifestDiscoveryType::env_var)
+ .set_json_name(TEST_JSON_NAME_VERSION_2_UNICODE));
+
+ InstWrapper inst{env.vulkan_functions};
+ inst.CheckCreate();
+
+ ASSERT_EQ(env.get_test_icd(0).called_vk_icd_gipa, CalledICDGIPA::vk_icd_gipa);
+}
+
// Test VK_DRIVER_FILES environment variable
TEST(EnvVarICDOverrideSetup, TestOnlyDriverEnvVar) {
FrameworkEnvironment env{};