[PATCH 2/2] mountmgr: Support the dbus service udisks for dynamic devices :-) [try 3]

Detlef Riekenberg wine.dev at web.de
Mon Jul 11 10:50:13 CDT 2011


udisks is prefered, but libhal support is still present as fallback.
This allow the libhal requirement on linux to die.

Binary packages should be build with libhal support for a while.

The logic to add/remove the devices/volumes is the same as present in
our libhal support.

autoheader/autoconf are needed before compilation

try 2:
remove a trailing space in the code an a trailing " \" in Makefile.in
try 3:
changes for configure.ac where missing in try 2

--
By by ... Detlef
---
 configure.ac                  |   20 ++-
 dlls/mountmgr.sys/Makefile.in |    5 +-
 dlls/mountmgr.sys/hal.c       |   15 ++
 dlls/mountmgr.sys/mountmgr.c  |    2 +
 dlls/mountmgr.sys/mountmgr.h  |    3 +
 dlls/mountmgr.sys/udisks.c    |  554 +++++++++++++++++++++++++++++++++++++++++
 6 files changed, 596 insertions(+), 3 deletions(-)
 create mode 100644 dlls/mountmgr.sys/udisks.c

diff --git a/configure.ac b/configure.ac
index b50d5ed..4d39606 100644
--- a/configure.ac
+++ b/configure.ac
@@ -42,6 +42,7 @@ AC_ARG_WITH(coreaudio, AS_HELP_STRING([--without-coreaudio],[do not use the Core
 AC_ARG_WITH(cups,      AS_HELP_STRING([--without-cups],[do not use CUPS]))
 AC_ARG_WITH(curses,    AS_HELP_STRING([--without-curses],[do not use (n)curses]),
             [if test "x$withval" = "xno"; then ac_cv_header_ncurses_h=no; ac_cv_header_curses_h=no; fi])
+AC_ARG_WITH(dbus,      AS_HELP_STRING([--without-dbus],[do not use dbus (dynamic device support)]))
 AC_ARG_WITH(esd,       AS_HELP_STRING([--without-esd],[do not use the EsounD sound support]))
 AC_ARG_WITH(fontconfig,AS_HELP_STRING([--without-fontconfig],[do not use fontconfig]),
             [if test "x$withval" = "xno"; then ac_cv_header_fontconfig_fontconfig_h=no; fi])
@@ -1214,6 +1215,23 @@ fi
 WINE_WARNING_WITH(xslt,[test "x$ac_cv_lib_soname_xslt" = "x"],
                  [libxslt ${notice_platform}development files not found, xslt won't be supported.])
 
+dnl **** Check for libdbus ****
+AC_SUBST(DBUSINCL,"")
+if test "x$with_dbus" != "xno"
+then
+    ac_save_CPPFLAGS="$CPPFLAGS"
+    if test "$PKG_CONFIG" != "false"
+    then
+        ac_dbus_libs="`$PKG_CONFIG --libs dbus-1 2>/dev/null`"
+        ac_dbus_cflags="`$PKG_CONFIG --cflags dbus-1 2>/dev/null`"
+        CPPFLAGS="$CPPFLAGS $ac_dbus_cflags"
+    fi
+    AC_CHECK_HEADER(dbus/dbus.h,
+        [WINE_CHECK_SONAME(dbus-1,dbus_bus_get,[DBUSINCL="$ac_dbus_cflags"],,[$ac_dbus_libs])])
+
+    CPPFLAGS="$ac_save_CPPFLAGS"
+fi
+
 dnl **** Check for libhal ****
 AC_SUBST(HALINCL,"")
 if test "x$with_hal" != "xno"
@@ -1234,7 +1252,7 @@ then
     fi
     CPPFLAGS="$ac_save_CPPFLAGS"
 fi
-WINE_NOTICE_WITH(hal,[test "x$ac_cv_lib_soname_hal" = "x" -a "x$ac_cv_header_DiskArbitration_DiskArbitration_h" != "xyes"],
+WINE_NOTICE_WITH(hal,[test "x$ac_cv_lib_soname_hal" = "x" -a "x$ac_cv_lib_soname_dbus_1" = "x" -a "x$ac_cv_header_DiskArbitration_DiskArbitration_h" != "xyes"],
                  [libhal/libdbus ${notice_platform}development files not found, no dynamic device support.])
 
 dnl **** Check for libgnutls ****
diff --git a/dlls/mountmgr.sys/Makefile.in b/dlls/mountmgr.sys/Makefile.in
index 91203e1..f3355e0 100644
--- a/dlls/mountmgr.sys/Makefile.in
+++ b/dlls/mountmgr.sys/Makefile.in
@@ -2,13 +2,14 @@ MODULE    = mountmgr.sys
 IMPORTS   = uuid advapi32 ntoskrnl.exe
 DELAYIMPORTS = user32
 EXTRADLLFLAGS = -Wb,--subsystem,native
-EXTRADEFS = @HALINCL@
+EXTRADEFS = @HALINCL@ @DBUSINCL@
 EXTRALIBS = @DISKARBITRATIONLIB@
 
 C_SRCS = \
 	device.c \
 	diskarb.c \
 	hal.c \
-	mountmgr.c
+	mountmgr.c \
+	udisks.c
 
 @MAKE_DLL_RULES@
diff --git a/dlls/mountmgr.sys/hal.c b/dlls/mountmgr.sys/hal.c
index ff10a3e..8e31624 100644
--- a/dlls/mountmgr.sys/hal.c
+++ b/dlls/mountmgr.sys/hal.c
@@ -245,6 +245,21 @@ void initialize_hal(void)
 {
     HANDLE handle;
 
+    /* wait for udisks, when needed */
+    if (dbus_present)
+    {
+        DWORD res;
+
+        TRACE("waiting for udisks\n");
+        res = WaitForSingleObject(dbus_present, 100);
+
+        if (!res && *udisks_version)
+        {
+            TRACE("Skipping, found udisks\n");
+            return;
+        }
+    }
+
     if (!load_functions()) return;
     if (!(handle = CreateThread( NULL, 0, hal_thread, NULL, 0, NULL ))) return;
     CloseHandle( handle );
diff --git a/dlls/mountmgr.sys/mountmgr.c b/dlls/mountmgr.sys/mountmgr.c
index 4e9900f..df0dbd3 100644
--- a/dlls/mountmgr.sys/mountmgr.c
+++ b/dlls/mountmgr.sys/mountmgr.c
@@ -443,6 +443,8 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
     RtlInitUnicodeString( &nameW, harddiskW );
     status = IoCreateDriver( &nameW, harddisk_driver_entry );
 
+    /* start udisks before hal */
+    initialize_udisks();
     initialize_hal();
     initialize_diskarbitration();
 
diff --git a/dlls/mountmgr.sys/mountmgr.h b/dlls/mountmgr.sys/mountmgr.h
index a8e4389..3c3c564 100644
--- a/dlls/mountmgr.sys/mountmgr.h
+++ b/dlls/mountmgr.sys/mountmgr.h
@@ -35,8 +35,11 @@
 #define WINE_MOUNTMGR_EXTENSIONS
 #include "ddk/mountmgr.h"
 
+extern void initialize_udisks(void) DECLSPEC_HIDDEN;
 extern void initialize_hal(void) DECLSPEC_HIDDEN;
 extern void initialize_diskarbitration(void) DECLSPEC_HIDDEN;
+extern HANDLE dbus_present;
+extern char udisks_version[];
 
 /* device functions */
 
diff --git a/dlls/mountmgr.sys/udisks.c b/dlls/mountmgr.sys/udisks.c
new file mode 100644
index 0000000..898f41d
--- /dev/null
+++ b/dlls/mountmgr.sys/udisks.c
@@ -0,0 +1,554 @@
+/*
+ * udisks devices support
+ *
+ * Copyright 2006 Alexandre Julliard
+ * Copyright 2011 Detlef Riekenberg
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#include "mountmgr.h"
+#include "winnls.h"
+#include "excpt.h"
+
+#include "wine/library.h"
+#include "wine/exception.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(mountmgr);
+
+HANDLE dbus_present = NULL;
+char   udisks_version[32];
+
+#ifdef SONAME_LIBDBUS_1
+
+#include <dbus/dbus.h>
+
+/* ########## */
+
+typedef struct properties_s {
+    CHAR *device_file;
+    CHAR *id_usage;
+    CHAR *id_type;
+    CHAR *id_uuid;
+    BOOL  device_is_mounted;
+    BOOL  device_is_optical_disc;
+    BOOL  device_is_removable;
+    CHAR *device_mount_paths;
+    CHAR *drive_media;
+    CHAR *drive_media_compatibility;
+    int   depth;
+    const char * last_name;
+}properties_t;
+
+static const char *my_match_rule = "interface=org.freedesktop.UDisks";
+static const char *dest_udisks_device = "org.freedesktop.UDisks.Device";
+static const char *dest_udisks = "org.freedesktop.UDisks";
+static const char *path_udisks = "/org/freedesktop/UDisks";
+static const char *iface_dbus_prop = "org.freedesktop.DBus.Properties";
+static const char *daemonversion = "DaemonVersion";
+
+/* ########## */
+
+#define DBUS_FUNCS \
+    DO_FUNC(dbus_bus_add_match); \
+    DO_FUNC(dbus_bus_get); \
+    DO_FUNC(dbus_bus_remove_match); \
+    DO_FUNC(dbus_connection_pop_message); \
+    DO_FUNC(dbus_connection_read_write_dispatch); \
+    DO_FUNC(dbus_connection_send_with_reply_and_block); \
+    DO_FUNC(dbus_connection_unref); \
+    DO_FUNC(dbus_error_free); \
+    DO_FUNC(dbus_error_init); \
+    DO_FUNC(dbus_error_is_set); \
+    DO_FUNC(dbus_message_append_args); \
+    DO_FUNC(dbus_message_get_member); \
+    DO_FUNC(dbus_message_iter_get_arg_type); \
+    DO_FUNC(dbus_message_iter_get_basic); \
+    DO_FUNC(dbus_message_iter_init); \
+    DO_FUNC(dbus_message_iter_next); \
+    DO_FUNC(dbus_message_iter_recurse); \
+    DO_FUNC(dbus_message_new_method_call); \
+    DO_FUNC(dbus_message_type_to_string); \
+    DO_FUNC(dbus_message_unref)
+
+#define DO_FUNC(f) static typeof(f) * p_##f
+DBUS_FUNCS;
+#undef DO_FUNC
+
+
+static BOOL load_dbus_functions(void)
+{
+    void *dbus_handle;
+    char error[128];
+
+    if (!(dbus_handle = wine_dlopen(SONAME_LIBDBUS_1, RTLD_NOW|RTLD_GLOBAL, error, sizeof(error))))
+        goto failed;
+
+#define DO_FUNC(f) if (!(p_##f = wine_dlsym(RTLD_DEFAULT, #f, error, sizeof(error)))) goto failed
+    DBUS_FUNCS;
+#undef DO_FUNC
+
+    return TRUE;
+
+failed:
+    WARN("failed to load udisks support: %s\n", error);
+    return FALSE;
+}
+
+/* ########## */
+
+static LONG WINAPI assert_fault(EXCEPTION_POINTERS *eptr)
+{
+    if (eptr->ExceptionRecord->ExceptionCode == EXCEPTION_WINE_ASSERTION)
+        return EXCEPTION_EXECUTE_HANDLER;
+    return EXCEPTION_CONTINUE_SEARCH;
+}
+
+/* #########################################
+ * get_properties_from_iter [internal]
+ *
+ * NOTES
+ *  format of args in a reply from GetAll:
+ *  an ARRAY of DICT_ENTRY
+ *  each DICT_ENTRY has a STRING (property name) and a VARIANT (property value)
+ *  each VARIANT has a BOOLEAN or a STRING or an ARRAY of STRING or an here unused value
+ */
+static BOOL get_properties_from_iter(properties_t * p, DBusMessageIter * iter)
+{
+    DBusMessageIter sub;
+    int arg_type = p_dbus_message_iter_get_arg_type(iter);
+
+    p->depth++;
+    while (arg_type != DBUS_TYPE_INVALID)
+    {
+        if ((arg_type == DBUS_TYPE_ARRAY) ||
+            (arg_type == DBUS_TYPE_DICT_ENTRY) ||
+            (arg_type == DBUS_TYPE_VARIANT))
+        {
+            p_dbus_message_iter_recurse(iter, &sub);
+            if (!get_properties_from_iter(p, &sub))
+            {
+                p->depth--;
+                return FALSE;
+            }
+        }
+        else if (arg_type == DBUS_TYPE_STRING)
+        {
+            char * data;
+            p_dbus_message_iter_get_basic(iter, &data);
+            if (p->depth == 3) p->last_name = data;
+            else if (p->last_name)
+            {
+                if (!strcmp(p->last_name, "DeviceFile"))
+                    p->device_file = data;
+                else if (!strcmp(p->last_name, "DeviceMountPaths"))
+                    p->device_mount_paths = data;  /* use only the first entry */
+                else if (!strcmp(p->last_name, "DriveMedia"))
+                    p->drive_media = data;
+                else if (!strcmp(p->last_name, "DriveMediaCompatibility"))
+                    p->drive_media_compatibility = data; /* use only the first entry */
+                else if (!strcmp(p->last_name, "IdType"))
+                    p->id_type = data;
+                else if (!strcmp(p->last_name, "IdUsage"))
+                    p->id_usage = data;
+                else if (!strcmp(p->last_name, "IdUuid"))
+                    p->id_uuid = data;
+
+                p->last_name = NULL;
+            }
+        }
+        else if (arg_type == DBUS_TYPE_BOOLEAN)
+        {
+            dbus_bool_t data;
+            if (p->last_name)
+            {
+                p_dbus_message_iter_get_basic(iter, &data);
+                if (!strcmp(p->last_name, "DeviceIsMounted"))
+                    p->device_is_mounted = data;
+                else if (!strcmp(p->last_name, "DeviceIsOpticalDisc"))
+                    p->device_is_optical_disc = data;
+                else if (!strcmp(p->last_name, "DeviceIsRemovable"))
+                    p->device_is_removable = data;
+
+                p->last_name = NULL;
+            }
+        }
+
+        p_dbus_message_iter_next(iter);
+        arg_type = p_dbus_message_iter_get_arg_type(iter);
+    }
+    p->depth--;
+    return TRUE;
+}
+
+/* ########### */
+
+static DBusMessage * get_properties_from_path(properties_t * p, DBusConnection *ctx, const char * path)
+{
+    DBusMessage *request;
+    DBusMessage *reply = NULL;
+    DBusMessageIter iter;
+    DBusError error;
+
+    TRACE("(%p, %p, %s)\n", p, ctx, path);
+
+    memset(p, 0, sizeof(properties_t));
+    request = p_dbus_message_new_method_call(dest_udisks, path, iface_dbus_prop, "GetAll");
+    if (request)
+    {
+        if (p_dbus_message_append_args(request, DBUS_TYPE_STRING, &dest_udisks_device, DBUS_TYPE_INVALID))
+        {
+            p_dbus_error_init(&error);
+            if ((reply = p_dbus_connection_send_with_reply_and_block(ctx, request, -1, &error)))
+            {
+                p_dbus_message_iter_init(reply, &iter);
+                get_properties_from_iter(p, &iter);
+            }
+            else
+                WARN("no reply for %s\n", path);
+
+            p_dbus_error_free(&error);
+        }
+        else
+            WARN("dbus_message_append_args failed for 'GetAll'\n");
+
+        p_dbus_message_unref(request);
+    }
+    return reply;
+}
+
+/* ########### */
+
+static int get_drive_type(properties_t * p)
+{
+    /* examples: optical_cd, optical_cd_rw, optical_dvd_plus_r_dl */
+    if (p->device_is_optical_disc && p->drive_media && !memcmp(p->drive_media, "optical_", 8))
+    {
+        if (!memcmp(p->drive_media + 8, "cd", 2))
+            return DEVICE_CDROM;
+        else
+            return DEVICE_DVD;
+    }
+    else if (p->drive_media_compatibility && !strcmp(p->drive_media_compatibility, "floppy"))
+        return DEVICE_FLOPPY;
+    else if (!p->device_is_removable && p->id_usage && !strcmp(p->id_usage, "filesystem"))
+        return DEVICE_HARDDISK_VOL;
+
+    return DEVICE_UNKNOWN;
+}
+
+/* ########### */
+
+static void udisks_add_device(DBusConnection *ctx, const char *path)
+{
+    DBusMessage *reply;
+    properties_t p;
+    GUID guid;
+    GUID *guid_ptr = NULL;
+
+    TRACE("%s\n", debugstr_a(path));
+
+    reply = get_properties_from_path(&p, ctx, path);
+    if (reply)
+    {
+        int drive_type = get_drive_type(&p);
+
+        TRACE("DeviceFile: %s\n", p.device_file);
+        TRACE("IdUsage: %s\n", p.id_usage);
+        TRACE("IdType: %s\n", p.id_type);
+        TRACE("IdUuid: %s\n", p.id_uuid);
+        TRACE("DeviceIsMounted: %d (%s)\n", p.device_is_mounted, p.device_is_mounted ? "true" : "false");
+        TRACE("DeviceIsOpticalDisc: %d (%s)\n", p.device_is_optical_disc, p.device_is_optical_disc ? "true" : "false");
+        TRACE("DeviceIsRemovable: %d (%s)\n", p.device_is_removable, p.device_is_removable ? "true" : "false");
+        TRACE("DeviceMountPaths: %s\n", p.device_mount_paths);
+        TRACE("DriveMedia: %s\n", p.drive_media);
+        TRACE("DriveMediaCompatibility: %s\n", p.drive_media_compatibility);
+        TRACE("using drive_type: %d\n", drive_type);
+
+        if (p.device_is_mounted && p.device_mount_paths)
+        {
+            if (p.id_uuid)
+                guid_ptr = parse_uuid(&guid, p.id_uuid);
+
+            if (p.device_is_removable)
+                add_dos_device(-1, path, p.device_file, p.device_mount_paths, drive_type, guid_ptr);
+            else if (guid_ptr)
+                add_volume(path, p.device_file, p.device_mount_paths, DEVICE_HARDDISK_VOL, guid_ptr);
+
+        }
+        p_dbus_message_unref(reply);
+    }
+}
+
+static void udisks_remove_device(DBusConnection *ctx, const char *path)
+{
+    TRACE("%s\n", debugstr_a(path));
+
+    if (remove_dos_device(-1, path))
+        remove_volume(path);
+}
+
+static void udisks_change_device(DBusConnection *ctx, const char *path)
+{
+    DBusMessage *reply;
+    properties_t p;
+
+    TRACE("%s\n", debugstr_a(path));
+
+    reply = get_properties_from_path(&p, ctx, path);
+    if (reply)
+    {
+        int drive_type = get_drive_type(&p);
+
+        if (p.device_is_mounted && p.device_mount_paths)
+            udisks_add_device(ctx, path);
+        else
+        {
+            TRACE("DeviceFile: %s\n", p.device_file);
+            TRACE("IdUsage: %s\n", p.id_usage);
+            TRACE("IdType: %s\n", p.id_type);
+            TRACE("IdUuid: %s\n", p.id_uuid);
+            TRACE("DeviceIsMounted: %d (%s)\n", p.device_is_mounted, p.device_is_mounted ? "true" : "false");
+            TRACE("DeviceIsOpticalDisc: %d (%s)\n", p.device_is_optical_disc, p.device_is_optical_disc ? "true" : "false");
+            TRACE("DeviceIsRemovable: %d (%s)\n", p.device_is_removable, p.device_is_removable ? "true" : "false");
+            TRACE("DeviceMountPaths: %s\n", p.device_mount_paths);
+            TRACE("DriveMedia: %s\n", p.drive_media);
+            TRACE("DriveMediaCompatibility: %s\n", p.drive_media_compatibility);
+            TRACE("using drive_type: %d\n", drive_type);
+
+            udisks_remove_device(ctx, path);
+        }
+        p_dbus_message_unref(reply);
+    }
+}
+
+/* ########### */
+
+static void udisks_get_all_devices(DBusConnection *ctx)
+{
+    DBusMessage *request;
+    DBusMessage *reply;
+    DBusMessageIter iter;
+    DBusMessageIter sub;
+    DBusError error;
+    int arg_type;
+
+    request = p_dbus_message_new_method_call(dest_udisks, path_udisks, dest_udisks, "EnumerateDevices");
+    if (request)
+    {
+        p_dbus_error_init(&error);
+        if ((reply = p_dbus_connection_send_with_reply_and_block(ctx, request, -1, &error)))
+        {
+            p_dbus_message_iter_init(reply, &iter);
+            arg_type = p_dbus_message_iter_get_arg_type(&iter);
+            if (arg_type == DBUS_TYPE_ARRAY)
+            {
+                p_dbus_message_iter_recurse(&iter, &sub);
+                while ((arg_type = p_dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_OBJECT_PATH)
+                {
+                    char * data;
+                    p_dbus_message_iter_get_basic(&sub, &data);
+                    udisks_add_device(ctx, data);
+                    p_dbus_message_iter_next(&sub);
+                }
+            }
+            else
+                WARN("expected ARRAY, got %c\n", arg_type);
+
+            p_dbus_message_unref(reply);
+        }
+        p_dbus_error_free(&error);
+        p_dbus_message_unref(request);
+    }
+}
+
+/* ########## */
+
+static void udisks_get_version(DBusConnection *ctx)
+{
+    DBusMessage *request;
+    DBusMessage *reply;
+    DBusMessageIter iter;
+    DBusMessageIter sub;
+    DBusError error;
+    int arg_type;
+
+    request = p_dbus_message_new_method_call(dest_udisks, path_udisks, iface_dbus_prop, "Get");
+    if (request)
+    {
+        if (p_dbus_message_append_args(request, DBUS_TYPE_STRING, &dest_udisks,
+                                                DBUS_TYPE_STRING, &daemonversion,
+                                                DBUS_TYPE_INVALID))
+        {
+            p_dbus_error_init(&error);
+            if ((reply = p_dbus_connection_send_with_reply_and_block(ctx, request, -1, &error)))
+            {
+                p_dbus_message_iter_init(reply, &iter);
+                arg_type = p_dbus_message_iter_get_arg_type(&iter);
+                if (arg_type == DBUS_TYPE_VARIANT)
+                {
+                    p_dbus_message_iter_recurse(&iter, &sub);
+                    arg_type = p_dbus_message_iter_get_arg_type(&sub);
+                    if (arg_type == DBUS_TYPE_STRING)
+                    {
+                        char * data;
+                        p_dbus_message_iter_get_basic(&sub, &data);
+                        lstrcpynA(udisks_version, data, sizeof(udisks_version) - 1);
+                        TRACE("found udisks daemon %s\n", udisks_version);
+                    }
+                    else
+                        WARN("expected STRING, got %c\n", arg_type);
+
+                }
+                else
+                    WARN("expected VARIANT, got %c\n", arg_type);
+
+                p_dbus_message_unref(reply);
+            }
+            p_dbus_error_free(&error);
+        }
+        else
+            WARN("dbus_message_append_args failed\n");
+
+        p_dbus_message_unref(request);
+    }
+    return;
+
+}
+
+/* ##### */
+
+static DWORD WINAPI udisks_thread( void *arg )
+{
+    DBusConnection *ctx;
+    DBusMessage *msg;
+    DBusMessageIter iter;
+    DBusError error;
+    const char *member;
+    int arg_type;
+    char *data;
+
+    p_dbus_error_init(&error);
+    ctx = p_dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+
+    if (!ctx)
+    {
+        SetEvent(dbus_present);     /* wakeup hal support */
+        WARN("failed to get system dbus connection: %s\n", error.message);
+        p_dbus_error_free(&error);
+        return 1;
+    }
+
+    p_dbus_bus_add_match(ctx, my_match_rule, &error);
+    if (p_dbus_error_is_set(&error))
+    {
+        SetEvent(dbus_present);     /* wakeup hal support */
+        WARN("add dbus filter failed: %s\n", error.message);
+        p_dbus_error_free(&error);
+        p_dbus_connection_unref(ctx);
+        return 1;
+    }
+
+    udisks_get_version(ctx);
+    SetEvent(dbus_present);         /* wakeup hal support */
+
+    if (!*udisks_version)
+    {
+        TRACE("udisks service not available\n");
+        p_dbus_bus_remove_match(ctx, my_match_rule, NULL);
+        p_dbus_error_free(&error);
+        p_dbus_connection_unref(ctx);
+        return 1;
+    }
+
+    __TRY
+    {
+        /* retrieve all existing devices */
+        udisks_get_all_devices(ctx);
+
+        while (p_dbus_connection_read_write_dispatch(ctx, -1 ))
+        {
+            while ((msg = p_dbus_connection_pop_message(ctx)))
+            {
+                member = p_dbus_message_get_member(msg);
+                p_dbus_message_iter_init(msg, &iter);
+                arg_type = p_dbus_message_iter_get_arg_type(&iter);
+
+                if (arg_type == DBUS_TYPE_OBJECT_PATH)
+                    p_dbus_message_iter_get_basic(&iter, &data);
+
+                if (!lstrcmpA(member, "DeviceChanged"))
+                    udisks_change_device(ctx, data);
+                else if (!lstrcmpA(member, "DeviceAdded"))
+                    udisks_add_device(ctx, data);
+                else if (!lstrcmpA(member, "DeviceRemoved"))
+                    udisks_remove_device(ctx, data);
+                else if (lstrcmpA(member, "DeviceJobChanged"))
+                    WARN("got signal for %s\n", member);
+
+                p_dbus_message_unref(msg);
+            }
+        }
+    }
+    __EXCEPT(assert_fault)
+    {
+        WARN("dbus assertion failure, disabling UDisks support\n");
+        return 1;
+    }
+    __ENDTRY;
+
+    p_dbus_bus_remove_match(ctx, my_match_rule, NULL);
+    p_dbus_error_free(&error);
+    p_dbus_connection_unref(ctx);
+    return 0;
+}
+
+void initialize_udisks(void)
+{
+    HANDLE handle = NULL;
+
+    dbus_present = NULL;
+    *udisks_version = 0;
+    if (!load_dbus_functions()) return;
+
+    /* delay hal support, start udisks thread */
+    if (!(dbus_present = CreateEventW(NULL, TRUE, FALSE, NULL)) ||
+        !(handle = CreateThread(NULL, 0, udisks_thread, NULL, 0, NULL)))
+    {
+        /* something failed: wakeup hal now */
+        if (dbus_present) SetEvent(dbus_present);
+        return;
+    }
+    CloseHandle(handle);
+}
+
+#else   /* SONAME_LIBDBUS_1 */
+
+void initialize_udisks(void)
+{
+    TRACE("Skipping, DBUS support not compiled in\n");
+}
+
+#endif  /* SONAME_LIBDBUS_1 */
-- 
1.7.5.4




More information about the wine-patches mailing list