1 /*++
2
3 Copyright (c) Microsoft Corporation
4
5 Module Name:
6
7 FxWorkItemApi.cpp
8
9 Abstract:
10
11 This implements the WDFWORKITEM API's
12
13 Author:
14
15
16
17 Environment:
18
19 Both kernel and user mode
20
21 Revision History:
22
23
24 --*/
25
26 #include "coreprivshared.hpp"
27
28 #include "fxworkitem.hpp"
29
30 extern "C" {
31 // #include "FxWorkItemApi.tmh"
32 }
33
34
35 //
36 // extern "C" the entire file
37 //
38 extern "C" {
39
40 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)41 __drv_maxIRQL(DISPATCH_LEVEL)
42 NTSTATUS
43 STDCALL
44 WDFEXPORT(WdfWorkItemCreate)(
45 __in
46 PWDF_DRIVER_GLOBALS DriverGlobals,
47 __in
48 PWDF_WORKITEM_CONFIG Config,
49 __in
50 PWDF_OBJECT_ATTRIBUTES Attributes,
51 __out
52 WDFWORKITEM* WorkItem
53 )
54
55 /*++
56
57 Routine Description:
58
59 Create a WorkItem object that will call the supplied function with
60 context when it fires. It returns a handle to the WDFWORKITEM object.
61
62 Arguments:
63
64 Config - Pointer to WDF_WORKITEM_CONFIG structure
65
66 Attributes - WDF_OBJECT_ATTRIBUTES to set the parent object and to request
67 a context memory allocation, and a DestroyCallback.
68
69 WorkItem - Pointer to the created WDFWORKITEM handle.
70
71 Returns:
72
73 STATUS_SUCCESS - A WDFWORKITEM handle has been created.
74
75 The WDFWORKITEM will be automatically deleted when the object it is
76 associated with is deleted.
77
78 Notes:
79
80 The WDFWORKITEM object is deleted either when the DEVICE or QUEUE it is
81 associated with is deleted, or WdfObjectDelete is called.
82
83 If the WDFWORKITEM is used to access WDM objects, a Cleanup callback should
84 be registered to allow references to be released.
85
86 --*/
87
88 {
89 DDI_ENTRY();
90
91 PFX_DRIVER_GLOBALS pFxDriverGlobals;
92 FxObject* pParent;
93 NTSTATUS status;
94
95 pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
96 status = FxValidateObjectAttributesForParentHandle(pFxDriverGlobals,
97 Attributes,
98 FX_VALIDATE_OPTION_PARENT_REQUIRED);
99 if (!NT_SUCCESS(status)) {
100 return status;
101 }
102
103 FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals,
104 Attributes->ParentObject,
105 FX_TYPE_OBJECT,
106 (PVOID*)&pParent,
107 &pFxDriverGlobals);
108
109 FxPointerNotNull(pFxDriverGlobals, Config);
110 FxPointerNotNull(pFxDriverGlobals, WorkItem);
111
112 if (Config->Size != sizeof(WDF_WORKITEM_CONFIG)) {
113 status = STATUS_INFO_LENGTH_MISMATCH;
114
115 DoTraceLevelMessage(
116 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
117 "WDF_WORKITEM_CONFIG Size got %d, expected %d, %!STATUS!",
118 Config->Size, sizeof(WDF_WORKITEM_CONFIG), status);
119
120 return status;
121 }
122
123 if (Config->EvtWorkItemFunc == NULL) {
124 status = STATUS_INVALID_PARAMETER;
125
126 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
127 "Supplied EvtWorkItemFunc == NULL, %!STATUS!",
128 status);
129
130 return status;
131 }
132
133 //
134 // The parent for FxWorkItem is explicitly part of the API, and ties
135 // synchronization and lifetime.
136 //
137 status = FxValidateObjectAttributes(pFxDriverGlobals, Attributes);
138 if (!NT_SUCCESS(status)) {
139 return status;
140 }
141
142 return FxWorkItem::_Create(
143 pFxDriverGlobals, Config, Attributes, pParent, WorkItem);
144 }
145
__drv_maxIRQL(DISPATCH_LEVEL)146 __drv_maxIRQL(DISPATCH_LEVEL)
147 VOID
148 STDCALL
149 WDFEXPORT(WdfWorkItemEnqueue)(
150 __in
151 PWDF_DRIVER_GLOBALS DriverGlobals,
152 __in
153 WDFWORKITEM WorkItem
154 )
155 /*++
156
157 Routine Description:
158
159 Enqueue a WorkItem to execute.
160
161 Arguments:
162
163 WorkItem - Handle to WDFWORKITEM
164
165 Returns:
166
167 None
168
169 --*/
170 {
171 DDI_ENTRY();
172
173 FxWorkItem* pFxWorkItem;
174
175 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
176 WorkItem,
177 FX_TYPE_WORKITEM,
178 (PVOID*)&pFxWorkItem);
179
180 pFxWorkItem->Enqueue();
181 }
182
__drv_maxIRQL(DISPATCH_LEVEL)183 __drv_maxIRQL(DISPATCH_LEVEL)
184 WDFOBJECT
185 STDCALL
186 WDFEXPORT(WdfWorkItemGetParentObject)(
187 __in
188 PWDF_DRIVER_GLOBALS DriverGlobals,
189 __in
190 WDFWORKITEM WorkItem
191 )
192
193 /*++
194
195 Routine Description:
196
197 Return the Object handle supplied to WdfWorkItemCreate
198
199 Arguments:
200
201 WDFWORKITEM - Handle to WDFWORKITEM object created with WdfWorkItemCreate.
202
203 Returns:
204
205 Handle to the framework object that is the specified work-item object's
206 parent object.
207
208 --*/
209
210 {
211 DDI_ENTRY();
212
213 FxWorkItem* pFxWorkItem;
214
215 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
216 WorkItem,
217 FX_TYPE_WORKITEM,
218 (PVOID*)&pFxWorkItem);
219
220 return pFxWorkItem->GetAssociatedObject();
221 }
222
__drv_maxIRQL(PASSIVE_LEVEL)223 __drv_maxIRQL(PASSIVE_LEVEL)
224 VOID
225 STDCALL
226 WDFEXPORT(WdfWorkItemFlush)(
227 __in
228 PWDF_DRIVER_GLOBALS DriverGlobals,
229 __in
230 WDFWORKITEM WorkItem
231 )
232 /*++
233
234 Routine Description:
235
236 Wait until any outstanding workitems have completed
237
238 Arguments:
239
240 WorkItem - Handle to WDFWORKITEM
241
242 Returns:
243
244 None
245
246 --*/
247 {
248 DDI_ENTRY();
249
250 FxWorkItem* pFxWorkItem;
251
252 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
253 WorkItem,
254 FX_TYPE_WORKITEM,
255 (PVOID*)&pFxWorkItem);
256
257 //
258 // Use the object's globals, not the caller's
259 //
260 if (!NT_SUCCESS(FxVerifierCheckIrqlLevel(pFxWorkItem->GetDriverGlobals(),
261 PASSIVE_LEVEL))) {
262 return;
263 }
264
265 pFxWorkItem->FlushAndWait();
266 }
267
268 } // extern "C"
269