From 864da5dc23a70ccb0e5ccc84b5843883a2872edc Mon Sep 17 00:00:00 2001 From: Ian Elliott Date: Tue, 31 Mar 2015 15:32:41 -0600 Subject: New loader_get_registry_value() function reads 32/64 registry ... This version should be able to find a key/value if it exists in either the 32 or 64 bit hive. Also, it also doesn't allocate any string data until it knows what size is needed. Changed the "xcv_nvidia.cpp" file to also use the new registry approach. --- loader/loader.c | 81 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 22 deletions(-) (limited to 'loader/loader.c') diff --git a/loader/loader.c b/loader/loader.c index 46a7bfcb..47cfb364 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -25,6 +25,7 @@ * Chia-I Wu * Jon Ashburn * Courtney Goeltzenleuchter + * Ian Elliott */ #define _GNU_SOURCE #include @@ -112,6 +113,57 @@ static struct { #if defined(WIN32) +char *loader_get_registry_string(const HKEY hive, + const LPCTSTR sub_key, + const char *value) +{ + DWORD access_flags = KEY_QUERY_VALUE; + DWORD value_type; + HKEY key; + LONG rtn_value; + char *rtn_str = NULL; + size_t rtn_len = 0; + size_t allocated_len = 0; + + rtn_value = RegOpenKeyEx(hive, sub_key, 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, sub_key, 0, access_flags, &key); + if (rtn_value != ERROR_SUCCESS) { + // We still couldn't find the key, so give up: + return NULL; + } + } + + rtn_value = RegQueryValueEx(key, value, NULL, &value_type, + (PVOID) rtn_str, &rtn_len); + if (rtn_value == ERROR_SUCCESS) { + // If we get to here, we found the key, and need to allocate memory + // large enough for rtn_str, and query again: + allocated_len = rtn_len + 4; + rtn_str = malloc(allocated_len); + rtn_value = RegQueryValueEx(key, value, NULL, &value_type, + (PVOID) rtn_str, &rtn_len); + if (rtn_value == ERROR_SUCCESS) { + // We added 4 extra bytes to rtn_str, so that we can ensure that + // the string is NULL-terminated (albeit, in a brute-force manner): + rtn_str[allocated_len-1] = '\0'; + } else { + // This should never occur, but in case it does, clean up: + free(rtn_str); + rtn_str = NULL; + } + } // else - shouldn't happen, but if it does, return rtn_str, which is NULL + + // Close the registry key that was opened: + RegCloseKey(key); + + return rtn_str; +} + + // For ICD developers, look in the registry, and look for an environment // variable for a path(s) where to find the ICD(s): static char *loader_get_registry_and_env(const char *env_var, @@ -119,30 +171,15 @@ static char *loader_get_registry_and_env(const char *env_var, { char *env_str = getenv(env_var); size_t env_len = (env_str == NULL) ? 0 : strlen(env_str); -#define INITIAL_STR_LEN 1024 - char *registry_str = malloc(INITIAL_STR_LEN); - DWORD registry_len = INITIAL_STR_LEN; - DWORD registry_value_type; - LONG registry_return_value; + char *registry_str = NULL; + DWORD registry_len = 0; char *rtn_str = NULL; size_t rtn_len; - registry_return_value = RegGetValue(HKEY_LOCAL_MACHINE, "Software\\XGL", - registry_value, - (RRF_RT_REG_SZ | RRF_ZEROONFAILURE), - ®istry_value_type, - (PVOID) registry_str, - ®istry_len); - - if (registry_return_value == ERROR_MORE_DATA) { - registry_str = realloc(registry_str, registry_len); - registry_return_value = RegGetValue(HKEY_LOCAL_MACHINE, "Software\\XGL", - registry_value, - (RRF_RT_REG_SZ | RRF_ZEROONFAILURE), - ®istry_value_type, - (PVOID) registry_str, - ®istry_len); - } + registry_str = loader_get_registry_string(HKEY_LOCAL_MACHINE, + "Software\\XGL", + registry_value); + registry_len = strlen(registry_str); rtn_len = env_len + registry_len + 1; if (rtn_len <= 2) { @@ -155,7 +192,7 @@ static char *loader_get_registry_and_env(const char *env_var, rtn_str = malloc(rtn_len); } - if (registry_return_value != ERROR_SUCCESS) { + if (registry_len == 0) { // We didn't find the desired registry value, and so we must have found // only the environment variable: _snprintf(rtn_str, rtn_len, "%s", env_str); -- cgit v1.2.3