📄 create.c
字号:
try_return( Iosb.Status = STATUS_OBJECT_PATH_NOT_FOUND );
}
//
// Otherwise we continue on processing the Irp and allowing ourselves
// to block for I/O as necessary. Find/create additional dcb's for
// the one we're trying to open. We loop until either remaining part
// is empty or we get a bad filename. When we exit FinalName is
// the last name in the string we're after, and ParentDcb is the
// parent directory that will contain the opened/created
// file/directory.
//
// Make sure the rest of the name is valid in at least the LFN
// character set (which just happens to be that of HPFS).
//
// If we are not in ChicagoMode, use FAT symantics.
//
ParentDcb = Fcb;
FirstLoop = TRUE;
while (TRUE) {
//
// We do one little optimization here on the first itterration of
// the loop since we know that we have already tried to convert
// FinalOemName from the original UNICODE.
//
if (FirstLoop) {
FirstLoop = FALSE;
RemainingPart = NextRemainingPart;
Status = OemFinalName.Length ? STATUS_SUCCESS : STATUS_UNMAPPABLE_CHARACTER;
} else {
//
// Dissect the remaining part.
//
DebugTrace(0, Dbg, "Dissecting the name %Z\n", &RemainingPart);
FsRtlDissectName( RemainingPart,
&FinalName,
&RemainingPart );
//
// If RemainingPart starts with a backslash the name is
// invalid.
// Check for no more than 255 characters in FinalName
//
if (((RemainingPart.Length != 0) && (RemainingPart.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. 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)) {
//
// We'll start by trying to locate the dirent for the name. Note
// that we already know that there isn't an Fcb/Dcb for the file
// otherwise we would have found it when we did our prefix lookup.
//
if (FatIsNameShortOemValid( IrpContext, OemFinalName, FALSE, FALSE, FALSE )) {
FatStringTo8dot3( IrpContext,
OemFinalName,
&LocalCcb.OemQueryTemplate.Constant );
LocalCcb.Flags = 0;
} else {
LocalCcb.Flags = CCB_FLAG_SKIP_SHORT_NAME_COMPARE;
}
} else {
LocalCcb.Flags = CCB_FLAG_SKIP_SHORT_NAME_COMPARE;
if (Status != STATUS_UNMAPPABLE_CHARACTER) {
try_return( Iosb.Status = Status );
}
}
//
// Now we know a lot about the final name, so do legal name
// checking here.
//
if (FatData.ChicagoMode) {
if (!FatIsNameLongUnicodeValid( IrpContext, &FinalName, FALSE, FALSE, FALSE )) {
try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
}
} else {
if (FlagOn(LocalCcb.Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE)) {
try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
}
}
DebugTrace(0, Dbg, "FinalName is %Z\n", &FinalName);
DebugTrace(0, Dbg, "RemainingPart is %Z\n", &RemainingPart);
FatEnsureStringBufferEnough( &UpcasedFinalName,
FinalName.Length);
if (!NT_SUCCESS(Status = RtlUpcaseUnicodeString( &UpcasedFinalName, &FinalName, FALSE))) {
try_return( Iosb.Status = Status );
}
LocalCcb.UnicodeQueryTemplate = UpcasedFinalName;
LocalCcb.ContainsWildCards = FALSE;
Lfn.Length = 0;
FatLocateDirent( IrpContext,
ParentDcb,
&LocalCcb,
0,
&Dirent,
&DirentBcb,
&DirentByteOffset,
&FileNameOpenedDos,
&Lfn);
//
// Remember we read this Dcb for error recovery.
//
FinalDcb = ParentDcb;
//
// If the remaining part is now empty then this is the last name
// in the string and the one we want to open
//
if (RemainingPart.Length == 0) { break; }
//
// We didn't find a dirent, bail.
//
if (Dirent == NULL) {
Iosb.Status = STATUS_OBJECT_PATH_NOT_FOUND;
try_return( Iosb.Status );
}
//
// We now have a dirent, make sure it is a directory
//
if (!FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY )) {
Iosb.Status = STATUS_OBJECT_PATH_NOT_FOUND;
try_return( Iosb.Status );
}
//
// Compute the LfnByteOffset.
//
LfnByteOffset = DirentByteOffset -
FAT_LFN_DIRENTS_NEEDED(&Lfn) * sizeof(LFN_DIRENT);
//
// Create a dcb for the new directory
//
ParentDcb = FatCreateDcb( IrpContext,
Vcb,
ParentDcb,
LfnByteOffset,
DirentByteOffset,
Dirent,
&Lfn );
//
// Remember we created this Dcb for error recovery.
//
FinalDcb = ParentDcb;
FatSetFullNameInFcb( IrpContext, ParentDcb, &FinalName );
}
//
// First check if the user wanted to open the target directory
// and if so then call the subroutine to finish the open.
//
if (OpenTargetDirectory) {
Iosb = FatOpenTargetDirectory( IrpContext,
FileObject,
ParentDcb,
DesiredAccess,
ShareAccess,
Dirent ? TRUE : FALSE);
Irp->IoStatus.Information = Iosb.Information;
try_return( Iosb.Status );
}
if (Dirent != NULL) {
//
// Compute the LfnByteOffset.
//
LfnByteOffset = DirentByteOffset -
FAT_LFN_DIRENTS_NEEDED(&Lfn) * sizeof(LFN_DIRENT);
//
// We were able to locate an existing dirent entry, so now
// see if it is a directory that we're trying to open.
//
if (FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY )) {
//
// Make sure its okay 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 directory\n", 0);
Iosb = FatOpenExistingDirectory( IrpContext,
FileObject,
Vcb,
ParentDcb,
Dirent,
LfnByteOffset,
DirentByteOffset,
&Lfn,
DesiredAccess,
ShareAccess,
CreateDisposition,
NoEaKnowledge,
DeleteOnClose );
Irp->IoStatus.Information = Iosb.Information;
try_return( Iosb.Status );
}
//
// Otherwise we're trying to open and existing file, and we
// need to check if the user only wanted 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 file\n", 0);
if ( TrailingBackslash ) {
try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
}
Iosb = FatOpenExistingFile( IrpContext,
FileObject,
Vcb,
ParentDcb,
Dirent,
LfnByteOffset,
DirentByteOffset,
&Lfn,
DesiredAccess,
ShareAccess,
AllocationSize,
EaBuffer,
EaLength,
FileAttributes,
CreateDisposition,
IsPagingFile,
NoEaKnowledge,
DeleteOnClose,
FileNameOpenedDos );
//
// 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_return( Iosb.Status );
}
//
// We can't locate a dirent so this is a new file.
//
//
// Now check to see if we wanted to only open an existing file.
// And then case on whether we wanted to create a file or a directory.
//
if ((CreateDisposition == FILE_OPEN) ||
(CreateDisposition == FILE_OVERWRITE)) {
DebugTrace( 0, Dbg, "Cannot open nonexisting file\n", 0);
try_return( Iosb.Status = STATUS_OBJECT_NAME_NOT_FOUND );
}
//
// Skip a few cycles later if we know now that the Oem name is not
// valid 8.3.
//
if (FlagOn(LocalCcb.Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE)) {
OemFinalName.Length = 0;
}
//
// Determine the granted access for this operation now.
//
if (!NT_SUCCESS( Iosb.Status = FatCheckSystemSecurityAccess( IrpContext ))) {
try_return( Iosb );
}
if (CreateDirectory) {
DebugTrace(0, Dbg, "Create new directory\n", 0);
//
// 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 );
}
//
// Don't allow people to create directories with the
// temporary bit set.
//
if (TemporaryFile) {
try_return( Iosb.Status = STATUS_INVALID_PARAMETER );
}
Iosb = FatCreateNewDirectory( IrpContext,
FileObject,
Vcb,
ParentDcb,
&OemFinalName,
&FinalName,
DesiredAccess,
ShareAccess,
EaBuffer,
EaLength,
FileAttributes,
NoEaKnowledge,
DeleteOnClose );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -