mirror of
https://github.com/reactos/reactos.git
synced 2026-07-02 11:44:21 +08:00
- implement IServiceGroup interface
- implement PcNewServiceGroup svn path=/trunk/; revision=37950
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
<file>undoc.c</file>
|
||||
<file>resource.c</file>
|
||||
<file>registry.c</file>
|
||||
<file>service_group.c</file>
|
||||
<file>port.c</file>
|
||||
<file>port_dmus.c</file>
|
||||
<file>port_midi.c</file>
|
||||
|
||||
270
reactos/drivers/wdm/audio/backpln/portcls/service_group.c
Normal file
270
reactos/drivers/wdm/audio/backpln/portcls/service_group.c
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user