📄 create.c
字号:
if ((FileName->Length > 2 * sizeof( WCHAR )) &&
(FileName->Buffer[2] == L'\\')) {
return STATUS_OBJECT_NAME_INVALID;
}
//
// Slide the name down in the buffer.
//
RtlMoveMemory( FileName->Buffer,
FileName->Buffer + 1,
FileName->Length );
FileName->Length -= sizeof( WCHAR );
}
//
// 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( UdfPagedPool,
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) {
*(Add2Ptr( NewFileName.Buffer, RelatedNameLength, PWCHAR )) = L'\\';
}
//
// Update the filename value we got from the user.
//
if (NewFileName.Buffer != FileName->Buffer) {
if (FileName->Buffer != NULL) {
ExFreePool( FileName->Buffer );
}
FileName->Buffer = NewFileName.Buffer;
FileName->MaximumLength = NewFileName.MaximumLength;
}
//
// Copy the name length to the user's filename.
//
FileName->Length = (USHORT) (RelatedNameLength + SeparatorLength + RemainingNameLength);
}
//
// Now update the remaining name to parse.
//
RemainingName->MaximumLength =
RemainingName->Length = (USHORT) RemainingNameLength;
RemainingName->Buffer = Add2Ptr( FileName->Buffer,
RelatedNameLength + SeparatorLength,
PWCHAR );
//
// Upcase the name if necessary.
//
if (IgnoreCase && (RemainingNameLength != 0)) {
UdfUpcaseName( IrpContext,
RemainingName,
RemainingName );
}
//
// Do a quick check to make sure there are no wildcards.
//
if (FsRtlDoesNameContainWildCards( RemainingName )) {
return STATUS_OBJECT_NAME_INVALID;
}
//
// For the open by file Id case we verify the name really contains
// a 64 bit value.
//
} else {
//
// Check for validity of the buffer.
//
if (FileName->Length != sizeof( FILE_ID )) {
return STATUS_INVALID_PARAMETER;
}
}
SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_FULL_NAME );
//
// If we are in the retry path then the full name is already in the
// file object name. If this is a case-sensitive operation then
// we need to upcase the name from the end of any related file name already stored
// there.
//
} else {
//
// Assume there is no relative name.
//
*RemainingName = *FileName;
//
// Nothing to do if the name length is zero.
//
if (RemainingName->Length != 0) {
//
// If there is a relative name then we need to walk past it.
//
if (RelatedTypeOfOpen != UnopenedFileObject) {
//
// Nothing to walk past if the RelatedCcb is opened by FileId.
//
if (!FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID )) {
//
// Related file name is a proper prefix of the full name.
// We step over the related name and if we are then
// pointing at a separator character we step over that.
//
RemainingName->Buffer = Add2Ptr( RemainingName->Buffer,
RelatedFileName->Length,
PWCHAR );
RemainingName->Length -= RelatedFileName->Length;
}
}
//
// If we are pointing at a separator character then step past that.
//
if (RemainingName->Length != 0) {
if (*(RemainingName->Buffer) == L'\\') {
RemainingName->Buffer = Add2Ptr( RemainingName->Buffer,
sizeof( WCHAR ),
PWCHAR );
RemainingName->Length -= sizeof( WCHAR );
}
}
}
//
// Upcase the name if necessary.
//
if (IgnoreCase && (RemainingName->Length != 0)) {
UdfUpcaseName( IrpContext,
RemainingName,
RemainingName );
}
}
return STATUS_SUCCESS;
}
//
// Local support routine
//
NTSTATUS
UdfOpenObjectByFileId (
IN PIRP_CONTEXT IrpContext,
IN PIO_STACK_LOCATION IrpSp,
IN PVCB Vcb,
IN OUT PFCB *CurrentFcb
)
/*++
Routine Description:
This routine is called to open a file by the FileId. The file Id is in
the FileObject name buffer and has been verified to be 64 bits.
We extract the Id number and then check to see whether we are opening a
file or directory and compare that with the create options. If this
generates no error then optimistically look up the Fcb in the Fcb Table.
If we don't find the Fcb then we take what is effectively a wild-a** guess.
Since we would need more than 64bits to contain the root extent length along
with the partition, lbn and dir/file flag we have to speculate that the
opener knows what they are doing and try to crack an ICB hierarchy at the
specified location. This can fail for any number of reasons, which then have
to be mapped to an open failure.
If found then build the Fcb from this entry and store the new Fcb in the
tree.
Finally we call our worker routine to complete the open on this Fcb.
Arguments:
IrpSp - Stack location within the create Irp.
Vcb - Vcb for this volume.
CurrentFcb - Address to store the Fcb for this open. We only store the
CurrentFcb here when we have acquired it so our caller knows to
free or deallocate it.
Return Value:
NTSTATUS - Status indicating the result of the operation.
--*/
{
NTSTATUS Status = STATUS_ACCESS_DENIED;
BOOLEAN UnlockVcb = FALSE;
BOOLEAN Found;
BOOLEAN FcbExisted;
ICB_SEARCH_CONTEXT IcbContext;
BOOLEAN CleanupIcbContext = FALSE;
NODE_TYPE_CODE NodeTypeCode;
TYPE_OF_OPEN TypeOfOpen;
FILE_ID FileId;
PFCB NextFcb = NULL;
PAGED_CODE();
//
// Check inputs.
//
ASSERT_IRP_CONTEXT( IrpContext );
ASSERT_VCB( Vcb );
//
// Extract the FileId from the FileObject.
//
RtlCopyMemory( &FileId, IrpSp->FileObject->FileName.Buffer, sizeof( FILE_ID ));
//
// Now do a quick check that the reserved, unused chunk of the fileid is
// unused in this specimen.
//
if (UdfGetFidReservedZero( FileId )) {
return STATUS_INVALID_PARAMETER;
}
//
// Go ahead and figure out the TypeOfOpen and NodeType. We can
// get these from the input FileId.
//
if (UdfIsFidDirectory( FileId )) {
TypeOfOpen = UserDirectoryOpen;
NodeTypeCode = UDFS_NTC_FCB_INDEX;
} else {
TypeOfOpen = UserFileOpen;
NodeTypeCode = UDFS_NTC_FCB_DATA;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -