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); -}