📄 create.c
字号:
/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
Create.c
Abstract:
This module implements the File Create routine for Cdfs called by the
Fsd/Fsp dispatch routines.
--*/
#include "CdProcs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (CDFS_BUG_CHECK_CREATE)
//
// Local support routines
//
NTSTATUS
CdNormalizeFileNames (
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 PCD_NAME RemainingName
);
NTSTATUS
CdOpenByFileId (
IN PIRP_CONTEXT IrpContext,
IN PIO_STACK_LOCATION IrpSp,
IN PVCB Vcb,
IN OUT PFCB *CurrentFcb
);
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
);
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
);
NTSTATUS
CdOpenFileFromFileContext (
IN PIRP_CONTEXT IrpContext,
IN PIO_STACK_LOCATION IrpSp,
IN PVCB Vcb,
IN OUT PFCB *CurrentFcb,
IN PCD_NAME FileName,
IN BOOLEAN IgnoreCase,
IN BOOLEAN ShortNameMatch,
IN PFILE_ENUM_CONTEXT FileContext,
IN PCCB RelatedCcb OPTIONAL
);
NTSTATUS
CdCompleteFcbOpen (
IN PIRP_CONTEXT IrpContext,
PIO_STACK_LOCATION IrpSp,
IN PVCB Vcb,
IN OUT PFCB *CurrentFcb,
IN TYPE_OF_OPEN TypeOfOpen,
IN ULONG UserCcbFlags,
IN ACCESS_MASK DesiredAccess
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, CdCommonCreate)
#pragma alloc_text(PAGE, CdCompleteFcbOpen)
#pragma alloc_text(PAGE, CdNormalizeFileNames)
#pragma alloc_text(PAGE, CdOpenByFileId)
#pragma alloc_text(PAGE, CdOpenDirectoryFromPathEntry)
#pragma alloc_text(PAGE, CdOpenExistingFcb)
#pragma alloc_text(PAGE, CdOpenFileFromFileContext)
#endif
NTSTATUS
CdCommonCreate (
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 this is not a Joliet disk then we will convert the unicode name to
an Oem string in this routine. 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;
COMPOUND_PATH_ENTRY CompoundPathEntry;
BOOLEAN CleanupCompoundPathEntry = FALSE;
FILE_ENUM_CONTEXT FileContext;
BOOLEAN CleanupFileContext = FALSE;
BOOLEAN FoundEntry;
PVCB Vcb;
BOOLEAN OpenByFileId;
BOOLEAN IgnoreCase;
ULONG CreateDisposition;
BOOLEAN ShortNameMatch;
ULONG ShortNameDirentOffset;
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.
//
TYPE_OF_OPEN RelatedTypeOfOpen = UnopenedFileObject;
PFILE_OBJECT RelatedFileObject;
PCCB RelatedCcb = NULL;
PFCB NextFcb;
PFCB CurrentFcb = 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.
//
// MatchingName - Address of name structure in FileContext which matched.
// We need this to know whether we matched the long or short name.
//
PUNICODE_STRING FileName;
PUNICODE_STRING RelatedFileName = NULL;
CD_NAME RemainingName;
CD_NAME FinalName;
PCD_NAME MatchingName;
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) {
CdCompleteRequest( 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)) {
CdCompleteRequest( 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 = CdDecodeFileObject( IrpContext, RelatedFileObject, &NextFcb, &RelatedCcb );
//
// Fail the request if this is not a user file object.
//
if (RelatedTypeOfOpen < UserVolumeOpen) {
CdCompleteRequest( 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 = CdNormalizeFileNames( IrpContext,
Vcb,
OpenByFileId,
IgnoreCase,
RelatedTypeOfOpen,
RelatedCcb,
RelatedFileName,
FileName,
&RemainingName );
//
// Return the error code if not successful.
//
if (!NT_SUCCESS( Status )) {
CdCompleteRequest( 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;
CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
} else {
CdAcquireVcbShared( 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.
//
CdVerifyVcb( IrpContext, Vcb );
//
// If the Vcb is locked then we cannot open another file
//
if (FlagOn( Vcb->VcbState, VCB_STATE_LOCKED )) {
try_return( Status = STATUS_ACCESS_DENIED );
}
//
// If we are opening this file by FileId then process this immediately
// and exit.
//
if (OpenByFileId) {
//
// We only allow Dasd opens of audio disks. Fail this request at
// this point.
//
if (FlagOn( Vcb->VcbState, VCB_STATE_AUDIO_DISK )) {
try_return( Status = STATUS_INVALID_DEVICE_REQUEST );
}
//
// The only create disposition we allow is OPEN.
//
if ((CreateDisposition != FILE_OPEN) &&
(CreateDisposition != FILE_OPEN_IF)) {
try_return( Status = STATUS_ACCESS_DENIED );
}
//
// Make sure we can wait for this request.
//
if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
CdRaiseStatus( IrpContext, STATUS_CANT_WAIT );
}
try_return( Status = CdOpenByFileId( IrpContext,
IrpSp,
Vcb,
&CurrentFcb ));
}
//
// If we are opening this volume Dasd then process this immediately
// and exit.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -