Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47109 Signed-off-by: Brendan Shanks bshanks@codeweavers.com --- v5: Write an absolute path to the library in the JSON file, clean up error handling, and remove incorrect error handling in Unregister.
dlls/winevulkan/Makefile.in | 2 +- dlls/winevulkan/make_vulkan | 3 + dlls/winevulkan/vulkan.c | 104 ++++++++++++++++++++++++++++++++ dlls/winevulkan/winevulkan.spec | 2 + loader/wine.inf.in | 1 + 5 files changed, 111 insertions(+), 1 deletion(-)
diff --git a/dlls/winevulkan/Makefile.in b/dlls/winevulkan/Makefile.in index e0bca6fad7..2ffff40c3a 100644 --- a/dlls/winevulkan/Makefile.in +++ b/dlls/winevulkan/Makefile.in @@ -1,6 +1,6 @@ MODULE = winevulkan.dll IMPORTLIB = winevulkan -IMPORTS = user32 gdi32 +IMPORTS = user32 gdi32 advapi32
C_SRCS = \ vulkan.c \ diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index e0b94a06cb..bccfa6a6d6 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -2509,6 +2509,9 @@ class VkGenerator(object): else: f.write("@ stub {0}\n".format(func.name))
+ f.write("@ stdcall -private DllRegisterServer()\n") + f.write("@ stdcall -private DllUnregisterServer()\n") + def generate_vulkan_loader_spec(self, f): self._generate_copyright(f, spec_file=True)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 59472bcef8..257416ab14 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -21,6 +21,7 @@
#include "windef.h" #include "winbase.h" +#include "winreg.h" #include "winuser.h"
#include "vulkan_private.h" @@ -50,6 +51,7 @@ static void *wine_vk_find_struct_(void *s, VkStructureType t)
static void *wine_vk_get_global_proc_addr(const char *name);
+static HINSTANCE hinstance; static const struct vulkan_funcs *vk_funcs; static VkResult (*p_vkEnumerateInstanceVersion)(uint32_t *version);
@@ -1268,6 +1270,7 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved) switch (reason) { case DLL_PROCESS_ATTACH: + hinstance = hinst; DisableThreadLibraryCalls(hinst); return wine_vk_init(); } @@ -1307,3 +1310,104 @@ void *native_vkGetInstanceProcAddrWINE(VkInstance instance, const char *name) { return vk_funcs->p_vkGetInstanceProcAddr(instance, name); } + + +static const WCHAR winevulkan_jsonW[] = {'\','w','i','n','e','v','u','l','k','a','n','.','j','s','o','n',0}; +static const WCHAR vulkan_driversW[] = {'S','o','f','t','w','a','r','e','\','K','h','r','o','n','o','s','\', + 'V','u','l','k','a','n','\','D','r','i','v','e','r','s',0}; +static BOOL writestr(HANDLE handle, const char *str) +{ + DWORD written; + return WriteFile(handle, str, strlen(str), &written, NULL); +} + +HRESULT WINAPI DllRegisterServer(void) +{ + WCHAR json_path[MAX_PATH]; + char dll_path[MAX_PATH], dll_path_escaped[MAX_PATH*2], vk_version[20]; + UINT i, j; + HANDLE file; + HKEY key; + DWORD zero = 0; + + /* Create the JSON manifest and registry key to register this ICD with the official Vulkan loader. */ + TRACE("\n"); + GetSystemDirectoryW(json_path, ARRAY_SIZE(json_path)); + lstrcatW(json_path, winevulkan_jsonW); + file = CreateFileW(json_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (file == INVALID_HANDLE_VALUE) + { + ERR("Unable to create JSON manifest.\n"); + return E_UNEXPECTED; + } + + if (!GetModuleFileNameA(hinstance, dll_path, ARRAY_SIZE(dll_path))) + { + ERR("Unable to get DLL path.\n"); + CloseHandle(file); + return E_UNEXPECTED; + } + /* Backslashes in the path need to be escaped for JSON */ + for (i = 0, j = 0; i < strlen(dll_path) + 1; i++, j++) + { + if (dll_path[i] == '\') + dll_path_escaped[j++] = '\'; + + dll_path_escaped[j] = dll_path[i]; + } + + snprintf(vk_version, sizeof(vk_version), "%u.%u.%u", + VK_VERSION_MAJOR(VK_HEADER_VERSION_COMPLETE), + VK_VERSION_MINOR(VK_HEADER_VERSION_COMPLETE), + VK_VERSION_PATCH(VK_HEADER_VERSION_COMPLETE)); + + writestr(file, "{\r\n"); + writestr(file, " "file_format_version": "1.0.0",\r\n"); + writestr(file, " "ICD": {\r\n"); + writestr(file, " "library_path": ""); + writestr(file, dll_path_escaped); + writestr(file, "",\r\n"); + writestr(file, " "api_version": ""); + writestr(file, vk_version); + writestr(file, ""\r\n"); + writestr(file, " }\r\n"); + writestr(file, "}\r\n"); + CloseHandle(file); + + if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, vulkan_driversW, 0, NULL, 0, KEY_SET_VALUE, + NULL, &key, NULL) != ERROR_SUCCESS) + { + ERR("Unable to create registry key.\n"); + return E_UNEXPECTED; + } + + if (RegSetValueExW(key, json_path, 0, REG_DWORD, (const BYTE *)&zero, sizeof(zero)) != ERROR_SUCCESS) + { + ERR("Unable to set registry value.\n"); + RegCloseKey(key); + return E_UNEXPECTED; + } + + RegCloseKey(key); + return S_OK; +} + +HRESULT WINAPI DllUnregisterServer(void) +{ + WCHAR json_path[MAX_PATH]; + HKEY key; + + /* Remove the JSON manifest and registry key */ + TRACE("\n"); + GetSystemDirectoryW(json_path, ARRAY_SIZE(json_path)); + lstrcatW(json_path, winevulkan_jsonW); + DeleteFileW(json_path); + + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, vulkan_driversW, 0, KEY_SET_VALUE, &key) == ERROR_SUCCESS) + { + RegDeleteValueW(key, json_path); + RegCloseKey(key); + } + + return S_OK; +} diff --git a/dlls/winevulkan/winevulkan.spec b/dlls/winevulkan/winevulkan.spec index c02af5aeaa..e024a43586 100644 --- a/dlls/winevulkan/winevulkan.spec +++ b/dlls/winevulkan/winevulkan.spec @@ -239,3 +239,5 @@ @ stdcall -private wine_vkUpdateDescriptorSets(ptr long ptr long ptr) @ stdcall -private wine_vkWaitForFences(ptr long ptr long int64) @ stdcall -private wine_vkWaitSemaphores(ptr ptr int64) +@ stdcall -private DllRegisterServer() +@ stdcall -private DllUnregisterServer() diff --git a/loader/wine.inf.in b/loader/wine.inf.in index 6e0cb21253..d0b156eb77 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -2569,6 +2569,7 @@ HKLM,%CurrentVersion%\Telephony\Country List\998,"SameAreaRule",,"G" 11,,windowscodecs.dll,1 11,,winegstreamer.dll,1 11,,wineqtdecoder.dll,1 +11,,winevulkan.dll,1 11,,wintrust.dll,1 11,,iexplore.exe,1