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