ofdbus/dbus-glib/dbus/dbus-gproxy.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /* -*- mode: C; c-file-style: "gnu" -*- */
       
     2 /* dbus-gproxy.c Proxy for remote objects
       
     3  *
       
     4  * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
       
     5  * Copyright (C) 2005 Nokia
       
     6  * Portion Copyright © 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
       
     7  * Licensed under the Academic Free License version 2.1
       
     8  * 
       
     9  * This program is free software; you can redistribute it and/or modify
       
    10  * it under the terms of the GNU General Public License as published by
       
    11  * the Free Software Foundation; either version 2 of the License, or
       
    12  * (at your option) any later version.
       
    13  *
       
    14  * This program is distributed in the hope that it will be useful,
       
    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    17  * GNU General Public License for more details.
       
    18  * 
       
    19  * You should have received a copy of the GNU General Public License
       
    20  * along with this program; if not, write to the Free Software
       
    21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    22  *
       
    23  */
       
    24 #include <dbus/dbus-glib.h>
       
    25 #include <dbus/dbus-glib-lowlevel.h>
       
    26 #include <dbus/dbus-signature.h>
       
    27 #include "dbus-gutils.h"
       
    28 #include "dbus-gsignature.h"
       
    29 #include "dbus-gvalue.h"
       
    30 #include "dbus-gvalue-utils.h"
       
    31 #include "dbus-gobject.h"
       
    32 #include <string.h>
       
    33 
       
    34 
       
    35 #ifdef __SYMBIAN32__
       
    36 #include<glib_global.h>
       
    37 #include<glib-object.h>
       
    38 #endif
       
    39 
       
    40 #ifndef __SYMBIAN32__
       
    41 #include <glib/gi18n.h>
       
    42 #include <libintl.h>
       
    43 #define _(x) dgettext (GETTEXT_PACKAGE, x)
       
    44 #define N_(x) x
       
    45 #else
       
    46 
       
    47 #define _(x) x
       
    48 #define N_(x) x
       
    49 #endif
       
    50 
       
    51 #include <gobject/gvaluecollector.h>
       
    52 
       
    53 #ifdef __SYMBIAN32__
       
    54 #include "libdbus_glib_wsd_solution.h"
       
    55 #endif
       
    56 
       
    57 #define DBUS_G_PROXY_CALL_TO_ID(x) (GPOINTER_TO_UINT(x))
       
    58 #define DBUS_G_PROXY_ID_TO_CALL(x) (GUINT_TO_POINTER(x))
       
    59 #define DBUS_G_PROXY_GET_PRIVATE(o)  \
       
    60        (G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUS_TYPE_G_PROXY, DBusGProxyPrivate))
       
    61 
       
    62 
       
    63 /**
       
    64  * @addtogroup DBusGLibInternals
       
    65  *
       
    66  * @{
       
    67  */
       
    68 
       
    69 /**
       
    70  * DBusGProxyManager typedef
       
    71  */
       
    72 
       
    73 typedef struct _DBusGProxyManager DBusGProxyManager;
       
    74 
       
    75 typedef struct _DBusGProxyPrivate DBusGProxyPrivate;
       
    76 
       
    77 /**
       
    78  * Internals of DBusGProxy
       
    79  */
       
    80 struct _DBusGProxyPrivate
       
    81 {
       
    82   DBusGProxyManager *manager; /**< Proxy manager */
       
    83   char *name;                 /**< Name messages go to or NULL */
       
    84   char *path;                 /**< Path messages go to or NULL */
       
    85   char *interface;            /**< Interface messages go to or NULL */
       
    86 
       
    87   DBusGProxyCall *name_call;  /**< Pending call id to retrieve name owner */
       
    88   guint for_owner : 1;        /**< Whether or not this proxy is for a name owner */
       
    89   guint associated : 1;       /**< Whether or not this proxy is associated (for name proxies) */
       
    90 
       
    91   /* FIXME: make threadsafe? */
       
    92   guint call_id_counter;      /**< Integer counter for pending calls */
       
    93 
       
    94   GData *signal_signatures;   /**< D-BUS signatures for each signal */
       
    95 
       
    96   GHashTable *pending_calls;  /**< Calls made on this proxy which have not yet returned */
       
    97 };
       
    98 
       
    99 static void dbus_g_proxy_init               (DBusGProxy      *proxy);
       
   100 static void dbus_g_proxy_class_init         (DBusGProxyClass *klass);
       
   101 static GObject *dbus_g_proxy_constructor    (GType                  type,
       
   102 					     guint                  n_construct_properties,
       
   103 					     GObjectConstructParam *construct_properties);
       
   104 static void     dbus_g_proxy_set_property       (GObject               *object,
       
   105 						 guint                  prop_id,
       
   106 						 const GValue          *value,
       
   107 						 GParamSpec            *pspec);
       
   108 static void     dbus_g_proxy_get_property       (GObject               *object,
       
   109 						 guint                  prop_id,
       
   110 						 GValue                *value,
       
   111 						 GParamSpec            *pspec);
       
   112 
       
   113 static void dbus_g_proxy_finalize           (GObject         *object);
       
   114 static void dbus_g_proxy_dispose            (GObject         *object);
       
   115 static void dbus_g_proxy_destroy            (DBusGProxy      *proxy);
       
   116 static void dbus_g_proxy_emit_remote_signal (DBusGProxy      *proxy,
       
   117                                              DBusMessage     *message);
       
   118 
       
   119 static DBusGProxyCall *manager_begin_bus_call (DBusGProxyManager    *manager,
       
   120 					       const char          *method,
       
   121 					       DBusGProxyCallNotify notify,
       
   122 					       gpointer             data,
       
   123 					       GDestroyNotify       destroy,
       
   124 					       GType                first_arg_type,
       
   125 					       ...);
       
   126 static guint dbus_g_proxy_begin_call_internal (DBusGProxy          *proxy,
       
   127 					       const char          *method,
       
   128 					       DBusGProxyCallNotify notify,
       
   129 					       gpointer             data,
       
   130 					       GDestroyNotify       destroy,
       
   131 					       GValueArray         *args,
       
   132 					       int timeout );
       
   133 static gboolean dbus_g_proxy_end_call_internal (DBusGProxy        *proxy,
       
   134 						guint              call_id,
       
   135 						GError           **error,
       
   136 						GType              first_arg_type,
       
   137 						va_list            args);
       
   138 
       
   139 /**
       
   140  * A list of proxies with a given name+path+interface, used to
       
   141  * route incoming signals.
       
   142  */
       
   143 typedef struct
       
   144 {
       
   145   GSList *proxies; /**< The list of proxies */
       
   146 
       
   147   char name[4]; /**< name (empty string for none), nul byte,
       
   148                  *   path, nul byte,
       
   149                  *   interface, nul byte
       
   150                  */
       
   151   
       
   152 } DBusGProxyList;
       
   153 
       
   154 /**
       
   155  * DBusGProxyManager's primary task is to route signals to the proxies
       
   156  * those signals are emitted on. In order to do this it also has to
       
   157  * track the owners of the names proxies are bound to.
       
   158  */
       
   159 struct _DBusGProxyManager
       
   160 {
       
   161   GStaticMutex lock; /**< Thread lock */
       
   162   int refcount;      /**< Reference count */
       
   163   DBusConnection *connection; /**< Connection we're associated with. */
       
   164 
       
   165   DBusGProxy *bus_proxy; /**< Special internal proxy used to talk to the bus */
       
   166 
       
   167   GHashTable *proxy_lists; /**< Hash used to route incoming signals
       
   168                             *   and iterate over proxies
       
   169                             */
       
   170   GHashTable *owner_names; /**< Hash to keep track of mapping from
       
   171 			    *   base name -> [name,name,...] for proxies which
       
   172 			    *   are for names.
       
   173 			    */
       
   174   GSList *unassociated_proxies;     /**< List of name proxies for which
       
   175 				     *   there was no result for
       
   176 				     *   GetNameOwner
       
   177 				     */
       
   178 };
       
   179 
       
   180 static DBusGProxyManager *dbus_g_proxy_manager_ref    (DBusGProxyManager *manager);
       
   181 static DBusHandlerResult  dbus_g_proxy_manager_filter (DBusConnection    *connection,
       
   182                                                        DBusMessage       *message,
       
   183                                                        void              *user_data);
       
   184 
       
   185 
       
   186 /** Lock the DBusGProxyManager */
       
   187 #define LOCK_MANAGER(mgr)   (g_static_mutex_lock (&(mgr)->lock))
       
   188 /** Unlock the DBusGProxyManager */
       
   189 #define UNLOCK_MANAGER(mgr) (g_static_mutex_unlock (&(mgr)->lock))
       
   190 
       
   191 
       
   192 #if EMULATOR
       
   193 GET_STATIC_VAR_FROM_TLS(g_proxy_manager_slot,dbus_gproxy,int )
       
   194 #define g_proxy_manager_slot (*GET_DBUS_WSD_VAR_NAME(g_proxy_manager_slot,dbus_gproxy,s)())
       
   195 GET_STATIC_VAR_FROM_TLS(connection_g_proxy_lock,dbus_gproxy,GStaticMutex )
       
   196 #define connection_g_proxy_lock (*GET_DBUS_WSD_VAR_NAME(connection_g_proxy_lock,dbus_gproxy,s)())
       
   197 
       
   198 #else
       
   199 static int g_proxy_manager_slot = -1;
       
   200 /* Lock controlling get/set manager as data on each connection */
       
   201 static GStaticMutex connection_g_proxy_lock = G_STATIC_MUTEX_INIT;
       
   202 
       
   203 #endif
       
   204 
       
   205 
       
   206 
       
   207 
       
   208 static DBusGProxyManager*
       
   209 dbus_g_proxy_manager_get (DBusConnection *connection)
       
   210 {
       
   211   DBusGProxyManager *manager;
       
   212 
       
   213   dbus_connection_allocate_data_slot (&g_proxy_manager_slot);
       
   214   if (g_proxy_manager_slot < 0)
       
   215     g_error ("out of memory");
       
   216   
       
   217   g_static_mutex_lock (&connection_g_proxy_lock);
       
   218   
       
   219   manager = dbus_connection_get_data (connection, g_proxy_manager_slot);
       
   220   if (manager != NULL)
       
   221     {
       
   222       dbus_connection_free_data_slot (&g_proxy_manager_slot);
       
   223       dbus_g_proxy_manager_ref (manager);
       
   224       g_static_mutex_unlock (&connection_g_proxy_lock);
       
   225       return manager;
       
   226     }
       
   227   
       
   228   manager = g_new0 (DBusGProxyManager, 1);
       
   229 
       
   230   manager->refcount = 1;
       
   231   manager->connection = connection;
       
   232 
       
   233   g_static_mutex_init (&manager->lock);
       
   234 
       
   235   /* Proxy managers keep the connection alive, which means that
       
   236    * DBusGProxy indirectly does. To free a connection you have to free
       
   237    * all the proxies referring to it.
       
   238    */
       
   239   dbus_connection_ref (manager->connection);
       
   240 
       
   241   dbus_connection_set_data (connection, g_proxy_manager_slot,
       
   242                             manager, NULL);
       
   243 
       
   244   dbus_connection_add_filter (connection, dbus_g_proxy_manager_filter,
       
   245                               manager, NULL);
       
   246   
       
   247   g_static_mutex_unlock (&connection_g_proxy_lock);
       
   248   
       
   249   return manager;
       
   250 }
       
   251 
       
   252 static DBusGProxyManager * 
       
   253 dbus_g_proxy_manager_ref (DBusGProxyManager *manager)
       
   254 {
       
   255   g_assert (manager != NULL);
       
   256   g_assert (manager->refcount > 0);
       
   257 
       
   258   LOCK_MANAGER (manager);
       
   259   
       
   260   manager->refcount += 1;
       
   261 
       
   262   UNLOCK_MANAGER (manager);
       
   263 
       
   264   return manager;
       
   265 }
       
   266 
       
   267 static void
       
   268 dbus_g_proxy_manager_unref (DBusGProxyManager *manager)
       
   269 {
       
   270   g_assert (manager != NULL);
       
   271   g_assert (manager->refcount > 0);
       
   272 
       
   273   LOCK_MANAGER (manager);
       
   274   manager->refcount -= 1;
       
   275   if (manager->refcount == 0)
       
   276     {
       
   277       UNLOCK_MANAGER (manager);
       
   278 
       
   279       if (manager->bus_proxy)
       
   280 	g_object_unref (manager->bus_proxy);
       
   281 
       
   282       if (manager->proxy_lists)
       
   283         {
       
   284           /* can't have any proxies left since they hold
       
   285            * a reference to the proxy manager.
       
   286            */
       
   287           g_assert (g_hash_table_size (manager->proxy_lists) == 0);
       
   288           
       
   289           g_hash_table_destroy (manager->proxy_lists);
       
   290           manager->proxy_lists = NULL;
       
   291 
       
   292         }
       
   293 
       
   294       if (manager->owner_names)
       
   295 	{
       
   296 	  /* Since we destroyed all proxies, none can be tracking
       
   297 	   * name owners
       
   298 	   */
       
   299           g_assert (g_hash_table_size (manager->owner_names) == 0);
       
   300 
       
   301 	  g_hash_table_destroy (manager->owner_names);
       
   302 	  manager->owner_names = NULL;
       
   303 	}
       
   304 
       
   305       g_assert (manager->unassociated_proxies == NULL);
       
   306       
       
   307       g_static_mutex_free (&manager->lock);
       
   308 
       
   309       g_static_mutex_lock (&connection_g_proxy_lock);
       
   310 
       
   311       dbus_connection_remove_filter (manager->connection, dbus_g_proxy_manager_filter,
       
   312                                      manager);
       
   313       
       
   314       dbus_connection_set_data (manager->connection,
       
   315                                 g_proxy_manager_slot,
       
   316                                 NULL, NULL);
       
   317 
       
   318       g_static_mutex_unlock (&connection_g_proxy_lock);
       
   319       
       
   320       dbus_connection_unref (manager->connection);
       
   321       g_free (manager);
       
   322 
       
   323       dbus_connection_free_data_slot (&g_proxy_manager_slot);
       
   324     }
       
   325   else
       
   326     {
       
   327       UNLOCK_MANAGER (manager);
       
   328     }
       
   329 }
       
   330 
       
   331 static guint
       
   332 tristring_hash (gconstpointer key)
       
   333 {
       
   334   const char *p = key;
       
   335   guint h = *p;
       
   336 
       
   337   if (h)
       
   338     {
       
   339       for (p += 1; *p != '\0'; p++)
       
   340         h = (h << 5) - h + *p;
       
   341     }
       
   342 
       
   343   /* skip nul and do the next substring */
       
   344   for (p += 1; *p != '\0'; p++)
       
   345     h = (h << 5) - h + *p;
       
   346 
       
   347   /* skip nul again and another substring */
       
   348   for (p += 1; *p != '\0'; p++)
       
   349     h = (h << 5) - h + *p;
       
   350   
       
   351   return h;
       
   352 }
       
   353 
       
   354 static gboolean
       
   355 strequal_len (const char *a,
       
   356               const char *b,
       
   357               size_t     *lenp)
       
   358 {
       
   359   size_t a_len;
       
   360   size_t b_len;
       
   361 
       
   362   a_len = strlen (a);
       
   363   b_len = strlen (b);
       
   364 
       
   365   if (a_len != b_len)
       
   366     return FALSE;
       
   367 
       
   368   if (memcmp (a, b, a_len) != 0)
       
   369     return FALSE;
       
   370   
       
   371   *lenp = a_len;
       
   372 
       
   373   return TRUE;
       
   374 }
       
   375 
       
   376 static gboolean
       
   377 tristring_equal (gconstpointer  a,
       
   378                  gconstpointer  b)
       
   379 {
       
   380   const char *ap = a;
       
   381   const char *bp = b;
       
   382   size_t len;
       
   383 
       
   384   if (!strequal_len (ap, bp, &len))
       
   385     return FALSE;
       
   386 
       
   387   ap += len + 1;
       
   388   bp += len + 1;
       
   389 
       
   390   if (!strequal_len (ap, bp, &len))
       
   391     return FALSE;
       
   392 
       
   393   ap += len + 1;
       
   394   bp += len + 1;
       
   395 
       
   396   if (strcmp (ap, bp) != 0)
       
   397     return FALSE;
       
   398   
       
   399   return TRUE;
       
   400 }
       
   401 
       
   402 static char*
       
   403 tristring_alloc_from_strings (size_t      padding_before,
       
   404                               const char *name,
       
   405                               const char *path,
       
   406                               const char *interface)
       
   407 {
       
   408   size_t name_len, iface_len, path_len, len;
       
   409   char *tri;
       
   410   
       
   411   if (name)
       
   412     name_len = strlen (name);
       
   413   else
       
   414     name_len = 0;
       
   415 
       
   416   path_len = strlen (path);
       
   417   
       
   418   iface_len = strlen (interface);
       
   419 
       
   420   tri = g_malloc (padding_before + name_len + path_len + iface_len + 3);
       
   421 
       
   422   len = padding_before;
       
   423   
       
   424   if (name)
       
   425     memcpy (&tri[len], name, name_len);
       
   426 
       
   427   len += name_len;
       
   428   tri[len] = '\0';
       
   429   len += 1;
       
   430 
       
   431   g_assert (len == (padding_before + name_len + 1));
       
   432   
       
   433   memcpy (&tri[len], path, path_len);
       
   434   len += path_len;
       
   435   tri[len] = '\0';
       
   436   len += 1;
       
   437 
       
   438   g_assert (len == (padding_before + name_len + path_len + 2));
       
   439   
       
   440   memcpy (&tri[len], interface, iface_len);
       
   441   len += iface_len;
       
   442   tri[len] = '\0';
       
   443   len += 1;
       
   444 
       
   445   g_assert (len == (padding_before + name_len + path_len + iface_len + 3));
       
   446 
       
   447   return tri;
       
   448 }
       
   449 
       
   450 static char*
       
   451 tristring_from_proxy (DBusGProxy *proxy)
       
   452 {
       
   453   DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
   454 
       
   455   return tristring_alloc_from_strings (0,
       
   456                                        priv->name,
       
   457                                        priv->path,
       
   458                                        priv->interface);
       
   459 }
       
   460 
       
   461 static char*
       
   462 tristring_from_message (DBusMessage *message)
       
   463 {
       
   464   const char *path;
       
   465   const char *interface;
       
   466 
       
   467   path = dbus_message_get_path (message);
       
   468   interface = dbus_message_get_interface (message);
       
   469 
       
   470   g_assert (path);
       
   471   g_assert (interface);
       
   472   
       
   473   return tristring_alloc_from_strings (0,
       
   474                                        dbus_message_get_sender (message),
       
   475                                        path, interface);
       
   476 }
       
   477 
       
   478 static DBusGProxyList*
       
   479 g_proxy_list_new (DBusGProxy *first_proxy)
       
   480 {
       
   481   DBusGProxyList *list;
       
   482   DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(first_proxy);
       
   483   
       
   484   list = (void*) tristring_alloc_from_strings (G_STRUCT_OFFSET (DBusGProxyList, name),
       
   485                                                priv->name,
       
   486                                                priv->path,
       
   487                                                priv->interface);
       
   488   list->proxies = NULL;
       
   489 
       
   490   return list;
       
   491 }
       
   492 
       
   493 static void
       
   494 g_proxy_list_free (DBusGProxyList *list)
       
   495 {
       
   496   /* we don't hold a reference to the proxies in the list,
       
   497    * as they ref the GProxyManager
       
   498    */
       
   499   g_slist_free (list->proxies);  
       
   500 
       
   501   g_free (list);
       
   502 }
       
   503 
       
   504 static char*
       
   505 g_proxy_get_match_rule (DBusGProxy *proxy)
       
   506 {
       
   507   DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
   508   /* FIXME Escaping is required here */
       
   509   
       
   510   if (priv->name)
       
   511     return g_strdup_printf ("type='signal',sender='%s',path='%s',interface='%s'",
       
   512                             priv->name, priv->path, priv->interface);
       
   513   else
       
   514     return g_strdup_printf ("type='signal',path='%s',interface='%s'",
       
   515                             priv->path, priv->interface);
       
   516 }
       
   517 
       
   518 typedef struct
       
   519 {
       
   520   char *name;
       
   521   guint refcount;
       
   522 } DBusGProxyNameOwnerInfo;
       
   523 
       
   524 static gint
       
   525 find_name_in_info (gconstpointer a, gconstpointer b)
       
   526 {
       
   527   const DBusGProxyNameOwnerInfo *info = a;
       
   528   const char *name = b;
       
   529 
       
   530   return strcmp (info->name, name);
       
   531 }
       
   532 
       
   533 typedef struct
       
   534 {
       
   535   const char *name;
       
   536   const char *owner;
       
   537   DBusGProxyNameOwnerInfo *info;
       
   538 } DBusGProxyNameOwnerForeachData;
       
   539 
       
   540 static void
       
   541 name_owner_foreach (gpointer key, gpointer val, gpointer data)
       
   542 {
       
   543   const char *owner;
       
   544   DBusGProxyNameOwnerForeachData *foreach_data;
       
   545   GSList *names;
       
   546   GSList *link;
       
   547 
       
   548   owner = key;
       
   549   names = val;
       
   550   foreach_data = data;
       
   551 
       
   552   if (foreach_data->owner != NULL)
       
   553     return;
       
   554 
       
   555   g_assert (foreach_data->info == NULL);
       
   556 
       
   557   link = g_slist_find_custom (names, foreach_data->name, find_name_in_info);
       
   558   if (link)
       
   559     {
       
   560       foreach_data->owner = owner;
       
   561       foreach_data->info = link->data;
       
   562     }
       
   563 }
       
   564 
       
   565 static gboolean
       
   566 dbus_g_proxy_manager_lookup_name_owner (DBusGProxyManager        *manager,
       
   567 					const char               *name,
       
   568 					DBusGProxyNameOwnerInfo **info,
       
   569 					const char              **owner)
       
   570 {
       
   571   DBusGProxyNameOwnerForeachData foreach_data;
       
   572 
       
   573   foreach_data.name = name;
       
   574   foreach_data.owner = NULL;
       
   575   foreach_data.info = NULL;
       
   576   
       
   577   g_hash_table_foreach (manager->owner_names, name_owner_foreach, &foreach_data);
       
   578 
       
   579   *info = foreach_data.info;
       
   580   *owner = foreach_data.owner;
       
   581   return *info != NULL;
       
   582 }
       
   583 
       
   584 static void
       
   585 insert_nameinfo (DBusGProxyManager       *manager,
       
   586 		 const char              *owner,
       
   587 		 DBusGProxyNameOwnerInfo *info)
       
   588 {
       
   589   GSList *names;
       
   590   gboolean insert;
       
   591 
       
   592   names = g_hash_table_lookup (manager->owner_names, owner);
       
   593 
       
   594   /* Only need to g_hash_table_insert the first time */
       
   595   insert = (names == NULL);
       
   596 
       
   597   names = g_slist_append (names, info); 
       
   598 
       
   599   if (insert)
       
   600     g_hash_table_insert (manager->owner_names, g_strdup (owner), names);
       
   601 }
       
   602 
       
   603 static void
       
   604 dbus_g_proxy_manager_monitor_name_owner (DBusGProxyManager  *manager,
       
   605 					 const char         *owner,
       
   606 					 const char         *name)
       
   607 {
       
   608   GSList *names;
       
   609   GSList *link;
       
   610   DBusGProxyNameOwnerInfo *nameinfo;
       
   611 
       
   612   names = g_hash_table_lookup (manager->owner_names, owner);
       
   613   link = g_slist_find_custom (names, name, find_name_in_info);
       
   614   
       
   615   if (!link)
       
   616     {
       
   617       nameinfo = g_new0 (DBusGProxyNameOwnerInfo, 1);
       
   618       nameinfo->name = g_strdup (name);
       
   619       nameinfo->refcount = 1;
       
   620 
       
   621       insert_nameinfo (manager, owner, nameinfo);
       
   622     }
       
   623   else
       
   624     {
       
   625       nameinfo = link->data;
       
   626       nameinfo->refcount++;
       
   627     }
       
   628 }
       
   629 
       
   630 static void
       
   631 dbus_g_proxy_manager_unmonitor_name_owner (DBusGProxyManager  *manager,
       
   632 					   const char         *name)
       
   633 {
       
   634   DBusGProxyNameOwnerInfo *info;
       
   635   const char *owner;
       
   636   gboolean ret;
       
   637 
       
   638   ret = dbus_g_proxy_manager_lookup_name_owner (manager, name, &info, &owner);
       
   639   g_assert (ret);
       
   640   g_assert (info != NULL);
       
   641   g_assert (owner != NULL);
       
   642 
       
   643   info->refcount--;
       
   644   if (info->refcount == 0)
       
   645     {
       
   646       GSList *names;
       
   647       GSList *link;
       
   648 
       
   649       names = g_hash_table_lookup (manager->owner_names, owner);
       
   650       link = g_slist_find_custom (names, name, find_name_in_info);
       
   651       names = g_slist_delete_link (names, link);
       
   652       if (names != NULL)
       
   653 	g_hash_table_insert (manager->owner_names, g_strdup (owner), names);
       
   654       else
       
   655 	g_hash_table_remove (manager->owner_names, owner);
       
   656 
       
   657       g_free (info->name);
       
   658       g_free (info);
       
   659     }
       
   660 }
       
   661 
       
   662 typedef struct
       
   663 {
       
   664   const char *name;
       
   665   GSList *destroyed;
       
   666 } DBusGProxyUnassociateData;
       
   667 
       
   668 static void
       
   669 unassociate_proxies (gpointer key, gpointer val, gpointer user_data)
       
   670 {
       
   671   DBusGProxyList *list;
       
   672   const char *name;
       
   673   GSList *tmp;
       
   674   DBusGProxyUnassociateData *data;
       
   675 
       
   676   list = val;
       
   677   data = user_data;
       
   678   name = data->name;
       
   679   
       
   680   for (tmp = list->proxies; tmp; tmp = tmp->next)
       
   681     {
       
   682       DBusGProxy *proxy = DBUS_G_PROXY (tmp->data);
       
   683       DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
   684       DBusGProxyManager *manager;
       
   685 
       
   686       manager = priv->manager;
       
   687 
       
   688       if (!strcmp (priv->name, name))
       
   689 	{
       
   690 	  if (!priv->for_owner)
       
   691 	    {
       
   692 	      g_assert (priv->associated);
       
   693 	      g_assert (priv->name_call == NULL);
       
   694 
       
   695 	      priv->associated = FALSE;
       
   696 	      manager->unassociated_proxies = g_slist_prepend (manager->unassociated_proxies, proxy);
       
   697 	    }
       
   698 	  else
       
   699 	    {
       
   700 	      data->destroyed = g_slist_prepend (data->destroyed, proxy);
       
   701               /* make contents of list into weak pointers in case the objects
       
   702                * unref each other when disposing */
       
   703               g_object_add_weak_pointer (G_OBJECT (proxy),
       
   704                   &(data->destroyed->data));
       
   705 	    }
       
   706 	}
       
   707     }
       
   708 }
       
   709 
       
   710 static void
       
   711 dbus_g_proxy_manager_replace_name_owner (DBusGProxyManager  *manager,
       
   712 					 const char         *name,
       
   713 					 const char         *prev_owner,
       
   714 					 const char         *new_owner)
       
   715 {
       
   716   GSList *names;
       
   717 	  
       
   718   if (prev_owner[0] == '\0')
       
   719     {
       
   720       GSList *tmp;
       
   721       GSList *removed;
       
   722 
       
   723       /* We have a new service, look at unassociated proxies */
       
   724 
       
   725       removed = NULL;
       
   726 
       
   727       for (tmp = manager->unassociated_proxies; tmp ; tmp = tmp->next)
       
   728 	{
       
   729 	  DBusGProxy *proxy = tmp->data;
       
   730 	  DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
   731 
       
   732 	  if (!strcmp (priv->name, name))
       
   733 	    {
       
   734 	      removed = g_slist_prepend (removed, tmp);
       
   735 	      
       
   736 	      dbus_g_proxy_manager_monitor_name_owner (manager, new_owner, name);
       
   737 	      priv->associated = TRUE;
       
   738 	    }
       
   739 	}
       
   740 
       
   741       for (tmp = removed; tmp; tmp = tmp->next)
       
   742 	manager->unassociated_proxies = g_slist_delete_link (manager->unassociated_proxies, tmp->data);
       
   743       g_slist_free (removed);
       
   744     }
       
   745   else
       
   746     {
       
   747       DBusGProxyNameOwnerInfo *info;
       
   748       GSList *link;
       
   749 
       
   750       /* Name owner changed or deleted */ 
       
   751 
       
   752       names = g_hash_table_lookup (manager->owner_names, prev_owner);
       
   753 
       
   754       info = NULL;
       
   755       if (names != NULL)
       
   756         {
       
   757 	  link = g_slist_find_custom (names, name, find_name_in_info);
       
   758 
       
   759 	  if (link != NULL)
       
   760 	    {
       
   761 	      info = link->data;
       
   762 	  
       
   763 	      names = g_slist_delete_link (names, link);
       
   764 
       
   765 	      if (names == NULL)
       
   766 	        g_hash_table_remove (manager->owner_names, prev_owner);
       
   767 	    }
       
   768         }
       
   769 
       
   770       if (new_owner[0] == '\0')
       
   771 	{
       
   772 	  DBusGProxyUnassociateData data;
       
   773 	  GSList *tmp;
       
   774 
       
   775 	  data.name = name;
       
   776 	  data.destroyed = NULL;
       
   777 
       
   778 	  /* A service went away, we need to unassociate proxies */
       
   779 	  g_hash_table_foreach (manager->proxy_lists,
       
   780 				unassociate_proxies, &data);
       
   781 
       
   782 	  UNLOCK_MANAGER (manager);
       
   783 
       
   784           /* the destroyed list's data pointers are weak pointers, so that we
       
   785            * don't end up calling destroy on proxies which have already been
       
   786            * freed up as a result of other ones being destroyed */
       
   787 	  for (tmp = data.destroyed; tmp; tmp = tmp->next)
       
   788             if (tmp->data != NULL)
       
   789               {
       
   790                 g_object_remove_weak_pointer (G_OBJECT (tmp->data),
       
   791                     &(tmp->data));
       
   792                 dbus_g_proxy_destroy (tmp->data);
       
   793               }
       
   794 	  g_slist_free (data.destroyed);
       
   795 
       
   796 	  LOCK_MANAGER (manager);
       
   797 
       
   798 	  if (info)
       
   799 	    {
       
   800 	      g_free (info->name);
       
   801 	      g_free (info);
       
   802 	    }
       
   803 	}
       
   804       else if (info)
       
   805 	{
       
   806 	  insert_nameinfo (manager, new_owner, info);
       
   807 	}
       
   808     }
       
   809 }
       
   810 
       
   811 static void
       
   812 got_name_owner_cb (DBusGProxy       *bus_proxy,
       
   813 		   DBusGProxyCall   *call,
       
   814 		   void             *user_data)
       
   815 {
       
   816   DBusGProxy *proxy = user_data;
       
   817   DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
   818   GError *error;
       
   819   char *owner;
       
   820 
       
   821   error = NULL;
       
   822   owner = NULL;
       
   823 
       
   824   LOCK_MANAGER (priv->manager);
       
   825 
       
   826   if (!dbus_g_proxy_end_call (bus_proxy, call, &error,
       
   827 			      G_TYPE_STRING, &owner,
       
   828 			      G_TYPE_INVALID))
       
   829     {
       
   830       if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_NAME_HAS_NO_OWNER)
       
   831 	{
       
   832 	  priv->manager->unassociated_proxies = g_slist_prepend (priv->manager->unassociated_proxies, proxy);
       
   833 	}
       
   834       else if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION)
       
   835 	g_warning ("Couldn't get name owner (%s): %s",
       
   836 		   dbus_g_error_get_name (error),
       
   837 		   error->message);
       
   838       else
       
   839 	g_warning ("Couldn't get name owner (code %d): %s",
       
   840                    error->code, error->message);
       
   841       g_clear_error (&error);
       
   842       goto out;
       
   843     }
       
   844   else
       
   845     {
       
   846       dbus_g_proxy_manager_monitor_name_owner (priv->manager, owner, priv->name);
       
   847       priv->associated = TRUE;
       
   848     }
       
   849 
       
   850  out:
       
   851   priv->name_call = NULL;
       
   852   UNLOCK_MANAGER (priv->manager);
       
   853   g_free (owner);
       
   854 }
       
   855 
       
   856 static char *
       
   857 get_name_owner (DBusConnection     *connection,
       
   858 		const char         *name,
       
   859 		GError            **error)
       
   860 {
       
   861   DBusError derror;
       
   862   DBusMessage *request, *reply;
       
   863   char *base_name;
       
   864   
       
   865   dbus_error_init (&derror);
       
   866 
       
   867   base_name = NULL;
       
   868   reply = NULL;
       
   869 
       
   870   request = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
       
   871 					  DBUS_PATH_DBUS,
       
   872 					  DBUS_INTERFACE_DBUS,
       
   873 					  "GetNameOwner");
       
   874   if (request == NULL)
       
   875     g_error ("Out of memory");
       
   876   
       
   877   if (!dbus_message_append_args (request, 
       
   878 				 DBUS_TYPE_STRING, &name, 
       
   879 				 DBUS_TYPE_INVALID))
       
   880     g_error ("Out of memory");
       
   881 
       
   882   reply =
       
   883     dbus_connection_send_with_reply_and_block (connection,
       
   884                                                request,
       
   885                                                2000, &derror);
       
   886   if (reply == NULL)
       
   887     goto error;
       
   888 
       
   889   if (dbus_set_error_from_message (&derror, reply))
       
   890     goto error;
       
   891 
       
   892   if (!dbus_message_get_args (reply, &derror, 
       
   893 			      DBUS_TYPE_STRING, &base_name, 
       
   894 			      DBUS_TYPE_INVALID))
       
   895     goto error;
       
   896 
       
   897   base_name = g_strdup (base_name);
       
   898   goto out;
       
   899 
       
   900  error:
       
   901   g_assert (dbus_error_is_set (&derror));
       
   902   dbus_set_g_error (error, &derror);
       
   903   dbus_error_free (&derror);
       
   904 
       
   905  out:
       
   906   if (request)
       
   907     dbus_message_unref (request);
       
   908   if (reply)
       
   909     dbus_message_unref (reply);
       
   910 
       
   911   return base_name;
       
   912 }
       
   913 
       
   914 
       
   915 static void
       
   916 dbus_g_proxy_manager_register (DBusGProxyManager *manager,
       
   917                                DBusGProxy        *proxy)
       
   918 {
       
   919   DBusGProxyList *list;
       
   920   DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
   921 
       
   922   LOCK_MANAGER (manager);
       
   923 
       
   924   if (manager->proxy_lists == NULL)
       
   925     {
       
   926       g_assert (manager->owner_names == NULL);
       
   927 
       
   928       list = NULL;
       
   929       manager->proxy_lists = g_hash_table_new_full (tristring_hash,
       
   930                                                     tristring_equal,
       
   931                                                     NULL,
       
   932                                                     (GFreeFunc) g_proxy_list_free);
       
   933       manager->owner_names = g_hash_table_new_full (g_str_hash,
       
   934                                                     g_str_equal,
       
   935                                                     g_free,
       
   936                                                     NULL);
       
   937       /* FIXME - for now we listen for all NameOwnerChanged; once
       
   938        * Anders' detail patch lands we should add individual rules
       
   939        */
       
   940       dbus_bus_add_match (manager->connection,
       
   941                           "type='signal',sender='" DBUS_SERVICE_DBUS
       
   942 			  "',path='" DBUS_PATH_DBUS
       
   943 			  "',interface='" DBUS_INTERFACE_DBUS
       
   944 			  "',member='NameOwnerChanged'",
       
   945 			  NULL);
       
   946     }
       
   947   else
       
   948     {
       
   949       char *tri;
       
   950 
       
   951       tri = tristring_from_proxy (proxy);
       
   952       
       
   953       list = g_hash_table_lookup (manager->proxy_lists, tri);
       
   954 
       
   955       g_free (tri);
       
   956     }
       
   957       
       
   958   if (list == NULL)
       
   959     {
       
   960       list = g_proxy_list_new (proxy);
       
   961       
       
   962       g_hash_table_replace (manager->proxy_lists,
       
   963                             list->name, list);
       
   964     }
       
   965 
       
   966   if (list->proxies == NULL && priv->name)
       
   967     {
       
   968       /* We have to add the match rule to the server,
       
   969        * but only if the server is a message bus,
       
   970        * not if it's a peer.
       
   971        */
       
   972        char *rule;
       
   973        
       
   974        rule = g_proxy_get_match_rule (proxy);
       
   975        
       
   976        /* We don't check for errors; it's not like anyone would handle them, and
       
   977         * we don't want a round trip here.
       
   978         */
       
   979        dbus_bus_add_match (manager->connection,
       
   980 			   rule, NULL);
       
   981        
       
   982        g_free (rule);
       
   983     }
       
   984 
       
   985   g_assert (g_slist_find (list->proxies, proxy) == NULL);
       
   986   
       
   987   list->proxies = g_slist_prepend (list->proxies, proxy);
       
   988 
       
   989   if (!priv->for_owner)
       
   990     {
       
   991       const char *owner;
       
   992       DBusGProxyNameOwnerInfo *info;
       
   993 
       
   994       if (!dbus_g_proxy_manager_lookup_name_owner (manager, priv->name, &info, &owner))
       
   995 	{
       
   996 	  priv->name_call = manager_begin_bus_call (manager, "GetNameOwner",
       
   997 						     got_name_owner_cb,
       
   998 						     proxy, NULL,
       
   999 						     G_TYPE_STRING,
       
  1000 						     priv->name, 
       
  1001 						     G_TYPE_INVALID);
       
  1002 	  
       
  1003 	  priv->associated = FALSE;
       
  1004 	}
       
  1005       else
       
  1006 	{
       
  1007 	  info->refcount++;
       
  1008 	  priv->associated = TRUE;
       
  1009 	}
       
  1010     }
       
  1011   
       
  1012   UNLOCK_MANAGER (manager);
       
  1013 }
       
  1014 
       
  1015 static void
       
  1016 dbus_g_proxy_manager_unregister (DBusGProxyManager *manager,
       
  1017                                 DBusGProxy        *proxy)
       
  1018 {
       
  1019   DBusGProxyList *list;
       
  1020   DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  1021   char *tri;
       
  1022   
       
  1023   LOCK_MANAGER (manager);
       
  1024 
       
  1025 #ifndef G_DISABLE_CHECKS
       
  1026   if (manager->proxy_lists == NULL)
       
  1027     {
       
  1028       g_warning ("Trying to unregister a proxy but there aren't any registered");
       
  1029       return;
       
  1030     }
       
  1031 #endif
       
  1032 
       
  1033   tri = tristring_from_proxy (proxy);
       
  1034   
       
  1035   list = g_hash_table_lookup (manager->proxy_lists, tri);
       
  1036 
       
  1037 #ifndef G_DISABLE_CHECKS
       
  1038   if (list == NULL)
       
  1039     {
       
  1040       g_warning ("Trying to unregister a proxy but it isn't registered");
       
  1041       return;
       
  1042     }
       
  1043 #endif
       
  1044 
       
  1045   g_assert (g_slist_find (list->proxies, proxy) != NULL);
       
  1046   
       
  1047   list->proxies = g_slist_remove (list->proxies, proxy);
       
  1048 
       
  1049   g_assert (g_slist_find (list->proxies, proxy) == NULL);
       
  1050 
       
  1051   if (!priv->for_owner)
       
  1052     {
       
  1053       if (!priv->associated)
       
  1054 	{
       
  1055 	  GSList *link;
       
  1056 
       
  1057 	  if (priv->name_call != 0)
       
  1058 	    {
       
  1059 	      dbus_g_proxy_cancel_call (manager->bus_proxy, priv->name_call);
       
  1060 	      priv->name_call = 0;
       
  1061 	    }
       
  1062 	  else
       
  1063 	    {
       
  1064 	      link = g_slist_find (manager->unassociated_proxies, proxy);
       
  1065 	      g_assert (link != NULL);
       
  1066 
       
  1067 	      manager->unassociated_proxies = g_slist_delete_link (manager->unassociated_proxies, link);
       
  1068 	    }
       
  1069 	}
       
  1070       else
       
  1071 	{
       
  1072 	  g_assert (priv->name_call == 0);
       
  1073 	  
       
  1074 	  dbus_g_proxy_manager_unmonitor_name_owner (manager, priv->name);
       
  1075 	}
       
  1076     }
       
  1077 
       
  1078   if (list->proxies == NULL)
       
  1079     {
       
  1080       char *rule;
       
  1081       g_hash_table_remove (manager->proxy_lists,
       
  1082                            tri);
       
  1083       list = NULL;
       
  1084 
       
  1085       rule = g_proxy_get_match_rule (proxy);
       
  1086       dbus_bus_remove_match (manager->connection,
       
  1087                              rule, NULL);
       
  1088       g_free (rule);
       
  1089     }
       
  1090   
       
  1091   if (g_hash_table_size (manager->proxy_lists) == 0)
       
  1092     {
       
  1093       g_hash_table_destroy (manager->proxy_lists);
       
  1094       manager->proxy_lists = NULL;
       
  1095     }
       
  1096 
       
  1097   g_free (tri);
       
  1098       
       
  1099   UNLOCK_MANAGER (manager);
       
  1100 }
       
  1101 
       
  1102 static void
       
  1103 list_proxies_foreach (gpointer key,
       
  1104                       gpointer value,
       
  1105                       gpointer user_data)
       
  1106 {
       
  1107   DBusGProxyList *list;
       
  1108   GSList **ret;
       
  1109   GSList *tmp;
       
  1110   
       
  1111   list = value;
       
  1112   ret = user_data;
       
  1113 
       
  1114   tmp = list->proxies;
       
  1115   while (tmp != NULL)
       
  1116     {
       
  1117       DBusGProxy *proxy = DBUS_G_PROXY (tmp->data);
       
  1118 
       
  1119       g_object_ref (proxy);
       
  1120       *ret = g_slist_prepend (*ret, proxy);
       
  1121       
       
  1122       tmp = tmp->next;
       
  1123     }
       
  1124 }
       
  1125 
       
  1126 static GSList*
       
  1127 dbus_g_proxy_manager_list_all (DBusGProxyManager *manager)
       
  1128 {
       
  1129   GSList *ret;
       
  1130 
       
  1131   ret = NULL;
       
  1132 
       
  1133   if (manager->proxy_lists)
       
  1134     {
       
  1135       g_hash_table_foreach (manager->proxy_lists,
       
  1136                             list_proxies_foreach,
       
  1137                             &ret);
       
  1138     }
       
  1139 
       
  1140   return ret;
       
  1141 }
       
  1142 
       
  1143 static DBusHandlerResult
       
  1144 dbus_g_proxy_manager_filter (DBusConnection    *connection,
       
  1145                              DBusMessage       *message,
       
  1146                              void              *user_data)
       
  1147 {
       
  1148   DBusGProxyManager *manager;
       
  1149   
       
  1150   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
       
  1151     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
       
  1152 
       
  1153   manager = user_data;
       
  1154 
       
  1155   dbus_g_proxy_manager_ref (manager);
       
  1156   
       
  1157   LOCK_MANAGER (manager);
       
  1158   
       
  1159   if (dbus_message_is_signal (message,
       
  1160                               DBUS_INTERFACE_LOCAL,
       
  1161                               "Disconnected"))
       
  1162     {
       
  1163       /* Destroy all the proxies, quite possibly resulting in unreferencing
       
  1164        * the proxy manager and the connection as well.
       
  1165        */
       
  1166       GSList *all;
       
  1167       GSList *tmp;
       
  1168 
       
  1169       all = dbus_g_proxy_manager_list_all (manager);
       
  1170 
       
  1171       tmp = all;
       
  1172       while (tmp != NULL)
       
  1173         {
       
  1174           DBusGProxy *proxy;
       
  1175 
       
  1176           proxy = DBUS_G_PROXY (tmp->data);
       
  1177 
       
  1178           UNLOCK_MANAGER (manager);
       
  1179           dbus_g_proxy_destroy (proxy);
       
  1180           g_object_unref (G_OBJECT (proxy));
       
  1181           LOCK_MANAGER (manager);
       
  1182           
       
  1183           tmp = tmp->next;
       
  1184         }
       
  1185 
       
  1186       g_slist_free (all);
       
  1187 
       
  1188 #ifndef G_DISABLE_CHECKS
       
  1189       if (manager->proxy_lists != NULL)
       
  1190         g_warning ("Disconnection emitted \"destroy\" on all DBusGProxy, but somehow new proxies were created in response to one of those destroy signals. This will cause a memory leak.");
       
  1191 #endif
       
  1192     }
       
  1193   else
       
  1194     {
       
  1195       char *tri;
       
  1196       GSList *full_list;
       
  1197       GSList *owned_names;
       
  1198       GSList *tmp;
       
  1199       const char *sender;
       
  1200 
       
  1201       /* First we handle NameOwnerChanged internally */
       
  1202       if (dbus_message_is_signal (message,
       
  1203 				  DBUS_INTERFACE_DBUS,
       
  1204 				  "NameOwnerChanged"))
       
  1205 	{
       
  1206 	  const char *name;
       
  1207 	  const char *prev_owner;
       
  1208 	  const char *new_owner;
       
  1209 	  DBusError derr;
       
  1210 
       
  1211 	  dbus_error_init (&derr);
       
  1212 	  if (!dbus_message_get_args (message,
       
  1213 				      &derr,
       
  1214 				      DBUS_TYPE_STRING,
       
  1215 				      &name,
       
  1216 				      DBUS_TYPE_STRING,
       
  1217 				      &prev_owner,
       
  1218 				      DBUS_TYPE_STRING,
       
  1219 				      &new_owner,
       
  1220 				      DBUS_TYPE_INVALID))
       
  1221 	    {
       
  1222 	      /* Ignore this error */
       
  1223 	      dbus_error_free (&derr);
       
  1224 	    }
       
  1225 	  else if (manager->owner_names != NULL)
       
  1226 	    {
       
  1227 	      dbus_g_proxy_manager_replace_name_owner (manager, name, prev_owner, new_owner);
       
  1228 	    }
       
  1229 	}
       
  1230 
       
  1231       sender = dbus_message_get_sender (message);
       
  1232 
       
  1233       /* dbus spec requires these, libdbus validates */
       
  1234       g_assert (dbus_message_get_path (message) != NULL);
       
  1235       g_assert (dbus_message_get_interface (message) != NULL);
       
  1236       g_assert (dbus_message_get_member (message) != NULL);
       
  1237       
       
  1238       tri = tristring_from_message (message);
       
  1239 
       
  1240       if (manager->proxy_lists)
       
  1241 	{
       
  1242 	  DBusGProxyList *owner_list;
       
  1243 	  owner_list = g_hash_table_lookup (manager->proxy_lists, tri);
       
  1244 	  if (owner_list)
       
  1245 	    full_list = g_slist_copy (owner_list->proxies);
       
  1246 	  else
       
  1247 	    full_list = NULL;
       
  1248 	}
       
  1249       else
       
  1250 	full_list = NULL;
       
  1251 
       
  1252       g_free (tri);
       
  1253 
       
  1254       if (manager->owner_names && sender)
       
  1255 	{
       
  1256 	  owned_names = g_hash_table_lookup (manager->owner_names, sender);
       
  1257 	  for (tmp = owned_names; tmp; tmp = tmp->next)
       
  1258 	    {
       
  1259 	      DBusGProxyList *owner_list;
       
  1260 	      DBusGProxyNameOwnerInfo *nameinfo;
       
  1261 
       
  1262 	      nameinfo = tmp->data;
       
  1263 	      g_assert (nameinfo->refcount > 0);
       
  1264 	      tri = tristring_alloc_from_strings (0, nameinfo->name,
       
  1265 						  dbus_message_get_path (message),
       
  1266 						  dbus_message_get_interface (message));
       
  1267 
       
  1268 	      owner_list = g_hash_table_lookup (manager->proxy_lists, tri);
       
  1269 	      if (owner_list != NULL)
       
  1270 		full_list = g_slist_concat (full_list, g_slist_copy (owner_list->proxies));
       
  1271 	      g_free (tri);
       
  1272 	    }
       
  1273 	}
       
  1274 
       
  1275 #if 0
       
  1276       g_print ("proxy got %s,%s,%s = list %p\n",
       
  1277                tri,
       
  1278                tri + strlen (tri) + 1,
       
  1279                tri + strlen (tri) + 1 + strlen (tri + strlen (tri) + 1) + 1,
       
  1280                list);
       
  1281 #endif
       
  1282       
       
  1283       /* Emit the signal */
       
  1284       
       
  1285       g_slist_foreach (full_list, (GFunc) g_object_ref, NULL);
       
  1286       
       
  1287       for (tmp = full_list; tmp; tmp = tmp->next)
       
  1288 	{
       
  1289 	  DBusGProxy *proxy;
       
  1290 	  
       
  1291 	  proxy = DBUS_G_PROXY (tmp->data);
       
  1292 	  
       
  1293 	  UNLOCK_MANAGER (manager);
       
  1294 	  dbus_g_proxy_emit_remote_signal (proxy, message);
       
  1295 	  g_object_unref (G_OBJECT (proxy));
       
  1296 	  LOCK_MANAGER (manager);
       
  1297 	}
       
  1298       g_slist_free (full_list);
       
  1299     }
       
  1300 
       
  1301   UNLOCK_MANAGER (manager);
       
  1302   dbus_g_proxy_manager_unref (manager);
       
  1303   
       
  1304   /* "Handling" signals doesn't make sense, they are for everyone
       
  1305    * who cares
       
  1306    */
       
  1307   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
       
  1308 }
       
  1309 
       
  1310 
       
  1311 
       
  1312 /*      ---------- DBusGProxy --------------   */
       
  1313 #define DBUS_G_PROXY_DESTROYED(proxy)  (DBUS_G_PROXY_GET_PRIVATE(proxy)->manager == NULL)
       
  1314 
       
  1315 static void
       
  1316 marshal_dbus_message_to_g_marshaller (GClosure     *closure,
       
  1317                                       GValue       *return_value,
       
  1318                                       guint         n_param_values,
       
  1319                                       const GValue *param_values,
       
  1320                                       gpointer      invocation_hint,
       
  1321                                       gpointer      marshal_data);
       
  1322 enum
       
  1323 {
       
  1324   PROP_0,
       
  1325   PROP_NAME,
       
  1326   PROP_PATH,
       
  1327   PROP_INTERFACE,
       
  1328   PROP_CONNECTION
       
  1329 };
       
  1330 
       
  1331 enum
       
  1332 {
       
  1333   DESTROY,
       
  1334   RECEIVED,
       
  1335   LAST_SIGNAL
       
  1336 };
       
  1337 
       
  1338 #if EMULATOR
       
  1339 GET_STATIC_VAR_FROM_TLS(parent_class,dbus_gproxy,void* )
       
  1340 #define parent_class (*GET_DBUS_WSD_VAR_NAME(parent_class,dbus_gproxy,s)())
       
  1341 
       
  1342 GET_STATIC_ARRAY_FROM_TLS(signals,dbus_gproxy,guint )
       
  1343 #define signals (GET_DBUS_WSD_VAR_NAME(signals,dbus_gproxy,s)())
       
  1344 
       
  1345 #else
       
  1346 static void *parent_class;
       
  1347 static guint signals[LAST_SIGNAL] = { 0 };
       
  1348 
       
  1349 #endif
       
  1350 
       
  1351 
       
  1352 static void
       
  1353 dbus_g_proxy_init (DBusGProxy *proxy)
       
  1354 {
       
  1355   DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  1356   
       
  1357   g_datalist_init (&priv->signal_signatures);
       
  1358   priv->pending_calls = g_hash_table_new_full (NULL, NULL, NULL,
       
  1359 				(GDestroyNotify) dbus_pending_call_unref);
       
  1360   priv->name_call = 0;
       
  1361   priv->associated = FALSE;
       
  1362 }
       
  1363 
       
  1364 static GObject *
       
  1365 dbus_g_proxy_constructor (GType                  type,
       
  1366 			  guint                  n_construct_properties,
       
  1367 			  GObjectConstructParam *construct_properties)
       
  1368 {
       
  1369   DBusGProxy *proxy;
       
  1370   DBusGProxyClass *klass;
       
  1371   GObjectClass *parent_class;
       
  1372   DBusGProxyPrivate *priv;
       
  1373 
       
  1374   klass = DBUS_G_PROXY_CLASS (g_type_class_peek (DBUS_TYPE_G_PROXY));
       
  1375 
       
  1376   parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
       
  1377 
       
  1378   proxy = DBUS_G_PROXY (parent_class->constructor (type, n_construct_properties,
       
  1379 						    construct_properties));
       
  1380 
       
  1381   priv = DBUS_G_PROXY_GET_PRIVATE (proxy);
       
  1382 
       
  1383   /* if these assertions fail, a deriving class has not set our required
       
  1384    * parameters - our own public constructors do return_if_fail checks
       
  1385    * on these parameters being provided. unfortunately we can't assert
       
  1386    * for manager because it's allowed to be NULL when tha mangager is
       
  1387    * setting up a bus proxy for its own calls */
       
  1388   g_assert (priv->path != NULL);
       
  1389   g_assert (priv->interface != NULL);
       
  1390 
       
  1391   if (priv->manager != NULL)
       
  1392     {
       
  1393       dbus_g_proxy_manager_register (priv->manager, proxy);
       
  1394     }
       
  1395 
       
  1396   return G_OBJECT (proxy);
       
  1397 }
       
  1398 
       
  1399 static void
       
  1400 dbus_g_proxy_class_init (DBusGProxyClass *klass)
       
  1401 {
       
  1402   GObjectClass *object_class = G_OBJECT_CLASS (klass);
       
  1403   
       
  1404   parent_class = g_type_class_peek_parent (klass);
       
  1405 
       
  1406   g_type_class_add_private (klass, sizeof (DBusGProxyPrivate));
       
  1407 
       
  1408   object_class->set_property = dbus_g_proxy_set_property;
       
  1409   object_class->get_property = dbus_g_proxy_get_property;
       
  1410 
       
  1411   g_object_class_install_property (object_class,
       
  1412 				   PROP_NAME,
       
  1413 				   g_param_spec_string ("name",
       
  1414 							"name",
       
  1415 							"name",
       
  1416 							NULL,
       
  1417 						//	#ifdef WINSCW
       
  1418 							G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
       
  1419 						//	#else
       
  1420 						 //   (GParamFlags)11));   // ARM complaining about enums mixing
       
  1421 					//		#endif
       
  1422 
       
  1423   g_object_class_install_property (object_class,
       
  1424 				   PROP_PATH,
       
  1425 				   g_param_spec_string ("path",
       
  1426 							"path",
       
  1427 							"path",
       
  1428 							NULL,
       
  1429 					//	    	#ifdef WINSCW
       
  1430 							G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
       
  1431 					//		#else
       
  1432 					//	    (GParamFlags)11));   // ARM complaining about enums mixing
       
  1433 					//		#endif
       
  1434 
       
  1435   g_object_class_install_property (object_class,
       
  1436 				   PROP_INTERFACE,
       
  1437 				   g_param_spec_string ("interface",
       
  1438 							"interface",
       
  1439 							"interface",
       
  1440 							NULL,
       
  1441 					//		#ifdef WINSCW
       
  1442 							G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
       
  1443 					//		#else
       
  1444 					//	    (GParamFlags)11));   // ARM complaining about enums mixing
       
  1445 					//		#endif
       
  1446   
       
  1447   g_object_class_install_property (object_class,
       
  1448 				   PROP_CONNECTION,
       
  1449 				   g_param_spec_boxed ("connection",
       
  1450 							"connection",
       
  1451 							"connection",
       
  1452 							DBUS_TYPE_G_CONNECTION,
       
  1453 					//		#ifdef WINSCW
       
  1454 							G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
       
  1455 					//		#else
       
  1456 					//	    (GParamFlags)11));   // ARM complaining about enums mixing
       
  1457 					//		#endif
       
  1458   
       
  1459   object_class->finalize = dbus_g_proxy_finalize;
       
  1460   object_class->dispose = dbus_g_proxy_dispose;
       
  1461   object_class->constructor = dbus_g_proxy_constructor;
       
  1462   
       
  1463   signals[DESTROY] =
       
  1464     g_signal_new ("destroy",
       
  1465 		  G_OBJECT_CLASS_TYPE (object_class),
       
  1466                   G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
       
  1467                   0,
       
  1468 		  NULL, NULL,
       
  1469                   g_cclosure_marshal_VOID__VOID,
       
  1470 		  G_TYPE_NONE, 0);
       
  1471 
       
  1472   signals[RECEIVED] =
       
  1473     g_signal_new ("received",
       
  1474 		  G_OBJECT_CLASS_TYPE (object_class),
       
  1475                   G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
       
  1476                   0,
       
  1477                   NULL, NULL,
       
  1478                   marshal_dbus_message_to_g_marshaller,
       
  1479                   G_TYPE_NONE, 2, DBUS_TYPE_MESSAGE, G_TYPE_POINTER);
       
  1480 }
       
  1481 
       
  1482 static void
       
  1483 cancel_pending_call (gpointer key, gpointer val, gpointer data)
       
  1484 {
       
  1485   DBusGProxyCall *call = key;
       
  1486   DBusGProxy *proxy = data;
       
  1487 
       
  1488   dbus_g_proxy_cancel_call (proxy, call);
       
  1489 }
       
  1490 
       
  1491 static void
       
  1492 dbus_g_proxy_dispose (GObject *object)
       
  1493 {
       
  1494   DBusGProxy *proxy = DBUS_G_PROXY (object);
       
  1495   DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  1496 
       
  1497   if (priv->pending_calls == NULL) 
       
  1498     {
       
  1499       return;
       
  1500     }
       
  1501 
       
  1502   /* Cancel outgoing pending calls */
       
  1503   g_hash_table_foreach (priv->pending_calls, cancel_pending_call, proxy);
       
  1504   g_hash_table_destroy (priv->pending_calls);
       
  1505   priv->pending_calls = NULL;
       
  1506 
       
  1507   if (priv->manager && proxy != priv->manager->bus_proxy)
       
  1508     {
       
  1509       dbus_g_proxy_manager_unregister (priv->manager, proxy);
       
  1510       dbus_g_proxy_manager_unref (priv->manager);
       
  1511     }
       
  1512   priv->manager = NULL;
       
  1513   
       
  1514   g_datalist_clear (&priv->signal_signatures);
       
  1515   
       
  1516   g_signal_emit (object, signals[DESTROY], 0);
       
  1517   
       
  1518   G_OBJECT_CLASS (parent_class)->dispose (object);
       
  1519 }
       
  1520 
       
  1521 static void
       
  1522 dbus_g_proxy_finalize (GObject *object)
       
  1523 {
       
  1524   DBusGProxy *proxy = DBUS_G_PROXY (object);
       
  1525   DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  1526   
       
  1527   g_return_if_fail (DBUS_G_PROXY_DESTROYED (proxy));
       
  1528   
       
  1529   g_free (priv->name);
       
  1530   g_free (priv->path);
       
  1531   g_free (priv->interface);
       
  1532   
       
  1533   G_OBJECT_CLASS (parent_class)->finalize (object);
       
  1534 }
       
  1535 
       
  1536 static void
       
  1537 dbus_g_proxy_destroy (DBusGProxy *proxy)
       
  1538 {
       
  1539   /* FIXME do we need the GTK_IN_DESTRUCTION style flag
       
  1540    * from GtkObject?
       
  1541    */
       
  1542   g_object_run_dispose (G_OBJECT (proxy));
       
  1543 }
       
  1544 
       
  1545 static void
       
  1546 dbus_g_proxy_set_property (GObject *object,
       
  1547 			   guint prop_id,
       
  1548 			   const GValue *value,
       
  1549 			   GParamSpec *pspec)
       
  1550 {
       
  1551   DBusGProxy *proxy = DBUS_G_PROXY (object);
       
  1552   DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  1553   DBusGConnection *connection;
       
  1554 
       
  1555   switch (prop_id)
       
  1556     {
       
  1557     case PROP_NAME:
       
  1558       priv->name = g_strdup (g_value_get_string (value));
       
  1559       if (priv->name)
       
  1560         priv->for_owner = (priv->name[0] == ':');
       
  1561       else
       
  1562         priv->for_owner = TRUE;
       
  1563       break;
       
  1564     case PROP_PATH:
       
  1565       priv->path = g_strdup (g_value_get_string (value));
       
  1566       break;
       
  1567     case PROP_INTERFACE:
       
  1568       priv->interface = g_strdup (g_value_get_string (value));
       
  1569       break;
       
  1570     case PROP_CONNECTION:
       
  1571       connection = g_value_get_boxed (value);
       
  1572       if (connection != NULL)
       
  1573         {
       
  1574           priv->manager = dbus_g_proxy_manager_get (DBUS_CONNECTION_FROM_G_CONNECTION (connection));
       
  1575         }
       
  1576       break;
       
  1577     default:
       
  1578       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
  1579       break;
       
  1580     }
       
  1581 }
       
  1582 
       
  1583 static void 
       
  1584 dbus_g_proxy_get_property (GObject *object,
       
  1585 			   guint prop_id,
       
  1586 			   GValue *value,
       
  1587 			   GParamSpec *pspec)
       
  1588 {
       
  1589   DBusGProxy *proxy = DBUS_G_PROXY (object);
       
  1590   DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  1591 
       
  1592   switch (prop_id)
       
  1593     {
       
  1594     case PROP_NAME:
       
  1595       g_value_set_string (value, priv->name);
       
  1596       break;
       
  1597     case PROP_PATH:
       
  1598       g_value_set_string (value, priv->path);
       
  1599       break;
       
  1600     case PROP_INTERFACE:
       
  1601       g_value_set_string (value, priv->interface);
       
  1602       break;
       
  1603     case PROP_CONNECTION:
       
  1604       g_value_set_boxed (value, DBUS_G_CONNECTION_FROM_CONNECTION(priv->manager->connection));
       
  1605       break;
       
  1606     default:
       
  1607       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
  1608       break;
       
  1609     }
       
  1610 }
       
  1611 
       
  1612 /* this is to avoid people using g_signal_connect() directly,
       
  1613  * to avoid confusion with local signal names, and because
       
  1614  * of the horribly broken current setup (signals are added
       
  1615  * globally to all proxies)
       
  1616  */
       
  1617 static char*
       
  1618 create_signal_name (const char *interface,
       
  1619                     const char *signal)
       
  1620 {
       
  1621   GString *str;
       
  1622   char *p;
       
  1623 
       
  1624   str = g_string_new (interface);
       
  1625 
       
  1626   g_string_append (str, "-");
       
  1627   
       
  1628   g_string_append (str, signal);
       
  1629 
       
  1630   /* GLib will silently barf on '.' in signal names */
       
  1631   p = str->str;
       
  1632   while (*p)
       
  1633     {
       
  1634       if (*p == '.')
       
  1635         *p = '-';
       
  1636       ++p;
       
  1637     }
       
  1638   
       
  1639   return g_string_free (str, FALSE);
       
  1640 }
       
  1641 
       
  1642 static void
       
  1643 marshal_dbus_message_to_g_marshaller (GClosure     *closure,
       
  1644                                       GValue       *return_value,
       
  1645                                       guint         n_param_values,
       
  1646                                       const GValue *param_values,
       
  1647                                       gpointer      invocation_hint,
       
  1648                                       gpointer      marshal_data)
       
  1649 {
       
  1650   /* Incoming here we have three params, the instance (Proxy), the
       
  1651    * DBusMessage, the signature. We want to convert that to an
       
  1652    * expanded GValue array, then call an appropriate normal GLib
       
  1653    * marshaller.
       
  1654    */
       
  1655 #define MAX_SIGNATURE_ARGS 20
       
  1656   GValueArray *value_array;
       
  1657   GSignalCMarshaller c_marshaller;
       
  1658   DBusGProxy *proxy;
       
  1659   DBusMessage *message;
       
  1660   GArray *gsignature;
       
  1661   const GType *types;
       
  1662   DBusGProxyPrivate *priv;
       
  1663 
       
  1664   g_assert (n_param_values == 3);
       
  1665 
       
  1666   proxy = g_value_get_object (&param_values[0]);
       
  1667   message = g_value_get_boxed (&param_values[1]);
       
  1668   gsignature = g_value_get_pointer (&param_values[2]);
       
  1669 
       
  1670   g_return_if_fail (DBUS_IS_G_PROXY (proxy));
       
  1671   g_return_if_fail (message != NULL);
       
  1672   g_return_if_fail (gsignature != NULL);
       
  1673 
       
  1674   priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  1675 
       
  1676   c_marshaller = _dbus_gobject_lookup_marshaller (G_TYPE_NONE, gsignature->len,
       
  1677 						  (GType*) gsignature->data);
       
  1678 
       
  1679   g_return_if_fail (c_marshaller != NULL);
       
  1680   
       
  1681   {
       
  1682     DBusGValueMarshalCtx context;
       
  1683     context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection);
       
  1684     context.proxy = proxy;
       
  1685 
       
  1686     types = (const GType*) gsignature->data;
       
  1687     value_array = _dbus_gvalue_demarshal_message (&context, message,
       
  1688 						 gsignature->len, types, NULL);
       
  1689   }
       
  1690 
       
  1691   if (value_array == NULL)
       
  1692     return;
       
  1693   
       
  1694   g_value_array_prepend (value_array, NULL);
       
  1695   g_value_init (g_value_array_get_nth (value_array, 0), G_TYPE_FROM_INSTANCE (proxy));
       
  1696   g_value_set_instance (g_value_array_get_nth (value_array, 0), proxy);
       
  1697 
       
  1698   (* c_marshaller) (closure, return_value, value_array->n_values,
       
  1699 		    value_array->values, invocation_hint, marshal_data);
       
  1700   
       
  1701   g_value_array_free (value_array);
       
  1702 }
       
  1703 
       
  1704 static void
       
  1705 dbus_g_proxy_emit_remote_signal (DBusGProxy  *proxy,
       
  1706                                  DBusMessage *message)
       
  1707 {
       
  1708   const char *interface;
       
  1709   const char *signal;
       
  1710   char *name;
       
  1711   GQuark q;
       
  1712   DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  1713   GArray *msg_gsignature = NULL;
       
  1714 
       
  1715   g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
       
  1716 
       
  1717   interface = dbus_message_get_interface (message);
       
  1718   signal = dbus_message_get_member (message);
       
  1719 
       
  1720   g_assert (interface != NULL);
       
  1721   g_assert (signal != NULL);
       
  1722 
       
  1723   name = create_signal_name (interface, signal);
       
  1724 
       
  1725   /* If the quark isn't preexisting, there's no way there
       
  1726    * are any handlers connected. We don't want to create
       
  1727    * extra quarks for every possible signal.
       
  1728    */
       
  1729   q = g_quark_try_string (name);
       
  1730 
       
  1731   if (q != 0)
       
  1732     {
       
  1733       GArray *gsignature;
       
  1734       guint i;
       
  1735       
       
  1736       gsignature = g_datalist_id_get_data (&priv->signal_signatures, q);
       
  1737       if (gsignature == NULL)
       
  1738 	goto out;
       
  1739       
       
  1740       msg_gsignature = _dbus_gtypes_from_arg_signature (dbus_message_get_signature (message),
       
  1741 						       TRUE);
       
  1742       for (i = 0; i < gsignature->len; i++)
       
  1743 	{
       
  1744 	  if (msg_gsignature->len == i
       
  1745 	      || g_array_index (gsignature, GType, i) != g_array_index (msg_gsignature, GType, i))
       
  1746 	    goto mismatch;
       
  1747 	}
       
  1748       if (msg_gsignature->len != i)
       
  1749 	goto mismatch;
       
  1750       
       
  1751       g_signal_emit (proxy,
       
  1752 		     signals[RECEIVED],
       
  1753 		     q,
       
  1754 		     message,
       
  1755 		     msg_gsignature);
       
  1756     }
       
  1757 
       
  1758  out:
       
  1759   g_free (name);
       
  1760   if (msg_gsignature)
       
  1761     g_array_free (msg_gsignature, TRUE);
       
  1762   return;
       
  1763  mismatch:
       
  1764 #if 0
       
  1765   /* Don't spew on remote errors */
       
  1766   g_warning ("Unexpected message signature '%s' for signal '%s'\n",
       
  1767 	     dbus_message_get_signature (message),
       
  1768 	     name);
       
  1769 #endif
       
  1770   goto out;
       
  1771 }
       
  1772 
       
  1773 typedef struct
       
  1774 {
       
  1775   DBusGProxy *proxy;
       
  1776   guint call_id;
       
  1777   DBusGProxyCallNotify func;
       
  1778   void *data;
       
  1779   GDestroyNotify free_data_func;
       
  1780 } GPendingNotifyClosure;
       
  1781 
       
  1782 static void
       
  1783 d_pending_call_notify (DBusPendingCall *dcall,
       
  1784                        void            *data)
       
  1785 {
       
  1786   GPendingNotifyClosure *closure = data;
       
  1787 
       
  1788   (* closure->func) (closure->proxy, DBUS_G_PROXY_ID_TO_CALL (closure->call_id), closure->data);
       
  1789 }
       
  1790 
       
  1791 static void
       
  1792 d_pending_call_free (void *data)
       
  1793 {
       
  1794   GPendingNotifyClosure *closure = data;
       
  1795   
       
  1796   if (closure->free_data_func)
       
  1797     (* closure->free_data_func) (closure->data);
       
  1798 
       
  1799   g_free (closure);
       
  1800 }
       
  1801   
       
  1802 #define DBUS_G_VALUE_ARRAY_COLLECT_ALL(VALARRAY, FIRST_ARG_TYPE, ARGS) \
       
  1803 do { \
       
  1804   GType valtype; \
       
  1805   int i = 0; \
       
  1806   VALARRAY = g_value_array_new (6); \
       
  1807   valtype = FIRST_ARG_TYPE; \
       
  1808   while (valtype != G_TYPE_INVALID) \
       
  1809     { \
       
  1810       const char *collect_err; \
       
  1811       GValue *val; \
       
  1812       g_value_array_append (VALARRAY, NULL); \
       
  1813       val = g_value_array_get_nth (VALARRAY, i); \
       
  1814       g_value_init (val, valtype); \
       
  1815       collect_err = NULL; \
       
  1816       G_VALUE_COLLECT (val, ARGS, G_VALUE_NOCOPY_CONTENTS, &collect_err); \
       
  1817       valtype = va_arg (ARGS, GType); \
       
  1818       i++; \
       
  1819     } \
       
  1820 } while (0)
       
  1821 
       
  1822 DBusGProxyCall *
       
  1823 manager_begin_bus_call (DBusGProxyManager    *manager,
       
  1824 			const char           *method,
       
  1825 			DBusGProxyCallNotify  notify,
       
  1826 			gpointer              user_data,
       
  1827 			GDestroyNotify        destroy,
       
  1828 			GType                 first_arg_type,
       
  1829 			...)
       
  1830 {
       
  1831   DBusGProxyCall *call;
       
  1832   DBusGProxyPrivate *priv;
       
  1833   va_list args;
       
  1834   GValueArray *arg_values;
       
  1835   
       
  1836   va_start (args, first_arg_type);
       
  1837 
       
  1838   if (!manager->bus_proxy)
       
  1839     {
       
  1840       manager->bus_proxy = g_object_new (DBUS_TYPE_G_PROXY,
       
  1841 					 "name", DBUS_SERVICE_DBUS,
       
  1842 					 "path", DBUS_PATH_DBUS,
       
  1843 					 "interface", DBUS_INTERFACE_DBUS,
       
  1844 					 NULL);
       
  1845       priv = DBUS_G_PROXY_GET_PRIVATE(manager->bus_proxy);
       
  1846       priv->manager = manager;
       
  1847     }
       
  1848 
       
  1849   DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
       
  1850   
       
  1851   call = DBUS_G_PROXY_ID_TO_CALL (dbus_g_proxy_begin_call_internal (manager->bus_proxy, method, notify, user_data, destroy, arg_values,-1));
       
  1852 
       
  1853   g_value_array_free (arg_values);
       
  1854 
       
  1855   va_end (args);
       
  1856 
       
  1857   return call;
       
  1858 }
       
  1859 
       
  1860 /** @} End of DBusGLibInternals */
       
  1861 
       
  1862 /** @addtogroup DBusGLib
       
  1863  * @{
       
  1864  */
       
  1865 
       
  1866 /**
       
  1867  * SECTION:dbus-gproxy
       
  1868  * @short_description: DBus Proxy
       
  1869  * @see_also: #DBusProxy
       
  1870  * @stability: Stable
       
  1871  *
       
  1872  * A #DBusGProxy is a boxed type abstracting a #DBusProxy.
       
  1873  */
       
  1874 
       
  1875 /**
       
  1876  * dbus_g_proxy_get_type:
       
  1877  * Standard GObject get_type() function for DBusGProxy.
       
  1878  *
       
  1879  * Returns: type ID for DBusGProxy class
       
  1880  */
       
  1881  #if EMULATOR
       
  1882 GET_STATIC_VAR_FROM_TLS(object_type,dbus_gproxy,GType)
       
  1883 #define object_type (*GET_DBUS_WSD_VAR_NAME(object_type,dbus_gproxy,s)())
       
  1884 #endif
       
  1885  	#ifdef __SYMBIAN32__
       
  1886 	EXPORT_C
       
  1887 	#endif
       
  1888 GType
       
  1889 dbus_g_proxy_get_type (void)
       
  1890 {
       
  1891  #ifndef EMULATOR
       
  1892   static GType object_type = 0;
       
  1893 #endif
       
  1894 
       
  1895 
       
  1896   if (!object_type)
       
  1897     {
       
  1898       static const GTypeInfo object_info =
       
  1899         {
       
  1900           sizeof (DBusGProxyClass),
       
  1901           (GBaseInitFunc) NULL,
       
  1902           (GBaseFinalizeFunc) NULL,
       
  1903           (GClassInitFunc) dbus_g_proxy_class_init,
       
  1904           NULL,           /* class_finalize */
       
  1905           NULL,           /* class_data */
       
  1906           sizeof (DBusGProxy),
       
  1907           0,              /* n_preallocs */
       
  1908           (GInstanceInitFunc) dbus_g_proxy_init,
       
  1909         };
       
  1910       
       
  1911       object_type = g_type_register_static (G_TYPE_OBJECT,
       
  1912                                             "DBusGProxy",
       
  1913                                             &object_info, 0);
       
  1914     }
       
  1915   
       
  1916   return object_type;
       
  1917 }
       
  1918 
       
  1919 static DBusGProxy*
       
  1920 dbus_g_proxy_new (DBusGConnection *connection,
       
  1921                   const char      *name,
       
  1922                   const char      *path_name,
       
  1923                   const char      *interface_name)
       
  1924 {
       
  1925   DBusGProxy *proxy;
       
  1926 
       
  1927   g_assert (connection != NULL);
       
  1928   
       
  1929   proxy = g_object_new (DBUS_TYPE_G_PROXY, 
       
  1930                         "name", name, 
       
  1931                         "path", path_name, 
       
  1932                         "interface", interface_name, 
       
  1933                         "connection", connection, NULL);
       
  1934 
       
  1935   return proxy;
       
  1936 }
       
  1937 
       
  1938 /**
       
  1939  * dbus_g_proxy_new_for_name:
       
  1940  * @connection: the connection to the remote bus
       
  1941  * @name: any name on the message bus
       
  1942  * @path_name: name of the object instance to call methods on
       
  1943  * @interface_name: name of the interface to call methods on
       
  1944  *
       
  1945  * Creates a new proxy for a remote interface exported by a connection
       
  1946  * on a message bus. Method calls and signal connections over this
       
  1947  * proxy will go to the name owner; the name's owner is expected to
       
  1948  * support the given interface name. THE NAME OWNER MAY CHANGE OVER
       
  1949  * TIME, for example between two different method calls, unless the
       
  1950  * name is a unique name. If you need a fixed owner, you need to
       
  1951  * request the current owner and bind a proxy to its unique name
       
  1952  * rather than to the generic name; see
       
  1953  * dbus_g_proxy_new_for_name_owner().
       
  1954  *
       
  1955  * A name-associated proxy only makes sense with a message bus, not
       
  1956  * for app-to-app direct dbus connections.
       
  1957  *
       
  1958  * This proxy will only emit the "destroy" signal if the
       
  1959  * #DBusConnection is disconnected, the proxy has no remaining
       
  1960  * references, or the name is a unique name and its owner
       
  1961  * disappears. If a well-known name changes owner, the proxy will
       
  1962  * still be alive.
       
  1963  *
       
  1964  * Returns: new proxy object
       
  1965  */
       
  1966  	#ifdef __SYMBIAN32__
       
  1967 	EXPORT_C
       
  1968 	#endif
       
  1969 DBusGProxy*
       
  1970 dbus_g_proxy_new_for_name (DBusGConnection *connection,
       
  1971                            const char      *name,
       
  1972                            const char      *path_name,
       
  1973                            const char      *interface_name)
       
  1974 {
       
  1975   g_return_val_if_fail (connection != NULL, NULL);
       
  1976   g_return_val_if_fail (name != NULL, NULL);
       
  1977   g_return_val_if_fail (path_name != NULL, NULL);
       
  1978   g_return_val_if_fail (interface_name != NULL, NULL);
       
  1979 
       
  1980   return dbus_g_proxy_new (connection, name,
       
  1981 			   path_name, interface_name);
       
  1982 }
       
  1983 
       
  1984 /**
       
  1985  * dbus_g_proxy_new_for_name_owner:
       
  1986  * @connection: the connection to the remote bus
       
  1987  * @name: any name on the message bus
       
  1988  * @path_name: name of the object inside the service to call methods on
       
  1989  * @interface_name: name of the interface to call methods on
       
  1990  * @error: return location for an error
       
  1991  *
       
  1992  * Similar to dbus_g_proxy_new_for_name(), but makes a round-trip
       
  1993  * request to the message bus to get the current name owner, then
       
  1994  * binds the proxy to the unique name of the current owner, rather
       
  1995  * than to the well-known name. As a result, the name owner will
       
  1996  * not change over time, and the proxy will emit the "destroy" signal
       
  1997  * when the owner disappears from the message bus.
       
  1998  *
       
  1999  * An example of the difference between dbus_g_proxy_new_for_name()
       
  2000  * and dbus_g_proxy_new_for_name_owner(): if you provide the well-known name
       
  2001  * "org.freedesktop.Database" dbus_g_proxy_new_for_name() remains bound
       
  2002  * to that name as it changes owner. dbus_g_proxy_new_for_name_owner()
       
  2003  * will fail if the name has no owner. If the name has an owner,
       
  2004  * dbus_g_proxy_new_for_name_owner() will bind to the unique name
       
  2005  * of that owner rather than the generic name.
       
  2006  * 
       
  2007  * Returns: new proxy object, or #NULL on error
       
  2008  */
       
  2009  	#ifdef __SYMBIAN32__
       
  2010 	EXPORT_C
       
  2011 	#endif
       
  2012 DBusGProxy*
       
  2013 dbus_g_proxy_new_for_name_owner (DBusGConnection          *connection,
       
  2014                                  const char               *name,
       
  2015                                  const char               *path_name,
       
  2016                                  const char               *interface_name,
       
  2017                                  GError                  **error)
       
  2018 {
       
  2019   DBusGProxy *proxy;
       
  2020   char *unique_name;
       
  2021 
       
  2022   g_return_val_if_fail (connection != NULL, NULL);
       
  2023   g_return_val_if_fail (name != NULL, NULL);
       
  2024   g_return_val_if_fail (path_name != NULL, NULL);
       
  2025   g_return_val_if_fail (interface_name != NULL, NULL);
       
  2026 
       
  2027   if (!(unique_name = get_name_owner (DBUS_CONNECTION_FROM_G_CONNECTION (connection), name, error)))
       
  2028     return NULL;
       
  2029 
       
  2030   proxy = dbus_g_proxy_new (connection, unique_name,
       
  2031 			    path_name, interface_name);
       
  2032   g_free (unique_name);
       
  2033   return proxy;
       
  2034 }
       
  2035 
       
  2036 /**
       
  2037  * dbus_g_proxy_new_from_proxy:
       
  2038  * @proxy: the proxy to use as a template
       
  2039  * @path: of the object inside the peer to call methods on
       
  2040  * @interface: name of the interface to call methods on
       
  2041  *
       
  2042  * Creates a proxy using an existing proxy as a template, substituting
       
  2043  * the specified interface and path.  Either or both may be NULL.
       
  2044  *
       
  2045  * Returns: new proxy object
       
  2046  */
       
  2047  	#ifdef __SYMBIAN32__
       
  2048 	EXPORT_C
       
  2049 	#endif
       
  2050 DBusGProxy*
       
  2051 dbus_g_proxy_new_from_proxy (DBusGProxy        *proxy,
       
  2052 			     const char        *interface,
       
  2053 			     const char        *path)
       
  2054 {
       
  2055   DBusGProxyPrivate *priv;
       
  2056 
       
  2057   g_return_val_if_fail (proxy != NULL, NULL);
       
  2058 
       
  2059   priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  2060   
       
  2061   if (interface == NULL)
       
  2062     interface = priv->interface;
       
  2063   if (path == NULL)
       
  2064     path = priv->path;
       
  2065 
       
  2066   return dbus_g_proxy_new (DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection),
       
  2067 			   priv->name,
       
  2068 			   path, interface);
       
  2069 }
       
  2070 
       
  2071 /**
       
  2072  * dbus_g_proxy_new_for_peer:
       
  2073  * @connection: the connection to the peer
       
  2074  * @path_name: name of the object inside the peer to call methods on
       
  2075  * @interface_name: name of the interface to call methods on
       
  2076  *
       
  2077  * Creates a proxy for an object in peer application (one
       
  2078  * we're directly connected to). That is, this function is
       
  2079  * intended for use when there's no message bus involved,
       
  2080  * we're doing a simple 1-to-1 communication between two
       
  2081  * applications.
       
  2082  *
       
  2083  * Returns: new proxy object
       
  2084  */
       
  2085  	#ifdef __SYMBIAN32__
       
  2086 	EXPORT_C
       
  2087 	#endif
       
  2088 DBusGProxy*
       
  2089 dbus_g_proxy_new_for_peer (DBusGConnection          *connection,
       
  2090                            const char               *path_name,
       
  2091                            const char               *interface_name)
       
  2092 {
       
  2093   DBusGProxy *proxy;
       
  2094   
       
  2095   g_return_val_if_fail (connection != NULL, NULL);
       
  2096   g_return_val_if_fail (path_name != NULL, NULL);
       
  2097   g_return_val_if_fail (interface_name != NULL, NULL);
       
  2098 
       
  2099   proxy = dbus_g_proxy_new (connection, NULL,
       
  2100                             path_name, interface_name);
       
  2101 
       
  2102   return proxy;
       
  2103 }
       
  2104 
       
  2105 /**
       
  2106  * dbus_g_proxy_get_bus_name:
       
  2107  * @proxy: the proxy
       
  2108  *
       
  2109  * Gets the bus name a proxy is bound to (may be #NULL in some cases).
       
  2110  * If you created the proxy with dbus_g_proxy_new_for_name(), then
       
  2111  * the name you passed to that will be returned.
       
  2112  * If you created it with dbus_g_proxy_new_for_name_owner(), then the
       
  2113  * unique connection name will be returned. If you created it
       
  2114  * with dbus_g_proxy_new_for_peer() then #NULL will be returned.
       
  2115  *
       
  2116  * Returns: the bus name the proxy sends messages to
       
  2117  */
       
  2118  	#ifdef __SYMBIAN32__
       
  2119 	EXPORT_C
       
  2120 	#endif
       
  2121 const char*
       
  2122 dbus_g_proxy_get_bus_name (DBusGProxy        *proxy)
       
  2123 {
       
  2124   DBusGProxyPrivate *priv;
       
  2125 
       
  2126   g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
       
  2127   g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
       
  2128 
       
  2129   priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  2130 
       
  2131   return priv->name;
       
  2132 }
       
  2133 
       
  2134 /**
       
  2135  * dbus_g_proxy_get_interface:
       
  2136  * @proxy: the proxy
       
  2137  *
       
  2138  * Gets the object interface proxy is bound to (may be #NULL in some cases).
       
  2139  *
       
  2140  * Returns: an object interface 
       
  2141  */
       
  2142  	#ifdef __SYMBIAN32__
       
  2143 	EXPORT_C
       
  2144 	#endif
       
  2145 const char*
       
  2146 dbus_g_proxy_get_interface (DBusGProxy        *proxy)
       
  2147 {
       
  2148   DBusGProxyPrivate *priv;
       
  2149   
       
  2150   g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
       
  2151   g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
       
  2152 
       
  2153   priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  2154 
       
  2155   return priv->interface;
       
  2156 }
       
  2157 
       
  2158 /**
       
  2159  * dbus_g_proxy_set_interface:
       
  2160  * @proxy: the proxy
       
  2161  * @interface_name: an object interface 
       
  2162  *
       
  2163  * Sets the object interface proxy is bound to
       
  2164  */
       
  2165  	#ifdef __SYMBIAN32__
       
  2166 	EXPORT_C
       
  2167 	#endif
       
  2168 void
       
  2169 dbus_g_proxy_set_interface (DBusGProxy        *proxy,
       
  2170 			    const char        *interface_name)
       
  2171 {
       
  2172   DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  2173   /* FIXME - need to unregister when we switch interface for now
       
  2174    * later should support idea of unset interface
       
  2175    */
       
  2176   dbus_g_proxy_manager_unregister (priv->manager, proxy);
       
  2177   g_free (priv->interface);
       
  2178   priv->interface = g_strdup (interface_name);
       
  2179   dbus_g_proxy_manager_register (priv->manager, proxy);
       
  2180 }
       
  2181 
       
  2182 /**
       
  2183  * dbus_g_proxy_get_path:
       
  2184  * Gets the path this proxy is bound to
       
  2185  * @proxy: the proxy
       
  2186  *
       
  2187  * Returns: an object path
       
  2188  */
       
  2189  	#ifdef __SYMBIAN32__
       
  2190 	EXPORT_C
       
  2191 	#endif
       
  2192 const char*
       
  2193 dbus_g_proxy_get_path (DBusGProxy        *proxy)
       
  2194 {
       
  2195   DBusGProxyPrivate *priv;
       
  2196   
       
  2197   g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
       
  2198   g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
       
  2199 
       
  2200   priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  2201 
       
  2202   return priv->path;
       
  2203 }
       
  2204 
       
  2205 static DBusMessage *
       
  2206 dbus_g_proxy_marshal_args_to_message (DBusGProxy  *proxy,
       
  2207 				      const char  *method,
       
  2208 				      GValueArray *args)
       
  2209 {
       
  2210   DBusMessage *message;
       
  2211   DBusMessageIter msgiter;
       
  2212   guint i;
       
  2213   DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  2214 
       
  2215   message = dbus_message_new_method_call (priv->name,
       
  2216                                           priv->path,
       
  2217                                           priv->interface,
       
  2218                                           method);
       
  2219   if (message == NULL)
       
  2220     goto oom;
       
  2221 
       
  2222   dbus_message_iter_init_append (message, &msgiter);
       
  2223   for (i = 0; i < args->n_values; i++)
       
  2224     {
       
  2225       GValue *gvalue;
       
  2226 
       
  2227       gvalue = g_value_array_get_nth (args, i);
       
  2228 
       
  2229       if (!_dbus_gvalue_marshal (&msgiter, gvalue))
       
  2230 	g_assert_not_reached ();
       
  2231     }
       
  2232   return message;
       
  2233  oom:
       
  2234   return NULL;
       
  2235 }
       
  2236 
       
  2237 static guint
       
  2238 dbus_g_proxy_begin_call_internal (DBusGProxy          *proxy,
       
  2239 				  const char          *method,
       
  2240 				  DBusGProxyCallNotify notify,
       
  2241 				  gpointer             user_data,
       
  2242 				  GDestroyNotify       destroy,
       
  2243 				  GValueArray         *args,
       
  2244 				  int timeout)
       
  2245 {
       
  2246   DBusMessage *message;
       
  2247   DBusPendingCall *pending;
       
  2248   GPendingNotifyClosure *closure;
       
  2249   guint call_id;
       
  2250   DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  2251 
       
  2252   pending = NULL;
       
  2253 
       
  2254   message = dbus_g_proxy_marshal_args_to_message (proxy, method, args);
       
  2255   if (!message)
       
  2256     goto oom;
       
  2257 
       
  2258   if (!dbus_connection_send_with_reply (priv->manager->connection,
       
  2259                                         message,
       
  2260                                         &pending,
       
  2261                                         timeout))
       
  2262     goto oom;
       
  2263   dbus_message_unref (message);
       
  2264   g_assert (pending != NULL);
       
  2265 
       
  2266   call_id = ++priv->call_id_counter;
       
  2267 
       
  2268   if (notify != NULL)
       
  2269     {
       
  2270       closure = g_new (GPendingNotifyClosure, 1);
       
  2271       closure->proxy = proxy; /* No need to ref as the lifecycle is tied to proxy */
       
  2272       closure->call_id = call_id;
       
  2273       closure->func = notify;
       
  2274       closure->data = user_data;
       
  2275       closure->free_data_func = destroy;
       
  2276       dbus_pending_call_set_notify (pending, d_pending_call_notify,
       
  2277 				    closure,
       
  2278 				    d_pending_call_free);
       
  2279     }
       
  2280 
       
  2281   g_hash_table_insert (priv->pending_calls, GUINT_TO_POINTER (call_id), pending);
       
  2282 
       
  2283   return call_id;
       
  2284  oom:
       
  2285   g_error ("Out of memory");
       
  2286   return 0;
       
  2287 }
       
  2288 
       
  2289 static gboolean
       
  2290 dbus_g_proxy_end_call_internal (DBusGProxy        *proxy,
       
  2291 				guint              call_id,
       
  2292 				GError           **error,
       
  2293 				GType              first_arg_type,
       
  2294 				va_list            args)
       
  2295 {
       
  2296   DBusMessage *reply;
       
  2297   DBusMessageIter msgiter;
       
  2298   DBusError derror;
       
  2299   va_list args_unwind;
       
  2300   guint over;
       
  2301   int n_retvals_processed;
       
  2302   gboolean ret;
       
  2303   GType valtype;
       
  2304   DBusPendingCall *pending;
       
  2305   DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  2306 
       
  2307   reply = NULL;
       
  2308   ret = FALSE;
       
  2309   n_retvals_processed = 0;
       
  2310   over = 0;
       
  2311 
       
  2312   pending = g_hash_table_lookup (priv->pending_calls, GUINT_TO_POINTER (call_id));
       
  2313   
       
  2314   dbus_pending_call_block (pending);
       
  2315   reply = dbus_pending_call_steal_reply (pending);
       
  2316 
       
  2317   g_assert (reply != NULL);
       
  2318 
       
  2319   dbus_error_init (&derror);
       
  2320 
       
  2321   switch (dbus_message_get_type (reply))
       
  2322     {
       
  2323     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
       
  2324       dbus_message_iter_init (reply, &msgiter);
       
  2325       valtype = first_arg_type;
       
  2326       while (valtype != G_TYPE_INVALID)
       
  2327 	{
       
  2328 	  int arg_type;
       
  2329 	  gpointer return_storage;
       
  2330 	  GValue gvalue = { 0, };
       
  2331 	  DBusGValueMarshalCtx context;
       
  2332 
       
  2333 	  context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection);
       
  2334 	  context.proxy = proxy;
       
  2335 
       
  2336 	  arg_type = dbus_message_iter_get_arg_type (&msgiter);
       
  2337 	  if (arg_type == DBUS_TYPE_INVALID)
       
  2338 	    {
       
  2339 	      g_set_error (error, DBUS_GERROR,
       
  2340 			   DBUS_GERROR_INVALID_ARGS,
       
  2341 			   _("Too few arguments in reply"));
       
  2342 	      goto out;
       
  2343 	    }
       
  2344 
       
  2345 	  return_storage = va_arg (args, gpointer);
       
  2346 	  if (return_storage == NULL)
       
  2347 	    goto next;
       
  2348 
       
  2349 	  /* We handle variants specially; the caller is expected
       
  2350 	   * to have already allocated storage for them.
       
  2351 	   */
       
  2352 	  if (arg_type == DBUS_TYPE_VARIANT
       
  2353 	      && g_type_is_a (valtype, G_TYPE_VALUE))
       
  2354 	    {
       
  2355 	      if (!_dbus_gvalue_demarshal_variant (&context, &msgiter, (GValue*) return_storage, NULL))
       
  2356 		{
       
  2357 		  g_set_error (error,
       
  2358 			       DBUS_GERROR,
       
  2359 			       DBUS_GERROR_INVALID_ARGS,
       
  2360 			       _("Couldn't convert argument, expected \"%s\""),
       
  2361 			       g_type_name (valtype));
       
  2362 		  goto out;
       
  2363 		}
       
  2364 	    }
       
  2365 	  else
       
  2366 	    {
       
  2367 	      g_value_init (&gvalue, valtype);
       
  2368 
       
  2369 	      if (!_dbus_gvalue_demarshal (&context, &msgiter, &gvalue, error))
       
  2370 		goto out;
       
  2371 
       
  2372 	      /* Anything that can be demarshaled must be storable */
       
  2373 	      if (!_dbus_gvalue_store (&gvalue, (gpointer*) return_storage))
       
  2374 		g_assert_not_reached ();
       
  2375 	      /* Ownership of the value passes to the client, don't unset */
       
  2376 	    }
       
  2377 	  
       
  2378 	next:
       
  2379 	  n_retvals_processed++;
       
  2380 	  dbus_message_iter_next (&msgiter);
       
  2381 	  valtype = va_arg (args, GType);
       
  2382 	}
       
  2383       
       
  2384       while (dbus_message_iter_get_arg_type (&msgiter) != DBUS_TYPE_INVALID)
       
  2385 	{
       
  2386 	  over++;
       
  2387 	  dbus_message_iter_next (&msgiter);
       
  2388 	}
       
  2389 
       
  2390       if (over > 0)
       
  2391 	{
       
  2392 	  g_set_error (error, DBUS_GERROR,
       
  2393 		       DBUS_GERROR_INVALID_ARGS,
       
  2394 		       _("Too many arguments in reply; expected %d, got %d"),
       
  2395 		       n_retvals_processed, over);
       
  2396 	  goto out;
       
  2397 	}
       
  2398       break;
       
  2399     case DBUS_MESSAGE_TYPE_ERROR:
       
  2400       dbus_set_error_from_message (&derror, reply);
       
  2401       dbus_set_g_error (error, &derror);
       
  2402       dbus_error_free (&derror);
       
  2403       goto out;
       
  2404       break;
       
  2405     default:
       
  2406       dbus_set_error (&derror, DBUS_ERROR_FAILED,
       
  2407                       "Reply was neither a method return nor an exception");
       
  2408       dbus_set_g_error (error, &derror);
       
  2409       dbus_error_free (&derror);
       
  2410       goto out;
       
  2411       break;
       
  2412     }
       
  2413 
       
  2414   ret = TRUE;
       
  2415  out:
       
  2416   va_end (args);
       
  2417 
       
  2418   if (ret == FALSE)
       
  2419     {
       
  2420       int i;
       
  2421       for (i = 0; i < n_retvals_processed; i++)
       
  2422 	{
       
  2423 	  gpointer retval;
       
  2424 
       
  2425 	  retval = va_arg (args_unwind, gpointer);
       
  2426 
       
  2427 	  g_free (retval);
       
  2428 	}
       
  2429     }
       
  2430   va_end (args_unwind);
       
  2431 
       
  2432   g_hash_table_remove (priv->pending_calls, GUINT_TO_POINTER (call_id));
       
  2433 
       
  2434   if (reply)
       
  2435     dbus_message_unref (reply);
       
  2436   return ret;
       
  2437 }
       
  2438 
       
  2439 /**
       
  2440  * dbus_g_proxy_begin_call:
       
  2441  * @proxy: a proxy for a remote interface
       
  2442  * @method: the name of the method to invoke
       
  2443  * @notify: callback to be invoked when method returns
       
  2444  * @user_data: user data passed to callback
       
  2445  * @destroy: function called to destroy user_data
       
  2446  * @first_arg_type: type of the first argument
       
  2447  *
       
  2448  * Asynchronously invokes a method on a remote interface. The method
       
  2449  * call will not be sent over the wire until the application returns
       
  2450  * to the main loop, or blocks in dbus_connection_flush() to write out
       
  2451  * pending data.  The call will be completed after a timeout, or when
       
  2452  * a reply is received.  When the call returns, the callback specified
       
  2453  * will be invoked; you can then collect the results of the call
       
  2454  * (which may be an error, or a reply), use dbus_g_proxy_end_call().
       
  2455  *
       
  2456  * TODO this particular function shouldn't die on out of memory,
       
  2457  * since you should be able to do a call with large arguments.
       
  2458  * 
       
  2459  * Returns: call identifier.
       
  2460  */
       
  2461  	#ifdef __SYMBIAN32__
       
  2462 	EXPORT_C
       
  2463 	#endif
       
  2464 DBusGProxyCall *
       
  2465 dbus_g_proxy_begin_call (DBusGProxy          *proxy,
       
  2466 			 const char          *method,
       
  2467 			 DBusGProxyCallNotify notify,
       
  2468 			 gpointer             user_data,
       
  2469 			 GDestroyNotify       destroy,
       
  2470 			 GType                first_arg_type,
       
  2471 			 ...)
       
  2472 {
       
  2473   guint call_id;
       
  2474   va_list args;
       
  2475   GValueArray *arg_values;
       
  2476   
       
  2477   g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
       
  2478   g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
       
  2479 
       
  2480   va_start (args, first_arg_type);
       
  2481 
       
  2482   DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
       
  2483   
       
  2484   call_id = dbus_g_proxy_begin_call_internal (proxy, method, notify, user_data, destroy, arg_values,-1);
       
  2485 
       
  2486   g_value_array_free (arg_values);
       
  2487 
       
  2488   va_end (args);
       
  2489 
       
  2490   return DBUS_G_PROXY_ID_TO_CALL (call_id);
       
  2491 }
       
  2492 
       
  2493 /**
       
  2494  * dbus_g_proxy_begin_call_with_timeout:
       
  2495  * @proxy: a proxy for a remote interface
       
  2496  * @method: the name of the method to invoke
       
  2497  * @notify: callback to be invoked when method returns
       
  2498  * @user_data: user data passed to callback
       
  2499  * @destroy: function called to destroy user_data
       
  2500  * @timeout: specify the timeout in milliseconds
       
  2501  * @first_arg_type: type of the first argument
       
  2502  *
       
  2503  * Asynchronously invokes a method on a remote interface. The method
       
  2504  * call will not be sent over the wire until the application returns
       
  2505  * to the main loop, or blocks in dbus_connection_flush() to write out
       
  2506  * pending data.  The call will be completed after a timeout, or when
       
  2507  * a reply is received.  When the call returns, the callback specified
       
  2508  * will be invoked; you can then collect the results of the call
       
  2509  * (which may be an error, or a reply), use dbus_g_proxy_end_call().
       
  2510  *
       
  2511  * TODO this particular function shouldn't die on out of memory,
       
  2512  * since you should be able to do a call with large arguments.
       
  2513  *
       
  2514  * Returns: call identifier.
       
  2515  */
       
  2516  	#ifdef __SYMBIAN32__
       
  2517 	EXPORT_C
       
  2518 	#endif
       
  2519 DBusGProxyCall *
       
  2520 dbus_g_proxy_begin_call_with_timeout (DBusGProxy          *proxy,
       
  2521                          const char          *method,
       
  2522                          DBusGProxyCallNotify notify,
       
  2523                          gpointer             user_data,
       
  2524                          GDestroyNotify       destroy,
       
  2525 			 int timeout,
       
  2526                          GType                first_arg_type,
       
  2527                          ...)
       
  2528 {
       
  2529   guint call_id;
       
  2530   va_list args;
       
  2531   GValueArray *arg_values;
       
  2532 
       
  2533   g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
       
  2534   g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
       
  2535 
       
  2536   va_start (args, first_arg_type);
       
  2537 
       
  2538   DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
       
  2539 
       
  2540   call_id = dbus_g_proxy_begin_call_internal (proxy, method, notify, user_data, destroy, arg_values,timeout);
       
  2541 
       
  2542   g_value_array_free (arg_values);
       
  2543 
       
  2544   va_end (args);
       
  2545 
       
  2546   return DBUS_G_PROXY_ID_TO_CALL (call_id);
       
  2547 }
       
  2548 
       
  2549 /**
       
  2550  * dbus_g_proxy_end_call:
       
  2551  * @proxy: a proxy for a remote interface
       
  2552  * @call: the pending call ID from dbus_g_proxy_begin_call()
       
  2553  * @error: return location for an error
       
  2554  * @first_arg_type: type of first "out" argument
       
  2555  *
       
  2556  * Collects the results of a method call. The method call was normally
       
  2557  * initiated with dbus_g_proxy_end_call(). You may use this function
       
  2558  * outside of the callback given to dbus_g_proxy_begin_call; in that
       
  2559  * case this function will block if the results haven't yet been
       
  2560  * received.
       
  2561  *
       
  2562  * If the call results in an error, the error is set as normal for
       
  2563  * GError and the function returns #FALSE.
       
  2564  *
       
  2565  * Otherwise, the "out" parameters and return value of the
       
  2566  * method are stored in the provided varargs list.
       
  2567  * The list should be terminated with G_TYPE_INVALID.
       
  2568  *
       
  2569  * Returns: #FALSE if an error is set.
       
  2570  */
       
  2571  	#ifdef __SYMBIAN32__
       
  2572 	EXPORT_C
       
  2573 	#endif
       
  2574 gboolean
       
  2575 dbus_g_proxy_end_call (DBusGProxy          *proxy,
       
  2576                        DBusGProxyCall      *call,
       
  2577                        GError             **error,
       
  2578                        GType                first_arg_type,
       
  2579                        ...)
       
  2580 {
       
  2581   gboolean ret;
       
  2582   va_list args;
       
  2583 
       
  2584   va_start (args, first_arg_type);
       
  2585 
       
  2586   ret = dbus_g_proxy_end_call_internal (proxy, GPOINTER_TO_UINT (call), error, first_arg_type, args);
       
  2587 
       
  2588   va_end (args);
       
  2589   
       
  2590   return ret;
       
  2591 }
       
  2592 
       
  2593 /**
       
  2594  * dbus_g_proxy_call:
       
  2595  * @proxy: a proxy for a remote interface
       
  2596  * @method: method to invoke
       
  2597  * @error: return location for an error
       
  2598  * @first_arg_type: type of first "in" argument
       
  2599  *
       
  2600  * Function for synchronously invoking a method and receiving reply
       
  2601  * values.  This function is equivalent to dbus_g_proxy_begin_call
       
  2602  * followed by dbus_g_proxy_end_call.  All of the input arguments are
       
  2603  * specified first, followed by G_TYPE_INVALID, followed by all of the
       
  2604  * output values, followed by a second G_TYPE_INVALID.  Note that  
       
  2605  * this means you must always specify G_TYPE_INVALID twice.
       
  2606  *
       
  2607  * Returns: #FALSE if an error is set, #TRUE otherwise.
       
  2608  */
       
  2609  	#ifdef __SYMBIAN32__
       
  2610 	EXPORT_C
       
  2611 	#endif
       
  2612 gboolean
       
  2613 dbus_g_proxy_call (DBusGProxy        *proxy,
       
  2614 		   const char        *method,
       
  2615 		   GError           **error,
       
  2616 		   GType              first_arg_type,
       
  2617 		   ...)
       
  2618 {
       
  2619   gboolean ret;
       
  2620   guint call_id;
       
  2621   va_list args;
       
  2622   GValueArray *in_args;
       
  2623 
       
  2624   g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE);
       
  2625   g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE);
       
  2626 
       
  2627   va_start (args, first_arg_type);
       
  2628 
       
  2629   DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
       
  2630 
       
  2631   call_id = dbus_g_proxy_begin_call_internal (proxy, method, NULL, NULL, NULL, in_args,-1);
       
  2632 
       
  2633   g_value_array_free (in_args);
       
  2634 
       
  2635   first_arg_type = va_arg (args, GType);
       
  2636   ret = dbus_g_proxy_end_call_internal (proxy, call_id, error, first_arg_type, args);
       
  2637 
       
  2638   va_end (args);
       
  2639 
       
  2640   return ret;
       
  2641 }
       
  2642 
       
  2643 /**
       
  2644  * dbus_g_proxy_call_with_timeout:
       
  2645  * @proxy: a proxy for a remote interface
       
  2646  * @method: method to invoke
       
  2647  * @timeout: specify the timeout in milliseconds
       
  2648  * @error: return location for an error
       
  2649  * @first_arg_type: type of first "in" argument
       
  2650  *
       
  2651  * Function for synchronously invoking a method and receiving reply
       
  2652  * values.  This function is equivalent to dbus_g_proxy_begin_call
       
  2653  * followed by dbus_g_proxy_end_call.  All of the input arguments are
       
  2654  * specified first, followed by G_TYPE_INVALID, followed by all of the
       
  2655  * output values, followed by a second G_TYPE_INVALID.  Note that
       
  2656  * this means you must always specify G_TYPE_INVALID twice.
       
  2657  *
       
  2658  * Returns: #FALSE if an error is set, #TRUE otherwise.
       
  2659  */
       
  2660  	#ifdef __SYMBIAN32__
       
  2661 	EXPORT_C
       
  2662 	#endif
       
  2663 gboolean
       
  2664 dbus_g_proxy_call_with_timeout (DBusGProxy        *proxy,
       
  2665                    const char        *method,
       
  2666 		   int timeout,
       
  2667                    GError           **error,
       
  2668                    GType              first_arg_type,
       
  2669                    ...)
       
  2670 {
       
  2671   gboolean ret;
       
  2672   guint call_id;
       
  2673   va_list args;
       
  2674   GValueArray *in_args;
       
  2675 
       
  2676   g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE);
       
  2677   g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE);
       
  2678 
       
  2679   va_start (args, first_arg_type);
       
  2680 
       
  2681   DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
       
  2682 
       
  2683   call_id = dbus_g_proxy_begin_call_internal (proxy, method, NULL, NULL, NULL, in_args,timeout);
       
  2684 
       
  2685   g_value_array_free (in_args);
       
  2686 
       
  2687   first_arg_type = va_arg (args, GType);
       
  2688   ret = dbus_g_proxy_end_call_internal (proxy, call_id, error, first_arg_type, args);
       
  2689 
       
  2690   va_end (args);
       
  2691 
       
  2692   return ret;
       
  2693 }
       
  2694 
       
  2695 /**
       
  2696  * dbus_g_proxy_call_no_reply:
       
  2697  * @proxy: a proxy for a remote interface
       
  2698  * @method: the name of the method to invoke
       
  2699  * @first_arg_type: type of the first argument
       
  2700  *
       
  2701  * Sends a method call message as with dbus_g_proxy_begin_call(), but
       
  2702  * does not ask for a reply or allow you to receive one.
       
  2703  *
       
  2704  * TODO: this particular function shouldn't die on out of memory,
       
  2705  * since you should be able to do a call with large arguments.
       
  2706  */
       
  2707  	#ifdef __SYMBIAN32__
       
  2708 	EXPORT_C
       
  2709 	#endif
       
  2710 void
       
  2711 dbus_g_proxy_call_no_reply (DBusGProxy               *proxy,
       
  2712 			    const char               *method,
       
  2713 			    GType                     first_arg_type,
       
  2714 			    ...)
       
  2715 {
       
  2716   DBusMessage *message;
       
  2717   va_list args;
       
  2718   GValueArray *in_args;
       
  2719   DBusGProxyPrivate *priv;
       
  2720   
       
  2721   g_return_if_fail (DBUS_IS_G_PROXY (proxy));
       
  2722   g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
       
  2723 
       
  2724   priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  2725 
       
  2726   va_start (args, first_arg_type);
       
  2727   DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
       
  2728 
       
  2729   message = dbus_g_proxy_marshal_args_to_message (proxy, method, in_args);
       
  2730 
       
  2731   g_value_array_free (in_args);
       
  2732   va_end (args);
       
  2733 
       
  2734   if (!message)
       
  2735     goto oom;
       
  2736 
       
  2737   dbus_message_set_no_reply (message, TRUE);
       
  2738 
       
  2739   if (!dbus_connection_send (priv->manager->connection,
       
  2740                              message,
       
  2741                              NULL))
       
  2742     goto oom;
       
  2743   dbus_message_unref (message);
       
  2744   return;
       
  2745   
       
  2746  oom:
       
  2747   g_error ("Out of memory");
       
  2748 }
       
  2749 
       
  2750 /**
       
  2751  * dbus_g_proxy_cancel_call
       
  2752  * @proxy: a proxy for a remote interface
       
  2753  * @call: the pending call ID from dbus_g_proxy_begin_call()
       
  2754  *
       
  2755  * Cancels a pending method call. The method call was normally
       
  2756  * initiated with dbus_g_proxy_begin_call().  This function
       
  2757  * may not be used on pending calls that have already been
       
  2758  * ended with dbus_g_proxy_end_call.
       
  2759  */
       
  2760  	#ifdef __SYMBIAN32__
       
  2761 	EXPORT_C
       
  2762 	#endif
       
  2763 void
       
  2764 dbus_g_proxy_cancel_call (DBusGProxy        *proxy,
       
  2765 			  DBusGProxyCall    *call)
       
  2766 {
       
  2767   guint call_id;
       
  2768   DBusPendingCall *pending;
       
  2769   DBusGProxyPrivate *priv;
       
  2770   
       
  2771   g_return_if_fail (DBUS_IS_G_PROXY (proxy));
       
  2772   g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
       
  2773 
       
  2774   priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  2775 
       
  2776   call_id = DBUS_G_PROXY_CALL_TO_ID (call);
       
  2777 
       
  2778   pending = g_hash_table_lookup (priv->pending_calls, GUINT_TO_POINTER (call_id));
       
  2779   g_return_if_fail (pending != NULL);
       
  2780 
       
  2781   dbus_pending_call_cancel (pending);
       
  2782 
       
  2783   g_hash_table_remove (priv->pending_calls, GUINT_TO_POINTER (call_id));
       
  2784 }
       
  2785 
       
  2786 /**
       
  2787  * dbus_g_proxy_send:
       
  2788  * @proxy: a proxy for a remote interface
       
  2789  * @message: the message to address and send
       
  2790  * @client_serial: return location for message's serial, or #NULL 
       
  2791  *
       
  2792  * Sends a message to the interface we're proxying for.  Does not
       
  2793  * block or wait for a reply. The message is only actually written out
       
  2794  * when you return to the main loop or block in
       
  2795  * dbus_connection_flush().
       
  2796  *
       
  2797  * The message is modified to be addressed to the target interface.
       
  2798  * That is, a destination name field or whatever is needed will be
       
  2799  * added to the message. The basic point of this function is to add
       
  2800  * the necessary header fields, otherwise it's equivalent to
       
  2801  * dbus_connection_send().
       
  2802  *
       
  2803  * This function adds a reference to the message, so the caller
       
  2804  * still owns its original reference.
       
  2805  */
       
  2806  	#ifdef __SYMBIAN32__
       
  2807 	EXPORT_C
       
  2808 	#endif
       
  2809 void
       
  2810 dbus_g_proxy_send (DBusGProxy          *proxy,
       
  2811                    DBusMessage         *message,
       
  2812                    dbus_uint32_t       *client_serial)
       
  2813 {
       
  2814   DBusGProxyPrivate *priv;
       
  2815   
       
  2816   g_return_if_fail (DBUS_IS_G_PROXY (proxy));
       
  2817   g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
       
  2818   
       
  2819   priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  2820   
       
  2821   if (priv->name)
       
  2822     {
       
  2823       if (!dbus_message_set_destination (message, priv->name))
       
  2824         g_error ("Out of memory");
       
  2825     }
       
  2826   if (priv->path)
       
  2827     {
       
  2828       if (!dbus_message_set_path (message, priv->path))
       
  2829         g_error ("Out of memory");
       
  2830     }
       
  2831   if (priv->interface)
       
  2832     {
       
  2833       if (!dbus_message_set_interface (message, priv->interface))
       
  2834         g_error ("Out of memory");
       
  2835     }
       
  2836   
       
  2837   if (!dbus_connection_send (priv->manager->connection, message, client_serial))
       
  2838     g_error ("Out of memory\n");
       
  2839 }
       
  2840 
       
  2841 static void
       
  2842 array_free_all (gpointer array)
       
  2843 {
       
  2844   g_array_free (array, TRUE);
       
  2845 }
       
  2846 
       
  2847 /**
       
  2848  * dbus_g_proxy_add_signal:
       
  2849  * @proxy: the proxy for a remote interface
       
  2850  * @signal_name: the name of the signal
       
  2851  * @first_type: the first argument type, or G_TYPE_INVALID if none
       
  2852  *
       
  2853  * Specifies the argument signature of a signal;.only necessary
       
  2854  * if the remote object does not support introspection.  The arguments
       
  2855  * specified are the GLib types expected.
       
  2856  */
       
  2857  	#ifdef __SYMBIAN32__
       
  2858 	EXPORT_C
       
  2859 	#endif
       
  2860 void
       
  2861 dbus_g_proxy_add_signal  (DBusGProxy        *proxy,
       
  2862                           const char        *signal_name,
       
  2863 			  GType              first_type,
       
  2864                           ...)
       
  2865 {
       
  2866   GQuark q;
       
  2867   char *name;
       
  2868   GArray *gtypesig;
       
  2869   GType gtype;
       
  2870   va_list args;
       
  2871   DBusGProxyPrivate *priv;
       
  2872 
       
  2873   g_return_if_fail (DBUS_IS_G_PROXY (proxy));
       
  2874   g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
       
  2875   g_return_if_fail (signal_name != NULL);
       
  2876   
       
  2877   priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  2878 
       
  2879   name = create_signal_name (priv->interface, signal_name);
       
  2880   
       
  2881   q = g_quark_from_string (name);
       
  2882   
       
  2883   g_return_if_fail (g_datalist_id_get_data (&priv->signal_signatures, q) == NULL);
       
  2884 
       
  2885   gtypesig = g_array_new (FALSE, TRUE, sizeof (GType));
       
  2886 
       
  2887   va_start (args, first_type);
       
  2888   gtype = first_type;
       
  2889   while (gtype != G_TYPE_INVALID)
       
  2890     {
       
  2891       g_array_append_val (gtypesig, gtype);
       
  2892       gtype = va_arg (args, GType);
       
  2893     }
       
  2894   va_end (args);
       
  2895 
       
  2896 #ifndef G_DISABLE_CHECKS
       
  2897   if (_dbus_gobject_lookup_marshaller (G_TYPE_NONE, gtypesig->len, (const GType*) gtypesig->data) == NULL)
       
  2898     g_warning ("No marshaller for signature of signal '%s'", signal_name);
       
  2899 #endif
       
  2900 
       
  2901   
       
  2902   g_datalist_id_set_data_full (&priv->signal_signatures,
       
  2903                                q, gtypesig,
       
  2904                                array_free_all);
       
  2905 
       
  2906   g_free (name);
       
  2907 }
       
  2908 
       
  2909 /**
       
  2910  * dbus_g_proxy_connect_signal:
       
  2911  * @proxy: a proxy for a remote interface
       
  2912  * @signal_name: the DBus signal name to listen for
       
  2913  * @handler: the handler to connect
       
  2914  * @data: data to pass to handler
       
  2915  * @free_data_func: callback function to destroy data
       
  2916  *
       
  2917  * Connect a signal handler to a proxy for a remote interface.  When
       
  2918  * the remote interface emits the specified signal, the proxy will
       
  2919  * emit a corresponding GLib signal.
       
  2920  */
       
  2921  	#ifdef __SYMBIAN32__
       
  2922 	EXPORT_C
       
  2923 	#endif
       
  2924 void
       
  2925 dbus_g_proxy_connect_signal (DBusGProxy             *proxy,
       
  2926                              const char             *signal_name,
       
  2927                              GCallback               handler,
       
  2928                              void                   *data,
       
  2929                              GClosureNotify          free_data_func)
       
  2930 {
       
  2931   char *name;
       
  2932   GClosure *closure;
       
  2933   GQuark q;
       
  2934   DBusGProxyPrivate *priv;
       
  2935 
       
  2936   g_return_if_fail (DBUS_IS_G_PROXY (proxy));
       
  2937   g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
       
  2938   g_return_if_fail (signal_name != NULL);
       
  2939   g_return_if_fail (handler != NULL);
       
  2940   
       
  2941   priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  2942   name = create_signal_name (priv->interface, signal_name);
       
  2943 
       
  2944   q = g_quark_try_string (name);
       
  2945 
       
  2946 #ifndef G_DISABLE_CHECKS
       
  2947   if (q == 0 || g_datalist_id_get_data (&priv->signal_signatures, q) == NULL)
       
  2948     {
       
  2949       g_warning ("Must add the signal '%s' with dbus_g_proxy_add_signal() prior to connecting to it\n", name);
       
  2950       g_free (name);
       
  2951       return;
       
  2952     }
       
  2953 #endif
       
  2954   
       
  2955   closure = g_cclosure_new (G_CALLBACK (handler), data, free_data_func);
       
  2956   
       
  2957   g_signal_connect_closure_by_id (G_OBJECT (proxy),
       
  2958                                   signals[RECEIVED],
       
  2959                                   q,
       
  2960                                   closure, FALSE);
       
  2961   
       
  2962   g_free (name);
       
  2963 }
       
  2964 
       
  2965 /**
       
  2966  * dbus_g_proxy_disconnect_signal:
       
  2967  * @proxy: a proxy for a remote interface
       
  2968  * @signal_name: the DBus signal name to disconnect
       
  2969  * @handler: the handler to disconnect
       
  2970  * @data: the data that was registered with handler
       
  2971  *
       
  2972  * Disconnect all signal handlers from a proxy that match the given
       
  2973  * criteria.
       
  2974  */
       
  2975  	#ifdef __SYMBIAN32__
       
  2976 	EXPORT_C
       
  2977 	#endif
       
  2978 void
       
  2979 dbus_g_proxy_disconnect_signal (DBusGProxy             *proxy,
       
  2980                                 const char             *signal_name,
       
  2981                                 GCallback               handler,
       
  2982                                 void                   *data)
       
  2983 {
       
  2984   char *name;
       
  2985   GQuark q;
       
  2986   DBusGProxyPrivate *priv;
       
  2987   
       
  2988   g_return_if_fail (DBUS_IS_G_PROXY (proxy));
       
  2989   g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
       
  2990   g_return_if_fail (signal_name != NULL);
       
  2991   g_return_if_fail (handler != NULL);
       
  2992 
       
  2993   priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
       
  2994   name = create_signal_name (priv->interface, signal_name);
       
  2995 
       
  2996   q = g_quark_try_string (name);
       
  2997   
       
  2998   if (q != 0)
       
  2999     {
       
  3000       g_signal_handlers_disconnect_matched (G_OBJECT (proxy),
       
  3001                                             G_SIGNAL_MATCH_DETAIL |
       
  3002                                             G_SIGNAL_MATCH_FUNC   |
       
  3003                                             G_SIGNAL_MATCH_DATA,
       
  3004                                             signals[RECEIVED],
       
  3005                                             q,
       
  3006                                             NULL,
       
  3007                                             #ifdef WINSCW
       
  3008                                             G_CALLBACK (handler), data);
       
  3009                                             #else
       
  3010                                             (gpointer)(handler), data);
       
  3011                                             #endif
       
  3012     }
       
  3013   else
       
  3014     {
       
  3015       g_warning ("Attempt to disconnect from signal '%s' which is not registered\n",
       
  3016                  name);
       
  3017     }
       
  3018 
       
  3019   g_free (name);
       
  3020 }
       
  3021 
       
  3022 /** @} End of DBusGLib public */
       
  3023 
       
  3024 #ifdef DBUS_BUILD_TESTS
       
  3025 
       
  3026 /**
       
  3027  * @ingroup DBusGLibInternals
       
  3028  * Unit test for GLib proxy functions
       
  3029  * Returns: #TRUE on success.
       
  3030  */
       
  3031 gboolean
       
  3032 _dbus_g_proxy_test (void)
       
  3033 {
       
  3034   
       
  3035   
       
  3036   return TRUE;
       
  3037 }
       
  3038 
       
  3039 #endif /* DBUS_BUILD_TESTS */