📄 create.c
字号:
// in the Path Table.
//
if (FlagOn( FileContext.InitialDirent->Dirent.Flags, CD_ATTRIBUTE_DIRECTORY )) {
CdRaiseStatus( IrpContext, STATUS_DISK_CORRUPT_ERROR );
}
//
// Make sure our opener didn't want a directory.
//
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 );
}
//
// If this is an ignore case open then copy the exact case
// in the file object name. Any version portion should
// already be upcased.
//
if (IgnoreCase) {
RtlCopyMemory( FinalName.FileName.Buffer,
MatchingName->FileName.Buffer,
MatchingName->FileName.Length );
}
//
// Open the file using the file context. We already have the
// first and last dirents.
//
try_return( Status = CdOpenFileFromFileContext( IrpContext,
IrpSp,
Vcb,
&CurrentFcb,
&FinalName,
IgnoreCase,
(BOOLEAN) (MatchingName == &FileContext.ShortName),
&FileContext,
RelatedCcb ));
try_exit: NOTHING;
} finally {
//
// Cleanup the PathEntry if initialized.
//
if (CleanupCompoundPathEntry) {
CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry );
}
//
// Cleanup the FileContext if initialized.
//
if (CleanupFileContext) {
CdCleanupFileContext( IrpContext, &FileContext );
}
//
// 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;
CdTeardownStructures( IrpContext, CurrentFcb, &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) {
CdReleaseFcb( IrpContext, CurrentFcb );
}
//
// Release the Vcb.
//
CdReleaseVcb( IrpContext, Vcb );
//
// Call our completion routine. It will handle the case where either
// the Irp and/or IrpContext are gone.
//
CdCompleteRequest( IrpContext, Irp, Status );
}
return Status;
}
//
// Local support routine
//
NTSTATUS
CdNormalizeFileNames (
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 PCD_NAME 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) {
//
// This is here because the Win32 layer can't avoid sending me double
// beginning backslashes.
//
if ((FileName->Length > sizeof( WCHAR )) &&
(FileName->Buffer[1] == L'\\') &&
(FileName->Buffer[0] == L'\\')) {
//
// If there are still two beginning backslashes, the name is bogus.
//
if ((FileName->Length > 2 * sizeof( WCHAR )) &&
(FileName->Buffer[2] == L'\\')) {
return STATUS_OBJECT_NAME_INVALID;
}
//
// Slide the name down in the buffer.
//
FileName->Length -= sizeof( WCHAR );
RtlMoveMemory( FileName->Buffer,
FileName->Buffer + 1,
FileName->Length );
}
//
// Check for a trailing backslash. Don't strip off if only character
// in the full name or for relative opens where this is illegal.
//
if (((FileName->Length > sizeof( WCHAR)) ||
((FileName->Length == sizeof( WCHAR )) && (RelatedTypeOfOpen == UserDirectoryOpen))) &&
(FileName->Buffer[ (FileName->Length/2) - 1 ] == L'\\')) {
SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH );
FileName->Length -= sizeof( WCHAR );
}
//
// Remember the length we need for this portion of the name.
//
RemainingNameLength = FileName->Length;
//
// If this is a related file object then we verify the compatibility
// of the name in the file object with the relative file object.
//
if (RelatedTypeOfOpen != UnopenedFileObject) {
//
// If the filename length was zero then it must be legal.
// If there are characters then check with the related
// type of open.
//
if (FileName->Length != 0) {
//
// The name length must always be zero for a volume open.
//
if (RelatedTypeOfOpen <= UserVolumeOpen) {
return STATUS_INVALID_PARAMETER;
//
// The remaining name cannot begin with a backslash.
//
} else if (FileName->Buffer[0] == L'\\' ) {
return STATUS_INVALID_PARAMETER;
//
// If the related file is a user file then there
// is no file with this path.
//
} else if (RelatedTypeOfOpen == UserFileOpen) {
return STATUS_OBJECT_PATH_NOT_FOUND;
}
}
//
// Remember the length of the related name when building
// the full name. We leave the RelatedNameLength and
// SeparatorLength at zero if the relative file is opened
// by Id.
//
if (!FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID )) {
//
// Add a separator if the name length is non-zero
// unless the relative Fcb is at the root.
//
if ((FileName->Length != 0) &&
(RelatedCcb->Fcb != Vcb->RootIndexFcb)) {
SeparatorLength = sizeof( WCHAR );
}
RelatedNameLength = RelatedFileName->Length;
}
//
// The full name is already in the filename. It must either
// be length 0 or begin with a backslash.
//
} else if (FileName->Length != 0) {
if (FileName->Buffer[0] != L'\\') {
return STATUS_INVALID_PARAMETER;
}
//
// We will want to trim the leading backslash from the
// remaining name we return.
//
RemainingNameLength -= sizeof( WCHAR );
SeparatorLength = sizeof( WCHAR );
}
//
// Now see if the buffer is large enough to hold the full name.
//
BufferLength = RelatedNameLength + SeparatorLength + RemainingNameLength;
//
// Check for an overflow of the maximum filename size.
//
if (BufferLength > MAXUSHORT) {
return STATUS_INVALID_PARAMETER;
}
//
// Now see if we need to allocate a new buffer.
//
if (FileName->MaximumLength < BufferLength) {
NewFileName.Buffer = FsRtlAllocatePoolWithTag( CdPagedPool,
BufferLength,
TAG_FILE_NAME );
NewFileName.MaximumLength = (USHORT) BufferLength;
} else {
NewFileName.Buffer = FileName->Buffer;
NewFileName.MaximumLength = FileName->MaximumLength;
}
//
// If there is a related name then we need to slide the remaining bytes up and
// insert the related name. Otherwise the name is in the correct position
// already.
//
if (RelatedNameLength != 0) {
//
// Store the remaining name in its correct position.
//
if (RemainingNameLength != 0) {
RtlMoveMemory( Add2Ptr( NewFileName.Buffer, RelatedNameLength + SeparatorLength, PVOID ),
FileName->Buffer,
RemainingNameLength );
}
RtlCopyMemory( NewFileName.Buffer,
RelatedFileName->Buffer,
RelatedNameLength );
//
// Add the separator if needed.
//
if (SeparatorLength != 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -