diff options
Diffstat (limited to 'filesys/fastfat/create.c')
| -rw-r--r-- | filesys/fastfat/create.c | 398 |
1 files changed, 292 insertions, 106 deletions
diff --git a/filesys/fastfat/create.c b/filesys/fastfat/create.c index 6de15823..8140019f 100644 --- a/filesys/fastfat/create.c +++ b/filesys/fastfat/create.c @@ -97,7 +97,7 @@ _Requires_lock_held_(_Global_critical_region_) IO_STATUS_BLOCK FatOpenExistingFcb ( _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, + _In_ PIO_STACK_LOCATION IrpSp, _Inout_ PFILE_OBJECT FileObject, _Inout_ PVCB Vcb, _Inout_ PFCB Fcb, @@ -106,7 +106,7 @@ FatOpenExistingFcb ( _In_ ULONG AllocationSize, _In_ PFILE_FULL_EA_INFORMATION EaBuffer, _In_ ULONG EaLength, - _In_ UCHAR FileAttributes, + _In_ USHORT FileAttributes, _In_ ULONG CreateDisposition, _In_ BOOLEAN NoEaKnowledge, _In_ BOOLEAN DeleteOnClose, @@ -132,7 +132,7 @@ _Requires_lock_held_(_Global_critical_region_) IO_STATUS_BLOCK FatOpenExistingDirectory ( _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, + _In_ PIO_STACK_LOCATION IrpSp, _Inout_ PFILE_OBJECT FileObject, _Inout_ PVCB Vcb, _Outptr_result_maybenull_ PDCB *Dcb, @@ -162,12 +162,13 @@ FatOpenExistingFile ( _In_ ULONG LfnByteOffset, _In_ ULONG DirentByteOffset, _In_ PUNICODE_STRING Lfn, + _In_ PUNICODE_STRING OrigLfn, _In_ PACCESS_MASK DesiredAccess, _In_ USHORT ShareAccess, _In_ ULONG AllocationSize, _In_ PFILE_FULL_EA_INFORMATION EaBuffer, _In_ ULONG EaLength, - _In_ UCHAR FileAttributes, + _In_ USHORT FileAttributes, _In_ ULONG CreateDisposition, _In_ BOOLEAN IsPagingFile, _In_ BOOLEAN NoEaKnowledge, @@ -180,7 +181,7 @@ _Requires_lock_held_(_Global_critical_region_) IO_STATUS_BLOCK FatCreateNewDirectory ( _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, + _In_ PIO_STACK_LOCATION IrpSp, _Inout_ PFILE_OBJECT FileObject, _Inout_ PVCB Vcb, _Inout_ PDCB ParentDcb, @@ -190,7 +191,7 @@ FatCreateNewDirectory ( _In_ USHORT ShareAccess, _In_ PFILE_FULL_EA_INFORMATION EaBuffer, _In_ ULONG EaLength, - _In_ UCHAR FileAttributes, + _In_ USHORT FileAttributes, _In_ BOOLEAN NoEaKnowledge, _In_ BOOLEAN DeleteOnClose, _In_ BOOLEAN OpenRequiringOplock @@ -200,7 +201,7 @@ _Requires_lock_held_(_Global_critical_region_) IO_STATUS_BLOCK FatCreateNewFile ( _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, + _In_ PIO_STACK_LOCATION IrpSp, _Inout_ PFILE_OBJECT FileObject, _Inout_ PVCB Vcb, _Inout_ PDCB ParentDcb, @@ -211,7 +212,7 @@ FatCreateNewFile ( _In_ ULONG AllocationSize, _In_ PFILE_FULL_EA_INFORMATION EaBuffer, _In_ ULONG EaLength, - _In_ UCHAR FileAttributes, + _In_ USHORT FileAttributes, _In_ PUNICODE_STRING LfnBuffer, _In_ BOOLEAN IsPagingFile, _In_ BOOLEAN NoEaKnowledge, @@ -220,6 +221,7 @@ FatCreateNewFile ( _In_ BOOLEAN TemporaryFile ); + _Requires_lock_held_(_Global_critical_region_) IO_STATUS_BLOCK FatSupersedeOrOverwriteFile ( @@ -229,7 +231,7 @@ FatSupersedeOrOverwriteFile ( _In_ ULONG AllocationSize, _In_ PFILE_FULL_EA_INFORMATION EaBuffer, _In_ ULONG EaLength, - _In_ UCHAR FileAttributes, + _In_ USHORT FileAttributes, _In_ ULONG CreateDisposition, _In_ BOOLEAN NoEaKnowledge ); @@ -252,6 +254,12 @@ FatCheckShareAccess ( #pragma alloc_text(PAGE, FatCheckShareAccess) #pragma alloc_text(PAGE, FatCheckSystemSecurityAccess) #pragma alloc_text(PAGE, FatCommonCreate) + +#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) +#pragma alloc_text(PAGE, FatCommonCreateOnNewStack) +#pragma alloc_text(PAGE, FatCommonCreateCallout) +#endif + #pragma alloc_text(PAGE, FatCreateNewDirectory) #pragma alloc_text(PAGE, FatCreateNewFile) #pragma alloc_text(PAGE, FatFsdCreate) @@ -337,7 +345,11 @@ Return Value: IrpContext = FatCreateIrpContext( Irp, TRUE ); +#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) + Status = FatCommonCreateOnNewStack( IrpContext, Irp ); +#else Status = FatCommonCreate( IrpContext, Irp ); +#endif } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) { @@ -356,9 +368,9 @@ Return Value: FsRtlExitFileSystem(); - + // - // Complete the request, unless we had an exception, in which case it + // Complete the request, unless we had an exception, in which case it // was completed in FatProcessException (and the IrpContext freed). // // IrpContext is freed inside FatCompleteRequest. @@ -367,7 +379,7 @@ Return Value: if (!ExceptionCompletedIrp && Status != STATUS_PENDING) { FatCompleteRequest( IrpContext, Irp, Status ); } - + // // And return to our caller // @@ -381,6 +393,158 @@ Return Value: return Status; } +#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) +_Requires_lock_held_(_Global_critical_region_) +VOID +FatCommonCreateCallout ( + _In_ PFAT_CALLOUT_PARAMETERS CalloutParameters + ) + +/*++ + +Routine Description: + + This function is the callout routine that will execute on a new stack when + processing a create. It simply calls FatCommonCreate() with the parameters + in the context and stores the return value in the context. + +Arguments: + + Context - Supplies an opaque pointer to this function's context. It is actually + an FAT_CALLOUT_PARAMETERS structure. + +Return Value: + + None. + +--*/ + +{ + PAGED_CODE(); + + // + // Call FatCommonCreate() with the passed parameters and store the result. + // Exceptions cannot be raised across stack boundaries, so we need to catch + // exceptions here and deal with them. + // + + try { + + CalloutParameters->IrpStatus = FatCommonCreate( CalloutParameters->Create.IrpContext, + CalloutParameters->Create.Irp ); + + } except (FatExceptionFilter( CalloutParameters->Create.IrpContext, GetExceptionInformation() )) { + + // + // Return the resulting status. + // + + CalloutParameters->ExceptionStatus = GetExceptionCode(); + } + +} + + +_Requires_lock_held_(_Global_critical_region_) +NTSTATUS +FatCommonCreateOnNewStack ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PIRP Irp + ) + +/*++ + +Routine Description: + + This routine sets up a switch to a new stack and call to FatCommonCreate(). + +Arguments: + + IrpContext - Supplies the context structure for the overall request. + + Irp - Supplies the IRP being processed. + + CreateContext - Supplies a pointer on the old stack that is used to + store context information for the create itself. + +Return Value: + + NTSTATUS - The status from FatCommonCreate(). + +--*/ +{ + FAT_CALLOUT_PARAMETERS CalloutParameters; + NTSTATUS status; + + PAGED_CODE(); + + // + // Create requests consume a lot of stack space. As such, we always switch to a + // new stack when processing a create. Setup the callout parameters and make the + // call. Note that this cannot fail, since we pass a stack context for a reserve stack. + // + + CalloutParameters.Create.IrpContext = IrpContext; + CalloutParameters.Create.Irp = Irp; + CalloutParameters.ExceptionStatus = CalloutParameters.IrpStatus = STATUS_SUCCESS; + + // + // Mark that we are swapping the stack + // + + SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_SWAPPED_STACK ); + + status = KeExpandKernelStackAndCalloutEx( FatCommonCreateCallout, + &CalloutParameters, + KERNEL_STACK_SIZE, + FALSE, + NULL ); + + // + // Mark that the stack is no longer swapped. Note that there are paths + // that may clear this flag before returning. + // + + if (status != STATUS_PENDING) { + + ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_SWAPPED_STACK ); + } + + // + // If we had an exception occur, re-raise the exception. + // + + if (!NT_SUCCESS( CalloutParameters.ExceptionStatus )) { + FatRaiseStatus( IrpContext, CalloutParameters.ExceptionStatus ); + } + + // + // If the call to KeExpandKernelStackAndCalloutEx returns an error this + // means that the callout routine (FatCommonCreateCallout) was never + // called. Translate that error, and return it. + // + + if (!NT_SUCCESS( status )) { + + // + // Translate to an expected error value + // + + if (status == STATUS_NO_MEMORY) { + + status = STATUS_INSUFFICIENT_RESOURCES; + } + + return status; + } + + // + // Return the status given to us by the callout. + // + + return CalloutParameters.IrpStatus; +} +#endif _Requires_lock_held_(_Global_critical_region_) NTSTATUS @@ -418,7 +582,7 @@ Return Value: PFILE_FULL_EA_INFORMATION EaBuffer; PACCESS_MASK DesiredAccess; ULONG Options; - UCHAR FileAttributes; + USHORT FileAttributes; USHORT ShareAccess; ULONG EaLength; @@ -463,11 +627,11 @@ Return Value: BOOLEAN FirstLoop = TRUE; ULONG MatchFlags = 0; - + CCB LocalCcb; UNICODE_STRING Lfn; UNICODE_STRING OrigLfn = {0}; - + WCHAR LfnBuffer[ FAT_CREATE_INITIAL_NAME_BUF_SIZE]; PAGED_CODE(); @@ -535,7 +699,7 @@ Return Value: EaBuffer = Irp->AssociatedIrp.SystemBuffer; DesiredAccess = &IrpSp->Parameters.Create.SecurityContext->DesiredAccess; Options = IrpSp->Parameters.Create.Options; - FileAttributes = (UCHAR)(IrpSp->Parameters.Create.FileAttributes & ~FILE_ATTRIBUTE_NORMAL); + FileAttributes = IrpSp->Parameters.Create.FileAttributes & ~FILE_ATTRIBUTE_NORMAL; ShareAccess = IrpSp->Parameters.Create.ShareAccess; EaLength = IrpSp->Parameters.Create.EaLength; @@ -560,7 +724,8 @@ Return Value: FileAttributes &= (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | - FILE_ATTRIBUTE_ARCHIVE ); + FILE_ATTRIBUTE_ARCHIVE | + FILE_ATTRIBUTE_ENCRYPTED); // // Locate the volume device object and Vcb that we are trying to access @@ -1296,7 +1461,7 @@ Return Value: // // Not and Fcb or a Dcb so we bug check // - + #pragma prefast( suppress:28159, "this is a serious corruption if it happens" ) FatBugCheck( NodeType(Fcb), (ULONG_PTR) Fcb, 0 ); } @@ -1476,8 +1641,8 @@ Return Value: if (RemainingPart.Length == 0) { - - break; + + break; } // @@ -1505,7 +1670,7 @@ Return Value: // LfnByteOffset = DirentByteOffset - - FAT_LFN_DIRENTS_NEEDED(&Lfn) * sizeof(LFN_DIRENT); + FAT_LFN_DIRENTS_NEEDED(&OrigLfn) * sizeof(LFN_DIRENT); // // Create a dcb for the new directory @@ -1554,7 +1719,7 @@ Return Value: // LfnByteOffset = DirentByteOffset - - FAT_LFN_DIRENTS_NEEDED(&Lfn) * sizeof(LFN_DIRENT); + FAT_LFN_DIRENTS_NEEDED(&OrigLfn) * sizeof(LFN_DIRENT); // // We were able to locate an existing dirent entry, so now @@ -1593,7 +1758,7 @@ Return Value: DeleteOnClose, FileNameOpenedDos, OpenRequiringOplock ); - + Irp->IoStatus.Information = Iosb.Information; try_return( Iosb.Status ); } @@ -1626,6 +1791,7 @@ Return Value: LfnByteOffset, DirentByteOffset, &Lfn, + &OrigLfn, DesiredAccess, ShareAccess, AllocationSize, @@ -1889,12 +2055,12 @@ Return Value: // SavedFlags = IrpContext->Flags; - + SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_RAISE | IRP_CONTEXT_FLAG_DISABLE_WRITE_THROUGH ); - + FatUnpinRepinnedBcbs( IrpContext ); - + if ((FinalDcb != NULL) && (NodeType(FinalDcb) == FAT_NTC_DCB) && IsListEmpty(&FinalDcb->Specific.Dcb.ParentDcbQueue) && @@ -1902,7 +2068,7 @@ Return Value: (FinalDcb->Specific.Dcb.DirectoryFile != NULL)) { PFILE_OBJECT DirectoryFileObject; - + DirectoryFileObject = FinalDcb->Specific.Dcb.DirectoryFile; FinalDcb->Specific.Dcb.DirectoryFile = NULL; @@ -1911,7 +2077,7 @@ Return Value: ObDereferenceObject( DirectoryFileObject ); } - + IrpContext->Flags = SavedFlags; } @@ -1952,7 +2118,7 @@ Return Value: } } else { - + FatUnpinRepinnedBcbs( IrpContext ); } @@ -1981,7 +2147,7 @@ Return Value: if (IsFileObjectReadOnly(FileObject)) { LocalVcb->ReadOnlyCount -= 1; } - + // // WinSE #307418 "Occasional data corruption when standby/resume // while copying files to removable FAT formatted media". @@ -1989,15 +2155,15 @@ Return Value: // operation we should revert the changes we made to the parent // directory and to the allocation table. // - + if (IrpContext->ExceptionStatus == STATUS_VERIFY_REQUIRED && NodeType( LocalFcb ) == FAT_NTC_FCB) { - - FatTruncateFileAllocation( IrpContext, LocalFcb, 0, TRUE ); + + FatTruncateFileAllocation( IrpContext, LocalFcb, 0 ); FatDeleteDirent( IrpContext, LocalFcb, NULL, TRUE ); } - + // // If we leafed out on a new Fcb we should get rid of it at this point. // @@ -2104,7 +2270,6 @@ Return Value: return Iosb.Status; } - // // Internal support routine // @@ -2578,7 +2743,7 @@ _Requires_lock_held_(_Global_critical_region_) IO_STATUS_BLOCK FatOpenExistingDcb ( _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, + _In_ PIO_STACK_LOCATION IrpSp, _Inout_ PFILE_OBJECT FileObject, _Inout_ PVCB Vcb, _Inout_ PDCB Dcb, @@ -2762,66 +2927,66 @@ Return Value: #if (NTDDI_VERSION >= NTDDI_WIN8) NTSTATUS OplockBreakStatus = STATUS_SUCCESS; - + // // If we got a sharing violation try to break outstanding handle // oplocks and retry the sharing check. If the caller specified // FILE_COMPLETE_IF_OPLOCKED we don't bother breaking the oplock; // we just return the sharing violation. // - + if ((Iosb.Status == STATUS_SHARING_VIOLATION) && !FlagOn( IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED )) { - + OplockBreakStatus = FsRtlOplockBreakH( FatGetFcbOplock(Dcb), IrpContext->OriginatingIrp, 0, IrpContext, FatOplockComplete, FatPrePostIrp ); - + // // If FsRtlOplockBreakH returned STATUS_PENDING, then the IRP // has been posted and we need to stop working. // - + if (OplockBreakStatus == STATUS_PENDING) { - + Iosb.Status = STATUS_PENDING; *OplockPostIrp = TRUE; try_return( NOTHING ); - + // // If FsRtlOplockBreakH returned an error we want to return that now. // - + } else if (!NT_SUCCESS( OplockBreakStatus )) { - + Iosb.Status = OplockBreakStatus; try_return( Iosb ); - + // // Otherwise FsRtlOplockBreakH returned STATUS_SUCCESS, indicating // that there is no oplock to be broken. The sharing violation is // returned in that case. // - + } else { - + NT_ASSERT( OplockBreakStatus == STATUS_SUCCESS ); - + try_return( Iosb ); } - + // // The initial sharing check failed with something other than sharing // violation (which should never happen, but let's be future-proof), // or we *did* get a sharing violation and the caller specified // FILE_COMPLETE_IF_OPLOCKED. Either way this create is over. // - + } else { - + try_return( Iosb ); } #else @@ -2937,7 +3102,7 @@ Return Value: SetFlag( Ccb->Flags, CCB_FLAG_DELETE_ON_CLOSE ); } if (FileNameOpenedDos) { - + SetFlag( Ccb->Flags, CCB_FLAG_OPENED_BY_SHORTNAME ); } @@ -2998,7 +3163,7 @@ _Requires_lock_held_(_Global_critical_region_) IO_STATUS_BLOCK FatOpenExistingFcb ( _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, + _In_ PIO_STACK_LOCATION IrpSp, _Inout_ PFILE_OBJECT FileObject, _Inout_ PVCB Vcb, _Inout_ PFCB Fcb, @@ -3007,7 +3172,7 @@ FatOpenExistingFcb ( _In_ ULONG AllocationSize, _In_ PFILE_FULL_EA_INFORMATION EaBuffer, _In_ ULONG EaLength, - _In_ UCHAR FileAttributes, + _In_ USHORT FileAttributes, _In_ ULONG CreateDisposition, _In_ BOOLEAN NoEaKnowledge, _In_ BOOLEAN DeleteOnClose, @@ -3277,7 +3442,7 @@ Return Value: // FILE_COMPLETE_IF_OPLOCKED we don't bother breaking the oplock; // we just return the sharing violation. // - + if ((Iosb.Status == STATUS_SHARING_VIOLATION) && !FlagOn( IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED )) { @@ -3313,7 +3478,7 @@ Return Value: // that there is no oplock to be broken. The sharing violation is // returned in that case. // - + } else { NT_ASSERT( OplockBreakStatus == STATUS_SUCCESS ); @@ -3609,7 +3774,7 @@ Return Value: ClearFlag( *DesiredAccess, AddedAccess ); -#pragma prefast( suppress:28931, "it needs to be there for debug assert" ); +#pragma prefast( suppress:28931, "it needs to be there for debug assert" ); Status = IoCheckShareAccess( *DesiredAccess, ShareAccess, FileObject, @@ -3946,7 +4111,7 @@ IO_STATUS_BLOCK #pragma warning(suppress:6101) // bug in PREFast means the _Success_ annotation is not correctly applied FatOpenExistingDirectory ( _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, + _In_ PIO_STACK_LOCATION IrpSp, _Inout_ PFILE_OBJECT FileObject, _Inout_ PVCB Vcb, _Outptr_result_maybenull_ PDCB *Dcb, @@ -4030,7 +4195,7 @@ Return Value: UNREFERENCED_PARAMETER( OpenRequiringOplock ); #endif UNREFERENCED_PARAMETER( IrpSp ); - + PAGED_CODE(); DebugTrace(+1, Dbg, "FatOpenExistingDirectory...\n", 0); @@ -4125,7 +4290,7 @@ Return Value: if (Iosb.Status != STATUS_SUCCESS) { NT_ASSERT( Iosb.Status != STATUS_PENDING ); - + FatRaiseStatus( IrpContext, Iosb.Status ); } #endif @@ -4138,7 +4303,7 @@ Return Value: ShareAccess, FileObject, &(*Dcb)->ShareAccess ); - + // // Setup the context and section object pointers, and update // our reference counts @@ -4195,14 +4360,14 @@ Return Value: (*Dcb)->UncleanCount -= 1; (*Dcb)->OpenCount -= 1; Vcb->OpenFileCount -= 1; - if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount -= 1; } + if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount -= 1; } } - if (UnwindDcb != NULL) { + if (UnwindDcb != NULL) { if (ARGUMENT_PRESENT( FileObject )) { FileObject->SectionObjectPointer = NULL; } - FatDeleteFcb( IrpContext, &UnwindDcb ); + FatDeleteFcb( IrpContext, &UnwindDcb ); *Dcb = NULL; } if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); } @@ -4231,12 +4396,13 @@ FatOpenExistingFile ( _In_ ULONG LfnByteOffset, _In_ ULONG DirentByteOffset, _In_ PUNICODE_STRING Lfn, + _In_ PUNICODE_STRING OrigLfn, _In_ PACCESS_MASK DesiredAccess, _In_ USHORT ShareAccess, _In_ ULONG AllocationSize, _In_ PFILE_FULL_EA_INFORMATION EaBuffer, _In_ ULONG EaLength, - _In_ UCHAR FileAttributes, + _In_ USHORT FileAttributes, _In_ ULONG CreateDisposition, _In_ BOOLEAN IsPagingFile, _In_ BOOLEAN NoEaKnowledge, @@ -4312,7 +4478,7 @@ Return Value: IO_STATUS_BLOCK Iosb = {0}; ACCESS_MASK AddedAccess = 0; - + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( IrpContext->OriginatingIrp ); // @@ -4441,12 +4607,13 @@ Return Value: DirentByteOffset, Dirent, Lfn, + OrigLfn, IsPagingFile, FALSE ); - + (*Fcb)->Header.ValidDataLength.LowPart = (*Fcb)->Header.FileSize.LowPart; - + // // If this is a paging file, lookup the allocation size so that // the Mcb is always valid @@ -4493,7 +4660,7 @@ Return Value: if (Iosb.Status != STATUS_SUCCESS) { NT_ASSERT( Iosb.Status != STATUS_PENDING ); - + FatRaiseStatus( IrpContext, Iosb.Status ); } #endif @@ -4645,14 +4812,14 @@ Return Value: (KPROCESSOR_MODE)( FlagOn( IrpSp->Flags, SL_FORCE_ACCESS_CHECK ) ? UserMode : IrpContext->OriginatingIrp->RequestorMode ))) { - + SetFlag( Ccb->Flags, CCB_FLAG_MANAGE_VOLUME_ACCESS ); } } } - + } finally { DebugUnwind( FatOpenExistingFile ); @@ -4663,7 +4830,7 @@ Return Value: if (AbnormalTermination()) { - if (CountsIncremented) { + if (CountsIncremented) { (*Fcb)->UncleanCount -= 1; (*Fcb)->OpenCount -= 1; if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) { @@ -4673,14 +4840,14 @@ Return Value: if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount -= 1; } } - if (UnwindFcb != NULL) { + if (UnwindFcb != NULL) { if (ARGUMENT_PRESENT( FileObject )) { FileObject->SectionObjectPointer = NULL; } FatDeleteFcb( IrpContext, &UnwindFcb ); *Fcb = NULL; } - + if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); } } @@ -4709,7 +4876,7 @@ FatCreateNewDirectory ( _In_ USHORT ShareAccess, _In_ PFILE_FULL_EA_INFORMATION EaBuffer, _In_ ULONG EaLength, - _In_ UCHAR FileAttributes, + _In_ USHORT FileAttributes, _In_ BOOLEAN NoEaKnowledge, _In_ BOOLEAN DeleteOnClose, _In_ BOOLEAN OpenRequiringOplock @@ -4792,7 +4959,7 @@ Return Value: BOOLEAN DirentFromPool = FALSE; - + OEM_STRING ShortName; UCHAR ShortNameBuffer[12]; @@ -4943,7 +5110,7 @@ Return Value: AllLowerComponent, AllLowerExtension, CreateLfn ? UnicodeName : NULL, - (UCHAR)(FileAttributes | FAT_DIRENT_ATTR_DIRECTORY), + FileAttributes | FAT_DIRENT_ATTR_DIRECTORY, TRUE, NULL ); @@ -4977,7 +5144,7 @@ Return Value: #if (NTDDI_VERSION >= NTDDI_WIN8) // // The next three FsRtl calls are for oplock work. We deliberately - // do these here so that if either call fails we will be able to + // do these here so that if either call fails we will be able to // clean up without adding a bunch of code to unwind counts, fix // the file object, etc. // @@ -5014,7 +5181,7 @@ Return Value: // off chance this fails with INSUFFICIENT_RESOURCES we do it here // where we can still tolerate a failure. // - + if (Iosb.Status == STATUS_SUCCESS) { Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(ParentDcb), @@ -5024,7 +5191,7 @@ Return Value: NULL, NULL ); } - + // // Get out if any of the oplock calls failed. // @@ -5307,7 +5474,7 @@ Return Value: // Now zap the allocation backing it. // - FatTruncateFileAllocation( IrpContext, Dcb, 0, TRUE ); + FatTruncateFileAllocation( IrpContext, Dcb, 0 ); } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) { @@ -5370,11 +5537,11 @@ Return Value: // we have to remove the Dcb and check if we should remove the parent. // For now we will just leave the parent lying around. // - -#pragma prefast( suppress: 28924, "prefast thinks this test is redundant, but FileObject can be NULL depending on where we raise" ) + +#pragma prefast( suppress: 28924, "prefast thinks this test is redundant, but FileObject can be NULL depending on where we raise" ) if (ARGUMENT_PRESENT( FileObject )) { FileObject->SectionObjectPointer = NULL; - } + } FatDeleteFcb( IrpContext, &Dcb ); } } @@ -5399,7 +5566,7 @@ _Requires_lock_held_(_Global_critical_region_) IO_STATUS_BLOCK FatCreateNewFile ( _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, + _In_ PIO_STACK_LOCATION IrpSp, _Inout_ PFILE_OBJECT FileObject, _Inout_ PVCB Vcb, _Inout_ PDCB ParentDcb, @@ -5410,7 +5577,7 @@ FatCreateNewFile ( _In_ ULONG AllocationSize, _In_ PFILE_FULL_EA_INFORMATION EaBuffer, _In_ ULONG EaLength, - _In_ UCHAR FileAttributes, + _In_ USHORT FileAttributes, _In_ PUNICODE_STRING LfnBuffer, _In_ BOOLEAN IsPagingFile, _In_ BOOLEAN NoEaKnowledge, @@ -5531,7 +5698,7 @@ Return Value: PCCB UnwindCcb = NULL; ULONG LocalAbnormalTermination = FALSE; - + #if (NTDDI_VERSION < NTDDI_WIN7) UNREFERENCED_PARAMETER( OpenRequiringOplock ); #endif @@ -5731,7 +5898,7 @@ Return Value: AllLowerComponent, AllLowerExtension, CreateLfn ? RealUnicodeName : NULL, - (UCHAR)(FileAttributes | FILE_ATTRIBUTE_ARCHIVE), + (FileAttributes | FILE_ATTRIBUTE_ARCHIVE), TRUE, (HaveTunneledInformation ? &TunneledCreationTime : NULL) ); @@ -5763,6 +5930,7 @@ Return Value: ShortDirentByteOffset, ShortDirent, CreateLfn ? RealUnicodeName : NULL, + CreateLfn ? RealUnicodeName : NULL, IsPagingFile, FALSE ); UnwindDirent = NULL; @@ -5770,7 +5938,7 @@ Return Value: #if (NTDDI_VERSION >= NTDDI_WIN7) // // The next three FsRtl calls are for oplock work. We deliberately - // do these here so that if either call fails we will be able to + // do these here so that if either call fails we will be able to // clean up without adding a bunch of code to unwind counts, fix // the file object, etc. // @@ -5809,7 +5977,7 @@ Return Value: // off chance this fails with INSUFFICIENT_RESOURCES we do it here // where we can still tolerate a failure. // - + if (Iosb.Status == STATUS_SUCCESS) { Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(ParentDcb), @@ -5841,12 +6009,15 @@ Return Value: SetFlag( Fcb->FcbState, FCB_STATE_TEMPORARY ); } - + // // Add some initial file allocation // + FatAddFileAllocation( IrpContext, Fcb, FileObject, AllocationSize ); + + UnwindAllocation = TRUE; Fcb->FcbState |= FCB_STATE_TRUNCATE_ON_CLOSE; @@ -5880,7 +6051,7 @@ Return Value: if (Fcb->FullFileName.Buffer == NULL) { FatSetFullNameInFcb( IrpContext, Fcb, RealUnicodeName ); } - + // // Setup the context and section object pointers, and update // our reference counts @@ -5965,13 +6136,13 @@ Return Value: (KPROCESSOR_MODE)( FlagOn( IrpSp->Flags, SL_FORCE_ACCESS_CHECK ) ? UserMode : IrpContext->OriginatingIrp->RequestorMode ))) { - + SetFlag( UnwindCcb->Flags, CCB_FLAG_MANAGE_VOLUME_ACCESS ); } } - + } finally { DebugUnwind( FatCreateNewFile ); @@ -6079,7 +6250,7 @@ Return Value: if (LocalAbnormalTermination) { if (UnwindAllocation) { - FatTruncateFileAllocation( IrpContext, Fcb, 0, TRUE ); + FatTruncateFileAllocation( IrpContext, Fcb, 0 ); } } @@ -6096,11 +6267,11 @@ Return Value: } finally { if (LocalAbnormalTermination) { - if (UnwindFcb != NULL) { + if (UnwindFcb != NULL) { if (ARGUMENT_PRESENT( FileObject )) { FileObject->SectionObjectPointer = NULL; } - FatDeleteFcb( IrpContext, &UnwindFcb ); + FatDeleteFcb( IrpContext, &UnwindFcb ); } if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); } } @@ -6140,7 +6311,7 @@ FatSupersedeOrOverwriteFile ( _In_ ULONG AllocationSize, _In_ PFILE_FULL_EA_INFORMATION EaBuffer, _In_ ULONG EaLength, - _In_ UCHAR FileAttributes, + _In_ USHORT FileAttributes, _In_ ULONG CreateDisposition, _In_ BOOLEAN NoEaKnowledge ) @@ -6190,6 +6361,8 @@ Return Value: PCCB Ccb; ULONG NotifyFilter; + ULONG HeaderSize = 0; + LARGE_INTEGER AllocSize = {0}; // // The following variables are for abnormal termination @@ -6276,7 +6449,7 @@ Return Value: // off chance this fails with INSUFFICIENT_RESOURCES we do it here // where we can still tolerate a failure. // - + Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(Fcb->ParentDcb), IrpContext->OriginatingIrp, OPLOCK_FLAG_PARENT_OBJECT, @@ -6303,6 +6476,20 @@ Return Value: Fcb->Header.ValidDataLength.LowPart = 0; Fcb->ValidDataToDisk = 0; + + // + // Validate that the allocation size will work. + // + + AllocSize.QuadPart = AllocationSize; + if (!FatIsIoRangeValid( Fcb->Vcb, AllocSize, 0 )) { + + DebugTrace(-1, Dbg, "Illegal allocation size\n", 0); + + FatRaiseStatus( IrpContext, STATUS_DISK_FULL ); + } + + // // Tell the cache manager the size went to zero // This call is unconditional, because MM always wants to know. @@ -6311,12 +6498,12 @@ Return Value: CcSetFileSizes( FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize ); - FatTruncateFileAllocation( IrpContext, Fcb, AllocationSize, FALSE ); + FatTruncateFileAllocation( IrpContext, Fcb, AllocationSize+HeaderSize ); ExReleaseResourceLite( Fcb->Header.PagingIoResource ); ReleasePaging = FALSE; - FatAddFileAllocation( IrpContext, Fcb, FileObject, AllocationSize ); + FatAddFileAllocation( IrpContext, Fcb, FileObject, AllocationSize+HeaderSize ); Fcb->FcbState |= FCB_STATE_TRUNCATE_ON_CLOSE; @@ -6346,11 +6533,11 @@ Return Value: if (CreateDisposition == FILE_SUPERSEDE) { - Dirent->Attributes = FileAttributes; + Dirent->Attributes = (UCHAR)FileAttributes; } else { - Dirent->Attributes |= FileAttributes; + Dirent->Attributes |= (UCHAR)FileAttributes; } Fcb->DirentFatFlags = Dirent->Attributes; @@ -6661,7 +6848,7 @@ Return Value: If the accessor has access to the file, STATUS_SUCCESS is returned. Otherwise, STATUS_SHARING_VIOLATION is returned. - + --*/ { @@ -6724,4 +6911,3 @@ FatCallSelfCompletionRoutine ( return STATUS_MORE_PROCESSING_REQUIRED; } - |
