From 7f7f90485408801152d0f7f94cbc152cf988b198 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Tue, 16 Dec 2008 13:19:53 +0000 Subject: [PATCH] - Implement KsCreateAllocator, KsRegisterWorker, KsUnregisterWorker, KsRegisterCountedWorker, KsDecrementCountedWorker, KsIncrementCountedWorker, KsQueueWorkItem svn path=/trunk/; revision=38115 --- reactos/drivers/ksfilter/ks/allocators.c | 14 +- reactos/drivers/ksfilter/ks/ks.rbuild | 1 + reactos/drivers/ksfilter/ks/worker.c | 155 ++++++++++++++++++++--- 3 files changed, 146 insertions(+), 24 deletions(-) diff --git a/reactos/drivers/ksfilter/ks/allocators.c b/reactos/drivers/ksfilter/ks/allocators.c index 5530a62244a..68f4eff9edc 100644 --- a/reactos/drivers/ksfilter/ks/allocators.c +++ b/reactos/drivers/ksfilter/ks/allocators.c @@ -20,14 +20,13 @@ KsCreateAllocator( } /* - @unimplemented + @implemented */ KSDDKAPI NTSTATUS NTAPI KsCreateDefaultAllocator( IN PIRP Irp) { - UNIMPLEMENTED; - return STATUS_UNSUCCESSFUL; + return KsCreateDefaultAllocatorEx(Irp, NULL, NULL, NULL, NULL, NULL); } /* @@ -54,7 +53,14 @@ KsCreateDefaultAllocatorEx( IN PFNKSINITIALIZEALLOCATOR InitializeAllocator OPTIONAL, IN PFNKSDELETEALLOCATOR DeleteAllocator OPTIONAL) { - UNIMPLEMENTED; + NTSTATUS Status; + PKSALLOCATOR_FRAMING AllocatorFraming; + + Status = KsValidateAllocatorCreateRequest(Irp, &AllocatorFraming); + if (!NT_SUCCESS(Status)) + return STATUS_INVALID_PARAMETER; + + return STATUS_UNSUCCESSFUL; } diff --git a/reactos/drivers/ksfilter/ks/ks.rbuild b/reactos/drivers/ksfilter/ks/ks.rbuild index 9c5bc8d8df2..86032af7fe4 100644 --- a/reactos/drivers/ksfilter/ks/ks.rbuild +++ b/reactos/drivers/ksfilter/ks/ks.rbuild @@ -6,6 +6,7 @@ ../include ntoskrnl + hal diff --git a/reactos/drivers/ksfilter/ks/worker.c b/reactos/drivers/ksfilter/ks/worker.c index cae6681a532..cbfb18fd90d 100644 --- a/reactos/drivers/ksfilter/ks/worker.c +++ b/reactos/drivers/ksfilter/ks/worker.c @@ -6,30 +6,87 @@ #include #include + +typedef struct +{ + KEVENT Event; + KSPIN_LOCK Lock; + WORK_QUEUE_TYPE Type; + LONG Counter; + PWORK_QUEUE_ITEM WorkItem; + ULONG WorkItemActive; + ULONG DeleteInProgress; +}KS_WORKER; + /* - @unimplemented + @implemented */ -KSDDKAPI NTSTATUS NTAPI +KSDDKAPI +NTSTATUS +NTAPI KsRegisterWorker( IN WORK_QUEUE_TYPE WorkQueueType, OUT PKSWORKER* Worker) { + KS_WORKER * KsWorker; UNIMPLEMENTED; - return STATUS_UNSUCCESSFUL; + + if (WorkQueueType != CriticalWorkQueue && + WorkQueueType != DelayedWorkQueue && + WorkQueueType != HyperCriticalWorkQueue) + { + return STATUS_INVALID_PARAMETER; + } + + KsWorker = ExAllocatePoolWithTag(NonPagedPool, sizeof(KS_WORKER), 0); + if (!KsWorker) + return STATUS_INSUFFICIENT_RESOURCES; + + KsWorker->Type = WorkQueueType; + KsWorker->Counter = 0; + KsWorker->WorkItemActive = 0; + KsWorker->WorkItem = NULL; + KsWorker->DeleteInProgress = TRUE; + KeInitializeSpinLock(&KsWorker->Lock); + KeInitializeEvent(&KsWorker->Event, NotificationEvent, FALSE); + + *Worker = KsWorker; + return STATUS_SUCCESS; } /* - @unimplemented + @implemented */ KSDDKAPI VOID NTAPI KsUnregisterWorker( IN PKSWORKER Worker) { - UNIMPLEMENTED; + KS_WORKER * KsWorker; + KIRQL OldIrql; + ULONG bWait = FALSE; + + if (!Worker) + return; + + KsWorker = (KS_WORKER *)Worker; + + KsWorker->DeleteInProgress = TRUE; + + if (KsWorker->WorkItemActive) + { + KeReleaseSpinLock(&KsWorker->Lock, OldIrql); + KeWaitForSingleObject(&KsWorker->Event, Executive, KernelMode, FALSE, NULL); + } + else + { + KeReleaseSpinLock(&KsWorker->Lock, OldIrql); + } + + ExFreePoolWithTag(KsWorker, 0); } /* - @unimplemented + @implemented */ KSDDKAPI NTSTATUS NTAPI KsRegisterCountedWorker( @@ -37,40 +94,98 @@ KsRegisterCountedWorker( IN PWORK_QUEUE_ITEM CountedWorkItem, OUT PKSWORKER* Worker) { - UNIMPLEMENTED; - return STATUS_UNSUCCESSFUL; + NTSTATUS Status; + KS_WORKER * KsWorker; + + Status = KsRegisterWorker(WorkQueueType, Worker); + + if (NT_SUCCESS(Status)) + { + KsWorker = (KS_WORKER *)Worker; + KsWorker->WorkItem = CountedWorkItem; + } + + return Status; } /* - @unimplemented + @implemented */ -KSDDKAPI ULONG NTAPI +KSDDKAPI +ULONG +NTAPI KsDecrementCountedWorker( IN PKSWORKER Worker) { - UNIMPLEMENTED; - return 0; + KS_WORKER * KsWorker; + LONG Counter; + + if (!Worker) + return STATUS_INVALID_PARAMETER; + + KsWorker = (KS_WORKER *)Worker; + Counter = InterlockedDecrement(&KsWorker->Counter); + + if (KsWorker->DeleteInProgress) + { + /* signal that we are done */ + KeSetEvent(&KsWorker->Event, 0, 0); + } + + return Counter; } /* - @unimplemented + @implemented */ -KSDDKAPI ULONG NTAPI +KSDDKAPI +ULONG +NTAPI KsIncrementCountedWorker( IN PKSWORKER Worker) { - UNIMPLEMENTED; - return 0; + KS_WORKER * KsWorker; + LONG Counter; + + if (!Worker) + return STATUS_INVALID_PARAMETER; + + KsWorker = (KS_WORKER *)Worker; + + Counter = InterlockedIncrement(&KsWorker->Counter); + if (Counter == 1) + { + KsQueueWorkItem(Worker, KsWorker->WorkItem); + } + return Counter; } /* - @unimplemented + @implemented */ -KSDDKAPI NTSTATUS NTAPI +KSDDKAPI +NTSTATUS +NTAPI KsQueueWorkItem( IN PKSWORKER Worker, IN PWORK_QUEUE_ITEM WorkItem) { - UNIMPLEMENTED; - return STATUS_UNSUCCESSFUL; + KS_WORKER * KsWorker; + KIRQL OldIrql; + NTSTATUS Status = STATUS_SUCCESS; + + if (!Worker || !WorkItem) + return STATUS_INVALID_PARAMETER; + + KsWorker = (KS_WORKER *)Worker; + KeAcquireSpinLock(&KsWorker->Lock, &OldIrql); + + if (!KsWorker->DeleteInProgress) + { + ExQueueWorkItem(WorkItem, KsWorker->Type); + Status = STATUS_UNSUCCESSFUL; + } + + KeReleaseSpinLock(&KsWorker->Lock, OldIrql); + return Status; }