[fastfat_new]
authorAleksey Bragin <aleksey@reactos.org>
Sat, 17 Oct 2009 13:18:29 +0000 (13:18 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Sat, 17 Oct 2009 13:18:29 +0000 (13:18 +0000)
- Implement FatiOpenExistingFcb.
- Make FatGetFcbUnicodeName supporting DCBs.
- Implement FF_OpenW wrapper around FullFAT to support opening files/dirs using a unicode name.

svn path=/trunk/; revision=43528

reactos/drivers/filesystems/fastfat_new/create.c
reactos/drivers/filesystems/fastfat_new/fastfat.h
reactos/drivers/filesystems/fastfat_new/fatstruc.h
reactos/drivers/filesystems/fastfat_new/fcb.c
reactos/drivers/filesystems/fastfat_new/fullfat.c
reactos/drivers/filesystems/fastfat_new/lock.c

index a92494b..a3a7bfb 100644 (file)
 #define NDEBUG
 #include "fastfat.h"
 
-NTSYSAPI
-NTSTATUS
-NTAPI
-RtlUpcaseUnicodeStringToCountedOemString(
-    IN OUT POEM_STRING DestinationString,
-    IN PCUNICODE_STRING SourceString,
-    IN BOOLEAN AllocateDestinationString
-);
-
-
 /* FUNCTIONS *****************************************************************/
 
 IO_STATUS_BLOCK
index 6f79db7..2b843df 100644 (file)
     ExReleaseResourceLite(&(FatGlobalData.Resource)); \
 }
 
+NTSYSAPI
+NTSTATUS
+NTAPI
+RtlUpcaseUnicodeStringToCountedOemString(
+    IN OUT POEM_STRING DestinationString,
+    IN PCUNICODE_STRING SourceString,
+    IN BOOLEAN AllocateDestinationString
+);
+
 
 /*  ------------------------------------------------------  shutdown.c  */
 
@@ -211,6 +220,14 @@ FatReadBlocks(FF_T_UINT8 *pBuffer, FF_T_UINT32 SectorAddress, FF_T_UINT32 Count,
 NTSTATUS NTAPI
 FatLockControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
 
+VOID NTAPI
+FatOplockComplete(IN PVOID Context,
+                  IN PIRP Irp);
+
+VOID NTAPI
+FatPrePostIrp(IN PVOID Context,
+              IN PIRP Irp);
+
 /*  ---------------------------------------------------------  fsctl.c  */
 
 NTSTATUS NTAPI
@@ -221,6 +238,10 @@ FatFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
 NTSTATUS NTAPI FatQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp);
 NTSTATUS NTAPI FatSetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp);
 
+/*  ---------------------------------------------------------  fullfat.c  */
+
+FF_FILE *FF_OpenW(FF_IOMAN *pIoman, PUNICODE_STRING pathW, FF_T_UINT8 Mode, FF_ERROR *pError);
+
 /*  ---------------------------------------------------------  iface.c  */
 
 NTSTATUS
index 3b846c8..fbf6bdb 100644 (file)
@@ -133,9 +133,10 @@ typedef struct _FAT_METHODS {
     PFAT_SETFAT_VALUE_RUN_ROUTINE SetValueRun;
 } FAT_METHODS, *PFAT_METHODS;
 
-#define VCB_STATE_FLAG_LOCKED   0x01
-#define VCB_STATE_FLAG_DIRTY    0x02
-#define VCB_STATE_MOUNTED_DIRTY 0x04
+#define VCB_STATE_FLAG_LOCKED        0x01
+#define VCB_STATE_FLAG_DIRTY         0x02
+#define VCB_STATE_MOUNTED_DIRTY      0x04
+#define VCB_STATE_CREATE_IN_PROGRESS 0x08
 
 typedef enum _VCB_CONDITION
 {
@@ -249,6 +250,8 @@ typedef enum _FCB_CONDITION
 
 #define FCB_STATE_HAS_NAMES        0x01
 #define FCB_STATE_HAS_UNICODE_NAME 0x02
+#define FCB_STATE_PAGEFILE         0x04
+#define FCB_STATE_DELAY_CLOSE      0x08
 
 typedef struct _FCB
 {
@@ -264,7 +267,6 @@ typedef struct _FCB
     ERESOURCE Resource; // nonpaged!
     ERESOURCE PagingIoResource; // nonpaged!
 
-    FILE_LOCK Lock;
     /* First cluster in the fat allocation chain */
     ULONG FirstClusterOfFile;
     /* A list of all FCBs of that DCB */
@@ -305,6 +307,13 @@ typedef struct _FCB
     PKEVENT OutstandingAsyncEvent;
     union
     {
+        struct
+        {
+            /* File and Op locks */
+            FILE_LOCK Lock;
+            OPLOCK Oplock;
+        } Fcb;
+
         struct
         {
             /* A list of all FCBs/DCBs opened under this DCB */
index b9fe0d8..cbc8f57 100644 (file)
@@ -191,9 +191,243 @@ FatiOpenExistingFcb(IN PFAT_IRP_CONTEXT IrpContext,
                     OUT PBOOLEAN OplockPostIrp)
 {
     IO_STATUS_BLOCK Iosb = {{0}};
+    ACCESS_MASK AddedAccess = 0;
+    BOOLEAN Hidden;
+    BOOLEAN System;
+    PCCB Ccb = NULL;
+    NTSTATUS Status;
+
+    /* Acquire exclusive FCB lock */
+    (VOID)FatAcquireExclusiveFcb(IrpContext, Fcb);
+
+    *OplockPostIrp = FALSE;
+
+    /* Check if there is a batch oplock */
+    if (FsRtlCurrentBatchOplock(&Fcb->Fcb.Oplock))
+    {
+        /* Return with a special information field */
+        Iosb.Information = FILE_OPBATCH_BREAK_UNDERWAY;
+
+        /* Check the oplock */
+        Iosb.Status = FsRtlCheckOplock(&Fcb->Fcb.Oplock,
+                                       IrpContext->Irp,
+                                       IrpContext,
+                                       FatOplockComplete,
+                                       FatPrePostIrp);
+
+        if (Iosb.Status != STATUS_SUCCESS &&
+            Iosb.Status != STATUS_OPLOCK_BREAK_IN_PROGRESS)
+        {
+            /* The Irp needs to be queued */
+            *OplockPostIrp = TRUE;
+
+            /* Release the FCB and return */
+            FatReleaseFcb(IrpContext, Fcb);
+            return Iosb;
+        }
+    }
+
+    /* Validate parameters and modify access */
+    if (CreateDisposition == FILE_CREATE)
+    {
+        Iosb.Status = STATUS_OBJECT_NAME_COLLISION;
+
+        /* Release the FCB and return */
+        FatReleaseFcb(IrpContext, Fcb);
+        return Iosb;
+    }
+    else if (CreateDisposition == FILE_SUPERSEDE)
+    {
+        SetFlag(AddedAccess, DELETE & ~(*DesiredAccess));
+        *DesiredAccess |= DELETE;
+    }
+    else if ((CreateDisposition == FILE_OVERWRITE) ||
+             (CreateDisposition == FILE_OVERWRITE_IF))
+    {
+        SetFlag(AddedAccess,
+                (FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
+                & ~(*DesiredAccess) );
+
+        *DesiredAccess |= FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES;
+    }
+
+    // TODO: Check desired access
+
+    // TODO: Check if this file is readonly and DeleteOnClose is set
+
+    /* Validate disposition information */
+    if ((CreateDisposition == FILE_SUPERSEDE) ||
+        (CreateDisposition == FILE_OVERWRITE) ||
+        (CreateDisposition == FILE_OVERWRITE_IF))
+    {
+        // TODO: Get this attributes from the dirent
+        Hidden = FALSE;
+        System = FALSE;
+
+        if ((Hidden && !FlagOn(FileAttributes, FILE_ATTRIBUTE_HIDDEN)) ||
+            (System && !FlagOn(FileAttributes, FILE_ATTRIBUTE_SYSTEM)))
+        {
+            DPRINT1("Hidden/system attributes don't match\n");
+
+            Iosb.Status = STATUS_ACCESS_DENIED;
+
+            /* Release the FCB and return */
+            FatReleaseFcb(IrpContext, Fcb);
+            return Iosb;
+        }
+
+        // TODO: Check for write protected volume
+    }
+
+    /* Check share access */
+    Iosb.Status = IoCheckShareAccess(*DesiredAccess,
+                                     ShareAccess,
+                                     FileObject,
+                                     &Fcb->ShareAccess,
+                                     FALSE);
+    if (!NT_SUCCESS(Iosb.Status))
+    {
+        /* Release the FCB and return */
+        FatReleaseFcb(IrpContext, Fcb);
+        return Iosb;
+    }
+
+    /* Check the oplock status after checking for share access */
+    Iosb.Status = FsRtlCheckOplock(&Fcb->Fcb.Oplock,
+                                   IrpContext->Irp,
+                                   IrpContext,
+                                   FatOplockComplete,
+                                   FatPrePostIrp );
+
+    if (Iosb.Status != STATUS_SUCCESS &&
+        Iosb.Status != STATUS_OPLOCK_BREAK_IN_PROGRESS)
+    {
+        /* The Irp needs to be queued */
+        *OplockPostIrp = TRUE;
+
+        /* Release the FCB and return */
+        FatReleaseFcb(IrpContext, Fcb);
+        return Iosb;
+    }
+
+    /* Set Fast I/O flag */
+    Fcb->Header.IsFastIoPossible = FALSE; //FatiIsFastIoPossible(Fcb);
+
+    /* Make sure image is not mapped */
+    if (DeleteOnClose || FlagOn(*DesiredAccess, FILE_WRITE_DATA))
+    {
+        /* Try to flush the image section */
+        if (!MmFlushImageSection(&Fcb->SectionObjectPointers, MmFlushForWrite))
+        {
+            /* Yes, image section exists, set correct status code */
+            if (DeleteOnClose)
+                Iosb.Status = STATUS_CANNOT_DELETE;
+            else
+                Iosb.Status = STATUS_SHARING_VIOLATION;
+
+            /* Release the FCB and return */
+            FatReleaseFcb(IrpContext, Fcb);
+            return Iosb;
+        }
+    }
+
+    /* Flush the cache if it's non-cached non-pagefile access */
+    if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING) &&
+        Fcb->SectionObjectPointers.DataSectionObject &&
+        !FlagOn(Fcb->State, FCB_STATE_PAGEFILE))
+    {
+        /* Set the flag that create is in progress */
+        SetFlag(Fcb->Vcb->State, VCB_STATE_CREATE_IN_PROGRESS);
+
+        /* Flush the cache */
+        CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, NULL);
+
+        /* Acquire and release Paging I/O resource before purging the cache section
+           to let lazy writer finish */
+        ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource, TRUE);
+        ExReleaseResourceLite( Fcb->Header.PagingIoResource );
+
+        /* Delete the cache section */
+        CcPurgeCacheSection(&Fcb->SectionObjectPointers, NULL, 0, FALSE);
+
+        /* Clear the flag */
+        ClearFlag(Fcb->Vcb->State, VCB_STATE_CREATE_IN_PROGRESS);
+    }
+
+    /* Check create disposition flags and branch accordingly */
+    if (CreateDisposition == FILE_OPEN ||
+        CreateDisposition == FILE_OPEN_IF)
+    {
+        DPRINT("Opening a file\n");
+
+        /* Check if we need to bother with EA */
+        if (NoEaKnowledge && FALSE /* FatIsFat32(Vcb)*/)
+        {
+            UNIMPLEMENTED;
+        }
+
+        /* Set up file object */
+        Ccb = FatCreateCcb(IrpContext);
+        FatSetFileObject(FileObject,
+                         UserFileOpen,
+                         Fcb,
+                         Ccb);
+
+        FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
+
+        /* The file is opened */
+        Iosb.Information = FILE_OPENED;
+        goto SuccComplete;
+    }
+    else if ((CreateDisposition == FILE_SUPERSEDE) ||
+             (CreateDisposition == FILE_OVERWRITE) ||
+             (CreateDisposition == FILE_OVERWRITE_IF))
+    {
+        UNIMPLEMENTED;
+        ASSERT(FALSE);
+    }
+    else
+    {
+        /* We can't get here */
+        KeBugCheckEx(0x23, CreateDisposition, 0, 0, 0);
+    }
 
-    Iosb.Status = STATUS_NOT_IMPLEMENTED;
-    UNIMPLEMENTED;
+
+SuccComplete:
+    /* If all is fine */
+    if (Iosb.Status != STATUS_PENDING &&
+        NT_SUCCESS(Iosb.Status))
+    {
+        /* Update access if needed */
+        if (AddedAccess)
+        {
+            /* Remove added access flags from desired access */
+            ClearFlag(*DesiredAccess, AddedAccess);
+
+            /* Check share access */
+            Status = IoCheckShareAccess(*DesiredAccess,
+                                        ShareAccess,
+                                        FileObject,
+                                        &Fcb->ShareAccess,
+                                        TRUE);
+
+            /* Make sure it's success */
+            ASSERT(Status == STATUS_SUCCESS);
+        }
+        else
+        {
+            /* Update the share access */
+            IoUpdateShareAccess(FileObject, &Fcb->ShareAccess);
+        }
+
+        /* Clear the delay close */
+        ClearFlag(Fcb->State, FCB_STATE_DELAY_CLOSE);
+
+        /* Increase global volume counter */
+        Vcb->OpenFileCount++;
+
+        // TODO: Handle DeleteOnClose and OpenedAsDos by storing those flags in CCB
+    }
 
     return Iosb;
 }
@@ -213,11 +447,16 @@ FatGetFcbUnicodeName(IN PFAT_IRP_CONTEXT IrpContext,
     OEM_STRING LongNameOem;
     NTSTATUS Status;
 
-    /* We support only files now, not directories */
-    if (Fcb->Header.NodeTypeCode != FAT_NTC_FCB)
+    /* Make sure this FCB has a FullFAT handle associated with it */
+    if (Fcb->FatHandle == NULL &&
+        FatNodeType(Fcb) == FAT_NTC_DCB)
     {
-        UNIMPLEMENTED;
-        ASSERT(FALSE);
+        /* Open the dir with FullFAT */
+        Fcb->FatHandle = FF_OpenW(Fcb->Vcb->Ioman, &Fcb->FullFileName, FF_MODE_DIR, NULL);
+        if (!Fcb->FatHandle)
+        {
+            ASSERT(FALSE);
+        }
     }
 
     /* Get the dir entry */
index bb0947a..f140706 100644 (file)
@@ -77,4 +77,27 @@ FatReadBlocks(FF_T_UINT8 *DestBuffer, FF_T_UINT32 SectorAddress, FF_T_UINT32 Cou
     return Count;
 }
 
+FF_FILE *FF_OpenW(FF_IOMAN *pIoman, PUNICODE_STRING pathW, FF_T_UINT8 Mode, FF_ERROR *pError)
+{
+    OEM_STRING AnsiName;
+    CHAR AnsiNameBuf[512];
+    NTSTATUS Status;
+
+    /* Convert the name to ANSI */
+    AnsiName.Buffer = AnsiNameBuf;
+    AnsiName.Length = 0;
+    AnsiName.MaximumLength = sizeof(AnsiNameBuf);
+    RtlZeroMemory(AnsiNameBuf, sizeof(AnsiNameBuf));
+    Status = RtlUpcaseUnicodeStringToCountedOemString(&AnsiName, pathW, FALSE);
+    if (!NT_SUCCESS(Status))
+    {
+        ASSERT(FALSE);
+    }
+
+    DPRINT1("Opening '%s'\n", AnsiName.Buffer);
+
+    /* Call FullFAT's handler */
+    return FF_Open(pIoman, AnsiName.Buffer, Mode, pError);
+}
+
 /* EOF */
index b72488c..d56cbc2 100644 (file)
@@ -21,4 +21,20 @@ FatLockControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
     return STATUS_NOT_IMPLEMENTED;
 }
 
+VOID
+NTAPI
+FatOplockComplete(IN PVOID Context,
+                  IN PIRP Irp)
+{
+    UNIMPLEMENTED;
+}
+
+VOID
+NTAPI
+FatPrePostIrp(IN PVOID Context,
+              IN PIRP Irp)
+{
+    UNIMPLEMENTED;
+}
+
 /* EOF */