mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
sys: FspVolumeFastTransact
This commit is contained in:
parent
43af829d46
commit
c0fa5696d7
@ -21,6 +21,7 @@
|
||||
|
||||
#include <sys/driver.h>
|
||||
|
||||
FAST_IO_DEVICE_CONTROL FspFastIoDeviceControl;
|
||||
static NTSTATUS FspFsctlDeviceControl(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
static NTSTATUS FspFsvrtDeviceControl(
|
||||
@ -35,6 +36,7 @@ static FSP_IOP_REQUEST_FINI FspFsvolDeviceControlRequestFini;
|
||||
FSP_DRIVER_DISPATCH FspDeviceControl;
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, FspFastIoDeviceControl)
|
||||
#pragma alloc_text(PAGE, FspFsctlDeviceControl)
|
||||
#pragma alloc_text(PAGE, FspFsvrtDeviceControl)
|
||||
#pragma alloc_text(PAGE, FspFsvrtDeviceControlStorageQuery)
|
||||
@ -49,6 +51,62 @@ enum
|
||||
RequestFileNode = 0,
|
||||
};
|
||||
|
||||
BOOLEAN FspFastIoDeviceControl(
|
||||
PFILE_OBJECT FileObject,
|
||||
BOOLEAN CanWait,
|
||||
PVOID InputBuffer,
|
||||
ULONG InputBufferLength,
|
||||
PVOID OutputBuffer,
|
||||
ULONG OutputBufferLength,
|
||||
ULONG IoControlCode,
|
||||
PIO_STATUS_BLOCK IoStatus,
|
||||
PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
FSP_ENTER_BOOL(PAGED_CODE());
|
||||
/* cannot use FSP_ENTER_FIO() because it only supports fsvol devices */
|
||||
|
||||
Result = DEBUGTEST(50) &&
|
||||
CanWait &&
|
||||
FSP_IOCTL_TRANSACT == IoControlCode &&
|
||||
FspFsctlDeviceExtensionKind == FspDeviceExtension(DeviceObject)->Kind;
|
||||
if (!Result)
|
||||
FSP_RETURN();
|
||||
|
||||
#if 0
|
||||
PDEVICE_OBJECT FsctlDeviceObject = DeviceObject;
|
||||
if (!FspDeviceReference(FsctlDeviceObject))
|
||||
{
|
||||
IoStatus->Status = STATUS_CANCELLED;
|
||||
IoStatus->Information = 0;
|
||||
FSP_RETURN();
|
||||
}
|
||||
#endif
|
||||
|
||||
ASSERT(0 == IoGetTopLevelIrp());
|
||||
IoSetTopLevelIrp((PIRP)FSRTL_FAST_IO_TOP_LEVEL_IRP);
|
||||
|
||||
IoStatus->Status = FspVolumeFastTransact(
|
||||
FileObject->FsContext2,
|
||||
IoControlCode,
|
||||
InputBuffer,
|
||||
InputBufferLength,
|
||||
OutputBuffer,
|
||||
OutputBufferLength,
|
||||
IoStatus,
|
||||
(PIRP)FSRTL_FAST_IO_TOP_LEVEL_IRP);
|
||||
|
||||
IoSetTopLevelIrp(0);
|
||||
|
||||
#if 0
|
||||
FspDeviceDereference(FsctlDeviceObject);
|
||||
#endif
|
||||
|
||||
FSP_LEAVE_BOOL(
|
||||
"%s, FileObject=%p",
|
||||
IoctlCodeSym(IoControlCode),
|
||||
FileObject);
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsctlDeviceControl(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
|
@ -97,7 +97,7 @@ NTSTATUS DriverEntry(
|
||||
//FspFastIoDispatch.FastIoUnlockSingle = 0;
|
||||
//FspFastIoDispatch.FastIoUnlockAll = 0;
|
||||
//FspFastIoDispatch.FastIoUnlockAllByKey = 0;
|
||||
//FspFastIoDispatch.FastIoDeviceControl = 0;
|
||||
FspFastIoDispatch.FastIoDeviceControl = FspFastIoDeviceControl;
|
||||
FspFastIoDispatch.AcquireFileForNtCreateSection = FspAcquireFileForNtCreateSection;
|
||||
FspFastIoDispatch.ReleaseFileForNtCreateSection = FspReleaseFileForNtCreateSection;
|
||||
//FspFastIoDispatch.FastIoDetachDevice = 0;
|
||||
|
@ -425,6 +425,7 @@ FSP_IOPREP_DISPATCH FspFsvolWritePrepare;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolWriteComplete;
|
||||
|
||||
/* fast I/O and resource acquisition callbacks */
|
||||
FAST_IO_DEVICE_CONTROL FspFastIoDeviceControl;
|
||||
FAST_IO_READ FspFastIoRead;
|
||||
FAST_IO_WRITE FspFastIoWrite;
|
||||
FAST_IO_QUERY_BASIC_INFO FspFastIoQueryBasicInfo;
|
||||
@ -687,6 +688,8 @@ NTSTATUS FspOplockFsctrl(
|
||||
FspNotifyFullReportChange(NS, NL, (PSTRING)(FN), FO, 0, (PSTRING)(NP), F, A, 0)
|
||||
#define FSP_NEXT_EA(Ea, EaEnd) \
|
||||
(0 != (Ea)->NextEntryOffset ? (PVOID)((PUINT8)(Ea) + (Ea)->NextEntryOffset) : (EaEnd))
|
||||
#define FSP_FUNCTION_FROM_CTL_CODE(ControlCode)\
|
||||
(((ControlCode) >> 2) & 0xfff)
|
||||
|
||||
/* utility: synchronous work queue */
|
||||
typedef struct
|
||||
@ -926,7 +929,7 @@ retry:
|
||||
{
|
||||
if (PsIsThreadTerminating(PsGetCurrentThread()))
|
||||
return STATUS_THREAD_IS_TERMINATING;
|
||||
if (0 != Irp && Irp->Cancel)
|
||||
if (0 != Irp && ((PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG >= Irp || Irp->Cancel))
|
||||
return STATUS_CANCELLED;
|
||||
if (0 != ExpirationTime)
|
||||
{
|
||||
@ -1424,6 +1427,15 @@ NTSTATUS FspVolumeGetNameList(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeTransact(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeFastTransact(
|
||||
PDEVICE_OBJECT FsvolDeviceObject,
|
||||
ULONG ControlCode,
|
||||
PVOID InputBuffer,
|
||||
ULONG InputBufferLength,
|
||||
PVOID OutputBuffer,
|
||||
ULONG OutputBufferLength,
|
||||
PIO_STATUS_BLOCK IoStatus,
|
||||
PIRP Irp);
|
||||
NTSTATUS FspVolumeTransactFsext(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeStop(
|
||||
|
@ -152,6 +152,7 @@
|
||||
#define FspIoqEventSet(E) KeSetEvent(E, 1, FALSE)
|
||||
#define FspIoqEventCancellableWait(E,T,I) FsRtlCancellableWaitForSingleObject(E,T,I)
|
||||
#define FspIoqEventClear(E) KeClearEvent(E)
|
||||
#error FsRtlCancellableWaitForSingleObject needs to support FSRTL_FAST_IO_TOP_LEVEL_IRP cancellation
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -46,6 +46,15 @@ static NTSTATUS FspVolumeGetNameListNoLock(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeTransact(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeFastTransact(
|
||||
PDEVICE_OBJECT FsvolDeviceObject,
|
||||
ULONG ControlCode,
|
||||
PVOID InputBuffer,
|
||||
ULONG InputBufferLength,
|
||||
PVOID OutputBuffer,
|
||||
ULONG OutputBufferLength,
|
||||
PIO_STATUS_BLOCK IoStatus,
|
||||
PIRP Irp);
|
||||
NTSTATUS FspVolumeTransactFsext(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeStop(
|
||||
@ -71,6 +80,7 @@ NTSTATUS FspVolumeWork(
|
||||
#pragma alloc_text(PAGE, FspVolumeGetNameList)
|
||||
#pragma alloc_text(PAGE, FspVolumeGetNameListNoLock)
|
||||
#pragma alloc_text(PAGE, FspVolumeTransact)
|
||||
#pragma alloc_text(PAGE, FspVolumeFastTransact)
|
||||
#pragma alloc_text(PAGE, FspVolumeTransactFsext)
|
||||
#pragma alloc_text(PAGE, FspVolumeStop)
|
||||
#pragma alloc_text(PAGE, FspVolumeNotify)
|
||||
@ -787,11 +797,12 @@ NTSTATUS FspVolumeTransact(
|
||||
/* check parameters */
|
||||
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
|
||||
ULONG ControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
|
||||
ULONG ControlFunction = FSP_FUNCTION_FROM_CTL_CODE(ControlCode);
|
||||
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
|
||||
ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
|
||||
PVOID InputBuffer = 0;
|
||||
PVOID OutputBuffer = 0;
|
||||
if (0x800 + 'I' /*FSP_xxCTL_TRANSACT_INTERNAL*/ == ((ControlCode >> 2) & 0xfff))
|
||||
if (FSP_FUNCTION_FROM_CTL_CODE(FSP_FSCTL_TRANSACT_INTERNAL) == ControlFunction)
|
||||
{
|
||||
InputBuffer = IrpSp->Parameters.FileSystemControl.Type3InputBuffer;
|
||||
if (KernelMode != Irp->RequestorMode)
|
||||
@ -808,13 +819,36 @@ NTSTATUS FspVolumeTransact(
|
||||
FSP_FSCTL_DEFAULT_ALIGN_UP(sizeof(FSP_FSCTL_TRANSACT_RSP)) > InputBufferLength)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if (0 != OutputBufferLength &&
|
||||
((0x800 + 'T' /*FSP_xxCTL_TRANSACT*/ == ((ControlCode >> 2) & 0xfff) &&
|
||||
((FSP_FUNCTION_FROM_CTL_CODE(FSP_FSCTL_TRANSACT) == ControlFunction &&
|
||||
FSP_FSCTL_TRANSACT_BUFFER_SIZEMIN > OutputBufferLength) ||
|
||||
(0x800 + 't' /*FSP_xxCTL_TRANSACT_BATCH*/ == ((ControlCode >> 2) & 0xfff) &&
|
||||
(FSP_FUNCTION_FROM_CTL_CODE(FSP_FSCTL_TRANSACT_BATCH) == ControlFunction &&
|
||||
FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN > OutputBufferLength)))
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
return FspVolumeFastTransact(
|
||||
FsvolDeviceObject,
|
||||
ControlCode,
|
||||
InputBuffer,
|
||||
InputBufferLength,
|
||||
OutputBuffer,
|
||||
OutputBufferLength,
|
||||
&Irp->IoStatus,
|
||||
Irp);
|
||||
}
|
||||
|
||||
NTSTATUS FspVolumeFastTransact(
|
||||
PDEVICE_OBJECT FsvolDeviceObject,
|
||||
ULONG ControlCode,
|
||||
PVOID InputBuffer,
|
||||
ULONG InputBufferLength,
|
||||
PVOID OutputBuffer,
|
||||
ULONG OutputBufferLength,
|
||||
PIO_STATUS_BLOCK IoStatus,
|
||||
PIRP Irp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
if (!FspDeviceReference(FsvolDeviceObject))
|
||||
return STATUS_CANCELLED;
|
||||
|
||||
@ -825,6 +859,7 @@ NTSTATUS FspVolumeTransact(
|
||||
|
||||
NTSTATUS Result;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
ULONG ControlFunction = FSP_FUNCTION_FROM_CTL_CODE(ControlCode);
|
||||
PUINT8 BufferEnd;
|
||||
FSP_FSCTL_TRANSACT_RSP *Response, *NextResponse;
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, *PendingIrpRequest;
|
||||
@ -894,27 +929,30 @@ NTSTATUS FspVolumeTransact(
|
||||
}
|
||||
}
|
||||
|
||||
/* were we sent an output buffer? */
|
||||
switch (ControlCode & 3)
|
||||
if ((PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG < Irp)
|
||||
{
|
||||
case METHOD_NEITHER:
|
||||
OutputBuffer = Irp->UserBuffer;
|
||||
break;
|
||||
case METHOD_OUT_DIRECT:
|
||||
if (0 != Irp->MdlAddress)
|
||||
OutputBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
|
||||
break;
|
||||
case METHOD_BUFFERED:
|
||||
if (0 != OutputBufferLength)
|
||||
OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
/* were we sent an output buffer? */
|
||||
switch (ControlCode & 3)
|
||||
{
|
||||
case METHOD_NEITHER:
|
||||
OutputBuffer = Irp->UserBuffer;
|
||||
break;
|
||||
case METHOD_OUT_DIRECT:
|
||||
if (0 != Irp->MdlAddress)
|
||||
OutputBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
|
||||
break;
|
||||
case METHOD_BUFFERED:
|
||||
if (0 != OutputBufferLength)
|
||||
OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (0 == OutputBuffer)
|
||||
{
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoStatus->Information = 0;
|
||||
Result = STATUS_SUCCESS;
|
||||
goto exit;
|
||||
}
|
||||
@ -935,7 +973,7 @@ NTSTATUS FspVolumeTransact(
|
||||
}
|
||||
if (FspIoqTimeout == PendingIrp || FspIoqCancelled == PendingIrp)
|
||||
{
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoStatus->Information = 0;
|
||||
Result = FspIoqTimeout == PendingIrp ? STATUS_SUCCESS : STATUS_CANCELLED;
|
||||
goto exit;
|
||||
}
|
||||
@ -944,7 +982,7 @@ NTSTATUS FspVolumeTransact(
|
||||
RepostedIrp = 0;
|
||||
Request = OutputBuffer;
|
||||
BufferEnd = (PUINT8)OutputBuffer + OutputBufferLength;
|
||||
ASSERT(FSP_FSCTL_TRANSACT_INTERNAL == ControlCode ?
|
||||
ASSERT(FSP_FUNCTION_FROM_CTL_CODE(FSP_FSCTL_TRANSACT_INTERNAL) == ControlFunction ?
|
||||
TRUE :
|
||||
FspFsctlTransactCanProduceRequest(Request, BufferEnd));
|
||||
LoopCount = FspIoqPendingIrpCount(FsvolDeviceExtension->Ioq);
|
||||
@ -967,7 +1005,7 @@ NTSTATUS FspVolumeTransact(
|
||||
FspIopCompleteIrp(PendingIrp, Result);
|
||||
else
|
||||
{
|
||||
if (FSP_FSCTL_TRANSACT_INTERNAL == ControlCode)
|
||||
if (FSP_FUNCTION_FROM_CTL_CODE(FSP_FSCTL_TRANSACT_INTERNAL) == ControlFunction)
|
||||
{
|
||||
InternalBuffer = FspAllocatePoolMustSucceed(
|
||||
PagedPool, PendingIrpRequest->Size, FSP_ALLOC_EXTERNAL_TAG);
|
||||
@ -991,7 +1029,7 @@ NTSTATUS FspVolumeTransact(
|
||||
ASSERT(FspIoqStopped(FsvolDeviceExtension->Ioq));
|
||||
if (0 != InternalBuffer)
|
||||
{
|
||||
ASSERT(FSP_FSCTL_TRANSACT_INTERNAL == ControlCode);
|
||||
ASSERT(FSP_FUNCTION_FROM_CTL_CODE(FSP_FSCTL_TRANSACT_INTERNAL) == ControlFunction);
|
||||
*(PVOID *)OutputBuffer = 0;
|
||||
FspFree(InternalBuffer);
|
||||
}
|
||||
@ -1001,14 +1039,14 @@ NTSTATUS FspVolumeTransact(
|
||||
}
|
||||
|
||||
/* are we doing single request or batch mode? */
|
||||
if (FSP_FSCTL_TRANSACT_INTERNAL == ControlCode)
|
||||
if (FSP_FUNCTION_FROM_CTL_CODE(FSP_FSCTL_TRANSACT_INTERNAL) == ControlFunction)
|
||||
{
|
||||
Irp->IoStatus.Information = sizeof(PVOID);
|
||||
IoStatus->Information = sizeof(PVOID);
|
||||
Result = STATUS_SUCCESS;
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
if (FSP_FSCTL_TRANSACT == ControlCode)
|
||||
if (FSP_FUNCTION_FROM_CTL_CODE(FSP_FSCTL_TRANSACT) == ControlFunction)
|
||||
break;
|
||||
|
||||
/* check that we have enough space before pulling the next pending IRP off the queue */
|
||||
@ -1025,7 +1063,7 @@ NTSTATUS FspVolumeTransact(
|
||||
break;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Information = (PUINT8)Request - (PUINT8)OutputBuffer;
|
||||
IoStatus->Information = (PUINT8)Request - (PUINT8)OutputBuffer;
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
|
Loading…
x
Reference in New Issue
Block a user