[glib] registrybackend: use unicode calls intead of the ansi ones



commit 05dd91a0b6cc8d036d1ef2c0ad457c966223989e
Author: Ignacio Casal Quinteiro <icq gnome org>
Date:   Thu Feb 4 08:39:24 2016 +0100

    registrybackend: use unicode calls intead of the ansi ones
    
    https://bugzilla.gnome.org/show_bug.cgi?id=761504

 gio/gregistrysettingsbackend.c |  107 +++++++++++++++++++++++++++++----------
 1 files changed, 79 insertions(+), 28 deletions(-)
---
diff --git a/gio/gregistrysettingsbackend.c b/gio/gregistrysettingsbackend.c
index 1497c97..2b57a83 100644
--- a/gio/gregistrysettingsbackend.c
+++ b/gio/gregistrysettingsbackend.c
@@ -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;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]