[fastfat_new]
authorAleksey Bragin <aleksey@reactos.org>
Mon, 28 Sep 2009 10:43:27 +0000 (10:43 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Mon, 28 Sep 2009 10:43:27 +0000 (10:43 +0000)
- Fix wrong comment in FatiCreate, spotted by Ged Murphy.
- Add some parameters validation to FatiCreate, and a check for volume open request.
- Add node types and a decoding routine.
- Implement VCB locking/unlocking.

svn path=/trunk/; revision=43202

reactos/drivers/filesystems/fastfat_new/create.c
reactos/drivers/filesystems/fastfat_new/fastfat.c
reactos/drivers/filesystems/fastfat_new/fastfat.h
reactos/drivers/filesystems/fastfat_new/fat.c
reactos/drivers/filesystems/fastfat_new/fatstruc.h

index 676a3f3..88ccc95 100644 (file)
@@ -33,7 +33,9 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
     ULONG CreateDisposition;
 
     /* Control blocks */
-    PVCB Vcb;
+    PVCB Vcb, DecodedVcb;
+    PFCB Fcb;
+    PCCB Ccb;
 
     /* IRP data */
     PFILE_OBJECT FileObject;
@@ -48,8 +50,8 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
     ULONG EaLength;
 
     /* Misc */
-    //NTSTATUS Status;
-    IO_STATUS_BLOCK Iosb;
+    NTSTATUS Status;
+    //IO_STATUS_BLOCK Iosb;
     PIO_STACK_LOCATION IrpSp;
 
     /* Get current IRP stack location */
@@ -75,14 +77,14 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
         (IrpSp->FileObject->FileName.Buffer[1] == L'\\') &&
         (IrpSp->FileObject->FileName.Buffer[0] == L'\\'))
     {
-        /* Remove two leading slashes */
+        /* Remove a leading slash */
         IrpSp->FileObject->FileName.Length -= sizeof(WCHAR);
-
         RtlMoveMemory(&IrpSp->FileObject->FileName.Buffer[0],
                       &IrpSp->FileObject->FileName.Buffer[1],
                       IrpSp->FileObject->FileName.Length );
 
-        /* If there are two leading slashes again, exit */
+        /* Check again: if there are still two leading slashes,
+           exit with an error */
         if ((IrpSp->FileObject->FileName.Length > sizeof(WCHAR)) &&
             (IrpSp->FileObject->FileName.Buffer[1] == L'\\') &&
             (IrpSp->FileObject->FileName.Buffer[0] == L'\\'))
@@ -146,6 +148,55 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
                                 ((CreateDisposition == FILE_OPEN) ||
                                  (CreateDisposition == FILE_OPEN_IF)));
 
+    /* Validate parameters: directory/nondirectory mismatch and
+       AllocationSize being more than 4GB */
+    if ((DirectoryFile && NonDirectoryFile) ||
+        Irp->Overlay.AllocationSize.HighPart != 0)
+    {
+        FatCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER);
+
+        DPRINT1("FatiCreate: STATUS_INVALID_PARAMETER\n", 0);
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Acquire the VCB lock exclusively */
+    if (!FatAcquireExclusiveVcb(IrpContext, Vcb))
+    {
+        // TODO: Postpone the IRP for later processing
+        ASSERT(FALSE);
+        return STATUS_NOT_IMPLEMENTED;
+    }
+
+    // TODO: Verify the VCB
+
+    /* If VCB is locked, then no file openings are possible */
+    if (Vcb->State & VCB_STATE_FLAG_LOCKED)
+    {
+        DPRINT1("This volume is locked\n");
+        Status = STATUS_ACCESS_DENIED;
+
+        /* Cleanup and return */
+        FatReleaseVcb(IrpContext, Vcb);
+        return Status;
+    }
+
+    // TODO: Check if the volume is write protected and disallow DELETE_ON_CLOSE
+
+    // TODO: Make sure EAs aren't supported on FAT32
+
+    if (FileName.Length == 0)
+    {
+        /* It is a volume open request, check related FO to be sure */
+
+        if (!RelatedFO ||
+            FatDecodeFileObject(RelatedFO, &DecodedVcb, &Fcb, &Ccb) == UserVolumeOpen)
+        {
+            /* It is indeed a volume open request */
+            DPRINT1("Volume open request, not implemented now!\n");
+            UNIMPLEMENTED;
+        }
+    }
+
     //return Iosb.Status;
     return STATUS_SUCCESS;
 }
index c4cc26e..925d83a 100644 (file)
@@ -271,4 +271,99 @@ FatQueueRequest(IN PFAT_IRP_CONTEXT IrpContext,
     ExQueueWorkItem(&IrpContext->WorkQueueItem,
         DelayedWorkQueue);
 }
+
+TYPE_OF_OPEN
+NTAPI
+FatDecodeFileObject(IN PFILE_OBJECT FileObject,
+                    OUT PVCB *Vcb,
+                    OUT PFCB *FcbOrDcb,
+                    OUT PCCB *Ccb)
+{
+    TYPE_OF_OPEN TypeOfOpen = UnopenedFileObject;
+    PVOID FsContext = FileObject->FsContext;
+    PVOID FsContext2 = FileObject->FsContext2;
+
+    /* If FsContext is NULL, then everything is NULL */
+    if (!FsContext)
+    {
+        *Ccb = NULL;
+        *FcbOrDcb = NULL;
+        *Vcb = NULL;
+
+        return TypeOfOpen;
+    }
+
+    /* CCB is always stored in FsContext2 */
+    *Ccb = FsContext2;
+
+    /* Switch according to the NodeType */
+    switch (FatNodeType(FsContext))
+    {
+        /* Volume */
+        case FAT_NTC_VCB:
+            *FcbOrDcb = NULL;
+            *Vcb = FsContext;
+
+            TypeOfOpen = ( *Ccb == NULL ? VirtualVolumeFile : UserVolumeOpen );
+
+            break;
+
+        /* Root or normal directory*/
+        case FAT_NTC_ROOT_DCB:
+        case FAT_NTC_DCB:
+            *FcbOrDcb = FsContext;
+            *Vcb = (*FcbOrDcb)->Vcb;
+
+            TypeOfOpen = (*Ccb == NULL ? DirectoryFile : UserDirectoryOpen);
+
+            DPRINT1("Referencing a directory: %Z\n", &(*FcbOrDcb)->FullFileName);
+            break;
+
+        /* File */
+        case FAT_NTC_FCB:
+            *FcbOrDcb = FsContext;
+            *Vcb = (*FcbOrDcb)->Vcb;
+
+            TypeOfOpen = (*Ccb == NULL ? EaFile : UserFileOpen);
+
+            DPRINT1("Referencing a file: %Z\n", &(*FcbOrDcb)->FullFileName);
+
+            break;
+
+        default:
+            DPRINT1("Unknown node type %x\n", FatNodeType(FsContext));
+            ASSERT(FALSE);
+    }
+
+    return TypeOfOpen;
+}
+
+
+BOOLEAN
+NTAPI
+FatAcquireExclusiveVcb(IN PFAT_IRP_CONTEXT IrpContext,
+                       IN PVCB Vcb)
+{
+    /* Acquire VCB's resource if possible */
+    if (ExAcquireResourceExclusiveLite(&Vcb->Resource,
+                                       BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
+    {
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+
+VOID
+NTAPI
+FatReleaseVcb(IN PFAT_IRP_CONTEXT IrpContext,
+              IN PVCB Vcb)
+{
+    /* Release VCB's resource */
+    ExReleaseResourceLite(&Vcb->Resource);
+}
+
+
 /* EOF */
index e8b0edf..32f090b 100644 (file)
@@ -132,6 +132,20 @@ FatCompleteRequest(PFAT_IRP_CONTEXT IrpContext OPTIONAL,
                    PIRP Irp OPTIONAL,
                    NTSTATUS Status);
 
+BOOLEAN NTAPI
+FatAcquireExclusiveVcb(IN PFAT_IRP_CONTEXT IrpContext,
+                       IN PVCB Vcb);
+
+VOID NTAPI
+FatReleaseVcb(IN PFAT_IRP_CONTEXT IrpContext,
+              IN PVCB Vcb);
+
+TYPE_OF_OPEN
+NTAPI
+FatDecodeFileObject(IN PFILE_OBJECT FileObject,
+                    OUT PVCB *Vcb,
+                    OUT PFCB *FcbOrDcb,
+                    OUT PCCB *Ccb);
 
 /* ---------------------------------------------------------  lock.c */
 
index 6722ea0..c1fa63a 100644 (file)
@@ -489,6 +489,12 @@ FatInitializeVcb(IN PFAT_IRP_CONTEXT IrpContext,
     Vcb->Header.ValidDataLength.HighPart = MAXLONG;
     Vcb->Header.ValidDataLength.LowPart = MAXULONG;
 
+    /* Set VCB to a good condition */
+    Vcb->Condition = VcbGood;
+
+    /* Initialize VCB's resource */
+    ExInitializeResourceLite(&Vcb->Resource);
+
     /* Initialize CC */
     CcInitializeCacheMap(Vcb->StreamFileObject,
                          (PCC_FILE_SIZES)&Vcb->Header.AllocationSize,
index ca0a4d3..d2b7412 100644 (file)
@@ -8,6 +8,18 @@ typedef PVOID PBCB;
 
 typedef NTSTATUS (*PFAT_OPERATION_HANDLER) (PFAT_IRP_CONTEXT);
 
+/* Node type stuff */
+typedef CSHORT FAT_NODE_TYPE;
+typedef FAT_NODE_TYPE *PFAT_NODE_TYPE;
+
+#define FatNodeType(Ptr) (*((PFAT_NODE_TYPE)(Ptr)))
+
+/* Node type codes */
+#define FAT_NTC_VCB      (CSHORT) '00VF'
+#define FAT_NTC_FCB      (CSHORT)   'CF'
+#define FAT_NTC_DCB      (CSHORT)   'DF'
+#define FAT_NTC_ROOT_DCB (CSHORT)  'RFD'
+
 typedef struct _FAT_GLOBAL_DATA
 {
     ERESOURCE Resource;
@@ -116,7 +128,14 @@ typedef struct _FAT_METHODS {
     PFAT_SETFAT_VALUE_RUN_ROUTINE SetValueRun;
 } FAT_METHODS, *PFAT_METHODS;
 
-#define FAT_NTC_VCB  (USHORT) '00VF'
+#define VCB_STATE_FLAG_LOCKED 0x01
+
+typedef enum _VCB_CONDITION
+{
+    VcbGood,
+    VcbNotMounted,
+    VcbBad
+} VCB_CONDITION;
 
 /* Volume Control Block */
 typedef struct _VCB
@@ -129,6 +148,9 @@ typedef struct _VCB
     PDEVICE_OBJECT TargetDeviceObject;
     LIST_ENTRY VcbLinks;
     PVPB Vpb;
+    ULONG State;
+    VCB_CONDITION Condition;
+    ERESOURCE Resource;
 
     /* Notifications support */
     PNOTIFY_SYNC NotifySync;
@@ -196,9 +218,6 @@ typedef struct _FCB_NAME_LINK {
     UCHAR Type;
 } FCB_NAME_LINK, *PFCB_NAME_LINK;
 
-#define FAT_NTC_FCB    (USHORT) 'CF'
-#define FAT_NTC_DCB    (USHORT) 'DF'
-
 typedef struct _FCB
 {
     FSRTL_ADVANCED_FCB_HEADER Header;
@@ -225,6 +244,8 @@ typedef struct _FCB
     FCB_NAME_LINK FileName[0x2];
     /* Buffer for the short name */
     WCHAR ShortNameBuffer[0xc];
+    /* Full file name */
+    UNICODE_STRING FullFileName;
     /* File basic info */
     FILE_BASIC_INFORMATION BasicInfo;
     union
@@ -285,6 +306,16 @@ typedef struct _CCB
     UCHAR Flags;
 } CCB, *PCCB;
 
+typedef enum _TYPE_OF_OPEN
+{
+    UnopenedFileObject,
+    UserFileOpen,
+    UserDirectoryOpen,
+    UserVolumeOpen,
+    VirtualVolumeFile,
+    DirectoryFile,
+    EaFile
+} TYPE_OF_OPEN;
 
 #define CCB_SEARCH_RETURN_SINGLE_ENTRY      0x01
 #define CCB_SEARCH_PATTERN_LEGAL_8DOT3      0x02