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