diff --git a/build/VStudio/winfsp.vcxproj b/build/VStudio/winfsp.vcxproj
index 4b118dde..f7d94004 100644
--- a/build/VStudio/winfsp.vcxproj
+++ b/build/VStudio/winfsp.vcxproj
@@ -149,7 +149,6 @@
-
diff --git a/build/VStudio/winfsp.vcxproj.filters b/build/VStudio/winfsp.vcxproj.filters
index fba2a105..eb72665c 100644
--- a/build/VStudio/winfsp.vcxproj.filters
+++ b/build/VStudio/winfsp.vcxproj.filters
@@ -77,9 +77,6 @@
Source
-
- Source
-
diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h
index 96a0d7bb..6f04daab 100644
--- a/inc/winfsp/fsctl.h
+++ b/inc/winfsp/fsctl.h
@@ -31,6 +31,7 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
#define FSP_FSCTL_CREATE_BUFFER_SIZE 64
#define FSP_FSCTL_TRANSACT_BUFFER_SIZE 4096
+#define FSP_FSCTL_TRANSACT_REQ_SIZEMAX 1536
/* marshalling */
#pragma warning(push)
diff --git a/src/sys/driver.h b/src/sys/driver.h
index 09dffdbc..b4a89652 100644
--- a/src/sys/driver.h
+++ b/src/sys/driver.h
@@ -162,25 +162,14 @@ typedef struct
IO_CSQ PendingIoCsq, ProcessIoCsq;
} FSP_IOQ;
VOID FspIoqInitialize(FSP_IOQ *Ioq);
-VOID FspIoqEnable(FSP_IOQ *Ioq, int Delta);
-PKEVENT FspIoqPendingIrpEvent(FSP_IOQ *Ioq);
+BOOLEAN FspIoqEnabled(FSP_IOQ *Ioq);
+VOID FspIoqDisable(FSP_IOQ *Ioq);
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp);
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, ULONG millis);
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp);
PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint);
VOID FspIoqCancelAll(FSP_IOQ *Ioq);
-/* transact thread */
-typedef struct
-{
- PKTHREAD Thread;
- KEVENT Event;
- FSP_IOQ *TransactIoq, *Ioq;
-} FSP_TRANSACT_THREAD;
-NTSTATUS FspTransactThreadStart(FSP_TRANSACT_THREAD *TransactThread,
- FSP_IOQ *TransactIoq, FSP_IOQ *Ioq);
-VOID FspTransactThreadStop(FSP_TRANSACT_THREAD *TransactThread);
-
/* device extensions */
enum
{
@@ -199,8 +188,7 @@ typedef struct
typedef struct
{
FSP_DEVICE_EXTENSION Base;
- FSP_IOQ TransactIoq, Ioq;
- FSP_TRANSACT_THREAD TransactThread;
+ FSP_IOQ Ioq;
UINT8 SecurityDescriptorBuf[];
} FSP_FSVRT_DEVICE_EXTENSION;
typedef struct
diff --git a/src/sys/fsctl.c b/src/sys/fsctl.c
index cf49bf9b..3b46f279 100644
--- a/src/sys/fsctl.c
+++ b/src/sys/fsctl.c
@@ -79,15 +79,10 @@ static NTSTATUS FspFsctlCreateVolume(
{
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
FsvrtDeviceExtension->Base.Kind = FspFsvrtDeviceExtensionKind;
- FspIoqInitialize(&FsvrtDeviceExtension->TransactIoq);
FspIoqInitialize(&FsvrtDeviceExtension->Ioq);
RtlCopyMemory(FspFsvrtDeviceExtension(FsvrtDeviceObject)->SecurityDescriptorBuf,
SecurityDescriptor, InputBufferLength);
Irp->IoStatus.Information = DeviceName.Length + 1;
- Result = FspTransactThreadStart(&FsvrtDeviceExtension->TransactThread,
- &FsvrtDeviceExtension->TransactIoq, &FsvrtDeviceExtension->Ioq);
- if (!NT_SUCCESS(Result))
- IoDeleteDevice(FsvrtDeviceObject);
}
/* free the temporary security descriptor */
@@ -125,9 +120,10 @@ static NTSTATUS FspFsvrtTransact(
NTSTATUS Result;
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
- PUINT8 SystemBufferEnd;
+ PUINT8 SystemBufferPtr, SystemBufferEnd;
FSP_TRANSACT_RSP *Response;
- PIRP ProcessIrp;
+ FSP_TRANSACT_REQ *Request;
+ PIRP ProcessIrp, PendingIrp;
/* access check */
Result = FspSecuritySubjectContextAccessCheck(
@@ -155,12 +151,43 @@ static NTSTATUS FspFsvrtTransact(
Response = (PVOID)((PUINT8)Response + Response->Size);
}
- if (FspIoqPostIrp(&FsvrtDeviceExtension->TransactIoq, Irp))
- Result = STATUS_PENDING;
- else
- Result = STATUS_ACCESS_DENIED;
+ /* wait for a pending IRP */
+ while (0 == (PendingIrp = FspIoqNextPendingIrp(&FsvrtDeviceExtension->Ioq, 300)))
+ {
+ if (!FspIoqEnabled(&FsvrtDeviceExtension->Ioq))
+ return STATUS_CANCELLED;
+ }
- return Result;
+ /* send any pending IRP's to the user-mode file system */
+ SystemBufferPtr = SystemBuffer;
+ SystemBufferEnd = (PUINT8)SystemBuffer + OutputBufferLength;
+ ASSERT(SystemBufferPtr + FSP_FSCTL_TRANSACT_REQ_SIZEMAX + sizeof(Request->Size) <= SystemBufferEnd);
+ for (BOOLEAN LoopedOnce = FALSE;; LoopedOnce = TRUE)
+ {
+ if (SystemBufferPtr + FSP_FSCTL_TRANSACT_REQ_SIZEMAX + sizeof(Request->Size) > SystemBufferEnd)
+ break;
+
+ if (!FspIoqStartProcessingIrp(&FsvrtDeviceExtension->Ioq, PendingIrp))
+ {
+ FspCompleteRequest(PendingIrp, STATUS_CANCELLED);
+ if (!LoopedOnce)
+ return STATUS_CANCELLED;
+ break;
+ }
+
+ Request = PendingIrp->Tail.Overlay.DriverContext[0];
+ RtlCopyMemory(SystemBufferPtr, Request, Request->Size);
+ SystemBufferPtr += Request->Size;
+
+ PendingIrp = FspIoqNextPendingIrp(&FsvrtDeviceExtension->Ioq, 0);
+ if (0 == PendingIrp)
+ break;
+ }
+ ASSERT(SystemBufferPtr + sizeof(Request->Size) <= SystemBufferEnd);
+ RtlZeroMemory(SystemBufferPtr, SystemBufferEnd - SystemBufferPtr);
+ Irp->IoStatus.Information = SystemBufferPtr - (PUINT8)SystemBuffer;
+
+ return STATUS_SUCCESS;
}
static NTSTATUS FspFsctlFileSystemControl(
diff --git a/src/sys/ioq.c b/src/sys/ioq.c
index 8a7f9e10..8051564f 100644
--- a/src/sys/ioq.c
+++ b/src/sys/ioq.c
@@ -57,7 +57,7 @@
static NTSTATUS FspIoqPendingInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext)
{
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq);
- if (0 > Ioq->Enabled)
+ if (0 >= Ioq->Enabled)
return STATUS_ACCESS_DENIED;
InsertTailList(&Ioq->PendingIrpList, &Irp->Tail.Overlay.ListEntry);
/* list is not empty; wake up any waiters */
@@ -101,7 +101,7 @@ static VOID FspIoqPendingCompleteCanceledIrp(PIO_CSQ IoCsq, PIRP Irp)
static NTSTATUS FspIoqProcessInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext)
{
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, ProcessIoCsq);
- if (0 > Ioq->Enabled)
+ if (0 >= Ioq->Enabled)
return STATUS_ACCESS_DENIED;
InsertTailList(&Ioq->ProcessIrpList, &Irp->Tail.Overlay.ListEntry);
return STATUS_SUCCESS;
@@ -164,21 +164,27 @@ VOID FspIoqInitialize(FSP_IOQ *Ioq)
FspIoqProcessAcquireLock,
FspIoqProcessReleaseLock,
FspIoqProcessCompleteCanceledIrp);
+ Ioq->Enabled = 1;
}
-VOID FspIoqEnable(FSP_IOQ *Ioq, int Delta)
+BOOLEAN FspIoqEnabled(FSP_IOQ *Ioq)
+{
+ BOOLEAN Result;
+ KIRQL Irql;
+ KeAcquireSpinLock(&Ioq->SpinLock, &Irql);
+ Result = 0 < Ioq->Enabled;
+ KeReleaseSpinLock(&Ioq->SpinLock, Irql);
+ return Result;
+}
+
+VOID FspIoqDisable(FSP_IOQ *Ioq)
{
KIRQL Irql;
KeAcquireSpinLock(&Ioq->SpinLock, &Irql);
- Ioq->Enabled += Delta;
+ Ioq->Enabled = 0;
KeReleaseSpinLock(&Ioq->SpinLock, Irql);
}
-PKEVENT FspIoqPendingIrpEvent(FSP_IOQ *Ioq)
-{
- return &Ioq->PendingIrpEvent;
-}
-
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp)
{
NTSTATUS Result;
diff --git a/src/sys/transact.c b/src/sys/transact.c
deleted file mode 100644
index 48005e8d..00000000
--- a/src/sys/transact.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * @file sys/transact.c
- *
- * @copyright 2015 Bill Zissimopoulos
- */
-
-#include
-
-static KSTART_ROUTINE FspTransactThread;
-NTSTATUS FspTransactThreadStart(FSP_TRANSACT_THREAD *TransactThread,
- FSP_IOQ *TransactIoq, FSP_IOQ *Ioq);
-VOID FspTransactThreadStop(FSP_TRANSACT_THREAD *TransactThread);
-
-#ifdef ALLOC_PRAGMA
-#pragma alloc_text(PAGE, FspTransactThread)
-#pragma alloc_text(PAGE, FspTransactThreadStart)
-#pragma alloc_text(PAGE, FspTransactThreadStop)
-#endif
-
-static VOID FspTransactThread(PVOID StartContext)
-{
- PAGED_CODE();
-
- FSP_TRANSACT_THREAD *TransactThread = StartContext;
- PVOID WaitObjects[2];
- WaitObjects[0] = &TransactThread->Event;
- WaitObjects[1] = FspIoqPendingIrpEvent(TransactThread->TransactIoq);
- for (;;)
- {
- NTSTATUS Result;
- PIRP Irp;
-
- Result = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, Executive, KernelMode, FALSE, 0, 0);
- if (STATUS_WAIT_0 == Result)
- break; /* stop thread */
- else if (STATUS_WAIT_1 != Result)
- continue; /* retry */
-
- Irp = FspIoqNextPendingIrp(TransactThread->TransactIoq, 0);
- if (0 == Irp)
- continue; /* retry */
- }
-
- PsTerminateSystemThread(STATUS_SUCCESS);
-}
-
-NTSTATUS FspTransactThreadStart(FSP_TRANSACT_THREAD *TransactThread,
- FSP_IOQ *TransactIoq, FSP_IOQ *Ioq)
-{
- PAGED_CODE();
-
- NTSTATUS Result;
- OBJECT_ATTRIBUTES ObjectAttributes;
- HANDLE ThreadHandle;
-
- RtlZeroMemory(TransactThread, sizeof *TransactThread);
- KeInitializeEvent(&TransactThread->Event, NotificationEvent, FALSE);
- TransactThread->TransactIoq = TransactIoq;
- TransactThread->Ioq = Ioq;
-
- InitializeObjectAttributes(&ObjectAttributes, 0, OBJ_KERNEL_HANDLE, 0, 0);
- Result = PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, &ObjectAttributes, 0, 0,
- FspTransactThread, TransactThread);
- if (!NT_SUCCESS(Result))
- return Result;
-
- Result = ObReferenceObjectByHandle(ThreadHandle, THREAD_ALL_ACCESS, *PsThreadType, KernelMode,
- &TransactThread->Thread, 0);
- ASSERT(NT_SUCCESS(Result));
-
- ZwClose(ThreadHandle);
-
- return STATUS_SUCCESS;
-}
-
-VOID FspTransactThreadStop(FSP_TRANSACT_THREAD *TransactThread)
-{
- PAGED_CODE();
-
- KeSetEvent(&TransactThread->Event, 1, TRUE);
- KeWaitForSingleObject(&TransactThread->Thread, Executive, KernelMode, FALSE, 0);
-}