2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/service_group.cpp
5 * PURPOSE: ServiceGroup object implementation
6 * PROGRAMMER: Johannes Anderwald
10 #include "private.hpp"
16 IN PVOID DeferredContext
,
17 IN PVOID SystemArgument1
,
18 IN PVOID SystemArgument2
24 IN PSERVICESINK pServiceSink
;
25 }GROUP_ENTRY
, *PGROUP_ENTRY
;
27 class CServiceGroup
: public IServiceGroup
30 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
32 STDMETHODIMP_(ULONG
) AddRef()
34 InterlockedIncrement(&m_Ref
);
37 STDMETHODIMP_(ULONG
) Release()
39 InterlockedDecrement(&m_Ref
);
50 CServiceGroup(IUnknown
* OuterUnknown
);
51 virtual ~CServiceGroup() {}
55 LIST_ENTRY m_ServiceSinkHead
;
64 friend VOID NTAPI
IServiceGroupDpc(IN
struct _KDPC
*Dpc
, IN PVOID DeferredContext
, IN PVOID SystemArgument1
, IN PVOID SystemArgument2
);
72 //---------------------------------------------------------------
79 CServiceGroup::QueryInterface(
83 UNICODE_STRING GuidString
;
85 if (IsEqualGUIDAligned(refiid
, IID_IServiceGroup
) ||
86 IsEqualGUIDAligned(refiid
, IID_IServiceSink
) ||
87 IsEqualGUIDAligned(refiid
, IID_IUnknown
))
89 *Output
= PVOID(PSERVICEGROUP(this));
90 PUNKNOWN(*Output
)->AddRef();
91 return STATUS_SUCCESS
;
94 if (RtlStringFromGUID(refiid
, &GuidString
) == STATUS_SUCCESS
)
96 DPRINT1("CServiceGroup::QueryInterface no interface!!! iface %S\n", GuidString
.Buffer
);
97 RtlFreeUnicodeString(&GuidString
);
100 return STATUS_UNSUCCESSFUL
;
102 //---------------------------------------------------------------
103 // IServiceSink methods
106 CServiceGroup::CServiceGroup(IUnknown
* OuterUnknown
)
108 KeInitializeDpc(&m_Dpc
, IServiceGroupDpc
, (PVOID
)this);
109 KeSetImportanceDpc(&m_Dpc
, HighImportance
);
110 KeInitializeEvent(&m_Event
, NotificationEvent
, FALSE
);
111 InitializeListHead(&m_ServiceSinkHead
);
116 CServiceGroup::RequestService()
120 DPRINT("CServiceGroup::RequestService() Dpc at Level %u\n", KeGetCurrentIrql());
122 if (KeGetCurrentIrql() > DISPATCH_LEVEL
)
124 KeInsertQueueDpc(&m_Dpc
, NULL
, NULL
);
128 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
129 KeInsertQueueDpc(&m_Dpc
, NULL
, NULL
);
130 KeLowerIrql(OldIrql
);
133 //---------------------------------------------------------------
134 // IServiceGroup methods
139 CServiceGroup::AddMember(
140 IN PSERVICESINK pServiceSink
)
144 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
146 Entry
= (PGROUP_ENTRY
)AllocateItem(NonPagedPool
, sizeof(GROUP_ENTRY
), TAG_PORTCLASS
);
148 return STATUS_INSUFFICIENT_RESOURCES
;
150 Entry
->pServiceSink
= pServiceSink
;
151 pServiceSink
->AddRef();
153 InsertTailList(&m_ServiceSinkHead
, &Entry
->Entry
);
155 return STATUS_SUCCESS
;
160 CServiceGroup::RemoveMember(
161 IN PSERVICESINK pServiceSink
)
163 PLIST_ENTRY CurEntry
;
166 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
168 CurEntry
= m_ServiceSinkHead
.Flink
;
169 while (CurEntry
!= &m_ServiceSinkHead
)
171 Entry
= CONTAINING_RECORD(CurEntry
, GROUP_ENTRY
, Entry
);
172 if (Entry
->pServiceSink
== pServiceSink
)
174 RemoveEntryList(&Entry
->Entry
);
175 pServiceSink
->Release();
176 FreeItem(Entry
, TAG_PORTCLASS
);
179 CurEntry
= CurEntry
->Flink
;
187 IN
struct _KDPC
*Dpc
,
188 IN PVOID DeferredContext
,
189 IN PVOID SystemArgument1
,
190 IN PVOID SystemArgument2
193 PLIST_ENTRY CurEntry
;
195 CServiceGroup
* This
= (CServiceGroup
*)DeferredContext
;
197 CurEntry
= This
->m_ServiceSinkHead
.Flink
;
198 while (CurEntry
!= &This
->m_ServiceSinkHead
)
200 Entry
= (PGROUP_ENTRY
)CONTAINING_RECORD(CurEntry
, GROUP_ENTRY
, Entry
);
201 Entry
->pServiceSink
->RequestService();
202 CurEntry
= CurEntry
->Flink
;
210 ServiceGroupThread(IN PVOID StartContext
)
213 KWAIT_BLOCK WaitBlockArray
[2];
214 PVOID WaitObjects
[2];
215 CServiceGroup
* This
= (CServiceGroup
*)StartContext
;
218 InterlockedIncrement(&This
->m_ThreadActive
);
220 // Setup the wait objects
221 WaitObjects
[0] = &m_Timer
;
222 WaitObjects
[1] = &m_Event
;
226 // Wait on our objects
227 Status
= KeWaitForMultipleObjects(2, WaitObjects
, WaitAny
, Executive
, KernelMode
, FALSE
, NULL
, WaitBlockArray
);
232 IServiceGroupDpc(&This
->m_Dpc
, (PVOID
)This
, NULL
, NULL
);
235 PsTerminateSystemThread(STATUS_SUCCESS
);
244 CServiceGroup::SupportDelayedService()
247 //HANDLE ThreadHandle;
249 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
254 KeInitializeTimerEx(&m_Timer
, NotificationTimer
);
257 Status
= PsCreateSystemThread(&ThreadHandle
, THREAD_ALL_ACCESS
, NULL
, 0, NULL
, ServiceGroupThread
, (PVOID
)This
);
258 if (NT_SUCCESS(Status
))
260 ZwClose(ThreadHandle
);
261 m_Initialized
= TRUE
;
268 CServiceGroup::RequestDelayedService(
269 IN ULONGLONG ullDelay
)
271 LARGE_INTEGER DueTime
;
273 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
275 DueTime
.QuadPart
= ullDelay
;
279 if (KeGetCurrentIrql() <= DISPATCH_LEVEL
)
280 KeSetTimer(&m_Timer
, DueTime
, &m_Dpc
);
282 KeInsertQueueDpc(&m_Dpc
, NULL
, NULL
);
288 CServiceGroup::CancelDelayedService()
290 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
294 KeCancelTimer(&m_Timer
);
301 OUT PSERVICEGROUP
* OutServiceGroup
,
302 IN PUNKNOWN OuterUnknown OPTIONAL
)
304 CServiceGroup
* This
;
306 DPRINT("PcNewServiceGroup entered\n");
308 This
= new(NonPagedPool
, TAG_PORTCLASS
)CServiceGroup(OuterUnknown
);
310 return STATUS_INSUFFICIENT_RESOURCES
;
312 Status
= This
->QueryInterface(IID_IServiceSink
, (PVOID
*)OutServiceGroup
);
314 if (!NT_SUCCESS(Status
))