mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-29 11:08:37 -05:00 
			
		
		
		
	sys: fsctl
This commit is contained in:
		| @@ -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 | ||||
|   | ||||
| @@ -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( | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -1,82 +0,0 @@ | ||||
| /** | ||||
|  * @file sys/transact.c | ||||
|  * | ||||
|  * @copyright 2015 Bill Zissimopoulos | ||||
|  */ | ||||
|  | ||||
| #include <sys/driver.h> | ||||
|  | ||||
| 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); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user