1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxDpc.hpp
8 
9 Abstract:
10 
11     This module implements a frameworks managed DPC that
12     can synchrononize with driver frameworks object locks.
13 
14 Author:
15 
16 
17 
18 Environment:
19 
20     kernel mode only
21 
22 Revision History:
23 
24 
25 --*/
26 
27 #ifndef _FXDPC_H_
28 #define _FXDPC_H_
29 
30 //
31 // Driver Frameworks DPC Design:
32 //
33 // The driver frameworks provides an optional DPC wrapper object that allows
34 // the creation of a reference counted DPC object that can synchronize
35 // automatically with certain frameworks objects.
36 //
37 // This provides automatic synchronization between the DPC's execution, and the
38 // frameworks objects' event callbacks into the device driver.
39 //
40 // The WDFDPC object is designed to be re-useable, in which it can be re-linked
41 // into the DPC queue after firing.
42 //
43 // In many cases, the KDPC struct is embedded inside another structure that
44 // represents a device command block. These device command blocks are typically
45 // submitted to another device driver. So the calling driver, which is utilizing
46 // the driver frameworks would not likely have an opportunity to make
47 // changes to this. In order to support this, the caller can optionally supply
48 // a DPC object pointer to Initialize, and the WDFDPC object will use this
49 // embedded user supplied DPC object, and pass its address as the RawDpc
50 // parameter to the callback function.
51 //
52 // If the user does not supply a DPC pointer by passing NULL, then the
53 // internal DPC object is used, and RawDPC is NULL.
54 //
55 // Calling GetDpcPtr returns the DPC to be used, and could be
56 // the caller supplied DPC, or the embedded one depending on
57 // whether the caller supplied a user DPC pointer to Initialize.
58 //
59 // The GetDpcPtr allows linking of the WDFDPC object into various DPC
60 // lists by the driver.
61 //
62 
63 class FxDpc : public FxNonPagedObject {
64 
65 private:
66 
67     KDPC               m_Dpc;
68 
69     //
70     // This is the Framework object who is associated with the DPC
71     // if supplied
72     //
73     FxObject*          m_Object;
74 
75     //
76     // This is the callback lock for the object this DPC will
77     // synchronize with
78     //
79     FxCallbackLock*    m_CallbackLock;
80 
81     //
82     // This is the object whose reference count actually controls
83     // the lifetime of the m_CallbackLock
84     //
85     FxObject*          m_CallbackLockObject;
86 
87     //
88     // This is the user supplied callback function
89     //
90     PFN_WDF_DPC        m_Callback;
91 
92     // Ensures only one of either Delete or Cleanup runs down the object
93     BOOLEAN            m_RunningDown;
94 
95 public:
96     static
97     _Must_inspect_result_
98     NTSTATUS
99     _Create(
100         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
101         __in PWDF_DPC_CONFIG Config,
102         __in PWDF_OBJECT_ATTRIBUTES Attributes,
103         __in FxObject* ParentObject,
104         __out WDFDPC* Dpc
105         );
106 
107     FxDpc(
108         __in PFX_DRIVER_GLOBALS FxDriverGlobals
109         );
110 
111     virtual
112     ~FxDpc(
113         VOID
114         );
115 
116     KDPC*
117     GetDpcPtr(
118         VOID
119         )
120     {
121          return &m_Dpc;
122     }
123 
124     WDFOBJECT
125     GetObject(
126         VOID
127         )
128     {
129         if (m_Object != NULL) {
130             return m_Object->GetObjectHandle();
131         }
132         else {
133             return NULL;
134         }
135     }
136 
137 /*++
138 
139 Routine Description:
140 
141     Initialize the DPC using either the caller supplied DPC
142     struct, or if NULL, our own internal one.
143 
144 Arguments:
145 
146 Returns:
147 
148     NTSTATUS
149 
150 --*/
151     _Must_inspect_result_
152     NTSTATUS
153     Initialize(
154         __in PWDF_OBJECT_ATTRIBUTES Attributes,
155         __in PWDF_DPC_CONFIG Config,
156         __in FxObject* ParentObject,
157         __out WDFDPC* Dpc
158         );
159 
160     virtual
161     BOOLEAN
162     Dispose(
163         VOID
164         );
165 
166     BOOLEAN
167     Cancel(
168         __in BOOLEAN Wait
169         );
170 
171     VOID
172     DpcHandler(
173         __in PKDPC Dpc,
174         __in PVOID SystemArgument1,
175         __in PVOID SystemArgument2
176         );
177 
178 private:
179 
180     //
181     // Called from Dispose, or cleanup list to perform final flushing of any
182     // outstanding DPC's and dereferencing of objects.
183     //
184     VOID
185     FlushAndRundown(
186         );
187 
188     static
189     KDEFERRED_ROUTINE
190     FxDpcThunk;
191 
192     static
193     VOID
194     WorkItemThunk(
195         PDEVICE_OBJECT DeviceObject,
196         PVOID          Context
197         );
198 };
199 
200 #endif // _FXDPC_H_
201 
202