📄 create.c
字号:
CCB LocalCcb;
UNICODE_STRING Lfn;
WCHAR LfnBuffer[ FAT_CREATE_INITIAL_NAME_BUF_SIZE];
//
// Get the current IRP stack location
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
DebugTrace(+1, Dbg, "FatCommonCreate\n", 0 );
DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp );
DebugTrace( 0, Dbg, "->Flags = %08lx\n", Irp->Flags );
DebugTrace( 0, Dbg, "->FileObject = %08lx\n", IrpSp->FileObject );
DebugTrace( 0, Dbg, " ->RelatedFileObject = %08lx\n", IrpSp->FileObject->RelatedFileObject );
DebugTrace( 0, Dbg, " ->FileName = %Z\n", &IrpSp->FileObject->FileName );
DebugTrace( 0, Dbg, "->AllocationSize.LowPart = %08lx\n", Irp->Overlay.AllocationSize.LowPart );
DebugTrace( 0, Dbg, "->AllocationSize.HighPart = %08lx\n", Irp->Overlay.AllocationSize.HighPart );
DebugTrace( 0, Dbg, "->SystemBuffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer );
DebugTrace( 0, Dbg, "->DesiredAccess = %08lx\n", IrpSp->Parameters.Create.SecurityContext->DesiredAccess );
DebugTrace( 0, Dbg, "->Options = %08lx\n", IrpSp->Parameters.Create.Options );
DebugTrace( 0, Dbg, "->FileAttributes = %04x\n", IrpSp->Parameters.Create.FileAttributes );
DebugTrace( 0, Dbg, "->ShareAccess = %04x\n", IrpSp->Parameters.Create.ShareAccess );
DebugTrace( 0, Dbg, "->EaLength = %08lx\n", IrpSp->Parameters.Create.EaLength );
//
// This is here because the Win32 layer can't avoid sending me double
// beginning backslashes.
//
if ((IrpSp->FileObject->FileName.Length > sizeof(WCHAR)) &&
(IrpSp->FileObject->FileName.Buffer[1] == L'\\') &&
(IrpSp->FileObject->FileName.Buffer[0] == L'\\')) {
IrpSp->FileObject->FileName.Length -= sizeof(WCHAR);
RtlMoveMemory( &IrpSp->FileObject->FileName.Buffer[0],
&IrpSp->FileObject->FileName.Buffer[1],
IrpSp->FileObject->FileName.Length );
//
// If there are still two beginning backslashes, the name is bogus.
//
if ((IrpSp->FileObject->FileName.Length > sizeof(WCHAR)) &&
(IrpSp->FileObject->FileName.Buffer[1] == L'\\') &&
(IrpSp->FileObject->FileName.Buffer[0] == L'\\')) {
FatCompleteRequest( IrpContext, Irp, STATUS_OBJECT_NAME_INVALID );
DebugTrace(-1, Dbg, "FatCommonCreate -> STATUS_OBJECT_NAME_INVALID\n", 0);
return STATUS_OBJECT_NAME_INVALID;
}
}
//
// Reference our input parameters to make things easier
//
ASSERT( IrpSp->Parameters.Create.SecurityContext != NULL );
FileObject = IrpSp->FileObject;
FileName = FileObject->FileName;
RelatedFileObject = FileObject->RelatedFileObject;
AllocationSize = Irp->Overlay.AllocationSize.LowPart;
EaBuffer = Irp->AssociatedIrp.SystemBuffer;
DesiredAccess = &IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
Options = IrpSp->Parameters.Create.Options;
FileAttributes = (UCHAR)(IrpSp->Parameters.Create.FileAttributes & ~FILE_ATTRIBUTE_NORMAL);
ShareAccess = IrpSp->Parameters.Create.ShareAccess;
EaLength = IrpSp->Parameters.Create.EaLength;
//
// Set up the file object's Vpb pointer in case anything happens.
// This will allow us to get a reasonable pop-up.
//
if ( RelatedFileObject != NULL ) {
FileObject->Vpb = RelatedFileObject->Vpb;
}
//
// Force setting the archive bit in the attributes byte to follow OS/2,
// & DOS semantics. Also mask out any extraneous bits, note that
// we can't use the ATTRIBUTE_VALID_FLAGS constant because that has
// the control and normal flags set.
//
// Delay setting ARCHIVE in case this is a directory: DavidGoe 2/16/95
//
FileAttributes &= (FILE_ATTRIBUTE_READONLY |
FILE_ATTRIBUTE_HIDDEN |
FILE_ATTRIBUTE_SYSTEM |
FILE_ATTRIBUTE_ARCHIVE );
//
// Locate the volume device object and Vcb that we are trying to access
//
Vcb = &((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->Vcb;
//
// Decipher Option flags and values
//
//
// If this is an open by fileid operation, just fail it explicitly. FAT's
// source of fileids is not reversible for open operations.
//
if (BooleanFlagOn( Options, FILE_OPEN_BY_FILE_ID )) {
FatCompleteRequest( IrpContext, Irp, STATUS_NOT_IMPLEMENTED );
return STATUS_NOT_IMPLEMENTED;
}
DirectoryFile = BooleanFlagOn( Options, FILE_DIRECTORY_FILE );
NonDirectoryFile = BooleanFlagOn( Options, FILE_NON_DIRECTORY_FILE );
SequentialOnly = BooleanFlagOn( Options, FILE_SEQUENTIAL_ONLY );
NoIntermediateBuffering = BooleanFlagOn( Options, FILE_NO_INTERMEDIATE_BUFFERING );
NoEaKnowledge = BooleanFlagOn( Options, FILE_NO_EA_KNOWLEDGE );
DeleteOnClose = BooleanFlagOn( Options, FILE_DELETE_ON_CLOSE );
TemporaryFile = BooleanFlagOn( IrpSp->Parameters.Create.FileAttributes,
FILE_ATTRIBUTE_TEMPORARY );
CreateDisposition = (Options >> 24) & 0x000000ff;
IsPagingFile = BooleanFlagOn( IrpSp->Flags, SL_OPEN_PAGING_FILE );
OpenTargetDirectory = BooleanFlagOn( IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY );
CreateDirectory = (BOOLEAN)(DirectoryFile &&
((CreateDisposition == FILE_CREATE) ||
(CreateDisposition == FILE_OPEN_IF)));
OpenDirectory = (BOOLEAN)(DirectoryFile &&
((CreateDisposition == FILE_OPEN) ||
(CreateDisposition == FILE_OPEN_IF)));
//
// Make sure the input large integer is valid and that the dir/nondir
// indicates a storage type we understand.
//
if (Irp->Overlay.AllocationSize.HighPart != 0 ||
(DirectoryFile && NonDirectoryFile)) {
FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
DebugTrace(-1, Dbg, "FatCommonCreate -> STATUS_INVALID_PARAMETER\n", 0);
return STATUS_INVALID_PARAMETER;
}
//
// Acquire exclusive access to the vcb, and enqueue the Irp if
// we didn't get it.
//
if (!FatAcquireExclusiveVcb( IrpContext, Vcb )) {
DebugTrace(0, Dbg, "Cannot acquire Vcb\n", 0);
Iosb.Status = FatFsdPostRequest( IrpContext, Irp );
DebugTrace(-1, Dbg, "FatCommonCreate -> %08lx\n", Iosb.Status );
return Iosb.Status;
}
//
// Make sure we haven't been called recursively by a filter inside an existing
// create request.
//
if (FlagOn( Vcb->VcbState, VCB_STATE_FLAG_CREATE_IN_PROGRESS)) {
FatBugCheck( 0, 0, 0);
}
//
// Initialize the DirentBcb to null
//
DirentBcb = NULL;
//
// Initialize our temp strings with their stack buffers.
//
OemFinalName.Length = 0;
OemFinalName.MaximumLength = sizeof( OemBuffer);
OemFinalName.Buffer = OemBuffer;
UpcasedFinalName.Length = 0;
UpcasedFinalName.MaximumLength = sizeof( UpcasedBuffer);
UpcasedFinalName.Buffer = UpcasedBuffer;
Lfn.Length = 0;
Lfn.MaximumLength = sizeof( LfnBuffer);
Lfn.Buffer = LfnBuffer;
try {
//
// Make sure the vcb is in a usable condition. This will raise
// and error condition if the volume is unusable
//
FatVerifyVcb( IrpContext, Vcb );
//
// If the Vcb is locked then we cannot open another file
//
if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_LOCKED)) {
DebugTrace(0, Dbg, "Volume is locked\n", 0);
Status = STATUS_ACCESS_DENIED;
if (Vcb->VcbCondition != VcbGood) {
Status = STATUS_VOLUME_DISMOUNTED;
}
try_return( Iosb.Status = Status );
}
//
// Don't allow the DELETE_ON_CLOSE option if the volume is
// write-protected.
//
if (DeleteOnClose && FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
//
// Set the real device for the pop-up info, and set the verify
// bit in the device object, so that we will force a verify
// in case the user put the correct media back in.
//
IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
Vcb->Vpb->RealDevice );
SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
FatRaiseStatus( IrpContext, STATUS_MEDIA_WRITE_PROTECTED );
}
//
// If this is a fat32 volume, EA's are not supported.
//
if (EaBuffer != NULL) {
try_return( Iosb.Status = STATUS_EAS_NOT_SUPPORTED );
}
//
// Check if we are opening the volume and not a file/directory.
// We are opening the volume if the name is empty and there
// isn't a related file object. If there is a related file object
// then it is the Vcb itself.
//
if (FileName.Length == 0) {
PVCB DecodeVcb;
if (RelatedFileObject == NULL ||
FatDecodeFileObject( RelatedFileObject,
&DecodeVcb,
&Fcb,
&Ccb ) == UserVolumeOpen) {
ASSERT( RelatedFileObject == NULL || Vcb == DecodeVcb );
//
// Check if we were to open a directory
//
if (DirectoryFile) {
DebugTrace(0, Dbg, "Cannot open volume as a directory\n", 0);
try_return( Iosb.Status = STATUS_NOT_A_DIRECTORY );
}
//
// Can't open the TargetDirectory of the DASD volume.
//
if (OpenTargetDirectory) {
try_return( Iosb.Status = STATUS_INVALID_PARAMETER );
}
DebugTrace(0, Dbg, "Opening the volume, Vcb = %08lx\n", Vcb);
CollectCreateHitStatistics(Vcb);
Iosb = FatOpenVolume( IrpContext,
FileObject,
Vcb,
DesiredAccess,
ShareAccess,
CreateDisposition );
Irp->IoStatus.Information = Iosb.Information;
try_return( Iosb.Status );
}
}
//
// If there is a related file object then this is a relative open.
// The related file object is the directory to start our search at.
// Return an error if it is not a directory.
//
if (RelatedFileObject != NULL) {
PVCB RelatedVcb;
PDCB RelatedDcb;
PCCB RelatedCcb;
TYPE_OF_OPEN TypeOfOpen;
TypeOfOpen = FatDecodeFileObject( RelatedFileObject,
&RelatedVcb,
&RelatedDcb,
&RelatedCcb );
if (TypeOfOpen != UserFileOpen &&
TypeOfOpen != UserDirectoryOpen) {
DebugTrace(0, Dbg, "Invalid related file object\n", 0);
try_return( Iosb.Status = STATUS_OBJECT_PATH_NOT_FOUND );
}
//
// A relative open must be via a relative path.
//
if (FileName.Length != 0 &&
FileName.Buffer[0] == L'\\') {
try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
}
//
// Set up the file object's Vpb pointer in case anything happens.
//
ASSERT( Vcb == RelatedVcb );
FileObject->Vpb = RelatedFileObject->Vpb;
//
// Now verify the related Fcb so we don't get in trouble later
// by assuming its in good shape.
//
FatVerifyFcb( IrpContext, RelatedDcb );
ParentDcb = RelatedDcb;
} else {
//
// This is not a relative open, so check if we're
// opening the root dcb
//
if ((FileName.Length == sizeof(WCHAR)) &&
(FileName.Buffer[0] == L'\\')) {
//
// Check if we were not supposed to open a directory
//
if (NonDirectoryFile) {
DebugTrace(0, Dbg, "Cannot open root directory as a file\n", 0);
try_return( Iosb.Status = STATUS_FILE_IS_A_DIRECTORY );
}
//
// Can't open the TargetDirectory of the root directory.
//
if (OpenTargetDirectory) {
try_return( Iosb.Status = STATUS_INVALID_PARAMETER );
}
//
// Not allowed to delete root directory.
//
if (DeleteOnClose) {
try_return( Iosb.Status = STATUS_CANNOT_DELETE );
}
DebugTrace(0, Dbg, "Opening root dcb\n", 0);
CollectCreateHitStatistics(Vcb);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -