/* change the information for an existing volume */ static NTSTATUS set_volume_info( struct volume *volume, struct dos_drive *drive, const char *device, const char *mount_point, enum device_type type, const GUID *guid ) { void *id = NULL; unsigned int id_len = 0; struct disk_device *disk_device = volume->device; NTSTATUS status; if (type != disk_device->type) { if ((status = create_disk_device( type, &disk_device ))) return status; if (volume->mount) { delete_mount_point( volume->mount ); volume->mount = NULL; } if (drive && drive->mount) { delete_mount_point( drive->mount ); drive->mount = NULL; } delete_disk_device( volume->device ); volume->device = disk_device; } else { RtlFreeHeap( GetProcessHeap(), 0, disk_device->unix_device ); RtlFreeHeap( GetProcessHeap(), 0, disk_device->unix_mount ); } disk_device->unix_device = strdupA( device ); disk_device->unix_mount = strdupA( mount_point ); if (guid && memcmp( &volume->guid, guid, sizeof(volume->guid) )) { volume->guid = *guid; if (volume->mount) { delete_mount_point( volume->mount ); volume->mount = NULL; } } if (!volume->mount) volume->mount = add_volume_mount_point( disk_device->dev_obj, &disk_device->name, &volume->guid ); if (drive && !drive->mount) drive->mount = add_dosdev_mount_point( disk_device->dev_obj, &disk_device->name, drive->drive ); if (disk_device->unix_mount) { id = disk_device->unix_mount; id_len = strlen( disk_device->unix_mount ) + 1; } if (volume->mount) set_mount_point_id( volume->mount, id, id_len, -1 ); if (drive && drive->mount) set_mount_point_id( drive->mount, id, id_len, drive->drive ); return STATUS_SUCCESS; }
/* delete the disk device for a given drive */ static void delete_dos_device( struct dos_drive *drive ) { list_remove( &drive->entry ); if (drive->mount) delete_mount_point( drive->mount ); release_volume( drive->volume ); RtlFreeHeap( GetProcessHeap(), 0, drive ); }
/* change the drive letter or volume for an existing drive */ static void set_drive_info( struct dos_drive *drive, int letter, struct volume *volume ) { if (drive->drive != letter) { if (drive->mount) delete_mount_point( drive->mount ); drive->mount = NULL; drive->drive = letter; } if (drive->volume != volume) { if (drive->mount) delete_mount_point( drive->mount ); drive->mount = NULL; grab_volume( volume ); release_volume( drive->volume ); drive->volume = volume; } }
/* delete the disk device for a given drive */ static void delete_disk_device( struct dos_drive *drive ) { TRACE( "deleting device %s\n", debugstr_w(drive->name.Buffer) ); list_remove( &drive->entry ); if (drive->dosdev) delete_mount_point( drive->dosdev ); if (drive->volume) delete_mount_point( drive->volume ); if (drive->symlink.Buffer) { IoDeleteSymbolicLink( &drive->symlink ); RtlFreeUnicodeString( &drive->symlink ); } RtlFreeHeap( GetProcessHeap(), 0, drive->unix_device ); RtlFreeHeap( GetProcessHeap(), 0, drive->unix_mount ); RtlFreeHeap( GetProcessHeap(), 0, drive->udi ); RtlFreeUnicodeString( &drive->name ); IoDeleteDevice( drive->device ); }
/* set or change the drive letter for an existing drive */ static void set_drive_letter( struct dos_drive *drive, int letter ) { void *id = NULL; unsigned int id_len = 0; if (drive->drive == letter) return; if (drive->dosdev) delete_mount_point( drive->dosdev ); if (drive->volume) delete_mount_point( drive->volume ); drive->drive = letter; if (letter == -1) return; if (drive->unix_mount) { id = drive->unix_mount; id_len = strlen( drive->unix_mount ) + 1; } drive->dosdev = add_dosdev_mount_point( drive->device, &drive->name, letter, id, id_len ); drive->volume = add_volume_mount_point( drive->device, &drive->name, letter, id, id_len ); }
/* release a volume and delete the corresponding disk device when refcount is 0 */ static unsigned int release_volume( struct volume *volume ) { unsigned int ret = --volume->ref; if (!ret) { TRACE( "%s udi %s\n", debugstr_guid(&volume->guid), debugstr_a(volume->udi) ); assert( !volume->udi ); list_remove( &volume->entry ); if (volume->mount) delete_mount_point( volume->mount ); delete_disk_device( volume->device ); RtlFreeHeap( GetProcessHeap(), 0, volume ); } return ret; }