Author: fireball
Date: Wed Feb 25 15:25:06 2009
New Revision: 39746
URL:
http://svn.reactos.org/svn/reactos?rev=39746&view=rev
Log:
Alex Vlasov
- blockdev.c: Implement misc helper functions.
- direntry.c: Some changes to query dirents info for IRP_MJ_DIRECTORY_CONTROL, and the
routine that locates a single dirent for IRP_MJ_CREATE.
- fastfat.c: Implement queuing support (FatQueueRequest / FatDequeueRequest).
- fat.c: Cleanup, use helper functions FatPin*Page.
- fcb.c: Add FCB helper routines.
- Header files: Change structures for future usage.
- Add PSEH2 library usage.
Modified:
trunk/reactos/drivers/filesystems/fastfat_new/blockdev.c
trunk/reactos/drivers/filesystems/fastfat_new/direntry.c
trunk/reactos/drivers/filesystems/fastfat_new/fastfat.c
trunk/reactos/drivers/filesystems/fastfat_new/fastfat.h
trunk/reactos/drivers/filesystems/fastfat_new/fastfat.rbuild
trunk/reactos/drivers/filesystems/fastfat_new/fat.c
trunk/reactos/drivers/filesystems/fastfat_new/fat.h
trunk/reactos/drivers/filesystems/fastfat_new/fatstruc.h
trunk/reactos/drivers/filesystems/fastfat_new/fcb.c
trunk/reactos/drivers/filesystems/fastfat_new/fsctl.c
Modified: trunk/reactos/drivers/filesystems/fastfat_new/blockdev.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/blockdev.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/blockdev.c [iso-8859-1] Wed Feb 25
15:25:06 2009
@@ -3,7 +3,7 @@
* LICENSE: GPL - See COPYING in the top level directory
* FILE: drivers/filesystems/fastfat/blockdev.c
* PURPOSE: Temporary sector reading support
- * PROGRAMMERS: Aleksey Bragin (aleksey(a)reactos.org)
+ * PROGRAMMERS: Alexey Vlasov
*/
/* INCLUDES *****************************************************************/
@@ -12,5 +12,460 @@
#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;
+}
+
+PVOID
+FatMapUserBuffer(
+ IN OUT PIRP Irp)
+/*
+ * FUNCTION:
+ *
+ *
+ * ARGUMENTS:
+ * IrpContext = Pointer to FCB structure for the file.
+ * Irp = Pointer to the IRP structure
+ * RETURNS: Status Value.
+ * NOTES:
+ */
+{
+ PVOID Address;
+
+ if (Irp->MdlAddress == NULL)
+ return Irp->UserBuffer;
+ Address = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
+ if (Address == NULL)
+ ExRaiseStatus( STATUS_INVALID_USER_BUFFER );
+ return Address;
+}
+
+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 */
Modified: trunk/reactos/drivers/filesystems/fastfat_new/direntry.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/direntry.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/direntry.c [iso-8859-1] Wed Feb 25
15:25:06 2009
@@ -12,37 +12,6 @@
#include "fastfat.h"
/* PROTOTYPES ***************************************************************/
-#define BYTES_PER_DIRENT_LOG 0x05
-
-typedef struct _FAT_ENUM_DIR_CONTEXT *PFAT_ENUM_DIR_CONTEXT;
-
-typedef ULONG (*PFAT_COPY_DIRENT_ROUTINE) (struct _FAT_ENUM_DIR_CONTEXT *, PDIR_ENTRY,
PVOID);
-
-typedef struct _FAT_ENUM_DIR_CONTEXT
-{
- PFILE_OBJECT FileObject;
- LARGE_INTEGER PageOffset;
- LONGLONG BeyondLastEntryOffset;
- PVOID PageBuffer;
- PBCB PageBcb;
-
- /*
- * We should always cache short file name
- * because we never know if there is a long
- * name for the dirent and when we find out
- * that our base dirent might become unpinned.
- */
- UCHAR DirentFileName[RTL_FIELD_SIZE(DIR_ENTRY, FileName) + 1];
- PFAT_COPY_DIRENT_ROUTINE CopyDirent;
- LONGLONG BytesPerClusterMask;
- /*
- * The following fields are
- * set by the copy routine
- */
- PULONG NextEntryOffset;
- PULONG FileNameLength;
- PWCHAR FileName;
-} FAT_ENUM_DIR_CONTEXT;
typedef enum _FILE_TIME_INDEX
{
@@ -51,10 +20,7 @@
FileLastWriteTime,
FileChangeTime
} FILE_TIME_INDEX;
-
-VOID
-FatQueryFileTimes(OUT PLARGE_INTEGER FileTimes,
- IN PDIR_ENTRY Dirent);
+
VOID
Fat8dot3ToUnicodeString(OUT PUNICODE_STRING FileName,
@@ -62,41 +28,426 @@
IN UCHAR Flags);
ULONG
-FatDirentToDirInfo(IN OUT PFAT_ENUM_DIR_CONTEXT Context,
+FatDirentToDirInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
IN PDIR_ENTRY Dirent,
IN PVOID Buffer);
ULONG
-FatDirentToFullDirInfo(IN OUT PFAT_ENUM_DIR_CONTEXT Context,
+FatDirentToFullDirInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
IN PDIR_ENTRY Dirent,
IN PVOID Buffer);
ULONG
-FatDirentToIdFullDirInfo(IN OUT PFAT_ENUM_DIR_CONTEXT Context,
+FatDirentToIdFullDirInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
IN PDIR_ENTRY Dirent,
IN PVOID Buffer);
ULONG
-FatDirentToBothDirInfo(IN OUT PFAT_ENUM_DIR_CONTEXT Context,
+FatDirentToBothDirInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
IN PDIR_ENTRY Dirent,
IN PVOID Buffer);
ULONG
-FatDirentToIdBothDirInfo(IN OUT PFAT_ENUM_DIR_CONTEXT Context,
+FatDirentToIdBothDirInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
IN PDIR_ENTRY Dirent,
IN PVOID Buffer);
ULONG
-FatDirentToNamesInfo(IN OUT PFAT_ENUM_DIR_CONTEXT Context,
+FatDirentToNamesInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
IN PDIR_ENTRY Dirent,
IN PVOID Buffer);
ULONG
-FatDirentToObjectIdInfo(IN OUT PFAT_ENUM_DIR_CONTEXT Context,
+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
@@ -280,14 +631,13 @@
}
ULONG
-FatDirentToDirInfo(IN OUT PFAT_ENUM_DIR_CONTEXT Context,
+FatDirentToDirInfo(IN OUT PFAT_ENUM_DIRENT_CONTEXT Context,
IN PDIR_ENTRY Dirent,
IN PVOID Buffer)
{
PFILE_DIRECTORY_INFORMATION Info;
- //UNICODE_STRING FileName;
-
Info = (PFILE_DIRECTORY_INFORMATION) Buffer;
+ Info->FileIndex = 0;
/* Setup Attributes */
Info->FileAttributes = Dirent->Attributes;
/* Setup times */
@@ -297,29 +647,20 @@
Info->AllocationSize.QuadPart =
(Context->BytesPerClusterMask + Dirent->FileSize)
& ~(Context->BytesPerClusterMask);
- //FileName.Buffer = Info->ShortName;
- //FileName.MaximumLength = sizeof(Info->ShortName);
- // FatQueryShortName(&FileName, Dirent);
- // Info->ShortNameLength = (CCHAR) FileName.Length;
+ FatQueryFileName(Info, Dirent);
Info->NextEntryOffset = sizeof(*Info);
- /* Associate LFN buffer and length pointers
- * of this entry with the context.
- */
- Context->NextEntryOffset = &Info->NextEntryOffset;
- Context->FileName = Info->FileName;
- Context->FileNameLength = &Info->FileNameLength;
- return Info->NextEntryOffset;
-}
-
-ULONG
-FatDirentToFullDirInfo(IN OUT PFAT_ENUM_DIR_CONTEXT Context,
+ 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;
- //UNICODE_STRING FileName;
-
Info = (PFILE_FULL_DIR_INFORMATION) Buffer;
+ Info->FileIndex = 0;
+ Info->EaSize = 0;
/* Setup Attributes */
Info->FileAttributes = Dirent->Attributes;
/* Setup times */
@@ -329,30 +670,21 @@
Info->AllocationSize.QuadPart =
(Context->BytesPerClusterMask + Dirent->FileSize)
& ~(Context->BytesPerClusterMask);
- //FileName.Buffer = Info->ShortName;
- //FileName.MaximumLength = sizeof(Info->ShortName);
- // FatQueryShortName(&FileName, Dirent);
- // Info->ShortNameLength = (CCHAR) FileName.Length;
+ FatQueryFileName(Info, Dirent);
Info->NextEntryOffset = sizeof(*Info);
- /*
- * Associate LFN buffer and length pointers
- * of this entry with the context.
- */
- Context->NextEntryOffset = &Info->NextEntryOffset;
- Context->FileName = Info->FileName;
- Context->FileNameLength = &Info->FileNameLength;
- return Info->NextEntryOffset;
-}
-
-ULONG
-FatDirentToIdFullDirInfo(IN OUT PFAT_ENUM_DIR_CONTEXT Context,
+ 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;
- //UNICODE_STRING FileName;
-
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 */
@@ -362,30 +694,20 @@
Info->AllocationSize.QuadPart =
(Context->BytesPerClusterMask + Dirent->FileSize)
& ~(Context->BytesPerClusterMask);
- //FileName.Buffer = Info->ShortName;
- //FileName.MaximumLength = sizeof(Info->ShortName);
- // FatQueryShortName(&FileName, Dirent);
- // Info->ShortNameLength = (CCHAR) FileName.Length;
+ FatQueryFileName(Info, Dirent);
Info->NextEntryOffset = sizeof(*Info);
- /*
- * Associate LFN buffer and length pointers
- * of this entry with the context.
- */
- Context->NextEntryOffset = &Info->NextEntryOffset;
- Context->FileName = Info->FileName;
- Context->FileNameLength = &Info->FileNameLength;
- return Info->NextEntryOffset;
-}
-
-ULONG
-FatDirentToBothDirInfo(IN OUT PFAT_ENUM_DIR_CONTEXT Context,
+ 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;
- UNICODE_STRING FileName;
-
Info = (PFILE_BOTH_DIR_INFORMATION) Buffer;
+ Info->FileIndex = 0;
+ Info->EaSize = 0;
/* Setup Attributes */
Info->FileAttributes = Dirent->Attributes;
/* Setup times */
@@ -395,29 +717,21 @@
Info->AllocationSize.QuadPart =
(Context->BytesPerClusterMask + Dirent->FileSize)
& ~(Context->BytesPerClusterMask);
- FileName.Buffer = Info->ShortName;
- FileName.MaximumLength = sizeof(Info->ShortName);
- Fat8dot3ToUnicodeString(&FileName, Dirent->FileName, Dirent->Case);
- Info->ShortNameLength = (CCHAR) FileName.Length;
+ FatQueryBothFileName(Info, Dirent);
Info->NextEntryOffset = sizeof(*Info);
- /* Associate LFN buffer and length pointers
- * of this entry with the context.
- */
- Context->NextEntryOffset = &Info->NextEntryOffset;
- Context->FileName = Info->FileName;
- Context->FileNameLength = &Info->FileNameLength;
- return Info->NextEntryOffset;
-}
-
-ULONG
-FatDirentToIdBothDirInfo(IN OUT PFAT_ENUM_DIR_CONTEXT Context,
+ 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;
- UNICODE_STRING FileName;
-
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 */
@@ -427,151 +741,35 @@
Info->AllocationSize.QuadPart =
(Context->BytesPerClusterMask + Dirent->FileSize)
& ~(Context->BytesPerClusterMask);
- FileName.Buffer = Info->ShortName;
- FileName.MaximumLength = sizeof(Info->ShortName);
- Fat8dot3ToUnicodeString(&FileName, Dirent->FileName, Dirent->Case);
- Info->ShortNameLength = (CCHAR) FileName.Length;
+ FatQueryBothFileName(Info, Dirent);
Info->NextEntryOffset = sizeof(*Info);
- /*
- * Associate LFN buffer and length pointers
- * of this entry with the context.
- */
- Context->NextEntryOffset = &Info->NextEntryOffset;
- Context->FileName = Info->FileName;
- Context->FileNameLength = &Info->FileNameLength;
- return Info->NextEntryOffset;
-}
-
-ULONG
-FatDirentToNamesInfo(IN OUT PFAT_ENUM_DIR_CONTEXT Context,
+ 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;
-// FatQueryShortName(&FileName, Dirent);
+ Info->FileIndex = 0;
+ FatQueryFileName(Info, Dirent);
Info->NextEntryOffset = sizeof(*Info);
- /* Associate LFN buffer and length pointers
- * of this entry with the context.
- */
- Context->NextEntryOffset = &Info->NextEntryOffset;
- Context->FileName = Info->FileName;
- Context->FileNameLength = &Info->FileNameLength;
- return Info->NextEntryOffset;
-}
-
-ULONG
-FatDirentToObjectIdInfo(IN OUT PFAT_ENUM_DIR_CONTEXT Context,
+ 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);
}
-ULONG
-FatEnumerateDirents(IN OUT PFAT_ENUM_DIR_CONTEXT Context,
- IN ULONG Index,
- IN BOOLEAN CanWait)
-{
- LONGLONG PageOffset;
- SIZE_T OffsetWithinPage, PageValidLength;
- PUCHAR Entry, BeyondLastEntry;
- /* Determine page offset and the offset within page
- * for the first cluster.
- */
- PageValidLength = PAGE_SIZE;
- PageOffset = ((LONGLONG) Index) << BYTES_PER_DIRENT_LOG;
- OffsetWithinPage = (SIZE_T) (PageOffset & (PAGE_SIZE - 1));
- PageOffset -= OffsetWithinPage;
- /* Check if the context already has the required page mapped.
- * Map the first page is necessary.
- */
- if (PageOffset != Context->PageOffset.QuadPart)
- {
- Context->PageOffset.QuadPart = PageOffset;
- if (Context->PageBcb != NULL)
- {
- CcUnpinData(Context->PageBcb);
- Context->PageBcb = NULL;
- }
- if (!CcMapData(Context->FileObject,
- &Context->PageOffset,
- PAGE_SIZE,
- CanWait,
- &Context->PageBcb,
- &Context->PageBuffer))
- {
- Context->PageOffset.QuadPart = 0LL;
- ExRaiseStatus(STATUS_CANT_WAIT);
- }
- }
- Entry = Add2Ptr(Context->PageBuffer, OffsetWithinPage, PUCHAR);
- /* Next Page Offset */
- PageOffset = Context->PageOffset.QuadPart + PAGE_SIZE;
- if (PageOffset > Context->BeyondLastEntryOffset)
- {
- PageValidLength = (SIZE_T) (Context->BeyondLastEntryOffset
- - Context->PageOffset.QuadPart);
- }
- BeyondLastEntry = Add2Ptr(Context->PageBuffer, PageValidLength, PUCHAR);
- while (TRUE)
- {
- do
- {
- if (*Entry == FAT_DIRENT_NEVER_USED)
- return 0; // TODO: return something reasonable.
- if (*Entry == FAT_DIRENT_DELETED)
- {
- continue;
- }
- if (Entry[0x0a] == FAT_DIRENT_ATTR_LFN)
- {
- PLONG_FILE_NAME_ENTRY Lfnent;
- Lfnent = (PLONG_FILE_NAME_ENTRY) Entry;
- }
- else
- {
- PDIR_ENTRY Dirent;
- Dirent = (PDIR_ENTRY) Entry;
- RtlCopyMemory(Context->DirentFileName,
- Dirent->FileName,
- sizeof(Dirent->FileName));
- }
- } while (++Entry < BeyondLastEntry);
- /* Check if this is the last available entry */
- if (PageValidLength < PAGE_SIZE)
- break;
- /* We are getting beyond current page and
- * are still in the continous run, map the next page.
- */
- Context->PageOffset.QuadPart = PageOffset;
- CcUnpinData(Context->PageBcb);
- if (!CcMapData(Context->FileObject,
- &Context->PageOffset,
- PAGE_SIZE,
- CanWait,
- &Context->PageBcb,
- &Context->PageBuffer))
- {
- Context->PageBcb = NULL;
- Context->PageOffset.QuadPart = 0LL;
- ExRaiseStatus(STATUS_CANT_WAIT);
- }
- Entry = (PUCHAR) Context->PageBuffer;
- /* Next Page Offset */
- PageOffset = Context->PageOffset.QuadPart + PAGE_SIZE;
- if (PageOffset > Context->BeyondLastEntryOffset)
- {
- PageValidLength = (SIZE_T) (Context->BeyondLastEntryOffset
- - Context->PageOffset.QuadPart);
- }
- BeyondLastEntry = Add2Ptr(Context->PageBuffer, PageValidLength, PUCHAR);
- }
- return 0;
-}
-
/* EOF */
Modified: trunk/reactos/drivers/filesystems/fastfat_new/fastfat.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fastfat.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fastfat.c [iso-8859-1] Wed Feb 25
15:25:06 2009
@@ -16,6 +16,7 @@
FAT_GLOBAL_DATA FatGlobalData;
/* FUNCTIONS ****************************************************************/
+
NTSTATUS
NTAPI
@@ -110,7 +111,6 @@
/* Register and reference our filesystem */
IoRegisterFileSystem(DeviceObject);
ObReferenceObject(DeviceObject);
-
return STATUS_SUCCESS;
}
@@ -221,5 +221,51 @@
}
}
-
+VOID
+NTAPI
+FatDequeueRequest(IN PVOID Context)
+{
+ PFAT_IRP_CONTEXT IrpContext;
+
+ IrpContext = (PFAT_IRP_CONTEXT) Context;
+
+ /* Enter critical region. */
+ FsRtlEnterFileSystem();
+
+ /* Handle top level IRP Correctly. */
+ if (!FlagOn(IrpContext->Flags, IRPCONTEXT_TOPLEVEL))
+ IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP);
+
+ /* Enable Synchronous IO. */
+ SetFlag(IrpContext->Flags, IRPCONTEXT_CANWAIT);
+
+ /* Invoke the handler routine. */
+ IrpContext->QueuedOperationHandler(IrpContext);
+
+ /* Restore top level IRP. */
+ IoSetTopLevelIrp(NULL);
+
+ /* Leave critical region. */
+ FsRtlExitFileSystem();
+}
+
+VOID
+NTAPI
+FatQueueRequest(IN PFAT_IRP_CONTEXT IrpContext,
+ IN PFAT_OPERATION_HANDLER OperationHandler)
+{
+ /* Save the worker routine. */
+ IrpContext->QueuedOperationHandler = OperationHandler;
+
+ /* Indicate if top level IRP was set. */
+ if (IoGetTopLevelIrp() == IrpContext->Irp)
+ SetFlag(IrpContext->Flags, IRPCONTEXT_TOPLEVEL);
+
+ /* Initialize work item. */
+ ExInitializeWorkItem(&IrpContext->WorkQueueItem,
+ FatDequeueRequest,
+ IrpContext);
+ ExQueueWorkItem(&IrpContext->WorkQueueItem,
+ DelayedWorkQueue);
+}
/* EOF */
Modified: trunk/reactos/drivers/filesystems/fastfat_new/fastfat.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fastfat.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fastfat.h [iso-8859-1] Wed Feb 25
15:25:06 2009
@@ -1,6 +1,7 @@
#include <ntifs.h>
#include <ntdddisk.h>
#include <debug.h>
+#include <pseh/pseh2.h>
#ifndef TAG
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) +
((D)<<24))
@@ -35,6 +36,23 @@
FatSetVolumeInfo(PDEVICE_OBJECT DeviceObject, PIRP Irp);
/* ------------------------------------------------------ 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);
+
+PVOID
+FatMapUserBuffer(
+ IN OUT PIRP Irp);
/* ----------------------------------------------------------- dir.c */
@@ -45,6 +63,7 @@
NTSTATUS NTAPI
FatCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp);
+
/* --------------------------------------------------------- close.c */
@@ -90,6 +109,11 @@
VOID NTAPI
FatDestroyIrpContext(PFAT_IRP_CONTEXT IrpContext);
+VOID
+NTAPI
+FatQueueRequest(IN PFAT_IRP_CONTEXT IrpContext,
+ IN PFAT_OPERATION_HANDLER OperationHandler);
+
VOID NTAPI
FatCompleteRequest(PFAT_IRP_CONTEXT IrpContext OPTIONAL,
PIRP Irp OPTIONAL,
@@ -118,6 +142,14 @@
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
/* ----------------------------------------------------------- fat.c */
+PVOID
+FatPinPage(
+ PFAT_PAGE_CONTEXT Context,
+ LONGLONG ByteOffset);
+
+PVOID
+FatPinNextPage(
+ PFAT_PAGE_CONTEXT Context);
NTSTATUS
FatInitializeVcb(
@@ -152,8 +184,50 @@
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);
+
+NTSTATUS
+FatCreateFcb(
+ OUT PFCB* CreatedFcb,
+ IN PFAT_IRP_CONTEXT IrpContext,
+ IN PFCB ParentFcb,
+ IN PDIR_ENTRY Dirent,
+ IN PUNICODE_STRING FileName,
+ IN PUNICODE_STRING LongFileName OPTIONAL);
+
+NTSTATUS
+FatOpenFcb(
+ OUT PFCB* Fcb,
+ IN PFAT_IRP_CONTEXT IrpContext,
+ IN PFCB ParentFcb,
+ IN PUNICODE_STRING FileName);
/* ------------------------------------------------------------ rw.c */
Modified: trunk/reactos/drivers/filesystems/fastfat_new/fastfat.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fastfat.rbuild [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fastfat.rbuild [iso-8859-1] Wed Feb 25
15:25:06 2009
@@ -5,6 +5,7 @@
<include base="fastfatn">.</include>
<library>ntoskrnl</library>
<library>hal</library>
+ <library>pseh</library>
<file>blockdev.c</file>
<file>cleanup.c</file>
<file>close.c</file>
Modified: trunk/reactos/drivers/filesystems/fastfat_new/fat.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fat.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fat.c [iso-8859-1] Wed Feb 25 15:25:06
2009
@@ -28,76 +28,9 @@
((ULONG) ((xOffset - (xVcb)->DataArea) >> (xVcb)->BytesPerClusterLog) +
0x02)
ULONG
-FatScanFat12ForContinousRun(IN OUT PFAT_SCAN_CONTEXT Context,
+FatScanFat32ForContinousRun(IN OUT PFAT_PAGE_CONTEXT Context,
IN OUT PULONG Index,
IN BOOLEAN CanWait);
-
-ULONG
-FatSetFat12ContinousRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN ULONG Index,
- IN ULONG Length,
- IN BOOLEAN CanWait);
-
-ULONG
-FatScanFat12ForValueRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN OUT PULONG Index,
- IN ULONG IndexValue,
- IN BOOLEAN CanWait);
-
-ULONG
-FatSetFat12ValueRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN ULONG Index,
- IN ULONG Length,
- IN ULONG IndexValue,
- IN BOOLEAN CanWait);
-
-ULONG
-FatScanFat16ForContinousRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN OUT PULONG Index,
- IN BOOLEAN CanWait);
-
-ULONG
-FatSetFat16ContinousRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN ULONG Index,
- IN ULONG Length,
- IN BOOLEAN CanWait);
-
-ULONG
-FatScanFat16ForValueRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN OUT PULONG Index,
- IN ULONG IndexValue,
- IN BOOLEAN CanWait);
-
-ULONG
-FatSetFat16ValueRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN ULONG Index,
- IN ULONG Length,
- IN ULONG IndexValue,
- IN BOOLEAN CanWait);
-
-ULONG
-FatScanFat32ForContinousRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN OUT PULONG Index,
- IN BOOLEAN CanWait);
-
-ULONG
-FatSetFat32ContinousRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN ULONG Index,
- IN ULONG Length,
- IN BOOLEAN CanWait);
-
-ULONG
-FatScanFat32ForValueRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN OUT PULONG Index,
- IN ULONG IndexValue,
- IN BOOLEAN CanWait);
-
-ULONG
-FatSetFat32ValueRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN ULONG Index,
- IN ULONG Length,
- IN ULONG IndexValue,
- IN BOOLEAN CanWait);
BOOLEAN
NTAPI
@@ -105,27 +38,122 @@
/* VARIABLES ****************************************************************/
FAT_METHODS Fat12Methods = {
- FatScanFat12ForContinousRun,
- FatSetFat12ContinousRun,
- FatScanFat16ForValueRun,
- FatSetFat12ValueRun
+ NULL,
+ NULL,
+ NULL,
+ NULL
};
FAT_METHODS Fat16Methods = {
- FatScanFat16ForContinousRun,
- FatSetFat16ContinousRun,
- FatScanFat16ForValueRun,
- FatSetFat16ValueRun
+ NULL,
+ NULL,
+ NULL,
+ NULL
};
FAT_METHODS Fat32Methods = {
FatScanFat32ForContinousRun,
- FatSetFat32ContinousRun,
- FatScanFat32ForValueRun,
- FatSetFat32ValueRun
+ 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)
+{
+ 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;
+}
/**
* Determines the index of the set bit.
@@ -148,83 +176,11 @@
return (((Temp + (Temp >> 3)) & 030707070707) % 63);
}
-ULONG
-FatScanFat12ForContinousRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN OUT PULONG Index,
- IN BOOLEAN CanWait)
-{
- ExRaiseStatus(STATUS_NOT_IMPLEMENTED);
-}
-
-ULONG
-FatSetFat12ContinousRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN ULONG Index,
- IN ULONG Length,
- IN BOOLEAN CanWait)
-{
- ExRaiseStatus(STATUS_NOT_IMPLEMENTED);
-}
-
-ULONG
-FatScanFat12ForValueRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN OUT PULONG Index,
- IN ULONG IndexValue,
- IN BOOLEAN CanWait)
-{
- ExRaiseStatus(STATUS_NOT_IMPLEMENTED);
-}
-
-ULONG
-FatSetFat12ValueRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN ULONG Index,
- IN ULONG Length,
- IN ULONG IndexValue,
- IN BOOLEAN CanWait)
-{
- ExRaiseStatus(STATUS_NOT_IMPLEMENTED);
-}
-
-ULONG
-FatScanFat16ForContinousRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN OUT PULONG Index,
- IN BOOLEAN CanWait)
-{
- ExRaiseStatus(STATUS_NOT_IMPLEMENTED);
-}
-
-ULONG
-FatSetFat16ContinousRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN ULONG Index,
- IN ULONG Length,
- IN BOOLEAN CanWait)
-{
- ExRaiseStatus(STATUS_NOT_IMPLEMENTED);
-}
-
-ULONG
-FatScanFat16ForValueRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN OUT PULONG Index,
- IN ULONG IndexValue,
- IN BOOLEAN CanWait)
-{
- ExRaiseStatus(STATUS_NOT_IMPLEMENTED);
-}
-
-ULONG
-FatSetFat16ValueRun(IN OUT PFAT_SCAN_CONTEXT Context,
- IN ULONG Index,
- IN ULONG Length,
- IN ULONG IndexValue,
- IN BOOLEAN CanWait)
-{
- ExRaiseStatus(STATUS_NOT_IMPLEMENTED);
-}
-
/**
* Scans FAT32 for continous chain of clusters
*
* @param Context
- * Pointer to FAT_SCAN_CONTEXT.
+ * Pointer to FAT_PAGE_CONTEXT.
*
* @param Index
* Supplies the Index of the first cluster
@@ -241,79 +197,26 @@
* Raises STATUS_CANT_WAIT race condition.
*/
ULONG
-FatScanFat32ForContinousRun(IN OUT PFAT_SCAN_CONTEXT Context,
+FatScanFat32ForContinousRun(IN OUT PFAT_PAGE_CONTEXT Context,
IN OUT PULONG Index,
IN BOOLEAN CanWait)
{
- LONGLONG PageOffset;
- SIZE_T OffsetWithinPage, PageValidLength;
- PULONG Entry, BeyoudLastEntry;
- /* Determine page offset and the offset within page
- * for the first cluster.
- */
- PageValidLength = PAGE_SIZE;
- PageOffset = ((LONGLONG) *Index) << 0x2;
- OffsetWithinPage = (SIZE_T) (PageOffset & (PAGE_SIZE - 1));
- PageOffset -= OffsetWithinPage;
- /* Check if the context already has the required page mapped.
- * Map the first page is necessary.
- */
- if (PageOffset != Context->PageOffset.QuadPart)
- {
- Context->PageOffset.QuadPart = PageOffset;
- if (Context->PageBcb != NULL)
- {
- CcUnpinData(Context->PageBcb);
- Context->PageBcb = NULL;
- }
- if (!CcMapData(Context->FileObject,
- &Context->PageOffset,
- PAGE_SIZE,
- CanWait,
- &Context->PageBcb,
- &Context->PageBuffer))
- {
- Context->PageOffset.QuadPart = 0LL;
- ExRaiseStatus(STATUS_CANT_WAIT);
- }
- }
- Entry = Add2Ptr(Context->PageBuffer, OffsetWithinPage, PULONG);
- /* Next Page Offset */
- PageOffset = Context->PageOffset.QuadPart + PAGE_SIZE;
- if (PageOffset > Context->BeyondLastEntryOffset)
- PageValidLength = (SIZE_T) (Context->BeyondLastEntryOffset
- - Context->PageOffset.QuadPart);
- BeyoudLastEntry = Add2Ptr(Context->PageBuffer, PageValidLength, PULONG);
+ 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 < BeyoudLastEntry);
+ } while (++Entry < EndOfPage);
/* Check if this is the last available entry */
- if (PageValidLength < PAGE_SIZE)
+ if (FatPinIsLastPage(Context))
break;
- /* We are getting beyond current page and
- * are still in the continous run, map the next page.
- */
- Context->PageOffset.QuadPart = PageOffset;
- CcUnpinData(Context->PageBcb);
- if (!CcMapData(Context->FileObject,
- &Context->PageOffset, PAGE_SIZE, CanWait,
- &Context->PageBcb, &Context->PageBuffer))
- {
- Context->PageBcb = NULL;
- Context->PageOffset.QuadPart = 0LL;
- ExRaiseStatus(STATUS_CANT_WAIT);
- }
- Entry = (PULONG) Context->PageBuffer;
- /* Next Page Offset */
- PageOffset = Context->PageOffset.QuadPart + PAGE_SIZE;
- if (PageOffset > Context->BeyondLastEntryOffset)
- PageValidLength = (SIZE_T) (Context->BeyondLastEntryOffset
- - Context->PageOffset.QuadPart);
- BeyoudLastEntry = Add2Ptr(Context->PageBuffer, PageValidLength, PULONG);
+ Entry = (PULONG) FatPinNextPage(Context);
+ EndOfPage = FatPinEndOfPage(Context, PULONG);
}
return (*Index - 1);
}
@@ -388,7 +291,7 @@
{
LONGLONG CurrentLbo, CurrentVbo, BeyondLastVbo, CurrentLength;
ULONG Entry, NextEntry, NumberOfEntries, CurrentIndex;
- FAT_SCAN_CONTEXT Context;
+ FAT_PAGE_CONTEXT Context;
PVCB Vcb;
/* Some often used values */
@@ -428,8 +331,11 @@
CurrentIndex = 0L;
CurrentVbo = 0LL;
}
+ /* Initialize Context */
RtlZeroMemory(&Context, sizeof(Context));
- Context.FileObject = Vcb->VolumeFileObject;
+ Context.FileObject = Vcb->StreamFileObject;
+ Context.EndOfData.QuadPart = Vcb->BeyondLastClusterInFat;
+
while (CurrentVbo < BeyondLastVbo)
{
/* Locate Continous run starting with the current entry */
@@ -532,6 +438,10 @@
Vcb->BytesPerCluster = SectorsToBytes(Vcb, Vcb->Bpb.SectorsPerCluster);
Vcb->BytesPerClusterLog = FatPowerOfTwo(Vcb->BytesPerCluster);
Vcb->BeyondLastClusterInFat = ((LONGLONG) Vcb->Clusters) * Vcb->IndexDepth /
0x8;
+
+ /* Update real volume size with the real value. */
+ Vcb->Header.FileSize.QuadPart =
+ Vcb->Header.AllocationSize.QuadPart = SectorsToBytes(Vcb, Vcb->Sectors);
}
NTSTATUS
@@ -558,18 +468,19 @@
/* Setup Vcb fields */
Vcb->TargetDeviceObject = TargetDeviceObject;
ObReferenceObject(TargetDeviceObject);
+ Vcb->Vpb = Vpb;
/* Setup FCB Header */
ExInitializeFastMutex(&Vcb->HeaderMutex);
FsRtlSetupAdvancedHeader(&Vcb->Header, &Vcb->HeaderMutex);
/* Create Volume File Object */
- Vcb->VolumeFileObject = IoCreateStreamFileObject(NULL,
+ Vcb->StreamFileObject = IoCreateStreamFileObject(NULL,
Vcb->TargetDeviceObject);
/* We have to setup all FCB fields needed for CC */
- Vcb->VolumeFileObject->FsContext = Vcb;
- Vcb->VolumeFileObject->SectionObjectPointer =
&Vcb->SectionObjectPointers;
+ Vcb->StreamFileObject->FsContext = Vcb;
+ Vcb->StreamFileObject->SectionObjectPointer =
&Vcb->SectionObjectPointers;
/* At least full boot sector should be available */
Vcb->Header.FileSize.QuadPart = sizeof(PACKED_BOOT_SECTOR);
@@ -578,7 +489,7 @@
Vcb->Header.ValidDataLength.LowPart = MAXULONG;
/* Initialize CC */
- CcInitializeCacheMap(Vcb->VolumeFileObject,
+ CcInitializeCacheMap(Vcb->StreamFileObject,
(PCC_FILE_SIZES)&Vcb->Header.AllocationSize,
FALSE,
&FatGlobalData.CacheMgrNoopCallbacks,
@@ -592,7 +503,7 @@
* any of the parameters set further
* in this routine.
*/
- if (CcMapData(Vcb->VolumeFileObject,
+ if (CcMapData(Vcb->StreamFileObject,
&Offset,
sizeof(PACKED_BOOT_SECTOR),
TRUE,
@@ -606,7 +517,7 @@
{
Status = STATUS_UNRECOGNIZED_VOLUME;
}
- CopyUchar4(&Vpb->SerialNumber, BootSector->Id);
+ CopyUchar4(&Vcb->Vpb->SerialNumber, BootSector->Id);
CcUnpinData(Bcb);
}
else
@@ -641,12 +552,12 @@
ZeroSize.QuadPart = 0LL;
/* Close volume file */
- if (Vcb->VolumeFileObject != NULL)
+ if (Vcb->StreamFileObject != NULL)
{
/* Uninitialize CC. */
- CcUninitializeCacheMap(Vcb->VolumeFileObject, &ZeroSize, NULL);
- ObDereferenceObject(Vcb->VolumeFileObject);
- Vcb->VolumeFileObject = NULL;
+ CcUninitializeCacheMap(Vcb->StreamFileObject, &ZeroSize, NULL);
+ ObDereferenceObject(Vcb->StreamFileObject);
+ Vcb->StreamFileObject = NULL;
}
/* Free notifications stuff */
Modified: trunk/reactos/drivers/filesystems/fastfat_new/fat.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fat.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fat.h [iso-8859-1] Wed Feb 25 15:25:06
2009
@@ -248,7 +248,7 @@
// sizeof = 0x020
typedef struct _LONG_FILE_NAME_ENTRY {
- UCHAR Index;
+ UCHAR SeqNum;
UCHAR NameA[10];
UCHAR Attributes;
UCHAR Type;
@@ -259,7 +259,13 @@
} LONG_FILE_NAME_ENTRY, *PLONG_FILE_NAME_ENTRY;
// sizeof = 0x020
-#define FAT_FN_DIR_ENTRY_TERM_INDEX 0x40
+#define FAT_LFN_NAME_LENGTH \
+ (RTL_FIELD_SIZE(LONG_FILE_NAME_ENTRY, NameA) \
+ + RTL_FIELD_SIZE(LONG_FILE_NAME_ENTRY, NameB) \
+ + RTL_FIELD_SIZE(LONG_FILE_NAME_ENTRY, NameC))
+
+#define FAT_FN_DIR_ENTRY_LAST 0x40
+#define FAT_FN_MAX_DIR_ENTIES 0x14
#define FAT_BYTES_PER_DIRENT 0x20
#define FAT_BYTES_PER_DIRENT_LOG 0x05
Modified: trunk/reactos/drivers/filesystems/fastfat_new/fatstruc.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fatstruc.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fatstruc.h [iso-8859-1] Wed Feb 25
15:25:06 2009
@@ -3,7 +3,10 @@
typedef struct _FAT_SCAN_CONTEXT *PFAT_SCAN_CONTEXT;
typedef struct _FAT_IO_CONTEXT *PFAT_IO_CONTEXT;
+typedef struct _FAT_IRP_CONTEXT *PFAT_IRP_CONTEXT;
typedef PVOID PBCB;
+
+typedef NTSTATUS (*PFAT_OPERATION_HANDLER) (PFAT_IRP_CONTEXT);
typedef struct _FAT_GLOBAL_DATA
{
@@ -22,6 +25,39 @@
LARGE_INTEGER DefaultFileTime;
} FAT_GLOBAL_DATA;
+typedef struct _FAT_PAGE_CONTEXT
+{
+ PFILE_OBJECT FileObject;
+ LARGE_INTEGER EndOfData;
+ LARGE_INTEGER Offset;
+ LARGE_INTEGER EndOfPage;
+ SIZE_T ValidLength;
+ PVOID Buffer;
+ PBCB Bcb;
+ BOOLEAN CanWait;
+} FAT_PAGE_CONTEXT, *PFAT_PAGE_CONTEXT;
+
+#define FatPinSetupContext(xContext, xFcb, CanWait) \
+{ \
+ (xContext)->FileObject = (xFcb)->StreamFileObject; \
+ (xContext)->EndOfData = (xFcb)->Header.FileSize; \
+ (xContext)->Offset.QuadPart = -1LL; \
+ (xContext)->Bcb = NULL; \
+ (xContext)->CanWait = CanWait; \
+}
+
+#define FatPinCleanupContext(xContext) \
+ if ((xContext)->Bcb != NULL) { \
+ CcUnpinData((xContext)->Bcb); \
+ (xContext)->Bcb = NULL; \
+ } \
+
+#define FatPinEndOfPage(xContext, xType) \
+ Add2Ptr((xContext)->Buffer, (xContext)->ValidLength, xType)
+
+#define FatPinIsLastPage(xContext) \
+ ((xContext)->ValidLength != PAGE_SIZE)
+
#define IRPCONTEXT_CANWAIT 0x0001
#define IRPCONTEXT_PENDINGRETURNED 0x0002
#define IRPCONTEXT_STACK_IO_CONTEXT 0x0004
@@ -38,18 +74,23 @@
ULONG Flags;
struct _VCB *Vcb;
ULONG PinCount;
+ FAT_PAGE_CONTEXT Page;
struct _FAT_IO_CONTEXT *FatIoContext;
-
WORK_QUEUE_ITEM WorkQueueItem;
+ PFAT_OPERATION_HANDLER QueuedOperationHandler;
PIO_STACK_LOCATION Stack;
KEVENT Event;
-} FAT_IRP_CONTEXT, *PFAT_IRP_CONTEXT;
+} FAT_IRP_CONTEXT;
typedef struct _FAT_IO_CONTEXT
{
PMDL ZeroMdl;
- PIRP MasterIrp;
- LONG IrpCount;
+ PIRP Irp;
+ LONG RunCount;
+ SIZE_T Length;
+ LONGLONG Offset;
+ PFILE_OBJECT FileObject;
+
union
{
struct
@@ -57,19 +98,16 @@
PERESOURCE Resource;
PERESOURCE PagingIoResource;
ERESOURCE_THREAD ResourceThreadId;
- ULONG RequestedByteCount;
- PFILE_OBJECT FileObject;
- BOOLEAN ReadOperation;
} Async;
KEVENT SyncEvent;
} Wait;
- PIRP Irp[0];
+ PIRP AssociatedIrp[0];
} FAT_IO_CONTEXT;
-typedef ULONG (*PFAT_SCANFAT_FOR_CONTINOUS_RUN_ROUTINE) (struct _FAT_SCAN_CONTEXT*,
PULONG, BOOLEAN);
-typedef ULONG (*PFAT_SETFAT_CONTINOUS_RUN_ROUTINE) (PFAT_SCAN_CONTEXT, ULONG, ULONG,
BOOLEAN);
-typedef ULONG (*PFAT_SCANFAT_FOR_VALUE_RUN_ROUTINE) (PFAT_SCAN_CONTEXT, PULONG, ULONG,
BOOLEAN);
-typedef ULONG (*PFAT_SETFAT_VALUE_RUN_ROUTINE) (PFAT_SCAN_CONTEXT, ULONG, ULONG, ULONG,
BOOLEAN);
+typedef ULONG (*PFAT_SCANFAT_FOR_CONTINOUS_RUN_ROUTINE) (PFAT_PAGE_CONTEXT, PULONG,
BOOLEAN);
+typedef ULONG (*PFAT_SETFAT_CONTINOUS_RUN_ROUTINE) (PFAT_PAGE_CONTEXT, ULONG, ULONG,
BOOLEAN);
+typedef ULONG (*PFAT_SCANFAT_FOR_VALUE_RUN_ROUTINE) (PFAT_PAGE_CONTEXT, PULONG, ULONG,
BOOLEAN);
+typedef ULONG (*PFAT_SETFAT_VALUE_RUN_ROUTINE) (PFAT_PAGE_CONTEXT, ULONG, ULONG, ULONG,
BOOLEAN);
typedef struct _FAT_METHODS {
PFAT_SCANFAT_FOR_CONTINOUS_RUN_ROUTINE ScanContinousRun;
@@ -78,7 +116,7 @@
PFAT_SETFAT_VALUE_RUN_ROUTINE SetValueRun;
} FAT_METHODS, *PFAT_METHODS;
-#define FAT_NTC_VCB (USHORT)TAG('F', 'V', 0, 0);
+#define FAT_NTC_VCB (USHORT) TAG('F', 'V', 0, 0)
/* Volume Control Block */
typedef struct _VCB
@@ -87,9 +125,10 @@
FAST_MUTEX HeaderMutex;
SECTION_OBJECT_POINTERS SectionObjectPointers;
- PFILE_OBJECT VolumeFileObject;
+ PFILE_OBJECT StreamFileObject;
PDEVICE_OBJECT TargetDeviceObject;
LIST_ENTRY VcbLinks;
+ PVPB Vpb;
/* Notifications support */
PNOTIFY_SYNC NotifySync;
@@ -186,10 +225,14 @@
FCB_NAME_LINK FileName[0x2];
/* Buffer for the short name */
WCHAR ShortNameBuffer[0xc];
+ /* File basic info */
+ FILE_BASIC_INFORMATION BasicInfo;
union
{
struct
{
+ /* Directory data stream (just handy to have it). */
+ PFILE_OBJECT StreamFileObject;
/* Bitmap to search for free dirents. */
/* RTL_BITMAP Bitmap; */
PRTL_SPLAY_LINKS SplayLinks;
@@ -197,13 +240,56 @@
};
} FCB, *PFCB;
+typedef struct _FAT_ENUM_DIRENT_CONTEXT *PFAT_ENUM_DIRENT_CONTEXT;
+typedef struct _FAT_ENUM_DIR_CONTEXT *PFAT_ENUM_DIR_CONTEXT;
+
+typedef ULONG (*PFAT_COPY_DIRENT_ROUTINE) (PFAT_ENUM_DIR_CONTEXT, PDIR_ENTRY, PVOID);
+
+typedef struct _FAT_ENUM_DIRENT_CONTEXT
+{
+ FAT_PAGE_CONTEXT Page;
+
+ /* Copy dirent to dirinfo */
+ PFAT_COPY_DIRENT_ROUTINE CopyDirent;
+ LONGLONG BytesPerClusterMask;
+
+ /* Info buffer characteristics */
+ PVOID Buffer;
+ SIZE_T Offset;
+ SIZE_T Length;
+
+ /* Criteria */
+ PUNICODE_STRING FileName;
+ UCHAR CcbFlags;
+
+ /* Lfn buffer/length offsets */
+ ULONG LengthOffset;
+ ULONG NameOffset;
+} FAT_ENUM_DIRENT_CONTEXT;
+
+typedef struct _FAT_FIND_DIRENT_CONTEXT
+{
+ FAT_PAGE_CONTEXT Page;
+ UNICODE_STRING ShortName;
+ WCHAR ShortNameBuffer[0x18];
+ /* Criteria */
+ PUNICODE_STRING FileName;
+ BOOLEAN Valid8dot3Name;
+} FAT_FIND_DIRENT_CONTEXT, *PFAT_FIND_DIRENT_CONTEXT;
+
typedef struct _CCB
{
LARGE_INTEGER CurrentByteOffset;
ULONG Entry;
UNICODE_STRING SearchPattern;
+ UCHAR Flags;
} CCB, *PCCB;
+
+#define CCB_SEARCH_RETURN_SINGLE_ENTRY 0x01
+#define CCB_SEARCH_PATTERN_LEGAL_8DOT3 0x02
+#define CCB_SEARCH_PATTERN_HAS_WILD_CARD 0x04
+#define CCB_DASD_IO 0x10
extern FAT_GLOBAL_DATA FatGlobalData;
#endif//__STRUCT_H__
Modified: trunk/reactos/drivers/filesystems/fastfat_new/fcb.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fcb.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fcb.c [iso-8859-1] Wed Feb 25 15:25:06
2009
@@ -1,9 +1,9 @@
/*
* PROJECT: ReactOS FAT file system driver
* LICENSE: GPL - See COPYING in the top level directory
- * FILE: drivers/filesystems/fastfat/rw.c
- * PURPOSE: Read/write support
- * PROGRAMMERS:
+ * FILE: drivers/filesystems/fastfat/fcb.c
+ * PURPOSE: FCB manipulation routines.
+ * PROGRAMMERS: Alexey Vlasov
*/
/* INCLUDES *****************************************************************/
@@ -13,5 +13,316 @@
/* FUNCTIONS ****************************************************************/
-
+/**
+ * Locates FCB by the supplied name in the cache trie of fcbs.
+ *
+ * @param ParentFcb
+ * Supplies a pointer to the parent FCB
+ *
+ * @param Name
+ * Supplied a name of the FCB to be located in cache.
+ *
+ * @return
+ * Pointer to the found FCB or NULL.
+ */
+PFCB
+FatLookupFcbByName(
+ IN PFCB ParentFcb,
+ IN PUNICODE_STRING Name)
+{
+ PFCB_NAME_LINK Node;
+ PRTL_SPLAY_LINKS Links;
+
+ /* Get sub-trie root node from the parent FCB */
+ Links = ParentFcb->Dcb.SplayLinks;
+ while (Links != NULL)
+ {
+ LONG Comparison;
+
+ Node = CONTAINING_RECORD(Links, FCB_NAME_LINK, Links);
+
+ /*
+ * Compare the name stored in the node
+ * and determine the direction to walk.
+ */
+ Comparison = RtlCompareUnicodeString(&Node->String, Name, TRUE);
+ if (Comparison > 0) {
+ /* Left child */
+ Links = RtlLeftChild(&Node->Links);
+ }
+ else if (Comparison < 0)
+ {
+ /* Right child */
+ Links = RtlRightChild(&Node->Links);
+ }
+ else
+ {
+ /* Strings are equal, we have found the node! */
+ break;
+ }
+ }
+
+ /* The case when nothing was found. */
+ if (Links == NULL)
+ return NULL;
+
+ /* Cast node to the FCB structure. */
+ return CONTAINING_RECORD(Links, FCB, FileName[Node->Type]);
+}
+
+/**
+ * Inserts FCB into FCBs cache trie.
+ *
+ * @param ParentFcb
+ * Supplies a pointer to the parent FCB
+ *
+ * @param Fcb
+ * Supplied a pointer to the being inserted FCB.
+ *
+ * @return
+ * TRUE if the FCB was successfully inserted,
+ * FASLE in the case of name collision.
+ */
+BOOLEAN
+FatLinkFcbNames(
+ IN PFCB ParentFcb,
+ IN PFCB Fcb)
+{
+ PFCB_NAME_LINK Name;
+ PRTL_SPLAY_LINKS Links;
+
+ /* None of the parameters can be NULL */
+ ASSERT(ParentFcb != NULL && Fcb != NULL);
+
+ /* Get root links of the parent FCB. */
+ Links = ParentFcb->Dcb.SplayLinks;
+
+ /*
+ * Get first file name
+ * (short name for FAT because it's always there.
+ */
+ Name = Fcb->FileName;
+
+ /*
+ * Check if ParentDcb links are initialized,
+ * at least one child FCB is cached.
+ */
+ if (Links == NULL)
+ {
+ ParentFcb->Dcb.SplayLinks = Links = &Name->Links;
+ RtlInitializeSplayLinks(Links);
+
+ /* Check if we have more names to cache. */
+ if ((++Name)->String.Length == 0)
+ return TRUE;
+ }
+ /* Lookup for the insertion point in the trie. */
+ do
+ {
+ LONG Comparison;
+ PFCB_NAME_LINK Node;
+ PRTL_SPLAY_LINKS PrevLinks;
+
+ PrevLinks = Links;
+ Node = CONTAINING_RECORD(Links, FCB_NAME_LINK, Links);
+ Comparison = RtlCompareUnicodeString(&Node->String, &Name->String,
TRUE);
+ if (Comparison > 0) {
+ Links = RtlLeftChild(&Node->Links);
+ if (Links == NULL)
+ {
+ RtlInsertAsLeftChild(PrevLinks, &Name->Links);
+ break;
+ }
+ }
+ else if (Comparison < 0)
+ {
+ Links = RtlRightChild(&Node->Links);
+ if (Links == NULL)
+ {
+ RtlInsertAsRightChild(PrevLinks, &Name->Links);
+ break;
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
+
+ /* Possibly switch to the second (lfn) name and cache that. */
+ } while (Name == Fcb->FileName && (++Name)->String.Length > 0);
+ return TRUE;
+}
+
+/**
+ * Unlinks FCB from the FCBs cache trie.
+ *
+ * @param ParentFcb
+ * Supplies a pointer to the parent FCB
+ *
+ * @param Fcb
+ * Supplied a pointer to the being unlinked FCB.
+ *
+ * @return
+ * VOID
+ */
+VOID
+FatUnlinkFcbNames(
+ IN PFCB ParentFcb,
+ IN PFCB Fcb)
+{
+ /* See if there is an lfn and unlink that. */
+ if (Fcb->FileName[FcbLongName].String.Length > 0)
+ ParentFcb->Dcb.SplayLinks =
+ RtlDelete(&Fcb->FileName[FcbLongName].Links);
+
+ /* See if there is a short name and unlink that. */
+ if (Fcb->FileName[FcbShortName].String.Length > 0)
+ ParentFcb->Dcb.SplayLinks =
+ RtlDelete(&Fcb->FileName[FcbShortName].Links);
+}
+
+NTSTATUS
+FatCreateFcb(
+ OUT PFCB* CreatedFcb,
+ IN PFAT_IRP_CONTEXT IrpContext,
+ IN PFCB ParentFcb,
+ IN PDIR_ENTRY Dirent,
+ IN PUNICODE_STRING FileName,
+ IN PUNICODE_STRING LongFileName OPTIONAL)
+{
+ NTSTATUS Status;
+ PFCB Fcb;
+
+ /* Allocate FCB structure. */
+ Fcb = (PFCB) ExAllocateFromNPagedLookasideList(&FatGlobalData.NonPagedFcbList);
+ if (Fcb == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+ RtlZeroMemory(Fcb, sizeof(FCB));
+
+ /* Setup FCB Advanced Header. */
+ Fcb->Header.NodeTypeCode = FAT_NTC_FCB;
+ Fcb->Header.NodeByteSize = sizeof(*Fcb);
+ ExInitializeResourceLite(&Fcb->Resource);
+ Fcb->Header.Resource = &Fcb->Resource;
+ ExInitializeResourceLite(&Fcb->PagingIoResource);
+ Fcb->Header.PagingIoResource = &Fcb->PagingIoResource;
+ ExInitializeFastMutex(&Fcb->HeaderMutex);
+ FsRtlSetupAdvancedHeader(&Fcb->Header, &Fcb->HeaderMutex);
+ Fcb->Header.FileSize.QuadPart = Dirent->FileSize;
+ Fcb->Header.ValidDataLength.QuadPart = Dirent->FileSize;
+ Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
+
+ /* Setup main fields. */
+ FsRtlInitializeFileLock(&Fcb->Lock, NULL, NULL);
+ FsRtlInitializeLargeMcb(&Fcb->Mcb, PagedPool);
+ Fcb->Vcb = IrpContext->Vcb;
+ Fcb->ParentFcb = ParentFcb;
+ Fcb->FirstCluster = Dirent->FirstCluster
+ | (Dirent->FirstClusterOfFileHi << 0x10);
+
+ /* Setup basic info. */
+ Fcb->BasicInfo.FileAttributes = Dirent->Attributes;
+ FatQueryFileTimes(&Fcb->BasicInfo.CreationTime, Dirent);
+
+ /* Setup short name since always present in FAT. */
+ Fcb->FileName[FcbShortName].Type = FcbShortName;
+ Fcb->FileName[FcbShortName].String.Buffer = Fcb->ShortNameBuffer;
+ Fcb->FileName[FcbShortName].String.MaximumLength = 0x0c;
+ Fcb->FileName[FcbShortName].String.Length = FileName->Length;
+ RtlCopyMemory(Fcb->ShortNameBuffer, FileName->Buffer, FileName->Length);
+
+ /* Just swap optional lfn. */
+ if (ARGUMENT_PRESENT(LongFileName) && LongFileName->Length > 0)
+ {
+ Fcb->FileName[FcbLongName].Type = FcbLongName;
+ Fcb->FileName[FcbLongName].String = *LongFileName;
+ RtlZeroMemory(LongFileName, sizeof(UNICODE_STRING));
+ }
+
+ /* Put FCB into cache trie. */
+ if (!FatLinkFcbNames(ParentFcb, Fcb))
+ {
+ Status = STATUS_OBJECT_NAME_COLLISION;
+ goto FsdFatCreateFcbCleanup;
+ }
+ *CreatedFcb = Fcb;
+
+ /* We are done! */
+ return STATUS_SUCCESS;
+
+FsdFatCreateFcbCleanup:
+ if (ARGUMENT_PRESENT(LongFileName) &&
+ Fcb->FileName[FcbLongName].String.Buffer != NULL)
+ {
+ /* Swap lfn back to the input parameter */
+ *LongFileName = Fcb->FileName[FcbLongName].String;
+ }
+ ExFreeToNPagedLookasideList(&FatGlobalData.NonPagedFcbList, Fcb);
+ return Status;
+}
+
+NTSTATUS
+FatOpenFcb(
+ OUT PFCB* Fcb,
+ IN PFAT_IRP_CONTEXT IrpContext,
+ IN PFCB ParentFcb,
+ IN PUNICODE_STRING FileName)
+{
+ FAT_FIND_DIRENT_CONTEXT Context;
+ UNICODE_STRING LongFileName;
+ PDIR_ENTRY Dirent;
+ NTSTATUS Status;
+
+ // TODO: _SEH_TRY {
+ if (ParentFcb->Dcb.StreamFileObject == NULL)
+ {
+ PFILE_OBJECT FileObject;
+ PVPB Vpb;
+
+ Vpb = IrpContext->Vcb->Vpb;
+
+ /* Create stream file object */
+ FileObject = IoCreateStreamFileObject(NULL, Vpb->RealDevice);
+ FileObject->Vpb = Vpb;
+ FileObject->SectionObjectPointer = &ParentFcb->SectionObjectPointers;
+ FileObject->FsContext = ParentFcb;
+ FileObject->FsContext2 = NULL;
+
+ /* Store it in parent fcb */
+ ParentFcb->Dcb.StreamFileObject = FileObject;
+
+ }
+
+ /* Check if cache is initialized. */
+ if (ParentFcb->Dcb.StreamFileObject->PrivateCacheMap == NULL )
+ {
+ CcInitializeCacheMap(ParentFcb->Dcb.StreamFileObject,
+ (PCC_FILE_SIZES) &ParentFcb->Header.AllocationSize,
+ TRUE,
+ &FatGlobalData.CacheMgrNoopCallbacks,
+ ParentFcb);
+ }
+
+ /* Page context */
+ Context.Page.FileObject = ParentFcb->Dcb.StreamFileObject;
+ Context.Page.EndOfData = ParentFcb->Header.FileSize;
+ Context.Page.Offset.QuadPart = -1LL;
+ Context.Page.Bcb = NULL;
+ Context.Page.CanWait = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT);
+ Context.Page.EndOfData = ParentFcb->Header.FileSize;
+
+ /* Search context */
+ Context.ShortName.Length = 0;
+ Context.ShortName.Buffer = Context.ShortNameBuffer;
+ Context.ShortName.MaximumLength = sizeof(Context.ShortNameBuffer);
+ Context.FileName = FileName;
+ Context.Valid8dot3Name = RtlIsNameLegalDOS8Dot3(FileName, NULL, NULL);
+
+ /* Locate the dirent */
+ FatFindDirent(&Context, &Dirent, &LongFileName);
+
+ Status = FatCreateFcb(Fcb, IrpContext, ParentFcb, Dirent,
+ &Context.ShortName, &LongFileName);
+ return Status;
+}
/* EOF */
Modified: trunk/reactos/drivers/filesystems/fastfat_new/fsctl.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fsctl.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fsctl.c [iso-8859-1] Wed Feb 25 15:25:06
2009
@@ -112,7 +112,7 @@
if (!NT_SUCCESS(Status)) goto FatMountVolumeCleanup;
- VolumeDevice->DeviceObject.SectorSize = DiskGeometry.BytesPerSector;
+ VolumeDevice->DeviceObject.SectorSize = (USHORT) DiskGeometry.BytesPerSector;
/* Signal we're done with initializing */
VolumeDevice->DeviceObject.Flags &= ~DO_DEVICE_INITIALIZING;
@@ -128,7 +128,7 @@
VolumeDevice->Vcb.MediaChangeCount = MediaChangeCount;
/* Notify about volume mount */
- FsRtlNotifyVolumeEvent(VolumeDevice->Vcb.VolumeFileObject, FSRTL_VOLUME_MOUNT);
+ FsRtlNotifyVolumeEvent(VolumeDevice->Vcb.StreamFileObject, FSRTL_VOLUME_MOUNT);
/* Return success */
return STATUS_SUCCESS;