1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxDeviceApi.cpp 8 9 Abstract: 10 11 This module exposes the "C" interface to the FxDevice object. 12 13 Author: 14 15 16 17 Environment: 18 19 Both kernel and user mode 20 21 Revision History: 22 23 --*/ 24 25 #include "coreprivshared.hpp" 26 #include "fxiotarget.hpp" 27 28 extern "C" { 29 #include "FxDeviceApi.tmh" 30 } 31 32 struct FxOffsetAndName { 33 __nullterminated PCHAR Name; 34 UCHAR Offset; 35 }; 36 37 #define OFFSET_AND_NAME(type, offset) { #offset, FIELD_OFFSET(type, offset) } 38 39 // 40 // extern "C" the entire file 41 // 42 extern "C" { 43 44 __drv_maxIRQL(DISPATCH_LEVEL) 45 WDFDRIVER 46 WDFEXPORT(WdfDeviceGetDriver)( 47 __in 48 PWDF_DRIVER_GLOBALS DriverGlobals, 49 __in 50 WDFDEVICE Device 51 ) 52 /*++ 53 54 Routine Description: 55 56 Given a Device Handle, return a Handle to the Driver object 57 containing this device. 58 59 Arguments: 60 Device - WDF Device handle. 61 62 Returns: 63 WDF Driver handle. 64 65 --*/ 66 67 { 68 DDI_ENTRY(); 69 70 FxDevice* pDevice; 71 72 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 73 Device, 74 FX_TYPE_DEVICE, 75 (PVOID*) &pDevice); 76 77 // 78 // No need to ref count the driver handle b/c it will be around as long 79 // as the device handle is. 80 // 81 return pDevice->GetDriver()->GetHandle(); 82 } 83 84 __drv_maxIRQL(DISPATCH_LEVEL) 85 WDFIOTARGET 86 WDFEXPORT(WdfDeviceGetIoTarget)( 87 __in 88 PWDF_DRIVER_GLOBALS DriverGlobals, 89 __in 90 WDFDEVICE Device 91 ) 92 { 93 DDI_ENTRY(); 94 95 FxIoTarget* pTarget; 96 FxDeviceBase *pDeviceBase; 97 98 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 99 Device, 100 FX_TYPE_DEVICE_BASE, 101 (PVOID*) &pDeviceBase); 102 103 pTarget = pDeviceBase->GetDefaultIoTarget(); 104 105 if (pTarget != NULL) { 106 return pTarget->GetHandle(); 107 } 108 109 return NULL; 110 } 111 112 _IRQL_requires_max_(DISPATCH_LEVEL) 113 WDFIOTARGET 114 WDFEXPORT(WdfDeviceGetSelfIoTarget)( 115 _In_ 116 PWDF_DRIVER_GLOBALS DriverGlobals, 117 _In_ 118 WDFDEVICE Device 119 ) 120 121 /*++ 122 123 Routine Description: 124 125 Return the handle to the Self IO target for the device. A Self 126 IO target is only created if the client opted for it by calling 127 WdfDeviceInitAllowSelfTarget 128 129 Arguments: 130 131 Device - Handle to the Device Object for which Self IO target is needed 132 133 Returns: 134 135 WDFIOTARGET handle to the Self IO Target. NULL is returned in case the 136 device does not have an Self IO target. 137 138 --*/ 139 140 { 141 DDI_ENTRY(); 142 143 FxIoTargetSelf* pTarget; 144 FxDevice *pDevice; 145 146 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 147 Device, 148 FX_TYPE_DEVICE, 149 (PVOID*) &pDevice); 150 151 pTarget = pDevice->GetSelfIoTarget(); 152 153 if (pTarget != NULL) { 154 return pTarget->GetHandle(); 155 } 156 157 return NULL; 158 } 159 160 _Must_inspect_result_ 161 __drv_maxIRQL(PASSIVE_LEVEL) 162 NTSTATUS 163 WDFEXPORT(WdfDeviceRetrieveDeviceName)( 164 __in 165 PWDF_DRIVER_GLOBALS DriverGlobals, 166 __in 167 WDFDEVICE Device, 168 __in 169 WDFSTRING String 170 ) 171 { 172 DDI_ENTRY(); 173 174 PFX_DRIVER_GLOBALS pFxDriverGlobals; 175 FxDevice *pDevice; 176 FxString* pString; 177 NTSTATUS status; 178 179 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 180 Device, 181 FX_TYPE_DEVICE, 182 (PVOID *) &pDevice, 183 &pFxDriverGlobals); 184 185 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 186 if (!NT_SUCCESS(status)) { 187 return status; 188 } 189 190 FxObjectHandleGetPtr(pFxDriverGlobals, 191 String, 192 FX_TYPE_STRING, 193 (PVOID*) &pString); 194 195 if (pDevice->m_DeviceName.Buffer != NULL) { 196 status = pString->Assign(&pDevice->m_DeviceName); 197 } 198 else { 199 status = STATUS_INVALID_PARAMETER; 200 DoTraceLevelMessage( 201 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 202 "Device name for WDFDEVICE 0x%p is NULL. Possibly incorrect " 203 "device handle was passed, %!STATUS!", Device, status); 204 } 205 206 return status; 207 } 208 209 __drv_maxIRQL(DISPATCH_LEVEL) 210 VOID 211 WDFEXPORT(WdfDeviceSetCharacteristics)( 212 __in 213 PWDF_DRIVER_GLOBALS DriverGlobals, 214 __in 215 WDFDEVICE Device, 216 __in 217 ULONG DeviceCharacteristics 218 ) 219 { 220 DDI_ENTRY(); 221 222 FxDevice *pDevice; 223 MxDeviceObject deviceObject; 224 225 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 226 Device, 227 FX_TYPE_DEVICE, 228 (PVOID*) &pDevice); 229 230 deviceObject.SetObject(pDevice->GetDeviceObject()); 231 deviceObject.SetCharacteristics(DeviceCharacteristics | 232 FILE_DEVICE_SECURE_OPEN); 233 } 234 235 __drv_maxIRQL(DISPATCH_LEVEL) 236 ULONG 237 WDFEXPORT(WdfDeviceGetCharacteristics)( 238 __in 239 PWDF_DRIVER_GLOBALS DriverGlobals, 240 __in 241 WDFDEVICE Device 242 ) 243 { 244 DDI_ENTRY(); 245 246 FxDevice *pDevice; 247 MxDeviceObject deviceObject; 248 249 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 250 Device, 251 FX_TYPE_DEVICE, 252 (PVOID*) &pDevice); 253 254 deviceObject.SetObject(pDevice->GetDeviceObject()); 255 256 return deviceObject.GetCharacteristics(); 257 } 258 259 __drv_maxIRQL(DISPATCH_LEVEL) 260 ULONG 261 WDFEXPORT(WdfDeviceGetAlignmentRequirement)( 262 __in 263 PWDF_DRIVER_GLOBALS DriverGlobals, 264 __in 265 WDFDEVICE Device 266 ) 267 { 268 DDI_ENTRY(); 269 270 FxDeviceBase* pDeviceBase; 271 MxDeviceObject deviceObject; 272 273 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 274 Device, 275 FX_TYPE_DEVICE_BASE, 276 (PVOID*) &pDeviceBase); 277 278 deviceObject.SetObject(pDeviceBase->GetDeviceObject()); 279 280 return deviceObject.GetAlignmentRequirement(); 281 } 282 283 __drv_maxIRQL(DISPATCH_LEVEL) 284 VOID 285 WDFEXPORT(WdfDeviceSetAlignmentRequirement)( 286 __in 287 PWDF_DRIVER_GLOBALS DriverGlobals, 288 __in 289 WDFDEVICE Device, 290 __in 291 ULONG AlignmentRequirement 292 ) 293 { 294 DDI_ENTRY(); 295 296 FxDeviceBase* pDeviceBase; 297 MxDeviceObject deviceObject; 298 299 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 300 Device, 301 FX_TYPE_DEVICE_BASE, 302 (PVOID*) &pDeviceBase); 303 304 deviceObject.SetObject(pDeviceBase->GetDeviceObject()); 305 306 deviceObject.SetAlignmentRequirement(AlignmentRequirement); 307 } 308 309 __drv_maxIRQL(DISPATCH_LEVEL) 310 WDF_DEVICE_PNP_STATE 311 WDFEXPORT(WdfDeviceGetDevicePnpState)( 312 __in 313 PWDF_DRIVER_GLOBALS DriverGlobals, 314 __in 315 WDFDEVICE Device 316 ) 317 { 318 DDI_ENTRY(); 319 320 FxDevice *pDevice; 321 322 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 323 Device, 324 FX_TYPE_DEVICE, 325 (PVOID*) &pDevice); 326 327 return pDevice->GetDevicePnpState(); 328 } 329 330 __drv_maxIRQL(DISPATCH_LEVEL) 331 WDF_DEVICE_POWER_STATE 332 WDFEXPORT(WdfDeviceGetDevicePowerState)( 333 __in 334 PWDF_DRIVER_GLOBALS DriverGlobals, 335 __in 336 WDFDEVICE Device 337 ) 338 { 339 DDI_ENTRY(); 340 341 FxDevice *pDevice; 342 343 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 344 Device, 345 FX_TYPE_DEVICE, 346 (PVOID*) &pDevice); 347 348 return pDevice->GetDevicePowerState(); 349 } 350 351 __drv_maxIRQL(DISPATCH_LEVEL) 352 WDF_DEVICE_POWER_POLICY_STATE 353 WDFEXPORT(WdfDeviceGetDevicePowerPolicyState)( 354 __in 355 PWDF_DRIVER_GLOBALS DriverGlobals, 356 __in 357 WDFDEVICE Device 358 ) 359 { 360 DDI_ENTRY(); 361 362 FxDevice *pDevice; 363 364 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 365 Device, 366 FX_TYPE_DEVICE, 367 (PVOID*) &pDevice); 368 369 return pDevice->GetDevicePowerPolicyState(); 370 } 371 372 _Must_inspect_result_ 373 __drv_maxIRQL(DISPATCH_LEVEL) 374 NTSTATUS 375 WDFEXPORT(WdfDeviceAssignS0IdleSettings)( 376 __in 377 PWDF_DRIVER_GLOBALS DriverGlobals, 378 __in 379 WDFDEVICE Device, 380 __in 381 PWDF_DEVICE_POWER_POLICY_IDLE_SETTINGS Settings 382 ) 383 { 384 DDI_ENTRY(); 385 386 PFX_DRIVER_GLOBALS pFxDriverGlobals; 387 NTSTATUS status; 388 FxDevice* pDevice; 389 390 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 391 Device, 392 FX_TYPE_DEVICE, 393 (PVOID *) &pDevice, 394 &pFxDriverGlobals); 395 396 FxPointerNotNull(pFxDriverGlobals, Settings); 397 398 if (pDevice->m_PkgPnp->IsPowerPolicyOwner() == FALSE) { 399 status = STATUS_INVALID_DEVICE_REQUEST; 400 401 DoTraceLevelMessage( 402 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 403 "Device 0x%p is not the power policy owner, caller cannot set S0" 404 " idle settings %!STATUS!", Device, status); 405 406 return status; 407 } 408 409 // 410 // Validate the Settings parameter 411 // 412 if (Settings->Size != sizeof(WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS) && 413 Settings->Size != sizeof(WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_V1_9) && 414 Settings->Size != sizeof(WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_V1_7)) { 415 status = STATUS_INFO_LENGTH_MISMATCH; 416 DoTraceLevelMessage( 417 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 418 "Expected Settings Size %d, got %d, %!STATUS!", 419 sizeof(WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS), Settings->Size, 420 status); 421 return status; 422 } 423 else if (Settings->DxState < PowerDeviceD1 || 424 Settings->DxState > PowerDeviceMaximum || 425 Settings->IdleCaps < IdleCannotWakeFromS0 || 426 Settings->IdleCaps > IdleUsbSelectiveSuspend || 427 Settings->UserControlOfIdleSettings < IdleDoNotAllowUserControl || 428 Settings->UserControlOfIdleSettings > IdleAllowUserControl || 429 Settings->Enabled < WdfFalse || 430 Settings->Enabled > WdfUseDefault) { 431 432 status = STATUS_INVALID_PARAMETER; 433 DoTraceLevelMessage( 434 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 435 "a field (DxState, IdleCaps, Enabled, or UserControlOfIdleSettings)" 436 " is out range, %!STATUS!", status); 437 return status; 438 } 439 440 // 441 // PowerUpIdleDeviceOnSystemWake is available only on > 1.7 and can be set to true 442 // only when IdleCaps is IdleCannotWakeFromS0 443 // 444 if (Settings->Size > sizeof(WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_V1_7)) { 445 if (Settings->PowerUpIdleDeviceOnSystemWake < WdfFalse || 446 Settings->PowerUpIdleDeviceOnSystemWake > WdfUseDefault) { 447 448 status = STATUS_INVALID_PARAMETER; 449 DoTraceLevelMessage( 450 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 451 "value of field PowerUpIdleDeviceOnSystemWake is out of range," 452 " %!STATUS!", status); 453 return status; 454 } 455 else if (Settings->IdleCaps != IdleCannotWakeFromS0 && 456 Settings->PowerUpIdleDeviceOnSystemWake != WdfUseDefault) { 457 458 status = STATUS_INVALID_PARAMETER; 459 DoTraceLevelMessage( 460 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 461 "value of field PowerUpIdleDeviceOnSystemWake should be set only when" 462 " IdleCaps is IdleCannotWakeFromS0, %!STATUS!", status); 463 return status; 464 } 465 } 466 467 // 468 // IdleTimeoutType is available only on > 1.9 469 // 470 if (Settings->Size > sizeof(WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_V1_9)) { 471 if (Settings->IdleTimeoutType > SystemManagedIdleTimeoutWithHint) { 472 status = STATUS_INVALID_PARAMETER; 473 DoTraceLevelMessage( 474 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 475 "WDFDEVICE %p, value of field IdleTimeoutType is out of range," 476 " %!STATUS!", Device, status); 477 return status; 478 } 479 } 480 481 return pDevice->m_PkgPnp->PowerPolicySetS0IdleSettings(Settings); 482 } 483 484 _Must_inspect_result_ 485 __drv_maxIRQL(DISPATCH_LEVEL) 486 NTSTATUS 487 WDFEXPORT(WdfDeviceAssignSxWakeSettings)( 488 __in 489 PWDF_DRIVER_GLOBALS DriverGlobals, 490 __in 491 WDFDEVICE Device, 492 __in 493 PWDF_DEVICE_POWER_POLICY_WAKE_SETTINGS Settings 494 ) 495 { 496 DDI_ENTRY(); 497 498 NTSTATUS status; 499 FxDevice* pDevice; 500 PFX_DRIVER_GLOBALS pFxDriverGlobals; 501 BOOLEAN armForWakeIfChildrenAreArmedForWake; 502 BOOLEAN indicateChildWakeOnParentWake; 503 504 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 505 Device, 506 FX_TYPE_DEVICE, 507 (PVOID *) &pDevice, 508 &pFxDriverGlobals); 509 510 FxPointerNotNull(pFxDriverGlobals, Settings); 511 512 if (pDevice->m_PkgPnp->IsPowerPolicyOwner() == FALSE) { 513 status = STATUS_INVALID_DEVICE_REQUEST; 514 515 DoTraceLevelMessage( 516 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 517 "Device 0x%p is not the power policy owner, caller cannot set Sx" 518 " wake settings %!STATUS!", Device, status); 519 520 return status; 521 } 522 523 // 524 // Validate the Settings parameter 525 // 526 if (Settings->Size != sizeof(WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS) && 527 Settings->Size != sizeof(WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_V1_5)) { 528 status = STATUS_INFO_LENGTH_MISMATCH; 529 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 530 "Expected Settings Size %x, got %x, %!STATUS!", 531 sizeof(WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS), 532 Settings->Size, 533 status); 534 return status; 535 } 536 else if (Settings->DxState < PowerDeviceD1 || 537 Settings->DxState > PowerDeviceMaximum || 538 Settings->UserControlOfWakeSettings < WakeDoNotAllowUserControl || 539 Settings->UserControlOfWakeSettings > WakeAllowUserControl || 540 Settings->Enabled < WdfFalse || 541 Settings->Enabled > WdfUseDefault) { 542 543 status = STATUS_INVALID_PARAMETER; 544 DoTraceLevelMessage( 545 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 546 "a field (DxState, Enabled, or UserControlOfIdleSettings) is out " 547 "range, %!STATUS!", status); 548 return status; 549 } 550 551 // 552 // Extract the values from the structure for all the parameters that were 553 // added after v1.5. Since the size of the structure can only grow, get 554 // the values only if we are using a version of the struct after v1.5 555 // 556 557 // 558 // ArmForWakeIfChildrenAreArmedForWake added after v1.5 559 // 560 armForWakeIfChildrenAreArmedForWake = 561 (Settings->Size > sizeof(WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_V1_5)) ? 562 Settings->ArmForWakeIfChildrenAreArmedForWake : 563 FALSE; 564 565 // 566 // IndicateChildWakeOnParentWake added after v1.5 567 // 568 indicateChildWakeOnParentWake = 569 (Settings->Size > sizeof(WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_V1_5)) ? 570 Settings->IndicateChildWakeOnParentWake : 571 FALSE; 572 573 return pDevice->m_PkgPnp->PowerPolicySetSxWakeSettings( 574 Settings, 575 armForWakeIfChildrenAreArmedForWake, 576 indicateChildWakeOnParentWake); 577 } 578 579 _Must_inspect_result_ 580 __drv_maxIRQL(PASSIVE_LEVEL) 581 NTSTATUS 582 WDFEXPORT(WdfDeviceOpenRegistryKey)( 583 __in 584 PWDF_DRIVER_GLOBALS DriverGlobals, 585 __in 586 WDFDEVICE Device, 587 __in 588 ULONG DeviceInstanceKeyType, 589 __in 590 ACCESS_MASK DesiredAccess, 591 __in_opt 592 PWDF_OBJECT_ATTRIBUTES KeyAttributes, 593 __out 594 WDFKEY* Key 595 ) 596 { 597 DDI_ENTRY(); 598 599 NTSTATUS status; 600 FxDevice* pDevice; 601 PFX_DRIVER_GLOBALS pFxDriverGlobals; 602 603 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 604 Device, 605 FX_TYPE_DEVICE, 606 (PVOID *) &pDevice, 607 &pFxDriverGlobals); 608 609 FxPointerNotNull(pFxDriverGlobals, Key); 610 611 *Key = NULL; 612 613 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 614 if (!NT_SUCCESS(status)) { 615 FxVerifierDbgBreakPoint(pFxDriverGlobals); 616 return status; 617 } 618 619 status = FxValidateObjectAttributes(pFxDriverGlobals, KeyAttributes, 620 FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED); 621 if (!NT_SUCCESS(status)) { 622 623 return status; 624 } 625 626 return FxDevice::_OpenKey(pDevice->GetDriverGlobals(), 627 NULL, 628 pDevice, 629 DeviceInstanceKeyType, 630 DesiredAccess, 631 KeyAttributes, 632 Key); 633 } 634 635 _Must_inspect_result_ 636 _IRQL_requires_max_(PASSIVE_LEVEL) 637 NTSTATUS 638 WDFEXPORT(WdfDeviceOpenDevicemapKey) ( 639 _In_ 640 PWDF_DRIVER_GLOBALS DriverGlobals, 641 _In_ 642 WDFDEVICE Device, 643 _In_ 644 PCUNICODE_STRING KeyName, 645 _In_ 646 ACCESS_MASK DesiredAccess, 647 _In_opt_ 648 PWDF_OBJECT_ATTRIBUTES KeyAttributes, 649 _Out_ 650 WDFKEY* Key 651 ) 652 { 653 DDI_ENTRY(); 654 655 NTSTATUS status; 656 FxDevice* pDevice; 657 PFX_DRIVER_GLOBALS pFxDriverGlobals; 658 FxRegKey* pKey = NULL; 659 WDFKEY keyHandle; 660 661 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 662 Device, 663 FX_TYPE_DEVICE, 664 (PVOID *) &pDevice, 665 &pFxDriverGlobals); 666 667 FxPointerNotNull(pFxDriverGlobals, Key); 668 669 *Key = NULL; 670 671 status = FxValidateUnicodeString(pFxDriverGlobals, KeyName); 672 if (!NT_SUCCESS(status)) { 673 return status; 674 } 675 676 if (KeyName->Length == 0) { 677 status = STATUS_INVALID_PARAMETER; 678 DoTraceLevelMessage( 679 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 680 "The subkey cannot be of length zero, %!STATUS!", status); 681 return status; 682 } 683 684 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 685 if (!NT_SUCCESS(status)) { 686 FxVerifierDbgBreakPoint(pFxDriverGlobals); 687 return status; 688 } 689 690 status = FxValidateObjectAttributes(pFxDriverGlobals, KeyAttributes, 691 FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED); 692 if (!NT_SUCCESS(status)) { 693 return status; 694 } 695 696 pKey = new(pFxDriverGlobals, KeyAttributes) FxRegKey(pFxDriverGlobals); 697 698 if (pKey == NULL) { 699 status = STATUS_INSUFFICIENT_RESOURCES; 700 DoTraceLevelMessage( 701 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 702 "Unable to allocate memory for WDFKEY object, %!STATUS!", status); 703 return status; 704 } 705 706 pKey->SetDeviceBase(pDevice); 707 708 status = pKey->Commit(KeyAttributes, (WDFOBJECT*)&keyHandle); 709 if (NT_SUCCESS(status)) { 710 711 status = pDevice->OpenDevicemapKeyWorker(pFxDriverGlobals, 712 KeyName, 713 DesiredAccess, 714 pKey); 715 if (NT_SUCCESS(status)) { 716 *Key = keyHandle; 717 } 718 } 719 720 if (!NT_SUCCESS(status)) { 721 pKey->DeleteFromFailedCreate(); 722 pKey = NULL; 723 } 724 725 return status; 726 } 727 728 __drv_maxIRQL(DISPATCH_LEVEL) 729 VOID 730 WDFEXPORT(WdfDeviceGetDeviceState)( 731 __in 732 PWDF_DRIVER_GLOBALS DriverGlobals, 733 __in 734 WDFDEVICE Device, 735 __out 736 PWDF_DEVICE_STATE DeviceState 737 ) 738 { 739 DDI_ENTRY(); 740 741 FxDevice *pDevice; 742 PFX_DRIVER_GLOBALS pFxDriverGlobals; 743 744 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 745 Device, 746 FX_TYPE_DEVICE, 747 (PVOID *) &pDevice, 748 &pFxDriverGlobals); 749 750 FxPointerNotNull(pFxDriverGlobals, DeviceState); 751 752 if (DeviceState->Size != sizeof(WDF_DEVICE_STATE)) { 753 DoTraceLevelMessage( 754 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 755 "WDFDEVICE 0x%p DeviceState Size %d, expected %d", 756 Device, DeviceState->Size, sizeof(WDF_DEVICE_STATE)); 757 758 FxVerifierDbgBreakPoint(pFxDriverGlobals); 759 760 return; // STATUS_INFO_LENGTH_MISMATCH; 761 } 762 763 pDevice->m_PkgPnp->GetPnpState(DeviceState); 764 } 765 766 __drv_maxIRQL(DISPATCH_LEVEL) 767 VOID 768 WDFEXPORT(WdfDeviceSetDeviceState)( 769 __in 770 PWDF_DRIVER_GLOBALS DriverGlobals, 771 __in 772 WDFDEVICE Device, 773 __in 774 PWDF_DEVICE_STATE DeviceState 775 ) 776 { 777 DDI_ENTRY(); 778 779 FxDevice *pDevice; 780 PFX_DRIVER_GLOBALS pFxDriverGlobals; 781 ULONG i; 782 783 const static FxOffsetAndName offsets[] = { 784 OFFSET_AND_NAME(WDF_DEVICE_STATE, Disabled), 785 OFFSET_AND_NAME(WDF_DEVICE_STATE, DontDisplayInUI), 786 OFFSET_AND_NAME(WDF_DEVICE_STATE, Failed), 787 OFFSET_AND_NAME(WDF_DEVICE_STATE, NotDisableable), 788 OFFSET_AND_NAME(WDF_DEVICE_STATE, Removed), 789 OFFSET_AND_NAME(WDF_DEVICE_STATE, ResourcesChanged), 790 }; 791 792 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 793 Device, 794 FX_TYPE_DEVICE, 795 (PVOID *) &pDevice, 796 &pFxDriverGlobals); 797 798 FxPointerNotNull(pFxDriverGlobals, DeviceState); 799 800 if (DeviceState->Size != sizeof(WDF_DEVICE_STATE)) { 801 DoTraceLevelMessage( 802 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 803 "WDFDEVICE 0x%p, DeviceState Size %d, expected %d", 804 Device, DeviceState->Size, sizeof(WDF_DEVICE_STATE)); 805 806 FxVerifierDbgBreakPoint(pFxDriverGlobals); 807 return; // STATUS_INFO_LENGTH_MISMATCH; 808 } 809 810 for (i = 0; i < ARRAY_SIZE(offsets); i++) { 811 WDF_TRI_STATE value; 812 813 // 814 // This check makes prefast happy 815 // 816 if (offsets[i].Offset + sizeof(WDF_TRI_STATE) > sizeof(*DeviceState)) { 817 return; 818 } 819 820 value = *(WDF_TRI_STATE*) WDF_PTR_ADD_OFFSET(DeviceState, 821 offsets[i].Offset); 822 823 switch (value) { 824 case WdfFalse: 825 case WdfTrue: 826 case WdfUseDefault: 827 break; 828 829 default: 830 DoTraceLevelMessage( 831 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 832 "WDFDEVICE 0x%p DeviceState WDF_TRI_STATE %s value out of range, " 833 "value is %d", Device, offsets[i].Name, value); 834 FxVerifierDbgBreakPoint(pFxDriverGlobals); 835 836 return; // STATUS_INVALID_PARAMETER 837 } 838 } 839 840 pDevice->m_PkgPnp->SetPnpState(DeviceState); 841 842 pDevice->InvalidateDeviceState(); 843 } 844 845 846 _Must_inspect_result_ 847 __drv_maxIRQL(PASSIVE_LEVEL) 848 NTSTATUS 849 WDFEXPORT(WdfDeviceCreate)( 850 __in 851 PWDF_DRIVER_GLOBALS DriverGlobals, 852 853 854 __inout 855 856 PWDFDEVICE_INIT* DeviceInit, 857 __in_opt 858 PWDF_OBJECT_ATTRIBUTES DeviceAttributes, 859 __out 860 WDFDEVICE* Device 861 ) 862 { 863 DDI_ENTRY(); 864 865 FxDevice* pDevice; 866 NTSTATUS status; 867 PFX_DRIVER_GLOBALS pFxDriverGlobals; 868 869 pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals); 870 871 FxPointerNotNull(pFxDriverGlobals, DeviceInit); 872 FxPointerNotNull(pFxDriverGlobals, *DeviceInit); 873 FxPointerNotNull(pFxDriverGlobals, Device); 874 875 // 876 // Use the object's globals, not the caller's globals 877 // 878 pFxDriverGlobals = (*DeviceInit)->DriverGlobals; 879 880 *Device = NULL; 881 882 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 883 if (!NT_SUCCESS(status)) { 884 return status; 885 } 886 887 // 888 // Make sure the device attributes is initialized properly if passed in 889 // 890 status = FxValidateObjectAttributes(pFxDriverGlobals, 891 DeviceAttributes, 892 (FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED | 893 FX_VALIDATE_OPTION_EXECUTION_LEVEL_ALLOWED | 894 FX_VALIDATE_OPTION_SYNCHRONIZATION_SCOPE_ALLOWED)); 895 896 if (!NT_SUCCESS(status)) { 897 return status; 898 } 899 900 if ((*DeviceInit)->CreatedDevice != NULL) { 901 // 902 // Already created the device! 903 // 904 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 905 "WDFDEVICE 0x%p already created" 906 "STATUS_INVALID_DEVICE_STATE", 907 Device); 908 909 return STATUS_INVALID_DEVICE_STATE; 910 } 911 912 // 913 // If security is specified, then the device being created *must* have a 914 // name to apply that security too. 915 // 916 if ((*DeviceInit)->Security.Sddl != NULL || (*DeviceInit)->Security.DeviceClassSet) { 917 if ((*DeviceInit)->HasName()) { 918 // 919 // Driver writer specified a name, all is good 920 // 921 DO_NOTHING(); 922 } 923 else { 924 status = STATUS_INVALID_SECURITY_DESCR; 925 926 DoTraceLevelMessage( 927 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 928 "Device init: has device class or SDDL set, but does not have " 929 "a name, %!STATUS!", status); 930 931 return status; 932 } 933 } 934 935 if ((*DeviceInit)->RequiresSelfIoTarget) { 936 if ((*DeviceInit)->InitType != FxDeviceInitTypeFdo) { 937 status = STATUS_INVALID_DEVICE_REQUEST; 938 DoTraceLevelMessage( 939 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 940 "Client called WdfDeviceInitAllowSelfTarget. Self " 941 "IO Targets are supported only for FDOs, %!STATUS!", status); 942 return status; 943 } 944 } 945 946 status = FxDevice::_Create(pFxDriverGlobals, 947 DeviceInit, 948 DeviceAttributes, 949 &pDevice); 950 if (NT_SUCCESS(status)) { 951 *Device = pDevice->GetHandle(); 952 } 953 954 return status; 955 } 956 957 _Must_inspect_result_ 958 __drv_maxIRQL(PASSIVE_LEVEL) 959 NTSTATUS 960 WDFEXPORT(WdfDeviceCreateSymbolicLink)( 961 __in 962 PWDF_DRIVER_GLOBALS DriverGlobals, 963 __in 964 WDFDEVICE Device, 965 __in 966 PCUNICODE_STRING SymbolicLinkName 967 ) 968 { 969 DDI_ENTRY(); 970 971 PFX_DRIVER_GLOBALS pFxDriverGlobals; 972 PUNICODE_STRING pName; 973 FxAutoString pdoName; 974 FxDevice* pDevice; 975 NTSTATUS status; 976 977 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 978 Device, 979 FX_TYPE_DEVICE, 980 (PVOID *) &pDevice, 981 &pFxDriverGlobals); 982 pName = NULL; 983 984 FxPointerNotNull(pFxDriverGlobals, SymbolicLinkName); 985 986 if (SymbolicLinkName->Length == 0) { 987 status = STATUS_INVALID_DEVICE_REQUEST; 988 989 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 990 "WDFDEVICE %p, SymbolicLinkName has no length, %!STATUS!", 991 Device, status); 992 993 return status; 994 } 995 996 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 997 if (!NT_SUCCESS(status)) { 998 return status; 999 } 1000 1001 status = FxValidateUnicodeString(pFxDriverGlobals, SymbolicLinkName); 1002 if (!NT_SUCCESS(status)) { 1003 return status; 1004 } 1005 1006 if (pDevice->m_SymbolicLinkName.Buffer != NULL) { 1007 status = STATUS_INVALID_DEVICE_REQUEST; 1008 1009 DoTraceLevelMessage( 1010 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 1011 "WDFDEVICE %p already has a symbolic link associated with it, %!STATUS!", 1012 Device, status); 1013 1014 return status; 1015 } 1016 1017 status = pDevice->CreateSymbolicLink(pFxDriverGlobals, SymbolicLinkName); 1018 1019 return status; 1020 } 1021 1022 _Must_inspect_result_ 1023 __drv_maxIRQL(PASSIVE_LEVEL) 1024 NTSTATUS 1025 WDFEXPORT(WdfDeviceQueryProperty)( 1026 __in 1027 PWDF_DRIVER_GLOBALS DriverGlobals, 1028 __in 1029 WDFDEVICE Device, 1030 __in 1031 DEVICE_REGISTRY_PROPERTY DeviceProperty, 1032 __in 1033 ULONG BufferLength, 1034 __out_bcount_full(BufferLength) 1035 PVOID PropertyBuffer, 1036 __out 1037 PULONG ResultLength 1038 ) 1039 /*++ 1040 1041 Routine Description: 1042 Retrieves the requested device property for the given device 1043 1044 Arguments: 1045 Device - the device whose PDO whose will be queried 1046 1047 DeviceProperty - the property being queried 1048 1049 BufferLength - length of PropertyBuffer in bytes 1050 1051 PropertyBuffer - Buffer which will receive the property being queried 1052 1053 ResultLength - if STATUS_BUFFER_TOO_SMALL is returned, then this will contain 1054 the required length 1055 1056 Return Value: 1057 NTSTATUS 1058 1059 --*/ 1060 { 1061 DDI_ENTRY(); 1062 1063 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1064 FxDevice* pDevice; 1065 NTSTATUS status; 1066 1067 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1068 Device, 1069 FX_TYPE_DEVICE, 1070 (PVOID *) &pDevice, 1071 &pFxDriverGlobals); 1072 1073 FxPointerNotNull(pFxDriverGlobals, ResultLength); 1074 if (BufferLength > 0) { 1075 FxPointerNotNull(pFxDriverGlobals, PropertyBuffer); 1076 } 1077 1078 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 1079 if (!NT_SUCCESS(status)) { 1080 return status; 1081 } 1082 1083 if (pDevice->IsLegacy()) { 1084 status = STATUS_INVALID_DEVICE_REQUEST; 1085 1086 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 1087 "WDFDEVICE 0x%p is not a PnP device %!STATUS!", 1088 Device, status); 1089 1090 return status; 1091 } 1092 1093 status = FxDevice::_QueryProperty(pFxDriverGlobals, 1094 NULL, 1095 pDevice, 1096 NULL, 1097 DeviceProperty, 1098 BufferLength, 1099 PropertyBuffer, 1100 ResultLength); 1101 1102 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGDEVICE, 1103 "exit WDFDEVICE %p, Property %d, %!STATUS!", 1104 Device, DeviceProperty, status); 1105 1106 return status; 1107 } 1108 1109 _Must_inspect_result_ 1110 __drv_maxIRQL(PASSIVE_LEVEL) 1111 NTSTATUS 1112 WDFEXPORT(WdfDeviceAllocAndQueryProperty)( 1113 __in 1114 PWDF_DRIVER_GLOBALS DriverGlobals, 1115 __in 1116 WDFDEVICE Device, 1117 __in 1118 DEVICE_REGISTRY_PROPERTY DeviceProperty, 1119 __in 1120 __drv_strictTypeMatch(__drv_typeExpr) 1121 POOL_TYPE PoolType, 1122 __in_opt 1123 PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes, 1124 __out 1125 WDFMEMORY* PropertyMemory 1126 ) 1127 /*++ 1128 1129 Routine Description: 1130 Allocates and retrieves the requested device property for the given device 1131 1132 Arguments: 1133 Device - the pnp device whose PDO whose will be queried 1134 1135 DeviceProperty - the property being queried 1136 1137 PoolType - what type of pool to allocate 1138 1139 PropertyMemoryAttributes - attributes to associate with PropertyMemory 1140 1141 PropertyMemory - handle which will receive the property buffer 1142 1143 Return Value: 1144 NTSTATUS 1145 1146 --*/ 1147 { 1148 DDI_ENTRY(); 1149 1150 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1151 FxDevice* pDevice; 1152 NTSTATUS status; 1153 1154 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1155 Device, 1156 FX_TYPE_DEVICE, 1157 (PVOID *) &pDevice, 1158 &pFxDriverGlobals); 1159 1160 FxPointerNotNull(pFxDriverGlobals, PropertyMemory); 1161 1162 *PropertyMemory = NULL; 1163 1164 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 1165 if (!NT_SUCCESS(status)) { 1166 return status; 1167 } 1168 1169 FxVerifierCheckNxPoolType(pFxDriverGlobals, PoolType, pFxDriverGlobals->Tag); 1170 1171 status = FxValidateObjectAttributes(pFxDriverGlobals, PropertyMemoryAttributes); 1172 if (!NT_SUCCESS(status)) { 1173 return status; 1174 } 1175 1176 if (pDevice->IsLegacy()) { 1177 status = STATUS_INVALID_DEVICE_REQUEST; 1178 1179 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 1180 "WDFDEVICE %p is not a PnP device, %!STATUS!", 1181 Device, status); 1182 1183 return status; 1184 } 1185 1186 status = FxDevice::_AllocAndQueryProperty(pFxDriverGlobals, 1187 NULL, 1188 pDevice, 1189 NULL, 1190 DeviceProperty, 1191 PoolType, 1192 PropertyMemoryAttributes, 1193 PropertyMemory); 1194 1195 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGDEVICE, 1196 "exit WDFDEVICE %p, Property %d, %!STATUS!", 1197 Device, DeviceProperty, status); 1198 1199 return status; 1200 } 1201 1202 __drv_maxIRQL(DISPATCH_LEVEL) 1203 VOID 1204 WDFEXPORT(WdfDeviceSetStaticStopRemove)( 1205 __in 1206 PWDF_DRIVER_GLOBALS DriverGlobals, 1207 __in 1208 WDFDEVICE Device, 1209 __in 1210 BOOLEAN Stoppable 1211 ) 1212 { 1213 DDI_ENTRY(); 1214 1215 FxDevice *pDevice; 1216 1217 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 1218 Device, 1219 FX_TYPE_DEVICE, 1220 (PVOID*) &pDevice); 1221 1222 if (Stoppable) { 1223 // 1224 // Stoppable means that query stop / query remove can succeed. 1225 // This means m_DeviceStopCount == 0 (eventually if there are nested 1226 // calls to this function). 1227 // 1228 ASSERT(pDevice->m_PkgPnp->m_DeviceStopCount > 0); 1229 InterlockedDecrement((PLONG) &pDevice->m_PkgPnp->m_DeviceStopCount); 1230 } 1231 else { 1232 InterlockedIncrement((PLONG) &pDevice->m_PkgPnp->m_DeviceStopCount); 1233 } 1234 1235 return; 1236 } 1237 1238 __drv_maxIRQL(DISPATCH_LEVEL) 1239 VOID 1240 WDFEXPORT(WdfDeviceSetFailed)( 1241 __in 1242 PWDF_DRIVER_GLOBALS DriverGlobals, 1243 __in 1244 WDFDEVICE Device, 1245 __in 1246 WDF_DEVICE_FAILED_ACTION FailedAction 1247 ) 1248 { 1249 DDI_ENTRY(); 1250 1251 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1252 FxDevice *pDevice; 1253 1254 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1255 Device, 1256 FX_TYPE_DEVICE, 1257 (PVOID *) &pDevice, 1258 &pFxDriverGlobals); 1259 1260 if (FailedAction < WdfDeviceFailedAttemptRestart || 1261 FailedAction > WdfDeviceFailedNoRestart) { 1262 DoTraceLevelMessage( 1263 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 1264 "Invalid FailedAction %d", FailedAction); 1265 FxVerifierDbgBreakPoint(pDevice->GetDriverGlobals()); 1266 return; 1267 } 1268 1269 DoTraceLevelMessage( 1270 pFxDriverGlobals, TRACE_LEVEL_INFORMATION, TRACINGDEVICE, 1271 "WDFDEVICE %p, !devobj %p SetFailed %!WDF_DEVICE_FAILED_ACTION!", 1272 Device, pDevice->GetDeviceObject(), FailedAction); 1273 1274 pDevice->m_PkgPnp->SetDeviceFailed(FailedAction); 1275 } 1276 1277 __inline 1278 NTSTATUS 1279 StopIdleWorker( 1280 __in 1281 PWDF_DRIVER_GLOBALS DriverGlobals, 1282 __in 1283 WDFDEVICE Device, 1284 __in 1285 BOOLEAN WaitForD0, 1286 __in 1287 PVOID Tag, 1288 __in 1289 LONG Line, 1290 __in 1291 PSTR File 1292 ) 1293 { 1294 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1295 NTSTATUS status; 1296 FxDevice *pDevice; 1297 1298 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1299 Device, 1300 FX_TYPE_DEVICE, 1301 (PVOID *) &pDevice, 1302 &pFxDriverGlobals); 1303 1304 if (WaitForD0) { 1305 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, 1306 PASSIVE_LEVEL); 1307 if (!NT_SUCCESS(status)) { 1308 return status; 1309 } 1310 } 1311 1312 1313 if (pDevice->m_PkgPnp->IsPowerPolicyOwner() == FALSE) { 1314 status = STATUS_INVALID_DEVICE_STATE; 1315 DoTraceLevelMessage( 1316 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 1317 "WDFDEVICE %p WdfDeviceStopIdle does nothing if you are not the power " 1318 "policy owner for the stack, %!STATUS!", Device, status); 1319 return status; 1320 } 1321 1322 status = pDevice->m_PkgPnp->PowerReference(WaitForD0, Tag, Line, File); 1323 1324 DoTraceLevelMessage( 1325 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGDEVICE, 1326 "WDFDEVICE %p WdfDeviceStopIdle, WaitForD0 %d %!STATUS!", 1327 Device, WaitForD0, status); 1328 1329 return status; 1330 } 1331 1332 __inline 1333 VOID 1334 ResumeIdleWorker( 1335 __in 1336 PWDF_DRIVER_GLOBALS DriverGlobals, 1337 __in 1338 WDFDEVICE Device, 1339 __in 1340 PVOID Tag, 1341 __in 1342 LONG Line, 1343 __in 1344 PSTR File 1345 ) 1346 { 1347 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1348 FxDevice *pDevice; 1349 1350 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1351 Device, 1352 FX_TYPE_DEVICE, 1353 (PVOID *) &pDevice, 1354 &pFxDriverGlobals); 1355 1356 if (pDevice->m_PkgPnp->IsPowerPolicyOwner() == FALSE) { 1357 DoTraceLevelMessage( 1358 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 1359 "WdfDeviceResumeIdle does nothing if you are not the power " 1360 "policy owner for the stack"); 1361 return; 1362 } 1363 1364 pDevice->m_PkgPnp->PowerDereference(Tag, Line, File); 1365 } 1366 1367 _Must_inspect_result_ 1368 __drv_when(WaitForD0 == 0, __drv_maxIRQL(DISPATCH_LEVEL)) 1369 __drv_when(WaitForD0 != 0, __drv_maxIRQL(PASSIVE_LEVEL)) 1370 NTSTATUS 1371 WDFEXPORT(WdfDeviceStopIdleNoTrack)( 1372 __in 1373 PWDF_DRIVER_GLOBALS DriverGlobals, 1374 __in 1375 WDFDEVICE Device, 1376 __in 1377 BOOLEAN WaitForD0 1378 ) 1379 { 1380 DDI_ENTRY(); 1381 1382 NTSTATUS status; 1383 1384 status = StopIdleWorker(DriverGlobals, 1385 Device, 1386 WaitForD0, 1387 NULL, 1388 0, 1389 NULL); 1390 1391 return status; 1392 } 1393 1394 _Must_inspect_result_ 1395 __drv_when(WaitForD0 == 0, __drv_maxIRQL(DISPATCH_LEVEL)) 1396 __drv_when(WaitForD0 != 0, __drv_maxIRQL(PASSIVE_LEVEL)) 1397 NTSTATUS 1398 WDFEXPORT(WdfDeviceStopIdleActual)( 1399 __in 1400 PWDF_DRIVER_GLOBALS DriverGlobals, 1401 __in 1402 WDFDEVICE Device, 1403 __in 1404 BOOLEAN WaitForD0, 1405 __in_opt 1406 PVOID Tag, 1407 __in 1408 LONG Line, 1409 __in 1410 PSTR File 1411 ) 1412 { 1413 DDI_ENTRY(); 1414 1415 NTSTATUS status; 1416 1417 status = StopIdleWorker(DriverGlobals, 1418 Device, 1419 WaitForD0, 1420 Tag, 1421 Line, 1422 File); 1423 1424 return status; 1425 } 1426 1427 __drv_maxIRQL(DISPATCH_LEVEL) 1428 VOID 1429 WDFEXPORT(WdfDeviceResumeIdleNoTrack)( 1430 __in 1431 PWDF_DRIVER_GLOBALS DriverGlobals, 1432 __in 1433 WDFDEVICE Device 1434 ) 1435 { 1436 DDI_ENTRY(); 1437 1438 ResumeIdleWorker(DriverGlobals, 1439 Device, 1440 NULL, 1441 0, 1442 NULL); 1443 } 1444 1445 __drv_maxIRQL(DISPATCH_LEVEL) 1446 VOID 1447 WDFEXPORT(WdfDeviceResumeIdleActual)( 1448 __in 1449 PWDF_DRIVER_GLOBALS DriverGlobals, 1450 __in 1451 WDFDEVICE Device, 1452 __in_opt 1453 PVOID Tag, 1454 __in 1455 LONG Line, 1456 __in 1457 PSTR File 1458 ) 1459 { 1460 DDI_ENTRY(); 1461 1462 ResumeIdleWorker(DriverGlobals, 1463 Device, 1464 Tag, 1465 Line, 1466 File); 1467 } 1468 1469 __drv_maxIRQL(DISPATCH_LEVEL) 1470 VOID 1471 WDFEXPORT(WdfDeviceSetPnpCapabilities)( 1472 __in 1473 PWDF_DRIVER_GLOBALS DriverGlobals, 1474 __in 1475 WDFDEVICE Device, 1476 __in 1477 PWDF_DEVICE_PNP_CAPABILITIES PnpCapabilities 1478 ) 1479 /*++ 1480 1481 Routine Description: 1482 Sets the pnp capabilities of the device. This function is usually called 1483 during AddDevice or EvtDevicePrepareHardware since these values are queried 1484 by the stack and pnp during start device processing or immediately afterwards. 1485 1486 Arguments: 1487 Device - Device being set 1488 1489 PnpCapabilities - Caps being set 1490 1491 Return Value: 1492 None 1493 1494 --*/ 1495 { 1496 DDI_ENTRY(); 1497 1498 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1499 FxDevice* pDevice; 1500 ULONG i; 1501 1502 const static FxOffsetAndName offsets[] = { 1503 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, LockSupported), 1504 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, EjectSupported), 1505 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, Removable), 1506 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, DockDevice), 1507 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, UniqueID), 1508 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, SilentInstall), 1509 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, SurpriseRemovalOK), 1510 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, HardwareDisabled), 1511 OFFSET_AND_NAME(WDF_DEVICE_PNP_CAPABILITIES, NoDisplayInUI), 1512 }; 1513 1514 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1515 Device, 1516 FX_TYPE_DEVICE, 1517 (PVOID *) &pDevice, 1518 &pFxDriverGlobals); 1519 1520 FxPointerNotNull(pFxDriverGlobals, PnpCapabilities); 1521 1522 if (PnpCapabilities->Size != sizeof(WDF_DEVICE_PNP_CAPABILITIES)) { 1523 DoTraceLevelMessage( 1524 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 1525 "WDFDEVICE 0x%p PnpCapabilities Size %d, expected %d", 1526 Device, PnpCapabilities->Size, sizeof(WDF_DEVICE_PNP_CAPABILITIES)); 1527 FxVerifierDbgBreakPoint(pFxDriverGlobals); 1528 1529 return; // STATUS_INFO_LENGTH_MISMATCH; 1530 } 1531 else { 1532 for (i = 0; i < ARRAY_SIZE(offsets); i++) { 1533 WDF_TRI_STATE value; 1534 1535 // 1536 // This check makes prefast happy 1537 // 1538 if (offsets[i].Offset + sizeof(WDF_TRI_STATE) > 1539 sizeof(*PnpCapabilities)) { 1540 return; 1541 } 1542 1543 value = *(WDF_TRI_STATE*) WDF_PTR_ADD_OFFSET(PnpCapabilities, 1544 offsets[i].Offset); 1545 switch (value) { 1546 case WdfFalse: 1547 case WdfTrue: 1548 case WdfUseDefault: 1549 break; 1550 1551 default: 1552 DoTraceLevelMessage( 1553 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 1554 "WDFDEVICE 0x%p PnpCapabilities WDF_TRI_STATE %s value out " 1555 "of range, value is %d", Device, offsets[i].Name, value); 1556 FxVerifierDbgBreakPoint(pFxDriverGlobals); 1557 1558 return; // STATUS_INVALID_PARAMETER 1559 } 1560 } 1561 } 1562 1563 pDevice->m_PkgPnp->SetPnpCaps(PnpCapabilities); 1564 } 1565 1566 __drv_maxIRQL(DISPATCH_LEVEL) 1567 VOID 1568 WDFEXPORT(WdfDeviceSetPowerCapabilities)( 1569 __in 1570 PWDF_DRIVER_GLOBALS DriverGlobals, 1571 __in 1572 WDFDEVICE Device, 1573 __in 1574 PWDF_DEVICE_POWER_CAPABILITIES PowerCapabilities 1575 ) 1576 /*++ 1577 1578 Routine Description: 1579 Sets the power capabilities of the device. This function is usually called 1580 during AddDevice or EvtDevicePrepareHardware since these values are queried 1581 by the stack and power during start device processing or immediately afterwards. 1582 1583 Arguments: 1584 Device - Device being set 1585 1586 PowerCapabilities - Caps being set 1587 1588 Return Value: 1589 None 1590 1591 --*/ 1592 { 1593 DDI_ENTRY(); 1594 1595 FxDevice* pDevice; 1596 ULONG i; 1597 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1598 1599 const static FxOffsetAndName offsets[] = { 1600 OFFSET_AND_NAME(WDF_DEVICE_POWER_CAPABILITIES, DeviceD1), 1601 OFFSET_AND_NAME(WDF_DEVICE_POWER_CAPABILITIES, DeviceD2), 1602 OFFSET_AND_NAME(WDF_DEVICE_POWER_CAPABILITIES, WakeFromD0), 1603 OFFSET_AND_NAME(WDF_DEVICE_POWER_CAPABILITIES, WakeFromD1), 1604 OFFSET_AND_NAME(WDF_DEVICE_POWER_CAPABILITIES, WakeFromD2), 1605 OFFSET_AND_NAME(WDF_DEVICE_POWER_CAPABILITIES, WakeFromD3), 1606 }; 1607 1608 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1609 Device, 1610 FX_TYPE_DEVICE, 1611 (PVOID *) &pDevice, 1612 &pFxDriverGlobals); 1613 1614 FxPointerNotNull(pFxDriverGlobals, PowerCapabilities); 1615 1616 if (PowerCapabilities->Size != sizeof(WDF_DEVICE_POWER_CAPABILITIES)) { 1617 1618 DoTraceLevelMessage( 1619 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 1620 "WDFDEVICE 0x%p PowerCapabilities Size %d, expected %d", 1621 Device, PowerCapabilities->Size, 1622 sizeof(WDF_DEVICE_POWER_CAPABILITIES)); 1623 1624 FxVerifierDbgBreakPoint(pFxDriverGlobals); 1625 1626 return; // STATUS_INFO_LENGTH_MISMATCH; 1627 } 1628 else { 1629 for (i = 0; i < ARRAY_SIZE(offsets); i++) { 1630 WDF_TRI_STATE value; 1631 1632 // 1633 // This check makes prefast happy 1634 // 1635 if (offsets[i].Offset + sizeof(WDF_TRI_STATE) > 1636 sizeof(*PowerCapabilities)) { 1637 return; 1638 } 1639 1640 value = *(WDF_TRI_STATE*) WDF_PTR_ADD_OFFSET(PowerCapabilities, 1641 offsets[i].Offset); 1642 switch (value) { 1643 case WdfFalse: 1644 case WdfTrue: 1645 case WdfUseDefault: 1646 break; 1647 1648 default: 1649 DoTraceLevelMessage( 1650 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 1651 "WDFDEVICE 0x%p PowerCapabilities WDF_TRI_STATE %s value out " 1652 "of range, value is %d", 1653 Device, offsets[i].Name, value); 1654 FxVerifierDbgBreakPoint(pFxDriverGlobals); 1655 1656 return; // STATUS_INVALID_PARAMETER 1657 } 1658 } 1659 1660 for (i = 0; i < ARRAY_SIZE(PowerCapabilities->DeviceState); i++) { 1661 if (PowerCapabilities->DeviceState[i] < PowerDeviceUnspecified || 1662 PowerCapabilities->DeviceState[i] > PowerDeviceMaximum) { 1663 1664 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 1665 "WDFDEVICE 0x%p PowerCapabilities DeviceState is invalid", 1666 Device); 1667 1668 FxVerifierDbgBreakPoint(pFxDriverGlobals); 1669 1670 return; // STATUS_INVALID_PARAMETER; 1671 } 1672 } 1673 1674 if (PowerCapabilities->DeviceWake < PowerDeviceUnspecified || 1675 PowerCapabilities->DeviceWake > PowerDeviceMaximum) { 1676 1677 DoTraceLevelMessage( 1678 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 1679 "WDFDEVICE 0x%p PowerCapabilities DeviceWake %d is out of range", 1680 Device, PowerCapabilities->DeviceWake); 1681 1682 FxVerifierDbgBreakPoint(pFxDriverGlobals); 1683 1684 return; // STATUS_INVALID_PARAMETER; 1685 } 1686 1687 if (PowerCapabilities->SystemWake < PowerSystemUnspecified || 1688 PowerCapabilities->SystemWake > PowerSystemMaximum) { 1689 1690 DoTraceLevelMessage( 1691 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 1692 "WDFDEVICE 0x%p PowerCapabilities SystemWake %d is out of range", 1693 Device, PowerCapabilities->SystemWake); 1694 1695 FxVerifierDbgBreakPoint(pFxDriverGlobals); 1696 1697 return; // STATUS_INVALID_PARAMETER; 1698 } 1699 1700 if (pDevice->m_PkgPnp->IsPowerPolicyOwner() == FALSE && 1701 PowerCapabilities->IdealDxStateForSx != PowerDeviceMaximum) { 1702 DoTraceLevelMessage( 1703 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 1704 "WDFDEVICE 0x%p PowerCapabilities IdealDxStateForSx %d can only" 1705 " be set by the power policy owner", 1706 Device, PowerCapabilities->IdealDxStateForSx); 1707 1708 FxVerifierDbgBreakPoint(pFxDriverGlobals); 1709 1710 return; // STATUS_INVALID_PARAMETER; 1711 } 1712 1713 // 1714 // D0 is not allowed as an ideal Dx state 1715 // 1716 if (PowerCapabilities->IdealDxStateForSx < PowerDeviceD1 || 1717 PowerCapabilities->IdealDxStateForSx > PowerDeviceMaximum) { 1718 1719 DoTraceLevelMessage( 1720 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 1721 "WDFDEVICE 0x%p PowerCapabilities IdealDxStateForSx %d is out " 1722 "of range", Device, PowerCapabilities->IdealDxStateForSx); 1723 1724 FxVerifierDbgBreakPoint(pFxDriverGlobals); 1725 1726 return; // STATUS_INVALID_PARAMETER; 1727 } 1728 } 1729 1730 1731 pDevice->m_PkgPnp->SetPowerCaps(PowerCapabilities); 1732 } 1733 1734 _Must_inspect_result_ 1735 __drv_maxIRQL(DISPATCH_LEVEL) 1736 NTSTATUS 1737 WDFEXPORT(WdfDeviceConfigureRequestDispatching)( 1738 __in 1739 PWDF_DRIVER_GLOBALS DriverGlobals, 1740 __in 1741 WDFDEVICE Device, 1742 __in 1743 WDFQUEUE Queue, 1744 __in 1745 __drv_strictTypeMatch(__drv_typeCond) 1746 WDF_REQUEST_TYPE RequestType 1747 ) 1748 1749 /*++ 1750 1751 Routine Description: 1752 1753 Configure which IRP_MJ_* requests are automatically 1754 forwarded by the I/O package to the specified Queue. 1755 1756 By default the I/O package sends all requests to the 1757 devices default queue. This API allows certain requests 1758 to be specified to their own queues under driver control. 1759 1760 Arguments: 1761 1762 Device - The device which is handling the IO. 1763 1764 Queue - I/O Queue object to forward specified request to. 1765 1766 RequestType - WDF Request type to be forwarded to the queue 1767 1768 Returns: 1769 1770 NTSTATUS 1771 1772 --*/ 1773 1774 { 1775 DDI_ENTRY(); 1776 1777 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1778 NTSTATUS status; 1779 FxDevice* pDevice; 1780 FxIoQueue* pFxIoQueue; 1781 1782 pDevice = NULL; 1783 pFxIoQueue = NULL; 1784 1785 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1786 Device, 1787 FX_TYPE_DEVICE, 1788 (PVOID *) &pDevice, 1789 &pFxDriverGlobals); 1790 1791 if (RequestType != WdfRequestTypeCreate && 1792 RequestType != WdfRequestTypeRead && 1793 RequestType != WdfRequestTypeWrite && 1794 RequestType != WdfRequestTypeDeviceControl && 1795 RequestType != WdfRequestTypeDeviceControlInternal) { 1796 status = STATUS_INVALID_PARAMETER; 1797 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO, 1798 "Invalid RequestType %!WDF_REQUEST_TYPE!, %!STATUS!", 1799 RequestType, status); 1800 return status; 1801 } 1802 1803 // 1804 // Validate the Queue handle 1805 // 1806 FxObjectHandleGetPtr(pFxDriverGlobals, 1807 Queue, 1808 FX_TYPE_QUEUE, 1809 (PVOID*)&pFxIoQueue); 1810 1811 if (pDevice != pFxIoQueue->GetDevice()) { 1812 status = STATUS_INVALID_DEVICE_REQUEST; 1813 1814 DoTraceLevelMessage( 1815 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO, 1816 "Input WDFQUEUE 0x%p doesn't belong to the WDFDEVICE 0x%p, %!STATUS!", 1817 Queue, Device, status); 1818 1819 return status; 1820 } 1821 1822 if (pDevice->IsLegacy()) { 1823 // 1824 // This is a controldevice. Make sure the create is called after the device 1825 // is initialized and ready to accept I/O. 1826 // 1827 MxDeviceObject deviceObject(pDevice->GetDeviceObject()); 1828 if ((deviceObject.GetFlags() & DO_DEVICE_INITIALIZING) == 0x0) { 1829 1830 status = STATUS_INVALID_DEVICE_STATE; 1831 DoTraceLevelMessage( 1832 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 1833 "Queue cannot be configured for automatic dispatching" 1834 " after WdfControlDeviceFinishInitializing" 1835 "is called on the WDFDEVICE %p is called %!STATUS!", 1836 Device, 1837 status); 1838 return status; 1839 } 1840 } 1841 else { 1842 // 1843 // This is either FDO or PDO. Make sure it's not started yet. 1844 // 1845 if (pDevice->GetDevicePnpState() != WdfDevStatePnpInit) { 1846 status = STATUS_INVALID_DEVICE_STATE; 1847 DoTraceLevelMessage( 1848 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 1849 "Queue cannot be configured for automatic dispatching" 1850 "after the WDFDEVICE %p is started, %!STATUS!", 1851 Device, status); 1852 return status; 1853 } 1854 } 1855 1856 if (RequestType == WdfRequestTypeCreate) { 1857 status = pDevice->m_PkgGeneral->ConfigureForwarding(pFxIoQueue); 1858 } 1859 else { 1860 status = pDevice->m_PkgIo->ConfigureForwarding(pFxIoQueue, RequestType); 1861 } 1862 1863 return status; 1864 } 1865 1866 __drv_maxIRQL(DISPATCH_LEVEL) 1867 WDFQUEUE 1868 WDFEXPORT(WdfDeviceGetDefaultQueue)( 1869 __in 1870 PWDF_DRIVER_GLOBALS DriverGlobals, 1871 __in 1872 WDFDEVICE Device 1873 ) 1874 1875 /*++ 1876 1877 Routine Description: 1878 1879 Return the handle to the default queue for the device. 1880 1881 Arguments: 1882 1883 Device - Handle to the Device Object 1884 1885 Returns: 1886 1887 WDFQUEUE 1888 1889 --*/ 1890 1891 { 1892 DDI_ENTRY(); 1893 1894 FxPkgIo* pPkgIo;; 1895 FxIoQueue* pFxIoQueue;; 1896 FxDevice * pFxDevice; 1897 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1898 1899 pPkgIo = NULL; 1900 pFxIoQueue = NULL; 1901 1902 // 1903 // Validate the I/O Package handle, and get the FxPkgIo* 1904 // 1905 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1906 Device, 1907 FX_TYPE_DEVICE, 1908 (PVOID *) &pFxDevice, 1909 &pFxDriverGlobals); 1910 1911 pPkgIo = (FxPkgIo *) pFxDevice->m_PkgIo; 1912 pFxIoQueue = pPkgIo->GetDefaultQueue(); 1913 1914 // 1915 // A default queue is optional 1916 // 1917 if (pFxIoQueue == NULL) { 1918 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGIO, 1919 "No default Queue configured " 1920 "for Device 0x%p", Device); 1921 return NULL; 1922 } 1923 1924 return (WDFQUEUE)pFxIoQueue->GetObjectHandle();; 1925 } 1926 1927 _Must_inspect_result_ 1928 __drv_maxIRQL(DISPATCH_LEVEL) 1929 NTSTATUS 1930 WDFEXPORT(WdfDeviceEnqueueRequest)( 1931 __in 1932 PWDF_DRIVER_GLOBALS DriverGlobals, 1933 __in 1934 WDFDEVICE Device, 1935 __in 1936 WDFREQUEST Request 1937 ) 1938 1939 /*++ 1940 1941 Routine Description: 1942 1943 Inserts a request into the I/O Package processing pipeline. 1944 1945 The given request is processed by the I/O package, forwarding 1946 it to its configured destination or the default queue. 1947 1948 If an EvtIoInCallerContext is callback is registered, it is not called. 1949 1950 Arguments: 1951 1952 Device - Handle to the Device Object 1953 1954 Request - Request to insert in the processing pipeline 1955 1956 Return Value: 1957 1958 STATUS_SUCCESS - Request has been inserted into the I/O processing pipeline 1959 1960 !NT_SUCCESS(status) 1961 STATUS_WDF_BUSY - Device is not accepting requests, the driver still owns the 1962 the request and must complete it, or correct the conditions. 1963 1964 --*/ 1965 1966 { 1967 DDI_ENTRY(); 1968 1969 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1970 FxDevice *pDevice; 1971 FxRequest* pRequest; 1972 1973 // 1974 // Validate the device object handle 1975 // 1976 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1977 Device, 1978 FX_TYPE_DEVICE, 1979 (PVOID *) &pDevice, 1980 &pFxDriverGlobals); 1981 // 1982 // Validate Device object handle 1983 // 1984 FxObjectHandleGetPtr(pFxDriverGlobals, 1985 Device, 1986 FX_TYPE_DEVICE, 1987 (PVOID *) &pDevice); 1988 1989 // 1990 // Validate the request object handle 1991 // 1992 FxObjectHandleGetPtr(pFxDriverGlobals, 1993 Request, 1994 FX_TYPE_REQUEST, 1995 (PVOID *) &pRequest); 1996 1997 // 1998 // Dispatch it to the Io Package object 1999 // 2000 return pDevice->m_PkgIo->EnqueueRequest(pDevice, pRequest); 2001 } 2002 2003 __drv_maxIRQL(DISPATCH_LEVEL) 2004 POWER_ACTION 2005 WDFEXPORT(WdfDeviceGetSystemPowerAction)( 2006 __in 2007 PWDF_DRIVER_GLOBALS DriverGlobals, 2008 __in 2009 WDFDEVICE Device 2010 ) 2011 2012 /*++ 2013 2014 Routine Description: 2015 2016 This DDI returns the System power action. 2017 2018 If the DDI is called in the power down path of a device, it will return the 2019 current system power transition type because of which the device is powering 2020 down. If the DDI is called in the power up path of a device, it will return 2021 the system power transition type which initially put the device into a lower 2022 power state. If the DDI is called during the normal functioning of a device 2023 that is not undergoing a power state transition, or if the device is powering 2024 up as part of the system start up, the DDI will return the PowerActionNone 2025 value. 2026 2027 Arguments: 2028 2029 Device - Handle to the Device Object 2030 2031 Return Value: 2032 2033 Returns a POWER_ACTION enum value that represents the current system power 2034 action with regards to any system power transition underway. 2035 2036 --*/ 2037 2038 { 2039 DDI_ENTRY(); 2040 2041 FxDevice *pDevice; 2042 2043 // 2044 // Validate Device object handle 2045 // 2046 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 2047 Device, 2048 FX_TYPE_DEVICE, 2049 (PVOID*) &pDevice); 2050 2051 return pDevice->m_PkgPnp->GetSystemPowerAction(); 2052 } 2053 2054 _Must_inspect_result_ 2055 _IRQL_requires_max_(APC_LEVEL) 2056 WDFAPI 2057 NTSTATUS 2058 WDFEXPORT(WdfDeviceQueryPropertyEx)( 2059 _In_ 2060 PWDF_DRIVER_GLOBALS DriverGlobals, 2061 _In_ 2062 WDFDEVICE Device, 2063 _In_ 2064 PWDF_DEVICE_PROPERTY_DATA DeviceProperty, 2065 _In_ 2066 ULONG BufferLength, 2067 _Out_ 2068 PVOID PropertyBuffer, 2069 _Out_ 2070 PULONG RequiredSize, 2071 _Out_ 2072 PDEVPROPTYPE Type 2073 ) 2074 /*++ 2075 2076 Routine Description: 2077 2078 This routine queries interface property. 2079 2080 Arguments: 2081 2082 DriverGlobals - DriverGlobals pointer 2083 2084 Device - WDF Device handle. 2085 2086 DeviceProperty - A pointer to WDF_DEVICE_PROPERTY_ DATA structure. 2087 2088 BufferLength - The size, in bytes, of the buffer that is pointed to by 2089 PropertyBuffer. 2090 2091 PropertyBuffer - A caller-supplied pointer to a caller-allocated buffer that 2092 receives the requested information. The pointer can be NULL 2093 if the BufferLength parameter is zero. 2094 2095 ResultLength - A caller-supplied location that, on return, contains the 2096 size, in bytes, of the information that the method stored in 2097 PropertyBuffer. If the function's return value is 2098 STATUS_BUFFER_TOO_SMALL, this location receives the required 2099 buffer size. 2100 2101 Type - A pointer to a DEVPROPTYPE variable. If method successfully retrieves 2102 the property data, the routine writes the property type value 2103 to this variable. This value indicates the type of property 2104 data that is in the Data buffer. 2105 2106 Return Value: 2107 2108 Method returns an NTSTATUS value. This routine might return one of the 2109 following values. 2110 2111 STATUS_BUFFER_TOO_SMALL - The supplied buffer is too small to receive the 2112 information. The ResultLength member receives the 2113 size of buffer required. 2114 STATUS_SUCCESS - The operation succeeded. 2115 STATUS_INVALID_PARAMETER - One of the parameters is incorrect. 2116 2117 The method might return other NTSTATUS values. 2118 2119 --*/ 2120 2121 { 2122 DDI_ENTRY(); 2123 2124 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2125 FxDevice* pDevice; 2126 NTSTATUS status; 2127 2128 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 2129 Device, 2130 FX_TYPE_DEVICE, 2131 (PVOID *) &pDevice, 2132 &pFxDriverGlobals); 2133 2134 FxPointerNotNull(pFxDriverGlobals, DeviceProperty); 2135 2136 // 2137 // Validate PropertyData 2138 // 2139 if (DeviceProperty->Size != sizeof(WDF_DEVICE_PROPERTY_DATA)) { 2140 status = STATUS_INFO_LENGTH_MISMATCH; 2141 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 2142 "PropertyData size (%d) incorrect, expected %d, %!STATUS!", 2143 DeviceProperty->Size, 2144 sizeof(WDF_DEVICE_PROPERTY_DATA), status); 2145 return status; 2146 } 2147 2148 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, APC_LEVEL); 2149 if (!NT_SUCCESS(status)) { 2150 FxVerifierDbgBreakPoint(pFxDriverGlobals); 2151 return status; 2152 } 2153 2154 FxPointerNotNull(pFxDriverGlobals, RequiredSize); 2155 FxPointerNotNull(pFxDriverGlobals, Type); 2156 2157 if (BufferLength != 0 && PropertyBuffer == NULL) { 2158 status = STATUS_INVALID_PARAMETER; 2159 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 2160 "Property buffer size is non-zero, while the buffer is NULL" 2161 ", %!STATUS!", status); 2162 return status; 2163 } 2164 2165 if (BufferLength == 0 && PropertyBuffer != NULL) { 2166 status = STATUS_INVALID_PARAMETER; 2167 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 2168 "Property buffer size is zero, while the buffer is non-NULL" 2169 ", %!STATUS!", status); 2170 return status; 2171 } 2172 2173 status = FxDevice::_QueryPropertyEx(pFxDriverGlobals, 2174 NULL, 2175 pDevice, 2176 DeviceProperty, 2177 FxDeviceProperty, 2178 BufferLength, 2179 PropertyBuffer, 2180 RequiredSize, 2181 Type); 2182 return status; 2183 } 2184 2185 _Must_inspect_result_ 2186 _IRQL_requires_max_(APC_LEVEL) 2187 WDFAPI 2188 NTSTATUS 2189 WDFEXPORT(WdfDeviceAllocAndQueryPropertyEx)( 2190 _In_ 2191 PWDF_DRIVER_GLOBALS DriverGlobals, 2192 _In_ 2193 WDFDEVICE Device, 2194 _In_ 2195 PWDF_DEVICE_PROPERTY_DATA DeviceProperty, 2196 _In_ 2197 _Strict_type_match_ 2198 POOL_TYPE PoolType, 2199 _In_opt_ 2200 PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes, 2201 _Out_ 2202 WDFMEMORY* PropertyMemory, 2203 _Out_ 2204 PDEVPROPTYPE Type 2205 ) 2206 /*++ 2207 2208 Routine Description: 2209 2210 This routine queries device property. 2211 2212 Arguments: 2213 2214 DriverGlobals - DriverGlobals pointer 2215 2216 Device - WDF Device handle. 2217 2218 PropertyData - A pointer to WDF_DEVICE_PROPERTY_ DATA structure. 2219 2220 PoolType - A POOL_TYPE-typed enumerator that specifies the type of memory 2221 to be allocated. 2222 2223 PropertyMemoryAttributes - optional, A pointer to a caller-allocated 2224 WDF_OBJECT_ATTRIBUTES structure that describes object attributes 2225 for the memory object that the function will allocate. This 2226 parameter is optional and can be WDF_NO_OBJECT_ATTRIBUTES. 2227 2228 PropertyMemory - A pointer to a WDFMEMORY-typed location that receives a 2229 handle to a framework memory object. 2230 2231 Type - A pointer to a DEVPROPTYPE variable. If method successfully retrieves 2232 the property data, the routine writes the property type value to 2233 this variable. This value indicates the type of property data 2234 that is in the Data buffer. 2235 2236 Return Value: 2237 2238 Method returns an NTSTATUS value. This routine might return one of the 2239 following values. It might return other NTSTATUS-codes as well. 2240 2241 STATUS_SUCCESS The operation succeeded. 2242 STATUS_INVALID_PARAMETER One of the parameters is incorrect. 2243 2244 --*/ 2245 { 2246 DDI_ENTRY(); 2247 2248 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2249 FxDevice* pDevice; 2250 NTSTATUS status; 2251 2252 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 2253 Device, 2254 FX_TYPE_DEVICE, 2255 (PVOID *) &pDevice, 2256 &pFxDriverGlobals); 2257 2258 FxPointerNotNull(pFxDriverGlobals, DeviceProperty); 2259 2260 // 2261 // Validate PropertyData 2262 // 2263 if (DeviceProperty->Size != sizeof(WDF_DEVICE_PROPERTY_DATA)) { 2264 status = STATUS_INFO_LENGTH_MISMATCH; 2265 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 2266 "PropertyData size (%d) incorrect, expected %d, %!STATUS!", 2267 DeviceProperty->Size, 2268 sizeof(WDF_DEVICE_PROPERTY_DATA), status); 2269 return status; 2270 } 2271 2272 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, APC_LEVEL); 2273 if (!NT_SUCCESS(status)) { 2274 FxVerifierDbgBreakPoint(pFxDriverGlobals); 2275 return status; 2276 } 2277 2278 FxVerifierCheckNxPoolType(pFxDriverGlobals, PoolType, pFxDriverGlobals->Tag); 2279 2280 FxPointerNotNull(pFxDriverGlobals, PropertyMemory); 2281 FxPointerNotNull(pFxDriverGlobals, Type); 2282 2283 *PropertyMemory = NULL; 2284 2285 status = FxValidateObjectAttributes(pFxDriverGlobals, PropertyMemoryAttributes); 2286 if (!NT_SUCCESS(status)) { 2287 return status; 2288 } 2289 2290 status = FxDevice::_AllocAndQueryPropertyEx(pFxDriverGlobals, 2291 NULL, 2292 pDevice, 2293 DeviceProperty, 2294 FxDeviceProperty, 2295 PoolType, 2296 PropertyMemoryAttributes, 2297 PropertyMemory, 2298 Type); 2299 return status; 2300 } 2301 2302 _Must_inspect_result_ 2303 _IRQL_requires_max_(APC_LEVEL) 2304 WDFAPI 2305 NTSTATUS 2306 WDFEXPORT(WdfDeviceAssignProperty)( 2307 _In_ 2308 PWDF_DRIVER_GLOBALS DriverGlobals, 2309 _In_ 2310 WDFDEVICE Device, 2311 _In_ 2312 PWDF_DEVICE_PROPERTY_DATA DeviceProperty, 2313 _In_ 2314 DEVPROPTYPE Type, 2315 _In_ 2316 ULONG BufferLength, 2317 _In_opt_ 2318 PVOID PropertyBuffer 2319 ) 2320 /*++ 2321 2322 Routine Description: 2323 2324 This routine assigns interface property. 2325 2326 Arguments: 2327 2328 DriverGlobals - DriverGlobals pointer 2329 2330 Device - WDF Device handle. 2331 2332 PropertyData - A pointer to WDF_DEVICE_PROPERTY_ DATA structure. 2333 2334 Type - Set this parameter to the DEVPROPTYPE value that specifies the type 2335 of the data that is supplied in the Data buffer. 2336 2337 BufferLength - Specifies the length, in bytes, of the buffer that 2338 PropertyBuffer points to. 2339 2340 PropertyBuffer - optional, A pointer to the device interface property data. 2341 Set this parameter to NULL to delete the specified property. 2342 2343 Return Value: 2344 2345 Mthod returns an NTSTATUS value. This routine might return one of the 2346 following values. It might return other NTSTATUS-codes as well. 2347 2348 STATUS_SUCCESS - The operation succeeded. 2349 STATUS_INVALID_PARAMETER - One of the parameters is incorrect. 2350 2351 --*/ 2352 2353 { 2354 DDI_ENTRY(); 2355 2356 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2357 FxDevice *pDevice; 2358 NTSTATUS status; 2359 2360 // 2361 // Validate the Device object handle and get its FxDevice. Also get the 2362 // driver globals pointer. 2363 // 2364 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 2365 Device, 2366 FX_TYPE_DEVICE, 2367 (PVOID *) &pDevice, 2368 &pFxDriverGlobals); 2369 2370 FxPointerNotNull(pFxDriverGlobals, DeviceProperty); 2371 2372 // 2373 // Validate PropertyData 2374 // 2375 if (DeviceProperty->Size != sizeof(WDF_DEVICE_PROPERTY_DATA)) { 2376 status = STATUS_INFO_LENGTH_MISMATCH; 2377 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 2378 "PropertyData size (%d) incorrect, expected %d, %!STATUS!", 2379 DeviceProperty->Size, 2380 sizeof(WDF_DEVICE_PROPERTY_DATA), status); 2381 return status; 2382 } 2383 2384 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, APC_LEVEL); 2385 if (!NT_SUCCESS(status)) { 2386 FxVerifierDbgBreakPoint(pFxDriverGlobals); 2387 return status; 2388 } 2389 2390 if (BufferLength == 0 && PropertyBuffer != NULL) { 2391 status = STATUS_INVALID_PARAMETER; 2392 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 2393 "Property buffer size is zero, while the buffer is non-NULL" 2394 ", %!STATUS!", status); 2395 return status; 2396 } 2397 2398 status = pDevice->AssignProperty(DeviceProperty, 2399 FxDeviceProperty, 2400 Type, 2401 BufferLength, 2402 PropertyBuffer 2403 ); 2404 return status; 2405 } 2406 2407 _Must_inspect_result_ 2408 __drv_maxIRQL(DISPATCH_LEVEL) 2409 WDFAPI 2410 NTSTATUS 2411 WDFEXPORT(WdfDeviceConfigureWdmIrpDispatchCallback)( 2412 _In_ 2413 PWDF_DRIVER_GLOBALS DriverGlobals, 2414 _In_ 2415 WDFDEVICE Device, 2416 _In_opt_ 2417 WDFDRIVER Driver, 2418 _In_ 2419 UCHAR MajorFunction, 2420 _In_ 2421 PFN_WDFDEVICE_WDM_IRP_DISPATCH EvtDeviceWdmIrpDispatch, 2422 _In_opt_ 2423 WDFCONTEXT DriverContext 2424 ) 2425 2426 /*++ 2427 2428 Routine Description: 2429 2430 Configure callbacks for IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_DEVICE_CONTROL, and 2431 IRP_MJ_INTERNAL_DEVICE_CONTROL (KMDF only). By default the I/O package sends all requests to 2432 a device's default queue, or to the queues configured with 2433 WdfDeviceConfigureRequestDisaptching. This DDI allows a driver specified 2434 callback to select a different queue dynamically during runtime. 2435 2436 Arguments: 2437 2438 Device - The device which is handling the I/O. 2439 2440 Driver - An optional driver handle. Used to associate the 2441 callback with a specific class extension. 2442 2443 MajorFunction - IRP major function type to be forwarded to the callback 2444 2445 EvtDeviceWdmIrpDispatch - Callback invoked when encountering the given major function. 2446 2447 DriverContext - An optional untyped driver specified context. 2448 2449 Returns: 2450 2451 STATUS_SUCCESS on success 2452 STATUS_INVALID_PARAMETER if an incorrect MajorFunction was provided 2453 STATUS_INSUFFICIENT_RESOURCES if insufficient memory was available 2454 STATUS_INVALID_DEVICE_STATE if this DDI was called at an improper time 2455 2456 --*/ 2457 { 2458 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2459 NTSTATUS status; 2460 FxDevice* pDevice; 2461 FxCxDeviceInfo* pCxDeviceInfo; 2462 ULONG deviceFlags; 2463 2464 pDevice = NULL; 2465 pCxDeviceInfo = NULL; 2466 2467 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 2468 Device, 2469 FX_TYPE_DEVICE, 2470 (PVOID *) &pDevice, 2471 &pFxDriverGlobals); 2472 2473 // 2474 // Validate the MajorFunction provided. Note that 2475 // IRP_MJ_INTERNAL_DEVICE_CONTROL is KMDF only. 2476 // 2477 switch (MajorFunction) { 2478 case IRP_MJ_WRITE: 2479 case IRP_MJ_READ: 2480 case IRP_MJ_DEVICE_CONTROL: 2481 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 2482 case IRP_MJ_INTERNAL_DEVICE_CONTROL: 2483 #endif 2484 break; 2485 default: 2486 status = STATUS_INVALID_PARAMETER; 2487 DoTraceLevelMessage( 2488 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 2489 "Invalid MajorFunction provided %!IRPMJ!, %!STATUS!", 2490 MajorFunction, status); 2491 goto exit; 2492 } 2493 2494 // 2495 // Validate the driver handle and get (if present) the associated cx info. 2496 // 2497 if (Driver != NULL) { 2498 FxDriver* pDriver; 2499 2500 FxObjectHandleGetPtr(pFxDriverGlobals, 2501 Driver, 2502 FX_TYPE_DRIVER, 2503 (PVOID*)&pDriver); 2504 2505 // 2506 // Find the driver's cx info if it's not the main driver for this device. 2507 // cx struct info can be NULL if cx acts as client driver. 2508 // 2509 pCxDeviceInfo = pDevice->GetCxDeviceInfo(pDriver); 2510 } 2511 2512 // 2513 // Make sure callback is not null. 2514 // 2515 FxPointerNotNull(pFxDriverGlobals, EvtDeviceWdmIrpDispatch); 2516 2517 // 2518 // This callback can only be called during initialization. 2519 // 2520 if (pDevice->IsLegacy()) { 2521 2522 // 2523 // Extract the device flags from the device object 2524 // 2525 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 2526 deviceFlags = pDevice->GetDeviceObject()->Flags; 2527 #else 2528 deviceFlags = pDevice->GetDeviceObject()->GetDeviceObjectWdmFlags(); 2529 #endif 2530 2531 // 2532 // This is a controldevice. Make sure the create is called after the device 2533 // is initialized and ready to accept I/O. 2534 // 2535 if ((deviceFlags & DO_DEVICE_INITIALIZING) == 0x0) { 2536 status = STATUS_INVALID_DEVICE_STATE; 2537 DoTraceLevelMessage( 2538 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 2539 "Driver cannot set IRP dispatch callback " 2540 "after WdfControlDeviceFinishInitializing " 2541 "is called on the WDFDEVICE %p, %!STATUS!", 2542 pDevice, status); 2543 goto exit; 2544 } 2545 } else { 2546 // 2547 // This is either FDO or PDO. Make sure it's not started yet. 2548 // 2549 if (pDevice->GetDevicePnpState() != WdfDevStatePnpInit) { 2550 status = STATUS_INVALID_DEVICE_STATE; 2551 DoTraceLevelMessage( 2552 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 2553 "Driver cannot set IRP dispatch callback " 2554 "after the WDFDEVICE %p is started, %!STATUS!", 2555 pDevice, status); 2556 goto exit; 2557 } 2558 } 2559 2560 // 2561 // Let I/O package do the rest. 2562 // 2563 status = pDevice->m_PkgIo->ConfigureDynamicDispatching(MajorFunction, 2564 pCxDeviceInfo, 2565 EvtDeviceWdmIrpDispatch, 2566 DriverContext); 2567 exit: 2568 return status; 2569 } 2570 2571 _Must_inspect_result_ 2572 NTSTATUS 2573 FX_VF_FUNCTION(VerifyWdfDeviceWdmDispatchIrpToIoQueue) ( 2574 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, 2575 _In_ FxDevice* device, 2576 _In_ MdIrp Irp, 2577 _In_ FxIoQueue* queue, 2578 _In_ ULONG Flags 2579 ) 2580 { 2581 NTSTATUS status = STATUS_SUCCESS; 2582 UCHAR majorFunction, minorFunction; 2583 FxIrp fxIrp(Irp); 2584 2585 PAGED_CODE_LOCKED(); 2586 2587 majorFunction = fxIrp.GetMajorFunction(); 2588 minorFunction = fxIrp.GetMinorFunction(); 2589 2590 DoTraceLevelMessage( 2591 FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIO, 2592 "WDFDEVICE 0x%p !devobj 0x%p %!IRPMJ!, IRP_MN %x, IRP 0x%p", 2593 device->GetHandle(), device->GetDeviceObject(), 2594 majorFunction, minorFunction, Irp); 2595 2596 // 2597 // Validate Flags. For UMDF, this field is reserved and must be zero. 2598 // 2599 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 2600 if (Flags & ~FX_DISPATCH_IRP_TO_IO_QUEUE_FLAGS_MASK) { 2601 #else 2602 if (Flags != WDF_DISPATCH_IRP_TO_IO_QUEUE_NO_FLAGS) { 2603 #endif 2604 status = STATUS_INVALID_PARAMETER; 2605 DoTraceLevelMessage( 2606 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO, 2607 "Flags 0x%x are invalid, %!STATUS!", 2608 Flags, status); 2609 FxVerifierDbgBreakPoint(FxDriverGlobals); 2610 goto Done; 2611 } 2612 2613 // 2614 // Only read/writes/ctrls/internal_ctrls IRPs are allowed, i.e., the I/O request set. 2615 // 2616 if (device->GetDispatchPackage(majorFunction) != device->m_PkgIo) { 2617 status = STATUS_INVALID_PARAMETER; 2618 DoTraceLevelMessage( 2619 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO, 2620 "Only Read/Write/Control/Internal-Control IRPs can be " 2621 "forwarded to I/O Queue 0x%p, Irp 0x%p, %!IRPMJ!, " 2622 "IRP_MN %x, Device 0x%p, %!STATUS!", 2623 queue->GetHandle(), Irp, majorFunction, minorFunction, 2624 device->GetObjectHandle(), status); 2625 FxVerifierDbgBreakPoint(FxDriverGlobals); 2626 goto Done; 2627 } 2628 2629 // 2630 // Make sure queue can handle the request. 2631 // 2632 if (FALSE == queue->IsIoEventHandlerRegistered( 2633 (WDF_REQUEST_TYPE)majorFunction)) { 2634 2635 status = STATUS_INVALID_PARAMETER; 2636 DoTraceLevelMessage( 2637 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO, 2638 "I/O Queue 0x%p cannot handle Irp 0x%p, %!IRPMJ!, " 2639 "IRP_MN %x, Device 0x%p, %!STATUS!", 2640 queue->GetHandle(), Irp, majorFunction, minorFunction, 2641 device->GetObjectHandle(), status); 2642 FxVerifierDbgBreakPoint(FxDriverGlobals); 2643 goto Done; 2644 } 2645 2646 if (device->m_ParentDevice == queue->GetDevice()) { 2647 // 2648 // Send to parent device's queue validation. 2649 // 2650 if (device->m_ParentDevice == NULL) { 2651 status = STATUS_INVALID_PARAMETER; 2652 DoTraceLevelMessage( 2653 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO, 2654 "No parent device for Device 0x%p, %!STATUS!", 2655 device->GetObjectHandle(), status); 2656 FxVerifierDbgBreakPoint(FxDriverGlobals); 2657 goto Done; 2658 } 2659 2660 // 2661 // Make sure the child device is a PDO 2662 // 2663 ASSERT(device->IsPdo()); 2664 2665 // 2666 // Check if the WdfPdoInitSetForwardRequestToParent was called to 2667 // increase the StackSize of the child Device to include the stack 2668 // size of the parent Device 2669 // 2670 if (device->IsPnp() && 2671 device->GetPdoPkg()->m_AllowForwardRequestToParent == FALSE) { 2672 status = STATUS_INVALID_DEVICE_REQUEST; 2673 DoTraceLevelMessage( 2674 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO, 2675 "WdfPdoInitSetForwardRequestToParent not called on " 2676 "Device 0x%p, %!STATUS!", 2677 device->GetObjectHandle(), status); 2678 FxVerifierDbgBreakPoint(FxDriverGlobals); 2679 goto Done; 2680 } 2681 } 2682 else { 2683 // 2684 // Send to current device's queue validation. 2685 // 2686 if (device != queue->GetDevice()) { 2687 status = STATUS_INVALID_PARAMETER; 2688 DoTraceLevelMessage( 2689 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO, 2690 "Cannot forward a request to " 2691 "a different Device 0x%p, %!STATUS!", 2692 queue->GetDevice()->GetObjectHandle(), status); 2693 FxVerifierDbgBreakPoint(FxDriverGlobals); 2694 goto Done; 2695 } 2696 } 2697 2698 Done: 2699 return status; 2700 } 2701 2702 } // extern "C" 2703