1*8a978a17SVictor Perevertkin /*++
2*8a978a17SVictor Perevertkin
3*8a978a17SVictor Perevertkin Copyright (c) Microsoft Corporation
4*8a978a17SVictor Perevertkin
5*8a978a17SVictor Perevertkin Module Name:
6*8a978a17SVictor Perevertkin
7*8a978a17SVictor Perevertkin FxObject.cpp
8*8a978a17SVictor Perevertkin
9*8a978a17SVictor Perevertkin Abstract:
10*8a978a17SVictor Perevertkin
11*8a978a17SVictor Perevertkin This module contains the implementation of the base object
12*8a978a17SVictor Perevertkin
13*8a978a17SVictor Perevertkin Author:
14*8a978a17SVictor Perevertkin
15*8a978a17SVictor Perevertkin
16*8a978a17SVictor Perevertkin
17*8a978a17SVictor Perevertkin
18*8a978a17SVictor Perevertkin
19*8a978a17SVictor Perevertkin Environment:
20*8a978a17SVictor Perevertkin
21*8a978a17SVictor Perevertkin Both kernel and user mode
22*8a978a17SVictor Perevertkin
23*8a978a17SVictor Perevertkin Revision History:
24*8a978a17SVictor Perevertkin
25*8a978a17SVictor Perevertkin
26*8a978a17SVictor Perevertkin
27*8a978a17SVictor Perevertkin
28*8a978a17SVictor Perevertkin
29*8a978a17SVictor Perevertkin
30*8a978a17SVictor Perevertkin
31*8a978a17SVictor Perevertkin
32*8a978a17SVictor Perevertkin
33*8a978a17SVictor Perevertkin
34*8a978a17SVictor Perevertkin --*/
35*8a978a17SVictor Perevertkin
36*8a978a17SVictor Perevertkin #include "fxobjectpch.hpp"
37*8a978a17SVictor Perevertkin
38*8a978a17SVictor Perevertkin extern "C" {
39*8a978a17SVictor Perevertkin
40*8a978a17SVictor Perevertkin #if defined(EVENT_TRACING)
41*8a978a17SVictor Perevertkin #include "FxObject.tmh"
42*8a978a17SVictor Perevertkin #else
43*8a978a17SVictor Perevertkin ULONG DebugLevel = TRACE_LEVEL_INFORMATION;
44*8a978a17SVictor Perevertkin ULONG DebugFlag = 0xff;
45*8a978a17SVictor Perevertkin #endif
46*8a978a17SVictor Perevertkin
47*8a978a17SVictor Perevertkin }
48*8a978a17SVictor Perevertkin
FxObject(__in WDFTYPE Type,__in USHORT Size,__in PFX_DRIVER_GLOBALS FxDriverGlobals)49*8a978a17SVictor Perevertkin FxObject::FxObject(
50*8a978a17SVictor Perevertkin __in WDFTYPE Type,
51*8a978a17SVictor Perevertkin __in USHORT Size,
52*8a978a17SVictor Perevertkin __in PFX_DRIVER_GLOBALS FxDriverGlobals
53*8a978a17SVictor Perevertkin ) :
54*8a978a17SVictor Perevertkin m_Type(Type),
55*8a978a17SVictor Perevertkin m_ObjectSize((USHORT) WDF_ALIGN_SIZE_UP(Size, MEMORY_ALLOCATION_ALIGNMENT)),
56*8a978a17SVictor Perevertkin m_Globals(FxDriverGlobals)
57*8a978a17SVictor Perevertkin #if FX_CORE_MODE==FX_CORE_USER_MODE
58*8a978a17SVictor Perevertkin #ifndef INLINE_WRAPPER_ALLOCATION
59*8a978a17SVictor Perevertkin ,m_COMWrapper(NULL)
60*8a978a17SVictor Perevertkin #endif
61*8a978a17SVictor Perevertkin #endif
62*8a978a17SVictor Perevertkin {
63*8a978a17SVictor Perevertkin ASSERT((((ULONG_PTR) this) & FxHandleFlagMask) == 0x0);
64*8a978a17SVictor Perevertkin
65*8a978a17SVictor Perevertkin Construct(FALSE);
66*8a978a17SVictor Perevertkin }
67*8a978a17SVictor Perevertkin
FxObject(__in WDFTYPE Type,__in USHORT Size,__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in FxObjectType ObjectType)68*8a978a17SVictor Perevertkin FxObject::FxObject(
69*8a978a17SVictor Perevertkin __in WDFTYPE Type,
70*8a978a17SVictor Perevertkin __in USHORT Size,
71*8a978a17SVictor Perevertkin __in PFX_DRIVER_GLOBALS FxDriverGlobals,
72*8a978a17SVictor Perevertkin __in FxObjectType ObjectType
73*8a978a17SVictor Perevertkin ) :
74*8a978a17SVictor Perevertkin m_Type(Type),
75*8a978a17SVictor Perevertkin m_ObjectSize((USHORT) WDF_ALIGN_SIZE_UP(Size, MEMORY_ALLOCATION_ALIGNMENT)),
76*8a978a17SVictor Perevertkin m_Globals(FxDriverGlobals)
77*8a978a17SVictor Perevertkin {
78*8a978a17SVictor Perevertkin if (ObjectType != FxObjectTypeEmbedded) {
79*8a978a17SVictor Perevertkin //
80*8a978a17SVictor Perevertkin // only for non embedded objects
81*8a978a17SVictor Perevertkin //
82*8a978a17SVictor Perevertkin ASSERT((((ULONG_PTR) this) & FxHandleFlagMask) == 0x0);
83*8a978a17SVictor Perevertkin }
84*8a978a17SVictor Perevertkin
85*8a978a17SVictor Perevertkin Construct(ObjectType == FxObjectTypeEmbedded ? TRUE : FALSE);
86*8a978a17SVictor Perevertkin }
87*8a978a17SVictor Perevertkin
~FxObject()88*8a978a17SVictor Perevertkin FxObject::~FxObject()
89*8a978a17SVictor Perevertkin {
90*8a978a17SVictor Perevertkin FxTagTracker *pTagTracker;
91*8a978a17SVictor Perevertkin
92*8a978a17SVictor Perevertkin
93*8a978a17SVictor Perevertkin
94*8a978a17SVictor Perevertkin
95*8a978a17SVictor Perevertkin
96*8a978a17SVictor Perevertkin
97*8a978a17SVictor Perevertkin
98*8a978a17SVictor Perevertkin pTagTracker = GetTagTracker();
99*8a978a17SVictor Perevertkin
100*8a978a17SVictor Perevertkin if (pTagTracker != NULL) {
101*8a978a17SVictor Perevertkin delete pTagTracker;
102*8a978a17SVictor Perevertkin }
103*8a978a17SVictor Perevertkin
104*8a978a17SVictor Perevertkin ASSERT(m_DisposeSingleEntry.Next == NULL);
105*8a978a17SVictor Perevertkin
106*8a978a17SVictor Perevertkin //
107*8a978a17SVictor Perevertkin // We need to ensure there are no leaked child objects, or
108*8a978a17SVictor Perevertkin // parent associations.
109*8a978a17SVictor Perevertkin //
110*8a978a17SVictor Perevertkin // This can occur if someone calls the C++ operator delete,
111*8a978a17SVictor Perevertkin // or Release() to destroy the object.
112*8a978a17SVictor Perevertkin //
113*8a978a17SVictor Perevertkin // This is generally invalid in the framework, though certain
114*8a978a17SVictor Perevertkin // objects may understand the underlying contract, but must
115*8a978a17SVictor Perevertkin // make sure there are no left over un-Disposed associations.
116*8a978a17SVictor Perevertkin //
117*8a978a17SVictor Perevertkin // Embedded FxObject's also don't have delete called on them,
118*8a978a17SVictor Perevertkin // and have to manually manage any child associations when
119*8a978a17SVictor Perevertkin // their parent object disposes by calling PerformEarlyDispose.
120*8a978a17SVictor Perevertkin //
121*8a978a17SVictor Perevertkin // They don't have an associated lifetime parent since they
122*8a978a17SVictor Perevertkin // are embedded.
123*8a978a17SVictor Perevertkin //
124*8a978a17SVictor Perevertkin if (m_ParentObject != NULL ||
125*8a978a17SVictor Perevertkin !IsListEmpty(&m_ChildListHead) || !IsListEmpty(&m_ChildEntry)) {
126*8a978a17SVictor Perevertkin PCSTR pHandleName;
127*8a978a17SVictor Perevertkin
128*8a978a17SVictor Perevertkin pHandleName = FxObjectTypeToHandleName(m_Type);
129*8a978a17SVictor Perevertkin if (pHandleName == NULL) {
130*8a978a17SVictor Perevertkin pHandleName = "WDFOBJECT";
131*8a978a17SVictor Perevertkin }
132*8a978a17SVictor Perevertkin
133*8a978a17SVictor Perevertkin ASSERTMSG(
134*8a978a17SVictor Perevertkin "Object was freed using WdfObjectDereference, not WdfObjectDelete\n",
135*8a978a17SVictor Perevertkin m_ParentObject == NULL &&
136*8a978a17SVictor Perevertkin IsListEmpty(&m_ChildEntry) &&
137*8a978a17SVictor Perevertkin IsListEmpty(&m_ChildListHead)
138*8a978a17SVictor Perevertkin );
139*8a978a17SVictor Perevertkin
140*8a978a17SVictor Perevertkin DoTraceLevelMessage(
141*8a978a17SVictor Perevertkin GetDriverGlobals(), TRACE_LEVEL_FATAL, TRACINGOBJECT,
142*8a978a17SVictor Perevertkin "Handle %s %p (raw object %p) was freed using "
143*8a978a17SVictor Perevertkin "WdfObjectDereference(), not WdfObjectDelete()",
144*8a978a17SVictor Perevertkin pHandleName, GetObjectHandleUnchecked(), this);
145*8a978a17SVictor Perevertkin
146*8a978a17SVictor Perevertkin FxVerifierBugCheck(GetDriverGlobals(),
147*8a978a17SVictor Perevertkin WDF_OBJECT_ERROR,
148*8a978a17SVictor Perevertkin (ULONG_PTR) GetObjectHandleUnchecked(),
149*8a978a17SVictor Perevertkin (ULONG_PTR) this);
150*8a978a17SVictor Perevertkin }
151*8a978a17SVictor Perevertkin
152*8a978a17SVictor Perevertkin //
153*8a978a17SVictor Perevertkin // This is called when the reference count goes to zero
154*8a978a17SVictor Perevertkin //
155*8a978a17SVictor Perevertkin SetObjectStateLocked(FxObjectStateDestroyed);
156*8a978a17SVictor Perevertkin }
157*8a978a17SVictor Perevertkin
158*8a978a17SVictor Perevertkin
159*8a978a17SVictor Perevertkin VOID
FX_VF_METHOD(FxObject,VerifyConstruct)160*8a978a17SVictor Perevertkin FX_VF_METHOD(FxObject, VerifyConstruct) (
161*8a978a17SVictor Perevertkin _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
162*8a978a17SVictor Perevertkin _In_ BOOLEAN Embedded
163*8a978a17SVictor Perevertkin )
164*8a978a17SVictor Perevertkin {
165*8a978a17SVictor Perevertkin UNREFERENCED_PARAMETER(FxDriverGlobals);
166*8a978a17SVictor Perevertkin
167*8a978a17SVictor Perevertkin #if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE))
168*8a978a17SVictor Perevertkin PAGED_CODE_LOCKED();
169*8a978a17SVictor Perevertkin #endif
170*8a978a17SVictor Perevertkin
171*8a978a17SVictor Perevertkin ASSERTMSG(
172*8a978a17SVictor Perevertkin "this object's type is not listed in FxObjectsInfo\n",
173*8a978a17SVictor Perevertkin FxVerifyObjectTypeInTable(m_Type));
174*8a978a17SVictor Perevertkin
175*8a978a17SVictor Perevertkin //
176*8a978a17SVictor Perevertkin // If this is an embedded object, there is no possibility of having
177*8a978a17SVictor Perevertkin // a debug extension, so do not set FXOBJECT_FLAGS_HAS_DEBUG *ever*
178*8a978a17SVictor Perevertkin // in this case.
179*8a978a17SVictor Perevertkin //
180*8a978a17SVictor Perevertkin if (m_Globals->IsObjectDebugOn() && Embedded == FALSE) {
181*8a978a17SVictor Perevertkin FxObjectDebugExtension* pExtension;
182*8a978a17SVictor Perevertkin
183*8a978a17SVictor Perevertkin m_ObjectFlags |= FXOBJECT_FLAGS_HAS_DEBUG;
184*8a978a17SVictor Perevertkin
185*8a978a17SVictor Perevertkin pExtension = GetDebugExtension();
186*8a978a17SVictor Perevertkin ASSERT(pExtension->Signature == FxObjectDebugExtensionSignature);
187*8a978a17SVictor Perevertkin
188*8a978a17SVictor Perevertkin //
189*8a978a17SVictor Perevertkin // Assume that zero is an invalid state.
190*8a978a17SVictor Perevertkin //
191*8a978a17SVictor Perevertkin WDFCASSERT(FxObjectStateInvalid == 0x0);
192*8a978a17SVictor Perevertkin RtlZeroMemory(&pExtension->StateHistory[0],
193*8a978a17SVictor Perevertkin ARRAY_SIZE(pExtension->StateHistory));
194*8a978a17SVictor Perevertkin pExtension->StateHistoryIndex = 0;
195*8a978a17SVictor Perevertkin
196*8a978a17SVictor Perevertkin //
197*8a978a17SVictor Perevertkin // Setup the first slot to our new state.
198*8a978a17SVictor Perevertkin //
199*8a978a17SVictor Perevertkin pExtension->StateHistory[0] = FxObjectStateCreated;
200*8a978a17SVictor Perevertkin
201*8a978a17SVictor Perevertkin AllocateTagTracker(m_Type);
202*8a978a17SVictor Perevertkin }
203*8a978a17SVictor Perevertkin }
204*8a978a17SVictor Perevertkin
205*8a978a17SVictor Perevertkin
206*8a978a17SVictor Perevertkin VOID
FinalRelease(VOID)207*8a978a17SVictor Perevertkin FxObject::FinalRelease(
208*8a978a17SVictor Perevertkin VOID
209*8a978a17SVictor Perevertkin )
210*8a978a17SVictor Perevertkin {
211*8a978a17SVictor Perevertkin
212*8a978a17SVictor Perevertkin
213*8a978a17SVictor Perevertkin
214*8a978a17SVictor Perevertkin
215*8a978a17SVictor Perevertkin
216*8a978a17SVictor Perevertkin
217*8a978a17SVictor Perevertkin
218*8a978a17SVictor Perevertkin
219*8a978a17SVictor Perevertkin
220*8a978a17SVictor Perevertkin
221*8a978a17SVictor Perevertkin
222*8a978a17SVictor Perevertkin
223*8a978a17SVictor Perevertkin //
224*8a978a17SVictor Perevertkin // No other access, OK to test flag without grabbing spinlock
225*8a978a17SVictor Perevertkin // since it can only be set at create.
226*8a978a17SVictor Perevertkin //
227*8a978a17SVictor Perevertkin if (ShouldDeferDisposeLocked()) {
228*8a978a17SVictor Perevertkin //
229*8a978a17SVictor Perevertkin // If this is a passive level only object, ensure we only destroy
230*8a978a17SVictor Perevertkin // it from passive level. No need to hold the object lock when
231*8a978a17SVictor Perevertkin // changing to this state since no other thread can change our
232*8a978a17SVictor Perevertkin // state.
233*8a978a17SVictor Perevertkin //
234*8a978a17SVictor Perevertkin SetObjectStateLocked(FxObjectStateDeferedDestroy);
235*8a978a17SVictor Perevertkin
236*8a978a17SVictor Perevertkin //
237*8a978a17SVictor Perevertkin // Note, we cannot be holding a lock while making this call b/c by
238*8a978a17SVictor Perevertkin // the time it returns, it could have freed the object and the
239*8a978a17SVictor Perevertkin // KeReleaseSpinLock call would have touched freed pool.
240*8a978a17SVictor Perevertkin //
241*8a978a17SVictor Perevertkin
242*8a978a17SVictor Perevertkin //FxToObjectItf::FxAddToDriverDisposeList(m_Globals, this);
243*8a978a17SVictor Perevertkin
244*8a978a17SVictor Perevertkin
245*8a978a17SVictor Perevertkin m_Globals->Driver->GetDisposeList()->Add(this);
246*8a978a17SVictor Perevertkin
247*8a978a17SVictor Perevertkin }
248*8a978a17SVictor Perevertkin else {
249*8a978a17SVictor Perevertkin ProcessDestroy();
250*8a978a17SVictor Perevertkin }
251*8a978a17SVictor Perevertkin }
252*8a978a17SVictor Perevertkin
253*8a978a17SVictor Perevertkin _Must_inspect_result_
254*8a978a17SVictor Perevertkin NTSTATUS
QueryInterface(__in FxQueryInterfaceParams * Params)255*8a978a17SVictor Perevertkin FxObject::QueryInterface(
256*8a978a17SVictor Perevertkin __in FxQueryInterfaceParams* Params
257*8a978a17SVictor Perevertkin )
258*8a978a17SVictor Perevertkin {
259*8a978a17SVictor Perevertkin NTSTATUS status;
260*8a978a17SVictor Perevertkin
261*8a978a17SVictor Perevertkin if (Params->Type == FX_TYPE_OBJECT) {
262*8a978a17SVictor Perevertkin *Params->Object = this;
263*8a978a17SVictor Perevertkin status = STATUS_SUCCESS;
264*8a978a17SVictor Perevertkin }
265*8a978a17SVictor Perevertkin else {
266*8a978a17SVictor Perevertkin status = STATUS_NOINTERFACE;
267*8a978a17SVictor Perevertkin }
268*8a978a17SVictor Perevertkin
269*8a978a17SVictor Perevertkin return status;
270*8a978a17SVictor Perevertkin }
271*8a978a17SVictor Perevertkin
272*8a978a17SVictor Perevertkin VOID
AllocateTagTracker(__in WDFTYPE Type)273*8a978a17SVictor Perevertkin FxObject::AllocateTagTracker(
274*8a978a17SVictor Perevertkin __in WDFTYPE Type
275*8a978a17SVictor Perevertkin )
276*8a978a17SVictor Perevertkin {
277*8a978a17SVictor Perevertkin ASSERT(IsDebug());
278*8a978a17SVictor Perevertkin
279*8a978a17SVictor Perevertkin if (m_Globals->DebugExtension != NULL &&
280*8a978a17SVictor Perevertkin m_Globals->DebugExtension->ObjectDebugInfo != NULL &&
281*8a978a17SVictor Perevertkin FxVerifierGetTrackReferences(
282*8a978a17SVictor Perevertkin m_Globals->DebugExtension->ObjectDebugInfo,
283*8a978a17SVictor Perevertkin Type)) {
284*8a978a17SVictor Perevertkin //
285*8a978a17SVictor Perevertkin // Failure to CreateAndInitialize a tag tracker is no big deal, we just
286*8a978a17SVictor Perevertkin // don't track references.
287*8a978a17SVictor Perevertkin //
288*8a978a17SVictor Perevertkin
289*8a978a17SVictor Perevertkin (void) FxTagTracker::CreateAndInitialize(
290*8a978a17SVictor Perevertkin &GetDebugExtension()->TagTracker,
291*8a978a17SVictor Perevertkin m_Globals,
292*8a978a17SVictor Perevertkin FxTagTrackerTypeHandle,
293*8a978a17SVictor Perevertkin FALSE,
294*8a978a17SVictor Perevertkin this
295*8a978a17SVictor Perevertkin );
296*8a978a17SVictor Perevertkin
297*8a978a17SVictor Perevertkin //
298*8a978a17SVictor Perevertkin // For now we overload the requirement of a tag tracker as also tracing
299*8a978a17SVictor Perevertkin // state changes.
300*8a978a17SVictor Perevertkin //
301*8a978a17SVictor Perevertkin m_ObjectFlags |= FXOBJECT_FLAGS_TRACE_STATE;
302*8a978a17SVictor Perevertkin }
303*8a978a17SVictor Perevertkin }
304*8a978a17SVictor Perevertkin
305*8a978a17SVictor Perevertkin VOID
operator delete(__in PVOID Memory)306*8a978a17SVictor Perevertkin FxObject::operator delete(
307*8a978a17SVictor Perevertkin __in PVOID Memory
308*8a978a17SVictor Perevertkin )
309*8a978a17SVictor Perevertkin {
310*8a978a17SVictor Perevertkin ASSERT(Memory != NULL);
311*8a978a17SVictor Perevertkin
312*8a978a17SVictor Perevertkin
313*8a978a17SVictor Perevertkin
314*8a978a17SVictor Perevertkin
315*8a978a17SVictor Perevertkin
316*8a978a17SVictor Perevertkin
317*8a978a17SVictor Perevertkin
318*8a978a17SVictor Perevertkin
319*8a978a17SVictor Perevertkin
320*8a978a17SVictor Perevertkin
321*8a978a17SVictor Perevertkin
322*8a978a17SVictor Perevertkin
323*8a978a17SVictor Perevertkin
324*8a978a17SVictor Perevertkin FxPoolFree(_GetBase((FxObject*) Memory));
325*8a978a17SVictor Perevertkin }
326*8a978a17SVictor Perevertkin
327*8a978a17SVictor Perevertkin VOID
CallCleanupCallbacks(VOID)328*8a978a17SVictor Perevertkin FxObject::CallCleanupCallbacks(
329*8a978a17SVictor Perevertkin VOID
330*8a978a17SVictor Perevertkin )
331*8a978a17SVictor Perevertkin {
332*8a978a17SVictor Perevertkin FxContextHeader* pHeader;
333*8a978a17SVictor Perevertkin WDFOBJECT h;
334*8a978a17SVictor Perevertkin
335*8a978a17SVictor Perevertkin //
336*8a978a17SVictor Perevertkin // Deleted before Commit or it is an internal object
337*8a978a17SVictor Perevertkin //
338*8a978a17SVictor Perevertkin if (IsCommitted() == FALSE) {
339*8a978a17SVictor Perevertkin return;
340*8a978a17SVictor Perevertkin }
341*8a978a17SVictor Perevertkin
342*8a978a17SVictor Perevertkin //
343*8a978a17SVictor Perevertkin // We only should have an object handle when we have an external object
344*8a978a17SVictor Perevertkin //
345*8a978a17SVictor Perevertkin h = GetObjectHandle();
346*8a978a17SVictor Perevertkin
347*8a978a17SVictor Perevertkin for (pHeader = GetContextHeader();
348*8a978a17SVictor Perevertkin pHeader != NULL;
349*8a978a17SVictor Perevertkin pHeader = pHeader->NextHeader) {
350*8a978a17SVictor Perevertkin if (pHeader->EvtCleanupCallback != NULL) {
351*8a978a17SVictor Perevertkin pHeader->EvtCleanupCallback(h);
352*8a978a17SVictor Perevertkin pHeader->EvtCleanupCallback = NULL;
353*8a978a17SVictor Perevertkin }
354*8a978a17SVictor Perevertkin }
355*8a978a17SVictor Perevertkin
356*8a978a17SVictor Perevertkin m_ObjectFlags &= ~FXOBJECT_FLAGS_HAS_CLEANUP;
357*8a978a17SVictor Perevertkin }
358*8a978a17SVictor Perevertkin
359*8a978a17SVictor Perevertkin VOID
ClearEvtCallbacks(VOID)360*8a978a17SVictor Perevertkin FxObject::ClearEvtCallbacks(
361*8a978a17SVictor Perevertkin VOID
362*8a978a17SVictor Perevertkin )
363*8a978a17SVictor Perevertkin /*++
364*8a978a17SVictor Perevertkin
365*8a978a17SVictor Perevertkin Routine Description:
366*8a978a17SVictor Perevertkin
367*8a978a17SVictor Perevertkin Clears out any assigned callbacks on the object.
368*8a978a17SVictor Perevertkin
369*8a978a17SVictor Perevertkin Arguments:
370*8a978a17SVictor Perevertkin None
371*8a978a17SVictor Perevertkin
372*8a978a17SVictor Perevertkin Return Value:
373*8a978a17SVictor Perevertkin None
374*8a978a17SVictor Perevertkin
375*8a978a17SVictor Perevertkin --*/
376*8a978a17SVictor Perevertkin {
377*8a978a17SVictor Perevertkin FxContextHeader *pHeader;
378*8a978a17SVictor Perevertkin
379*8a978a17SVictor Perevertkin for (pHeader = GetContextHeader();
380*8a978a17SVictor Perevertkin pHeader != NULL;
381*8a978a17SVictor Perevertkin pHeader = pHeader->NextHeader) {
382*8a978a17SVictor Perevertkin
383*8a978a17SVictor Perevertkin pHeader->EvtDestroyCallback = NULL;
384*8a978a17SVictor Perevertkin pHeader->EvtCleanupCallback = NULL;
385*8a978a17SVictor Perevertkin }
386*8a978a17SVictor Perevertkin
387*8a978a17SVictor Perevertkin m_ObjectFlags &= ~FXOBJECT_FLAGS_HAS_CLEANUP;
388*8a978a17SVictor Perevertkin }
389*8a978a17SVictor Perevertkin
390*8a978a17SVictor Perevertkin VOID
DeleteFromFailedCreate(VOID)391*8a978a17SVictor Perevertkin FxObject::DeleteFromFailedCreate(
392*8a978a17SVictor Perevertkin VOID
393*8a978a17SVictor Perevertkin )
394*8a978a17SVictor Perevertkin /*++
395*8a978a17SVictor Perevertkin
396*8a978a17SVictor Perevertkin Routine Description:
397*8a978a17SVictor Perevertkin Clears out any assigned callbacks on the object and then deletes it. Clearing
398*8a978a17SVictor Perevertkin out the callbacks are necessary so that the driver's callbacks are not called
399*8a978a17SVictor Perevertkin on a buffer that they didn't initialize.
400*8a978a17SVictor Perevertkin
401*8a978a17SVictor Perevertkin Arguments:
402*8a978a17SVictor Perevertkin None
403*8a978a17SVictor Perevertkin
404*8a978a17SVictor Perevertkin Return Value:
405*8a978a17SVictor Perevertkin None
406*8a978a17SVictor Perevertkin
407*8a978a17SVictor Perevertkin --*/
408*8a978a17SVictor Perevertkin {
409*8a978a17SVictor Perevertkin ClearEvtCallbacks();
410*8a978a17SVictor Perevertkin
411*8a978a17SVictor Perevertkin //
412*8a978a17SVictor Perevertkin // After this call returns "this" is destroyed is not a valid pointer!
413*8a978a17SVictor Perevertkin //
414*8a978a17SVictor Perevertkin DeleteObject();
415*8a978a17SVictor Perevertkin
416*8a978a17SVictor Perevertkin //
417*8a978a17SVictor Perevertkin // "this" is now freed memory, do not touch it!
418*8a978a17SVictor Perevertkin //
419*8a978a17SVictor Perevertkin }
420*8a978a17SVictor Perevertkin
421*8a978a17SVictor Perevertkin //
422*8a978a17SVictor Perevertkin // FxObject Parent/Child Rules:
423*8a978a17SVictor Perevertkin //
424*8a978a17SVictor Perevertkin // The FxObject state machine protects state transitions when
425*8a978a17SVictor Perevertkin // objects are being associated with each other, and races
426*8a978a17SVictor Perevertkin // that can occur when a child and parent object are being
427*8a978a17SVictor Perevertkin // deleted at the same time. This provides the backbone of
428*8a978a17SVictor Perevertkin // assurance on the objects state.
429*8a978a17SVictor Perevertkin //
430*8a978a17SVictor Perevertkin // While transiting object states, the following must be taken
431*8a978a17SVictor Perevertkin // into consideration:
432*8a978a17SVictor Perevertkin //
433*8a978a17SVictor Perevertkin // Reference counts:
434*8a978a17SVictor Perevertkin //
435*8a978a17SVictor Perevertkin // When an object is created with operator new(), it has a reference count
436*8a978a17SVictor Perevertkin // of one.
437*8a978a17SVictor Perevertkin //
438*8a978a17SVictor Perevertkin // When a DeleteObject is done on it, the reference count is decremented
439*8a978a17SVictor Perevertkin // after delete processing is done (which can include disposing children),
440*8a978a17SVictor Perevertkin // and this results in the objects destruction.
441*8a978a17SVictor Perevertkin //
442*8a978a17SVictor Perevertkin // When an object is created by operator new() and immediately associated
443*8a978a17SVictor Perevertkin // with a parent object, its reference count remains one.
444*8a978a17SVictor Perevertkin //
445*8a978a17SVictor Perevertkin // When either the DeleteObject() method is invoked, or the parent object
446*8a978a17SVictor Perevertkin // disposes the child object with ParentDeleteEvent(), eventually the
447*8a978a17SVictor Perevertkin // object will dereference itself after delete processing is done only
448*8a978a17SVictor Perevertkin // once.
449*8a978a17SVictor Perevertkin //
450*8a978a17SVictor Perevertkin // Even in the face of race conditions, the object state machine ensures that
451*8a978a17SVictor Perevertkin // only one set of the proper delete conditions occur (dispose children, invoke
452*8a978a17SVictor Perevertkin // driver and class dispose callbacks, dereference object).
453*8a978a17SVictor Perevertkin //
454*8a978a17SVictor Perevertkin // An object is responsible for releasing its own reference count on its
455*8a978a17SVictor Perevertkin // self when it goes into the FxObjectStateDeletedAndDisposed.
456*8a978a17SVictor Perevertkin //
457*8a978a17SVictor Perevertkin // This has been *carefully* designed so that only the original object
458*8a978a17SVictor Perevertkin // references are required for this automatic lifetime case to avoid
459*8a978a17SVictor Perevertkin // extra interlocked operations in AddRef and Release frequently. These
460*8a978a17SVictor Perevertkin // extra interlocked operations can have a big performance impact on
461*8a978a17SVictor Perevertkin // the WDF main I/O paths, in which object relationship's are being used.
462*8a978a17SVictor Perevertkin //
463*8a978a17SVictor Perevertkin // A simpler implementation may try and have the parent add a reference
464*8a978a17SVictor Perevertkin // to the child, and the child add a reference to the parent, but this
465*8a978a17SVictor Perevertkin // is a tightly coupled implementation controlled by the object state
466*8a978a17SVictor Perevertkin // machine. A circular reference pattern is OK for objects that
467*8a978a17SVictor Perevertkin // do not have a formal designed in relationship that can be expressed
468*8a978a17SVictor Perevertkin // in the complex tear down contract implemented in the state machine.
469*8a978a17SVictor Perevertkin //
470*8a978a17SVictor Perevertkin // SpinLocks:
471*8a978a17SVictor Perevertkin //
472*8a978a17SVictor Perevertkin // The m_SpinLock field protects each indivdual objects m_ObjectState
473*8a978a17SVictor Perevertkin // variable, the list of child objects that it has, and the m_ParentObject
474*8a978a17SVictor Perevertkin // field.
475*8a978a17SVictor Perevertkin //
476*8a978a17SVictor Perevertkin // In addition, if any object associates itself with a parent object,
477*8a978a17SVictor Perevertkin // it effectively "lends" its m_ChildEntry field to the parent object,
478*8a978a17SVictor Perevertkin // and these are manipulated and protected by the parent objects m_SpinLock.
479*8a978a17SVictor Perevertkin //
480*8a978a17SVictor Perevertkin // Lock Order:
481*8a978a17SVictor Perevertkin //
482*8a978a17SVictor Perevertkin // Currently the lock order is Child -> Parent, meaning a child
483*8a978a17SVictor Perevertkin // can call the AddChildObjectInternal, RemoveChildObjectInternal, methods with
484*8a978a17SVictor Perevertkin // the child lock held.
485*8a978a17SVictor Perevertkin //
486*8a978a17SVictor Perevertkin // The parent object will not invoke any child object ParentDeleteEvent()
487*8a978a17SVictor Perevertkin // while holding the parents m_SpinLock.
488*8a978a17SVictor Perevertkin //
489*8a978a17SVictor Perevertkin // This order allows potential races between child DeleteObject and parent
490*8a978a17SVictor Perevertkin // Dispose to be resolved without extra reference counts and multiple
491*8a978a17SVictor Perevertkin // acquires and releases of the spinlocks in the normal cases.
492*8a978a17SVictor Perevertkin //
493*8a978a17SVictor Perevertkin //
494*8a978a17SVictor Perevertkin // AddChildObjectInternal/RemoveChildObjectInternal:
495*8a978a17SVictor Perevertkin //
496*8a978a17SVictor Perevertkin // When a child object is added to the parent, the parent can delete
497*8a978a17SVictor Perevertkin // the child object at any time when the parent object is deleted
498*8a978a17SVictor Perevertkin // or disposed.
499*8a978a17SVictor Perevertkin //
500*8a978a17SVictor Perevertkin // If a call to RemoveChildObjectInternal is made, the caller may not "win"
501*8a978a17SVictor Perevertkin // the inherent race with a parent object Dispose() occuring. This
502*8a978a17SVictor Perevertkin // is similar to the WDM IRP cancel race, and is handled in exactly
503*8a978a17SVictor Perevertkin // the same fashion.
504*8a978a17SVictor Perevertkin //
505*8a978a17SVictor Perevertkin // If an object is associated with a parent, and later removal
506*8a978a17SVictor Perevertkin // is desired, the return status of RemoveChildObjectInternal must be
507*8a978a17SVictor Perevertkin // tested, and if not success, the caller should not delete the
508*8a978a17SVictor Perevertkin // child object itself, since the parent is in the process
509*8a978a17SVictor Perevertkin // of doing so. The caller "lost the Dispose race".
510*8a978a17SVictor Perevertkin //
511*8a978a17SVictor Perevertkin //
512*8a978a17SVictor Perevertkin // m_ParentObject field:
513*8a978a17SVictor Perevertkin //
514*8a978a17SVictor Perevertkin // This field is set by the child object after it successfully
515*8a978a17SVictor Perevertkin // adds a parent object, and clear it when it is disposed by
516*8a978a17SVictor Perevertkin // the parent, or removes the parent association.
517*8a978a17SVictor Perevertkin //
518*8a978a17SVictor Perevertkin // It is protected by the childs m_SpinLock field.
519*8a978a17SVictor Perevertkin //
520*8a978a17SVictor Perevertkin
521*8a978a17SVictor Perevertkin
522*8a978a17SVictor Perevertkin
523*8a978a17SVictor Perevertkin
524*8a978a17SVictor Perevertkin
525*8a978a17SVictor Perevertkin
526*8a978a17SVictor Perevertkin
527*8a978a17SVictor Perevertkin _Must_inspect_result_
528*8a978a17SVictor Perevertkin NTSTATUS
AssignParentObject(__in FxObject * ParentObject)529*8a978a17SVictor Perevertkin FxObject::AssignParentObject(
530*8a978a17SVictor Perevertkin __in FxObject* ParentObject
531*8a978a17SVictor Perevertkin )
532*8a978a17SVictor Perevertkin /*++
533*8a978a17SVictor Perevertkin
534*8a978a17SVictor Perevertkin Routine Description:
535*8a978a17SVictor Perevertkin Assign a parent to the current object. The parent can not be the same
536*8a978a17SVictor Perevertkin object.
537*8a978a17SVictor Perevertkin
538*8a978a17SVictor Perevertkin Arguments:
539*8a978a17SVictor Perevertkin ParentObject - Object to become the parent for this object
540*8a978a17SVictor Perevertkin
541*8a978a17SVictor Perevertkin Returns:
542*8a978a17SVictor Perevertkin
543*8a978a17SVictor Perevertkin Comments:
544*8a978a17SVictor Perevertkin
545*8a978a17SVictor Perevertkin The caller "passes" its initial object reference to us, so we
546*8a978a17SVictor Perevertkin do not take an additional reference on the object.
547*8a978a17SVictor Perevertkin
548*8a978a17SVictor Perevertkin If we are deleted, Dispose() will be invoked on the object, and
549*8a978a17SVictor Perevertkin its reference will be released.
550*8a978a17SVictor Perevertkin
551*8a978a17SVictor Perevertkin This provides automatic deletion of associated child objects if
552*8a978a17SVictor Perevertkin the object does not keep any extra references.
553*8a978a17SVictor Perevertkin
554*8a978a17SVictor Perevertkin --*/
555*8a978a17SVictor Perevertkin {
556*8a978a17SVictor Perevertkin KIRQL oldIrql;
557*8a978a17SVictor Perevertkin NTSTATUS status;
558*8a978a17SVictor Perevertkin
559*8a978a17SVictor Perevertkin m_SpinLock.Acquire(&oldIrql);
560*8a978a17SVictor Perevertkin
561*8a978a17SVictor Perevertkin //
562*8a978a17SVictor Perevertkin // Can't add a parent if the current object is being deleted
563*8a978a17SVictor Perevertkin //
564*8a978a17SVictor Perevertkin if (m_ObjectState != FxObjectStateCreated) {
565*8a978a17SVictor Perevertkin TraceDroppedEvent(FxObjectDroppedEventAssignParentObject);
566*8a978a17SVictor Perevertkin m_SpinLock.Release(oldIrql);
567*8a978a17SVictor Perevertkin return STATUS_DELETE_PENDING;
568*8a978a17SVictor Perevertkin }
569*8a978a17SVictor Perevertkin
570*8a978a17SVictor Perevertkin //
571*8a978a17SVictor Perevertkin // Current Object can't already have a parent, and can't
572*8a978a17SVictor Perevertkin // be its own parent.
573*8a978a17SVictor Perevertkin //
574*8a978a17SVictor Perevertkin if (m_ParentObject != NULL) {
575*8a978a17SVictor Perevertkin m_SpinLock.Release(oldIrql);
576*8a978a17SVictor Perevertkin return STATUS_WDF_PARENT_ALREADY_ASSIGNED;
577*8a978a17SVictor Perevertkin }
578*8a978a17SVictor Perevertkin
579*8a978a17SVictor Perevertkin if (m_ParentObject == this) {
580*8a978a17SVictor Perevertkin m_SpinLock.Release(oldIrql);
581*8a978a17SVictor Perevertkin return STATUS_WDF_PARENT_IS_SELF;
582*8a978a17SVictor Perevertkin }
583*8a978a17SVictor Perevertkin
584*8a978a17SVictor Perevertkin //
585*8a978a17SVictor Perevertkin // We don't allow a parent object to be assigned after
586*8a978a17SVictor Perevertkin // FxObject::Commit().
587*8a978a17SVictor Perevertkin //
588*8a978a17SVictor Perevertkin ASSERTMSG("Parent object can not be assigned after Commit()\n", !IsCommitted());
589*8a978a17SVictor Perevertkin
590*8a978a17SVictor Perevertkin ASSERT(IsListEmpty(&this->m_ChildEntry));
591*8a978a17SVictor Perevertkin
592*8a978a17SVictor Perevertkin status = ParentObject->AddChildObjectInternal(this);
593*8a978a17SVictor Perevertkin
594*8a978a17SVictor Perevertkin if (NT_SUCCESS(status)) {
595*8a978a17SVictor Perevertkin m_ParentObject = ParentObject;
596*8a978a17SVictor Perevertkin }
597*8a978a17SVictor Perevertkin
598*8a978a17SVictor Perevertkin m_SpinLock.Release(oldIrql);
599*8a978a17SVictor Perevertkin
600*8a978a17SVictor Perevertkin return status;
601*8a978a17SVictor Perevertkin }
602*8a978a17SVictor Perevertkin
603*8a978a17SVictor Perevertkin _Must_inspect_result_
604*8a978a17SVictor Perevertkin NTSTATUS
AddContext(__in FxContextHeader * Header,__in PVOID * Context,__in PWDF_OBJECT_ATTRIBUTES Attributes)605*8a978a17SVictor Perevertkin FxObject::AddContext(
606*8a978a17SVictor Perevertkin __in FxContextHeader *Header,
607*8a978a17SVictor Perevertkin __in PVOID* Context,
608*8a978a17SVictor Perevertkin __in PWDF_OBJECT_ATTRIBUTES Attributes
609*8a978a17SVictor Perevertkin )
610*8a978a17SVictor Perevertkin {
611*8a978a17SVictor Perevertkin FxContextHeader *pCur, **ppLast;
612*8a978a17SVictor Perevertkin NTSTATUS status;
613*8a978a17SVictor Perevertkin KIRQL irql;
614*8a978a17SVictor Perevertkin
615*8a978a17SVictor Perevertkin status = STATUS_UNSUCCESSFUL;
616*8a978a17SVictor Perevertkin
617*8a978a17SVictor Perevertkin pCur = GetContextHeader();
618*8a978a17SVictor Perevertkin
619*8a978a17SVictor Perevertkin //
620*8a978a17SVictor Perevertkin // This should never happen since all outward facing objects have a
621*8a978a17SVictor Perevertkin // context header; framework never calls this function on internal
622*8a978a17SVictor Perevertkin // objects.
623*8a978a17SVictor Perevertkin //
624*8a978a17SVictor Perevertkin ASSERT(pCur != NULL);
625*8a978a17SVictor Perevertkin
626*8a978a17SVictor Perevertkin //
627*8a978a17SVictor Perevertkin // Acquire the lock to lock the object's state. A side affect of grabbing
628*8a978a17SVictor Perevertkin // the lock is that all updaters who want to add a context are serialized.
629*8a978a17SVictor Perevertkin // All callers who want to find a context do not need to acquire the lock
630*8a978a17SVictor Perevertkin // becuase they are not going to update the list, just read from it.
631*8a978a17SVictor Perevertkin //
632*8a978a17SVictor Perevertkin // Once a context has been added, it will not be removed until the object
633*8a978a17SVictor Perevertkin // has been deleted.
634*8a978a17SVictor Perevertkin //
635*8a978a17SVictor Perevertkin m_SpinLock.Acquire(&irql);
636*8a978a17SVictor Perevertkin
637*8a978a17SVictor Perevertkin if (m_ObjectState == FxObjectStateCreated && pCur != NULL) {
638*8a978a17SVictor Perevertkin //
639*8a978a17SVictor Perevertkin // Iterate over the list of contexts already on this object and see if
640*8a978a17SVictor Perevertkin // this type already is attached.
641*8a978a17SVictor Perevertkin //
642*8a978a17SVictor Perevertkin for (ppLast = &pCur->NextHeader;
643*8a978a17SVictor Perevertkin pCur != NULL;
644*8a978a17SVictor Perevertkin ppLast = &pCur->NextHeader, pCur = pCur->NextHeader) {
645*8a978a17SVictor Perevertkin
646*8a978a17SVictor Perevertkin if (pCur->ContextTypeInfo == Header->ContextTypeInfo) {
647*8a978a17SVictor Perevertkin //
648*8a978a17SVictor Perevertkin // Dupe found, return error but give the caller the context
649*8a978a17SVictor Perevertkin // pointer
650*8a978a17SVictor Perevertkin //
651*8a978a17SVictor Perevertkin if (Context != NULL) {
652*8a978a17SVictor Perevertkin *Context = &pCur->Context[0];
653*8a978a17SVictor Perevertkin }
654*8a978a17SVictor Perevertkin
655*8a978a17SVictor Perevertkin status = STATUS_OBJECT_NAME_EXISTS;
656*8a978a17SVictor Perevertkin break;
657*8a978a17SVictor Perevertkin }
658*8a978a17SVictor Perevertkin }
659*8a978a17SVictor Perevertkin
660*8a978a17SVictor Perevertkin if (pCur == NULL) {
661*8a978a17SVictor Perevertkin //
662*8a978a17SVictor Perevertkin // By using the interlocked to update, we don't need to use a lock
663*8a978a17SVictor Perevertkin // when walking the list to find the context. The only reason
664*8a978a17SVictor Perevertkin // we are holding the object lock is to lock the current state
665*8a978a17SVictor Perevertkin // (m_ObjectState) of the object.
666*8a978a17SVictor Perevertkin //
667*8a978a17SVictor Perevertkin InterlockedExchangePointer((PVOID*) ppLast, Header);
668*8a978a17SVictor Perevertkin status = STATUS_SUCCESS;
669*8a978a17SVictor Perevertkin
670*8a978a17SVictor Perevertkin if (Context != NULL) {
671*8a978a17SVictor Perevertkin *Context = &Header->Context[0];
672*8a978a17SVictor Perevertkin }
673*8a978a17SVictor Perevertkin
674*8a978a17SVictor Perevertkin //
675*8a978a17SVictor Perevertkin // FxContextHeaderInit does not set these callbacks. If this were
676*8a978a17SVictor Perevertkin // the creation of the object itself, FxObject::Commit would have done
677*8a978a17SVictor Perevertkin // this assignment.
678*8a978a17SVictor Perevertkin //
679*8a978a17SVictor Perevertkin Header->EvtDestroyCallback = Attributes->EvtDestroyCallback;
680*8a978a17SVictor Perevertkin
681*8a978a17SVictor Perevertkin if (Attributes->EvtCleanupCallback != NULL) {
682*8a978a17SVictor Perevertkin Header->EvtCleanupCallback = Attributes->EvtCleanupCallback;
683*8a978a17SVictor Perevertkin m_ObjectFlags |= FXOBJECT_FLAGS_HAS_CLEANUP;
684*8a978a17SVictor Perevertkin }
685*8a978a17SVictor Perevertkin
686*8a978a17SVictor Perevertkin }
687*8a978a17SVictor Perevertkin }
688*8a978a17SVictor Perevertkin else {
689*8a978a17SVictor Perevertkin //
690*8a978a17SVictor Perevertkin // Object is being torn down, adding a context is a bad idea because we
691*8a978a17SVictor Perevertkin // cannot guarantee that the cleanup or destroy routines will be called
692*8a978a17SVictor Perevertkin //
693*8a978a17SVictor Perevertkin status = STATUS_DELETE_PENDING;
694*8a978a17SVictor Perevertkin }
695*8a978a17SVictor Perevertkin
696*8a978a17SVictor Perevertkin m_SpinLock.Release(irql);
697*8a978a17SVictor Perevertkin
698*8a978a17SVictor Perevertkin return status;
699*8a978a17SVictor Perevertkin }
700*8a978a17SVictor Perevertkin
701*8a978a17SVictor Perevertkin _Must_inspect_result_
702*8a978a17SVictor Perevertkin NTSTATUS
AddChildObjectInternal(__in FxObject * ChildObject)703*8a978a17SVictor Perevertkin FxObject::AddChildObjectInternal(
704*8a978a17SVictor Perevertkin __in FxObject* ChildObject
705*8a978a17SVictor Perevertkin )
706*8a978a17SVictor Perevertkin
707*8a978a17SVictor Perevertkin /*++
708*8a978a17SVictor Perevertkin
709*8a978a17SVictor Perevertkin Routine Description:
710*8a978a17SVictor Perevertkin Called by an object to be added to this objects child list
711*8a978a17SVictor Perevertkin
712*8a978a17SVictor Perevertkin Arguments:
713*8a978a17SVictor Perevertkin ChildObject - Object to add this this objects child list
714*8a978a17SVictor Perevertkin
715*8a978a17SVictor Perevertkin Returns:
716*8a978a17SVictor Perevertkin NTSTATUS
717*8a978a17SVictor Perevertkin
718*8a978a17SVictor Perevertkin Comments:
719*8a978a17SVictor Perevertkin The caller "passes" its initial object reference to us, so we
720*8a978a17SVictor Perevertkin do not take an additional reference on the object.
721*8a978a17SVictor Perevertkin
722*8a978a17SVictor Perevertkin If we are deleted, Dispose() will be invoked on the object, and
723*8a978a17SVictor Perevertkin its reference will be released.
724*8a978a17SVictor Perevertkin
725*8a978a17SVictor Perevertkin This provides automatic deletion of associated child objects if
726*8a978a17SVictor Perevertkin the object does not keep any extra references.
727*8a978a17SVictor Perevertkin
728*8a978a17SVictor Perevertkin --*/
729*8a978a17SVictor Perevertkin {
730*8a978a17SVictor Perevertkin KIRQL oldIrql;
731*8a978a17SVictor Perevertkin
732*8a978a17SVictor Perevertkin m_SpinLock.Acquire(&oldIrql);
733*8a978a17SVictor Perevertkin
734*8a978a17SVictor Perevertkin //
735*8a978a17SVictor Perevertkin // Can't add child if the current object is being deleted
736*8a978a17SVictor Perevertkin //
737*8a978a17SVictor Perevertkin if (m_ObjectState != FxObjectStateCreated) {
738*8a978a17SVictor Perevertkin TraceDroppedEvent(FxObjectDroppedEventAddChildObjectInternal);
739*8a978a17SVictor Perevertkin m_SpinLock.Release(oldIrql);
740*8a978a17SVictor Perevertkin return STATUS_DELETE_PENDING;
741*8a978a17SVictor Perevertkin }
742*8a978a17SVictor Perevertkin
743*8a978a17SVictor Perevertkin //
744*8a978a17SVictor Perevertkin // ChildObject can't already have a parent, and can't
745*8a978a17SVictor Perevertkin // be its own parent.
746*8a978a17SVictor Perevertkin //
747*8a978a17SVictor Perevertkin ASSERT(ChildObject->m_ParentObject == NULL);
748*8a978a17SVictor Perevertkin ASSERT(IsListEmpty(&ChildObject->m_ChildEntry));
749*8a978a17SVictor Perevertkin ASSERT(ChildObject != this);
750*8a978a17SVictor Perevertkin
751*8a978a17SVictor Perevertkin //
752*8a978a17SVictor Perevertkin // Add to our m_ChildList
753*8a978a17SVictor Perevertkin //
754*8a978a17SVictor Perevertkin InsertTailList(&m_ChildListHead, &ChildObject->m_ChildEntry);
755*8a978a17SVictor Perevertkin
756*8a978a17SVictor Perevertkin if (ChildObject->GetDeviceBase() == NULL) {
757*8a978a17SVictor Perevertkin //
758*8a978a17SVictor Perevertkin // Propagate the device base downward to the child
759*8a978a17SVictor Perevertkin //
760*8a978a17SVictor Perevertkin ChildObject->SetDeviceBase(GetDeviceBase());
761*8a978a17SVictor Perevertkin }
762*8a978a17SVictor Perevertkin
763*8a978a17SVictor Perevertkin m_SpinLock.Release(oldIrql);
764*8a978a17SVictor Perevertkin
765*8a978a17SVictor Perevertkin return STATUS_SUCCESS;
766*8a978a17SVictor Perevertkin }
767*8a978a17SVictor Perevertkin
768*8a978a17SVictor Perevertkin _Must_inspect_result_
769*8a978a17SVictor Perevertkin NTSTATUS
RemoveChildObjectInternal(__in FxObject * ChildObject)770*8a978a17SVictor Perevertkin FxObject::RemoveChildObjectInternal(
771*8a978a17SVictor Perevertkin __in FxObject* ChildObject
772*8a978a17SVictor Perevertkin )
773*8a978a17SVictor Perevertkin /*++
774*8a978a17SVictor Perevertkin
775*8a978a17SVictor Perevertkin Routine Description:
776*8a978a17SVictor Perevertkin
777*8a978a17SVictor Perevertkin Remove a ChildObject from our child associations list.
778*8a978a17SVictor Perevertkin
779*8a978a17SVictor Perevertkin The ChildObject must exist in our list if we are not
780*8a978a17SVictor Perevertkin otherwise disposing or deleting ourselves.
781*8a978a17SVictor Perevertkin
782*8a978a17SVictor Perevertkin If we are not disposing, the child is removed from the list
783*8a978a17SVictor Perevertkin and its reference count is unmodified.
784*8a978a17SVictor Perevertkin
785*8a978a17SVictor Perevertkin If we are disposing, a failure is returned so that the caller
786*8a978a17SVictor Perevertkin does not delete or dereference the child object itself, since
787*8a978a17SVictor Perevertkin this is similar to a cancel IRP race condition.
788*8a978a17SVictor Perevertkin
789*8a978a17SVictor Perevertkin Arguments:
790*8a978a17SVictor Perevertkin ChildObject - the object to remove this object's list of children
791*8a978a17SVictor Perevertkin
792*8a978a17SVictor Perevertkin Returns:
793*8a978a17SVictor Perevertkin
794*8a978a17SVictor Perevertkin STATUS_SUCCESS - Child was removed from the list, no parent Dispose()
795*8a978a17SVictor Perevertkin can occur.
796*8a978a17SVictor Perevertkin
797*8a978a17SVictor Perevertkin !STATUS_SUCCESS - Child can not be removed from the list, and is being
798*8a978a17SVictor Perevertkin Disposed by the parent. The caller must *not* delete
799*8a978a17SVictor Perevertkin the object itself.
800*8a978a17SVictor Perevertkin
801*8a978a17SVictor Perevertkin --*/
802*8a978a17SVictor Perevertkin
803*8a978a17SVictor Perevertkin {
804*8a978a17SVictor Perevertkin KIRQL oldIrql;
805*8a978a17SVictor Perevertkin
806*8a978a17SVictor Perevertkin m_SpinLock.Acquire(&oldIrql);
807*8a978a17SVictor Perevertkin
808*8a978a17SVictor Perevertkin //
809*8a978a17SVictor Perevertkin // Object is already being deleted, this object will be removed as a child
810*8a978a17SVictor Perevertkin // by the parents Dispose()
811*8a978a17SVictor Perevertkin //
812*8a978a17SVictor Perevertkin if (m_ObjectState != FxObjectStateCreated) {
813*8a978a17SVictor Perevertkin TraceDroppedEvent(FxObjectDroppedEventRemoveChildObjectInternal);
814*8a978a17SVictor Perevertkin m_SpinLock.Release(oldIrql);
815*8a978a17SVictor Perevertkin return STATUS_DELETE_PENDING;
816*8a978a17SVictor Perevertkin }
817*8a978a17SVictor Perevertkin
818*8a978a17SVictor Perevertkin //
819*8a978a17SVictor Perevertkin // We should be the child object's parent
820*8a978a17SVictor Perevertkin //
821*8a978a17SVictor Perevertkin ASSERT(ChildObject->m_ParentObject == this);
822*8a978a17SVictor Perevertkin
823*8a978a17SVictor Perevertkin //
824*8a978a17SVictor Perevertkin // Child should be on our list
825*8a978a17SVictor Perevertkin //
826*8a978a17SVictor Perevertkin ASSERT(!IsListEmpty(&ChildObject->m_ChildEntry));
827*8a978a17SVictor Perevertkin
828*8a978a17SVictor Perevertkin //
829*8a978a17SVictor Perevertkin // We should have entries if someone wants to remove from our list
830*8a978a17SVictor Perevertkin //
831*8a978a17SVictor Perevertkin ASSERT(!IsListEmpty(&m_ChildListHead));
832*8a978a17SVictor Perevertkin
833*8a978a17SVictor Perevertkin RemoveEntryList(&ChildObject->m_ChildEntry);
834*8a978a17SVictor Perevertkin
835*8a978a17SVictor Perevertkin //
836*8a978a17SVictor Perevertkin // Mark it removed
837*8a978a17SVictor Perevertkin //
838*8a978a17SVictor Perevertkin InitializeListHead(&ChildObject->m_ChildEntry);
839*8a978a17SVictor Perevertkin
840*8a978a17SVictor Perevertkin //
841*8a978a17SVictor Perevertkin // We did not take a reference on the child object when it
842*8a978a17SVictor Perevertkin // was added to the list, so we do not dereference it
843*8a978a17SVictor Perevertkin // on the remove call.
844*8a978a17SVictor Perevertkin //
845*8a978a17SVictor Perevertkin // Note: We only dereference child objects when we are deleted
846*8a978a17SVictor Perevertkin // ourselves, not when the child object manually breaks the
847*8a978a17SVictor Perevertkin // association by calling this method.
848*8a978a17SVictor Perevertkin //
849*8a978a17SVictor Perevertkin m_SpinLock.Release(oldIrql);
850*8a978a17SVictor Perevertkin
851*8a978a17SVictor Perevertkin return STATUS_SUCCESS;
852*8a978a17SVictor Perevertkin }
853*8a978a17SVictor Perevertkin
854*8a978a17SVictor Perevertkin _Must_inspect_result_
855*8a978a17SVictor Perevertkin FxObject*
GetParentObjectReferenced(__in PVOID Tag)856*8a978a17SVictor Perevertkin FxObject::GetParentObjectReferenced(
857*8a978a17SVictor Perevertkin __in PVOID Tag
858*8a978a17SVictor Perevertkin )
859*8a978a17SVictor Perevertkin
860*8a978a17SVictor Perevertkin /*++
861*8a978a17SVictor Perevertkin
862*8a978a17SVictor Perevertkin Routine Description:
863*8a978a17SVictor Perevertkin Return this objects parent, which could be NULL if
864*8a978a17SVictor Perevertkin the object is not part of an association, or this or
865*8a978a17SVictor Perevertkin the parent object is deleting.
866*8a978a17SVictor Perevertkin
867*8a978a17SVictor Perevertkin An extra reference is taken on the parent object which
868*8a978a17SVictor Perevertkin must eventually be released by the caller.
869*8a978a17SVictor Perevertkin
870*8a978a17SVictor Perevertkin Arguments:
871*8a978a17SVictor Perevertkin Tag - Tag to use when referencing the parent
872*8a978a17SVictor Perevertkin
873*8a978a17SVictor Perevertkin Returns:
874*8a978a17SVictor Perevertkin
875*8a978a17SVictor Perevertkin Parent object, otherwise NULL if no parent for this object
876*8a978a17SVictor Perevertkin
877*8a978a17SVictor Perevertkin --*/
878*8a978a17SVictor Perevertkin
879*8a978a17SVictor Perevertkin {
880*8a978a17SVictor Perevertkin KIRQL oldIrql;
881*8a978a17SVictor Perevertkin FxObject* parentObject;
882*8a978a17SVictor Perevertkin
883*8a978a17SVictor Perevertkin m_SpinLock.Acquire(&oldIrql);
884*8a978a17SVictor Perevertkin
885*8a978a17SVictor Perevertkin if (m_ObjectState == FxObjectStateCreated) {
886*8a978a17SVictor Perevertkin parentObject = m_ParentObject;
887*8a978a17SVictor Perevertkin }
888*8a978a17SVictor Perevertkin else {
889*8a978a17SVictor Perevertkin // Parent is disposing us, or we are being disposed
890*8a978a17SVictor Perevertkin parentObject = NULL;
891*8a978a17SVictor Perevertkin }
892*8a978a17SVictor Perevertkin
893*8a978a17SVictor Perevertkin if (parentObject != NULL) {
894*8a978a17SVictor Perevertkin parentObject->ADDREF(Tag);
895*8a978a17SVictor Perevertkin }
896*8a978a17SVictor Perevertkin
897*8a978a17SVictor Perevertkin m_SpinLock.Release(oldIrql);
898*8a978a17SVictor Perevertkin
899*8a978a17SVictor Perevertkin return parentObject;
900*8a978a17SVictor Perevertkin }
901*8a978a17SVictor Perevertkin
902*8a978a17SVictor Perevertkin _Must_inspect_result_
903*8a978a17SVictor Perevertkin NTSTATUS
Commit(__in_opt PWDF_OBJECT_ATTRIBUTES Attributes,__out_opt WDFOBJECT * ObjectHandle,__in_opt FxObject * Parent,__in BOOLEAN AssignDriverAsDefaultParent)904*8a978a17SVictor Perevertkin FxObject::Commit(
905*8a978a17SVictor Perevertkin __in_opt PWDF_OBJECT_ATTRIBUTES Attributes,
906*8a978a17SVictor Perevertkin __out_opt WDFOBJECT* ObjectHandle,
907*8a978a17SVictor Perevertkin __in_opt FxObject* Parent,
908*8a978a17SVictor Perevertkin __in BOOLEAN AssignDriverAsDefaultParent
909*8a978a17SVictor Perevertkin )
910*8a978a17SVictor Perevertkin /*++
911*8a978a17SVictor Perevertkin
912*8a978a17SVictor Perevertkin Routine Description:
913*8a978a17SVictor Perevertkin Commit the object before returning the handle to the caller.
914*8a978a17SVictor Perevertkin
915*8a978a17SVictor Perevertkin Arguments:
916*8a978a17SVictor Perevertkin Attributes - PWDF_OBJECT_ATTRIBUTES to assign to this object
917*8a978a17SVictor Perevertkin
918*8a978a17SVictor Perevertkin ObjectHandle - Location to return the objects handle
919*8a978a17SVictor Perevertkin
920*8a978a17SVictor Perevertkin Returns:
921*8a978a17SVictor Perevertkin NTSTATUS of the result. STATUS_SUCCESS if success.
922*8a978a17SVictor Perevertkin
923*8a978a17SVictor Perevertkin Returns WDFOBJECT handle if success.
924*8a978a17SVictor Perevertkin
925*8a978a17SVictor Perevertkin --*/
926*8a978a17SVictor Perevertkin {
927*8a978a17SVictor Perevertkin NTSTATUS status;
928*8a978a17SVictor Perevertkin WDFOBJECT object;
929*8a978a17SVictor Perevertkin FxObject* parent;
930*8a978a17SVictor Perevertkin
931*8a978a17SVictor Perevertkin parent = NULL;
932*8a978a17SVictor Perevertkin
933*8a978a17SVictor Perevertkin if (m_ObjectSize == 0) {
934*8a978a17SVictor Perevertkin ASSERTMSG("Only external objects can call Commit()\n",
935*8a978a17SVictor Perevertkin m_ObjectSize != 0);
936*8a978a17SVictor Perevertkin return STATUS_INVALID_HANDLE;
937*8a978a17SVictor Perevertkin }
938*8a978a17SVictor Perevertkin
939*8a978a17SVictor Perevertkin //
940*8a978a17SVictor Perevertkin // For an object to be committed into a handle, it needs to have an object
941*8a978a17SVictor Perevertkin // size. Internal objects set their size to zero as the indication they
942*8a978a17SVictor Perevertkin // are internal and will not be converted into handles.
943*8a978a17SVictor Perevertkin //
944*8a978a17SVictor Perevertkin ASSERT(m_ObjectSize != 0);
945*8a978a17SVictor Perevertkin
946*8a978a17SVictor Perevertkin //
947*8a978a17SVictor Perevertkin // Caller has already validated basic WDF_OBJECT_ATTRIBUTES
948*8a978a17SVictor Perevertkin // with FxValidateObjectAttributes
949*8a978a17SVictor Perevertkin //
950*8a978a17SVictor Perevertkin
951*8a978a17SVictor Perevertkin //
952*8a978a17SVictor Perevertkin // Set object execution level constraint if specified
953*8a978a17SVictor Perevertkin //
954*8a978a17SVictor Perevertkin if (Attributes != NULL &&
955*8a978a17SVictor Perevertkin Attributes->ExecutionLevel == WdfExecutionLevelPassive) {
956*8a978a17SVictor Perevertkin MarkPassiveCallbacks();
957*8a978a17SVictor Perevertkin }
958*8a978a17SVictor Perevertkin
959*8a978a17SVictor Perevertkin //
960*8a978a17SVictor Perevertkin // Assign parent if supplied
961*8a978a17SVictor Perevertkin //
962*8a978a17SVictor Perevertkin if (Parent != NULL) {
963*8a978a17SVictor Perevertkin parent = Parent;
964*8a978a17SVictor Perevertkin }
965*8a978a17SVictor Perevertkin else if (Attributes != NULL && Attributes->ParentObject != NULL) {
966*8a978a17SVictor Perevertkin FxObjectHandleGetPtr(
967*8a978a17SVictor Perevertkin m_Globals,
968*8a978a17SVictor Perevertkin Attributes->ParentObject,
969*8a978a17SVictor Perevertkin FX_TYPE_OBJECT,
970*8a978a17SVictor Perevertkin (PVOID*)&parent
971*8a978a17SVictor Perevertkin );
972*8a978a17SVictor Perevertkin }
973*8a978a17SVictor Perevertkin else {
974*8a978a17SVictor Perevertkin
975*8a978a17SVictor Perevertkin //
976*8a978a17SVictor Perevertkin // If the object already does not have a parent, and
977*8a978a17SVictor Perevertkin // one has not been specified we default it to FxDriver.
978*8a978a17SVictor Perevertkin //
979*8a978a17SVictor Perevertkin // We check to ensure we are not FxDriver being created.
980*8a978a17SVictor Perevertkin //
981*8a978a17SVictor Perevertkin if (AssignDriverAsDefaultParent &&
982*8a978a17SVictor Perevertkin m_ParentObject == NULL) {
983*8a978a17SVictor Perevertkin
984*8a978a17SVictor Perevertkin //parent = FxToObjectItf::FxGetDriverAsDefaultParent(m_Globals, this);
985*8a978a17SVictor Perevertkin
986*8a978a17SVictor Perevertkin
987*8a978a17SVictor Perevertkin if (m_Globals->Driver != this) {
988*8a978a17SVictor Perevertkin parent = m_Globals->Driver;
989*8a978a17SVictor Perevertkin }
990*8a978a17SVictor Perevertkin
991*8a978a17SVictor Perevertkin }
992*8a978a17SVictor Perevertkin }
993*8a978a17SVictor Perevertkin
994*8a978a17SVictor Perevertkin ASSERT(parent != this);
995*8a978a17SVictor Perevertkin
996*8a978a17SVictor Perevertkin if (parent != NULL) {
997*8a978a17SVictor Perevertkin //
998*8a978a17SVictor Perevertkin // Make it the parent of this object
999*8a978a17SVictor Perevertkin //
1000*8a978a17SVictor Perevertkin status = AssignParentObject(parent);
1001*8a978a17SVictor Perevertkin
1002*8a978a17SVictor Perevertkin if (!NT_SUCCESS(status)) {
1003*8a978a17SVictor Perevertkin return status;
1004*8a978a17SVictor Perevertkin }
1005*8a978a17SVictor Perevertkin }
1006*8a978a17SVictor Perevertkin
1007*8a978a17SVictor Perevertkin //
1008*8a978a17SVictor Perevertkin // Now assign the optional EvtObjectCleanup, EvtObjectDestroy callbacks
1009*8a978a17SVictor Perevertkin //
1010*8a978a17SVictor Perevertkin if (Attributes != NULL) {
1011*8a978a17SVictor Perevertkin FxContextHeader* pHeader;
1012*8a978a17SVictor Perevertkin
1013*8a978a17SVictor Perevertkin pHeader = GetContextHeader();
1014*8a978a17SVictor Perevertkin
1015*8a978a17SVictor Perevertkin if (Attributes->EvtDestroyCallback != NULL) {
1016*8a978a17SVictor Perevertkin pHeader->EvtDestroyCallback = Attributes->EvtDestroyCallback;
1017*8a978a17SVictor Perevertkin }
1018*8a978a17SVictor Perevertkin
1019*8a978a17SVictor Perevertkin if (Attributes->EvtCleanupCallback != NULL) {
1020*8a978a17SVictor Perevertkin pHeader->EvtCleanupCallback = Attributes->EvtCleanupCallback;
1021*8a978a17SVictor Perevertkin m_ObjectFlags |= FXOBJECT_FLAGS_HAS_CLEANUP;
1022*8a978a17SVictor Perevertkin }
1023*8a978a17SVictor Perevertkin }
1024*8a978a17SVictor Perevertkin
1025*8a978a17SVictor Perevertkin //
1026*8a978a17SVictor Perevertkin // We mark the handle as committed so that we can create the handle.
1027*8a978a17SVictor Perevertkin //
1028*8a978a17SVictor Perevertkin MarkCommitted();
1029*8a978a17SVictor Perevertkin
1030*8a978a17SVictor Perevertkin //
1031*8a978a17SVictor Perevertkin // Create the object handle, assign EvtObjectCleanup, EvtObjectDestroy
1032*8a978a17SVictor Perevertkin //
1033*8a978a17SVictor Perevertkin FxObjectHandleCreate(this, &object);
1034*8a978a17SVictor Perevertkin
1035*8a978a17SVictor Perevertkin if (ObjectHandle != NULL) {
1036*8a978a17SVictor Perevertkin *ObjectHandle = object;
1037*8a978a17SVictor Perevertkin }
1038*8a978a17SVictor Perevertkin
1039*8a978a17SVictor Perevertkin return STATUS_SUCCESS;
1040*8a978a17SVictor Perevertkin }
1041*8a978a17SVictor Perevertkin
1042*8a978a17SVictor Perevertkin _Must_inspect_result_
1043*8a978a17SVictor Perevertkin NTSTATUS
_GetEffectiveLock(__in FxObject * Object,__in_opt IFxHasCallbacks * Callbacks,__in BOOLEAN AutomaticLocking,__in BOOLEAN PassiveCallbacks,__out FxCallbackLock ** CallbackLock,__out_opt FxObject ** CallbackLockObject)1044*8a978a17SVictor Perevertkin FxObject::_GetEffectiveLock(
1045*8a978a17SVictor Perevertkin __in FxObject* Object,
1046*8a978a17SVictor Perevertkin __in_opt IFxHasCallbacks* Callbacks,
1047*8a978a17SVictor Perevertkin __in BOOLEAN AutomaticLocking,
1048*8a978a17SVictor Perevertkin __in BOOLEAN PassiveCallbacks,
1049*8a978a17SVictor Perevertkin __out FxCallbackLock** CallbackLock,
1050*8a978a17SVictor Perevertkin __out_opt FxObject** CallbackLockObject
1051*8a978a17SVictor Perevertkin )
1052*8a978a17SVictor Perevertkin /*++
1053*8a978a17SVictor Perevertkin
1054*8a978a17SVictor Perevertkin Routine Description:
1055*8a978a17SVictor Perevertkin
1056*8a978a17SVictor Perevertkin This gets the effective lock based on the callback constraints
1057*8a978a17SVictor Perevertkin configuration of the supplied object.
1058*8a978a17SVictor Perevertkin
1059*8a978a17SVictor Perevertkin This is a common routine shared by all FxObject's that utilize
1060*8a978a17SVictor Perevertkin DPC's. Currently, this is FxDpc, FxTimer, and FxInterrupt.
1061*8a978a17SVictor Perevertkin
1062*8a978a17SVictor Perevertkin This contains the common serialization configuration logic for these
1063*8a978a17SVictor Perevertkin objects.
1064*8a978a17SVictor Perevertkin
1065*8a978a17SVictor Perevertkin Arguments:
1066*8a978a17SVictor Perevertkin
1067*8a978a17SVictor Perevertkin Object - Object to serialize with
1068*8a978a17SVictor Perevertkin
1069*8a978a17SVictor Perevertkin Callbacks - Optional interface for acquiring constraints and locking pointers
1070*8a978a17SVictor Perevertkin
1071*8a978a17SVictor Perevertkin AutomaticLocking - TRUE if automatic serialization with Object is required
1072*8a978a17SVictor Perevertkin
1073*8a978a17SVictor Perevertkin PassiveCallbacks - TRUE if the caller requires passive level callback, FALSE
1074*8a978a17SVictor Perevertkin if the
1075*8a978a17SVictor Perevertkin CallbackLock - Lock that is in effect for Object
1076*8a978a17SVictor Perevertkin
1077*8a978a17SVictor Perevertkin CallbackLockOjbect - FxObject that contains the callback lock
1078*8a978a17SVictor Perevertkin
1079*8a978a17SVictor Perevertkin Returns:
1080*8a978a17SVictor Perevertkin
1081*8a978a17SVictor Perevertkin NTSTATUS
1082*8a978a17SVictor Perevertkin
1083*8a978a17SVictor Perevertkin --*/
1084*8a978a17SVictor Perevertkin {
1085*8a978a17SVictor Perevertkin PFX_DRIVER_GLOBALS pFxDriverGlobals;
1086*8a978a17SVictor Perevertkin WDF_EXECUTION_LEVEL parentLevel;
1087*8a978a17SVictor Perevertkin WDF_SYNCHRONIZATION_SCOPE parentScope;
1088*8a978a17SVictor Perevertkin
1089*8a978a17SVictor Perevertkin pFxDriverGlobals = Object->GetDriverGlobals();
1090*8a978a17SVictor Perevertkin *CallbackLock = NULL;
1091*8a978a17SVictor Perevertkin *CallbackLockObject = NULL;
1092*8a978a17SVictor Perevertkin
1093*8a978a17SVictor Perevertkin //
1094*8a978a17SVictor Perevertkin // No automatic locking, nothing to do
1095*8a978a17SVictor Perevertkin //
1096*8a978a17SVictor Perevertkin if (AutomaticLocking == FALSE) {
1097*8a978a17SVictor Perevertkin return STATUS_SUCCESS;
1098*8a978a17SVictor Perevertkin }
1099*8a978a17SVictor Perevertkin
1100*8a978a17SVictor Perevertkin //
1101*8a978a17SVictor Perevertkin // Objects that have callback locks must support this interface.
1102*8a978a17SVictor Perevertkin //
1103*8a978a17SVictor Perevertkin if (Callbacks == NULL) {
1104*8a978a17SVictor Perevertkin return STATUS_INVALID_DEVICE_REQUEST;
1105*8a978a17SVictor Perevertkin }
1106*8a978a17SVictor Perevertkin
1107*8a978a17SVictor Perevertkin //
1108*8a978a17SVictor Perevertkin // Get the callback constraints in effect for the object
1109*8a978a17SVictor Perevertkin //
1110*8a978a17SVictor Perevertkin Callbacks->GetConstraints(&parentLevel, &parentScope);
1111*8a978a17SVictor Perevertkin
1112*8a978a17SVictor Perevertkin if (parentScope == WdfSynchronizationScopeInheritFromParent ||
1113*8a978a17SVictor Perevertkin parentScope == WdfSynchronizationScopeNone) {
1114*8a978a17SVictor Perevertkin //
1115*8a978a17SVictor Perevertkin // Do nothing, no synchronization specified
1116*8a978a17SVictor Perevertkin //
1117*8a978a17SVictor Perevertkin DO_NOTHING();
1118*8a978a17SVictor Perevertkin }
1119*8a978a17SVictor Perevertkin else {
1120*8a978a17SVictor Perevertkin //
1121*8a978a17SVictor Perevertkin // If the caller wants passive callbacks and the object does not support
1122*8a978a17SVictor Perevertkin // it, failure.
1123*8a978a17SVictor Perevertkin //
1124*8a978a17SVictor Perevertkin // If the caller wants non passive callbacks and the object supports
1125*8a978a17SVictor Perevertkin // passive only callbacks, failure.
1126*8a978a17SVictor Perevertkin //
1127*8a978a17SVictor Perevertkin if ((PassiveCallbacks && Object->IsPassiveCallbacks() == FALSE) ||
1128*8a978a17SVictor Perevertkin (PassiveCallbacks == FALSE && Object->IsPassiveCallbacks())) {
1129*8a978a17SVictor Perevertkin FxVerifierDbgBreakPoint(pFxDriverGlobals);
1130*8a978a17SVictor Perevertkin return STATUS_WDF_INCOMPATIBLE_EXECUTION_LEVEL;
1131*8a978a17SVictor Perevertkin }
1132*8a978a17SVictor Perevertkin
1133*8a978a17SVictor Perevertkin *CallbackLock = Callbacks->GetCallbackLockPtr(CallbackLockObject);
1134*8a978a17SVictor Perevertkin }
1135*8a978a17SVictor Perevertkin
1136*8a978a17SVictor Perevertkin return STATUS_SUCCESS;
1137*8a978a17SVictor Perevertkin }
1138