From 95615a4afbac69b171d54533a4494e43f7811b55 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 26 Nov 2021 15:38:17 +0100 Subject: [PATCH] mountmgr: Move the DBus support to the Unix library. Signed-off-by: Alexandre Julliard --- dlls/mountmgr.sys/dbus.c | 134 +++++++++++++++++------------------ dlls/mountmgr.sys/mountmgr.c | 50 ++++++++++++- dlls/mountmgr.sys/mountmgr.h | 3 +- dlls/mountmgr.sys/unixlib.c | 67 ++++++++++++++++++ dlls/mountmgr.sys/unixlib.h | 55 ++++++++++++++ 5 files changed, 238 insertions(+), 71 deletions(-) diff --git a/dlls/mountmgr.sys/dbus.c b/dlls/mountmgr.sys/dbus.c index 2b0e269ead3..43f79d39034 100644 --- a/dlls/mountmgr.sys/dbus.c +++ b/dlls/mountmgr.sys/dbus.c @@ -18,27 +18,29 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "config.h" -#include "wine/port.h" +#if 0 +#pragma makedep unix +#endif + +#include "config.h" -#include #include #include #include +#include +#include +#include +#include #ifdef SONAME_LIBDBUS_1 # include #endif #include "mountmgr.h" -#include "winnls.h" -#include "excpt.h" #define USE_WS_PREFIX #include "winsock2.h" -#include "ws2ipdef.h" -#include "ip2string.h" #include "dhcpcsdk.h" +#include "unixlib.h" -#include "wine/exception.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(mountmgr); @@ -82,13 +84,6 @@ DBUS_FUNCS; static int udisks_timeout = -1; static DBusConnection *connection; -static LONG WINAPI assert_fault(EXCEPTION_POINTERS *eptr) -{ - if (eptr->ExceptionRecord->ExceptionCode == EXCEPTION_WINE_ASSERTION) - return EXCEPTION_EXECUTE_HANDLER; - return EXCEPTION_CONTINUE_SEARCH; -} - static inline int starts_with( const char *str, const char *prefix ) { return !strncmp( str, prefix, strlen(prefix) ); @@ -97,19 +92,32 @@ static inline int starts_with( const char *str, const char *prefix ) static GUID *parse_uuid( GUID *guid, const char *str ) { /* standard uuid format */ - if (strlen(str) == 36) + if (strlen(str) == 36 && str[8] == '-' && str[13] == '-' && str[18] == '-' && str[23] == '-') { - UNICODE_STRING strW; - WCHAR buffer[39]; + int i; + unsigned char *out = guid->Data4; - if (MultiByteToWideChar( CP_UNIXCP, 0, str, 36, buffer + 1, 36 )) + if (sscanf( str, "%x-%hx-%hx-", &guid->Data1, &guid->Data2, &guid->Data3 ) != 3) return NULL; + for (i = 19; i < 36; i++) { - buffer[0] = '{'; - buffer[37] = '}'; - buffer[38] = 0; - RtlInitUnicodeString( &strW, buffer ); - if (!RtlGUIDFromString( &strW, guid )) return guid; + unsigned char val; + + if (i == 23) continue; + + if (str[i] >= '0' && str[i] <= '9') val = str[i] - '0'; + else if (str[i] >= 'a' && str[i] <= 'f') val = str[i] - 'a' + 10; + else if (str[i] >= 'A' && str[i] <= 'F') val = str[i] - 'A' + 10; + else return NULL; + val <<= 4; + i++; + + if (str[i] >= '0' && str[i] <= '9') val += str[i] - '0'; + else if (str[i] >= 'a' && str[i] <= 'f') val += str[i] - 'a' + 10; + else if (str[i] >= 'A' && str[i] <= 'F') val += str[i] - 'A' + 10; + else return NULL; + *out++ = val; } + return guid; } /* check for xxxx-xxxx format (FAT serial number) */ @@ -257,8 +265,8 @@ static void udisks_new_device( const char *udi ) if (device) { - if (removable) add_dos_device( -1, udi, device, mount_point, drive_type, guid_ptr, NULL ); - else if (guid_ptr) add_volume( udi, device, mount_point, DEVICE_HARDDISK_VOL, guid_ptr, NULL, NULL ); + if (removable) queue_device_op( ADD_DOS_DEVICE, udi, device, mount_point, drive_type, guid_ptr, NULL, NULL ); + else if (guid_ptr) queue_device_op( ADD_VOLUME, udi, device, mount_point, DEVICE_HARDDISK_VOL, guid_ptr, NULL, NULL ); } p_dbus_message_unref( reply ); @@ -268,8 +276,7 @@ static void udisks_new_device( const char *udi ) static void udisks_removed_device( const char *udi ) { TRACE( "removed %s\n", wine_dbgstr_a(udi) ); - - if (!remove_dos_device( -1, udi )) remove_volume( udi ); + queue_device_op( REMOVE_DEVICE, udi, NULL, NULL, 0, NULL, NULL, NULL ); } /* UDisks callback for changed device */ @@ -426,8 +433,8 @@ static void udisks2_add_device( const char *udi, DBusMessageIter *dict, DBusMess } if (device) { - if (removable) add_dos_device( -1, udi, device, mount_point, drive_type, guid_ptr, NULL ); - else if (guid_ptr) add_volume( udi, device, mount_point, DEVICE_HARDDISK_VOL, guid_ptr, id, NULL ); + if (removable) queue_device_op( ADD_DOS_DEVICE, udi, device, mount_point, drive_type, guid_ptr, id, NULL ); + else if (guid_ptr) queue_device_op( ADD_VOLUME, udi, device, mount_point, DEVICE_HARDDISK_VOL, guid_ptr, id, NULL ); } } @@ -522,7 +529,7 @@ static DBusHandlerResult udisks_filter( DBusConnection *ctx, DBusMessage *msg, v return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -static DWORD WINAPI dbus_thread( void *arg ) +void run_dbus_loop(void) { static const char udisks_match[] = "type='signal'," "interface='org.freedesktop.UDisks'," @@ -536,12 +543,14 @@ static DWORD WINAPI dbus_thread( void *arg ) DBusError error; + if (!load_dbus_functions()) return; + p_dbus_error_init( &error ); if (!(connection = p_dbus_bus_get( DBUS_BUS_SYSTEM, &error ))) { WARN( "failed to get system dbus connection: %s\n", error.message ); p_dbus_error_free( &error ); - return 1; + return; } /* first try UDisks2 */ @@ -561,27 +570,7 @@ static DWORD WINAPI dbus_thread( void *arg ) p_dbus_connection_remove_filter( connection, udisks_filter, NULL ); found: - __TRY - { - while (p_dbus_connection_read_write_dispatch( connection, -1 )) /* nothing */ ; - } - __EXCEPT( assert_fault ) - { - WARN( "dbus assertion failure, disabling support\n" ); - return 1; - } - __ENDTRY; - - return 0; -} - -void initialize_dbus(void) -{ - HANDLE handle; - - if (!load_dbus_functions()) return; - if (!(handle = CreateThread( NULL, 0, dbus_thread, NULL, 0, NULL ))) return; - CloseHandle( handle ); + while (p_dbus_connection_read_write_dispatch( connection, -1 )) /* nothing */ ; } #if !defined(HAVE_SYSTEMCONFIGURATION_SCDYNAMICSTORECOPYDHCPINFO_H) || !defined(HAVE_SYSTEMCONFIGURATION_SCNETWORKCONFIGURATION_H) @@ -776,28 +765,29 @@ static const char *map_option( ULONG option ) } } -ULONG get_dhcp_request_param( const char *unix_name, struct mountmgr_dhcp_request_param *param, char *buf, ULONG offset, - ULONG size ) +NTSTATUS dhcp_request( void *args ) { + const struct dhcp_request_params *params = args; DBusMessage *reply; const char *value; ULONG ret = 0; - param->offset = param->size = 0; + params->req->offset = params->req->size = 0; - if (!(reply = dhcp4_config_option_request( unix_name, map_option(param->id), &value ))) return 0; + if (!(reply = dhcp4_config_option_request( params->unix_name, map_option(params->req->id), &value ))) return 0; - switch (param->id) + switch (params->req->id) { case OPTION_SUBNET_MASK: case OPTION_ROUTER_ADDRESS: case OPTION_BROADCAST_ADDRESS: { - IN_ADDR *ptr = (IN_ADDR *)(buf + offset); - if (value && size >= sizeof(IN_ADDR) && !RtlIpv4StringToAddressA( value, TRUE, NULL, ptr )) + IN_ADDR *ptr = (IN_ADDR *)(params->buffer + params->offset); + if (value && params->size >= sizeof(IN_ADDR)) { - param->offset = offset; - param->size = sizeof(*ptr); + ptr->S_un.S_addr = inet_addr( value ); + params->req->offset = params->offset; + params->req->size = sizeof(*ptr); TRACE( "returning %08x\n", *(DWORD *)ptr ); } ret = sizeof(*ptr); @@ -807,33 +797,39 @@ ULONG get_dhcp_request_param( const char *unix_name, struct mountmgr_dhcp_reques case OPTION_DOMAIN_NAME: case OPTION_MSFT_IE_PROXY: { - char *ptr = buf + offset; + char *ptr = params->buffer + params->offset; int len = value ? strlen( value ) : 0; - if (len && size >= len) + if (len && params->size >= len) { memcpy( ptr, value, len ); - param->offset = offset; - param->size = len; + params->req->offset = params->offset; + params->req->size = len; TRACE( "returning %s\n", debugstr_an(ptr, len) ); } ret = len; break; } default: - FIXME( "option %u not supported\n", param->id ); + FIXME( "option %u not supported\n", params->req->id ); break; } p_dbus_message_unref( reply ); - return ret; + *params->ret_size = ret; + return STATUS_SUCCESS; } #endif #else /* SONAME_LIBDBUS_1 */ -void initialize_dbus(void) +void run_dbus_loop(void) { TRACE( "Skipping, DBUS support not compiled in\n" ); } +NTSTATUS dhcp_request( void *args ) +{ + return STATUS_NOT_SUPPORTED; +} + #endif /* SONAME_LIBDBUS_1 */ diff --git a/dlls/mountmgr.sys/mountmgr.c b/dlls/mountmgr.sys/mountmgr.c index 31ad073d8c7..8aeaee8dc04 100644 --- a/dlls/mountmgr.sys/mountmgr.c +++ b/dlls/mountmgr.sys/mountmgr.c @@ -408,7 +408,15 @@ static void WINAPI query_dhcp_request_params( TP_CALLBACK_INSTANCE *instance, vo offset = FIELD_OFFSET(struct mountmgr_dhcp_request_params, params[query->count]); for (i = 0; i < query->count; i++) { +#ifdef __APPLE__ offset += get_dhcp_request_param( query->unix_name, &query->params[i], (char *)query, offset, outsize - offset ); +#else + ULONG ret_size; + struct dhcp_request_params params = { query->unix_name, &query->params[i], + (char *)query, offset, outsize - offset, &ret_size }; + MOUNTMGR_CALL( dhcp_request, ¶ms ); + offset += ret_size; +#endif if (offset > outsize) { if (offset >= sizeof(query->size)) query->size = offset; @@ -438,6 +446,30 @@ static void WINAPI query_symbol_file_callback( TP_CALLBACK_INSTANCE *instance, v IoCompleteRequest( irp, IO_NO_INCREMENT ); } +/* NT APC called from Unix side to add/remove devices */ +static void CALLBACK device_op( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 ) +{ + struct device_info info; + struct dequeue_device_op_params params = { arg1, &info }; + + if (MOUNTMGR_CALL( dequeue_device_op, ¶ms )) return; + + switch (info.op) + { + case ADD_DOS_DEVICE: + add_dos_device( -1, info.udi, info.device, info.mount_point, + info.type, info.guid, info.scsi_info ); + break; + case ADD_VOLUME: + add_volume( info.udi, info.device, info.mount_point, DEVICE_HARDDISK_VOL, + info.guid, info.serial, info.scsi_info ); + break; + case REMOVE_DEVICE: + if (!remove_dos_device( -1, info.udi )) remove_volume( info.udi ); + break; + } +} + /* handler for ioctls on the mount manager device */ static NTSTATUS WINAPI mountmgr_ioctl( DEVICE_OBJECT *device, IRP *irp ) { @@ -579,6 +611,18 @@ static NTSTATUS WINAPI mountmgr_ioctl( DEVICE_OBJECT *device, IRP *irp ) return status; } +static DWORD WINAPI device_op_thread( void *arg ) +{ + for (;;) SleepEx( INFINITE, TRUE ); /* wait for APCs */ + return 0; +} + +static DWORD WINAPI run_loop_thread( void *arg ) +{ + return MOUNTMGR_CALL( run_loop, arg ); +} + + /* main entry point for the mount point manager driver */ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) { @@ -606,6 +650,7 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) DEVICE_OBJECT *device; HKEY devicemap_key; NTSTATUS status; + struct run_loop_params params; TRACE( "%s\n", debugstr_w(path->Buffer) ); @@ -636,7 +681,10 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) RtlInitUnicodeString( &nameW, harddiskW ); status = IoCreateDriver( &nameW, harddisk_driver_entry ); - initialize_dbus(); + params.op_thread = CreateThread( NULL, 0, device_op_thread, NULL, 0, NULL ); + params.op_apc = device_op; + CloseHandle( CreateThread( NULL, 0, run_loop_thread, ¶ms, 0, NULL )); + initialize_diskarbitration(); #ifdef _WIN64 diff --git a/dlls/mountmgr.sys/mountmgr.h b/dlls/mountmgr.sys/mountmgr.h index 520055f3fb8..c3557d7e548 100644 --- a/dlls/mountmgr.sys/mountmgr.h +++ b/dlls/mountmgr.sys/mountmgr.h @@ -36,7 +36,6 @@ #define WINE_MOUNTMGR_EXTENSIONS #include "ddk/mountmgr.h" -extern void initialize_dbus(void) DECLSPEC_HIDDEN; extern void initialize_diskarbitration(void) DECLSPEC_HIDDEN; extern WCHAR *strdupW( const WCHAR * ) DECLSPEC_HIDDEN; @@ -115,6 +114,8 @@ extern struct mount_point *add_volume_mount_point( DEVICE_OBJECT *device, UNICOD extern void delete_mount_point( struct mount_point *mount ) DECLSPEC_HIDDEN; extern void set_mount_point_id( struct mount_point *mount, const void *id, unsigned int id_len ) DECLSPEC_HIDDEN; +#ifdef __APPLE__ extern ULONG get_dhcp_request_param( const char *unix_name, struct mountmgr_dhcp_request_param *param, char *buf, ULONG offset, ULONG size ) DECLSPEC_HIDDEN; +#endif #endif /* __WINE_MOUNTMGR_H */ diff --git a/dlls/mountmgr.sys/unixlib.c b/dlls/mountmgr.sys/unixlib.c index 7b14e2a8a15..caecb0140a8 100644 --- a/dlls/mountmgr.sys/unixlib.c +++ b/dlls/mountmgr.sys/unixlib.c @@ -34,6 +34,7 @@ #include "unixlib.h" +static struct run_loop_params run_loop_params; static char *get_dosdevices_path( const char *dev ) { @@ -87,6 +88,69 @@ static void detect_devices( const char **paths, char *names, ULONG size ) *names = 0; } +void queue_device_op( enum device_op op, const char *udi, const char *device, + const char *mount_point, enum device_type type, const GUID *guid, + const char *serial, const struct scsi_info *scsi_info ) +{ + struct device_info *info; + char *str, *end; + + info = calloc( 1, sizeof(*info) ); + str = info->str_buffer; + end = info->str_buffer + sizeof(info->str_buffer); + info->op = op; + info->type = type; +#define ADD_STR(s) if (s && str + strlen(s) + 1 <= end) \ + { \ + info->s = strcpy( str, s ); \ + str += strlen(str) + 1; \ + } + ADD_STR(udi); + ADD_STR(device); + ADD_STR(mount_point); + ADD_STR(serial); +#undef ADD_STR + if (guid) + { + info->guid_buffer = *guid; + info->guid = &info->guid_buffer; + } + if (scsi_info) + { + info->scsi_buffer = *scsi_info; + info->scsi_info = &info->scsi_buffer; + } + NtQueueApcThread( run_loop_params.op_thread, run_loop_params.op_apc, (ULONG_PTR)info, 0, 0 ); +} + +static NTSTATUS run_loop( void *args ) +{ + const struct run_loop_params *params = args; + + run_loop_params = *params; + run_dbus_loop(); + return STATUS_SUCCESS; +} + +static NTSTATUS dequeue_device_op( void *args ) +{ + const struct dequeue_device_op_params *params = args; + struct device_info *src = (struct device_info *)params->arg; + struct device_info *dst = params->info; + + /* copy info to client address space and fix up pointers */ + *dst = *src; + if (dst->udi) dst->udi = (char *)dst + (src->udi - (char *)src); + if (dst->device) dst->device = (char *)dst + (src->device - (char *)src); + if (dst->mount_point) dst->mount_point = (char *)dst + (src->mount_point - (char *)src); + if (dst->serial) dst->serial = (char *)dst + (src->serial - (char *)src); + if (dst->guid) dst->guid = &dst->guid_buffer; + if (dst->scsi_info) dst->scsi_info = &dst->scsi_buffer; + + free( src ); + return STATUS_SUCCESS; +} + /* find or create a DOS drive for the corresponding Unix device */ static NTSTATUS add_drive( void *args ) { @@ -361,6 +425,8 @@ static NTSTATUS get_shell_folder( void *args ) const unixlib_entry_t __wine_unix_call_funcs[] = { + run_loop, + dequeue_device_op, add_drive, get_dosdev_symlink, set_dosdev_symlink, @@ -371,4 +437,5 @@ const unixlib_entry_t __wine_unix_call_funcs[] = detect_parallel_ports, set_shell_folder, get_shell_folder, + dhcp_request, }; diff --git a/dlls/mountmgr.sys/unixlib.h b/dlls/mountmgr.sys/unixlib.h index e7a72857846..afaed5fa559 100644 --- a/dlls/mountmgr.sys/unixlib.h +++ b/dlls/mountmgr.sys/unixlib.h @@ -21,6 +21,42 @@ #include "mountmgr.h" #include "wine/unixlib.h" +enum device_op +{ + ADD_DOS_DEVICE, + ADD_VOLUME, + REMOVE_DEVICE +}; + +struct device_info +{ + enum device_op op; + enum device_type type; + const char *udi; + const char *device; + const char *mount_point; + const char *serial; + GUID *guid; + struct scsi_info *scsi_info; + + /* buffer space for pointers */ + GUID guid_buffer; + struct scsi_info scsi_buffer; + char str_buffer[1024]; +}; + +struct run_loop_params +{ + HANDLE op_thread; + PNTAPCFUNC op_apc; +}; + +struct dequeue_device_op_params +{ + ULONG_PTR arg; + struct device_info *info; +}; + struct add_drive_params { const char *device; @@ -81,8 +117,20 @@ struct get_shell_folder_params ULONG size; }; +struct dhcp_request_params +{ + const char *unix_name; + struct mountmgr_dhcp_request_param *req; + char *buffer; + ULONG offset; + ULONG size; + ULONG *ret_size; +}; + enum mountmgr_funcs { + unix_run_loop, + unix_dequeue_device_op, unix_add_drive, unix_get_dosdev_symlink, unix_set_dosdev_symlink, @@ -93,12 +141,19 @@ enum mountmgr_funcs unix_detect_parallel_ports, unix_set_shell_folder, unix_get_shell_folder, + unix_dhcp_request, }; extern unixlib_handle_t mountmgr_handle; #define MOUNTMGR_CALL( func, params ) __wine_unix_call( mountmgr_handle, unix_ ## func, params ) +extern void queue_device_op( enum device_op op, const char *udi, const char *device, + const char *mount_point, enum device_type type, const GUID *guid, + const char *disk_serial, const struct scsi_info *info ) DECLSPEC_HIDDEN; +extern void run_dbus_loop(void) DECLSPEC_HIDDEN; + +extern NTSTATUS dhcp_request( void *args ) DECLSPEC_HIDDEN; extern NTSTATUS query_symbol_file( void *buff, ULONG insize, ULONG outsize, ULONG *info ) DECLSPEC_HIDDEN; extern NTSTATUS read_credential( void *buff, ULONG insize, ULONG outsize, ULONG *info ) DECLSPEC_HIDDEN; extern NTSTATUS write_credential( void *buff, ULONG insize, ULONG outsize, ULONG *info ) DECLSPEC_HIDDEN;