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