📄 create.c
字号:
//
// Use a try-finally to facilitate cleanup.
//
try {
//
// Acquire the Vcb and check if there is already an Fcb.
// If not we will need to carefully hunt for the on-disc
// structures.
//
// We will post the request if we don't find the Fcb and this
// request can't wait.
//
UdfLockVcb( IrpContext, Vcb );
UnlockVcb = TRUE;
NextFcb = UdfCreateFcb( IrpContext, FileId, NodeTypeCode, &FcbExisted );
//
// Now, if the Fcb was not already here we have some work to do.
//
if (!FcbExisted) {
//
// If we can't wait then post this request.
//
if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT );
}
//
// Use a try-finally to transform errors we get as a result of going
// off on a wild goose chase into a simple open failure.
//
try {
NextFcb->FileId = FileId;
UdfInitializeIcbContextFromFcb( IrpContext, &IcbContext, NextFcb );
CleanupIcbContext = TRUE;
UdfLookupActiveIcb( IrpContext, &IcbContext );
UdfInitializeFcbFromIcbContext( IrpContext,
NextFcb,
&IcbContext );
UdfCleanupIcbContext( IrpContext, &IcbContext );
CleanupIcbContext = FALSE;
} except( UdfExceptionFilter( IrpContext, GetExceptionInformation() )) {
//
// Any error we receive is an indication that the given fileid is
// not valid.
//
Status = STATUS_INVALID_PARAMETER;
}
//
// Do a little dance to leave the exception handler if we had problems.
//
if (Status == STATUS_INVALID_PARAMETER) {
try_leave( NOTHING );
}
}
//
// We have the Fcb. Check that the type of the file is compatible with
// the desired type of file to open.
//
if (FlagOn( NextFcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) {
try_leave( Status = STATUS_FILE_IS_A_DIRECTORY );
}
} else if (FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) {
try_leave( Status = STATUS_NOT_A_DIRECTORY );
}
//
// 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, the
// Vcb and then dereference the Fcb.
//
if (!UdfAcquireFcbExclusive( IrpContext, NextFcb, TRUE )) {
NextFcb->FcbReference += 1;
UdfUnlockVcb( IrpContext, Vcb );
UdfAcquireFcbExclusive( IrpContext, NextFcb, FALSE );
UdfLockVcb( IrpContext, Vcb );
NextFcb->FcbReference -= 1;
}
UdfUnlockVcb( IrpContext, Vcb );
UnlockVcb = FALSE;
//
// Move to this Fcb.
//
*CurrentFcb = NextFcb;
//
// Check the requested access on this Fcb.
//
if (!UdfIllegalFcbAccess( IrpContext,
TypeOfOpen,
IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) {
//
// Call our worker routine to complete the open.
//
Status = UdfCompleteFcbOpen( IrpContext,
IrpSp,
Vcb,
CurrentFcb,
NULL,
TypeOfOpen,
CCB_FLAG_OPEN_BY_ID,
IrpSp->Parameters.Create.SecurityContext->DesiredAccess );
}
} finally {
if (UnlockVcb) {
UdfUnlockVcb( IrpContext, Vcb );
}
if (CleanupIcbContext) {
UdfCleanupIcbContext( IrpContext, &IcbContext );
}
//
// Destroy the new Fcb if it was not fully initialized.
//
if (NextFcb && !FlagOn( NextFcb->FcbState, FCB_STATE_INITIALIZED )) {
UdfDeleteFcb( IrpContext, NextFcb );
}
}
return Status;
}
//
// Local support routine
//
NTSTATUS
UdfOpenExistingFcb (
IN PIRP_CONTEXT IrpContext,
IN PIO_STACK_LOCATION IrpSp,
IN OUT PFCB *CurrentFcb,
IN PLCB OpenLcb,
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.
OpenLcb - Lcb used to find this Fcb.
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 inputs.
//
ASSERT_IRP_CONTEXT( IrpContext );
ASSERT_EXCLUSIVE_FCB( *CurrentFcb );
ASSERT_OPTIONAL_CCB( RelatedCcb );
//
// Check that the desired access is legal.
//
if (!UdfIllegalFcbAccess( 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 )) {
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 = UdfCompleteFcbOpen( IrpContext,
IrpSp,
(*CurrentFcb)->Vcb,
CurrentFcb,
OpenLcb,
TypeOfOpen,
CcbFlags,
IrpSp->Parameters.Create.SecurityContext->DesiredAccess );
}
return Status;
}
//
// Local support routine
//
NTSTATUS
UdfOpenObjectFromDirContext (
IN PIRP_CONTEXT IrpContext,
IN PIO_STACK_LOCATION IrpSp,
IN PVCB Vcb,
IN OUT PFCB *CurrentFcb,
IN BOOLEAN ShortNameMatch,
IN BOOLEAN IgnoreCase,
IN PDIR_ENUM_CONTEXT DirContext,
IN BOOLEAN PerformUserOpen,
IN PCCB RelatedCcb OPTIONAL
)
/*++
Routine Description:
This routine is called to open an object found in a directory scan. This
can be a directory or a file as indicated in the scan's results.
We first check that the desired access is legal for this file. 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.
Lookup the active ICB, 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 the current volume.
CurrentFcb - On input this is the parent of the Fcb to open. On output we
store the Fcb for the file being opened.
ShortNameMatch - Indicates whether this object was opened by the shortname.
IgnoreCase - Indicates the case sensitivity of the caller.
DirContext - This is the context used to find the object.
PerformUserOpen - Indicates if we are at the object the user wants to finally open.
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 = NULL;
PFCB ParentFcb = NULL;
TYPE_OF_OPEN TypeOfOpen;
NODE_TYPE_CODE NodeTypeCode;
ICB_SEARCH_CONTEXT IcbContext;
BOOLEAN CleanupIcbContext = FALSE;
PLCB OpenLcb;
NTSTATUS Status;
PAGED_CODE();
//
// Figure out what kind of open we will be performing here. The caller has already insured
// that the user is expecting us to do this.
//
if (FlagOn( DirContext->Fid->Flags, NSR_FID_F_DIRECTORY )) {
TypeOfOpen = UserDirectoryOpen;
NodeTypeCode = UDFS_NTC_FCB_INDEX;
} else {
TypeOfOpen = UserFileOpen;
NodeTypeCode = UDFS_NTC_FCB_DATA;
}
//
// Check for illegal access to this file.
//
if (PerformUserOpen &&
UdfIllegalFcbAccess( IrpContext,
TypeOfOpen,
IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) {
return STATUS_ACCESS_DENIED;
}
//
// Use a try-finally to facilitate cleanup.
//
try {
//
// Check the related Ccb to see if this was an OpenByFileId.
//
if (ARGUMENT_PRESENT( RelatedCcb ) &&
FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID | CCB_FLAG_OPEN_RELATIVE_BY_ID )) {
SetFlag( CcbFlags, CCB_FLAG_OPEN_RELATIVE_BY_ID );
}
if (IgnoreCase) {
SetFlag( CcbFlags, CCB_FLAG_IGNORE_CASE );
}
//
// Build the file Id for this object.
//
UdfSetFidFromLbAddr( FileId, DirContext->Fid->Icb.Start );
if (TypeOfOpen == UserDirectoryOpen) {
UdfSetFidDirectory( FileId );
}
//
// Lock the Vcb so we can examine the Fcb Table.
//
UdfLockVcb( IrpContext, Vcb );
UnlockVcb = TRUE;
//
// Get the Fcb for this file.
//
NextFcb = UdfCreateFcb( IrpContext, FileId, NodeTypeCode, &FcbExisted );
//
// If the Fcb was created here then initialize from the values in the
// dirent. We have optimistically assumed that there isn't any corrupt
// information to this point - we're about to discover it if there is.
//
if (!FcbExisted) {
//
// Set the root extent length and go get the active ICB, initialize.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -