2020-09-30 17:17:25 +02:00

141 lines
3.5 KiB
C

/*++
Copyright (c) 2000-2001 Microsoft Corporation
Module Name:
create.c
Abstract:
This module implements routines related to handling IRP_MJ_CREATE.
--*/
#include "rawx.h"
NTSTATUS
RawxFsdCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is called by the I/O manager to handle IRP_MJ_CREATE requests.
Arguments:
DeviceObject - Specifies the device object that the I/O request is for.
Irp - Specifies the packet that describes the I/O request.
Return Value:
Status of operation.
--*/
{
NTSTATUS status;
PRAW_VOLUME_EXTENSION VolumeExtension;
PIO_STACK_LOCATION IrpSp;
ACCESS_MASK DesiredAccess;
USHORT ShareAccess;
ULONG CreateOptions;
PFILE_OBJECT FileObject;
ULONG CreateDisposition;
VolumeExtension = (PRAW_VOLUME_EXTENSION)DeviceObject->DeviceExtension;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
DesiredAccess = IrpSp->Parameters.Create.DesiredAccess;
ShareAccess = IrpSp->Parameters.Create.ShareAccess;
CreateOptions = IrpSp->Parameters.Create.Options;
FileObject = IrpSp->FileObject;
RawxAcquireVolumeMutexExclusive(VolumeExtension);
//
// Check if the volume has been dismounted.
//
if (VolumeExtension->Dismounted) {
status = STATUS_VOLUME_DISMOUNTED;
goto CleanupAndExit;
}
//
// Don't allow a relative path to be opened.
//
if (IrpSp->FileObject->RelatedFileObject != NULL) {
status = STATUS_INVALID_PARAMETER;
goto CleanupAndExit;
} else if (IrpSp->Parameters.Create.RemainingName->Length != 0) {
status = STATUS_OBJECT_PATH_NOT_FOUND;
goto CleanupAndExit;
}
//
// Verify that the create disposition is for open access only.
//
CreateDisposition = (CreateOptions >> 24) & 0xFF;
if ((CreateDisposition != FILE_OPEN) && (CreateDisposition != FILE_OPEN_IF)) {
status = STATUS_ACCESS_DENIED;
goto CleanupAndExit;
}
//
// The caller shouldn't be expecting to see a directory file.
//
if (RawxIsFlagSet(CreateOptions, FILE_DIRECTORY_FILE)) {
status = STATUS_NOT_A_DIRECTORY;
goto CleanupAndExit;
}
//
// If this is the first open handle to the file, then initialize the sharing
// mode. Otherwise, verify that the requested sharing mode is compatible
// with the current sharing mode.
//
if (VolumeExtension->ShareAccess.OpenCount == 0) {
IoSetShareAccess(DesiredAccess, ShareAccess, FileObject,
&VolumeExtension->ShareAccess);
status = STATUS_SUCCESS;
} else {
status = IoCheckShareAccess(DesiredAccess, ShareAccess, FileObject,
&VolumeExtension->ShareAccess, TRUE);
}
if (NT_SUCCESS(status)) {
//
// Physical volume access is always non-cached. Mark the file object as
// non-cached so that the I/O manager enforces alignment requirements.
//
FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
//
// Indicate to the caller that we opened the file as opposed to creating
// or overwriting the file.
//
Irp->IoStatus.Information = FILE_OPENED;
status = STATUS_SUCCESS;
}
CleanupAndExit:
RawxReleaseVolumeMutex(VolumeExtension);
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}