📄 create.c
字号:
if (VolumeOpen) {
//
// The only create disposition we allow is OPEN.
//
if ((CreateDisposition != FILE_OPEN) &&
(CreateDisposition != FILE_OPEN_IF)) {
try_return( Status = STATUS_ACCESS_DENIED );
}
//
// If they wanted to open a directory, surprise.
//
if (FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) {
try_return( Status = STATUS_NOT_A_DIRECTORY );
}
//
// Acquire the Fcb first.
//
CurrentFcb = Vcb->VolumeDasdFcb;
CdAcquireFcbExclusive( IrpContext, CurrentFcb, FALSE );
try_return( Status = CdOpenExistingFcb( IrpContext,
IrpSp,
&CurrentFcb,
UserVolumeOpen,
FALSE,
NULL ));
}
//
// At this point CurrentFcb points to the deepest Fcb for this open
// in the tree. Let's acquire this Fcb to keep it from being deleted
// beneath us.
//
CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE );
CurrentFcb = NextFcb;
//
// Do a prefix search if there is more of the name to parse.
//
if (RemainingName.FileName.Length != 0) {
//
// Do the prefix search to find the longest matching name.
//
CdFindPrefix( IrpContext,
&CurrentFcb,
&RemainingName.FileName,
IgnoreCase );
}
//
// If the remaining name length is zero then we have found our
// target.
//
if (RemainingName.FileName.Length == 0) {
//
// If this is a file so verify the user didn't want to open
// a directory.
//
if (SafeNodeType( CurrentFcb ) == CDFS_NTC_FCB_DATA) {
if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ) ||
FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) {
try_return( Status = STATUS_NOT_A_DIRECTORY );
}
//
// The only create disposition we allow is OPEN.
//
if ((CreateDisposition != FILE_OPEN) &&
(CreateDisposition != FILE_OPEN_IF)) {
try_return( Status = STATUS_ACCESS_DENIED );
}
try_return( Status = CdOpenExistingFcb( IrpContext,
IrpSp,
&CurrentFcb,
UserFileOpen,
IgnoreCase,
RelatedCcb ));
//
// This is a directory. Verify the user didn't want to open
// as a file.
//
} else if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) {
try_return( Status = STATUS_FILE_IS_A_DIRECTORY );
//
// Open the file as a directory.
//
} else {
//
// The only create disposition we allow is OPEN.
//
if ((CreateDisposition != FILE_OPEN) &&
(CreateDisposition != FILE_OPEN_IF)) {
try_return( Status = STATUS_ACCESS_DENIED );
}
try_return( Status = CdOpenExistingFcb( IrpContext,
IrpSp,
&CurrentFcb,
UserDirectoryOpen,
IgnoreCase,
RelatedCcb ));
}
}
//
// We have more work to do. We have a starting Fcb which we own shared.
// We also have the remaining name to parse. Walk through the name
// component by component looking for the full name.
//
//
// Our starting Fcb better be a directory.
//
if (!FlagOn( CurrentFcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
try_return( Status = STATUS_OBJECT_PATH_NOT_FOUND );
}
//
// If we can't wait then post this request.
//
if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
CdRaiseStatus( IrpContext, STATUS_CANT_WAIT );
}
//
// Make sure the final name has no version string.
//
FinalName.VersionString.Length = 0;
while (TRUE) {
ShortNameMatch = FALSE;
//
// Split off the next component from the name.
//
CdDissectName( IrpContext,
&RemainingName.FileName,
&FinalName.FileName );
//
// Go ahead and look this entry up in the path table.
//
CdInitializeCompoundPathEntry( IrpContext, &CompoundPathEntry );
CleanupCompoundPathEntry = TRUE;
FoundEntry = CdFindPathEntry( IrpContext,
CurrentFcb,
&FinalName,
IgnoreCase,
&CompoundPathEntry );
//
// If we didn't find the entry then check if the current name
// is a possible short name.
//
if (!FoundEntry) {
ShortNameDirentOffset = CdShortNameDirentOffset( IrpContext, &FinalName.FileName );
//
// If there is an embedded short name offset then look for the
// matching long name in the directory.
//
if (ShortNameDirentOffset != MAXULONG) {
if (CleanupFileContext) {
CdCleanupFileContext( IrpContext, &FileContext );
}
CdInitializeFileContext( IrpContext, &FileContext );
CleanupFileContext = TRUE;
FoundEntry = CdFindFileByShortName( IrpContext,
CurrentFcb,
&FinalName,
IgnoreCase,
ShortNameDirentOffset,
&FileContext );
//
// If we found an entry and it is a directory then look
// this up in the path table.
//
if (FoundEntry) {
ShortNameMatch = TRUE;
if (FlagOn( FileContext.InitialDirent->Dirent.DirentFlags,
CD_ATTRIBUTE_DIRECTORY )) {
CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry );
CdInitializeCompoundPathEntry( IrpContext, &CompoundPathEntry );
FoundEntry = CdFindPathEntry( IrpContext,
CurrentFcb,
&FileContext.InitialDirent->Dirent.CdCaseFileName,
IgnoreCase,
&CompoundPathEntry );
//
// We better find this entry.
//
if (!FoundEntry) {
CdRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
//
// Upcase the name with the short name if case
// insensitive.
//
if (IgnoreCase) {
CdUpcaseName( IrpContext, &FinalName, &FinalName );
}
//
// We found a matching file. If we are at the last
// entry then break out of the loop and open the
// file below. Otherwise we return an error.
//
} else if (RemainingName.FileName.Length == 0) {
//
// Break out of the loop. We will process the dirent
// below.
//
MatchingName = &FileContext.ShortName;
break;
} else {
try_return( Status = STATUS_OBJECT_PATH_NOT_FOUND );
}
}
}
//
// We didn't find the name in either the path table or as
// a short name in a directory. If the remaining name
// length is zero then break out of the loop to search
// the directory.
//
if (!FoundEntry) {
if (RemainingName.FileName.Length == 0) {
break;
//
// Otherwise this path could not be cracked.
//
} else {
try_return( Status = STATUS_OBJECT_PATH_NOT_FOUND );
}
}
}
//
// If this is an ignore case open then copy the exact case
// in the file object name. If it was a short name match then
// the name must be upcase already.
//
if (IgnoreCase && !ShortNameMatch) {
RtlCopyMemory( FinalName.FileName.Buffer,
CompoundPathEntry.PathEntry.CdDirName.FileName.Buffer,
CompoundPathEntry.PathEntry.CdDirName.FileName.Length );
}
//
// If we have found the last component then open this as a directory
// and return to our caller.
//
if (RemainingName.FileName.Length == 0) {
if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) {
try_return( Status = STATUS_FILE_IS_A_DIRECTORY );
}
//
// The only create disposition we allow is OPEN.
//
if ((CreateDisposition != FILE_OPEN) &&
(CreateDisposition != FILE_OPEN_IF)) {
try_return( Status = STATUS_ACCESS_DENIED );
}
try_return( Status = CdOpenDirectoryFromPathEntry( IrpContext,
IrpSp,
Vcb,
&CurrentFcb,
&FinalName,
IgnoreCase,
ShortNameMatch,
&CompoundPathEntry.PathEntry,
TRUE,
RelatedCcb ));
}
//
// Otherwise open an Fcb for this intermediate index Fcb.
//
CdOpenDirectoryFromPathEntry( IrpContext,
IrpSp,
Vcb,
&CurrentFcb,
&FinalName,
IgnoreCase,
ShortNameMatch,
&CompoundPathEntry.PathEntry,
FALSE,
NULL );
CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry );
CleanupCompoundPathEntry = FALSE;
}
//
// We need to scan the current directory for a matching file name
// if we don't already have one.
//
if (!FoundEntry) {
if (CleanupFileContext) {
CdCleanupFileContext( IrpContext, &FileContext );
}
CdInitializeFileContext( IrpContext, &FileContext );
CleanupFileContext = TRUE;
//
// Split our search name into separate components.
//
CdConvertNameToCdName( IrpContext, &FinalName );
FoundEntry = CdFindFile( IrpContext,
CurrentFcb,
&FinalName,
IgnoreCase,
&FileContext,
&MatchingName );
}
//
// If we didn't find a match then check if the name is invalid to
// determine which error code to return.
//
if (!FoundEntry) {
if ((CreateDisposition == FILE_OPEN) ||
(CreateDisposition == FILE_OVERWRITE)) {
try_return( Status = STATUS_OBJECT_NAME_NOT_FOUND );
}
//
// Any other operation return STATUS_ACCESS_DENIED.
//
try_return( Status = STATUS_ACCESS_DENIED );
}
//
// If this is a directory then the disk is corrupt because it wasn't
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -