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
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(PASSIVE_LEVEL)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_
__drv_maxIRQL(PASSIVE_LEVEL)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_
__drv_maxIRQL(PASSIVE_LEVEL)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