- implement IServiceGroup interface

- implement PcNewServiceGroup

svn path=/trunk/; revision=37950
This commit is contained in:
Johannes Anderwald
2008-12-08 23:30:16 +00:00
parent 678aeae6f0
commit 0bfc5f6d4d
4 changed files with 271 additions and 14 deletions

View File

@@ -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>

View 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;
}

View File

@@ -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
*/