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