1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-gobject.c Exporting a GObject remotely
4 * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
5 * Copyright (C) 2005 Nokia
7 * Licensed under the Academic Free License version 2.1
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.
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.
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
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"
40 G_GNUC_NORETURN static void
41 oom (const gchar *explanation)
43 g_error ("%s", explanation == NULL ? "Out of memory" : explanation);
44 g_assert_not_reached ();
48 reply_or_die (DBusMessage *in_reply_to)
52 g_return_val_if_fail (in_reply_to != NULL, NULL);
54 reply = dbus_message_new_method_return (in_reply_to);
57 oom ("dbus_message_new_method_return failed: out of memory?");
63 error_or_die (DBusMessage *in_reply_to,
64 const gchar *error_name,
65 const gchar *error_message)
69 g_return_val_if_fail (in_reply_to != NULL, NULL);
70 /* error names are syntactically the same as interface names */
71 g_return_val_if_fail (g_dbus_is_interface_name (error_name), NULL);
72 g_return_val_if_fail (g_utf8_validate (error_message, -1, NULL), NULL);
74 reply = dbus_message_new_error (in_reply_to, error_name, error_message);
77 oom ("dbus_message_new_error failed: out of memory?");
83 connection_send_or_die (DBusConnection *connection,
86 g_return_if_fail (connection != NULL);
87 g_return_if_fail (message != NULL);
89 if (!dbus_connection_send (connection, message, NULL))
90 oom ("dbus_connection_send failed: out of memory?");
93 static char *lookup_property_name (GObject *object,
94 const char *wincaps_propiface,
95 const char *requested_propname);
103 static GStaticRWLock globals_lock = G_STATIC_RW_LOCK_INIT;
104 /* See comments in check_property_access */
105 static gboolean disable_legacy_property_access = FALSE;
106 static GHashTable *marshal_table = NULL;
107 static GData *error_metadata = NULL;
110 uscore_to_wincaps_full (const char *uscore,
111 gboolean uppercase_first,
112 gboolean strip_underscores)
116 gboolean last_was_uscore;
118 last_was_uscore = uppercase_first;
120 str = g_string_new (NULL);
124 if (*p == '-' || (strip_underscores && *p == '_'))
126 last_was_uscore = TRUE;
132 g_string_append_c (str, g_ascii_toupper (*p));
133 last_was_uscore = FALSE;
136 g_string_append_c (str, *p);
141 return g_string_free (str, FALSE);
144 /* Ugly yes - but we have to accept strings from both formats */
146 compare_strings_ignoring_uscore_vs_dash (const char *a, const char *b)
150 for (i = 0; a[i] && b[i]; i++)
152 if ((a[i] == '-' && b[i] == '_')
153 || (a[i] == '_' && b[i] == '-'))
158 return (a[i] == '\0') && (b[i] == '\0');
162 uscore_to_wincaps (const char *uscore)
164 return uscore_to_wincaps_full (uscore, TRUE, TRUE);
168 string_table_next (const char *table)
170 return (table + (strlen (table) + 1));
174 string_table_lookup (const char *table, int index)
181 ret = string_table_next (ret);
187 get_method_data (const DBusGObjectInfo *object,
188 const DBusGMethodInfo *method)
190 return object->data + method->data_offset;
194 object_error_domain_prefix_from_object_info (const DBusGObjectInfo *info)
201 object_error_code_from_object_info (const DBusGObjectInfo *info, GQuark domain, gint code)
208 method_interface_from_object_info (const DBusGObjectInfo *object,
209 const DBusGMethodInfo *method)
211 return string_table_lookup (get_method_data (object, method), 0);
215 method_name_from_object_info (const DBusGObjectInfo *object,
216 const DBusGMethodInfo *method)
218 return string_table_lookup (get_method_data (object, method), 1);
222 method_arg_info_from_object_info (const DBusGObjectInfo *object,
223 const DBusGMethodInfo *method)
225 return string_table_lookup (get_method_data (object, method), 3);/*RB was 2*/
237 * @data: a pointer to the beginning of an argument entry in a string table
238 * @name: (out) (allow-none): used to return the name of the next argument
239 * @in: (out) (allow-none): used to return %TRUE for an "in" argument or
240 * %FALSE for an "out" argument
241 * @constval: (out) (allow-none): used to return %TRUE if the argument is
242 * an "out" argument and has the "C" (const) flag indicating that it
243 * should not be freed after it is returned; normally, "out" arguments
245 * @retval: (out) (allow-none): used to return %RETVAL_NONE if this
246 * D-Bus argument is not an "out" argument or is obtained like a C "out"
247 * parameter, %RETVAL_ERROR if this argument is obtained from the C
248 * return value and is also used to signal errors, or %RETVAL_NOERROR
249 * if this argument is obtained from the C return value and the method
250 * can never raise an error
251 * @type: (out) (allow-none): used to return the D-Bus signature of this
254 * The data format is:
260 * if direction == "O":
268 * If none of the arguments has @retval != %RETVAL_NONE, the method is
269 * assumed to return a gboolean, which behaves like %RETVAL_ERROR but is
270 * not sent over D-Bus at all.
272 * Returns: the value of @data to use for the next call, or a pointer to '\0'
273 * if this function must not be called again
276 arg_iterate (const char *data,
288 data = string_table_next (data);
298 g_warning ("invalid arg direction '%c'", *data);
307 data = string_table_next (data);
319 g_warning ("invalid arg const value '%c'", *data);
322 data = string_table_next (data);
327 *retval = RETVAL_NONE;
331 *retval = RETVAL_ERROR;
335 *retval = RETVAL_NOERROR;
338 g_warning ("invalid arg ret value '%c'", *data);
350 data = string_table_next (data);
354 return string_table_next (data);
358 method_dir_signature_from_object_info (const DBusGObjectInfo *object,
359 const DBusGMethodInfo *method,
365 arg = method_arg_info_from_object_info (object, method);
367 ret = g_string_new (NULL);
375 arg = arg_iterate (arg, &name, &arg_in, NULL, NULL, &type);
378 g_string_append (ret, type);
381 return g_string_free (ret, FALSE);
385 method_input_signature_from_object_info (const DBusGObjectInfo *object,
386 const DBusGMethodInfo *method)
388 return method_dir_signature_from_object_info (object, method, TRUE);
392 method_output_signature_from_object_info (const DBusGObjectInfo *object,
393 const DBusGMethodInfo *method)
395 return method_dir_signature_from_object_info (object, method, FALSE);
399 signal_iterate (const char *data, const char **iface, const char **name)
403 data = string_table_next (data);
406 return string_table_next (data);
410 property_iterate (const char *data,
413 const char **exported_name,
414 const char **name_uscored,
415 const char **access_type)
419 data = string_table_next (data);
420 *exported_name = data;
422 data = string_table_next (data);
423 if (format_version == 1)
425 *name_uscored = data;
426 data = string_table_next (data);
428 return string_table_next (data);
432 /* This tells the caller they need to compute it */
433 *name_uscored = NULL;
434 /* We don't know here, however note that we will still check against the
435 * readable/writable flags from GObject's metadata.
437 *access_type = "readwrite";
443 * property_info_from_object_info:
444 * @object: introspection data
445 * @interface_name: (allow-none): Expected interface name, or %NULL for any
446 * @property_name: Expected property name (can use "-" or "_" as separator)
447 * @access_type: (out): Can be one of "read", "write", "readwrite"
449 * Look up property introspection data for the given interface/name pair.
451 * Returns: %TRUE if property was found
454 property_info_from_object_info (const DBusGObjectInfo *object,
455 const char *interface_name,
456 const char *property_name,
457 const char **access_type)
459 const char *properties_iter;
461 properties_iter = object->exported_properties;
462 while (properties_iter != NULL && *properties_iter)
464 const char *cur_interface_name;
465 const char *cur_property_name;
466 const char *cur_uscore_property_name;
467 const char *cur_access_type;
470 properties_iter = property_iterate (properties_iter, object->format_version,
471 &cur_interface_name, &cur_property_name,
472 &cur_uscore_property_name, &cur_access_type);
474 if (interface_name && strcmp (interface_name, cur_interface_name) != 0)
477 /* This big pile of ugly is necessary to support the matrix resulting from multiplying
478 * (v0 data, v1 data) * (FooBar, foo-bar)
479 * In v1 data we have both forms of string, so we do a comparison against both without
481 * For v0 data, we need to reconstruct the foo-bar form.
483 * Adding to the complexity is that we *also* have to ignore the distinction between
484 * '-' and '_', because g_object_{get,set} does.
486 /* First, compare against the primary property name - no malloc required */
487 if (!compare_strings_ignoring_uscore_vs_dash (property_name, cur_property_name))
489 if (cur_uscore_property_name != NULL
490 && !compare_strings_ignoring_uscore_vs_dash (property_name, cur_uscore_property_name))
494 /* v0 metadata, construct uscore */
497 tmp_uscored = _dbus_gutils_wincaps_to_uscore (cur_property_name);
498 matches = compare_strings_ignoring_uscore_vs_dash (property_name, tmp_uscored);
499 g_free (tmp_uscored);
505 *access_type = cur_access_type;
512 dbus_g_object_type_dbus_metadata_quark (void)
517 quark = g_quark_from_static_string ("DBusGObjectTypeDBusMetadataQuark");
521 /* Iterator function should return FALSE to stop iteration, TRUE to continue */
522 typedef gboolean (*ForeachObjectInfoFn) (const DBusGObjectInfo *info,
527 foreach_object_info (GObject *object,
528 ForeachObjectInfoFn callback,
531 GType *interfaces, *p;
532 const DBusGObjectInfo *info;
535 interfaces = g_type_interfaces (G_TYPE_FROM_INSTANCE (object), NULL);
537 for (p = interfaces; *p != 0; p++)
539 info = g_type_get_qdata (*p, dbus_g_object_type_dbus_metadata_quark ());
540 if (info != NULL && info->format_version >= 0)
542 if (!callback (info, *p, user_data))
549 for (classtype = G_TYPE_FROM_INSTANCE (object); classtype != 0; classtype = g_type_parent (classtype))
551 info = g_type_get_qdata (classtype, dbus_g_object_type_dbus_metadata_quark ());
552 if (info != NULL && info->format_version >= 0)
554 if (!callback (info, classtype, user_data))
562 lookup_object_info_cb (const DBusGObjectInfo *info,
566 GList **list = (GList **) user_data;
568 *list = g_list_prepend (*list, (gpointer) info);
573 lookup_object_info (GObject *object)
575 GList *info_list = NULL;
577 foreach_object_info (object, lookup_object_info_cb, &info_list);
584 const DBusGObjectInfo *info;
587 } LookupObjectInfoByIfaceData;
590 lookup_object_info_by_iface_cb (const DBusGObjectInfo *info,
594 LookupObjectInfoByIfaceData *lookup_data = (LookupObjectInfoByIfaceData *) user_data;
596 /* If interface is not specified, choose the first info */
597 if (lookup_data->fallback && (!lookup_data->iface || strlen (lookup_data->iface) == 0))
599 lookup_data->info = info;
600 lookup_data->iface_type = gtype;
602 else if (info->exported_properties && !strcmp (info->exported_properties, lookup_data->iface))
604 lookup_data->info = info;
605 lookup_data->iface_type = gtype;
608 return !lookup_data->info;
611 static const DBusGObjectInfo *
612 lookup_object_info_by_iface (GObject *object,
615 GType *out_iface_type)
617 LookupObjectInfoByIfaceData data;
621 data.fallback = fallback;
624 foreach_object_info (object, lookup_object_info_by_iface_cb, &data);
626 if (out_iface_type && data.info)
627 *out_iface_type = data.iface_type;
634 GSList *registrations;
635 /* weak ref, or NULL if the object has been disposed */
640 /* pseudo-weak ref, never NULL */
641 DBusGConnection *connection;
642 /* owned, never NULL */
644 /* borrowed pointer to parent, never NULL */
645 ObjectExport *export;
646 } ObjectRegistration;
648 static void object_export_object_died (gpointer user_data, GObject *dead);
651 object_export_unregister_all (ObjectExport *oe)
653 while (oe->registrations != NULL)
655 GSList *old = oe->registrations;
656 ObjectRegistration *o = oe->registrations->data;
658 dbus_connection_unregister_object_path (
659 DBUS_CONNECTION_FROM_G_CONNECTION (o->connection), o->object_path);
661 /* the link should have been removed by doing that */
662 g_assert (oe->registrations != old);
667 object_export_free (ObjectExport *oe)
669 g_slice_free (ObjectExport, oe);
672 static ObjectExport *
673 object_export_new (void)
675 return g_slice_new0 (ObjectExport);
678 static ObjectRegistration *
679 object_registration_new (DBusGConnection *connection,
680 const gchar *object_path,
681 ObjectExport *export)
683 ObjectRegistration *o = g_slice_new0 (ObjectRegistration);
685 o->connection = connection;
686 o->object_path = g_strdup (object_path);
693 object_registration_free (ObjectRegistration *o)
695 g_assert (o->export != NULL);
696 o->export->registrations = g_slist_remove (o->export->registrations, o);
698 g_free (o->object_path);
700 g_slice_free (ObjectRegistration, o);
703 /* Called when the object falls off the bus (e.g. because connection just
706 object_registration_unregistered (DBusConnection *connection,
709 object_registration_free (user_data);
717 const DBusGObjectInfo *object_info;
718 } DBusGLibWriteIterfaceData;
725 } DBusGLibWriteInterfaceValues;
728 write_interface (gpointer key, gpointer val, gpointer user_data)
735 const DBusGObjectInfo *object_info;
736 DBusGLibWriteIterfaceData *data;
737 DBusGLibWriteInterfaceValues *values;
742 methods = values->methods;
743 signals = values->signals;
744 properties = values->properties;
748 object_info = data->object_info;
750 g_string_append_printf (xml, " <interface name=\"%s\">\n", name);
752 /* FIXME: recurse to parent types ? */
753 for (; methods; methods = methods->next)
755 DBusGMethodInfo *method;
757 method = methods->data;
759 g_string_append_printf (xml, " <method name=\"%s\">\n",
760 method_name_from_object_info (object_info, method));
762 args = method_arg_info_from_object_info (object_info, method);
770 args = arg_iterate (args, &name, &arg_in, NULL, NULL, &type);
772 /* FIXME - handle container types */
773 g_string_append_printf (xml, " <arg name=\"%s\" type=\"%s\" direction=\"%s\"/>\n",
774 name, type, arg_in ? "in" : "out");
777 g_string_append (xml, " </method>\n");
780 g_slist_free (values->methods);
782 for (; signals; signals = signals->next)
790 signame = signals->data;
792 s = _dbus_gutils_wincaps_to_uscore (signame);
794 id = g_signal_lookup (s, data->gtype);
797 g_signal_query (id, &query);
798 g_assert (query.return_type == G_TYPE_NONE);
800 g_string_append_printf (xml, " <signal name=\"%s\">\n", signame);
802 for (arg = 0; arg < query.n_params; arg++)
804 char *dbus_type = _dbus_gtype_to_signature (query.param_types[arg]);
806 g_assert (dbus_type != NULL);
808 g_string_append (xml, " <arg type=\"");
809 g_string_append (xml, dbus_type);
810 g_string_append (xml, "\"/>\n");
814 g_string_append (xml, " </signal>\n");
817 g_slist_free (values->signals);
819 for (; properties; properties = properties->next)
822 const char *propname;
823 const char *propname_uscore;
824 const char *access_type;
833 property_iterate (properties->data, object_info->format_version, &iface, &propname, &propname_uscore, &access_type);
835 s = lookup_property_name (data->object, name, propname);
837 spec = g_object_class_find_property (g_type_class_peek (data->gtype), s);
838 g_assert (spec != NULL);
841 dbus_type = _dbus_gtype_to_signature (G_PARAM_SPEC_VALUE_TYPE (spec));
842 g_assert (dbus_type != NULL);
844 can_set = strcmp (access_type, "readwrite") == 0
845 && ((spec->flags & G_PARAM_WRITABLE) != 0
846 && (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
848 can_get = (spec->flags & G_PARAM_READABLE) != 0;
850 if (can_set || can_get)
852 g_string_append_printf (xml, " <property name=\"%s\" ", propname);
853 g_string_append (xml, "type=\"");
854 g_string_append (xml, dbus_type);
855 g_string_append (xml, "\" access=\"");
857 if (can_set && can_get)
858 g_string_append (xml, "readwrite");
860 g_string_append (xml, "read");
864 g_string_append (xml, "write");
867 g_string_append (xml, "\"/>\n");
872 g_slist_free (values->properties);
875 g_string_append (xml, " </interface>\n");
878 static DBusGLibWriteInterfaceValues *
879 lookup_values (GHashTable *interfaces, const char *method_interface)
881 DBusGLibWriteInterfaceValues *values;
882 if ((values = g_hash_table_lookup (interfaces, (gpointer) method_interface)) == NULL)
884 values = g_new0 (DBusGLibWriteInterfaceValues, 1);
885 g_hash_table_insert (interfaces, (gpointer) method_interface, values);
891 introspect_interfaces (GObject *object, GString *xml)
894 const GList *info_list_walk;
895 const DBusGObjectInfo *info;
896 DBusGLibWriteIterfaceData data;
898 GHashTable *interfaces;
899 DBusGLibWriteInterfaceValues *values;
902 info_list = lookup_object_info (object);
904 g_assert (info_list != NULL);
906 /* Gather a list of all interfaces, indexed into their methods */
907 for (info_list_walk = info_list; info_list_walk != NULL; info_list_walk = g_list_next (info_list_walk))
909 info = (DBusGObjectInfo *) info_list_walk->data;
910 interfaces = g_hash_table_new (g_str_hash, g_str_equal);
912 g_assert (info != NULL);
914 for (i = 0; i < info->n_method_infos; i++)
916 const char *method_interface;
917 const DBusGMethodInfo *method;
919 method = &(info->method_infos[i]);
921 method_interface = method_interface_from_object_info (info, method);
923 values = lookup_values (interfaces, method_interface);
924 values->methods = g_slist_prepend (values->methods, (gpointer) method);
927 propsig = info->exported_signals;
928 while (propsig != NULL && *propsig)
933 propsig = signal_iterate (propsig, &iface, &signame);
935 values = lookup_values (interfaces, iface);
936 values->signals = g_slist_prepend (values->signals, (gpointer) signame);
939 propsig = info->exported_properties;
940 while (propsig != NULL && *propsig)
943 const char *propname;
944 const char *propname_uscore;
945 const char *access_type;
947 propsig = property_iterate (propsig, info->format_version, &iface, &propname, &propname_uscore, &access_type);
949 values = lookup_values (interfaces, iface);
950 values->properties = g_slist_prepend (values->properties, (gpointer)iface);
953 memset (&data, 0, sizeof (data));
955 data.gtype = G_TYPE_FROM_INSTANCE (object);
956 data.object_info = info;
957 data.object = object;
959 g_hash_table_foreach (interfaces, write_interface, &data);
960 g_hash_table_destroy (interfaces);
963 g_list_free (info_list);
966 static DBusHandlerResult
967 handle_introspect (DBusConnection *connection,
968 DBusMessage *message,
976 if (!dbus_connection_list_registered (connection,
977 dbus_message_get_path (message),
981 xml = g_string_new (NULL);
983 g_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
985 g_string_append (xml, "<node>\n");
987 /* We are introspectable, though I guess that was pretty obvious */
988 g_string_append_printf (xml, " <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE);
989 g_string_append (xml, " <method name=\"Introspect\">\n");
990 g_string_append_printf (xml, " <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
991 g_string_append (xml, " </method>\n");
992 g_string_append (xml, " </interface>\n");
994 /* We support get/set/getall properties */
995 g_string_append_printf (xml, " <interface name=\"%s\">\n", DBUS_INTERFACE_PROPERTIES);
996 g_string_append (xml, " <method name=\"Get\">\n");
997 g_string_append_printf (xml, " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
998 g_string_append_printf (xml, " <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
999 g_string_append_printf (xml, " <arg name=\"value\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_VARIANT_AS_STRING);
1000 g_string_append (xml, " </method>\n");
1001 g_string_append (xml, " <method name=\"Set\">\n");
1002 g_string_append_printf (xml, " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
1003 g_string_append_printf (xml, " <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
1004 g_string_append_printf (xml, " <arg name=\"value\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_VARIANT_AS_STRING);
1005 g_string_append (xml, " </method>\n");
1006 g_string_append (xml, " <method name=\"GetAll\">\n");
1007 g_string_append_printf (xml, " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
1008 g_string_append_printf (xml, " <arg name=\"props\" direction=\"out\" type=\"%s\"/>\n",
1009 DBUS_TYPE_ARRAY_AS_STRING
1010 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1011 DBUS_TYPE_STRING_AS_STRING
1012 DBUS_TYPE_VARIANT_AS_STRING
1013 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
1016 g_string_append (xml, " </method>\n");
1017 g_string_append (xml, " </interface>\n");
1019 introspect_interfaces (object, xml);
1021 /* Append child nodes */
1022 for (i = 0; children[i]; i++)
1023 g_string_append_printf (xml, " <node name=\"%s\"/>\n",
1026 /* Close the XML, and send it to the requesting app */
1027 g_string_append (xml, "</node>\n");
1029 ret = reply_or_die (message);
1031 dbus_message_append_args (ret,
1032 DBUS_TYPE_STRING, &xml->str,
1035 connection_send_or_die (connection, ret);
1036 dbus_message_unref (ret);
1038 g_string_free (xml, TRUE);
1040 dbus_free_string_array (children);
1042 return DBUS_HANDLER_RESULT_HANDLED;
1046 set_object_property (DBusConnection *connection,
1047 DBusMessage *message,
1048 DBusMessageIter *iter,
1052 GValue value = { 0, };
1054 DBusMessageIter sub;
1055 DBusGValueMarshalCtx context;
1057 dbus_message_iter_recurse (iter, &sub);
1059 context.recursion_depth = 0;
1060 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
1061 context.proxy = NULL;
1063 g_value_init (&value, pspec->value_type);
1064 if (_dbus_gvalue_demarshal (&context, &sub, &value, NULL))
1066 g_object_set_property (object,
1070 g_value_unset (&value);
1072 ret = reply_or_die (message);
1076 ret = error_or_die (message,
1077 DBUS_ERROR_INVALID_ARGS,
1078 "Argument's D-BUS type can't be converted to a GType");
1085 * @pspec: the paramspec for a D-Bus-exported property
1087 * Returns: a reply for the Get() D-Bus method, either successful or error
1090 get_object_property (DBusConnection *connection,
1091 DBusMessage *message,
1096 GValue value = {0, };
1099 DBusMessageIter iter, subiter;
1100 gchar *error_message = NULL;
1102 ret = reply_or_die (message);
1104 g_value_init (&value, pspec->value_type);
1105 g_object_get_property (object, pspec->name, &value);
1107 variant_sig = _dbus_gvalue_to_signature (&value);
1108 if (variant_sig == NULL)
1110 value_gtype = G_VALUE_TYPE (&value);
1111 error_message = g_strdup_printf (
1112 "Internal error: cannot marshal type \"%s\" in variant",
1113 g_type_name (value_gtype));
1117 dbus_message_iter_init_append (ret, &iter);
1118 if (!dbus_message_iter_open_container (&iter,
1123 error_message = g_strdup_printf (
1124 "Internal error: cannot open variant container for signature %s",
1129 if (!_dbus_gvalue_marshal (&subiter, &value))
1131 dbus_message_iter_abandon_container (&iter, &subiter);
1132 error_message = g_strdup_printf (
1133 "Internal error: could not marshal type \"%s\" in variant",
1134 G_VALUE_TYPE_NAME (&value));
1138 dbus_message_iter_close_container (&iter, &subiter);
1141 g_value_unset (&value);
1142 g_free (variant_sig);
1144 if (error_message != NULL)
1146 dbus_message_unref (ret);
1147 ret = error_or_die (message, DBUS_ERROR_FAILED, error_message);
1148 g_critical ("%s", error_message);
1149 g_free (error_message);
1155 #define SHADOW_PROP_QUARK (dbus_g_object_type_dbus_shadow_property_quark ())
1158 dbus_g_object_type_dbus_shadow_property_quark (void)
1160 static GQuark quark;
1163 quark = g_quark_from_static_string ("DBusGObjectTypeDBusShadowPropertyQuark");
1167 /* Look for shadow properties on the given interface first, otherwise
1168 * just return the original property name. This allows implementations to
1169 * get around the glib limitation of unique property names among all
1170 * GInterfaces by registering a "shadow" property name that the get/set
1171 * request will be redirected to.
1173 * Shadow property data is stored as qdata on each GInterface. If there
1174 * is no interface info, or there is no registered shadow property, just
1175 * return the original property name.
1178 lookup_property_name (GObject *object,
1179 const char *wincaps_propiface,
1180 const char *requested_propname)
1182 const DBusGObjectInfo *object_info;
1183 GHashTable *shadow_props;
1184 char *shadow_prop_name = NULL, *uscore_name;
1185 GType iface_type = 0;
1187 g_assert (wincaps_propiface != NULL);
1188 g_assert (requested_propname != NULL);
1190 uscore_name = _dbus_gutils_wincaps_to_uscore (requested_propname);
1192 object_info = lookup_object_info_by_iface (object, wincaps_propiface, FALSE, &iface_type);
1196 shadow_props = (GHashTable *) g_type_get_qdata (iface_type, SHADOW_PROP_QUARK);
1199 shadow_prop_name = g_strdup (g_hash_table_lookup (shadow_props, requested_propname));
1200 if (shadow_prop_name)
1201 g_free (uscore_name);
1204 return shadow_prop_name ? shadow_prop_name : uscore_name;
1208 * dbus_g_object_type_register_shadow_property:
1209 * @iface_type: #GType for the #GInterface
1210 * @dbus_prop_name: D-Bus property name (as specified in the introspection data)
1211 * to override with the shadow property name (as specified in the GType's
1212 * initialization function, ie glib-style)
1213 * @shadow_prop_name: property name which should override the shadow property
1215 * Registers a new property name @shadow_prop_name that overrides the
1216 * @dbus_prop_name in D-Bus property get/set requests. Since all properties for
1217 * all interfaces implemented by a GObject exist in the same namespace, this
1218 * allows implementations to use the same property name in two or more D-Bus
1219 * interfaces implemented by the same GObject, as long as one of those D-Bus
1220 * interface properties is registered with a shadow property name.
1222 * For example, if both org.foobar.Baz.InterfaceA and org.foobar.Baz.InterfaceB
1223 * have a D-Bus property called "Bork", the developer assigns a shadow property
1224 * name to the conflicting property name in one or both of these GInterfaces to
1225 * resolve the conflict. Assume the GInterface implementing
1226 * org.foobar.Baz.InterfaceA registers a shadow property called "a-bork", while
1227 * the GInterface implementing org.foobar.Baz.InterfaceB registers a shadow
1228 * property called "b-bork". The GObject implementing both these GInterfaces
1229 * would then use #g_object_class_override_property() to implement both
1230 * "a-bork" and "b-bork" and D-Bus requests for "Bork" on either D-Bus interface
1231 * will not conflict.
1234 dbus_g_object_type_register_shadow_property (GType iface_type,
1235 const char *dbus_prop_name,
1236 const char *shadow_prop_name)
1238 GHashTable *shadow_props;
1240 g_return_if_fail (G_TYPE_IS_CLASSED (iface_type) || G_TYPE_IS_INTERFACE (iface_type));
1241 g_return_if_fail (dbus_prop_name != NULL);
1242 g_return_if_fail (shadow_prop_name != NULL);
1244 shadow_props = (GHashTable *) g_type_get_qdata (iface_type, SHADOW_PROP_QUARK);
1247 shadow_props = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1248 g_type_set_qdata (iface_type,
1249 dbus_g_object_type_dbus_shadow_property_quark (),
1253 g_assert (shadow_props);
1254 g_hash_table_insert (shadow_props, g_strdup (dbus_prop_name), g_strdup (shadow_prop_name));
1258 get_all_object_properties (DBusConnection *connection,
1259 DBusMessage *message,
1260 const DBusGObjectInfo *object_info,
1261 const char *wincaps_propiface,
1265 DBusMessageIter iter_ret;
1266 DBusMessageIter iter_dict;
1267 DBusMessageIter iter_dict_entry;
1268 DBusMessageIter iter_dict_value;
1270 char *uscore_propname;
1272 ret = reply_or_die (message);
1274 dbus_message_iter_init_append (ret, &iter_ret);
1276 /* the types are all hard-coded, so this can only fail via OOM */
1277 if (!dbus_message_iter_open_container (&iter_ret,
1279 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1280 DBUS_TYPE_STRING_AS_STRING
1281 DBUS_TYPE_VARIANT_AS_STRING
1282 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1286 p = object_info->exported_properties;
1287 while (p != NULL && *p != '\0')
1289 const char *prop_ifname;
1290 const char *prop_name;
1291 const char *prop_uscored;
1292 const char *access_flags;
1295 GValue value = {0, };
1298 p = property_iterate (p, object_info->format_version, &prop_ifname, &prop_name, &prop_uscored, &access_flags);
1300 /* Conventionally, property names are valid member names, but dbus-glib
1301 * doesn't enforce this, and some dbus-glib services use GObject-style
1302 * property names (e.g. "foo-bar"). */
1303 if (!g_utf8_validate (prop_name, -1, NULL))
1305 g_critical ("property name isn't UTF-8: %s", prop_name);
1309 uscore_propname = lookup_property_name (object, wincaps_propiface, prop_name);
1311 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), uscore_propname);
1314 g_warning ("introspection data references non-existing property %s", uscore_propname);
1315 g_free (uscore_propname);
1319 g_free (uscore_propname);
1321 g_value_init (&value, pspec->value_type);
1322 g_object_get_property (object, pspec->name, &value);
1324 variant_sig = _dbus_gvalue_to_signature (&value);
1325 if (variant_sig == NULL)
1327 value_gtype = G_VALUE_TYPE (&value);
1328 g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
1329 g_value_unset (&value);
1333 /* a signature returned by _dbus_gvalue_to_signature had better be
1335 g_assert (g_variant_is_signature (variant_sig));
1337 /* type is hard-coded, so this can't fail except by OOM */
1338 if (!dbus_message_iter_open_container (&iter_dict,
1339 DBUS_TYPE_DICT_ENTRY,
1344 /* prop_name is valid UTF-8, so this can't fail except by OOM; no point
1345 * in abandoning @iter_dict_entry since we're about to crash out */
1346 if (!dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &prop_name))
1349 /* variant_sig has been asserted to be valid, so this can't fail
1351 if (!dbus_message_iter_open_container (&iter_dict_entry,
1357 g_free (variant_sig);
1359 /* this can fail via programming error: the GObject property was
1360 * malformed (non-UTF8 string or something) */
1361 if (!_dbus_gvalue_marshal (&iter_dict_value, &value))
1363 gchar *contents = g_strdup_value_contents (&value);
1364 gchar *error_message = g_strdup_printf (
1365 "cannot GetAll(%s): failed to serialize %s value of type %s: %s",
1366 wincaps_propiface, prop_name, G_VALUE_TYPE_NAME (&value),
1369 g_critical ("%s", error_message);
1372 dbus_message_iter_abandon_container (&iter_dict_entry,
1374 dbus_message_iter_abandon_container (&iter_dict, &iter_dict_entry);
1375 dbus_message_unref (ret);
1376 ret = error_or_die (message, DBUS_ERROR_FAILED, error_message);
1379 g_free (error_message);
1380 g_value_unset (&value);
1384 /* these shouldn't fail except by OOM now that we were successful */
1385 if (!dbus_message_iter_close_container (&iter_dict_entry,
1388 if (!dbus_message_iter_close_container (&iter_dict, &iter_dict_entry))
1391 g_value_unset (&value);
1394 if (!dbus_message_iter_close_container (&iter_ret, &iter_dict))
1401 lookup_object_and_method (GObject *object,
1402 DBusMessage *message,
1403 const DBusGObjectInfo **object_ret,
1404 const DBusGMethodInfo **method_ret)
1406 const char *interface;
1408 const char *signature;
1410 const GList *info_list_walk;
1411 const DBusGObjectInfo *info;
1414 interface = dbus_message_get_interface (message);
1415 member = dbus_message_get_member (message);
1416 signature = dbus_message_get_signature (message);
1418 info_list = lookup_object_info (object);
1420 for (info_list_walk = info_list; info_list_walk != NULL; info_list_walk = g_list_next (info_list_walk))
1422 info = (DBusGObjectInfo *) info_list_walk->data;
1425 for (i = 0; i < info->n_method_infos; i++)
1427 const char *expected_member;
1428 const char *expected_interface;
1429 char *expected_signature;
1430 const DBusGMethodInfo *method;
1432 method = &(info->method_infos[i]);
1434 /* Check method interface/name and input signature */
1435 expected_interface = method_interface_from_object_info (*object_ret, method);
1436 expected_member = method_name_from_object_info (*object_ret, method);
1437 expected_signature = method_input_signature_from_object_info (*object_ret, method);
1439 if ((interface == NULL
1440 || strcmp (expected_interface, interface) == 0)
1441 && strcmp (expected_member, member) == 0
1442 && strcmp (expected_signature, signature) == 0)
1444 g_free (expected_signature);
1445 *method_ret = method;
1446 g_list_free (info_list);
1449 g_free (expected_signature);
1454 g_list_free (info_list);
1460 gerror_domaincode_to_dbus_error_name (const DBusGObjectInfo *object_info,
1461 const char *msg_interface,
1462 GQuark domain, gint code)
1464 const char *domain_str;
1465 const char *code_str;
1466 GString *dbus_error_name;
1468 domain_str = object_error_domain_prefix_from_object_info (object_info);
1469 code_str = object_error_code_from_object_info (object_info, domain, code);
1471 if (!domain_str || !code_str)
1473 DBusGErrorInfo *info;
1475 g_static_rw_lock_reader_lock (&globals_lock);
1477 if (error_metadata != NULL)
1478 info = g_datalist_id_get_data (&error_metadata, domain);
1482 g_static_rw_lock_reader_unlock (&globals_lock);
1489 klass = g_type_class_ref (info->code_enum);
1490 value = g_enum_get_value (klass, code);
1491 g_type_class_unref (klass);
1493 domain_str = info->default_iface;
1496 code_str = value->value_nick;
1500 g_warning ("Error code %d out of range for GError domain %s",
1501 code, g_quark_to_string (domain));
1508 domain_str = msg_interface;
1510 if (!domain_str || !code_str)
1512 const char *domain_string;
1513 /* If we can't map it sensibly, make up an error name */
1515 dbus_error_name = g_string_new ("org.freedesktop.DBus.GLib.UnmappedError.");
1517 domain_string = g_quark_to_string (domain);
1518 if (domain_string != NULL)
1520 char *uscored = uscore_to_wincaps (domain_string);
1521 g_string_append (dbus_error_name, uscored);
1522 g_string_append_c (dbus_error_name, '.');
1526 /* Map -1 to (unsigned) -1 to avoid "-", which is not valid */
1527 g_string_append_printf (dbus_error_name, "Code%u", (unsigned) code);
1531 gchar *code_str_wincaps;
1532 dbus_error_name = g_string_new (domain_str);
1533 g_string_append_c (dbus_error_name, '.');
1534 /* We can't uppercase here for backwards compatibility
1535 * reasons; if someone had a lowercase enumeration value,
1536 * previously we'd just send it across unaltered.
1538 code_str_wincaps = uscore_to_wincaps_full (code_str, FALSE, FALSE);
1539 g_string_append (dbus_error_name, code_str_wincaps);
1540 g_free (code_str_wincaps);
1543 return g_string_free (dbus_error_name, FALSE);
1546 static DBusMessage *
1547 gerror_to_dbus_error_message (const DBusGObjectInfo *object_info,
1548 DBusMessage *message,
1549 const GError *error)
1557 error_msg = g_strdup_printf ("Method invoked for %s returned FALSE but did not set error", dbus_message_get_member (message));
1558 reply = error_or_die (message, "org.freedesktop.DBus.GLib.ErrorError", error_msg);
1563 if (error->domain == DBUS_GERROR)
1565 const gchar *name = DBUS_ERROR_FAILED;
1567 switch (error->code)
1569 case DBUS_GERROR_FAILED:
1570 name = DBUS_ERROR_FAILED;
1572 case DBUS_GERROR_NO_MEMORY:
1573 name = DBUS_ERROR_NO_MEMORY;
1575 case DBUS_GERROR_SERVICE_UNKNOWN:
1576 name = DBUS_ERROR_SERVICE_UNKNOWN;
1578 case DBUS_GERROR_NAME_HAS_NO_OWNER:
1579 name = DBUS_ERROR_NAME_HAS_NO_OWNER;
1581 case DBUS_GERROR_NO_REPLY:
1582 name = DBUS_ERROR_NO_REPLY;
1584 case DBUS_GERROR_IO_ERROR:
1585 name = DBUS_ERROR_IO_ERROR;
1587 case DBUS_GERROR_BAD_ADDRESS:
1588 name = DBUS_ERROR_BAD_ADDRESS;
1590 case DBUS_GERROR_NOT_SUPPORTED:
1591 name = DBUS_ERROR_NOT_SUPPORTED;
1593 case DBUS_GERROR_LIMITS_EXCEEDED:
1594 name = DBUS_ERROR_LIMITS_EXCEEDED;
1596 case DBUS_GERROR_ACCESS_DENIED:
1597 name = DBUS_ERROR_ACCESS_DENIED;
1599 case DBUS_GERROR_AUTH_FAILED:
1600 name = DBUS_ERROR_AUTH_FAILED;
1602 case DBUS_GERROR_NO_SERVER:
1603 name = DBUS_ERROR_NO_SERVER;
1605 case DBUS_GERROR_TIMEOUT:
1606 name = DBUS_ERROR_TIMEOUT;
1608 case DBUS_GERROR_NO_NETWORK:
1609 name = DBUS_ERROR_NO_NETWORK;
1611 case DBUS_GERROR_ADDRESS_IN_USE:
1612 name = DBUS_ERROR_ADDRESS_IN_USE;
1614 case DBUS_GERROR_DISCONNECTED:
1615 name = DBUS_ERROR_DISCONNECTED;
1617 case DBUS_GERROR_INVALID_ARGS:
1618 name = DBUS_ERROR_INVALID_ARGS;
1620 case DBUS_GERROR_FILE_NOT_FOUND:
1621 name = DBUS_ERROR_FILE_NOT_FOUND;
1623 case DBUS_GERROR_REMOTE_EXCEPTION:
1624 name = dbus_g_error_get_name ((GError*) error);
1628 reply = error_or_die (message, name, error->message);
1633 error_name = gerror_domaincode_to_dbus_error_name (object_info,
1634 dbus_message_get_interface (message),
1635 error->domain, error->code);
1636 reply = error_or_die (message, error_name, error->message);
1637 g_free (error_name);
1645 * SECTION:dbus-gmethod
1646 * @short_description: GMethod Info & Invocation
1647 * @see_also: #DBusGMessage
1648 * @stability: Stable
1650 * These types are used to call methods on #GObject objects.
1654 * DBusGMethodInvocation:
1656 * The context of an asynchronous method call. See dbus_g_method_return() and
1657 * dbus_g_method_return_error().
1659 struct _DBusGMethodInvocation {
1660 DBusGConnection *connection; /**< The connection */
1661 DBusGMessage *message; /**< The message which generated the method call */
1662 const DBusGObjectInfo *object; /**< The object the method was called on */
1663 const DBusGMethodInfo *method; /**< The method called */
1664 gboolean send_reply;
1667 static DBusHandlerResult
1668 invoke_object_method (GObject *object,
1669 const DBusGObjectInfo *object_info,
1670 const DBusGMethodInfo *method,
1671 DBusConnection *connection,
1672 DBusMessage *message)
1674 gboolean had_error, is_async, send_reply;
1676 GValueArray *value_array;
1677 GValue return_value = {0,};
1680 GArray *out_param_values = NULL;
1681 GValueArray *out_param_gvalues = NULL;
1682 int out_param_count;
1683 int out_param_pos, out_param_gvalue_pos;
1684 DBusMessage *reply = NULL;
1685 gboolean have_retval;
1686 gboolean retval_signals_error;
1687 gboolean retval_is_synthetic;
1688 gboolean retval_is_constant;
1689 const char *arg_metadata;
1693 /* This flag says whether invokee is handed a special DBusGMethodInvocation structure,
1694 * instead of being required to fill out all return values in the context of the function.
1695 * Some additional data is also exposed, such as the message sender.
1697 is_async = strcmp (string_table_lookup (get_method_data (object_info, method), 2), "A") == 0;
1699 /* Messages can be sent with a flag that says "I don't need a reply". This is an optimization
1700 * normally, but in the context of the system bus it's important to not send a reply
1701 * to these kinds of messages, because they will be unrequested replies, and thus subject
1702 * to denial and logging. We don't want to fill up logs.
1703 * http://bugs.freedesktop.org/show_bug.cgi?id=19441
1705 send_reply = !dbus_message_get_no_reply (message);
1707 have_retval = FALSE;
1708 retval_signals_error = FALSE;
1709 retval_is_synthetic = FALSE;
1710 retval_is_constant = FALSE;
1712 /* This is evil. We do this to work around the fact that
1713 * the generated glib marshallers check a flag in the closure object
1714 * which we don't care about. We don't need/want to create
1715 * a new closure for each invocation.
1717 memset (&closure, 0, sizeof (closure));
1719 in_signature = method_input_signature_from_object_info (object_info, method);
1721 /* Convert method IN parameters to GValueArray */
1723 GArray *types_array;
1726 DBusGValueMarshalCtx context;
1727 GError *error = NULL;
1729 context.recursion_depth = 0;
1730 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
1731 context.proxy = NULL;
1733 types_array = _dbus_gtypes_from_arg_signature (in_signature, FALSE);
1734 n_params = types_array->len;
1735 types = (const GType*) types_array->data;
1737 value_array = _dbus_gvalue_demarshal_message (&context, message, n_params, types, &error);
1738 if (value_array == NULL)
1740 g_free (in_signature);
1741 g_array_free (types_array, TRUE);
1742 reply = error_or_die (message, "org.freedesktop.DBus.GLib.ErrorError", error->message);
1743 connection_send_or_die (connection, reply);
1744 dbus_message_unref (reply);
1745 g_error_free (error);
1746 return DBUS_HANDLER_RESULT_HANDLED;
1748 g_array_free (types_array, TRUE);
1751 /* Prepend object as first argument */
1752 g_value_array_prepend (value_array, NULL);
1753 g_value_init (g_value_array_get_nth (value_array, 0), G_TYPE_OBJECT);
1754 g_value_set_object (g_value_array_get_nth (value_array, 0), object);
1758 GValue context_value = {0,};
1759 DBusGMethodInvocation *context;
1760 context = g_new (DBusGMethodInvocation, 1);
1761 context->connection = dbus_g_connection_ref (DBUS_G_CONNECTION_FROM_CONNECTION (connection));
1762 context->message = dbus_g_message_ref (DBUS_G_MESSAGE_FROM_MESSAGE (message));
1763 context->object = object_info;
1764 context->method = method;
1765 context->send_reply = send_reply;
1766 g_value_init (&context_value, G_TYPE_POINTER);
1767 g_value_set_pointer (&context_value, context);
1768 g_value_array_append (value_array, &context_value);
1777 arg_metadata = method_arg_info_from_object_info (object_info, method);
1779 /* Count number of output parameters, and look for a return value */
1780 out_param_count = 0;
1781 while (*arg_metadata)
1783 arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, &arg_const, &retval, &argsig);
1786 if (retval != RETVAL_NONE)
1788 DBusSignatureIter tmp_sigiter;
1789 /* This is the function return value */
1790 g_assert (!have_retval);
1792 retval_is_synthetic = FALSE;
1797 g_assert_not_reached ();
1799 case RETVAL_NOERROR:
1800 retval_signals_error = FALSE;
1803 retval_signals_error = TRUE;
1807 retval_is_constant = arg_const;
1809 /* Initialize our return GValue with the specified type */
1810 dbus_signature_iter_init (&tmp_sigiter, argsig);
1811 g_value_init (&return_value, _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE));
1815 /* It's a regular output value */
1820 /* For compatibility, if we haven't found a return value, we assume
1821 * the function returns a gboolean for signalling an error
1822 * (and therefore also takes a GError). We also note that it
1823 * is a "synthetic" return value; i.e. we aren't going to be
1824 * sending it over the bus, it's just to signal an error.
1829 retval_is_synthetic = TRUE;
1830 retval_signals_error = TRUE;
1831 g_value_init (&return_value, G_TYPE_BOOLEAN);
1834 /* Create an array to store the actual values of OUT parameters
1835 * (other than the real function return, if any). Then, create
1836 * a GValue boxed POINTER to each of those values, and append to
1837 * the invocation, so the method can return the OUT parameters.
1839 out_param_values = g_array_sized_new (FALSE, TRUE, sizeof (GTypeCValue), out_param_count);
1841 /* We have a special array of GValues for toplevel GValue return
1844 out_param_gvalues = g_value_array_new (out_param_count);
1846 out_param_gvalue_pos = 0;
1848 /* Reset argument metadata pointer */
1849 arg_metadata = method_arg_info_from_object_info (object_info, method);
1851 /* Iterate over output arguments again, this time allocating space for
1852 * them as appopriate.
1854 while (*arg_metadata)
1856 GValue value = {0, };
1857 GTypeCValue storage;
1858 DBusSignatureIter tmp_sigiter;
1859 GType current_gtype;
1861 arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, NULL, &retval, &argsig);
1862 /* Skip over input arguments and the return value, if any */
1863 if (arg_in || retval != RETVAL_NONE)
1866 dbus_signature_iter_init (&tmp_sigiter, argsig);
1867 current_gtype = _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE);
1869 g_value_init (&value, G_TYPE_POINTER);
1871 /* We special case variants to make method invocation a bit nicer */
1872 if (current_gtype != G_TYPE_VALUE)
1874 memset (&storage, 0, sizeof (storage));
1875 g_array_append_val (out_param_values, storage);
1876 g_value_set_pointer (&value, &(g_array_index (out_param_values, GTypeCValue, out_param_pos)));
1881 g_value_array_append (out_param_gvalues, NULL);
1882 g_value_set_pointer (&value, out_param_gvalues->values + out_param_gvalue_pos);
1883 out_param_gvalue_pos++;
1885 g_value_array_append (value_array, &value);
1889 /* Append GError as final argument if necessary */
1890 if (retval_signals_error)
1892 g_assert (have_retval);
1893 g_value_array_append (value_array, NULL);
1894 g_value_init (g_value_array_get_nth (value_array, value_array->n_values - 1), G_TYPE_POINTER);
1895 g_value_set_pointer (g_value_array_get_nth (value_array, value_array->n_values - 1), &gerror);
1898 /* Actually invoke method */
1899 method->marshaller (&closure, have_retval ? &return_value : NULL,
1900 value_array->n_values,
1901 value_array->values,
1902 NULL, method->function);
1908 if (retval_signals_error)
1909 had_error = _dbus_gvalue_signals_error (&return_value);
1915 DBusMessageIter iter;
1917 /* Careful here - there are two major cases in this section of the code.
1918 * If send_reply is TRUE, we're constructing a dbus message and freeing
1919 * the return values. If it's FALSE, then we just need to free the
1924 reply = reply_or_die (message);
1926 /* Append output arguments to reply */
1927 dbus_message_iter_init_append (reply, &iter);
1930 /* First, append the return value, unless it's synthetic */
1931 if (have_retval && !retval_is_synthetic)
1933 if (reply != NULL && !_dbus_gvalue_marshal (&iter, &return_value))
1935 gchar *desc = g_strdup_value_contents (&return_value);
1937 g_critical ("unable to append retval of type %s for %s: %s",
1938 G_VALUE_TYPE_NAME (&return_value),
1939 method_name_from_object_info (object_info, method),
1942 /* the reply is now unusable but we still need to free
1944 dbus_message_unref (reply);
1948 if (!retval_is_constant)
1949 g_value_unset (&return_value);
1952 /* Grab the argument metadata and iterate over it */
1953 arg_metadata = method_arg_info_from_object_info (object_info, method);
1955 /* Now append any remaining return values */
1957 out_param_gvalue_pos = 0;
1958 while (*arg_metadata)
1960 GValue gvalue = {0, };
1961 const char *arg_name;
1965 const char *arg_signature;
1966 DBusSignatureIter argsigiter;
1970 /* Iterate over only output values; skip over input
1971 arguments and the return value */
1972 arg_metadata = arg_iterate (arg_metadata, &arg_name, &arg_in, &constval, &retval, &arg_signature);
1974 while ((arg_in || retval != RETVAL_NONE) && *arg_metadata);
1976 /* If the last argument we saw was input or the return
1977 * value, we must be done iterating over output arguments.
1979 if (arg_in || retval != RETVAL_NONE)
1982 dbus_signature_iter_init (&argsigiter, arg_signature);
1984 g_value_init (&gvalue, _dbus_gtype_from_signature_iter (&argsigiter, FALSE));
1985 if (G_VALUE_TYPE (&gvalue) != G_TYPE_VALUE)
1987 if (!_dbus_gvalue_take (&gvalue,
1988 &(g_array_index (out_param_values, GTypeCValue, out_param_pos))))
1989 g_assert_not_reached ();
1994 g_value_set_static_boxed (&gvalue, out_param_gvalues->values + out_param_gvalue_pos);
1995 out_param_gvalue_pos++;
1998 if (reply && !_dbus_gvalue_marshal (&iter, &gvalue))
2000 gchar *desc = g_strdup_value_contents (&gvalue);
2002 g_critical ("unable to append OUT arg of type %s for %s: %s",
2003 G_VALUE_TYPE_NAME (&gvalue),
2004 method_name_from_object_info (object_info, method),
2007 /* the reply is now unusable but we still need to free
2009 dbus_message_unref (reply);
2013 /* Here we actually free the allocated value; we
2014 * took ownership of it with _dbus_gvalue_take, unless
2015 * an annotation has specified this value as constant.
2018 g_value_unset (&gvalue);
2021 else if (send_reply)
2022 reply = gerror_to_dbus_error_message (object_info, message, gerror);
2026 connection_send_or_die (connection, reply);
2027 dbus_message_unref (reply);
2031 g_free (in_signature);
2035 g_array_free (out_param_values, TRUE);
2036 g_value_array_free (out_param_gvalues);
2040 g_clear_error (&gerror);
2042 g_value_array_free (value_array);
2043 return DBUS_HANDLER_RESULT_HANDLED;
2047 * @wincaps_propiface: the D-Bus interface name, conventionally WindowsCaps
2048 * @requested_propname: the D-Bus property name, conventionally WindowsCaps
2049 * @uscore_propname: the GObject property name, conventionally
2050 * words_with_underscores or words-with-dashes
2051 * @is_set: %TRUE if we're going to set the property, %FALSE if we're going
2054 * Check that the requested property exists and the requested access is
2055 * allowed. If not, reply with a D-Bus AccessDenied error message.
2057 * Returns: %TRUE if property access can continue, or %FALSE if an error
2058 * reply has been sent
2061 check_property_access (DBusConnection *connection,
2062 DBusMessage *message,
2064 const char *wincaps_propiface,
2065 const char *requested_propname,
2066 const char *uscore_propname,
2069 const DBusGObjectInfo *object_info;
2070 const char *access_type;
2072 gchar *error_message;
2074 if (!is_set && !disable_legacy_property_access)
2077 object_info = lookup_object_info_by_iface (object, wincaps_propiface, TRUE, NULL);
2080 error_message = g_strdup_printf (
2081 "Interface \"%s\" isn't exported (or may not exist), can't access property \"%s\"",
2082 wincaps_propiface, requested_propname);
2087 /* Try both forms of property names: "foo_bar" or "FooBar"; for historical
2088 * reasons we accept both.
2091 && !(property_info_from_object_info (object_info, wincaps_propiface, requested_propname, &access_type)
2092 || property_info_from_object_info (object_info, wincaps_propiface, uscore_propname, &access_type)))
2094 error_message = g_strdup_printf (
2095 "Property \"%s\" of interface \"%s\" isn't exported (or may not exist)",
2096 requested_propname, wincaps_propiface);
2101 if (strcmp (access_type, "readwrite") == 0)
2104 if (is_set ? strcmp (access_type, "read") == 0
2105 : strcmp (access_type, "write") == 0)
2107 error_message = g_strdup_printf (
2108 "Property \"%s\" of interface \"%s\" is not %s",
2111 is_set ? "settable" : "readable");
2119 ret = error_or_die (message, DBUS_ERROR_ACCESS_DENIED, error_message);
2120 g_free (error_message);
2122 connection_send_or_die (connection, ret);
2123 dbus_message_unref (ret);
2127 static DBusHandlerResult
2128 object_registration_message (DBusConnection *connection,
2129 DBusMessage *message,
2138 const char *requested_propname;
2139 const char *wincaps_propiface;
2140 DBusMessageIter iter;
2141 const DBusGMethodInfo *method;
2142 const DBusGObjectInfo *object_info;
2144 ObjectRegistration *o;
2147 /* export is always non-NULL. If the object has been disposed, the weak-ref
2148 * callback removes all registrations from the DBusConnection, so this
2149 * should never be reached with object = NULL. */
2150 object = G_OBJECT (o->export->object);
2151 g_assert (object != NULL);
2153 if (dbus_message_is_method_call (message,
2154 DBUS_INTERFACE_INTROSPECTABLE,
2156 return handle_introspect (connection, message, object);
2158 /* Try the metainfo, which lets us invoke methods */
2160 if (lookup_object_and_method (object, message, &object_info, &method))
2161 return invoke_object_method (object, object_info, method, connection, message);
2163 /* If no metainfo, we can still do properties and signals
2164 * via standard GLib introspection. Note we do now check
2165 * property access against the metainfo if available.
2170 if (dbus_message_is_method_call (message,
2171 DBUS_INTERFACE_PROPERTIES,
2174 else if (dbus_message_is_method_call (message,
2175 DBUS_INTERFACE_PROPERTIES,
2178 else if (dbus_message_is_method_call (message,
2179 DBUS_INTERFACE_PROPERTIES,
2183 if (!(setter || getter || getall))
2184 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2188 dbus_message_iter_init (message, &iter);
2190 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
2192 ret = error_or_die (message, DBUS_ERROR_INVALID_ARGS,
2193 "First argument to Get(), GetAll() or Set() must be an interface string");
2197 dbus_message_iter_get_basic (&iter, &wincaps_propiface);
2198 dbus_message_iter_next (&iter);
2202 object_info = lookup_object_info_by_iface (object, wincaps_propiface, TRUE, NULL);
2203 if (object_info != NULL)
2204 ret = get_all_object_properties (connection, message, object_info, wincaps_propiface, object);
2206 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2210 g_assert (getter || setter);
2212 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
2214 ret = error_or_die (message, DBUS_ERROR_INVALID_ARGS,
2215 "Second argument to Get() or Set() must be a property name string");
2219 dbus_message_iter_get_basic (&iter, &requested_propname);
2220 dbus_message_iter_next (&iter);
2222 s = lookup_property_name (object, wincaps_propiface, requested_propname);
2224 if (!check_property_access (connection, message, object, wincaps_propiface, requested_propname, s, setter))
2227 return DBUS_HANDLER_RESULT_HANDLED;
2230 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
2239 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT)
2241 ret = error_or_die (message, DBUS_ERROR_INVALID_ARGS,
2242 "Third argument to Set() must be a variant");
2246 ret = set_object_property (connection, message, &iter,
2248 dbus_message_iter_next (&iter);
2253 ret = get_object_property (connection, message,
2259 gchar *error_message = g_strdup_printf ("No such property %s",
2260 requested_propname);
2262 ret = error_or_die (message, DBUS_ERROR_INVALID_ARGS, error_message);
2263 g_free (error_message);
2267 g_assert (ret != NULL);
2269 /* FIXME: this should be returned as a D-Bus error, not spammed out
2270 * as a warning. This is too late to do that, though - we've already
2271 * had any side-effects we were going to have - and it would break
2272 * anything that's relying on ability to give us too many arguments. */
2273 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID)
2274 g_warning ("Property get, set or set all had too many arguments\n");
2277 connection_send_or_die (connection, ret);
2278 dbus_message_unref (ret);
2279 return DBUS_HANDLER_RESULT_HANDLED;
2282 static const DBusObjectPathVTable gobject_dbus_vtable = {
2283 object_registration_unregistered,
2284 object_registration_message,
2290 DBusGConnection *connection;
2292 const char *signame;
2293 const char *sigiface;
2294 } DBusGSignalClosure;
2297 dbus_g_signal_closure_new (GObject *object,
2298 const char *signame,
2299 const char *sigiface)
2301 DBusGSignalClosure *closure;
2303 closure = (DBusGSignalClosure*) g_closure_new_simple (sizeof (DBusGSignalClosure), NULL);
2305 closure->object = object;
2306 closure->signame = signame;
2307 closure->sigiface = sigiface;
2308 return (GClosure*) closure;
2312 emit_signal_for_registration (ObjectRegistration *o,
2313 DBusGSignalClosure *sigclosure,
2315 guint n_param_values,
2316 const GValue *param_values)
2318 DBusMessage *signal;
2319 DBusMessageIter iter;
2322 g_assert (g_variant_is_object_path (o->object_path));
2323 g_assert (g_dbus_is_interface_name (sigclosure->sigiface));
2324 g_assert (g_dbus_is_member_name (sigclosure->signame));
2326 signal = dbus_message_new_signal (o->object_path,
2327 sigclosure->sigiface,
2328 sigclosure->signame);
2332 dbus_message_iter_init_append (signal, &iter);
2334 /* First argument is the object itself, and we can't marshall that */
2335 for (i = 1; i < n_param_values; i++)
2337 if (!_dbus_gvalue_marshal (&iter,
2338 (GValue *) (&(param_values[i]))))
2340 g_warning ("failed to marshal parameter %d for signal %s",
2341 i, sigclosure->signame);
2346 connection_send_or_die (DBUS_CONNECTION_FROM_G_CONNECTION (o->connection),
2349 dbus_message_unref (signal);
2353 signal_emitter_marshaller (GClosure *closure,
2355 guint n_param_values,
2356 const GValue *param_values,
2357 gpointer invocation_hint,
2358 gpointer marshal_data)
2360 DBusGSignalClosure *sigclosure;
2361 const ObjectExport *oe;
2364 sigclosure = (DBusGSignalClosure *) closure;
2366 g_assert (retval == NULL);
2368 oe = g_object_get_data (sigclosure->object, "dbus_glib_object_registrations");
2369 /* If the object has ever been exported, this should exist; it persists until
2370 * the object is actually freed. */
2371 g_assert (oe != NULL);
2373 for (iter = oe->registrations; iter; iter = iter->next)
2375 ObjectRegistration *o = iter->data;
2377 emit_signal_for_registration (o, sigclosure, retval, n_param_values, param_values);
2382 export_signals (const GList *info_list, GObject *object)
2385 const char *sigdata;
2387 const char *signame;
2388 const DBusGObjectInfo *info;
2390 gtype = G_TYPE_FROM_INSTANCE (object);
2392 for (; info_list != NULL; info_list = g_list_next (info_list))
2394 info = (DBusGObjectInfo *) info_list->data;
2396 sigdata = info->exported_signals;
2398 while (*sigdata != '\0')
2405 sigdata = signal_iterate (sigdata, &iface, &signame);
2407 if (!g_dbus_is_interface_name (iface))
2409 g_critical ("invalid interface name found in %s: %s",
2410 g_type_name (gtype), iface);
2414 if (!g_dbus_is_member_name (signame))
2416 g_critical ("invalid signal name found in %s: %s",
2417 g_type_name (gtype), signame);
2421 s = _dbus_gutils_wincaps_to_uscore (signame);
2423 id = g_signal_lookup (s, gtype);
2426 g_warning ("signal \"%s\" (from \"%s\") exported but not found in object class \"%s\"",
2427 s, signame, g_type_name (gtype));
2432 g_signal_query (id, &query);
2434 if (query.return_type != G_TYPE_NONE)
2436 g_warning ("Not exporting signal \"%s\" for object class \"%s\" as it has a return type \"%s\"",
2437 s, g_type_name (gtype), g_type_name (query.return_type));
2439 continue; /* FIXME: these could be listed as methods ? */
2442 closure = dbus_g_signal_closure_new (object, signame, (char*) iface);
2443 g_closure_set_marshal (closure, signal_emitter_marshaller);
2445 g_signal_connect_closure_by_id (object,
2457 dbus_error_to_gerror_code (const char *derr)
2460 else if (!strcmp (derr, DBUS_ERROR_FAILED ))
2461 return DBUS_GERROR_FAILED ;
2462 else if (!strcmp (derr, DBUS_ERROR_NO_MEMORY ))
2463 return DBUS_GERROR_NO_MEMORY ;
2464 else if (!strcmp (derr, DBUS_ERROR_SERVICE_UNKNOWN ))
2465 return DBUS_GERROR_SERVICE_UNKNOWN ;
2466 else if (!strcmp (derr, DBUS_ERROR_NAME_HAS_NO_OWNER ))
2467 return DBUS_GERROR_NAME_HAS_NO_OWNER ;
2468 else if (!strcmp (derr, DBUS_ERROR_NO_REPLY ))
2469 return DBUS_GERROR_NO_REPLY ;
2470 else if (!strcmp (derr, DBUS_ERROR_IO_ERROR ))
2471 return DBUS_GERROR_IO_ERROR ;
2472 else if (!strcmp (derr, DBUS_ERROR_BAD_ADDRESS ))
2473 return DBUS_GERROR_BAD_ADDRESS ;
2474 else if (!strcmp (derr, DBUS_ERROR_NOT_SUPPORTED ))
2475 return DBUS_GERROR_NOT_SUPPORTED ;
2476 else if (!strcmp (derr, DBUS_ERROR_LIMITS_EXCEEDED ))
2477 return DBUS_GERROR_LIMITS_EXCEEDED ;
2478 else if (!strcmp (derr, DBUS_ERROR_ACCESS_DENIED ))
2479 return DBUS_GERROR_ACCESS_DENIED ;
2480 else if (!strcmp (derr, DBUS_ERROR_AUTH_FAILED ))
2481 return DBUS_GERROR_AUTH_FAILED ;
2482 else if (!strcmp (derr, DBUS_ERROR_NO_SERVER ))
2483 return DBUS_GERROR_NO_SERVER ;
2484 else if (!strcmp (derr, DBUS_ERROR_TIMEOUT ))
2485 return DBUS_GERROR_TIMEOUT ;
2486 else if (!strcmp (derr, DBUS_ERROR_NO_NETWORK ))
2487 return DBUS_GERROR_NO_NETWORK ;
2488 else if (!strcmp (derr, DBUS_ERROR_ADDRESS_IN_USE ))
2489 return DBUS_GERROR_ADDRESS_IN_USE ;
2490 else if (!strcmp (derr, DBUS_ERROR_DISCONNECTED ))
2491 return DBUS_GERROR_DISCONNECTED ;
2492 else if (!strcmp (derr, DBUS_ERROR_INVALID_ARGS ))
2493 return DBUS_GERROR_INVALID_ARGS ;
2494 else if (!strcmp (derr, DBUS_ERROR_FILE_NOT_FOUND ))
2495 return DBUS_GERROR_FILE_NOT_FOUND ;
2496 else if (!strcmp (derr, DBUS_ERROR_FILE_EXISTS ))
2497 return DBUS_GERROR_FILE_EXISTS ;
2498 else if (!strcmp (derr, DBUS_ERROR_UNKNOWN_METHOD ))
2499 return DBUS_GERROR_UNKNOWN_METHOD ;
2500 else if (!strcmp (derr, DBUS_ERROR_TIMED_OUT ))
2501 return DBUS_GERROR_TIMED_OUT ;
2502 else if (!strcmp (derr, DBUS_ERROR_MATCH_RULE_NOT_FOUND ))
2503 return DBUS_GERROR_MATCH_RULE_NOT_FOUND ;
2504 else if (!strcmp (derr, DBUS_ERROR_MATCH_RULE_INVALID ))
2505 return DBUS_GERROR_MATCH_RULE_INVALID ;
2506 else if (!strcmp (derr, DBUS_ERROR_SPAWN_EXEC_FAILED ))
2507 return DBUS_GERROR_SPAWN_EXEC_FAILED ;
2508 else if (!strcmp (derr, DBUS_ERROR_SPAWN_FORK_FAILED ))
2509 return DBUS_GERROR_SPAWN_FORK_FAILED ;
2510 else if (!strcmp (derr, DBUS_ERROR_SPAWN_CHILD_EXITED ))
2511 return DBUS_GERROR_SPAWN_CHILD_EXITED ;
2512 else if (!strcmp (derr, DBUS_ERROR_SPAWN_CHILD_SIGNALED ))
2513 return DBUS_GERROR_SPAWN_CHILD_SIGNALED ;
2514 else if (!strcmp (derr, DBUS_ERROR_SPAWN_FAILED ))
2515 return DBUS_GERROR_SPAWN_FAILED ;
2516 else if (!strcmp (derr, DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN ))
2517 return DBUS_GERROR_UNIX_PROCESS_ID_UNKNOWN ;
2518 else if (!strcmp (derr, DBUS_ERROR_INVALID_SIGNATURE ))
2519 return DBUS_GERROR_INVALID_SIGNATURE ;
2520 else if (!strcmp (derr, DBUS_ERROR_INVALID_FILE_CONTENT ))
2521 return DBUS_GERROR_INVALID_FILE_CONTENT ;
2522 else if (!strcmp (derr, DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN ))
2523 return DBUS_GERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN ;
2525 return DBUS_GERROR_REMOTE_EXCEPTION;
2531 * @derror: a #DBusError
2533 * Store the information from a DBus method error return into a
2534 * GError. For the normal case of an arbitrary remote process,
2535 * the error code will be DBUS_GERROR_REMOTE_EXCEPTION. Now,
2536 * DBus errors have two components; a message and a "name".
2537 * The former is an arbitrary (normally American English) string.
2538 * The second is a string like com.example.FooFailure which
2539 * programs can use as a conditional source. Because a GError
2540 * only has one string, we use a hack to encode both values:
2542 * <human readable string><null><error name><null>
2544 * You can use the following code to retrieve both values:
2546 * |[const char *msg = error->message;
2547 * size_t len = strlen(msg);
2548 * const char *error_name = msg+len+1;]|
2551 dbus_set_g_error (GError **gerror,
2556 g_return_if_fail (derror != NULL);
2557 g_return_if_fail (dbus_error_is_set (derror));
2558 g_return_if_fail (gerror == NULL || *gerror == NULL);
2560 code = dbus_error_to_gerror_code (derror->name);
2561 if (code != DBUS_GERROR_REMOTE_EXCEPTION)
2562 g_set_error (gerror, DBUS_GERROR,
2567 g_set_error (gerror, DBUS_GERROR,
2570 derror->message ? derror->message : "",
2576 dbus_g_error_info_free (gpointer p)
2578 DBusGErrorInfo *info;
2582 g_free (info->default_iface);
2587 * SECTION:dbus-gobject
2588 * @short_description: Exporting a #GObject remotely
2589 * @see_also: #GObject
2590 * @stability: Stable
2596 * dbus_glib_global_set_disable_legacy_property_access:
2598 * For historical reasons, DBus-GLib will allow read-only
2599 * access to every GObject property of an object exported
2600 * to the bus, regardless of whether or not the property
2601 * is listed in the type info installed with
2602 * dbus_g_object_type_install_info(). (Write access is
2605 * If you wish to restrict even read-only access, you
2606 * can call this method to globally change the behavior
2607 * for the entire process.
2612 dbus_glib_global_set_disable_legacy_property_access (void)
2614 disable_legacy_property_access = TRUE;
2618 * dbus_g_object_type_install_info:
2619 * @object_type: #GType for the object
2620 * @info: introspection data generated by #dbus-glib-tool
2622 * Install introspection information about the given object #GType
2623 * sufficient to allow methods on the object to be invoked by name.
2624 * The introspection information is normally generated by
2625 * dbus-glib-tool, then this function is called in the
2626 * class_init() for the object class.
2628 * Once introspection information has been installed, instances of the
2629 * object registered with dbus_g_connection_register_g_object() can have
2630 * their methods invoked remotely.
2633 dbus_g_object_type_install_info (GType object_type,
2634 const DBusGObjectInfo *info)
2636 g_return_if_fail (G_TYPE_IS_CLASSED (object_type) || G_TYPE_IS_INTERFACE (object_type));
2638 _dbus_g_value_types_init ();
2640 g_type_set_qdata (object_type,
2641 dbus_g_object_type_dbus_metadata_quark (),
2646 * dbus_g_error_domain_register:
2647 * @domain: the #GError domain
2648 * @default_iface: the prefix used for error values, or %NULL
2649 * @code_enum: a #GType for a #GEnum of the error codes
2651 * Register a #GError domain and set of codes with D-Bus. When an object
2652 * raises a #GError in the domain @domain from one of its D-Bus methods,
2653 * the D-Bus error name used will be @default_iface, followed by a dot,
2654 * followed by the #GEnumValue.value_nick corresponding to the #GError.code.
2655 * For D-Bus, it's conventional to use an error name (value_nick) that is
2658 * (For instance, if a D-Bus method <code>com.example.MyObject.GetThings</code>
2659 * can raise a #GError with domain <code>MY_ERROR</code> and code
2660 * <code>MY_ERROR_NOT_HAPPY</code>, you could call
2661 * <code>dbus_g_error_domain_register (MY_ERROR, "com.example.MyError",
2662 * MY_TYPE_ERROR)</code>, and set up the value_nick for
2663 * <code>MY_ERROR_NOT_HAPPY</code> to be <code>NotHappy</code>,
2664 * resulting in the D-Bus error string
2665 * <code>com.example.MyError.NotHappy</code>.)
2667 * If @default_iface is %NULL, the D-Bus interface of the method that failed
2670 * (For instance, if the above example had called
2671 * <code>dbus_g_error_domain_register (MY_ERROR, NULL, MY_TYPE_ERROR)</code>
2672 * instead, then the D-Bus error string would be
2673 * <code>com.example.MyObject.NotHappy</code>.)
2676 dbus_g_error_domain_register (GQuark domain,
2677 const char *default_iface,
2680 DBusGErrorInfo *info;
2682 g_return_if_fail (g_quark_to_string (domain) != NULL);
2683 g_return_if_fail (code_enum != G_TYPE_INVALID);
2684 g_return_if_fail (G_TYPE_FUNDAMENTAL (code_enum) == G_TYPE_ENUM);
2686 g_static_rw_lock_writer_lock (&globals_lock);
2688 if (error_metadata == NULL)
2689 g_datalist_init (&error_metadata);
2691 info = g_datalist_id_get_data (&error_metadata, domain);
2695 g_warning ("Metadata for error domain \"%s\" already registered\n",
2696 g_quark_to_string (domain));
2700 info = g_new0 (DBusGErrorInfo, 1);
2701 info->default_iface = g_strdup (default_iface);
2702 info->code_enum = code_enum;
2704 g_datalist_id_set_data_full (&error_metadata,
2707 dbus_g_error_info_free);
2710 g_static_rw_lock_writer_unlock (&globals_lock);
2713 /* Called when the object is destroyed */
2715 object_export_object_died (gpointer user_data, GObject *dead)
2717 ObjectExport *oe = user_data;
2719 g_assert (dead == oe->object);
2721 /* this prevents the weak unref from taking place, which would cause an
2722 * assertion failure since the object has already gone... */
2725 /* ... while this results in a call to object_registration_unregistered
2726 * for each contained registration */
2727 object_export_unregister_all (oe);
2729 /* We deliberately don't remove the ObjectExport yet, in case the object is
2730 * resurrected and re-registered: if that happens, we wouldn't want to call
2731 * export_signals() again. */
2735 * dbus_g_connection_unregister_g_object:
2736 * @connection: the D-BUS connection
2737 * @object: the object
2739 * Removes @object from any object paths at which it is exported on
2740 * @connection. Properties, methods, and signals
2741 * of the object can no longer be accessed remotely.
2744 dbus_g_connection_unregister_g_object (DBusGConnection *connection,
2748 GSList *registrations;
2750 g_return_if_fail (connection != NULL);
2751 g_return_if_fail (G_IS_OBJECT (object));
2753 oe = g_object_get_data (object, "dbus_glib_object_registrations");
2755 g_return_if_fail (oe != NULL);
2756 g_return_if_fail (oe->registrations != NULL);
2758 /* Copy the list before iterating it: it will be modified in
2759 * object_registration_free() each time an object path is unregistered.
2761 for (registrations = g_slist_copy (oe->registrations);
2762 registrations != NULL;
2763 registrations = g_slist_delete_link (registrations, registrations))
2765 ObjectRegistration *o = registrations->data;
2767 if (o->connection != connection)
2770 dbus_connection_unregister_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (o->connection),
2776 * dbus_g_connection_register_g_object:
2777 * @connection: the D-BUS connection
2778 * @at_path: the path where the object will live (the object's name)
2779 * @object: the object
2781 * Registers a #GObject at the given path. Properties, methods, and signals
2782 * of the object can then be accessed remotely. Methods are only available
2783 * if method introspection data has been added to the object's class
2784 * with dbus_g_object_type_install_info().
2786 * The registration will be cancelled if either the #DBusConnection or
2787 * the #GObject gets finalized, or if dbus_g_connection_unregister_g_object()
2790 * Note: If an object is registered multiple times, the first registration
2791 * takes priority for cases such as turning an object into an object path.
2794 dbus_g_connection_register_g_object (DBusGConnection *connection,
2795 const char *at_path,
2800 ObjectRegistration *o;
2803 g_return_if_fail (connection != NULL);
2804 g_return_if_fail (g_variant_is_object_path (at_path));
2805 g_return_if_fail (G_IS_OBJECT (object));
2807 oe = g_object_get_data (object, "dbus_glib_object_registrations");
2811 GList *info_list = lookup_object_info (object);
2813 if (info_list == NULL)
2815 g_warning ("No introspection data registered for object class \"%s\"",
2816 g_type_name (G_TYPE_FROM_INSTANCE (object)));
2820 /* This adds a hook into every signal for the object. Only do this
2821 * on the first registration, because inside the signal marshaller
2822 * we emit a signal for each registration.
2824 export_signals (info_list, object);
2825 g_list_free (info_list);
2827 oe = object_export_new ();
2828 g_object_set_data_full (object, "dbus_glib_object_registrations", oe,
2829 (GDestroyNotify) object_export_free);
2832 if (oe->object == NULL)
2834 /* Either the ObjectExport is newly-created, or it already existed but
2835 * the object was disposed and resurrected, causing the weak ref to
2837 oe->object = object;
2838 g_object_weak_ref (object, object_export_object_died, oe);
2841 for (iter = oe->registrations; iter; iter = iter->next)
2845 /* Silently ignore duplicate registrations */
2846 if (strcmp (o->object_path, at_path) == 0 && o->connection == connection)
2850 o = object_registration_new (connection, at_path, oe);
2852 dbus_error_init (&error);
2853 if (!dbus_connection_try_register_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (connection),
2855 &gobject_dbus_vtable,
2859 g_error ("Failed to register GObject with DBusConnection: %s %s",
2860 error.name, error.message);
2861 dbus_error_free (&error);
2862 object_registration_free (o);
2866 oe->registrations = g_slist_append (oe->registrations, o);
2870 * dbus_g_connection_lookup_g_object:
2871 * @connection: a #DBusGConnection
2876 * Returns: the object at path @at_path
2879 dbus_g_connection_lookup_g_object (DBusGConnection *connection,
2880 const char *at_path)
2883 ObjectRegistration *o;
2885 g_return_val_if_fail (connection != NULL, NULL);
2886 g_return_val_if_fail (g_variant_is_object_path (at_path), NULL);
2888 if (!dbus_connection_get_object_path_data (DBUS_CONNECTION_FROM_G_CONNECTION (connection), at_path, &p))
2896 if (o->export->object == NULL)
2899 return G_OBJECT (o->export->object);
2906 } DBusGFuncSignature;
2909 funcsig_hash (gconstpointer key)
2911 const DBusGFuncSignature *sig = key;
2917 types = sig->params;
2919 for (i = 0; i < sig->n_params; i++)
2921 ret += (int) (*types);
2929 funcsig_equal (gconstpointer aval,
2932 const DBusGFuncSignature *a = aval;
2933 const DBusGFuncSignature *b = bval;
2934 const GType *atypes;
2935 const GType *btypes;
2938 if (a->rettype != b->rettype
2939 || a->n_params != b->n_params)
2945 for (i = 0; i < a->n_params; i++)
2947 if (*btypes != *atypes)
2957 funcsig_free (DBusGFuncSignature *sig)
2959 g_free (sig->params);
2964 _dbus_gobject_lookup_marshaller (GType rettype,
2966 const GType *param_types)
2968 GClosureMarshal ret;
2969 DBusGFuncSignature sig;
2973 /* Convert to fundamental types */
2974 rettype = G_TYPE_FUNDAMENTAL (rettype);
2975 params = g_new (GType, n_params);
2976 for (i = 0; i < n_params; i++)
2977 params[i] = G_TYPE_FUNDAMENTAL (param_types[i]);
2979 sig.rettype = rettype;
2980 sig.n_params = n_params;
2981 sig.params = params;
2983 g_static_rw_lock_reader_lock (&globals_lock);
2986 ret = g_hash_table_lookup (marshal_table, &sig);
2990 g_static_rw_lock_reader_unlock (&globals_lock);
2994 if (rettype == G_TYPE_NONE)
2997 ret = g_cclosure_marshal_VOID__VOID;
2998 else if (n_params == 1)
3002 case G_TYPE_BOOLEAN:
3003 ret = g_cclosure_marshal_VOID__BOOLEAN;
3006 ret = g_cclosure_marshal_VOID__UCHAR;
3009 ret = g_cclosure_marshal_VOID__INT;
3012 ret = g_cclosure_marshal_VOID__UINT;
3015 ret = g_cclosure_marshal_VOID__DOUBLE;
3018 ret = g_cclosure_marshal_VOID__STRING;
3021 ret = g_cclosure_marshal_VOID__BOXED;
3025 else if (n_params == 3
3026 && params[0] == G_TYPE_STRING
3027 && params[1] == G_TYPE_STRING
3028 && params[2] == G_TYPE_STRING)
3030 ret = _dbus_g_marshal_NONE__STRING_STRING_STRING;
3040 * dbus_g_object_register_marshaller:
3041 * @marshaller: a GClosureMarshal to be used for invocation
3042 * @rettype: a GType for the return type of the function
3043 * @...: The parameter #GTypes, followed by %G_TYPE_INVALID
3045 * Register a #GClosureMarshal to be used for signal invocations,
3046 * giving its return type and a list of parameter types,
3047 * followed by %G_TYPE_INVALID.
3049 * This function will not be needed once GLib includes libffi.
3052 dbus_g_object_register_marshaller (GClosureMarshal marshaller,
3060 va_start (args, rettype);
3062 types = g_array_new (TRUE, TRUE, sizeof (GType));
3064 while ((gtype = va_arg (args, GType)) != G_TYPE_INVALID)
3065 g_array_append_val (types, gtype);
3067 dbus_g_object_register_marshaller_array (marshaller, rettype,
3068 types->len, (GType*) types->data);
3070 g_array_free (types, TRUE);
3075 * dbus_g_object_register_marshaller_array:
3076 * @marshaller: a #GClosureMarshal to be used for invocation
3077 * @rettype: a #GType for the return type of the function
3078 * @n_types: number of function parameters
3079 * @types: a C array of GTypes values
3081 * Register a #GClosureMarshal to be used for signal invocations.
3082 * @see_also dbus_g_object_register_marshaller()
3085 dbus_g_object_register_marshaller_array (GClosureMarshal marshaller,
3090 DBusGFuncSignature *sig;
3093 g_static_rw_lock_writer_lock (&globals_lock);
3095 if (marshal_table == NULL)
3096 marshal_table = g_hash_table_new_full (funcsig_hash,
3098 (GDestroyNotify) funcsig_free,
3100 sig = g_new0 (DBusGFuncSignature, 1);
3101 sig->rettype = G_TYPE_FUNDAMENTAL (rettype);
3102 sig->n_params = n_types;
3103 sig->params = g_new (GType, n_types);
3104 for (i = 0; i < n_types; i++)
3105 sig->params[i] = G_TYPE_FUNDAMENTAL (types[i]);
3107 g_hash_table_insert (marshal_table, sig, marshaller);
3109 g_static_rw_lock_writer_unlock (&globals_lock);
3113 * dbus_g_method_get_sender:
3114 * @context: the method context
3116 * Get the sender of a message so we can send a
3117 * "reply" later (i.e. send a message directly
3118 * to a service which invoked the method at a
3121 * Returns: the unique name of the sender. It
3122 * is up to the caller to free the returned string.
3125 dbus_g_method_get_sender (DBusGMethodInvocation *context)
3127 const gchar *sender;
3129 g_return_val_if_fail (context != NULL, NULL);
3131 sender = dbus_message_get_sender (dbus_g_message_get_message (context->message));
3132 return g_strdup (sender);
3136 * dbus_g_method_get_reply:
3137 * @context: the method context
3139 * Get the reply message to append reply values
3140 * Used as a sidedoor when you can't generate dbus values
3141 * of the correct type due to glib binding limitations
3143 * Returns: a #DBusMessage with the reply
3146 dbus_g_method_get_reply (DBusGMethodInvocation *context)
3148 g_return_val_if_fail (context != NULL, NULL);
3150 return reply_or_die (dbus_g_message_get_message (context->message));
3154 * dbus_g_method_send_reply:
3155 * @context: the method context
3156 * @reply: the reply message, will be unreffed
3158 * Send a manually created reply message.
3160 * Used as a sidedoor when you can't generate dbus values
3161 * of the correct type due to glib binding limitations
3164 dbus_g_method_send_reply (DBusGMethodInvocation *context, DBusMessage *reply)
3166 g_return_if_fail (context != NULL);
3167 g_return_if_fail (reply != NULL);
3169 connection_send_or_die (dbus_g_connection_get_connection (context->connection),
3171 dbus_message_unref (reply);
3173 dbus_g_connection_unref (context->connection);
3174 dbus_g_message_unref (context->message);
3180 * dbus_g_method_return:
3181 * @context: the method context
3182 * @...: zero or more values to return from the method, with their number
3183 * and types given by its #DBusGObjectInfo
3185 * Send a return message for a given method invocation, with arguments.
3186 * This function also frees the sending context.
3189 dbus_g_method_return (DBusGMethodInvocation *context, ...)
3192 DBusMessageIter iter;
3198 g_return_if_fail (context != NULL);
3200 /* This field was initialized inside invoke_object_method; we
3201 * carry it over through the async invocation to here.
3203 if (!context->send_reply)
3206 reply = dbus_g_method_get_reply (context);
3207 out_sig = method_output_signature_from_object_info (context->object, context->method);
3208 argsig = _dbus_gtypes_from_arg_signature (out_sig, FALSE);
3210 dbus_message_iter_init_append (reply, &iter);
3212 va_start (args, context);
3213 for (i = 0; i < argsig->len; i++)
3215 GValue value = {0,};
3217 g_value_init (&value, g_array_index (argsig, GType, i));
3219 G_VALUE_COLLECT (&value, args, G_VALUE_NOCOPY_CONTENTS, &error);
3222 g_warning("%s", error);
3227 if (!_dbus_gvalue_marshal (&iter, &value))
3228 g_warning ("failed to marshal parameter %d for method %s",
3229 i, dbus_message_get_member (
3230 dbus_g_message_get_message (context->message)));
3235 connection_send_or_die (dbus_g_connection_get_connection (context->connection),
3237 dbus_message_unref (reply);
3240 g_array_free (argsig, TRUE);
3243 dbus_g_connection_unref (context->connection);
3244 dbus_g_message_unref (context->message);
3249 * dbus_g_method_return_error:
3250 * @context: the method context
3251 * @error: the error to send
3253 * Send a error message for a given method invocation.
3254 * This function also frees the sending context.
3257 dbus_g_method_return_error (DBusGMethodInvocation *context, const GError *error)
3261 g_return_if_fail (context != NULL);
3262 g_return_if_fail (error != NULL);
3264 /* See comment in dbus_g_method_return */
3265 if (!context->send_reply)
3268 reply = gerror_to_dbus_error_message (context->object, dbus_g_message_get_message (context->message), error);
3269 connection_send_or_die (
3270 dbus_g_connection_get_connection (context->connection), reply);
3271 dbus_message_unref (reply);
3274 dbus_g_connection_unref (context->connection);
3275 dbus_g_message_unref (context->message);
3280 _dbus_gobject_get_path (GObject *obj)
3283 ObjectRegistration *o;
3285 oe = g_object_get_data (obj, "dbus_glib_object_registrations");
3287 if (oe == NULL || oe->registrations == NULL)
3290 /* First one to have been registered wins */
3291 o = oe->registrations->data;
3293 return o->object_path;
3296 #ifdef DBUS_BUILD_TESTS
3300 _dummy_function (void)
3304 /* Data structures copied from one generated by current dbus-binding-tool;
3305 * we need to support this layout forever
3307 static const DBusGMethodInfo dbus_glib_internal_test_methods[] = {
3308 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 0 },
3309 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 49 },
3310 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 117 },
3311 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 191 },
3312 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 270 },
3313 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 320 },
3314 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 391 },
3315 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 495 },
3316 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 623 },
3317 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 693 },
3318 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 765 },
3319 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 838 },
3320 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 911 },
3321 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 988 },
3322 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1064 },
3323 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1140 },
3324 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1204 },
3325 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1278 },
3326 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1347 },
3327 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1408 },
3328 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1460 },
3329 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1533 },
3330 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1588 },
3331 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1647 },
3332 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1730 },
3333 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1784 },
3334 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1833 },
3335 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1895 },
3336 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1947 },
3337 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1999 },
3340 const DBusGObjectInfo dbus_glib_internal_test_object_info = {
3342 dbus_glib_internal_test_methods,
3344 "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",
3345 "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",
3351 * Unit test for GLib GObject integration ("skeletons")
3352 * Returns: %TRUE on success.
3355 _dbus_gobject_test (const char *test_data_dir)
3359 const char *arg_name;
3363 const char *arg_signature;
3364 const char *sigdata;
3366 const char *signame;
3368 static struct { const char *wincaps; const char *uscore; } name_pairs[] = {
3369 { "SetFoo", "set_foo" },
3371 { "GetFooBar", "get_foo_bar" },
3372 { "Hello", "hello" }
3374 /* Impossible-to-handle cases */
3375 /* { "FrobateUIHandler", "frobate_ui_handler" } */
3378 /* Test lookup in our hardcoded object info; if these tests fail
3379 * then it likely means you changed the generated object info in an
3380 * incompatible way and broke the lookup functions. In that case
3381 * you need to bump the version and use a new structure instead. */
3383 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
3384 &(dbus_glib_internal_test_methods[0]));
3385 g_assert (*arg == '\0');
3388 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
3389 &(dbus_glib_internal_test_methods[1]));
3390 g_assert (*arg != '\0');
3391 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3392 g_assert (!strcmp (arg_name, "x"));
3393 g_assert (arg_in == TRUE);
3394 g_assert (!strcmp (arg_signature, "u"));
3395 g_assert (*arg != '\0');
3396 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3397 g_assert (arg_in == FALSE);
3398 g_assert (retval == RETVAL_NONE);
3399 g_assert (!strcmp (arg_signature, "u"));
3400 g_assert (*arg == '\0');
3402 /* IncrementRetval */
3403 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
3404 &(dbus_glib_internal_test_methods[2]));
3405 g_assert (*arg != '\0');
3406 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3407 g_assert (!strcmp (arg_name, "x"));
3408 g_assert (arg_in == TRUE);
3409 g_assert (!strcmp (arg_signature, "u"));
3410 g_assert (*arg != '\0');
3411 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3412 g_assert (retval == RETVAL_NOERROR);
3413 g_assert (arg_in == FALSE);
3414 g_assert (!strcmp (arg_signature, "u"));
3415 g_assert (*arg == '\0');
3417 /* IncrementRetvalError */
3418 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
3419 &(dbus_glib_internal_test_methods[3]));
3420 g_assert (*arg != '\0');
3421 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3422 g_assert (!strcmp (arg_name, "x"));
3423 g_assert (arg_in == TRUE);
3424 g_assert (!strcmp (arg_signature, "u"));
3425 g_assert (*arg != '\0');
3426 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3427 g_assert (retval == RETVAL_ERROR);
3428 g_assert (arg_in == FALSE);
3429 g_assert (!strcmp (arg_signature, "u"));
3430 g_assert (*arg == '\0');
3433 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
3434 &(dbus_glib_internal_test_methods[8]));
3435 g_assert (*arg != '\0');
3436 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3437 g_assert (!strcmp (arg_name, "val"));
3438 g_assert (arg_in == TRUE);
3439 g_assert (!strcmp (arg_signature, "v"));
3440 g_assert (*arg != '\0');
3441 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
3442 g_assert (retval == RETVAL_NONE);
3443 g_assert (arg_in == FALSE);
3444 g_assert (!strcmp (arg_signature, "s"));
3445 g_assert (*arg == '\0');
3447 sigdata = dbus_glib_internal_test_object_info.exported_signals;
3448 g_assert (*sigdata != '\0');
3449 sigdata = signal_iterate (sigdata, &iface, &signame);
3450 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.MyObject"));
3451 g_assert (!strcmp (signame, "Frobnicate"));
3452 g_assert (*sigdata != '\0');
3453 sigdata = signal_iterate (sigdata, &iface, &signame);
3454 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
3455 g_assert (!strcmp (signame, "Sig0"));
3456 g_assert (*sigdata != '\0');
3457 sigdata = signal_iterate (sigdata, &iface, &signame);
3458 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
3459 g_assert (!strcmp (signame, "Sig1"));
3460 g_assert (*sigdata != '\0');
3461 sigdata = signal_iterate (sigdata, &iface, &signame);
3462 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
3463 g_assert (!strcmp (signame, "Sig2"));
3464 g_assert (*sigdata == '\0');
3468 while (i < (int) G_N_ELEMENTS (name_pairs))
3473 uscore = _dbus_gutils_wincaps_to_uscore (name_pairs[i].wincaps);
3474 wincaps = uscore_to_wincaps (name_pairs[i].uscore);
3476 if (strcmp (uscore, name_pairs[i].uscore) != 0)
3478 g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
3479 name_pairs[i].wincaps, name_pairs[i].uscore,
3484 if (strcmp (wincaps, name_pairs[i].wincaps) != 0)
3486 g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
3487 name_pairs[i].uscore, name_pairs[i].wincaps,
3501 #endif /* DBUS_BUILD_TESTS */