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 if (KeGetCurrentIrql() > DISPATCH_LEVEL
)
122 KeInsertQueueDpc(&m_Dpc
, NULL
, NULL
);
126 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
127 KeInsertQueueDpc(&m_Dpc
, NULL
, NULL
);
128 KeLowerIrql(OldIrql
);
131 //---------------------------------------------------------------
132 // IServiceGroup methods
137 CServiceGroup::AddMember(
138 IN PSERVICESINK pServiceSink
)
142 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
144 Entry
= (PGROUP_ENTRY
)AllocateItem(NonPagedPool
, sizeof(GROUP_ENTRY
), TAG_PORTCLASS
);
146 return STATUS_INSUFFICIENT_RESOURCES
;
148 Entry
->pServiceSink
= pServiceSink
;
149 pServiceSink
->AddRef();
151 InsertTailList(&m_ServiceSinkHead
, &Entry
->Entry
);
153 return STATUS_SUCCESS
;
158 CServiceGroup::RemoveMember(
159 IN PSERVICESINK pServiceSink
)
161 PLIST_ENTRY CurEntry
;
164 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
166 CurEntry
= m_ServiceSinkHead
.Flink
;
167 while (CurEntry
!= &m_ServiceSinkHead
)
169 Entry
= CONTAINING_RECORD(CurEntry
, GROUP_ENTRY
, Entry
);
170 if (Entry
->pServiceSink
== pServiceSink
)
172 RemoveEntryList(&Entry
->Entry
);
173 pServiceSink
->Release();
174 FreeItem(Entry
, TAG_PORTCLASS
);
177 CurEntry
= CurEntry
->Flink
;
185 IN
struct _KDPC
*Dpc
,
186 IN PVOID DeferredContext
,
187 IN PVOID SystemArgument1
,
188 IN PVOID SystemArgument2
191 PLIST_ENTRY CurEntry
;
193 CServiceGroup
* This
= (CServiceGroup
*)DeferredContext
;
195 CurEntry
= This
->m_ServiceSinkHead
.Flink
;
196 while (CurEntry
!= &This
->m_ServiceSinkHead
)
198 Entry
= (PGROUP_ENTRY
)CONTAINING_RECORD(CurEntry
, GROUP_ENTRY
, Entry
);
199 Entry
->pServiceSink
->RequestService();
200 CurEntry
= CurEntry
->Flink
;
208 ServiceGroupThread(IN PVOID StartContext
)
211 KWAIT_BLOCK WaitBlockArray
[2];
212 PVOID WaitObjects
[2];
213 CServiceGroup
* This
= (CServiceGroup
*)StartContext
;
216 InterlockedIncrement(&This
->m_ThreadActive
);
218 // Setup the wait objects
219 WaitObjects
[0] = &m_Timer
;
220 WaitObjects
[1] = &m_Event
;
224 // Wait on our objects
225 Status
= KeWaitForMultipleObjects(2, WaitObjects
, WaitAny
, Executive
, KernelMode
, FALSE
, NULL
, WaitBlockArray
);
230 IServiceGroupDpc(&This
->m_Dpc
, (PVOID
)This
, NULL
, NULL
);
233 PsTerminateSystemThread(STATUS_SUCCESS
);
242 CServiceGroup::SupportDelayedService()
245 //HANDLE ThreadHandle;
247 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
252 KeInitializeTimerEx(&m_Timer
, NotificationTimer
);
255 Status
= PsCreateSystemThread(&ThreadHandle
, THREAD_ALL_ACCESS
, NULL
, 0, NULL
, ServiceGroupThread
, (PVOID
)This
);
256 if (NT_SUCCESS(Status
))
258 ZwClose(ThreadHandle
);
259 m_Initialized
= TRUE
;
266 CServiceGroup::RequestDelayedService(
267 IN ULONGLONG ullDelay
)
269 LARGE_INTEGER DueTime
;
271 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
273 DueTime
.QuadPart
= ullDelay
;
277 if (KeGetCurrentIrql() <= DISPATCH_LEVEL
)
278 KeSetTimer(&m_Timer
, DueTime
, &m_Dpc
);
280 KeInsertQueueDpc(&m_Dpc
, NULL
, NULL
);
286 CServiceGroup::CancelDelayedService()
288 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
292 KeCancelTimer(&m_Timer
);
299 OUT PSERVICEGROUP
* OutServiceGroup
,
300 IN PUNKNOWN OuterUnknown OPTIONAL
)
302 CServiceGroup
* This
;
304 DPRINT("PcNewServiceGroup entered\n");
306 This
= new(NonPagedPool
, TAG_PORTCLASS
)CServiceGroup(OuterUnknown
);
308 return STATUS_INSUFFICIENT_RESOURCES
;
310 Status
= This
->QueryInterface(IID_IServiceSink
, (PVOID
*)OutServiceGroup
);
312 if (!NT_SUCCESS(Status
))