📄 create.c
字号:
CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE );
CdLockVcb( IrpContext, Vcb );
NextFcb->FcbReference -= 1;
CdUnlockVcb( IrpContext, Vcb );
} else {
CdUnlockVcb( IrpContext, Vcb );
}
UnlockVcb = FALSE;
//
// Set up the CurrentFcb pointers. We know there was
// no previous parent in this case.
//
*CurrentFcb = NextFcb;
//
// Calculate the offset in the stream.
//
StreamOffset = CdQueryFidDirentOffset( FileId );
//
// Create the stream file if it doesn't exist. This will update
// the Fcb with the size from the self entry.
//
CdVerifyOrCreateDirStreamFile( IrpContext, NextFcb);
//
// If our offset is beyond the end of the directory then the
// FileId is invalid.
//
if (StreamOffset > NextFcb->FileSize.LowPart) {
try_return( Status = STATUS_INVALID_PARAMETER );
}
//
// Otherwise position ourselves at the self entry and walk
// through dirent by dirent until this location is found.
//
CdInitializeFileContext( IrpContext, &FileContext );
CdLookupInitialFileDirent( IrpContext,
NextFcb,
&FileContext,
NextFcb->StreamOffset );
CleanupFileContext = TRUE;
while (TRUE) {
//
// Move to the first entry of the next file.
//
Found = CdLookupNextInitialFileDirent( IrpContext,
NextFcb,
&FileContext );
//
// If we didn't find the entry or are beyond it then the
// input Id is invalid.
//
if (!Found ||
(FileContext.InitialDirent->Dirent.DirentOffset > StreamOffset)) {
try_return( Status = STATUS_INVALID_PARAMETER );
}
}
//
// This better not be a directory. Directory FileIds must
// refer to the self entry for directories.
//
if (FlagOn( FileContext.InitialDirent->Dirent.DirentFlags,
CD_ATTRIBUTE_DIRECTORY )) {
try_return( Status = STATUS_INVALID_PARAMETER );
}
//
// Check that our caller wanted to open a file.
//
if (FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) {
try_return( Status = STATUS_NOT_A_DIRECTORY );
}
//
// Otherwise we want to collect all of the dirents for this file
// and create an Fcb with this.
//
CdLookupLastFileDirent( IrpContext, NextFcb, &FileContext );
CdLockVcb( IrpContext, Vcb );
UnlockVcb = TRUE;
NextFcb = CdCreateFcb( IrpContext, FileId, NodeTypeCode, &Found );
//
// It's possible that someone has since created this Fcb since we
// first checked. If so then can simply use this. Otherwise
// we need to initialize a new Fcb and attach it to our parent
// and insert it into the Fcb Table.
//
if (!Found) {
CdInitializeFcbFromFileContext( IrpContext,
NextFcb,
*CurrentFcb,
&FileContext );
}
}
//
// We have the Fcb. Check that the type of the file is compatible with
// the desired type of file to open.
//
} else {
if (FlagOn( NextFcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) {
try_return( Status = STATUS_FILE_IS_A_DIRECTORY );
}
} else if (FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) {
try_return( Status = STATUS_NOT_A_DIRECTORY );
}
}
//
// If we have a the previous Fcb and have inserted the next Fcb into
// the Fcb Table. It is safe to release the current Fcb if present
// since it is referenced through the child Fcb.
//
if (*CurrentFcb != NULL) {
CdReleaseFcb( IrpContext, *CurrentFcb );
}
//
// We now know the Fcb and currently hold the Vcb lock.
// Try to acquire this Fcb without waiting. Otherwise we
// need to reference it, drop the Vcb, acquire the Fcb and
// then dereference the Fcb.
//
if (!CdAcquireFcbExclusive( IrpContext, NextFcb, TRUE )) {
NextFcb->FcbReference += 1;
CdUnlockVcb( IrpContext, Vcb );
CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE );
CdLockVcb( IrpContext, Vcb );
NextFcb->FcbReference -= 1;
CdUnlockVcb( IrpContext, Vcb );
} else {
CdUnlockVcb( IrpContext, Vcb );
}
UnlockVcb = FALSE;
//
// Move to this Fcb.
//
*CurrentFcb = NextFcb;
//
// Check the requested access on this Fcb.
//
if (!CdIllegalFcbAccess( IrpContext,
TypeOfOpen,
IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) {
//
// Call our worker routine to complete the open.
//
Status = CdCompleteFcbOpen( IrpContext,
IrpSp,
Vcb,
CurrentFcb,
TypeOfOpen,
CCB_FLAG_OPEN_BY_ID,
IrpSp->Parameters.Create.SecurityContext->DesiredAccess );
}
try_exit: NOTHING;
} finally {
if (UnlockVcb) {
CdUnlockVcb( IrpContext, Vcb );
}
if (CleanupFileContext) {
CdCleanupFileContext( IrpContext, &FileContext );
}
if (CleanupCompoundPathEntry) {
CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry );
}
}
return Status;
}
//
// Local support routine
//
NTSTATUS
CdOpenExistingFcb (
IN PIRP_CONTEXT IrpContext,
IN PIO_STACK_LOCATION IrpSp,
IN OUT PFCB *CurrentFcb,
IN TYPE_OF_OPEN TypeOfOpen,
IN BOOLEAN IgnoreCase,
IN PCCB RelatedCcb OPTIONAL
)
/*++
Routine Description:
This routine is called to open an Fcb which is already in the Fcb table.
We will verify the access to the file and then call our worker routine
to perform the final operations.
Arguments:
IrpSp - Pointer to the stack location for this open.
CurrentFcb - Address of Fcb to open. We will clear this if the Fcb
is released here.
TypeOfOpen - Indicates whether we are opening a file, directory or volume.
IgnoreCase - Indicates if this open is case-insensitive.
RelatedCcb - Ccb for related file object if relative open. We use
this when setting the Ccb flags for this open. It will tell
us whether the name currently in the file object is relative or
absolute.
Return Value:
NTSTATUS - Status indicating the result of the operation.
--*/
{
ULONG CcbFlags = 0;
NTSTATUS Status = STATUS_ACCESS_DENIED;
PAGED_CODE();
//
// Check that the desired access is legal.
//
if (!CdIllegalFcbAccess( IrpContext,
TypeOfOpen,
IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) {
//
// Set the Ignore case.
//
if (IgnoreCase) {
SetFlag( CcbFlags, CCB_FLAG_IGNORE_CASE );
}
//
// Check the related Ccb to see if this was an OpenByFileId and
// whether there was a version.
//
if (ARGUMENT_PRESENT( RelatedCcb )) {
SetFlag( CcbFlags, FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_WITH_VERSION ));
if (FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID | CCB_FLAG_OPEN_RELATIVE_BY_ID )) {
SetFlag( CcbFlags, CCB_FLAG_OPEN_RELATIVE_BY_ID );
}
}
//
// Call our worker routine to complete the open.
//
Status = CdCompleteFcbOpen( IrpContext,
IrpSp,
(*CurrentFcb)->Vcb,
CurrentFcb,
TypeOfOpen,
CcbFlags,
IrpSp->Parameters.Create.SecurityContext->DesiredAccess );
}
return Status;
}
//
// Local support routine
//
NTSTATUS
CdOpenDirectoryFromPathEntry (
IN PIRP_CONTEXT IrpContext,
IN PIO_STACK_LOCATION IrpSp,
IN PVCB Vcb,
IN OUT PFCB *CurrentFcb,
IN PCD_NAME DirName,
IN BOOLEAN IgnoreCase,
IN BOOLEAN ShortNameMatch,
IN PPATH_ENTRY PathEntry,
IN BOOLEAN PerformUserOpen,
IN PCCB RelatedCcb OPTIONAL
)
/*++
Routine Description:
This routine is called to open a directory where the directory was found
in the path table. This routine is called in the case where this is the
file to open for the user and where this is an intermediate node in the
full path to open.
We first check that the desired access is legal for a directory. Then we
construct the FileId for this and do a check to see if it is the Fcb
Table. It is always possible that either it was created since or simply
wasn't in the prefix table at the time of the prefix table search.
Initialize the Fcb and store into the FcbTable if not present.
Next we will add this to the prefix table of our parent if needed.
Once we know that the new Fcb has been initialized then we move our pointer
in the tree down to this position.
This routine does not own the Vcb lock on entry. We must be sure to release
it on exit.
Arguments:
IrpSp - Stack location for this request.
Vcb - Vcb for this volume.
CurrentFcb - On input this is the parent of the Fcb to open. On output we
store the Fcb for the file being opened.
DirName - This is always the exact name used to reach this file.
IgnoreCase - Indicates the type of case match for the open.
ShortNameMatch - Indicates if we are opening via the short name.
PathEntry - Path entry for the entry found.
PerformUserOpen - TRUE if we are to open this for a user, FALSE otherwise.
RelatedCcb - RelatedCcb for relative file object used to make this open.
Return Value:
NTSTATUS - Status indicating the result of the operation.
--*/
{
ULONG CcbFlags = 0;
FILE_ID FileId;
BOOLEAN UnlockVcb = FALSE;
BOOLEAN FcbExisted;
PFCB NextFcb;
PFCB ParentFcb = NULL;
NTSTATUS Status;
PAGED_CODE();
//
// Check for illegal access to this file.
//
if (Per
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -