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