📄 create.c
字号:
Iosb = FatOpenRootDcb( IrpContext,
FileObject,
Vcb,
DesiredAccess,
ShareAccess,
CreateDisposition );
Irp->IoStatus.Information = Iosb.Information;
try_return( Iosb.Status );
}
//
// Nope, we will be opening relative to the root directory.
//
ParentDcb = Vcb->RootDcb;
}
//
// FatCommonCreate(): trailing backslash check
//
if ((FileName.Length != 0) &&
(FileName.Buffer[FileName.Length/sizeof(WCHAR)-1] == L'\\')) {
FileName.Length -= sizeof(WCHAR);
TrailingBackslash = TRUE;
} else {
TrailingBackslash = FALSE;
}
//
// Check for max path. We might want to tighten this down to DOS MAX_PATH
// for maximal interchange with non-NT platforms, but for now defer to the
// possibility of something depending on it.
//
if (ParentDcb->FullFileName.Buffer == NULL) {
FatSetFullFileNameInFcb( IrpContext, ParentDcb );
}
if ((USHORT) (ParentDcb->FullFileName.Length + sizeof(WCHAR) + FileName.Length) <= FileName.Length) {
try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
}
//
// We loop here until we land on an Fcb that is in a good
// condition. This way we can reopen files that have stale handles
// to files of the same name but are now different.
//
while ( TRUE ) {
Fcb = ParentDcb;
RemainingPart = FileName;
//
// Now walk down the Dcb tree looking for the longest prefix.
// This one exit condition in the while() is to handle a
// special case condition (relative NULL name open), the main
// exit conditions are at the bottom of the loop.
//
while (RemainingPart.Length != 0) {
PFCB NextFcb;
FsRtlDissectName( RemainingPart,
&FinalName,
&NextRemainingPart );
//
// If RemainingPart starts with a backslash the name is
// invalid.
// Check for no more than 255 characters in FinalName
//
if (((NextRemainingPart.Length != 0) && (NextRemainingPart.Buffer[0] == L'\\')) ||
(FinalName.Length > 255*sizeof(WCHAR))) {
try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
}
//
// Now, try to convert this one component into Oem and search
// the splay tree. If it works then that's great, otherwise
// we have to try with the UNICODE name instead.
//
FatEnsureStringBufferEnough( &OemFinalName,
FinalName.Length);
Status = RtlUpcaseUnicodeStringToCountedOemString( &OemFinalName, &FinalName, FALSE );
if (NT_SUCCESS(Status)) {
NextFcb = FatFindFcb( IrpContext,
&Fcb->Specific.Dcb.RootOemNode,
(PSTRING)&OemFinalName,
&FileNameOpenedDos );
} else {
NextFcb = NULL;
OemFinalName.Length = 0;
if (Status != STATUS_UNMAPPABLE_CHARACTER) {
try_return( Iosb.Status = Status );
}
}
//
// If we didn't find anything searching the Oem space, we
// have to try the Unicode space. To save cycles in the
// common case that this tree is empty, we do a quick check
// here.
//
if ((NextFcb == NULL) && Fcb->Specific.Dcb.RootUnicodeNode) {
//
// First downcase, then upcase the string, because this
// is what happens when putting names into the tree (see
// strucsup.c, FatConstructNamesInFcb()).
//
FatEnsureStringBufferEnough( &UpcasedFinalName,
FinalName.Length);
Status = RtlDowncaseUnicodeString(&UpcasedFinalName, &FinalName, FALSE );
ASSERT( NT_SUCCESS( Status ));
Status = RtlUpcaseUnicodeString( &UpcasedFinalName, &UpcasedFinalName, FALSE );
ASSERT( NT_SUCCESS( Status ));
NextFcb = FatFindFcb( IrpContext,
&Fcb->Specific.Dcb.RootUnicodeNode,
(PSTRING)&UpcasedFinalName,
&FileNameOpenedDos );
}
//
// If we got back an Fcb then we consumed the FinalName
// legitimately, so the remaining name is now RemainingPart.
//
if (NextFcb != NULL) {
Fcb = NextFcb;
RemainingPart = NextRemainingPart;
}
if ((NextFcb == NULL) ||
(NodeType(NextFcb) == FAT_NTC_FCB) ||
(NextRemainingPart.Length == 0)) {
break;
}
}
//
// Remaining name cannot start with a backslash
//
if (RemainingPart.Length && (RemainingPart.Buffer[0] == L'\\')) {
RemainingPart.Length -= sizeof(WCHAR);
RemainingPart.Buffer += 1;
}
//
// Now verify that everybody up to the longest found prefix is valid.
//
try {
FatVerifyFcb( IrpContext, Fcb );
} except( (GetExceptionCode() == STATUS_FILE_INVALID) ?
EXCEPTION_EXECUTE_HANDLER :
EXCEPTION_CONTINUE_SEARCH ) {
FatResetExceptionState( IrpContext );
}
if ( Fcb->FcbCondition == FcbGood ) {
//
// If we are trying to open a paging file and have happened
// upon the DelayedCloseFcb, make it go away, and try again.
//
if (IsPagingFile && FirstLoop &&
(NodeType(Fcb) == FAT_NTC_FCB) &&
(!IsListEmpty( &FatData.AsyncCloseList ) ||
!IsListEmpty( &FatData.DelayedCloseList ))) {
FatFspClose(Vcb);
FirstLoop = FALSE;
continue;
} else {
break;
}
} else {
FatRemoveNames( IrpContext, Fcb );
}
}
ASSERT( Fcb->FcbCondition == FcbGood );
//
// If there is already an Fcb for a paging file open and
// it was not already opened as a paging file, we cannot
// continue as it is too difficult to move a live Fcb to
// non-paged pool.
//
if (IsPagingFile) {
if (NodeType(Fcb) == FAT_NTC_FCB &&
!FlagOn( Fcb->FcbState, FCB_STATE_PAGING_FILE )) {
try_return( Iosb.Status = STATUS_SHARING_VIOLATION );
}
//
// Check for a system file.
//
} else if (FlagOn( Fcb->FcbState, FCB_STATE_SYSTEM_FILE )) {
try_return( Iosb.Status = STATUS_ACCESS_DENIED );
}
//
// If the longest prefix is pending delete (either the file or
// some higher level directory), we cannot continue.
//
if (FlagOn( Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE )) {
try_return( Iosb.Status = STATUS_DELETE_PENDING );
}
//
// Now that we've found the longest matching prefix we'll
// check if there isn't any remaining part because that means
// we've located an existing fcb/dcb to open and we can do the open
// without going to the disk
//
if (RemainingPart.Length == 0) {
//
// First check if the user wanted to open the target directory
// and if so then call the subroutine to finish the open.
//
if (OpenTargetDirectory) {
CollectCreateHitStatistics(Vcb);
Iosb = FatOpenTargetDirectory( IrpContext,
FileObject,
Fcb->ParentDcb,
DesiredAccess,
ShareAccess,
TRUE );
Irp->IoStatus.Information = Iosb.Information;
try_return( Iosb.Status );
}
//
// We can open an existing fcb/dcb, now we only need to case
// on which type to open.
//
if (NodeType(Fcb) == FAT_NTC_DCB || NodeType(Fcb) == FAT_NTC_ROOT_DCB) {
//
// This is a directory we're opening up so check if
// we were not to open a directory
//
if (NonDirectoryFile) {
DebugTrace(0, Dbg, "Cannot open directory as a file\n", 0);
try_return( Iosb.Status = STATUS_FILE_IS_A_DIRECTORY );
}
DebugTrace(0, Dbg, "Open existing dcb, Dcb = %08lx\n", Fcb);
CollectCreateHitStatistics(Vcb);
Iosb = FatOpenExistingDcb( IrpContext,
FileObject,
Vcb,
(PDCB)Fcb,
DesiredAccess,
ShareAccess,
CreateDisposition,
NoEaKnowledge,
DeleteOnClose );
Irp->IoStatus.Information = Iosb.Information;
try_return( Iosb.Status );
}
//
// Check if we're trying to open an existing Fcb and that
// the user didn't want to open a directory. Note that this
// call might actually come back with status_pending because
// the user wanted to supersede or overwrite the file and we
// cannot block. If it is pending then we do not complete the
// request, and we fall through the bottom to the code that
// dispatches the request to the fsp.
//
if (NodeType(Fcb) == FAT_NTC_FCB) {
//
// Check if we were only to open a directory
//
if (OpenDirectory) {
DebugTrace(0, Dbg, "Cannot open file as directory\n", 0);
try_return( Iosb.Status = STATUS_NOT_A_DIRECTORY );
}
DebugTrace(0, Dbg, "Open existing fcb, Fcb = %08lx\n", Fcb);
if ( TrailingBackslash ) {
try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
}
CollectCreateHitStatistics(Vcb);
Iosb = FatOpenExistingFcb( IrpContext,
FileObject,
Vcb,
Fcb,
DesiredAccess,
ShareAccess,
AllocationSize,
EaBuffer,
EaLength,
FileAttributes,
CreateDisposition,
NoEaKnowledge,
DeleteOnClose,
FileNameOpenedDos,
&OplockPostIrp );
if (Iosb.Status != STATUS_PENDING) {
//
// 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;
} else {
DebugTrace(0, Dbg, "Enqueue Irp to FSP\n", 0);
PostIrp = TRUE;
}
try_return( Iosb.Status );
}
//
// Not and Fcb or a Dcb so we bug check
//
FatBugCheck( NodeType(Fcb), (ULONG_PTR) Fcb, 0 );
}
//
// There is more in the name to parse than we have in existing
// fcbs/dcbs. So now make sure that fcb we got for the largest
// matching prefix is really a dcb otherwise we can't go any
// further
//
if ((NodeType(Fcb) != FAT_NTC_DCB) && (NodeType(Fcb) != FAT_NTC_ROOT_DCB)) {
DebugTrace(0, Dbg, "Cannot open file as subdirectory, Fcb = %08lx\n", Fcb);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -