ReactOS 0.4.16-dev-122-g325d74c
fxdpc.cpp
Go to the documentation of this file.
1/*++
2
3Copyright (c) Microsoft Corporation
4
5Module Name:
6
7 FxDpc.hpp
8
9Abstract:
10
11 This module implements a frameworks managed DPC that
12 can synchrononize with driver frameworks object locks.
13
14Author:
15
16
17
18Environment:
19
20 Kernel mode only
21
22Revision History:
23
24
25--*/
26
27#include "fxcorepch.hpp"
28
29#include "fxdpc.hpp"
30
31// Tracing support
32extern "C" {
33// #include "FxDpc.tmh"
34}
35
36//
37// Public constructors
38//
39
41 __in PFX_DRIVER_GLOBALS FxDriverGlobals
42 ) :
43 FxNonPagedObject(FX_TYPE_DPC, sizeof(FxDpc), FxDriverGlobals)
44{
45 m_Object = NULL;
50
51 //
52 // Mark the object has having passive level dispose so that KeFlushQueuedDpcs
53 // can be called in Dispose().
54 //
56
58}
59
60
62{
63 //
64 // If this hits, its because someone destroyed the DPC by
65 // removing too many references by mistake without calling WdfObjectDelete
66 //
67 if (m_Object != NULL) {
70 "Destroy WDFDPC %p destroyed without calling WdfObjectDelete, or by"
71 " Framework processing DeviceRemove. Possible reference count "
72 "problem?", GetObjectHandleUnchecked());
74 }
75}
76
80 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
83 __in FxObject* ParentObject,
84 __out WDFDPC* Dpc
85 )
86/*++
87
88Routine Description:
89
90 Create an FxDpc factory method
91
92Arguments:
93
94 All arguments have been valided by the FxDpcApi stub.
95
96Returns:
97
98 NTSTATUS
99
100--*/
101{
102 FxDpc* pFxDpc;
104
105 pFxDpc = new(FxDriverGlobals, Attributes) FxDpc(FxDriverGlobals);
106
107 if (pFxDpc == NULL) {
109 }
110
113 Config,
114 ParentObject,
115 Dpc
116 );
117
118 if (!NT_SUCCESS(status)) {
120 }
121
122 return status;
123}
124
130 __in FxObject* ParentObject,
131 __out WDFDPC* Dpc
132 )
133{
135 IFxHasCallbacks* pCallbacks;
137 KDPC* pDpc;
138
140 pDpc = NULL;
141 pCallbacks = NULL;
142
143 pDpc = &m_Dpc;
144
145 //
146 // Set user's callback function
147 //
148 m_Callback = Config->EvtDpcFunc;
149
150 //
151 // Initialize the DPC to point to our thunk
152 //
154 pDpc, // Dpc
155 FxDpcThunk, // DeferredRoutine
156 this // DeferredContext
157 );
158
159 //
160 // As long as we are associated, the parent object holds a reference
161 // count on the DPC.
162 //
163 // We keep an extra reference count since on Dispose, we wait until
164 // all outstanding DPC's complete before allowing finalization.
165 //
166 // This reference must be taken early before we return any failure,
167 // since Dispose() expects this extra reference, and Dispose() will
168 // be called even if we return a failure status right now.
169 //
170 ADDREF(this);
171
172 //
173 // DPC's can be parented by, and optionally serialize with an FxDevice or
174 // an FxQueue.
175 //
176 m_DeviceBase = FxDeviceBase::_SearchForDevice(ParentObject, &pCallbacks);
177
178 if (m_DeviceBase == NULL) {
180 }
181
182 //
183 // Configure Serialization for the DPC and callbacks on the supplied object
184 //
186 ParentObject,
187 pCallbacks,
188 Config->AutomaticSerialization,
189 FALSE,
192 );
193
194 if (!NT_SUCCESS(status)) {
196
197
198
199
200
201
204 "ParentObject %p can not automatically synchronize callbacks "
205 "with a DPC since it is configured for passive level callback "
206 "constraints. Set AutomaticSerialization to FALSE. %!STATUS!",
207 Attributes->ParentObject, status);
208 }
209
210 return status;
211 }
212
213 //
214 // We automatically synchronize with and reference count
215 // the lifetime of the framework object to prevent any DPC races
216 // that can access the object while it is going away.
217 //
218
219 //
220 // The caller supplied object is the object the caller wants the
221 // DPC to be associated with, and the framework must ensure this
222 // object remains live until the DPC object is destroyed. Otherwise,
223 // it could access either object context memory, or an object API
224 // on a freed object.
225 //
226 // Due to the locking model of the framework, the lock may actually
227 // be owned by a higher level object as well. This is the lockObject
228 // returned. As long was we are a child of this object, the lockObject
229 // does not need to be dereferenced since it will notify us of Cleanup
230 // before it goes away.
231 //
232
233 //
234 // Associate the FxDpc with the object. When this object gets deleted or
235 // disposed, it will notify our Dispose function as well.
236 //
237
238 //
239 // Add a reference to the parent object we are associated with.
240 // We will be notified of Cleanup to release this reference.
241 //
242 ParentObject->ADDREF(this);
243
244 // Save the ptr to the object the DPC is associated with
245 m_Object = ParentObject;
246
247 //
248 // Attributes->ParentObject is the same as ParentObject. Since we already
249 // converted it to an object, use that.
250 //
251 status = Commit(Attributes, (WDFOBJECT*)Dpc, ParentObject);
252
253 if (!NT_SUCCESS(status)) {
254 return status;
255 }
256
257 return status;
258}
259
263 )
264{
266
268
269 //
270 // If result == FALSE, then the DPC could already be running.
271 //
272 // If the caller supplies Wait == TRUE, they want to wait and
273 // ensure on return the DPC has finished running.
274 //
275 // The trick here is to implement this without adding execessive
276 // overhead to the "normal" path, such as tracking reference counts,
277 // locking, signaling events to waiting threads, etc.
278 //
279 // So we take the expensive approach for the Cancel call in the
280 // case the caller wants to wait, and misses the DPC window. In
281 // this case we will just do the system wide FlushQueuedDpc's to
282 // ensure the DPC has finished running before return.
283 //
284 if( Wait && !result ) {
285
287
289 }
290
291 return result;
292}
293
294VOID
296 __in PKDPC Dpc,
299 )
300{
304
306
307 if (m_Callback != NULL) {
308
310
311 if (m_CallbackLock != NULL) {
312 KIRQL irql = 0;
313
315 m_Callback((WDFDPC)(this->GetObjectHandle()));
316 m_CallbackLock->Unlock(irql);
317 }
318 else {
319 m_Callback((WDFDPC)(this->GetObjectHandle()));
320 }
321 }
322}
323
324VOID
326 __in PKDPC Dpc,
330 )
331
332/*++
333
334Routine Description:
335
336 This is the C routine called by the kernels DPC handler
337
338Arguments:
339
340 Dpc - our DPC object associated with our Timer
341 DeferredContext - Context for the DPC that we setup in DriverEntry
342 SystemArgument1 -
343 SystemArgument2 -
344
345Return Value:
346
347 Nothing.
348
349--*/
350
351{
352 FxDpc* pDpc = (FxDpc*)DeferredContext;
353
354 pDpc->DpcHandler(
355 Dpc,
358 );
359
360 return;
361}
362
363//
364// Called when DeleteObject is called, or when the parent
365// is being deleted or Disposed.
366//
367// Also invoked directly by the cleanup list at our request after
368// a Dispose occurs and must be deferred if not at passive level.
369//
372{
373 // MarkPassiveDispose() in Initialize ensures this
375
377
379
380 return TRUE;
381}
382
383//
384// Called by the system work item to finish the rundown
385//
386VOID
388{
390
391 //
392 // If we have the KeFlushQueuedDpcs function call it
393 // to ensure the DPC routine is no longer running before
394 // we release the final reference and memory to the framework objects
395 //
397
398 //
399 // Release our reference count to the associated parent object if present
400 //
401 if (m_Object != NULL) {
403 m_Object = NULL;
404
405 pObject->RELEASE(this);
406 }
407
408 //
409 // Perform our final release to ourselves, destroying the FxDpc
410 //
411 RELEASE(this);
412}
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
virtual void Lock(__out PKIRQL PreviousIrql)=0
virtual void Unlock(__in KIRQL PreviousIrql)=0
static FxDeviceBase * _SearchForDevice(__in FxObject *Object, __out_opt IFxHasCallbacks **Callbacks)
Definition: fxdpc.hpp:63
static KDEFERRED_ROUTINE FxDpcThunk
Definition: fxdpc.hpp:190
PFN_WDF_DPC m_Callback
Definition: fxdpc.hpp:90
VOID FlushAndRundown()
Definition: fxdpc.cpp:387
FxDpc(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
Definition: fxdpc.cpp:40
FxObject * m_Object
Definition: fxdpc.hpp:73
BOOLEAN Cancel(__in BOOLEAN Wait)
Definition: fxdpc.cpp:261
_Must_inspect_result_ NTSTATUS Initialize(__in PWDF_OBJECT_ATTRIBUTES Attributes, __in PWDF_DPC_CONFIG Config, __in FxObject *ParentObject, __out WDFDPC *Dpc)
Definition: fxdpc.cpp:127
FxCallbackLock * m_CallbackLock
Definition: fxdpc.hpp:79
BOOLEAN m_RunningDown
Definition: fxdpc.hpp:93
KDPC m_Dpc
Definition: fxdpc.hpp:67
VOID DpcHandler(__in PKDPC Dpc, __in PVOID SystemArgument1, __in PVOID SystemArgument2)
Definition: fxdpc.cpp:295
virtual ~FxDpc(VOID)
Definition: fxdpc.cpp:61
virtual BOOLEAN Dispose(VOID)
Definition: fxdpc.cpp:371
static _Must_inspect_result_ NTSTATUS _Create(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PWDF_DPC_CONFIG Config, __in PWDF_OBJECT_ATTRIBUTES Attributes, __in FxObject *ParentObject, __out WDFDPC *Dpc)
Definition: fxdpc.cpp:79
FxObject * m_CallbackLockObject
Definition: fxdpc.hpp:85
VOID MarkPassiveDispose(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:944
PVOID __inline GetObjectHandleUnchecked(VOID)
Definition: fxobject.hpp:446
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
static _Must_inspect_result_ NTSTATUS _GetEffectiveLock(__in FxObject *Object, __in_opt IFxHasCallbacks *Callbacks, __in BOOLEAN AutomaticLocking, __in BOOLEAN PassiveCallbacks, __out FxCallbackLock **CallbackLock, __out_opt FxObject **CallbackLockObject)
Definition: fxobject.cpp:1044
CfxDeviceBase * m_DeviceBase
Definition: fxobject.hpp:328
VOID DeleteFromFailedCreate(VOID)
Definition: fxobject.cpp:391
VOID MarkDisposeOverride(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:1101
_Must_inspect_result_ NTSTATUS Commit(__in_opt PWDF_OBJECT_ATTRIBUTES Attributes, __out_opt WDFOBJECT *ObjectHandle, __in_opt FxObject *Parent=NULL, __in BOOLEAN AssignDriverAsDefaultParent=TRUE)
Definition: fxobject.cpp:904
#define __in
Definition: dbghelp.h:35
#define __out
Definition: dbghelp.h:62
#define TRACINGDEVICE
Definition: dbgtrace.h:58
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:712
BOOLEAN NTAPI KeRemoveQueueDpc(IN PKDPC Dpc)
Definition: dpc.c:878
VOID NTAPI KeFlushQueuedDpcs(VOID)
Definition: dpc.c:919
KIRQL irql
Definition: wave.h:1
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
PFX_DRIVER_GLOBALS pFxDriverGlobals
return pObject GetObjectHandle()
FX_TRACK_DRIVER(fxDriverGlobals)
FxVerifierDbgBreakPoint(pFxDriverGlobals)
FxDpc * pFxDpc
Definition: fxdpcapi.cpp:238
return pFxDpc GetDpcPtr()
@ ObjectDoNotLock
Definition: fxobject.hpp:128
#define ADDREF(_tag)
Definition: fxobject.hpp:49
#define RELEASE(_tag)
Definition: fxobject.hpp:50
FxObject * pObject
FORCEINLINE VOID FxPerfTraceDpc(_In_ PVOID DriverCallback)
@ FX_TYPE_DPC
Definition: fxtypes.h:68
GLuint64EXT * result
Definition: glext.h:11304
#define ASSERT(a)
Definition: mode.c:44
#define _Must_inspect_result_
Definition: ms_sal.h:558
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
Definition: ketypes.h:699
Definition: ps.c:97
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_CHILD_LIST_CONFIG Config
Definition: wdfchildlist.h:476
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
#define STATUS_WDF_INCOMPATIBLE_EXECUTION_LEVEL
Definition: wdfstatus.h:198
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:688
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:687
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:689