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