mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-03 17:56:17 +01:00
Merge branch 'w32reg-mui' into 'master'
MUI capabilities for GWin32RegistryKey See merge request GNOME/glib!1341
This commit is contained in:
commit
2ba0f14b52
@ -497,80 +497,6 @@ static GWin32RegistryKey *classes_root_key;
|
||||
*/
|
||||
#include "giowin32-private.c"
|
||||
|
||||
static gunichar2 *
|
||||
read_resource_string (gunichar2 *res)
|
||||
{
|
||||
gunichar2 *id_str;
|
||||
gunichar2 *id_str_end;
|
||||
gunichar2 *filename_str;
|
||||
unsigned long id;
|
||||
HMODULE resource_module;
|
||||
gunichar2 *buffer;
|
||||
int string_length;
|
||||
int buffer_length;
|
||||
|
||||
if (res == NULL || res[0] != L'@')
|
||||
return res;
|
||||
|
||||
id_str = wcsrchr (res, L'-');
|
||||
|
||||
if (id_str == NULL || id_str[-1] != L',')
|
||||
return res;
|
||||
|
||||
id_str += 1;
|
||||
|
||||
id = wcstoul (id_str, &id_str_end, 10);
|
||||
|
||||
if (id_str_end == id_str || id_str_end[0] != L'\0' || id == ULONG_MAX)
|
||||
return res;
|
||||
|
||||
filename_str = &res[1];
|
||||
id_str[-2] = L'\0';
|
||||
|
||||
resource_module = LoadLibraryExW (filename_str,
|
||||
0,
|
||||
LOAD_LIBRARY_AS_DATAFILE |
|
||||
LOAD_LIBRARY_AS_IMAGE_RESOURCE);
|
||||
|
||||
g_free (res);
|
||||
|
||||
if (resource_module == NULL)
|
||||
return NULL;
|
||||
|
||||
buffer_length = 256;
|
||||
string_length = buffer_length - 1;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
buffer = g_malloc (buffer_length * sizeof (gunichar2));
|
||||
string_length = LoadStringW (resource_module, id, buffer, buffer_length);
|
||||
|
||||
if (string_length != 0 && string_length == buffer_length - 1)
|
||||
{
|
||||
g_free (buffer);
|
||||
buffer_length *= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string_length == 0)
|
||||
g_clear_pointer (&buffer, g_free);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FreeLibrary (resource_module);
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
gunichar2 *result = g_wcsdup (buffer, -1);
|
||||
g_free (buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
read_handler_icon (GWin32RegistryKey *proxy_key,
|
||||
GWin32RegistryKey *program_key,
|
||||
@ -601,6 +527,7 @@ read_handler_icon (GWin32RegistryKey *proxy_key,
|
||||
gchar *default_value;
|
||||
|
||||
if (g_win32_registry_key_get_value (icon_key,
|
||||
NULL,
|
||||
TRUE,
|
||||
"",
|
||||
&default_type,
|
||||
@ -763,6 +690,7 @@ follow_class_chain_to_handler (const gunichar2 *program_id,
|
||||
if (key != NULL)
|
||||
{
|
||||
got_value = g_win32_registry_key_get_value_w (key,
|
||||
NULL,
|
||||
TRUE,
|
||||
L"",
|
||||
&val_type,
|
||||
@ -799,6 +727,7 @@ follow_class_chain_to_handler (const gunichar2 *program_id,
|
||||
return FALSE;
|
||||
|
||||
got_value = g_win32_registry_key_get_value_w (key,
|
||||
NULL,
|
||||
TRUE,
|
||||
L"",
|
||||
&val_type,
|
||||
@ -826,6 +755,7 @@ follow_class_chain_to_handler (const gunichar2 *program_id,
|
||||
}
|
||||
|
||||
got_value = g_win32_registry_key_get_value_w (key,
|
||||
NULL,
|
||||
TRUE,
|
||||
L"",
|
||||
&val_type,
|
||||
@ -890,6 +820,7 @@ get_url_association (const gunichar2 *schema)
|
||||
schema_rec = g_hash_table_lookup (urls, schema_folded);
|
||||
|
||||
if (!g_win32_registry_key_get_value_w (user_choice,
|
||||
NULL,
|
||||
TRUE,
|
||||
L"Progid",
|
||||
&val_type,
|
||||
@ -1054,6 +985,7 @@ get_file_ext (const gunichar2 *ext)
|
||||
if (user_choice != NULL)
|
||||
{
|
||||
if (g_win32_registry_key_get_value_w (user_choice,
|
||||
NULL,
|
||||
TRUE,
|
||||
L"Progid",
|
||||
&val_type,
|
||||
@ -1336,6 +1268,7 @@ collect_capable_apps_from_clients (GPtrArray *capable_apps,
|
||||
continue;
|
||||
|
||||
if (g_win32_registry_key_get_value_w (system_client_type,
|
||||
NULL,
|
||||
TRUE,
|
||||
L"",
|
||||
&default_type,
|
||||
@ -1591,6 +1524,7 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea
|
||||
shell_open_command = NULL;
|
||||
|
||||
success = g_win32_registry_key_get_value_w (shell_open_command_key,
|
||||
NULL,
|
||||
TRUE,
|
||||
L"",
|
||||
&vtype,
|
||||
@ -1655,6 +1589,7 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea
|
||||
|
||||
fallback_friendly_name = NULL;
|
||||
success = g_win32_registry_key_get_value_w (appkey,
|
||||
NULL,
|
||||
TRUE,
|
||||
L"",
|
||||
&vtype,
|
||||
@ -1678,6 +1613,7 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea
|
||||
|
||||
friendly_name = NULL;
|
||||
success = g_win32_registry_key_get_value_w (capabilities,
|
||||
g_win32_registry_get_os_dirs_w (),
|
||||
TRUE,
|
||||
L"LocalizedString",
|
||||
&vtype,
|
||||
@ -1685,11 +1621,9 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (success && (vtype != G_WIN32_REGISTRY_VALUE_STR || friendly_name[0] != L'@'))
|
||||
if (success && vtype != G_WIN32_REGISTRY_VALUE_STR)
|
||||
g_clear_pointer (&friendly_name, g_free);
|
||||
|
||||
friendly_name = read_resource_string (friendly_name);
|
||||
|
||||
if (friendly_name && app->localized_pretty_name == NULL)
|
||||
{
|
||||
app->localized_pretty_name = g_wcsdup (friendly_name, -1);
|
||||
@ -1703,6 +1637,7 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea
|
||||
|
||||
description = NULL;
|
||||
success = g_win32_registry_key_get_value_w (capabilities,
|
||||
g_win32_registry_get_os_dirs_w (),
|
||||
TRUE,
|
||||
L"ApplicationDescription",
|
||||
&vtype,
|
||||
@ -1713,8 +1648,6 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea
|
||||
if (success && vtype != G_WIN32_REGISTRY_VALUE_STR)
|
||||
g_clear_pointer (&description, g_free);
|
||||
|
||||
description = read_resource_string (description);
|
||||
|
||||
if (description && app->description == NULL)
|
||||
{
|
||||
app->description = g_wcsdup (description, -1);
|
||||
@ -1731,6 +1664,7 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea
|
||||
if (default_icon_key != NULL)
|
||||
{
|
||||
success = g_win32_registry_key_get_value_w (default_icon_key,
|
||||
NULL,
|
||||
TRUE,
|
||||
L"",
|
||||
&vtype,
|
||||
@ -1747,6 +1681,7 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea
|
||||
if (icon_source == NULL)
|
||||
{
|
||||
success = g_win32_registry_key_get_value_w (capabilities,
|
||||
NULL,
|
||||
TRUE,
|
||||
L"ApplicationIcon",
|
||||
&vtype,
|
||||
@ -1767,6 +1702,7 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea
|
||||
|
||||
narrow_application_name = NULL;
|
||||
success = g_win32_registry_key_get_value_w (capabilities,
|
||||
g_win32_registry_get_os_dirs_w (),
|
||||
TRUE,
|
||||
L"ApplicationName",
|
||||
&vtype,
|
||||
@ -1777,8 +1713,6 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea
|
||||
if (success && vtype != G_WIN32_REGISTRY_VALUE_STR)
|
||||
g_clear_pointer (&narrow_application_name, g_free);
|
||||
|
||||
narrow_application_name = read_resource_string (narrow_application_name);
|
||||
|
||||
/* TODO: do something with the narrow name. Maybe make a kind of sub-app?
|
||||
* Narrow name is a more precise name of the application in given context.
|
||||
* I.e. Thunderbird's name is "Thunderbird", whereas its narrow name is
|
||||
@ -2218,6 +2152,7 @@ read_exeapps (void)
|
||||
if (shell_open_command_key != NULL)
|
||||
{
|
||||
success = g_win32_registry_key_get_value_w (shell_open_command_key,
|
||||
NULL,
|
||||
TRUE,
|
||||
L"",
|
||||
&vtype,
|
||||
@ -2237,6 +2172,7 @@ read_exeapps (void)
|
||||
|
||||
friendly_app_name = NULL;
|
||||
success = g_win32_registry_key_get_value_w (incapable_app,
|
||||
g_win32_registry_get_os_dirs_w (),
|
||||
TRUE,
|
||||
L"FriendlyAppName",
|
||||
&vtype,
|
||||
@ -2247,10 +2183,9 @@ read_exeapps (void)
|
||||
if (success && vtype != G_WIN32_REGISTRY_VALUE_STR)
|
||||
g_clear_pointer (&friendly_app_name, g_free);
|
||||
|
||||
friendly_app_name = read_resource_string (friendly_app_name);
|
||||
|
||||
no_open_with = FALSE;
|
||||
success = g_win32_registry_key_get_value_w (incapable_app,
|
||||
NULL,
|
||||
TRUE,
|
||||
L"NoOpenWith",
|
||||
&vtype,
|
||||
@ -2272,6 +2207,7 @@ read_exeapps (void)
|
||||
{
|
||||
success =
|
||||
g_win32_registry_key_get_value_w (default_icon_key,
|
||||
NULL,
|
||||
TRUE,
|
||||
L"",
|
||||
&vtype,
|
||||
@ -2590,6 +2526,7 @@ read_class_url (GWin32RegistryKey *classes_root,
|
||||
return;
|
||||
|
||||
success = g_win32_registry_key_get_value_w (class_key,
|
||||
NULL,
|
||||
TRUE,
|
||||
L"URL Protocol",
|
||||
&vtype,
|
||||
@ -3980,6 +3917,7 @@ get_appath_for_exe (gunichar2 *exe_basename)
|
||||
return NULL;
|
||||
|
||||
got_value = g_win32_registry_key_get_value_w (apppath_key,
|
||||
NULL,
|
||||
TRUE,
|
||||
L"Path",
|
||||
&val_type,
|
||||
|
@ -1838,9 +1838,119 @@ g_win32_registry_key_get_path_w (GWin32RegistryKey *key)
|
||||
return key->priv->absolute_path_w;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_win32_registry_get_os_dirs_w:
|
||||
*
|
||||
* Returns a list of directories for DLL lookups.
|
||||
* Can be used with g_win32_registry_key_get_value_w().
|
||||
*
|
||||
* Returns: (array zero-terminated=1) (transfer none): a %NULL-terminated array of UTF-16 strings.
|
||||
*
|
||||
* Since: 2.66
|
||||
*/
|
||||
const gunichar2 * const *
|
||||
g_win32_registry_get_os_dirs_w (void)
|
||||
{
|
||||
static gunichar2 **mui_os_dirs = NULL;
|
||||
|
||||
if (g_once_init_enter (&mui_os_dirs))
|
||||
{
|
||||
gunichar2 **new_mui_os_dirs;
|
||||
gunichar2 *system32 = NULL;
|
||||
gunichar2 *syswow64 = NULL;
|
||||
UINT buffer_size;
|
||||
gsize array_index = 0;
|
||||
|
||||
buffer_size = GetSystemWow64DirectoryW (NULL, 0);
|
||||
|
||||
if (buffer_size > 0)
|
||||
{
|
||||
UINT copied;
|
||||
syswow64 = g_malloc (buffer_size * sizeof (gunichar2));
|
||||
copied = GetSystemWow64DirectoryW (syswow64, buffer_size);
|
||||
if (copied <= 0)
|
||||
g_clear_pointer (&syswow64, g_free);
|
||||
}
|
||||
|
||||
buffer_size = GetSystemDirectoryW (NULL, 0);
|
||||
|
||||
if (buffer_size > 0)
|
||||
{
|
||||
UINT copied;
|
||||
system32 = g_malloc (buffer_size * sizeof (gunichar2));
|
||||
copied = GetSystemDirectoryW (system32, buffer_size);
|
||||
if (copied <= 0)
|
||||
g_clear_pointer (&system32, g_free);
|
||||
}
|
||||
|
||||
new_mui_os_dirs = g_new0 (gunichar2 *, 3);
|
||||
|
||||
if (system32 != NULL)
|
||||
new_mui_os_dirs[array_index++] = system32;
|
||||
|
||||
if (syswow64 != NULL)
|
||||
new_mui_os_dirs[array_index++] = syswow64;
|
||||
|
||||
new_mui_os_dirs[array_index++] = NULL;
|
||||
|
||||
g_once_init_leave (&mui_os_dirs, new_mui_os_dirs);
|
||||
}
|
||||
|
||||
return (const gunichar2 * const *) mui_os_dirs;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_win32_registry_get_os_dirs:
|
||||
*
|
||||
* Returns a list of directories for DLL lookups.
|
||||
* Can be used with g_win32_registry_key_get_value().
|
||||
*
|
||||
* Returns: (array zero-terminated=1) (transfer none): a %NULL-terminated array of UTF-8 strings.
|
||||
*
|
||||
* Since: 2.66
|
||||
*/
|
||||
const gchar * const *
|
||||
g_win32_registry_get_os_dirs (void)
|
||||
{
|
||||
static gchar **mui_os_dirs = NULL;
|
||||
|
||||
if (g_once_init_enter (&mui_os_dirs))
|
||||
{
|
||||
gchar **new_mui_os_dirs;
|
||||
gsize array_index;
|
||||
gsize new_array_index;
|
||||
const gunichar2 * const *mui_os_dirs_utf16 = g_win32_registry_get_os_dirs_w ();
|
||||
|
||||
for (array_index = 0; mui_os_dirs_utf16[array_index] != NULL; array_index++)
|
||||
;
|
||||
|
||||
new_mui_os_dirs = g_new0 (gchar *, array_index + 1);
|
||||
|
||||
for (array_index = 0, new_array_index = 0;
|
||||
mui_os_dirs_utf16[array_index] != NULL;
|
||||
array_index++)
|
||||
{
|
||||
new_mui_os_dirs[new_array_index] = g_utf16_to_utf8 (mui_os_dirs_utf16[array_index],
|
||||
-1, NULL, NULL, NULL);
|
||||
if (new_mui_os_dirs[new_array_index] != NULL)
|
||||
new_array_index += 1;
|
||||
else
|
||||
g_critical ("Failed to convert to a system directory #%zu to UTF-8", array_index);
|
||||
}
|
||||
|
||||
g_once_init_leave (&mui_os_dirs, new_mui_os_dirs);
|
||||
}
|
||||
|
||||
return (const gchar * const *) mui_os_dirs;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_win32_registry_key_get_value:
|
||||
* @key: (in) (transfer none): a #GWin32RegistryKey
|
||||
* @mui_dll_dirs: (in) (transfer none) (array zero-terminated=1) (optional): a %NULL-terminated
|
||||
* array of directory names where the OS
|
||||
* should look for a DLL indicated in a MUI string, if the
|
||||
* DLL path in the string is not absolute
|
||||
* @auto_expand: (in) %TRUE to automatically expand G_WIN32_REGISTRY_VALUE_EXPAND_STR
|
||||
* to G_WIN32_REGISTRY_VALUE_STR.
|
||||
* @value_name: (in) (transfer none): name of the value to get (in UTF-8).
|
||||
@ -1854,12 +1964,32 @@ g_win32_registry_key_get_path_w (GWin32RegistryKey *key)
|
||||
* Get data from a value of a key. String data is guaranteed to be
|
||||
* appropriately terminated and will be in UTF-8.
|
||||
*
|
||||
* When not %NULL, @mui_dll_dirs indicates that `RegLoadMUIStringW()` API
|
||||
* should be used instead of the usual `RegQueryValueExW()`. This implies
|
||||
* that the value being queried is of type `REG_SZ` or `REG_EXPAND_SZ` (if it is not, the function
|
||||
* falls back to `RegQueryValueExW()`), and that this string must undergo special processing
|
||||
* (see [`SHLoadIndirectString()` documentation](https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-shloadindirectstring) for an explanation on what
|
||||
* kinds of strings are processed) to get the result.
|
||||
*
|
||||
* If no specific MUI DLL directories need to be used, pass
|
||||
* the return value of g_win32_registry_get_os_dirs() as @mui_dll_dirs
|
||||
* (as an bonus, the value from g_win32_registry_get_os_dirs()
|
||||
* does not add any extra UTF8->UTF16 conversion overhead).
|
||||
*
|
||||
* @auto_expand works with @mui_dll_dirs, but only affects the processed
|
||||
* string, making it somewhat useless. The unprocessed string is always expanded
|
||||
* internally, if its type is `REG_EXPAND_SZ` - there is no need to enable
|
||||
* @auto_expand for this to work.
|
||||
*
|
||||
* The API for this function changed in GLib 2.66 to add the @mui_dll_dirs argument.
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE on failure.
|
||||
*
|
||||
* Since: 2.46
|
||||
* Since: 2.66
|
||||
**/
|
||||
gboolean
|
||||
g_win32_registry_key_get_value (GWin32RegistryKey *key,
|
||||
const gchar * const *mui_dll_dirs,
|
||||
gboolean auto_expand,
|
||||
const gchar *value_name,
|
||||
GWin32RegistryValueType *value_type,
|
||||
@ -1874,6 +2004,9 @@ g_win32_registry_key_get_value (GWin32RegistryKey *key,
|
||||
gchar *value_data_u8;
|
||||
gsize value_data_u8_len;
|
||||
gboolean result;
|
||||
gsize mui_dll_dirs_count;
|
||||
gunichar2 **mui_dll_dirs_utf16;
|
||||
const gchar * const *mui_os_dirs;
|
||||
|
||||
g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
|
||||
g_return_val_if_fail (value_name != NULL, FALSE);
|
||||
@ -1889,7 +2022,48 @@ g_win32_registry_key_get_value (GWin32RegistryKey *key,
|
||||
if (value_name_w == NULL)
|
||||
return FALSE;
|
||||
|
||||
mui_dll_dirs_utf16 = NULL;
|
||||
mui_os_dirs = g_win32_registry_get_os_dirs ();
|
||||
|
||||
if (mui_dll_dirs != NULL &&
|
||||
mui_dll_dirs != mui_os_dirs)
|
||||
{
|
||||
gsize i;
|
||||
|
||||
mui_dll_dirs_count = g_strv_length ((gchar **) mui_dll_dirs);
|
||||
mui_dll_dirs_utf16 = g_new0 (gunichar2 *, mui_dll_dirs_count + 1);
|
||||
|
||||
for (i = 0; mui_dll_dirs[i] != NULL; i++)
|
||||
{
|
||||
mui_dll_dirs_utf16[i] = g_utf8_to_utf16 (mui_dll_dirs[i], -1, NULL, NULL, error);
|
||||
|
||||
if (mui_dll_dirs_utf16[i] == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
if (mui_dll_dirs[i] != NULL)
|
||||
{
|
||||
g_prefix_error (error,
|
||||
"A mui_dll_dirs string #%zu `%s' failed to convert: ",
|
||||
i, mui_dll_dirs[i]);
|
||||
|
||||
for (i = 0; i < mui_dll_dirs_count; i++)
|
||||
g_free (mui_dll_dirs_utf16[i]);
|
||||
|
||||
g_free (mui_dll_dirs_utf16);
|
||||
g_free (value_name_w);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if (mui_dll_dirs != NULL &&
|
||||
mui_dll_dirs == mui_os_dirs)
|
||||
{
|
||||
mui_dll_dirs_utf16 = (gunichar2 **) g_win32_registry_get_os_dirs_w ();
|
||||
}
|
||||
|
||||
result = g_win32_registry_key_get_value_w (key,
|
||||
(const gunichar2 * const *) mui_dll_dirs_utf16,
|
||||
auto_expand,
|
||||
value_name_w,
|
||||
&value_type_g,
|
||||
@ -1898,6 +2072,14 @@ g_win32_registry_key_get_value (GWin32RegistryKey *key,
|
||||
error);
|
||||
|
||||
g_free (value_name_w);
|
||||
if (mui_dll_dirs_utf16 != NULL &&
|
||||
mui_dll_dirs != mui_os_dirs)
|
||||
{
|
||||
gsize array_index;
|
||||
for (array_index = 0; mui_dll_dirs_utf16[array_index] != NULL; array_index++)
|
||||
g_free (mui_dll_dirs_utf16[array_index]);
|
||||
g_free (mui_dll_dirs_utf16);
|
||||
}
|
||||
|
||||
if (!result)
|
||||
return FALSE;
|
||||
@ -1944,9 +2126,98 @@ g_win32_registry_key_get_value (GWin32RegistryKey *key,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* A wrapper that calls either RegQueryValueExW() or
|
||||
* RegLoadMUIStringW() depending on the value of the
|
||||
* last argument.
|
||||
* Apart from the extra argument, the function behaves
|
||||
* just like RegQueryValueExW(), with a few caveats.
|
||||
*/
|
||||
static LSTATUS
|
||||
MuiRegQueryValueExW (HKEY hKey,
|
||||
LPCWSTR lpValueName,
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpType,
|
||||
LPBYTE lpData,
|
||||
LPDWORD lpcbData,
|
||||
const gunichar2 * const *mui_dll_dirs)
|
||||
{
|
||||
gsize dir_index;
|
||||
LSTATUS result = ERROR_PATH_NOT_FOUND;
|
||||
DWORD bufsize;
|
||||
DWORD data_size;
|
||||
PVOID old_value;
|
||||
|
||||
if (mui_dll_dirs == NULL)
|
||||
return RegQueryValueExW (hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
|
||||
|
||||
bufsize = 0;
|
||||
|
||||
if (lpcbData != NULL)
|
||||
bufsize = *lpcbData;
|
||||
|
||||
if (mui_dll_dirs[0] != NULL)
|
||||
{
|
||||
/* Optimization: check that the value actually exists,
|
||||
* before we start trying different mui dll dirs
|
||||
*/
|
||||
result = RegQueryValueExW (hKey, lpValueName, NULL, NULL, NULL, 0);
|
||||
|
||||
if (result == ERROR_FILE_NOT_FOUND)
|
||||
return result;
|
||||
}
|
||||
|
||||
Wow64DisableWow64FsRedirection (&old_value);
|
||||
|
||||
/* Try with NULL dir first */
|
||||
result = RegLoadMUIStringW (hKey,
|
||||
lpValueName,
|
||||
(wchar_t *) lpData,
|
||||
bufsize,
|
||||
&data_size,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
/* Not a MUI value, load normally */
|
||||
if (result == ERROR_INVALID_DATA)
|
||||
{
|
||||
Wow64RevertWow64FsRedirection (old_value);
|
||||
|
||||
return RegQueryValueExW (hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
|
||||
}
|
||||
|
||||
for (dir_index = 0;
|
||||
result == ERROR_FILE_NOT_FOUND &&
|
||||
mui_dll_dirs[dir_index] != NULL;
|
||||
dir_index++)
|
||||
result = RegLoadMUIStringW (hKey,
|
||||
lpValueName,
|
||||
(wchar_t *) lpData,
|
||||
bufsize,
|
||||
&data_size,
|
||||
0,
|
||||
mui_dll_dirs[dir_index]);
|
||||
|
||||
Wow64RevertWow64FsRedirection (old_value);
|
||||
|
||||
if (lpcbData != NULL &&
|
||||
result == ERROR_MORE_DATA)
|
||||
*lpcbData = data_size;
|
||||
|
||||
if (lpType != NULL &&
|
||||
result != ERROR_INVALID_DATA &&
|
||||
result != ERROR_FILE_NOT_FOUND)
|
||||
*lpType = REG_SZ;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_win32_registry_key_get_value_w:
|
||||
* @key: (in) (transfer none): a #GWin32RegistryKey
|
||||
* @mui_dll_dirs: (in) (transfer none) (array zero-terminated=1) (optional): a %NULL-terminated
|
||||
* array of directory names where the OS
|
||||
* should look for a DLL indicated in a MUI string, if the
|
||||
* DLL path in the string is not absolute
|
||||
* @auto_expand: (in) %TRUE to automatically expand G_WIN32_REGISTRY_VALUE_EXPAND_STR
|
||||
* to G_WIN32_REGISTRY_VALUE_STR.
|
||||
* @value_name: (in) (transfer none): name of the value to get (in UTF-16).
|
||||
@ -1957,8 +2228,6 @@ g_win32_registry_key_get_value (GWin32RegistryKey *key,
|
||||
* by @value_data.
|
||||
* @error: (nullable): a pointer to %NULL #GError, or %NULL
|
||||
*
|
||||
* Get data from a value of a key.
|
||||
*
|
||||
* Get data from a value of a key. String data is guaranteed to be
|
||||
* appropriately terminated and will be in UTF-16.
|
||||
*
|
||||
@ -1968,12 +2237,30 @@ g_win32_registry_key_get_value (GWin32RegistryKey *key,
|
||||
* termination cannot be checked and fixed unless the data is retreived
|
||||
* too.
|
||||
*
|
||||
* When not %NULL, @mui_dll_dirs indicates that `RegLoadMUIStringW()` API
|
||||
* should be used instead of the usual `RegQueryValueExW()`. This implies
|
||||
* that the value being queried is of type `REG_SZ` or `REG_EXPAND_SZ` (if it is not, the function
|
||||
* falls back to `RegQueryValueExW()`), and that this string must undergo special processing
|
||||
* (see [`SHLoadIndirectString()` documentation](https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-shloadindirectstring) for an explanation on what
|
||||
* kinds of strings are processed) to get the result.
|
||||
*
|
||||
* If no specific MUI DLL directories need to be used, pass
|
||||
* the return value of g_win32_registry_get_os_dirs_w() as @mui_dll_dirs.
|
||||
*
|
||||
* @auto_expand works with @mui_dll_dirs, but only affects the processed
|
||||
* string, making it somewhat useless. The unprocessed string is always expanded
|
||||
* internally, if its type is `REG_EXPAND_SZ` - there is no need to enable
|
||||
* @auto_expand for this to work.
|
||||
*
|
||||
* The API for this function changed in GLib 2.66 to add the @mui_dll_dirs argument.
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE on failure.
|
||||
*
|
||||
* Since: 2.46
|
||||
* Since: 2.66
|
||||
**/
|
||||
gboolean
|
||||
g_win32_registry_key_get_value_w (GWin32RegistryKey *key,
|
||||
const gunichar2 * const *mui_dll_dirs,
|
||||
gboolean auto_expand,
|
||||
const gunichar2 *value_name,
|
||||
GWin32RegistryValueType *value_type,
|
||||
@ -2000,12 +2287,13 @@ g_win32_registry_key_get_value_w (GWin32RegistryKey *key,
|
||||
value_data_size != NULL, FALSE);
|
||||
|
||||
req_value_data_size = 0;
|
||||
status = RegQueryValueExW (key->priv->handle,
|
||||
value_name,
|
||||
NULL,
|
||||
&value_type_w,
|
||||
NULL,
|
||||
&req_value_data_size);
|
||||
status = MuiRegQueryValueExW (key->priv->handle,
|
||||
value_name,
|
||||
NULL,
|
||||
&value_type_w,
|
||||
NULL,
|
||||
&req_value_data_size,
|
||||
mui_dll_dirs);
|
||||
|
||||
if (status != ERROR_MORE_DATA && status != ERROR_SUCCESS)
|
||||
{
|
||||
@ -2032,12 +2320,13 @@ g_win32_registry_key_get_value_w (GWin32RegistryKey *key,
|
||||
|
||||
req_value_data = g_malloc (req_value_data_size + sizeof (gunichar2) * 2);
|
||||
req_value_data_size2 = req_value_data_size;
|
||||
status = RegQueryValueExW (key->priv->handle,
|
||||
value_name,
|
||||
NULL,
|
||||
&value_type_w2,
|
||||
(gpointer) req_value_data,
|
||||
&req_value_data_size2);
|
||||
status = MuiRegQueryValueExW (key->priv->handle,
|
||||
value_name,
|
||||
NULL,
|
||||
&value_type_w2,
|
||||
(gpointer) req_value_data,
|
||||
&req_value_data_size2,
|
||||
mui_dll_dirs);
|
||||
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
|
@ -239,8 +239,9 @@ gboolean g_win32_registry_value_iter_get_data_w (GWin32RegistryValu
|
||||
gsize *value_data_size,
|
||||
GError **error);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_46
|
||||
GLIB_AVAILABLE_IN_2_66
|
||||
gboolean g_win32_registry_key_get_value (GWin32RegistryKey *key,
|
||||
const gchar * const *mui_dll_dirs,
|
||||
gboolean auto_expand,
|
||||
const gchar *value_name,
|
||||
GWin32RegistryValueType *value_type,
|
||||
@ -248,8 +249,9 @@ gboolean g_win32_registry_key_get_value (GWin32RegistryKey
|
||||
gsize *value_data_size,
|
||||
GError **error);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_46
|
||||
GLIB_AVAILABLE_IN_2_66
|
||||
gboolean g_win32_registry_key_get_value_w (GWin32RegistryKey *key,
|
||||
const gunichar2 * const *mui_dll_dirs,
|
||||
gboolean auto_expand,
|
||||
const gunichar2 *value_name,
|
||||
GWin32RegistryValueType *value_type,
|
||||
@ -276,6 +278,12 @@ gboolean g_win32_registry_key_has_changed (GWin32RegistryKey
|
||||
GLIB_AVAILABLE_IN_2_46
|
||||
void g_win32_registry_key_erase_change_indicator (GWin32RegistryKey *key);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_66
|
||||
const gunichar2 * const *g_win32_registry_get_os_dirs_w (void);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_66
|
||||
const gchar * const *g_win32_registry_get_os_dirs (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* G_PLATFORM_WIN32 */
|
||||
|
10
glib.supp
10
glib.supp
@ -887,6 +887,16 @@
|
||||
fun:g_dbus_error_quark
|
||||
}
|
||||
|
||||
# g_win32_registry_get_os_dirs_w*() caches an array of strings that is allocated only once.
|
||||
{
|
||||
g_win32_registry_get_os_dirs
|
||||
Memcheck:Leak
|
||||
match-leak-kinds:reachable,definite
|
||||
fun:malloc
|
||||
...
|
||||
fun:g_win32_registry_get_os_dirs*
|
||||
}
|
||||
|
||||
# Thread-private data allocated once per thread
|
||||
{
|
||||
g_private_set_alloc0
|
||||
|
Loading…
Reference in New Issue
Block a user