ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

service_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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.