Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenservice_group.cpp
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Kernel Streaming 00004 * FILE: drivers/wdm/audio/backpln/portcls/service_group.cpp 00005 * PURPOSE: ServiceGroup object implementation 00006 * PROGRAMMER: Johannes Anderwald 00007 */ 00008 00009 00010 #include "private.hpp" 00011 00012 VOID 00013 NTAPI 00014 IServiceGroupDpc( 00015 IN struct _KDPC *Dpc, 00016 IN PVOID DeferredContext, 00017 IN PVOID SystemArgument1, 00018 IN PVOID SystemArgument2 00019 ); 00020 00021 typedef struct 00022 { 00023 LIST_ENTRY Entry; 00024 IN PSERVICESINK pServiceSink; 00025 }GROUP_ENTRY, *PGROUP_ENTRY; 00026 00027 class CServiceGroup : public IServiceGroup 00028 { 00029 public: 00030 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); 00031 00032 STDMETHODIMP_(ULONG) AddRef() 00033 { 00034 InterlockedIncrement(&m_Ref); 00035 return m_Ref; 00036 } 00037 STDMETHODIMP_(ULONG) Release() 00038 { 00039 InterlockedDecrement(&m_Ref); 00040 00041 if (!m_Ref) 00042 { 00043 delete this; 00044 return 0; 00045 } 00046 return m_Ref; 00047 } 00048 00049 IMP_IServiceGroup; 00050 CServiceGroup(IUnknown * OuterUnknown); 00051 virtual ~CServiceGroup() {} 00052 00053 protected: 00054 00055 LIST_ENTRY m_ServiceSinkHead; 00056 00057 BOOL m_TimerInitialized; 00058 KTIMER m_Timer; 00059 KDPC m_Dpc; 00060 KSPIN_LOCK m_Lock; 00061 00062 friend VOID NTAPI IServiceGroupDpc(IN struct _KDPC *Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2); 00063 00064 LONG m_Ref; 00065 00066 }; 00067 00068 00069 00070 //--------------------------------------------------------------- 00071 // IUnknown methods 00072 // 00073 00074 00075 NTSTATUS 00076 NTAPI 00077 CServiceGroup::QueryInterface( 00078 IN REFIID refiid, 00079 OUT PVOID* Output) 00080 { 00081 UNICODE_STRING GuidString; 00082 00083 if (IsEqualGUIDAligned(refiid, IID_IServiceGroup) || 00084 IsEqualGUIDAligned(refiid, IID_IServiceSink) || 00085 IsEqualGUIDAligned(refiid, IID_IUnknown)) 00086 { 00087 *Output = PVOID(PSERVICEGROUP(this)); 00088 PUNKNOWN(*Output)->AddRef(); 00089 return STATUS_SUCCESS; 00090 } 00091 00092 if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS) 00093 { 00094 DPRINT1("CServiceGroup::QueryInterface no interface!!! iface %S\n", GuidString.Buffer); 00095 RtlFreeUnicodeString(&GuidString); 00096 } 00097 00098 return STATUS_UNSUCCESSFUL; 00099 } 00100 //--------------------------------------------------------------- 00101 // IServiceSink methods 00102 // 00103 00104 CServiceGroup::CServiceGroup(IUnknown * OuterUnknown) 00105 { 00106 // initialize dpc 00107 KeInitializeDpc(&m_Dpc, IServiceGroupDpc, (PVOID)this); 00108 00109 // set highest importance 00110 KeSetImportanceDpc(&m_Dpc, HighImportance); 00111 00112 // initialize service group list lock 00113 KeInitializeSpinLock(&m_Lock); 00114 00115 // initialize service group list 00116 InitializeListHead(&m_ServiceSinkHead); 00117 } 00118 00119 VOID 00120 NTAPI 00121 CServiceGroup::RequestService() 00122 { 00123 KIRQL OldIrql; 00124 00125 DPRINT("CServiceGroup::RequestService() Dpc at Level %u\n", KeGetCurrentIrql()); 00126 00127 if (m_TimerInitialized) 00128 { 00129 LARGE_INTEGER DueTime; 00130 00131 // no due time 00132 DueTime.QuadPart = 0LL; 00133 00134 // delayed service requested 00135 KeSetTimer(&m_Timer, DueTime, &m_Dpc); 00136 } 00137 else 00138 { 00139 // check curent irql 00140 if (KeGetCurrentIrql() > DISPATCH_LEVEL) 00141 { 00142 //insert dpc to queue 00143 KeInsertQueueDpc(&m_Dpc, NULL, NULL); 00144 } 00145 else 00146 { 00147 // raise irql to dispatch level to make dpc fire immediately 00148 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00149 // insert dpc to queue 00150 KeInsertQueueDpc(&m_Dpc, NULL, NULL); 00151 // lower irql to old level 00152 KeLowerIrql(OldIrql); 00153 } 00154 } 00155 } 00156 00157 //--------------------------------------------------------------- 00158 // IServiceGroup methods 00159 // 00160 00161 NTSTATUS 00162 NTAPI 00163 CServiceGroup::AddMember( 00164 IN PSERVICESINK pServiceSink) 00165 { 00166 PGROUP_ENTRY Entry; 00167 KIRQL OldLevel; 00168 00169 // sanity check 00170 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 00171 00172 // allocate service sink entry 00173 Entry = (PGROUP_ENTRY)AllocateItem(NonPagedPool, sizeof(GROUP_ENTRY), TAG_PORTCLASS); 00174 if (!Entry) 00175 { 00176 // out of memory 00177 return STATUS_INSUFFICIENT_RESOURCES; 00178 } 00179 00180 // initialize service sink entry 00181 Entry->pServiceSink = pServiceSink; 00182 // increment reference count 00183 pServiceSink->AddRef(); 00184 00185 // acquire service group list lock 00186 KeAcquireSpinLock(&m_Lock, &OldLevel); 00187 00188 // insert into service sink list 00189 InsertTailList(&m_ServiceSinkHead, &Entry->Entry); 00190 00191 // release service group list lock 00192 KeReleaseSpinLock(&m_Lock, OldLevel); 00193 00194 return STATUS_SUCCESS; 00195 } 00196 00197 VOID 00198 NTAPI 00199 CServiceGroup::RemoveMember( 00200 IN PSERVICESINK pServiceSink) 00201 { 00202 PLIST_ENTRY CurEntry; 00203 PGROUP_ENTRY Entry; 00204 KIRQL OldLevel; 00205 00206 // sanity check 00207 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 00208 00209 // acquire service group list lock 00210 KeAcquireSpinLock(&m_Lock, &OldLevel); 00211 00212 // grab first entry 00213 CurEntry = m_ServiceSinkHead.Flink; 00214 00215 // loop list until the passed entry is found 00216 while (CurEntry != &m_ServiceSinkHead) 00217 { 00218 // grab entry 00219 Entry = CONTAINING_RECORD(CurEntry, GROUP_ENTRY, Entry); 00220 00221 // check if it matches the passed entry 00222 if (Entry->pServiceSink == pServiceSink) 00223 { 00224 // remove entry from list 00225 RemoveEntryList(&Entry->Entry); 00226 00227 // release service sink reference 00228 pServiceSink->Release(); 00229 00230 // free service sink entry 00231 FreeItem(Entry, TAG_PORTCLASS); 00232 00233 // leave loop 00234 break; 00235 } 00236 // move to next entry 00237 CurEntry = CurEntry->Flink; 00238 } 00239 00240 // release service group list lock 00241 KeReleaseSpinLock(&m_Lock, OldLevel); 00242 00243 } 00244 00245 VOID 00246 NTAPI 00247 IServiceGroupDpc( 00248 IN struct _KDPC *Dpc, 00249 IN PVOID DeferredContext, 00250 IN PVOID SystemArgument1, 00251 IN PVOID SystemArgument2 00252 ) 00253 { 00254 PLIST_ENTRY CurEntry; 00255 PGROUP_ENTRY Entry; 00256 CServiceGroup * This = (CServiceGroup*)DeferredContext; 00257 00258 // acquire service group list lock 00259 KeAcquireSpinLockAtDpcLevel(&This->m_Lock); 00260 00261 // grab first entry 00262 CurEntry = This->m_ServiceSinkHead.Flink; 00263 00264 // loop the list and call the attached service sink/group 00265 while (CurEntry != &This->m_ServiceSinkHead) 00266 { 00267 //grab current entry 00268 Entry = (PGROUP_ENTRY)CONTAINING_RECORD(CurEntry, GROUP_ENTRY, Entry); 00269 00270 // call service sink/group 00271 Entry->pServiceSink->RequestService(); 00272 00273 // move to next entry 00274 CurEntry = CurEntry->Flink; 00275 } 00276 00277 // release service group list lock 00278 KeReleaseSpinLockFromDpcLevel(&This->m_Lock); 00279 } 00280 00281 VOID 00282 NTAPI 00283 CServiceGroup::SupportDelayedService() 00284 { 00285 PC_ASSERT_IRQL(DISPATCH_LEVEL); 00286 00287 // initialize the timer 00288 KeInitializeTimer(&m_Timer); 00289 00290 // use the timer to perform service requests 00291 m_TimerInitialized = TRUE; 00292 } 00293 00294 VOID 00295 NTAPI 00296 CServiceGroup::RequestDelayedService( 00297 IN ULONGLONG ullDelay) 00298 { 00299 LARGE_INTEGER DueTime; 00300 00301 // sanity check 00302 PC_ASSERT_IRQL(DISPATCH_LEVEL); 00303 PC_ASSERT(m_TimerInitialized); 00304 00305 DueTime.QuadPart = ullDelay; 00306 00307 // set the timer 00308 KeSetTimer(&m_Timer, DueTime, &m_Dpc); 00309 } 00310 00311 VOID 00312 NTAPI 00313 CServiceGroup::CancelDelayedService() 00314 { 00315 PC_ASSERT_IRQL(DISPATCH_LEVEL); 00316 PC_ASSERT(m_TimerInitialized); 00317 00318 // cancel the timer 00319 KeCancelTimer(&m_Timer); 00320 } 00321 00322 NTSTATUS 00323 NTAPI 00324 PcNewServiceGroup( 00325 OUT PSERVICEGROUP* OutServiceGroup, 00326 IN PUNKNOWN OuterUnknown OPTIONAL) 00327 { 00328 CServiceGroup * This; 00329 NTSTATUS Status; 00330 00331 DPRINT("PcNewServiceGroup entered\n"); 00332 00333 //FIXME support aggregation 00334 PC_ASSERT(OuterUnknown == NULL); 00335 00336 // allocate a service group object 00337 This = new(NonPagedPool, TAG_PORTCLASS)CServiceGroup(OuterUnknown); 00338 00339 if (!This) 00340 { 00341 // out of memory 00342 return STATUS_INSUFFICIENT_RESOURCES; 00343 } 00344 00345 // request IServiceSink interface 00346 Status = This->QueryInterface(IID_IServiceSink, (PVOID*)OutServiceGroup); 00347 00348 if (!NT_SUCCESS(Status)) 00349 { 00350 // failed to acquire service sink interface 00351 delete This; 00352 return Status; 00353 } 00354 00355 // done 00356 return Status; 00357 } Generated on Sat May 26 2012 04:27:12 for ReactOS by
1.7.6.1
|