📄 create.c
字号:
Irp->IoStatus.Information = Iosb.Information;
try_return( Iosb.Status );
}
DebugTrace(0, Dbg, "Create new file\n", 0);
if ( TrailingBackslash ) {
try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
}
//
// If this media is write protected, don't even try the create.
//
if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
//
// Set the real device for the pop-up info, and set the verify
// bit in the device object, so that we will force a verify
// in case the user put the correct media back in.
//
IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
Vcb->Vpb->RealDevice );
SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
FatRaiseStatus( IrpContext, STATUS_MEDIA_WRITE_PROTECTED );
}
Iosb = FatCreateNewFile( IrpContext,
FileObject,
Vcb,
ParentDcb,
&OemFinalName,
&FinalName,
DesiredAccess,
ShareAccess,
AllocationSize,
EaBuffer,
EaLength,
FileAttributes,
&Lfn,
IsPagingFile,
NoEaKnowledge,
DeleteOnClose,
TemporaryFile );
//
// Check if we need to set the cache support flag in
// the file object
//
if (NT_SUCCESS(Iosb.Status) && !NoIntermediateBuffering) {
FileObject->Flags |= FO_CACHE_SUPPORTED;
}
Irp->IoStatus.Information = Iosb.Information;
try_exit: NOTHING;
//
// This is a Beta Fix. Do this at a better place later.
//
if (NT_SUCCESS(Iosb.Status) && !OpenTargetDirectory) {
PFCB LocalFcb;
//
// If there is an Fcb/Dcb, set the long file name.
//
LocalFcb = FileObject->FsContext;
if (LocalFcb &&
((NodeType(LocalFcb) == FAT_NTC_FCB) ||
(NodeType(LocalFcb) == FAT_NTC_DCB)) &&
(LocalFcb->FullFileName.Buffer == NULL)) {
FatSetFullNameInFcb( IrpContext, LocalFcb, &FinalName );
}
}
} finally {
DebugUnwind( FatCommonCreate );
//
// There used to be a test here - the ASSERT replaces it. We will
// never have begun enumerating directories if we post the IRP for
// oplock reasons.
//
ASSERT( !OplockPostIrp || DirentBcb == NULL );
FatUnpinBcb( IrpContext, DirentBcb );
//
// If we are in an error path, check for any created subdir Dcbs that
// have to be unwound. Don't whack the root directory.
//
// Note this will leave a branch of Dcbs dangling if the directory file
// had not been built on the leaf (case: opening path which has an
// element containing an invalid character name).
//
if ((AbnormalTermination() || !NT_SUCCESS(Iosb.Status)) &&
(FinalDcb != NULL) &&
(NodeType(FinalDcb) == FAT_NTC_DCB) &&
IsListEmpty(&FinalDcb->Specific.Dcb.ParentDcbQueue) &&
(FinalDcb->OpenCount == 0) &&
(FinalDcb->Specific.Dcb.DirectoryFile != NULL)) {
PFILE_OBJECT DirectoryFileObject;
ULONG SavedFlags;
//
// Before doing the uninitialize, we have to unpin anything
// that has been repinned, but disable writethrough first. We
// disable raise from unpin-repin since we're already failing.
//
SavedFlags = IrpContext->Flags;
SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_RAISE |
IRP_CONTEXT_FLAG_DISABLE_WRITE_THROUGH );
FatUnpinRepinnedBcbs( IrpContext );
DirectoryFileObject = FinalDcb->Specific.Dcb.DirectoryFile;
FinalDcb->Specific.Dcb.DirectoryFile = NULL;
CcUninitializeCacheMap( DirectoryFileObject, NULL, NULL );
ObDereferenceObject( DirectoryFileObject );
IrpContext->Flags = SavedFlags;
}
if (AbnormalTermination()) {
FatReleaseVcb( IrpContext, Vcb );
}
//
// Free up any string buffers we allocated
//
FatFreeStringBuffer( &OemFinalName);
FatFreeStringBuffer( &UpcasedFinalName);
FatFreeStringBuffer( &Lfn);
}
//
// The following code is only executed if we are exiting the
// procedure through a normal termination. We complete the request
// and if for any reason that bombs out then we need to unreference
// and possibly delete the fcb and ccb.
//
try {
if (PostIrp) {
//
// If the Irp hasn't already been posted, do it now.
//
if (!OplockPostIrp) {
Iosb.Status = FatFsdPostRequest( IrpContext, Irp );
}
} else {
FatUnpinRepinnedBcbs( IrpContext );
}
} finally {
DebugUnwind( FatCommonCreate-in-FatCompleteRequest );
if (AbnormalTermination()) {
PVCB LocalVcb;
PFCB LocalFcb;
PCCB LocalCcb2;
PFILE_OBJECT DirectoryFileObject;
//
// Unwind all of our counts. Note that if a write failed, then
// the volume has been marked for verify, and all volume
// structures will be cleaned up automatically.
//
(VOID) FatDecodeFileObject( FileObject, &LocalVcb, &LocalFcb, &LocalCcb2 );
LocalFcb->UncleanCount -= 1;
LocalFcb->OpenCount -= 1;
LocalVcb->OpenFileCount -= 1;
if (IsFileObjectReadOnly(FileObject)) { LocalVcb->ReadOnlyCount -= 1; }
//
// If we leafed out on a new Fcb we should get rid of it at this point.
//
// Since the object isn't being opened, we have to do all of the teardown
// here. Our close path will not occur for this fileobject. Note this
// will leave a branch of Dcbs dangling since we do it by hand and don't
// chase to the root.
//
if (LocalFcb->OpenCount == 0 &&
(NodeType( LocalFcb ) == FAT_NTC_FCB ||
IsListEmpty(&LocalFcb->Specific.Dcb.ParentDcbQueue))) {
ASSERT( NodeType( LocalFcb ) != FAT_NTC_ROOT_DCB );
if ( (NodeType( LocalFcb ) == FAT_NTC_DCB) &&
(LocalFcb->Specific.Dcb.DirectoryFile != NULL) ) {
FatSyncUninitializeCacheMap( IrpContext,
LocalFcb->Specific.Dcb.DirectoryFile );
DirectoryFileObject = LocalFcb->Specific.Dcb.DirectoryFile;
LocalFcb->Specific.Dcb.DirectoryFile = NULL;
ObDereferenceObject( DirectoryFileObject );
} else {
FatDeleteFcb( IrpContext, &LocalFcb );
}
}
FatDeleteCcb( IrpContext, &LocalCcb2 );
FatReleaseVcb( IrpContext, LocalVcb );
} else {
FatReleaseVcb( IrpContext, Vcb );
if ( !PostIrp ) {
//
// If this request is successful and the file was opened
// for FILE_EXECUTE access, then set the FileObject bit.
//
ASSERT( IrpSp->Parameters.Create.SecurityContext != NULL );
if (FlagOn( *DesiredAccess, FILE_EXECUTE )) {
SetFlag( FileObject->Flags, FO_FILE_FAST_IO_READ );
}
//
// Lock volume in drive if we opened a paging file, allocating a
// reserve MDL to guarantee paging file operations can always
// go forward.
//
if (IsPagingFile && NT_SUCCESS(Iosb.Status)) {
if (!FatReserveMdl) {
PMDL ReserveMdl = IoAllocateMdl( NULL,
FAT_RESERVE_MDL_SIZE * PAGE_SIZE,
TRUE,
FALSE,
NULL );
//
// Stash the MDL, and if it turned out there was already one there
// just free what we got.
//
InterlockedCompareExchangePointer( &FatReserveMdl, ReserveMdl, NULL );
if (FatReserveMdl != ReserveMdl) {
IoFreeMdl( ReserveMdl );
}
}
SetFlag(Vcb->VcbState, VCB_STATE_FLAG_BOOT_OR_PAGING_FILE);
if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA)) {
FatToggleMediaEjectDisable( IrpContext, Vcb, TRUE );
}
}
//
// Complete the request.
//
FatCompleteRequest( IrpContext, Irp, Iosb.Status );
}
}
DebugTrace(-1, Dbg, "FatCommonCreate -> %08lx\n", Iosb.Status);
}
CollectCreateStatistics(Vcb, Iosb.Status);
return Iosb.Status;
}
//
// Internal support routine
//
IO_STATUS_BLOCK
FatOpenVolume (
IN PIRP_CONTEXT IrpContext,
IN PFILE_OBJECT FileObject,
IN PVCB Vcb,
IN PACCESS_MASK DesiredAccess,
IN USHORT ShareAccess,
IN ULONG CreateDisposition
)
/*++
Routine Description:
This routine opens the specified volume for DASD access
Arguments:
FileObject - Supplies the File object
Vcb - Supplies the Vcb denoting the volume being opened
DesiredAccess - Supplies the desired access of the caller
ShareAccess - Supplies the share access of the caller
CreateDisposition - Supplies the create disposition for this operation
Return Value:
IO_STATUS_BLOCK - Returns the completion status for the operation
--*/
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp;
IO_STATUS_BLOCK Iosb = {0,0};
BOOLEAN CleanedVolume = FALSE;
//
// The following variables are for abnormal termination
//
BOOLEAN UnwindShareAccess = FALSE;
PCCB UnwindCcb = NULL;
BOOLEAN UnwindCounts = FALSE;
BOOLEAN UnwindVolumeLock = FALSE;
DebugTrace(+1, Dbg, "FatOpenVolume...\n", 0);
try {
//
// Check for proper desired access and rights
//
if ((CreateDisposition != FILE_OPEN) &&
(CreateDisposition != FILE_OPEN_IF)) {
try_return( Iosb.Status = STATUS_ACCESS_DENIED );
}
//
// If the user does not want to share write or delete then we will try
// and take out a lock on the volume.
//
if (!FlagOn(ShareAccess, FILE_SHARE_WRITE) &&
!FlagOn(ShareAccess, FILE_SHARE_DELETE)) {
//
// Do a quick check here for handles on exclusive open.
//
if (!FlagOn(ShareAccess, FILE_SHARE_READ) &&
!FatIsHandleCountZero( IrpContext, Vcb )) {
try_return( Iosb.Status = STATUS_SHARING_VIOLATION );
}
//
// Force Mm to get rid of its referenced file objects.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -