Alexandre Julliard : mountmgr: Add ref counting for volume objects.
Alexandre Julliard
julliard at winehq.org
Thu Jul 23 09:59:15 CDT 2009
Module: wine
Branch: master
Commit: 0da2e46eaf37049dea45133c904d37475a704193
URL: http://source.winehq.org/git/wine.git/?a=commit;h=0da2e46eaf37049dea45133c904d37475a704193
Author: Alexandre Julliard <julliard at winehq.org>
Date: Wed Jul 22 20:55:24 2009 +0200
mountmgr: Add ref counting for volume objects.
---
dlls/mountmgr.sys/device.c | 70 ++++++++++++++++++++++++++++++--------------
1 files changed, 48 insertions(+), 22 deletions(-)
diff --git a/dlls/mountmgr.sys/device.c b/dlls/mountmgr.sys/device.c
index 3753c96..35797e4 100644
--- a/dlls/mountmgr.sys/device.c
+++ b/dlls/mountmgr.sys/device.c
@@ -71,6 +71,7 @@ struct volume
struct list entry; /* entry in volumes list */
struct disk_device *device; /* disk device */
char *udi; /* unique identifier for dynamic volumes */
+ unsigned int ref; /* ref count */
GUID guid; /* volume uuid */
struct mount_point *mount; /* Volume{xxx} mount point */
};
@@ -299,6 +300,46 @@ static void delete_disk_device( struct disk_device *device )
IoDeleteDevice( device->dev_obj );
}
+/* grab another reference to a volume */
+static unsigned int grab_volume( struct volume *volume )
+{
+ return ++volume->ref;
+}
+
+/* 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;
+
+ TRACE( "%s udi %s count now %u\n", debugstr_guid(&volume->guid), debugstr_a(volume->udi), ret );
+ if (!ret)
+ {
+ 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;
+}
+
+/* set the volume udi */
+static void set_volume_udi( struct volume *volume, const char *udi )
+{
+ if (udi)
+ {
+ assert( !volume->udi );
+ /* having a udi means the HAL side holds an extra reference */
+ if ((volume->udi = strdupA( udi ))) grab_volume( volume );
+ }
+ else if (volume->udi)
+ {
+ RtlFreeHeap( GetProcessHeap(), 0, volume->udi );
+ volume->udi = NULL;
+ release_volume( volume );
+ }
+}
+
/* create a disk volume */
static NTSTATUS create_volume( const char *udi, enum device_type type, struct volume **volume_ret )
{
@@ -308,32 +349,15 @@ static NTSTATUS create_volume( const char *udi, enum device_type type, struct vo
if (!(volume = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*volume) )))
return STATUS_NO_MEMORY;
- if (udi && !(volume->udi = strdupA( udi )))
- {
- RtlFreeHeap( GetProcessHeap(), 0, volume );
- return STATUS_NO_MEMORY;
- }
if (!(status = create_disk_device( type, &volume->device )))
{
+ if (udi) set_volume_udi( volume, udi );
list_add_tail( &volumes_list, &volume->entry );
*volume_ret = volume;
}
- else
- {
- RtlFreeHeap( GetProcessHeap(), 0, volume->udi );
- RtlFreeHeap( GetProcessHeap(), 0, volume );
- }
- return status;
-}
+ else RtlFreeHeap( GetProcessHeap(), 0, volume );
-/* delete a volume and the corresponding disk device */
-static void delete_volume( struct volume *volume )
-{
- list_remove( &volume->entry );
- if (volume->mount) delete_mount_point( volume->mount );
- delete_disk_device( volume->device );
- RtlFreeHeap( GetProcessHeap(), 0, volume->udi );
- RtlFreeHeap( GetProcessHeap(), 0, volume );
+ return status;
}
/* create the disk device for a given volume */
@@ -349,6 +373,7 @@ static NTSTATUS create_dos_device( const char *udi, int letter, enum device_type
if (!(status = create_volume( udi, type, &drive->volume )))
{
+ grab_volume( drive->volume );
list_add_tail( &drives_list, &drive->entry );
*drive_ret = drive;
}
@@ -362,7 +387,7 @@ static void delete_dos_device( struct dos_drive *drive )
{
list_remove( &drive->entry );
if (drive->mount) delete_mount_point( drive->mount );
- delete_volume( drive->volume );
+ release_volume( drive->volume );
RtlFreeHeap( GetProcessHeap(), 0, drive );
}
@@ -604,7 +629,7 @@ NTSTATUS remove_volume( const char *udi )
LIST_FOR_EACH_ENTRY( volume, &volumes_list, struct volume, entry )
{
if (!volume->udi || strcmp( udi, volume->udi )) continue;
- delete_volume( volume );
+ set_volume_udi( volume, NULL );
return STATUS_SUCCESS;
}
return STATUS_NO_SUCH_DEVICE;
@@ -699,6 +724,7 @@ NTSTATUS remove_dos_device( int letter, const char *udi )
{
if (!drive->volume->udi) continue;
if (strcmp( udi, drive->volume->udi )) continue;
+ set_volume_udi( drive->volume, NULL );
}
else if (drive->drive != letter) continue;
More information about the wine-cvs
mailing list