From d1fe27f996d44065804ef4195f8d1a36dbe99ea0 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Mon, 15 Feb 2016 15:07:05 -0800 Subject: [PATCH] sys: FSP_FSCTL_TRANSACT/FSP_FSCTL_TRANSACT_BATCH --- inc/winfsp/fsctl.h | 5 ++++- src/dll/fsctl.c | 6 ++++-- src/dll/loop.c | 8 ++++---- src/sys/debug.c | 1 + src/sys/fsctl.c | 1 + src/sys/volume.c | 14 ++++++++++++-- tst/winfsp-tests/mount-test.c | 4 ++-- tst/winfsp-tests/timeout-test.c | 6 +++--- 8 files changed, 31 insertions(+), 14 deletions(-) diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index c4853301..8ba9b2d8 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -36,6 +36,8 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'N', METHOD_BUFFERED, FILE_ANY_ACCESS) #define FSP_FSCTL_TRANSACT \ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'T', METHOD_OUT_DIRECT, FILE_ANY_ACCESS) +#define FSP_FSCTL_TRANSACT_BATCH \ + CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 't', METHOD_OUT_DIRECT, FILE_ANY_ACCESS) #define FSP_FSCTL_VOLUME_NAME_SIZEMAX 128 @@ -317,7 +319,8 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath, PHANDLE PVolumeHandle); FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle, PVOID ResponseBuf, SIZE_T ResponseBufSize, - PVOID RequestBuf, SIZE_T *PRequestBufSize); + PVOID RequestBuf, SIZE_T *PRequestBufSize, + BOOLEAN Batch); #endif #ifdef __cplusplus diff --git a/src/dll/fsctl.c b/src/dll/fsctl.c index 0cff67e4..2144006d 100644 --- a/src/dll/fsctl.c +++ b/src/dll/fsctl.c @@ -84,7 +84,8 @@ exit: FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle, PVOID ResponseBuf, SIZE_T ResponseBufSize, - PVOID RequestBuf, SIZE_T *PRequestBufSize) + PVOID RequestBuf, SIZE_T *PRequestBufSize, + BOOLEAN Batch) { NTSTATUS Result = STATUS_SUCCESS; DWORD Bytes = 0; @@ -95,7 +96,8 @@ FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle, *PRequestBufSize = 0; } - if (!DeviceIoControl(VolumeHandle, FSP_FSCTL_TRANSACT, + if (!DeviceIoControl(VolumeHandle, + Batch ? FSP_FSCTL_TRANSACT_BATCH : FSP_FSCTL_TRANSACT, ResponseBuf, (DWORD)ResponseBufSize, RequestBuf, Bytes, &Bytes, 0)) { diff --git a/src/dll/loop.c b/src/dll/loop.c index 90290bd0..0ba42508 100644 --- a/src/dll/loop.c +++ b/src/dll/loop.c @@ -70,14 +70,14 @@ FSP_API NTSTATUS FspFileSystemLoop(FSP_FILE_SYSTEM *FileSystem) SIZE_T RequestBufSize; FSP_FSCTL_TRANSACT_REQ *Request, *NextRequest; - RequestBuf = MemAlloc(FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMIN); + RequestBuf = MemAlloc(FSP_FSCTL_TRANSACT_REQ_SIZEMAX); if (0 == RequestBuf) return STATUS_INSUFFICIENT_RESOURCES; for (;;) { - RequestBufSize = FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMIN; - Result = FspFsctlTransact(FileSystem->VolumeHandle, 0, 0, RequestBuf, &RequestBufSize); + RequestBufSize = FSP_FSCTL_TRANSACT_REQ_SIZEMAX; + Result = FspFsctlTransact(FileSystem->VolumeHandle, 0, 0, RequestBuf, &RequestBufSize, FALSE); if (!NT_SUCCESS(Result)) goto exit; @@ -178,7 +178,7 @@ FSP_API VOID FspFileSystemPoolDispatcher(FSP_FILE_SYSTEM *FileSystem, FSP_API NTSTATUS FspFileSystemSendResponse(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_RSP *Response) { - return FspFsctlTransact(FileSystem->VolumeHandle, Response, Response->Size, 0, 0); + return FspFsctlTransact(FileSystem->VolumeHandle, Response, Response->Size, 0, 0, FALSE); } FSP_API NTSTATUS FspFileSystemSendResponseWithStatus(FSP_FILE_SYSTEM *FileSystem, diff --git a/src/sys/debug.c b/src/sys/debug.c index a00514a6..b568e759 100644 --- a/src/sys/debug.c +++ b/src/sys/debug.c @@ -159,6 +159,7 @@ const char *IoctlCodeSym(ULONG ControlCode) { SYM(FSP_FSCTL_VOLUME_NAME) SYM(FSP_FSCTL_TRANSACT) + SYM(FSP_FSCTL_TRANSACT_BATCH) SYM(FSP_FSCTL_WORK) SYM(FSP_FSCTL_WORK_BEST_EFFORT) // cygwin: sed -n '/[IF][OS]CTL.*CTL_CODE/s/^#define[ \t]*\([^ \t]*\).*/SYM(\1)/p' diff --git a/src/sys/fsctl.c b/src/sys/fsctl.c index 3ba5820e..104303a9 100644 --- a/src/sys/fsctl.c +++ b/src/sys/fsctl.c @@ -36,6 +36,7 @@ static NTSTATUS FspFsctlFileSystemControl( Result = FspVolumeGetName(DeviceObject, Irp, IrpSp); break; case FSP_FSCTL_TRANSACT: + case FSP_FSCTL_TRANSACT_BATCH: if (0 != IrpSp->FileObject->FsContext2) Result = FspVolumeTransact(DeviceObject, Irp, IrpSp); break; diff --git a/src/sys/volume.c b/src/sys/volume.c index 54772f9e..29a5e324 100644 --- a/src/sys/volume.c +++ b/src/sys/volume.c @@ -496,11 +496,14 @@ NTSTATUS FspVolumeTransact( ASSERT(IRP_MJ_FILE_SYSTEM_CONTROL == IrpSp->MajorFunction); ASSERT(IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction); - ASSERT(FSP_FSCTL_TRANSACT == IrpSp->Parameters.FileSystemControl.FsControlCode); + ASSERT( + FSP_FSCTL_TRANSACT == IrpSp->Parameters.FileSystemControl.FsControlCode || + FSP_FSCTL_TRANSACT_BATCH == IrpSp->Parameters.FileSystemControl.FsControlCode); ASSERT(0 != IrpSp->FileObject->FsContext2); /* check parameters */ PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2; + ULONG ControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode; ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength; ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength; PVOID SystemBuffer = Irp->AssociatedIrp.SystemBuffer; @@ -509,7 +512,10 @@ NTSTATUS FspVolumeTransact( FSP_FSCTL_DEFAULT_ALIGN_UP(sizeof(FSP_FSCTL_TRANSACT_RSP)) > InputBufferLength) return STATUS_INVALID_PARAMETER; if (0 != OutputBufferLength && - FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMIN > OutputBufferLength) + ((FSP_FSCTL_TRANSACT == ControlCode && + FSP_FSCTL_TRANSACT_REQ_SIZEMAX > OutputBufferLength) || + (FSP_FSCTL_TRANSACT_BATCH == ControlCode && + FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMIN > OutputBufferLength))) return STATUS_BUFFER_TOO_SMALL; if (!FspDeviceReference(FsvolDeviceObject)) @@ -645,6 +651,10 @@ NTSTATUS FspVolumeTransact( goto exit; } + /* are we doing single request or batch mode? */ + if (FSP_FSCTL_TRANSACT == ControlCode) + break; + /* check that we have enough space before pulling the next pending IRP off the queue */ if (!FspFsctlTransactCanProduceRequest(Request, BufferEnd)) break; diff --git a/tst/winfsp-tests/mount-test.c b/tst/winfsp-tests/mount-test.c index df7b5c2a..6637e62c 100644 --- a/tst/winfsp-tests/mount-test.c +++ b/tst/winfsp-tests/mount-test.c @@ -184,7 +184,7 @@ void mount_volume_transact_dotest(PWSTR DeviceName, PWSTR Prefix) ResponseBufSize = 0; RequestBufSize = sizeof RequestBuf; - Result = FspFsctlTransact(VolumeHandle, 0, 0, RequestBuf, &RequestBufSize); + Result = FspFsctlTransact(VolumeHandle, 0, 0, RequestBuf, &RequestBufSize, TRUE); ASSERT(STATUS_SUCCESS == Result); RequestBufEnd = RequestBuf + RequestBufSize; @@ -235,7 +235,7 @@ void mount_volume_transact_dotest(PWSTR DeviceName, PWSTR Prefix) ResponseBufSize = (PUINT8)Response - ResponseBuf; RequestBufSize = 0; - Result = FspFsctlTransact(VolumeHandle, ResponseBuf, ResponseBufSize, 0, &RequestBufSize); + Result = FspFsctlTransact(VolumeHandle, ResponseBuf, ResponseBufSize, 0, &RequestBufSize, TRUE); ASSERT(STATUS_SUCCESS == Result); Success = CloseHandle(VolumeHandle); diff --git a/tst/winfsp-tests/timeout-test.c b/tst/winfsp-tests/timeout-test.c index 728a9c03..cf998e30 100644 --- a/tst/winfsp-tests/timeout-test.c +++ b/tst/winfsp-tests/timeout-test.c @@ -179,7 +179,7 @@ void timeout_transact_dotest(PWSTR DeviceName, PWSTR Prefix) ResponseBufSize = 0; RequestBufSize = sizeof RequestBuf; - Result = FspFsctlTransact(VolumeHandle, ResponseBuf, ResponseBufSize, RequestBuf, &RequestBufSize); + Result = FspFsctlTransact(VolumeHandle, ResponseBuf, ResponseBufSize, RequestBuf, &RequestBufSize, TRUE); ASSERT(STATUS_SUCCESS == Result); ASSERT(0 == RequestBufSize); @@ -190,7 +190,7 @@ void timeout_transact_dotest(PWSTR DeviceName, PWSTR Prefix) ResponseBufSize = 0; RequestBufSize = sizeof RequestBuf; - Result = FspFsctlTransact(VolumeHandle, ResponseBuf, ResponseBufSize, RequestBuf, &RequestBufSize); + Result = FspFsctlTransact(VolumeHandle, ResponseBuf, ResponseBufSize, RequestBuf, &RequestBufSize, TRUE); ASSERT(STATUS_SUCCESS == Result); RequestBufEnd = RequestBuf + RequestBufSize; @@ -222,7 +222,7 @@ void timeout_transact_dotest(PWSTR DeviceName, PWSTR Prefix) ResponseBufSize = 0; RequestBufSize = sizeof RequestBuf; - Result = FspFsctlTransact(VolumeHandle, ResponseBuf, ResponseBufSize, RequestBuf, &RequestBufSize); + Result = FspFsctlTransact(VolumeHandle, ResponseBuf, ResponseBufSize, RequestBuf, &RequestBufSize, TRUE); ASSERT(STATUS_SUCCESS == Result); ASSERT(0 == RequestBufSize);