📄 create.c
字号:
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
Create.c
Abstract:
This module implements the File Create routine for Udfs called by the
Fsd/Fsp dispatch routines.
Author:
Dan Lovinger [DanLo] 9-October-1996
Revision History:
--*/
#include "UdfProcs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (UDFS_BUG_CHECK_CREATE)
//
// The local debug trace level
//
#define Dbg (UDFS_DEBUG_LEVEL_CREATE)
//
// Local support routines
//
NTSTATUS
UdfNormalizeFileNames (
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 PUNICODE_STRING RemainingName
);
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
);
NTSTATUS
UdfOpenObjectByFileId (
IN PIRP_CONTEXT IrpContext,
IN PIO_STACK_LOCATION IrpSp,
IN PVCB Vcb,
IN OUT PFCB *CurrentFcb
);
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
);
NTSTATUS
UdfCompleteFcbOpen (
IN PIRP_CONTEXT IrpContext,
PIO_STACK_LOCATION IrpSp,
IN PVCB Vcb,
IN OUT PFCB *CurrentFcb,
IN PLCB OpenLcb,
IN TYPE_OF_OPEN TypeOfOpen,
IN ULONG UserCcbFlags,
IN ACCESS_MASK DesiredAccess
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, UdfCommonCreate)
#pragma alloc_text(PAGE, UdfCompleteFcbOpen)
#pragma alloc_text(PAGE, UdfNormalizeFileNames)
#pragma alloc_text(PAGE, UdfOpenObjectByFileId)
#pragma alloc_text(PAGE, UdfOpenExistingFcb)
#pragma alloc_text(PAGE, UdfOpenObjectFromDirContext)
#endif
NTSTATUS
UdfCommonCreate (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This is the common routine for opening a file called by both the
Fsp and Fsd threads.
The file can be opened either by name or by file Id either with or without
a relative name. The file name field in the file object passed to this routine
contains either a unicode string or a 64 bit value which is the file Id.
If there is a related file object with a name then we will already have converted
that name to Oem.
We will store the full name for the file in the file object on a successful
open. We will allocate a larger buffer if necessary and combine the
related and file object names. The only exception is the relative open
when the related file object is for an OpenByFileId file. If we need to
allocate a buffer for a case insensitive name then we allocate it at
the tail of the buffer we will store into the file object. The upcased
portion will begin immediately after the name defined by the FileName
in the file object.
Once we have the full name in the file object we don't want to split the
name in the event of a retry. We use a flag in the IrpContext to indicate
that the name has been split.
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - This is the status from this open operation.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
PFILE_OBJECT FileObject;
DIR_ENUM_CONTEXT DirContext;
BOOLEAN CleanupDirContext = FALSE;
BOOLEAN FoundEntry;
PVCB Vcb;
BOOLEAN OpenByFileId;
BOOLEAN IgnoreCase;
ULONG CreateDisposition;
BOOLEAN ShortNameMatch;
BOOLEAN VolumeOpen = FALSE;
//
// We will be acquiring and releasing file Fcb's as we move down the
// directory tree during opens. At any time we need to know the deepest
// point we have traversed down in the tree in case we need to cleanup
// any structures created here.
//
// CurrentFcb - represents this point. If non-null it means we have
// acquired it and need to release it in finally clause.
//
// NextFcb - represents the NextFcb to walk to but haven't acquired yet.
//
// CurrentLcb - represents the name of the CurrentFcb.
//
TYPE_OF_OPEN RelatedTypeOfOpen = UnopenedFileObject;
PFILE_OBJECT RelatedFileObject;
PCCB RelatedCcb = NULL;
PFCB NextFcb;
PFCB CurrentFcb = NULL;
PLCB CurrentLcb = NULL;
//
// During the open we need to combine the related file object name
// with the remaining name. We also may need to upcase the file name
// in order to do a case-insensitive name comparison. We also need
// to restore the name in the file object in the event that we retry
// the request. We use the following string variables to manage the
// name. We will can put these strings into either Unicode or Ansi
// form.
//
// FileName - Pointer to name as currently stored in the file
// object. We store the full name into the file object early in
// the open operation.
//
// RelatedFileName - Pointer to the name in the related file object.
//
// RemainingName - String containing remaining name to parse.
//
PUNICODE_STRING FileName;
PUNICODE_STRING RelatedFileName;
UNICODE_STRING RemainingName;
UNICODE_STRING FinalName;
PAGED_CODE();
//
// If we were called with our file system device object instead of a
// volume device object, just complete this request with STATUS_SUCCESS.
//
if (IrpContext->Vcb == NULL) {
UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
return STATUS_SUCCESS;
}
//
// Get create parameters from the Irp.
//
OpenByFileId = BooleanFlagOn( IrpSp->Parameters.Create.Options, FILE_OPEN_BY_FILE_ID );
IgnoreCase = !BooleanFlagOn( IrpSp->Flags, SL_CASE_SENSITIVE );
CreateDisposition = (IrpSp->Parameters.Create.Options >> 24) & 0x000000ff;
//
// Do some preliminary checks to make sure the operation is supported.
// We fail in the following cases immediately.
//
// - Open a paging file.
// - Open a target directory.
// - Open a file with Eas.
// - Create a file.
//
if (FlagOn( IrpSp->Flags, SL_OPEN_PAGING_FILE | SL_OPEN_TARGET_DIRECTORY) ||
(IrpSp->Parameters.Create.EaLength != 0) ||
(CreateDisposition == FILE_CREATE)) {
UdfCompleteRequest( IrpContext, Irp, STATUS_ACCESS_DENIED );
return STATUS_ACCESS_DENIED;
}
//
// Copy the Vcb to a local. Assume the starting directory is the root.
//
Vcb = IrpContext->Vcb;
NextFcb = Vcb->RootIndexFcb;
//
// Reference our input parameters to make things easier
//
FileObject = IrpSp->FileObject;
RelatedFileObject = NULL;
FileName = &FileObject->FileName;
//
// Set up the file object's Vpb pointer in case anything happens.
// This will allow us to get a reasonable pop-up.
//
if ((FileObject->RelatedFileObject != NULL) && !OpenByFileId) {
RelatedFileObject = FileObject->RelatedFileObject;
FileObject->Vpb = RelatedFileObject->Vpb;
RelatedTypeOfOpen = UdfDecodeFileObject( RelatedFileObject, &NextFcb, &RelatedCcb );
//
// Fail the request if this is not a user file object.
//
if (RelatedTypeOfOpen < UserVolumeOpen) {
UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
return STATUS_INVALID_PARAMETER;
}
//
// Remember the name in the related file object.
//
RelatedFileName = &RelatedFileObject->FileName;
}
//
// If we haven't initialized the names then make sure the strings are valid.
// If this an OpenByFileId then verify the file id buffer.
//
// After this routine returns we know that the full name is in the
// FileName buffer and the buffer will hold the upcased portion
// of the name yet to parse immediately after the full name in the
// buffer. Any trailing backslash has been removed and the flag
// in the IrpContext will indicate whether we removed the
// backslash.
//
Status = UdfNormalizeFileNames( IrpContext,
Vcb,
OpenByFileId,
IgnoreCase,
RelatedTypeOfOpen,
RelatedCcb,
RelatedFileName,
FileName,
&RemainingName );
//
// Return the error code if not successful.
//
if (!NT_SUCCESS( Status )) {
UdfCompleteRequest( IrpContext, Irp, Status );
return Status;
}
//
// We want to acquire the Vcb. Exclusively for a volume open, shared otherwise.
// The file name is empty for a volume open.
//
if ((FileName->Length == 0) &&
(RelatedTypeOfOpen <= UserVolumeOpen) &&
!OpenByFileId) {
VolumeOpen = TRUE;
UdfAcquireVcbExclusive( IrpContext, Vcb, FALSE );
} else {
UdfAcquireVcbShared( IrpContext, Vcb, FALSE );
}
//
// Use a try-finally to facilitate cleanup.
//
try {
//
// Verify that the Vcb is not in an unusable condition. This routine
// will raise if not usable.
//
UdfVerifyVcb( IrpContext, Vcb );
//
// If the Vcb is locked then we cannot open another file
//
if (FlagOn( Vcb->VcbState, VCB_STATE_LOCKED )) {
try_leave( Status = STATUS_ACCESS_DENIED );
}
//
// If we are opening this file by FileId then process this immediately
// and exit.
//
if (OpenByFileId) {
//
// The only create disposition we allow is OPEN.
//
if ((CreateDisposition != FILE_OPEN) &&
(CreateDisposition != FILE_OPEN_IF)) {
try_leave( Status = STATUS_ACCESS_DENIED );
}
try_leave( Status = UdfOpenObjectByFileId( IrpContext,
IrpSp,
Vcb,
&CurrentFcb ));
}
//
// If we are opening this volume Dasd then process this immediately
// and exit.
//
if (VolumeOpen) {
//
// The only create disposition we allow is OPEN.
//
if ((CreateDisposition != FILE_OPEN) &&
(CreateDisposition != FILE_OPEN_IF)) {
try_leave( Status = STATUS_ACCESS_DENIED );
}
//
// If they wanted to open a directory, surprise.
//
if (FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) {
try_leave( Status = STATUS_NOT_A_DIRECTORY );
}
//
// Acquire the Fcb first.
//
CurrentFcb = Vcb->VolumeDasdFcb;
UdfAcquireFcbExclusive( IrpContext, CurrentFcb, FALSE );
try_leave( Status = UdfOpenExistingFcb( IrpContext,
IrpSp,
&CurrentFcb,
NULL,
UserVolumeOpen,
FALSE,
NULL ));
}
//
// Acquire the Fcb at the beginning of our search to keep it from being
// deleted beneath us.
//
UdfAcquireFcbExclusive( IrpContext, NextFcb, FALSE );
CurrentFcb = NextFcb;
//
// Do a prefix search if there is more of the name to parse.
//
if (RemainingName.Length != 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -