sys,dll: DeviceControl operation

This commit is contained in:
Bill Zissimopoulos
2018-05-04 13:56:20 -07:00
parent 7aadf259d9
commit 894ae7b8f3
10 changed files with 296 additions and 5 deletions

View File

@ -162,6 +162,7 @@ FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath,
FileSystem->Operations[FspFsctlTransactSetVolumeInformationKind] = FspFileSystemOpSetVolumeInformation;
FileSystem->Operations[FspFsctlTransactQueryDirectoryKind] = FspFileSystemOpQueryDirectory;
FileSystem->Operations[FspFsctlTransactFileSystemControlKind] = FspFileSystemOpFileSystemControl;
FileSystem->Operations[FspFsctlTransactDeviceControlKind] = FspFileSystemOpDeviceControl;
FileSystem->Operations[FspFsctlTransactQuerySecurityKind] = FspFileSystemOpQuerySecurity;
FileSystem->Operations[FspFsctlTransactSetSecurityKind] = FspFileSystemOpSetSecurity;
FileSystem->Operations[FspFsctlTransactQueryStreamInformationKind] = FspFileSystemOpQueryStreamInformation;

View File

@ -1247,6 +1247,30 @@ FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
return Result;
}
FSP_API NTSTATUS FspFileSystemOpDeviceControl(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
{
NTSTATUS Result;
ULONG BytesTransferred;
if (0 == FileSystem->Interface->Control)
return STATUS_INVALID_DEVICE_REQUEST;
Result = FileSystem->Interface->Control(FileSystem,
(PVOID)ValOfFileContext(Request->Req.DeviceControl),
Request->Req.DeviceControl.IoControlCode,
Request->Buffer, Request->Req.DeviceControl.Buffer.Size,
Response->Buffer, Request->Req.DeviceControl.OutputLength/* FSD guarantees correct size! */,
&BytesTransferred);
if (!NT_SUCCESS(Result))
return STATUS_BUFFER_OVERFLOW != Result ? Result : STATUS_BUFFER_TOO_SMALL;
Response->Size = (UINT16)(sizeof *Response + BytesTransferred);
Response->Rsp.DeviceControl.Buffer.Offset = 0;
Response->Rsp.DeviceControl.Buffer.Size = (UINT16)BytesTransferred;
return STATUS_SUCCESS;
}
FSP_API NTSTATUS FspFileSystemOpQuerySecurity(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
{

View File

@ -20,20 +20,81 @@
static NTSTATUS FspFsvolDeviceControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
FSP_IOCMPL_DISPATCH FspFsvolDeviceControlComplete;
static FSP_IOP_REQUEST_FINI FspFsvolDeviceControlRequestFini;
FSP_DRIVER_DISPATCH FspDeviceControl;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFsvolDeviceControl)
#pragma alloc_text(PAGE, FspFsvolDeviceControlComplete)
#pragma alloc_text(PAGE, FspFsvolDeviceControlRequestFini)
#pragma alloc_text(PAGE, FspDeviceControl)
#endif
enum
{
RequestFileNode = 0,
};
static NTSTATUS FspFsvolDeviceControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
PAGED_CODE();
return STATUS_INVALID_DEVICE_REQUEST;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
PFILE_OBJECT FileObject = IrpSp->FileObject;
ULONG IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
/* do we support DeviceControl? */
if (!FsvolDeviceExtension->VolumeParams.DeviceControl)
return STATUS_INVALID_DEVICE_REQUEST;
/* do not forward IRP's originating in the kernel! */
if (KernelMode == Irp->RequestorMode)
return STATUS_INVALID_DEVICE_REQUEST;
/* only allow custom devices and METHOD_BUFFERED */
if (0 == (DEVICE_TYPE_FROM_CTL_CODE(IoControlCode) & 0x8000) ||
METHOD_BUFFERED != METHOD_FROM_CTL_CODE(IoControlCode))
return STATUS_INVALID_DEVICE_REQUEST;
/* is this a valid FileObject? */
if (!FspFileNodeIsValid(FileObject->FsContext))
return STATUS_INVALID_PARAMETER;
NTSTATUS Result;
FSP_FILE_NODE *FileNode = FileObject->FsContext;
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
PVOID InputBuffer = Irp->AssociatedIrp.SystemBuffer;
ULONG InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
FSP_FSCTL_TRANSACT_REQ *Request;
ASSERT(FileNode == FileDesc->FileNode);
if (FSP_FSCTL_DEVICECONTROL_SIZEMAX < InputBufferLength ||
FSP_FSCTL_DEVICECONTROL_SIZEMAX < OutputBufferLength)
return STATUS_INVALID_BUFFER_SIZE;
Result = FspIopCreateRequestEx(Irp, 0, InputBufferLength,
FspFsvolDeviceControlRequestFini, &Request);
if (!NT_SUCCESS(Result))
return Result;
FspFileNodeAcquireShared(FileNode, Full);
Request->Kind = FspFsctlTransactDeviceControlKind;
Request->Req.DeviceControl.UserContext = FileNode->UserContext;
Request->Req.DeviceControl.UserContext2 = FileDesc->UserContext2;
Request->Req.DeviceControl.IoControlCode = IoControlCode;
Request->Req.DeviceControl.Buffer.Offset = 0;
Request->Req.DeviceControl.Buffer.Size = (UINT16)InputBufferLength;
Request->Req.DeviceControl.OutputLength = OutputBufferLength;
RtlCopyMemory(Request->Buffer, InputBuffer, InputBufferLength);
FspFileNodeSetOwner(FileNode, Full, Request);
FspIopRequestContext(Request, RequestFileNode) = FileNode;
return FSP_STATUS_IOQ_POST;
}
NTSTATUS FspFsvolDeviceControlComplete(
@ -41,12 +102,46 @@ NTSTATUS FspFsvolDeviceControlComplete(
{
FSP_ENTER_IOC(PAGED_CODE());
if (!NT_SUCCESS(Response->IoStatus.Status))
{
Irp->IoStatus.Information = 0;
Result = Response->IoStatus.Status;
FSP_RETURN();
}
PVOID OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
if (Response->Buffer + Response->Rsp.DeviceControl.Buffer.Offset +
Response->Rsp.DeviceControl.Buffer.Size > (PUINT8)Response + Response->Size)
FSP_RETURN(Result = STATUS_INTERNAL_ERROR);
if (OutputBufferLength >= Response->Rsp.DeviceControl.Buffer.Size)
OutputBufferLength = Response->Rsp.DeviceControl.Buffer.Size;
else
Result = STATUS_BUFFER_OVERFLOW;
RtlCopyMemory(OutputBuffer, Response->Buffer + Response->Rsp.DeviceControl.Buffer.Offset,
OutputBufferLength);
Irp->IoStatus.Information = OutputBufferLength;
FSP_LEAVE_IOC(
"%s, FileObject=%p",
IoctlCodeSym(IrpSp->Parameters.DeviceIoControl.IoControlCode),
IrpSp->FileObject);
}
static VOID FspFsvolDeviceControlRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4])
{
PAGED_CODE();
FSP_FILE_NODE *FileNode = Context[RequestFileNode];
if (0 != FileNode)
FspFileNodeReleaseOwner(FileNode, Full, Request);
}
NTSTATUS FspDeviceControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp)
{