📄 create.c
字号:
*(Add2Ptr( NewFileName.Buffer, RelatedNameLength, PWCHAR )) = L'\\';
}
//
// Update the filename value we got from the user.
//
if (NewFileName.Buffer != FileName->Buffer) {
if (FileName->Buffer != NULL) {
CdFreePool( &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->FileName.MaximumLength =
RemainingName->FileName.Length = (USHORT) RemainingNameLength;
RemainingName->VersionString.Length = 0;
RemainingName->FileName.Buffer = Add2Ptr( FileName->Buffer,
RelatedNameLength + SeparatorLength,
PWCHAR );
//
// Upcase the name if necessary.
//
if (IgnoreCase && (RemainingNameLength != 0)) {
CdUpcaseName( IrpContext,
RemainingName,
RemainingName );
}
//
// Do a quick check to make sure there are no wildcards.
//
if (FsRtlDoesNameContainWildCards( &RemainingName->FileName )) {
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 = *FileName;
RemainingName->VersionString.Length = 0;
//
// Nothing to do if the name length is zero.
//
if (RemainingName->FileName.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->FileName.Buffer = Add2Ptr( RemainingName->FileName.Buffer,
RelatedFileName->Length,
PWCHAR );
RemainingName->FileName.Length -= RelatedFileName->Length;
}
}
//
// If we are pointing at a separator character then step past that.
//
if (RemainingName->FileName.Length != 0) {
if (*(RemainingName->FileName.Buffer) == L'\\') {
RemainingName->FileName.Buffer = Add2Ptr( RemainingName->FileName.Buffer,
sizeof( WCHAR ),
PWCHAR );
RemainingName->FileName.Length -= sizeof( WCHAR );
}
}
}
//
// Upcase the name if necessary.
//
if (IgnoreCase && (RemainingName->FileName.Length != 0)) {
CdUpcaseName( IrpContext,
RemainingName,
RemainingName );
}
}
return STATUS_SUCCESS;
}
//
// Local support routine
//
NTSTATUS
CdOpenByFileId (
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 need to carefully verify there is a file
at this offset. First check whether the Parent Fcb is in the table. If
not then lookup the parent at the path table offset given by file ID.
If found then build the Fcb from this entry and store the new Fcb in the
tree.
We know have the parent Fcb. Do a directory scan to find the dirent at
the given offset in this stream. This must point to the first entry
of a valid file.
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;
ULONG StreamOffset;
NODE_TYPE_CODE NodeTypeCode;
TYPE_OF_OPEN TypeOfOpen;
FILE_ENUM_CONTEXT FileContext;
BOOLEAN CleanupFileContext = FALSE;
COMPOUND_PATH_ENTRY CompoundPathEntry;
BOOLEAN CleanupCompoundPathEntry = FALSE;
FILE_ID FileId;
FILE_ID ParentFileId;
PFCB NextFcb;
PAGED_CODE();
//
// Extract the FileId from the FileObject.
//
RtlCopyMemory( &FileId, IrpSp->FileObject->FileName.Buffer, sizeof( FILE_ID ));
//
// Use a try-finally to facilitate cleanup.
//
try {
//
// Go ahead and figure out the TypeOfOpen and NodeType. We can
// get these from the input FileId.
//
if (CdFidIsDirectory( FileId )) {
TypeOfOpen = UserDirectoryOpen;
NodeTypeCode = CDFS_NTC_FCB_INDEX;
//
// If the offset isn't zero then the file Id is bad.
//
if (CdQueryFidDirentOffset( FileId ) != 0) {
try_return( Status = STATUS_INVALID_PARAMETER );
}
} else {
TypeOfOpen = UserFileOpen;
NodeTypeCode = CDFS_NTC_FCB_DATA;
}
//
// Acquire the Vcb and check if there is already an Fcb.
// If not we will need to carefully verify the Fcb.
// We will post the request if we don't find the Fcb and this
// request can't wait.
//
CdLockVcb( IrpContext, Vcb );
UnlockVcb = TRUE;
NextFcb = CdLookupFcbTable( IrpContext, Vcb, FileId );
if (NextFcb == NULL) {
//
// Get the path table offset from the file id.
//
StreamOffset = CdQueryFidPathTableOffset( FileId );
//
// Build the parent FileId for this and try looking it
// up in the PathTable.
//
CdSetFidDirentOffset( ParentFileId, 0 );
CdSetFidPathTableOffset( ParentFileId, StreamOffset );
CdFidSetDirectory( ParentFileId );
NextFcb = CdLookupFcbTable( IrpContext, Vcb, ParentFileId );
//
// If not present then walk through the PathTable to this point.
//
if (NextFcb == NULL) {
CdUnlockVcb( IrpContext, Vcb );
UnlockVcb = FALSE;
//
// Check that the path table offset lies within the path
// table.
//
if (StreamOffset > Vcb->PathTableFcb->FileSize.LowPart) {
try_return( Status = STATUS_INVALID_PARAMETER );
}
CdInitializeCompoundPathEntry( IrpContext, &CompoundPathEntry );
CleanupCompoundPathEntry = TRUE;
//
// Start at the first entry in the PathTable.
//
CdLookupPathEntry( IrpContext,
Vcb->PathTableFcb->StreamOffset,
1,
TRUE,
&CompoundPathEntry );
//
// Continue looking until we have passed our target offset.
//
while (TRUE) {
//
// Move to the next entry.
//
Found = CdLookupNextPathEntry( IrpContext,
&CompoundPathEntry.PathContext,
&CompoundPathEntry.PathEntry );
//
// If we didn't find the entry or are beyond it then the
// input Id is invalid.
//
if (!Found ||
(CompoundPathEntry.PathEntry.PathTableOffset > StreamOffset)) {
try_return( Status = STATUS_INVALID_PARAMETER );
}
}
//
// If the FileId specified a directory then we have found
// the entry. Make sure our caller wanted to open a directory.
//
if ((TypeOfOpen == UserDirectoryOpen) &&
FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) {
try_return( Status = STATUS_FILE_IS_A_DIRECTORY );
}
//
// Lock the Vcb and create the Fcb if necessary.
//
CdLockVcb( IrpContext, Vcb );
UnlockVcb = TRUE;
NextFcb = CdCreateFcb( IrpContext, ParentFileId, NodeTypeCode, &Found );
//
// It's possible that someone got in here ahead of us.
//
if (!Found) {
CdInitializeFcbFromPathEntry( IrpContext,
NextFcb,
NULL,
&CompoundPathEntry.PathEntry );
}
//
// If the user wanted to open a directory then we have found
// it. Store this Fcb into the CurrentFcb and skip the
// directory scan.
//
if (TypeOfOpen == UserDirectoryOpen) {
*CurrentFcb = NextFcb;
NextFcb = NULL;
}
}
//
// Perform the directory scan if we don't already have our target.
//
if (NextFcb != NULL) {
//
// Acquire the parent. We currently own the Vcb lock so
// do this without waiting first.
//
if (!CdAcquireFcbExclusive( IrpContext,
NextFcb,
TRUE )) {
NextFcb->FcbReference += 1;
CdUnlockVcb( IrpContext, Vcb );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -