mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-24 04:56:14 +01:00
registrybackend: use unicode calls intead of the ansi ones
https://bugzilla.gnome.org/show_bug.cgi?id=761504
This commit is contained in:
parent
7161d70955
commit
05dd91a0b6
@ -62,9 +62,8 @@
|
||||
* allow [A-Za-z\-] so no escaping is needed. No attempt is made to solve
|
||||
* clashes between keys differing only in case.
|
||||
*
|
||||
* - RegCreateKeyA is used - Windows can also handle UTF16LE strings.
|
||||
* GSettings doesn't pay any attention to encoding, so by using ANSI we
|
||||
* hopefully avoid passing any invalid Unicode.
|
||||
* - RegCreateKeyW is used - We should always make the UTF-8 -> UTF-16
|
||||
* conversion ourselves to avoid problems when the system language changes.
|
||||
*
|
||||
* - The Windows registry has the following limitations: a key may not exceed
|
||||
* 255 characters, an entry's value may not exceed 16,383 characters, and
|
||||
@ -159,7 +158,8 @@ G_DECLARE_FINAL_TYPE (GRegistryBackend, g_registry_backend, G, REGISTRY_BACKEND,
|
||||
struct _GRegistryBackend {
|
||||
GSettingsBackend parent_instance;
|
||||
|
||||
char *base_path;
|
||||
gchar *base_path;
|
||||
gunichar2 *base_pathw;
|
||||
|
||||
/* A stored copy of the whole tree being watched. When we receive a change notification
|
||||
* we have to check against this to see what has changed ... every time ...*/
|
||||
@ -771,25 +771,30 @@ registry_read (HKEY hpath,
|
||||
const gchar *value_name,
|
||||
RegistryValue *p_value)
|
||||
{
|
||||
LONG result;
|
||||
DWORD value_data_size;
|
||||
LONG result;
|
||||
DWORD value_data_size;
|
||||
gpointer *buffer;
|
||||
gunichar2 *value_namew;
|
||||
|
||||
g_return_val_if_fail (p_value != NULL, FALSE);
|
||||
|
||||
p_value->type = REG_NONE;
|
||||
p_value->ptr = NULL;
|
||||
|
||||
result = RegQueryValueExA (hpath, value_name, 0, &p_value->type, NULL, &value_data_size);
|
||||
value_namew = g_utf8_to_utf16 (value_name, -1, NULL, NULL, NULL);
|
||||
|
||||
result = RegQueryValueExW (hpath, value_namew, 0, &p_value->type, NULL, &value_data_size);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
handle_read_error (result, path_name, value_name);
|
||||
g_free (value_namew);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (p_value->type == REG_SZ && value_data_size == 0)
|
||||
{
|
||||
p_value->ptr = g_strdup ("");
|
||||
g_free (value_namew);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -799,7 +804,9 @@ registry_read (HKEY hpath,
|
||||
else
|
||||
buffer = p_value->ptr = g_malloc (value_data_size);
|
||||
|
||||
result = RegQueryValueExA (hpath, value_name, 0, NULL, (LPBYTE)buffer, &value_data_size);
|
||||
result = RegQueryValueExW (hpath, value_namew, 0, NULL, (LPBYTE)buffer, &value_data_size);
|
||||
g_free (value_namew);
|
||||
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
handle_read_error (result, path_name, value_name);
|
||||
@ -911,7 +918,9 @@ g_registry_backend_write_one (const char *key_name,
|
||||
HKEY hroot;
|
||||
HKEY hpath;
|
||||
gchar *path_name;
|
||||
gunichar2 *path_namew;
|
||||
gchar *value_name = NULL;
|
||||
gunichar2 *value_namew;
|
||||
DWORD value_data_size;
|
||||
LPVOID value_data;
|
||||
LONG result;
|
||||
@ -993,18 +1002,25 @@ g_registry_backend_write_one (const char *key_name,
|
||||
|
||||
trace ("Set key: %s / %s\n", path_name, value_name);
|
||||
|
||||
path_namew = g_utf8_to_utf16 (path_name, -1, NULL, NULL, NULL);
|
||||
|
||||
/* Store the value in the registry */
|
||||
result = RegCreateKeyExA (hroot, path_name, 0, NULL, 0, KEY_WRITE, NULL, &hpath, NULL);
|
||||
result = RegCreateKeyExW (hroot, path_namew, 0, NULL, 0, KEY_WRITE, NULL, &hpath, NULL);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
g_message_win32_error (result, "gregistrybackend: opening key %s failed",
|
||||
path_name + 1);
|
||||
registry_value_free (value);
|
||||
g_free (path_namew);
|
||||
g_free (path_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
result = RegSetValueExA (hpath, value_name, 0, value.type, value_data, value_data_size);
|
||||
g_free (path_namew);
|
||||
|
||||
value_namew = g_utf8_to_utf16 (value_name, -1, NULL, NULL, NULL);
|
||||
|
||||
result = RegSetValueExW (hpath, value_namew, 0, value.type, value_data, value_data_size);
|
||||
if (result != ERROR_SUCCESS)
|
||||
g_message_win32_error (result, "gregistrybackend: setting value %s\\%s\\%s failed.\n",
|
||||
self->base_path, path_name, value_name);
|
||||
@ -1016,6 +1032,7 @@ g_registry_backend_write_one (const char *key_name,
|
||||
|
||||
RegCloseKey (hpath);
|
||||
g_free (path_name);
|
||||
g_free (value_namew);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@ -1035,7 +1052,7 @@ g_registry_backend_write (GSettingsBackend *backend,
|
||||
HKEY hroot;
|
||||
RegistryWrite action;
|
||||
|
||||
result = RegCreateKeyExA (HKEY_CURRENT_USER, self->base_path, 0, NULL, 0,
|
||||
result = RegCreateKeyExW (HKEY_CURRENT_USER, self->base_pathw, 0, NULL, 0,
|
||||
KEY_WRITE, NULL, &hroot, NULL);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
@ -1063,7 +1080,7 @@ g_registry_backend_write_tree (GSettingsBackend *backend,
|
||||
HKEY hroot;
|
||||
RegistryWrite action;
|
||||
|
||||
result = RegCreateKeyExA (HKEY_CURRENT_USER, self->base_path, 0, NULL, 0,
|
||||
result = RegCreateKeyExW (HKEY_CURRENT_USER, self->base_pathw, 0, NULL, 0,
|
||||
KEY_WRITE, NULL, &hroot, NULL);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
@ -1088,7 +1105,10 @@ g_registry_backend_reset (GSettingsBackend *backend,
|
||||
gpointer origin_tag)
|
||||
{
|
||||
GRegistryBackend *self = G_REGISTRY_BACKEND (backend);
|
||||
gchar *path_name, *value_name = NULL;
|
||||
gchar *path_name;
|
||||
gunichar2 *path_namew;
|
||||
gchar *value_name = NULL;
|
||||
gunichar2 *value_namew;
|
||||
GNode *cache_node;
|
||||
LONG result;
|
||||
HKEY hpath;
|
||||
@ -1102,8 +1122,11 @@ g_registry_backend_reset (GSettingsBackend *backend,
|
||||
|
||||
/* Remove from the registry */
|
||||
path_name = parse_key (key_name, self->base_path, &value_name);
|
||||
path_namew = g_utf8_to_utf16 (path_name, -1, NULL, NULL, NULL);
|
||||
|
||||
result = RegOpenKeyExW (HKEY_CURRENT_USER, path_namew, 0, KEY_SET_VALUE, &hpath);
|
||||
g_free (path_namew);
|
||||
|
||||
result = RegOpenKeyExA (HKEY_CURRENT_USER, path_name, 0, KEY_SET_VALUE, &hpath);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
g_message_win32_error (result, "Registry: resetting key '%s'", path_name);
|
||||
@ -1111,7 +1134,10 @@ g_registry_backend_reset (GSettingsBackend *backend,
|
||||
return;
|
||||
}
|
||||
|
||||
result = RegDeleteValueA (hpath, value_name);
|
||||
value_namew = g_utf8_to_utf16 (value_name, -1, NULL, NULL, NULL);
|
||||
|
||||
result = RegDeleteValueW (hpath, value_namew);
|
||||
g_free (value_namew);
|
||||
RegCloseKey (hpath);
|
||||
|
||||
if (result != ERROR_SUCCESS)
|
||||
@ -1231,7 +1257,8 @@ registry_cache_update (GRegistryBackend *self,
|
||||
int n_watches,
|
||||
RegistryEvent *event)
|
||||
{
|
||||
gchar buffer[MAX_KEY_NAME_LENGTH + 1];
|
||||
gunichar2 bufferw[MAX_KEY_NAME_LENGTH + 1];
|
||||
gchar *buffer;
|
||||
gchar *key_name;
|
||||
gint i;
|
||||
LONG result;
|
||||
@ -1259,20 +1286,24 @@ registry_cache_update (GRegistryBackend *self,
|
||||
i = 0;
|
||||
while (1)
|
||||
{
|
||||
DWORD buffer_size = MAX_KEY_NAME_LENGTH;
|
||||
DWORD bufferw_size = MAX_KEY_NAME_LENGTH + 1;
|
||||
HKEY hsubpath;
|
||||
|
||||
result = RegEnumKeyEx (hpath, i++, buffer, &buffer_size, NULL, NULL, NULL, NULL);
|
||||
result = RegEnumKeyExW (hpath, i++, bufferw, &bufferw_size, NULL, NULL, NULL, NULL);
|
||||
if (result != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
result = RegOpenKeyEx (hpath, buffer, 0, KEY_READ, &hsubpath);
|
||||
result = RegOpenKeyExW (hpath, bufferw, 0, KEY_READ, &hsubpath);
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
GNode *subkey_node;
|
||||
RegistryCacheItem *child_item;
|
||||
gchar *new_partial_key_name;
|
||||
|
||||
buffer = g_utf16_to_utf8 (bufferw, -1, NULL, NULL, NULL);
|
||||
if (buffer == NULL)
|
||||
continue;
|
||||
|
||||
subkey_node = registry_cache_find_immediate_child (cache_node, buffer);
|
||||
if (subkey_node == NULL)
|
||||
{
|
||||
@ -1289,6 +1320,7 @@ registry_cache_update (GRegistryBackend *self,
|
||||
child_item = subkey_node->data;
|
||||
child_item->readable = TRUE;
|
||||
|
||||
g_free (buffer);
|
||||
RegCloseKey (hsubpath);
|
||||
}
|
||||
}
|
||||
@ -1300,24 +1332,32 @@ registry_cache_update (GRegistryBackend *self,
|
||||
i = 0;
|
||||
while (1)
|
||||
{
|
||||
DWORD buffer_size = MAX_KEY_NAME_LENGTH;
|
||||
DWORD bufferw_size = MAX_KEY_NAME_LENGTH + 1;
|
||||
GNode *cache_child_node;
|
||||
RegistryCacheItem *child_item;
|
||||
RegistryValue value;
|
||||
gboolean changed = FALSE;
|
||||
|
||||
result = RegEnumValue (hpath, i++, buffer, &buffer_size, NULL, NULL, NULL, NULL);
|
||||
result = RegEnumValueW (hpath, i++, bufferw, &bufferw_size, NULL, NULL, NULL, NULL);
|
||||
if (result != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
if (buffer[0]==0)
|
||||
/* This is the key's 'default' value, for which we have no use. */
|
||||
continue;
|
||||
buffer = g_utf16_to_utf8 (bufferw, -1, NULL, NULL, NULL);
|
||||
|
||||
if (buffer == NULL || buffer[0] == 0)
|
||||
{
|
||||
/* This is the key's 'default' value, for which we have no use. */
|
||||
g_free (buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
cache_child_node = registry_cache_find_immediate_child (cache_node, buffer);
|
||||
|
||||
if (!registry_read (hpath, key_name, buffer, &value))
|
||||
continue;
|
||||
{
|
||||
g_free (buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
trace ("\tgot value %s for %s, node %x\n",
|
||||
registry_value_dump (value), buffer, cache_child_node);
|
||||
@ -1354,6 +1394,8 @@ registry_cache_update (GRegistryBackend *self,
|
||||
|
||||
g_ptr_array_add (event->items, item);
|
||||
}
|
||||
|
||||
g_free (buffer);
|
||||
}
|
||||
|
||||
if (result != ERROR_NO_MORE_ITEMS)
|
||||
@ -1364,6 +1406,7 @@ registry_cache_update (GRegistryBackend *self,
|
||||
registry_cache_remove_deleted, event);
|
||||
|
||||
trace ("registry cache update complete.\n");
|
||||
|
||||
g_free (key_name);
|
||||
}
|
||||
|
||||
@ -1878,7 +1921,9 @@ g_registry_backend_subscribe (GSettingsBackend *backend,
|
||||
const char *key_name)
|
||||
{
|
||||
GRegistryBackend *self = G_REGISTRY_BACKEND (backend);
|
||||
gchar *path_name, *value_name = NULL;
|
||||
gchar *path_name;
|
||||
gunichar2 *path_namew;
|
||||
gchar *value_name = NULL;
|
||||
HKEY hpath;
|
||||
HANDLE event;
|
||||
LONG result;
|
||||
@ -1904,11 +1949,14 @@ g_registry_backend_subscribe (GSettingsBackend *backend,
|
||||
|
||||
trace ("Subscribing to %s [registry %s / %s] - watch %x\n", key_name, path_name, value_name, self->watch);
|
||||
|
||||
path_namew = g_utf8_to_utf16 (path_name, -1, NULL, NULL, NULL);
|
||||
g_free (path_name);
|
||||
|
||||
/* Give the caller the benefit of the doubt if the key doesn't exist and create it. The caller
|
||||
* is almost certainly a new g_settings with this path as base path. */
|
||||
result = RegCreateKeyExA (HKEY_CURRENT_USER, path_name, 0, NULL, 0, KEY_READ, NULL, &hpath,
|
||||
result = RegCreateKeyExW (HKEY_CURRENT_USER, path_namew, 0, NULL, 0, KEY_READ, NULL, &hpath,
|
||||
NULL);
|
||||
g_free (path_name);
|
||||
g_free (path_namew);
|
||||
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
@ -1971,6 +2019,7 @@ g_registry_backend_finalize (GObject *object)
|
||||
g_slice_free (CRITICAL_SECTION, self->cache_lock);
|
||||
|
||||
g_free (self->base_path);
|
||||
g_free (self->base_pathw);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1994,7 +2043,9 @@ static void
|
||||
g_registry_backend_init (GRegistryBackend *self)
|
||||
{
|
||||
RegistryCacheItem *item;
|
||||
|
||||
self->base_path = g_strdup_printf ("Software\\GSettings");
|
||||
self->base_pathw = g_utf8_to_utf16 (self->base_path, -1, NULL, NULL, NULL);
|
||||
|
||||
item = g_slice_new (RegistryCacheItem);
|
||||
item->value.type = REG_NONE;
|
||||
|
Loading…
Reference in New Issue
Block a user