[fastfat_new]
authorAleksey Bragin <aleksey@reactos.org>
Tue, 20 Oct 2009 10:02:27 +0000 (10:02 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Tue, 20 Oct 2009 10:02:27 +0000 (10:02 +0000)
- Cleanup the source code from parts which aren't needed anymore (after switching to FullFAT library usage). About 40kb of source code removed.

svn path=/trunk/; revision=43641

reactos/drivers/filesystems/fastfat_new/blockdev.c [deleted file]
reactos/drivers/filesystems/fastfat_new/direntry.c [deleted file]
reactos/drivers/filesystems/fastfat_new/fastfat.h
reactos/drivers/filesystems/fastfat_new/fastfat.rbuild
reactos/drivers/filesystems/fastfat_new/fat.c
reactos/drivers/filesystems/fastfat_new/fatstruc.h
reactos/drivers/filesystems/fastfat_new/fullfat.c
reactos/drivers/filesystems/fastfat_new/rw.c

diff --git a/reactos/drivers/filesystems/fastfat_new/blockdev.c b/reactos/drivers/filesystems/fastfat_new/blockdev.c
deleted file mode 100644 (file)
index 8e1d0fb..0000000
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- * PROJECT:         ReactOS FAT file system driver
- * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            drivers/filesystems/fastfat/blockdev.c
- * PURPOSE:         Temporary sector reading support
- * PROGRAMMERS:     Alexey Vlasov
- */
-
-/* INCLUDES *****************************************************************/
-
-#define NDEBUG
-#include "fastfat.h"
-
-/* FUNCTIONS ***************************************************************/
-//FIXME: There is a conflicting function FatPerformDevIoCtrl doing same thing!
-NTSTATUS 
-FatDiskIoControl_(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN ULONG IoCtlCode,
-    IN PVOID InputBuffer,
-    IN ULONG InputBufferSize,
-    IN OUT PVOID OutputBuffer,
-    IN OUT PULONG OutputBufferSize OPTIONAL)
-{
-    PIRP Irp;
-    KEVENT Event;
-    NTSTATUS Status;
-    ULONG OutBufferSize;
-    IO_STATUS_BLOCK IoStatus;
-
-    /* Set out buffer size if it was supplied. */
-    OutBufferSize = (ARGUMENT_PRESENT(OutputBufferSize)
-        ? 0 : *OutputBufferSize);
-
-    /* Initialize event if the operation will be pended. */
-    KeInitializeEvent(&Event, NotificationEvent, FALSE);
-
-    /* Build the Irp. */
-    Irp = IoBuildDeviceIoControlRequest(IoCtlCode, DeviceObject,
-        InputBuffer, InputBufferSize, OutputBuffer, OutBufferSize,
-        FALSE, &Event, &IoStatus);
-    if (Irp == NULL)
-        return STATUS_INSUFFICIENT_RESOURCES;
-
-    /* Send IRP to Disk Device */
-    Status = IoCallDriver(DeviceObject, Irp);
-    if (Status == STATUS_PENDING)
-    {
-        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
-        Status = IoStatus.Status;
-    }
-
-    /* Return output buffer length if required. */
-    if (ARGUMENT_PRESENT(OutputBufferSize))
-        *OutputBufferSize = IoStatus.Information;
-    return Status;
-}
-
-NTSTATUS
-FatLockUserBuffer (
-    IN PFAT_IRP_CONTEXT IrpContext,
-    IN LOCK_OPERATION Operation,
-    IN ULONG BufferLength)
-/*
- * FUNCTION:
- *      
- *      
- * ARGUMENTS:
- *      IrpContext = Pointer to FCB structure for the file.
- *      Operation = Type of lock operation.
- *      BufferLength = Buffer length to be locked.
- * RETURNS: Status Value.
- * NOTES:
- */
-{
-    PMDL Mdl;
-    PIRP Irp;
-    NTSTATUS Status;
-
-    Mdl = NULL;
-    Irp = IrpContext->Irp;
-    Status = STATUS_SUCCESS;
-    if (Irp->MdlAddress == NULL)
-    {
-        NTSTATUS Status;
-        Mdl = IoAllocateMdl(Irp->UserBuffer,
-        BufferLength, FALSE, FALSE, Irp);
-        if (Mdl == NULL)
-            return STATUS_INSUFFICIENT_RESOURCES;
-        _SEH2_TRY
-        {
-            MmProbeAndLockPages(Mdl,
-            Irp->RequestorMode, Operation);
-        }
-        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-        {
-            Status = _SEH2_GetExceptionCode();
-            IoFreeMdl( Mdl );
-            Irp->MdlAddress = NULL;
-        } _SEH2_END
-    }
-    return Status;
-}
-
-NTSTATUS
-FatIoSyncCompletionRoutine(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN PIRP Irp,
-    IN PVOID Context)
-{
-    PFAT_IO_CONTEXT IoContext;
-
-    IoContext = (PFAT_IO_CONTEXT) Context;
-
-   /* Check if this is an associated irp. */
-    if (Irp != IoContext->Irp)
-    {
-        if (!NT_SUCCESS(Irp->IoStatus.Status))
-            IoContext->Irp->IoStatus = Irp->IoStatus;
-        IoFreeMdl(Irp->MdlAddress);
-        IoFreeIrp(Irp);
-        if (InterlockedDecrement(&IoContext->RunCount) != 0)
-            return STATUS_MORE_PROCESSING_REQUIRED;
-        /* This was the last run, update master irp. */
-        if (NT_SUCCESS(IoContext->Irp->IoStatus.Status))
-            IoContext->Irp->IoStatus.Information = IoContext->Length;
-    }
-
-    /* This is the last associated irp or a single irp IO. */
-    if (NT_SUCCESS(IoContext->Irp->IoStatus.Status) &&
-        !FlagOn(IoContext->Irp->Flags, IRP_PAGING_IO))
-    {
-        /* Maintain FileObject CurrentByteOffset */
-        IoContext->FileObject->CurrentByteOffset.QuadPart =
-            IoContext->Offset + IoContext->Irp->IoStatus.Information;
-    }
-
-    /* Signal about completion. */
-    KeSetEvent(&IoContext->Wait.SyncEvent, 0, FALSE);
-    return STATUS_MORE_PROCESSING_REQUIRED;
-}
-
-NTSTATUS
-FatIoAsyncCompletionRoutine(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN PIRP Irp,
-    IN PVOID Context)
-{
-    PFAT_IO_CONTEXT IoContext;
-
-    IoContext = (PFAT_IO_CONTEXT) Context;
-
-   /* Check if this is an associated irp. */
-    if (Irp != IoContext->Irp)
-    {
-        if (!NT_SUCCESS(Irp->IoStatus.Status))
-            IoContext->Irp->IoStatus = Irp->IoStatus;
-        IoFreeMdl(Irp->MdlAddress);
-        IoFreeIrp(Irp);
-        if (InterlockedDecrement(&IoContext->RunCount) != 0)
-            return STATUS_MORE_PROCESSING_REQUIRED;
-        /* This was the last run, update master irp. */
-        if (NT_SUCCESS(IoContext->Irp->IoStatus.Status))
-            IoContext->Irp->IoStatus.Information = IoContext->Length;
-    }
-
-
-    /* This is the last associated irp or a single irp IO. */
-    if (NT_SUCCESS(IoContext->Irp->IoStatus.Status) &&
-        !FlagOn(IoContext->Irp->Flags, IRP_PAGING_IO))
-    {
-        /* Maintain FileObject Flags */
-        if (IoGetCurrentIrpStackLocation(IoContext->Irp)->MajorFunction
-                == IRP_MJ_READ)
-        {
-            SetFlag(IoContext->FileObject->Flags, FO_FILE_FAST_IO_READ);
-        }
-        else
-        {
-            SetFlag(IoContext->FileObject->Flags, FO_FILE_MODIFIED);
-        }
-    }
-    if (IoContext->Wait.Async.Resource != NULL)
-        ExReleaseResourceForThreadLite(
-            IoContext->Wait.Async.Resource,
-            IoContext->Wait.Async.ResourceThreadId);
-
-    if (IoContext->Wait.Async.PagingIoResource != NULL)
-        ExReleaseResourceForThreadLite(
-            IoContext->Wait.Async.PagingIoResource,
-            IoContext->Wait.Async.ResourceThreadId);
-
-    IoMarkIrpPending(Irp);
-    ExFreePool(Context);
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-NTAPI
-FatPerformLboIo(
-    IN PFAT_IRP_CONTEXT IrpContext,
-    IN PLARGE_INTEGER Offset,
-    IN SIZE_T Length)
-{
-    BOOLEAN CanWait, ReadOperation;
-    PIO_STACK_LOCATION IoStack;
-
-    CanWait = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT);
-    ReadOperation = (IrpContext->Stack->MajorFunction == IRP_MJ_READ);
-
-    /* Allocate completion context */
-    IrpContext->FatIoContext = FsRtlAllocatePoolWithTag(
-        NonPagedPool, sizeof(FAT_IO_CONTEXT), (ULONG) 'xCoI');
-
-    if (IrpContext->FatIoContext == NULL)
-        return STATUS_INSUFFICIENT_RESOURCES;
-
-    RtlZeroMemory(IrpContext->FatIoContext,
-        sizeof(FAT_IO_CONTEXT));
-
-    /* Initialize event if we are supposed to wait. */
-    if (CanWait)
-    {
-        KeInitializeEvent(
-            &IrpContext->FatIoContext->Wait.SyncEvent,
-            NotificationEvent, FALSE);
-    }
-
-    /* Set the completion routine depending on wait semantics. */
-    IoSetCompletionRoutine(IrpContext->Irp,
-        (CanWait
-            ? FatIoSyncCompletionRoutine
-            : FatIoAsyncCompletionRoutine),
-        IrpContext->FatIoContext, TRUE, TRUE, TRUE);
-
-    /* Setup stack location. */
-    IoStack = IoGetNextIrpStackLocation(IrpContext->Irp);
-    IoStack->MajorFunction = IrpContext->MajorFunction;
-    IoStack->Parameters.Read.Length = (ULONG) Length;
-    IoStack->Parameters.Read.ByteOffset = *Offset;
-    if (FlagOn(IrpContext->Flags, IRPCONTEXT_WRITETHROUGH))
-        SetFlag(IoStack->Flags, SL_WRITE_THROUGH);
-
-    IoCallDriver(
-        IrpContext->Vcb->TargetDeviceObject,
-        IrpContext->Irp);
-    if (CanWait)
-    {
-        KeWaitForSingleObject(
-            &IrpContext->FatIoContext->Wait.SyncEvent,
-            Executive, KernelMode, FALSE, NULL);
-        return IrpContext->Irp->IoStatus.Status;
-    }
-    SetFlag(IrpContext->Flags, IRPCONTEXT_STACK_IO_CONTEXT);
-    return STATUS_PENDING;
-}
-
-
-
-NTSTATUS
-FatPerformVirtualNonCachedIo(
-    IN PFAT_IRP_CONTEXT IrpContext,
-    IN PFCB Fcb,
-    IN PLARGE_INTEGER Offset,
-    IN SIZE_T Length)
-{
-    NTSTATUS Status;
-    PIO_STACK_LOCATION IoStack;
-    LONGLONG Vbo, Lbo, RunLength;
-    ULONG RunCount, CleanupIndex, FirstIndex, BeyoundLastIndex;
-    BOOLEAN CanWait, ReadOperation;
-    PIRP* RunIrp;
-    PMDL Mdl;
-
-    ASSERT(IrpContext->FatIoContext == NULL);
-
-
-    FirstIndex = CleanupIndex = 0;
-    CanWait = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT);
-    ReadOperation = (IrpContext->Stack->MajorFunction == IRP_MJ_READ);
-    Status = FatLockUserBuffer(IrpContext,
-        (ReadOperation ? IoWriteAccess : IoReadAccess),
-        Length);
-    if (!NT_SUCCESS(Status))
-        goto FatIoPerformNonCachedCleanup;
-    Vbo = Offset->QuadPart;
-    RunLength = Length;
-    _SEH2_TRY
-    {
-        BeyoundLastIndex = FatScanFat(Fcb, Vbo,
-            &Lbo, &RunLength, &FirstIndex, CanWait);
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        Status = _SEH2_GetExceptionCode();
-        _SEH2_YIELD(goto FatIoPerformNonCachedCleanup;)
-    }_SEH2_END
-    RunCount = BeyoundLastIndex - FirstIndex;
-    if (RunCount == 0)
-    {
-        Status = STATUS_END_OF_FILE;
-        goto FatIoPerformNonCachedCleanup;
-    }
-    Length = sizeof(FAT_IO_CONTEXT);
-    if (RunCount > 0x1)
-        Length += RunCount * sizeof(PIRP);
-    IrpContext->FatIoContext = FsRtlAllocatePoolWithTag(
-        NonPagedPool, Length, (ULONG) 'xCoI');
-    if (IrpContext->FatIoContext == NULL)
-    {
-        Status = STATUS_INSUFFICIENT_RESOURCES;
-        goto FatIoPerformNonCachedCleanup;
-    }
-    RtlZeroMemory(IrpContext->FatIoContext, Length);
-    if (CanWait)
-    {
-        KeInitializeEvent(
-            &IrpContext->FatIoContext->Wait.SyncEvent,
-            NotificationEvent, FALSE);
-    }
-    if (RunCount == 0x1)
-    {
-        IoSetCompletionRoutine(IrpContext->Irp,
-            (CanWait ? FatIoSyncCompletionRoutine
-            : FatIoAsyncCompletionRoutine),
-        IrpContext->FatIoContext, TRUE, TRUE, TRUE);
-        IoStack = IoGetNextIrpStackLocation(IrpContext->Irp);
-        IoStack->MajorFunction = IrpContext->Stack->MajorFunction;
-        IoStack->Parameters.Read.Length = (ULONG) RunLength;
-        IoStack->Parameters.Read.ByteOffset.QuadPart = Lbo;
-        IoStack->Flags = FlagOn(
-            IrpContext->Stack->Flags,
-            SL_WRITE_THROUGH);
-        Status = IoCallDriver(
-            IrpContext->Vcb->TargetDeviceObject,
-            IrpContext->Irp);
-        goto FatIoPerformNonCachedComplete;
-    }
-   /*
-    * We already have the first run retrieved by FatiScanFat.
-    */
-    for (RunIrp = &IrpContext->FatIoContext->Irp,
-            CleanupIndex = FirstIndex;
-        CleanupIndex < BeyoundLastIndex;
-        CleanupIndex ++, RunIrp ++)
-    {
-#if DBG
-        LONGLONG NextVbo = Vbo + RunLength;
-        BOOLEAN RunExists;
-#endif
-       /*
-        * Allocate Irp for the run.
-        */
-        *RunIrp = IoMakeAssociatedIrp(IrpContext->Irp,
-            (CCHAR)(IrpContext->Vcb->TargetDeviceObject->StackSize + 1));
-        if (*RunIrp == NULL) 
-        {
-            Status = STATUS_INSUFFICIENT_RESOURCES;
-            goto FatIoPerformNonCachedCleanup;
-        }
-        CleanupIndex ++;
-        /*
-        * Build Mdl for the run range.
-        */
-        Mdl = IoAllocateMdl(
-            Add2Ptr(IrpContext->Irp->UserBuffer, Vbo, PVOID),
-            (ULONG) RunLength, FALSE, FALSE, *RunIrp);
-        if (Mdl == NULL) 
-        {
-            Status = STATUS_INSUFFICIENT_RESOURCES;
-            goto FatIoPerformNonCachedCleanup;
-        }
-        IoBuildPartialMdl(IrpContext->Irp->MdlAddress, Mdl,
-            Add2Ptr(IrpContext->Irp->UserBuffer, Vbo, PVOID),
-            (ULONG) RunLength);
-        /*
-        * Setup IRP for each run.
-        */
-        IoSetCompletionRoutine(IrpContext->Irp,
-            (CanWait ? FatIoSyncCompletionRoutine
-                : FatIoAsyncCompletionRoutine),
-        IrpContext->FatIoContext, TRUE, TRUE, TRUE);
-        IoStack = IoGetNextIrpStackLocation(*RunIrp);
-        IoStack->MajorFunction = IrpContext->Stack->MajorFunction;
-        IoStack->Parameters.Read.Length = (ULONG) RunLength;
-        IoStack->Parameters.Read.ByteOffset.QuadPart = Lbo;
-
-        /*
-        * Propagate write-through to the associated IRPs
-        */
-        if (FlagOn(IrpContext->Flags, IRPCONTEXT_WRITETHROUGH))
-            SetFlag(IoStack->Flags, SL_WRITE_THROUGH);
-        /*
-        * Prepare for next iteration:
-        */
-    #if DBG
-        RunExists =
-    #endif
-        FsRtlGetNextLargeMcbEntry(&Fcb->Mcb, CleanupIndex, &Vbo, &Lbo, &RunLength);
-        ASSERT(RunExists);
-        ASSERT(NextVbo == Vbo);
-    }
-   /*
-    * Send all IRPs to the volume device, we don't need to check
-    * status code because cleanup will be done
-    * by the completion routine in any case.
-    */
-    for (RunIrp = &IrpContext->FatIoContext->Irp,
-        CleanupIndex = FirstIndex;
-        CleanupIndex < BeyoundLastIndex;
-        CleanupIndex ++, RunIrp ++)
-    {
-        IoCallDriver(IrpContext->Vcb->TargetDeviceObject, *RunIrp);
-    }
-
-FatIoPerformNonCachedComplete:
-    if (CanWait)
-    {
-        KeWaitForSingleObject(
-            &IrpContext->FatIoContext->Wait.SyncEvent,
-            Executive, KernelMode, FALSE, NULL);
-        return IrpContext->Irp->IoStatus.Status;
-    }
-    SetFlag(IrpContext->Flags, IRPCONTEXT_STACK_IO_CONTEXT);
-    return STATUS_PENDING;
-   /*
-    * The following block of code implements unwind logic
-    */
-FatIoPerformNonCachedCleanup:
-    if (IrpContext->FatIoContext != NULL)
-    {
-        RunIrp = &IrpContext->FatIoContext->Irp;
-        while (FirstIndex < CleanupIndex)
-        {
-            if ((*RunIrp)->MdlAddress != NULL)
-                IoFreeMdl((*RunIrp)->MdlAddress);
-            IoFreeIrp(*RunIrp);
-            FirstIndex ++;
-            RunIrp ++;
-        }
-        ExFreePool(IrpContext->FatIoContext);
-        IrpContext->FatIoContext = NULL;
-    }
-    return Status;
-}
-
-/* EOF */
diff --git a/reactos/drivers/filesystems/fastfat_new/direntry.c b/reactos/drivers/filesystems/fastfat_new/direntry.c
deleted file mode 100644 (file)
index d50d268..0000000
+++ /dev/null
@@ -1,775 +0,0 @@
-/*
- * PROJECT:         ReactOS FAT file system driver
- * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            drivers/filesystems/fastfat/direntry.c
- * PURPOSE:         Directory entries
- * PROGRAMMERS:     Alexey Vlasov
- */
-
-/* INCLUDES *****************************************************************/
-
-#define NDEBUG
-#include "fastfat.h"
-
-/* PROTOTYPES ***************************************************************/
-
-typedef enum _FILE_TIME_INDEX
-{
-    FileCreationTime = 0,
-    FileLastAccessTime,
-    FileLastWriteTime,
-    FileChangeTime
-} FILE_TIME_INDEX;
-
-VOID
-Fat8dot3ToUnicodeString(OUT PUNICODE_STRING FileName,
-                        IN PUCHAR ShortName,
-                        IN UCHAR Flags);
-
-ULONG
-FatDirentToDirInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
-                   IN PDIR_ENTRY Dirent,
-                   IN PVOID Buffer);
-
-ULONG
-FatDirentToFullDirInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
-                       IN PDIR_ENTRY Dirent,
-                       IN PVOID Buffer);
-
-ULONG
-FatDirentToIdFullDirInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
-                         IN PDIR_ENTRY Dirent,
-                         IN PVOID Buffer);
-
-ULONG
-FatDirentToBothDirInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
-                       IN PDIR_ENTRY Dirent,
-                       IN PVOID Buffer);
-
-ULONG
-FatDirentToIdBothDirInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
-                         IN PDIR_ENTRY Dirent,
-                         IN PVOID Buffer);
-
-ULONG
-FatDirentToNamesInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
-                     IN PDIR_ENTRY Dirent,
-                     IN PVOID Buffer);
-
-ULONG
-FatDirentToObjectIdInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
-                        IN PDIR_ENTRY Dirent,
-                        IN PVOID Buffer);
-
-/* FUNCTIONS *****************************************************************/
-
-#define FatQueryFileName(xInfo, xDirent)                    \
-{                                                           \
-    UNICODE_STRING FileName;                                \
-    if (Info->FileNameLength == 0)                          \
-    {                                                       \
-        FileName.Buffer = Info->FileName;                   \
-        FileName.MaximumLength = 0x18;                      \
-        Fat8dot3ToUnicodeString(&FileName,                  \
-            (xDirent)->FileName, (xDirent)->Case);          \
-        Info->FileNameLength = FileName.Length;             \
-    }                                                       \
-}
-
-#define FatQueryBothFileName(xInfo, xDirent)                \
-{                                                           \
-    UNICODE_STRING FileName;                                \
-    FileName.MaximumLength = 0x18;                          \
-    if (Info->FileNameLength == 0)                          \
-    {                                                       \
-        FileName.Buffer = Info->FileName;                   \
-        Fat8dot3ToUnicodeString(&FileName,                  \
-            (xDirent)->FileName, (xDirent)->Case);          \
-        Info->FileNameLength = FileName.Length;             \
-        Info->ShortNameLength = 0;                          \
-    }                                                       \
-    else                                                    \
-    {                                                       \
-        FileName.Buffer = Info->ShortName;                  \
-        Fat8dot3ToUnicodeString(&FileName,                  \
-            (xDirent)->FileName, (xDirent)->Case);          \
-        Info->ShortNameLength = (CCHAR) FileName.Length;    \
-    }                                                       \
-}
-
-FORCEINLINE
-UCHAR
-FatLfnChecksum(
-    PUCHAR Buffer
-)
-{
-    UCHAR Index, Chksum;
-
-    for (Index = 0x1, Chksum = *Buffer;
-        Index < RTL_FIELD_SIZE(DIR_ENTRY, FileName);
-        Index ++)
-    {
-        Chksum = (((Chksum & 0x1) << 0x7) | (Chksum >> 0x1))
-            + Buffer[Index];
-    }
-    return Chksum;
-}
-
-VOID
-FatFindDirent(IN OUT PFAT_FIND_DIRENT_CONTEXT Context,
-              OUT PDIR_ENTRY* Dirent,
-              OUT PUNICODE_STRING LongFileName OPTIONAL)
-{
-    PDIR_ENTRY Entry, EndOfPage;
-    UCHAR SeqNum = 0, Checksum = 0;
-    PUNICODE_STRING FileName;
-
-    /* Pin first page. */
-    Entry = (PDIR_ENTRY) FatPinPage(&Context->Page, 0);
-    EndOfPage = FatPinEndOfPage(&Context->Page, PDIR_ENTRY);
-
-    /* Run dirents. */
-    FileName = NULL;
-    while (TRUE)
-    {
-        /* Check if we have entered the area of never used dirents */
-        if (Entry->FileName[0] == FAT_DIRENT_NEVER_USED)
-            ExRaiseStatus(STATUS_OBJECT_NAME_NOT_FOUND);
-
-        /* Just ignore entries marked as deleted */
-        if (Entry->FileName[0] == FAT_DIRENT_DELETED)
-            goto FatFindDirentNext;
-
-        /* Check if it's an lfn */
-        if (Entry->Attributes == FAT_DIRENT_ATTR_LFN)
-        {
-            PLONG_FILE_NAME_ENTRY LfnEntry;
-       
-            FileName = LongFileName;
-            LfnEntry = (PLONG_FILE_NAME_ENTRY) Entry;
-
-            /* Run lfns and collect file name if required */
-            do {
-                PWSTR Lfn;
-
-                /* Check if we just running lfn */
-                if (FileName == NULL)
-                    goto FatFindDirentRunLfn;
-
-                /* Check for cluster index to be zero. */
-                if (LfnEntry->Reserved != 0)
-                {
-                    FileName = NULL;
-                    goto FatFindDirentRunLfn;
-                }
-
-                /* Check if this is the last lfn entry. */
-                if (FlagOn(LfnEntry->SeqNum, FAT_FN_DIR_ENTRY_LAST))
-                {
-                    SeqNum = (LfnEntry->SeqNum & ~FAT_FN_DIR_ENTRY_LAST);
-                    Checksum = LfnEntry->Checksum;
-
-                    /* Check if we exceed max number of lfns */
-                    if (SeqNum > (FAT_FN_MAX_DIR_ENTIES + 1))
-                    {
-                        FileName = NULL;
-                        goto FatFindDirentRunLfn;
-                    }
-
-                    /* Setup maximal expected lfn length */
-                    FileName->Length = (SeqNum * FAT_LFN_NAME_LENGTH);
-
-                    /* Extend lfn buffer if needed */
-                    if (FileName->Length > FileName->MaximumLength)
-                    {
-                        Lfn = ExAllocatePoolWithTag(PagedPool,
-                            LongFileName->Length, TAG_VFAT);
-                        if (Lfn == NULL)
-                            ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
-                        if (FileName->Buffer != NULL)
-                            ExFreePool(FileName->Buffer);
-                        FileName->Buffer = Lfn;
-                        FileName->MaximumLength = FileName->Length;
-                    }
-                }
-                else if (!(LfnEntry->SeqNum == SeqNum
-                    && LfnEntry->Checksum == Checksum))
-                {
-                   /* Wrong SeqNum or CheckSum. */
-                    FileName = NULL;
-                    goto FatFindDirentRunLfn;
-                }
-                /* Gather file name */
-                Lfn = Add2Ptr(FileName->Buffer, (SeqNum * FAT_LFN_NAME_LENGTH)
-                        - sizeof(LfnEntry->NameC), PWSTR);
-                RtlCopyMemory(Lfn, LfnEntry->NameC, sizeof(LfnEntry->NameC));
-                Lfn -= (sizeof(LfnEntry->NameB) / sizeof(WCHAR));
-                RtlCopyMemory(Lfn, LfnEntry->NameB, sizeof(LfnEntry->NameB));
-                Lfn -= (sizeof(LfnEntry->NameA) / sizeof(WCHAR));
-                RtlCopyMemory(Lfn, LfnEntry->NameA, sizeof(LfnEntry->NameA));
-
-                /* If last lfn determine exact lfn length. */
-                if (FlagOn(LfnEntry->SeqNum, FAT_FN_DIR_ENTRY_LAST))
-                {
-                    PWSTR LfnEnd = Add2Ptr(FileName->Buffer,
-                        (FileName->Length - sizeof(WCHAR)), PWSTR);
-
-                    /* Trim trailing 0xffff's */
-                    while (LfnEnd > Lfn && *LfnEnd == 0xffff) --LfnEnd;
-
-                    /* Trim 0 terminator is the one is there. */
-                    if (*LfnEnd == 0x0) --LfnEnd;
-
-                    /* Set correct lfn size */
-                    FileName->Length = (USHORT)PtrOffset(FileName->Buffer, LfnEnd);
-                }
-                /* Setup validation for the next iteration */
-                SeqNum = LfnEntry->SeqNum - 0x1;
-                Checksum = LfnEntry->Checksum;
-
-FatFindDirentRunLfn:
-                /* Get next dirent */
-                LfnEntry ++;
-                if (LfnEntry > (PLONG_FILE_NAME_ENTRY) EndOfPage)
-                {
-                    if (FatPinIsLastPage(&Context->Page))
-                        ExRaiseStatus(STATUS_OBJECT_NAME_NOT_FOUND);
-                    LfnEntry = (PLONG_FILE_NAME_ENTRY) FatPinNextPage(&Context->Page);
-                    EndOfPage = FatPinEndOfPage(&Context->Page, PDIR_ENTRY);
-                }
-            }
-            while (LfnEntry->Attributes == FAT_DIRENT_ATTR_LFN);
-            Entry = (PDIR_ENTRY) LfnEntry;
-            continue;
-        }
-
-        /* If we've got here then this is a normal dirent */
-        if (FileName != NULL && FileName->Length > 0)
-        {
-            /* Check if we have a correct lfn collected. */
-            if (FatLfnChecksum(Entry->FileName) != Checksum)
-            {
-                FileName = NULL;
-            }
-            else
-            {
-                /* See if we were looking for this dirent. */
-                if (!Context->Valid8dot3Name &&
-                    FsRtlAreNamesEqual(FileName, Context->FileName, TRUE, NULL))
-                {
-                    Fat8dot3ToUnicodeString(&Context->ShortName, Entry->FileName, Entry->Case);
-                    *Dirent = Entry;
-                    return;
-                }
-            }
-        }
-
-       /* We surely have a short name, check if we were looking for that. */
-        if (Context->Valid8dot3Name)
-        {
-            Fat8dot3ToUnicodeString(&Context->ShortName,
-                Entry->FileName, Entry->Case);
-            if (FsRtlAreNamesEqual(&Context->ShortName, Context->FileName, TRUE, NULL))
-            {
-                if (ARGUMENT_PRESENT(LongFileName) && FileName == NULL)
-                    LongFileName->Length = 0;
-                *Dirent = Entry;
-                return;
-            }
-        }
-        FileName = NULL;
-
-FatFindDirentNext:
-        Entry ++;
-        if (Entry > EndOfPage)
-        {
-            if (FatPinIsLastPage(&Context->Page))
-                ExRaiseStatus(STATUS_OBJECT_NAME_NOT_FOUND);
-            Entry = (PDIR_ENTRY) FatPinNextPage(&Context->Page);
-            EndOfPage = FatPinEndOfPage(&Context->Page, PDIR_ENTRY);
-        }
-    }
-    /* Should never get here! */
-    ASSERT(TRUE);
-}
-
-VOID
-FatEnumerateDirents(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
-                    IN SIZE_T Offset)
-{
-    PUCHAR Entry, EndOfPage;
-    PWSTR FileName;
-    USHORT FileNameLength;
-    USHORT FileNameMaximumLength;
-    PVOID InfoEntry;
-    UCHAR SeqNum = 0;
-    UCHAR Checksum = 0;
-
-    /* Pin first page. */
-    Entry = (PUCHAR)FatPinPage(&Context->Page, Offset);
-    EndOfPage = FatPinEndOfPage(&Context->Page, PUCHAR);
-
-    /* Iterate dirents. */
-    while (TRUE)
-    {
-        /* Check if we have entered the area of never used dirents */
-        if (*Entry == FAT_DIRENT_NEVER_USED)
-            ExRaiseStatus(STATUS_NO_MORE_FILES);
-
-        /* Just ignore entries marked as deleted */
-        if (*Entry == FAT_DIRENT_DELETED)
-            goto FatEnumerateDirentsNext;
-
-        /* Get info pointer. */
-        InfoEntry = Add2Ptr(Context->Buffer, Context->Offset, PVOID);
-
-        /* Check if info class has file name */
-        if (Context->NameOffset == Context->LengthOffset)
-        {
-            FileName = NULL;
-            FileNameMaximumLength = 0;
-        }
-        else
-        {
-            FileName = Add2Ptr(InfoEntry, Context->NameOffset, PWSTR);
-            FileNameMaximumLength = (USHORT) (Context->Length
-                - Context->Offset + Context->NameOffset);
-        }
-        FileNameLength = 0;
-
-        /* Check if it's an lfn */
-        while (Entry[0xb] == FAT_DIRENT_ATTR_LFN)
-        {
-            PWSTR Lfn;
-            PLONG_FILE_NAME_ENTRY LfnEntry;
-
-            /* Check if we just running lfn */
-            if (FileNameMaximumLength == 0)
-                goto FatEnumerateDirentsRunLfn;
-
-            LfnEntry = (PLONG_FILE_NAME_ENTRY) Entry;
-
-            /* Check for cluster index to be zero. */
-            if (LfnEntry->Reserved != 0)
-            {
-                FileNameMaximumLength = 0;
-                goto FatEnumerateDirentsRunLfn;
-            }
-
-            /* Check if this is the last lfn entry. */
-            if (FlagOn(LfnEntry->SeqNum, FAT_FN_DIR_ENTRY_LAST))
-            {
-                SeqNum = (LfnEntry->SeqNum & ~FAT_FN_DIR_ENTRY_LAST);
-                Checksum = LfnEntry->Checksum;
-
-                /* Check if we exceed max number of lfns */
-                if (SeqNum > (FAT_FN_MAX_DIR_ENTIES + 1))
-                {
-                    FileNameMaximumLength = 0;
-                    goto FatEnumerateDirentsRunLfn;
-                }
-
-                /* Setup maximal expected lfn length */
-                FileNameLength = SeqNum * FAT_LFN_NAME_LENGTH;
-
-                /* Validate the maximal expected lfn length */
-                if (FileNameLength > FileNameMaximumLength)
-                    goto FatEnumerateDirentsRunLfn;
-            }
-            else if (!(LfnEntry->SeqNum == SeqNum
-                && LfnEntry->Checksum == Checksum))
-            {
-               /* Wrong SeqNum or CheckSum. */
-                FileNameMaximumLength = 0;
-                goto FatEnumerateDirentsRunLfn;
-            }
-            /* Gather file name */
-            Lfn = Add2Ptr(FileName, (SeqNum * FAT_LFN_NAME_LENGTH)
-                    - sizeof(LfnEntry->NameC), PWSTR);
-            RtlCopyMemory(Lfn, LfnEntry->NameC, sizeof(LfnEntry->NameC));
-            Lfn -= (sizeof(LfnEntry->NameB) / sizeof(WCHAR));
-            RtlCopyMemory(Lfn, LfnEntry->NameB, sizeof(LfnEntry->NameB));
-            Lfn -= (sizeof(LfnEntry->NameA) / sizeof(WCHAR));
-            RtlCopyMemory(Lfn, LfnEntry->NameA, sizeof(LfnEntry->NameA));
-
-            /* If last lfn determine exact lfn length. */
-            if (FlagOn(LfnEntry->SeqNum, FAT_FN_DIR_ENTRY_LAST))
-            {
-                PWSTR LfnEnd = Add2Ptr(FileName, FileNameLength
-                    - sizeof(WCHAR), PWSTR);
-
-                /* Trim trailing 0xffff's */
-                while (LfnEnd > Lfn && *LfnEnd == 0xffff) --LfnEnd;
-
-                /* Trim 0 terminator is the one is there. */
-                if (*LfnEnd == 0x0) --LfnEnd;
-
-                /* Set correct lfn size */
-                FileNameLength = (USHORT)PtrOffset(FileName, LfnEnd);
-            }
-            /* Setup vaidation for the next iteration */
-            SeqNum = LfnEntry->SeqNum - 0x1;
-            Checksum = LfnEntry->Checksum;
-FatEnumerateDirentsRunLfn:
-            Entry = Add2Ptr(Entry, sizeof(DIR_ENTRY), PUCHAR);
-            if (Entry > EndOfPage)
-            {
-                if (FatPinIsLastPage(&Context->Page))
-                    ExRaiseStatus(STATUS_NO_MORE_FILES);
-                Entry = (PUCHAR) FatPinNextPage(&Context->Page);
-                EndOfPage = FatPinEndOfPage(&Context->Page, PUCHAR);
-            }
-        }
-
-        /* if lfn was found, validate and commit. */
-        if (FileNameLength > 0 && FatLfnChecksum(Entry) == Checksum)
-        {
-            *Add2Ptr(InfoEntry, Context->LengthOffset, PULONG) = FileNameLength;
-        }
-        else
-        {
-            *Add2Ptr(InfoEntry, Context->LengthOffset, PULONG) = 0;
-        }
-        /* TODO: Implement Filtering using Context->FileName & Context->CcbFlags. */
-
-        /* Copy the entry values. */
-        Context->Offset += Context->CopyDirent((PFAT_ENUM_DIR_CONTEXT)Context, (PDIR_ENTRY) Entry, InfoEntry);
-
-FatEnumerateDirentsNext:
-        /* Get next entry */
-        Entry = Add2Ptr(Entry, sizeof(DIR_ENTRY), PUCHAR);
-        if (Entry > EndOfPage)
-        {
-            if (FatPinIsLastPage(&Context->Page))
-                ExRaiseStatus(STATUS_NO_MORE_FILES);
-            Entry = (PUCHAR) FatPinNextPage(&Context->Page);
-            EndOfPage = FatPinEndOfPage(&Context->Page, PUCHAR);
-        }
-    }
-}
-
-FORCEINLINE
-VOID
-FatDateTimeToSystemTime(OUT PLARGE_INTEGER SystemTime,
-                        IN PFAT_DATETIME FatDateTime,
-                        IN UCHAR TenMs OPTIONAL)
-{
-    TIME_FIELDS TimeFields;
-
-    /* Setup time fields */
-    TimeFields.Year = FatDateTime->Date.Year + 1980;
-    TimeFields.Month = FatDateTime->Date.Month;
-    TimeFields.Day = FatDateTime->Date.Day;
-    TimeFields.Hour = FatDateTime->Time.Hour;
-    TimeFields.Minute = FatDateTime->Time.Minute;
-    TimeFields.Second = (FatDateTime->Time.DoubleSeconds << 1);
-
-    /* Adjust up to 10 milliseconds
-     * if the parameter was supplied
-     */
-    if (ARGUMENT_PRESENT(TenMs))
-    {
-        TimeFields.Second += TenMs / 100;
-        TimeFields.Milliseconds = (TenMs % 100) * 10;
-    }
-    else
-    {
-        TimeFields.Milliseconds = 0;
-    }
-
-    /* Fix seconds value that might get beyoud the bound */
-    if (TimeFields.Second > 59) TimeFields.Second = 0;
-
-    /* Perform ceonversion to system time if possible */
-    if (RtlTimeFieldsToTime(&TimeFields, SystemTime))
-    {
-        /* Convert to system time */
-        ExLocalTimeToSystemTime(SystemTime, SystemTime);
-    }
-    else
-    {
-        /* Set to default time if conversion failed */
-        *SystemTime = FatGlobalData.DefaultFileTime;
-    }
-}
-
-VOID
-FatQueryFileTimes(OUT PLARGE_INTEGER FileTimes,
-                  IN PDIR_ENTRY Dirent)
-{
-    /* Convert LastWriteTime */
-    FatDateTimeToSystemTime(&FileTimes[FileLastWriteTime],
-                            &Dirent->LastWriteDateTime,
-                            0);
-    /* All other time fileds are valid (according to MS)
-     * only if Win31 compatability mode is set.
-     */
-    if (FatGlobalData.Win31FileSystem)
-    {
-       /* We can avoid calling conversion routine
-        * if time in dirent is 0 or equals to already
-        * known time (LastWriteTime).
-        */
-        if (Dirent->CreationDateTime.Value == 0)
-        {
-            /* Set it to default time */
-            FileTimes[FileCreationTime] = FatGlobalData.DefaultFileTime;
-        }
-        else if (Dirent->CreationDateTime.Value
-            == Dirent->LastWriteDateTime.Value)
-        {
-            /* Assign the already known time */
-            FileTimes[FileCreationTime] = FileTimes[FileLastWriteTime];
-            /* Adjust milliseconds from extra dirent field */
-            FileTimes[FileCreationTime].QuadPart
-                += (ULONG) Dirent->CreationTimeTenMs * 100000;
-        }
-        else
-        {
-            /* Perform conversion */
-            FatDateTimeToSystemTime(&FileTimes[FileCreationTime],
-                                    &Dirent->CreationDateTime,
-                                    Dirent->CreationTimeTenMs);
-        }
-        if (Dirent->LastAccessDate.Value == 0)
-        {
-            /* Set it to default time */
-            FileTimes[FileLastAccessTime] = FatGlobalData.DefaultFileTime;
-        }
-        else if (Dirent->LastAccessDate.Value
-                == Dirent->LastWriteDateTime.Date.Value)
-        {
-            /* Assign the already known time */
-            FileTimes[FileLastAccessTime] = FileTimes[FileLastWriteTime];
-        }
-        else
-        {
-            /* Perform conversion */
-            FAT_DATETIME LastAccessDateTime;
-
-            LastAccessDateTime.Date.Value = Dirent->LastAccessDate.Value;
-            LastAccessDateTime.Time.Value = 0;
-            FatDateTimeToSystemTime(&FileTimes[FileLastAccessTime],
-                                    &LastAccessDateTime,
-                                    0);
-        }
-    }
-}
-
-VOID
-Fat8dot3ToUnicodeString(OUT PUNICODE_STRING FileName,
-                        IN PUCHAR ShortName,
-                        IN UCHAR Flags)
-{
-    PCHAR Name;
-    UCHAR Index, Ext = 0;
-    OEM_STRING Oem;
-
-    Name = Add2Ptr(FileName->Buffer, 0x0c, PCHAR);
-    RtlCopyMemory(Name, ShortName, 0x0b);
-
-    /* Restore the name byte used to mark deleted entries */
-    if (Name[0] == 0x05)
-        Name[0] |= 0xe0;
-
-    /* Locate the end of name part */
-    for (Index = 0; Index < 0x08
-        && Name[Index] != 0x20; Index++);
-
-    /* Locate the end of extension part */
-    if (Name[0x08] != 0x20)
-    {
-        Ext = 0x2;
-        Name[Index++] = 0x2e;
-        Name[Index++] = Name[0x08];
-        if ((Name[Index] = Name[0x09]) != 0x20)
-        {
-            Index ++; Ext ++;
-        }
-        if ((Name[Index] = Name[0x0a]) != 0x20)
-        {
-            Index ++; Ext ++;
-        }
-    }
-
-    /* Perform Oem to Unicode conversion. */
-    Oem.Buffer = Name;
-    Oem.Length = Index;
-    Oem.MaximumLength = Index;
-    RtlOemStringToUnicodeString(FileName, &Oem, FALSE);
-    Index = FlagOn(Flags, FAT_CASE_LOWER_BASE|FAT_CASE_LOWER_EXT);
-    if (Index > 0)
-    {
-        /* Downcase the whole name */
-        if (Index == (FAT_CASE_LOWER_BASE|FAT_CASE_LOWER_EXT))
-        {
-            RtlUpcaseUnicodeString(FileName, FileName, FALSE);
-        }
-        else
-        {
-            if (Index == FAT_CASE_LOWER_EXT)
-            {
-                /* Set extension for downcase */
-                Oem.Length = Ext * sizeof(WCHAR);
-                Oem.Buffer = Add2Ptr(FileName->Buffer,
-                                     FileName->Length - Oem.Length,
-                                     PSTR);
-            }
-            else
-            {
-                /* Set base name for downcase */
-                Oem.Buffer = (PSTR) FileName->Buffer;
-                Oem.Length = FileName->Length - Ext * sizeof(WCHAR);
-            }
-            Oem.MaximumLength = Oem.Length;
-            RtlUpcaseUnicodeString((PUNICODE_STRING)&Oem,
-                                   (PUNICODE_STRING)&Oem,
-                                    FALSE);
-        }
-    }
-}
-
-ULONG
-FatDirentToDirInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
-                   IN PDIR_ENTRY Dirent,
-                   IN PVOID Buffer)
-{
-    PFILE_DIRECTORY_INFORMATION Info;
-    Info = (PFILE_DIRECTORY_INFORMATION) Buffer;
-    Info->FileIndex = 0;
-    /* Setup Attributes */
-    Info->FileAttributes = Dirent->Attributes;
-    /* Setup times */
-    FatQueryFileTimes(&Info->CreationTime, Dirent);
-    /* Setup sizes */
-    Info->EndOfFile.QuadPart = Dirent->FileSize;
-    Info->AllocationSize.QuadPart =
-        (Context->BytesPerClusterMask + Dirent->FileSize)
-            & ~(Context->BytesPerClusterMask);
-    FatQueryFileName(Info, Dirent);
-    Info->NextEntryOffset = sizeof(*Info);
-    return Info->NextEntryOffset + Info->FileNameLength;
-}
-
-ULONG
-FatDirentToFullDirInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
-                       IN PDIR_ENTRY Dirent,
-                       IN PVOID Buffer)
-{
-    PFILE_FULL_DIR_INFORMATION Info;
-    Info = (PFILE_FULL_DIR_INFORMATION) Buffer;
-    Info->FileIndex = 0;
-    Info->EaSize = 0;
-    /* Setup Attributes */
-    Info->FileAttributes = Dirent->Attributes;
-    /* Setup times */
-    FatQueryFileTimes(&Info->CreationTime, Dirent);
-    /* Setup sizes */
-    Info->EndOfFile.QuadPart = Dirent->FileSize;
-    Info->AllocationSize.QuadPart =
-        (Context->BytesPerClusterMask + Dirent->FileSize)
-            & ~(Context->BytesPerClusterMask);
-    FatQueryFileName(Info, Dirent);
-    Info->NextEntryOffset = sizeof(*Info);
-    return Info->NextEntryOffset + Info->FileNameLength;
-}
-
-ULONG
-FatDirentToIdFullDirInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
-                         IN PDIR_ENTRY Dirent,
-                         IN PVOID Buffer)
-{
-    PFILE_ID_FULL_DIR_INFORMATION Info;
-    Info = (PFILE_ID_FULL_DIR_INFORMATION) Buffer;
-    Info->FileId.QuadPart = 0;
-    Info->FileIndex = 0;
-    Info->EaSize = 0;
-    /* Setup Attributes */
-    Info->FileAttributes = Dirent->Attributes;
-    /* Setup times */
-    FatQueryFileTimes(&Info->CreationTime, Dirent);
-    /* Setup sizes */
-    Info->EndOfFile.QuadPart = Dirent->FileSize;
-    Info->AllocationSize.QuadPart =
-        (Context->BytesPerClusterMask + Dirent->FileSize)
-            & ~(Context->BytesPerClusterMask);
-    FatQueryFileName(Info, Dirent);
-    Info->NextEntryOffset = sizeof(*Info);
-    return Info->NextEntryOffset + Info->FileNameLength;
-}
-
-ULONG
-FatDirentToBothDirInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
-                       IN PDIR_ENTRY Dirent,
-                       IN PVOID Buffer)
-{
-    PFILE_BOTH_DIR_INFORMATION Info;
-    Info = (PFILE_BOTH_DIR_INFORMATION) Buffer;
-    Info->FileIndex = 0;
-    Info->EaSize = 0;
-    /* Setup Attributes */
-    Info->FileAttributes = Dirent->Attributes;
-    /* Setup times */
-    FatQueryFileTimes(&Info->CreationTime, Dirent);
-    /* Setup sizes */
-    Info->EndOfFile.QuadPart = Dirent->FileSize;
-    Info->AllocationSize.QuadPart =
-        (Context->BytesPerClusterMask + Dirent->FileSize)
-            & ~(Context->BytesPerClusterMask);
-    FatQueryBothFileName(Info, Dirent);
-    Info->NextEntryOffset = sizeof(*Info);
-    return Info->NextEntryOffset + Info->FileNameLength;
-}
-
-ULONG
-FatDirentToIdBothDirInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
-                         IN PDIR_ENTRY Dirent,
-                         IN PVOID Buffer)
-{
-    PFILE_ID_BOTH_DIR_INFORMATION Info;
-    Info = (PFILE_ID_BOTH_DIR_INFORMATION) Buffer;
-    Info->FileId.QuadPart = 0;
-    Info->FileIndex = 0;
-    Info->EaSize = 0;
-    /* Setup Attributes */
-    Info->FileAttributes = Dirent->Attributes;
-    /* Setup times */
-    FatQueryFileTimes(&Info->CreationTime, Dirent);
-    /* Setup sizes */
-    Info->EndOfFile.QuadPart = Dirent->FileSize;
-    Info->AllocationSize.QuadPart =
-        (Context->BytesPerClusterMask + Dirent->FileSize)
-            & ~(Context->BytesPerClusterMask);
-    FatQueryBothFileName(Info, Dirent);
-    Info->NextEntryOffset = sizeof(*Info);
-    return Info->NextEntryOffset + Info->FileNameLength;
-}
-
-ULONG
-FatDirentToNamesInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
-                     IN PDIR_ENTRY Dirent,
-                     IN PVOID Buffer)
-{
-    PFILE_NAMES_INFORMATION Info;
-    Info = (PFILE_NAMES_INFORMATION) Buffer;
-    Info->FileIndex = 0;
-    FatQueryFileName(Info, Dirent);
-    Info->NextEntryOffset = sizeof(*Info);
-    return Info->NextEntryOffset + Info->FileNameLength;
-}
-
-ULONG
-FatDirentToObjectIdInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
-                        IN PDIR_ENTRY Dirent,
-                        IN PVOID Buffer)
-{
-    PFILE_OBJECTID_INFORMATION Info;
-    Info = (PFILE_OBJECTID_INFORMATION) Buffer;
-    Info->FileReference = 0;
-    ((PLONGLONG)Info->ObjectId)[0] = 0LL;
-    ((PLONGLONG)Info->ObjectId)[1] = 0LL;
-    return sizeof(*Info);
-}
-
-/* EOF */
index 2b843df..7b5f250 100644 (file)
@@ -66,21 +66,6 @@ FatReadStreamFile(PVCB Vcb,
                   PBCB *Bcb,
                   PVOID *Buffer);
 
-/*  ------------------------------------------------------  blockdev.c  */
-NTSTATUS
-NTAPI
-FatPerformLboIo(
-    IN PFAT_IRP_CONTEXT IrpContext,
-    IN PLARGE_INTEGER Offset,
-    IN SIZE_T Length);
-
-NTSTATUS
-FatPerformVirtualNonCachedIo(
-    IN PFAT_IRP_CONTEXT IrpContext,
-    IN PFCB Fcb,
-    IN PLARGE_INTEGER Offset,
-    IN SIZE_T Length);
-
 /*  -----------------------------------------------------------  dir.c  */
 
 NTSTATUS NTAPI
@@ -215,6 +200,10 @@ FatWriteBlocks(FF_T_UINT8 *pBuffer, FF_T_UINT32 SectorAddress, FF_T_UINT32 Count
 FF_T_SINT32
 FatReadBlocks(FF_T_UINT8 *pBuffer, FF_T_UINT32 SectorAddress, FF_T_UINT32 Count, void *pParam);
 
+VOID NTAPI
+FatQueryFileTimes(OUT PLARGE_INTEGER FileTimes,
+                  IN PDIR_ENTRY Dirent);
+
 /* ---------------------------------------------------------  lock.c */
 
 NTSTATUS NTAPI
@@ -249,34 +238,17 @@ NTAPI
 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
 
 /*  -----------------------------------------------------------  fat.c  */
-PVOID
-FatPinPage(
-    PFAT_PAGE_CONTEXT Context,
-    LONGLONG ByteOffset);
-
-PVOID
-FatPinNextPage(
-    PFAT_PAGE_CONTEXT Context);
-
-NTSTATUS
+NTSTATUS NTAPI
 FatInitializeVcb(
     IN PFAT_IRP_CONTEXT IrpContext,
     IN PVCB Vcb,
     IN PDEVICE_OBJECT TargetDeviceObject,
     IN PVPB Vpb);
 
-VOID
+VOID NTAPI
 FatUninitializeVcb(
     IN PVCB Vcb);
 
-ULONG
-FatScanFat(
-    IN PFCB Fcb,
-    IN LONGLONG Vbo, OUT PLONGLONG Lbo,
-    IN OUT PLONGLONG Length,
-    OUT PULONG Index,
-    IN BOOLEAN CanWait);
-
 /*  ------------------------------------------------------  device.c  */
 
 NTSTATUS NTAPI
@@ -291,36 +263,7 @@ FatPerformDevIoCtrl(PDEVICE_OBJECT DeviceObject,
                     ULONG OutputBufferSize,
                     BOOLEAN Override);
 
-/*  ------------------------------------------------------  direntry.c  */
-VOID
-FatFindDirent(IN OUT PFAT_FIND_DIRENT_CONTEXT Context,
-              OUT PDIR_ENTRY* Dirent,
-              OUT PUNICODE_STRING LongFileName OPTIONAL);
-
-VOID
-FatEnumerateDirents(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
-                    IN SIZE_T Offset);
-
-VOID
-FatQueryFileTimes(OUT PLARGE_INTEGER FileTimes,
-                  IN PDIR_ENTRY Dirent);
-
 /*  -----------------------------------------------------------  fcb.c  */
-PFCB
-FatLookupFcbByName(
-       IN PFCB ParentFcb,
-       IN PUNICODE_STRING Name);
-
-BOOLEAN
-FatLinkFcbNames(
-       IN PFCB ParentFcb,
-       IN PFCB Fcb);
-
-VOID
-FatUnlinkFcbNames(
-       IN PFCB ParentFcb,
-       IN PFCB Fcb);
-
 PFCB NTAPI
 FatCreateFcb(
     IN PFAT_IRP_CONTEXT IrpContext,
index f29c915..bd8f6c8 100644 (file)
@@ -8,13 +8,11 @@
        <library>ntoskrnl</library>
        <library>hal</library>
        <library>pseh</library>
-       <file>blockdev.c</file>
        <file>cleanup.c</file>
        <file>close.c</file>
        <file>create.c</file>
        <file>device.c</file>
        <file>dir.c</file>
-       <file>direntry.c</file>
        <file>ea.c</file>
        <file>fastfat.c</file>
        <file>fat.c</file>
index db6d517..e483e67 100644 (file)
@@ -3,7 +3,7 @@
  * LICENSE:         GPL - See COPYING in the top level directory
  * FILE:            drivers/filesystems/fastfat/fat.c
  * PURPOSE:         FAT support routines
- * PROGRAMMERS:     Alexey Vlasov
+ * PROGRAMMERS:     Aleksey Bragin <aleksey@reactos.org>
  */
 
 /* INCLUDES *****************************************************************/
 #include "fastfat.h"
 
 /* PROTOTYPES ***************************************************************/
-typedef struct _FAT_SCAN_CONTEXT
-{
-    PFILE_OBJECT FileObject;
-    LARGE_INTEGER PageOffset;
-    LONGLONG BeyondLastEntryOffset;
-    PVOID PageBuffer;
-    PBCB PageBcb;
-} FAT_SCAN_CONTEXT;
-
-#define FatEntryToDataOffset(xEntry, xVcb) \
-    ((xVcb)->DataArea + (((LONGLONG) ((xEntry) - 0x02)) << (xVcb)->BytesPerClusterLog))
-
-#define FatDataOffsetToEntry(xOffset, xVcb) \
-    ((ULONG) ((xOffset - (xVcb)->DataArea) >> (xVcb)->BytesPerClusterLog) + 0x02)
-
-ULONG
-FatScanFat32ForContinousRun(IN OUT PFAT_PAGE_CONTEXT Context,
-                            IN OUT PULONG Index,
-                            IN BOOLEAN CanWait);
 
 BOOLEAN
 NTAPI
 FatValidBpb(IN PBIOS_PARAMETER_BLOCK Bpb);
 
 /* VARIABLES ****************************************************************/
-FAT_METHODS Fat12Methods = {
-    NULL,
-    NULL,
-    NULL,
-    NULL
-};
-
-FAT_METHODS Fat16Methods = {
-    NULL,
-    NULL,
-    NULL,
-    NULL
-};
-
-FAT_METHODS Fat32Methods = {
-    FatScanFat32ForContinousRun,
-    NULL,
-    NULL,
-    NULL
-};
-
-/* FUNCTIONS ****************************************************************/
-
-/**
- * Pins the page containing ByteOffset byte.
- *
- * @param Context
- * Keeps current BCB, Buffer pointer
- * and maintains current and next page offset.
- *
- * @param ByteOffset
- * Offset from the beginning of the data stream to be pinned.
- *
- * @return
- * Pointer to the buffer starting with the specified ByteOffset.
- */
-PVOID
-FatPinPage(
-    PFAT_PAGE_CONTEXT Context,
-    LONGLONG ByteOffset)
-{
-    SIZE_T OffsetWithinPage;
 
-    OffsetWithinPage = (SIZE_T) (ByteOffset & (PAGE_SIZE - 1));
-    ByteOffset -= OffsetWithinPage;
-    if (ByteOffset != Context->Offset.QuadPart)
-    {
-        Context->Offset.QuadPart = ByteOffset;
-        if (Context->Bcb != NULL)
-        {
-            CcUnpinData(Context->Bcb);
-            Context->Bcb = NULL;
-        }
-        if (!CcMapData(Context->FileObject,
-                       &Context->Offset,
-                       PAGE_SIZE,
-                       Context->CanWait,
-                       &Context->Bcb,
-                       &Context->Buffer))
-        {
-            Context->Offset.QuadPart = 0LL;
-            ExRaiseStatus(STATUS_CANT_WAIT);
-        }
-    }
-    Context->EndOfPage.QuadPart =
-        Context->Offset.QuadPart + PAGE_SIZE;
-    if (Context->EndOfPage.QuadPart
-        > Context->EndOfData.QuadPart)
-    {
-        Context->ValidLength = (SIZE_T)
-            (Context->EndOfData.QuadPart
-                - Context->Offset.QuadPart);
-    }
-    else
-    {
-        Context->ValidLength = PAGE_SIZE;
-    }
-    return Add2Ptr(Context->Buffer, OffsetWithinPage, PVOID);
-}
-
-/**
- * Pins the next page of data stream.
- *
- * @param Context
- * Keeps current BCB, Buffer pointer
- * and maintains current and next page offset.
- *
- * @return
- * Pointer to the buffer starting with the beginning of the next page.
- */
-PVOID
-FatPinNextPage(
-    PFAT_PAGE_CONTEXT Context)
+BOOLEAN
+NTAPI
+FatValidBpb(IN PBIOS_PARAMETER_BLOCK Bpb)
 {
-    ASSERT ((Context->Offset.QuadPart % PAGE_SIZE)
-        != (Context->EndOfPage.QuadPart % PAGE_SIZE)
-        && Context->Bcb != NULL);
-
-    ASSERT  (Context->ValidLength == PAGE_SIZE);
-
-    Context->Offset = Context->EndOfPage;
-    CcUnpinData(Context->Bcb);
-    if (!CcMapData(Context->FileObject,
-                   &Context->Offset,
-                   PAGE_SIZE,
-                   Context->CanWait,
-                   &Context->Bcb,
-                   &Context->Buffer))
-    {
-        Context->Bcb = NULL;
-        Context->Offset.QuadPart = 0LL;
-        ExRaiseStatus(STATUS_CANT_WAIT);
-    }
-    Context->EndOfPage.QuadPart =
-        Context->Offset.QuadPart + PAGE_SIZE;
-    return Context->Buffer;
+    return (FatValidBytesPerSector(Bpb->BytesPerSector)
+        && FatValidSectorsPerCluster(Bpb->SectorsPerCluster)
+        && Bpb->ReservedSectors > 0
+        && Bpb->Fats > 0
+        && (Bpb->Sectors > 0 || Bpb->LargeSectors > 0)
+        && (Bpb->SectorsPerFat > 0
+            || (Bpb->LargeSectorsPerFat > 0 && Bpb->FsVersion == 0))
+        && (Bpb->Media == 0xf0
+            || Bpb->Media == 0xf8
+            || Bpb->Media == 0xf9
+            || Bpb->Media == 0xfb
+            || Bpb->Media == 0xfc
+            || Bpb->Media == 0xfd
+            || Bpb->Media == 0xfe
+            || Bpb->Media == 0xff)
+        && (Bpb->SectorsPerFat == 0 || Bpb->RootEntries > 0)
+        && (Bpb->SectorsPerFat > 0 || !Bpb->MirrorDisabled));
 }
 
 /**
@@ -176,231 +63,8 @@ FatPowerOfTwo(
     return (((Temp + (Temp >> 3)) & 030707070707) % 63);
 }
 
-/**
- * Scans FAT32 for continous chain of clusters
- *
- * @param Context
- * Pointer to FAT_PAGE_CONTEXT.
- *
- * @param Index
- * Supplies the Index of the first cluster
- * and receves the last index after the last
- * cluster in the chain.
- *
- * @param CanWait
- * Indicates if the context allows blocking.
- *
- * @return
- * Value of the last claster terminated the scan.
- *
- * @note
- * Raises STATUS_CANT_WAIT race condition.
- */
-ULONG
-FatScanFat32ForContinousRun(IN OUT PFAT_PAGE_CONTEXT Context,
-                            IN OUT PULONG Index,
-                            IN BOOLEAN CanWait)
-{
-    PULONG Entry, EndOfPage;
-
-    Entry = FatPinPage(Context, ((LONGLONG) *Index) << 0x2);
-    EndOfPage = FatPinEndOfPage(Context, PULONG);
-    while (TRUE)
-    {
-        do
-        {
-            if ((*Entry & FAT_CLUSTER_LAST) != ++(*Index))
-                return (*Entry & FAT_CLUSTER_LAST);
-        } while (++Entry < EndOfPage);
-        /* Check if this is the last available entry */
-        if (FatPinIsLastPage(Context))
-            break;
-        Entry = (PULONG) FatPinNextPage(Context);
-        EndOfPage = FatPinEndOfPage(Context, PULONG);
-    }
-    return (*Index - 1);
-}
-
-ULONG
-FatSetFat32ContinousRun(IN OUT PFAT_SCAN_CONTEXT Context,
-                        IN ULONG Index,
-                        IN ULONG Length,
-                        IN BOOLEAN CanWait)
-{
-    ExRaiseStatus(STATUS_NOT_IMPLEMENTED);
-}
-
-ULONG
-FatScanFat32ForValueRun(IN OUT PFAT_SCAN_CONTEXT Context,
-                        IN OUT PULONG Index,
-                        IN ULONG IndexValue,
-                        IN BOOLEAN CanWait)
-{
-    ExRaiseStatus(STATUS_NOT_IMPLEMENTED);
-}
-
-ULONG
-FatSetFat32ValueRun(IN OUT PFAT_SCAN_CONTEXT Context,
-                    IN ULONG Index,
-                    IN ULONG Length,
-                    IN ULONG IndexValue,
-                    IN BOOLEAN CanWait)
-{
-    ExRaiseStatus(STATUS_NOT_IMPLEMENTED);
-}
-
-/**
- * Queries file MCB for the specified region [Vbo, Vbo + Length],
- * returns the number of runs in the region as well as the first
- * run of the range itself.
- * If the specified region is not fully cached in MCB the routine
- * scans FAT for the file and fills the MCB until the file offset
- * (defined as Vbo + Length) is reached.
- *
- * @param Fcb
- * Pointer to FCB structure for the file.
- *
- * @param Vbo
- * Virtual Byte Offset in the file.
- *
- * @param Lbo
- * Receives the Value of Logical Byte offset corresponding
- * to supplied Vbo Value.
- *
- * @param Length
- * Supplies file range length to be examined and receives
- * the length of first run.
- *
- * @param OutIndex
- * Receives the index (in MCB cache) of first run.
- *
- * @return
- * Incremented index of the last run (+1).
- *
- * @note
- * Should be called by I/O routines to split the I/O operation
- * into sequential or parallel I/O operations.
- */
-ULONG
-FatScanFat(IN PFCB Fcb,
-           IN LONGLONG Vbo,
-           OUT PLONGLONG Lbo,
-           IN OUT PLONGLONG Length,
-           OUT PULONG Index,
-           IN BOOLEAN CanWait)
-{
-    LONGLONG CurrentLbo, CurrentVbo, BeyondLastVbo, CurrentLength;
-    ULONG Entry, NextEntry, NumberOfEntries, CurrentIndex;
-    FAT_PAGE_CONTEXT Context;
-    PVCB Vcb;
-
-    /* Some often used values */
-    Vcb = Fcb->Vcb;
-    CurrentIndex = 0;
-    BeyondLastVbo = Vbo + *Length;
-    CurrentLength = ((LONGLONG) Vcb->Clusters) << Vcb->BytesPerClusterLog;
-    if (BeyondLastVbo > CurrentLength) 
-        BeyondLastVbo = CurrentLength;
-    /* Try to locate first run */
-    if (FsRtlLookupLargeMcbEntry(&Fcb->Mcb, Vbo, Lbo, Length, NULL, NULL, Index))
-    {
-        /* Check if we have a single mapped run */
-        if (Vbo >= BeyondLastVbo)
-            goto FatScanFcbFatExit;
-    } else {
-        *Length = 0L;
-    }
-    /* Get the first scan startup values */
-    if (FsRtlLookupLastLargeMcbEntryAndIndex(
-        &Fcb->Mcb, &CurrentVbo, &CurrentLbo, &CurrentIndex))
-    {
-        Entry = FatDataOffsetToEntry(CurrentLbo, Vcb);
-    }
-    else
-    {
-        /* Map is empty, set up initial values */
-        Entry = Fcb->FirstCluster;
-        if (Entry <= 0x2)
-            ExRaiseStatus(STATUS_FILE_CORRUPT_ERROR);
-        if (Entry >= Vcb->Clusters)
-        {
-            if (Entry < FAT_CLUSTER_LAST)
-                ExRaiseStatus(STATUS_FILE_CORRUPT_ERROR);
-                BeyondLastVbo = 0LL;
-        }
-        CurrentIndex = 0L;
-        CurrentVbo = 0LL;
-    }
-    /* Initialize Context */
-    RtlZeroMemory(&Context, sizeof(Context));
-    Context.FileObject = Vcb->StreamFileObject;
-    Context.EndOfData.QuadPart = Vcb->BeyondLastClusterInFat;
-
-    while (CurrentVbo < BeyondLastVbo)
-    {
-        /* Locate Continous run starting with the current entry */
-        NumberOfEntries = Entry;
-        NextEntry = Vcb->Methods.ScanContinousRun(
-        &Context, &NumberOfEntries, CanWait);
-        NumberOfEntries -= Entry;
-        /* Check value that terminated the for being valid for FAT */
-        if (NextEntry <= 0x2)
-            ExRaiseStatus(STATUS_FILE_CORRUPT_ERROR);
-        if (NextEntry >= Vcb->Clusters)
-        {
-            if (NextEntry < FAT_CLUSTER_LAST)
-            ExRaiseStatus(STATUS_FILE_CORRUPT_ERROR);
-            break;
-        }
-       /* Add new run */
-        CurrentLength = ((LONGLONG) NumberOfEntries) 
-            << Vcb->BytesPerClusterLog;
-        FsRtlAddLargeMcbEntry(&Fcb->Mcb,
-            CurrentVbo,
-            FatEntryToDataOffset(Entry, Vcb),
-            CurrentLength);
-        /* Setup next iteration */
-        Entry = NextEntry;
-        CurrentVbo += CurrentLength;
-        CurrentIndex ++;
-    }
-    if (*Length == 0LL && CurrentIndex > 0)
-    {
-        if (!FsRtlLookupLargeMcbEntry(&Fcb->Mcb,
-            Vbo, Lbo, Length, NULL, NULL, Index))
-        {
-            *Index = 0L;
-            *Lbo = 0LL;
-        }
-    }
-FatScanFcbFatExit:
-    return CurrentIndex;
-}
-
-BOOLEAN
-NTAPI
-FatValidBpb(IN PBIOS_PARAMETER_BLOCK Bpb)
-{
-    return (FatValidBytesPerSector(Bpb->BytesPerSector)
-        && FatValidSectorsPerCluster(Bpb->SectorsPerCluster)
-        && Bpb->ReservedSectors > 0
-        && Bpb->Fats > 0
-        && (Bpb->Sectors > 0 || Bpb->LargeSectors > 0)
-        && (Bpb->SectorsPerFat > 0
-            || (Bpb->LargeSectorsPerFat > 0 && Bpb->FsVersion == 0))
-        && (Bpb->Media == 0xf0
-            || Bpb->Media == 0xf8
-            || Bpb->Media == 0xf9
-            || Bpb->Media == 0xfb
-            || Bpb->Media == 0xfc
-            || Bpb->Media == 0xfd
-            || Bpb->Media == 0xfe
-            || Bpb->Media == 0xff)
-        && (Bpb->SectorsPerFat == 0 || Bpb->RootEntries > 0)
-        && (Bpb->SectorsPerFat > 0 || !Bpb->MirrorDisabled));
-}
-
 VOID
+NTAPI
 FatiInitializeVcb(PVCB Vcb)
 {
     ULONG ClustersCapacity;
@@ -420,17 +84,17 @@ FatiInitializeVcb(PVCB Vcb)
     if (Vcb->BytesPerClusterLog < 4087)
     {
         Vcb->IndexDepth = 0x0c;
-        Vcb->Methods = Fat12Methods;
+        //Vcb->Methods = Fat12Methods;
     }
     else
     {
         Vcb->IndexDepth = 0x10;
-        Vcb->Methods = Fat16Methods;
+        //Vcb->Methods = Fat16Methods;
     }
     /* Large Sectors are used for FAT32 */
     if (Vcb->Bpb.Sectors == 0) {
         Vcb->IndexDepth = 0x20;
-        Vcb->Methods = Fat32Methods;
+        //Vcb->Methods = Fat32Methods;
     }
     ClustersCapacity = (SectorsToBytes(Vcb, Vcb->Sectors) * 0x8 / Vcb->IndexDepth) - 1;
     if (Vcb->Clusters > ClustersCapacity)
@@ -445,6 +109,7 @@ FatiInitializeVcb(PVCB Vcb)
 }
 
 NTSTATUS
+NTAPI
 FatInitializeVcb(IN PFAT_IRP_CONTEXT IrpContext,
                  IN PVCB Vcb,
                  IN PDEVICE_OBJECT TargetDeviceObject,
@@ -558,6 +223,7 @@ FatInitializeVcbCleanup:
 }
 
 VOID
+NTAPI
 FatUninitializeVcb(IN PVCB Vcb)
 {
     LARGE_INTEGER ZeroSize;
index fbf6bdb..4f8d684 100644 (file)
@@ -388,6 +388,14 @@ typedef enum _TYPE_OF_OPEN
     EaFile
 } TYPE_OF_OPEN;
 
+typedef enum _FILE_TIME_INDEX
+{
+    FileCreationTime = 0,
+    FileLastAccessTime,
+    FileLastWriteTime,
+    FileChangeTime
+} FILE_TIME_INDEX;
+
 #define CCB_SEARCH_RETURN_SINGLE_ENTRY      0x01
 #define CCB_SEARCH_PATTERN_LEGAL_8DOT3      0x02
 #define CCB_SEARCH_PATTERN_HAS_WILD_CARD    0x04
index f140706..5ab9572 100644 (file)
@@ -100,4 +100,114 @@ FF_FILE *FF_OpenW(FF_IOMAN *pIoman, PUNICODE_STRING pathW, FF_T_UINT8 Mode, FF_E
     return FF_Open(pIoman, AnsiName.Buffer, Mode, pError);
 }
 
+FORCEINLINE
+VOID
+FatDateTimeToSystemTime(OUT PLARGE_INTEGER SystemTime,
+                        IN PFAT_DATETIME FatDateTime,
+                        IN UCHAR TenMs OPTIONAL)
+{
+    TIME_FIELDS TimeFields;
+
+    /* Setup time fields */
+    TimeFields.Year = FatDateTime->Date.Year + 1980;
+    TimeFields.Month = FatDateTime->Date.Month;
+    TimeFields.Day = FatDateTime->Date.Day;
+    TimeFields.Hour = FatDateTime->Time.Hour;
+    TimeFields.Minute = FatDateTime->Time.Minute;
+    TimeFields.Second = (FatDateTime->Time.DoubleSeconds << 1);
+
+    /* Adjust up to 10 milliseconds
+     * if the parameter was supplied
+     */
+    if (ARGUMENT_PRESENT(TenMs))
+    {
+        TimeFields.Second += TenMs / 100;
+        TimeFields.Milliseconds = (TenMs % 100) * 10;
+    }
+    else
+    {
+        TimeFields.Milliseconds = 0;
+    }
+
+    /* Fix seconds value that might get beyoud the bound */
+    if (TimeFields.Second > 59) TimeFields.Second = 0;
+
+    /* Perform ceonversion to system time if possible */
+    if (RtlTimeFieldsToTime(&TimeFields, SystemTime))
+    {
+        /* Convert to system time */
+        ExLocalTimeToSystemTime(SystemTime, SystemTime);
+    }
+    else
+    {
+        /* Set to default time if conversion failed */
+        *SystemTime = FatGlobalData.DefaultFileTime;
+    }
+}
+
+// TODO: Make it a helper around FullFAT library
+VOID
+NTAPI
+FatQueryFileTimes(OUT PLARGE_INTEGER FileTimes,
+                  IN PDIR_ENTRY Dirent)
+{
+    /* Convert LastWriteTime */
+    FatDateTimeToSystemTime(&FileTimes[FileLastWriteTime],
+                            &Dirent->LastWriteDateTime,
+                            0);
+    /* All other time fileds are valid (according to MS)
+     * only if Win31 compatability mode is set.
+     */
+    if (FatGlobalData.Win31FileSystem)
+    {
+       /* We can avoid calling conversion routine
+        * if time in dirent is 0 or equals to already
+        * known time (LastWriteTime).
+        */
+        if (Dirent->CreationDateTime.Value == 0)
+        {
+            /* Set it to default time */
+            FileTimes[FileCreationTime] = FatGlobalData.DefaultFileTime;
+        }
+        else if (Dirent->CreationDateTime.Value
+            == Dirent->LastWriteDateTime.Value)
+        {
+            /* Assign the already known time */
+            FileTimes[FileCreationTime] = FileTimes[FileLastWriteTime];
+            /* Adjust milliseconds from extra dirent field */
+            FileTimes[FileCreationTime].QuadPart
+                += (ULONG) Dirent->CreationTimeTenMs * 100000;
+        }
+        else
+        {
+            /* Perform conversion */
+            FatDateTimeToSystemTime(&FileTimes[FileCreationTime],
+                                    &Dirent->CreationDateTime,
+                                    Dirent->CreationTimeTenMs);
+        }
+        if (Dirent->LastAccessDate.Value == 0)
+        {
+            /* Set it to default time */
+            FileTimes[FileLastAccessTime] = FatGlobalData.DefaultFileTime;
+        }
+        else if (Dirent->LastAccessDate.Value
+                == Dirent->LastWriteDateTime.Date.Value)
+        {
+            /* Assign the already known time */
+            FileTimes[FileLastAccessTime] = FileTimes[FileLastWriteTime];
+        }
+        else
+        {
+            /* Perform conversion */
+            FAT_DATETIME LastAccessDateTime;
+
+            LastAccessDateTime.Date.Value = Dirent->LastAccessDate.Value;
+            LastAccessDateTime.Time.Value = 0;
+            FatDateTimeToSystemTime(&FileTimes[FileLastAccessTime],
+                                    &LastAccessDateTime,
+                                    0);
+        }
+    }
+}
+
 /* EOF */
index a6a2120..44eb9d0 100644 (file)
@@ -4,7 +4,6 @@
  * FILE:            drivers/filesystems/fastfat/rw.c
  * PURPOSE:         Read/write support
  * PROGRAMMERS:     Aleksey Bragin (aleksey@reactos.org)
- *                  Alexey Vlasov
  */
 
 /* INCLUDES *****************************************************************/