📄 create.c
字号:
//
// Do the prefix search to find the longest matching name.
//
CurrentLcb = UdfFindPrefix( IrpContext,
&CurrentFcb,
&RemainingName,
IgnoreCase );
}
//
// At this point CurrentFcb points at the lowest Fcb in the tree for this
// file name, CurrentLcb is that name, and RemainingName is the rest of the
// name we have to do any directory traversals for.
//
//
// If the remaining name length is zero then we have found our
// target.
//
if (RemainingName.Length == 0) {
//
// If this is a file so verify the user didn't want to open
// a directory.
//
if (SafeNodeType( CurrentFcb ) == UDFS_NTC_FCB_DATA) {
if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ) ||
FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) {
try_leave( Status = STATUS_NOT_A_DIRECTORY );
}
//
// The only create disposition we allow is OPEN.
//
if ((CreateDisposition != FILE_OPEN) &&
(CreateDisposition != FILE_OPEN_IF)) {
try_leave( Status = STATUS_ACCESS_DENIED );
}
try_leave( Status = UdfOpenExistingFcb( IrpContext,
IrpSp,
&CurrentFcb,
CurrentLcb,
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_leave( 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_leave( Status = STATUS_ACCESS_DENIED );
}
try_leave( Status = UdfOpenExistingFcb( IrpContext,
IrpSp,
&CurrentFcb,
CurrentLcb,
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_leave( Status = STATUS_OBJECT_PATH_NOT_FOUND );
}
//
// If we can't wait then post this request.
//
if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT );
}
//
// Prepare the enumeration context for use.
//
UdfInitializeDirContext( IrpContext, &DirContext );
CleanupDirContext = TRUE;
while (TRUE) {
ShortNameMatch = FALSE;
//
// Split off the next component from the name.
//
UdfDissectName( IrpContext,
&RemainingName,
&FinalName );
//
// Go ahead and look this entry up in the directory.
//
FoundEntry = UdfFindDirEntry( IrpContext,
CurrentFcb,
&FinalName,
IgnoreCase,
FALSE,
&DirContext );
//
// If we didn't find the entry then check if the current name
// is a possible short name.
//
if (!FoundEntry && UdfCandidateShortName( IrpContext, &FinalName)) {
//
// If the name looks like it could be a short name, try to find
// a matching real directory entry.
//
ShortNameMatch =
FoundEntry = UdfFindDirEntry( IrpContext,
CurrentFcb,
&FinalName,
IgnoreCase,
TRUE,
&DirContext );
}
//
// If we didn't find a match then check what the caller was trying to do to
// determine which error code to return.
//
if (!FoundEntry) {
if ((CreateDisposition == FILE_OPEN) ||
(CreateDisposition == FILE_OVERWRITE)) {
try_leave( Status = STATUS_OBJECT_NAME_NOT_FOUND );
}
//
// Any other operation return STATUS_ACCESS_DENIED.
//
try_leave( Status = STATUS_ACCESS_DENIED );
}
//
// If this is an ignore case open then copy the exact case
// in the file object name.
//
if (IgnoreCase && !ShortNameMatch) {
ASSERT( FinalName.Length == DirContext.ObjectName.Length );
RtlCopyMemory( FinalName.Buffer,
DirContext.ObjectName.Buffer,
DirContext.ObjectName.Length );
}
//
// If we have found the last component then break out to open for the caller.
//
if (RemainingName.Length == 0) {
break;
}
//
// The object we just found must be a directory.
//
if (!FlagOn( DirContext.Fid->Flags, NSR_FID_F_DIRECTORY )) {
try_leave( Status = STATUS_OBJECT_PATH_NOT_FOUND );
}
//
// Now open an Fcb for this intermediate index Fcb.
//
UdfOpenObjectFromDirContext( IrpContext,
IrpSp,
Vcb,
&CurrentFcb,
ShortNameMatch,
IgnoreCase,
&DirContext,
FALSE,
NULL );
}
//
// Make sure our opener is about to get what they expect.
//
if ((FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ) ||
FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) &&
!FlagOn( DirContext.Fid->Flags, NSR_FID_F_DIRECTORY )) {
try_leave( Status = STATUS_NOT_A_DIRECTORY );
}
if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE ) &&
FlagOn( DirContext.Fid->Flags, NSR_FID_F_DIRECTORY )) {
try_leave( Status = STATUS_FILE_IS_A_DIRECTORY );
}
//
// The only create disposition we allow is OPEN.
//
if ((CreateDisposition != FILE_OPEN) &&
(CreateDisposition != FILE_OPEN_IF)) {
try_leave( Status = STATUS_ACCESS_DENIED );
}
//
// Open the object for the caller.
//
try_leave( Status = UdfOpenObjectFromDirContext( IrpContext,
IrpSp,
Vcb,
&CurrentFcb,
ShortNameMatch,
IgnoreCase,
&DirContext,
TRUE,
RelatedCcb ));
} finally {
//
// Cleanup the enumeration context if initialized.
//
if (CleanupDirContext) {
UdfCleanupDirContext( IrpContext, &DirContext );
}
//
// The result of this open could be success, pending or some error
// condition.
//
if (AbnormalTermination()) {
//
// In the error path we start by calling our teardown routine if we
// have a CurrentFcb.
//
if (CurrentFcb != NULL) {
BOOLEAN RemovedFcb;
UdfTeardownStructures( IrpContext, CurrentFcb, FALSE, &RemovedFcb );
if (RemovedFcb) {
CurrentFcb = NULL;
}
}
//
// No need to complete the request.
//
IrpContext = NULL;
Irp = NULL;
//
// If we posted this request through the oplock package we need
// to show that there is no reason to complete the request.
//
} else if (Status == STATUS_PENDING) {
IrpContext = NULL;
Irp = NULL;
}
//
// Release the Current Fcb if still acquired.
//
if (CurrentFcb != NULL) {
UdfReleaseFcb( IrpContext, CurrentFcb );
}
//
// Release the Vcb.
//
UdfReleaseVcb( IrpContext, Vcb );
//
// Call our completion routine. It will handle the case where either
// the Irp and/or IrpContext are gone.
//
UdfCompleteRequest( IrpContext, Irp, Status );
}
return Status;
}
//
// Local support routine
//
NTSTATUS
UdfNormalizeFileNames (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN BOOLEAN OpenByFileId,
IN BOOLEAN IgnoreCase,
IN TYPE_OF_OPEN RelatedTypeOfOpen,
IN PCCB RelatedCcb OPTIONAL,
IN PUNICODE_STRING RelatedFileName OPTIONAL,
IN OUT PUNICODE_STRING FileName,
IN OUT PUNICODE_STRING RemainingName
)
/*++
Routine Description:
This routine is called to store the full name and upcased name into the
filename buffer. We only upcase the portion yet to parse. We also
check for a trailing backslash and lead-in double backslashes. This
routine also verifies the mode of the related open against the name
currently in the filename.
Arguments:
Vcb - Vcb for this volume.
OpenByFileId - Indicates if the filename should be a 64 bit FileId.
IgnoreCase - Indicates if this open is a case-insensitive operation.
RelatedTypeOfOpen - Indicates the type of the related file object.
RelatedCcb - Ccb for the related open. Ignored if no relative open.
RelatedFileName - FileName buffer for related open. Ignored if no
relative open.
FileName - FileName to update in this routine. The name should
either be a 64-bit FileId or a Unicode string.
RemainingName - Name with the remaining portion of the name. This
will begin after the related name and any separator. For a
non-relative open we also step over the initial separator.
Return Value:
NTSTATUS - STATUS_SUCCESS if the names are OK, appropriate error code
otherwise.
--*/
{
ULONG RemainingNameLength;
ULONG RelatedNameLength = 0;
ULONG SeparatorLength = 0;
ULONG BufferLength;
UNICODE_STRING NewFileName;
PAGED_CODE();
//
// If this is the first pass then we need to build the full name and
// check for name compatibility.
//
if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_FULL_NAME )) {
//
// Deal with the regular file name case first.
//
if (!OpenByFileId) {
//
// Here is the "M A R K L U C O V S K Y" hack.
//
// It's here because Mark says he can't avoid sending me double beginning
// backslashes via the Win32 layer.
//
if ((FileName->Length > sizeof( WCHAR )) &&
(FileName->Buffer[1] == L'\\') &&
(FileName->Buffer[0] == L'\\')) {
//
// If there are still two beginning backslashes, the name is bogus.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -