diff options
| author | Jon Ashburn <jon@lunarg.com> | 2015-06-30 14:46:22 -0700 |
|---|---|---|
| committer | Jon Ashburn <jon@lunarg.com> | 2015-07-01 10:29:45 -0600 |
| commit | 7ddece584fbfde91655486701fbf24afc9082e55 (patch) | |
| tree | 4ecc0bd6c4797d391eba5993aa644c2daf5af264 /loader | |
| parent | f2c5c984f32b658ec3fc647c7393c9d5007efa2a (diff) | |
| download | usermoji-7ddece584fbfde91655486701fbf24afc9082e55.tar.xz | |
loader: Support gettting JSON ICD manifest files from registry
Windows now supports the JSON manifest file for ICDs
Diffstat (limited to 'loader')
| -rw-r--r-- | loader/loader.c | 199 | ||||
| -rw-r--r-- | loader/loader_platform.h | 9 |
2 files changed, 148 insertions, 60 deletions
diff --git a/loader/loader.c b/loader/loader.c index 0258a9be..54d9f795 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -105,7 +105,95 @@ LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_icd); LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_layer); LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_exts); +static void loader_log(VkFlags msg_type, int32_t msg_code, + const char *format, ...) +{ + char msg[256]; + va_list ap; + int ret; + + if (!(msg_type & g_loader_log_msgs)) { + return; + } + + va_start(ap, format); + ret = vsnprintf(msg, sizeof(msg), format, ap); + if ((ret >= (int) sizeof(msg)) || ret < 0) { + msg[sizeof(msg)-1] = '\0'; + } + va_end(ap); + +#if defined(WIN32) + OutputDebugString(msg); +#endif + fputs(msg, stderr); + fputc('\n', stderr); +} + #if defined(WIN32) +/** +* Find the list of registry files (names within a key) in key "location". +* +* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location" +* for a list or name/values which are added to a returned list (function return value). +* The DWORD values within the key must be 0 or they are skipped. +* Function return is a string with a ';' seperated list of filenames. +* Function return is NULL if no valid name/value pairs are found in the key, +* or the key is not found. +* +* \returns +* A string list of filenames as pointer. +* When done using the returned string list, pointer should be freed. +*/ +static char *loader_get_registry_files(const char *location) +{ + LONG rtn_value; + HKEY hive, key; + DWORD access_flags = KEY_QUERY_VALUE; + char name[2048]; + char *out = NULL; + + hive = DEFAULT_VK_REGISTRY_HIVE; + rtn_value = RegOpenKeyEx(hive, location, 0, access_flags, &key); + if (rtn_value != ERROR_SUCCESS) { + // We didn't find the key. Try the 32-bit hive (where we've seen the + // key end up on some people's systems): + access_flags |= KEY_WOW64_32KEY; + rtn_value = RegOpenKeyEx(hive, location, 0, access_flags, &key); + if (rtn_value != ERROR_SUCCESS) { + // We still couldn't find the key, so give up: + return NULL; + } + } + + DWORD idx = 0; + DWORD name_size = sizeof(name); + DWORD value; + DWORD total_size = 4096; + DWORD value_size = sizeof(value); + while((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) { + if (value_size == sizeof(value) && value == 0) { + if (out == NULL) { + out = malloc(total_size); + out[0] = '\0'; + } + else if (strlen(out) + name_size + 1 > total_size) { + out = realloc(out, total_size * 2); + total_size *= 2; + } + if (out == NULL) { + loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory, failed loader_get_registry_files"); + return NULL; + } + if (strlen(out) == 0) + snprintf(out, name_size + 1, "%s", name); + else + snprintf(out + strlen(out), name_size + 1, "%c%s", PATH_SEPERATOR, name); + } + } + return out; +} + char *loader_get_registry_string(const HKEY hive, const LPCTSTR sub_key, const char *value) @@ -113,7 +201,7 @@ char *loader_get_registry_string(const HKEY hive, DWORD access_flags = KEY_QUERY_VALUE; DWORD value_type; HKEY key; - VkResult rtn_value; + LONG rtn_value; char *rtn_str = NULL; DWORD rtn_len = 0; size_t allocated_len = 0; @@ -206,31 +294,6 @@ static char *loader_get_registry_and_env(const char *env_var, } #endif // WIN32 -static void loader_log(VkFlags msg_type, int32_t msg_code, - const char *format, ...) -{ - char msg[256]; - va_list ap; - int ret; - - if (!(msg_type & g_loader_log_msgs)) { - return; - } - - va_start(ap, format); - ret = vsnprintf(msg, sizeof(msg), format, ap); - if ((ret >= (int) sizeof(msg)) || ret < 0) { - msg[sizeof(msg) - 1] = '\0'; - } - va_end(ap); - -#if defined(WIN32) - OutputDebugString(msg); -#endif - fputs(msg, stderr); - fputc('\n', stderr); -} - bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2) { return memcmp(op1, op2, sizeof(VkExtensionProperties)) == 0 ? true : false; @@ -915,12 +978,18 @@ static cJSON *loader_get_json(const char *filename) * A string list of manifest files to be opened in out_files param. * List has a pointer to string for each manifest filename. * When done using the list in out_files, pointers should be freed. + * Location or override string lists can be either files or directories as follows: + * | location | override + * -------------------------------- + * Win ICD | files | files + * Win Layer | files | dirs + * Linux ICD | dirs | files + * Linux Layer| dirs | dirs */ static void loader_get_manifest_files(const char *env_override, - bool override_is_dir, - const char *location, - struct loader_manifest_files *out_files - ) + bool is_layer, + const char *location, + struct loader_manifest_files *out_files) { char *override = NULL; char *loc; @@ -928,16 +997,16 @@ static void loader_get_manifest_files(const char *env_override, size_t alloced_count = 64; char full_path[2048]; DIR *sysdir = NULL; + bool list_is_dirs = false; struct dirent *dent; out_files->count = 0; out_files->filename_list = NULL; - //TODO handle registry locations if (env_override != NULL && (override = getenv(env_override))) { #if defined(__linux__) if (geteuid() != getuid()) { - /* Don't allow setuid apps to use the env var: */ + /* Don't allow setuid apps to use the env var: */ override = NULL; } #endif @@ -945,26 +1014,47 @@ static void loader_get_manifest_files(const char *env_override, if (location == NULL) { loader_log(VK_DBG_REPORT_ERROR_BIT, 0, - "Can't get manifest files with NULL location, env_override=%s", - env_override); + "Can't get manifest files with NULL location, env_override=%s", + env_override); return; } +#if defined(__linux__) + list_is_dirs = (override == NULL || is_layer) ? true : false; +#else //WIN32 + list_is_dirs = (is_layer && override != NULL) ? true : false; +#endif // Make a copy of the input we are using so it is not modified - if (override == NULL) + // Also handle getting the location(s) from registry on Windows + if (override == NULL) { +#if defined (_WIN32) + loc = loader_get_registry_files(location); + if (loc == NULL) { + loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Registry lookup failed can't get manifest files"); + return; + } +#else loc = alloca(strlen(location) + 1); - else + if (loc == NULL) { + loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files"); + return; + } + strcpy(loc, location); +#endif + } + else { loc = alloca(strlen(override) + 1); - if (loc == NULL) { - loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files"); - return; + if (loc == NULL) { + loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files"); + return; + } + strcpy(loc, override); } - strcpy(loc, (override == NULL) ? location : override); file = loc; while (*file) { next_file = loader_get_next_path(file); - if (override == NULL || override_is_dir) { + if (list_is_dirs) { sysdir = opendir(file); name = NULL; if (sysdir) { @@ -977,6 +1067,8 @@ static void loader_get_manifest_files(const char *env_override, } } else { +#if defined(__linux__) + // only Linux has relative paths char *dir; // make a copy of location so it isn't modified dir = alloca(strlen(location) + 1); @@ -989,6 +1081,9 @@ static void loader_get_manifest_files(const char *env_override, loader_get_fullpath(file, dir, sizeof(full_path), full_path); name = full_path; +#else // WIN32 + name = file; +#endif } while (name) { /* Look for files ending with ".json" suffix */ @@ -1015,7 +1110,7 @@ static void loader_get_manifest_files(const char *env_override, strcpy(out_files->filename_list[out_files->count], name); out_files->count++; } - if (override == NULL || override_is_dir) { + if (list_is_dirs) { dent = readdir(sysdir); if (dent == NULL) break; @@ -1054,20 +1149,6 @@ void loader_icd_scan(void) // convenient place to initialize a mutex loader_platform_thread_create_mutex(&loader_lock); -#if 0 //TODO -#if defined(WIN32) - bool must_free_libPaths; - libPaths = loader_get_registry_and_env(DRIVER_PATH_ENV, - DRIVER_PATH_REGISTRY_VALUE); - if (libPaths != NULL) { - must_free_libPaths = true; - } else { - must_free_libPaths = false; - libPaths = DEFAULT_VK_DRIVERS_PATH; - } -#endif // WIN32 -#endif - // convenient place to initialize logging loader_debug_init(); @@ -1091,7 +1172,6 @@ void loader_icd_scan(void) char *icd_filename = cJSON_PrintUnformatted(icd_json); char *icd_file = icd_filename; if (icd_filename != NULL) { - char full_path[2048]; char def_dir[] = DEFAULT_VK_DRIVERS_PATH; char *dir = def_dir; // strip off extra quotes @@ -1099,8 +1179,13 @@ void loader_icd_scan(void) icd_filename[strlen(icd_filename) - 1] = '\0'; if (icd_filename[0] == '"') icd_filename++; +#if defined(__linux__) + char full_path[2048]; loader_get_fullpath(icd_filename, dir, sizeof(full_path), full_path); loader_scanned_icd_add(full_path); +#else // WIN32 + loader_scanned_icd_add(icd_filename); +#endif free(icd_file); } } diff --git a/loader/loader_platform.h b/loader/loader_platform.h index b0bd2d51..a7bd0c64 100644 --- a/loader/loader_platform.h +++ b/loader/loader_platform.h @@ -161,6 +161,8 @@ static inline void loader_platform_thread_cond_broadcast(loader_platform_thread_ #include <windows.h> #include <assert.h> #include <stdio.h> +#include <io.h> +#include <stdbool.h> #ifdef __cplusplus #include <iostream> #include <string> @@ -170,7 +172,8 @@ using namespace std; // VK Library Filenames, Paths, etc.: #define PATH_SEPERATOR ';' #define DIRECTORY_SYMBOL '\\' -#define DEFAULT_VK_DRIVERS_INFO "HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\Drivers" +#define DEFAULT_VK_REGISTRY_HIVE HKEY_LOCAL_MACHINE +#define DEFAULT_VK_DRIVERS_INFO "SOFTWARE\\Khronos\\Vulkan\\Drivers" // TODO: Are these the correct paths #define DEFAULT_VK_DRIVERS_PATH "C:\\Windows\\System32;C:\\Windows\\SysWow64" // TODO/TBD: Is this an appropriate prefix for Windows? @@ -222,9 +225,9 @@ static char *basename(char *pathname) } // File IO -static inline bool loader_platform_file_exists(const char *path) +static bool loader_platform_file_exists(const char *path) { - if (_access(path, 0)) + if ((_access(path, 0)) == -1) return false; else return true; |
