Imported Upstream version 2.66.6
[platform/upstream/glib.git] / gio / gregistrysettingsbackend.c
1 /*
2  * Copyright © 2009-10 Sam Thursfield
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16  *
17  * Author: Sam Thursfield <ssssam@gmail.com>
18  */
19
20 /* GRegistryBackend implementation notes:
21  *
22  *   - All settings are stored under the path:
23  *       HKEY_CURRENT_USER\Software\GSettings\
24  *     This means all settings are per-user. Permissions and system-wide
25  *     defaults are not implemented and will probably always be out of scope of
26  *     the Windows port of GLib.
27  *
28  *   - The registry type system is limited. Most GVariant types are stored as
29  *     literals via g_variant_print/parse(). Strings are stored without the
30  *     quotes that GVariant requires. Integer types are stored as native
31  *     REG_DWORD or REG_QWORD. The REG_MULTI_SZ (string array) type could be
32  *     used to avoid flattening container types.
33  *
34  *   - Notifications are handled; the change event is watched for in a separate
35  *     thread (Windows does not provide a callback API) which sends them with
36  *     g_idle_add to the GLib main loop. The threading is done using Windows
37  *     API functions, so there is no dependence on GThread.
38  *
39  *   - Windows doesn't tell us which value has changed. This means we have to
40  *     maintain a cache of every stored value so we can play spot the
41  *     difference. This should not be a performance issue because if you are
42  *     storing thousands of values in GSettings, you are probably using it
43  *     wrong.
44  *
45  *   - The cache stores the value as a registry type. Because many variants are
46  *     stored as string representations, values which have changed equality but
47  *     not equivalence may trigger spurious change notifications. GSettings
48  *     users must already deal with this possibility and converting all data to
49  *     GVariant values would be more effort.
50  *
51  *   - Because we have to cache every registry value locally, reads are done
52  *     from the cache rather than directly from the registry. Writes update
53  *     both. This means that the backend will not work if the watch thread is
54  *     not running. A GSettings object always subscribes to changes so we can
55  *     be sure that the watch thread will be running, but if for some reason
56  *     the backend is being used directly you should bear that in mind.
57  *
58  *   - The registry is totally user-editable, so we are very forgiving about
59  *     errors in the data we get.
60  *
61  *   - The registry uses backslashes as path separators. GSettings keys only
62  *     allow [A-Za-z\-] so no escaping is needed. No attempt is made to solve
63  *     clashes between keys differing only in case.
64  *
65  *   - RegCreateKeyW is used - We should always make the UTF-8 -> UTF-16
66  *     conversion ourselves to avoid problems when the system language changes.
67  *
68  *   - The Windows registry has the following limitations: a key may not exceed
69  *     255 characters, an entry's value may not exceed 16,383 characters, and
70  *     all the values of a key may not exceed 65,535 characters.
71  *
72  *   - Terminology:
73  *     * in GSettings, a 'key' is eg. /desktop/gnome/background/primary-color
74  *     * in the registry, the 'key' is path, which contains some 'values'.
75  *     * in this file, any GSettings key is a 'key', while a registry key is
76  *       termed a 'path', which contains 'values'.
77  *
78  *   - My set of tests for this backend are currently at:
79  *       http://gitorious.org/gsettings-gtk/gsettings-test.git
80  *
81  *   - There is an undocumented function in ntdll.dll which might be more
82  *     than RegNotifyChangeKeyValue(), NtNotifyChangeKey:
83  *       http://source.winehq.org/source/dlls/ntdll/reg.c#L618
84  *       http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/Key/NtNotifyChangeKey.html
85  *
86  *   - If updating the cache ever becomes a performance issue it may make sense
87  *     to use a red-black tree, but I don't currently think it's worth the time
88  */
89
90 #include "config.h"
91
92 #include "gregistrysettingsbackend.h"
93 #include "gsettingsbackend.h"
94 #include "giomodule.h"
95
96 #include <windows.h>
97
98 //#define TRACE
99
100 /* GSettings' limit */
101 #define MAX_KEY_NAME_LENGTH   128
102
103 /* Testing (on Windows XP SP3) shows that WaitForMultipleObjects fails with
104  * "The parameter is incorrect" after 64 watches. We need one for the
105  * message_sent cond, which is allowed for in the way the watches_remaining
106  * variable is used.
107  */
108 #define MAX_WATCHES   64
109
110 /* A watch on one registry path and its subkeys */
111 typedef struct
112 {
113   HANDLE event;
114   HKEY hpath;
115   char *prefix;
116   GNode *cache_node;
117 } RegistryWatch;
118
119 /* Simple message passing for the watch thread. Not enough traffic to
120  * justify a queue.
121  */
122 typedef enum
123 {
124   WATCH_THREAD_NONE,
125   WATCH_THREAD_ADD_WATCH,
126   WATCH_THREAD_REMOVE_WATCH,
127   WATCH_THREAD_STOP
128 } WatchThreadMessageType;
129
130 typedef struct
131 {
132   WatchThreadMessageType type;
133   RegistryWatch watch;
134 } WatchThreadMessage;
135
136 typedef struct
137 {
138   GSettingsBackend *owner;
139   HANDLE *thread;
140
141   /* Details of the things we are watching. */
142   int watches_remaining;
143   GPtrArray *events, *handles, *prefixes, *cache_nodes;
144
145   /* Communication with the main thread. Only one message is stored at a time,
146    * to make sure that messages are acknowledged before being overwritten we
147    * create two events - one is signalled when a new message is set, the
148    * other is signalled by the thread when it has processed the message.
149    */
150   WatchThreadMessage message;
151   CRITICAL_SECTION *message_lock;
152   HANDLE message_sent_event, message_received_event;
153 } WatchThreadState;
154
155 #define G_TYPE_REGISTRY_BACKEND      (g_registry_backend_get_type ())
156 #define G_REGISTRY_BACKEND(inst)     (G_TYPE_CHECK_INSTANCE_CAST ((inst),         \
157                                       G_TYPE_REGISTRY_BACKEND, GRegistryBackend))
158 #define G_IS_REGISTRY_BACKEND(inst)  (G_TYPE_CHECK_INSTANCE_TYPE ((inst),         \
159                                       G_TYPE_REGISTRY_BACKEND))
160
161 typedef GSettingsBackendClass GRegistryBackendClass;
162
163 typedef struct {
164   GSettingsBackend parent_instance;
165
166   gchar *base_path;
167   gunichar2 *base_pathw;
168
169   /* A stored copy of the whole tree being watched. When we receive a change notification
170    * we have to check against this to see what has changed ... every time ...*/
171   CRITICAL_SECTION *cache_lock;
172   GNode *cache_root;
173
174   WatchThreadState *watch;
175 } GRegistryBackend;
176
177 G_DEFINE_TYPE_WITH_CODE (GRegistryBackend,
178                          g_registry_backend,
179                          G_TYPE_SETTINGS_BACKEND,
180                          g_io_extension_point_implement (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME,
181                                                          g_define_type_id, "registry", 90))
182
183 /**********************************************************************************
184  * Utility functions
185  **********************************************************************************/
186
187 #include <stdio.h>
188 static void
189 trace (const char *format,
190        ...)
191 {
192 #ifdef TRACE
193   va_list va; va_start (va, format);
194   vprintf (format, va);
195   fflush (stdout);
196   va_end (va);
197 #endif
198 }
199
200 /* g_message including a windows error message. It is not useful to have an
201  * equivalent function for g_warning because none of the registry errors can
202  * result from programmer error (Microsoft programmers don't count), instead
203  * they will mostly occur from people messing with the registry by hand. */
204 static void G_GNUC_PRINTF (2, 3)
205 g_message_win32_error (DWORD        result_code,
206                        const gchar *format,
207                       ...)
208 {
209   va_list va;
210   gchar *message;
211   gchar *win32_error;
212   gchar *win32_message;
213
214   g_return_if_fail (result_code != 0);
215
216   va_start (va, format);
217   message = g_strdup_vprintf (format, va);
218   win32_error = g_win32_error_message (result_code);
219   win32_message = g_strdup_printf ("%s: %s", message, win32_error);
220   g_free (message);
221   g_free (win32_error);
222
223   if (result_code == ERROR_KEY_DELETED)
224     trace ("(%s)", win32_message);
225   else
226     g_message ("%s", win32_message);
227
228   g_free (win32_message);
229 }
230
231 /* Make gsettings key into a registry path & value pair. 
232  * 
233  * Note that the return value *only* needs freeing - registry_value_name
234  * is a pointer to further inside the same block of memory.
235  */
236 static gchar *
237 parse_key (const gchar  *key_name,
238            const gchar  *registry_prefix,
239            gchar       **value_name)
240 {
241   gchar *path_name, *c;
242
243   /* All key paths are treated as absolute; gsettings doesn't seem to enforce a
244    * preceding /.
245    */
246   if (key_name[0] == '/')
247     key_name++;
248
249   if (registry_prefix == NULL)
250     path_name = g_strdup (key_name);
251   else
252     path_name = g_strjoin ("/", registry_prefix, key_name, NULL);
253
254   /* Prefix is expected to be in registry format (\ separators) so don't escape that. */
255   for (c = path_name + (registry_prefix ? strlen (registry_prefix) : 0); *c != 0; c++)
256     {
257       if (*c == '/')
258         {
259           *c = '\\';
260           *value_name = c;
261         }
262     }
263
264   **value_name = 0;
265   (*value_name)++;
266
267   return path_name;
268 }
269
270 static DWORD
271 g_variant_get_as_dword (GVariant *variant)
272 {
273   switch (g_variant_get_type_string (variant)[0])
274     {
275     case 'b':
276       return g_variant_get_boolean (variant);
277     case 'y':
278       return g_variant_get_byte (variant);
279     case 'n':
280       return g_variant_get_int16 (variant);
281     case 'q':
282       return g_variant_get_uint16 (variant);
283     case 'i':
284       return g_variant_get_int32 (variant);
285     case 'u':
286       return g_variant_get_uint32 (variant);
287     default:
288       g_warn_if_reached ();
289     }
290   return 0;
291 }
292
293 static DWORDLONG
294 g_variant_get_as_qword (GVariant *variant)
295 {
296   switch (g_variant_get_type_string (variant)[0])
297     {
298     case 'x':
299       return g_variant_get_int64 (variant);
300     case 't':
301       return g_variant_get_uint64 (variant);
302     default:
303       g_warn_if_reached ();
304     }
305   return 0;
306 }
307
308 static void
309 handle_read_error (LONG         result,
310                    const gchar *path_name,
311                    const gchar *value_name)
312 {
313   /* file not found means key value not set, this isn't an error for us. */
314   if (result != ERROR_FILE_NOT_FOUND)
315     g_message_win32_error (result, "Unable to query value %s/%s",
316                            path_name, value_name);
317 }
318
319 /***************************************************************************
320  * Cache of registry values
321  ***************************************************************************/
322
323 /* Generic container for registry values */
324 typedef struct {
325   DWORD type;
326
327   union {
328     gint  dword;  /* FIXME: could inline QWORD on 64-bit systems too */
329     void *ptr;
330   };
331 } RegistryValue;
332
333 static char *
334 registry_value_dump (RegistryValue value)
335 {
336   if (value.type == REG_DWORD)
337     return g_strdup_printf ("%d", value.dword);
338   else if (value.type == REG_QWORD)
339     return g_strdup_printf ("%"G_GINT64_FORMAT, value.ptr == NULL ? 0: *(DWORDLONG *)value.ptr);
340   else if (value.type == REG_SZ)
341     return g_strdup_printf ("%s", (char *)value.ptr);
342   else if (value.type == REG_NONE)
343     return g_strdup_printf ("<empty>");
344   else
345     return g_strdup_printf ("<invalid>");
346 }
347
348 static void
349 registry_value_free (RegistryValue value)
350 {
351   if (value.type == REG_SZ || value.type == REG_QWORD)
352     g_free (value.ptr);
353
354   value.type = REG_NONE;
355   value.ptr = NULL;
356 }
357
358 /* The registry cache is stored as a tree, for easy traversal. Right now we
359  * don't sort it in a clever way. Each node corresponds to a path element
360  * ('key' in registry terms) or a value.
361  *
362  * Each subscription uses the same cache. Because GSettings can subscribe to
363  * the tree at any node any number of times, we need to reference count the
364  * nodes.
365  */
366 typedef struct
367 {
368   /* Component of path that this node represents */
369   gchar *name;
370
371   /* If a watch is subscribed at this point (subscription_count > 0) we can
372    * block its next notification. This is useful because if two watches cover
373    * the same path, both will trigger when it changes. It also allows changes
374    * done by the application to be ignored by the watch thread.
375    */
376   gint32 block_count : 8;
377
378   /* Number of times g_settings_subscribe has been called for this location
379    * (I guess you can't subscribe more than 16383 times) */
380   gint32 subscription_count : 14;
381   
382   gint32 ref_count : 9;
383
384   gint32 readable : 1;
385   RegistryValue value;
386 } RegistryCacheItem;
387
388 static GNode *
389 registry_cache_add_item (GNode         *parent,
390                          gchar         *name,
391                          RegistryValue  value,
392                          gint           ref_count)
393 {
394   RegistryCacheItem *item;
395   GNode *cache_node;
396
397   g_return_val_if_fail (name != NULL, NULL);
398   g_return_val_if_fail (parent != NULL, NULL);
399
400   item = g_slice_new (RegistryCacheItem);
401
402   /* Ref count should be the number of watch points above this node */
403   item->ref_count = ref_count;
404
405   item->name = g_strdup (name);
406   item->value = value;
407   item->subscription_count = 0;
408   item->block_count = 0;
409   item->readable = FALSE;
410
411   trace ("\tregistry cache: adding %s to %s\n",
412          name, ((RegistryCacheItem *)parent->data)->name);
413
414   cache_node = g_node_new (item);
415   g_node_append (parent, cache_node);
416
417   return cache_node;
418 }
419
420 /* The reference counting of cache tree nodes works like this: when a node is
421  * subscribed to (GSettings wants us to watch that path and everything below
422  * it) the reference count of that node and everything below is increased, as
423  * well as each parent up to the root.
424  */
425
426 static void
427 _ref_down (GNode *node)
428 {
429   RegistryCacheItem *item = node->data;
430
431   g_node_children_foreach (node, G_TRAVERSE_ALL,
432                            (GNodeForeachFunc)_ref_down, NULL);
433   item->ref_count++;
434 }
435
436 static void
437 registry_cache_ref_tree (GNode *tree)
438 {
439   RegistryCacheItem *item = tree->data;
440   GNode *node = tree->parent;
441
442   g_return_if_fail (tree != NULL);
443
444   item->ref_count++;
445
446   g_node_children_foreach (tree, G_TRAVERSE_ALL,
447                            (GNodeForeachFunc)_ref_down, NULL);
448
449   for (node = tree->parent; node; node = node->parent)
450     {
451       item = node->data;
452       item->ref_count++;
453     }
454 }
455
456 static void
457 registry_cache_item_free (RegistryCacheItem *item)
458 {
459   trace ("\t -- Free node %s\n", item->name);
460
461   g_free (item->name);
462   registry_value_free (item->value);
463   g_slice_free (RegistryCacheItem, item);
464 }
465
466 /* Unreferencing has to be done bottom-up */
467 static void
468 _unref_node (GNode *node)
469 {
470   RegistryCacheItem *item = node->data;
471
472   item->ref_count--;
473
474   g_warn_if_fail (item->ref_count >= 0);
475
476   if (item->ref_count == 0)
477     {
478       registry_cache_item_free (item);
479       g_node_destroy (node);
480     }
481 }
482
483 static void
484 _unref_down (GNode *node)
485 {
486   g_node_children_foreach (node, G_TRAVERSE_ALL,
487                            (GNodeForeachFunc)_unref_down, NULL);
488   _unref_node (node);
489 }
490
491 static void
492 registry_cache_unref_tree (GNode *tree)
493 {
494   GNode *parent = tree->parent, *next_parent;
495
496   _unref_down (tree);
497
498   while (parent)
499     {
500       next_parent = parent->parent;
501       _unref_node (parent);
502       parent = next_parent;
503     }
504 }
505
506 #if 0
507 static void
508 registry_cache_dump (GNode    *cache_node,
509                      gpointer  data)
510 {
511   RegistryCacheItem *item = cache_node->data;
512
513   int depth     = GPOINTER_TO_INT(data),
514       new_depth = depth+1,
515       i;
516
517   g_return_if_fail (cache_node != NULL);
518
519   for (i=0; i<depth; i++)
520     g_print ("  ");
521   if (item == NULL)
522     g_print ("*root*\n");
523   else
524     g_print ("'%s'  [%i] @ %x = %s\n", item->name, item->ref_count, (guint)cache_node,
525              registry_value_dump (item->value));
526   g_node_children_foreach (cache_node, G_TRAVERSE_ALL, registry_cache_dump,
527                            GINT_TO_POINTER (new_depth));
528 }
529 #endif
530
531 typedef struct
532 {
533   gchar *name;
534   GNode *result;
535 } RegistryCacheSearch;
536
537 static gboolean
538 registry_cache_find_compare (GNode    *node,
539                              gpointer  data)
540 {
541   RegistryCacheSearch *search = data;
542   RegistryCacheItem *item = node->data;
543
544   if (item == NULL)  /* root node */
545     return FALSE;
546
547   g_return_val_if_fail (search->name != NULL, FALSE);
548   g_return_val_if_fail (item->name != NULL, FALSE);
549
550   if (strcmp (search->name, item->name) == 0)
551     {
552       search->result = node;
553       return TRUE;
554     }
555
556   return FALSE;
557 }
558
559 static GNode *
560 registry_cache_find_immediate_child (GNode *node,
561                                      gchar *name)
562 {
563   RegistryCacheSearch search;
564
565   search.result = NULL;
566   search.name = name;
567
568   g_node_traverse (node, G_POST_ORDER, G_TRAVERSE_ALL, 2,
569                    registry_cache_find_compare, &search);
570
571   return search.result;
572 }
573
574 static GNode *
575 registry_cache_get_node_for_key_recursive (GNode    *node,
576                                            gchar    *key_name,
577                                            gboolean  create_if_not_found,
578                                            gint      n_parent_watches)
579 {
580   RegistryCacheItem *item;
581   gchar *component = key_name;
582   gchar *c = strchr (component, '/');
583   GNode *child;
584
585   if (c != NULL)
586     *c = 0;
587
588   /* We count up how many watch points we travel through finding this node,
589    * because a new node should have as many references as there are watches at
590    * points above it in the tree.
591    */
592   item = node->data;
593   if (item->subscription_count > 0)
594     n_parent_watches++;
595
596   child = registry_cache_find_immediate_child (node, component);
597   if (child == NULL && create_if_not_found)
598     {
599       RegistryValue null_value = { REG_NONE, {0} };
600
601       child = registry_cache_add_item (node, component,
602                                        null_value, n_parent_watches);
603
604       trace ("\tget node for key recursive: new %x = %s.\n", node, component);
605     }
606
607   /* We are done if there are no more path components. Allow for a trailing /. */
608   if (child == NULL || c == NULL || *(c + 1) == 0)
609     return child;
610
611   trace ("get node for key recursive: next: %s.\n", c + 1);
612
613   return registry_cache_get_node_for_key_recursive (child, c + 1,
614                                                     create_if_not_found,
615                                                     n_parent_watches);
616 }
617
618 /* Look up a GSettings key in the cache. */
619 static GNode *
620 registry_cache_get_node_for_key (GNode       *root,
621                                  const gchar *key_name,
622                                  gboolean     create_if_not_found)
623 {
624   GNode *child = NULL;
625   GNode *result = NULL;
626   gchar *component, *c;
627
628   g_return_val_if_fail (key_name != NULL, NULL);
629
630   if (key_name[0] == '/')
631     key_name++;
632
633   /* Ignore preceding / */
634   component = g_strdup (key_name);
635   c = strchr (component, '/');
636
637   if (c == NULL)
638     {
639       g_free (component);
640       return root;
641     }
642
643   if (c != NULL)
644     *c = 0;
645
646   child = registry_cache_find_immediate_child (root, component);
647   if (child == NULL && create_if_not_found)
648     {
649       RegistryValue null_value = { REG_NONE, {0} };
650
651       /* Reference count is set to 0, tree should be referenced by the caller */
652       child = registry_cache_add_item (root, component,
653                                        null_value, 0);
654
655       trace ("get_node_for_key: New node for component '%s'\n", component);
656     }
657
658   if (*(c + 1) == 0)
659     result = child;
660   else if (child != NULL)
661     result = registry_cache_get_node_for_key_recursive (child, c + 1,
662                                                         create_if_not_found, 0);
663
664   g_free (component);
665
666   return result;
667 }
668
669 /* Check the cache node against the registry key it represents. Return TRUE if
670  * they differ, and update the cache with the new value.
671  */
672 static gboolean
673 registry_cache_update_node (GNode        *cache_node,
674                             RegistryValue registry_value)
675 {
676   RegistryCacheItem *cache_item;
677
678   g_return_val_if_fail (cache_node != NULL, FALSE);
679   g_return_val_if_fail (cache_node->data != NULL, FALSE);
680
681   cache_item = cache_node->data;
682
683   if (registry_value.type != cache_item->value.type)
684     {
685       /* The type has changed. Update cache item and register it as changed.
686        * Either the schema has changed and this is entirely legitimate, or
687        * whenever the app reads the key it will get the default value due to
688        * the type mismatch.
689        */
690       cache_item->value = registry_value;
691       return TRUE;
692     }
693  
694   switch (registry_value.type)
695     {
696     case REG_DWORD:
697       {
698         if (cache_item->value.dword == registry_value.dword)
699           return FALSE;
700         else
701           {
702             cache_item->value.dword = registry_value.dword;
703             return TRUE;
704           }
705       }
706     case REG_QWORD:
707       {
708         g_return_val_if_fail (registry_value.ptr != NULL &&
709                               cache_item->value.ptr != NULL, FALSE);
710
711         if (memcmp (registry_value.ptr, cache_item->value.ptr, 8)==0)
712           {
713             g_free (registry_value.ptr);
714             return FALSE;
715           }
716         else
717           {
718             g_free (cache_item->value.ptr);
719             cache_item->value.ptr = registry_value.ptr;
720             return TRUE;
721           }
722       }
723     case REG_SZ:
724       {
725         /* Value should not exist if it is NULL, an empty string is "" */
726         g_return_val_if_fail (cache_item->value.ptr != NULL, FALSE);
727         g_return_val_if_fail (registry_value.ptr != NULL, FALSE);
728
729         if (strcmp (registry_value.ptr, cache_item->value.ptr) == 0)
730           {
731             g_free (registry_value.ptr);
732             return FALSE;
733           }
734         else
735           {
736             g_free (cache_item->value.ptr);
737             cache_item->value.ptr = registry_value.ptr;
738             return TRUE;
739           }
740       }
741     default:
742       g_warning ("gregistrybackend: registry_cache_update_node: Unhandled value type");
743       return FALSE;
744     }
745 }
746
747 /* Blocking notifications is a useful optimisation. When a change is made
748  * through GSettings we update the cache manually, but a notification is
749  * triggered as well. This function is also used for nested notifications,
750  * eg. if /test and /test/foo are watched, and /test/foo/value is changed then
751  * we will get notified both for /test/foo and /test and it is helpful to block
752  * the second.
753  */
754 static void
755 registry_cache_block_notification (GNode *node)
756 {
757   RegistryCacheItem *item = node->data;
758
759   g_return_if_fail (node != NULL);
760
761   if (item->subscription_count > 0)
762     item->block_count++;
763
764   if (node->parent != NULL)
765     registry_cache_block_notification (node->parent);
766 }
767
768 static void registry_cache_destroy_tree (GNode            *node,
769                                          WatchThreadState *self);
770
771 /***************************************************************************
772  * Reading and writing
773  ***************************************************************************/
774
775 static gboolean
776 registry_read (HKEY           hpath,
777                const gchar   *path_name,
778                const gchar   *value_name,
779                RegistryValue *p_value)
780 {
781   LONG result;
782   DWORD value_data_size;
783   gpointer *buffer;
784   gunichar2 *value_namew;
785
786   g_return_val_if_fail (p_value != NULL, FALSE);
787
788   p_value->type = REG_NONE;
789   p_value->ptr = NULL;
790
791   value_namew = g_utf8_to_utf16 (value_name, -1, NULL, NULL, NULL);
792
793   result = RegQueryValueExW (hpath, value_namew, 0, &p_value->type, NULL, &value_data_size);
794   if (result != ERROR_SUCCESS)
795     {
796       handle_read_error (result, path_name, value_name);
797       g_free (value_namew);
798       return FALSE;
799     }
800
801   if (p_value->type == REG_SZ && value_data_size == 0)
802     {
803       p_value->ptr = g_strdup ("");
804       g_free (value_namew);
805       return TRUE;
806     }
807
808   if (p_value->type == REG_DWORD)
809     /* REG_DWORD is inlined */
810     buffer = (void *)&p_value->dword;
811   else
812     buffer = p_value->ptr = g_malloc (value_data_size);
813
814   result = RegQueryValueExW (hpath, value_namew, 0, NULL, (LPBYTE)buffer, &value_data_size);
815   g_free (value_namew);
816
817   if (result != ERROR_SUCCESS)
818     {
819       handle_read_error (result, path_name, value_name);
820
821       if (p_value->type != REG_DWORD)
822         g_free (buffer);
823
824       return FALSE;
825     }
826
827   if (p_value->type == REG_SZ)
828     {
829       gchar *valueu8 = g_utf16_to_utf8 (p_value->ptr, -1, NULL, NULL, NULL);
830       g_free (p_value->ptr);
831       p_value->ptr = valueu8;
832     }
833
834   return TRUE;
835 }
836
837 static GVariant *
838 g_registry_backend_read (GSettingsBackend   *backend,
839                          const gchar        *key_name,
840                          const GVariantType *expected_type,
841                          gboolean            default_value)
842 {
843   GRegistryBackend *self = G_REGISTRY_BACKEND (backend);
844   GNode *cache_node;
845   RegistryValue registry_value;
846   GVariant *gsettings_value = NULL;
847   gchar *gsettings_type;
848
849   g_return_val_if_fail (expected_type != NULL, NULL);
850
851   if (default_value)
852     return NULL;
853
854   /* Simply read from the cache, which is updated from the registry by the
855    * watch thread as soon as changes can propagate. Any changes not yet in the
856    * cache will have the 'changed' signal emitted after this function returns.
857    */
858   EnterCriticalSection (self->cache_lock);
859   cache_node = registry_cache_get_node_for_key (self->cache_root, key_name, FALSE);
860   LeaveCriticalSection (self->cache_lock);
861
862   trace ("Reading key %s, cache node %x\n", key_name, cache_node);
863
864   /* Maybe it's not set, we can return to default */
865   if (cache_node == NULL)
866     return NULL;
867
868   trace ("\t- cached value %s\n", registry_value_dump (((RegistryCacheItem *)cache_node->data)->value));
869
870   registry_value = ((RegistryCacheItem *)cache_node->data)->value;
871
872   gsettings_type = g_variant_type_dup_string (expected_type);
873
874   /* The registry is user-editable, so we need to be fault-tolerant here. */
875   switch (gsettings_type[0])
876     {
877     case 'b':
878     case 'y':
879     case 'n':
880     case 'q':
881     case 'i':
882     case 'u':
883       if (registry_value.type == REG_DWORD)
884         gsettings_value = g_variant_new (gsettings_type, registry_value.dword);
885       break;
886
887     case 't':
888     case 'x':
889       if (registry_value.type == REG_QWORD)
890         {
891           DWORDLONG qword_value = *(DWORDLONG *)registry_value.ptr;
892           gsettings_value = g_variant_new (gsettings_type, qword_value);
893         }
894       break;
895
896     default:
897       if (registry_value.type == REG_SZ)
898         {
899           if (gsettings_type[0] == 's')
900             gsettings_value = g_variant_new_string ((char *)registry_value.ptr);
901           else
902             {
903               GError *error = NULL;
904
905               gsettings_value = g_variant_parse (expected_type, registry_value.ptr,
906                                                  NULL, NULL, &error);
907
908               if (error != NULL)
909                 g_message ("gregistrysettingsbackend: error parsing key %s: %s",
910                            key_name, error->message);
911             }
912         }
913         break;
914     }
915
916   g_free (gsettings_type);
917
918   return gsettings_value;
919 }
920
921
922 typedef struct
923 {
924   GRegistryBackend *self;
925   HKEY hroot;
926 } RegistryWrite;
927
928 static gboolean
929 g_registry_backend_write_one (const char *key_name,
930                               GVariant   *variant,
931                               gpointer    user_data)
932 {
933   GRegistryBackend *self;
934   RegistryWrite *action;
935   RegistryValue value;
936   HKEY hroot;
937   HKEY hpath;
938   gchar *path_name;
939   gunichar2 *path_namew;
940   gchar *value_name = NULL;
941   gunichar2 *value_namew;
942   DWORD value_data_size;
943   LPVOID value_data;
944   gunichar2 *value_dataw;
945   LONG result;
946   GNode *node;
947   gboolean changed;
948   const gchar *type_string;
949
950   type_string = g_variant_get_type_string (variant);
951   action = user_data;
952   self = G_REGISTRY_BACKEND (action->self);
953   hroot = action->hroot;
954
955   value.type = REG_NONE;
956   value.ptr = NULL;
957
958   switch (type_string[0])
959     {
960     case 'b':
961     case 'y':
962     case 'n':
963     case 'q':
964     case 'i':
965     case 'u':
966       value.type = REG_DWORD;
967       value.dword = g_variant_get_as_dword (variant);
968       value_data_size = 4;
969       value_data = &value.dword;
970       break;
971
972     case 'x':
973     case 't':
974       value.type = REG_QWORD;
975       value.ptr = g_malloc (8);
976       *(DWORDLONG *)value.ptr = g_variant_get_as_qword (variant);
977       value_data_size = 8;
978       value_data = value.ptr;
979       break;
980
981     default:
982       value.type = REG_SZ;
983       if (type_string[0] == 's')
984         {
985           gsize length;
986           value.ptr = g_strdup (g_variant_get_string (variant, &length));
987           value_data_size = length + 1;
988           value_data = value.ptr;
989         }
990       else
991         {
992           GString *value_string;
993           value_string = g_variant_print_string (variant, NULL, FALSE);
994           value_data_size = value_string->len + 1;
995           value.ptr = value_data = g_string_free (value_string, FALSE);
996         }
997       break;
998     }
999
1000   /* First update the cache, because the value may not have changed and we can
1001    * save a write.
1002    * 
1003    * If 'value' has changed then its memory will not be freed by update_node(),
1004    * because it will be stored in the node.
1005    */
1006   EnterCriticalSection (self->cache_lock);
1007   node = registry_cache_get_node_for_key (self->cache_root, key_name, TRUE);
1008   changed = registry_cache_update_node (node, value);
1009   LeaveCriticalSection (self->cache_lock);
1010
1011   if (!changed)
1012     return FALSE;
1013
1014   /* Block the next notification to any watch points above this location,
1015    * because they will each get triggered on a change that is already updated
1016    * in the cache.
1017    */
1018   registry_cache_block_notification (node);
1019
1020   path_name = parse_key (key_name, NULL, &value_name);
1021
1022   trace ("Set key: %s / %s\n", path_name, value_name);
1023
1024   path_namew = g_utf8_to_utf16 (path_name, -1, NULL, NULL, NULL);
1025
1026   /* Store the value in the registry */
1027   result = RegCreateKeyExW (hroot, path_namew, 0, NULL, 0, KEY_WRITE, NULL, &hpath, NULL);
1028   if (result != ERROR_SUCCESS)
1029     {
1030       g_message_win32_error (result, "gregistrybackend: opening key %s failed",
1031                              path_name + 1);
1032       registry_value_free (value);
1033       g_free (path_namew);
1034       g_free (path_name);
1035       return FALSE;
1036     }
1037
1038   g_free (path_namew);
1039
1040   value_namew = g_utf8_to_utf16 (value_name, -1, NULL, NULL, NULL);
1041
1042   value_dataw = NULL;
1043
1044   switch (type_string[0])
1045     {
1046     case 'b':
1047     case 'y':
1048     case 'n':
1049     case 'q':
1050     case 'i':
1051     case 'u':
1052     case 'x':
1053     case 't':
1054       break;
1055     default:
1056       value_dataw = g_utf8_to_utf16 (value_data, -1, NULL, NULL, NULL);
1057       value_data = value_dataw;
1058       value_data_size = (DWORD)((wcslen (value_data) + 1) * sizeof (gunichar2));
1059       break;
1060     }
1061
1062   result = RegSetValueExW (hpath, value_namew, 0, value.type, value_data, value_data_size);
1063
1064   if (result != ERROR_SUCCESS)
1065     g_message_win32_error (result, "gregistrybackend: setting value %s\\%s\\%s failed.\n",
1066                            self->base_path, path_name, value_name);
1067
1068   /* If the write fails then it will seem like the value has changed until the
1069    * next execution (because we wrote to the cache first). There's no reason
1070    * for it to fail unless something is weirdly broken, however.
1071    */
1072
1073   RegCloseKey (hpath);
1074   g_free (path_name);
1075   g_free (value_namew);
1076   g_free (value_dataw);
1077
1078   return FALSE;
1079 }
1080
1081 /* The dconf write policy is to do the write while making out it succeeded, 
1082  * and then backtrack if it didn't. The registry functions are synchronous so
1083  * we can't do that. */
1084
1085 static gboolean
1086 g_registry_backend_write (GSettingsBackend *backend,
1087                           const gchar      *key_name,
1088                           GVariant         *value,
1089                           gpointer          origin_tag)
1090 {
1091   GRegistryBackend *self = G_REGISTRY_BACKEND (backend);
1092   LONG result;
1093   HKEY hroot;
1094   RegistryWrite action;
1095
1096   result = RegCreateKeyExW (HKEY_CURRENT_USER, self->base_pathw, 0, NULL, 0,
1097                             KEY_WRITE, NULL, &hroot, NULL);
1098   if (result != ERROR_SUCCESS)
1099     {
1100       trace ("Error opening/creating key %s.\n", self->base_path);
1101       return FALSE;
1102     }
1103
1104   action.self = self;
1105   action.hroot = hroot;
1106   g_registry_backend_write_one (key_name, value, &action);
1107   g_settings_backend_changed (backend, key_name, origin_tag);
1108
1109   RegCloseKey (hroot);
1110
1111   return TRUE;
1112 }
1113
1114 static gboolean
1115 g_registry_backend_write_tree (GSettingsBackend *backend,
1116                                GTree            *values,
1117                                gpointer          origin_tag)
1118 {
1119   GRegistryBackend *self = G_REGISTRY_BACKEND (backend);
1120   LONG result;
1121   HKEY hroot;
1122   RegistryWrite action;
1123
1124   result = RegCreateKeyExW (HKEY_CURRENT_USER, self->base_pathw, 0, NULL, 0,
1125                             KEY_WRITE, NULL, &hroot, NULL);
1126   if (result != ERROR_SUCCESS)
1127     {
1128       trace ("Error opening/creating key %s.\n", self->base_path);
1129       return FALSE;
1130     }
1131
1132   action.self =  self;
1133   action.hroot = hroot;
1134   g_tree_foreach (values, (GTraverseFunc)g_registry_backend_write_one,
1135                   &action);
1136
1137   g_settings_backend_changed_tree (backend, values, origin_tag);
1138   RegCloseKey (hroot);
1139
1140   return TRUE;
1141 }
1142
1143 static void
1144 g_registry_backend_reset (GSettingsBackend *backend,
1145                           const gchar      *key_name,
1146                           gpointer          origin_tag)
1147 {
1148   GRegistryBackend *self = G_REGISTRY_BACKEND (backend);
1149   gchar *path_name;
1150   gunichar2 *path_namew;
1151   gchar *value_name = NULL;
1152   gunichar2 *value_namew;
1153   GNode *cache_node;
1154   LONG result;
1155   HKEY hpath;
1156
1157   /* Remove from cache */
1158   EnterCriticalSection (self->cache_lock);
1159   cache_node = registry_cache_get_node_for_key (self->cache_root, key_name, FALSE);
1160   if (cache_node)
1161     registry_cache_destroy_tree (cache_node, self->watch);
1162   LeaveCriticalSection (self->cache_lock);
1163
1164   /* Remove from the registry */
1165   path_name = parse_key (key_name, self->base_path, &value_name);
1166   path_namew = g_utf8_to_utf16 (path_name, -1, NULL, NULL, NULL);
1167
1168   result = RegOpenKeyExW (HKEY_CURRENT_USER, path_namew, 0, KEY_SET_VALUE, &hpath);
1169   g_free (path_namew);
1170
1171   if (result != ERROR_SUCCESS)
1172     {
1173       g_message_win32_error (result, "Registry: resetting key '%s'", path_name);
1174       g_free (path_name);
1175       return;
1176     }
1177
1178   value_namew = g_utf8_to_utf16 (value_name, -1, NULL, NULL, NULL);
1179
1180   result = RegDeleteValueW (hpath, value_namew);
1181   g_free (value_namew);
1182   RegCloseKey (hpath);
1183
1184   if (result != ERROR_SUCCESS)
1185     {
1186       g_message_win32_error (result, "Registry: resetting key '%s'", path_name);
1187       g_free (path_name);
1188       return;
1189     }
1190
1191   g_free (path_name);
1192
1193   g_settings_backend_changed (backend, key_name, origin_tag);
1194 }
1195
1196 static gboolean
1197 g_registry_backend_get_writable (GSettingsBackend *backend,
1198                                  const gchar      *key_name)
1199 {
1200   GRegistryBackend *self = G_REGISTRY_BACKEND (backend);
1201   gchar *path_name;
1202   gunichar2 *path_namew;
1203   gchar *value_name;
1204   HKEY hpath;
1205   LONG result;
1206
1207   path_name = parse_key (key_name, self->base_path, &value_name);
1208   path_namew = g_utf8_to_utf16 (path_name, -1, NULL, NULL, NULL);
1209
1210   /* Note: we create the key if it wasn't created yet, but it is not much
1211    * of a problem since at the end of the day we have to create it anyway
1212    * to read or to write from it
1213    */
1214   result = RegCreateKeyExW (HKEY_CURRENT_USER, path_namew, 0, NULL, 0,
1215                             KEY_WRITE, NULL, &hpath, NULL);
1216   g_free (path_namew);
1217
1218   if (result != ERROR_SUCCESS)
1219     {
1220       trace ("Error opening/creating key to check writability: %s.\n",
1221              path_name);
1222       g_free (path_name);
1223
1224       return FALSE;
1225     }
1226
1227   g_free (path_name);
1228   RegCloseKey (hpath);
1229
1230   return TRUE;
1231 }
1232
1233 /********************************************************************************
1234  * Spot-the-difference engine
1235  ********************************************************************************/
1236
1237 static void
1238 _free_watch (WatchThreadState *self,
1239              guint             index,
1240              GNode            *cache_node);
1241
1242 static void
1243 registry_cache_item_reset_readable (GNode    *node,
1244                                     gpointer  data)
1245 {
1246   RegistryCacheItem *item = node->data;
1247   item->readable = FALSE;
1248 }
1249
1250 /* Delete a node and any children, for when it has been deleted from the registry */
1251 static void
1252 registry_cache_destroy_tree (GNode            *node,
1253                              WatchThreadState *self)
1254 {
1255   RegistryCacheItem *item = node->data;
1256
1257   g_node_children_foreach (node, G_TRAVERSE_ALL,
1258                            (GNodeForeachFunc)registry_cache_destroy_tree, self);
1259
1260   if (item->subscription_count > 0)
1261     {
1262       guint i;
1263
1264       /* There must be some watches active if this node is a watch point */
1265       g_warn_if_fail (self->cache_nodes->len > 1);
1266
1267       /* This is a watch point that has been deleted. Let's free the watch! */
1268       for (i = 1; i < self->cache_nodes->len; i++)
1269         {
1270           if (g_ptr_array_index (self->cache_nodes, i) == node)
1271             break;
1272         }
1273
1274       if (i >= self->cache_nodes->len)
1275         g_warning ("watch thread: a watch point was deleted, but unable to "
1276                    "find '%s' in the list of %i watch nodes\n", item->name,
1277                    self->cache_nodes->len - 1);
1278       else
1279         {
1280           _free_watch (self, i, node);
1281           g_atomic_int_inc (&self->watches_remaining);
1282         }
1283     }
1284   registry_cache_item_free (node->data);
1285   g_node_destroy (node);
1286 }
1287
1288 /* One of these is sent down the pipe when something happens in the registry. */
1289 typedef struct
1290 {
1291   GRegistryBackend *self;
1292   gchar *prefix;          /* prefix is a gsettings path, all items are subkeys of this. */
1293   GPtrArray *items;       /* each item is a subkey below prefix that has changed. */
1294 } RegistryEvent;
1295
1296 typedef struct
1297 {
1298   RegistryEvent *event;
1299   gchar *current_key_name;
1300 } DeletedItemData;
1301
1302 static void
1303 mark_all_subkeys_as_changed (GNode    *node,
1304                              gpointer  data)
1305 {
1306   RegistryCacheItem *item = node->data;
1307   DeletedItemData *item_data = data;
1308
1309   if (item_data->current_key_name == NULL)
1310     item_data->current_key_name = g_strdup (item->name);
1311   else
1312     {
1313       gchar *name;
1314
1315       name = g_build_path ("/", item_data->current_key_name, item->name, NULL);
1316       g_free (item_data->current_key_name);
1317       item_data->current_key_name = name;
1318     }
1319
1320   /* Iterate until we find an item that is a value */
1321   if (item->value.type == REG_NONE)
1322     g_node_children_foreach (node, G_TRAVERSE_ALL,
1323                              mark_all_subkeys_as_changed, data);
1324   else
1325     g_ptr_array_add (item_data->event->items, item_data->current_key_name);
1326 }
1327
1328 static void
1329 registry_cache_remove_deleted (GNode    *node,
1330                                gpointer  data)
1331 {
1332   RegistryCacheItem *item = node->data;
1333   RegistryEvent *event = data;
1334
1335   if (!item->readable)
1336     {
1337       DeletedItemData item_data;
1338
1339       item_data.event = event;
1340       item_data.current_key_name = NULL;
1341
1342       mark_all_subkeys_as_changed (node, &item_data);
1343       registry_cache_destroy_tree (node, event->self->watch);
1344     }
1345 }
1346
1347 /* Update cache from registry, and optionally report on the changes.
1348  * 
1349  * This function is sometimes called from the watch thread, with no locking. It
1350  * does call g_registry_backend functions, but this is okay because they only
1351  * access self->base which is constant.
1352  *
1353  * When looking at this code bear in mind the terminology: in the registry, keys
1354  * are containers that contain values, and other keys. Keys have a 'default'
1355  * value which we always ignore.
1356  *
1357  * n_parent_watches: a counter used to set the reference count of any new nodes
1358  *                   that are created - they should have as many references as
1359  *                   there are notifications that are watching them.
1360  */
1361 static void
1362 registry_cache_update (GRegistryBackend *self,
1363                        HKEY              hpath,
1364                        const gchar      *prefix,
1365                        const gchar      *partial_key_name,
1366                        GNode            *cache_node,
1367                        int               n_watches,
1368                        RegistryEvent    *event)
1369 {
1370   gunichar2 bufferw[MAX_KEY_NAME_LENGTH + 1];
1371   gchar *buffer;
1372   gchar *key_name;
1373   gint i;
1374   LONG result;
1375   RegistryCacheItem *item;
1376
1377   item = cache_node->data;
1378
1379   if (item->subscription_count > 0)
1380     n_watches++;
1381
1382   /* prefix is the level that all changes occur below; partial_key_name should
1383    * be NULL on the first call to this function */
1384   key_name = g_build_path ("/", prefix, partial_key_name, NULL);
1385
1386   trace ("registry cache update: %s. Node %x has %i children\n", key_name,
1387          cache_node, g_node_n_children (cache_node));
1388
1389   /* Start by zeroing 'readable' flag. When the registry traversal is done, any unreadable nodes
1390    * must have been deleted from the registry.
1391    */
1392   g_node_children_foreach (cache_node, G_TRAVERSE_ALL,
1393                            registry_cache_item_reset_readable, NULL);
1394
1395   /* Recurse into each subpath at the current level, if any */
1396   i = 0;
1397   while (1)
1398     {
1399       DWORD bufferw_size = MAX_KEY_NAME_LENGTH + 1;
1400       HKEY  hsubpath;
1401
1402       result = RegEnumKeyExW (hpath, i++, bufferw, &bufferw_size, NULL, NULL, NULL, NULL);
1403       if (result != ERROR_SUCCESS)
1404         break;
1405
1406       result = RegOpenKeyExW (hpath, bufferw, 0, KEY_READ, &hsubpath);
1407       if (result == ERROR_SUCCESS)
1408         {
1409           GNode *subkey_node;
1410           RegistryCacheItem *child_item;
1411           gchar *new_partial_key_name;
1412
1413           buffer = g_utf16_to_utf8 (bufferw, -1, NULL, NULL, NULL);
1414           if (buffer == NULL)
1415             continue;
1416
1417           subkey_node = registry_cache_find_immediate_child (cache_node, buffer);
1418           if (subkey_node == NULL)
1419             {
1420               RegistryValue null_value = {REG_NONE, {0}};
1421               subkey_node = registry_cache_add_item (cache_node, buffer,
1422                                                      null_value, n_watches);
1423             }
1424
1425           new_partial_key_name = g_build_path ("/", partial_key_name, buffer, NULL);
1426           registry_cache_update (self, hsubpath, prefix, new_partial_key_name,
1427                                  subkey_node, n_watches, event);
1428           g_free (new_partial_key_name);
1429
1430           child_item = subkey_node->data;
1431           child_item->readable = TRUE;
1432
1433           g_free (buffer);
1434           RegCloseKey (hsubpath);
1435         }
1436     }
1437
1438   if (result != ERROR_NO_MORE_ITEMS)
1439     g_message_win32_error (result, "gregistrybackend: error enumerating subkeys for cache.");
1440
1441   /* Enumerate each value at 'path' and check if it has changed */
1442   i = 0;
1443   while (1)
1444     {
1445       DWORD bufferw_size = MAX_KEY_NAME_LENGTH + 1;
1446       GNode *cache_child_node;
1447       RegistryCacheItem *child_item;
1448       RegistryValue value;
1449       gboolean changed = FALSE;
1450
1451       result = RegEnumValueW (hpath, i++, bufferw, &bufferw_size, NULL, NULL, NULL, NULL);
1452       if (result != ERROR_SUCCESS)
1453         break;
1454
1455       buffer = g_utf16_to_utf8 (bufferw, -1, NULL, NULL, NULL);
1456
1457       if (buffer == NULL || buffer[0] == 0)
1458         {
1459           /* This is the key's 'default' value, for which we have no use. */
1460           g_free (buffer);
1461           continue;
1462         }
1463
1464       cache_child_node = registry_cache_find_immediate_child (cache_node, buffer);
1465
1466       if (!registry_read (hpath, key_name, buffer, &value))
1467         {
1468           g_free (buffer);
1469           continue;
1470         }
1471
1472       trace ("\tgot value %s for %s, node %x\n",
1473              registry_value_dump (value), buffer, cache_child_node);
1474
1475       if (cache_child_node == NULL)
1476         {
1477           /* This is a new value */
1478           cache_child_node = registry_cache_add_item (cache_node, buffer, value,
1479                                                       n_watches);
1480           changed = TRUE;
1481         }
1482       else
1483         {
1484          /* For efficiency, instead of converting every value back to a GVariant to
1485           * compare it, we compare them as registry values (integers, or string
1486           * representations of the variant). The spurious change notifications that may
1487           * result should not be a big issue.
1488           *
1489           * Note that 'value' is swallowed or freed.
1490           */
1491           changed = registry_cache_update_node (cache_child_node, value);
1492         }
1493
1494       child_item = cache_child_node->data;
1495       child_item->readable = TRUE;
1496       if (changed && event != NULL)
1497         {
1498           gchar *item;
1499
1500           if (partial_key_name == NULL)
1501             item = g_strdup (buffer);
1502           else
1503             item = g_build_path ("/", partial_key_name, buffer, NULL);
1504
1505           g_ptr_array_add (event->items, item);
1506         }
1507
1508       g_free (buffer);
1509     }
1510
1511   if (result != ERROR_NO_MORE_ITEMS)
1512     g_message_win32_error (result, "gregistrybackend: error enumerating values for cache");
1513
1514   /* Any nodes now left unreadable must have been deleted, remove them from cache */
1515   g_node_children_foreach (cache_node, G_TRAVERSE_ALL,
1516                            registry_cache_remove_deleted, event);
1517
1518   trace ("registry cache update complete.\n");
1519
1520   g_free (key_name);
1521 }
1522
1523 /***********************************************************************************
1524  * Thread to watch for registry change events
1525  ***********************************************************************************/
1526
1527 /* Called by watch thread. Apply for notifications on a registry key and its subkeys. */
1528 static DWORD
1529 registry_watch_key (HKEY   hpath,
1530                     HANDLE event)
1531 {
1532   return RegNotifyChangeKeyValue (hpath, TRUE,
1533                                   REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET,
1534                                   event, TRUE);
1535 }
1536
1537 /* This handler runs in the main thread to emit the changed signals */
1538 static gboolean
1539 watch_handler (RegistryEvent *event)
1540 {
1541   trace ("Watch handler: got event in %s, items %i.\n", event->prefix, event->items->len);
1542
1543   /* GSettings requires us to NULL-terminate the array. */
1544   g_ptr_array_add (event->items, NULL);
1545   g_settings_backend_keys_changed (G_SETTINGS_BACKEND (event->self), event->prefix,
1546                                    (gchar const **)event->items->pdata, NULL);
1547
1548   g_ptr_array_free (event->items, TRUE);
1549   g_free (event->prefix);
1550   g_object_unref (event->self);
1551   g_slice_free (RegistryEvent, event);
1552
1553   return G_SOURCE_REMOVE;
1554 }
1555
1556 static void
1557 _free_watch (WatchThreadState *self,
1558              guint             index,
1559              GNode            *cache_node)
1560 {
1561   HKEY hpath;
1562   HANDLE cond;
1563   gchar *prefix;
1564
1565   g_return_if_fail (index > 0 && index < self->events->len);
1566
1567   cond = g_ptr_array_index (self->events, index);
1568   hpath = g_ptr_array_index (self->handles, index);
1569   prefix = g_ptr_array_index (self->prefixes, index);
1570
1571   trace ("Freeing watch %i [%s]\n", index, prefix);
1572  
1573   /* These can be NULL if the watch was already dead, this can happen when eg.
1574    * a key is deleted but GSettings is still subscribed to it - the watch is
1575    * kept alive so that the unsubscribe function works properly, but does not
1576    * do anything.
1577    */
1578   if (hpath != NULL)
1579     RegCloseKey (hpath);
1580
1581   if (cache_node != NULL)
1582     {
1583       //registry_cache_dump (G_REGISTRY_BACKEND (self->owner)->cache_root, NULL);
1584       registry_cache_unref_tree (cache_node);
1585     }
1586
1587   CloseHandle (cond);
1588   g_free (prefix);
1589
1590   /* As long as we remove from each array at the same time, it doesn't matter that
1591    * their orders get messed up - they all get messed up the same.
1592    */
1593   g_ptr_array_remove_index_fast (self->handles, index);
1594   g_ptr_array_remove_index_fast (self->events, index);
1595   g_ptr_array_remove_index_fast (self->prefixes, index);
1596   g_ptr_array_remove_index_fast (self->cache_nodes, index);
1597 }
1598
1599 static void
1600 watch_thread_handle_message (WatchThreadState *self)
1601 {
1602   switch (self->message.type)
1603     {
1604     case WATCH_THREAD_NONE:
1605       trace ("watch thread: you woke me up for nothin', man!");
1606       break;
1607
1608     case WATCH_THREAD_ADD_WATCH:
1609       {
1610         RegistryWatch *watch = &self->message.watch;
1611         LONG result;
1612
1613         result = registry_watch_key (watch->hpath, watch->event);
1614
1615         if (result == ERROR_SUCCESS)
1616           {
1617             g_ptr_array_add (self->events, watch->event);
1618             g_ptr_array_add (self->handles, watch->hpath);
1619             g_ptr_array_add (self->prefixes, watch->prefix);
1620             g_ptr_array_add (self->cache_nodes, watch->cache_node);
1621
1622             trace ("watch thread: new watch on %s, %i total\n", watch->prefix,
1623                    self->events->len);
1624           }
1625         else
1626           {
1627             g_message_win32_error (result, "watch thread: could not watch %s", watch->prefix);
1628
1629             CloseHandle (watch->event);
1630             RegCloseKey (watch->hpath);
1631             g_free (watch->prefix);
1632             registry_cache_unref_tree (watch->cache_node);
1633           }
1634         break;
1635       }
1636
1637     case WATCH_THREAD_REMOVE_WATCH:
1638       {
1639         GNode *cache_node;
1640         RegistryCacheItem *cache_item;
1641         guint i;
1642
1643         for (i = 1; i < self->prefixes->len; i++)
1644           {
1645             if (strcmp (g_ptr_array_index (self->prefixes, i),
1646                         self->message.watch.prefix) == 0)
1647               break;
1648           }
1649
1650         if (i >= self->prefixes->len)
1651           {
1652             /* Don't make a fuss if the prefix is not being watched because
1653              * maybe the path was deleted so we removed the watch.
1654              */
1655             trace ("unsubscribe: prefix %s is not being watched [%i things are]!\n",
1656                    self->message.watch.prefix, self->prefixes->len);
1657             g_free (self->message.watch.prefix);
1658             break;
1659           }
1660
1661         cache_node = g_ptr_array_index (self->cache_nodes, i);
1662
1663         trace ("watch thread: unsubscribe: freeing node %p, prefix %s, index %i\n",
1664                cache_node, self->message.watch.prefix, i);
1665
1666         if (cache_node != NULL)
1667           {
1668             cache_item = cache_node->data;
1669
1670             /* There may be more than one GSettings object subscribed to this
1671              * path, only free the watch when the last one unsubscribes.
1672              */
1673             cache_item->subscription_count--;
1674             if (cache_item->subscription_count > 0)
1675               break;
1676           }
1677
1678         _free_watch (self, i, cache_node);
1679         g_free (self->message.watch.prefix);
1680
1681         g_atomic_int_inc (&self->watches_remaining);
1682         break;
1683       }
1684
1685     case WATCH_THREAD_STOP:
1686       {
1687         guint i;
1688
1689         /* Free any remaining cache and watch handles */
1690         for (i = 1; i < self->events->len; i++)
1691           _free_watch (self, i, g_ptr_array_index (self->cache_nodes, i));
1692
1693         SetEvent (self->message_received_event);
1694         ExitThread (0);
1695       }
1696     }
1697
1698   self->message.type = WATCH_THREAD_NONE;
1699   SetEvent (self->message_received_event);
1700 }
1701
1702 /* Thread which watches for win32 registry events */
1703 static DWORD WINAPI
1704 watch_thread_function (LPVOID parameter)
1705 {
1706   WatchThreadState *self = (WatchThreadState *)parameter;
1707   DWORD result;
1708
1709   self->events = g_ptr_array_new ();
1710   self->handles = g_ptr_array_new ();
1711   self->prefixes = g_ptr_array_new ();
1712   self->cache_nodes = g_ptr_array_new ();
1713   g_ptr_array_add (self->events, self->message_sent_event);
1714   g_ptr_array_add (self->handles, NULL);
1715   g_ptr_array_add (self->prefixes, NULL);
1716   g_ptr_array_add (self->cache_nodes, NULL);
1717
1718   while (1)
1719     {
1720       trace ("watch thread: going to sleep; %i events watched.\n", self->events->len);
1721       result = WaitForMultipleObjects (self->events->len, self->events->pdata, FALSE, INFINITE);
1722
1723       if (result == WAIT_OBJECT_0)
1724         {
1725           /* A message to you. The sender (main thread) will block until we signal the received
1726            * event, so there should be no danger of it sending another before we receive the
1727            * first.
1728            */
1729           watch_thread_handle_message (self);
1730         }
1731       else if (result > WAIT_OBJECT_0 && result <= WAIT_OBJECT_0 + self->events->len)
1732         {
1733           HKEY hpath;
1734           HANDLE cond;
1735           gchar *prefix;
1736           GNode *cache_node;
1737           RegistryCacheItem *cache_item;
1738           RegistryEvent *event;
1739           gint notify_index;
1740
1741           /* One of our notifications has triggered. All we know is which one, and which key
1742            * this is for. We do most of the processing here, because we may as well. If the
1743            * registry changes further while we are processing it doesn't matter - we will then
1744            * receive another change notification from the OS anyway.
1745            */
1746           notify_index = result - WAIT_OBJECT_0;
1747           hpath = g_ptr_array_index (self->handles, notify_index);
1748           cond = g_ptr_array_index (self->events, notify_index);
1749           prefix = g_ptr_array_index (self->prefixes, notify_index);
1750           cache_node = g_ptr_array_index (self->cache_nodes, notify_index);
1751
1752           trace ("Watch thread: notify received on prefix %i: %s.\n", notify_index, prefix);
1753
1754           if (cache_node == NULL)
1755             {
1756               /* This path has been deleted */
1757               trace ("Notify received on a path that was deleted\n");
1758               continue;
1759             }
1760
1761           /* Firstly we need to reapply for the notification, because (what a
1762            * sensible API) we won't receive any more. MSDN is pretty
1763            * inconsistent on this matter:
1764            *   http://msdn.microsoft.com/en-us/library/ms724892%28VS.85%29.aspx
1765            *   http://support.microsoft.com/kb/236570
1766            * But my tests (on Windows XP SP3) show that we need to reapply
1767            * each time.
1768            */
1769           result = registry_watch_key (hpath, cond);
1770
1771           if (result != ERROR_SUCCESS)
1772             {
1773               /* Watch failed, most likely because the key has just been
1774                * deleted. Free the watch and unref the cache nodes.
1775                */
1776              if (result != ERROR_KEY_DELETED)
1777                g_message_win32_error (result, "watch thread: failed to watch %s", prefix);
1778
1779              _free_watch (self, notify_index, cache_node);
1780              g_atomic_int_inc (&self->watches_remaining);
1781              continue;
1782             }
1783
1784           /* The notification may have been blocked because we just changed
1785            * some data ourselves.
1786            */
1787           cache_item = cache_node->data;
1788           if (cache_item->block_count)
1789             {
1790               cache_item->block_count--;
1791               trace ("Watch thread: notify blocked at %s\n", prefix);
1792               continue;
1793             }
1794
1795           /* Now we update our stored cache from registry data, and find which keys have
1796            * actually changed. If more changes happen while we are processing, we will get
1797            * another event because we have reapplied for change notifications already.
1798            *
1799            * Working here rather than in the main thread is preferable because the UI is less
1800            * likely to block (only when changing notification subscriptions).
1801            */
1802           event = g_slice_new (RegistryEvent);
1803           event->self = G_REGISTRY_BACKEND (g_object_ref (self->owner));
1804           event->prefix = g_strdup (prefix);
1805           event->items = g_ptr_array_new_with_free_func (g_free);
1806
1807           EnterCriticalSection (G_REGISTRY_BACKEND (self->owner)->cache_lock);
1808           registry_cache_update (G_REGISTRY_BACKEND (self->owner), hpath,
1809                                  prefix, NULL, cache_node, 0, event);
1810           LeaveCriticalSection (G_REGISTRY_BACKEND (self->owner)->cache_lock);
1811
1812           if (event->items->len > 0)
1813             g_idle_add ((GSourceFunc) watch_handler, event);
1814           else
1815             {
1816               g_object_unref (event->self);
1817               g_free (event->prefix);
1818               g_ptr_array_free (event->items, TRUE);
1819               g_slice_free (RegistryEvent, event);
1820             }
1821         }
1822       else
1823         {
1824           /* God knows what has happened */
1825           g_message_win32_error (GetLastError(), "watch thread: WaitForMultipleObjects error");
1826         }
1827     }
1828
1829   return -1;
1830 }
1831
1832 static gboolean
1833 watch_start (GRegistryBackend *self)
1834 {
1835   WatchThreadState *watch;
1836
1837   g_return_val_if_fail (self->watch == NULL, FALSE);
1838
1839   watch = g_slice_new (WatchThreadState);
1840   watch->owner = G_SETTINGS_BACKEND (self);
1841
1842   watch->watches_remaining = MAX_WATCHES;
1843
1844   watch->message_lock = g_slice_new (CRITICAL_SECTION);
1845   InitializeCriticalSection (watch->message_lock);
1846   watch->message_sent_event = CreateEvent (NULL, FALSE, FALSE, NULL);
1847   watch->message_received_event = CreateEvent (NULL, FALSE, FALSE, NULL);
1848   if (watch->message_sent_event == NULL || watch->message_received_event == NULL)
1849     {
1850       g_message_win32_error (GetLastError (), "gregistrybackend: Failed to create sync objects.");
1851       goto fail;
1852     }
1853
1854   /* Use a small stack to make the thread more lightweight. */
1855   watch->thread = CreateThread (NULL, 1024, watch_thread_function, watch, 0, NULL);
1856   if (watch->thread == NULL)
1857     {
1858       g_message_win32_error (GetLastError (), "gregistrybackend: Failed to create notify watch thread.");
1859       goto fail;
1860     }
1861
1862   self->watch = watch;
1863
1864   return TRUE;
1865
1866 fail:
1867   DeleteCriticalSection (watch->message_lock);
1868   g_slice_free (CRITICAL_SECTION, watch->message_lock);
1869   if (watch->message_sent_event != NULL)
1870     CloseHandle (watch->message_sent_event);
1871   if (watch->message_received_event != NULL)
1872     CloseHandle (watch->message_received_event);
1873   g_slice_free (WatchThreadState, watch);
1874
1875   return FALSE;
1876 }
1877
1878 /* This function assumes you hold the message lock! */
1879 static void
1880 watch_stop_unlocked (GRegistryBackend *self)
1881 {
1882   WatchThreadState *watch = self->watch;
1883   DWORD result;
1884
1885   g_return_if_fail (watch != NULL);
1886
1887   watch->message.type = WATCH_THREAD_STOP;
1888   SetEvent (watch->message_sent_event);
1889
1890   /* This is signalled as soon as the message is received. We must not return
1891    * while the watch thread is still firing off callbacks. Freeing all of the
1892    * memory is done in the watch thread after this is signalled.
1893    */
1894   result = WaitForSingleObject (watch->message_received_event, INFINITE);
1895   if (result != WAIT_OBJECT_0)
1896     {
1897       g_warning ("gregistrybackend: unable to stop watch thread.");
1898       return;
1899     }
1900
1901   LeaveCriticalSection (watch->message_lock);
1902   DeleteCriticalSection (watch->message_lock);
1903   g_slice_free (CRITICAL_SECTION, watch->message_lock);
1904   CloseHandle (watch->message_sent_event);
1905   CloseHandle (watch->message_received_event);
1906   CloseHandle (watch->thread);
1907   g_slice_free (WatchThreadState, watch);
1908
1909   trace ("\nwatch thread: %x: all data freed.\n", self);
1910   self->watch = NULL;
1911 }
1912
1913 static gboolean
1914 watch_add_notify (GRegistryBackend *self,
1915                   HANDLE            event,
1916                   HKEY              hpath,
1917                   gchar            *gsettings_prefix)
1918 {
1919   WatchThreadState *watch = self->watch;
1920   GNode *cache_node;
1921   RegistryCacheItem *cache_item;
1922 #ifdef TRACE
1923   DWORD result;
1924 #endif
1925
1926   g_return_val_if_fail (watch != NULL, FALSE);
1927
1928   trace ("watch_add_notify: prefix %s.\n", gsettings_prefix);
1929
1930   /* Duplicate tree into the cache in the main thread, before we add the notify: if we do it in the
1931    * thread we can miss changes while we are caching.
1932    */
1933   EnterCriticalSection (self->cache_lock);
1934   cache_node = registry_cache_get_node_for_key (self->cache_root, gsettings_prefix, TRUE);
1935
1936   if (cache_node == NULL || cache_node->data == NULL)
1937     {
1938       LeaveCriticalSection (self->cache_lock);
1939       g_warn_if_reached ();
1940       return FALSE;
1941     }
1942   
1943   cache_item = cache_node->data;
1944
1945   cache_item->subscription_count++;
1946   if (cache_item->subscription_count > 1)
1947     {
1948       trace ("watch_add_notify: prefix %s already watched, %i subscribers.\n",
1949              gsettings_prefix, cache_item->subscription_count);
1950       LeaveCriticalSection (self->cache_lock);
1951       return FALSE;
1952     }
1953
1954   registry_cache_ref_tree (cache_node);
1955   registry_cache_update (self, hpath, gsettings_prefix, NULL, cache_node, 0, NULL);
1956   //registry_cache_dump (self->cache_root, NULL);
1957   LeaveCriticalSection (self->cache_lock);
1958
1959   EnterCriticalSection (watch->message_lock);
1960   watch->message.type = WATCH_THREAD_ADD_WATCH;
1961   watch->message.watch.event = event;
1962   watch->message.watch.hpath = hpath;
1963   watch->message.watch.prefix = gsettings_prefix;
1964   watch->message.watch.cache_node = cache_node;
1965
1966   SetEvent (watch->message_sent_event);
1967
1968   /* Wait for the received event in return, to avoid sending another message before the first
1969    * one was received. If it takes > 200ms there is a possible race but the worst outcome is
1970    * a notification is ignored.
1971    */
1972 #ifdef TRACE
1973   result =
1974 #endif
1975     WaitForSingleObject (watch->message_received_event, 200);
1976 #ifdef TRACE
1977   if (result != WAIT_OBJECT_0)
1978     trace ("watch thread is slow to respond - notification may not be added.");
1979 #endif
1980
1981   LeaveCriticalSection (watch->message_lock);
1982
1983   return TRUE;
1984 }
1985
1986 static void
1987 watch_remove_notify (GRegistryBackend *self,
1988                      const gchar      *key_name)
1989 {
1990   WatchThreadState *watch = self->watch;
1991   LONG result;
1992
1993   if (self->watch == NULL)
1994     /* Here we assume that the unsubscribe message is for somewhere that was
1995      * deleted, and so it has already been removed and the watch thread has
1996      * stopped.
1997      */
1998     return;
1999
2000   EnterCriticalSection (watch->message_lock);
2001   watch->message.type = WATCH_THREAD_REMOVE_WATCH;
2002   watch->message.watch.prefix = g_strdup (key_name);
2003
2004   SetEvent (watch->message_sent_event);
2005
2006   /* Wait for the received event in return, to avoid sending another message before the first
2007    * one was received.
2008    */
2009   result = WaitForSingleObject (watch->message_received_event, INFINITE);
2010
2011   if (result != ERROR_SUCCESS)
2012     g_warning ("unsubscribe from %s: message not acknowledged", key_name);
2013
2014   if (g_atomic_int_get (&watch->watches_remaining) >= MAX_WATCHES)
2015     /* Stop it before any new ones can get added and confuse things */
2016     watch_stop_unlocked (self);
2017   else
2018     LeaveCriticalSection (watch->message_lock);
2019 }
2020
2021 /* dconf semantics are: if the key ends in /, watch the keys underneath it - if not, watch that
2022  * key. Our job is easier because keys and values are separate.
2023  */
2024 static void
2025 g_registry_backend_subscribe (GSettingsBackend *backend,
2026                               const char       *key_name)
2027 {
2028   GRegistryBackend *self = G_REGISTRY_BACKEND (backend);
2029   gchar *path_name;
2030   gunichar2 *path_namew;
2031   gchar *value_name = NULL;
2032   HKEY hpath;
2033   HANDLE event;
2034   LONG result;
2035
2036   if (self->watch == NULL && !watch_start (self))
2037     return;
2038
2039   if (g_atomic_int_dec_and_test (&self->watch->watches_remaining))
2040     {
2041       g_atomic_int_inc (&self->watch->watches_remaining);
2042       g_warning ("subscribe() failed: only %i different paths may be watched.", MAX_WATCHES);
2043       return;
2044     }
2045
2046   path_name = parse_key (key_name, self->base_path, &value_name);
2047
2048   /* Must check for this, otherwise strange crashes occur because the cache
2049    * node that is being watched gets freed. All path names to subscribe must
2050    * end in a slash!
2051    */
2052   if (value_name != NULL && *value_name != 0)
2053     g_warning ("subscribe() failed: path must end in a /, got %s", key_name);
2054
2055   trace ("Subscribing to %s [registry %s / %s] - watch %x\n", key_name, path_name, value_name, self->watch);
2056
2057   path_namew = g_utf8_to_utf16 (path_name, -1, NULL, NULL, NULL);
2058   g_free (path_name);
2059
2060   /* Give the caller the benefit of the doubt if the key doesn't exist and create it. The caller
2061    * is almost certainly a new g_settings with this path as base path. */
2062   result = RegCreateKeyExW (HKEY_CURRENT_USER, path_namew, 0, NULL, 0, KEY_READ, NULL, &hpath,
2063                             NULL);
2064   g_free (path_namew);
2065
2066   if (result != ERROR_SUCCESS)
2067     {
2068       g_message_win32_error (result, "gregistrybackend: Unable to subscribe to key %s.", key_name);
2069       g_atomic_int_inc (&self->watch->watches_remaining);
2070       return;
2071     }
2072
2073   event = CreateEvent (NULL, FALSE, FALSE, NULL);
2074   if (event == NULL)
2075     {
2076       g_message_win32_error (result, "gregistrybackend: CreateEvent failed.");
2077       g_atomic_int_inc (&self->watch->watches_remaining);
2078       RegCloseKey (hpath);
2079       return;
2080     }
2081
2082   /* The actual watch is added by the thread, which has to re-subscribe each time it
2083    * receives a change. */
2084   if (!watch_add_notify (self, event, hpath, g_strdup (key_name)))
2085     {
2086       g_atomic_int_inc (&self->watch->watches_remaining);
2087       RegCloseKey (hpath);
2088       CloseHandle (event);
2089     }
2090 }
2091
2092 static void
2093 g_registry_backend_unsubscribe (GSettingsBackend *backend,
2094                                 const char       *key_name)
2095 {
2096   trace ("unsubscribe: %s.\n", key_name);
2097
2098   watch_remove_notify (G_REGISTRY_BACKEND (backend), key_name);
2099 }
2100
2101 /********************************************************************************
2102  * Object management junk
2103  ********************************************************************************/
2104
2105 static void
2106 g_registry_backend_finalize (GObject *object)
2107 {
2108   GRegistryBackend *self = G_REGISTRY_BACKEND (object);
2109   RegistryCacheItem *item;
2110
2111   item = self->cache_root->data;
2112   g_warn_if_fail (item->ref_count == 1);
2113
2114   registry_cache_item_free (item);
2115   g_node_destroy (self->cache_root);
2116
2117   if (self->watch != NULL)
2118     {
2119       EnterCriticalSection (self->watch->message_lock);
2120       watch_stop_unlocked (self);
2121     }
2122
2123   DeleteCriticalSection (self->cache_lock);
2124   g_slice_free (CRITICAL_SECTION, self->cache_lock);
2125
2126   g_free (self->base_path);
2127   g_free (self->base_pathw);
2128 }
2129
2130 static void
2131 g_registry_backend_class_init (GRegistryBackendClass *class)
2132 {
2133   GSettingsBackendClass *backend_class = G_SETTINGS_BACKEND_CLASS (class);
2134   GObjectClass *object_class = G_OBJECT_CLASS (class);
2135
2136   object_class->finalize = g_registry_backend_finalize;
2137
2138   backend_class->read = g_registry_backend_read;
2139   backend_class->write = g_registry_backend_write;
2140   backend_class->write_tree = g_registry_backend_write_tree;
2141   backend_class->reset = g_registry_backend_reset;
2142   backend_class->get_writable = g_registry_backend_get_writable;
2143   backend_class->subscribe = g_registry_backend_subscribe;
2144   backend_class->unsubscribe = g_registry_backend_unsubscribe;
2145 }
2146
2147 static void
2148 g_registry_backend_init (GRegistryBackend *self)
2149 {
2150   RegistryCacheItem *item;
2151
2152   self->base_path = g_strdup_printf ("Software\\GSettings");
2153   self->base_pathw = g_utf8_to_utf16 (self->base_path, -1, NULL, NULL, NULL);
2154
2155   item = g_slice_new (RegistryCacheItem);
2156   item->value.type = REG_NONE;
2157   item->value.ptr = NULL;
2158   item->name = g_strdup ("<root>");
2159   item->ref_count = 1;
2160   self->cache_root = g_node_new (item);
2161
2162   self->cache_lock = g_slice_new (CRITICAL_SECTION);
2163   InitializeCriticalSection (self->cache_lock);
2164
2165   self->watch = NULL;
2166 }