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