00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 #include <config.h>
00026 #include <gobject/gvaluecollector.h>
00027 #include <dbus/dbus-glib.h>
00028 #include <dbus/dbus-glib-lowlevel.h>
00029 #include "dbus-gtest.h"
00030 #include "dbus-gutils.h"
00031 #include "dbus-gobject.h"
00032 #include "dbus-gsignature.h"
00033 #include "dbus-gvalue.h"
00034 #include "dbus-gmarshal.h"
00035 #include "dbus-gvalue-utils.h"
00036 #include <string.h>
00037 
00038 typedef struct
00039 {
00040   char *default_iface;
00041   GType code_enum;
00042 } DBusGErrorInfo;
00043 
00044 static GStaticRWLock globals_lock = G_STATIC_RW_LOCK_INIT;
00045 static GHashTable *marshal_table = NULL;
00046 static GData *error_metadata = NULL;
00047 
00048 static char*
00049 uscore_to_wincaps (const char *uscore)
00050 {
00051   const char *p;
00052   GString *str;
00053   gboolean last_was_uscore;
00054 
00055   last_was_uscore = TRUE;
00056   
00057   str = g_string_new (NULL);
00058   p = uscore;
00059   while (p && *p)
00060     {
00061       if (*p == '-' || *p == '_')
00062         {
00063           last_was_uscore = TRUE;
00064         }
00065       else
00066         {
00067           if (last_was_uscore)
00068             {
00069               g_string_append_c (str, g_ascii_toupper (*p));
00070               last_was_uscore = FALSE;
00071             }
00072           else
00073             g_string_append_c (str, *p);
00074         }
00075       ++p;
00076     }
00077 
00078   return g_string_free (str, FALSE);
00079 }
00080 
00081 static const char *
00082 string_table_next (const char *table)
00083 {
00084   return (table + (strlen (table) + 1));
00085 }
00086 
00087 static const char *
00088 string_table_lookup (const char *table, int index)
00089 {
00090   const char *ret;
00091 
00092   ret = table;
00093 
00094   while (index--)
00095     ret = string_table_next (ret);
00096 
00097   return ret;
00098 }
00099 
00100 static const char *
00101 get_method_data (const DBusGObjectInfo *object,
00102                  const DBusGMethodInfo *method)
00103 {
00104   return object->data + method->data_offset;
00105 }
00106 
00107 static char *
00108 object_error_domain_prefix_from_object_info (const DBusGObjectInfo *info)
00109 {
00110   
00111   return NULL;
00112 }
00113 
00114 static char *
00115 object_error_code_from_object_info (const DBusGObjectInfo *info, GQuark domain, gint code)
00116 {
00117   
00118   return NULL;
00119 }
00120 
00121 static const char *
00122 method_interface_from_object_info (const DBusGObjectInfo *object,
00123                               const DBusGMethodInfo *method)
00124 {
00125   return string_table_lookup (get_method_data (object, method), 0);
00126 }
00127 
00128 static const char *
00129 method_name_from_object_info (const DBusGObjectInfo *object,
00130                               const DBusGMethodInfo *method)
00131 {
00132   return string_table_lookup (get_method_data (object, method), 1);
00133 }
00134 
00135 static const char *
00136 method_arg_info_from_object_info (const DBusGObjectInfo *object,
00137                                   const DBusGMethodInfo *method)
00138 {
00139   return string_table_lookup (get_method_data (object, method), 3);
00140 }
00141 
00142 typedef enum
00143 {
00144   RETVAL_NONE,    
00145   RETVAL_NOERROR,    
00146   RETVAL_ERROR
00147 } RetvalType;
00148 
00149 static const char *
00150 arg_iterate (const char    *data,
00151              const char   **name,
00152              gboolean      *in,
00153              gboolean      *constval,
00154              RetvalType    *retval,
00155              const char   **type)
00156 {
00157   gboolean inarg;
00158 
00159   if (name)
00160     *name = data;
00161 
00162   data = string_table_next (data);
00163   switch (*data)
00164     {
00165     case 'I':
00166       inarg = TRUE;
00167       break;
00168     case 'O':
00169       inarg = FALSE;
00170       break;
00171     default:
00172       g_warning ("invalid arg direction '%c'", *data);
00173       inarg = FALSE;
00174       break;
00175     }
00176   if (in)
00177     *in = inarg;
00178 
00179   if (!inarg)
00180     {
00181       data = string_table_next (data);
00182       switch (*data)
00183         {
00184         case 'F':
00185           if (constval)
00186             *constval = FALSE;
00187           break;
00188         case 'C':
00189           if (constval)
00190             *constval = TRUE;
00191           break;
00192         default:
00193           g_warning ("invalid arg const value '%c'", *data);
00194           break;
00195         }
00196       data = string_table_next (data);
00197       switch (*data)
00198         {
00199         case 'N':
00200           if (retval)
00201             *retval = RETVAL_NONE;
00202           break;
00203         case 'E':
00204           if (retval)
00205             *retval = RETVAL_ERROR;
00206           break;
00207         case 'R':
00208           if (retval)
00209             *retval = RETVAL_NOERROR;
00210           break;
00211         default:
00212           g_warning ("invalid arg ret value '%c'", *data);
00213           break;
00214         }
00215     }
00216   else
00217     {
00218       if (constval)
00219         *constval = FALSE;
00220       if (retval)
00221         *retval = FALSE;
00222     }
00223   
00224   data = string_table_next (data);
00225   if (type)
00226     *type = data;
00227 
00228   return string_table_next (data);
00229 }
00230 
00231 static char *
00232 method_dir_signature_from_object_info (const DBusGObjectInfo *object,
00233                                        const DBusGMethodInfo *method,
00234                                        gboolean               in)
00235 {
00236   const char *arg;
00237   GString *ret;
00238 
00239   arg = method_arg_info_from_object_info (object, method);
00240 
00241   ret = g_string_new (NULL);
00242 
00243   while (*arg)
00244     {
00245       const char *name;
00246       gboolean arg_in;
00247       const char *type;
00248 
00249       arg = arg_iterate (arg, &name, &arg_in, NULL, NULL, &type);
00250 
00251       if (arg_in == in)
00252         g_string_append (ret, type);
00253     }
00254 
00255   return g_string_free (ret, FALSE);
00256 }
00257 
00258 static char *
00259 method_input_signature_from_object_info (const DBusGObjectInfo *object,
00260                                          const DBusGMethodInfo *method)
00261 {
00262   return method_dir_signature_from_object_info (object, method, TRUE);
00263 }
00264 
00265 static char *
00266 method_output_signature_from_object_info (const DBusGObjectInfo *object,
00267                                           const DBusGMethodInfo *method)
00268 {
00269   return method_dir_signature_from_object_info (object, method, FALSE);
00270 }
00271 
00272 static const char *
00273 propsig_iterate (const char *data, const char **iface, const char **name)
00274 {
00275   *iface = data;
00276 
00277   data = string_table_next (data);
00278   *name = data;
00279 
00280   return string_table_next (data);
00281 }
00282 
00283 static GQuark
00284 dbus_g_object_type_dbus_metadata_quark (void)
00285 {
00286   static GQuark quark;
00287 
00288   if (!quark)
00289     quark = g_quark_from_static_string ("DBusGObjectTypeDBusMetadataQuark");
00290   return quark;
00291 }
00292 
00293 static GList *
00294 lookup_object_info (GObject *object)
00295 {
00296   GType *interfaces, *p;
00297   GList *info_list = NULL;
00298   const DBusGObjectInfo *info;
00299   GType classtype;
00300 
00301   interfaces = g_type_interfaces (G_TYPE_FROM_INSTANCE (object), NULL);
00302 
00303   for (p = interfaces; *p != 0; p++)
00304     {
00305       info = g_type_get_qdata (*p, dbus_g_object_type_dbus_metadata_quark ());
00306       if (info != NULL && info->format_version >= 0)
00307           info_list = g_list_prepend (info_list, (gpointer) info);
00308     }
00309 
00310   g_free (interfaces);
00311 
00312   for (classtype = G_TYPE_FROM_INSTANCE (object); classtype != 0; classtype = g_type_parent (classtype))
00313     {
00314       info = g_type_get_qdata (classtype, dbus_g_object_type_dbus_metadata_quark ());
00315       if (info != NULL && info->format_version >= 0)
00316           info_list = g_list_prepend (info_list, (gpointer) info);
00317     }
00318 
00319   
00320 
00321 
00322   
00323   return info_list;
00324 }
00325 
00326 static void
00327 gobject_unregister_function (DBusConnection  *connection,
00328                              void            *user_data)
00329 {
00330   GObject *object;
00331 
00332   object = G_OBJECT (user_data);
00333 
00334   
00335 
00336 }
00337 
00338 typedef struct
00339 {
00340   GString *xml;
00341   GType gtype;
00342   const DBusGObjectInfo *object_info;
00343 } DBusGLibWriteIterfaceData;
00344 
00345 typedef struct
00346 {
00347   GSList *methods;
00348   GSList *signals;
00349   GSList *properties;
00350 } DBusGLibWriteInterfaceValues;
00351 
00352 static void
00353 write_interface (gpointer key, gpointer val, gpointer user_data)
00354 {
00355   const char *name;
00356   GSList *methods;
00357   GSList *signals;
00358   GSList *properties;
00359   GString *xml;
00360   const DBusGObjectInfo *object_info;
00361   DBusGLibWriteIterfaceData *data;
00362   DBusGLibWriteInterfaceValues *values;
00363 
00364   name = key;
00365 
00366   values = val;
00367   methods = values->methods;
00368   signals = values->signals;
00369   properties = values->properties;
00370 
00371   data = user_data;
00372   xml = data->xml;
00373   object_info = data->object_info;
00374 
00375   g_string_append_printf (xml, "  <interface name=\"%s\">\n", name);
00376 
00377   
00378   for (; methods; methods = methods->next)
00379     {
00380       DBusGMethodInfo *method;
00381       const char *args;
00382       method = methods->data;
00383 
00384       g_string_append_printf (xml, "    <method name=\"%s\">\n",
00385                               method_name_from_object_info (object_info, method));
00386 
00387       args = method_arg_info_from_object_info (object_info, method);
00388 
00389       while (*args)
00390         {
00391           const char *name;
00392           gboolean arg_in;
00393           const char *type;
00394           
00395           args = arg_iterate (args, &name, &arg_in, NULL, NULL, &type);
00396 
00397           
00398           g_string_append_printf (xml, "      <arg name=\"%s\" type=\"%s\" direction=\"%s\"/>\n",
00399                                   name, type, arg_in ? "in" : "out");
00400 
00401         }
00402       g_string_append (xml, "    </method>\n");
00403 
00404     }
00405   g_slist_free (values->methods);
00406 
00407   for (; signals; signals = signals->next)
00408     {
00409       guint id;
00410       guint arg;
00411       const char *signame;
00412       GSignalQuery query;
00413       char *s;
00414 
00415       signame = signals->data;
00416 
00417       s = _dbus_gutils_wincaps_to_uscore (signame);
00418       
00419       id = g_signal_lookup (s, data->gtype);
00420       g_assert (id != 0);
00421 
00422       g_signal_query (id, &query);
00423       g_assert (query.return_type == G_TYPE_NONE);
00424 
00425       g_string_append_printf (xml, "    <signal name=\"%s\">\n", signame);
00426 
00427       for (arg = 0; arg < query.n_params; arg++)
00428         {
00429           char *dbus_type = _dbus_gtype_to_signature (query.param_types[arg]);
00430 
00431           g_assert (dbus_type != NULL);
00432 
00433           g_string_append (xml, "      <arg type=\"");
00434           g_string_append (xml, dbus_type);
00435           g_string_append (xml, "\"/>\n");
00436           g_free (dbus_type);
00437         }
00438 
00439       g_string_append (xml, "    </signal>\n");
00440       g_free (s);
00441     }
00442   g_slist_free (values->signals);
00443 
00444   for (; properties; properties = properties->next)
00445     {
00446       const char *propname;
00447       GParamSpec *spec;
00448       char *dbus_type;
00449       gboolean can_set;
00450       gboolean can_get;
00451       char *s;
00452 
00453       propname = properties->data;
00454       spec = NULL;
00455 
00456       s = _dbus_gutils_wincaps_to_uscore (propname);
00457 
00458       spec = g_object_class_find_property (g_type_class_peek (data->gtype), s);
00459       g_assert (spec != NULL);
00460       g_free (s);
00461       
00462       dbus_type = _dbus_gtype_to_signature (G_PARAM_SPEC_VALUE_TYPE (spec));
00463       g_assert (dbus_type != NULL);
00464       
00465       can_set = ((spec->flags & G_PARAM_WRITABLE) != 0 &&
00466                  (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
00467       
00468       can_get = (spec->flags & G_PARAM_READABLE) != 0;
00469       
00470       if (can_set || can_get)
00471         {
00472           g_string_append_printf (xml, "    <property name=\"%s\" ", propname);
00473           g_string_append (xml, "type=\"");
00474           g_string_append (xml, dbus_type);
00475           g_string_append (xml, "\" access=\"");
00476 
00477           if (can_set && can_get)
00478             g_string_append (xml, "readwrite");
00479           else if (can_get)
00480             g_string_append (xml, "read");
00481           else
00482             {
00483               g_assert (can_set);
00484               g_string_append (xml, "write");
00485             }
00486           
00487           g_string_append (xml, "\"/>\n");
00488         }
00489       
00490       g_free (dbus_type);
00491     }
00492   g_slist_free (values->properties);
00493 
00494   g_free (values);
00495   g_string_append (xml, "  </interface>\n");
00496 }
00497 
00498 static DBusGLibWriteInterfaceValues *
00499 lookup_values (GHashTable *interfaces, const char *method_interface)
00500 {
00501   DBusGLibWriteInterfaceValues *values;
00502   if ((values = g_hash_table_lookup (interfaces, (gpointer) method_interface)) == NULL)
00503     {
00504       values = g_new0 (DBusGLibWriteInterfaceValues, 1);
00505       g_hash_table_insert (interfaces, (gpointer) method_interface, values);
00506     }
00507   return values;
00508 }
00509 
00510 static void
00511 introspect_interfaces (GObject *object, GString *xml)
00512 {
00513   GList *info_list;
00514   const GList *info_list_walk;
00515   const DBusGObjectInfo *info;
00516   DBusGLibWriteIterfaceData data;
00517   int i;
00518   GHashTable *interfaces;
00519   DBusGLibWriteInterfaceValues *values;
00520   const char *propsig;
00521 
00522   info_list = lookup_object_info (object);
00523 
00524   g_assert (info_list != NULL);
00525 
00526   
00527   for (info_list_walk = info_list; info_list_walk != NULL; info_list_walk = g_list_next (info_list_walk))
00528     {
00529       info = (DBusGObjectInfo *) info_list_walk->data;
00530       interfaces = g_hash_table_new (g_str_hash, g_str_equal);
00531       
00532       g_assert (info != NULL);
00533 
00534       for (i = 0; i < info->n_method_infos; i++)
00535         {
00536           const char *method_name;
00537           const char *method_interface;
00538           const char *method_args;
00539           const DBusGMethodInfo *method;
00540 
00541           method = &(info->method_infos[i]);
00542 
00543           method_interface = method_interface_from_object_info (info, method);
00544           method_name = method_name_from_object_info (info, method);
00545           method_args = method_arg_info_from_object_info (info, method);
00546 
00547           values = lookup_values (interfaces, method_interface);
00548           values->methods = g_slist_prepend (values->methods, (gpointer) method);
00549         }
00550 
00551       propsig = info->exported_signals;
00552       while (*propsig)
00553         {
00554           const char *iface;
00555           const char *signame;
00556 
00557           propsig = propsig_iterate (propsig, &iface, &signame);
00558 
00559           values = lookup_values (interfaces, iface);
00560           values->signals = g_slist_prepend (values->signals, (gpointer) signame);
00561         }
00562 
00563       propsig = info->exported_properties;
00564       while (*propsig)
00565         {
00566           const char *iface;
00567           const char *propname;
00568 
00569           propsig = propsig_iterate (propsig, &iface, &propname);
00570 
00571           values = lookup_values (interfaces, iface);
00572           values->properties = g_slist_prepend (values->properties, (gpointer) propname);
00573         }
00574       
00575       memset (&data, 0, sizeof (data));
00576       data.xml = xml;
00577       data.gtype = G_TYPE_FROM_INSTANCE (object);
00578       data.object_info = info;
00579 
00580       g_hash_table_foreach (interfaces, write_interface, &data);
00581       g_hash_table_destroy (interfaces);
00582     }
00583 
00584   g_list_free (info_list);
00585 }
00586 
00587 static DBusHandlerResult
00588 handle_introspect (DBusConnection *connection,
00589                    DBusMessage    *message,
00590                    GObject        *object)
00591 {
00592   GString *xml;
00593   unsigned int i;
00594   DBusMessage *ret;
00595   char **children;
00596   
00597   if (!dbus_connection_list_registered (connection, 
00598                                         dbus_message_get_path (message),
00599                                         &children))
00600     g_error ("Out of memory");
00601   
00602   xml = g_string_new (NULL);
00603 
00604   g_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
00605   
00606   g_string_append (xml, "<node>\n");
00607 
00608   
00609   g_string_append_printf (xml, "  <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE);
00610   g_string_append (xml, "    <method name=\"Introspect\">\n");
00611   g_string_append_printf (xml, "      <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
00612   g_string_append (xml, "    </method>\n");
00613   g_string_append (xml, "  </interface>\n");
00614 
00615   
00616   g_string_append_printf (xml, "  <interface name=\"%s\">\n", DBUS_INTERFACE_PROPERTIES);
00617   g_string_append (xml, "    <method name=\"Get\">\n");
00618   g_string_append_printf (xml, "      <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
00619   g_string_append_printf (xml, "      <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
00620   g_string_append_printf (xml, "      <arg name=\"value\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_VARIANT_AS_STRING);
00621   g_string_append (xml, "    </method>\n");
00622   g_string_append (xml, "    <method name=\"Set\">\n");
00623   g_string_append_printf (xml, "      <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
00624   g_string_append_printf (xml, "      <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
00625   g_string_append_printf (xml, "      <arg name=\"value\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_VARIANT_AS_STRING);
00626   g_string_append (xml, "    </method>\n");
00627   g_string_append (xml, "    <method name=\"GetAll\">\n");
00628   g_string_append_printf (xml, "      <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
00629   g_string_append_printf (xml, "      <arg name=\"props\" direction=\"out\" type=\"%s\"/>\n",
00630                           DBUS_TYPE_ARRAY_AS_STRING
00631                           DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
00632                             DBUS_TYPE_STRING_AS_STRING
00633                             DBUS_TYPE_VARIANT_AS_STRING
00634                           DBUS_DICT_ENTRY_END_CHAR_AS_STRING
00635                           );
00636 
00637   g_string_append (xml, "    </method>\n");
00638   g_string_append (xml, "  </interface>\n");
00639   
00640   introspect_interfaces (object, xml);
00641 
00642   
00643   for (i = 0; children[i]; i++)
00644       g_string_append_printf (xml, "  <node name=\"%s\"/>\n",
00645                               children[i]);
00646   
00647   
00648   g_string_append (xml, "</node>\n");
00649 
00650   ret = dbus_message_new_method_return (message);
00651   if (ret == NULL)
00652     g_error ("Out of memory");
00653 
00654   dbus_message_append_args (ret,
00655                             DBUS_TYPE_STRING, &xml->str,
00656                             DBUS_TYPE_INVALID);
00657 
00658   dbus_connection_send (connection, ret, NULL);
00659   dbus_message_unref (ret);
00660 
00661   g_string_free (xml, TRUE);
00662 
00663   dbus_free_string_array (children);
00664   
00665   return DBUS_HANDLER_RESULT_HANDLED;
00666 }
00667 
00668 static DBusMessage*
00669 set_object_property (DBusConnection  *connection,
00670                      DBusMessage     *message,
00671                      DBusMessageIter *iter,
00672                      GObject         *object,
00673                      GParamSpec      *pspec)
00674 {
00675   GValue value = { 0, };
00676   DBusMessage *ret;
00677   DBusMessageIter sub;
00678   DBusGValueMarshalCtx context;
00679 
00680   dbus_message_iter_recurse (iter, &sub);
00681 
00682   context.recursion_depth = 0;
00683   context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
00684   context.proxy = NULL;
00685 
00686   g_value_init (&value, pspec->value_type);
00687   if (_dbus_gvalue_demarshal (&context, &sub, &value, NULL))
00688     {
00689       g_object_set_property (object,
00690                              pspec->name,
00691                              &value);
00692 
00693       g_value_unset (&value);
00694 
00695       ret = dbus_message_new_method_return (message);
00696       if (ret == NULL)
00697         g_error ("out of memory");
00698     }
00699   else
00700     {
00701       ret = dbus_message_new_error (message,
00702                                     DBUS_ERROR_INVALID_ARGS,
00703                                     "Argument's D-BUS type can't be converted to a GType");
00704       if (ret == NULL)
00705         g_error ("out of memory");
00706     }
00707 
00708   return ret;
00709 }
00710 
00711 static DBusMessage*
00712 get_object_property (DBusConnection *connection,
00713                      DBusMessage    *message,
00714                      GObject        *object,
00715                      GParamSpec     *pspec)
00716 {
00717   GType value_gtype;
00718   GValue value = {0, };
00719   gchar *variant_sig;
00720   DBusMessage *ret;
00721   DBusMessageIter iter, subiter;
00722 
00723   ret = dbus_message_new_method_return (message);
00724   if (ret == NULL)
00725     g_error ("out of memory");
00726 
00727 
00728   g_value_init (&value, pspec->value_type);
00729   g_object_get_property (object, pspec->name, &value);
00730 
00731   variant_sig = _dbus_gvalue_to_signature (&value);
00732   if (variant_sig == NULL)
00733     {
00734       value_gtype = G_VALUE_TYPE (&value);
00735       g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
00736       g_value_unset (&value);
00737       return ret;
00738     }
00739 
00740   dbus_message_iter_init_append (ret, &iter);
00741   if (!dbus_message_iter_open_container (&iter,
00742                                          DBUS_TYPE_VARIANT,
00743                                          variant_sig,
00744                                          &subiter))
00745     {
00746       g_free (variant_sig);
00747       g_value_unset (&value);
00748       return ret;
00749     }
00750 
00751   if (!_dbus_gvalue_marshal (&subiter, &value))
00752     {
00753       dbus_message_unref (ret);
00754       ret = dbus_message_new_error (message,
00755                                     DBUS_ERROR_UNKNOWN_METHOD,
00756                                     "Can't convert GType of object property to a D-BUS type");
00757     }
00758 
00759   dbus_message_iter_close_container (&iter, &subiter);
00760 
00761   g_value_unset (&value);
00762   g_free (variant_sig);
00763 
00764   return ret;
00765 }
00766 
00767 static DBusMessage*
00768 get_all_object_properties (DBusConnection        *connection,
00769                            DBusMessage           *message,
00770                            const DBusGObjectInfo *object_info,
00771                            GObject               *object)
00772 {
00773   DBusMessage *ret;
00774   DBusMessageIter iter_ret;
00775   DBusMessageIter iter_dict;
00776   DBusMessageIter iter_dict_entry;
00777   DBusMessageIter iter_dict_value;
00778   const char *p;
00779   char *uscore_propname;
00780 
00781   ret = dbus_message_new_method_return (message);
00782   if (ret == NULL)
00783     goto oom;
00784 
00785   dbus_message_iter_init_append (ret, &iter_ret);
00786 
00787   if (!dbus_message_iter_open_container (&iter_ret,
00788                                          DBUS_TYPE_ARRAY,
00789                                          DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
00790                                          DBUS_TYPE_STRING_AS_STRING
00791                                          DBUS_TYPE_VARIANT_AS_STRING
00792                                          DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
00793                                          &iter_dict))
00794     goto oom;
00795 
00796   p = object_info->exported_properties;
00797   while (p != NULL && *p != '\0')
00798     {
00799       const char *prop_ifname;
00800       const char *prop_name;
00801       GParamSpec *pspec;
00802       GType value_gtype;
00803       GValue value = {0, };
00804       gchar *variant_sig;
00805 
00806       prop_ifname = p;
00807 
00808       while (*p != '\0')
00809         p++;
00810       p++;
00811       if (*p == '\0') {
00812         g_warning ("malformed exported_properties in object_info");
00813         break;
00814       }
00815       prop_name = p;
00816       while (*p != '\0')
00817         p++;
00818       p++;
00819 
00820       uscore_propname = _dbus_gutils_wincaps_to_uscore (prop_name);
00821 
00822       pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), uscore_propname);
00823       if (pspec == NULL)
00824         {
00825           g_warning ("introspection data references non-existing property %s", uscore_propname);
00826           g_free (uscore_propname);
00827           continue;
00828         }
00829 
00830       g_free (uscore_propname);
00831 
00832       g_value_init (&value, pspec->value_type);
00833       g_object_get_property (object, pspec->name, &value);
00834 
00835       variant_sig = _dbus_gvalue_to_signature (&value);
00836       if (variant_sig == NULL)
00837         {
00838           value_gtype = G_VALUE_TYPE (&value);
00839           g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
00840           g_value_unset (&value);
00841           continue;
00842         }
00843 
00844       if (!dbus_message_iter_open_container (&iter_dict,
00845                                              DBUS_TYPE_DICT_ENTRY,
00846                                              NULL,
00847                                              &iter_dict_entry))
00848         goto oom;
00849       if (!dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &prop_name))
00850         goto oom;
00851 
00852       if (!dbus_message_iter_open_container (&iter_dict_entry,
00853                                              DBUS_TYPE_VARIANT,
00854                                              variant_sig,
00855                                              &iter_dict_value))
00856         goto oom;
00857 
00858       if (!_dbus_gvalue_marshal (&iter_dict_value, &value))
00859         goto oom;
00860 
00861       if (!dbus_message_iter_close_container (&iter_dict_entry,
00862                                               &iter_dict_value))
00863         goto oom;
00864       if (!dbus_message_iter_close_container (&iter_dict, &iter_dict_entry))
00865         goto oom;
00866 
00867       g_value_unset (&value);
00868       g_free (variant_sig);
00869   }
00870 
00871   if (!dbus_message_iter_close_container (&iter_ret, &iter_dict))
00872     goto oom;
00873 
00874   return ret;
00875 
00876  oom:
00877   g_error ("out of memory");
00878 }
00879 
00880 static gboolean
00881 lookup_object_and_method (GObject      *object,
00882                           DBusMessage  *message,
00883                           const DBusGObjectInfo **object_ret,
00884                           const DBusGMethodInfo **method_ret)
00885 {
00886   const char *interface;
00887   const char *member;
00888   const char *signature;
00889   GList *info_list;
00890   const GList *info_list_walk;
00891   const DBusGObjectInfo *info;
00892   int i;
00893 
00894   interface = dbus_message_get_interface (message);
00895   member = dbus_message_get_member (message);
00896   signature = dbus_message_get_signature (message);
00897 
00898   info_list = lookup_object_info (object);
00899   
00900   for (info_list_walk = info_list; info_list_walk != NULL; info_list_walk = g_list_next (info_list_walk))
00901     {
00902       info = (DBusGObjectInfo *) info_list_walk->data;
00903       *object_ret = info;
00904 
00905       for (i = 0; i < info->n_method_infos; i++)
00906         {
00907           const char *expected_member;
00908           const char *expected_interface;
00909           char *expected_signature;
00910           const DBusGMethodInfo *method;
00911 
00912           method = &(info->method_infos[i]);
00913 
00914            
00915           expected_interface = method_interface_from_object_info (*object_ret, method);
00916           expected_member = method_name_from_object_info (*object_ret, method);
00917           expected_signature = method_input_signature_from_object_info (*object_ret, method);
00918 
00919           if ((interface == NULL
00920               || strcmp (expected_interface, interface) == 0)
00921               && strcmp (expected_member, member) == 0
00922               && strcmp (expected_signature, signature) == 0)
00923             {
00924               g_free (expected_signature);
00925               *method_ret = method;
00926               g_list_free (info_list);
00927               return TRUE;
00928             }
00929             g_free (expected_signature);
00930         }
00931     }
00932 
00933   if (info_list)
00934     g_list_free (info_list);
00935 
00936   return FALSE;
00937 }
00938 
00939 static char *
00940 gerror_domaincode_to_dbus_error_name (const DBusGObjectInfo *object_info,
00941                                       const char *msg_interface,
00942                                       GQuark domain, gint code)
00943 {
00944   const char *domain_str;
00945   const char *code_str;
00946   GString *dbus_error_name;
00947 
00948   domain_str = object_error_domain_prefix_from_object_info (object_info);
00949   code_str = object_error_code_from_object_info (object_info, domain, code);
00950 
00951   if (!domain_str || !code_str)
00952     {
00953       DBusGErrorInfo *info;
00954 
00955       g_static_rw_lock_reader_lock (&globals_lock);
00956 
00957       if (error_metadata != NULL)
00958         info = g_datalist_id_get_data (&error_metadata, domain);
00959       else
00960         info = NULL;
00961 
00962       g_static_rw_lock_reader_unlock (&globals_lock);
00963 
00964       if (info)
00965         {
00966           GEnumValue *value;
00967           GEnumClass *klass;
00968 
00969           klass = g_type_class_ref (info->code_enum);
00970           value = g_enum_get_value (klass, code);
00971           g_type_class_unref (klass);
00972 
00973           domain_str = info->default_iface;
00974           code_str = value->value_nick;
00975         }
00976     }
00977 
00978   if (!domain_str)
00979     domain_str = msg_interface;
00980 
00981   if (!domain_str || !code_str)
00982     {
00983       
00984       char *domain_from_quark;
00985       
00986       dbus_error_name = g_string_new ("org.freedesktop.DBus.GLib.UnmappedError.");
00987 
00988       domain_from_quark = uscore_to_wincaps (g_quark_to_string (domain));
00989       g_string_append (dbus_error_name, domain_from_quark);
00990       g_free (domain_from_quark);
00991         
00992       g_string_append_printf (dbus_error_name, ".Code%d", code);
00993     }
00994   else
00995     {
00996       dbus_error_name = g_string_new (domain_str);
00997       g_string_append_c (dbus_error_name, '.');
00998       g_string_append (dbus_error_name, code_str);
00999     }
01000 
01001   return g_string_free (dbus_error_name, FALSE);
01002 }
01003 
01004 static DBusMessage *
01005 gerror_to_dbus_error_message (const DBusGObjectInfo *object_info,
01006                               DBusMessage     *message,
01007                               GError          *error)
01008 {
01009   DBusMessage *reply;
01010 
01011   if (!error)
01012     {
01013       char *error_msg;
01014       
01015       error_msg = g_strdup_printf ("Method invoked for %s returned FALSE but did not set error", dbus_message_get_member (message));
01016       reply = dbus_message_new_error (message, "org.freedesktop.DBus.GLib.ErrorError", error_msg);
01017       g_free (error_msg);
01018     }
01019   else
01020     {
01021       if (error->domain == DBUS_GERROR)
01022         {
01023           const gchar *name = DBUS_ERROR_FAILED;
01024 
01025           switch (error->code)
01026             {
01027             case DBUS_GERROR_FAILED:
01028               name = DBUS_ERROR_FAILED;
01029               break;
01030             case DBUS_GERROR_NO_MEMORY:
01031               name = DBUS_ERROR_NO_MEMORY;
01032               break;
01033             case DBUS_GERROR_SERVICE_UNKNOWN:
01034               name = DBUS_ERROR_SERVICE_UNKNOWN;
01035               break;
01036             case DBUS_GERROR_NAME_HAS_NO_OWNER:
01037               name = DBUS_ERROR_NAME_HAS_NO_OWNER;
01038               break;
01039             case DBUS_GERROR_NO_REPLY:
01040               name = DBUS_ERROR_NO_REPLY;
01041               break;
01042             case DBUS_GERROR_IO_ERROR:
01043               name = DBUS_ERROR_IO_ERROR;
01044               break;
01045             case DBUS_GERROR_BAD_ADDRESS:
01046               name = DBUS_ERROR_BAD_ADDRESS;
01047               break;
01048             case DBUS_GERROR_NOT_SUPPORTED:
01049               name = DBUS_ERROR_NOT_SUPPORTED;
01050               break;
01051             case DBUS_GERROR_LIMITS_EXCEEDED:
01052               name = DBUS_ERROR_LIMITS_EXCEEDED;
01053               break;
01054             case DBUS_GERROR_ACCESS_DENIED:
01055               name = DBUS_ERROR_ACCESS_DENIED;
01056               break;
01057             case DBUS_GERROR_AUTH_FAILED:
01058               name = DBUS_ERROR_AUTH_FAILED;
01059               break;
01060             case DBUS_GERROR_NO_SERVER:
01061               name = DBUS_ERROR_NO_SERVER;
01062               break;
01063             case DBUS_GERROR_TIMEOUT:
01064               name = DBUS_ERROR_TIMEOUT;
01065               break;
01066             case DBUS_GERROR_NO_NETWORK:
01067               name = DBUS_ERROR_NO_NETWORK;
01068               break;
01069             case DBUS_GERROR_ADDRESS_IN_USE:
01070               name = DBUS_ERROR_ADDRESS_IN_USE;
01071               break;
01072             case DBUS_GERROR_DISCONNECTED:
01073               name = DBUS_ERROR_DISCONNECTED;
01074               break;
01075             case DBUS_GERROR_INVALID_ARGS:
01076               name = DBUS_ERROR_INVALID_ARGS;
01077               break;
01078             case DBUS_GERROR_FILE_NOT_FOUND:
01079               name = DBUS_ERROR_FILE_NOT_FOUND;
01080               break;
01081             case DBUS_GERROR_REMOTE_EXCEPTION:
01082               name = dbus_g_error_get_name (error);
01083               break;
01084             }
01085 
01086           reply = dbus_message_new_error (message, name, error->message);
01087         }
01088       else
01089         {
01090           char *error_name;
01091           error_name = gerror_domaincode_to_dbus_error_name (object_info,
01092                                                              dbus_message_get_interface (message),
01093                                                              error->domain, error->code);
01094           reply = dbus_message_new_error (message, error_name, error->message);
01095           g_free (error_name); 
01096         }
01097     }
01098   return reply;
01099 }
01100 
01114 struct _DBusGMethodInvocation {
01115   DBusGConnection *connection; 
01116   DBusGMessage *message; 
01117   const DBusGObjectInfo *object; 
01118   const DBusGMethodInfo *method; 
01119 };
01120 
01121 static DBusHandlerResult
01122 invoke_object_method (GObject         *object,
01123                       const DBusGObjectInfo *object_info,
01124                       const DBusGMethodInfo *method,
01125                       DBusConnection  *connection,
01126                       DBusMessage     *message)
01127 {
01128   gboolean had_error, call_only;
01129   GError *gerror;
01130   GValueArray *value_array;
01131   GValue return_value = {0,};
01132   GClosure closure;
01133   char *in_signature;
01134   GArray *out_param_values = NULL;
01135   GValueArray *out_param_gvalues = NULL;
01136   int out_param_count;
01137   int out_param_pos, out_param_gvalue_pos;
01138   DBusHandlerResult result;
01139   DBusMessage *reply;
01140   gboolean have_retval;
01141   gboolean retval_signals_error;
01142   gboolean retval_is_synthetic;
01143   gboolean retval_is_constant;
01144   const char *arg_metadata;
01145 
01146   gerror = NULL;
01147 
01148   
01149 
01150 
01151   if (strcmp (string_table_lookup (get_method_data (object_info, method), 2), "A") == 0)
01152     call_only = TRUE;
01153   else
01154     call_only = FALSE;
01155 
01156   have_retval = FALSE;
01157   retval_signals_error = FALSE;
01158   retval_is_synthetic = FALSE;
01159   retval_is_constant = FALSE;
01160 
01161   
01162 
01163 
01164 
01165 
01166   memset (&closure, 0, sizeof (closure));
01167 
01168   in_signature = method_input_signature_from_object_info (object_info, method); 
01169   
01170   
01171   {
01172     GArray *types_array;
01173     guint n_params;
01174     const GType *types;
01175     DBusGValueMarshalCtx context;
01176     GError *error = NULL;
01177     
01178     context.recursion_depth = 0;
01179     context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
01180     context.proxy = NULL;
01181 
01182     types_array = _dbus_gtypes_from_arg_signature (in_signature, FALSE);
01183     n_params = types_array->len;
01184     types = (const GType*) types_array->data;
01185 
01186     value_array = _dbus_gvalue_demarshal_message (&context, message, n_params, types, &error);
01187     if (value_array == NULL)
01188       {
01189         g_free (in_signature); 
01190         g_array_free (types_array, TRUE);
01191         reply = dbus_message_new_error (message, "org.freedesktop.DBus.GLib.ErrorError", error->message);
01192         dbus_connection_send (connection, reply, NULL);
01193         dbus_message_unref (reply);
01194         g_error_free (error);
01195         return DBUS_HANDLER_RESULT_HANDLED;
01196       }
01197     g_array_free (types_array, TRUE);
01198   }
01199 
01200    
01201   g_value_array_prepend (value_array, NULL);
01202   g_value_init (g_value_array_get_nth (value_array, 0), G_TYPE_OBJECT);
01203   g_value_set_object (g_value_array_get_nth (value_array, 0), object);
01204   
01205   if (call_only)
01206     {
01207       GValue context_value = {0,};
01208       DBusGMethodInvocation *context;
01209       context = g_new (DBusGMethodInvocation, 1);
01210       context->connection = dbus_g_connection_ref (DBUS_G_CONNECTION_FROM_CONNECTION (connection));
01211       context->message = dbus_g_message_ref (DBUS_G_MESSAGE_FROM_MESSAGE (message));
01212       context->object = object_info;
01213       context->method = method;
01214       g_value_init (&context_value, G_TYPE_POINTER);
01215       g_value_set_pointer (&context_value, context);
01216       g_value_array_append (value_array, &context_value);
01217     }
01218   else
01219     {
01220       RetvalType retval;
01221       gboolean arg_in;
01222       gboolean arg_const;
01223       const char *argsig;
01224 
01225       arg_metadata = method_arg_info_from_object_info (object_info, method);
01226       
01227       
01228       out_param_count = 0;
01229       while (*arg_metadata)
01230         {
01231           arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, &arg_const, &retval, &argsig);
01232           if (arg_in)
01233             continue;
01234           if (retval != RETVAL_NONE)
01235             {
01236               DBusSignatureIter tmp_sigiter;
01237               
01238               g_assert (!have_retval);
01239               have_retval = TRUE;
01240               retval_is_synthetic = FALSE;
01241 
01242               switch (retval)
01243                 {
01244                 case RETVAL_NONE:
01245                   g_assert_not_reached ();
01246                   break;
01247                 case RETVAL_NOERROR:
01248                   retval_signals_error = FALSE;
01249                   break;
01250                 case RETVAL_ERROR:
01251                   retval_signals_error = TRUE;
01252                   break;
01253                 }
01254 
01255               retval_is_constant = arg_const;
01256 
01257               
01258               dbus_signature_iter_init (&tmp_sigiter, argsig);
01259               g_value_init (&return_value, _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE));
01260             }
01261           else
01262             {
01263               
01264               out_param_count++;
01265             }
01266         }
01267 
01268       
01269 
01270 
01271 
01272 
01273 
01274       if (!have_retval)
01275         {
01276           have_retval = TRUE;
01277           retval_is_synthetic = TRUE;
01278           retval_signals_error = TRUE;
01279           g_value_init (&return_value, G_TYPE_BOOLEAN);
01280         }
01281 
01282       
01283 
01284 
01285 
01286 
01287       out_param_values = g_array_sized_new (FALSE, TRUE, sizeof (GTypeCValue), out_param_count);
01288 
01289       
01290 
01291 
01292       out_param_gvalues = g_value_array_new (out_param_count);
01293       out_param_pos = 0;
01294       out_param_gvalue_pos = 0;
01295 
01296       
01297       arg_metadata = method_arg_info_from_object_info (object_info, method);
01298       
01299       
01300 
01301 
01302       while (*arg_metadata)
01303         {
01304           GValue value = {0, };
01305           GTypeCValue storage;
01306           DBusSignatureIter tmp_sigiter;
01307           GType current_gtype;
01308 
01309           arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, NULL, &retval, &argsig);
01310           
01311           if (arg_in || retval != RETVAL_NONE)
01312             continue;
01313 
01314           dbus_signature_iter_init (&tmp_sigiter, argsig);
01315           current_gtype = _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE);
01316 
01317           g_value_init (&value, G_TYPE_POINTER);
01318 
01319           
01320           if (current_gtype != G_TYPE_VALUE)
01321             {
01322               memset (&storage, 0, sizeof (storage));
01323               g_array_append_val (out_param_values, storage);
01324               g_value_set_pointer (&value, &(g_array_index (out_param_values, GTypeCValue, out_param_pos)));
01325               out_param_pos++;
01326             }
01327           else
01328             {
01329               g_value_array_append (out_param_gvalues, NULL);
01330               g_value_set_pointer (&value, out_param_gvalues->values + out_param_gvalue_pos);
01331               out_param_gvalue_pos++;
01332             }
01333           g_value_array_append (value_array, &value);
01334         }
01335     }
01336 
01337   
01338   if (retval_signals_error)
01339     {
01340       g_assert (have_retval);
01341       g_value_array_append (value_array, NULL);
01342       g_value_init (g_value_array_get_nth (value_array, value_array->n_values - 1), G_TYPE_POINTER);
01343       g_value_set_pointer (g_value_array_get_nth (value_array, value_array->n_values - 1), &gerror);
01344     }
01345   
01346   
01347   method->marshaller (&closure, have_retval ? &return_value : NULL,
01348                       value_array->n_values,
01349                       value_array->values,
01350                       NULL, method->function);
01351   if (call_only)
01352     {
01353       result = DBUS_HANDLER_RESULT_HANDLED;
01354       goto done;
01355     }
01356   if (retval_signals_error)
01357     had_error = _dbus_gvalue_signals_error (&return_value);
01358   else
01359     had_error = FALSE;
01360 
01361   if (!had_error)
01362     {
01363       DBusMessageIter iter;
01364 
01365       reply = dbus_message_new_method_return (message);
01366       if (reply == NULL)
01367         goto nomem;
01368 
01369       
01370       dbus_message_iter_init_append (reply, &iter);
01371 
01372       
01373       if (have_retval && !retval_is_synthetic)
01374         {
01375           if (!_dbus_gvalue_marshal (&iter, &return_value))
01376             goto nomem;
01377           if (!retval_is_constant)
01378             g_value_unset (&return_value);
01379         }
01380 
01381       
01382       arg_metadata = method_arg_info_from_object_info (object_info, method);
01383       
01384       
01385       out_param_pos = 0;
01386       out_param_gvalue_pos = 0;
01387       while (*arg_metadata)
01388         {
01389           GValue gvalue = {0, };
01390           const char *arg_name;
01391           gboolean arg_in;
01392           gboolean constval;
01393           RetvalType retval;
01394           const char *arg_signature;
01395           DBusSignatureIter argsigiter;
01396 
01397           do
01398             {
01399               
01400 
01401               arg_metadata = arg_iterate (arg_metadata, &arg_name, &arg_in, &constval, &retval, &arg_signature);
01402             }
01403           while ((arg_in || retval != RETVAL_NONE) && *arg_metadata);
01404 
01405           
01406 
01407 
01408           if (arg_in || retval != RETVAL_NONE)
01409             break;
01410 
01411           dbus_signature_iter_init (&argsigiter, arg_signature);
01412           
01413           g_value_init (&gvalue, _dbus_gtype_from_signature_iter (&argsigiter, FALSE));
01414           if (G_VALUE_TYPE (&gvalue) != G_TYPE_VALUE)
01415             {
01416               if (!_dbus_gvalue_take (&gvalue,
01417                                      &(g_array_index (out_param_values, GTypeCValue, out_param_pos))))
01418                 g_assert_not_reached ();
01419               out_param_pos++;
01420             }
01421           else
01422             {
01423               g_value_set_static_boxed (&gvalue, out_param_gvalues->values + out_param_gvalue_pos);
01424               out_param_gvalue_pos++;
01425             }
01426               
01427           if (!_dbus_gvalue_marshal (&iter, &gvalue))
01428             goto nomem;
01429           
01430 
01431 
01432 
01433           if (!constval)
01434             g_value_unset (&gvalue);
01435         }
01436     }
01437   else
01438     reply = gerror_to_dbus_error_message (object_info, message, gerror);
01439 
01440   if (reply)
01441     {
01442       dbus_connection_send (connection, reply, NULL);
01443       dbus_message_unref (reply);
01444     }
01445 
01446   result = DBUS_HANDLER_RESULT_HANDLED;
01447  done:
01448   g_free (in_signature);
01449   if (!call_only)
01450     {
01451       g_array_free (out_param_values, TRUE);
01452       g_value_array_free (out_param_gvalues);
01453     }
01454   g_value_array_free (value_array);
01455   return result;
01456  nomem:
01457   result = DBUS_HANDLER_RESULT_NEED_MEMORY;
01458   goto done;
01459 }
01460 
01461 static DBusHandlerResult
01462 gobject_message_function (DBusConnection  *connection,
01463                           DBusMessage     *message,
01464                           void            *user_data)
01465 {
01466   GParamSpec *pspec;
01467   GObject *object;
01468   gboolean setter;
01469   gboolean getter;
01470   gboolean getall;
01471   char *s;
01472   const char *wincaps_propname;
01473   
01474   DBusMessageIter iter;
01475   const DBusGMethodInfo *method;
01476   const DBusGObjectInfo *object_info;
01477   DBusMessage *ret;
01478 
01479   object = G_OBJECT (user_data);
01480 
01481   if (dbus_message_is_method_call (message,
01482                                    DBUS_INTERFACE_INTROSPECTABLE,
01483                                    "Introspect"))
01484     return handle_introspect (connection, message, object);
01485 
01486   
01487   object_info = NULL;
01488   if (lookup_object_and_method (object, message, &object_info, &method))
01489     return invoke_object_method (object, object_info, method, connection, message);
01490 
01491   
01492 
01493 
01494   getter = FALSE;
01495   setter = FALSE;
01496   getall = FALSE;
01497   if (dbus_message_is_method_call (message,
01498                                    DBUS_INTERFACE_PROPERTIES,
01499                                    "Get"))
01500     getter = TRUE;
01501   else if (dbus_message_is_method_call (message,
01502                                         DBUS_INTERFACE_PROPERTIES,
01503                                         "Set"))
01504     setter = TRUE;
01505   else if (dbus_message_is_method_call (message,
01506                                    DBUS_INTERFACE_PROPERTIES,
01507                                    "GetAll"))
01508     getall = TRUE;
01509 
01510   if (!(setter || getter || getall))
01511     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01512 
01513   ret = NULL;
01514 
01515   dbus_message_iter_init (message, &iter);
01516 
01517   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
01518     {
01519       g_warning ("Property get or set does not have an interface string as first arg\n");
01520       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01521     }
01522   
01523 
01524 
01525   
01526   dbus_message_iter_next (&iter);
01527 
01528   if (getall)
01529     {
01530       if (object_info != NULL)
01531           ret = get_all_object_properties (connection, message, object_info, object);
01532       else
01533           return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01534     }
01535   else if (getter || setter)
01536     {
01537       if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
01538         {
01539           g_warning ("Property get or set does not have a property name string as second arg\n");
01540           return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01541         }
01542       dbus_message_iter_get_basic (&iter, &wincaps_propname);
01543       dbus_message_iter_next (&iter);
01544 
01545       s = _dbus_gutils_wincaps_to_uscore (wincaps_propname);
01546 
01547       pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
01548                                             s);
01549 
01550       g_free (s);
01551 
01552       if (pspec != NULL)
01553         {
01554           if (setter)
01555             {
01556               if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT)
01557                 {
01558                   g_warning ("Property set does not have a variant value as third arg\n");
01559                   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01560                 }
01561 
01562               ret = set_object_property (connection, message, &iter,
01563                                          object, pspec);
01564               dbus_message_iter_next (&iter);
01565             }
01566           else if (getter)
01567             {
01568               ret = get_object_property (connection, message,
01569                                          object, pspec);
01570             }
01571           else
01572             {
01573               g_assert_not_reached ();
01574               ret = NULL;
01575             }
01576         }
01577       else
01578         {
01579           ret = dbus_message_new_error_printf (message,
01580                                                DBUS_ERROR_INVALID_ARGS,
01581                                                "No such property %s", wincaps_propname);
01582         }
01583     }
01584 
01585   g_assert (ret != NULL);
01586 
01587   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID)
01588     g_warning ("Property get, set or set all had too many arguments\n");
01589 
01590   dbus_connection_send (connection, ret, NULL);
01591   dbus_message_unref (ret);
01592   return DBUS_HANDLER_RESULT_HANDLED;
01593 }
01594 
01595 static const DBusObjectPathVTable gobject_dbus_vtable = {
01596   gobject_unregister_function,
01597   gobject_message_function,
01598   NULL
01599 };
01600 
01601 typedef struct {
01602   GClosure         closure;
01603   DBusGConnection *connection;
01604   GObject         *object;
01605   const char      *signame;
01606   const char      *sigiface;
01607 } DBusGSignalClosure;
01608 
01609 static GClosure *
01610 dbus_g_signal_closure_new (DBusGConnection *connection,
01611                            GObject         *object,
01612                            const char      *signame,
01613                            const char      *sigiface)
01614 {
01615   DBusGSignalClosure *closure;
01616   
01617   closure = (DBusGSignalClosure*) g_closure_new_simple (sizeof (DBusGSignalClosure), NULL);
01618 
01619   closure->connection = dbus_g_connection_ref (connection);
01620   closure->object = object;
01621   closure->signame = signame;
01622   closure->sigiface = sigiface;
01623   return (GClosure*) closure;
01624 }
01625 
01626 static void
01627 dbus_g_signal_closure_finalize (gpointer data,
01628                                 GClosure *closure)
01629 {
01630   DBusGSignalClosure *sigclosure = (DBusGSignalClosure *) closure;
01631 
01632   dbus_g_connection_unref (sigclosure->connection);
01633 }
01634 
01635 static void
01636 signal_emitter_marshaller (GClosure        *closure,
01637                            GValue          *retval,
01638                            guint            n_param_values,
01639                            const GValue    *param_values,
01640                            gpointer         invocation_hint,
01641                            gpointer         marshal_data)
01642 {
01643   DBusGSignalClosure *sigclosure;
01644   DBusMessage *signal;
01645   DBusMessageIter iter;
01646   guint i;
01647   const char *path;
01648 
01649   sigclosure = (DBusGSignalClosure *) closure;
01650   
01651   g_assert (retval == NULL);
01652 
01653   path = _dbus_gobject_get_path (sigclosure->object);
01654 
01655   g_assert (path != NULL);
01656 
01657   signal = dbus_message_new_signal (path,
01658                                     sigclosure->sigiface,
01659                                     sigclosure->signame);
01660   if (!signal)
01661     {
01662       g_error ("out of memory");
01663       return;
01664     }
01665 
01666   dbus_message_iter_init_append (signal, &iter);
01667 
01668   
01669   for (i = 1; i < n_param_values; i++)
01670     {
01671       if (!_dbus_gvalue_marshal (&iter,
01672                                 (GValue *) (&(param_values[i]))))
01673         {
01674           g_warning ("failed to marshal parameter %d for signal %s",
01675                      i, sigclosure->signame);
01676           goto out;
01677         }
01678     }
01679   dbus_connection_send (DBUS_CONNECTION_FROM_G_CONNECTION (sigclosure->connection),
01680                         signal, NULL);
01681  out:
01682   dbus_message_unref (signal);
01683 }
01684 
01685 static void
01686 export_signals (DBusGConnection *connection, const GList *info_list, GObject *object)
01687 {
01688   GType gtype;
01689   const char *sigdata;
01690   const char *iface;
01691   const char *signame;
01692   const DBusGObjectInfo *info;
01693 
01694   gtype = G_TYPE_FROM_INSTANCE (object);
01695 
01696   for (; info_list != NULL; info_list = g_list_next (info_list))
01697     {
01698       info = (DBusGObjectInfo *) info_list->data;
01699       
01700       sigdata = info->exported_signals;
01701       
01702       while (*sigdata != '\0')
01703         {
01704           guint id;
01705           GSignalQuery query;
01706           GClosure *closure;
01707           char *s;
01708 
01709           sigdata = propsig_iterate (sigdata, &iface, &signame);
01710           
01711           s = _dbus_gutils_wincaps_to_uscore (signame);
01712 
01713           id = g_signal_lookup (s, gtype);
01714           if (id == 0)
01715             {
01716               g_warning ("signal \"%s\" (from \"%s\") exported but not found in object class \"%s\"",
01717                      s, signame, g_type_name (gtype));
01718               g_free (s);
01719               continue;
01720             }
01721 
01722           g_signal_query (id, &query);
01723 
01724           if (query.return_type != G_TYPE_NONE)
01725             {
01726               g_warning ("Not exporting signal \"%s\" for object class \"%s\" as it has a return type \"%s\"",
01727                      s, g_type_name (gtype), g_type_name (query.return_type));
01728               g_free (s);
01729               continue; 
01730             }
01731           
01732           closure = dbus_g_signal_closure_new (connection, object, signame, (char*) iface);
01733           g_closure_set_marshal (closure, signal_emitter_marshaller);
01734 
01735           g_signal_connect_closure_by_id (object,
01736                           id,
01737                           0,
01738                           closure,
01739                           FALSE);
01740 
01741           g_closure_add_finalize_notifier (closure, NULL,
01742                            dbus_g_signal_closure_finalize);
01743           g_free (s);
01744         }
01745     }
01746 }
01747 
01748 static gint
01749 dbus_error_to_gerror_code (const char *derr)
01750 {
01751   if (0) ; 
01752   else if (!strcmp (derr,  DBUS_ERROR_FAILED  )) 
01753     return  DBUS_GERROR_FAILED ;
01754   else if (!strcmp (derr,  DBUS_ERROR_NO_MEMORY  )) 
01755     return  DBUS_GERROR_NO_MEMORY ;
01756   else if (!strcmp (derr,  DBUS_ERROR_SERVICE_UNKNOWN  )) 
01757     return  DBUS_GERROR_SERVICE_UNKNOWN ;
01758   else if (!strcmp (derr,  DBUS_ERROR_NAME_HAS_NO_OWNER  )) 
01759     return  DBUS_GERROR_NAME_HAS_NO_OWNER ;
01760   else if (!strcmp (derr,  DBUS_ERROR_NO_REPLY  )) 
01761     return  DBUS_GERROR_NO_REPLY ;
01762   else if (!strcmp (derr,  DBUS_ERROR_IO_ERROR  )) 
01763     return  DBUS_GERROR_IO_ERROR ;
01764   else if (!strcmp (derr,  DBUS_ERROR_BAD_ADDRESS  )) 
01765     return  DBUS_GERROR_BAD_ADDRESS ;
01766   else if (!strcmp (derr,  DBUS_ERROR_NOT_SUPPORTED  )) 
01767     return  DBUS_GERROR_NOT_SUPPORTED ;
01768   else if (!strcmp (derr,  DBUS_ERROR_LIMITS_EXCEEDED  )) 
01769     return  DBUS_GERROR_LIMITS_EXCEEDED ;
01770   else if (!strcmp (derr,  DBUS_ERROR_ACCESS_DENIED  )) 
01771     return  DBUS_GERROR_ACCESS_DENIED ;
01772   else if (!strcmp (derr,  DBUS_ERROR_AUTH_FAILED  )) 
01773     return  DBUS_GERROR_AUTH_FAILED ;
01774   else if (!strcmp (derr,  DBUS_ERROR_NO_SERVER  )) 
01775     return  DBUS_GERROR_NO_SERVER ;
01776   else if (!strcmp (derr,  DBUS_ERROR_TIMEOUT  )) 
01777     return  DBUS_GERROR_TIMEOUT ;
01778   else if (!strcmp (derr,  DBUS_ERROR_NO_NETWORK  )) 
01779     return  DBUS_GERROR_NO_NETWORK ;
01780   else if (!strcmp (derr,  DBUS_ERROR_ADDRESS_IN_USE  )) 
01781     return  DBUS_GERROR_ADDRESS_IN_USE ;
01782   else if (!strcmp (derr,  DBUS_ERROR_DISCONNECTED  )) 
01783     return  DBUS_GERROR_DISCONNECTED ;
01784   else if (!strcmp (derr,  DBUS_ERROR_INVALID_ARGS  )) 
01785     return  DBUS_GERROR_INVALID_ARGS ;
01786   else if (!strcmp (derr,  DBUS_ERROR_FILE_NOT_FOUND  )) 
01787     return  DBUS_GERROR_FILE_NOT_FOUND ;
01788   else if (!strcmp (derr,  DBUS_ERROR_FILE_EXISTS  )) 
01789     return  DBUS_GERROR_FILE_EXISTS ;
01790   else if (!strcmp (derr,  DBUS_ERROR_UNKNOWN_METHOD  )) 
01791     return  DBUS_GERROR_UNKNOWN_METHOD ;
01792   else if (!strcmp (derr,  DBUS_ERROR_TIMED_OUT  )) 
01793     return  DBUS_GERROR_TIMED_OUT ;
01794   else if (!strcmp (derr,  DBUS_ERROR_MATCH_RULE_NOT_FOUND  )) 
01795     return  DBUS_GERROR_MATCH_RULE_NOT_FOUND ;
01796   else if (!strcmp (derr,  DBUS_ERROR_MATCH_RULE_INVALID  )) 
01797     return  DBUS_GERROR_MATCH_RULE_INVALID ;
01798   else if (!strcmp (derr,  DBUS_ERROR_SPAWN_EXEC_FAILED  )) 
01799     return  DBUS_GERROR_SPAWN_EXEC_FAILED ;
01800   else if (!strcmp (derr,  DBUS_ERROR_SPAWN_FORK_FAILED  )) 
01801     return  DBUS_GERROR_SPAWN_FORK_FAILED ;
01802   else if (!strcmp (derr,  DBUS_ERROR_SPAWN_CHILD_EXITED  )) 
01803     return  DBUS_GERROR_SPAWN_CHILD_EXITED ;
01804   else if (!strcmp (derr,  DBUS_ERROR_SPAWN_CHILD_SIGNALED  )) 
01805     return  DBUS_GERROR_SPAWN_CHILD_SIGNALED ;
01806   else if (!strcmp (derr,  DBUS_ERROR_SPAWN_FAILED  )) 
01807     return  DBUS_GERROR_SPAWN_FAILED ;
01808   else if (!strcmp (derr,  DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN  )) 
01809     return  DBUS_GERROR_UNIX_PROCESS_ID_UNKNOWN ;
01810   else if (!strcmp (derr,  DBUS_ERROR_INVALID_SIGNATURE  )) 
01811     return  DBUS_GERROR_INVALID_SIGNATURE ;
01812   else if (!strcmp (derr,  DBUS_ERROR_INVALID_FILE_CONTENT  )) 
01813     return  DBUS_GERROR_INVALID_FILE_CONTENT ;
01814   else if (!strcmp (derr,  DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN  )) 
01815     return  DBUS_GERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN ;
01816   else
01817     return DBUS_GERROR_REMOTE_EXCEPTION;
01818 }
01819 
01842 void
01843 dbus_set_g_error (GError    **gerror,
01844                   DBusError  *error)
01845 {
01846   int code;
01847 
01848   code = dbus_error_to_gerror_code (error->name);
01849   if (code != DBUS_GERROR_REMOTE_EXCEPTION)
01850     g_set_error (gerror, DBUS_GERROR,
01851                  code,
01852                  "%s",
01853                  error->message);
01854   else
01855     g_set_error (gerror, DBUS_GERROR,
01856                  code,
01857                  "%s%c%s",
01858                  error->message ? error->message : "",
01859                  '\0',
01860                  error->name);
01861 }
01862 
01863 static void
01864 dbus_g_error_info_free (gpointer p)
01865 {
01866   DBusGErrorInfo *info;
01867 
01868   info = p;
01869 
01870   g_free (info->default_iface);
01871   g_free (info);
01872 }
01873 
01898 void
01899 dbus_g_object_type_install_info (GType                  object_type,
01900                                  const DBusGObjectInfo *info)
01901 {
01902   g_return_if_fail (G_TYPE_IS_CLASSED (object_type) || G_TYPE_IS_INTERFACE (object_type));
01903 
01904   _dbus_g_value_types_init ();
01905 
01906   g_type_set_qdata (object_type,
01907                     dbus_g_object_type_dbus_metadata_quark (),
01908                     (gpointer) info);
01909 }
01910 
01921 void
01922 dbus_g_error_domain_register (GQuark                domain,
01923                               const char           *default_iface,
01924                               GType                 code_enum)
01925 {
01926   DBusGErrorInfo *info;
01927   
01928   g_return_if_fail (g_quark_to_string (domain) != NULL);
01929   g_return_if_fail (code_enum != G_TYPE_INVALID);
01930   g_return_if_fail (G_TYPE_FUNDAMENTAL (code_enum) == G_TYPE_ENUM);
01931 
01932   g_static_rw_lock_writer_lock (&globals_lock);
01933 
01934   if (error_metadata == NULL)
01935     g_datalist_init (&error_metadata);
01936 
01937   info = g_datalist_id_get_data (&error_metadata, domain);
01938 
01939   if (info != NULL)
01940     {
01941       g_warning ("Metadata for error domain \"%s\" already registered\n",
01942                  g_quark_to_string (domain));
01943     }
01944   else
01945     {
01946       info = g_new0 (DBusGErrorInfo, 1);
01947       info->default_iface = g_strdup (default_iface);
01948       info->code_enum = code_enum;
01949 
01950       g_datalist_id_set_data_full (&error_metadata,
01951                                    domain,
01952                                    info,
01953                                    dbus_g_error_info_free);
01954     }
01955 
01956   g_static_rw_lock_writer_unlock (&globals_lock);
01957 }
01958 
01959 static void
01960 unregister_gobject (DBusGConnection *connection, GObject *dead)
01961 {
01962   char *path;
01963   path = g_object_steal_data (dead, "dbus_glib_object_path");
01964   dbus_connection_unregister_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (connection), path);
01965   g_free (path);
01966 }
01967 
01982 void
01983 dbus_g_connection_register_g_object (DBusGConnection       *connection,
01984                                      const char            *at_path,
01985                                      GObject               *object)
01986 {
01987   GList *info_list;
01988   g_return_if_fail (connection != NULL);
01989   g_return_if_fail (at_path != NULL);
01990   g_return_if_fail (G_IS_OBJECT (object));
01991 
01992   info_list = lookup_object_info (object);
01993   if (info_list == NULL)
01994     {
01995       g_warning ("No introspection data registered for object class \"%s\"",
01996                  g_type_name (G_TYPE_FROM_INSTANCE (object)));
01997       return;
01998     }
01999 
02000   if (!dbus_connection_register_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (connection),
02001                                              at_path,
02002                                              &gobject_dbus_vtable,
02003                                              object))
02004     {
02005       g_error ("Failed to register GObject with DBusConnection");
02006       return;
02007     }
02008 
02009   export_signals (connection, info_list, object);
02010   g_list_free (info_list);
02011 
02012   g_object_set_data (object, "dbus_glib_object_path", g_strdup (at_path));
02013   g_object_weak_ref (object, (GWeakNotify)unregister_gobject, connection);
02014 }
02015 
02025 GObject *
02026 dbus_g_connection_lookup_g_object (DBusGConnection       *connection,
02027                                    const char            *at_path)
02028 {
02029   gpointer ret;
02030   if (!dbus_connection_get_object_path_data (DBUS_CONNECTION_FROM_G_CONNECTION (connection), at_path, &ret))
02031     return NULL;
02032   return ret;
02033 }
02034 
02035 typedef struct {
02036   GType    rettype;
02037   guint    n_params;
02038   GType   *params;
02039 } DBusGFuncSignature;
02040 
02041 static guint
02042 funcsig_hash (gconstpointer key)
02043 {
02044   const DBusGFuncSignature *sig = key;
02045   GType *types;
02046   guint ret;
02047   guint i;
02048 
02049   ret = sig->rettype;
02050   types = sig->params;
02051 
02052   for (i = 0; i < sig->n_params; i++)
02053     {
02054       ret += (int) (*types);
02055       types++;
02056     }
02057       
02058   return ret;
02059 }
02060 
02061 static gboolean
02062 funcsig_equal (gconstpointer aval,
02063                gconstpointer bval)
02064 {
02065   const DBusGFuncSignature *a = aval;
02066   const DBusGFuncSignature *b = bval;
02067   const GType *atypes;
02068   const GType *btypes;
02069   guint i;
02070 
02071   if (a->rettype != b->rettype
02072       || a->n_params != b->n_params)
02073     return FALSE;
02074 
02075   atypes = a->params;
02076   btypes = b->params;
02077 
02078   for (i = 0; i < a->n_params; i++)
02079     {
02080       if (*btypes != *atypes)
02081         return FALSE;
02082       atypes++;
02083       btypes++;
02084     }
02085       
02086   return TRUE;
02087 }
02088 
02089 static void
02090 funcsig_free (DBusGFuncSignature *sig)
02091 {
02092   g_free (sig->params);
02093   g_free (sig);
02094 }
02095 
02096 GClosureMarshal
02097 _dbus_gobject_lookup_marshaller (GType        rettype,
02098                                  guint        n_params,
02099                                  const GType *param_types)
02100 {
02101   GClosureMarshal ret;
02102   DBusGFuncSignature sig;
02103   GType *params;
02104   guint i;
02105 
02106   
02107   rettype = G_TYPE_FUNDAMENTAL (rettype);
02108   params = g_new (GType, n_params);
02109   for (i = 0; i < n_params; i++)
02110     params[i] = G_TYPE_FUNDAMENTAL (param_types[i]);
02111 
02112   sig.rettype = rettype;
02113   sig.n_params = n_params;
02114   sig.params = params;
02115   
02116   g_static_rw_lock_reader_lock (&globals_lock);
02117 
02118   if (marshal_table)
02119     ret = g_hash_table_lookup (marshal_table, &sig);
02120   else
02121     ret = NULL;
02122 
02123   g_static_rw_lock_reader_unlock (&globals_lock);
02124 
02125   if (ret == NULL)
02126     {
02127       if (rettype == G_TYPE_NONE)
02128         {
02129           if (n_params == 0)
02130             ret = g_cclosure_marshal_VOID__VOID;
02131           else if (n_params == 1)
02132             {
02133               switch (params[0])
02134                 {
02135                 case G_TYPE_BOOLEAN:
02136                   ret = g_cclosure_marshal_VOID__BOOLEAN;
02137                   break;
02138                 case G_TYPE_UCHAR:
02139                   ret = g_cclosure_marshal_VOID__UCHAR;
02140                   break;
02141                 case G_TYPE_INT:
02142                   ret = g_cclosure_marshal_VOID__INT;
02143                   break;
02144                 case G_TYPE_UINT:
02145                   ret = g_cclosure_marshal_VOID__UINT;
02146                   break;
02147                 case G_TYPE_DOUBLE:
02148                   ret = g_cclosure_marshal_VOID__DOUBLE;
02149                   break;
02150                 case G_TYPE_STRING:
02151                   ret = g_cclosure_marshal_VOID__STRING;
02152                   break;
02153                 case G_TYPE_BOXED:
02154                   ret = g_cclosure_marshal_VOID__BOXED;
02155                   break;
02156                 }
02157             }
02158           else if (n_params == 3
02159                    && params[0] == G_TYPE_STRING
02160                    && params[1] == G_TYPE_STRING
02161                    && params[2] == G_TYPE_STRING)
02162             {
02163               ret = _dbus_g_marshal_NONE__STRING_STRING_STRING;
02164             }
02165         }
02166     }
02167 
02168   g_free (params);
02169   return ret;
02170 }
02171 
02184 void
02185 dbus_g_object_register_marshaller (GClosureMarshal  marshaller,
02186                                    GType            rettype,
02187                                    ...)
02188 {
02189   va_list args;
02190   GArray *types;
02191   GType gtype;
02192 
02193   va_start (args, rettype);
02194 
02195   types = g_array_new (TRUE, TRUE, sizeof (GType));
02196 
02197   while ((gtype = va_arg (args, GType)) != G_TYPE_INVALID)
02198     g_array_append_val (types, gtype);
02199 
02200   dbus_g_object_register_marshaller_array (marshaller, rettype,
02201                                            types->len, (GType*) types->data);
02202 
02203   g_array_free (types, TRUE);
02204   va_end (args);
02205 }
02206 
02217 void
02218 dbus_g_object_register_marshaller_array (GClosureMarshal  marshaller,
02219                                          GType            rettype,
02220                                          guint            n_types,
02221                                          const GType*     types)
02222 {
02223   DBusGFuncSignature *sig;
02224   guint i;
02225 
02226   g_static_rw_lock_writer_lock (&globals_lock);
02227 
02228   if (marshal_table == NULL)
02229     marshal_table = g_hash_table_new_full (funcsig_hash,
02230                                            funcsig_equal,
02231                                            (GDestroyNotify) funcsig_free,
02232                                            NULL);
02233   sig = g_new0 (DBusGFuncSignature, 1);
02234   sig->rettype = G_TYPE_FUNDAMENTAL (rettype);
02235   sig->n_params = n_types;
02236   sig->params = g_new (GType, n_types);
02237   for (i = 0; i < n_types; i++)
02238     sig->params[i] = G_TYPE_FUNDAMENTAL (types[i]);
02239 
02240   g_hash_table_insert (marshal_table, sig, marshaller);
02241 
02242   g_static_rw_lock_writer_unlock (&globals_lock);
02243 }
02244 
02257 gchar *
02258 dbus_g_method_get_sender (DBusGMethodInvocation *context)
02259 {
02260   const gchar *sender;
02261 
02262   sender = dbus_message_get_sender (dbus_g_message_get_message (context->message));
02263 
02264   if (sender == NULL)
02265     return NULL;
02266     
02267   return strdup (sender);
02268 }
02269 
02280 DBusMessage *
02281 dbus_g_method_get_reply (DBusGMethodInvocation *context)
02282 {
02283   return dbus_message_new_method_return (dbus_g_message_get_message (context->message));
02284 }
02285 
02295 void
02296 dbus_g_method_send_reply (DBusGMethodInvocation *context, DBusMessage *reply)
02297 {
02298   dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
02299   dbus_message_unref (reply);
02300 
02301   dbus_g_connection_unref (context->connection);
02302   dbus_g_message_unref (context->message);
02303   g_free (context);
02304 }
02305 
02306 
02314 void
02315 dbus_g_method_return (DBusGMethodInvocation *context, ...)
02316 {
02317   DBusMessage *reply;
02318   DBusMessageIter iter;
02319   va_list args;
02320   char *out_sig;
02321   GArray *argsig;
02322   guint i;
02323 
02324   reply = dbus_message_new_method_return (dbus_g_message_get_message (context->message));
02325   out_sig = method_output_signature_from_object_info (context->object, context->method);
02326   argsig = _dbus_gtypes_from_arg_signature (out_sig, FALSE);
02327 
02328   dbus_message_iter_init_append (reply, &iter);
02329 
02330   va_start (args, context);
02331   for (i = 0; i < argsig->len; i++)
02332     {
02333       GValue value = {0,};
02334       char *error;
02335       g_value_init (&value, g_array_index (argsig, GType, i));
02336       error = NULL;
02337       G_VALUE_COLLECT (&value, args, G_VALUE_NOCOPY_CONTENTS, &error);
02338       if (error)
02339         {
02340           g_warning(error);
02341           g_free (error);
02342         }
02343       _dbus_gvalue_marshal (&iter, &value);
02344     }
02345   va_end (args);
02346 
02347   dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
02348   dbus_message_unref (reply);
02349 
02350   dbus_g_connection_unref (context->connection);
02351   dbus_g_message_unref (context->message);
02352   g_free (context);
02353   g_free (out_sig);
02354   g_array_free (argsig, TRUE);
02355 }
02356 
02365 void
02366 dbus_g_method_return_error (DBusGMethodInvocation *context, GError *error)
02367 {
02368   DBusMessage *reply;
02369   reply = gerror_to_dbus_error_message (context->object, dbus_g_message_get_message (context->message), error);
02370   dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
02371   dbus_message_unref (reply);
02372   
02373   dbus_g_connection_unref (context->connection);
02374   dbus_g_message_unref (context->message);
02375   g_free (context);
02376 }
02377 
02378 const char * _dbus_gobject_get_path (GObject *obj)
02379 {
02380   return g_object_get_data (obj, "dbus_glib_object_path");
02381 }
02382 
02383 #ifdef DBUS_BUILD_TESTS
02384 #include <stdlib.h>
02385 
02386 static void
02387 _dummy_function (void)
02388 {
02389 }
02390 
02391 
02392 
02393 
02394 static const DBusGMethodInfo dbus_glib_internal_test_methods[] = {
02395   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 0 },
02396   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 49 },
02397   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 117 },
02398   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 191 },
02399   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 270 },
02400   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 320 },
02401   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 391 },
02402   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 495 },
02403   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 623 },
02404   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 693 },
02405   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 765 },
02406   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 838 },
02407   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 911 },
02408   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 988 },
02409   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1064 },
02410   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1140 },
02411   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1204 },
02412   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1278 },
02413   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1347 },
02414   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1408 },
02415   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1460 },
02416   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1533 },
02417   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1588 },
02418   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1647 },
02419   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1730 },
02420   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1784 },
02421   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1833 },
02422   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1895 },
02423   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1947 },
02424   { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1999 },
02425 };
02426 
02427 const DBusGObjectInfo dbus_glib_internal_test_object_info = {
02428   0,
02429   dbus_glib_internal_test_methods,
02430   30,
02431 "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",
02432 "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",
02433 "\0"
02434 };
02435 
02436 
02442 gboolean
02443 _dbus_gobject_test (const char *test_data_dir)
02444 {
02445   int i;
02446   const char *arg;
02447   const char *arg_name;
02448   gboolean arg_in;
02449   gboolean constval;
02450   RetvalType retval;
02451   const char *arg_signature;
02452   const char *sigdata;
02453   const char *iface;
02454   const char *signame;
02455   
02456   static struct { const char *wincaps; const char *uscore; } name_pairs[] = {
02457     { "SetFoo", "set_foo" },
02458     { "Foo", "foo" },
02459     { "GetFooBar", "get_foo_bar" },
02460     { "Hello", "hello" }
02461     
02462     
02463     
02464   };
02465 
02466   
02467 
02468 
02469 
02470   
02471   arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02472                                           &(dbus_glib_internal_test_methods[0]));
02473   g_assert (*arg == '\0');
02474 
02475   
02476   arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02477                                           &(dbus_glib_internal_test_methods[1]));
02478   g_assert (*arg != '\0');
02479   arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02480   g_assert (!strcmp (arg_name, "x"));
02481   g_assert (arg_in == TRUE);
02482   g_assert (!strcmp (arg_signature, "u"));
02483   g_assert (*arg != '\0');
02484   arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02485   g_assert (arg_in == FALSE);
02486   g_assert (retval == RETVAL_NONE);
02487   g_assert (!strcmp (arg_signature, "u"));
02488   g_assert (*arg == '\0');
02489 
02490   
02491   arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02492                                           &(dbus_glib_internal_test_methods[2]));
02493   g_assert (*arg != '\0');
02494   arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02495   g_assert (!strcmp (arg_name, "x"));
02496   g_assert (arg_in == TRUE);
02497   g_assert (!strcmp (arg_signature, "u"));
02498   g_assert (*arg != '\0');
02499   arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02500   g_assert (retval == RETVAL_NOERROR);
02501   g_assert (arg_in == FALSE);
02502   g_assert (!strcmp (arg_signature, "u"));
02503   g_assert (*arg == '\0');
02504 
02505   
02506   arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02507                                           &(dbus_glib_internal_test_methods[3]));
02508   g_assert (*arg != '\0');
02509   arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02510   g_assert (!strcmp (arg_name, "x"));
02511   g_assert (arg_in == TRUE);
02512   g_assert (!strcmp (arg_signature, "u"));
02513   g_assert (*arg != '\0');
02514   arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02515   g_assert (retval == RETVAL_ERROR);
02516   g_assert (arg_in == FALSE);
02517   g_assert (!strcmp (arg_signature, "u"));
02518   g_assert (*arg == '\0');
02519   
02520   
02521   arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02522                                           &(dbus_glib_internal_test_methods[8]));
02523   g_assert (*arg != '\0');
02524   arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02525   g_assert (!strcmp (arg_name, "val"));
02526   g_assert (arg_in == TRUE);
02527   g_assert (!strcmp (arg_signature, "v"));
02528   g_assert (*arg != '\0');
02529   arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02530   g_assert (retval == RETVAL_NONE);
02531   g_assert (arg_in == FALSE);
02532   g_assert (!strcmp (arg_signature, "s"));
02533   g_assert (*arg == '\0');
02534 
02535   sigdata = dbus_glib_internal_test_object_info.exported_signals;
02536   g_assert (*sigdata != '\0');
02537   sigdata = propsig_iterate (sigdata, &iface, &signame);
02538   g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.MyObject"));
02539   g_assert (!strcmp (signame, "Frobnicate"));
02540   g_assert (*sigdata != '\0');
02541   sigdata = propsig_iterate (sigdata, &iface, &signame);
02542   g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
02543   g_assert (!strcmp (signame, "Sig0"));
02544   g_assert (*sigdata != '\0');
02545   sigdata = propsig_iterate (sigdata, &iface, &signame);
02546   g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
02547   g_assert (!strcmp (signame, "Sig1"));
02548   g_assert (*sigdata != '\0');
02549   sigdata = propsig_iterate (sigdata, &iface, &signame);
02550   g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
02551   g_assert (!strcmp (signame, "Sig2"));
02552   g_assert (*sigdata == '\0');
02553   
02554 
02555   i = 0;
02556   while (i < (int) G_N_ELEMENTS (name_pairs))
02557     {
02558       char *uscore;
02559       char *wincaps;
02560 
02561       uscore = _dbus_gutils_wincaps_to_uscore (name_pairs[i].wincaps);
02562       wincaps = uscore_to_wincaps (name_pairs[i].uscore);
02563 
02564       if (strcmp (uscore, name_pairs[i].uscore) != 0)
02565         {
02566           g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
02567                       name_pairs[i].wincaps, name_pairs[i].uscore,
02568                       uscore);
02569           exit (1);
02570         }
02571       
02572       if (strcmp (wincaps, name_pairs[i].wincaps) != 0)
02573         {
02574           g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
02575                       name_pairs[i].uscore, name_pairs[i].wincaps,
02576                       wincaps);
02577           exit (1);
02578         }
02579       
02580       g_free (uscore);
02581       g_free (wincaps);
02582 
02583       ++i;
02584     }
02585   
02586   return TRUE;
02587 }
02588 
02589 #endif