diff --git a/reactos/drivers/wdm/audio/backpln/portcls/MiniportWavePci.cpp b/reactos/drivers/wdm/audio/backpln/portcls/MiniportWavePci.cpp deleted file mode 100644 index 8b137891791..00000000000 --- a/reactos/drivers/wdm/audio/backpln/portcls/MiniportWavePci.cpp +++ /dev/null @@ -1 +0,0 @@ - diff --git a/reactos/drivers/wdm/audio/backpln/portcls/portcls.rbuild b/reactos/drivers/wdm/audio/backpln/portcls/portcls.rbuild index 303f87f949c..4359c202b5c 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/portcls.rbuild +++ b/reactos/drivers/wdm/audio/backpln/portcls/portcls.rbuild @@ -21,6 +21,7 @@ undoc.c resource.c registry.c + service_group.c port.c port_dmus.c port_midi.c diff --git a/reactos/drivers/wdm/audio/backpln/portcls/service_group.c b/reactos/drivers/wdm/audio/backpln/portcls/service_group.c new file mode 100644 index 00000000000..f178c3a2af3 --- /dev/null +++ b/reactos/drivers/wdm/audio/backpln/portcls/service_group.c @@ -0,0 +1,270 @@ +#include "private.h" + +typedef struct +{ + LIST_ENTRY Entry; + IN PSERVICESINK pServiceSink; +}GROUP_ENTRY, *PGROUP_ENTRY; + +typedef struct +{ + IServiceGroupVtbl *lpVtbl; + + LONG ref; + LIST_ENTRY ServiceSinkHead; + + BOOL Initialized; + BOOL TimerActive; + KTIMER Timer; + KEVENT DpcEvent; + KDPC Dpc; + +}IServiceGroupImpl; + +const GUID IID_IServiceGroup; +const GUID IID_IServiceSink; + +//--------------------------------------------------------------- +// IUnknown methods +// + + +NTSTATUS +STDMETHODCALLTYPE +IServiceGroup_fnQueryInterface( + IServiceGroup* iface, + IN REFIID refiid, + OUT PVOID* Output) +{ + IServiceGroupImpl * This = (IServiceGroupImpl*)iface; + if (IsEqualGUIDAligned(refiid, &IID_IServiceGroup) || + IsEqualGUIDAligned(refiid, &IID_IServiceSink)) + { + *Output = &This->lpVtbl; + InterlockedIncrement(&This->ref); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + +ULONG +STDMETHODCALLTYPE +IServiceGroup_fnAddRef( + IServiceGroup* iface) +{ + IServiceGroupImpl * This = (IServiceGroupImpl*)iface; + + return InterlockedIncrement(&This->ref); +} + +ULONG +STDMETHODCALLTYPE +IServiceGroup_fnRelease( + IServiceGroup* iface) +{ + PLIST_ENTRY CurEntry; + PGROUP_ENTRY Entry; + IServiceGroupImpl * This = (IServiceGroupImpl*)iface; + + InterlockedDecrement(&This->ref); + + if (This->ref == 0) + { + while(!IsListEmpty(&This->ServiceSinkHead)) + { + CurEntry = RemoveHeadList(&This->ServiceSinkHead); + Entry = CONTAINING_RECORD(CurEntry, GROUP_ENTRY, Entry); + Entry->pServiceSink->lpVtbl->Release(Entry->pServiceSink); + ExFreePoolWithTag(Entry, TAG_PORTCLASS); + } + KeWaitForSingleObject(&This->DpcEvent, Executive, KernelMode, FALSE, NULL); + KeCancelTimer(&This->Timer); + ExFreePoolWithTag(This, TAG_PORTCLASS); + return 0; + } + /* Return new reference count */ + return This->ref; +} + + + +//--------------------------------------------------------------- +// IServiceSink methods +// + +VOID +NTAPI +IServiceGroup_fnRequestService( + IN IServiceGroup * iface) +{ + PLIST_ENTRY CurEntry; + PGROUP_ENTRY Entry; + IServiceGroupImpl * This = (IServiceGroupImpl*)iface; + + CurEntry = This->ServiceSinkHead.Flink; + while (CurEntry != &This->ServiceSinkHead) + { + Entry = CONTAINING_RECORD(CurEntry, GROUP_ENTRY, Entry); + Entry->pServiceSink->lpVtbl->RequestService(Entry->pServiceSink); + CurEntry = CurEntry->Flink; + } +} + +//--------------------------------------------------------------- +// IServiceGroup methods +// + +NTSTATUS +NTAPI +IServiceGroup_fnAddMember( + IN IServiceGroup * iface, + IN PSERVICESINK pServiceSink) +{ + PGROUP_ENTRY Entry; + IServiceGroupImpl * This = (IServiceGroupImpl*)iface; + + Entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(GROUP_ENTRY), TAG_PORTCLASS); + if (!Entry) + return STATUS_INSUFFICIENT_RESOURCES; + + Entry->pServiceSink = pServiceSink; + pServiceSink->lpVtbl->AddRef(pServiceSink); + + //FIXME + //check if Dpc is active + InsertTailList(&This->ServiceSinkHead, &Entry->Entry); + + return STATUS_SUCCESS; +} + +VOID +NTAPI +IServiceGroup_fnRemoveMember( + IN IServiceGroup * iface, + IN PSERVICESINK pServiceSink) +{ + PLIST_ENTRY CurEntry; + PGROUP_ENTRY Entry; + IServiceGroupImpl * This = (IServiceGroupImpl*)iface; + + //FIXME + //check if Dpc is active + // + + CurEntry = This->ServiceSinkHead.Flink; + while (CurEntry != &This->ServiceSinkHead) + { + Entry = CONTAINING_RECORD(CurEntry, GROUP_ENTRY, Entry); + if (Entry->pServiceSink == pServiceSink) + { + RemoveEntryList(&Entry->Entry); + pServiceSink->lpVtbl->Release(pServiceSink); + ExFreePoolWithTag(Entry, TAG_PORTCLASS); + return; + } + CurEntry = CurEntry->Flink; + } + +} + +VOID +NTAPI +IServiceGroupDpc( + IN struct _KDPC *Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2 + ) +{ + IServiceGroupImpl * This = (IServiceGroupImpl*)DeferredContext; + IServiceGroup_fnRequestService((IServiceGroup*)DeferredContext); + KeSetEvent(&This->DpcEvent, 0, FALSE); +} + + +VOID +NTAPI +IServiceGroup_fnSupportDelayedService( + IN IServiceGroup * iface) +{ + IServiceGroupImpl * This = (IServiceGroupImpl*)iface; + + if (!This->Initialized) + { + KeInitializeEvent(&This->DpcEvent, NotificationEvent, FALSE); + KeInitializeTimerEx(&This->Timer, NotificationTimer); + KeInitializeDpc(&This->Dpc, IServiceGroupDpc, (PVOID)This); + This->Initialized = TRUE; + } +} + +VOID +NTAPI +IServiceGroup_fnRequestDelayedService( + IN IServiceGroup * iface, + IN ULONGLONG ullDelay) +{ + LARGE_INTEGER DueTime; + IServiceGroupImpl * This = (IServiceGroupImpl*)iface; + + DueTime.QuadPart = ullDelay; + + if (This->Initialized) + { + KeSetTimer(&This->Timer, DueTime, &This->Dpc); + KeClearEvent(&This->DpcEvent); + } +} + +VOID +NTAPI +IServiceGroup_fnCancelDelayedService( + IN IServiceGroup * iface) +{ + IServiceGroupImpl * This = (IServiceGroupImpl*)iface; + + if (This->Initialized) + { + KeCancelTimer(&This->Timer); + } +} + +static IServiceGroupVtbl vt_IServiceGroup = +{ + /* IUnknown methods */ + IServiceGroup_fnQueryInterface, + IServiceGroup_fnAddRef, + IServiceGroup_fnRelease, + IServiceGroup_fnRequestService, + IServiceGroup_fnAddMember, + IServiceGroup_fnRemoveMember, + IServiceGroup_fnSupportDelayedService, + IServiceGroup_fnRequestDelayedService, + IServiceGroup_fnCancelDelayedService +}; + +/* + * @unimplemented + */ +NTSTATUS NTAPI +PcNewServiceGroup( + OUT PSERVICEGROUP* OutServiceGroup, + IN PUNKNOWN OuterUnknown OPTIONAL) +{ + IServiceGroupImpl * This; + + This = ExAllocatePoolWithTag(NonPagedPool, sizeof(IServiceGroupImpl), TAG_PORTCLASS); + if (!This) + return STATUS_INSUFFICIENT_RESOURCES; + + This->lpVtbl = &vt_IServiceGroup; + This->ref = 1; + InitializeListHead(&This->ServiceSinkHead); + This->Initialized = FALSE; + *OutServiceGroup = (PSERVICEGROUP)&This->lpVtbl; + + return STATUS_UNSUCCESSFUL; +} + + + diff --git a/reactos/drivers/wdm/audio/backpln/portcls/stubs.c b/reactos/drivers/wdm/audio/backpln/portcls/stubs.c index b3c377c5056..4d6302fc5c7 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/stubs.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/stubs.c @@ -28,19 +28,6 @@ PcNewDmaChannel( return STATUS_UNSUCCESSFUL; } -/* - * @unimplemented - */ -NTSTATUS NTAPI -PcNewServiceGroup( - OUT PSERVICEGROUP* OutServiceGroup, - IN PUNKNOWN OuterUnknown OPTIONAL) -{ - UNIMPLEMENTED; - return STATUS_UNSUCCESSFUL; -} - - /* =============================================================== Power Management */