gio: Fix C99 style variable declarations (bug #633075)
[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_int16 (variant);
284       case 'q': return g_variant_get_uint16 (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 'x': return g_variant_get_int64 (variant);
298       case 't': return g_variant_get_uint64 (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   GNode *child;
573
574   if (c != NULL)
575     *c = 0;
576
577   /* We count up how many watch points we travel through finding this node,
578    * because a new node should have as many references as there are watches at
579    * points above it in the tree.
580    */
581   item = node->data;
582   if (item->subscription_count > 0)
583     n_parent_watches ++;  
584
585   child = registry_cache_find_immediate_child (node, component);
586   if (child == NULL && create_if_not_found)
587     {
588       item = g_slice_new (RegistryCacheItem);
589       item->name = g_strdup (component);
590       item->value.type = REG_NONE;
591       item->value.ptr = NULL;
592       item->ref_count = n_parent_watches;
593       child = g_node_new (item);
594       g_node_append (node, child);
595       trace ("\tget node for key recursive: new %x = %s.\n", node, item->name);
596     }
597
598   /* We are done if there are no more path components. Allow for a trailing /. */
599   if (child==NULL || c == NULL || *(c+1)==0)
600     return child;
601   else
602     {
603       trace ("get node for key recursive: next: %s.\n", c+1);
604       return registry_cache_get_node_for_key_recursive
605                (child, c+1, create_if_not_found, n_parent_watches);
606     }
607 }
608
609 /* Look up a GSettings key in the cache. */
610 static GNode *
611 registry_cache_get_node_for_key (GNode       *root,
612                                  const gchar *key_name,
613                                  gboolean     create_if_not_found)
614 {
615   GNode *child = NULL,
616         *result = NULL;
617   gchar *component, *c;
618
619   g_return_val_if_fail (key_name != NULL, NULL);
620
621   if (key_name[0] == '/')
622     key_name ++;
623
624   /* Ignore preceeding / */
625   component = g_strdup (key_name);
626   c = strchr (component, '/');
627   if (c != NULL)
628     *c = 0;
629
630   child = registry_cache_find_immediate_child (root, component);
631   if (child == NULL && create_if_not_found)
632     {
633       /* Reference count is set to 0, tree should be referenced by the caller */
634       RegistryCacheItem *item = g_slice_new (RegistryCacheItem);
635       item->value.type = REG_NONE;
636       item->value.ptr = NULL;
637       item->name = g_strdup (component);
638       item->ref_count = 0;
639       trace ("get_node_for_key: New node for component '%s'\n", item->name);
640       child = g_node_new (item);
641       g_node_append (root, child);
642     }
643
644   if (c == NULL)
645     result = root;
646   else if (*(c+1)==0)
647     result = child;
648   else if (child != NULL)
649     result = registry_cache_get_node_for_key_recursive (child, c+1, create_if_not_found, 0);
650
651   g_free (component);
652
653   return result;
654 }
655
656 /* Check the cache node against the registry key it represents. Return TRUE if
657  * they differ, and update the cache with the new value.
658  */
659 static gboolean
660 registry_cache_update_node (GNode        *cache_node,
661                             RegistryValue registry_value)
662 {
663   RegistryCacheItem *cache_item = cache_node->data;
664
665   g_return_val_if_fail (cache_node != NULL, FALSE);
666   g_return_val_if_fail (cache_item != NULL, FALSE);
667
668   if (registry_value.type != cache_item->value.type)
669     {
670       /* The type has changed. Update cache item and register it as changed.
671        * Either the schema has changed and this is entirely legitimate, or
672        * whenever the app reads the key it will get the default value due to
673        * the type mismatch.
674        */
675       cache_item->value = registry_value;
676       return TRUE;
677     }
678  
679   switch (registry_value.type)
680     {
681       case REG_DWORD:
682         {
683           if (cache_item->value.dword == registry_value.dword)
684             return FALSE;
685           else
686             {
687               cache_item->value.dword = registry_value.dword;
688               return TRUE;
689             }
690         }
691       case REG_QWORD:
692         {
693           g_return_val_if_fail (registry_value.ptr != NULL &&
694                                 cache_item->value.ptr != NULL, FALSE);
695
696           if (memcmp (registry_value.ptr, cache_item->value.ptr, 8)==0)
697             {
698               g_free (registry_value.ptr);
699               return FALSE;
700             }
701           else
702             {
703               g_free (cache_item->value.ptr);
704               cache_item->value.ptr = registry_value.ptr;
705               return TRUE;
706             }
707         }
708       case REG_SZ:
709         {
710           /* Value should not exist if it is NULL, an empty string is "" */
711           g_return_val_if_fail (cache_item->value.ptr != NULL, FALSE);
712           g_return_val_if_fail (registry_value.ptr != NULL, FALSE);
713
714           if (strcmp (registry_value.ptr, cache_item->value.ptr) == 0)
715             {
716               g_free (registry_value.ptr);
717               return FALSE;
718             }
719           else
720             {
721               g_free (cache_item->value.ptr);
722               cache_item->value.ptr = registry_value.ptr;
723               return TRUE;
724             }
725         }
726       default:
727         g_warning ("gregistrybackend: registry_cache_update_node: Unhandled value type :(");
728         return FALSE;
729     }
730 }
731
732 /* Blocking notifications is a useful optimisation. When a change is made
733  * through GSettings we update the cache manually, but a notifcation is
734  * triggered as well. This function is also used for nested notifications,
735  * eg. if /test and /test/foo are watched, and /test/foo/value is changed then
736  * we will get notified both for /test/foo and /test and it is helpful to block
737  * the second.
738  */
739 static void
740 registry_cache_block_notification (GNode *node)
741 {
742   RegistryCacheItem *item = node->data;
743
744   g_return_if_fail (node != NULL);
745
746   if (item->subscription_count > 0)
747     item->block_count ++;
748
749   if (node->parent != NULL)
750     registry_cache_block_notification (node->parent);
751 }
752
753 static void
754 registry_cache_destroy_tree (GNode            *node,
755                              WatchThreadState *self);
756
757 /***************************************************************************
758  * Reading and writing
759  ***************************************************************************/
760
761 static gboolean
762 registry_read (HKEY           hpath,
763                const gchar   *path_name,
764                const gchar   *value_name,
765                RegistryValue *p_value)
766 {
767   LONG      result;
768   DWORD     value_data_size;
769   gpointer *buffer;
770
771   g_return_val_if_fail (p_value != NULL, FALSE);
772
773   p_value->type = REG_NONE;
774   p_value->ptr = NULL;
775
776   result = RegQueryValueExA (hpath, value_name, 0, &p_value->type, NULL, &value_data_size);
777   if (result != ERROR_SUCCESS)
778      {
779       handle_read_error (result, path_name, value_name);
780       return FALSE;
781      }
782
783   if (p_value->type == REG_SZ && value_data_size == 0)
784     {
785       p_value->ptr = g_strdup ("");
786       return TRUE;
787     }
788
789   if (p_value->type == REG_DWORD)
790     /* REG_DWORD is inlined */
791     buffer = (void *)&p_value->dword;
792   else
793     buffer = p_value->ptr = g_malloc (value_data_size);
794
795   result = RegQueryValueExA (hpath, value_name, 0, NULL, (LPBYTE)buffer, &value_data_size);
796   if (result != ERROR_SUCCESS)
797     {
798       handle_read_error (result, path_name, value_name);
799       return FALSE;
800     }
801
802   return TRUE;
803 }
804
805
806 static GVariant *
807 g_registry_backend_read (GSettingsBackend   *backend,
808                          const gchar        *key_name,
809                          const GVariantType *expected_type,
810                          gboolean            default_value)
811 {
812   GRegistryBackend *self = G_REGISTRY_BACKEND (backend);
813
814   GNode         *cache_node;
815   RegistryValue  registry_value;
816   GVariant      *gsettings_value = NULL;
817   gchar         *gsettings_type;
818
819   g_return_val_if_fail (expected_type != NULL, NULL);
820
821   if (default_value)
822     return NULL;
823
824   /* Simply read from the cache, which is updated from the registry by the
825    * watch thread as soon as changes can propagate. Any changes not yet in the
826    * cache will have the 'changed' signal emitted after this function returns.
827    */
828   EnterCriticalSection (self->cache_lock);
829   cache_node = registry_cache_get_node_for_key (self->cache_root, key_name, FALSE);
830   LeaveCriticalSection (self->cache_lock);
831
832   trace ("Reading key %s, cache node %x\n", key_name, cache_node);
833
834   /* Maybe it's not set, we can return to default */
835   if (cache_node == NULL)
836     return NULL;
837
838   trace ("\t- cached value %s\n", registry_value_dump (((RegistryCacheItem *)cache_node->data)->value));
839
840   registry_value = ((RegistryCacheItem *)cache_node->data)->value;
841
842   gsettings_type = g_variant_type_dup_string (expected_type);
843
844   /* The registry is user-editable, so we need to be fault-tolerant here. */
845   switch (gsettings_type[0])
846     {
847       case 'b': case 'y': case 'n': case 'q': case 'i': case 'u':
848         if (registry_value.type == REG_DWORD)
849           gsettings_value = g_variant_new (gsettings_type, registry_value.dword);
850         break;
851
852       case 't': case 'x':
853         if (registry_value.type == REG_QWORD)
854           {
855             DWORDLONG qword_value = *(DWORDLONG *)registry_value.ptr;
856             gsettings_value = g_variant_new (gsettings_type, qword_value);
857           }
858         break;
859
860       default:
861         if (registry_value.type == REG_SZ)
862           {
863             if (gsettings_type[0]=='s')
864               gsettings_value = g_variant_new_string ((char *)registry_value.ptr);
865             else
866               {
867                 GError *error = NULL;
868                 gsettings_value = g_variant_parse (expected_type, registry_value.ptr, NULL, NULL, &error);
869
870                 if (error != NULL)
871                 g_message ("gregistrysettingsbackend: error parsing key %s: %s\n",
872                            key_name, error->message);
873               }
874           }
875           break;
876     }
877
878   g_free (gsettings_type);
879
880   return gsettings_value;
881 }
882
883
884 typedef struct
885 {
886   GRegistryBackend  *self;
887   HKEY               hroot;
888 } RegistryWrite;
889
890 static gboolean
891 g_registry_backend_write_one (const char *key_name,
892                               GVariant   *variant,
893                               gpointer    user_data)
894 {
895   GRegistryBackend *self;
896   RegistryWrite    *action;
897   RegistryValue     value;
898
899   HKEY    hroot, hpath;
900   gchar  *path_name, *value_name = NULL;
901   DWORD   value_data_size;
902   LPVOID  value_data;
903   LONG    result;
904
905   GNode    *node;
906   gboolean  changed;
907
908   const gchar *type_string = g_variant_get_type_string (variant);
909
910   action = user_data;
911   self = G_REGISTRY_BACKEND (action->self);
912   hroot = action->hroot;
913
914   value.type = REG_NONE;
915   value.ptr = NULL;
916
917   switch (type_string[0])
918     {
919       case 'b': case 'y': case 'n': case 'q': case 'i': case 'u':
920         value.type = REG_DWORD;
921         value.dword = g_variant_get_as_dword (variant);
922         value_data_size = 4;
923         value_data = &value.dword;
924         break;
925
926       case 'x': case 't':
927         value.type = REG_QWORD;
928         value.ptr = g_malloc (8);
929         *(DWORDLONG *)value.ptr = g_variant_get_as_qword (variant);
930         value_data_size = 8;
931         value_data = value.ptr;
932         break;
933
934       default:
935         value.type = REG_SZ;
936         if (type_string[0]=='s')
937           {
938             gsize length;
939             value.ptr = g_strdup (g_variant_get_string (variant, &length));
940             value_data_size = length + 1;
941             value_data = value.ptr;
942           }
943         else
944           {
945             GString *value_string;
946             value_string = g_variant_print_string (variant, NULL, FALSE);
947             value_data_size = value_string->len+1;
948             value.ptr = value_data = g_string_free (value_string, FALSE);
949           }
950         break;
951     }
952
953   /* First update the cache, because the value may not have changed and we can
954    * save a write.
955    * 
956    * If 'value' has changed then its memory will not be freed by update_node(),
957    * because it will be stored in the node.
958    */
959   EnterCriticalSection (self->cache_lock);
960   node = registry_cache_get_node_for_key (self->cache_root, key_name, TRUE);
961   changed = registry_cache_update_node (node, value);
962   LeaveCriticalSection (self->cache_lock);
963
964   if (!changed)
965     return FALSE;
966
967   /* Block the next notification to any watch points above this location,
968    * because they will each get triggered on a change that is already updated
969    * in the cache.
970    */
971   registry_cache_block_notification (node);
972
973   path_name = parse_key (key_name, NULL, &value_name);
974
975   trace ("Set key: %s / %s\n", path_name, value_name);
976
977   /* Store the value in the registry */
978   result = RegCreateKeyExA (hroot, path_name, 0, NULL, 0, KEY_WRITE, NULL, &hpath, NULL);
979   if (result != ERROR_SUCCESS)
980     {
981       g_message_win32_error (result, "gregistrybackend: opening key %s failed", path_name+1);
982       registry_value_free (value);
983       g_free (path_name);
984       return FALSE;
985     }
986
987   result = RegSetValueExA (hpath, value_name, 0, value.type, value_data, value_data_size);
988   if (result != ERROR_SUCCESS)
989       g_message_win32_error (result, "gregistrybackend: setting value %s\\%s\\%s failed.\n",
990                              self->base_path, path_name, value_name);
991
992   /* If the write fails then it will seem like the value has changed until the
993    * next execution (because we wrote to the cache first). There's no reason
994    * for it to fail unless something is weirdly broken, however.
995    */
996
997   RegCloseKey (hpath);
998   g_free (path_name);
999
1000   return FALSE;
1001 };
1002
1003 /* The dconf write policy is to do the write while making out it succeeded, 
1004  * and then backtrack if it didn't. The registry functions are synchronous so
1005  * we can't do that. */
1006
1007 static gboolean
1008 g_registry_backend_write (GSettingsBackend *backend,
1009                           const gchar      *key_name,
1010                           GVariant         *value,
1011                           gpointer          origin_tag)
1012 {
1013   GRegistryBackend *self = G_REGISTRY_BACKEND (backend);
1014   LONG result;
1015   HKEY hroot;
1016   RegistryWrite action;
1017
1018   result = RegCreateKeyExA (HKEY_CURRENT_USER, self->base_path, 0, NULL, 0,
1019                             KEY_WRITE, NULL, &hroot, NULL);
1020   if (result != ERROR_SUCCESS) {
1021     trace ("Error opening/creating key %s.\n", self->base_path);
1022     return FALSE;
1023   }
1024
1025   action.self = self;
1026   action.hroot = hroot;
1027   g_registry_backend_write_one (key_name, value, &action);
1028   g_settings_backend_changed (backend, key_name, origin_tag);
1029
1030   RegCloseKey (hroot);
1031
1032   return TRUE;
1033 }
1034
1035 static gboolean
1036 g_registry_backend_write_tree (GSettingsBackend *backend,
1037                                GTree            *values,
1038                                gpointer          origin_tag)
1039 {
1040   GRegistryBackend *self = G_REGISTRY_BACKEND (backend);
1041   LONG result;
1042   HKEY hroot;
1043   RegistryWrite action;
1044
1045   result = RegCreateKeyExA (HKEY_CURRENT_USER, self->base_path, 0, NULL, 0,
1046                             KEY_WRITE, NULL, &hroot, NULL);
1047   if (result != ERROR_SUCCESS) {
1048     trace ("Error opening/creating key %s.\n", self->base_path);
1049     return FALSE;
1050   }
1051
1052   action.self =  self;
1053   action.hroot = hroot;
1054   g_tree_foreach (values, (GTraverseFunc)g_registry_backend_write_one,
1055                   &action);
1056
1057   g_settings_backend_changed_tree (backend, values, origin_tag);
1058   RegCloseKey (hroot);
1059
1060   return TRUE;
1061 }
1062
1063 static void
1064 g_registry_backend_reset (GSettingsBackend *backend,
1065                           const gchar      *key_name,
1066                           gpointer          origin_tag)
1067 {
1068   GRegistryBackend *self = G_REGISTRY_BACKEND (backend);
1069   gchar *path_name, *value_name = NULL;
1070   GNode *cache_node;
1071   LONG result;
1072   HKEY hpath;
1073
1074   /* Remove from cache */
1075   EnterCriticalSection (self->cache_lock);
1076   cache_node = registry_cache_get_node_for_key (self->cache_root, key_name, FALSE);
1077   if (cache_node)
1078     registry_cache_destroy_tree (cache_node, self->watch);
1079   LeaveCriticalSection (self->cache_lock);
1080
1081   /* Remove from the registry */
1082   path_name = parse_key (key_name, self->base_path, &value_name);
1083
1084   result = RegOpenKeyExA (HKEY_CURRENT_USER, path_name, 0, KEY_SET_VALUE, &hpath);
1085   if (result != ERROR_SUCCESS)
1086     {
1087       g_message_win32_error (result, "Registry: resetting key '%s'", path_name);
1088       g_free (path_name);
1089       return;
1090     }
1091
1092   result = RegDeleteValueA (hpath, value_name);
1093   RegCloseKey (hpath);
1094
1095   if (result != ERROR_SUCCESS)
1096     {
1097       g_message_win32_error (result, "Registry: resetting key '%s'", path_name);
1098       g_free (path_name);
1099       return;
1100     }
1101
1102   g_free (path_name);
1103
1104
1105   g_settings_backend_changed (backend, key_name, origin_tag);
1106 }
1107
1108 /* Not implemented and probably beyond the scope of this backend */
1109 static gboolean
1110 g_registry_backend_get_writable (GSettingsBackend *backend,
1111                                  const gchar      *key_name)
1112 {
1113   return TRUE;
1114 }
1115
1116 static GPermission *
1117 g_registry_backend_get_permission (GSettingsBackend *backend,
1118                                    const gchar      *key_name)
1119 {
1120   return g_simple_permission_new (TRUE);
1121 }
1122
1123
1124 /********************************************************************************
1125  * Spot-the-difference engine
1126  ********************************************************************************/
1127
1128 static void
1129 _free_watch (WatchThreadState *self,
1130              gint              index,
1131              GNode            *cache_node);
1132
1133 static void
1134 registry_cache_item_reset_touched (GNode    *node,
1135                                    gpointer  data)
1136 {
1137   RegistryCacheItem *item = node->data;
1138   item->touched = FALSE;
1139 }
1140
1141 /* Delete a node and any children, for when it has been deleted from the registry */
1142 static void
1143 registry_cache_destroy_tree (GNode            *node,
1144                              WatchThreadState *self)
1145 {
1146   RegistryCacheItem *item = node->data;
1147
1148   g_node_children_foreach (node, G_TRAVERSE_ALL,
1149                            (GNodeForeachFunc)registry_cache_destroy_tree, self);
1150
1151   if (item->subscription_count > 0)
1152     {
1153           gint i;
1154       /* There must be some watches active if this node is a watch point */
1155       g_warn_if_fail (self->cache_nodes->len > 1);
1156
1157       /* This is a watch point that has been deleted. Let's free the watch! */
1158       for (i=1; i<self->cache_nodes->len; i++)
1159         if (g_ptr_array_index (self->cache_nodes, i) == node)
1160           break;
1161       if (i >= self->cache_nodes->len)
1162         g_warning ("watch thread: a watch point was deleted, but unable to "
1163                    "find '%s' in the list of %i watch nodes\n", item->name,
1164                    self->cache_nodes->len-1);
1165       else
1166         {
1167           _free_watch (self, i, node);
1168           g_atomic_int_inc (&self->watches_remaining);
1169         }
1170     }
1171   _free_cache_item (node->data);
1172   g_node_destroy (node);
1173 }
1174
1175 static void
1176 registry_cache_remove_deleted (GNode    *node,
1177                                gpointer  data)
1178 {
1179   RegistryCacheItem *item = node->data;
1180
1181   if (!item->touched)
1182     registry_cache_destroy_tree (node, data);
1183 }
1184
1185 /* Update cache from registry, and optionally report on the changes.
1186  * 
1187  * This function is sometimes called from the watch thread, with no locking. It
1188  * does call g_registry_backend functions, but this is okay because they only
1189  * access self->base which is constant.
1190  *
1191  * When looking at this code bear in mind the terminology: in the registry, keys
1192  * are containers that contain values, and other keys. Keys have a 'default'
1193  * value which we always ignore.
1194  *
1195  * n_parent_watches: a counter used to set the reference count of any new nodes
1196  *                   that are created - they should have as many references as
1197  *                   there are notifications that are watching them.
1198  */
1199 static void
1200 registry_cache_update (GRegistryBackend *self,
1201                        HKEY              hpath,
1202                        const gchar      *prefix,
1203                        const gchar      *partial_key_name,
1204                        GNode            *cache_node,
1205                        int               n_watches, 
1206                        GPtrArray        *changes)
1207 {
1208   gchar  buffer[MAX_KEY_NAME_LENGTH + 1];
1209   gchar *key_name;
1210   gint   i;
1211   LONG   result;
1212
1213   RegistryCacheItem *item = cache_node->data;
1214
1215   if (item->subscription_count > 0)
1216     n_watches ++;
1217
1218   /* prefix is the level that all changes occur below; partial_key_name should
1219    * be NULL on the first call to this function */
1220   key_name = g_build_path ("/", prefix, partial_key_name, NULL);
1221
1222   trace ("registry cache update: %s. Node %x has %i children\n", key_name,
1223          cache_node, g_node_n_children (cache_node));
1224
1225   /* Start by zeroing 'touched' flag. When the registry traversal is done, any untouched nodes
1226    * must have been deleted from the registry.
1227    */
1228   g_node_children_foreach (cache_node, G_TRAVERSE_ALL,
1229                            registry_cache_item_reset_touched, NULL);
1230
1231   /* Recurse into each subpath at the current level, if any */
1232   i = 0;
1233   while (1)
1234     {
1235       DWORD buffer_size = MAX_KEY_NAME_LENGTH;
1236       HKEY  hsubpath;
1237
1238       result = RegEnumKeyEx (hpath, i++, buffer, &buffer_size, NULL, NULL, NULL, NULL);
1239       if (result != ERROR_SUCCESS)
1240         break;
1241
1242       result = RegOpenKeyEx (hpath, buffer, 0, KEY_READ, &hsubpath);
1243       if (result == ERROR_SUCCESS)
1244         {
1245           GNode             *subkey_node;
1246           RegistryCacheItem *child_item;
1247
1248           subkey_node = registry_cache_find_immediate_child (cache_node, buffer);
1249           if (subkey_node == NULL)
1250             {
1251               RegistryValue null_value = {REG_NONE, {0}};
1252               subkey_node = registry_cache_add_item (cache_node, buffer,
1253                                                      null_value, n_watches);
1254             }
1255
1256
1257           registry_cache_update (self, hsubpath, prefix, buffer, subkey_node,
1258                                  n_watches, changes);
1259           child_item = subkey_node->data;
1260           child_item->touched = TRUE;
1261         }
1262       RegCloseKey (hsubpath);
1263     }
1264
1265   if (result != ERROR_NO_MORE_ITEMS)
1266     g_message_win32_error (result, "gregistrybackend: error enumerating subkeys for cache.");
1267
1268   /* Enumerate each value at 'path' and check if it has changed */
1269   i = 0;
1270   while (1)
1271     {
1272       DWORD              buffer_size = MAX_KEY_NAME_LENGTH;
1273       GNode             *cache_child_node;
1274       RegistryCacheItem *child_item;
1275       RegistryValue      value;
1276       gboolean           changed = FALSE;
1277
1278       result = RegEnumValue (hpath, i++, buffer, &buffer_size, NULL, NULL, NULL, NULL);
1279       if (result != ERROR_SUCCESS)
1280         break;
1281
1282       if (buffer[0]==0)
1283         /* This is the key's 'default' value, for which we have no use. */
1284         continue;
1285
1286       cache_child_node = registry_cache_find_immediate_child (cache_node, buffer);
1287
1288       if (!registry_read (hpath, key_name, buffer, &value))
1289         continue;
1290
1291       trace ("\tgot value %s for %s, node %x\n", registry_value_dump (value), buffer, cache_child_node);
1292
1293       if (cache_child_node == NULL)
1294         {
1295           /* This is a new value */
1296           cache_child_node = registry_cache_add_item (cache_node, buffer, value,
1297                                                       n_watches);
1298           changed = TRUE;
1299         }
1300       else
1301         {
1302          /* For efficiency, instead of converting every value back to a GVariant to
1303           * compare it, we compare them as registry values (integers, or string
1304           * representations of the variant). The spurious change notifications that may
1305           * result should not be a big issue.
1306           *
1307           * Note that 'value' is swallowed or freed.
1308           */
1309           changed = registry_cache_update_node (cache_child_node, value);
1310         }
1311
1312       child_item = cache_child_node->data;
1313       child_item->touched = TRUE;
1314       if (changed == TRUE && changes != NULL)
1315         {
1316           gchar *item;
1317           if (partial_key_name == NULL)
1318             item = g_strdup (buffer);
1319           else
1320             item = g_build_path ("/", partial_key_name, buffer, NULL);
1321           g_ptr_array_add (changes, item);
1322         }
1323     }
1324
1325   if (result != ERROR_NO_MORE_ITEMS)
1326     g_message_win32_error (result, "gregistrybackend: error enumerating values for cache");
1327
1328   /* Any nodes now left untouched must have been deleted, remove them from cache */
1329   g_node_children_foreach (cache_node, G_TRAVERSE_ALL,
1330                            registry_cache_remove_deleted, self->watch);
1331
1332   trace ("registry cache update complete.\n");
1333   g_free (key_name);
1334 };
1335
1336
1337
1338 /***********************************************************************************
1339  * Thread to watch for registry change events
1340  ***********************************************************************************/
1341
1342 /* Called by watch thread. Apply for notifications on a registry key and its subkeys. */
1343 static DWORD
1344 registry_watch_key (HKEY hpath, HANDLE event)
1345 {
1346   return RegNotifyChangeKeyValue (hpath, TRUE,
1347                                   REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET,
1348                                   event, TRUE);
1349 }
1350
1351
1352 /* One of these is sent down the pipe when something happens in the registry. */
1353 typedef struct
1354 {
1355   GRegistryBackend *self;
1356   gchar *prefix;          /* prefix is a gsettings path, all items are subkeys of this. */
1357   GPtrArray *items;       /* each item is a subkey below prefix that has changed. */
1358 } RegistryEvent;
1359
1360 /* This handler runs in the main thread to emit the changed signals */
1361 static gboolean
1362 watch_handler (RegistryEvent *event)
1363 {
1364   gint i;
1365   trace ("Watch handler: got event in %s, items %i.\n", event->prefix, event->items->len);
1366
1367   /* GSettings requires us to NULL-terminate the array. */
1368   g_ptr_array_add (event->items, NULL);
1369   g_settings_backend_keys_changed (G_SETTINGS_BACKEND (event->self), event->prefix,
1370                                    (gchar const **)event->items->pdata, NULL);
1371
1372   for (i=0; i<event->items->len; i++)
1373     g_free (g_ptr_array_index (event->items, i));
1374   g_ptr_array_free (event->items, TRUE);
1375
1376   g_free (event->prefix);
1377   g_object_unref (event->self);
1378   
1379   g_slice_free (RegistryEvent, event);
1380   return FALSE;
1381 };
1382
1383
1384 static void
1385 _free_watch (WatchThreadState *self,
1386              gint              index,
1387              GNode            *cache_node)
1388 {
1389   HKEY    hpath;
1390   HANDLE  cond;
1391   gchar  *prefix;
1392
1393   g_return_if_fail (index > 0 && index < self->events->len);
1394
1395   cond       = g_ptr_array_index (self->events,      index);
1396   hpath      = g_ptr_array_index (self->handles,     index);
1397   prefix     = g_ptr_array_index (self->prefixes,    index);
1398
1399   trace ("Freeing watch %i [%s]\n", index, prefix);
1400  
1401   /* These can be NULL if the watch was already dead, this can happen when eg.
1402    * a key is deleted but GSettings is still subscribed to it - the watch is
1403    * kept alive so that the unsubscribe function works properly, but does not
1404    * do anything.
1405    */
1406   if (hpath != NULL)
1407     RegCloseKey (hpath);
1408
1409   if (cache_node != NULL)
1410     {
1411       //registry_cache_dump (G_REGISTRY_BACKEND (self->owner)->cache_root, NULL);
1412       registry_cache_unref_tree (cache_node);
1413     }
1414
1415   CloseHandle (cond);
1416   g_free (prefix);
1417
1418   /* As long as we remove from each array at the same time, it doesn't matter that
1419    * their orders get messed up - they all get messed up the same.
1420    */
1421   g_ptr_array_remove_index_fast (self->handles,     index);
1422   g_ptr_array_remove_index_fast (self->events,      index);
1423   g_ptr_array_remove_index_fast (self->prefixes,    index);
1424   g_ptr_array_remove_index_fast (self->cache_nodes, index);
1425 }
1426
1427 static void
1428 watch_thread_handle_message (WatchThreadState *self)
1429 {
1430   switch (self->message.type)
1431     {
1432       case WATCH_THREAD_NONE:
1433         trace ("watch thread: you woke me up for nothin', man!");
1434         break;
1435
1436       case WATCH_THREAD_ADD_WATCH:
1437         {
1438           RegistryWatch *watch = &self->message.watch;
1439           LONG           result;
1440           result = registry_watch_key (watch->hpath, watch->event);
1441           if (result == ERROR_SUCCESS)
1442             {
1443               g_ptr_array_add (self->events,      watch->event);
1444               g_ptr_array_add (self->handles,     watch->hpath);
1445               g_ptr_array_add (self->prefixes,    watch->prefix);
1446               g_ptr_array_add (self->cache_nodes, watch->cache_node);
1447               trace ("watch thread: new watch on %s, %i total\n", watch->prefix,
1448                      self->events->len);
1449             }
1450           else
1451             {
1452               g_message_win32_error (result, "watch thread: could not watch %s", watch->prefix);
1453               CloseHandle (watch->event);
1454               RegCloseKey (watch->hpath);
1455               g_free (watch->prefix);
1456               registry_cache_unref_tree (watch->cache_node);
1457             }
1458           break;
1459         }
1460
1461       case WATCH_THREAD_REMOVE_WATCH:
1462         {
1463           GNode             *cache_node;
1464           RegistryCacheItem *cache_item;
1465           gint               i;
1466
1467           for (i=1; i<self->prefixes->len; i++)
1468             if (strcmp (g_ptr_array_index (self->prefixes, i),
1469                         self->message.watch.prefix) == 0)
1470                 break;
1471  
1472           if (i >= self->prefixes->len)
1473             {
1474               /* Don't make a fuss if the prefix is not being watched because
1475                * maybe the path was deleted so we removed the watch.
1476                */
1477               trace ("unsubscribe: prefix %s is not being watched [%i things are]!\n",
1478                      self->message.watch.prefix, self->prefixes->len);
1479               g_free (self->message.watch.prefix);
1480               break;
1481             }
1482
1483           cache_node = g_ptr_array_index (self->cache_nodes, i);
1484
1485           trace ("watch thread: unsubscribe: freeing node %x, prefix %s, index %i\n",
1486                  (guint)cache_node, self->message.watch.prefix, i);
1487           if (cache_node != NULL)
1488             {
1489               cache_item = cache_node->data;
1490
1491               /* There may be more than one GSettings object subscribed to this
1492                * path, only free the watch when the last one unsubscribes.
1493                */
1494               cache_item->subscription_count --;
1495               if (cache_item->subscription_count > 0)
1496                 break;
1497             }
1498
1499           _free_watch (self, i, cache_node);
1500           g_free (self->message.watch.prefix);
1501
1502           g_atomic_int_inc (&self->watches_remaining);
1503           break;
1504         }
1505
1506       case WATCH_THREAD_STOP:
1507         {
1508           gint i;
1509
1510           /* Free any remaining cache and watch handles */
1511           for (i=1; i<self->events->len; i++)
1512             _free_watch (self, i, g_ptr_array_index (self->cache_nodes, i));
1513
1514           SetEvent (self->message_received_event);
1515           ExitThread (0);
1516         }
1517     }
1518
1519   self->message.type = WATCH_THREAD_NONE;
1520   SetEvent (self->message_received_event);
1521 }
1522
1523
1524 /* Thread which watches for win32 registry events */
1525 static DWORD WINAPI
1526 watch_thread_function (LPVOID parameter)
1527 {
1528   WatchThreadState *self = (WatchThreadState *)parameter;
1529   DWORD result;
1530
1531   self->events = g_ptr_array_new ();
1532   self->handles = g_ptr_array_new ();
1533   self->prefixes = g_ptr_array_new ();
1534   self->cache_nodes = g_ptr_array_new ();
1535   g_ptr_array_add (self->events, self->message_sent_event);
1536   g_ptr_array_add (self->handles, NULL);
1537   g_ptr_array_add (self->prefixes, NULL);
1538   g_ptr_array_add (self->cache_nodes, NULL);
1539
1540   while (1)
1541     {
1542       trace ("watch thread: going to sleep; %i events watched.\n", self->events->len);
1543       result = WaitForMultipleObjects (self->events->len, self->events->pdata, FALSE, INFINITE);
1544
1545       if (result == WAIT_OBJECT_0)
1546         {
1547           /* A message to you. The sender (main thread) will block until we signal the received
1548            * event, so there should be no danger of it sending another before we receive the
1549            * first.
1550            */
1551           watch_thread_handle_message (self);
1552         }
1553       else if (result > WAIT_OBJECT_0 && result <= WAIT_OBJECT_0 + self->events->len)
1554         {
1555           HKEY               hpath;
1556           HANDLE             cond;
1557           gchar             *prefix;
1558           GNode             *cache_node;
1559           RegistryCacheItem *cache_item;
1560           RegistryEvent     *event;
1561
1562           /* One of our notifications has triggered. All we know is which one, and which key
1563            * this is for. We do most of the processing here, because we may as well. If the
1564            * registry changes further while we are processing it doesn't matter - we will then
1565            * receive another change notification from the OS anyway.
1566            */
1567           gint notify_index = result - WAIT_OBJECT_0;
1568           hpath      = g_ptr_array_index (self->handles,     notify_index);
1569           cond       = g_ptr_array_index (self->events,      notify_index);
1570           prefix     = g_ptr_array_index (self->prefixes,    notify_index);
1571           cache_node = g_ptr_array_index (self->cache_nodes, notify_index);
1572
1573           trace ("Watch thread: notify received on prefix %i: %s.\n", notify_index, prefix);
1574
1575           if (cache_node == NULL)
1576             {
1577               /* This path has been deleted */
1578               trace ("Notify received on a path that was deleted :(\n");
1579               continue;
1580             }
1581
1582           /* Firstly we need to reapply for the notification, because (what a
1583            * sensible API) we won't receive any more. MSDN is pretty
1584            * inconsistent on this matter:
1585            *   http://msdn.microsoft.com/en-us/library/ms724892%28VS.85%29.aspx
1586            *   http://support.microsoft.com/kb/236570
1587            * But my tests (on Windows XP SP3) show that we need to reapply
1588            * each time.
1589            */
1590           result = registry_watch_key (hpath, cond);
1591
1592           if (result != ERROR_SUCCESS)
1593             {
1594               /* Watch failed, most likely because the key has just been
1595                * deleted. Free the watch and unref the cache nodes.
1596                */
1597              if (result != ERROR_KEY_DELETED)
1598                g_message_win32_error (result, "watch thread: failed to watch %s", prefix);
1599              _free_watch (self, notify_index, cache_node);
1600              g_atomic_int_inc (&self->watches_remaining);
1601              continue;
1602             }
1603
1604           /* The notification may have been blocked because we just changed
1605            * some data ourselves.
1606            */
1607           cache_item = cache_node->data;
1608           if (cache_item->block_count)
1609             {
1610               cache_item->block_count --;
1611               trace ("Watch thread: notify blocked at %s\n", prefix);
1612               continue;
1613             }
1614   
1615           /* Now we update our stored cache from registry data, and find which keys have
1616            * actually changed. If more changes happen while we are processing, we will get
1617            * another event because we have reapplied for change notifications already.
1618            *
1619            * Working here rather than in the main thread is preferable because the UI is less
1620            * likely to block (only when changing notification subscriptions).
1621            */
1622           event = g_slice_new (RegistryEvent);
1623
1624           event->self = G_REGISTRY_BACKEND (self->owner);
1625           g_object_ref (self->owner);
1626
1627           event->items = g_ptr_array_new ();
1628
1629           EnterCriticalSection (G_REGISTRY_BACKEND (self->owner)->cache_lock);
1630           registry_cache_update (G_REGISTRY_BACKEND (self->owner), hpath,
1631                                  prefix, NULL, cache_node, 0, event->items);
1632           LeaveCriticalSection (G_REGISTRY_BACKEND (self->owner)->cache_lock);
1633
1634           if (event->items->len > 0)
1635             {
1636               event->prefix = g_strdup (prefix);
1637               g_idle_add ((GSourceFunc) watch_handler, event);
1638             }
1639           else
1640             {
1641               g_ptr_array_free (event->items, TRUE);
1642               g_slice_free (RegistryEvent, event);
1643             }
1644         }
1645       else
1646         {
1647           /* God knows what has happened */
1648           g_message_win32_error (GetLastError(), "watch thread: WaitForMultipleObjects error");
1649         }
1650     }
1651
1652   return -1;
1653 }
1654
1655 static gboolean
1656 watch_start (GRegistryBackend *self)
1657 {
1658   WatchThreadState *watch;
1659
1660   g_return_val_if_fail (self->watch == NULL, FALSE);
1661
1662   self->cache_lock = g_slice_new (CRITICAL_SECTION);
1663   InitializeCriticalSection (self->cache_lock);
1664
1665   watch = g_slice_new (WatchThreadState);
1666   watch->owner = G_SETTINGS_BACKEND (self);
1667
1668   watch->watches_remaining = MAX_WATCHES;
1669
1670   watch->message_lock = g_slice_new (CRITICAL_SECTION);
1671   InitializeCriticalSection (watch->message_lock);
1672   watch->message_sent_event = CreateEvent (NULL, FALSE, FALSE, NULL);
1673   watch->message_received_event = CreateEvent (NULL, FALSE, FALSE, NULL);
1674   if (watch->message_sent_event == NULL || watch->message_received_event == NULL)
1675     {
1676       g_message_win32_error (0, "gregistrybackend: Failed to create sync objects.");
1677       goto fail_1;
1678     }
1679
1680   /* Use a small stack to make the thread more lightweight. */
1681   watch->thread = CreateThread (NULL, 1024, watch_thread_function, watch, 0, NULL);
1682   if (watch->thread == NULL)
1683     {
1684       g_message_win32_error (0, "gregistrybackend: Failed to create notify watch thread.");
1685       goto fail_2;
1686     }
1687
1688   self->watch = watch;
1689
1690   return TRUE;
1691
1692 fail_2:
1693   DeleteCriticalSection (self->cache_lock);
1694   g_slice_free (CRITICAL_SECTION, self->cache_lock);
1695   DeleteCriticalSection (watch->message_lock);
1696   g_slice_free (CRITICAL_SECTION, watch->message_lock);
1697   CloseHandle (watch->message_sent_event);
1698   CloseHandle (watch->message_received_event);
1699 fail_1:
1700   g_slice_free (WatchThreadState, watch);
1701   return FALSE;
1702 }
1703
1704 /* This function assumes you hold the message lock! */
1705 static void
1706 watch_stop_unlocked (GRegistryBackend *self)
1707 {
1708   WatchThreadState *watch = self->watch;
1709   DWORD result;
1710   g_return_if_fail (watch != NULL);
1711
1712   watch->message.type = WATCH_THREAD_STOP;
1713   SetEvent (watch->message_sent_event);
1714
1715   /* This is signalled as soon as the message is received. We must not return
1716    * while the watch thread is still firing off callbacks. Freeing all of the
1717    * memory is done in the watch thread after this is signalled.
1718    */
1719   result = WaitForSingleObject (watch->message_received_event, INFINITE);
1720   if (result != WAIT_OBJECT_0)
1721     {
1722       g_warning ("gregistrybackend: unable to stop watch thread.");
1723       return;
1724     }
1725
1726   LeaveCriticalSection (watch->message_lock);
1727   DeleteCriticalSection (watch->message_lock);
1728   DeleteCriticalSection (self->cache_lock);
1729   g_slice_free (CRITICAL_SECTION, watch->message_lock);
1730   g_slice_free (CRITICAL_SECTION, self->cache_lock);
1731   CloseHandle (watch->message_sent_event);
1732   CloseHandle (watch->message_received_event);
1733   CloseHandle (watch->thread);
1734   g_slice_free (WatchThreadState, watch);
1735
1736   trace ("\nwatch thread: %x: all data freed.\n", self);
1737   self->watch = NULL;
1738 };
1739
1740 static gboolean
1741 watch_add_notify (GRegistryBackend *self,
1742                   HANDLE            event,
1743                   HKEY              hpath,
1744                   gchar            *gsettings_prefix)
1745 {
1746   WatchThreadState  *watch = self->watch;
1747   GNode             *cache_node;
1748   RegistryCacheItem *cache_item;
1749   DWORD              result;
1750
1751   g_return_val_if_fail (watch != NULL, FALSE);
1752   trace ("watch_add_notify: prefix %s.\n", gsettings_prefix);
1753
1754   /* Duplicate tree into the cache in the main thread, before we add the notify: if we do it in the
1755    * thread we can miss changes while we are caching.
1756    */
1757   EnterCriticalSection (self->cache_lock);
1758   cache_node = registry_cache_get_node_for_key (self->cache_root, gsettings_prefix, TRUE);
1759
1760   g_return_val_if_fail (cache_node != NULL, FALSE);
1761   g_return_val_if_fail (cache_node->data != NULL, FALSE);
1762   
1763   cache_item = cache_node->data;
1764
1765   cache_item->subscription_count ++;
1766   if (cache_item->subscription_count > 1)
1767     {
1768       trace ("watch_add_notify: prefix %s already watched, %i subscribers.\n",
1769              gsettings_prefix, cache_item->subscription_count);
1770       return FALSE;
1771     }
1772
1773   registry_cache_ref_tree (cache_node);
1774   registry_cache_update (self, hpath, gsettings_prefix, NULL, cache_node, 0, NULL);
1775   //registry_cache_dump (self->cache_root, NULL);
1776   LeaveCriticalSection (self->cache_lock);
1777
1778   EnterCriticalSection (watch->message_lock);
1779   watch->message.type = WATCH_THREAD_ADD_WATCH;
1780   watch->message.watch.event      = event;
1781   watch->message.watch.hpath      = hpath;
1782   watch->message.watch.prefix     = gsettings_prefix;
1783   watch->message.watch.cache_node = cache_node;
1784
1785   SetEvent (watch->message_sent_event);
1786
1787   /* Wait for the received event in return, to avoid sending another message before the first
1788    * one was received. If it takes > 200ms there is a possible race but the worst outcome is
1789    * a notification is ignored.
1790    */
1791   result = WaitForSingleObject (watch->message_received_event, 200);
1792   #ifdef TRACE
1793     if (result != WAIT_OBJECT_0)
1794       trace ("watch thread is slow to respond - notification may not be added.");
1795   #endif
1796   LeaveCriticalSection (watch->message_lock);
1797
1798   return TRUE;
1799 };
1800
1801
1802 static void
1803 watch_remove_notify (GRegistryBackend *self,
1804                      const gchar      *key_name)
1805 {
1806   WatchThreadState *watch = self->watch;
1807   LONG     result;
1808
1809   if (self->watch == NULL)
1810     /* Here we assume that the unsubscribe message is for somewhere that was
1811      * deleted, and so it has already been removed and the watch thread has
1812      * stopped.
1813      */
1814     return;
1815
1816   EnterCriticalSection (watch->message_lock);
1817   watch->message.type = WATCH_THREAD_REMOVE_WATCH;
1818   watch->message.watch.prefix = g_strdup (key_name);
1819
1820   SetEvent (watch->message_sent_event);
1821
1822   /* Wait for the received event in return, to avoid sending another message before the first
1823    * one was received.
1824    */
1825   result = WaitForSingleObject (watch->message_received_event, INFINITE);
1826
1827   if (result != ERROR_SUCCESS)
1828     g_warning ("unsubscribe from %s: message not acknowledged\n", key_name);
1829
1830   if (g_atomic_int_get (&watch->watches_remaining) >= MAX_WATCHES)
1831     /* Stop it before any new ones can get added and confuse things */
1832     watch_stop_unlocked (self); 
1833   else
1834     LeaveCriticalSection (watch->message_lock);
1835 }
1836
1837 /* dconf semantics are: if the key ends in /, watch the keys underneath it - if not, watch that
1838  * key. Our job is easier because keys and values are separate.
1839  */
1840 static void
1841 g_registry_backend_subscribe (GSettingsBackend *backend,
1842                               const char       *key_name)
1843 {
1844   GRegistryBackend *self = G_REGISTRY_BACKEND (backend);
1845   gchar *path_name, *value_name = NULL;
1846   HKEY hpath;
1847   HANDLE event;
1848   LONG result;
1849
1850   if (self->watch == NULL)
1851     if (!watch_start (self))
1852       return;
1853
1854   if (g_atomic_int_dec_and_test (&self->watch->watches_remaining))
1855     {
1856       g_atomic_int_inc (&self->watch->watches_remaining);
1857       g_warning ("subscribe() failed: only %i different paths may be watched.\n", MAX_WATCHES);
1858       return;
1859     }
1860
1861   path_name = parse_key (key_name, self->base_path, &value_name);
1862
1863   /* Must check for this, otherwise strange crashes occur because the cache
1864    * node that is being watched gets freed. All path names to subscribe must
1865    * end in a slash!
1866    */
1867   if (value_name != NULL && *value_name != 0)
1868     g_warning ("subscribe() failed: path must end in a /, got %s\n", key_name);
1869
1870   trace ("Subscribing to %s [registry %s / %s] - watch %x\n", key_name, path_name, value_name, self->watch);
1871
1872
1873   /* Give the caller the benefit of the doubt if the key doesn't exist and create it. The caller
1874    * is almost certainly a new g_settings with this path as base path. */
1875   result = RegCreateKeyExA (HKEY_CURRENT_USER, path_name, 0, NULL, 0, KEY_READ, NULL, &hpath,
1876                             NULL);
1877   g_free (path_name);
1878
1879   if (result != ERROR_SUCCESS)
1880     {
1881       g_message_win32_error (result, "gregistrybackend: Unable to subscribe to key %s.", key_name);
1882       g_atomic_int_inc (&self->watch->watches_remaining);
1883       return;
1884     }
1885
1886   event = CreateEvent (NULL, FALSE, FALSE, NULL);
1887   if (event == NULL)
1888     {
1889       g_message_win32_error (result, "gregistrybackend: CreateEvent failed.\n");
1890       g_atomic_int_inc (&self->watch->watches_remaining);
1891       RegCloseKey (hpath);
1892       return;
1893     }
1894
1895   /* The actual watch is added by the thread, which has to re-subscribe each time it
1896    * receives a change. */
1897   if (!watch_add_notify (self, event, hpath, g_strdup (key_name)))
1898     g_atomic_int_inc (&self->watch->watches_remaining);
1899 }
1900
1901 static void
1902 g_registry_backend_unsubscribe (GSettingsBackend *backend,
1903                                 const char       *key_name)
1904 {
1905   trace ("unsubscribe: %s.\n", key_name);
1906
1907   watch_remove_notify (G_REGISTRY_BACKEND (backend), key_name);
1908 }
1909
1910
1911 /********************************************************************************
1912  * Object management junk
1913  ********************************************************************************/
1914
1915 GSettingsBackend *
1916 g_registry_backend_new (void) {
1917   return g_object_new (G_TYPE_REGISTRY_BACKEND, NULL);
1918 }
1919
1920 static void
1921 g_registry_backend_finalize (GObject *object)
1922 {
1923   GRegistryBackend  *self = G_REGISTRY_BACKEND (object);
1924   RegistryCacheItem *item;
1925
1926   item = self->cache_root->data;
1927   g_warn_if_fail (item->ref_count == 1);
1928
1929   _free_cache_item (item);
1930   g_node_destroy (self->cache_root);
1931
1932   if (self->watch != NULL)
1933     {
1934       EnterCriticalSection (self->watch->message_lock);
1935       watch_stop_unlocked (self);
1936     }
1937
1938   g_free (self->base_path);
1939 }
1940
1941 static void
1942 g_registry_backend_class_init (GRegistryBackendClass *class)
1943 {
1944   GSettingsBackendClass *backend_class = G_SETTINGS_BACKEND_CLASS (class);
1945   GObjectClass *object_class = G_OBJECT_CLASS (class);
1946
1947   object_class->finalize = g_registry_backend_finalize;
1948
1949   backend_class->read = g_registry_backend_read;
1950   backend_class->write = g_registry_backend_write;
1951   backend_class->write_tree = g_registry_backend_write_tree;
1952   backend_class->reset = g_registry_backend_reset;
1953   backend_class->get_writable = g_registry_backend_get_writable;
1954   backend_class->get_permission = g_registry_backend_get_permission;
1955   backend_class->subscribe = g_registry_backend_subscribe;
1956   backend_class->unsubscribe = g_registry_backend_unsubscribe;
1957 }
1958
1959 static void
1960 g_registry_backend_init (GRegistryBackend *self)
1961 {
1962   RegistryCacheItem *item;
1963   self->base_path = g_strdup_printf ("Software\\GSettings");
1964
1965   item = g_slice_new (RegistryCacheItem);
1966   item->value.type = REG_NONE;
1967   item->value.ptr = NULL;
1968   item->name = g_strdup ("<root>");
1969   item->ref_count = 1;
1970   self->cache_root = g_node_new (item);
1971
1972   self->watch = NULL;
1973 }