Implement FSCTL_IS_VOLUME_DIRTY and FSCTL_MARK_VOLUME_DIRTY
Modified: trunk/reactos/drivers/fs/vfat/fsctl.c
Modified: trunk/reactos/drivers/fs/vfat/shutdown.c
Modified: trunk/reactos/drivers/fs/vfat/vfat.h

Modified: trunk/reactos/drivers/fs/vfat/fsctl.c
--- trunk/reactos/drivers/fs/vfat/fsctl.c	2005-04-16 12:50:33 UTC (rev 14635)
+++ trunk/reactos/drivers/fs/vfat/fsctl.c	2005-04-16 16:04:38 UTC (rev 14636)
@@ -373,6 +373,7 @@
    UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\$$Fat$$");
    UNICODE_STRING VolumeNameU = RTL_CONSTANT_STRING(L"\\$$Volume$$");
    ULONG HashTableSize;
+   ULONG eocMark;
    FATINFO FatInfo;
 
    DPRINT("VfatMount(IrpContext %x)\n", IrpContext);
@@ -460,6 +461,7 @@
          DeviceExt->GetNextCluster = FAT12GetNextCluster;
          DeviceExt->FindAndMarkAvailableCluster = FAT12FindAndMarkAvailableCluster;
          DeviceExt->WriteCluster = FAT12WriteCluster;
+         DeviceExt->CleanShutBitMask = 0;
          break;
 
       case FAT16:
@@ -467,6 +469,7 @@
          DeviceExt->GetNextCluster = FAT16GetNextCluster;
          DeviceExt->FindAndMarkAvailableCluster = FAT16FindAndMarkAvailableCluster;
          DeviceExt->WriteCluster = FAT16WriteCluster;
+         DeviceExt->CleanShutBitMask = 0x8000;
          break;
 
       case FAT32:
@@ -474,6 +477,7 @@
          DeviceExt->GetNextCluster = FAT32GetNextCluster;
          DeviceExt->FindAndMarkAvailableCluster = FAT32FindAndMarkAvailableCluster;
          DeviceExt->WriteCluster = FAT32WriteCluster;
+         DeviceExt->CleanShutBitMask = 0x80000000;
          break;
    }
    
@@ -576,6 +580,20 @@
 
    /* read volume label */
    ReadVolumeLabel(DeviceExt,  DeviceObject->Vpb);
+   
+   /* read clean shutdown bit status */
+   Status = GetNextCluster(DeviceExt, 1, &eocMark);
+   if (NT_SUCCESS(Status))
+   {
+      if (eocMark & DeviceExt->CleanShutBitMask)
+      {
+         /* unset clean shutdown bit */
+         eocMark &= ~DeviceExt->CleanShutBitMask;
+         WriteCluster(DeviceExt, 1, eocMark);
+         VolumeFcb->Flags |= VCB_CLEAR_DIRTY;
+      }
+   }
+   VolumeFcb->Flags |= VCB_IS_DIRTY;
 
    Status = STATUS_SUCCESS;
 ByeBye:
@@ -787,6 +805,56 @@
 }
 #endif
 
+static NTSTATUS
+VfatIsVolumeDirty(PVFAT_IRP_CONTEXT IrpContext)
+{
+   PULONG Flags;
+   
+   DPRINT("VfatIsVolumeDirty(IrpContext %x)\n", IrpContext);
+   
+   if (IrpContext->Stack->Parameters.FileSystemControl.OutputBufferLength != sizeof(ULONG))
+      return STATUS_INVALID_BUFFER_SIZE;
+   else if (!IrpContext->Irp->AssociatedIrp.SystemBuffer)
+      return STATUS_INVALID_USER_BUFFER;
+   
+   Flags = (PULONG)IrpContext->Irp->AssociatedIrp.SystemBuffer;
+   *Flags = 0;
+   
+   if (IrpContext->DeviceExt->VolumeFcb->Flags & VCB_IS_DIRTY
+      && !(IrpContext->DeviceExt->VolumeFcb->Flags & VCB_CLEAR_DIRTY))
+   {
+      *Flags |= VOLUME_IS_DIRTY;
+   }
+   
+   return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+VfatMarkVolumeDirty(PVFAT_IRP_CONTEXT IrpContext)
+{
+   ULONG eocMark;
+   PDEVICE_EXTENSION DeviceExt;
+   NTSTATUS Status = STATUS_SUCCESS;
+   
+   DPRINT("VfatMarkVolumeDirty(IrpContext %x)\n", IrpContext);
+   DeviceExt = IrpContext->DeviceExt;
+   
+   if (!(DeviceExt->VolumeFcb->Flags & VCB_IS_DIRTY))
+   {
+      Status = GetNextCluster(DeviceExt, 1, &eocMark);
+      if (NT_SUCCESS(Status))
+      {
+         /* unset clean shutdown bit */
+         eocMark &= ~DeviceExt->CleanShutBitMask;
+         Status = WriteCluster(DeviceExt, 1, eocMark);
+      }
+   }
+   
+   DeviceExt->VolumeFcb->Flags &= ~VCB_CLEAR_DIRTY;
+   
+   return Status;
+}
+
 NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext)
 /*
  * FUNCTION: File system control
@@ -822,6 +890,12 @@
 	       Status = VfatRosQueryLcnMapping(IrpContext);
 	       break;
 #endif
+	    case FSCTL_IS_VOLUME_DIRTY:
+	       Status = VfatIsVolumeDirty(IrpContext);
+	       break;
+	    case FSCTL_MARK_VOLUME_DIRTY:
+	       Status = VfatMarkVolumeDirty(IrpContext);
+	       break;
 	    default:
 	       Status = STATUS_INVALID_DEVICE_REQUEST;
 	 }

Modified: trunk/reactos/drivers/fs/vfat/shutdown.c
--- trunk/reactos/drivers/fs/vfat/shutdown.c	2005-04-16 12:50:33 UTC (rev 14635)
+++ trunk/reactos/drivers/fs/vfat/shutdown.c	2005-04-16 16:04:38 UTC (rev 14636)
@@ -48,6 +48,7 @@
    NTSTATUS Status;
    PLIST_ENTRY ListEntry;
    PDEVICE_EXTENSION DeviceExt;
+   ULONG eocMark;
 
    DPRINT("VfatShutdown(DeviceObject %x, Irp %x)\n",DeviceObject, Irp);
 
@@ -64,6 +65,17 @@
          ListEntry = ListEntry->Flink;
 
 	 ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
+         if (DeviceExt->VolumeFcb->Flags & VCB_CLEAR_DIRTY)
+         {
+            /* set clean shutdown bit */
+            Status = GetNextCluster(DeviceExt, 1, &eocMark);
+            if (NT_SUCCESS(Status))
+            {
+               eocMark |= DeviceExt->CleanShutBitMask;
+               if (NT_SUCCESS(WriteCluster(DeviceExt, 1, eocMark)))
+                  DeviceExt->VolumeFcb->Flags &= ~VCB_IS_DIRTY;
+            }
+         }
          Status = VfatFlushVolume(DeviceExt, DeviceExt->VolumeFcb);
          if (NT_SUCCESS(Status))
          {

Modified: trunk/reactos/drivers/fs/vfat/vfat.h
--- trunk/reactos/drivers/fs/vfat/vfat.h	2005-04-16 12:50:33 UTC (rev 14635)
+++ trunk/reactos/drivers/fs/vfat/vfat.h	2005-04-16 16:04:38 UTC (rev 14636)
@@ -13,6 +13,7 @@
 NTSTATUS NTAPI RtlDowncaseUnicodeString(PUNICODE_STRING, PCUNICODE_STRING, BOOLEAN);
 NTSTATUS NTAPI RtlUnicodeStringToOemString(POEM_STRING, PCUNICODE_STRING, BOOLEAN);
 #undef DeleteFile /* FIXME */
+#define VOLUME_IS_DIRTY 0x00000001 /* FIXME */
 #endif
 
 #ifdef USE_ROS_CC_AND_FS
@@ -193,6 +194,8 @@
 #define VCB_VOLUME_LOCKED       0x0001
 #define VCB_DISMOUNT_PENDING    0x0002
 #define VCB_IS_FATX             0x0004
+#define VCB_IS_DIRTY            0x4000 /* Volume is dirty */
+#define VCB_CLEAR_DIRTY         0x8000 /* Clean dirty flag at shutdown */
 
 typedef struct
 {
@@ -257,6 +260,7 @@
   PGET_NEXT_CLUSTER GetNextCluster;
   PFIND_AND_MARK_AVAILABLE_CLUSTER FindAndMarkAvailableCluster;
   PWRITE_CLUSTER WriteCluster;
+  ULONG CleanShutBitMask;
   
   /* Pointers to functions for manipulating directory entries. */
   PGET_NEXT_DIR_ENTRY GetNextDirEntry;