From 8afdf4041b8d73e4818e6ae932af82297fde4be2 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Fri, 7 Mar 2008 14:57:53 -0800 Subject: [PATCH] mountmgr.sys: Integrate hal with the rest of the device manager --- dlls/mountmgr.sys/diskarb.c | 2 +- dlls/mountmgr.sys/hal.c | 103 +++++++---- dlls/mountmgr.sys/mountmgr.c | 391 +++++++++++++++++++++++++---------------- dlls/mountmgr.sys/mountmgr.h | 2 +- 4 files changed, 307 insertions(+), 191 deletions(-) diff --git a/dlls/mountmgr.sys/diskarb.c b/dlls/mountmgr.sys/diskarb.c index d5f3d61..bcac5eb 100644 --- a/dlls/mountmgr.sys/diskarb.c +++ b/dlls/mountmgr.sys/diskarb.c @@ -74,7 +74,7 @@ static void appeared_callback( DADiskRef disk, void *context ) TRACE( "got mount notification for '%s' on '%s'\n", device, mount_point ); - add_dos_device( device, device, mount_point, type ); + add_dos_device( device, NULL, device, mount_point, type ); done: CFRelease( dict ); } diff --git a/dlls/mountmgr.sys/hal.c b/dlls/mountmgr.sys/hal.c index 615edf0..5a04ae5 100644 --- a/dlls/mountmgr.sys/hal.c +++ b/dlls/mountmgr.sys/hal.c @@ -19,6 +19,8 @@ */ #include "config.h" +#define NONAMELESSUNION +#define NONAMELESSSTRUCT #include "wine/port.h" #include @@ -27,11 +29,20 @@ #include #include +#include "ntstatus.h" +#define WIN32_NO_STATUS #include "windef.h" #include "winbase.h" +#include "winternl.h" +#include "winioctl.h" #include "winreg.h" #include "winuser.h" -#include "excpt.h" +#include "setupapi.h" +#include "ddk/wdm.h" +#include "ddk/mountmgr.h" +#include "initguid.h" +#include "ntddstor.h" +#include "ntddcdrm.h" #include "wine/library.h" #include "wine/exception.h" @@ -117,6 +128,8 @@ static void new_device( LibHalContext *ctx, const char *udi ) char *mount_point = NULL; char *device = NULL; char *type = NULL; + char *filesystem = NULL; + char *parent_block = NULL; p_dbus_error_init( &error ); @@ -135,12 +148,23 @@ static void new_device( LibHalContext *ctx, const char *udi ) if (!(type = p_libhal_device_get_property_string( ctx, parent, "storage.drive_type", &error ))) p_dbus_error_free( &error ); /* ignore error */ - add_dos_device( udi, device, mount_point, type ); + filesystem = p_libhal_device_get_property_string( ctx, udi, "volume.fstype", NULL ); + if ((!type || strcasecmp(type, "cdrom")) && (!filesystem || !filesystem[0])) + goto done; + + if (mount_point[0]) + { + parent_block = p_libhal_device_get_property_string( ctx, parent, "block.device", NULL ); + add_dos_device( udi, parent_block, device, mount_point, type ); + if (parent_block) p_libhal_free_string( parent_block ); + } + else remove_dos_device( udi ); /* add property watch for mount point */ p_libhal_device_add_property_watch( ctx, udi, &error ); done: + if (filesystem) p_libhal_free_string( filesystem ); if (type) p_libhal_free_string( type ); if (parent) p_libhal_free_string( parent ); if (device) p_libhal_free_string( device ); @@ -173,23 +197,51 @@ static void property_modified (LibHalContext *ctx, const char *udi, if (!strcmp( key, "volume.mount_point" )) new_device( ctx, udi ); } +static DBusError error; +static DBusConnection *dbc; +static LibHalContext *ctx; +static int i, num; +static char **list; + +static void hal_cleanup(void) +{ + p_libhal_ctx_shutdown( ctx, &error ); + p_dbus_error_free( &error ); /* just in case */ + p_dbus_connection_close( dbc ); + p_libhal_ctx_free( ctx ); +} static DWORD WINAPI hal_thread( void *arg ) { - DBusError error; - DBusConnection *dbc; - LibHalContext *ctx; - int i, num; - char **list; + __TRY + { + while (p_dbus_connection_read_write_dispatch( dbc, -1 )) /* nothing */ ; + } + __EXCEPT( assert_fault ) + { + WARN( "dbus assertion failure, disabling HAL support\n" ); + return 1; + } + __ENDTRY; + + hal_cleanup(); + return 0; +} + +void initialize_hal(void) +{ + HANDLE handle; + + if (!load_functions()) return; - if (!(ctx = p_libhal_ctx_new())) return 1; + if (!(ctx = p_libhal_ctx_new())) return; p_dbus_error_init( &error ); if (!(dbc = 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; } p_libhal_ctx_set_dbus_connection( ctx, dbc ); @@ -201,10 +253,10 @@ static DWORD WINAPI hal_thread( void *arg ) { WARN( "HAL context init failed: %s\n", error.message ); p_dbus_error_free( &error ); - return 1; + return; } - /* retrieve all existing devices */ + /* retrieve all existing devices, we really need to have completed this prior to returning */ if (!(list = p_libhal_get_all_devices( ctx, &num, &error ))) p_dbus_error_free( &error ); else { @@ -212,31 +264,10 @@ static DWORD WINAPI hal_thread( void *arg ) p_libhal_free_string_array( list ); } - __TRY - { - while (p_dbus_connection_read_write_dispatch( dbc, -1 )) /* nothing */ ; - } - __EXCEPT( assert_fault ) - { - WARN( "dbus assertion failure, disabling HAL support\n" ); - return 1; - } - __ENDTRY; - - p_libhal_ctx_shutdown( ctx, &error ); - p_dbus_error_free( &error ); /* just in case */ - p_dbus_connection_close( dbc ); - p_libhal_ctx_free( ctx ); - return 0; -} - -void initialize_hal(void) -{ - HANDLE handle; - - if (!load_functions()) return; - if (!(handle = CreateThread( NULL, 0, hal_thread, NULL, 0, NULL ))) return; - CloseHandle( handle ); + if ((handle = CreateThread( NULL, 0, hal_thread, NULL, 0, NULL ))) + CloseHandle( handle ); + else /* Clean up from failing */ + hal_cleanup(); } #else /* SONAME_LIBHAL */ diff --git a/dlls/mountmgr.sys/mountmgr.c b/dlls/mountmgr.sys/mountmgr.c index dd40f6a..ebba481 100644 --- a/dlls/mountmgr.sys/mountmgr.c +++ b/dlls/mountmgr.sys/mountmgr.c @@ -54,7 +54,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mountmgr); #define MAX_DOS_DRIVES 26 -#define MAX_MOUNT_POINTS (2 * MAX_DOS_DRIVES) +#define MAX_MOUNT_POINTS 2*MAX_DOS_DRIVES /* extra info for disk devices, stored in DeviceExtension */ struct disk_device_info @@ -62,6 +62,7 @@ struct disk_device_info UNICODE_STRING name; /* device name */ STORAGE_DEVICE_NUMBER devnum; /* device number info */ ULONG partitioncount; /* extension for primary harddisk: Keep track of partition count */ + char *dev_node; }; struct mount_point @@ -70,20 +71,26 @@ struct mount_point UNICODE_STRING link; /* DOS device symlink */ void *id; /* device unique id */ unsigned int id_len; + DEVICE_OBJECT *parent; }; -struct dos_drive -{ - struct list entry; - char *udi; - int drive; -}; - -static struct list drives_list = LIST_INIT(drives_list); - static struct mount_point mount_points[MAX_MOUNT_POINTS]; -static HKEY mount_key; +static HKEY mount_key, drive_key; static ULONG globaldevicenumber; +static unsigned initializing; +static DEVICE_OBJECT *harddisk0; +static DRIVER_OBJECT *hddriver; + +static const WCHAR drive_types[][8] = +{ + { 0 }, /* DRIVE_UNKNOWN */ + { 0 }, /* DRIVE_NO_ROOT_DIR */ + {'f','l','o','p','p','y',0}, /* DRIVE_REMOVABLE */ + {'h','d',0}, /* DRIVE_FIXED */ + {'n','e','t','w','o','r','k',0}, /* DRIVE_REMOTE */ + {'c','d','r','o','m',0}, /* DRIVE_CDROM */ + {'r','a','m','d','i','s','k',0} /* DRIVE_RAMDISK */ +}; static inline UNICODE_STRING *get_device_name( DEVICE_OBJECT *dev ) { @@ -174,6 +181,7 @@ static NTSTATUS create_disk_device( DRIVER_OBJECT *driver, DWORD type, DEVICE_OB } info->devnum.DeviceNumber = devicenumber; info->devnum.PartitionNumber = disknumber; + info->dev_node = NULL; } else { @@ -184,7 +192,7 @@ static NTSTATUS create_disk_device( DRIVER_OBJECT *driver, DWORD type, DEVICE_OB } -static NTSTATUS add_mount_point( DEVICE_OBJECT *device, DRIVER_OBJECT *driver, DWORD type, int drive, +static NTSTATUS add_mount_point( DEVICE_OBJECT *device, DRIVER_OBJECT *driver, int drive, const void *id, unsigned int id_len ) { static const WCHAR driveW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\','%','c',':',0}; @@ -192,30 +200,29 @@ static NTSTATUS add_mount_point( DEVICE_OBJECT *device, DRIVER_OBJECT *driver, D '%','0','8','x','-','%','0','4','x','-','%','0','4','x','-', '%','0','2','x','%','0','2','x','-','%','0','2','x','%','0','2','x', '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','}',0}; + WCHAR disk[4] = {'A',':','\\',0}; WCHAR *drive_link, *volume_link; + WCHAR strtype[8]; NTSTATUS status; GUID guid; - UINT i; struct mount_point *mount_drive = NULL, *mount_volume = NULL; struct disk_device_info *info = device->DeviceExtension; LONG devnumberused; LONG partnumberused = ~0u; + DWORD type; + int i; + LONG size = sizeof(strtype); /* find two free mount points */ - for (i = 0; i < MAX_MOUNT_POINTS; i++) + mount_drive = mount_points + 2*drive; + mount_volume = mount_drive + 1; + + if (mount_drive->device || mount_volume->device) { - if (mount_points[i].device) continue; - if (!mount_drive) - { - mount_drive = &mount_points[i]; - continue; - } - mount_volume = &mount_points[i]; - break; + ERR("Apparantly this device (%c:) is already taken!\n", 'A'+drive); + return STATUS_NO_MEMORY; } - if (!mount_volume) return STATUS_NO_MEMORY; - /* create the volume */ memset( &guid, 0, sizeof(guid) ); /* FIXME */ @@ -230,6 +237,19 @@ static NTSTATUS add_mount_point( DEVICE_OBJECT *device, DRIVER_OBJECT *driver, D RtlInitUnicodeString( &mount_drive->link, drive_link ); RtlInitUnicodeString( &mount_volume->link, volume_link ); + disk[0] += drive; + + + RegQueryValueW(drive_key, disk, strtype, &size); + type = DRIVE_FIXED; + for (i = 0; i < sizeof(drive_types)/sizeof(drive_types[0]); i++) + { + if (!strcmpiW( strtype, drive_types[i] )) + { + type = i; + break; + } + } if (type == DRIVE_REMOVABLE || type == DRIVE_CDROM) devnumberused = globaldevicenumber++; else @@ -256,6 +276,7 @@ static NTSTATUS add_mount_point( DEVICE_OBJECT *device, DRIVER_OBJECT *driver, D IoCreateSymbolicLink( &mount_drive->link, get_device_name(mount_drive->device) ); IoCreateSymbolicLink( &mount_volume->link, get_device_name(mount_volume->device) ); + mount_drive->parent = mount_volume->parent = device; TRACE( "created device %s symlinks %s %s\n", debugstr_w(get_device_name(mount_drive->device)->Buffer), debugstr_w(mount_drive->link.Buffer), debugstr_w(mount_volume->link.Buffer) ); @@ -433,32 +454,50 @@ static NTSTATUS WINAPI harddisk_ioctl( DEVICE_OBJECT *device, IRP *irp ) return irp->IoStatus.u.Status; } +static char *get_dosdevices_path(void) +{ + const char *config_dir = wine_get_config_dir(); + size_t len = strlen(config_dir) + sizeof("/dosdevices/a::"); + char *path = RtlAllocateHeap( GetProcessHeap(), 0, len ); + if (path) + { + strcpy( path, config_dir ); + strcat( path, "/dosdevices/a::" ); + } + return path; +} + /* create mount points for mapped drives */ static void create_drive_mount_points( DEVICE_OBJECT *device, DRIVER_OBJECT *driver ) { - const char *config_dir = wine_get_config_dir(); char *buffer, *p, *link; unsigned int i; - if ((buffer = RtlAllocateHeap( GetProcessHeap(), 0, - strlen(config_dir) + sizeof("/dosdevices/a:") ))) - { - strcpy( buffer, config_dir ); - strcat( buffer, "/dosdevices/a:" ); - p = buffer + strlen(buffer) - 2; + buffer = get_dosdevices_path(); + if (!buffer) + return; + /* Remove the extra : */ + buffer[strlen(buffer)-1] = 0; - for (i = 0; i < MAX_DOS_DRIVES; i++) + p = buffer + strlen(buffer) - 2; + + for (i = 0; i < MAX_DOS_DRIVES; i++) + { + if (mount_points[i*2].device) { - *p = 'a' + i; - if (!(link = read_symlink( buffer ))) continue; - add_mount_point( device, driver, DRIVE_FIXED, i, link, strlen(link) ); - RtlFreeHeap( GetProcessHeap(), 0, link ); + TRACE("Drive %c: already exists, skipping\n", 'a'+i); + continue; } - RtlFreeHeap( GetProcessHeap(), 0, buffer ); + + *p = 'a' + i; + if (!(link = read_symlink( buffer ))) continue; + add_mount_point( device, driver, i, link, strlen(link) ); + RtlFreeHeap( GetProcessHeap(), 0, link ); } + RtlFreeHeap( GetProcessHeap(), 0, buffer ); } -static NTSTATUS WINAPI create_harddisk( DRIVER_OBJECT *driver, DEVICE_OBJECT **dev_obj ) +static NTSTATUS WINAPI create_harddisk( DRIVER_OBJECT *driver, DEVICE_OBJECT **dev_obj, const char *parent_device ) { static const WCHAR harddiskW[] = {'\\','D','e','v','i','c','e','\\','H','a','r','d','d','i','s','k','%','u',0}; static const WCHAR physdriveW[] = {'\\','?','?','\\','P','h','y','s','i','c','a','l','D','r','i','v','e','%','u',0}; @@ -494,6 +533,8 @@ static NTSTATUS WINAPI create_harddisk( DRIVER_OBJECT *driver, DEVICE_OBJECT **d info->devnum.DeviceNumber = globaldevicenumber++; info->devnum.PartitionNumber = 0; info->partitioncount = 0; + info->dev_node = RtlAllocateHeap(GetProcessHeap(), 0, strlen(parent_device)+1); + strcpy(info->dev_node, parent_device); } else { @@ -508,23 +549,33 @@ static NTSTATUS WINAPI harddisk_driver_entry( DRIVER_OBJECT *driver, UNICODE_STR { static const WCHAR mounted_devicesW[] = {'S','y','s','t','e','m','\\', 'M','o','u','n','t','e','d','D','e','v','i','c','e','s',0}; - DEVICE_OBJECT *device; + static const WCHAR wine_drivesW[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\', + 'D','r','i','v','e','s',0}; NTSTATUS status; driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = harddisk_ioctl; RegCreateKeyExW( HKEY_LOCAL_MACHINE, mounted_devicesW, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &mount_key, NULL ); + RegCreateKeyExW( HKEY_LOCAL_MACHINE, wine_drivesW, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &drive_key, NULL ); - status = create_harddisk( driver, &device ); + status = create_harddisk( driver, &harddisk0, "/dev/null" ); if (status) { FIXME( "failed to create device error %x\n", status ); return status; } + hddriver = driver; - create_drive_mount_points( device, driver ); + /* Suppress device notifications during initialization */ + initializing = 1; + initialize_hal(); + initialize_diskarbitration(); + + initializing = 0; + + create_drive_mount_points( harddisk0, driver ); return status; } @@ -553,34 +604,19 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) return status; } - initialize_hal(); - initialize_diskarbitration(); - RtlInitUnicodeString( &nameW, harddiskW ); status = IoCreateDriver( &nameW, harddisk_driver_entry ); - return status; } -static char *get_dosdevices_path(void) -{ - const char *config_dir = wine_get_config_dir(); - size_t len = strlen(config_dir) + sizeof("/dosdevices/a::"); - char *path = HeapAlloc( GetProcessHeap(), 0, len ); - if (path) - { - strcpy( path, config_dir ); - strcat( path, "/dosdevices/a::" ); - } - return path; -} - /* send notification about a change to a given drive */ static void send_notify( int drive, int code ) { DWORD_PTR result; DEV_BROADCAST_VOLUME info; + if (initializing) return; + info.dbcv_size = sizeof(info); info.dbcv_devicetype = DBT_DEVTYP_VOLUME; info.dbcv_reserved = 0; @@ -604,17 +640,14 @@ static inline int is_valid_device( struct stat *st ) static int add_drive( const char *device, const char *type ) { char *path, *p; - char in_use[26]; struct stat dev_st, drive_st; - int drive, first, last, avail = 0; + int drive, first, last, avail = -1; if (stat( device, &dev_st ) == -1 || !is_valid_device( &dev_st )) return -1; if (!(path = get_dosdevices_path())) return -1; p = path + strlen(path) - 3; - memset( in_use, 0, sizeof(in_use) ); - first = 2; last = 26; if (type && !strcmp( type, "floppy" )) @@ -623,60 +656,47 @@ static int add_drive( const char *device, const char *type ) last = 2; } - while (avail != -1) + for (drive = first; drive < last; ++drive) { - avail = -1; - for (drive = first; drive < last; drive++) + *p = drive + 'a'; + + if (stat( path, &drive_st) == -1) { - if (in_use[drive]) continue; /* already checked */ - *p = 'a' + drive; - if (stat( path, &drive_st ) == -1) - { - if (lstat( path, &drive_st ) == -1 && errno == ENOENT) /* this is a candidate */ - { - if (avail == -1) - { - p[2] = 0; - /* if mount point symlink doesn't exist either, it's available */ - if (lstat( path, &drive_st ) == -1 && errno == ENOENT) avail = drive; - p[2] = ':'; - } - } - else in_use[drive] = 1; - } - else + if (avail == -1 && errno == ENOENT && !mount_points[drive*2].device) { - in_use[drive] = 1; - if (!is_valid_device( &drive_st )) continue; - if (dev_st.st_rdev == drive_st.st_rdev) goto done; + p[2] = 0; + if (lstat( path, &drive_st ) == -1 && errno == ENOENT) + avail = drive; + p[2] = ':'; } } - if (avail != -1) - { - /* try to use the one we found */ - drive = avail; - *p = 'a' + drive; - if (symlink( device, path ) != -1) goto done; - /* failed, retry the search */ - } + else if (is_valid_device( &drive_st ) && dev_st.st_rdev == drive_st.st_rdev) + break; } - drive = -1; + if (drive == last) + drive = avail; -done: - HeapFree( GetProcessHeap(), 0, path ); + if (drive != -1 && drive == avail) + { + *p = 'a'+avail; + symlink(device, path); + } + + RtlFreeHeap( GetProcessHeap(), 0, path ); return drive; } -static BOOL set_mount_point( struct dos_drive *drive, const char *mount_point ) +static BOOL set_mount_point( int drive, const char *mount_point ) { char *path, *p; struct stat path_st, mnt_st; BOOL modified = FALSE; - if (drive->drive == -1) return FALSE; - if (!(path = get_dosdevices_path())) return FALSE; + if (!(path = get_dosdevices_path())) + return FALSE; + p = path + strlen(path) - 3; - *p = 'a' + drive->drive; + *p = 'a' + drive; p[2] = 0; if (mount_point[0]) @@ -695,86 +715,151 @@ static BOOL set_mount_point( struct dos_drive *drive, const char *mount_point ) if (unlink( path ) != -1) modified = TRUE; } - HeapFree( GetProcessHeap(), 0, path ); + RtlFreeHeap( GetProcessHeap(), 0, path ); return modified; } -BOOL add_dos_device( const char *udi, const char *device, - const char *mount_point, const char *type ) +static DEVICE_OBJECT *find_parent_device(const char *parent_device) { - struct dos_drive *drive; + struct disk_device_info *info; + DEVICE_OBJECT *devobj; + NTSTATUS status; - /* first check if it already exists */ - LIST_FOR_EACH_ENTRY( drive, &drives_list, struct dos_drive, entry ) + int i; + if (!parent_device) + return harddisk0; + + for (i = 0; i < MAX_MOUNT_POINTS; ++i) + { + if (!mount_points[i].parent) + continue; + info = mount_points[i].parent->DeviceExtension; + if (!strcmp(info->dev_node, parent_device)) + { + TRACE("Found existing hard disk for %s\n", parent_device); + return mount_points[i].parent; + } + } + status = create_harddisk( hddriver, &devobj, parent_device ); + if (status) { - if (!strcmp( udi, drive->udi )) goto found; + ERR("Creating harddisk failed: %08x\n", status); + return harddisk0; } + TRACE("Created parent device for %s\n", parent_device); + return devobj; +} + +BOOL add_dos_device( const char *udi, const char *parent_device, const char *device, + const char *mount_point, const char *type ) +{ + DEVICE_OBJECT *parent; + int drive; + char name[3] = "a:"; + struct disk_device_info *info; + + TRACE("add_dos_device(%s, %s, %s, %s, %s)\n", udi, parent_device, device, mount_point, type); + + drive = add_drive( device, type ); + if (drive == -1) + return FALSE; - if (!(drive = HeapAlloc( GetProcessHeap(), 0, sizeof(*drive) ))) return FALSE; - if (!(drive->udi = HeapAlloc( GetProcessHeap(), 0, strlen(udi)+1 ))) + if (mount_points[drive * 2].device) { - HeapFree( GetProcessHeap(), 0, drive ); + ERR("Already added %s!\n", device); return FALSE; } - strcpy( drive->udi, udi ); - list_add_tail( &drives_list, &drive->entry ); -found: - drive->drive = add_drive( device, type ); - if (drive->drive != -1) - { - HKEY hkey; + set_mount_point( drive, mount_point ); - set_mount_point( drive, mount_point ); + name[0] += drive; + if (!type || strcmp( type, "cdrom" )) type = "hd"; + RegSetValueExA( drive_key, name, 0, REG_SZ, (const BYTE *)type, strlen(type) + 1 ); - TRACE( "added device %c: udi %s for %s on %s type %s\n", - 'a' + drive->drive, wine_dbgstr_a(udi), wine_dbgstr_a(device), - wine_dbgstr_a(mount_point), wine_dbgstr_a(type) ); + parent = find_parent_device( parent_device ); + add_mount_point( parent, hddriver, drive, udi, strlen(udi) ); - /* hack: force the drive type in the registry */ - if (!RegCreateKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Drives", &hkey )) - { - char name[3] = "a:"; - name[0] += drive->drive; - if (!type || strcmp( type, "cdrom" )) type = "floppy"; /* FIXME: default to floppy */ - RegSetValueExA( hkey, name, 0, REG_SZ, (const BYTE *)type, strlen(type) + 1 ); - RegCloseKey( hkey ); - } + info = mount_points[drive * 2].device->DeviceExtension; + info->dev_node = RtlAllocateHeap(GetProcessHeap(), 0, strlen(device)+1); + strcpy(info->dev_node, device); - send_notify( drive->drive, DBT_DEVICEARRIVAL ); - } + /* Check to see if there already is a parent with parent_device */ + + TRACE( "added device %c: udi %s for %s on %s type %s\n", + 'a' + drive, wine_dbgstr_a(udi), wine_dbgstr_a(device), + wine_dbgstr_a(mount_point), wine_dbgstr_a(type) ); + + send_notify( drive, DBT_DEVICEARRIVAL ); return TRUE; } -BOOL remove_dos_device( const char *udi ) +static void delete_disk_device(DEVICE_OBJECT *device) { - HKEY hkey; - struct dos_drive *drive; + struct disk_device_info info; + info = *(struct disk_device_info*)device->DeviceExtension; - LIST_FOR_EACH_ENTRY( drive, &drives_list, struct dos_drive, entry ) - { - if (strcmp( udi, drive->udi )) continue; + IoDeleteDevice(device); + RtlFreeHeap(GetProcessHeap(), 0, info.dev_node); + RtlFreeHeap(GetProcessHeap(), 0, info.name.Buffer); +} + +static void free_mount_point(struct mount_point *drive) +{ + RegDeleteValueW( mount_key, drive->link.Buffer ); + RtlFreeUnicodeString(&drive->link); + RtlFreeHeap(GetProcessHeap(), 0, drive->id); + memset(drive, 0, sizeof(*drive)); +} + +static void delete_mount_point(struct mount_point *drive) +{ + int i; + DEVICE_OBJECT *parent = drive->parent; + + delete_disk_device(drive->device); + free_mount_point(drive); + free_mount_point(drive+1); - if (drive->drive != -1) + if (parent != harddisk0) + { + /* Scan for drives that still have the parent */ + for (i = 0; i < MAX_MOUNT_POINTS; ++i) + { + if (mount_points[i].parent == parent) + break; + } + if (i == MAX_MOUNT_POINTS) { - BOOL modified = set_mount_point( drive, "" ); + TRACE("Deleting parent device for %s\n", ((struct disk_device_info*)parent->DeviceExtension)->dev_node); + delete_disk_device(parent); + } + } +} - /* clear the registry key too */ - if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Drives", &hkey )) +BOOL remove_dos_device( const char *udi ) +{ + int i; + TRACE("remove_dos_device(%s)\n", udi); + + for (i = 0; i < MAX_DOS_DRIVES; ++i) + if (mount_points[i*2].device) + { + struct mount_point *drive = mount_points + (i*2); + if (!strcmp(udi, drive->id)) { - char name[3] = "a:"; - name[0] += drive->drive; - RegDeleteValueA( hkey, name ); - RegCloseKey( hkey ); - } + /* clear the registry key too */ + WCHAR name[3] = {'a',':',0}; + if (!set_mount_point( i, "" )) break; + + delete_mount_point(drive); - if (modified) send_notify( drive->drive, DBT_DEVICEREMOVECOMPLETE ); + name[0] += i; + TRACE("Deleting %s\n", debugstr_w(name)); + RegDeleteValueW( drive_key, name ); + + send_notify( i, DBT_DEVICEREMOVECOMPLETE ); + } } - list_remove( &drive->entry ); - HeapFree( GetProcessHeap(), 0, drive->udi ); - HeapFree( GetProcessHeap(), 0, drive ); - return TRUE; - } return FALSE; } diff --git a/dlls/mountmgr.sys/mountmgr.h b/dlls/mountmgr.sys/mountmgr.h index 394904e..d0cb5ad 100644 --- a/dlls/mountmgr.sys/mountmgr.h +++ b/dlls/mountmgr.sys/mountmgr.h @@ -20,7 +20,7 @@ void initialize_hal(void); void initialize_diskarbitration(void); -BOOL add_dos_device( const char *udi, const char *device, +BOOL add_dos_device( const char *udi, const char *device, const char *parent_device, const char *mount_point, const char *type ); BOOL remove_dos_device( const char *udi ); -- 1.5.4.1