[ros-diffs] [janderwald] 44100: [KS] - Implement KsEnableEvent, KsEnableEventWithAllocator, KsDiscardEvent [PORTCLS] - Fix signalling the event - DirectSound clients can now use IDirectSoundNotify interface to be notified of a position change

janderwald at svn.reactos.org janderwald at svn.reactos.org
Wed Nov 11 10:04:43 CET 2009


Author: janderwald
Date: Wed Nov 11 10:04:42 2009
New Revision: 44100

URL: http://svn.reactos.org/svn/reactos?rev=44100&view=rev
Log:
[KS]
- Implement KsEnableEvent, KsEnableEventWithAllocator, KsDiscardEvent
[PORTCLS]
- Fix signalling the event
- DirectSound clients can now use IDirectSoundNotify interface to be notified of a position change

Modified:
    trunk/reactos/drivers/ksfilter/ks/event.c
    trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp

Modified: trunk/reactos/drivers/ksfilter/ks/event.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/ksfilter/ks/event.c?rev=44100&r1=44099&r2=44100&view=diff
==============================================================================
--- trunk/reactos/drivers/ksfilter/ks/event.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/ksfilter/ks/event.c [iso-8859-1] Wed Nov 11 10:04:42 2009
@@ -71,9 +71,312 @@
     return Result;
 }
 
-
-/*
-    @unimplemented
+BOOLEAN
+NTAPI
+SyncAddEvent(
+    PKSEVENT_CTX Context)
+{
+    InsertTailList(Context->List, &Context->EventEntry->ListEntry);
+    return TRUE;
+}
+
+NTSTATUS
+KspEnableEvent(
+    IN  PIRP Irp,
+    IN  ULONG EventSetsCount,
+    IN  PKSEVENT_SET EventSet,
+    IN  OUT PLIST_ENTRY EventsList OPTIONAL,
+    IN  KSEVENTS_LOCKTYPE EventsFlags OPTIONAL,
+    IN  PVOID EventsLock OPTIONAL,
+    IN  PFNKSALLOCATOR Allocator OPTIONAL,
+    IN  ULONG EventItemSize OPTIONAL)
+{
+    PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status;
+    KSEVENT Event;
+    PKSEVENT_ITEM EventItem, FoundEventItem;
+    PKSEVENTDATA EventData;
+    PKSEVENT_SET FoundEventSet;
+    PKSEVENT_ENTRY EventEntry;
+    ULONG Index, SubIndex, Size;
+    PVOID Object;
+    KSEVENT_CTX Ctx;
+    LPGUID Guid;
+
+    /* get current stack location */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSEVENT))
+    {
+        /* invalid parameter */
+        return STATUS_NOT_SUPPORTED;
+    }
+
+    if (Irp->RequestorMode == UserMode)
+    {
+        _SEH2_TRY
+        {
+           ProbeForRead(IoStack->Parameters.DeviceIoControl.Type3InputBuffer, sizeof(KSEVENT), sizeof(UCHAR));
+           ProbeForRead(Irp->UserBuffer, IoStack->Parameters.DeviceIoControl.OutputBufferLength, sizeof(UCHAR));
+           RtlMoveMemory(&Event, IoStack->Parameters.DeviceIoControl.Type3InputBuffer, sizeof(KSEVENT));
+           Status = STATUS_SUCCESS;
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            /* Exception, get the error code */
+            Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END;
+
+        /* check for success */
+        if (!NT_SUCCESS(Status))
+        {
+            /* failed to probe parameters */
+            return Status;
+        }
+    }
+    else
+    {
+        /* copy event struct */
+        RtlMoveMemory(&Event, IoStack->Parameters.DeviceIoControl.Type3InputBuffer, sizeof(KSEVENT));
+    }
+
+    FoundEventItem = NULL;
+    FoundEventSet = NULL;
+
+
+    if (IsEqualGUIDAligned(&Event.Set, &GUID_NULL) && Event.Id == 0 && Event.Flags == KSEVENT_TYPE_SETSUPPORT)
+    {
+        // store output size
+        Irp->IoStatus.Information = sizeof(GUID) * EventSetsCount;
+        if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(GUID) * EventSetsCount)
+        {
+            // buffer too small
+            return STATUS_MORE_ENTRIES;
+        }
+
+        // get output buffer
+        Guid = (LPGUID)Irp->UserBuffer;
+
+       // copy property guids from property sets
+       for(Index = 0; Index < EventSetsCount; Index++)
+       {
+           RtlMoveMemory(&Guid[Index], EventSet[Index].Set, sizeof(GUID));
+       }
+       return STATUS_SUCCESS;
+    }
+
+    /* now try to find event set */
+    for(Index = 0; Index < EventSetsCount; Index++)
+    {
+        if (IsEqualGUIDAligned(&Event.Set, EventSet[Index].Set))
+        {
+            EventItem = (PKSEVENT_ITEM)EventSet[Index].EventItem;
+
+            /* sanity check */
+            ASSERT(EventSet[Index].EventsCount);
+            ASSERT(EventItem);
+
+            /* now find matching event id */
+            for(SubIndex = 0; SubIndex < EventSet[Index].EventsCount; SubIndex++)
+            {
+                if (EventItem[SubIndex].EventId == Event.Id)
+                {
+                    /* found event item */
+                    FoundEventItem = &EventItem[SubIndex];
+                    FoundEventSet = &EventSet[Index];
+                    break;
+                }
+            }
+
+            if (FoundEventSet)
+                break;
+        }
+    }
+
+    if (!FoundEventSet)
+    {
+        UNICODE_STRING GuidString;
+
+        RtlStringFromGUID(&Event.Set, &GuidString);
+
+        DPRINT("Guid %S Id %u Flags %x not found\n", GuidString.Buffer, Event.Id, Event.Flags);
+        RtlFreeUnicodeString(&GuidString);
+        return STATUS_PROPSET_NOT_FOUND;
+
+
+    }
+
+    if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < FoundEventItem->DataInput)
+    {
+        /* buffer too small */
+        DPRINT1("Got %u expected %u\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength, FoundEventItem->DataInput);
+        return STATUS_SUCCESS;
+    }
+
+    if (!FoundEventItem->AddHandler && !EventsList)
+    {
+        /* no add handler and no list to add the new entry to */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* get event data */
+    EventData = Irp->UserBuffer;
+
+    /* sanity check */
+    ASSERT(EventData);
+
+    if (Irp->RequestorMode == UserMode)
+    {
+        if (EventData->NotificationType == KSEVENTF_SEMAPHORE_HANDLE)
+        {
+            /* get semaphore object handle */
+            Status = ObReferenceObjectByHandle(EventData->SemaphoreHandle.Semaphore, SEMAPHORE_MODIFY_STATE, ExSemaphoreObjectType, Irp->RequestorMode, &Object, NULL);
+
+            if (!NT_SUCCESS(Status))
+            {
+                /* invalid semaphore handle */
+                return STATUS_INVALID_PARAMETER;
+            }
+        }
+        else if (EventData->NotificationType == KSEVENTF_EVENT_HANDLE)
+        {
+            /* get event object handle */
+            Status = ObReferenceObjectByHandle(EventData->EventHandle.Event, EVENT_MODIFY_STATE, ExEventObjectType, Irp->RequestorMode, &Object, NULL);
+
+            if (!NT_SUCCESS(Status))
+            {
+                /* invalid event handle */
+                return STATUS_INVALID_PARAMETER;
+            }
+        }
+        else
+        {
+            /* user mode client can only pass an event or semaphore handle */
+            return STATUS_INVALID_PARAMETER;
+        }
+    }
+    else
+    {
+        if (EventData->NotificationType != KSEVENTF_EVENT_OBJECT &&
+            EventData->NotificationType != KSEVENTF_SEMAPHORE_OBJECT &&
+            EventData->NotificationType != KSEVENTF_DPC &&
+            EventData->NotificationType != KSEVENTF_WORKITEM &&
+            EventData->NotificationType != KSEVENTF_KSWORKITEM)
+        {
+            /* invalid type requested */
+            return STATUS_INVALID_PARAMETER;
+        }
+    } 
+
+
+    /* calculate request size */
+    Size = sizeof(KSEVENT_ENTRY) + FoundEventItem->ExtraEntryData;
+
+    /* do we have an allocator */
+    if (Allocator)
+    {
+        /* allocate event entry */
+        Status = Allocator(Irp, Size, FALSE);
+
+        if (!NT_SUCCESS(Status))
+        {
+            /* failed */
+            return Status;
+        }
+
+        /* assume the caller put it there */
+        EventEntry = KSEVENT_ENTRY_IRP_STORAGE(Irp);
+
+    }
+    else
+    {
+        /* allocate it from nonpaged pool */
+        EventEntry = ExAllocatePool(NonPagedPool, Size);
+    }
+
+    if (!EventEntry)
+    {
+        /* not enough memory */
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* zero event entry */
+    RtlZeroMemory(EventEntry, Size);
+
+    /* initialize event entry */
+    EventEntry->EventData = EventData;
+    EventEntry->NotificationType = EventData->NotificationType;
+    EventEntry->EventItem = FoundEventItem;
+    EventEntry->EventSet = FoundEventSet;
+    EventEntry->FileObject = IoStack->FileObject;
+
+    switch(EventEntry->NotificationType)
+    {
+        case KSEVENTF_EVENT_HANDLE:
+            EventEntry->Object = Object;
+            EventEntry->Reserved = 0;
+            break;
+        case KSEVENTF_SEMAPHORE_HANDLE:
+            EventEntry->Object = Object;
+            EventEntry->SemaphoreAdjustment = EventData->SemaphoreHandle.Adjustment;
+            EventEntry->Reserved = 0;
+            break;
+        case KSEVENTF_EVENT_OBJECT:
+            EventEntry->Object = EventData->EventObject.Event;
+            EventEntry->Reserved = EventData->EventObject.Increment;
+            break;
+        case KSEVENTF_SEMAPHORE_OBJECT:
+            EventEntry->Object = EventData->SemaphoreObject.Semaphore;
+            EventEntry->SemaphoreAdjustment = EventData->SemaphoreObject.Adjustment;
+            EventEntry->Reserved = EventData->SemaphoreObject.Increment;
+            break;
+        case KSEVENTF_DPC:
+            EventEntry->Object = EventData->Dpc.Dpc;
+            EventData->Dpc.ReferenceCount = 0;
+            break;
+        case KSEVENTF_WORKITEM:
+            EventEntry->Object = EventData->WorkItem.WorkQueueItem;
+            EventEntry->BufferItem = (PKSBUFFER_ITEM)UlongToPtr(EventData->WorkItem.WorkQueueType);
+            break;
+        case KSEVENTF_KSWORKITEM:
+            EventEntry->Object = EventData->KsWorkItem.KsWorkerObject;
+            EventEntry->DpcItem = (PKSDPC_ITEM)EventData->KsWorkItem.WorkQueueItem;
+            break;
+        default:
+            /* should not happen */
+            ASSERT(0);
+    }
+
+    if (FoundEventItem->AddHandler)
+    {
+        /* now add the event */
+        Status = FoundEventItem->AddHandler(Irp, EventData, EventEntry);
+
+        if (!NT_SUCCESS(Status))
+        {
+            /* discard event entry */
+            KsDiscardEvent(EventEntry);
+        }
+    }
+    else
+    {
+        /* setup context */
+        Ctx.List = EventsList;
+        Ctx.EventEntry = EventEntry;
+
+         /* add the event */
+        (void)KspSynchronizedEventRoutine(EventsFlags, EventsLock, SyncAddEvent, &Ctx);
+
+        Status = STATUS_SUCCESS;
+    }
+
+    /* done */
+    return Status;
+}
+
+/*
+    @implemented
 */
 KSDDKAPI
 NTSTATUS
@@ -86,12 +389,11 @@
     IN  KSEVENTS_LOCKTYPE EventsFlags OPTIONAL,
     IN  PVOID EventsLock OPTIONAL)
 {
-    UNIMPLEMENTED;
-    return STATUS_SUCCESS;
-}
-
-/*
-    @unimplemented
+    return KspEnableEvent(Irp, EventSetsCount, EventSet, EventsList, EventsFlags, EventsLock, NULL, 0);
+}
+
+/*
+    @implemented
 */
 KSDDKAPI
 NTSTATUS
@@ -106,8 +408,7 @@
     IN  PFNKSALLOCATOR Allocator OPTIONAL,
     IN  ULONG EventItemSize OPTIONAL)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
+    return KspEnableEvent(Irp, EventSetsCount, EventSet, EventsList, EventsFlags, EventsLock, Allocator, EventItemSize);
 }
 
 BOOLEAN
@@ -210,7 +511,7 @@
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 KSDDKAPI
 VOID
@@ -218,7 +519,17 @@
 KsDiscardEvent(
     IN  PKSEVENT_ENTRY EventEntry)
 {
-    //UNIMPLEMENTED;
+    /* sanity check */
+    ASSERT(EventEntry->Object);
+
+    if (EventEntry->NotificationType == KSEVENTF_SEMAPHORE_HANDLE || EventEntry->NotificationType == KSEVENTF_EVENT_HANDLE)
+    {
+        /* release object */
+        ObDereferenceObject(EventEntry->Object);
+    }
+
+    /* free event entry */
+    ExFreePool(EventEntry);
 }
 
 
@@ -295,33 +606,35 @@
 {
     if (EntryEvent->NotificationType == KSEVENTF_EVENT_HANDLE || EntryEvent->NotificationType == KSEVENTF_EVENT_OBJECT)
     {
-        // signal event
-        KeSetEvent(EntryEvent->Object, 0, FALSE);
+        /* signal event */
+        KeSetEvent(EntryEvent->Object, EntryEvent->Reserved, FALSE);
     }
     else if (EntryEvent->NotificationType == KSEVENTF_SEMAPHORE_HANDLE || EntryEvent->NotificationType == KSEVENTF_SEMAPHORE_OBJECT)
     {
-        // release semaphore
-        KeReleaseSemaphore(EntryEvent->Object, 0, EntryEvent->SemaphoreAdjustment, FALSE);
+        /* release semaphore */
+        KeReleaseSemaphore(EntryEvent->Object, EntryEvent->Reserved, EntryEvent->SemaphoreAdjustment, FALSE);
     }
     else if (EntryEvent->NotificationType == KSEVENTF_DPC)
     {
-        // queue dpc
+        /* increment reference count to indicate dpc is pending */
+        InterlockedIncrement((PLONG)&EntryEvent->EventData->Dpc.ReferenceCount);
+        /* queue dpc */
         KeInsertQueueDpc((PRKDPC)EntryEvent->Object, NULL, NULL);
     }
     else if (EntryEvent->NotificationType == KSEVENTF_WORKITEM)
     {
-        // queue work item
+        /* queue work item */
         ExQueueWorkItem((PWORK_QUEUE_ITEM)EntryEvent->Object, PtrToUlong(EntryEvent->BufferItem));
     }
     else if (EntryEvent->NotificationType == KSEVENTF_KSWORKITEM)
     {
-        // queue work item of ks worker
+        /* queue work item of ks worker */
         return KsQueueWorkItem((PKSWORKER)EntryEvent->Object, (PWORK_QUEUE_ITEM)EntryEvent->DpcItem);
     }
     else
     {
-        UNIMPLEMENTED;
-        return STATUS_UNSUCCESSFUL;
+        /* unsupported type requested */
+        return STATUS_INVALID_PARAMETER;
     }
 
     return STATUS_SUCCESS;

Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp?rev=44100&r1=44099&r2=44100&view=diff
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp [iso-8859-1] Wed Nov 11 10:04:42 2009
@@ -41,7 +41,7 @@
 
     VOID UpdateCommonBuffer(ULONG Position, ULONG MaxTransferCount);
     VOID UpdateCommonBufferOverlap(ULONG Position, ULONG MaxTransferCount);
-    VOID GeneratePositionEvents(IN ULONG OldCommonBufferOffset, IN ULONG NewCommonBufferOffset);
+    VOID GeneratePositionEvents(IN ULONGLONG OldOffset, IN ULONGLONG NewOffset);
     NTSTATUS NTAPI HandleKsStream(IN PIRP Irp);
     NTSTATUS NTAPI HandleKsProperty(IN PIRP Irp);
 
@@ -261,6 +261,8 @@
     Entry->bLoopedStreaming = TRUE;
     Entry->Position = Data->Position;
 
+    DPRINT1("Added event\n");
+
     // insert item
     (void)ExInterlockedInsertTailList(&Pin->m_EventList, &EventEntry->ListEntry, &Pin->m_EventListLock);
 
@@ -342,7 +344,7 @@
         }
         else if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
         {
-            Position->PlayOffset = Pin->m_Position.PlayOffset % Pin->m_Position.WriteOffset;
+            Position->PlayOffset = Pin->m_Position.PlayOffset;
             Position->WriteOffset = (ULONGLONG)Pin->m_IrpQueue->GetCurrentIrpOffset();
             DPRINT("Play %lu Write %lu\n", Position->PlayOffset, Position->WriteOffset);
         }
@@ -540,8 +542,8 @@
 
 VOID
 CPortPinWaveCyclic::GeneratePositionEvents(
-    IN ULONG OldCommonBufferOffset,
-    IN ULONG NewCommonBufferOffset)
+    IN ULONGLONG OldOffset,
+    IN ULONGLONG NewOffset)
 {
     PLIST_ENTRY Entry;
     PKSEVENT_ENTRY EventEntry;
@@ -563,11 +565,15 @@
 
         if (Context->bLoopedStreaming == TRUE)
         {
-            if (NewCommonBufferOffset > OldCommonBufferOffset)
+            if (NewOffset > OldOffset)
             {
                 /* buffer progress no overlap */
-                if (OldCommonBufferOffset < Context->Position && Context->Position <= NewCommonBufferOffset)
+                if (OldOffset < Context->Position && Context->Position <= NewOffset)
                 {
+                    /* when someone eventually fixes sprintf... */
+                    DPRINT("Generating event at OldOffset %I64u\n", OldOffset);
+                    DPRINT("Context->Position %I64u\n", Context->Position);
+                    DPRINT("NewOffset %I64u\n", NewOffset);
                     /* generate event */
                     KsGenerateEvent(EventEntry);
                 }
@@ -575,8 +581,12 @@
             else
             {
                 /* buffer wrap-arround */
-                if (OldCommonBufferOffset < Context->Position || NewCommonBufferOffset > Context->Position)
+                if (OldOffset < Context->Position || NewOffset > Context->Position)
                 {
+                    /* when someone eventually fixes sprintf... */
+                    DPRINT("Generating event at OldOffset %I64u\n", OldOffset);
+                    DPRINT("Context->Position %I64u\n", Context->Position);
+                    DPRINT("NewOffset %I64u\n", NewOffset);
                     /* generate event */
                     KsGenerateEvent(EventEntry);
                 }
@@ -627,6 +637,12 @@
 
         BufferLength = Position - m_CommonBufferOffset;
         m_Position.PlayOffset += BytesToCopy;
+
+        if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
+        {
+            // normalize position
+            m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset;
+        }
     }
 }
 
@@ -670,6 +686,13 @@
         m_Position.PlayOffset += BytesToCopy;
 
         BufferLength = m_CommonBufferSize - m_CommonBufferOffset;
+
+        if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
+        {
+            // normalize position
+            m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset;
+        }
+
     }
 
     if (Gap == Length)
@@ -693,7 +716,7 @@
     NTSTATUS Status;
     PUCHAR Buffer;
     ULONG BufferSize;
-    ULONG OldCommonBufferOffset;
+    ULONGLONG OldOffset, NewOffset;
 
     PC_ASSERT_IRQL(DISPATCH_LEVEL);
 
@@ -706,7 +729,7 @@
     Status = m_Stream->GetPosition(&Position);
     DPRINT("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u Capture %u\n", Position, Buffer, m_CommonBufferSize, BufferSize, m_Capture);
 
-    OldCommonBufferOffset = m_CommonBufferOffset;
+    OldOffset = m_Position.PlayOffset;
 
     if (Position < m_CommonBufferOffset)
     {
@@ -717,7 +740,9 @@
         UpdateCommonBuffer(Position, m_FrameSize);
     }
 
-    GeneratePositionEvents(OldCommonBufferOffset, m_CommonBufferOffset);
+    NewOffset = m_Position.PlayOffset;
+
+    GeneratePositionEvents(OldOffset, NewOffset);
 }
 
 NTSTATUS




More information about the Ros-diffs mailing list