1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxIoTargetAPIKm.cpp
8 
9 Abstract:
10 
11     This module implements the IO Target APIs
12 
13 Author:
14 
15 Environment:
16 
17     kernel mode only
18 
19 Revision History:
20 
21 --*/
22 
23 #include "../../fxtargetsshared.hpp"
24 
25 extern "C" {
26 // #include "FxIoTargetAPIKm.tmh"
27 }
28 
29 //
30 // Extern the entire file
31 //
32 extern "C" {
33 
34 __drv_maxIRQL(DISPATCH_LEVEL)
35 PDEVICE_OBJECT
36 STDCALL
37 WDFEXPORT(WdfIoTargetWdmGetTargetDeviceObject)(
38     __in
39     PWDF_DRIVER_GLOBALS DriverGlobals,
40     __in
41     WDFIOTARGET IoTarget
42     )
43 /*++
44 
45 Routine Description:
46     Returns the PDEVICE_OBJECT.  This is the device which PIRPs are sent to.
47     This is not necessarily the PDEVICE_OBJECT that WDFDEVICE is attached to.
48 
49 Arguments:
50     IoTarget - target whose WDM device object is being returned
51 
52 Return Value:
53     valid PDEVICE_OBJECT or NULL on failure
54 
55   --*/
56 {
57     PFX_DRIVER_GLOBALS pFxDriverGlobals;
58     FxIoTarget* pTarget;
59     PDEVICE_OBJECT pDevice;
60 
61     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
62                                    IoTarget,
63                                    FX_TYPE_IO_TARGET,
64                                    (PVOID*) &pTarget,
65                                    &pFxDriverGlobals);
66 
67     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
68                         "enter WDFIOTARGET 0x%p", IoTarget);
69 
70     pDevice = pTarget->GetTargetDevice();
71 
72     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
73                         "exit WDFIOTARGET 0x%p, WDM DevObj 0x%p", IoTarget, pDevice);
74 
75     return pDevice;
76 }
77 
78 __drv_maxIRQL(DISPATCH_LEVEL)
79 PDEVICE_OBJECT
80 STDCALL
81 WDFEXPORT(WdfIoTargetWdmGetTargetPhysicalDevice)(
82     __in
83     PWDF_DRIVER_GLOBALS DriverGlobals,
84     __in
85     WDFIOTARGET IoTarget
86     )
87 /*++
88 
89 Routine Description:
90     Returns the PDO for the target itself.  This is not necessarily the same
91     PDO as the WDFDEVICE that owns the target.  Not all targets have a PDO since
92     you can open a legacy non pnp PDEVICE_OBJECT which does not have one.
93 
94 Arguments:
95     IoTarget - target whose PDO is being returned
96 
97 Return Value:
98     A valid PDEVICE_OBJECT or NULL upon success
99 
100   --*/
101 {
102     PFX_DRIVER_GLOBALS pFxDriverGlobals;
103     FxIoTarget* pTarget;
104     PDEVICE_OBJECT pPdo;
105 
106     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
107                                    IoTarget,
108                                    FX_TYPE_IO_TARGET,
109                                    (PVOID*) &pTarget,
110                                    &pFxDriverGlobals);
111 
112     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
113                         "enter WDFIOTARGET 0x%p", IoTarget);
114 
115     pPdo = pTarget->GetTargetPDO();
116 
117     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
118                         "exit WDFIOTARGET 0x%p, WDM PDO 0x%p", IoTarget, pPdo);
119 
120     return pPdo;
121 }
122 
123 
124 __drv_maxIRQL(DISPATCH_LEVEL)
125 PFILE_OBJECT
126 STDCALL
127 WDFEXPORT(WdfIoTargetWdmGetTargetFileObject)(
128     __in
129     PWDF_DRIVER_GLOBALS DriverGlobals,
130     __in
131     WDFIOTARGET IoTarget
132     )
133 /*++
134 
135 Routine Description:
136     Returns the PFILE_OBJECT associated with the target.  Not all targets have
137     an underlying file object so NULL is a valid and successful return value.
138 
139 Arguments:
140     IoTarget - the target whose fileobject is being returned
141 
142 Return Value:
143     a valid PFILE_OBJECT or NULL upon success
144 
145   --*/
146 {
147     PFX_DRIVER_GLOBALS pFxDriverGlobals;
148     FxIoTarget* pTarget;
149     MdFileObject pFile;
150 
151     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
152                                    IoTarget,
153                                    FX_TYPE_IO_TARGET,
154                                    (PVOID*) &pTarget,
155                                    &pFxDriverGlobals);
156 
157     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
158                         "enter WDFIOTARGET 0x%p", IoTarget);
159 
160     pFile = pTarget->GetTargetFileObject();
161 
162     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
163                         "exit WDFIOTARGET 0x%p, WDM FileObj 0x%p", IoTarget, pFile);
164 
165     return pFile;
166 }
167 
168 __drv_maxIRQL(PASSIVE_LEVEL)
169 _Must_inspect_result_
170 NTSTATUS
171 STDCALL
172 WDFEXPORT(WdfIoTargetQueryForInterface)(
173     __in
174     PWDF_DRIVER_GLOBALS DriverGlobals,
175     __in
176     WDFIOTARGET IoTarget,
177     __in
178     LPCGUID InterfaceType,
179     __out
180     PINTERFACE Interface,
181     __in
182     USHORT Size,
183     __in
184     USHORT Version,
185     __in_opt
186     PVOID InterfaceSpecificData
187     )
188 /*++
189 
190 Routine Description:
191     Sends a query interface pnp request to the top of the target's stack.
192 
193 Arguments:
194     IoTarget - the target which is being queried
195 
196     InterfaceType - interface type specifier
197 
198     Interface - Interface block which will be filled in by the component which
199                 responds to the query interface
200 
201     Size - size in bytes of Interface
202 
203     Version - version of InterfaceType being requested
204 
205     InterfaceSpecificData - Additional data associated with Interface
206 
207 Return Value:
208     NTSTATUS
209 
210   --*/
211 {
212     FxIoTarget* pTarget;
213     PFX_DRIVER_GLOBALS pFxDriverGlobals;
214     PDEVICE_OBJECT pTopOfStack;
215     NTSTATUS status;
216 
217     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
218                                    IoTarget,
219                                    FX_TYPE_IO_TARGET,
220                                    (PVOID*) &pTarget,
221                                    &pFxDriverGlobals);
222 
223     FxPointerNotNull(pFxDriverGlobals, InterfaceType);
224     FxPointerNotNull(pFxDriverGlobals, Interface);
225 
226     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
227     if (!NT_SUCCESS(status)) {
228         return status;
229     }
230 
231     pTopOfStack = IoGetAttachedDeviceReference(pTarget->GetTargetDevice());
232     ASSERT(pTopOfStack != NULL);
233 
234     status = FxQueryInterface::_QueryForInterface(pTopOfStack,
235                                                   InterfaceType,
236                                                   Interface,
237                                                   Size,
238                                                   Version,
239                                                   InterfaceSpecificData);
240 
241     ObDereferenceObject(pTopOfStack);
242 
243     return status;
244 }
245 
246 _Must_inspect_result_
247 __drv_maxIRQL(PASSIVE_LEVEL)
248 NTSTATUS
249 STDCALL
250 WDFEXPORT(WdfIoTargetQueryTargetProperty)(
251     __in
252     PWDF_DRIVER_GLOBALS DriverGlobals,
253     __in
254     WDFIOTARGET IoTarget,
255     __in
256     DEVICE_REGISTRY_PROPERTY  DeviceProperty,
257     __in
258     ULONG BufferLength,
259     __drv_when(BufferLength != 0, __out_bcount_part_opt(BufferLength, *ResultLength))
260     __drv_when(BufferLength == 0, __out_opt)
261     PVOID PropertyBuffer,
262     __deref_out_range(<=,BufferLength)
263     PULONG ResultLength
264     )
265 /*++
266 
267 Routine Description:
268     Retrieves the requested device property for the given target
269 
270 Arguments:
271     IoTarget - the target whose PDO whose will be queried
272 
273     DeviceProperty - the property being queried
274 
275     BufferLength - length of PropertyBuffer in bytes
276 
277     PropertyBuffer - Buffer which will receive the property being queried
278 
279     ResultLength - if STATUS_BUFFER_TOO_SMALL is returned, then this will contain
280                    the required length
281 
282 Return Value:
283     NTSTATUS
284 
285   --*/
286 {
287     DDI_ENTRY();
288 
289     PFX_DRIVER_GLOBALS pGlobals;
290     NTSTATUS status;
291     FxIoTarget* pTarget;
292     MdDeviceObject pPdo;
293 
294     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
295                                    IoTarget,
296                                    FX_TYPE_IO_TARGET,
297                                    (PVOID*) &pTarget,
298                                    &pGlobals);
299 
300     FxPointerNotNull(pGlobals, ResultLength);
301     if (BufferLength > 0) {
302         FxPointerNotNull(pGlobals, PropertyBuffer);
303     }
304 
305     status = FxVerifierCheckIrqlLevel(pGlobals, PASSIVE_LEVEL);
306     if (!NT_SUCCESS(status)) {
307         return status;
308     }
309 
310     pPdo = pTarget->GetTargetPDO();
311 
312     if (pPdo == NULL) {
313         status = STATUS_INVALID_DEVICE_REQUEST;
314 
315         DoTraceLevelMessage(pGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
316                             "WDFIOTARGET 0x%p has no PDO (not opened yet?), %!STATUS!",
317                             IoTarget, status);
318 
319         return status;
320     }
321 
322     status = FxDevice::_GetDeviceProperty(pPdo,
323                                           DeviceProperty,
324                                           BufferLength,
325                                           PropertyBuffer,
326                                           ResultLength);
327 
328     DoTraceLevelMessage(pGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
329                         "exit WDFIOTARGET 0x%p, Property %d, %!STATUS!",
330                         IoTarget, DeviceProperty, status);
331 
332 
333 
334     return status;
335 }
336 
337 _Must_inspect_result_
338 __drv_maxIRQL(PASSIVE_LEVEL)
339 WDFAPI
340 NTSTATUS
341 STDCALL
342 WDFEXPORT(WdfIoTargetAllocAndQueryTargetProperty)(
343     __in
344     PWDF_DRIVER_GLOBALS DriverGlobals,
345     __in
346     WDFIOTARGET IoTarget,
347     __in
348     DEVICE_REGISTRY_PROPERTY DeviceProperty,
349     __in
350     __drv_strictTypeMatch(1)
351     POOL_TYPE PoolType,
352     __in_opt
353     PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes,
354     __out
355     WDFMEMORY*  PropertyMemory
356     )
357 /*++
358 
359 Routine Description:
360     Allocates and retrieves the requested device property for the given target
361 
362 Arguments:
363     IoTarget - the target whose PDO whose will be queried
364 
365     DeviceProperty - the property being queried
366 
367     PoolType - what type of pool to allocate
368 
369     PropertyMemoryAttributes - attributes to associate with PropertyMemory
370 
371     PropertyMemory - handle which will receive the property buffer
372 
373 Return Value:
374     NTSTATUS
375 
376   --*/
377 {
378     DDI_ENTRY();
379 
380     PFX_DRIVER_GLOBALS pFxDriverGlobals;
381     NTSTATUS status;
382     FxIoTarget* pTarget;
383     MdDeviceObject pPdo;
384 
385     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
386                                    IoTarget,
387                                    FX_TYPE_IO_TARGET,
388                                    (PVOID*) &pTarget,
389                                    &pFxDriverGlobals);
390 
391     FxPointerNotNull(pFxDriverGlobals, PropertyMemory);
392 
393     *PropertyMemory = NULL;
394 
395     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
396     if (!NT_SUCCESS(status)) {
397         return status;
398     }
399 
400     FxVerifierCheckNxPoolType(pFxDriverGlobals, PoolType, pFxDriverGlobals->Tag);
401 
402     status = FxValidateObjectAttributes(pFxDriverGlobals, PropertyMemoryAttributes);
403     if (!NT_SUCCESS(status)) {
404         return status;
405     }
406 
407     pPdo = pTarget->GetTargetPDO();
408 
409     if (pPdo == NULL) {
410         status = STATUS_INVALID_DEVICE_REQUEST;
411 
412         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
413                             "WDFIOTARGET %p has no PDO (not opened yet?), %!STATUS!",
414                             IoTarget, status);
415 
416         return status;
417     }
418 
419     //
420     // Worker function which does the 2 passes.  First pass to query the size,
421     // the second pass w/the correctly sized buffer.
422     //
423     status = FxDevice::_AllocAndQueryProperty(pFxDriverGlobals,
424                                               NULL,
425                                               NULL,
426                                               pPdo,
427                                               DeviceProperty,
428                                               PoolType,
429                                               PropertyMemoryAttributes,
430                                               PropertyMemory);
431 
432     DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
433                         "exit WDFIOTARGET 0x%p, Property %d, %!STATUS!",
434                         IoTarget, DeviceProperty, status);
435 
436     return status;
437 }
438 
439 }
440