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... ============================================================================== --- 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/p... ============================================================================== --- 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