1*8a978a17SVictor Perevertkin /*++
2*8a978a17SVictor Perevertkin
3*8a978a17SVictor Perevertkin Copyright (c) Microsoft Corporation. All rights reserved.
4*8a978a17SVictor Perevertkin
5*8a978a17SVictor Perevertkin Module Name:
6*8a978a17SVictor Perevertkin
7*8a978a17SVictor Perevertkin Verifier.cpp
8*8a978a17SVictor Perevertkin
9*8a978a17SVictor Perevertkin Abstract:
10*8a978a17SVictor Perevertkin
11*8a978a17SVictor Perevertkin This file has implementation of verifier support routines
12*8a978a17SVictor Perevertkin
13*8a978a17SVictor Perevertkin Author:
14*8a978a17SVictor Perevertkin
15*8a978a17SVictor Perevertkin
16*8a978a17SVictor Perevertkin
17*8a978a17SVictor Perevertkin Environment:
18*8a978a17SVictor Perevertkin
19*8a978a17SVictor Perevertkin Shared (Kernel and user)
20*8a978a17SVictor Perevertkin
21*8a978a17SVictor Perevertkin Revision History:
22*8a978a17SVictor Perevertkin
23*8a978a17SVictor Perevertkin
24*8a978a17SVictor Perevertkin
25*8a978a17SVictor Perevertkin --*/
26*8a978a17SVictor Perevertkin
27*8a978a17SVictor Perevertkin
28*8a978a17SVictor Perevertkin #include "vfpriv.hpp"
29*8a978a17SVictor Perevertkin
30*8a978a17SVictor Perevertkin extern "C"
31*8a978a17SVictor Perevertkin {
32*8a978a17SVictor Perevertkin
33*8a978a17SVictor Perevertkin extern WDFVERSION WdfVersion;
34*8a978a17SVictor Perevertkin
35*8a978a17SVictor Perevertkin // Tracing support
36*8a978a17SVictor Perevertkin #if defined(EVENT_TRACING)
37*8a978a17SVictor Perevertkin #include "verifier.tmh"
38*8a978a17SVictor Perevertkin #endif
39*8a978a17SVictor Perevertkin
40*8a978a17SVictor Perevertkin #ifdef ALLOC_PRAGMA
41*8a978a17SVictor Perevertkin #pragma alloc_text(FX_ENHANCED_VERIFIER_SECTION_NAME, \
42*8a978a17SVictor Perevertkin AddEventHooksWdfDeviceCreate, \
43*8a978a17SVictor Perevertkin AddEventHooksWdfIoQueueCreate, \
44*8a978a17SVictor Perevertkin VfAddContextToHandle, \
45*8a978a17SVictor Perevertkin VfAllocateContext, \
46*8a978a17SVictor Perevertkin VfWdfObjectGetTypedContext \
47*8a978a17SVictor Perevertkin )
48*8a978a17SVictor Perevertkin #endif
49*8a978a17SVictor Perevertkin
50*8a978a17SVictor Perevertkin _Must_inspect_result_
51*8a978a17SVictor Perevertkin NTSTATUS
AddEventHooksWdfDeviceCreate(__inout PVF_HOOK_PROCESS_INFO HookProcessInfo,__in PWDF_DRIVER_GLOBALS DriverGlobals,__in PWDFDEVICE_INIT * DeviceInit,__in PWDF_OBJECT_ATTRIBUTES DeviceAttributes,__out WDFDEVICE * Device)52*8a978a17SVictor Perevertkin AddEventHooksWdfDeviceCreate(
53*8a978a17SVictor Perevertkin __inout PVF_HOOK_PROCESS_INFO HookProcessInfo,
54*8a978a17SVictor Perevertkin __in PWDF_DRIVER_GLOBALS DriverGlobals,
55*8a978a17SVictor Perevertkin __in PWDFDEVICE_INIT* DeviceInit,
56*8a978a17SVictor Perevertkin __in PWDF_OBJECT_ATTRIBUTES DeviceAttributes,
57*8a978a17SVictor Perevertkin __out WDFDEVICE* Device
58*8a978a17SVictor Perevertkin )
59*8a978a17SVictor Perevertkin /*++
60*8a978a17SVictor Perevertkin
61*8a978a17SVictor Perevertkin Routine Description:
62*8a978a17SVictor Perevertkin
63*8a978a17SVictor Perevertkin This routine is called by main hook for WdfDeviceCreate.
64*8a978a17SVictor Perevertkin The routine swaps the event callbacks provided by client.
65*8a978a17SVictor Perevertkin
66*8a978a17SVictor Perevertkin Arguments:
67*8a978a17SVictor Perevertkin
68*8a978a17SVictor Perevertkin Return value:
69*8a978a17SVictor Perevertkin
70*8a978a17SVictor Perevertkin --*/
71*8a978a17SVictor Perevertkin {
72*8a978a17SVictor Perevertkin NTSTATUS status;
73*8a978a17SVictor Perevertkin PWDFDEVICE_INIT deviceInit = *DeviceInit;
74*8a978a17SVictor Perevertkin WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerEvtsOriginal;
75*8a978a17SVictor Perevertkin WDF_PNPPOWER_EVENT_CALLBACKS *pnpPowerEvts;
76*8a978a17SVictor Perevertkin PFX_DRIVER_GLOBALS pFxDriverGlobals;
77*8a978a17SVictor Perevertkin PVOID contextHeader = NULL;
78*8a978a17SVictor Perevertkin WDF_OBJECT_ATTRIBUTES attributes;
79*8a978a17SVictor Perevertkin
80*8a978a17SVictor Perevertkin PAGED_CODE_LOCKED();
81*8a978a17SVictor Perevertkin
82*8a978a17SVictor Perevertkin pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
83*8a978a17SVictor Perevertkin
84*8a978a17SVictor Perevertkin FxPointerNotNull(pFxDriverGlobals, DeviceInit);
85*8a978a17SVictor Perevertkin FxPointerNotNull(pFxDriverGlobals, *DeviceInit);
86*8a978a17SVictor Perevertkin FxPointerNotNull(pFxDriverGlobals, Device);
87*8a978a17SVictor Perevertkin
88*8a978a17SVictor Perevertkin //
89*8a978a17SVictor Perevertkin // Check if there are any callbacks set by the client driver. If not, we
90*8a978a17SVictor Perevertkin // don't need any callback hooking.
91*8a978a17SVictor Perevertkin //
92*8a978a17SVictor Perevertkin if (deviceInit->PnpPower.PnpPowerEventCallbacks.Size !=
93*8a978a17SVictor Perevertkin sizeof(WDF_PNPPOWER_EVENT_CALLBACKS)) {
94*8a978a17SVictor Perevertkin //
95*8a978a17SVictor Perevertkin // no hooking required.
96*8a978a17SVictor Perevertkin //
97*8a978a17SVictor Perevertkin status = STATUS_SUCCESS;
98*8a978a17SVictor Perevertkin HookProcessInfo->DonotCallKmdfLib = FALSE;
99*8a978a17SVictor Perevertkin return status;
100*8a978a17SVictor Perevertkin }
101*8a978a17SVictor Perevertkin
102*8a978a17SVictor Perevertkin //
103*8a978a17SVictor Perevertkin // Hooking can be done only if we are able to allocate context memory.
104*8a978a17SVictor Perevertkin // Try to allocate a context
105*8a978a17SVictor Perevertkin //
106*8a978a17SVictor Perevertkin WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
107*8a978a17SVictor Perevertkin &attributes,
108*8a978a17SVictor Perevertkin VF_WDFDEVICECREATE_CONTEXT
109*8a978a17SVictor Perevertkin );
110*8a978a17SVictor Perevertkin
111*8a978a17SVictor Perevertkin status = VfAllocateContext(DriverGlobals, &attributes, &contextHeader);
112*8a978a17SVictor Perevertkin
113*8a978a17SVictor Perevertkin if (!NT_SUCCESS(status)) {
114*8a978a17SVictor Perevertkin //
115*8a978a17SVictor Perevertkin // couldn't allocate context. hooking not possible
116*8a978a17SVictor Perevertkin //
117*8a978a17SVictor Perevertkin HookProcessInfo->DonotCallKmdfLib = FALSE;
118*8a978a17SVictor Perevertkin return status;
119*8a978a17SVictor Perevertkin }
120*8a978a17SVictor Perevertkin
121*8a978a17SVictor Perevertkin //
122*8a978a17SVictor Perevertkin // store original driver callbacks to local variable
123*8a978a17SVictor Perevertkin //
124*8a978a17SVictor Perevertkin RtlCopyMemory(&pnpPowerEvtsOriginal,
125*8a978a17SVictor Perevertkin &deviceInit->PnpPower.PnpPowerEventCallbacks,
126*8a978a17SVictor Perevertkin sizeof(WDF_PNPPOWER_EVENT_CALLBACKS)
127*8a978a17SVictor Perevertkin );
128*8a978a17SVictor Perevertkin
129*8a978a17SVictor Perevertkin //
130*8a978a17SVictor Perevertkin // Set callback hooks
131*8a978a17SVictor Perevertkin //
132*8a978a17SVictor Perevertkin // Normally override the hooks on local copy of stucture (not the original
133*8a978a17SVictor Perevertkin // structure itself) and then pass the local struture to DDI call and
134*8a978a17SVictor Perevertkin // copy back the original poniter when returning back to caller. In this case
135*8a978a17SVictor Perevertkin // device_init is null'ed out by fx when returning to caller so we can
136*8a978a17SVictor Perevertkin // directly override the original
137*8a978a17SVictor Perevertkin //
138*8a978a17SVictor Perevertkin pnpPowerEvts = &deviceInit->PnpPower.PnpPowerEventCallbacks;
139*8a978a17SVictor Perevertkin
140*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceD0Entry);
141*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceD0EntryPostInterruptsEnabled);
142*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceD0Exit);
143*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceD0ExitPreInterruptsDisabled);
144*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDevicePrepareHardware);
145*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceReleaseHardware);
146*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceSelfManagedIoCleanup);
147*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceSelfManagedIoFlush);
148*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceSelfManagedIoInit);
149*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceSelfManagedIoSuspend);
150*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceSelfManagedIoRestart);
151*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceSurpriseRemoval);
152*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceQueryRemove);
153*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceQueryStop);
154*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceUsageNotification);
155*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceUsageNotificationEx);
156*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceRelationsQuery);
157*8a978a17SVictor Perevertkin
158*8a978a17SVictor Perevertkin //
159*8a978a17SVictor Perevertkin // Call the DDI on behalf of driver.
160*8a978a17SVictor Perevertkin //
161*8a978a17SVictor Perevertkin status = ((PFN_WDFDEVICECREATE)WdfVersion.Functions.pfnWdfDeviceCreate)(
162*8a978a17SVictor Perevertkin DriverGlobals,
163*8a978a17SVictor Perevertkin DeviceInit,
164*8a978a17SVictor Perevertkin DeviceAttributes,
165*8a978a17SVictor Perevertkin Device
166*8a978a17SVictor Perevertkin );
167*8a978a17SVictor Perevertkin //
168*8a978a17SVictor Perevertkin // Tell main hook routine not to call the DDI in kmdf lib since we
169*8a978a17SVictor Perevertkin // already called it
170*8a978a17SVictor Perevertkin //
171*8a978a17SVictor Perevertkin HookProcessInfo->DonotCallKmdfLib = TRUE;
172*8a978a17SVictor Perevertkin HookProcessInfo->DdiCallStatus = status;
173*8a978a17SVictor Perevertkin
174*8a978a17SVictor Perevertkin //
175*8a978a17SVictor Perevertkin // if DDI Succeeds, add context
176*8a978a17SVictor Perevertkin //
177*8a978a17SVictor Perevertkin if (NT_SUCCESS(status)) {
178*8a978a17SVictor Perevertkin PVF_WDFDEVICECREATE_CONTEXT context = NULL;
179*8a978a17SVictor Perevertkin
180*8a978a17SVictor Perevertkin //
181*8a978a17SVictor Perevertkin // add the already allocated context to the object.
182*8a978a17SVictor Perevertkin //
183*8a978a17SVictor Perevertkin status = VfAddContextToHandle(contextHeader,
184*8a978a17SVictor Perevertkin &attributes,
185*8a978a17SVictor Perevertkin *Device,
186*8a978a17SVictor Perevertkin (PVOID *)&context);
187*8a978a17SVictor Perevertkin
188*8a978a17SVictor Perevertkin if (NT_SUCCESS(status)) {
189*8a978a17SVictor Perevertkin //
190*8a978a17SVictor Perevertkin // store the DriverGlobals pointer used to associate the driver
191*8a978a17SVictor Perevertkin // with its client driver callback later in the callback hooks
192*8a978a17SVictor Perevertkin //
193*8a978a17SVictor Perevertkin context->CommonHeader.DriverGlobals = DriverGlobals;
194*8a978a17SVictor Perevertkin
195*8a978a17SVictor Perevertkin //
196*8a978a17SVictor Perevertkin // store original client driver callbacks in context
197*8a978a17SVictor Perevertkin //
198*8a978a17SVictor Perevertkin RtlCopyMemory(
199*8a978a17SVictor Perevertkin &context->PnpPowerEventCallbacksOriginal,
200*8a978a17SVictor Perevertkin &pnpPowerEvtsOriginal,
201*8a978a17SVictor Perevertkin sizeof(WDF_PNPPOWER_EVENT_CALLBACKS)
202*8a978a17SVictor Perevertkin );
203*8a978a17SVictor Perevertkin }
204*8a978a17SVictor Perevertkin else {
205*8a978a17SVictor Perevertkin //
206*8a978a17SVictor Perevertkin // For some reason adding context to handle failed. This should be
207*8a978a17SVictor Perevertkin // rare failure, because context allocation was already successful,
208*8a978a17SVictor Perevertkin // only adding to handle failed.
209*8a978a17SVictor Perevertkin //
210*8a978a17SVictor Perevertkin // Hooking failed if adding context is unsuccessful. This means
211*8a978a17SVictor Perevertkin // kmdf has callbacks hooks but verifier cannot assiociate client
212*8a978a17SVictor Perevertkin // driver callbacks with callback hooks. This would be a fatal error.
213*8a978a17SVictor Perevertkin //
214*8a978a17SVictor Perevertkin ASSERTMSG("KMDF Enhanced Verifier failed to add context to object "
215*8a978a17SVictor Perevertkin "handle\n", FALSE);
216*8a978a17SVictor Perevertkin
217*8a978a17SVictor Perevertkin if (contextHeader != NULL) {
218*8a978a17SVictor Perevertkin FxPoolFree(contextHeader);
219*8a978a17SVictor Perevertkin }
220*8a978a17SVictor Perevertkin }
221*8a978a17SVictor Perevertkin }
222*8a978a17SVictor Perevertkin else {
223*8a978a17SVictor Perevertkin //
224*8a978a17SVictor Perevertkin // KMDF DDI call failed. In case of failure, DeviceInit is not NULL'ed
225*8a978a17SVictor Perevertkin // so the driver could potentially call WdfDeviceCreate again with this
226*8a978a17SVictor Perevertkin // DeviceInit that contains callback hooks, and result in infinite
227*8a978a17SVictor Perevertkin // callback loop. So put original callbacks back
228*8a978a17SVictor Perevertkin //
229*8a978a17SVictor Perevertkin if ((*DeviceInit) != NULL) {
230*8a978a17SVictor Perevertkin //
231*8a978a17SVictor Perevertkin // we overwrote only the pnppower callbacks. Put the original back.
232*8a978a17SVictor Perevertkin //
233*8a978a17SVictor Perevertkin deviceInit = *DeviceInit;
234*8a978a17SVictor Perevertkin RtlCopyMemory(&deviceInit->PnpPower.PnpPowerEventCallbacks,
235*8a978a17SVictor Perevertkin &pnpPowerEvtsOriginal,
236*8a978a17SVictor Perevertkin sizeof(WDF_PNPPOWER_EVENT_CALLBACKS)
237*8a978a17SVictor Perevertkin );
238*8a978a17SVictor Perevertkin }
239*8a978a17SVictor Perevertkin
240*8a978a17SVictor Perevertkin if (contextHeader != NULL) {
241*8a978a17SVictor Perevertkin FxPoolFree(contextHeader);
242*8a978a17SVictor Perevertkin }
243*8a978a17SVictor Perevertkin }
244*8a978a17SVictor Perevertkin
245*8a978a17SVictor Perevertkin return status;
246*8a978a17SVictor Perevertkin }
247*8a978a17SVictor Perevertkin
248*8a978a17SVictor Perevertkin _Must_inspect_result_
249*8a978a17SVictor Perevertkin NTSTATUS
AddEventHooksWdfIoQueueCreate(__inout PVF_HOOK_PROCESS_INFO HookProcessInfo,__in PWDF_DRIVER_GLOBALS DriverGlobals,__in WDFDEVICE Device,__in PWDF_IO_QUEUE_CONFIG Config,__in PWDF_OBJECT_ATTRIBUTES QueueAttributes,__out WDFQUEUE * Queue)250*8a978a17SVictor Perevertkin AddEventHooksWdfIoQueueCreate(
251*8a978a17SVictor Perevertkin __inout PVF_HOOK_PROCESS_INFO HookProcessInfo,
252*8a978a17SVictor Perevertkin __in PWDF_DRIVER_GLOBALS DriverGlobals,
253*8a978a17SVictor Perevertkin __in WDFDEVICE Device,
254*8a978a17SVictor Perevertkin __in PWDF_IO_QUEUE_CONFIG Config,
255*8a978a17SVictor Perevertkin __in PWDF_OBJECT_ATTRIBUTES QueueAttributes,
256*8a978a17SVictor Perevertkin __out WDFQUEUE* Queue
257*8a978a17SVictor Perevertkin )
258*8a978a17SVictor Perevertkin /*++
259*8a978a17SVictor Perevertkin
260*8a978a17SVictor Perevertkin Routine Description:
261*8a978a17SVictor Perevertkin
262*8a978a17SVictor Perevertkin Arguments:
263*8a978a17SVictor Perevertkin
264*8a978a17SVictor Perevertkin Return value:
265*8a978a17SVictor Perevertkin
266*8a978a17SVictor Perevertkin --*/
267*8a978a17SVictor Perevertkin {
268*8a978a17SVictor Perevertkin NTSTATUS status;
269*8a978a17SVictor Perevertkin WDF_IO_QUEUE_CONFIG configNew;
270*8a978a17SVictor Perevertkin PFX_DRIVER_GLOBALS pFxDriverGlobals;
271*8a978a17SVictor Perevertkin WDFQUEUE *pQueue;
272*8a978a17SVictor Perevertkin WDFQUEUE queue;
273*8a978a17SVictor Perevertkin PVOID contextHeader = NULL;
274*8a978a17SVictor Perevertkin WDF_OBJECT_ATTRIBUTES attributes;
275*8a978a17SVictor Perevertkin
276*8a978a17SVictor Perevertkin PAGED_CODE_LOCKED();
277*8a978a17SVictor Perevertkin
278*8a978a17SVictor Perevertkin pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
279*8a978a17SVictor Perevertkin
280*8a978a17SVictor Perevertkin FxPointerNotNull(pFxDriverGlobals, Config);
281*8a978a17SVictor Perevertkin
282*8a978a17SVictor Perevertkin //
283*8a978a17SVictor Perevertkin // Check if there are any callbacks set by the client driver. If not, we
284*8a978a17SVictor Perevertkin // don't need any callback hooking.
285*8a978a17SVictor Perevertkin //
286*8a978a17SVictor Perevertkin if (Config->Size != sizeof(WDF_IO_QUEUE_CONFIG)) {
287*8a978a17SVictor Perevertkin //
288*8a978a17SVictor Perevertkin // no hooking required.
289*8a978a17SVictor Perevertkin //
290*8a978a17SVictor Perevertkin status = STATUS_SUCCESS;
291*8a978a17SVictor Perevertkin HookProcessInfo->DonotCallKmdfLib = FALSE;
292*8a978a17SVictor Perevertkin return status;
293*8a978a17SVictor Perevertkin }
294*8a978a17SVictor Perevertkin
295*8a978a17SVictor Perevertkin //
296*8a978a17SVictor Perevertkin // Hooking can be done only if we are able to allocate context memory.
297*8a978a17SVictor Perevertkin // Try to allocate a context
298*8a978a17SVictor Perevertkin //
299*8a978a17SVictor Perevertkin WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes,
300*8a978a17SVictor Perevertkin VF_WDFIOQUEUECREATE_CONTEXT);
301*8a978a17SVictor Perevertkin
302*8a978a17SVictor Perevertkin status = VfAllocateContext(DriverGlobals, &attributes, &contextHeader);
303*8a978a17SVictor Perevertkin
304*8a978a17SVictor Perevertkin if (!NT_SUCCESS(status)) {
305*8a978a17SVictor Perevertkin //
306*8a978a17SVictor Perevertkin // couldn't allocate context. hooking not possible
307*8a978a17SVictor Perevertkin //
308*8a978a17SVictor Perevertkin HookProcessInfo->DonotCallKmdfLib = FALSE;
309*8a978a17SVictor Perevertkin return status;
310*8a978a17SVictor Perevertkin }
311*8a978a17SVictor Perevertkin
312*8a978a17SVictor Perevertkin //
313*8a978a17SVictor Perevertkin // create a local copy of config
314*8a978a17SVictor Perevertkin //
315*8a978a17SVictor Perevertkin RtlCopyMemory(&configNew,
316*8a978a17SVictor Perevertkin Config,
317*8a978a17SVictor Perevertkin sizeof(configNew)
318*8a978a17SVictor Perevertkin );
319*8a978a17SVictor Perevertkin
320*8a978a17SVictor Perevertkin //
321*8a978a17SVictor Perevertkin // Override local copy with event callback hooks.
322*8a978a17SVictor Perevertkin //
323*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(Config, &configNew, EvtIoDefault);
324*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(Config, &configNew, EvtIoRead);
325*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(Config, &configNew, EvtIoWrite);
326*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(Config, &configNew, EvtIoDeviceControl);
327*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(Config, &configNew, EvtIoInternalDeviceControl);
328*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(Config, &configNew, EvtIoStop);
329*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(Config, &configNew, EvtIoResume);
330*8a978a17SVictor Perevertkin SET_HOOK_IF_CALLBACK_PRESENT(Config, &configNew, EvtIoCanceledOnQueue);
331*8a978a17SVictor Perevertkin
332*8a978a17SVictor Perevertkin //
333*8a978a17SVictor Perevertkin // Queue handle is an optional parameter
334*8a978a17SVictor Perevertkin //
335*8a978a17SVictor Perevertkin if (Queue == NULL) {
336*8a978a17SVictor Perevertkin pQueue = &queue;
337*8a978a17SVictor Perevertkin }
338*8a978a17SVictor Perevertkin else {
339*8a978a17SVictor Perevertkin pQueue = Queue;
340*8a978a17SVictor Perevertkin }
341*8a978a17SVictor Perevertkin
342*8a978a17SVictor Perevertkin //
343*8a978a17SVictor Perevertkin // call the DDI
344*8a978a17SVictor Perevertkin //
345*8a978a17SVictor Perevertkin status = WdfVersion.Functions.pfnWdfIoQueueCreate(
346*8a978a17SVictor Perevertkin DriverGlobals,
347*8a978a17SVictor Perevertkin Device,
348*8a978a17SVictor Perevertkin &configNew,
349*8a978a17SVictor Perevertkin QueueAttributes,
350*8a978a17SVictor Perevertkin pQueue
351*8a978a17SVictor Perevertkin );
352*8a978a17SVictor Perevertkin
353*8a978a17SVictor Perevertkin //
354*8a978a17SVictor Perevertkin // Tell main hook routine not to call the DDI in kmdf lib since we
355*8a978a17SVictor Perevertkin // already called it
356*8a978a17SVictor Perevertkin //
357*8a978a17SVictor Perevertkin HookProcessInfo->DonotCallKmdfLib = TRUE;
358*8a978a17SVictor Perevertkin HookProcessInfo->DdiCallStatus = status;
359*8a978a17SVictor Perevertkin
360*8a978a17SVictor Perevertkin //
361*8a978a17SVictor Perevertkin // if DDI Succeeds, add context
362*8a978a17SVictor Perevertkin //
363*8a978a17SVictor Perevertkin if (NT_SUCCESS(status)) {
364*8a978a17SVictor Perevertkin PVF_WDFIOQUEUECREATE_CONTEXT context = NULL;
365*8a978a17SVictor Perevertkin
366*8a978a17SVictor Perevertkin //
367*8a978a17SVictor Perevertkin // add the already allocated context to the object.
368*8a978a17SVictor Perevertkin //
369*8a978a17SVictor Perevertkin status = VfAddContextToHandle(contextHeader,
370*8a978a17SVictor Perevertkin &attributes,
371*8a978a17SVictor Perevertkin *pQueue,
372*8a978a17SVictor Perevertkin (PVOID *)&context);
373*8a978a17SVictor Perevertkin
374*8a978a17SVictor Perevertkin if (NT_SUCCESS(status)) {
375*8a978a17SVictor Perevertkin //
376*8a978a17SVictor Perevertkin // store the DriverGlobals pointer used to associate the driver
377*8a978a17SVictor Perevertkin // with its client driver callback later in the callback hooks
378*8a978a17SVictor Perevertkin //
379*8a978a17SVictor Perevertkin context->CommonHeader.DriverGlobals = DriverGlobals;
380*8a978a17SVictor Perevertkin
381*8a978a17SVictor Perevertkin //
382*8a978a17SVictor Perevertkin // add stored original callbacks to context
383*8a978a17SVictor Perevertkin //
384*8a978a17SVictor Perevertkin RtlCopyMemory(
385*8a978a17SVictor Perevertkin &context->IoQueueConfigOriginal,
386*8a978a17SVictor Perevertkin Config,
387*8a978a17SVictor Perevertkin sizeof(WDF_IO_QUEUE_CONFIG)
388*8a978a17SVictor Perevertkin );
389*8a978a17SVictor Perevertkin }
390*8a978a17SVictor Perevertkin else {
391*8a978a17SVictor Perevertkin //
392*8a978a17SVictor Perevertkin // For some reason adding context to handle failed. This should be
393*8a978a17SVictor Perevertkin // rare failure, because context allocation was already successful,
394*8a978a17SVictor Perevertkin // only adding to handle failed.
395*8a978a17SVictor Perevertkin //
396*8a978a17SVictor Perevertkin // Hooking failed if adding context is unsuccessful. This means
397*8a978a17SVictor Perevertkin // kmdf has callbacks hooks but verifier cannot assiociate client
398*8a978a17SVictor Perevertkin // driver callbacks with callback hooks. This would be a fatal error.
399*8a978a17SVictor Perevertkin //
400*8a978a17SVictor Perevertkin ASSERTMSG("KMDF Enhanced Verifier failed to add context to object "
401*8a978a17SVictor Perevertkin "handle\n", FALSE);
402*8a978a17SVictor Perevertkin
403*8a978a17SVictor Perevertkin if (contextHeader != NULL) {
404*8a978a17SVictor Perevertkin FxPoolFree(contextHeader);
405*8a978a17SVictor Perevertkin }
406*8a978a17SVictor Perevertkin }
407*8a978a17SVictor Perevertkin }
408*8a978a17SVictor Perevertkin else {
409*8a978a17SVictor Perevertkin //
410*8a978a17SVictor Perevertkin // DDI call to KMDF failed. Nothing to do by verifier. Just return
411*8a978a17SVictor Perevertkin // kmdf's status after freeing context header memory.
412*8a978a17SVictor Perevertkin //
413*8a978a17SVictor Perevertkin if (contextHeader != NULL) {
414*8a978a17SVictor Perevertkin FxPoolFree(contextHeader);
415*8a978a17SVictor Perevertkin }
416*8a978a17SVictor Perevertkin }
417*8a978a17SVictor Perevertkin
418*8a978a17SVictor Perevertkin return status;
419*8a978a17SVictor Perevertkin }
420*8a978a17SVictor Perevertkin
421*8a978a17SVictor Perevertkin _Must_inspect_result_
422*8a978a17SVictor Perevertkin PVOID
423*8a978a17SVictor Perevertkin FASTCALL
VfWdfObjectGetTypedContext(__in WDFOBJECT Handle,__in PCWDF_OBJECT_CONTEXT_TYPE_INFO TypeInfo)424*8a978a17SVictor Perevertkin VfWdfObjectGetTypedContext(
425*8a978a17SVictor Perevertkin __in
426*8a978a17SVictor Perevertkin WDFOBJECT Handle,
427*8a978a17SVictor Perevertkin __in
428*8a978a17SVictor Perevertkin PCWDF_OBJECT_CONTEXT_TYPE_INFO TypeInfo
429*8a978a17SVictor Perevertkin )
430*8a978a17SVictor Perevertkin /*++
431*8a978a17SVictor Perevertkin
432*8a978a17SVictor Perevertkin Routine Description:
433*8a978a17SVictor Perevertkin Retrieves the requested type from a handle
434*8a978a17SVictor Perevertkin
435*8a978a17SVictor Perevertkin Arguments:
436*8a978a17SVictor Perevertkin Handle - the handle to retrieve the context from
437*8a978a17SVictor Perevertkin TypeInfo - global constant pointer which describes the type. Since the pointer
438*8a978a17SVictor Perevertkin value is unique in all of kernel space, we will perform a pointer compare
439*8a978a17SVictor Perevertkin instead of a deep structure compare
440*8a978a17SVictor Perevertkin
441*8a978a17SVictor Perevertkin Return Value:
442*8a978a17SVictor Perevertkin A valid context pointere or NULL. NULL is not a failure, querying for a type
443*8a978a17SVictor Perevertkin not associated with the handle is a legitimate operation.
444*8a978a17SVictor Perevertkin
445*8a978a17SVictor Perevertkin --*/
446*8a978a17SVictor Perevertkin {
447*8a978a17SVictor Perevertkin FxContextHeader* pHeader;
448*8a978a17SVictor Perevertkin FxObject* pObject;
449*8a978a17SVictor Perevertkin PFX_DRIVER_GLOBALS pFxDriverGlobals;
450*8a978a17SVictor Perevertkin WDFOBJECT_OFFSET offset;
451*8a978a17SVictor Perevertkin
452*8a978a17SVictor Perevertkin PAGED_CODE_LOCKED();
453*8a978a17SVictor Perevertkin
454*8a978a17SVictor Perevertkin //
455*8a978a17SVictor Perevertkin // Do not call FxObjectHandleGetPtr( , , FX_TYPE_OBJECT) because this is a
456*8a978a17SVictor Perevertkin // hot spot / workhorse function that should be as efficient as possible.
457*8a978a17SVictor Perevertkin //
458*8a978a17SVictor Perevertkin // A call to FxObjectHandleGetPtr would :
459*8a978a17SVictor Perevertkin // 1) invoke a virtual call to QueryInterface
460*8a978a17SVictor Perevertkin //
461*8a978a17SVictor Perevertkin // 2) ASSERT that the ref count of the object is > zero. Since this is one
462*8a978a17SVictor Perevertkin // of the few functions that can be called in EvtObjectDestroy where the
463*8a978a17SVictor Perevertkin // ref count is zero, that is not a good side affect.
464*8a978a17SVictor Perevertkin //
465*8a978a17SVictor Perevertkin offset = 0;
466*8a978a17SVictor Perevertkin pObject = FxObject::_GetObjectFromHandle(Handle, &offset);
467*8a978a17SVictor Perevertkin
468*8a978a17SVictor Perevertkin //
469*8a978a17SVictor Perevertkin // Use the object's globals, not the caller's
470*8a978a17SVictor Perevertkin //
471*8a978a17SVictor Perevertkin pFxDriverGlobals = pObject->GetDriverGlobals();
472*8a978a17SVictor Perevertkin
473*8a978a17SVictor Perevertkin FxPointerNotNull(pFxDriverGlobals, Handle);
474*8a978a17SVictor Perevertkin FxPointerNotNull(pFxDriverGlobals, TypeInfo);
475*8a978a17SVictor Perevertkin
476*8a978a17SVictor Perevertkin pHeader = pObject->GetContextHeader();
477*8a978a17SVictor Perevertkin
478*8a978a17SVictor Perevertkin for ( ; pHeader != NULL; pHeader = pHeader->NextHeader) {
479*8a978a17SVictor Perevertkin if (pHeader->ContextTypeInfo == TypeInfo) {
480*8a978a17SVictor Perevertkin return &pHeader->Context[0];
481*8a978a17SVictor Perevertkin }
482*8a978a17SVictor Perevertkin }
483*8a978a17SVictor Perevertkin
484*8a978a17SVictor Perevertkin PCHAR pGivenName;
485*8a978a17SVictor Perevertkin
486*8a978a17SVictor Perevertkin if (TypeInfo->ContextName != NULL) {
487*8a978a17SVictor Perevertkin pGivenName = TypeInfo->ContextName;
488*8a978a17SVictor Perevertkin }
489*8a978a17SVictor Perevertkin else {
490*8a978a17SVictor Perevertkin pGivenName = "<no typename given>";
491*8a978a17SVictor Perevertkin }
492*8a978a17SVictor Perevertkin
493*8a978a17SVictor Perevertkin DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGDEVICE,
494*8a978a17SVictor Perevertkin "Attempting to get context type %s from WDFOBJECT 0x%p",
495*8a978a17SVictor Perevertkin pGivenName, Handle);
496*8a978a17SVictor Perevertkin
497*8a978a17SVictor Perevertkin return NULL;
498*8a978a17SVictor Perevertkin }
499*8a978a17SVictor Perevertkin
500*8a978a17SVictor Perevertkin _Must_inspect_result_
501*8a978a17SVictor Perevertkin NTSTATUS
VfAllocateContext(__in PWDF_DRIVER_GLOBALS DriverGlobals,__in PWDF_OBJECT_ATTRIBUTES Attributes,__out PVOID * ContextHeader)502*8a978a17SVictor Perevertkin VfAllocateContext(
503*8a978a17SVictor Perevertkin __in PWDF_DRIVER_GLOBALS DriverGlobals,
504*8a978a17SVictor Perevertkin __in PWDF_OBJECT_ATTRIBUTES Attributes,
505*8a978a17SVictor Perevertkin __out PVOID* ContextHeader
506*8a978a17SVictor Perevertkin )
507*8a978a17SVictor Perevertkin /*++
508*8a978a17SVictor Perevertkin
509*8a978a17SVictor Perevertkin Routine Description:
510*8a978a17SVictor Perevertkin Allocates an additional context on the handle if the object is in the
511*8a978a17SVictor Perevertkin correct state
512*8a978a17SVictor Perevertkin
513*8a978a17SVictor Perevertkin Arguments:
514*8a978a17SVictor Perevertkin Handle - handle on which to add a context
515*8a978a17SVictor Perevertkin Attributes - attributes which describe the type and size of the new context
516*8a978a17SVictor Perevertkin Context - optional pointer which will recieve the new context
517*8a978a17SVictor Perevertkin
518*8a978a17SVictor Perevertkin Return Value:
519*8a978a17SVictor Perevertkin STATUS_SUCCESS upon success, STATUS_OBJECT_NAME_EXISTS if the context type
520*8a978a17SVictor Perevertkin is already attached to the handle, and !NT_SUCCESS on failure
521*8a978a17SVictor Perevertkin
522*8a978a17SVictor Perevertkin --*/
523*8a978a17SVictor Perevertkin {
524*8a978a17SVictor Perevertkin PFX_DRIVER_GLOBALS pFxDriverGlobals;
525*8a978a17SVictor Perevertkin NTSTATUS status;
526*8a978a17SVictor Perevertkin FxContextHeader *pHeader;
527*8a978a17SVictor Perevertkin size_t size;
528*8a978a17SVictor Perevertkin
529*8a978a17SVictor Perevertkin PAGED_CODE_LOCKED();
530*8a978a17SVictor Perevertkin
531*8a978a17SVictor Perevertkin pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
532*8a978a17SVictor Perevertkin
533*8a978a17SVictor Perevertkin status = FxValidateObjectAttributes(
534*8a978a17SVictor Perevertkin pFxDriverGlobals, Attributes, FX_VALIDATE_OPTION_ATTRIBUTES_REQUIRED);
535*8a978a17SVictor Perevertkin if (!NT_SUCCESS(status)) {
536*8a978a17SVictor Perevertkin return status;
537*8a978a17SVictor Perevertkin }
538*8a978a17SVictor Perevertkin
539*8a978a17SVictor Perevertkin //
540*8a978a17SVictor Perevertkin // Must have a context type!
541*8a978a17SVictor Perevertkin //
542*8a978a17SVictor Perevertkin if (Attributes->ContextTypeInfo == NULL) {
543*8a978a17SVictor Perevertkin status = STATUS_OBJECT_NAME_INVALID;
544*8a978a17SVictor Perevertkin DoTraceLevelMessage(
545*8a978a17SVictor Perevertkin pFxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGHANDLE,
546*8a978a17SVictor Perevertkin "Attributes %p ContextTypeInfo is NULL, %!STATUS!",
547*8a978a17SVictor Perevertkin Attributes, status);
548*8a978a17SVictor Perevertkin return status;
549*8a978a17SVictor Perevertkin }
550*8a978a17SVictor Perevertkin
551*8a978a17SVictor Perevertkin //
552*8a978a17SVictor Perevertkin // By passing 0's for raw object size and extra size, we can compute the
553*8a978a17SVictor Perevertkin // size of only the header and its contents.
554*8a978a17SVictor Perevertkin //
555*8a978a17SVictor Perevertkin status = FxCalculateObjectTotalSize(pFxDriverGlobals, 0, 0, Attributes, &size);
556*8a978a17SVictor Perevertkin if (!NT_SUCCESS(status)) {
557*8a978a17SVictor Perevertkin return status;
558*8a978a17SVictor Perevertkin }
559*8a978a17SVictor Perevertkin
560*8a978a17SVictor Perevertkin pHeader = (FxContextHeader*)
561*8a978a17SVictor Perevertkin FxPoolAllocate(pFxDriverGlobals, NonPagedPool, size);
562*8a978a17SVictor Perevertkin
563*8a978a17SVictor Perevertkin if (pHeader != NULL) {
564*8a978a17SVictor Perevertkin *ContextHeader = pHeader;
565*8a978a17SVictor Perevertkin status = STATUS_SUCCESS;
566*8a978a17SVictor Perevertkin }
567*8a978a17SVictor Perevertkin else {
568*8a978a17SVictor Perevertkin status = STATUS_INSUFFICIENT_RESOURCES;
569*8a978a17SVictor Perevertkin }
570*8a978a17SVictor Perevertkin
571*8a978a17SVictor Perevertkin return status;
572*8a978a17SVictor Perevertkin }
573*8a978a17SVictor Perevertkin
574*8a978a17SVictor Perevertkin _Must_inspect_result_
575*8a978a17SVictor Perevertkin NTSTATUS
VfAddContextToHandle(__in PVOID ContextHeader,__in PWDF_OBJECT_ATTRIBUTES Attributes,__in WDFOBJECT Handle,__out_opt PVOID * Context)576*8a978a17SVictor Perevertkin VfAddContextToHandle(
577*8a978a17SVictor Perevertkin __in PVOID ContextHeader,
578*8a978a17SVictor Perevertkin __in PWDF_OBJECT_ATTRIBUTES Attributes,
579*8a978a17SVictor Perevertkin __in WDFOBJECT Handle,
580*8a978a17SVictor Perevertkin __out_opt PVOID* Context
581*8a978a17SVictor Perevertkin )
582*8a978a17SVictor Perevertkin {
583*8a978a17SVictor Perevertkin PFX_DRIVER_GLOBALS pFxDriverGlobals;
584*8a978a17SVictor Perevertkin NTSTATUS status = STATUS_SUCCESS;
585*8a978a17SVictor Perevertkin FxObject* pObject;
586*8a978a17SVictor Perevertkin FxContextHeader *pHeader;
587*8a978a17SVictor Perevertkin WDFOBJECT_OFFSET offset;
588*8a978a17SVictor Perevertkin
589*8a978a17SVictor Perevertkin PAGED_CODE_LOCKED();
590*8a978a17SVictor Perevertkin
591*8a978a17SVictor Perevertkin pHeader = (FxContextHeader *)ContextHeader;
592*8a978a17SVictor Perevertkin
593*8a978a17SVictor Perevertkin if (pHeader == NULL) {
594*8a978a17SVictor Perevertkin return STATUS_INVALID_PARAMETER;
595*8a978a17SVictor Perevertkin }
596*8a978a17SVictor Perevertkin
597*8a978a17SVictor Perevertkin //
598*8a978a17SVictor Perevertkin // No need to call FxObjectHandleGetPtr( , , FX_TYPE_OBJECT) because
599*8a978a17SVictor Perevertkin // we assume that the object handle will point back to an FxObject. (The
600*8a978a17SVictor Perevertkin // call to FxObjectHandleGetPtr will just make needless virtual call into
601*8a978a17SVictor Perevertkin // FxObject anyways).
602*8a978a17SVictor Perevertkin //
603*8a978a17SVictor Perevertkin offset = 0;
604*8a978a17SVictor Perevertkin pObject = FxObject::_GetObjectFromHandle(Handle, &offset);
605*8a978a17SVictor Perevertkin
606*8a978a17SVictor Perevertkin pFxDriverGlobals = pObject->GetDriverGlobals();
607*8a978a17SVictor Perevertkin
608*8a978a17SVictor Perevertkin if (offset != 0) {
609*8a978a17SVictor Perevertkin //
610*8a978a17SVictor Perevertkin // for lack of a better error code
611*8a978a17SVictor Perevertkin //
612*8a978a17SVictor Perevertkin status = STATUS_OBJECT_PATH_INVALID;
613*8a978a17SVictor Perevertkin
614*8a978a17SVictor Perevertkin DoTraceLevelMessage(
615*8a978a17SVictor Perevertkin pFxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGHANDLE,
616*8a978a17SVictor Perevertkin "WDFHANDLE %p cannot have contexts added to it, %!STATUS!",
617*8a978a17SVictor Perevertkin Handle, status);
618*8a978a17SVictor Perevertkin
619*8a978a17SVictor Perevertkin goto cleanup;
620*8a978a17SVictor Perevertkin }
621*8a978a17SVictor Perevertkin
622*8a978a17SVictor Perevertkin pObject->ADDREF(&status);
623*8a978a17SVictor Perevertkin
624*8a978a17SVictor Perevertkin FxContextHeaderInit(pHeader, pObject, Attributes);
625*8a978a17SVictor Perevertkin
626*8a978a17SVictor Perevertkin status = pObject->AddContext(pHeader, Context, Attributes);
627*8a978a17SVictor Perevertkin
628*8a978a17SVictor Perevertkin //
629*8a978a17SVictor Perevertkin // STATUS_OBJECT_NAME_EXISTS will not fail NT_SUCCESS, so check
630*8a978a17SVictor Perevertkin // explicitly for STATUS_SUCCESS.
631*8a978a17SVictor Perevertkin //
632*8a978a17SVictor Perevertkin if (status != STATUS_SUCCESS) {
633*8a978a17SVictor Perevertkin DoTraceLevelMessage(
634*8a978a17SVictor Perevertkin pFxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGHANDLE,
635*8a978a17SVictor Perevertkin "WDFHANDLE %p failed to add context, %!STATUS!",
636*8a978a17SVictor Perevertkin Handle, status);
637*8a978a17SVictor Perevertkin }
638*8a978a17SVictor Perevertkin
639*8a978a17SVictor Perevertkin pObject->RELEASE(&status);
640*8a978a17SVictor Perevertkin
641*8a978a17SVictor Perevertkin cleanup:
642*8a978a17SVictor Perevertkin
643*8a978a17SVictor Perevertkin if (status != STATUS_SUCCESS && pHeader != NULL) {
644*8a978a17SVictor Perevertkin FxPoolFree(pHeader);
645*8a978a17SVictor Perevertkin }
646*8a978a17SVictor Perevertkin
647*8a978a17SVictor Perevertkin return status;
648*8a978a17SVictor Perevertkin }
649*8a978a17SVictor Perevertkin
650*8a978a17SVictor Perevertkin } // extern "C"
651