mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-19 23:28:54 +02:00
registrybackend: use unicode calls intead of the ansi ones
https://bugzilla.gnome.org/show_bug.cgi?id=761504
This commit is contained in:
@@ -62,9 +62,8 @@
|
|||||||
* allow [A-Za-z\-] so no escaping is needed. No attempt is made to solve
|
* allow [A-Za-z\-] so no escaping is needed. No attempt is made to solve
|
||||||
* clashes between keys differing only in case.
|
* clashes between keys differing only in case.
|
||||||
*
|
*
|
||||||
* - RegCreateKeyA is used - Windows can also handle UTF16LE strings.
|
* - RegCreateKeyW is used - We should always make the UTF-8 -> UTF-16
|
||||||
* GSettings doesn't pay any attention to encoding, so by using ANSI we
|
* conversion ourselves to avoid problems when the system language changes.
|
||||||
* hopefully avoid passing any invalid Unicode.
|
|
||||||
*
|
*
|
||||||
* - The Windows registry has the following limitations: a key may not exceed
|
* - 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
|
* 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 {
|
struct _GRegistryBackend {
|
||||||
GSettingsBackend parent_instance;
|
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
|
/* 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 ...*/
|
* we have to check against this to see what has changed ... every time ...*/
|
||||||
@@ -774,22 +774,27 @@ registry_read (HKEY hpath,
|
|||||||
LONG result;
|
LONG result;
|
||||||
DWORD value_data_size;
|
DWORD value_data_size;
|
||||||
gpointer *buffer;
|
gpointer *buffer;
|
||||||
|
gunichar2 *value_namew;
|
||||||
|
|
||||||
g_return_val_if_fail (p_value != NULL, FALSE);
|
g_return_val_if_fail (p_value != NULL, FALSE);
|
||||||
|
|
||||||
p_value->type = REG_NONE;
|
p_value->type = REG_NONE;
|
||||||
p_value->ptr = NULL;
|
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)
|
if (result != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
handle_read_error (result, path_name, value_name);
|
handle_read_error (result, path_name, value_name);
|
||||||
|
g_free (value_namew);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_value->type == REG_SZ && value_data_size == 0)
|
if (p_value->type == REG_SZ && value_data_size == 0)
|
||||||
{
|
{
|
||||||
p_value->ptr = g_strdup ("");
|
p_value->ptr = g_strdup ("");
|
||||||
|
g_free (value_namew);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -799,7 +804,9 @@ registry_read (HKEY hpath,
|
|||||||
else
|
else
|
||||||
buffer = p_value->ptr = g_malloc (value_data_size);
|
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)
|
if (result != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
handle_read_error (result, path_name, value_name);
|
handle_read_error (result, path_name, value_name);
|
||||||
@@ -911,7 +918,9 @@ g_registry_backend_write_one (const char *key_name,
|
|||||||
HKEY hroot;
|
HKEY hroot;
|
||||||
HKEY hpath;
|
HKEY hpath;
|
||||||
gchar *path_name;
|
gchar *path_name;
|
||||||
|
gunichar2 *path_namew;
|
||||||
gchar *value_name = NULL;
|
gchar *value_name = NULL;
|
||||||
|
gunichar2 *value_namew;
|
||||||
DWORD value_data_size;
|
DWORD value_data_size;
|
||||||
LPVOID value_data;
|
LPVOID value_data;
|
||||||
LONG result;
|
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);
|
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 */
|
/* 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)
|
if (result != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
g_message_win32_error (result, "gregistrybackend: opening key %s failed",
|
g_message_win32_error (result, "gregistrybackend: opening key %s failed",
|
||||||
path_name + 1);
|
path_name + 1);
|
||||||
registry_value_free (value);
|
registry_value_free (value);
|
||||||
|
g_free (path_namew);
|
||||||
g_free (path_name);
|
g_free (path_name);
|
||||||
return FALSE;
|
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)
|
if (result != ERROR_SUCCESS)
|
||||||
g_message_win32_error (result, "gregistrybackend: setting value %s\\%s\\%s failed.\n",
|
g_message_win32_error (result, "gregistrybackend: setting value %s\\%s\\%s failed.\n",
|
||||||
self->base_path, path_name, value_name);
|
self->base_path, path_name, value_name);
|
||||||
@@ -1016,6 +1032,7 @@ g_registry_backend_write_one (const char *key_name,
|
|||||||
|
|
||||||
RegCloseKey (hpath);
|
RegCloseKey (hpath);
|
||||||
g_free (path_name);
|
g_free (path_name);
|
||||||
|
g_free (value_namew);
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -1035,7 +1052,7 @@ g_registry_backend_write (GSettingsBackend *backend,
|
|||||||
HKEY hroot;
|
HKEY hroot;
|
||||||
RegistryWrite action;
|
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);
|
KEY_WRITE, NULL, &hroot, NULL);
|
||||||
if (result != ERROR_SUCCESS)
|
if (result != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
@@ -1063,7 +1080,7 @@ g_registry_backend_write_tree (GSettingsBackend *backend,
|
|||||||
HKEY hroot;
|
HKEY hroot;
|
||||||
RegistryWrite action;
|
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);
|
KEY_WRITE, NULL, &hroot, NULL);
|
||||||
if (result != ERROR_SUCCESS)
|
if (result != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
@@ -1088,7 +1105,10 @@ g_registry_backend_reset (GSettingsBackend *backend,
|
|||||||
gpointer origin_tag)
|
gpointer origin_tag)
|
||||||
{
|
{
|
||||||
GRegistryBackend *self = G_REGISTRY_BACKEND (backend);
|
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;
|
GNode *cache_node;
|
||||||
LONG result;
|
LONG result;
|
||||||
HKEY hpath;
|
HKEY hpath;
|
||||||
@@ -1102,8 +1122,11 @@ g_registry_backend_reset (GSettingsBackend *backend,
|
|||||||
|
|
||||||
/* Remove from the registry */
|
/* Remove from the registry */
|
||||||
path_name = parse_key (key_name, self->base_path, &value_name);
|
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)
|
if (result != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
g_message_win32_error (result, "Registry: resetting key '%s'", path_name);
|
g_message_win32_error (result, "Registry: resetting key '%s'", path_name);
|
||||||
@@ -1111,7 +1134,10 @@ g_registry_backend_reset (GSettingsBackend *backend,
|
|||||||
return;
|
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);
|
RegCloseKey (hpath);
|
||||||
|
|
||||||
if (result != ERROR_SUCCESS)
|
if (result != ERROR_SUCCESS)
|
||||||
@@ -1231,7 +1257,8 @@ registry_cache_update (GRegistryBackend *self,
|
|||||||
int n_watches,
|
int n_watches,
|
||||||
RegistryEvent *event)
|
RegistryEvent *event)
|
||||||
{
|
{
|
||||||
gchar buffer[MAX_KEY_NAME_LENGTH + 1];
|
gunichar2 bufferw[MAX_KEY_NAME_LENGTH + 1];
|
||||||
|
gchar *buffer;
|
||||||
gchar *key_name;
|
gchar *key_name;
|
||||||
gint i;
|
gint i;
|
||||||
LONG result;
|
LONG result;
|
||||||
@@ -1259,20 +1286,24 @@ registry_cache_update (GRegistryBackend *self,
|
|||||||
i = 0;
|
i = 0;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
DWORD buffer_size = MAX_KEY_NAME_LENGTH;
|
DWORD bufferw_size = MAX_KEY_NAME_LENGTH + 1;
|
||||||
HKEY hsubpath;
|
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)
|
if (result != ERROR_SUCCESS)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
result = RegOpenKeyEx (hpath, buffer, 0, KEY_READ, &hsubpath);
|
result = RegOpenKeyExW (hpath, bufferw, 0, KEY_READ, &hsubpath);
|
||||||
if (result == ERROR_SUCCESS)
|
if (result == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
GNode *subkey_node;
|
GNode *subkey_node;
|
||||||
RegistryCacheItem *child_item;
|
RegistryCacheItem *child_item;
|
||||||
gchar *new_partial_key_name;
|
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);
|
subkey_node = registry_cache_find_immediate_child (cache_node, buffer);
|
||||||
if (subkey_node == NULL)
|
if (subkey_node == NULL)
|
||||||
{
|
{
|
||||||
@@ -1289,6 +1320,7 @@ registry_cache_update (GRegistryBackend *self,
|
|||||||
child_item = subkey_node->data;
|
child_item = subkey_node->data;
|
||||||
child_item->readable = TRUE;
|
child_item->readable = TRUE;
|
||||||
|
|
||||||
|
g_free (buffer);
|
||||||
RegCloseKey (hsubpath);
|
RegCloseKey (hsubpath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1300,24 +1332,32 @@ registry_cache_update (GRegistryBackend *self,
|
|||||||
i = 0;
|
i = 0;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
DWORD buffer_size = MAX_KEY_NAME_LENGTH;
|
DWORD bufferw_size = MAX_KEY_NAME_LENGTH + 1;
|
||||||
GNode *cache_child_node;
|
GNode *cache_child_node;
|
||||||
RegistryCacheItem *child_item;
|
RegistryCacheItem *child_item;
|
||||||
RegistryValue value;
|
RegistryValue value;
|
||||||
gboolean changed = FALSE;
|
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)
|
if (result != ERROR_SUCCESS)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (buffer[0]==0)
|
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. */
|
/* This is the key's 'default' value, for which we have no use. */
|
||||||
|
g_free (buffer);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
cache_child_node = registry_cache_find_immediate_child (cache_node, buffer);
|
cache_child_node = registry_cache_find_immediate_child (cache_node, buffer);
|
||||||
|
|
||||||
if (!registry_read (hpath, key_name, buffer, &value))
|
if (!registry_read (hpath, key_name, buffer, &value))
|
||||||
|
{
|
||||||
|
g_free (buffer);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
trace ("\tgot value %s for %s, node %x\n",
|
trace ("\tgot value %s for %s, node %x\n",
|
||||||
registry_value_dump (value), buffer, cache_child_node);
|
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_ptr_array_add (event->items, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_free (buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != ERROR_NO_MORE_ITEMS)
|
if (result != ERROR_NO_MORE_ITEMS)
|
||||||
@@ -1364,6 +1406,7 @@ registry_cache_update (GRegistryBackend *self,
|
|||||||
registry_cache_remove_deleted, event);
|
registry_cache_remove_deleted, event);
|
||||||
|
|
||||||
trace ("registry cache update complete.\n");
|
trace ("registry cache update complete.\n");
|
||||||
|
|
||||||
g_free (key_name);
|
g_free (key_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1878,7 +1921,9 @@ g_registry_backend_subscribe (GSettingsBackend *backend,
|
|||||||
const char *key_name)
|
const char *key_name)
|
||||||
{
|
{
|
||||||
GRegistryBackend *self = G_REGISTRY_BACKEND (backend);
|
GRegistryBackend *self = G_REGISTRY_BACKEND (backend);
|
||||||
gchar *path_name, *value_name = NULL;
|
gchar *path_name;
|
||||||
|
gunichar2 *path_namew;
|
||||||
|
gchar *value_name = NULL;
|
||||||
HKEY hpath;
|
HKEY hpath;
|
||||||
HANDLE event;
|
HANDLE event;
|
||||||
LONG result;
|
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);
|
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
|
/* 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. */
|
* 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);
|
NULL);
|
||||||
g_free (path_name);
|
g_free (path_namew);
|
||||||
|
|
||||||
if (result != ERROR_SUCCESS)
|
if (result != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
@@ -1971,6 +2019,7 @@ g_registry_backend_finalize (GObject *object)
|
|||||||
g_slice_free (CRITICAL_SECTION, self->cache_lock);
|
g_slice_free (CRITICAL_SECTION, self->cache_lock);
|
||||||
|
|
||||||
g_free (self->base_path);
|
g_free (self->base_path);
|
||||||
|
g_free (self->base_pathw);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1994,7 +2043,9 @@ static void
|
|||||||
g_registry_backend_init (GRegistryBackend *self)
|
g_registry_backend_init (GRegistryBackend *self)
|
||||||
{
|
{
|
||||||
RegistryCacheItem *item;
|
RegistryCacheItem *item;
|
||||||
|
|
||||||
self->base_path = g_strdup_printf ("Software\\GSettings");
|
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 = g_slice_new (RegistryCacheItem);
|
||||||
item->value.type = REG_NONE;
|
item->value.type = REG_NONE;
|
||||||
|
Reference in New Issue
Block a user