[FASTFAT]
[reactos.git] / reactos / drivers / filesystems / fastfat / fsctl.c
index 19f9785..43e582a 100644 (file)
@@ -521,6 +521,14 @@ VfatMount(
     /* Initialize this resource early ... it's used in VfatCleanup */
     ExInitializeResourceLite(&DeviceExt->DirResource);
 
+    DeviceExt->IoVPB = DeviceObject->Vpb;
+    DeviceExt->SpareVPB = ExAllocatePoolWithTag(NonPagedPool, sizeof(VPB), TAG_VFAT);
+    if (DeviceExt->SpareVPB == NULL)
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto ByeBye;
+    }
+
     DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
     Fcb = vfatNewFCB(DeviceExt, &NameU);
     if (Fcb == NULL)
@@ -612,7 +620,7 @@ VfatMount(
     FsRtlNotifyInitializeSync(&DeviceExt->NotifySync);
     InitializeListHead(&DeviceExt->NotifyList);
 
-    DPRINT1("Mount success\n");
+    DPRINT("Mount success\n");
 
     Status = STATUS_SUCCESS;
 
@@ -622,6 +630,8 @@ ByeBye:
         /* Cleanup */
         if (DeviceExt && DeviceExt->FATFileObject)
             ObDereferenceObject (DeviceExt->FATFileObject);
+        if (DeviceExt && DeviceExt->SpareVPB)
+            ExFreePoolWithTag(DeviceExt->SpareVPB, TAG_VFAT);
         if (Fcb)
             vfatDestroyFCB(Fcb);
         if (Ccb)
@@ -865,14 +875,16 @@ VfatLockOrUnlockVolume(
 {
     PFILE_OBJECT FileObject;
     PDEVICE_EXTENSION DeviceExt;
+    PVFATFCB Fcb;
 
-    DPRINT1("VfatLockOrUnlockVolume(%p, %d)\n", IrpContext, Lock);
+    DPRINT("VfatLockOrUnlockVolume(%p, %d)\n", IrpContext, Lock);
 
     DeviceExt = IrpContext->DeviceExt;
     FileObject = IrpContext->FileObject;
+    Fcb = FileObject->FsContext;
 
     /* Only allow locking with the volume open */
-    if (FileObject->FsContext != DeviceExt->VolumeFcb)
+    if (!(Fcb->Flags & FCB_IS_VOLUME))
     {
         return STATUS_ACCESS_DENIED;
     }
@@ -909,18 +921,57 @@ VfatDismountVolume(
     PVFAT_IRP_CONTEXT IrpContext)
 {
     PDEVICE_EXTENSION DeviceExt;
+    PLIST_ENTRY NextEntry;
+    PVFATFCB Fcb;
+    PFILE_OBJECT FileObject;
 
-    DPRINT1("VfatDismountVolume(%p)\n", IrpContext);
+    DPRINT("VfatDismountVolume(%p)\n", IrpContext);
 
     DeviceExt = IrpContext->DeviceExt;
+    FileObject = IrpContext->FileObject;
 
+    /* We HAVE to be locked. Windows also allows dismount with no lock
+     * but we're here mainly for 1st stage, so KISS
+     */
     if (!(DeviceExt->Flags & VCB_VOLUME_LOCKED))
     {
         return STATUS_ACCESS_DENIED;
     }
 
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    /* Race condition? */
+    if (DeviceExt->Flags & VCB_DISMOUNT_PENDING)
+    {
+        return STATUS_VOLUME_DISMOUNTED;
+    }
+
+    /* Notify we'll dismount. Pass that point there's no reason we fail */
+    FsRtlNotifyVolumeEvent(IrpContext->Stack->FileObject, FSRTL_VOLUME_DISMOUNT);
+
+    ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
+
+    /* Flush volume & files */
+    VfatFlushVolume(DeviceExt, (PVFATFCB)FileObject->FsContext);
+
+    /* Rebrowse the FCB in order to free them now */
+    while (!IsListEmpty(&DeviceExt->FcbListHead))
+    {
+        NextEntry = RemoveHeadList(&DeviceExt->FcbListHead);
+        Fcb = CONTAINING_RECORD(NextEntry, VFATFCB, FcbListEntry);
+        vfatDestroyFCB(Fcb);
+    }
+
+    /* Mark we're being dismounted */
+    DeviceExt->Flags |= VCB_DISMOUNT_PENDING;
+    IrpContext->DeviceObject->Vpb->Flags &= ~VPB_MOUNTED;
+
+    ExReleaseResourceLite(&DeviceExt->FatResource);
+
+    /* Release a few resources and quit, we're done */
+    ExDeleteResourceLite(&DeviceExt->DirResource);
+    ExDeleteResourceLite(&DeviceExt->FatResource);
+    ObDereferenceObject(DeviceExt->FATFileObject);
+
+    return STATUS_SUCCESS;
 }
 
 /*