diff -purN a/dbus/dbus-binding-tool-glib.c b/dbus/dbus-binding-tool-glib.c
--- a/dbus/dbus-binding-tool-glib.c	2010-08-13 10:02:50.769451000 +0200
+++ b/dbus/dbus-binding-tool-glib.c	2010-08-13 10:03:08.687972000 +0200
@@ -38,6 +38,10 @@
 #include <string.h>
 #include <unistd.h>
 
+/* Remember to grep for ->format_version in the code if you change this,
+ * most changes should be in dbus-gobject.c. */
+#define FORMAT_VERSION 1
+
 #define MARSHAL_PREFIX "dbus_glib_marshal_"
 
 typedef struct
@@ -489,10 +493,9 @@ generate_glue (BaseInfo *base, DBusBindi
 
       /* Information about the object. */
 
-      if (!write_printf_to_iochannel ("const DBusGObjectInfo dbus_glib_%s_object_info = {\n",
-				      channel, error, data->prefix))
-	goto io_lose;
-      WRITE_OR_LOSE ("  0,\n");
+      if (!write_printf_to_iochannel ("const DBusGObjectInfo dbus_glib_%s_object_info = {  %d,\n",
+                                  channel, error, data->prefix, FORMAT_VERSION))
+        goto io_lose;
       if (!write_printf_to_iochannel ("  dbus_glib_%s_methods,\n", channel, error, data->prefix))
 	goto io_lose;
       if (!write_printf_to_iochannel ("  %d,\n", channel, error, data->count))
@@ -736,13 +739,36 @@ generate_glue (BaseInfo *base, DBusBindi
       for (tmp = properties; tmp != NULL; tmp = g_slist_next (tmp))
         {
           PropertyInfo *prop;
-	  
-	  prop = tmp->data;
+          PropertyAccessFlags access_flags;
+          const char *access_string;
+          char *uscored;
+
+          prop = tmp->data;
+
+          access_flags = property_info_get_access (prop);
+          if ((access_flags & PROPERTY_READ) && (access_flags & PROPERTY_WRITE))
+            access_string = "readwrite";
+          else if (access_flags & PROPERTY_READ)
+            access_string = "read";
+          else if (access_flags & PROPERTY_WRITE)
+            access_string = "write";
+          else
+            continue;
+
+          /* We append both in the blob so we have to malloc() less when processing
+           * properties */
+          uscored = _dbus_gutils_wincaps_to_uscore (property_info_get_name (prop));
+
+          g_string_append (data->property_blob, interface_info_get_name (interface));
+          g_string_append_c (data->property_blob, '\0');
+          g_string_append (data->property_blob, property_info_get_name (prop));
+          g_string_append_c (data->property_blob, '\0');
+          g_string_append (data->property_blob, uscored);
+          g_string_append_c (data->property_blob, '\0');
+          g_string_append (data->property_blob, access_string);
+          g_string_append_c (data->property_blob, '\0');
 
-	  g_string_append (data->property_blob, interface_info_get_name (interface));
-	  g_string_append_c (data->property_blob, '\0');
-	  g_string_append (data->property_blob, property_info_get_name (prop));
-	  g_string_append_c (data->property_blob, '\0');
+          g_free (uscored);
 	}
     }
   return TRUE;
diff -purN a/dbus/dbus-glib.h b/dbus/dbus-glib.h
--- a/dbus/dbus-glib.h	2010-08-13 10:02:50.948464000 +0200
+++ b/dbus/dbus-glib.h	2010-08-13 10:03:08.714008000 +0200
@@ -150,6 +150,8 @@ struct _DBusGObjectInfo
   const char *exported_properties; 
 };
 
+void       dbus_glib_global_set_disable_legacy_property_access (void);
+
 void       dbus_g_object_type_install_info     (GType                 object_type,
                                                 const DBusGObjectInfo *info);
 
diff -purN a/dbus/dbus-gobject.c b/dbus/dbus-gobject.c
--- a/dbus/dbus-gobject.c	2010-08-13 10:02:50.736463000 +0200
+++ b/dbus/dbus-gobject.c	2010-08-13 10:03:08.748979000 +0200
@@ -42,9 +42,28 @@ typedef struct
 } DBusGErrorInfo;
 
 static GStaticRWLock globals_lock = G_STATIC_RW_LOCK_INIT;
+/* See comments in check_property_access */
+static gboolean disable_legacy_property_access = FALSE;
 static GHashTable *marshal_table = NULL;
 static GData *error_metadata = NULL;
 
+/* Ugly yes - but we have to accept strings from both formats */
+static gboolean
+compare_strings_ignoring_uscore_vs_dash (const char *a, const char *b)
+{
+  guint i;
+
+  for (i = 0; a[i] && b[i]; i++)
+    {
+      if ((a[i] == '-' && b[i] == '_')
+          || (a[i] == '_' && b[i] == '-'))
+        continue;
+      if (a[i] != b[i])
+        return FALSE;
+    }
+  return (a[i] == '\0') && (b[i] == '\0');
+}
+
 static char*
 uscore_to_wincaps (const char *uscore)
 {
@@ -270,7 +289,7 @@ method_output_signature_from_object_info
 }
 
 static const char *
-propsig_iterate (const char *data, const char **iface, const char **name)
+signal_iterate (const char *data, const char **iface, const char **name)
 {
   *iface = data;
 
@@ -280,6 +299,108 @@ propsig_iterate (const char *data, const
   return string_table_next (data);
 }
 
+static const char *
+property_iterate (const char  *data,
+                  int          format_version,
+                  const char **iface,
+                  const char **exported_name,
+                  const char **name_uscored,
+                  const char **access_type)
+{
+  *iface = data;
+
+  data = string_table_next (data);
+  *exported_name = data;
+
+  data = string_table_next (data);
+  if (format_version == 1)
+    {
+      *name_uscored = data;
+      data = string_table_next (data);
+      *access_type = data;
+      return string_table_next (data);
+    }
+  else
+    {
+      /* This tells the caller they need to compute it */
+      *name_uscored = NULL;
+      /* We don't know here, however note that we will still check against the
+       * readable/writable flags from GObject's metadata.
+       */
+      *access_type = "readwrite";
+      return data;
+    }
+}
+
+/**
+ * property_info_from_object_info:
+ * @object: introspection data
+ * @interface_name: (allow-none): Expected interface name, or %NULL for any
+ * @property_name: Expected property name (can use "-" or "_" as separator)
+ * @access_type: (out): Can be one of "read", "write", "readwrite"
+ *
+ * Look up property introspection data for the given interface/name pair.
+ *
+ * Returns: %TRUE if property was found
+ */
+static gboolean
+property_info_from_object_info (const DBusGObjectInfo  *object,
+                                const char             *interface_name,
+                                const char             *property_name,
+                                const char            **access_type)
+{
+  const char *properties_iter;
+
+  properties_iter = object->exported_properties;
+  while (properties_iter != NULL && *properties_iter)
+    {
+      const char *cur_interface_name;
+      const char *cur_property_name;
+      const char *cur_uscore_property_name;
+      const char *cur_access_type;
+
+
+      properties_iter = property_iterate (properties_iter, object->format_version,
+                                          &cur_interface_name, &cur_property_name,
+                                          &cur_uscore_property_name, &cur_access_type);
+
+      if (interface_name && strcmp (interface_name, cur_interface_name) != 0)
+        continue;
+
+      /* This big pile of ugly is necessary to support the matrix resulting from multiplying
+       * (v0 data, v1 data) * (FooBar, foo-bar)
+       * In v1 data we have both forms of string, so we do a comparison against both without
+       * having to malloc.
+       * For v0 data, we need to reconstruct the foo-bar form.
+       *
+       * Adding to the complexity is that we *also* have to ignore the distinction between
+       * '-' and '_', because g_object_{get,set} does.
+       */
+      /* First, compare against the primary property name - no malloc required */
+      if (!compare_strings_ignoring_uscore_vs_dash (property_name, cur_property_name))
+        {
+          if (cur_uscore_property_name != NULL
+              && !compare_strings_ignoring_uscore_vs_dash (property_name, cur_uscore_property_name))
+            continue;
+          else
+            {
+              /* v0 metadata, construct uscore */
+              char *tmp_uscored;
+              gboolean matches;
+              tmp_uscored = _dbus_gutils_wincaps_to_uscore (cur_property_name);
+              matches = compare_strings_ignoring_uscore_vs_dash (property_name, tmp_uscored);
+              g_free (tmp_uscored);
+              if (!matches)
+                continue;
+            }
+        }
+
+      *access_type = cur_access_type;
+      return TRUE;
+    }
+  return FALSE;
+}
+
 static GQuark
 dbus_g_object_type_dbus_metadata_quark (void)
 {
@@ -290,11 +411,17 @@ dbus_g_object_type_dbus_metadata_quark (
   return quark;
 }
 
-static GList *
-lookup_object_info (GObject *object)
+/* Iterator function should return FALSE to stop iteration, TRUE to continue */
+typedef gboolean (*ForeachObjectInfoFn) (const DBusGObjectInfo *info,
+                                         GType                 gtype,
+                                         gpointer              user_data);
+
+static void
+foreach_object_info (GObject *object,
+		     ForeachObjectInfoFn callback,
+		     gpointer user_data)
 {
   GType *interfaces, *p;
-  GList *info_list = NULL;
   const DBusGObjectInfo *info;
   GType classtype;
 
@@ -304,7 +431,10 @@ lookup_object_info (GObject *object)
     {
       info = g_type_get_qdata (*p, dbus_g_object_type_dbus_metadata_quark ());
       if (info != NULL && info->format_version >= 0)
-          info_list = g_list_prepend (info_list, (gpointer) info);
+        {
+	  if (!callback (info, *p, user_data))
+	    break;
+	}
     }
 
   g_free (interfaces);
@@ -313,16 +443,85 @@ lookup_object_info (GObject *object)
     {
       info = g_type_get_qdata (classtype, dbus_g_object_type_dbus_metadata_quark ());
       if (info != NULL && info->format_version >= 0)
-          info_list = g_list_prepend (info_list, (gpointer) info);
+	{
+	  if (!callback (info, classtype, user_data))
+	    break;
+	}
     }
 
-  /* if needed only:
-  return g_list_reverse (info_list);
-  */
-  
+}
+
+static gboolean
+lookup_object_info_cb (const DBusGObjectInfo *info,
+                       GType gtype,
+		       gpointer user_data)
+{
+  GList **list = (GList **) user_data;
+
+  *list = g_list_prepend (*list, (gpointer) info);
+  return TRUE;
+}
+
+static GList *
+lookup_object_info (GObject *object)
+{
+  GList *info_list = NULL;
+
+  foreach_object_info (object, lookup_object_info_cb, &info_list);
+
   return info_list;
 }
 
+typedef struct {
+  const char *iface;
+  const DBusGObjectInfo *info;
+  gboolean fallback;
+  GType iface_type;
+} LookupObjectInfoByIfaceData;
+
+static gboolean
+lookup_object_info_by_iface_cb (const DBusGObjectInfo *info,
+				GType gtype,
+				gpointer user_data)
+{
+  LookupObjectInfoByIfaceData *lookup_data = (LookupObjectInfoByIfaceData *) user_data;
+
+  /* If interface is not specified, choose the first info */
+  if (lookup_data->fallback && (!lookup_data->iface || strlen (lookup_data->iface) == 0))
+    {
+      lookup_data->info = info;
+      lookup_data->iface_type = gtype;
+    }
+  else if (info->exported_properties && !strcmp (info->exported_properties, lookup_data->iface))
+    {
+      lookup_data->info = info;
+      lookup_data->iface_type = gtype;
+    }
+
+  return !lookup_data->info;
+}
+
+static const DBusGObjectInfo *
+lookup_object_info_by_iface (GObject     *object,
+			     const char  *iface,
+			     gboolean     fallback,
+			     GType       *out_iface_type)
+{
+  LookupObjectInfoByIfaceData data;
+
+  data.iface = iface;
+  data.info = NULL;
+  data.fallback = fallback;
+  data.iface_type = 0;
+
+  foreach_object_info (object, lookup_object_info_by_iface_cb, &data);
+
+  if (out_iface_type && data.info)
+    *out_iface_type = data.iface_type;
+
+  return data.info;
+}
+
 static void
 gobject_unregister_function (DBusConnection  *connection,
                              void            *user_data)
@@ -443,30 +642,41 @@ write_interface (gpointer key, gpointer 
 
   for (; properties; properties = properties->next)
     {
+      const char *iface;
       const char *propname;
+      const char *propname_uscore;
+      const char *access_type;
       GParamSpec *spec;
       char *dbus_type;
       gboolean can_set;
       gboolean can_get;
       char *s;
 
-      propname = properties->data;
       spec = NULL;
 
-      s = _dbus_gutils_wincaps_to_uscore (propname);
+      property_iterate (properties->data, object_info->format_version, &iface, &propname, &propname_uscore, &access_type);
 
-      spec = g_object_class_find_property (g_type_class_peek (data->gtype), s);
+      if (!propname_uscore)
+        {
+          char *s = _dbus_gutils_wincaps_to_uscore (propname);
+          spec = g_object_class_find_property (g_type_class_peek (data->gtype), s);
+          g_free (s);
+        }
+      else
+        {
+          spec =  g_object_class_find_property (g_type_class_peek (data->gtype), propname_uscore);
+        }
       g_assert (spec != NULL);
-      g_free (s);
-      
+
       dbus_type = _dbus_gtype_to_signature (G_PARAM_SPEC_VALUE_TYPE (spec));
       g_assert (dbus_type != NULL);
-      
-      can_set = ((spec->flags & G_PARAM_WRITABLE) != 0 &&
-		 (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
-      
+
+      can_set = strcmp (access_type, "readwrite") == 0
+                    && ((spec->flags & G_PARAM_WRITABLE) != 0
+                    && (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
+
       can_get = (spec->flags & G_PARAM_READABLE) != 0;
-      
+
       if (can_set || can_get)
 	{
 	  g_string_append_printf (xml, "    <property name=\"%s\" ", propname);
@@ -554,7 +764,7 @@ introspect_interfaces (GObject *object, 
           const char *iface;
           const char *signame;
 
-          propsig = propsig_iterate (propsig, &iface, &signame);
+          propsig = signal_iterate (propsig, &iface, &signame);
 
           values = lookup_values (interfaces, iface);
           values->signals = g_slist_prepend (values->signals, (gpointer) signame);
@@ -565,13 +775,15 @@ introspect_interfaces (GObject *object, 
         {
           const char *iface;
           const char *propname;
+          const char *propname_uscore;
+          const char *access_type;
 
-          propsig = propsig_iterate (propsig, &iface, &propname);
+          propsig = property_iterate (propsig, info->format_version, &iface, &propname, &propname_uscore, &access_type);
 
           values = lookup_values (interfaces, iface);
-          values->properties = g_slist_prepend (values->properties, (gpointer) propname);
+          values->properties = g_slist_prepend (values->properties, (gpointer)iface);
         }
-      
+
       memset (&data, 0, sizeof (data));
       data.xml = xml;
       data.gtype = G_TYPE_FROM_INSTANCE (object);
@@ -1403,6 +1615,70 @@ invoke_object_method (GObject         *o
   goto done;
 }
 
+static gboolean
+check_property_access (DBusConnection  *connection,
+                       DBusMessage     *message,
+                       GObject         *object,
+                       const char      *wincaps_propiface,
+                       const char      *requested_propname,
+                       const char      *uscore_propname,
+                       gboolean         is_set)
+{
+  const DBusGObjectInfo *object_info;
+  const char *access_type;
+  DBusMessage *ret;
+
+  if (!is_set && !disable_legacy_property_access)
+    return TRUE;
+
+  object_info = lookup_object_info_by_iface (object, wincaps_propiface, TRUE, NULL);
+  if (!object_info)
+    {
+      ret = dbus_message_new_error_printf (message,
+                                           DBUS_ERROR_ACCESS_DENIED,
+                                           "Interface \"%s\" isn't exported (or may not exist), can't access property \"%s\"",
+                                           wincaps_propiface,
+                                           requested_propname);
+      dbus_connection_send (connection, ret, NULL);
+      dbus_message_unref (ret);
+      return FALSE;
+    }
+
+  /* Try both forms of property names: "foo_bar" or "FooBar"; for historical
+   * reasons we accept both.
+   */
+  if (object_info
+      && !(property_info_from_object_info (object_info, wincaps_propiface, requested_propname, &access_type)
+           || property_info_from_object_info (object_info, wincaps_propiface, uscore_propname, &access_type)))
+    {
+      ret = dbus_message_new_error_printf (message,
+                                           DBUS_ERROR_ACCESS_DENIED,
+                                           "Property \"%s\" of interface \"%s\" isn't exported (or may not exist)",
+                                           requested_propname,
+                                           wincaps_propiface);
+      dbus_connection_send (connection, ret, NULL);
+      dbus_message_unref (ret);
+      return FALSE;
+    }
+
+  if (strcmp (access_type, "readwrite") == 0)
+    return TRUE;
+  else if (is_set ? strcmp (access_type, "read") == 0
+             : strcmp (access_type, "write") == 0)
+    {
+       ret = dbus_message_new_error_printf (message,
+                                           DBUS_ERROR_ACCESS_DENIED,
+                                           "Property \"%s\" of interface \"%s\" is not %s",
+                                           requested_propname,
+                                           wincaps_propiface,
+                                           is_set ? "settable" : "readable");
+      dbus_connection_send (connection, ret, NULL);
+      dbus_message_unref (ret);
+      return FALSE;
+    }
+  return TRUE;
+}
+
 static DBusHandlerResult
 gobject_message_function (DBusConnection  *connection,
                           DBusMessage     *message,
@@ -1414,8 +1690,8 @@ gobject_message_function (DBusConnection
   gboolean getter;
   gboolean getall;
   char *s;
-  const char *wincaps_propname;
-  /* const char *wincaps_propiface; */
+  const char *requested_propname;
+  const char *wincaps_propiface;
   DBusMessageIter iter;
   const DBusGMethodInfo *method;
   const DBusGObjectInfo *object_info;
@@ -1434,7 +1710,8 @@ gobject_message_function (DBusConnection
     return invoke_object_method (object, object_info, method, connection, message);
 
   /* If no metainfo, we can still do properties and signals
-   * via standard GLib introspection
+   * via standard GLib introspection.  Note we do now check
+   * property access against the metainfo if available.
    */
   getter = FALSE;
   setter = FALSE;
@@ -1464,10 +1741,8 @@ gobject_message_function (DBusConnection
       g_warning ("Property get or set does not have an interface string as first arg\n");
       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
     }
-  /* We never use the interface name; if we did, we'd need to
-   * remember that it can be empty string for "pick one for me"
-   */
-  /* dbus_message_iter_get_basic (&iter, &wincaps_propiface); */
+
+  dbus_message_iter_get_basic (&iter, &wincaps_propiface);
   dbus_message_iter_next (&iter);
 
   if (getall)
@@ -1484,13 +1759,19 @@ gobject_message_function (DBusConnection
           g_warning ("Property get or set does not have a property name string as second arg\n");
           return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
         }
-      dbus_message_iter_get_basic (&iter, &wincaps_propname);
+
+  dbus_message_iter_get_basic (&iter, &requested_propname);
       dbus_message_iter_next (&iter);
 
-      s = _dbus_gutils_wincaps_to_uscore (wincaps_propname);
+  s = _dbus_gutils_wincaps_to_uscore (requested_propname);
 
-      pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
-                                            s);
+  pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), s);
+
+  if (!check_property_access (connection, message, object, wincaps_propiface, requested_propname, s, setter))
+    {
+      g_free (s);
+      return DBUS_HANDLER_RESULT_HANDLED;
+    }
 
       g_free (s);
 
@@ -1526,6 +1807,16 @@ gobject_message_function (DBusConnection
                                                "No such property %s", wincaps_propname);
         }
     }
+  else
+    {
+      DBusMessage *ret;
+
+      ret = dbus_message_new_error_printf (message,
+                                           DBUS_ERROR_INVALID_ARGS,
+                                           "No such property %s", requested_propname);
+      dbus_connection_send (connection, ret, NULL);
+      dbus_message_unref (ret);
+    }
 
   g_assert (ret != NULL);
 
@@ -1651,8 +1942,8 @@ export_signals (DBusGConnection *connect
           GClosure *closure;
           char *s;
 
-          sigdata = propsig_iterate (sigdata, &iface, &signame);
-          
+          sigdata = signal_iterate (sigdata, &iface, &signame);
+
           s = _dbus_gutils_wincaps_to_uscore (signame);
 
           id = g_signal_lookup (s, gtype);
@@ -1826,6 +2117,32 @@ dbus_g_error_info_free (gpointer p)
  */
 
 /**
+ * dbus_glib_global_set_disable_legacy_property_access:
+ *
+ * Historically, DBus-GLib allowed read/write access to any property
+ * regardless of the access flags specified in the introspection XML,
+ * and regardless of the DBus interface given.
+ * 
+ * As of version 0.88, DBus-GLib by default allows read-only access to
+ * every GObject property of an object exported to the bus, regardless
+ * of whether or not the property is listed in the type info installed
+ * with dbus_g_object_type_install_info() and regardless of whether
+ * the correct interface is specified.  Write access is denied.
+ *
+ * After calling this method, it will be required that the property is
+ * exported on the given interface, and even read-only access will be
+ * checked.  This method changes behavior globally for the entire
+ * process.
+ *
+ * Since: 0.88
+ */
+void
+dbus_glib_global_set_disable_legacy_property_access (void)
+{
+  disable_legacy_property_access = TRUE;
+}
+
+/**
  * dbus_g_object_type_install_info:
  * @object_type: #GType for the object
  * @info: introspection data generated by #dbus-glib-tool
@@ -2490,23 +2807,23 @@ _dbus_gobject_test (const char *test_dat
 
   sigdata = dbus_glib_internal_test_object_info.exported_signals;
   g_assert (*sigdata != '\0');
-  sigdata = propsig_iterate (sigdata, &iface, &signame);
+  sigdata = signal_iterate (sigdata, &iface, &signame);
   g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.MyObject"));
   g_assert (!strcmp (signame, "Frobnicate"));
   g_assert (*sigdata != '\0');
-  sigdata = propsig_iterate (sigdata, &iface, &signame);
+  sigdata = signal_iterate (sigdata, &iface, &signame);
   g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
   g_assert (!strcmp (signame, "Sig0"));
   g_assert (*sigdata != '\0');
-  sigdata = propsig_iterate (sigdata, &iface, &signame);
+  sigdata = signal_iterate (sigdata, &iface, &signame);
   g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
   g_assert (!strcmp (signame, "Sig1"));
   g_assert (*sigdata != '\0');
-  sigdata = propsig_iterate (sigdata, &iface, &signame);
+  sigdata = signal_iterate (sigdata, &iface, &signame);
   g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
   g_assert (!strcmp (signame, "Sig2"));
   g_assert (*sigdata == '\0');
-  
+
 
   i = 0;
   while (i < (int) G_N_ELEMENTS (name_pairs))
diff -purN dbus-glib-0.76-unpatched/test/core/my-object.c dbus-glib-0.76/test/core/my-object.c
--- dbus-glib-0.76-unpatched/test/core/my-object.c	2010-08-13 10:02:50.402534000 +0200
+++ dbus-glib-0.76/test/core/my-object.c	2010-08-13 10:03:08.771955000 +0200
@@ -11,6 +11,859 @@
 enum
 {
   PROP_0,
+  PROP_THIS_IS_A_STRING,
+  PROP_NO_TOUCHING,
+  PROP_SUPER_STUDLY,
+  PROP_SHOULD_BE_HIDDEN
+};
+
+enum
+{
+  FROBNICATE,
+  SIG0,
+  SIG1,
+  SIG2,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE(MyObject, my_object, G_TYPE_OBJECT)
+
+static void
+my_object_finalize (GObject *object)
+{
+  MyObject *mobject = MY_OBJECT (object);
+
+  g_free (mobject->this_is_a_string);
+
+  (G_OBJECT_CLASS (my_object_parent_class)->finalize) (object);
+}
+
+static void
+my_object_set_property (GObject      *object,
+                        guint         prop_id,
+                        const GValue *value,
+                        GParamSpec   *pspec)
+{
+  MyObject *mobject;
+
+  mobject = MY_OBJECT (object);
+
+  switch (prop_id)
+    {
+    case PROP_THIS_IS_A_STRING:
+      g_free (mobject->this_is_a_string);
+      mobject->this_is_a_string = g_value_dup_string (value);
+      break;
+
+    case PROP_NO_TOUCHING:
+      mobject->notouching = g_value_get_uint (value);
+      break;
+
+    case PROP_SUPER_STUDLY:
+      mobject->super_studly = g_value_get_double (value);
+      break;
+
+    case PROP_SHOULD_BE_HIDDEN:
+      mobject->should_be_hidden = g_value_get_boolean (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+my_object_get_property (GObject      *object,
+                        guint         prop_id,
+                        GValue       *value,
+                        GParamSpec   *pspec)
+{
+  MyObject *mobject;
+
+  mobject = MY_OBJECT (object);
+
+  switch (prop_id)
+    {
+    case PROP_THIS_IS_A_STRING:
+      g_value_set_string (value, mobject->this_is_a_string);
+      break;
+
+    case PROP_NO_TOUCHING:
+      g_value_set_uint (value, mobject->notouching);
+      break;
+
+    case PROP_SUPER_STUDLY:
+      g_value_set_double (value, mobject->super_studly);
+      break;
+
+    case PROP_SHOULD_BE_HIDDEN:
+      g_value_set_boolean (value, mobject->should_be_hidden);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+my_object_init (MyObject *obj)
+{
+  obj->val = 0;
+  obj->notouching = 42;
+}
+
+static void
+my_object_class_init (MyObjectClass *mobject_class)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (mobject_class);
+
+  dbus_g_object_type_install_info (MY_TYPE_OBJECT,
+				   &dbus_glib_my_object_object_info);
+
+  gobject_class->finalize = my_object_finalize;
+  gobject_class->set_property = my_object_set_property;
+  gobject_class->get_property = my_object_get_property;
+
+  g_object_class_install_property (gobject_class,
+				   PROP_THIS_IS_A_STRING,
+				   g_param_spec_string ("this_is_a_string",
+                                                        _("Sample string"),
+                                                        _("Example of a string property"),
+                                                        "default value",
+                                                        G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class,
+                                   PROP_NO_TOUCHING,
+                                   g_param_spec_uint ("no_touching",
+                                                      _("Don't touch"),
+                                                      _("Example of a readonly property (for export)"),
+                                                      0, 100, 42,
+                                                      G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                				   PROP_SUPER_STUDLY,
+				                   g_param_spec_double ("super-studly",
+                                                        _("In Studly Caps"),
+                                                        _("Example of a StudlyCaps property"),
+                                                        0, 256, 128,
+                                                        G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                				   PROP_SHOULD_BE_HIDDEN,
+				                   g_param_spec_boolean ("should-be-hidden",
+                                                        _("A non-exported property"),
+                                                        _("Example of a property we don't want exported"),
+                                                        FALSE,
+                                                        G_PARAM_READWRITE));
+
+  signals[FROBNICATE] =
+    g_signal_new ("frobnicate",
+		  G_OBJECT_CLASS_TYPE (mobject_class),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+                  0,
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__INT,
+                  G_TYPE_NONE, 1, G_TYPE_INT);
+
+  signals[SIG0] =
+    g_signal_new ("sig0",
+		  G_OBJECT_CLASS_TYPE (mobject_class),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+                  0,
+                  NULL, NULL,
+                  my_object_marshal_VOID__STRING_INT_STRING,
+                  G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
+
+  signals[SIG1] =
+    g_signal_new ("sig1",
+		  G_OBJECT_CLASS_TYPE (mobject_class),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+                  0,
+                  NULL, NULL,
+                  my_object_marshal_VOID__STRING_BOXED,
+                  G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_VALUE);
+
+  signals[SIG2] =
+    g_signal_new ("sig2",
+		  G_OBJECT_CLASS_TYPE (mobject_class),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+                  0,
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__BOXED,
+                  G_TYPE_NONE, 1, DBUS_TYPE_G_STRING_STRING_HASHTABLE);
+}
+
+GQuark
+my_object_error_quark (void)
+{
+  static GQuark quark = 0;
+  if (!quark)
+    quark = g_quark_from_static_string ("my_object_error");
+
+  return quark;
+}
+
+/* This should really be standard. */
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+
+GType
+my_object_error_get_type (void)
+{
+	static GType etype = 0;
+
+	if (etype == 0)
+	{
+		static const GEnumValue values[] =
+		{
+
+			ENUM_ENTRY (MY_OBJECT_ERROR_FOO, "Foo"),
+			ENUM_ENTRY (MY_OBJECT_ERROR_BAR, "Bar"),
+			ENUM_ENTRY (MY_OBJECT_ERROR_MULTI_WORD, "Multi-word"),
+			{ 0, 0, 0 }
+		};
+
+		etype = g_enum_register_static ("MyObjectError", values);
+	}
+
+	return etype;
+}
+
+gboolean
+my_object_do_nothing (MyObject *obj, GError **error)
+{
+  return TRUE;
+}
+
+gboolean
+my_object_increment (MyObject *obj, gint32 x, gint32 *ret, GError **error)
+{
+  *ret = x +1;
+  return TRUE;
+}
+
+gint32
+my_object_increment_retval (MyObject *obj, gint32 x)
+{
+  return x + 1;
+}
+
+gint32
+my_object_increment_retval_error (MyObject *obj, gint32 x, GError **error)
+{
+  if (x + 1 > 10)
+    {
+      g_set_error (error,
+		   MY_OBJECT_ERROR,
+		   MY_OBJECT_ERROR_FOO,
+		   "%s",
+		   "x is bigger than 9");
+      return FALSE;
+    }
+  return x + 1;
+}
+
+gboolean
+my_object_throw_error (MyObject *obj, GError **error)
+{
+  g_set_error (error,
+	       MY_OBJECT_ERROR,
+	       MY_OBJECT_ERROR_FOO,
+	       "%s",
+	       "this method always loses");
+  return FALSE;
+}
+
+gboolean
+my_object_throw_not_supported (MyObject *obj, GError **error)
+{
+  g_set_error (error,
+	       DBUS_GERROR,
+	       DBUS_GERROR_NOT_SUPPORTED,
+	       "%s",
+	       "this method always loses");
+  return FALSE;
+}
+
+gboolean
+my_object_throw_error_multi_word (MyObject *obj, GError **error)
+{
+  g_set_error (error,
+	       MY_OBJECT_ERROR,
+	       MY_OBJECT_ERROR_MULTI_WORD,
+	       "%s",
+	       "this method's error has a hyphen");
+  return FALSE;
+}
+
+gboolean
+my_object_throw_unregistered_error (MyObject *obj, GError **error)
+{
+  /* Unregistered errors shouldn't cause a dbus abort.  See
+   * https://bugzilla.redhat.com/show_bug.cgi?id=581794
+   */
+  g_set_error (error, 0, 0,
+	       "%s",
+	       "this method always loses more");
+  return FALSE;
+}
+
+
+gboolean
+my_object_uppercase (MyObject *obj, const char *str, char **ret, GError **error)
+{
+  *ret = g_ascii_strup (str, -1);
+  return TRUE;
+}
+
+gboolean
+my_object_many_args (MyObject *obj, guint32 x, const char *str, double trouble, double *d_ret, char **str_ret, GError **error)
+{
+  *d_ret = trouble + (x * 2);
+  *str_ret = g_ascii_strup (str, -1);
+  return TRUE;
+}
+
+gboolean
+my_object_many_return (MyObject *obj, guint32 *arg0, char **arg1, gint32 *arg2, guint32 *arg3, guint32 *arg4, const char **arg5, GError **error)
+{
+  *arg0 = 42;
+  *arg1 = g_strdup ("42");
+  *arg2 = -67;
+  *arg3 = 2;
+  *arg4 = 26;
+  *arg5 = "hello world"; /* Annotation specifies as const */
+  return TRUE;
+}
+
+gboolean
+my_object_stringify (MyObject *obj, GValue *value, char **ret, GError **error)
+{
+  GValue valstr = {0, };
+
+  g_value_init (&valstr, G_TYPE_STRING);
+  if (!g_value_transform (value, &valstr))
+    {
+      g_set_error (error,
+		   MY_OBJECT_ERROR,
+		   MY_OBJECT_ERROR_FOO,
+		   "couldn't transform value");
+      return FALSE;
+    }
+  *ret = g_value_dup_string (&valstr);
+  g_value_unset (&valstr);
+  return TRUE;
+}
+
+gboolean
+my_object_unstringify (MyObject *obj, const char *str, GValue *value, GError **error)
+{
+  if (str[0] == '\0' || !g_ascii_isdigit (str[0])) {
+    g_value_init (value, G_TYPE_STRING);
+    g_value_set_string (value, str);
+  } else {
+    g_value_init (value, G_TYPE_INT);
+    g_value_set_int (value, (int) g_ascii_strtoull (str, NULL, 10));
+  }
+  return TRUE;
+}
+
+gboolean
+my_object_recursive1 (MyObject *obj, GArray *array, guint32 *len_ret, GError **error)
+{
+  *len_ret = array->len;
+  return TRUE;
+}
+
+gboolean
+my_object_recursive2 (MyObject *obj, guint32 reqlen, GArray **ret, GError **error)
+{
+  guint32 val;
+  GArray *array;
+
+  array = g_array_new (FALSE, TRUE, sizeof (guint32));
+
+  while (reqlen > 0) {
+    val = 42;
+    g_array_append_val (array, val);
+    val = 26;
+    g_array_append_val (array, val);
+    reqlen--;
+  }
+  val = 2;
+  g_array_append_val (array, val);
+  *ret = array;
+  return TRUE;
+}
+
+gboolean
+my_object_many_uppercase (MyObject *obj, const char * const *in, char ***out, GError **error)
+{
+  int len;
+  int i;
+
+  len = g_strv_length ((char**) in);
+
+  *out = g_new0 (char *, len + 1);
+  for (i = 0; i < len; i++)
+    {
+      (*out)[i] = g_ascii_strup (in[i], -1);
+    }
+  (*out)[i] = NULL;
+
+  return TRUE;
+}
+
+static void
+hash_foreach_stringify (gpointer key, gpointer val, gpointer user_data)
+{
+  const char *keystr = key;
+  const GValue *value = val;
+  GValue *sval;
+  GHashTable *ret = user_data;
+
+  sval = g_new0 (GValue, 1);
+  g_value_init (sval, G_TYPE_STRING);
+  if (!g_value_transform (value, sval))
+    g_assert_not_reached ();
+
+  g_hash_table_insert (ret, g_strdup (keystr), sval);
+}
+
+static void
+unset_and_free_gvalue (gpointer val)
+{
+  g_value_unset (val);
+  g_free (val);
+}
+
+gboolean
+my_object_many_stringify (MyObject *obj, GHashTable /* char * -> GValue * */ *vals, GHashTable /* char * -> GValue * */ **ret, GError **error)
+{
+  *ret = g_hash_table_new_full (g_str_hash, g_str_equal,
+				g_free, unset_and_free_gvalue);
+  g_hash_table_foreach (vals, hash_foreach_stringify, *ret);
+  return TRUE;
+}
+
+gboolean
+my_object_rec_arrays (MyObject *obj, GPtrArray *in, GPtrArray **ret, GError **error)
+{
+  char **strs;
+  GArray *ints;
+  guint v_UINT;
+
+  if (in->len != 2)
+    {
+      g_set_error (error,
+		   MY_OBJECT_ERROR,
+		   MY_OBJECT_ERROR_FOO,
+		   "invalid array len");
+      return FALSE;
+    }
+
+  strs = g_ptr_array_index (in, 0);
+  if (!*strs || strcmp (*strs, "foo"))
+    {
+      g_set_error (error,
+		   MY_OBJECT_ERROR,
+		   MY_OBJECT_ERROR_FOO,
+		   "invalid string 0");
+      return FALSE;
+    }
+  strs++;
+  if (!*strs || strcmp (*strs, "bar"))
+    {
+      g_set_error (error,
+		   MY_OBJECT_ERROR,
+		   MY_OBJECT_ERROR_FOO,
+		   "invalid string 1");
+      return FALSE;
+    }
+  strs++;
+  if (*strs)
+    {
+      g_set_error (error,
+		   MY_OBJECT_ERROR,
+		   MY_OBJECT_ERROR_FOO,
+		   "invalid string array len in pos 0");
+      return FALSE;
+    }
+  strs = g_ptr_array_index (in, 1);
+  if (!*strs || strcmp (*strs, "baz"))
+    {
+      g_set_error (error,
+		   MY_OBJECT_ERROR,
+		   MY_OBJECT_ERROR_FOO,
+		   "invalid string 0");
+      return FALSE;
+    }
+  strs++;
+  if (!*strs || strcmp (*strs, "whee"))
+    {
+      g_set_error (error,
+		   MY_OBJECT_ERROR,
+		   MY_OBJECT_ERROR_FOO,
+		   "invalid string 1");
+      return FALSE;
+    }
+  strs++;
+  if (!*strs || strcmp (*strs, "moo"))
+    {
+      g_set_error (error,
+		   MY_OBJECT_ERROR,
+		   MY_OBJECT_ERROR_FOO,
+		   "invalid string 2");
+      return FALSE;
+    }
+  strs++;
+  if (*strs)
+    {
+      g_set_error (error,
+		   MY_OBJECT_ERROR,
+		   MY_OBJECT_ERROR_FOO,
+		   "invalid string array len in pos 1");
+      return FALSE;
+    }
+
+  *ret = g_ptr_array_new ();
+
+  ints = g_array_new (TRUE, TRUE, sizeof (guint));
+  v_UINT = 10;
+  g_array_append_val (ints, v_UINT);
+  v_UINT = 42;
+  g_array_append_val (ints, v_UINT);
+  v_UINT = 27;
+  g_array_append_val (ints, v_UINT);
+  g_ptr_array_add (*ret, ints);
+
+  ints = g_array_new (TRUE, TRUE, sizeof (guint));
+  v_UINT = 30;
+  g_array_append_val (ints, v_UINT);
+  g_ptr_array_add (*ret, ints);
+  return TRUE;
+}
+
+gboolean
+my_object_objpath (MyObject *obj, const char *incoming, const char **outgoing, GError **error)
+{
+  if (strcmp (incoming, "/org/freedesktop/DBus/GLib/Tests/MyTestObject"))
+    {
+      g_set_error (error,
+		   MY_OBJECT_ERROR,
+		   MY_OBJECT_ERROR_FOO,
+		   "invalid incoming object");
+      return FALSE;
+    }
+  *outgoing = "/org/freedesktop/DBus/GLib/Tests/MyTestObject2";
+  return TRUE;
+}
+
+gboolean
+my_object_get_objs (MyObject *obj, GPtrArray **objs, GError **error)
+{
+  *objs = g_ptr_array_new ();
+
+  g_ptr_array_add (*objs, g_strdup ("/org/freedesktop/DBus/GLib/Tests/MyTestObject"));
+  g_ptr_array_add (*objs, g_strdup ("/org/freedesktop/DBus/GLib/Tests/MyTestObject2"));
+
+  return TRUE;
+}
+
+static void
+hash_foreach (gpointer key, gpointer val, gpointer user_data)
+{
+  const char *keystr = key;
+  const char *valstr = val;
+  guint *count = user_data;
+
+  *count += (strlen (keystr) + strlen (valstr));
+  g_print ("%s -> %s\n", keystr, valstr);
+}
+
+gboolean
+my_object_str_hash_len (MyObject *obj, GHashTable *table, guint *len, GError **error)
+{
+  *len = 0;
+  g_hash_table_foreach (table, hash_foreach, len);
+  return TRUE;
+}
+
+gboolean
+my_object_send_car (MyObject *obj, GValueArray *invals, GValueArray **outvals, GError **error)
+{
+  if (invals->n_values != 3
+      || G_VALUE_TYPE (g_value_array_get_nth (invals, 0)) != G_TYPE_STRING
+      || G_VALUE_TYPE (g_value_array_get_nth (invals, 1)) != G_TYPE_UINT
+      || G_VALUE_TYPE (g_value_array_get_nth (invals, 2)) != G_TYPE_VALUE)
+    {
+      g_set_error (error,
+		   MY_OBJECT_ERROR,
+		   MY_OBJECT_ERROR_FOO,
+		   "invalid incoming values");
+      return FALSE;
+    }
+  *outvals = g_value_array_new (2);
+  g_value_array_append (*outvals, NULL);
+  g_value_init (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1), G_TYPE_UINT);
+  g_value_set_uint (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1),
+		    g_value_get_uint (g_value_array_get_nth (invals, 1)) + 1);
+  g_value_array_append (*outvals, NULL);
+  g_value_init (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1), DBUS_TYPE_G_OBJECT_PATH);
+  g_value_set_boxed (g_value_array_get_nth (*outvals, (*outvals)->n_values - 1),
+		     g_strdup ("/org/freedesktop/DBus/GLib/Tests/MyTestObject2"));
+  return TRUE;
+}
+
+gboolean
+my_object_get_hash (MyObject *obj, GHashTable **ret, GError **error)
+{
+  GHashTable *table;
+
+  table = g_hash_table_new (g_str_hash, g_str_equal);
+  g_hash_table_insert (table, "foo", "bar");
+  g_hash_table_insert (table, "baz", "whee");
+  g_hash_table_insert (table, "cow", "crack");
+  *ret = table;
+  return TRUE;
+}
+
+gboolean
+my_object_increment_val (MyObject *obj, GError **error)
+{
+  obj->val++;
+  return TRUE;
+}
+
+gboolean
+my_object_get_val (MyObject *obj, guint *ret, GError **error)
+{
+  *ret = obj->val;
+  return TRUE;
+}
+
+gboolean
+my_object_get_value (MyObject *obj, guint *ret, GError **error)
+{
+  *ret = obj->val;
+  return TRUE;
+}
+
+gboolean
+my_object_echo_variant (MyObject *obj, GValue *variant, GValue *ret, GError **error)
+{
+    GType t;
+    t = G_VALUE_TYPE(variant);
+    g_value_init (ret, t);
+    g_value_copy (variant, ret);
+
+    return TRUE;
+}
+
+gboolean
+my_object_echo_signature (MyObject *obj, const gchar *in, gchar **out, GError **error)
+{
+  *out = g_strdup (in);
+  return TRUE;
+}
+
+gboolean
+my_object_process_variant_of_array_of_ints123 (MyObject *obj, GValue *variant, GError **error)
+{
+  GArray *array;
+  int i;
+  int j;
+
+  j = 0;
+
+  array = (GArray *)g_value_get_boxed (variant);
+
+  for (i = 0; i <= 2; i++)
+    {
+      j = g_array_index (array, int, i);
+      if (j != i + 1)
+        goto error;
+    }
+
+  return TRUE;
+
+error:
+  *error = g_error_new (MY_OBJECT_ERROR,
+		       MY_OBJECT_ERROR_FOO,
+		       "Error decoding a variant of type ai (i + 1 = %i, j = %i)",
+		       i, j + 1);
+  return FALSE;
+}
+
+
+typedef struct _HashAndString HashAndString;
+
+struct _HashAndString
+{
+  GHashTable *hash;
+  gchar* string;
+};
+
+static void
+hash_foreach_prepend_string (gpointer key, gpointer val, gpointer user_data)
+{
+  HashAndString *data = (HashAndString*) user_data;
+  gchar *in = (gchar*) val;
+  g_hash_table_insert (data->hash, g_strdup ((gchar*) key),
+                       g_strjoin (" ", data->string, in, NULL));
+}
+
+
+static void
+hash_foreach_mangle_dict_of_strings (gpointer key, gpointer val, gpointer user_data)
+{
+  GHashTable *out = (GHashTable*) user_data;
+  GHashTable *in_dict = (GHashTable *) val;
+  HashAndString *data = g_new0 (HashAndString, 1);
+
+  data->string = (gchar*) key;
+  data->hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                            g_free, g_free);
+  g_hash_table_foreach (in_dict, hash_foreach_prepend_string, data);
+
+  g_hash_table_insert(out, g_strdup ((gchar*) key), data->hash);
+}
+
+gboolean
+my_object_dict_of_dicts (MyObject *obj, GHashTable *in,
+                                GHashTable **out, GError **error)
+{
+  *out = g_hash_table_new_full (g_str_hash, g_str_equal,
+				(GDestroyNotify) g_free,
+                                (GDestroyNotify) g_hash_table_destroy);
+  g_hash_table_foreach (in, hash_foreach_mangle_dict_of_strings, *out);
+  return TRUE;
+}
+
+void
+my_object_dict_of_sigs (MyObject *obj,
+                        GHashTable *dict,
+                        DBusGMethodInvocation *context)
+{
+  dbus_g_method_return (context, dict);
+}
+
+void
+my_object_dict_of_objs (MyObject *obj,
+                        GHashTable *dict,
+                        DBusGMethodInvocation *context)
+{
+  dbus_g_method_return (context, dict);
+}
+
+gboolean
+my_object_emit_frobnicate (MyObject *obj, GError **error)
+{
+  g_signal_emit (obj, signals[FROBNICATE], 0, 42);
+  return TRUE;
+}
+
+gboolean
+my_object_emit_signals (MyObject *obj, GError **error)
+{
+  GValue val = {0, };
+
+  g_signal_emit (obj, signals[SIG0], 0, "foo", 22, "moo");
+
+  g_value_init (&val, G_TYPE_STRING);
+  g_value_set_string (&val, "bar");
+  g_signal_emit (obj, signals[SIG1], 0, "baz", &val);
+  g_value_unset (&val);
+
+  return TRUE;
+}
+
+gboolean
+my_object_emit_signal2 (MyObject *obj, GError **error)
+{
+  GHashTable *table;
+
+  table = g_hash_table_new (g_str_hash, g_str_equal);
+  g_hash_table_insert (table, "baz", "cow");
+  g_hash_table_insert (table, "bar", "foo");
+  g_signal_emit (obj, signals[SIG2], 0, table);
+  g_hash_table_destroy (table);
+  return TRUE;
+}
+
+typedef struct {
+  gint32 x;
+  DBusGMethodInvocation *context;
+} IncrementData;
+
+static gboolean
+do_async_increment (IncrementData *data)
+{
+  gint32 newx = data->x + 1;
+  dbus_g_method_return (data->context, newx);
+  g_free (data);
+  return FALSE;
+}
+
+void
+my_object_async_increment (MyObject *obj, gint32 x, DBusGMethodInvocation *context)
+{
+  IncrementData *data = g_new0 (IncrementData, 1);
+  data->x = x;
+  data->context = context;
+  g_idle_add ((GSourceFunc)do_async_increment, data);
+}
+
+static gboolean
+do_async_error (IncrementData *data)
+{
+  GError *error;
+  error = g_error_new (MY_OBJECT_ERROR,
+		       MY_OBJECT_ERROR_FOO,
+		       "%s",
+		       "this method always loses");
+  dbus_g_method_return_error (data->context, error);
+  g_free (data);
+  return FALSE;
+}
+
+void
+my_object_async_throw_error (MyObject *obj, DBusGMethodInvocation *context)
+{
+  IncrementData *data = g_new0(IncrementData, 1);
+  data->context = context;
+  g_idle_add ((GSourceFunc)do_async_error,  data);
+}
+
+extern GMainLoop *loop;
+
+gboolean
+my_object_terminate (MyObject *obj, GError **error)
+{
+  g_main_loop_quit (loop);
+  return TRUE;
+}
+
+void
+my_object_unsafe_disable_legacy_property_access (MyObject *obj)
+{
+  dbus_glib_global_set_disable_legacy_property_access ();
+}
+#include <config.h>
+#include <string.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include "my-object.h"
+#include "my-object-marshal.h"
+
+#include "test-service-glib-glue.h"
+
+/* Properties */
+enum
+{
+  PROP_0,
   PROP_THIS_IS_A_STRING
 };
 
diff -purN dbus-glib-0.76-unpatched/test/core/my-object.h dbus-glib-0.76/test/core/my-object.h
--- dbus-glib-0.76-unpatched/test/core/my-object.h	2010-08-13 10:02:50.395534000 +0200
+++ dbus-glib-0.76/test/core/my-object.h	2010-08-13 10:03:08.790963000 +0200
@@ -13,6 +13,124 @@ struct MyObject
 {
   GObject parent;
   char *this_is_a_string;
+  guint notouching;
+  guint val;
+  gdouble super_studly;
+  gboolean should_be_hidden;
+};
+
+struct MyObjectClass
+{
+  GObjectClass parent;
+};
+
+#define MY_TYPE_OBJECT              (my_object_get_type ())
+#define MY_OBJECT(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), MY_TYPE_OBJECT, MyObject))
+#define MY_OBJECT_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), MY_TYPE_OBJECT, MyObjectClass))
+#define MY_IS_OBJECT(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), MY_TYPE_OBJECT))
+#define MY_IS_OBJECT_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), MY_TYPE_OBJECT))
+#define MY_OBJECT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), MY_TYPE_OBJECT, MyObjectClass))
+
+typedef enum
+{
+  MY_OBJECT_ERROR_FOO,
+  MY_OBJECT_ERROR_BAR,
+  MY_OBJECT_ERROR_MULTI_WORD
+} MyObjectError;
+
+#define MY_OBJECT_ERROR (my_object_error_quark ())
+#define MY_TYPE_ERROR (my_object_error_get_type ())
+
+GQuark my_object_error_quark (void);
+GType my_object_error_get_type (void);
+
+gboolean my_object_do_nothing (MyObject *obj, GError **error);
+
+gboolean my_object_increment (MyObject *obj, gint32 x, gint32 *ret, GError **error);
+
+gint32   my_object_increment_retval (MyObject *obj, gint32 x);
+
+gint32   my_object_increment_retval_error (MyObject *obj, gint32 x, GError **error);
+
+gboolean my_object_throw_error (MyObject *obj, GError **error);
+gboolean my_object_throw_not_supported (MyObject *obj, GError **error);
+gboolean my_object_throw_error_multi_word (MyObject *obj, GError **error);
+gboolean my_object_throw_unregistered_error (MyObject *obj, GError **error);
+
+gboolean my_object_uppercase (MyObject *obj, const char *str, char **ret, GError **error);
+
+gboolean my_object_many_args (MyObject *obj, guint32 x, const char *str, double trouble, double *d_ret, char **str_ret, GError **error);
+
+gboolean my_object_many_return (MyObject *obj, guint32 *arg0, char **arg1, gint32 *arg2, guint32 *arg3, guint32 *arg4, const char **arg5, GError **error);
+
+gboolean my_object_recursive1 (MyObject *obj, GArray *array, guint32 *len_ret, GError **error);
+gboolean my_object_recursive2 (MyObject *obj, guint32 reqlen, GArray **array, GError **error);
+
+gboolean my_object_many_stringify (MyObject *obj, GHashTable *vals, GHashTable **ret, GError **error);
+
+gboolean my_object_rec_arrays (MyObject *obj, GPtrArray *in, GPtrArray **ret, GError **error);
+
+gboolean my_object_objpath (MyObject *obj, const char *in, const char **arg1, GError **error);
+
+gboolean my_object_get_objs (MyObject *obj, GPtrArray **objs, GError **error);
+
+gboolean my_object_stringify (MyObject *obj, GValue *value, char **ret, GError **error);
+gboolean my_object_unstringify (MyObject *obj, const char *str, GValue *value, GError **error);
+
+gboolean my_object_many_uppercase (MyObject *obj, const char * const *in, char ***out, GError **error);
+
+gboolean my_object_str_hash_len (MyObject *obj, GHashTable *table, guint *len, GError **error);
+
+gboolean my_object_send_car (MyObject *obj, GValueArray *invals, GValueArray **outvals, GError **error);
+
+gboolean my_object_get_hash (MyObject *obj, GHashTable **table, GError **error);
+
+gboolean my_object_increment_val (MyObject *obj, GError **error);
+
+gboolean my_object_get_val (MyObject *obj, guint *ret, GError **error);
+
+gboolean my_object_get_value (MyObject *obj, guint *ret, GError **error);
+
+gboolean my_object_emit_signals (MyObject *obj, GError **error);
+gboolean my_object_emit_signal2 (MyObject *obj, GError **error);
+
+gboolean my_object_emit_frobnicate (MyObject *obj, GError **error);
+
+gboolean my_object_echo_variant (MyObject *obj, GValue *variant, GValue *ret, GError **error);
+gboolean my_object_echo_signature (MyObject *obj, const gchar *in, gchar **out, GError **error);
+
+gboolean my_object_process_variant_of_array_of_ints123 (MyObject *obj, GValue *variant, GError **error);
+
+gboolean my_object_dict_of_dicts (MyObject *obj, GHashTable *dict, GHashTable **ret, GError **error);
+
+void my_object_dict_of_sigs (MyObject *obj, GHashTable *dict, DBusGMethodInvocation *ctx);
+
+void my_object_dict_of_objs (MyObject *obj, GHashTable *dict, DBusGMethodInvocation *ctx);
+
+gboolean my_object_terminate (MyObject *obj, GError **error);
+
+void my_object_async_increment (MyObject *obj, gint32 x, DBusGMethodInvocation *context);
+
+void my_object_async_throw_error (MyObject *obj, DBusGMethodInvocation *context);
+
+void my_object_unsafe_disable_legacy_property_access (MyObject *obj);
+
+#endif
+#ifndef __MY_OBJECT_H__
+#define __MY_OBJECT_H__
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+typedef struct MyObject MyObject;
+typedef struct MyObjectClass MyObjectClass;
+
+GType my_object_get_type (void);
+
+struct MyObject
+{
+  GObject parent;
+  char *this_is_a_string;
   guint val;
 };
 
diff -purN dbus-glib-0.76-unpatched/test/core/test-dbus-glib.c dbus-glib-0.76/test/core/test-dbus-glib.c
--- dbus-glib-0.76-unpatched/test/core/test-dbus-glib.c	2010-08-13 10:02:50.428549000 +0200
+++ dbus-glib-0.76/test/core/test-dbus-glib.c	2010-08-13 10:03:08.819974000 +0200
@@ -268,7 +268,6 @@ increment_async_cb (DBusGProxy *proxy, g
   g_source_remove (exit_timeout);
 }
 
-
 static void
 lose (const char *str, ...)
 {
@@ -1609,7 +1608,10 @@ main (int argc, char **argv)
 
     node = description_load_from_string (v_STRING_2, strlen (v_STRING_2), &error);
     if (!node)
-      lose_gerror ("Failed to parse introspection data: %s", error);
+      {
+        g_printerr ("===\n%s\n===\n", v_STRING_2);
+        lose_gerror ("Failed to parse introspection data: %s", error);
+      }
 
     found_introspectable = FALSE;
     found_properties = FALSE;
@@ -1627,9 +1629,10 @@ main (int argc, char **argv)
 	  {
 	    GSList *elt;
 	    gboolean found_manyargs;
-	    
+	    gboolean found_no_touching = FALSE;
+
 	    found_myobject = TRUE;
-	    
+
 	    found_manyargs = FALSE;
 	    for (elt = interface_info_get_methods (iface); elt; elt = elt->next)
 	      {
@@ -1644,6 +1647,23 @@ main (int argc, char **argv)
 	      }
 	    if (!found_manyargs)
 	      lose ("Missing method org.freedesktop.DBus.GLib.Tests.MyObject.ManyArgs");
+	    for (elt = interface_info_get_properties (iface); elt; elt = elt->next)
+	      {
+	        PropertyInfo *prop = elt->data;
+
+	        if (strcmp (property_info_get_name (prop), "no-touching") == 0)
+	          {
+	            if (property_info_get_access (prop) != PROPERTY_READ)
+	              lose ("property no-touching had incorrect access %d", property_info_get_access (prop));
+	            else
+	              {
+	                found_no_touching = TRUE;
+	                break;
+	              }
+	          }
+	      }
+	    if (!found_no_touching)
+	      lose ("didn't find property \"no-touching\" in org.freedesktop.DBus.GLib.Tests.MyObject");
 	  }
 	else if (!found_fooobject && strcmp (interface_info_get_name (iface), "org.freedesktop.DBus.GLib.Tests.FooObject") == 0)
 	  found_fooobject = TRUE;
--- a/dbus/dbus-gobject.c  2010-08-13 15:26:56.995808000 +0200
+++ b/dbus/dbus-gobject.c     2010-08-13 15:29:22.108766000 +0200
@@ -1804,7 +1804,7 @@ gobject_message_function (DBusConnection
         {
           ret = dbus_message_new_error_printf (message,
                                                DBUS_ERROR_INVALID_ARGS,
-                                               "No such property %s", wincaps_propname);
+                                               "No such property %s", requested_propname);
         }
     }
   else
