Git init
[external/dbus-glib.git] / dbus / dbus-gobject.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-gobject.c Exporting a GObject remotely
3  *
4  * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
5  * Copyright (C) 2005 Nokia
6  *
7  * Licensed under the Academic Free License version 2.1
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25 #include <config.h>
26 #include <gobject/gvaluecollector.h>
27 #include <dbus/dbus-glib.h>
28 #include <dbus/dbus-glib-lowlevel.h>
29 #include "dbus-gtest.h"
30 #include "dbus-gutils.h"
31 #include "dbus-gobject.h"
32 #include "dbus-gsignature.h"
33 #include "dbus-gvalue.h"
34 #include "dbus-gmarshal.h"
35 #include "dbus-gvalue-utils.h"
36 #include <string.h>
37
38 static char *lookup_property_name (GObject    *object,
39                                    const char *wincaps_propiface,
40                                    const char *requested_propname);
41
42 typedef struct
43 {
44   char *default_iface;
45   GType code_enum;
46 } DBusGErrorInfo;
47
48 static GStaticRWLock globals_lock = G_STATIC_RW_LOCK_INIT;
49 /* See comments in check_property_access */
50 static gboolean disable_legacy_property_access = FALSE;
51 static GHashTable *marshal_table = NULL;
52 static GData *error_metadata = NULL;
53
54 static char*
55 uscore_to_wincaps_full (const char *uscore,
56                         gboolean    uppercase_first)
57 {
58   const char *p;
59   GString *str;
60   gboolean last_was_uscore;
61
62   last_was_uscore = uppercase_first;
63   
64   str = g_string_new (NULL);
65   p = uscore;
66   while (p && *p)
67     {
68       if (*p == '-' || *p == '_')
69         {
70           last_was_uscore = TRUE;
71         }
72       else
73         {
74           if (last_was_uscore)
75             {
76               g_string_append_c (str, g_ascii_toupper (*p));
77               last_was_uscore = FALSE;
78             }
79           else
80             g_string_append_c (str, *p);
81         }
82       ++p;
83     }
84
85   return g_string_free (str, FALSE);
86 }
87
88 /* Ugly yes - but we have to accept strings from both formats */
89 static gboolean
90 compare_strings_ignoring_uscore_vs_dash (const char *a, const char *b)
91 {
92   guint i;
93
94   for (i = 0; a[i] && b[i]; i++)
95     {
96       if ((a[i] == '-' && b[i] == '_')
97           || (a[i] == '_' && b[i] == '-'))
98         continue;
99       if (a[i] != b[i])
100         return FALSE;
101     }
102   return (a[i] == '\0') && (b[i] == '\0');
103 }
104
105 static char *
106 uscore_to_wincaps (const char *uscore)
107 {
108   return uscore_to_wincaps_full (uscore, TRUE);
109 }
110
111 static const char *
112 string_table_next (const char *table)
113 {
114   return (table + (strlen (table) + 1));
115 }
116
117 static const char *
118 string_table_lookup (const char *table, int index)
119 {
120   const char *ret;
121
122   ret = table;
123
124   while (index--)
125     ret = string_table_next (ret);
126
127   return ret;
128 }
129
130 static const char *
131 get_method_data (const DBusGObjectInfo *object,
132                  const DBusGMethodInfo *method)
133 {
134   return object->data + method->data_offset;
135 }
136
137 static char *
138 object_error_domain_prefix_from_object_info (const DBusGObjectInfo *info)
139 {
140   /* FIXME */
141   return NULL;
142 }
143
144 static char *
145 object_error_code_from_object_info (const DBusGObjectInfo *info, GQuark domain, gint code)
146 {
147   /* FIXME */
148   return NULL;
149 }
150
151 static const char *
152 method_interface_from_object_info (const DBusGObjectInfo *object,
153                               const DBusGMethodInfo *method)
154 {
155   return string_table_lookup (get_method_data (object, method), 0);
156 }
157
158 static const char *
159 method_name_from_object_info (const DBusGObjectInfo *object,
160                               const DBusGMethodInfo *method)
161 {
162   return string_table_lookup (get_method_data (object, method), 1);
163 }
164
165 static const char *
166 method_arg_info_from_object_info (const DBusGObjectInfo *object,
167                                   const DBusGMethodInfo *method)
168 {
169   return string_table_lookup (get_method_data (object, method), 3);/*RB was 2*/
170 }
171
172 typedef enum
173 {
174   RETVAL_NONE,    
175   RETVAL_NOERROR,    
176   RETVAL_ERROR
177 } RetvalType;
178
179 static const char *
180 arg_iterate (const char    *data,
181              const char   **name,
182              gboolean      *in,
183              gboolean      *constval,
184              RetvalType    *retval,
185              const char   **type)
186 {
187   gboolean inarg;
188
189   if (name)
190     *name = data;
191
192   data = string_table_next (data);
193   switch (*data)
194     {
195     case 'I':
196       inarg = TRUE;
197       break;
198     case 'O':
199       inarg = FALSE;
200       break;
201     default:
202       g_warning ("invalid arg direction '%c'", *data);
203       inarg = FALSE;
204       break;
205     }
206   if (in)
207     *in = inarg;
208
209   if (!inarg)
210     {
211       data = string_table_next (data);
212       switch (*data)
213         {
214         case 'F':
215           if (constval)
216             *constval = FALSE;
217           break;
218         case 'C':
219           if (constval)
220             *constval = TRUE;
221           break;
222         default:
223           g_warning ("invalid arg const value '%c'", *data);
224           break;
225         }
226       data = string_table_next (data);
227       switch (*data)
228         {
229         case 'N':
230           if (retval)
231             *retval = RETVAL_NONE;
232           break;
233         case 'E':
234           if (retval)
235             *retval = RETVAL_ERROR;
236           break;
237         case 'R':
238           if (retval)
239             *retval = RETVAL_NOERROR;
240           break;
241         default:
242           g_warning ("invalid arg ret value '%c'", *data);
243           break;
244         }
245     }
246   else
247     {
248       if (constval)
249         *constval = FALSE;
250       if (retval)
251         *retval = FALSE;
252     }
253   
254   data = string_table_next (data);
255   if (type)
256     *type = data;
257
258   return string_table_next (data);
259 }
260
261 static char *
262 method_dir_signature_from_object_info (const DBusGObjectInfo *object,
263                                        const DBusGMethodInfo *method,
264                                        gboolean               in)
265 {
266   const char *arg;
267   GString *ret;
268
269   arg = method_arg_info_from_object_info (object, method);
270
271   ret = g_string_new (NULL);
272
273   while (*arg)
274     {
275       const char *name;
276       gboolean arg_in;
277       const char *type;
278
279       arg = arg_iterate (arg, &name, &arg_in, NULL, NULL, &type);
280
281       if (arg_in == in)
282         g_string_append (ret, type);
283     }
284
285   return g_string_free (ret, FALSE);
286 }
287
288 static char *
289 method_input_signature_from_object_info (const DBusGObjectInfo *object,
290                                          const DBusGMethodInfo *method)
291 {
292   return method_dir_signature_from_object_info (object, method, TRUE);
293 }
294
295 static char *
296 method_output_signature_from_object_info (const DBusGObjectInfo *object,
297                                           const DBusGMethodInfo *method)
298 {
299   return method_dir_signature_from_object_info (object, method, FALSE);
300 }
301
302 static const char *
303 signal_iterate (const char *data, const char **iface, const char **name)
304 {
305   *iface = data;
306
307   data = string_table_next (data);
308   *name = data;
309
310   return string_table_next (data);
311 }
312
313 static const char *
314 property_iterate (const char  *data,
315                   int          format_version,
316                   const char **iface,
317                   const char **exported_name,
318                   const char **name_uscored,
319                   const char **access_type)
320 {
321   *iface = data;
322
323   data = string_table_next (data);
324   *exported_name = data;
325
326   data = string_table_next (data);
327   if (format_version == 1)
328     {
329       *name_uscored = data;
330       data = string_table_next (data);
331       *access_type = data;
332       return string_table_next (data);
333     }
334   else
335     {
336       /* This tells the caller they need to compute it */
337       *name_uscored = NULL;
338       /* We don't know here, however note that we will still check against the
339        * readable/writable flags from GObject's metadata.
340        */
341       *access_type = "readwrite";
342       return data;
343     }
344 }
345
346 /**
347  * property_info_from_object_info:
348  * @object: introspection data
349  * @interface_name: (allow-none): Expected interface name, or %NULL for any
350  * @property_name: Expected property name (can use "-" or "_" as separator)
351  * @access_type: (out): Can be one of "read", "write", "readwrite"
352  *
353  * Look up property introspection data for the given interface/name pair.
354  *
355  * Returns: %TRUE if property was found
356  */
357 static gboolean
358 property_info_from_object_info (const DBusGObjectInfo  *object,
359                                 const char             *interface_name,
360                                 const char             *property_name,
361                                 const char            **access_type)
362 {
363   const char *properties_iter;
364
365   properties_iter = object->exported_properties;
366   while (properties_iter != NULL && *properties_iter)
367     {
368       const char *cur_interface_name;
369       const char *cur_property_name;
370       const char *cur_uscore_property_name;
371       const char *cur_access_type;
372
373
374       properties_iter = property_iterate (properties_iter, object->format_version,
375                                           &cur_interface_name, &cur_property_name,
376                                           &cur_uscore_property_name, &cur_access_type);
377
378       if (interface_name && strcmp (interface_name, cur_interface_name) != 0)
379         continue;
380
381       /* This big pile of ugly is necessary to support the matrix resulting from multiplying
382        * (v0 data, v1 data) * (FooBar, foo-bar)
383        * In v1 data we have both forms of string, so we do a comparison against both without
384        * having to malloc.
385        * For v0 data, we need to reconstruct the foo-bar form.
386        *
387        * Adding to the complexity is that we *also* have to ignore the distinction between
388        * '-' and '_', because g_object_{get,set} does.
389        */
390       /* First, compare against the primary property name - no malloc required */
391       if (!compare_strings_ignoring_uscore_vs_dash (property_name, cur_property_name))
392         {
393           if (cur_uscore_property_name != NULL
394               && !compare_strings_ignoring_uscore_vs_dash (property_name, cur_uscore_property_name))
395             continue;
396           else
397             {
398               /* v0 metadata, construct uscore */
399               char *tmp_uscored;
400               gboolean matches;
401               tmp_uscored = _dbus_gutils_wincaps_to_uscore (cur_property_name);
402               matches = compare_strings_ignoring_uscore_vs_dash (property_name, tmp_uscored);
403               g_free (tmp_uscored);
404               if (!matches)
405                 continue;
406             }
407         }
408
409       *access_type = cur_access_type;
410       return TRUE;
411     }
412   return FALSE;
413 }
414
415 static GQuark
416 dbus_g_object_type_dbus_metadata_quark (void)
417 {
418   static GQuark quark;
419
420   if (!quark)
421     quark = g_quark_from_static_string ("DBusGObjectTypeDBusMetadataQuark");
422   return quark;
423 }
424
425 /* Iterator function should return FALSE to stop iteration, TRUE to continue */
426 typedef gboolean (*ForeachObjectInfoFn) (const DBusGObjectInfo *info,
427                                          GType                 gtype,
428                                          gpointer              user_data);
429
430 static void
431 foreach_object_info (GObject *object,
432                      ForeachObjectInfoFn callback,
433                      gpointer user_data)
434 {
435   GType *interfaces, *p;
436   const DBusGObjectInfo *info;
437   GType classtype;
438
439   interfaces = g_type_interfaces (G_TYPE_FROM_INSTANCE (object), NULL);
440
441   for (p = interfaces; *p != 0; p++)
442     {
443       info = g_type_get_qdata (*p, dbus_g_object_type_dbus_metadata_quark ());
444       if (info != NULL && info->format_version >= 0)
445         {
446           if (!callback (info, *p, user_data))
447             break;
448         }
449     }
450
451   g_free (interfaces);
452
453   for (classtype = G_TYPE_FROM_INSTANCE (object); classtype != 0; classtype = g_type_parent (classtype))
454     {
455       info = g_type_get_qdata (classtype, dbus_g_object_type_dbus_metadata_quark ());
456       if (info != NULL && info->format_version >= 0)
457         {
458           if (!callback (info, classtype, user_data))
459             break;
460         }
461     }
462
463 }
464
465 static gboolean
466 lookup_object_info_cb (const DBusGObjectInfo *info,
467                        GType gtype,
468                        gpointer user_data)
469 {
470   GList **list = (GList **) user_data;
471
472   *list = g_list_prepend (*list, (gpointer) info);
473   return TRUE;
474 }
475
476 static GList *
477 lookup_object_info (GObject *object)
478 {
479   GList *info_list = NULL;
480
481   foreach_object_info (object, lookup_object_info_cb, &info_list);
482
483   return info_list;
484 }
485
486 typedef struct {
487   const char *iface;
488   const DBusGObjectInfo *info;
489   gboolean fallback;
490   GType iface_type;
491 } LookupObjectInfoByIfaceData;
492
493 static gboolean
494 lookup_object_info_by_iface_cb (const DBusGObjectInfo *info,
495                                 GType gtype,
496                                 gpointer user_data)
497 {
498   LookupObjectInfoByIfaceData *lookup_data = (LookupObjectInfoByIfaceData *) user_data;
499
500   /* If interface is not specified, choose the first info */
501   if (lookup_data->fallback && (!lookup_data->iface || strlen (lookup_data->iface) == 0))
502     {
503       lookup_data->info = info;
504       lookup_data->iface_type = gtype;
505     }
506   else if (info->exported_properties && !strcmp (info->exported_properties, lookup_data->iface))
507     {
508       lookup_data->info = info;
509       lookup_data->iface_type = gtype;
510     }
511
512   return !lookup_data->info;
513 }
514
515 static const DBusGObjectInfo *
516 lookup_object_info_by_iface (GObject     *object,
517                              const char  *iface,
518                              gboolean     fallback,
519                              GType       *out_iface_type)
520 {
521   LookupObjectInfoByIfaceData data;
522
523   data.iface = iface;
524   data.info = NULL;
525   data.fallback = fallback;
526   data.iface_type = 0;
527
528   foreach_object_info (object, lookup_object_info_by_iface_cb, &data);
529
530   if (out_iface_type && data.info)
531     *out_iface_type = data.iface_type;
532
533   return data.info;
534 }
535
536 typedef struct {
537     DBusGConnection *connection;
538     gchar *object_path;
539     GObject *object;
540 } ObjectRegistration;
541
542 static void object_registration_object_died (gpointer user_data, GObject *dead);
543
544 static ObjectRegistration *
545 object_registration_new (DBusGConnection *connection,
546                          const gchar *object_path,
547                          GObject *object)
548 {
549   ObjectRegistration *o = g_slice_new0 (ObjectRegistration);
550
551   o->connection = connection;
552   o->object_path = g_strdup (object_path);
553   o->object = object;
554
555   g_object_weak_ref (o->object, object_registration_object_died, o);
556
557   return o;
558 }
559
560 static void
561 object_registration_free (ObjectRegistration *o)
562 {
563   if (o->object != NULL)
564     {
565       GSList *registrations;
566
567       /* Ok, the object is still around; clear out this particular registration
568        * from the registrations list.
569        */
570       registrations = g_object_steal_data (o->object, "dbus_glib_object_registrations");
571       registrations = g_slist_remove (registrations, o);
572
573       if (registrations != NULL)
574         g_object_set_data (o->object, "dbus_glib_object_registrations", registrations);
575
576       g_object_weak_unref (o->object, object_registration_object_died, o);
577     }
578
579   g_free (o->object_path);
580
581   g_slice_free (ObjectRegistration, o);
582 }
583
584 /* Called when the object falls off the bus (e.g. because connection just
585  * closed) */
586 static void
587 object_registration_unregistered (DBusConnection *connection,
588                                   void *user_data)
589 {
590   object_registration_free (user_data);
591 }
592
593 typedef struct
594 {
595   GObject *object;
596   GString *xml;
597   GType gtype;
598   const DBusGObjectInfo *object_info;
599 } DBusGLibWriteIterfaceData;
600
601 typedef struct
602 {
603   GSList *methods;
604   GSList *signals;
605   GSList *properties;
606 } DBusGLibWriteInterfaceValues;
607
608 static void
609 write_interface (gpointer key, gpointer val, gpointer user_data)
610 {
611   const char *name;
612   GSList *methods;
613   GSList *signals;
614   GSList *properties;
615   GString *xml;
616   const DBusGObjectInfo *object_info;
617   DBusGLibWriteIterfaceData *data;
618   DBusGLibWriteInterfaceValues *values;
619
620   name = key;
621
622   values = val;
623   methods = values->methods;
624   signals = values->signals;
625   properties = values->properties;
626
627   data = user_data;
628   xml = data->xml;
629   object_info = data->object_info;
630
631   g_string_append_printf (xml, "  <interface name=\"%s\">\n", name);
632
633   /* FIXME: recurse to parent types ? */
634   for (; methods; methods = methods->next)
635     {
636       DBusGMethodInfo *method;
637       const char *args;
638       method = methods->data;
639
640       g_string_append_printf (xml, "    <method name=\"%s\">\n",
641                               method_name_from_object_info (object_info, method));
642
643       args = method_arg_info_from_object_info (object_info, method);
644
645       while (*args)
646         {
647           const char *name;
648           gboolean arg_in;
649           const char *type;
650           
651           args = arg_iterate (args, &name, &arg_in, NULL, NULL, &type);
652
653           /* FIXME - handle container types */
654           g_string_append_printf (xml, "      <arg name=\"%s\" type=\"%s\" direction=\"%s\"/>\n",
655                                   name, type, arg_in ? "in" : "out");
656
657         }
658       g_string_append (xml, "    </method>\n");
659
660     }
661   g_slist_free (values->methods);
662
663   for (; signals; signals = signals->next)
664     {
665       guint id;
666       guint arg;
667       const char *signame;
668       GSignalQuery query;
669       char *s;
670
671       signame = signals->data;
672
673       s = _dbus_gutils_wincaps_to_uscore (signame);
674       
675       id = g_signal_lookup (s, data->gtype);
676       g_assert (id != 0);
677
678       g_signal_query (id, &query);
679       g_assert (query.return_type == G_TYPE_NONE);
680
681       g_string_append_printf (xml, "    <signal name=\"%s\">\n", signame);
682
683       for (arg = 0; arg < query.n_params; arg++)
684         {
685           char *dbus_type = _dbus_gtype_to_signature (query.param_types[arg]);
686
687           g_assert (dbus_type != NULL);
688
689           g_string_append (xml, "      <arg type=\"");
690           g_string_append (xml, dbus_type);
691           g_string_append (xml, "\"/>\n");
692           g_free (dbus_type);
693         }
694
695       g_string_append (xml, "    </signal>\n");
696       g_free (s);
697     }
698   g_slist_free (values->signals);
699
700   for (; properties; properties = properties->next)
701     {
702       const char *iface;
703       const char *propname;
704       const char *propname_uscore;
705       const char *access_type;
706       GParamSpec *spec;
707       char *dbus_type;
708       gboolean can_set;
709       gboolean can_get;
710       char *s;
711
712       spec = NULL;
713
714       property_iterate (properties->data, object_info->format_version, &iface, &propname, &propname_uscore, &access_type);
715
716       s = lookup_property_name (data->object, name, propname);
717
718       spec = g_object_class_find_property (g_type_class_peek (data->gtype), s);
719       g_assert (spec != NULL);
720       g_free (s);
721       
722       dbus_type = _dbus_gtype_to_signature (G_PARAM_SPEC_VALUE_TYPE (spec));
723       g_assert (dbus_type != NULL);
724
725       can_set = strcmp (access_type, "readwrite") == 0
726                     && ((spec->flags & G_PARAM_WRITABLE) != 0
727                     && (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
728
729       can_get = (spec->flags & G_PARAM_READABLE) != 0;
730
731       if (can_set || can_get)
732         {
733           g_string_append_printf (xml, "    <property name=\"%s\" ", propname);
734           g_string_append (xml, "type=\"");
735           g_string_append (xml, dbus_type);
736           g_string_append (xml, "\" access=\"");
737
738           if (can_set && can_get)
739             g_string_append (xml, "readwrite");
740           else if (can_get)
741             g_string_append (xml, "read");
742           else
743             {
744               g_assert (can_set);
745               g_string_append (xml, "write");
746             }
747           
748           g_string_append (xml, "\"/>\n");
749         }
750       
751       g_free (dbus_type);
752     }
753   g_slist_free (values->properties);
754
755   g_free (values);
756   g_string_append (xml, "  </interface>\n");
757 }
758
759 static DBusGLibWriteInterfaceValues *
760 lookup_values (GHashTable *interfaces, const char *method_interface)
761 {
762   DBusGLibWriteInterfaceValues *values;
763   if ((values = g_hash_table_lookup (interfaces, (gpointer) method_interface)) == NULL)
764     {
765       values = g_new0 (DBusGLibWriteInterfaceValues, 1);
766       g_hash_table_insert (interfaces, (gpointer) method_interface, values);
767     }
768   return values;
769 }
770
771 static void
772 introspect_interfaces (GObject *object, GString *xml)
773 {
774   GList *info_list;
775   const GList *info_list_walk;
776   const DBusGObjectInfo *info;
777   DBusGLibWriteIterfaceData data;
778   int i;
779   GHashTable *interfaces;
780   DBusGLibWriteInterfaceValues *values;
781   const char *propsig;
782
783   info_list = lookup_object_info (object);
784
785   g_assert (info_list != NULL);
786
787   /* Gather a list of all interfaces, indexed into their methods */
788   for (info_list_walk = info_list; info_list_walk != NULL; info_list_walk = g_list_next (info_list_walk))
789     {
790       info = (DBusGObjectInfo *) info_list_walk->data;
791       interfaces = g_hash_table_new (g_str_hash, g_str_equal);
792       
793       g_assert (info != NULL);
794
795       for (i = 0; i < info->n_method_infos; i++)
796         {
797           const char *method_name;
798           const char *method_interface;
799           const char *method_args;
800           const DBusGMethodInfo *method;
801
802           method = &(info->method_infos[i]);
803
804           method_interface = method_interface_from_object_info (info, method);
805           method_name = method_name_from_object_info (info, method);
806           method_args = method_arg_info_from_object_info (info, method);
807
808           values = lookup_values (interfaces, method_interface);
809           values->methods = g_slist_prepend (values->methods, (gpointer) method);
810         }
811
812       propsig = info->exported_signals;
813       while (propsig != NULL && *propsig)
814         {
815           const char *iface;
816           const char *signame;
817
818           propsig = signal_iterate (propsig, &iface, &signame);
819
820           values = lookup_values (interfaces, iface);
821           values->signals = g_slist_prepend (values->signals, (gpointer) signame);
822         }
823
824       propsig = info->exported_properties;
825       while (propsig != NULL && *propsig)
826         {
827           const char *iface;
828           const char *propname;
829           const char *propname_uscore;
830           const char *access_type;
831
832           propsig = property_iterate (propsig, info->format_version, &iface, &propname, &propname_uscore, &access_type);
833
834           values = lookup_values (interfaces, iface);
835           values->properties = g_slist_prepend (values->properties, (gpointer)iface);
836         }
837
838       memset (&data, 0, sizeof (data));
839       data.xml = xml;
840       data.gtype = G_TYPE_FROM_INSTANCE (object);
841       data.object_info = info;
842       data.object = object;
843
844       g_hash_table_foreach (interfaces, write_interface, &data);
845       g_hash_table_destroy (interfaces);
846     }
847
848   g_list_free (info_list);
849 }
850
851 static DBusHandlerResult
852 handle_introspect (DBusConnection *connection,
853                    DBusMessage    *message,
854                    GObject        *object)
855 {
856   GString *xml;
857   unsigned int i;
858   DBusMessage *ret;
859   char **children;
860   
861   if (!dbus_connection_list_registered (connection, 
862                                         dbus_message_get_path (message),
863                                         &children))
864     g_error ("Out of memory");
865   
866   xml = g_string_new (NULL);
867
868   g_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
869   
870   g_string_append (xml, "<node>\n");
871
872   /* We are introspectable, though I guess that was pretty obvious */
873   g_string_append_printf (xml, "  <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE);
874   g_string_append (xml, "    <method name=\"Introspect\">\n");
875   g_string_append_printf (xml, "      <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
876   g_string_append (xml, "    </method>\n");
877   g_string_append (xml, "  </interface>\n");
878
879   /* We support get/set/getall properties */
880   g_string_append_printf (xml, "  <interface name=\"%s\">\n", DBUS_INTERFACE_PROPERTIES);
881   g_string_append (xml, "    <method name=\"Get\">\n");
882   g_string_append_printf (xml, "      <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
883   g_string_append_printf (xml, "      <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
884   g_string_append_printf (xml, "      <arg name=\"value\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_VARIANT_AS_STRING);
885   g_string_append (xml, "    </method>\n");
886   g_string_append (xml, "    <method name=\"Set\">\n");
887   g_string_append_printf (xml, "      <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
888   g_string_append_printf (xml, "      <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
889   g_string_append_printf (xml, "      <arg name=\"value\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_VARIANT_AS_STRING);
890   g_string_append (xml, "    </method>\n");
891   g_string_append (xml, "    <method name=\"GetAll\">\n");
892   g_string_append_printf (xml, "      <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
893   g_string_append_printf (xml, "      <arg name=\"props\" direction=\"out\" type=\"%s\"/>\n",
894                           DBUS_TYPE_ARRAY_AS_STRING
895                           DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
896                             DBUS_TYPE_STRING_AS_STRING
897                             DBUS_TYPE_VARIANT_AS_STRING
898                           DBUS_DICT_ENTRY_END_CHAR_AS_STRING
899                           );
900
901   g_string_append (xml, "    </method>\n");
902   g_string_append (xml, "  </interface>\n");
903   
904   introspect_interfaces (object, xml);
905
906   /* Append child nodes */
907   for (i = 0; children[i]; i++)
908       g_string_append_printf (xml, "  <node name=\"%s\"/>\n",
909                               children[i]);
910   
911   /* Close the XML, and send it to the requesting app */
912   g_string_append (xml, "</node>\n");
913
914   ret = dbus_message_new_method_return (message);
915   if (ret == NULL)
916     g_error ("Out of memory");
917
918   dbus_message_append_args (ret,
919                             DBUS_TYPE_STRING, &xml->str,
920                             DBUS_TYPE_INVALID);
921
922   dbus_connection_send (connection, ret, NULL);
923   dbus_message_unref (ret);
924
925   g_string_free (xml, TRUE);
926
927   dbus_free_string_array (children);
928   
929   return DBUS_HANDLER_RESULT_HANDLED;
930 }
931
932 static DBusMessage*
933 set_object_property (DBusConnection  *connection,
934                      DBusMessage     *message,
935                      DBusMessageIter *iter,
936                      GObject         *object,
937                      GParamSpec      *pspec)
938 {
939   GValue value = { 0, };
940   DBusMessage *ret;
941   DBusMessageIter sub;
942   DBusGValueMarshalCtx context;
943
944   dbus_message_iter_recurse (iter, &sub);
945
946   context.recursion_depth = 0;
947   context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
948   context.proxy = NULL;
949
950   g_value_init (&value, pspec->value_type);
951   if (_dbus_gvalue_demarshal (&context, &sub, &value, NULL))
952     {
953       g_object_set_property (object,
954                              pspec->name,
955                              &value);
956
957       g_value_unset (&value);
958
959       ret = dbus_message_new_method_return (message);
960       if (ret == NULL)
961         g_error ("out of memory");
962     }
963   else
964     {
965       ret = dbus_message_new_error (message,
966                                     DBUS_ERROR_INVALID_ARGS,
967                                     "Argument's D-BUS type can't be converted to a GType");
968       if (ret == NULL)
969         g_error ("out of memory");
970     }
971
972   return ret;
973 }
974
975 static DBusMessage*
976 get_object_property (DBusConnection *connection,
977                      DBusMessage    *message,
978                      GObject        *object,
979                      GParamSpec     *pspec)
980 {
981   GType value_gtype;
982   GValue value = {0, };
983   gchar *variant_sig;
984   DBusMessage *ret;
985   DBusMessageIter iter, subiter;
986
987   ret = dbus_message_new_method_return (message);
988   if (ret == NULL)
989     g_error ("out of memory");
990
991
992   g_value_init (&value, pspec->value_type);
993   g_object_get_property (object, pspec->name, &value);
994
995   variant_sig = _dbus_gvalue_to_signature (&value);
996   if (variant_sig == NULL)
997     {
998       value_gtype = G_VALUE_TYPE (&value);
999       g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
1000       g_value_unset (&value);
1001       return ret;
1002     }
1003
1004   dbus_message_iter_init_append (ret, &iter);
1005   if (!dbus_message_iter_open_container (&iter,
1006                                          DBUS_TYPE_VARIANT,
1007                                          variant_sig,
1008                                          &subiter))
1009     {
1010       g_free (variant_sig);
1011       g_value_unset (&value);
1012       return ret;
1013     }
1014
1015   if (!_dbus_gvalue_marshal (&subiter, &value))
1016     {
1017       dbus_message_unref (ret);
1018       ret = dbus_message_new_error (message,
1019                                     DBUS_ERROR_UNKNOWN_METHOD,
1020                                     "Can't convert GType of object property to a D-BUS type");
1021     }
1022
1023   dbus_message_iter_close_container (&iter, &subiter);
1024
1025   g_value_unset (&value);
1026   g_free (variant_sig);
1027
1028   return ret;
1029 }
1030
1031 #define SHADOW_PROP_QUARK (dbus_g_object_type_dbus_shadow_property_quark ())
1032
1033 static GQuark
1034 dbus_g_object_type_dbus_shadow_property_quark (void)
1035 {
1036   static GQuark quark;
1037
1038   if (!quark)
1039     quark = g_quark_from_static_string ("DBusGObjectTypeDBusShadowPropertyQuark");
1040   return quark;
1041 }
1042
1043 /* Look for shadow properties on the given interface first, otherwise
1044  * just return the original property name.  This allows implementations to
1045  * get around the glib limitation of unique property names among all
1046  * GInterfaces by registering a "shadow" property name that the get/set
1047  * request will be redirected to.
1048  *
1049  * Shadow property data is stored as qdata on each GInterface.  If there
1050  * is no interface info, or there is no registered shadow property, just
1051  * return the original property name.
1052  */
1053 static char *
1054 lookup_property_name (GObject    *object,
1055                       const char *wincaps_propiface,
1056                       const char *requested_propname)
1057 {
1058   const DBusGObjectInfo *object_info;
1059   GHashTable *shadow_props;
1060   char *shadow_prop_name = NULL, *uscore_name;
1061   GType iface_type = 0;
1062
1063   g_assert (wincaps_propiface != NULL);
1064   g_assert (requested_propname != NULL);
1065
1066   uscore_name = _dbus_gutils_wincaps_to_uscore (requested_propname);
1067
1068   object_info = lookup_object_info_by_iface (object, wincaps_propiface, FALSE, &iface_type);
1069   if (!object_info)
1070     return uscore_name;
1071
1072   shadow_props = (GHashTable *) g_type_get_qdata (iface_type, SHADOW_PROP_QUARK);
1073   if (shadow_props)
1074     {
1075       shadow_prop_name = g_strdup (g_hash_table_lookup (shadow_props, requested_propname));
1076       if (shadow_prop_name)
1077         g_free (uscore_name);
1078     }
1079
1080   return shadow_prop_name ? shadow_prop_name : uscore_name;
1081 }
1082
1083 /**
1084  * dbus_g_object_type_register_shadow_property:
1085  * @iface_type: #GType for the #GInterface
1086  * @dbus_prop_name: D-Bus property name (as specified in the introspection data)
1087  *  to override with the shadow property name (as specified in the GType's
1088  *  initialization function, ie glib-style)
1089  * @shadow_prop_name: property name which should override the shadow property
1090  *
1091  * Registers a new property name @shadow_prop_name that overrides the
1092  * @dbus_prop_name in D-Bus property get/set requests.  Since all properties for
1093  * all interfaces implemented by a GObject exist in the same namespace, this
1094  * allows implementations to use the same property name in two or more D-Bus
1095  * interfaces implemented by the same GObject, as long as one of those D-Bus
1096  * interface properties is registered with a shadow property name.
1097  *
1098  * For example, if both org.foobar.Baz.InterfaceA and org.foobar.Baz.InterfaceB
1099  * have a D-Bus property called "Bork", the developer assigns a shadow property
1100  * name to the conflicting property name in one or both of these GInterfaces to
1101  * resolve the conflict.  Assume the GInterface implementing
1102  * org.foobar.Baz.InterfaceA registers a shadow property called "a-bork", while
1103  * the GInterface implementing org.foobar.Baz.InterfaceB registers a shadow
1104  * property called "b-bork".  The GObject implementing both these GInterfaces
1105  * would then use #g_object_class_override_property() to implement both
1106  * "a-bork" and "b-bork" and D-Bus requests for "Bork" on either D-Bus interface
1107  * will not conflict.
1108  */
1109 void
1110 dbus_g_object_type_register_shadow_property (GType      iface_type,
1111                                              const char *dbus_prop_name,
1112                                              const char *shadow_prop_name)
1113 {
1114   GHashTable *shadow_props;
1115
1116   g_return_if_fail (G_TYPE_IS_CLASSED (iface_type) || G_TYPE_IS_INTERFACE (iface_type));
1117   g_return_if_fail (dbus_prop_name != NULL);
1118   g_return_if_fail (shadow_prop_name != NULL);
1119
1120   shadow_props = (GHashTable *) g_type_get_qdata (iface_type, SHADOW_PROP_QUARK);
1121   if (!shadow_props)
1122     {
1123       shadow_props = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1124       g_type_set_qdata (iface_type,
1125                         dbus_g_object_type_dbus_shadow_property_quark (),
1126                         shadow_props);
1127     }
1128
1129   g_assert (shadow_props);
1130   g_hash_table_insert (shadow_props, g_strdup (dbus_prop_name), g_strdup (shadow_prop_name));
1131 }
1132
1133 static DBusMessage*
1134 get_all_object_properties (DBusConnection        *connection,
1135                            DBusMessage           *message,
1136                            const DBusGObjectInfo *object_info,
1137                            const char            *wincaps_propiface,
1138                            GObject               *object)
1139 {
1140   DBusMessage *ret;
1141   DBusMessageIter iter_ret;
1142   DBusMessageIter iter_dict;
1143   DBusMessageIter iter_dict_entry;
1144   DBusMessageIter iter_dict_value;
1145   const char *p;
1146   char *uscore_propname;
1147
1148   ret = dbus_message_new_method_return (message);
1149   if (ret == NULL)
1150     goto oom;
1151
1152   dbus_message_iter_init_append (ret, &iter_ret);
1153
1154   if (!dbus_message_iter_open_container (&iter_ret,
1155                                          DBUS_TYPE_ARRAY,
1156                                          DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1157                                          DBUS_TYPE_STRING_AS_STRING
1158                                          DBUS_TYPE_VARIANT_AS_STRING
1159                                          DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1160                                          &iter_dict))
1161     goto oom;
1162
1163   p = object_info->exported_properties;
1164   while (p != NULL && *p != '\0')
1165     {
1166       const char *prop_ifname;
1167       const char *prop_name;
1168       const char *prop_uscored;
1169       const char *access_flags;
1170       GParamSpec *pspec;
1171       GType value_gtype;
1172       GValue value = {0, };
1173       gchar *variant_sig;
1174
1175       p = property_iterate (p, object_info->format_version, &prop_ifname, &prop_name, &prop_uscored, &access_flags);
1176
1177       uscore_propname = lookup_property_name (object, wincaps_propiface, prop_name);
1178
1179       pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), uscore_propname);
1180       if (pspec == NULL)
1181         {
1182           g_warning ("introspection data references non-existing property %s", uscore_propname);
1183           g_free (uscore_propname);
1184           continue;
1185         }
1186
1187       g_free (uscore_propname);
1188
1189       g_value_init (&value, pspec->value_type);
1190       g_object_get_property (object, pspec->name, &value);
1191
1192       variant_sig = _dbus_gvalue_to_signature (&value);
1193       if (variant_sig == NULL)
1194         {
1195           value_gtype = G_VALUE_TYPE (&value);
1196           g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
1197           g_value_unset (&value);
1198           continue;
1199         }
1200
1201       if (!dbus_message_iter_open_container (&iter_dict,
1202                                              DBUS_TYPE_DICT_ENTRY,
1203                                              NULL,
1204                                              &iter_dict_entry))
1205         goto oom;
1206       if (!dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &prop_name))
1207         goto oom;
1208
1209       if (!dbus_message_iter_open_container (&iter_dict_entry,
1210                                              DBUS_TYPE_VARIANT,
1211                                              variant_sig,
1212                                              &iter_dict_value))
1213         goto oom;
1214
1215       if (!_dbus_gvalue_marshal (&iter_dict_value, &value))
1216         goto oom;
1217
1218       if (!dbus_message_iter_close_container (&iter_dict_entry,
1219                                               &iter_dict_value))
1220         goto oom;
1221       if (!dbus_message_iter_close_container (&iter_dict, &iter_dict_entry))
1222         goto oom;
1223
1224       g_value_unset (&value);
1225       g_free (variant_sig);
1226   }
1227
1228   if (!dbus_message_iter_close_container (&iter_ret, &iter_dict))
1229     goto oom;
1230
1231   return ret;
1232
1233  oom:
1234   g_error ("out of memory");
1235 }
1236
1237 static gboolean
1238 lookup_object_and_method (GObject      *object,
1239                           DBusMessage  *message,
1240                           const DBusGObjectInfo **object_ret,
1241                           const DBusGMethodInfo **method_ret)
1242 {
1243   const char *interface;
1244   const char *member;
1245   const char *signature;
1246   GList *info_list;
1247   const GList *info_list_walk;
1248   const DBusGObjectInfo *info;
1249   int i;
1250
1251   interface = dbus_message_get_interface (message);
1252   member = dbus_message_get_member (message);
1253   signature = dbus_message_get_signature (message);
1254
1255   info_list = lookup_object_info (object);
1256   
1257   for (info_list_walk = info_list; info_list_walk != NULL; info_list_walk = g_list_next (info_list_walk))
1258     {
1259       info = (DBusGObjectInfo *) info_list_walk->data;
1260       *object_ret = info;
1261
1262       for (i = 0; i < info->n_method_infos; i++)
1263         {
1264           const char *expected_member;
1265           const char *expected_interface;
1266           char *expected_signature;
1267           const DBusGMethodInfo *method;
1268
1269           method = &(info->method_infos[i]);
1270
1271           /* Check method interface/name and input signature */ 
1272           expected_interface = method_interface_from_object_info (*object_ret, method);
1273           expected_member = method_name_from_object_info (*object_ret, method);
1274           expected_signature = method_input_signature_from_object_info (*object_ret, method);
1275
1276           if ((interface == NULL
1277               || strcmp (expected_interface, interface) == 0)
1278               && strcmp (expected_member, member) == 0
1279               && strcmp (expected_signature, signature) == 0)
1280             {
1281               g_free (expected_signature);
1282               *method_ret = method;
1283               g_list_free (info_list);
1284               return TRUE;
1285             }
1286             g_free (expected_signature);
1287         }
1288     }
1289
1290   if (info_list)
1291     g_list_free (info_list);
1292
1293   return FALSE;
1294 }
1295
1296 static char *
1297 gerror_domaincode_to_dbus_error_name (const DBusGObjectInfo *object_info,
1298                                       const char *msg_interface,
1299                                       GQuark domain, gint code)
1300 {
1301   const char *domain_str;
1302   const char *code_str;
1303   GString *dbus_error_name;
1304
1305   domain_str = object_error_domain_prefix_from_object_info (object_info);
1306   code_str = object_error_code_from_object_info (object_info, domain, code);
1307
1308   if (!domain_str || !code_str)
1309     {
1310       DBusGErrorInfo *info;
1311
1312       g_static_rw_lock_reader_lock (&globals_lock);
1313
1314       if (error_metadata != NULL)
1315         info = g_datalist_id_get_data (&error_metadata, domain);
1316       else
1317         info = NULL;
1318
1319       g_static_rw_lock_reader_unlock (&globals_lock);
1320
1321       if (info)
1322         {
1323           GEnumValue *value;
1324           GEnumClass *klass;
1325
1326           klass = g_type_class_ref (info->code_enum);
1327           value = g_enum_get_value (klass, code);
1328           g_type_class_unref (klass);
1329
1330           domain_str = info->default_iface;
1331           code_str = value->value_nick;
1332         }
1333     }
1334
1335   if (!domain_str)
1336     domain_str = msg_interface;
1337
1338   if (!domain_str || !code_str)
1339     {
1340       const char *domain_string;
1341       /* If we can't map it sensibly, make up an error name */
1342       
1343       dbus_error_name = g_string_new ("org.freedesktop.DBus.GLib.UnmappedError.");
1344
1345       domain_string = g_quark_to_string (domain);
1346       if (domain_string != NULL)
1347         {
1348           char *uscored = uscore_to_wincaps (domain_string);
1349           g_string_append (dbus_error_name, uscored);
1350           g_string_append_c (dbus_error_name, '.');
1351           g_free (uscored);
1352         }
1353
1354       g_string_append_printf (dbus_error_name, "Code%d", code);
1355     }
1356   else
1357     {
1358       gchar *code_str_wincaps;
1359       dbus_error_name = g_string_new (domain_str);
1360       g_string_append_c (dbus_error_name, '.');
1361       /* We can't uppercase here for backwards compatibility
1362        * reasons; if someone had a lowercase enumeration value,
1363        * previously we'd just send it across unaltered.
1364        */
1365       code_str_wincaps = uscore_to_wincaps_full (code_str, FALSE);
1366       g_string_append (dbus_error_name, code_str_wincaps);
1367       g_free (code_str_wincaps);
1368     }
1369
1370   return g_string_free (dbus_error_name, FALSE);
1371 }
1372
1373 static DBusMessage *
1374 gerror_to_dbus_error_message (const DBusGObjectInfo *object_info,
1375                               DBusMessage           *message,
1376                               const GError          *error)
1377 {
1378   DBusMessage *reply;
1379
1380   if (!error)
1381     {
1382       char *error_msg;
1383       
1384       error_msg = g_strdup_printf ("Method invoked for %s returned FALSE but did not set error", dbus_message_get_member (message));
1385       reply = dbus_message_new_error (message, "org.freedesktop.DBus.GLib.ErrorError", error_msg);
1386       g_free (error_msg);
1387     }
1388   else
1389     {
1390       if (error->domain == DBUS_GERROR)
1391         {
1392           const gchar *name = DBUS_ERROR_FAILED;
1393
1394           switch (error->code)
1395             {
1396             case DBUS_GERROR_FAILED:
1397               name = DBUS_ERROR_FAILED;
1398               break;
1399             case DBUS_GERROR_NO_MEMORY:
1400               name = DBUS_ERROR_NO_MEMORY;
1401               break;
1402             case DBUS_GERROR_SERVICE_UNKNOWN:
1403               name = DBUS_ERROR_SERVICE_UNKNOWN;
1404               break;
1405             case DBUS_GERROR_NAME_HAS_NO_OWNER:
1406               name = DBUS_ERROR_NAME_HAS_NO_OWNER;
1407               break;
1408             case DBUS_GERROR_NO_REPLY:
1409               name = DBUS_ERROR_NO_REPLY;
1410               break;
1411             case DBUS_GERROR_IO_ERROR:
1412               name = DBUS_ERROR_IO_ERROR;
1413               break;
1414             case DBUS_GERROR_BAD_ADDRESS:
1415               name = DBUS_ERROR_BAD_ADDRESS;
1416               break;
1417             case DBUS_GERROR_NOT_SUPPORTED:
1418               name = DBUS_ERROR_NOT_SUPPORTED;
1419               break;
1420             case DBUS_GERROR_LIMITS_EXCEEDED:
1421               name = DBUS_ERROR_LIMITS_EXCEEDED;
1422               break;
1423             case DBUS_GERROR_ACCESS_DENIED:
1424               name = DBUS_ERROR_ACCESS_DENIED;
1425               break;
1426             case DBUS_GERROR_AUTH_FAILED:
1427               name = DBUS_ERROR_AUTH_FAILED;
1428               break;
1429             case DBUS_GERROR_NO_SERVER:
1430               name = DBUS_ERROR_NO_SERVER;
1431               break;
1432             case DBUS_GERROR_TIMEOUT:
1433               name = DBUS_ERROR_TIMEOUT;
1434               break;
1435             case DBUS_GERROR_NO_NETWORK:
1436               name = DBUS_ERROR_NO_NETWORK;
1437               break;
1438             case DBUS_GERROR_ADDRESS_IN_USE:
1439               name = DBUS_ERROR_ADDRESS_IN_USE;
1440               break;
1441             case DBUS_GERROR_DISCONNECTED:
1442               name = DBUS_ERROR_DISCONNECTED;
1443               break;
1444             case DBUS_GERROR_INVALID_ARGS:
1445               name = DBUS_ERROR_INVALID_ARGS;
1446               break;
1447             case DBUS_GERROR_FILE_NOT_FOUND:
1448               name = DBUS_ERROR_FILE_NOT_FOUND;
1449               break;
1450             case DBUS_GERROR_REMOTE_EXCEPTION:
1451               name = dbus_g_error_get_name ((GError*) error);
1452               break;
1453             }
1454
1455           reply = dbus_message_new_error (message, name, error->message);
1456         }
1457       else
1458         {
1459           char *error_name;
1460           error_name = gerror_domaincode_to_dbus_error_name (object_info,
1461                                                              dbus_message_get_interface (message),
1462                                                              error->domain, error->code);
1463           reply = dbus_message_new_error (message, error_name, error->message);
1464           g_free (error_name); 
1465         }
1466     }
1467   return reply;
1468 }
1469
1470 /**
1471  * SECTION:dbus-gmethod
1472  * @short_description: GMethod Info & Invocation
1473  * @see_also: #DBusGMessage
1474  * @stability: Stable
1475  *
1476  * These types are used to call methods on #GObject objects.
1477  */
1478
1479 /**
1480  * The context of an asynchronous method call.  See dbus_g_method_return() and
1481  * dbus_g_method_return_error().
1482  */
1483 struct _DBusGMethodInvocation {
1484   DBusGConnection *connection; /**< The connection */
1485   DBusGMessage *message; /**< The message which generated the method call */
1486   const DBusGObjectInfo *object; /**< The object the method was called on */
1487   const DBusGMethodInfo *method; /**< The method called */
1488   gboolean send_reply;
1489 };
1490
1491 static DBusHandlerResult
1492 invoke_object_method (GObject         *object,
1493                       const DBusGObjectInfo *object_info,
1494                       const DBusGMethodInfo *method,
1495                       DBusConnection  *connection,
1496                       DBusMessage     *message)
1497 {
1498   gboolean had_error, is_async, send_reply;
1499   GError *gerror;
1500   GValueArray *value_array;
1501   GValue return_value = {0,};
1502   GClosure closure;
1503   char *in_signature;
1504   GArray *out_param_values = NULL;
1505   GValueArray *out_param_gvalues = NULL;
1506   int out_param_count;
1507   int out_param_pos, out_param_gvalue_pos;
1508   DBusHandlerResult result;
1509   DBusMessage *reply = NULL;
1510   gboolean have_retval;
1511   gboolean retval_signals_error;
1512   gboolean retval_is_synthetic;
1513   gboolean retval_is_constant;
1514   const char *arg_metadata;
1515
1516   gerror = NULL;
1517
1518   /* This flag says whether invokee is handed a special DBusGMethodInvocation structure,
1519    * instead of being required to fill out all return values in the context of the function.
1520    * Some additional data is also exposed, such as the message sender.
1521    */
1522   is_async = strcmp (string_table_lookup (get_method_data (object_info, method), 2), "A") == 0;
1523   
1524   /* Messages can be sent with a flag that says "I don't need a reply".  This is an optimization
1525    * normally, but in the context of the system bus it's important to not send a reply
1526    * to these kinds of messages, because they will be unrequested replies, and thus subject
1527    * to denial and logging.  We don't want to fill up logs.
1528    * http://bugs.freedesktop.org/show_bug.cgi?id=19441
1529    */
1530   send_reply = !dbus_message_get_no_reply (message); 
1531
1532   have_retval = FALSE;
1533   retval_signals_error = FALSE;
1534   retval_is_synthetic = FALSE;
1535   retval_is_constant = FALSE;
1536
1537   /* This is evil.  We do this to work around the fact that
1538    * the generated glib marshallers check a flag in the closure object
1539    * which we don't care about.  We don't need/want to create
1540    * a new closure for each invocation.
1541    */
1542   memset (&closure, 0, sizeof (closure));
1543
1544   in_signature = method_input_signature_from_object_info (object_info, method); 
1545   
1546   /* Convert method IN parameters to GValueArray */
1547   {
1548     GArray *types_array;
1549     guint n_params;
1550     const GType *types;
1551     DBusGValueMarshalCtx context;
1552     GError *error = NULL;
1553     
1554     context.recursion_depth = 0;
1555     context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
1556     context.proxy = NULL;
1557
1558     types_array = _dbus_gtypes_from_arg_signature (in_signature, FALSE);
1559     n_params = types_array->len;
1560     types = (const GType*) types_array->data;
1561
1562     value_array = _dbus_gvalue_demarshal_message (&context, message, n_params, types, &error);
1563     if (value_array == NULL)
1564       {
1565         g_free (in_signature); 
1566         g_array_free (types_array, TRUE);
1567         reply = dbus_message_new_error (message, "org.freedesktop.DBus.GLib.ErrorError", error->message);
1568         dbus_connection_send (connection, reply, NULL);
1569         dbus_message_unref (reply);
1570         g_error_free (error);
1571         return DBUS_HANDLER_RESULT_HANDLED;
1572       }
1573     g_array_free (types_array, TRUE);
1574   }
1575
1576   /* Prepend object as first argument */ 
1577   g_value_array_prepend (value_array, NULL);
1578   g_value_init (g_value_array_get_nth (value_array, 0), G_TYPE_OBJECT);
1579   g_value_set_object (g_value_array_get_nth (value_array, 0), object);
1580   
1581   if (is_async)
1582     {
1583       GValue context_value = {0,};
1584       DBusGMethodInvocation *context;
1585       context = g_new (DBusGMethodInvocation, 1);
1586       context->connection = dbus_g_connection_ref (DBUS_G_CONNECTION_FROM_CONNECTION (connection));
1587       context->message = dbus_g_message_ref (DBUS_G_MESSAGE_FROM_MESSAGE (message));
1588       context->object = object_info;
1589       context->method = method;
1590       context->send_reply = send_reply;
1591       g_value_init (&context_value, G_TYPE_POINTER);
1592       g_value_set_pointer (&context_value, context);
1593       g_value_array_append (value_array, &context_value);
1594     }
1595   else
1596     {
1597       RetvalType retval;
1598       gboolean arg_in;
1599       gboolean arg_const;
1600       const char *argsig;
1601
1602       arg_metadata = method_arg_info_from_object_info (object_info, method);
1603       
1604       /* Count number of output parameters, and look for a return value */
1605       out_param_count = 0;
1606       while (*arg_metadata)
1607         {
1608           arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, &arg_const, &retval, &argsig);
1609           if (arg_in)
1610             continue;
1611           if (retval != RETVAL_NONE)
1612             {
1613               DBusSignatureIter tmp_sigiter;
1614               /* This is the function return value */
1615               g_assert (!have_retval);
1616               have_retval = TRUE;
1617               retval_is_synthetic = FALSE;
1618
1619               switch (retval)
1620                 {
1621                 case RETVAL_NONE:
1622                   g_assert_not_reached ();
1623                   break;
1624                 case RETVAL_NOERROR:
1625                   retval_signals_error = FALSE;
1626                   break;
1627                 case RETVAL_ERROR:
1628                   retval_signals_error = TRUE;
1629                   break;
1630                 }
1631
1632               retval_is_constant = arg_const;
1633
1634               /* Initialize our return GValue with the specified type */
1635               dbus_signature_iter_init (&tmp_sigiter, argsig);
1636               g_value_init (&return_value, _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE));
1637             }
1638           else
1639             {
1640               /* It's a regular output value */
1641               out_param_count++;
1642             }
1643         }
1644
1645       /* For compatibility, if we haven't found a return value, we assume
1646        * the function returns a gboolean for signalling an error
1647        * (and therefore also takes a GError).  We also note that it
1648        * is a "synthetic" return value; i.e. we aren't going to be
1649        * sending it over the bus, it's just to signal an error.
1650        */
1651       if (!have_retval)
1652         {
1653           have_retval = TRUE;
1654           retval_is_synthetic = TRUE;
1655           retval_signals_error = TRUE;
1656           g_value_init (&return_value, G_TYPE_BOOLEAN);
1657         }
1658
1659       /* Create an array to store the actual values of OUT parameters
1660        * (other than the real function return, if any).  Then, create
1661        * a GValue boxed POINTER to each of those values, and append to
1662        * the invocation, so the method can return the OUT parameters.
1663        */
1664       out_param_values = g_array_sized_new (FALSE, TRUE, sizeof (GTypeCValue), out_param_count);
1665
1666       /* We have a special array of GValues for toplevel GValue return
1667        * types.
1668        */
1669       out_param_gvalues = g_value_array_new (out_param_count);
1670       out_param_pos = 0;
1671       out_param_gvalue_pos = 0;
1672
1673       /* Reset argument metadata pointer */
1674       arg_metadata = method_arg_info_from_object_info (object_info, method);
1675       
1676       /* Iterate over output arguments again, this time allocating space for
1677        * them as appopriate.
1678        */
1679       while (*arg_metadata)
1680         {
1681           GValue value = {0, };
1682           GTypeCValue storage;
1683           DBusSignatureIter tmp_sigiter;
1684           GType current_gtype;
1685
1686           arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, NULL, &retval, &argsig);
1687           /* Skip over input arguments and the return value, if any */
1688           if (arg_in || retval != RETVAL_NONE)
1689             continue;
1690
1691           dbus_signature_iter_init (&tmp_sigiter, argsig);
1692           current_gtype = _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE);
1693
1694           g_value_init (&value, G_TYPE_POINTER);
1695
1696           /* We special case variants to make method invocation a bit nicer */
1697           if (current_gtype != G_TYPE_VALUE)
1698             {
1699               memset (&storage, 0, sizeof (storage));
1700               g_array_append_val (out_param_values, storage);
1701               g_value_set_pointer (&value, &(g_array_index (out_param_values, GTypeCValue, out_param_pos)));
1702               out_param_pos++;
1703             }
1704           else
1705             {
1706               g_value_array_append (out_param_gvalues, NULL);
1707               g_value_set_pointer (&value, out_param_gvalues->values + out_param_gvalue_pos);
1708               out_param_gvalue_pos++;
1709             }
1710           g_value_array_append (value_array, &value);
1711         }
1712     }
1713
1714   /* Append GError as final argument if necessary */
1715   if (retval_signals_error)
1716     {
1717       g_assert (have_retval);
1718       g_value_array_append (value_array, NULL);
1719       g_value_init (g_value_array_get_nth (value_array, value_array->n_values - 1), G_TYPE_POINTER);
1720       g_value_set_pointer (g_value_array_get_nth (value_array, value_array->n_values - 1), &gerror);
1721     }
1722   
1723   /* Actually invoke method */
1724   method->marshaller (&closure, have_retval ? &return_value : NULL,
1725                       value_array->n_values,
1726                       value_array->values,
1727                       NULL, method->function);
1728   if (is_async)
1729     {
1730       result = DBUS_HANDLER_RESULT_HANDLED;
1731       goto done;
1732     }
1733   if (retval_signals_error)
1734     had_error = _dbus_gvalue_signals_error (&return_value);
1735   else
1736     had_error = FALSE;
1737
1738   if (!had_error)
1739     {
1740       DBusMessageIter iter;
1741
1742       /* Careful here - there are two major cases in this section of the code.
1743        * If send_reply is TRUE, we're constructing a dbus message and freeing
1744        * the return values.  If it's FALSE, then we just need to free the
1745        * values.
1746        */
1747       if (send_reply)
1748         {
1749           reply = dbus_message_new_method_return (message);
1750           if (reply == NULL)
1751             goto nomem;
1752
1753           /* Append output arguments to reply */
1754           dbus_message_iter_init_append (reply, &iter);
1755         }
1756
1757       /* First, append the return value, unless it's synthetic */
1758       if (have_retval && !retval_is_synthetic)
1759         { 
1760           if (send_reply && !_dbus_gvalue_marshal (&iter, &return_value))
1761             goto nomem;
1762           if (!retval_is_constant)
1763             g_value_unset (&return_value);
1764         }
1765
1766       /* Grab the argument metadata and iterate over it */
1767       arg_metadata = method_arg_info_from_object_info (object_info, method);
1768       
1769       /* Now append any remaining return values */
1770       out_param_pos = 0;
1771       out_param_gvalue_pos = 0;
1772       while (*arg_metadata)
1773         {
1774           GValue gvalue = {0, };
1775           const char *arg_name;
1776           gboolean arg_in;
1777           gboolean constval;
1778           RetvalType retval;
1779           const char *arg_signature;
1780           DBusSignatureIter argsigiter;
1781
1782           do
1783             {
1784               /* Iterate over only output values; skip over input
1785                  arguments and the return value */
1786               arg_metadata = arg_iterate (arg_metadata, &arg_name, &arg_in, &constval, &retval, &arg_signature);
1787             }
1788           while ((arg_in || retval != RETVAL_NONE) && *arg_metadata);
1789
1790           /* If the last argument we saw was input or the return
1791            * value, we must be done iterating over output arguments.
1792            */
1793           if (arg_in || retval != RETVAL_NONE)
1794             break;
1795
1796           dbus_signature_iter_init (&argsigiter, arg_signature);
1797           
1798           g_value_init (&gvalue, _dbus_gtype_from_signature_iter (&argsigiter, FALSE));
1799           if (G_VALUE_TYPE (&gvalue) != G_TYPE_VALUE)
1800             {
1801               if (!_dbus_gvalue_take (&gvalue,
1802                                      &(g_array_index (out_param_values, GTypeCValue, out_param_pos))))
1803                 g_assert_not_reached ();
1804               out_param_pos++;
1805             }
1806           else
1807             {
1808               g_value_set_static_boxed (&gvalue, out_param_gvalues->values + out_param_gvalue_pos);
1809               out_param_gvalue_pos++;
1810             }
1811               
1812           if (send_reply && !_dbus_gvalue_marshal (&iter, &gvalue))
1813             goto nomem;
1814           /* Here we actually free the allocated value; we
1815            * took ownership of it with _dbus_gvalue_take, unless
1816            * an annotation has specified this value as constant.
1817            */
1818           if (!constval)
1819             g_value_unset (&gvalue);
1820         }
1821     }
1822   else if (send_reply)
1823     reply = gerror_to_dbus_error_message (object_info, message, gerror);
1824
1825   if (reply)
1826     {
1827       dbus_connection_send (connection, reply, NULL);
1828       dbus_message_unref (reply);
1829     }
1830
1831   result = DBUS_HANDLER_RESULT_HANDLED;
1832  done:
1833   g_free (in_signature);
1834   if (!is_async)
1835     {
1836       g_array_free (out_param_values, TRUE);
1837       g_value_array_free (out_param_gvalues);
1838     }
1839
1840   if (gerror != NULL)
1841     g_clear_error (&gerror);
1842
1843   g_value_array_free (value_array);
1844   return result;
1845  nomem:
1846   result = DBUS_HANDLER_RESULT_NEED_MEMORY;
1847   goto done;
1848 }
1849
1850 static gboolean
1851 check_property_access (DBusConnection  *connection,
1852                        DBusMessage     *message,
1853                        GObject         *object,
1854                        const char      *wincaps_propiface,
1855                        const char      *requested_propname,
1856                        const char      *uscore_propname,
1857                        gboolean         is_set)
1858 {
1859   const DBusGObjectInfo *object_info;
1860   const char *access_type;
1861   DBusMessage *ret;
1862
1863   if (!is_set && !disable_legacy_property_access)
1864     return TRUE;
1865
1866   object_info = lookup_object_info_by_iface (object, wincaps_propiface, TRUE, NULL);
1867   if (!object_info)
1868     {
1869       ret = dbus_message_new_error_printf (message,
1870                                            DBUS_ERROR_ACCESS_DENIED,
1871                                            "Interface \"%s\" isn't exported (or may not exist), can't access property \"%s\"",
1872                                            wincaps_propiface,
1873                                            requested_propname);
1874       dbus_connection_send (connection, ret, NULL);
1875       dbus_message_unref (ret);
1876       return FALSE;
1877     }
1878
1879   /* Try both forms of property names: "foo_bar" or "FooBar"; for historical
1880    * reasons we accept both.
1881    */
1882   if (object_info
1883       && !(property_info_from_object_info (object_info, wincaps_propiface, requested_propname, &access_type)
1884            || property_info_from_object_info (object_info, wincaps_propiface, uscore_propname, &access_type)))
1885     {
1886       ret = dbus_message_new_error_printf (message,
1887                                            DBUS_ERROR_ACCESS_DENIED,
1888                                            "Property \"%s\" of interface \"%s\" isn't exported (or may not exist)",
1889                                            requested_propname,
1890                                            wincaps_propiface);
1891       dbus_connection_send (connection, ret, NULL);
1892       dbus_message_unref (ret);
1893       return FALSE;
1894     }
1895
1896   if (strcmp (access_type, "readwrite") == 0)
1897     return TRUE;
1898   else if (is_set ? strcmp (access_type, "read") == 0
1899              : strcmp (access_type, "write") == 0)
1900     {
1901        ret = dbus_message_new_error_printf (message,
1902                                            DBUS_ERROR_ACCESS_DENIED,
1903                                            "Property \"%s\" of interface \"%s\" is not %s",
1904                                            requested_propname,
1905                                            wincaps_propiface,
1906                                            is_set ? "settable" : "readable");
1907       dbus_connection_send (connection, ret, NULL);
1908       dbus_message_unref (ret);
1909       return FALSE;
1910     }
1911   return TRUE;
1912 }
1913
1914 static DBusHandlerResult
1915 object_registration_message (DBusConnection  *connection,
1916                              DBusMessage     *message,
1917                              void            *user_data)
1918 {
1919   GParamSpec *pspec;
1920   GObject *object;
1921   gboolean setter;
1922   gboolean getter;
1923   gboolean getall;
1924   char *s;
1925   const char *requested_propname;
1926   const char *wincaps_propiface;
1927   DBusMessageIter iter;
1928   const DBusGMethodInfo *method;
1929   const DBusGObjectInfo *object_info;
1930   DBusMessage *ret;
1931   ObjectRegistration *o;
1932
1933   o = user_data;
1934   object = G_OBJECT (o->object);
1935
1936   if (dbus_message_is_method_call (message,
1937                                    DBUS_INTERFACE_INTROSPECTABLE,
1938                                    "Introspect"))
1939     return handle_introspect (connection, message, object);
1940
1941   /* Try the metainfo, which lets us invoke methods */
1942   object_info = NULL;
1943   if (lookup_object_and_method (object, message, &object_info, &method))
1944     return invoke_object_method (object, object_info, method, connection, message);
1945
1946   /* If no metainfo, we can still do properties and signals
1947    * via standard GLib introspection.  Note we do now check
1948    * property access against the metainfo if available.
1949    */
1950   getter = FALSE;
1951   setter = FALSE;
1952   getall = FALSE;
1953   if (dbus_message_is_method_call (message,
1954                                    DBUS_INTERFACE_PROPERTIES,
1955                                    "Get"))
1956     getter = TRUE;
1957   else if (dbus_message_is_method_call (message,
1958                                         DBUS_INTERFACE_PROPERTIES,
1959                                         "Set"))
1960     setter = TRUE;
1961   else if (dbus_message_is_method_call (message,
1962                                    DBUS_INTERFACE_PROPERTIES,
1963                                    "GetAll"))
1964     getall = TRUE;
1965
1966   if (!(setter || getter || getall))
1967     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1968
1969   ret = NULL;
1970
1971   dbus_message_iter_init (message, &iter);
1972
1973   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
1974     {
1975       g_warning ("Property get or set does not have an interface string as first arg\n");
1976       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1977     }
1978
1979   dbus_message_iter_get_basic (&iter, &wincaps_propiface);
1980   dbus_message_iter_next (&iter);
1981
1982   if (getall)
1983     {
1984       object_info = lookup_object_info_by_iface (object, wincaps_propiface, TRUE, NULL);
1985       if (object_info != NULL)
1986           ret = get_all_object_properties (connection, message, object_info, wincaps_propiface, object);
1987       else
1988           return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1989     }
1990   else if (getter || setter)
1991     {
1992       if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
1993         {
1994           g_warning ("Property get or set does not have a property name string as second arg\n");
1995           return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1996         }
1997       dbus_message_iter_get_basic (&iter, &requested_propname);
1998       dbus_message_iter_next (&iter);
1999
2000       s = lookup_property_name (object, wincaps_propiface, requested_propname);
2001
2002       if (!check_property_access (connection, message, object, wincaps_propiface, requested_propname, s, setter))
2003         {
2004           g_free (s);
2005           return DBUS_HANDLER_RESULT_HANDLED;
2006         }
2007
2008       pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
2009                                             s);
2010
2011       g_free (s);
2012
2013       if (pspec != NULL)
2014         {
2015           if (setter)
2016             {
2017               if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT)
2018                 {
2019                   g_warning ("Property set does not have a variant value as third arg\n");
2020                   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2021                 }
2022
2023               ret = set_object_property (connection, message, &iter,
2024                                          object, pspec);
2025               dbus_message_iter_next (&iter);
2026             }
2027           else if (getter)
2028             {
2029               ret = get_object_property (connection, message,
2030                                          object, pspec);
2031             }
2032           else
2033             {
2034               g_assert_not_reached ();
2035               ret = NULL;
2036             }
2037         }
2038       else
2039         {
2040           ret = dbus_message_new_error_printf (message,
2041                                                DBUS_ERROR_INVALID_ARGS,
2042                                                "No such property %s", requested_propname);
2043         }
2044     }
2045
2046   g_assert (ret != NULL);
2047
2048   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID)
2049     g_warning ("Property get, set or set all had too many arguments\n");
2050
2051   dbus_connection_send (connection, ret, NULL);
2052   dbus_message_unref (ret);
2053   return DBUS_HANDLER_RESULT_HANDLED;
2054 }
2055
2056 static const DBusObjectPathVTable gobject_dbus_vtable = {
2057   object_registration_unregistered,
2058   object_registration_message,
2059   NULL
2060 };
2061
2062 typedef struct {
2063   GClosure         closure;
2064   DBusGConnection *connection;
2065   GObject         *object;
2066   const char      *signame;
2067   const char      *sigiface;
2068 } DBusGSignalClosure;
2069
2070 static GClosure *
2071 dbus_g_signal_closure_new (DBusGConnection *connection,
2072                            GObject         *object,
2073                            const char      *signame,
2074                            const char      *sigiface)
2075 {
2076   DBusGSignalClosure *closure;
2077   
2078   closure = (DBusGSignalClosure*) g_closure_new_simple (sizeof (DBusGSignalClosure), NULL);
2079
2080   closure->connection = dbus_g_connection_ref (connection);
2081   closure->object = object;
2082   closure->signame = signame;
2083   closure->sigiface = sigiface;
2084   return (GClosure*) closure;
2085 }
2086
2087 static void
2088 dbus_g_signal_closure_finalize (gpointer data,
2089                                 GClosure *closure)
2090 {
2091   DBusGSignalClosure *sigclosure = (DBusGSignalClosure *) closure;
2092
2093   dbus_g_connection_unref (sigclosure->connection);
2094 }
2095
2096 static void
2097 emit_signal_for_registration (ObjectRegistration *o,
2098                               DBusGSignalClosure *sigclosure,
2099                               GValue             *retval,
2100                               guint               n_param_values,
2101                               const GValue       *param_values)
2102 {
2103   DBusMessage *signal;
2104   DBusMessageIter iter;
2105   guint i;
2106
2107   signal = dbus_message_new_signal (o->object_path,
2108                                     sigclosure->sigiface,
2109                                     sigclosure->signame);
2110   if (!signal)
2111     {
2112       g_error ("out of memory");
2113       return;
2114     }
2115
2116   dbus_message_iter_init_append (signal, &iter);
2117
2118   /* First argument is the object itself, and we can't marshall that */
2119   for (i = 1; i < n_param_values; i++)
2120     {
2121       if (!_dbus_gvalue_marshal (&iter,
2122                                 (GValue *) (&(param_values[i]))))
2123         {
2124           g_warning ("failed to marshal parameter %d for signal %s",
2125                      i, sigclosure->signame);
2126           goto out;
2127         }
2128     }
2129   dbus_connection_send (DBUS_CONNECTION_FROM_G_CONNECTION (sigclosure->connection),
2130                         signal, NULL);
2131 out:
2132   dbus_message_unref (signal);
2133 }
2134
2135 static void
2136 signal_emitter_marshaller (GClosure        *closure,
2137                            GValue          *retval,
2138                            guint            n_param_values,
2139                            const GValue    *param_values,
2140                            gpointer         invocation_hint,
2141                            gpointer         marshal_data)
2142 {
2143   DBusGSignalClosure *sigclosure;
2144   GSList *registrations, *iter;
2145
2146   sigclosure = (DBusGSignalClosure *) closure;
2147
2148   g_assert (retval == NULL);
2149
2150   registrations = g_object_get_data (sigclosure->object, "dbus_glib_object_registrations");
2151
2152   for (iter = registrations; iter; iter = iter->next)
2153     {
2154       ObjectRegistration *o = iter->data;
2155
2156       emit_signal_for_registration (o, sigclosure, retval, n_param_values, param_values);
2157     }
2158 }
2159
2160 static void
2161 export_signals (DBusGConnection *connection, const GList *info_list, GObject *object)
2162 {
2163   GType gtype;
2164   const char *sigdata;
2165   const char *iface;
2166   const char *signame;
2167   const DBusGObjectInfo *info;
2168
2169   gtype = G_TYPE_FROM_INSTANCE (object);
2170
2171   for (; info_list != NULL; info_list = g_list_next (info_list))
2172     {
2173       info = (DBusGObjectInfo *) info_list->data;
2174       
2175       sigdata = info->exported_signals;
2176       
2177       while (*sigdata != '\0')
2178         {
2179           guint id;
2180           GSignalQuery query;
2181           GClosure *closure;
2182           char *s;
2183
2184           sigdata = signal_iterate (sigdata, &iface, &signame);
2185
2186           s = _dbus_gutils_wincaps_to_uscore (signame);
2187
2188           id = g_signal_lookup (s, gtype);
2189           if (id == 0)
2190             {
2191               g_warning ("signal \"%s\" (from \"%s\") exported but not found in object class \"%s\"",
2192                      s, signame, g_type_name (gtype));
2193               g_free (s);
2194               continue;
2195             }
2196
2197           g_signal_query (id, &query);
2198
2199           if (query.return_type != G_TYPE_NONE)
2200             {
2201               g_warning ("Not exporting signal \"%s\" for object class \"%s\" as it has a return type \"%s\"",
2202                      s, g_type_name (gtype), g_type_name (query.return_type));
2203               g_free (s);
2204               continue; /* FIXME: these could be listed as methods ? */
2205             }
2206           
2207           closure = dbus_g_signal_closure_new (connection, object, signame, (char*) iface);
2208           g_closure_set_marshal (closure, signal_emitter_marshaller);
2209
2210           g_signal_connect_closure_by_id (object,
2211                           id,
2212                           0,
2213                           closure,
2214                           FALSE);
2215
2216           g_closure_add_finalize_notifier (closure, NULL,
2217                            dbus_g_signal_closure_finalize);
2218           g_free (s);
2219         }
2220     }
2221 }
2222
2223 static gint
2224 dbus_error_to_gerror_code (const char *derr)
2225 {
2226   if (0) ; 
2227   else if (!strcmp (derr,  DBUS_ERROR_FAILED  )) 
2228     return  DBUS_GERROR_FAILED ;
2229   else if (!strcmp (derr,  DBUS_ERROR_NO_MEMORY  )) 
2230     return  DBUS_GERROR_NO_MEMORY ;
2231   else if (!strcmp (derr,  DBUS_ERROR_SERVICE_UNKNOWN  )) 
2232     return  DBUS_GERROR_SERVICE_UNKNOWN ;
2233   else if (!strcmp (derr,  DBUS_ERROR_NAME_HAS_NO_OWNER  )) 
2234     return  DBUS_GERROR_NAME_HAS_NO_OWNER ;
2235   else if (!strcmp (derr,  DBUS_ERROR_NO_REPLY  )) 
2236     return  DBUS_GERROR_NO_REPLY ;
2237   else if (!strcmp (derr,  DBUS_ERROR_IO_ERROR  )) 
2238     return  DBUS_GERROR_IO_ERROR ;
2239   else if (!strcmp (derr,  DBUS_ERROR_BAD_ADDRESS  )) 
2240     return  DBUS_GERROR_BAD_ADDRESS ;
2241   else if (!strcmp (derr,  DBUS_ERROR_NOT_SUPPORTED  )) 
2242     return  DBUS_GERROR_NOT_SUPPORTED ;
2243   else if (!strcmp (derr,  DBUS_ERROR_LIMITS_EXCEEDED  )) 
2244     return  DBUS_GERROR_LIMITS_EXCEEDED ;
2245   else if (!strcmp (derr,  DBUS_ERROR_ACCESS_DENIED  )) 
2246     return  DBUS_GERROR_ACCESS_DENIED ;
2247   else if (!strcmp (derr,  DBUS_ERROR_AUTH_FAILED  )) 
2248     return  DBUS_GERROR_AUTH_FAILED ;
2249   else if (!strcmp (derr,  DBUS_ERROR_NO_SERVER  )) 
2250     return  DBUS_GERROR_NO_SERVER ;
2251   else if (!strcmp (derr,  DBUS_ERROR_TIMEOUT  )) 
2252     return  DBUS_GERROR_TIMEOUT ;
2253   else if (!strcmp (derr,  DBUS_ERROR_NO_NETWORK  )) 
2254     return  DBUS_GERROR_NO_NETWORK ;
2255   else if (!strcmp (derr,  DBUS_ERROR_ADDRESS_IN_USE  )) 
2256     return  DBUS_GERROR_ADDRESS_IN_USE ;
2257   else if (!strcmp (derr,  DBUS_ERROR_DISCONNECTED  )) 
2258     return  DBUS_GERROR_DISCONNECTED ;
2259   else if (!strcmp (derr,  DBUS_ERROR_INVALID_ARGS  )) 
2260     return  DBUS_GERROR_INVALID_ARGS ;
2261   else if (!strcmp (derr,  DBUS_ERROR_FILE_NOT_FOUND  )) 
2262     return  DBUS_GERROR_FILE_NOT_FOUND ;
2263   else if (!strcmp (derr,  DBUS_ERROR_FILE_EXISTS  )) 
2264     return  DBUS_GERROR_FILE_EXISTS ;
2265   else if (!strcmp (derr,  DBUS_ERROR_UNKNOWN_METHOD  )) 
2266     return  DBUS_GERROR_UNKNOWN_METHOD ;
2267   else if (!strcmp (derr,  DBUS_ERROR_TIMED_OUT  )) 
2268     return  DBUS_GERROR_TIMED_OUT ;
2269   else if (!strcmp (derr,  DBUS_ERROR_MATCH_RULE_NOT_FOUND  )) 
2270     return  DBUS_GERROR_MATCH_RULE_NOT_FOUND ;
2271   else if (!strcmp (derr,  DBUS_ERROR_MATCH_RULE_INVALID  )) 
2272     return  DBUS_GERROR_MATCH_RULE_INVALID ;
2273   else if (!strcmp (derr,  DBUS_ERROR_SPAWN_EXEC_FAILED  )) 
2274     return  DBUS_GERROR_SPAWN_EXEC_FAILED ;
2275   else if (!strcmp (derr,  DBUS_ERROR_SPAWN_FORK_FAILED  )) 
2276     return  DBUS_GERROR_SPAWN_FORK_FAILED ;
2277   else if (!strcmp (derr,  DBUS_ERROR_SPAWN_CHILD_EXITED  )) 
2278     return  DBUS_GERROR_SPAWN_CHILD_EXITED ;
2279   else if (!strcmp (derr,  DBUS_ERROR_SPAWN_CHILD_SIGNALED  )) 
2280     return  DBUS_GERROR_SPAWN_CHILD_SIGNALED ;
2281   else if (!strcmp (derr,  DBUS_ERROR_SPAWN_FAILED  )) 
2282     return  DBUS_GERROR_SPAWN_FAILED ;
2283   else if (!strcmp (derr,  DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN  )) 
2284     return  DBUS_GERROR_UNIX_PROCESS_ID_UNKNOWN ;
2285   else if (!strcmp (derr,  DBUS_ERROR_INVALID_SIGNATURE  )) 
2286     return  DBUS_GERROR_INVALID_SIGNATURE ;
2287   else if (!strcmp (derr,  DBUS_ERROR_INVALID_FILE_CONTENT  )) 
2288     return  DBUS_GERROR_INVALID_FILE_CONTENT ;
2289   else if (!strcmp (derr,  DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN  )) 
2290     return  DBUS_GERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN ;
2291   else
2292     return DBUS_GERROR_REMOTE_EXCEPTION;
2293 }
2294
2295 /**
2296  * dbus_set_g_error:
2297  * @gerror: an error
2298  * @error: a #DBusError
2299  *
2300  * Store the information from a DBus method error return into a
2301  * GError.  For the normal case of an arbitrary remote process,
2302  * the error code will be DBUS_GERROR_REMOTE_EXCEPTION.  Now,
2303  * DBus errors have two components; a message and a "name". 
2304  * The former is an arbitrary (normally American English) string.  
2305  * The second is a string like com.example.FooFailure which 
2306  * programs can use as a conditional source.  Because a GError
2307  * only has one string, we use a hack to encode both values:
2308  *
2309  * &lt;human readable string&gt;&lt;null&gt;&lt;error name&gt;&lt;null&gt;
2310  * 
2311  * You can use the following code to retrieve both values:
2312  * 
2313  * |[const char *msg = error->message;
2314  * size_t len = strlen(msg);
2315  * const char *error_name = msg+len+1;]|
2316  */
2317 void
2318 dbus_set_g_error (GError    **gerror,
2319                   DBusError  *error)
2320 {
2321   int code;
2322
2323   code = dbus_error_to_gerror_code (error->name);
2324   if (code != DBUS_GERROR_REMOTE_EXCEPTION)
2325     g_set_error (gerror, DBUS_GERROR,
2326                  code,
2327                  "%s",
2328                  error->message);
2329   else
2330     g_set_error (gerror, DBUS_GERROR,
2331                  code,
2332                  "%s%c%s",
2333                  error->message ? error->message : "",
2334                  '\0',
2335                  error->name);
2336 }
2337
2338 static void
2339 dbus_g_error_info_free (gpointer p)
2340 {
2341   DBusGErrorInfo *info;
2342
2343   info = p;
2344
2345   g_free (info->default_iface);
2346   g_free (info);
2347 }
2348
2349 /**
2350  * SECTION:dbus-gobject
2351  * @short_description: Exporting a #GObject remotely
2352  * @see_also: #GObject
2353  * @stability: Stable
2354  *
2355  * FIXME
2356  */
2357
2358 /**
2359  * dbus_glib_global_set_disable_legacy_property_access:
2360  *
2361  * For historical reasons, DBus-GLib will allow read-only
2362  * access to every GObject property of an object exported
2363  * to the bus, regardless of whether or not the property
2364  * is listed in the type info installed with
2365  * dbus_g_object_type_install_info().  (Write access is
2366  * denied however).
2367  *
2368  * If you wish to restrict even read-only access, you
2369  * can call this method to globally change the behavior
2370  * for the entire process.
2371  *
2372  * Since: 0.88
2373  */
2374 void
2375 dbus_glib_global_set_disable_legacy_property_access (void)
2376 {
2377   disable_legacy_property_access = TRUE;
2378 }
2379
2380 /**
2381  * dbus_g_object_type_install_info:
2382  * @object_type: #GType for the object
2383  * @info: introspection data generated by #dbus-glib-tool
2384  *
2385  * Install introspection information about the given object #GType
2386  * sufficient to allow methods on the object to be invoked by name.
2387  * The introspection information is normally generated by
2388  * dbus-glib-tool, then this function is called in the
2389  * class_init() for the object class.
2390  *
2391  * Once introspection information has been installed, instances of the
2392  * object registered with #dbus_g_connection_register_g_object() can have
2393  * their methods invoked remotely.
2394  */
2395 void
2396 dbus_g_object_type_install_info (GType                  object_type,
2397                                  const DBusGObjectInfo *info)
2398 {
2399   g_return_if_fail (G_TYPE_IS_CLASSED (object_type) || G_TYPE_IS_INTERFACE (object_type));
2400
2401   _dbus_g_value_types_init ();
2402
2403   g_type_set_qdata (object_type,
2404                     dbus_g_object_type_dbus_metadata_quark (),
2405                     (gpointer) info);
2406 }
2407
2408 /**
2409  * dbus_g_error_domain_register:
2410  * @domain: the #GError domain
2411  * @default_iface: the prefix used for error values, or %NULL
2412  * @code_enum: a #GType for a #GEnum of the error codes
2413  *
2414  * Register a #GError domain and set of codes with D-Bus. When an object
2415  * raises a #GError in the domain @domain from one of its D-Bus methods,
2416  * the D-Bus error name used will be @default_iface, followed by a dot,
2417  * followed by the #GEnumValue.value_nick corresponding to the #GError.code.
2418  * For D-Bus, it's conventional to use an error name (value_nick) that is
2419  * in CamelCase.
2420  *
2421  * (For instance, if a D-Bus method <code>com.example.MyObject.GetThings</code>
2422  * can raise a #GError with domain <code>MY_ERROR</code> and code
2423  * <code>MY_ERROR_NOT_HAPPY</code>, you could call
2424  * <code>dbus_g_error_domain_register (MY_ERROR, "com.example.MyError",
2425  * MY_TYPE_ERROR)</code>, and set up the value_nick for
2426  * <code>MY_ERROR_NOT_HAPPY</code> to be <code>NotHappy</code>,
2427  * resulting in the D-Bus error string
2428  * <code>com.example.MyError.NotHappy</code>.)
2429  *
2430  * If @default_iface is %NULL, the D-Bus interface of the method that failed
2431  * will be used.
2432  *
2433  * (For instance, if the above example had called
2434  * <code>dbus_g_error_domain_register (MY_ERROR, NULL, MY_TYPE_ERROR)</code>
2435  * instead, then the D-Bus error string would be
2436  * <code>com.example.MyObject.NotHappy</code>.)
2437  */
2438 void
2439 dbus_g_error_domain_register (GQuark                domain,
2440                               const char           *default_iface,
2441                               GType                 code_enum)
2442 {
2443   DBusGErrorInfo *info;
2444   
2445   g_return_if_fail (g_quark_to_string (domain) != NULL);
2446   g_return_if_fail (code_enum != G_TYPE_INVALID);
2447   g_return_if_fail (G_TYPE_FUNDAMENTAL (code_enum) == G_TYPE_ENUM);
2448
2449   g_static_rw_lock_writer_lock (&globals_lock);
2450
2451   if (error_metadata == NULL)
2452     g_datalist_init (&error_metadata);
2453
2454   info = g_datalist_id_get_data (&error_metadata, domain);
2455
2456   if (info != NULL)
2457     {
2458       g_warning ("Metadata for error domain \"%s\" already registered\n",
2459                  g_quark_to_string (domain));
2460     }
2461   else
2462     {
2463       info = g_new0 (DBusGErrorInfo, 1);
2464       info->default_iface = g_strdup (default_iface);
2465       info->code_enum = code_enum;
2466
2467       g_datalist_id_set_data_full (&error_metadata,
2468                                    domain,
2469                                    info,
2470                                    dbus_g_error_info_free);
2471     }
2472
2473   g_static_rw_lock_writer_unlock (&globals_lock);
2474 }
2475
2476 /* Called when the object is destroyed */
2477 static void
2478 object_registration_object_died (gpointer user_data, GObject *dead)
2479 {
2480   ObjectRegistration *o = user_data;
2481
2482   g_assert (dead == o->object);
2483
2484   /* this prevents the weak unref from taking place, which would cause an
2485    * assertion failure since the object has already gone... */
2486   o->object = NULL;
2487
2488   /* ... while this results in a call to object_registration_unregistered */
2489   dbus_connection_unregister_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (o->connection), o->object_path);
2490 }
2491
2492 /**
2493  * dbus_g_connection_unregister_g_object:
2494  * @connection: the D-BUS connection
2495  * @object: the object
2496  *
2497  * Removes @object from the bus. Properties, methods, and signals
2498  * of the object can no longer be accessed remotely.
2499  */
2500 void
2501 dbus_g_connection_unregister_g_object (DBusGConnection *connection,
2502                                        GObject *object)
2503 {
2504   GList *registrations, *iter;
2505
2506   /* Copy the list before iterating it: it will be modified in
2507    * object_registration_free() each time an object path is unregistered.
2508    */
2509   registrations = g_list_copy (g_object_get_data (object, "dbus_glib_object_registrations"));
2510
2511   g_return_if_fail (registrations != NULL);
2512
2513   for (iter = registrations; iter; iter = iter->next)
2514     {
2515       ObjectRegistration *o = iter->data;
2516       dbus_connection_unregister_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (o->connection),
2517           o->object_path);
2518     }
2519
2520   g_list_free (registrations);
2521   g_assert (g_object_get_data (object, "dbus_glib_object_registrations") == NULL);
2522 }
2523
2524 /**
2525  * dbus_g_connection_register_g_object:
2526  * @connection: the D-BUS connection
2527  * @at_path: the path where the object will live (the object's name)
2528  * @object: the object
2529  *
2530  * Registers a #GObject at the given path. Properties, methods, and signals
2531  * of the object can then be accessed remotely. Methods are only available
2532  * if method introspection data has been added to the object's class
2533  * with dbus_g_object_type_install_info().
2534  *
2535  * The registration will be cancelled if either the #DBusConnection or
2536  * the #GObject gets finalized, or if dbus_g_connection_unregister_g_object()
2537  * is used.
2538  *
2539  * Note: If an object is registered multiple times, the first registration
2540  * takes priority for cases such as turning an object into an object path.
2541  */
2542 void
2543 dbus_g_connection_register_g_object (DBusGConnection       *connection,
2544                                      const char            *at_path,
2545                                      GObject               *object)
2546 {
2547   GList *info_list;
2548   GSList *registrations, *iter;
2549   ObjectRegistration *o;
2550   gboolean is_first_registration;
2551
2552   g_return_if_fail (connection != NULL);
2553   g_return_if_fail (at_path != NULL);
2554   g_return_if_fail (G_IS_OBJECT (object));
2555
2556   /* This is a GSList of ObjectRegistration*  */
2557   registrations = g_object_steal_data (object, "dbus_glib_object_registrations");
2558
2559   for (iter = registrations; iter; iter = iter->next)
2560     {
2561       o = iter->data;
2562
2563       /* Silently ignore duplicate registrations */
2564       if (strcmp (o->object_path, at_path) == 0 && o->connection == connection)
2565         return;
2566     }
2567
2568   is_first_registration = registrations == NULL;
2569
2570   /* This is used to hook up signals below, but we do this check
2571    * before trying to register the object to make sure we have
2572    * introspection data for it.
2573    */
2574   if (is_first_registration)
2575     {
2576       info_list = lookup_object_info (object);
2577       if (info_list == NULL)
2578         {
2579           g_warning ("No introspection data registered for object class \"%s\"",
2580                      g_type_name (G_TYPE_FROM_INSTANCE (object)));
2581           return;
2582         }
2583     }
2584   else
2585     info_list = NULL;
2586
2587   o = object_registration_new (connection, at_path, object);
2588
2589   if (!dbus_connection_register_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (connection),
2590                                              at_path,
2591                                              &gobject_dbus_vtable,
2592                                              o))
2593     {
2594       g_error ("Failed to register GObject with DBusConnection");
2595       object_registration_free (o);
2596       g_list_free (info_list);
2597       return;
2598     }
2599
2600   if (is_first_registration)
2601     {
2602       /* This adds a hook into every signal for the object.  Only do this
2603        * on the first registration, because inside the signal marshaller
2604        * we emit a signal for each registration.
2605        */
2606       export_signals (connection, info_list, object);
2607       g_list_free (info_list);
2608     }
2609
2610   registrations = g_slist_append (registrations, o);
2611   g_object_set_data (object, "dbus_glib_object_registrations", registrations);
2612 }
2613
2614 /**
2615  * dbus_g_connection_lookup_g_object:
2616  * @connection: a #DBusGConnection
2617  * @at_path: path
2618  *
2619  * FIXME 
2620  *
2621  * Returns: the object at path @at_path
2622  */
2623 GObject *
2624 dbus_g_connection_lookup_g_object (DBusGConnection       *connection,
2625                                    const char            *at_path)
2626 {
2627   gpointer p;
2628   ObjectRegistration *o;
2629
2630   if (!dbus_connection_get_object_path_data (DBUS_CONNECTION_FROM_G_CONNECTION (connection), at_path, &p))
2631     return NULL;
2632
2633   if (p == NULL)
2634     return NULL;
2635
2636   o = p;
2637   return G_OBJECT (o->object);
2638 }
2639
2640 typedef struct {
2641   GType    rettype;
2642   guint    n_params;
2643   GType   *params;
2644 } DBusGFuncSignature;
2645
2646 static guint
2647 funcsig_hash (gconstpointer key)
2648 {
2649   const DBusGFuncSignature *sig = key;
2650   GType *types;
2651   guint ret;
2652   guint i;
2653
2654   ret = sig->rettype;
2655   types = sig->params;
2656
2657   for (i = 0; i < sig->n_params; i++)
2658     {
2659       ret += (int) (*types);
2660       types++;
2661     }
2662       
2663   return ret;
2664 }
2665
2666 static gboolean
2667 funcsig_equal (gconstpointer aval,
2668                gconstpointer bval)
2669 {
2670   const DBusGFuncSignature *a = aval;
2671   const DBusGFuncSignature *b = bval;
2672   const GType *atypes;
2673   const GType *btypes;
2674   guint i;
2675
2676   if (a->rettype != b->rettype
2677       || a->n_params != b->n_params)
2678     return FALSE;
2679
2680   atypes = a->params;
2681   btypes = b->params;
2682
2683   for (i = 0; i < a->n_params; i++)
2684     {
2685       if (*btypes != *atypes)
2686         return FALSE;
2687       atypes++;
2688       btypes++;
2689     }
2690       
2691   return TRUE;
2692 }
2693
2694 static void
2695 funcsig_free (DBusGFuncSignature *sig)
2696 {
2697   g_free (sig->params);
2698   g_free (sig);
2699 }
2700
2701 GClosureMarshal
2702 _dbus_gobject_lookup_marshaller (GType        rettype,
2703                                  guint        n_params,
2704                                  const GType *param_types)
2705 {
2706   GClosureMarshal ret;
2707   DBusGFuncSignature sig;
2708   GType *params;
2709   guint i;
2710
2711   /* Convert to fundamental types */
2712   rettype = G_TYPE_FUNDAMENTAL (rettype);
2713   params = g_new (GType, n_params);
2714   for (i = 0; i < n_params; i++)
2715     params[i] = G_TYPE_FUNDAMENTAL (param_types[i]);
2716
2717   sig.rettype = rettype;
2718   sig.n_params = n_params;
2719   sig.params = params;
2720   
2721   g_static_rw_lock_reader_lock (&globals_lock);
2722
2723   if (marshal_table)
2724     ret = g_hash_table_lookup (marshal_table, &sig);
2725   else
2726     ret = NULL;
2727
2728   g_static_rw_lock_reader_unlock (&globals_lock);
2729
2730   if (ret == NULL)
2731     {
2732       if (rettype == G_TYPE_NONE)
2733         {
2734           if (n_params == 0)
2735             ret = g_cclosure_marshal_VOID__VOID;
2736           else if (n_params == 1)
2737             {
2738               switch (params[0])
2739                 {
2740                 case G_TYPE_BOOLEAN:
2741                   ret = g_cclosure_marshal_VOID__BOOLEAN;
2742                   break;
2743                 case G_TYPE_UCHAR:
2744                   ret = g_cclosure_marshal_VOID__UCHAR;
2745                   break;
2746                 case G_TYPE_INT:
2747                   ret = g_cclosure_marshal_VOID__INT;
2748                   break;
2749                 case G_TYPE_UINT:
2750                   ret = g_cclosure_marshal_VOID__UINT;
2751                   break;
2752                 case G_TYPE_DOUBLE:
2753                   ret = g_cclosure_marshal_VOID__DOUBLE;
2754                   break;
2755                 case G_TYPE_STRING:
2756                   ret = g_cclosure_marshal_VOID__STRING;
2757                   break;
2758                 case G_TYPE_BOXED:
2759                   ret = g_cclosure_marshal_VOID__BOXED;
2760                   break;
2761                 }
2762             }
2763           else if (n_params == 3
2764                    && params[0] == G_TYPE_STRING
2765                    && params[1] == G_TYPE_STRING
2766                    && params[2] == G_TYPE_STRING)
2767             {
2768               ret = _dbus_g_marshal_NONE__STRING_STRING_STRING;
2769             }
2770         }
2771     }
2772
2773   g_free (params);
2774   return ret;
2775 }
2776
2777 /**
2778  * dbus_g_object_register_marshaller:
2779  * @marshaller: a GClosureMarshal to be used for invocation
2780  * @rettype: a GType for the return type of the function
2781  * @:... The parameter #GTypes, followed by %G_TYPE_INVALID
2782  *
2783  * Register a #GClosureMarshal to be used for signal invocations,
2784  * giving its return type and a list of parameter types,
2785  * followed by %G_TYPE_INVALID.
2786  *
2787  * This function will not be needed once GLib includes libffi.
2788  */
2789 void
2790 dbus_g_object_register_marshaller (GClosureMarshal  marshaller,
2791                                    GType            rettype,
2792                                    ...)
2793 {
2794   va_list args;
2795   GArray *types;
2796   GType gtype;
2797
2798   va_start (args, rettype);
2799
2800   types = g_array_new (TRUE, TRUE, sizeof (GType));
2801
2802   while ((gtype = va_arg (args, GType)) != G_TYPE_INVALID)
2803     g_array_append_val (types, gtype);
2804
2805   dbus_g_object_register_marshaller_array (marshaller, rettype,
2806                                            types->len, (GType*) types->data);
2807
2808   g_array_free (types, TRUE);
2809   va_end (args);
2810 }
2811
2812 /**
2813  * dbus_g_object_register_marshaller_array:
2814  * @marshaller: a #GClosureMarshal to be used for invocation
2815  * @rettype: a #GType for the return type of the function
2816  * @n_types: number of function parameters
2817  * @types: a C array of GTypes values
2818  *
2819  * Register a #GClosureMarshal to be used for signal invocations.
2820  * @see_also #dbus_g_object_register_marshaller
2821  */
2822 void
2823 dbus_g_object_register_marshaller_array (GClosureMarshal  marshaller,
2824                                          GType            rettype,
2825                                          guint            n_types,
2826                                          const GType*     types)
2827 {
2828   DBusGFuncSignature *sig;
2829   guint i;
2830
2831   g_static_rw_lock_writer_lock (&globals_lock);
2832
2833   if (marshal_table == NULL)
2834     marshal_table = g_hash_table_new_full (funcsig_hash,
2835                                            funcsig_equal,
2836                                            (GDestroyNotify) funcsig_free,
2837                                            NULL);
2838   sig = g_new0 (DBusGFuncSignature, 1);
2839   sig->rettype = G_TYPE_FUNDAMENTAL (rettype);
2840   sig->n_params = n_types;
2841   sig->params = g_new (GType, n_types);
2842   for (i = 0; i < n_types; i++)
2843     sig->params[i] = G_TYPE_FUNDAMENTAL (types[i]);
2844
2845   g_hash_table_insert (marshal_table, sig, marshaller);
2846
2847   g_static_rw_lock_writer_unlock (&globals_lock);
2848 }
2849
2850 /**
2851  * dbus_g_method_get_sender:
2852  * @context: the method context
2853  *
2854  * Get the sender of a message so we can send a
2855  * "reply" later (i.e. send a message directly
2856  * to a service which invoked the method at a
2857  * later time).
2858  *
2859  * Returns: the unique name of the sender. It
2860  * is up to the caller to free the returned string.
2861  */
2862 gchar *
2863 dbus_g_method_get_sender (DBusGMethodInvocation *context)
2864 {
2865   const gchar *sender;
2866
2867   sender = dbus_message_get_sender (dbus_g_message_get_message (context->message));
2868   return g_strdup (sender);
2869 }
2870
2871 /**
2872  * dbus_g_method_get_reply:
2873  * @context: the method context
2874  *
2875  * Get the reply message to append reply values
2876  * Used as a sidedoor when you can't generate dbus values
2877  * of the correct type due to glib binding limitations
2878  *
2879  * Returns: a #DBusMessage with the reply
2880  */
2881 DBusMessage *
2882 dbus_g_method_get_reply (DBusGMethodInvocation *context)
2883 {
2884   return dbus_message_new_method_return (dbus_g_message_get_message (context->message));
2885 }
2886
2887 /**
2888  * dbus_g_method_send_reply:
2889  * Send a manually created reply message
2890  * @context: the method context
2891  * @reply: the reply message, will be unreffed
2892  *
2893  * Used as a sidedoor when you can't generate dbus values
2894  * of the correct type due to glib binding limitations
2895  */
2896 void
2897 dbus_g_method_send_reply (DBusGMethodInvocation *context, DBusMessage *reply)
2898 {
2899   dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
2900   dbus_message_unref (reply);
2901
2902   dbus_g_connection_unref (context->connection);
2903   dbus_g_message_unref (context->message);
2904   g_free (context);
2905 }
2906
2907
2908 /**
2909  * dbus_g_method_return:
2910  * @context: the method context
2911  *
2912  * Send a return message for a given method invocation, with arguments.
2913  * This function also frees the sending context.
2914  */
2915 void
2916 dbus_g_method_return (DBusGMethodInvocation *context, ...)
2917 {
2918   DBusMessage *reply;
2919   DBusMessageIter iter;
2920   va_list args;
2921   char *out_sig;
2922   GArray *argsig;
2923   guint i;
2924   
2925   /* This field was initialized inside invoke_object_method; we
2926    * carry it over through the async invocation to here.
2927    */
2928   if (!context->send_reply)
2929     goto out;
2930
2931   reply = dbus_message_new_method_return (dbus_g_message_get_message (context->message));
2932   out_sig = method_output_signature_from_object_info (context->object, context->method);
2933   argsig = _dbus_gtypes_from_arg_signature (out_sig, FALSE);
2934
2935   dbus_message_iter_init_append (reply, &iter);
2936
2937   va_start (args, context);
2938   for (i = 0; i < argsig->len; i++)
2939     {
2940       GValue value = {0,};
2941       char *error;
2942       g_value_init (&value, g_array_index (argsig, GType, i));
2943       error = NULL;
2944       G_VALUE_COLLECT (&value, args, G_VALUE_NOCOPY_CONTENTS, &error);
2945       if (error)
2946         {
2947           g_warning("%s", error);
2948           g_free (error);
2949         }
2950       _dbus_gvalue_marshal (&iter, &value);
2951     }
2952   va_end (args);
2953
2954   dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
2955   dbus_message_unref (reply);
2956
2957   g_free (out_sig);
2958   g_array_free (argsig, TRUE);
2959
2960 out:
2961   dbus_g_connection_unref (context->connection);
2962   dbus_g_message_unref (context->message);
2963   g_free (context);
2964 }
2965
2966 /**
2967  * dbus_g_method_return_error:
2968  * @context: the method context
2969  * @error: the error to send
2970  *
2971  * Send a error message for a given method invocation.
2972  * This function also frees the sending context.
2973  */
2974 void
2975 dbus_g_method_return_error (DBusGMethodInvocation *context, const GError *error)
2976 {
2977   DBusMessage *reply;
2978
2979   /* See comment in dbus_g_method_return */
2980   if (!context->send_reply)
2981     goto out;
2982
2983   reply = gerror_to_dbus_error_message (context->object, dbus_g_message_get_message (context->message), error);
2984   dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
2985   dbus_message_unref (reply);
2986
2987 out:
2988   dbus_g_connection_unref (context->connection);
2989   dbus_g_message_unref (context->message);
2990   g_free (context);
2991 }
2992
2993 const char *
2994 _dbus_gobject_get_path (GObject *obj)
2995 {
2996   GSList *registrations;
2997   ObjectRegistration *o;
2998
2999   registrations = g_object_get_data (obj, "dbus_glib_object_registrations");
3000
3001   if (registrations == NULL)
3002     return NULL;
3003
3004   /* First one to have been registered wins */
3005   o = registrations->data;
3006
3007   return o->object_path;
3008 }
3009
3010 #ifdef DBUS_BUILD_TESTS
3011 #include <stdlib.h>
3012
3013 static void
3014 _dummy_function (void)
3015 {
3016 }
3017
3018 /* Data structures copied from one generated by current dbus-binding-tool;
3019  * we need to support this layout forever
3020  */
3021 static const DBusGMethodInfo dbus_glib_internal_test_methods[] = {
3022   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 0 },
3023   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 49 },
3024   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 117 },
3025   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 191 },
3026   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 270 },
3027   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 320 },
3028   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 391 },
3029   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 495 },
3030   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 623 },
3031   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 693 },
3032   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 765 },
3033   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 838 },
3034   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 911 },
3035   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 988 },
3036   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1064 },
3037   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1140 },
3038   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1204 },
3039   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1278 },
3040   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1347 },
3041   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1408 },
3042   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1460 },
3043   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1533 },
3044   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1588 },
3045   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1647 },
3046   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1730 },
3047   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1784 },
3048   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1833 },
3049   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1895 },
3050   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1947 },
3051   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1999 },
3052 };
3053
3054 const DBusGObjectInfo dbus_glib_internal_test_object_info = {
3055   0,
3056   dbus_glib_internal_test_methods,
3057   30,
3058 "org.freedesktop.DBus.Tests.MyObject\0DoNothing\0S\0\0org.freedesktop.DBus.Tests.MyObject\0Increment\0S\0x\0I\0u\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0IncrementRetval\0S\0x\0I\0u\0arg1\0O\0F\0R\0u\0\0org.freedesktop.DBus.Tests.MyObject\0IncrementRetvalError\0S\0x\0I\0u\0arg1\0O\0F\0E\0u\0\0org.freedesktop.DBus.Tests.MyObject\0ThrowError\0S\0\0org.freedesktop.DBus.Tests.MyObject\0Uppercase\0S\0arg0\0I\0s\0arg1\0O\0F\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0ManyArgs\0S\0x\0I\0u\0str\0I\0s\0trouble\0I\0d\0d_ret\0O\0F\0N\0d\0str_ret\0O\0F\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0ManyReturn\0S\0arg0\0O\0F\0N\0u\0arg1\0O\0F\0N\0s\0arg2\0O\0F\0N\0i\0arg3\0O\0F\0N\0u\0arg4\0O\0F\0N\0u\0arg5\0O\0C\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0Stringify\0S\0val\0I\0v\0arg1\0O\0F\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0Unstringify\0S\0val\0I\0s\0arg1\0O\0F\0N\0v\0\0org.freedesktop.DBus.Tests.MyObject\0Recursive1\0S\0arg0\0I\0au\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0Recursive2\0S\0arg0\0I\0u\0arg1\0O\0F\0N\0au\0\0org.freedesktop.DBus.Tests.MyObject\0ManyUppercase\0S\0arg0\0I\0as\0arg1\0O\0F\0N\0as\0\0org.freedesktop.DBus.Tests.MyObject\0StrHashLen\0S\0arg0\0I\0a{ss}\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0SendCar\0S\0arg0\0I\0(suv)\0arg1\0O\0F\0N\0(uo)\0\0org.freedesktop.DBus.Tests.MyObject\0GetHash\0S\0arg0\0O\0F\0N\0a{ss}\0\0org.freedesktop.DBus.Tests.MyObject\0RecArrays\0S\0val\0I\0aas\0arg1\0O\0F\0N\0aau\0\0org.freedesktop.DBus.Tests.MyObject\0Objpath\0S\0arg0\0I\0o\0arg1\0O\0C\0N\0o\0\0org.freedesktop.DBus.Tests.MyObject\0GetObjs\0S\0arg0\0O\0F\0N\0ao\0\0org.freedesktop.DBus.Tests.MyObject\0IncrementVal\0S\0\0org.freedesktop.DBus.Tests.MyObject\0AsyncIncrement\0A\0x\0I\0u\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0AsyncThrowError\0A\0\0org.freedesktop.DBus.Tests.MyObject\0GetVal\0S\0arg0\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0ManyStringify\0S\0arg0\0I\0a{sv}\0arg1\0O\0F\0N\0a{sv}\0\0org.freedesktop.DBus.Tests.MyObject\0EmitFrobnicate\0S\0\0org.freedesktop.DBus.Tests.MyObject\0Terminate\0S\0\0org.freedesktop.DBus.Tests.FooObject\0GetValue\0S\0arg0\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.FooObject\0EmitSignals\0S\0\0org.freedesktop.DBus.Tests.FooObject\0EmitSignal2\0S\0\0org.freedesktop.DBus.Tests.FooObject\0Terminate\0S\0\0\0",
3059 "org.freedesktop.DBus.Tests.MyObject\0Frobnicate\0org.freedesktop.DBus.Tests.FooObject\0Sig0\0org.freedesktop.DBus.Tests.FooObject\0Sig1\0org.freedesktop.DBus.Tests.FooObject\0Sig2\0\0",
3060 "\0"
3061 };
3062
3063
3064 /**
3065  * @ingroup DBusGLibInternals
3066  * Unit test for GLib GObject integration ("skeletons")
3067  * Returns: #TRUE on success.
3068  */
3069 gboolean
3070 _dbus_gobject_test (const char *test_data_dir)
3071 {
3072   int i;
3073   const char *arg;
3074   const char *arg_name;
3075   gboolean arg_in;
3076   gboolean constval;
3077   RetvalType retval;
3078   const char *arg_signature;
3079   const char *sigdata;
3080   const char *iface;
3081   const char *signame;
3082   
3083   static struct { const char *wincaps; const char *uscore; } name_pairs[] = {
3084     { "SetFoo", "set_foo" },
3085     { "Foo", "foo" },
3086     { "GetFooBar", "get_foo_bar" },
3087     { "Hello", "hello" }
3088     
3089     /* Impossible-to-handle cases */
3090     /* { "FrobateUIHandler", "frobate_ui_handler" } */
3091   };
3092
3093   /* Test lookup in our hardcoded object info; if these tests fail
3094    * then it likely means you changed the generated object info in an
3095    * incompatible way and broke the lookup functions.  In that case
3096    * you need to bump the version and use a new structure instead. */
3097   /* DoNothing */
3098   arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
3099                                           &(dbus_glib_internal_test_methods[0]));
3100   g_assert (*arg == '\0');
3101
3102   /* Increment */
3103   arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
3104                                           &(dbus_glib_internal_test_methods[1]));
3105   g_assert (*arg != '\0');
3106   arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3107   g_assert (!strcmp (arg_name, "x"));
3108   g_assert (arg_in == TRUE);
3109   g_assert (!strcmp (arg_signature, "u"));
3110   g_assert (*arg != '\0');
3111   arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3112   g_assert (arg_in == FALSE);
3113   g_assert (retval == RETVAL_NONE);
3114   g_assert (!strcmp (arg_signature, "u"));
3115   g_assert (*arg == '\0');
3116
3117   /* IncrementRetval */
3118   arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
3119                                           &(dbus_glib_internal_test_methods[2]));
3120   g_assert (*arg != '\0');
3121   arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3122   g_assert (!strcmp (arg_name, "x"));
3123   g_assert (arg_in == TRUE);
3124   g_assert (!strcmp (arg_signature, "u"));
3125   g_assert (*arg != '\0');
3126   arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3127   g_assert (retval == RETVAL_NOERROR);
3128   g_assert (arg_in == FALSE);
3129   g_assert (!strcmp (arg_signature, "u"));
3130   g_assert (*arg == '\0');
3131
3132   /* IncrementRetvalError */
3133   arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
3134                                           &(dbus_glib_internal_test_methods[3]));
3135   g_assert (*arg != '\0');
3136   arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3137   g_assert (!strcmp (arg_name, "x"));
3138   g_assert (arg_in == TRUE);
3139   g_assert (!strcmp (arg_signature, "u"));
3140   g_assert (*arg != '\0');
3141   arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3142   g_assert (retval == RETVAL_ERROR);
3143   g_assert (arg_in == FALSE);
3144   g_assert (!strcmp (arg_signature, "u"));
3145   g_assert (*arg == '\0');
3146   
3147   /* Stringify */
3148   arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
3149                                           &(dbus_glib_internal_test_methods[8]));
3150   g_assert (*arg != '\0');
3151   arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3152   g_assert (!strcmp (arg_name, "val"));
3153   g_assert (arg_in == TRUE);
3154   g_assert (!strcmp (arg_signature, "v"));
3155   g_assert (*arg != '\0');
3156   arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3157   g_assert (retval == RETVAL_NONE);
3158   g_assert (arg_in == FALSE);
3159   g_assert (!strcmp (arg_signature, "s"));
3160   g_assert (*arg == '\0');
3161
3162   sigdata = dbus_glib_internal_test_object_info.exported_signals;
3163   g_assert (*sigdata != '\0');
3164   sigdata = signal_iterate (sigdata, &iface, &signame);
3165   g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.MyObject"));
3166   g_assert (!strcmp (signame, "Frobnicate"));
3167   g_assert (*sigdata != '\0');
3168   sigdata = signal_iterate (sigdata, &iface, &signame);
3169   g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
3170   g_assert (!strcmp (signame, "Sig0"));
3171   g_assert (*sigdata != '\0');
3172   sigdata = signal_iterate (sigdata, &iface, &signame);
3173   g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
3174   g_assert (!strcmp (signame, "Sig1"));
3175   g_assert (*sigdata != '\0');
3176   sigdata = signal_iterate (sigdata, &iface, &signame);
3177   g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
3178   g_assert (!strcmp (signame, "Sig2"));
3179   g_assert (*sigdata == '\0');
3180
3181
3182   i = 0;
3183   while (i < (int) G_N_ELEMENTS (name_pairs))
3184     {
3185       char *uscore;
3186       char *wincaps;
3187
3188       uscore = _dbus_gutils_wincaps_to_uscore (name_pairs[i].wincaps);
3189       wincaps = uscore_to_wincaps (name_pairs[i].uscore);
3190
3191       if (strcmp (uscore, name_pairs[i].uscore) != 0)
3192         {
3193           g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
3194                       name_pairs[i].wincaps, name_pairs[i].uscore,
3195                       uscore);
3196           exit (1);
3197         }
3198       
3199       if (strcmp (wincaps, name_pairs[i].wincaps) != 0)
3200         {
3201           g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
3202                       name_pairs[i].uscore, name_pairs[i].wincaps,
3203                       wincaps);
3204           exit (1);
3205         }
3206       
3207       g_free (uscore);
3208       g_free (wincaps);
3209
3210       ++i;
3211     }
3212   
3213   return TRUE;
3214 }
3215
3216 #endif /* DBUS_BUILD_TESTS */