1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxRequestApi.cpp 8 9 Abstract: 10 11 This module implements FxRequest object 12 13 Author: 14 15 16 17 18 19 Environment: 20 21 Both kernel and user mode 22 23 Revision History: 24 25 26 --*/ 27 #include "coreprivshared.hpp" 28 29 // Tracing support 30 extern "C" { 31 // #include "FxRequestApi.tmh" 32 33 // 34 // Verifiers 35 // 36 // Do not supply Argument names 37 FX_DECLARE_VF_FUNCTION_P1( 38 NTSTATUS, 39 VerifyRequestComplete, 40 _In_ FxRequest* 41 ); 42 43 // Do not supply Argument names 44 FX_DECLARE_VF_FUNCTION_P1( 45 NTSTATUS, 46 VerifyWdfRequestIsCanceled, 47 _In_ FxRequest* 48 ); 49 50 //Do not supply argument names 51 FX_DECLARE_VF_FUNCTION_P1( 52 NTSTATUS, 53 VerifyWdfRequestForwardToIoQueue, 54 _In_ FxRequest* 55 ); 56 57 //Do not supply argument names 58 FX_DECLARE_VF_FUNCTION_P1( 59 NTSTATUS, 60 VerifyWdfRequestForwardToParentDeviceIoQueue, 61 _In_ FxRequest* 62 ); 63 64 _Must_inspect_result_ 65 __drv_maxIRQL(DISPATCH_LEVEL) 66 NTSTATUS 67 STDCALL 68 WDFEXPORT(WdfRequestCreate)( 69 __in 70 PWDF_DRIVER_GLOBALS DriverGlobals, 71 __in_opt 72 PWDF_OBJECT_ATTRIBUTES RequestAttributes, 73 __in_opt 74 WDFIOTARGET Target, 75 __out 76 WDFREQUEST* Request 77 ) 78 79 /*++ 80 81 Routine Description: 82 Creates a WDFREQUEST handle that is suitable to be submitted to the provided 83 target 84 85 Arguments: 86 RequestAttributes - Attributes associated with the request. If NULL, the 87 size of the user context associated with the request will be 88 the default size specified in WdfDriverCreate. 89 90 Target - Target for which the request will be sent to. If NULL, then 91 WdfRequestChangeTarget must be called before the request is formatted 92 or sent to any target 93 94 Request - Pointer which will receive the newly created request 95 96 Return Value: 97 NT_SUCCESS if successful, otherwise appropriate error code 98 99 --*/ 100 101 { 102 PFX_DRIVER_GLOBALS pFxDriverGlobals; 103 FxRequest* pRequest; 104 FxIoTarget* pTarget; 105 NTSTATUS status; 106 107 pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals); 108 109 if (Target != NULL) { 110 FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals, 111 Target, 112 FX_TYPE_IO_TARGET, 113 (PVOID*)&pTarget, 114 &pFxDriverGlobals); 115 } 116 else { 117 pTarget = NULL; 118 119 // 120 // For class extension support, get globals from parent object. 121 // 122 if (RequestAttributes != NULL && 123 RequestAttributes->ParentObject != NULL) { 124 125 FxObjectHandleGetGlobals( 126 pFxDriverGlobals, 127 RequestAttributes->ParentObject, 128 &pFxDriverGlobals); 129 } 130 } 131 132 FxPointerNotNull(pFxDriverGlobals, Request); 133 *Request = NULL; 134 135 status = FxRequest::_Create(pFxDriverGlobals, 136 RequestAttributes, 137 NULL, 138 pTarget, 139 FxRequestOwnsIrp, 140 FxRequestConstructorCallerIsDriver, 141 &pRequest); 142 143 if (NT_SUCCESS(status)) { 144 *Request = pRequest->GetHandle(); 145 146 #if FX_VERBOSE_TRACE 147 DoTraceLevelMessage( 148 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 149 "Created WDFREQUEST %p, %!STATUS!", 150 *Request, status); 151 #endif // FX_VERBOSE_TRACE 152 } 153 154 return status; 155 } 156 157 _Must_inspect_result_ 158 __drv_maxIRQL(DISPATCH_LEVEL) 159 NTSTATUS 160 STDCALL 161 WDFEXPORT(WdfRequestCreateFromIrp)( 162 __in 163 PWDF_DRIVER_GLOBALS DriverGlobals, 164 __in_opt 165 PWDF_OBJECT_ATTRIBUTES RequestAttributes, 166 __in 167 MdIrp Irp, 168 __in 169 BOOLEAN RequestFreesIrp, 170 __out 171 WDFREQUEST* Request 172 ) 173 174 /*++ 175 176 Routine Description: 177 Creates a request handle that uses an external IRP instead of an internally 178 allocated irp. 179 180 Arguments: 181 RequestAttributes - Attributes associated with the request. If NULL, the 182 size of the user context associated with the request will be 183 the default size specified in WdfDriverCreate. 184 185 Irp - The IRP to use 186 187 RequestFreesIrp - If TRUE, when the request handle is destroyed, it will 188 free the IRP with IoFreeIrp. If FALSE, it is the responsibility of the 189 calller to free the IRP 190 191 Request - Pointer which will receive the newly created request 192 193 Return Value: 194 NT_SUCCESS or appropriate error code 195 196 --*/ 197 198 { 199 FxRequest* pRequest; 200 NTSTATUS status; 201 PFX_DRIVER_GLOBALS pFxDriverGlobals; 202 203 pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals); 204 205 // 206 // For class extension support, get globals from parent object. 207 // 208 if (RequestAttributes != NULL && 209 RequestAttributes->ParentObject != NULL) { 210 211 FxObjectHandleGetGlobals( 212 pFxDriverGlobals, 213 RequestAttributes->ParentObject, 214 &pFxDriverGlobals); 215 } 216 217 FxPointerNotNull(pFxDriverGlobals, Irp); 218 FxPointerNotNull(pFxDriverGlobals, Request); 219 220 *Request = NULL; 221 222 status = FxRequest::_Create(pFxDriverGlobals, 223 RequestAttributes, 224 Irp, 225 NULL, 226 RequestFreesIrp ? FxRequestOwnsIrp 227 : FxRequestDoesNotOwnIrp, 228 FxRequestConstructorCallerIsDriver, 229 &pRequest); 230 231 if (NT_SUCCESS(status)) { 232 *Request = pRequest->GetHandle(); 233 234 #if FX_VERBOSE_TRACE 235 DoTraceLevelMessage( 236 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 237 "Irp %p RequestFreesIrp %d WDFREQUEST %p created", 238 Irp, RequestFreesIrp, *Request); 239 #endif // FX_VERBOSE_TRACE 240 } 241 242 return status; 243 } 244 245 246 #define WDF_REQUEST_REUSE_VALID_FLAGS_V1_9 \ 247 (WDF_REQUEST_REUSE_SET_NEW_IRP) 248 249 #define WDF_REQUEST_REUSE_VALID_FLAGS \ 250 (WDF_REQUEST_REUSE_SET_NEW_IRP | WDF_REQUEST_REUSE_MUST_COMPLETE) 251 252 253 254 255 256 257 258 __drv_maxIRQL(DISPATCH_LEVEL) 259 NTSTATUS 260 STDCALL 261 WDFEXPORT(WdfRequestReuse)( 262 __in 263 PWDF_DRIVER_GLOBALS DriverGlobals, 264 __in 265 WDFREQUEST Request, 266 __in 267 PWDF_REQUEST_REUSE_PARAMS ReuseParams 268 ) 269 /*++ 270 271 Routine Description: 272 Clears out the internal state of the irp, which includes, but is not limited 273 to: 274 a) Any internal allocations for the previously formatted request 275 b) The completion routine and its context 276 c) The request's intended i/o target 277 d) All of the internal IRP's stack locations 278 279 Arguments: 280 Request - The request to be reused. 281 282 ReuseParams - Parameters controlling the reuse of the request, see comments 283 for each field in the structure for usage 284 285 Return Value: 286 NT_SUCCESS or appropriate error code 287 288 --*/ 289 { 290 PFX_DRIVER_GLOBALS pFxDriverGlobals; 291 FxRequest *pRequest; 292 ULONG validFlags; 293 294 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 295 Request, 296 FX_TYPE_REQUEST, 297 (PVOID*)&pRequest, 298 &pFxDriverGlobals); 299 300 FxPointerNotNull(pFxDriverGlobals, ReuseParams); 301 302 if (ReuseParams->Size != sizeof(WDF_REQUEST_REUSE_PARAMS)) { 303 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 304 "ReuseParams Size %d, expected %d %!STATUS!", 305 ReuseParams->Size, sizeof(WDF_REQUEST_REUSE_PARAMS), 306 STATUS_INVALID_PARAMETER); 307 return STATUS_INVALID_PARAMETER; 308 } 309 310 if (pFxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,11)) { 311 validFlags = WDF_REQUEST_REUSE_VALID_FLAGS; 312 } 313 else { 314 validFlags = WDF_REQUEST_REUSE_VALID_FLAGS_V1_9; 315 } 316 317 if (ReuseParams->Flags & ~validFlags) { 318 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 319 "ReuseParams Flags 0x%x, valid mask 0x%x, %!STATUS!", 320 ReuseParams->Flags, 321 (ULONG) ~validFlags, 322 STATUS_INVALID_PARAMETER); 323 return STATUS_INVALID_PARAMETER; 324 } 325 326 return pRequest->Reuse(ReuseParams); 327 } 328 329 _Must_inspect_result_ 330 __drv_maxIRQL(DISPATCH_LEVEL) 331 NTSTATUS 332 STDCALL 333 WDFEXPORT(WdfRequestChangeTarget)( 334 __in 335 PWDF_DRIVER_GLOBALS DriverGlobals, 336 __in 337 WDFREQUEST Request, 338 __in 339 WDFIOTARGET IoTarget 340 ) 341 { 342 PFX_DRIVER_GLOBALS pFxDriverGlobals; 343 FxRequest* pRequest; 344 FxIoTarget* pTarget; 345 346 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 347 Request, 348 FX_TYPE_REQUEST, 349 (PVOID*)&pRequest, 350 &pFxDriverGlobals); 351 352 FxObjectHandleGetPtr(pFxDriverGlobals, 353 IoTarget, 354 FX_TYPE_IO_TARGET, 355 (PVOID*)&pTarget); 356 357 return pRequest->ValidateTarget(pTarget); 358 } 359 360 _Must_inspect_result_ 361 NTSTATUS 362 FX_VF_FUNCTION(VerifyRequestComplete) ( 363 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, 364 _In_ FxRequest* pRequest 365 ) 366 { 367 NTSTATUS status; 368 KIRQL irql; 369 370 PAGED_CODE_LOCKED(); 371 372 pRequest->Lock(&irql); 373 374 status = pRequest->VerifyRequestIsDriverOwned(FxDriverGlobals); 375 if (NT_SUCCESS(status)) { 376 status = pRequest->VerifyRequestCanBeCompleted(FxDriverGlobals); 377 } 378 379 pRequest->Unlock(irql); 380 return status; 381 } 382 383 __drv_maxIRQL(DISPATCH_LEVEL) 384 VOID 385 WDFAPI 386 STDCALL 387 WDFEXPORT(WdfRequestComplete)( 388 __in 389 PWDF_DRIVER_GLOBALS DriverGlobals, 390 __in 391 WDFREQUEST Request, 392 __in 393 NTSTATUS RequestStatus 394 ) 395 396 /*++ 397 398 Routine Description: 399 400 Complete the request with supplied status. 401 402 Any default reference counts implied by handle are invalid after 403 completion. 404 405 Arguments: 406 407 Request - Handle to the Request object 408 409 RequestStatus - Wdm Status to complete the request with 410 411 Returns: 412 413 None 414 415 --*/ 416 { 417 NTSTATUS status; 418 FxRequest *pRequest; 419 420 // 421 // Validate the request handle, and get the FxRequest* 422 // 423 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 424 Request, 425 FX_TYPE_REQUEST, 426 (PVOID*)&pRequest); 427 #if FX_VERBOSE_TRACE 428 // 429 // Use object's globals, not the caller's 430 // 431 DoTraceLevelMessage(pRequest->GetDriverGlobals(), 432 TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 433 "Completing WDFREQUEST 0x%p, %!STATUS!", 434 Request, RequestStatus); 435 #endif 436 status = VerifyRequestComplete(pRequest->GetDriverGlobals(), pRequest ); 437 if (!NT_SUCCESS(status)) { 438 return; 439 } 440 441 pRequest->Complete(RequestStatus); 442 } 443 444 __drv_maxIRQL(DISPATCH_LEVEL) 445 VOID 446 WDFAPI 447 STDCALL 448 WDFEXPORT(WdfRequestCompleteWithPriorityBoost)( 449 __in 450 PWDF_DRIVER_GLOBALS DriverGlobals, 451 __in 452 WDFREQUEST Request, 453 __in 454 NTSTATUS RequestStatus, 455 __in 456 CCHAR PriorityBoost 457 ) 458 459 /*++ 460 461 Routine Description: 462 463 Complete the request with supplied status. 464 465 Any default reference counts implied by handle are invalid after 466 completion. 467 468 Arguments: 469 470 Request - Handle to the Request object 471 472 RequestStatus - Wdm Status to complete the request with 473 474 PriorityBoost - A system-defined constant value by which to increment the 475 run-time priority of the original thread that requested the operation. 476 477 Returns: 478 479 None 480 481 --*/ 482 483 { 484 NTSTATUS status; 485 FxRequest *pRequest; 486 487 // 488 // Validate the request handle, and get the FxRequest* 489 // 490 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 491 Request, 492 FX_TYPE_REQUEST, 493 (PVOID*)&pRequest); 494 495 #if FX_VERBOSE_TRACE 496 // 497 // Use the object's globals, not the caller's 498 // 499 DoTraceLevelMessage(pRequest->GetDriverGlobals(), 500 TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 501 "Completing WDFREQUEST 0x%p, %!STATUS!", 502 Request, RequestStatus); 503 #endif 504 status = VerifyRequestComplete(pRequest->GetDriverGlobals(), 505 pRequest); 506 if (!NT_SUCCESS(status)) { 507 return; 508 } 509 510 pRequest->CompleteWithPriority(RequestStatus, PriorityBoost); 511 } 512 513 __drv_maxIRQL(DISPATCH_LEVEL) 514 VOID 515 WDFAPI 516 STDCALL 517 WDFEXPORT(WdfRequestCompleteWithInformation)( 518 __in 519 PWDF_DRIVER_GLOBALS DriverGlobals, 520 __in 521 WDFREQUEST Request, 522 __in 523 NTSTATUS RequestStatus, 524 __in 525 ULONG_PTR Information 526 ) 527 528 /*++ 529 530 Routine Description: 531 532 Complete the request with supplied status and information. 533 534 Any default reference counts implied by handle are invalid after 535 completion. 536 537 Arguments: 538 539 Request - Handle to the Request object 540 541 RequestStatus - Wdm Status to complete the request with 542 543 Information - Information to complete request with 544 545 Returns: 546 547 None 548 549 --*/ 550 551 { 552 FxRequest *pRequest; 553 NTSTATUS status; 554 555 // 556 // Validate the request handle, and get the FxRequest* 557 // 558 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 559 Request, 560 FX_TYPE_REQUEST, 561 (PVOID*)&pRequest); 562 563 #if FX_VERBOSE_TRACE 564 // 565 // Use the object's globals, not the caller's 566 // 567 DoTraceLevelMessage(pRequest->GetDriverGlobals(), 568 TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 569 "Completing WDFREQUEST 0x%p, %!STATUS!", 570 Request, RequestStatus); 571 #endif 572 status = VerifyRequestComplete(pRequest->GetDriverGlobals(), pRequest); 573 if (!NT_SUCCESS(status)) { 574 return; 575 } 576 577 578 pRequest->CompleteWithInformation(RequestStatus, Information); 579 } 580 581 __drv_maxIRQL(DISPATCH_LEVEL) 582 VOID 583 WDFAPI 584 STDCALL 585 WDFEXPORT(WdfRequestSetInformation)( 586 __in 587 PWDF_DRIVER_GLOBALS DriverGlobals, 588 __in 589 WDFREQUEST Request, 590 __in 591 ULONG_PTR Information 592 ) 593 594 /*++ 595 596 Routine Description: 597 598 Set the transfer information for the request. 599 600 This sets the NT Irp->Status.Information field. 601 602 Arguments: 603 604 Request - Handle to the Request object 605 606 Information - Value to be set 607 608 Returns: 609 610 None 611 612 --*/ 613 614 { 615 FxRequest *pRequest; 616 617 // 618 // Validate the request handle, and get the FxRequest* 619 // 620 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 621 Request, 622 FX_TYPE_REQUEST, 623 (PVOID*)&pRequest); 624 625 #if FX_VERBOSE_TRACE 626 // 627 // Use the object's globals, not the caller's 628 // 629 DoTraceLevelMessage(pRequest->GetDriverGlobals(), 630 TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 631 "Enter: WDFREQUEST 0x%p, Information 0x%p", 632 Request, (VOID*)Information); 633 #endif // FX_VERBOSE_TRACE 634 635 pRequest->SetInformation(Information); 636 } 637 638 __drv_maxIRQL(DISPATCH_LEVEL) 639 ULONG_PTR 640 WDFAPI 641 STDCALL 642 WDFEXPORT(WdfRequestGetInformation)( 643 __in 644 PWDF_DRIVER_GLOBALS DriverGlobals, 645 __in 646 WDFREQUEST Request 647 ) 648 649 /*++ 650 651 Routine Description: 652 653 Get the transfer information for the reuqest. 654 655 656 Arguments: 657 658 Request - Handle to the Request object 659 660 661 Returns: 662 663 Returns Irp->IoStatus.Information value. 664 665 --*/ 666 667 { 668 FxRequest *pRequest; 669 670 // 671 // Validate the request handle, and get the FxRequest* 672 // 673 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 674 Request, 675 FX_TYPE_REQUEST, 676 (PVOID*)&pRequest); 677 678 return pRequest->GetInformation(); 679 } 680 681 _Must_inspect_result_ 682 __drv_maxIRQL(DISPATCH_LEVEL) 683 NTSTATUS 684 WDFAPI 685 STDCALL 686 WDFEXPORT(WdfRequestRetrieveInputMemory)( 687 __in 688 PWDF_DRIVER_GLOBALS DriverGlobals, 689 __in 690 WDFREQUEST Request, 691 __out 692 WDFMEMORY *Memory 693 ) 694 /*++ 695 696 Routine Description: 697 698 Return the WDFMEMORY buffer associated with the request. 699 700 The memory buffer is valid in any thread/process context, 701 and may be accessed at IRQL > PASSIVE_LEVEL. 702 703 The memory buffer is automatically released when the request 704 is completed. 705 706 The memory buffers access permissions are validated according 707 to the command type (IRP_MJ_READ, IRP_MJ_WRITE), and may 708 only be accessed according to the access semantics of the request. 709 710 The memory buffer is not valid for a METHOD_NEITHER IRP_MJ_DEVICE_CONTROL, 711 or if neither of the DO_BUFFERED_IO or DO_DIRECT_IO flags are 712 configured for the device object. 713 714 The Memory buffer is as follows for each buffering mode: 715 716 DO_BUFFERED_IO: 717 718 Irp->AssociatedIrp.SystemBuffer 719 720 DO_DIRECT_IO: 721 722 MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) 723 724 NEITHER flag set: 725 726 NULL. Must use WdfDeviceInitSetIoInCallerContextCallback in order 727 to access the request in the calling threads address space before 728 it is placed into any I/O Queues. 729 730 The buffer is only valid until the request is completed. 731 732 Arguments: 733 734 Request - Handle to the Request object 735 736 Memory - Pointer location to return WDFMEMORY handle 737 738 Returns: 739 740 NTSTATUS 741 742 --*/ 743 744 { 745 PFX_DRIVER_GLOBALS pFxDriverGlobals; 746 NTSTATUS status; 747 FxRequest *pRequest; 748 IFxMemory* pMemory; 749 PVOID pBuffer; 750 size_t length; 751 752 pMemory = NULL; 753 754 // 755 // Validate the request handle, and get the FxRequest* 756 // 757 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 758 Request, 759 FX_TYPE_REQUEST, 760 (PVOID*)&pRequest, 761 &pFxDriverGlobals); 762 763 FxPointerNotNull(pFxDriverGlobals, Memory); 764 765 #if FX_VERBOSE_TRACE 766 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 767 "Enter: WDFREQUEST 0x%p", Request); 768 #endif // FX_VERBOSE_TRACE 769 770 // 771 // This call is not valid on Read request. 772 // 773 if (pRequest->GetFxIrp()->GetMajorFunction() == IRP_MJ_READ) { 774 status = STATUS_INVALID_DEVICE_REQUEST; 775 776 DoTraceLevelMessage( 777 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 778 "This call is not valid on the Read request, you should call" 779 " WdfRequestRetrieveOutputMemory to get the Memory for WDFREQUEST " 780 "0x%p, %!STATUS!", Request, status); 781 782 return status; 783 } 784 785 status = pRequest->GetMemoryObject(&pMemory, &pBuffer, &length); 786 if (NT_SUCCESS(status)) { 787 *Memory = pMemory->GetHandle(); 788 } 789 790 return status; 791 } 792 793 _Must_inspect_result_ 794 __drv_maxIRQL(DISPATCH_LEVEL) 795 NTSTATUS 796 WDFAPI 797 STDCALL 798 WDFEXPORT(WdfRequestRetrieveOutputMemory)( 799 __in 800 PWDF_DRIVER_GLOBALS DriverGlobals, 801 __in 802 WDFREQUEST Request, 803 __out 804 WDFMEMORY *Memory 805 ) 806 807 /*++ 808 809 Routine Description: 810 811 Return the WDFMEMORY buffer associated with the request. 812 813 The memory buffer is valid in any thread/process context, 814 and may be accessed at IRQL > PASSIVE_LEVEL. 815 816 The memory buffer is automatically released when the request 817 is completed. 818 819 The memory buffers access permissions are validated according 820 to the command type (IRP_MJ_READ, IRP_MJ_WRITE), and may 821 only be accessed according to the access semantics of the request. 822 823 The memory buffer is not valid for a METHOD_NEITHER IRP_MJ_DEVICE_CONTROL, 824 or if neither of the DO_BUFFERED_IO or DO_DIRECT_IO flags are 825 configured for the device object. 826 827 The Memory buffer is as follows for each buffering mode: 828 829 DO_BUFFERED_IO: 830 831 Irp->AssociatedIrp.SystemBuffer 832 833 DO_DIRECT_IO: 834 835 MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) 836 837 NEITHER flag set: 838 839 NULL. Must use WdfDeviceInitSetIoInCallerContextCallback in order 840 to access the request in the calling threads address space before 841 it is placed into any I/O Queues. 842 843 The buffer is only valid until the request is completed. 844 845 Arguments: 846 847 Request - Handle to the Request object 848 849 Memory - Pointer location to return WDFMEMORY handle 850 851 Returns: 852 853 NTSTATUS 854 855 --*/ 856 857 { 858 PFX_DRIVER_GLOBALS pFxDriverGlobals; 859 NTSTATUS status; 860 FxRequest *pRequest; 861 IFxMemory* pMemory; 862 PVOID pBuffer; 863 size_t length; 864 UCHAR majorFunction; 865 866 pMemory = NULL; 867 868 // 869 // Validate the request handle, and get the FxRequest* 870 // 871 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 872 Request, 873 FX_TYPE_REQUEST, 874 (PVOID*)&pRequest, 875 &pFxDriverGlobals); 876 877 FxPointerNotNull(pFxDriverGlobals, Memory); 878 879 #if FX_VERBOSE_TRACE 880 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 881 "Enter: WDFREQUEST 0x%p", Request); 882 #endif // FX_VERBOSE_TRACE 883 884 // 885 // This call is not valid on Write request. 886 // 887 majorFunction = pRequest->GetFxIrp()->GetMajorFunction(); 888 889 if (majorFunction == IRP_MJ_WRITE) { 890 status = STATUS_INVALID_DEVICE_REQUEST; 891 892 DoTraceLevelMessage( 893 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 894 "This call is not valid on the Write request, you should call" 895 " WdfRequestRetrieveInputMemory to get the Memory for WDFREQUEST " 896 "0x%p, %!STATUS!", Request, status); 897 898 return status; 899 } 900 901 if( (majorFunction == IRP_MJ_DEVICE_CONTROL) || 902 (majorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) ) { 903 status = pRequest->GetDeviceControlOutputMemoryObject(&pMemory, &pBuffer, &length); 904 } 905 else { 906 status = pRequest->GetMemoryObject(&pMemory, &pBuffer, &length); 907 } 908 909 if (NT_SUCCESS(status)) { 910 *Memory = pMemory->GetHandle(); 911 } 912 913 return status; 914 } 915 916 _Must_inspect_result_ 917 __drv_maxIRQL(DISPATCH_LEVEL) 918 NTSTATUS 919 WDFAPI 920 STDCALL 921 WDFEXPORT(WdfRequestRetrieveInputBuffer)( 922 __in 923 PWDF_DRIVER_GLOBALS DriverGlobals, 924 __in 925 WDFREQUEST Request, 926 __in 927 size_t RequiredLength, 928 __deref_out_bcount(*Length) 929 PVOID* Buffer, 930 __out_opt 931 size_t* Length 932 ) 933 /*++ 934 935 Routine Description: 936 937 Return the memory buffer associated with the request along 938 with its maximum length. 939 940 The memory buffer is valid in any thread/process context, 941 and may be accessed at IRQL > PASSIVE_LEVEL. 942 943 The memory buffer is automatically released when the request 944 is completed. 945 946 The memory buffers access permissions are validated according 947 to the command type (IRP_MJ_READ, IRP_MJ_WRITE), and may 948 only be accessed according to the access semantics of the request. 949 950 The memory buffer is not valid for a METHOD_NEITHER IRP_MJ_DEVICE_CONTROL, 951 or if neither of the DO_BUFFERED_IO or DO_DIRECT_IO flags are 952 configured for the device object. 953 954 The Memory buffer is as follows for each buffering mode: 955 956 DO_BUFFERED_IO: 957 958 Irp->AssociatedIrp.SystemBuffer 959 960 DO_DIRECT_IO: 961 962 MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) 963 964 NEITHER flag set: 965 966 NULL. Must use WdfDeviceInitSetIoInCallerContextCallback in order 967 to access the request in the calling threads address space before 968 it is placed into any I/O Queues. 969 970 The buffer is only valid until the request is completed. 971 972 Arguments: 973 974 Request - Handle to the Request object 975 976 RequiredLength - This is the minimum size expected by the caller 977 978 Buffer - Pointer location to return buffer ptr 979 980 Length - actual size of the buffer. This is >= to RequiredLength 981 982 Returns: 983 984 NTSTATUS 985 986 --*/ 987 { 988 PFX_DRIVER_GLOBALS pFxDriverGlobals; 989 NTSTATUS status; 990 FxRequest *pRequest; 991 IFxMemory* pMemory; 992 PVOID pBuffer; 993 size_t length; 994 995 pMemory = NULL; 996 997 // 998 // Validate the request handle, and get the FxRequest* 999 // 1000 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1001 Request, 1002 FX_TYPE_REQUEST, 1003 (PVOID*)&pRequest, 1004 &pFxDriverGlobals); 1005 1006 // 1007 // Validate the pointers and set its content to NULL 1008 // 1009 FxPointerNotNull(pFxDriverGlobals, Buffer); 1010 *Buffer = NULL; 1011 1012 if (Length != NULL) { 1013 *Length = 0; 1014 } 1015 1016 #if FX_VERBOSE_TRACE 1017 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1018 "Enter: WDFREQUEST 0x%p", Request); 1019 #endif //FX_VERBOSE_TRACE 1020 1021 // 1022 // This call is not valid on Read request. 1023 // 1024 if (pRequest->GetFxIrp()->GetMajorFunction() == IRP_MJ_READ) { 1025 status = STATUS_INVALID_DEVICE_REQUEST; 1026 1027 DoTraceLevelMessage( 1028 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1029 "This call is not valid on the read request, you should call" 1030 " WdfRequestRetrieveOutputBuffer to get the buffer for WDFREQUEST " 1031 "0x%p, %!STATUS!", Request, status); 1032 1033 return status; 1034 } 1035 1036 status = pRequest->GetMemoryObject(&pMemory, &pBuffer, &length); 1037 1038 if (NT_SUCCESS(status)) { 1039 if (length < RequiredLength) { 1040 status = STATUS_BUFFER_TOO_SMALL; 1041 1042 DoTraceLevelMessage( 1043 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1044 "WDFREQUEST 0x%p buffer size %I64d is less than RequiredLength " 1045 "%I64d, %!STATUS!", Request, length, RequiredLength, status); 1046 1047 return status; 1048 } 1049 1050 *Buffer = pBuffer; 1051 1052 if (Length != NULL) { 1053 *Length = length; 1054 } 1055 } 1056 1057 return status; 1058 } 1059 1060 _Must_inspect_result_ 1061 __drv_maxIRQL(DISPATCH_LEVEL) 1062 NTSTATUS 1063 WDFAPI 1064 STDCALL 1065 WDFEXPORT(WdfRequestRetrieveOutputBuffer)( 1066 __in 1067 PWDF_DRIVER_GLOBALS DriverGlobals, 1068 __in 1069 WDFREQUEST Request, 1070 __in 1071 size_t RequiredLength, 1072 __deref_out_bcount(*Length) 1073 PVOID* Buffer, 1074 __out_opt 1075 size_t* Length 1076 ) 1077 /*++ 1078 1079 Routine Description: 1080 1081 Return the memory buffer associated with the request along 1082 with its maximum length. 1083 1084 The memory buffer is valid in any thread/process context, 1085 and may be accessed at IRQL > PASSIVE_LEVEL. 1086 1087 The memory buffer is automatically released when the request 1088 is completed. 1089 1090 The memory buffers access permissions are validated according 1091 to the command type (IRP_MJ_READ, IRP_MJ_WRITE), and may 1092 only be accessed according to the access semantics of the request. 1093 1094 The memory buffer is not valid for a METHOD_NEITHER IRP_MJ_DEVICE_CONTROL, 1095 or if neither of the DO_BUFFERED_IO or DO_DIRECT_IO flags are 1096 configured for the device object. 1097 1098 The Memory buffer is as follows for each buffering mode: 1099 1100 DO_BUFFERED_IO: 1101 1102 Irp->AssociatedIrp.SystemBuffer 1103 1104 DO_DIRECT_IO: 1105 1106 MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) 1107 1108 NEITHER flag set: 1109 1110 NULL. Must use WdfDeviceInitSetIoInCallerContextCallback in order 1111 to access the request in the calling threads address space before 1112 it is placed into any I/O Queues. 1113 1114 The buffer is only valid until the request is completed. 1115 1116 Arguments: 1117 1118 Request - Handle to the Request object 1119 1120 RequiredLength - This is the minimum size expected by the caller 1121 1122 Buffer - Pointer location to return buffer ptr 1123 1124 Length - actual size of the buffer. This is >= to RequiredLength 1125 1126 Returns: 1127 1128 NTSTATUS 1129 1130 --*/ 1131 { 1132 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1133 NTSTATUS status; 1134 FxRequest *pRequest; 1135 IFxMemory* pMemory; 1136 PVOID pBuffer; 1137 size_t length; 1138 UCHAR majorFunction; 1139 1140 pMemory = NULL; 1141 1142 // 1143 // Validate the request handle, and get the FxRequest* 1144 // 1145 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1146 Request, 1147 FX_TYPE_REQUEST, 1148 (PVOID*)&pRequest, 1149 &pFxDriverGlobals); 1150 1151 // 1152 // Validate the pointers and set its content to NULL 1153 // 1154 FxPointerNotNull(pFxDriverGlobals, Buffer); 1155 *Buffer = NULL; 1156 1157 if (Length != NULL) { 1158 *Length = 0; 1159 } 1160 1161 #if FX_VERBOSE_TRACE 1162 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1163 "Enter: WDFREQUEST 0x%p", Request); 1164 #endif //FX_VERBOSE_TRACE 1165 1166 // 1167 // This call is not valid on Write request. 1168 // 1169 majorFunction = pRequest->GetFxIrp()->GetMajorFunction(); 1170 1171 if (majorFunction == IRP_MJ_WRITE) { 1172 status = STATUS_INVALID_DEVICE_REQUEST; 1173 1174 DoTraceLevelMessage( 1175 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1176 "This call is not valid on write request, you should call" 1177 " WdfRequestRetrieveInputBuffer to get the buffer for WDFREQUEST " 1178 "0x%p, %!STATUS!", Request, status); 1179 1180 return status; 1181 } 1182 1183 if (majorFunction == IRP_MJ_DEVICE_CONTROL || 1184 majorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) { 1185 status = pRequest->GetDeviceControlOutputMemoryObject( 1186 &pMemory, &pBuffer, &length); 1187 } 1188 else { 1189 status = pRequest->GetMemoryObject(&pMemory, &pBuffer, &length); 1190 } 1191 1192 if (NT_SUCCESS(status)) { 1193 if (length < RequiredLength) { 1194 status = STATUS_BUFFER_TOO_SMALL; 1195 1196 DoTraceLevelMessage( 1197 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1198 "WDFREQUEST 0x%p buffer size %I64d is less than RequiredLength " 1199 "%I64d, %!STATUS!", Request, length, RequiredLength, status); 1200 1201 return status; 1202 } 1203 1204 *Buffer = pBuffer; 1205 1206 if (Length != NULL) { 1207 *Length = length; 1208 } 1209 } 1210 1211 return status; 1212 } 1213 1214 _Must_inspect_result_ 1215 __drv_maxIRQL(PASSIVE_LEVEL) 1216 NTSTATUS 1217 WDFAPI 1218 STDCALL 1219 WDFEXPORT(WdfRequestRetrieveUnsafeUserInputBuffer)( 1220 __in 1221 PWDF_DRIVER_GLOBALS DriverGlobals, 1222 __in 1223 WDFREQUEST Request, 1224 __in 1225 size_t RequiredLength, 1226 __deref_out_bcount_opt(*Length) 1227 PVOID* InputBuffer, 1228 __out_opt 1229 size_t* Length 1230 ) 1231 /*++ 1232 1233 Routine Description: 1234 1235 Returns input buffer of a method-neither request. This function can be 1236 called only in the context of EvtDeviceIoInProcessContextCallback at 1237 PASSIVE_LEVEL. 1238 1239 This call is valid on public IOCTL and Write request. 1240 1241 The returned buffer is valid only in the caller's process context. This 1242 call should be typically used in a toplevel or monolithic driver to 1243 guarantee the caller's context. 1244 1245 1246 The Memory buffer is as follows for each type of request: 1247 1248 For IOCTL, it will return irpStack->Parameters.DeviceIoControl.Type3InputBuffer 1249 1250 For Write, it will return Irp->UserBuffer. 1251 1252 For read and internal-device control and other type of request, this call 1253 will return an error. 1254 1255 1256 Arguments: 1257 1258 Request - Handle to the Request object 1259 1260 RequiredLength - minimum length of the buffer expected by the caller. 1261 If it's not this call will return an error. 1262 1263 1264 InputBuffer - Pointer location to return buffer ptr 1265 1266 Length - actual size of the buffer. This is >= to RequiredLength 1267 1268 Returns: 1269 1270 NTSTATUS 1271 1272 --*/ 1273 { 1274 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1275 NTSTATUS status; 1276 FxRequest *pRequest; 1277 UCHAR majorFunction; 1278 FxDevice* pDevice; 1279 1280 // 1281 // Validate the request handle, and get the FxRequest* 1282 // 1283 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1284 Request, 1285 FX_TYPE_REQUEST, 1286 (PVOID*)&pRequest, 1287 &pFxDriverGlobals); 1288 1289 #if FX_VERBOSE_TRACE 1290 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1291 "Enter: WDREQUEST 0x%p", Request); 1292 #endif // FX_VERBOSE_TRACE 1293 1294 FxPointerNotNull(pFxDriverGlobals, InputBuffer); 1295 *InputBuffer = NULL; 1296 1297 if (Length != NULL) { 1298 *Length = 0; 1299 } 1300 1301 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 1302 if (!NT_SUCCESS(status)) { 1303 return status; 1304 } 1305 1306 // 1307 // Make sure this function is called in the context of in-process callback 1308 // 1309 if (pFxDriverGlobals->FxVerifierOn) { 1310 KIRQL irql; 1311 1312 pRequest->Lock(&irql); 1313 1314 status = pRequest->VerifyRequestIsInCallerContext(pFxDriverGlobals); 1315 1316 pRequest->Unlock(irql); 1317 1318 if (!NT_SUCCESS(status)) { 1319 return status; 1320 } 1321 } 1322 1323 FxIrp* irp = pRequest->GetFxIrp(); 1324 1325 pDevice = FxDevice::GetFxDevice(irp->GetDeviceObject()); 1326 1327 // 1328 // This call is not valid on Read request. 1329 // 1330 majorFunction = irp->GetMajorFunction(); 1331 1332 if (majorFunction == IRP_MJ_READ) { 1333 status = STATUS_INVALID_DEVICE_REQUEST; 1334 1335 DoTraceLevelMessage( 1336 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1337 "This call is not valid on read request, you should call" 1338 " WdfRequestRetrieveUnsafeUserOutputBuffer to get the buffer for " 1339 "WDFREQUEST 0x%p, %!STATUS!", Request, status); 1340 1341 return status; 1342 } 1343 1344 if (majorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) { 1345 status = STATUS_INVALID_DEVICE_REQUEST; 1346 1347 DoTraceLevelMessage( 1348 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1349 "This call is not valid on internal-ioctl request, you should call" 1350 " safer WdfRequestRetrieveInputBuffer to get the buffer for " 1351 "WDFREQUEST 0x%p, %!STATUS!", Request, status); 1352 1353 return status; 1354 } 1355 1356 if (majorFunction == IRP_MJ_DEVICE_CONTROL && 1357 irp->GetParameterIoctlCodeBufferMethod() == METHOD_NEITHER) { 1358 1359 if (irp->GetParameterIoctlInputBufferLength() < RequiredLength) { 1360 status = STATUS_BUFFER_TOO_SMALL; 1361 1362 DoTraceLevelMessage( 1363 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1364 "WDFREQUEST %p buffer size %d is less than RequiredLength %I64d," 1365 " %!STATUS!", 1366 Request, irp->GetParameterIoctlInputBufferLength(), 1367 RequiredLength, status); 1368 1369 return status; 1370 } 1371 1372 *InputBuffer = irp->GetParameterIoctlType3InputBuffer(); 1373 if (Length != NULL) { 1374 *Length = irp->GetParameterIoctlInputBufferLength(); 1375 } 1376 1377 return STATUS_SUCCESS; 1378 1379 } 1380 else if (majorFunction == IRP_MJ_WRITE && 1381 pDevice->GetIoType() == WdfDeviceIoNeither) { 1382 1383 if (irp->GetParameterWriteLength() < RequiredLength) { 1384 status = STATUS_BUFFER_TOO_SMALL; 1385 1386 DoTraceLevelMessage( 1387 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1388 "WDFREQUEST 0x%p buffer size %d is less than RequiredLength " 1389 "%I64d, %!STATUS!", 1390 Request, irp->GetParameterWriteLength(), RequiredLength, 1391 status); 1392 1393 return status; 1394 } 1395 1396 *InputBuffer = pRequest->GetFxIrp()->GetUserBuffer(); 1397 if (Length != NULL) { 1398 *Length = irp->GetParameterWriteLength(); 1399 } 1400 1401 return STATUS_SUCCESS; 1402 1403 } else { 1404 status = STATUS_INVALID_DEVICE_REQUEST; 1405 1406 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 1407 "Error: This call is valid only on method-neither " 1408 "ioctl and write WDFREQUEST %p, %!STATUS!", 1409 Request, status); 1410 FxVerifierDbgBreakPoint(pFxDriverGlobals); 1411 1412 return status; 1413 } 1414 1415 // NOTREACHED 1416 } 1417 1418 _Must_inspect_result_ 1419 __drv_maxIRQL(PASSIVE_LEVEL) 1420 NTSTATUS 1421 WDFAPI 1422 STDCALL 1423 WDFEXPORT(WdfRequestRetrieveUnsafeUserOutputBuffer)( 1424 __in 1425 PWDF_DRIVER_GLOBALS DriverGlobals, 1426 __in 1427 WDFREQUEST Request, 1428 __in 1429 size_t RequiredLength, 1430 __deref_out_bcount_opt(*Length) 1431 PVOID* OutputBuffer, 1432 __out_opt 1433 size_t* Length 1434 ) 1435 /*++ 1436 1437 Routine Description: 1438 1439 Returns output buffer of a method-neither request. This function can be called only 1440 in the context of EvtDeviceIoInProcessContextCallback at PASSIVE_LEVEL. 1441 1442 This call is valid on public IOCTL and Read request. 1443 1444 The returned buffer is valid only in the caller's process context. This call should 1445 be typically used in a toplevel or monolithic driver to guarantee the caller's context. 1446 1447 1448 The Memory buffer is as follows for each type of request: 1449 1450 For IOCTL, it will return Irp->UserBuffer 1451 1452 For Read, it will return Irp->UserBuffer. 1453 1454 For Write and internal-device control and other type of request, this call will return an error. 1455 1456 1457 Arguments: 1458 1459 Request - Handle to the Request object 1460 1461 RequiredLength - minimum length of the buffer expected by the caller. If it's not 1462 this call will return an error. 1463 1464 1465 OutputBuffer - Pointer location to return buffer ptr 1466 1467 Length - actual size of the buffer. This is >= to RequiredLength 1468 1469 1470 Returns: 1471 1472 NTSTATUS 1473 1474 --*/ 1475 { 1476 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1477 NTSTATUS status; 1478 FxRequest *pRequest; 1479 UCHAR majorFunction; 1480 FxDevice* pDevice; 1481 1482 // 1483 // Validate the request handle, and get the FxRequest* 1484 // 1485 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1486 Request, 1487 FX_TYPE_REQUEST, 1488 (PVOID*)&pRequest, 1489 &pFxDriverGlobals); 1490 1491 FxPointerNotNull(pFxDriverGlobals, OutputBuffer); 1492 *OutputBuffer = NULL; 1493 1494 if (Length != NULL) { 1495 *Length = 0; 1496 } 1497 1498 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 1499 if (!NT_SUCCESS(status)) { 1500 return status; 1501 } 1502 1503 // 1504 // Make sure this function is called in the context of in-process callback 1505 // 1506 if (pFxDriverGlobals->FxVerifierOn) { 1507 KIRQL irql; 1508 1509 pRequest->Lock(&irql); 1510 1511 status = pRequest->VerifyRequestIsInCallerContext(pFxDriverGlobals); 1512 1513 pRequest->Unlock(irql); 1514 1515 if (!NT_SUCCESS(status)) { 1516 return status; 1517 } 1518 } 1519 1520 #if FX_VERBOSE_TRACE 1521 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1522 "Enter: WDFREQUEST 0x%p", pRequest); 1523 #endif // FX_VERBOSE_TRACE 1524 1525 FxIrp* irp = pRequest->GetFxIrp(); 1526 pDevice = FxDevice::GetFxDevice(irp->GetDeviceObject()); 1527 1528 // 1529 // This call is not valid on Write request. 1530 // 1531 majorFunction = irp->GetMajorFunction(); 1532 1533 if (majorFunction == IRP_MJ_WRITE) { 1534 status = STATUS_INVALID_DEVICE_REQUEST; 1535 1536 DoTraceLevelMessage( 1537 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1538 "This call is not valid on Write request, you should call" 1539 " WdfRequestRetrieveUnsafeUserInputBuffer to get the buffer for " 1540 "WDFREQUEST 0x%p, %!STATUS!", Request, status); 1541 1542 return status; 1543 1544 } 1545 1546 if (majorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) { 1547 status = STATUS_INVALID_DEVICE_REQUEST; 1548 1549 DoTraceLevelMessage( 1550 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1551 "This call is not valid on an internal IOCTL request, you should call" 1552 " safer WdfRequestRetrieveOutputBuffer to get the buffer for " 1553 "WDFREQUEST 0x%p, %!STATUS!", Request, status); 1554 1555 return status; 1556 } 1557 1558 if (majorFunction == IRP_MJ_DEVICE_CONTROL && 1559 irp->GetParameterIoctlCodeBufferMethod() == METHOD_NEITHER) { 1560 1561 if (irp->GetParameterIoctlOutputBufferLength() < RequiredLength) { 1562 status = STATUS_BUFFER_TOO_SMALL; 1563 1564 DoTraceLevelMessage( 1565 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1566 "WDFREQUEST 0x%p buffer size %d is less than RequiredLength " 1567 "%I64d, %!STATUS!", 1568 Request, irp->GetParameterIoctlOutputBufferLength(), 1569 RequiredLength, status); 1570 1571 return status; 1572 } 1573 1574 *OutputBuffer = pRequest->GetFxIrp()->GetUserBuffer(); 1575 1576 if (Length != NULL) { 1577 *Length = irp->GetParameterIoctlOutputBufferLength(); 1578 } 1579 1580 return STATUS_SUCCESS; 1581 1582 } else if (majorFunction == IRP_MJ_READ && 1583 pDevice->GetIoType() == WdfDeviceIoNeither) { 1584 1585 if (irp->GetParameterReadLength() < RequiredLength) { 1586 status = STATUS_BUFFER_TOO_SMALL; 1587 1588 DoTraceLevelMessage( 1589 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1590 "WDFREQUEST 0x%p buffer size %d is less than RequiredLength " 1591 "%I64d, %!STATUS!", 1592 Request, irp->GetParameterReadLength(), RequiredLength, 1593 status); 1594 1595 return status; 1596 } 1597 1598 *OutputBuffer = pRequest->GetFxIrp()->GetUserBuffer(); 1599 if (Length != NULL) { 1600 *Length = irp->GetParameterReadLength(); 1601 } 1602 1603 return STATUS_SUCCESS; 1604 1605 } else { 1606 status = STATUS_INVALID_DEVICE_REQUEST; 1607 1608 DoTraceLevelMessage( 1609 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 1610 "Error: This call is valid only on method-neither ioctl and read " 1611 "WDFREQUEST 0x%p, %!STATUS!", Request, status); 1612 1613 return status; 1614 } 1615 1616 // NOTREACHED 1617 } 1618 1619 1620 _Must_inspect_result_ 1621 __drv_maxIRQL(DISPATCH_LEVEL) 1622 NTSTATUS 1623 WDFAPI 1624 STDCALL 1625 WDFEXPORT(WdfRequestRetrieveInputWdmMdl)( 1626 __in 1627 PWDF_DRIVER_GLOBALS DriverGlobals, 1628 __in 1629 WDFREQUEST Request, 1630 __deref_out 1631 PMDL *Mdl 1632 ) 1633 1634 /*++ 1635 1636 Routine Description: 1637 1638 Return the MDL associated with the request. 1639 1640 The MDL is automatically released when the request is completed. 1641 1642 The MDL's access permissions are validated according 1643 to the command type (IRP_MJ_READ, IRP_MJ_WRITE), and may 1644 only be accessed according to the access semantics of the request. 1645 1646 The MDL is not valid for a METHOD_NEITHER IRP_MJ_DEVICE_CONTROL, 1647 or if neither of the DO_BUFFERED_IO or DO_DIRECT_IO flags are 1648 configured for the device object. 1649 1650 The MDL is as follows for each buffering mode: 1651 1652 DO_BUFFERED_IO: 1653 1654 MmBuildMdlForNonPagedPool(IoAllocateMdl(Irp->AssociatedIrp.SystemBuffer, ... )) 1655 1656 DO_DIRECT_IO: 1657 1658 Irp->MdlAddress 1659 1660 NEITHER flag set: 1661 1662 NULL. Must use WdfDeviceInitSetIoInCallerContextCallback in order 1663 to access the request in the calling threads address space before 1664 it is placed into any I/O Queues. 1665 1666 The MDL is only valid until the request is completed. 1667 1668 Arguments: 1669 1670 Request - Handle to the Request object 1671 1672 Mdl - Pointer location to return MDL ptr 1673 1674 Returns: 1675 1676 NTSTATUS 1677 1678 --*/ 1679 1680 { 1681 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1682 NTSTATUS status; 1683 FxRequest *pRequest; 1684 1685 // 1686 // Validate the request handle, and get the FxRequest* 1687 // 1688 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1689 Request, 1690 FX_TYPE_REQUEST, 1691 (PVOID*)&pRequest, 1692 &pFxDriverGlobals); 1693 1694 FxPointerNotNull(pFxDriverGlobals, Mdl); 1695 *Mdl = NULL; 1696 1697 #if FX_VERBOSE_TRACE 1698 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1699 "Enter: WDFREQUEST 0x%p", Request); 1700 #endif // FX_VERBOSE_TRACE 1701 1702 // 1703 // This call is not valid on Read request. 1704 // 1705 if (pRequest->GetFxIrp()->GetMajorFunction() == IRP_MJ_READ) { 1706 DoTraceLevelMessage( 1707 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1708 "This call is not valid on the Read request, you should call" 1709 " WdfRequestRetrieveOutputMdl to get the Mdl for WFDREQUEST 0x%p, " 1710 " %!STATUS!", Request, STATUS_INVALID_DEVICE_REQUEST); 1711 1712 return STATUS_INVALID_DEVICE_REQUEST; 1713 } 1714 1715 status = pRequest->GetMdl(Mdl); 1716 1717 return status; 1718 } 1719 1720 _Must_inspect_result_ 1721 __drv_maxIRQL(DISPATCH_LEVEL) 1722 NTSTATUS 1723 WDFAPI 1724 STDCALL 1725 WDFEXPORT(WdfRequestRetrieveOutputWdmMdl)( 1726 __in 1727 PWDF_DRIVER_GLOBALS DriverGlobals, 1728 __in 1729 WDFREQUEST Request, 1730 __deref_out 1731 PMDL *Mdl 1732 ) 1733 1734 /*++ 1735 1736 Routine Description: 1737 1738 Return the MDL associated with the request. 1739 1740 The MDL is automatically released when the request is completed. 1741 1742 The MDL's access permissions are validated according 1743 to the command type (IRP_MJ_READ, IRP_MJ_WRITE), and may 1744 only be accessed according to the access semantics of the request. 1745 1746 The MDL is not valid for a METHOD_NEITHER IRP_MJ_DEVICE_CONTROL, 1747 or if neither of the DO_BUFFERED_IO or DO_DIRECT_IO flags are 1748 configured for the device object. 1749 1750 The MDL is as follows for each buffering mode: 1751 1752 DO_BUFFERED_IO: 1753 1754 MmBuildMdlForNonPagedPool(IoAllocateMdl(Irp->AssociatedIrp.SystemBuffer, ... )) 1755 1756 DO_DIRECT_IO: 1757 1758 Irp->MdlAddress 1759 1760 NEITHER flag set: 1761 1762 NULL. Must use WdfDeviceInitSetIoInCallerContextCallback in order 1763 to access the request in the calling threads address space before 1764 it is placed into any I/O Queues. 1765 1766 The MDL is only valid until the request is completed. 1767 1768 Arguments: 1769 1770 Request - Handle to the Request object 1771 1772 Mdl - Pointer location to return MDL ptr 1773 1774 Returns: 1775 1776 NTSTATUS 1777 1778 --*/ 1779 1780 { 1781 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1782 NTSTATUS status; 1783 FxRequest *pRequest; 1784 UCHAR majorFunction; 1785 1786 // 1787 // Validate the request handle, and get the FxRequest* 1788 // 1789 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1790 Request, 1791 FX_TYPE_REQUEST, 1792 (PVOID*)&pRequest, 1793 &pFxDriverGlobals); 1794 1795 FxPointerNotNull(pFxDriverGlobals, Mdl); 1796 *Mdl = NULL; 1797 1798 #if FX_VERBOSE_TRACE 1799 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1800 "Enter: WDFREQUEST 0x%p", Request); 1801 #endif // FX_VERBOSE_TRACE 1802 1803 // 1804 // This call is not valid on Write request. 1805 // 1806 majorFunction = pRequest->GetFxIrp()->GetMajorFunction(); 1807 if (majorFunction == IRP_MJ_WRITE) { 1808 DoTraceLevelMessage( 1809 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1810 "This call is not valid on the Write request, you should call" 1811 " WdfRequestRetrieveInputMemory to get the Memory for WDFREQUEST 0x%p, " 1812 "%!STATUS!",Request, STATUS_INVALID_DEVICE_REQUEST); 1813 1814 return STATUS_INVALID_DEVICE_REQUEST; 1815 } 1816 1817 if( (majorFunction == IRP_MJ_DEVICE_CONTROL) || 1818 (majorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) ) { 1819 status = pRequest->GetDeviceControlOutputMdl(Mdl); 1820 } 1821 else { 1822 status = pRequest->GetMdl(Mdl); 1823 } 1824 1825 return status; 1826 } 1827 1828 void 1829 CheckUnionAssumptions( 1830 VOID 1831 ) 1832 /*++ 1833 1834 Routine Description: 1835 Make sure our assumptions about using the passed in parameters as locals 1836 does not exceed the space allocated on the stack for the passed in variables, 1837 otherwise we could corrupt the stack. 1838 1839 *DO NOT REMOVE* this function even though no code calls it. Because it uses 1840 WDFCASSERT, if our assumptions were false, it would not compile. 1841 1842 Arguments: 1843 None. 1844 1845 Return Value: 1846 None 1847 1848 --*/ 1849 { 1850 // ActionUnion check 1851 WDFCASSERT(sizeof(ULONG) <= sizeof(PWDF_DRIVER_GLOBALS)); 1852 // RequestUnion check 1853 WDFCASSERT(sizeof(FxRequest*) <= sizeof(WDFREQUEST)); 1854 // TargetUnion check 1855 WDFCASSERT(sizeof(FxIoTarget*) <= sizeof(WDFIOTARGET)); 1856 } 1857 1858 #define GLOBALS_ACTION(globals) ((ULONG)(ULONG_PTR)(globals)) 1859 #define PGLOBALS_ACTION(globals) ((PULONG)(PULONG_PTR)(globals)) 1860 1861 #define GLOBALS_DEVICE(globals) ((FxDevice*)(ULONG_PTR)(globals)) 1862 #define PGLOBALS_DEVICE(globals) ((FxDevice**)(PULONG_PTR)(globals)) 1863 1864 #define WDFREQUEST_FXREQUEST(handle) ((FxRequest*)(handle)) 1865 #define WDFIOTARGET_FXIOTARGET(handle) ((FxIoTarget*)(handle)) 1866 1867 _Must_inspect_result_ 1868 __drv_maxIRQL(DISPATCH_LEVEL) 1869 BOOLEAN 1870 STDCALL 1871 WDFEXPORT(WdfRequestSend)( 1872 __in 1873 PWDF_DRIVER_GLOBALS DriverGlobals, 1874 __in 1875 WDFREQUEST Request, 1876 __in 1877 WDFIOTARGET Target, 1878 __in_opt 1879 PWDF_REQUEST_SEND_OPTIONS Options 1880 ) 1881 /*++ 1882 1883 Routine Description: 1884 Sends a previously created and formatted request to the target device 1885 object. The target device object will typically be the device object that 1886 this device is attached to. The submission can also be controlled by a set 1887 of options. 1888 1889 Arguments: 1890 Request - The request to be submitted 1891 1892 Target - The target of the request 1893 1894 Options - Optional options applied to the sending of the request 1895 1896 In the aggressive attempt to conserve stack space, the passed in parameters 1897 are unionized with the locals this function would need. On an optimized 1898 build, the compiler may already do this, but we want to be extra aggressive 1899 and ensure that this type of stack reuse is done. 1900 1901 Return Value: 1902 TRUE if the request was sent to the target, FALSE otherwise. 1903 1904 To retrieve the status of the request, call WdfRequestGetStatus. 1905 WdfRequestGetStatus should only be called if WdfRequestSend returns FALSE 1906 or if the caller specified that the request be synchronous in 1907 WDF_REQUEST_SEND_OPTIONS. Otherwise, the request is asynchronous and the status 1908 will be returned in the request's completion routine. 1909 1910 --*/ 1911 { 1912 // 1913 // Validate the request handle, and get the FxRequest* 1914 // 1915 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 1916 Request, 1917 FX_TYPE_REQUEST, 1918 (PVOID*) &Request); 1919 1920 // 1921 // Request stack memory now holds an FxRequest pointer. 1922 // Request as a handle is no longer valid! 1923 // 1924 if (!NT_SUCCESS(FxValidateRequestOptions( 1925 WDFREQUEST_FXREQUEST(Request)->GetDriverGlobals(), 1926 Options, WDFREQUEST_FXREQUEST(Request)))) { 1927 1928 WDFREQUEST_FXREQUEST(Request)->SetStatus(STATUS_INVALID_PARAMETER); 1929 1930 FxVerifierDbgBreakPoint(WDFREQUEST_FXREQUEST(Request)->GetDriverGlobals()); 1931 return FALSE; 1932 } 1933 1934 FxObjectHandleGetPtr(WDFREQUEST_FXREQUEST(Request)->GetDriverGlobals(), 1935 Target, 1936 FX_TYPE_IO_TARGET, 1937 (PVOID*) &Target); 1938 1939 // 1940 // Target stack memory now hold an FxIoTarget pointer. 1941 // Target as a handle is no longer valid! 1942 // 1943 if (Options != NULL && 1944 (Options->Flags & (WDF_REQUEST_SEND_OPTION_SYNCHRONOUS | 1945 WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET)) != 0x0) { 1946 1947 if (Options->Flags & WDF_REQUEST_SEND_OPTION_SYNCHRONOUS) { 1948 // 1949 // This sets impersonation flags for UMDF. Noop for KMDF. 1950 // 1951 WDFREQUEST_FXREQUEST(Request)->SetImpersonationFlags(Options->Flags); 1952 1953 *PGLOBALS_ACTION(&DriverGlobals) = SubmitSyncCallCompletion; 1954 (void) WDFIOTARGET_FXIOTARGET(Target)->SubmitSync( 1955 WDFREQUEST_FXREQUEST(Request), 1956 Options, 1957 PGLOBALS_ACTION(&DriverGlobals) 1958 ); 1959 } 1960 else if (Options->Flags & WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET) { 1961 if (WDFREQUEST_FXREQUEST(Request)->IsAllocatedFromIo() == FALSE) { 1962 DoTraceLevelMessage( 1963 WDFREQUEST_FXREQUEST(Request)->GetDriverGlobals(), 1964 TRACE_LEVEL_ERROR, TRACINGIOTARGET, 1965 "WDFREQUEST %p must be a WDFQUEUE presented request", 1966 WDFREQUEST_FXREQUEST(Request)->GetHandle()); 1967 1968 WDFREQUEST_FXREQUEST(Request)->SetStatus( 1969 STATUS_INVALID_DEVICE_STATE 1970 ); 1971 1972 *PGLOBALS_ACTION(&DriverGlobals) = 0; 1973 } 1974 else if (WDFREQUEST_FXREQUEST(Request)->HasContext()) { 1975 // 1976 // Cannot send-and-forget a request with formatted IO context. 1977 // 1978 DoTraceLevelMessage( 1979 WDFREQUEST_FXREQUEST(Request)->GetDriverGlobals(), 1980 TRACE_LEVEL_ERROR, TRACINGIOTARGET, 1981 "Cannot send-and-forget WDFREQUEST 0x%p with formatted IO" 1982 " context, %!STATUS!", 1983 WDFREQUEST_FXREQUEST(Request)->GetHandle(), 1984 STATUS_INVALID_DEVICE_REQUEST ); 1985 1986 WDFREQUEST_FXREQUEST(Request)->SetStatus( 1987 STATUS_INVALID_DEVICE_REQUEST 1988 ); 1989 1990 *PGLOBALS_ACTION(&DriverGlobals) = 0; 1991 1992 FxVerifierDbgBreakPoint( 1993 WDFREQUEST_FXREQUEST(Request)->GetDriverGlobals()); 1994 } 1995 else { 1996 // 1997 // We split processing into pre and post processing to reduce 1998 // stack usage (by not making the call to IoCallDriver in a 1999 // deep function. 2000 // 2001 2002 // 2003 // This will skip the current stack location 2004 // 2005 WDFREQUEST_FXREQUEST(Request)->PreProcessSendAndForget(); 2006 2007 // 2008 // This sets impersonation flags for UMDF. Noop for KMDF. 2009 // 2010 WDFREQUEST_FXREQUEST(Request)->SetImpersonationFlags(Options->Flags); 2011 2012 MdIrp submitIrp = WDFREQUEST_FXREQUEST(Request)->GetSubmitIrp(); 2013 2014 WDFIOTARGET_FXIOTARGET(Target)->Send(submitIrp); 2015 2016 // 2017 // This will free the request memory and pop the queue 2018 // 2019 WDFREQUEST_FXREQUEST(Request)->PostProcessSendAndForget(); 2020 return TRUE; 2021 } 2022 } 2023 } 2024 else if (WDFREQUEST_FXREQUEST(Request)->IsCompletionRoutineSet() == FALSE && 2025 WDFREQUEST_FXREQUEST(Request)->IsAllocatedFromIo()) { 2026 // 2027 // Cannot send an asynchronous queue presented request without a 2028 // completion routine. 2029 // 2030 DoTraceLevelMessage( 2031 WDFREQUEST_FXREQUEST(Request)->GetDriverGlobals(), 2032 TRACE_LEVEL_ERROR, TRACINGIOTARGET, 2033 "WDFREQUEST %p is a WDFQUEUE presented request with no" 2034 " completion routine, %!STATUS!", 2035 WDFREQUEST_FXREQUEST(Request)->GetHandle(), 2036 STATUS_INVALID_DEVICE_REQUEST ); 2037 2038 WDFREQUEST_FXREQUEST(Request)->SetStatus( 2039 STATUS_INVALID_DEVICE_REQUEST 2040 ); 2041 2042 *PGLOBALS_ACTION(&DriverGlobals) = 0; 2043 2044 FxVerifierDbgBreakPoint( 2045 WDFREQUEST_FXREQUEST(Request)->GetDriverGlobals()); 2046 } 2047 else { 2048 #if FX_VERBOSE_TRACE 2049 DoTraceLevelMessage( 2050 WDFREQUEST_FXREQUEST(Request)->GetDriverGlobals(), 2051 TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, 2052 "Enter: WDFIOTARGET %p, WDFREQUEST %p", 2053 WDFIOTARGET_FXIOTARGET(Target)->GetObjectHandle(), 2054 WDFREQUEST_FXREQUEST(Request)); 2055 #endif // FX_VERBOSE_TRACE 2056 2057 // 2058 // This sets impersonation flags for UMDF. Noop for KMDF. 2059 // 2060 if (Options != NULL) { 2061 WDFREQUEST_FXREQUEST(Request)->SetImpersonationFlags(Options->Flags); 2062 } 2063 2064 // 2065 // Submit will return whether the request should be sent *right now*. 2066 // If SubmitSend is clear, then SubmitQueued must be checked. If set, 2067 // then the request was queued, otherwise, the request has failed. 2068 // 2069 // NOTE: by calling FxIoTarget::Submit instead of acquiring the lock 2070 // in this call frame, we don't have expend stack space for the KIRQL 2071 // storage 2072 // 2073 *PGLOBALS_ACTION(&DriverGlobals) = 2074 WDFIOTARGET_FXIOTARGET(Target)->Submit( 2075 WDFREQUEST_FXREQUEST(Request), 2076 Options, 2077 (Options != NULL) ? Options->Flags : 0 2078 ); 2079 2080 // DriverGlobals stack memory now hold a ULONG action value. 2081 // DriverGlobals as a pointer is no longer valid! 2082 2083 #if FX_VERBOSE_TRACE 2084 DoTraceLevelMessage( 2085 WDFIOTARGET_FXIOTARGET(Target)->GetDriverGlobals(), 2086 TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, 2087 "action 0x%x", GLOBALS_ACTION(DriverGlobals)); 2088 #endif // FX_VERBOSE_TRACE 2089 2090 if (GLOBALS_ACTION(DriverGlobals) & SubmitSend) { 2091 2092 *PGLOBALS_ACTION(&DriverGlobals) |= SubmitSent; 2093 2094 ASSERT((GLOBALS_ACTION(DriverGlobals) & SubmitQueued) == 0); 2095 2096 #if FX_VERBOSE_TRACE 2097 DoTraceLevelMessage( 2098 WDFREQUEST_FXREQUEST(Request)->GetDriverGlobals(), 2099 TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, 2100 "Sending FxRequest %p (WDFREQUEST %p), Irp %p", 2101 WDFREQUEST_FXREQUEST(Request), 2102 WDFREQUEST_FXREQUEST(Request)->GetHandle(), 2103 WDFREQUEST_FXREQUEST(Request)->GetSubmitIrp()); 2104 #endif // FX_VERBOSE_TRACE 2105 2106 MdIrp submitIrp = WDFREQUEST_FXREQUEST(Request)->GetSubmitIrp(); 2107 2108 WDFIOTARGET_FXIOTARGET(Target)->Send(submitIrp); 2109 } 2110 else if (GLOBALS_ACTION(DriverGlobals) & SubmitQueued) { 2111 // 2112 // To the caller, we saw and sent the request (and all the cancel 2113 // semantics of a sent request still work). 2114 // 2115 *(PGLOBALS_ACTION(&DriverGlobals)) |= SubmitSent; 2116 } 2117 } 2118 2119 return (GLOBALS_ACTION(DriverGlobals) & SubmitSent) ? TRUE : FALSE; 2120 } 2121 2122 _Must_inspect_result_ 2123 __drv_maxIRQL(DISPATCH_LEVEL) 2124 NTSTATUS 2125 STDCALL 2126 WDFEXPORT(WdfRequestGetStatus)( 2127 __in 2128 PWDF_DRIVER_GLOBALS DriverGlobals, 2129 __in 2130 WDFREQUEST Request 2131 ) 2132 { 2133 FxRequest* pRequest; 2134 2135 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 2136 Request, 2137 FX_TYPE_REQUEST, 2138 (PVOID*)&pRequest); 2139 2140 return pRequest->GetStatus(); 2141 } 2142 2143 __drv_maxIRQL(DISPATCH_LEVEL) 2144 BOOLEAN 2145 WDFAPI 2146 STDCALL 2147 WDFEXPORT(WdfRequestCancelSentRequest)( 2148 __in 2149 PWDF_DRIVER_GLOBALS DriverGlobals, 2150 __in 2151 WDFREQUEST Request 2152 ) 2153 2154 /*++ 2155 2156 Routine Description: 2157 Cancels a previously submitted request. 2158 2159 Arguments: 2160 Request - The previously submitted request 2161 2162 Return Value: 2163 TRUE if the cancel was *attempted*. The caller must still synchronize with 2164 the request's completion routine since TRUE just means the owner of the 2165 request was successfully asked to cancel the request. 2166 2167 --*/ 2168 2169 { 2170 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2171 FxRequest *pRequest; 2172 BOOLEAN result; 2173 2174 // 2175 // Validate the request handle, and get the FxRequest* 2176 // 2177 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 2178 Request, 2179 FX_TYPE_REQUEST, 2180 (PVOID*)&pRequest, 2181 &pFxDriverGlobals); 2182 2183 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 2184 "Enter: WDFREQUEST %p to be cancelled", Request); 2185 2186 result = pRequest->Cancel(); 2187 2188 #if FX_VERBOSE_TRACE 2189 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 2190 "Exit: WDFREQUEST %p, result %d", Request, result); 2191 #endif // FX_VERBOSE_TRACE 2192 2193 return result; 2194 } 2195 2196 _Must_inspect_result_ 2197 __drv_maxIRQL(APC_LEVEL) 2198 BOOLEAN 2199 STDCALL 2200 WDFEXPORT(WdfRequestIsFrom32BitProcess)( 2201 __in 2202 PWDF_DRIVER_GLOBALS DriverGlobals, 2203 __in 2204 WDFREQUEST Request 2205 ) 2206 /*++ 2207 2208 Routine Description: 2209 Indicates to the caller if the I/O request originated in a 32 bit process 2210 or not. On 32 bit systems, this function always returns TRUE. 2211 2212 Arguments: 2213 Request - The request being queried 2214 2215 Return Value: 2216 TRUE if the request came from a 32 bit process, FALSE otherwise. 2217 2218 --*/ 2219 2220 { 2221 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2222 FxRequest* pRequest; 2223 BOOLEAN result; 2224 2225 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 2226 Request, 2227 FX_TYPE_REQUEST, 2228 (PVOID*) &pRequest, 2229 &pFxDriverGlobals); 2230 2231 result = pRequest->GetFxIrp()->Is32bitProcess(); 2232 2233 #if FX_VERBOSE_TRACE 2234 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 2235 "Enter: WDFREQUEST %p is from 32 bit process = %d", 2236 Request, result); 2237 #endif // FX_VERBOSE_TRACE 2238 2239 return result; 2240 } 2241 2242 __drv_maxIRQL(DISPATCH_LEVEL) 2243 2244 VOID 2245 STDCALL 2246 WDFEXPORT(WdfRequestFormatRequestUsingCurrentType)( 2247 __in 2248 PWDF_DRIVER_GLOBALS DriverGlobals, 2249 __in 2250 WDFREQUEST Request 2251 ) 2252 /*++ 2253 2254 Routine Description: 2255 Copies the current Irp stack location to the next one. This is the 2256 equivalent of IoCopyCurrentIrpStackLocationToNext. 2257 2258 Arguments: 2259 Request - The request that will be formatted. 2260 2261 Return Value: 2262 None 2263 2264 --*/ 2265 2266 { 2267 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2268 FxRequest *pRequest; 2269 FxIrp* irp; 2270 2271 // 2272 // Validate the request handle, and get the FxRequest* 2273 // 2274 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 2275 Request, 2276 FX_TYPE_REQUEST, 2277 (PVOID*)&pRequest, 2278 &pFxDriverGlobals); 2279 2280 #if FX_VERBOSE_TRACE 2281 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 2282 "Enter: WDFREQUEST %p", Request); 2283 #endif // FX_VERBOSE_TRACE 2284 2285 irp = pRequest->GetSubmitFxIrp(); 2286 2287 if (irp->GetIrp() == NULL) { 2288 FxVerifierBugCheck(pFxDriverGlobals, 2289 WDF_REQUEST_FATAL_ERROR, 2290 WDF_REQUEST_FATAL_ERROR_NULL_IRP, 2291 (ULONG_PTR) Request); 2292 return; // not reached 2293 } 2294 2295 // 2296 // 1 is the minimum for CurrentLocation. Since the next stack location is 2297 // CurrentLocation-1, the CurrentLocation must be at least 2. 2298 // 2299 if (irp->HasStack(2) == FALSE) { 2300 FxVerifierBugCheck(pFxDriverGlobals, 2301 WDF_REQUEST_FATAL_ERROR, 2302 WDF_REQUEST_FATAL_ERROR_NO_MORE_STACK_LOCATIONS, 2303 (ULONG_PTR) irp->GetIrp()); 2304 return; // not reached 2305 } 2306 2307 pRequest->m_NextStackLocationFormatted = TRUE; 2308 irp->CopyCurrentIrpStackLocationToNext(); 2309 2310 pRequest->VerifierSetFormatted(); 2311 } 2312 2313 __drv_maxIRQL(DISPATCH_LEVEL) 2314 VOID 2315 WDFAPI 2316 STDCALL 2317 WDFEXPORT(WdfRequestWdmFormatUsingStackLocation)( 2318 __in 2319 PWDF_DRIVER_GLOBALS DriverGlobals, 2320 __in 2321 WDFREQUEST Request, 2322 __in 2323 PIO_STACK_LOCATION Stack 2324 ) 2325 2326 /*++ 2327 2328 Routine Description: 2329 Sets the next IRP stack location to the one provided by the caller. The 2330 Context and CompletionRoutine values will be ignored. If the caller wants 2331 to set a completion routine, WdfRequestSetCompletionRoutine should be used 2332 instead. 2333 2334 Arguments: 2335 Request - The request to be formatted 2336 2337 Stack - A pointer to an IO_STACK_LOCATION structure that contains 2338 driver-supplied information 2339 2340 Return Value: 2341 None. 2342 2343 --*/ 2344 2345 { 2346 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2347 FxRequest *pRequest; 2348 FxIrp* pIrp; 2349 2350 // 2351 // Validate the request handle, and get the FxRequest* 2352 // 2353 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 2354 Request, 2355 FX_TYPE_REQUEST, 2356 (PVOID*)&pRequest, 2357 &pFxDriverGlobals); 2358 2359 FxPointerNotNull(pFxDriverGlobals, Stack); 2360 2361 #if FX_VERBOSE_TRACE 2362 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 2363 "Enter: WDFREQUEST %p", Request); 2364 #endif // FX_VERBOSE_TRACE 2365 2366 pIrp = pRequest->GetSubmitFxIrp(); 2367 2368 if (pIrp == NULL) { 2369 FxVerifierBugCheck(pFxDriverGlobals, 2370 WDF_REQUEST_FATAL_ERROR, 2371 WDF_REQUEST_FATAL_ERROR_NULL_IRP, 2372 (ULONG_PTR) Request); 2373 return; // not reached 2374 } 2375 2376 // 2377 // 1 is the minimum for CurrentLocation. Since the next stack location is 2378 // CurrentLocation-1, the CurrentLocation must be at least 2. 2379 // 2380 if (pIrp->GetCurrentIrpStackLocationIndex() < 2) { 2381 FxVerifierBugCheck(pFxDriverGlobals, 2382 WDF_REQUEST_FATAL_ERROR, 2383 WDF_REQUEST_FATAL_ERROR_NO_MORE_STACK_LOCATIONS, 2384 (ULONG_PTR) pIrp); 2385 return; // not reached 2386 } 2387 2388 pRequest->m_NextStackLocationFormatted = TRUE; 2389 pIrp->CopyToNextIrpStackLocation(Stack); 2390 2391 pRequest->VerifierSetFormatted(); 2392 } 2393 2394 __drv_maxIRQL(DISPATCH_LEVEL) 2395 VOID 2396 WDFAPI 2397 STDCALL 2398 WDFEXPORT(WdfRequestSetCompletionRoutine)( 2399 __in 2400 PWDF_DRIVER_GLOBALS DriverGlobals, 2401 __in 2402 WDFREQUEST Request, 2403 __in_opt 2404 PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine, 2405 __in_opt 2406 WDFCONTEXT CompletionContext 2407 ) 2408 { 2409 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2410 FxRequest *pRequest; 2411 2412 // 2413 // Validate the request handle, and get the FxRequest* 2414 // 2415 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 2416 Request, 2417 FX_TYPE_REQUEST, 2418 (PVOID*)&pRequest, 2419 &pFxDriverGlobals); 2420 2421 #if FX_VERBOSE_TRACE 2422 DoTraceLevelMessage( 2423 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 2424 "Enter: WDFREQUEST %p, Routine %p, Context %p", 2425 Request, CompletionRoutine, CompletionContext); 2426 #endif // FX_VERBOSE_TRACE 2427 2428 pRequest->SetCompletionRoutine(CompletionRoutine, CompletionContext); 2429 2430 return; 2431 } 2432 2433 __drv_maxIRQL(DISPATCH_LEVEL) 2434 VOID 2435 WDFAPI 2436 STDCALL 2437 WDFEXPORT(WdfRequestGetParameters)( 2438 __in 2439 PWDF_DRIVER_GLOBALS DriverGlobals, 2440 __in 2441 WDFREQUEST Request, 2442 __out 2443 PWDF_REQUEST_PARAMETERS Parameters 2444 ) 2445 { 2446 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2447 FxRequest *pRequest; 2448 2449 // 2450 // Validate the request handle, and get the FxRequest* 2451 // 2452 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 2453 Request, 2454 FX_TYPE_REQUEST, 2455 (PVOID*)&pRequest, 2456 &pFxDriverGlobals); 2457 2458 FxPointerNotNull(pFxDriverGlobals, Parameters); 2459 2460 #if FX_VERBOSE_TRACE 2461 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 2462 "Enter: Request %p, Parameters %p", Request, Parameters); 2463 #endif // FX_VERBOSE_TRACE 2464 2465 if (Parameters->Size != sizeof(WDF_REQUEST_PARAMETERS)) { 2466 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2467 "Params size %d incorrect, expected %d", 2468 Parameters->Size, sizeof(WDF_REQUEST_PARAMETERS)); 2469 2470 FxVerifierDbgBreakPoint(pFxDriverGlobals); 2471 2472 return; 2473 } 2474 2475 2476 2477 2478 (VOID) pRequest->GetParameters(Parameters); 2479 2480 return; 2481 } 2482 2483 __drv_maxIRQL(DISPATCH_LEVEL) 2484 VOID 2485 WDFAPI 2486 STDCALL 2487 WDFEXPORT(WdfRequestGetCompletionParams)( 2488 __in 2489 PWDF_DRIVER_GLOBALS DriverGlobals, 2490 __in 2491 WDFREQUEST Request, 2492 __out 2493 PWDF_REQUEST_COMPLETION_PARAMS Params 2494 ) 2495 { 2496 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2497 FxRequest *pRequest; 2498 2499 // 2500 // Validate the request handle, and get the FxRequest* 2501 // 2502 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 2503 Request, 2504 FX_TYPE_REQUEST, 2505 (PVOID*)&pRequest, 2506 &pFxDriverGlobals); 2507 2508 #if FX_VERBOSE_TRACE 2509 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 2510 "Enter: WDFREQUEST %p, Params %p", Request, Params); 2511 #endif // FX_VERBOSE_TRACE 2512 2513 FxPointerNotNull(pFxDriverGlobals, Params); 2514 2515 if (Params->Size != sizeof(WDF_REQUEST_COMPLETION_PARAMS)) { 2516 DoTraceLevelMessage( 2517 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2518 "Params Size 0x%x, expected 0x%x", 2519 Params->Size, sizeof(WDF_REQUEST_COMPLETION_PARAMS)); 2520 FxVerifierDbgBreakPoint(pFxDriverGlobals); 2521 return; 2522 } 2523 2524 pRequest->CopyCompletionParams(Params); 2525 2526 return; 2527 2528 } 2529 2530 __drv_maxIRQL(DISPATCH_LEVEL) 2531 MdIrp 2532 WDFAPI 2533 STDCALL 2534 WDFEXPORT(WdfRequestWdmGetIrp)( 2535 __in 2536 PWDF_DRIVER_GLOBALS DriverGlobals, 2537 __in 2538 WDFREQUEST Request 2539 ) 2540 2541 /*++ 2542 2543 Routine Description: 2544 2545 This routine returns the WDM IRP associated with the given 2546 request. 2547 2548 The WDM IRP is invalid once WdfRequestComplete is called, regardless 2549 of any reference counts on the WDFREQUEST object. 2550 2551 Arguments: 2552 2553 Request - Handle to the Request object 2554 2555 Returns: 2556 2557 PIRP 2558 2559 --*/ 2560 2561 { 2562 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2563 NTSTATUS status; 2564 FxRequest *pRequest; 2565 MdIrp irp; 2566 2567 // 2568 // Validate the request handle, and get the FxRequest* 2569 // 2570 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 2571 Request, 2572 FX_TYPE_REQUEST, 2573 (PVOID*)&pRequest, 2574 &pFxDriverGlobals); 2575 2576 #if FX_VERBOSE_TRACE 2577 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 2578 "Enter: WDFREQUEST 0x%p", Request); 2579 #endif // FX_VERBOSE_TRACE 2580 2581 status = pRequest->GetIrp(&irp); 2582 2583 if (!NT_SUCCESS(status)) { 2584 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2585 "WDFREQUEST is already completed 0x%p, %!STATUS!", 2586 Request, status); 2587 FxVerifierDbgBreakPoint(pFxDriverGlobals); 2588 return NULL; 2589 } 2590 2591 return irp; 2592 } 2593 2594 _Must_inspect_result_ 2595 __drv_maxIRQL(DISPATCH_LEVEL) 2596 NTSTATUS 2597 WDFAPI 2598 STDCALL 2599 WDFEXPORT(WdfRequestAllocateTimer)( 2600 __in 2601 PWDF_DRIVER_GLOBALS DriverGlobals, 2602 __in 2603 WDFREQUEST Request 2604 ) 2605 /*++ 2606 2607 Routine Description: 2608 Preallocates a timer to be associated with the passed in request object. 2609 By preallocating the timer, WdfSendRequest cannot fail with insufficient 2610 resources when attempting to allocate a timer when a timeout constraint has 2611 been passed in. 2612 2613 If the request already has a timer allocated for it, then the function will 2614 succeed. 2615 2616 Arguments: 2617 Request - the request to allocate a timer for 2618 2619 Return Value: 2620 NT_SUCCESS upon success, STATUS_INSUFFICIENT_RESOURCES upon failure 2621 2622 --*/ 2623 2624 { 2625 FxRequest* pRequest; 2626 2627 // 2628 // Validate the request handle, and get the FxRequest* 2629 // 2630 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 2631 Request, 2632 FX_TYPE_REQUEST, 2633 (PVOID*)&pRequest); 2634 2635 return pRequest->CreateTimer(); 2636 } 2637 2638 __drv_maxIRQL(DISPATCH_LEVEL) 2639 WDFFILEOBJECT 2640 WDFAPI 2641 STDCALL 2642 WDFEXPORT(WdfRequestGetFileObject)( 2643 __in 2644 PWDF_DRIVER_GLOBALS DriverGlobals, 2645 __in 2646 WDFREQUEST Request 2647 ) 2648 2649 /*++ 2650 2651 Routine Description: 2652 2653 This routine returns the WDFFILEOBJECT associated with the given 2654 request. 2655 2656 Arguments: 2657 2658 Request - Handle to the Request object 2659 2660 Returns: 2661 2662 WDFFILEOBJECT handle. 2663 2664 --*/ 2665 2666 { 2667 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2668 NTSTATUS status; 2669 FxRequest *pRequest; 2670 FxFileObject* pFO; 2671 2672 // 2673 // Validate the request handle, and get the FxRequest* 2674 // 2675 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 2676 Request, 2677 FX_TYPE_REQUEST, 2678 (PVOID*) &pRequest, 2679 &pFxDriverGlobals); 2680 2681 pFO = NULL; 2682 2683 #if FX_VERBOSE_TRACE 2684 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 2685 "Enter: WDFREQUEST 0x%p", Request); 2686 #endif // FX_VERBOSE_TRACE 2687 2688 if (pRequest->GetDriverGlobals()->IsVerificationEnabled( 2689 1,9, OkForDownLevel)) { 2690 KIRQL irql; 2691 2692 pRequest->Lock(&irql); 2693 status = pRequest->VerifyRequestIsDriverOwned(pFxDriverGlobals); 2694 pRequest->Unlock(irql); 2695 if (!NT_SUCCESS(status)) { 2696 return NULL; 2697 } 2698 } 2699 2700 status = pRequest->GetFileObject(&pFO); 2701 if (!NT_SUCCESS(status)) { 2702 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2703 "GetFileobject failed with %!STATUS!", status); 2704 return NULL; 2705 } 2706 else if (NULL == pFO) { 2707 // 2708 // Success and NULL file object: driver during init told us that it 2709 // knows how to handle NULL file objects. 2710 // 2711 return NULL; 2712 } 2713 2714 return pFO->GetHandle(); 2715 } 2716 2717 _Must_inspect_result_ 2718 __drv_maxIRQL(PASSIVE_LEVEL) 2719 NTSTATUS 2720 WDFAPI 2721 STDCALL 2722 WDFEXPORT(WdfRequestProbeAndLockUserBufferForRead)( 2723 __in 2724 PWDF_DRIVER_GLOBALS DriverGlobals, 2725 __in 2726 WDFREQUEST Request, 2727 __in_bcount(Length) 2728 PVOID Buffer, 2729 __in 2730 size_t Length, 2731 __out 2732 WDFMEMORY* MemoryObject 2733 ) 2734 2735 /*++ 2736 2737 Routine Description: 2738 2739 This routine probes and locks the specified user mode address into 2740 an MDL, and associates it with the WDFREQUEST object. 2741 2742 The MDL, and its associated system buffer is represented by a WDFMEMORY 2743 object. 2744 2745 The WDFMEMORY object and the MDL is automatically released when the 2746 WDFREQUEST is completed by WdfRequestComplete. 2747 2748 Arguments: 2749 2750 Request - Handle to the Request object 2751 2752 Buffer - Buffer to probe and lock into an MDL 2753 2754 Length - Length of buffer 2755 2756 MemoryObject - Location to return WDFMEMORY handle 2757 2758 Returns: 2759 2760 NTSTATUS 2761 2762 --*/ 2763 2764 { 2765 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2766 NTSTATUS status; 2767 FxRequest *pRequest; 2768 FxRequestMemory* pMemory; 2769 2770 // 2771 // Validate the request handle, and get the FxRequest* 2772 // 2773 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 2774 Request, 2775 FX_TYPE_REQUEST, 2776 (PVOID*)&pRequest, 2777 &pFxDriverGlobals); 2778 2779 FxPointerNotNull(pFxDriverGlobals, Buffer); 2780 FxPointerNotNull(pFxDriverGlobals, MemoryObject); 2781 *MemoryObject = NULL; 2782 2783 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 2784 if (!NT_SUCCESS(status)) { 2785 return status; 2786 } 2787 2788 #if FX_VERBOSE_TRACE 2789 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 2790 "Enter: WDFREQUEST 0x%p", Request); 2791 #endif // FX_VERBOSE_TRACE 2792 2793 if (pRequest->GetDriverGlobals()->IsVerificationEnabled( 2794 1,9, OkForDownLevel)) { 2795 KIRQL irql; 2796 2797 pRequest->Lock(&irql); 2798 status = pRequest->VerifyRequestIsDriverOwned(pFxDriverGlobals); 2799 pRequest->Unlock(irql); 2800 if (!NT_SUCCESS(status)) { 2801 return status; 2802 } 2803 } 2804 2805 status = pRequest->ProbeAndLockForRead(Buffer, (ULONG) Length, &pMemory); 2806 2807 if (!NT_SUCCESS(status)) { 2808 DoTraceLevelMessage( 2809 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2810 "ProbeAndLockForRead failed with %!STATUS!", status); 2811 return status; 2812 } 2813 2814 *MemoryObject = (WDFMEMORY) pMemory->GetObjectHandle(); 2815 2816 return status; 2817 } 2818 2819 _Must_inspect_result_ 2820 __drv_maxIRQL(PASSIVE_LEVEL) 2821 NTSTATUS 2822 WDFAPI 2823 STDCALL 2824 WDFEXPORT(WdfRequestProbeAndLockUserBufferForWrite)( 2825 __in 2826 PWDF_DRIVER_GLOBALS DriverGlobals, 2827 __in 2828 WDFREQUEST Request, 2829 __in_bcount(Length) 2830 PVOID Buffer, 2831 __in 2832 size_t Length, 2833 __out 2834 WDFMEMORY* MemoryObject 2835 ) 2836 2837 /*++ 2838 2839 Routine Description: 2840 2841 This routine probes and locks the specified user mode address into 2842 an MDL, and associates it with the WDFREQUEST object. 2843 2844 The MDL, and its associated system buffer is represented by a WDFMEMORY 2845 object. 2846 2847 The WDFMEMORY object and the MDL is automatically released when the 2848 WDFREQUEST is completed by WdfRequestComplete. 2849 2850 Arguments: 2851 2852 Request - Handle to the Request object 2853 2854 Buffer - Buffer to probe and lock into an MDL 2855 2856 Length - Length of buffer 2857 2858 MemoryObject - Location to return WDFMEMORY handle 2859 2860 Returns: 2861 2862 NTSTATUS 2863 2864 --*/ 2865 2866 { 2867 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2868 NTSTATUS status; 2869 FxRequest *pRequest; 2870 FxRequestMemory* pMemory; 2871 2872 // 2873 // Validate the request handle, and get the FxRequest* 2874 // 2875 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 2876 Request, 2877 FX_TYPE_REQUEST, 2878 (PVOID*)&pRequest, 2879 &pFxDriverGlobals); 2880 2881 FxPointerNotNull(pFxDriverGlobals, Buffer); 2882 FxPointerNotNull(pFxDriverGlobals, MemoryObject); 2883 2884 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 2885 if (!NT_SUCCESS(status)) { 2886 return status; 2887 } 2888 2889 #if FX_VERBOSE_TRACE 2890 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 2891 "Enter: WDFREQUEST 0x%p", Request); 2892 #endif // FX_VERBOSE_TRACE 2893 2894 if (pRequest->GetDriverGlobals()->IsVerificationEnabled( 2895 1,9, OkForDownLevel)) { 2896 KIRQL irql; 2897 2898 pRequest->Lock(&irql); 2899 status = pRequest->VerifyRequestIsDriverOwned(pFxDriverGlobals); 2900 pRequest->Unlock(irql); 2901 if (!NT_SUCCESS(status)) { 2902 return status; 2903 } 2904 } 2905 2906 status = pRequest->ProbeAndLockForWrite(Buffer, (ULONG) Length, &pMemory); 2907 if (!NT_SUCCESS(status)) { 2908 DoTraceLevelMessage( 2909 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2910 "ProbeAndLockForWrite failed with %!STATUS!", status); 2911 return status; 2912 } 2913 2914 *MemoryObject = (WDFMEMORY)pMemory->GetObjectHandle(); 2915 2916 return status; 2917 } 2918 2919 __drv_maxIRQL(DISPATCH_LEVEL) 2920 KPROCESSOR_MODE 2921 WDFAPI 2922 STDCALL 2923 WDFEXPORT(WdfRequestGetRequestorMode)( 2924 __in 2925 PWDF_DRIVER_GLOBALS DriverGlobals, 2926 __in 2927 WDFREQUEST Request 2928 ) 2929 2930 /*++ 2931 2932 Routine Description: 2933 2934 Returns the RequestorMode information from the IRP. 2935 2936 2937 Arguments: 2938 2939 Request - Handle to the Request object 2940 2941 2942 Returns: 2943 2944 KPROCESSOR_MODE is CCHAR 2945 2946 --*/ 2947 2948 { 2949 FxRequest *pRequest; 2950 2951 // 2952 // Validate the request handle, and get the FxRequest* 2953 // 2954 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 2955 Request, 2956 FX_TYPE_REQUEST, 2957 (PVOID*)&pRequest); 2958 2959 return pRequest->GetRequestorMode(); 2960 } 2961 2962 __drv_maxIRQL(DISPATCH_LEVEL) 2963 WDFQUEUE 2964 WDFAPI 2965 STDCALL 2966 WDFEXPORT(WdfRequestGetIoQueue)( 2967 __in 2968 PWDF_DRIVER_GLOBALS DriverGlobals, 2969 __in 2970 WDFREQUEST Request 2971 ) 2972 2973 /*++ 2974 2975 Routine Description: 2976 2977 Returns the queue handle that currently owns the request. 2978 2979 2980 Arguments: 2981 2982 Request - Handle to the Request object 2983 2984 2985 Returns: 2986 2987 WDFQUEUE 2988 2989 --*/ 2990 2991 { 2992 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2993 FxRequest *pRequest; 2994 2995 // 2996 // Validate the request handle, and get the FxRequest* 2997 // 2998 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 2999 Request, 3000 FX_TYPE_REQUEST, 3001 (PVOID*)&pRequest, 3002 &pFxDriverGlobals); 3003 3004 #if FX_VERBOSE_TRACE 3005 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 3006 "Enter: WDFREQUEST 0x%p", Request); 3007 #endif // FX_VERBOSE_TRACE 3008 3009 if (pRequest->GetCurrentQueue() == NULL) { 3010 // 3011 // For a driver-created request, the queue can be NULL. It is not 3012 // necessarily an error to call WdfRequestGetIoQueue on a driver- 3013 // created request, because the caller may not really know whether or 3014 // not the request is driver-created. 3015 // 3016 // For example, it is possible for a class extension to create a request 3017 // and pass it to the client driver, in which case the client driver 3018 // wouldn't really know whether or not it was driver-created. Or a 3019 // client driver is might be using a helper library for some of its 3020 // tasks and it might pass in a request object to the helper library. In 3021 // this case, the helper library wouldn't really know whether or not the 3022 // request was driver-created. Therefore, the log message below is at 3023 // verbose level and not at error or warning level. 3024 // 3025 DoTraceLevelMessage(pFxDriverGlobals, 3026 TRACE_LEVEL_VERBOSE, 3027 TRACINGREQUEST, 3028 "WDFREQUEST %p doesn't belong to any queue", 3029 Request); 3030 return NULL; 3031 } 3032 3033 if (pRequest->GetFxIrp()->GetMajorFunction() == IRP_MJ_CREATE) { 3034 // 3035 // If the queue for Create is the framework internal queue 3036 // return NULL. 3037 // 3038 FxPkgGeneral* devicePkgGeneral = pRequest->GetDevice()->m_PkgGeneral; 3039 3040 if (devicePkgGeneral->GetDeafultInternalCreateQueue() == 3041 pRequest->GetCurrentQueue()) { 3042 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO, 3043 "Getting queue handle for Create request is " 3044 "not allowed for WDFREQUEST 0x%p", pRequest); 3045 FxVerifierDbgBreakPoint(pFxDriverGlobals); 3046 return NULL; 3047 } 3048 } 3049 3050 return (WDFQUEUE) pRequest->GetCurrentQueue()->GetObjectHandle(); 3051 } 3052 3053 _Must_inspect_result_ 3054 NTSTATUS 3055 FX_VF_FUNCTION(VerifyWdfRequestForwardToIoQueue) ( 3056 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, 3057 _In_ FxRequest* request 3058 ) 3059 { 3060 NTSTATUS status = STATUS_SUCCESS; 3061 3062 PAGED_CODE_LOCKED(); 3063 3064 // 3065 // * Is request I/O allocated but without a queue? This should not happen. 3066 // * Is WDF driver v1.9 or below trying to use this feature? We don't allow it. 3067 // 3068 if (request->IsAllocatedDriver() == FALSE || 3069 FxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,11) == FALSE) { 3070 status = STATUS_INVALID_DEVICE_REQUEST; 3071 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 3072 "WDFREQUEST %p doesn't belong to any queue, %!STATUS!", 3073 request->GetHandle(), status); 3074 FxVerifierDbgBreakPoint(FxDriverGlobals); 3075 return status; 3076 } 3077 3078 // 3079 // Make sure current IRP stack location is valid. See helper routine for error msgs. 3080 // 3081 status = request->VerifyRequestCanBeCompleted(FxDriverGlobals); 3082 return status; 3083 } 3084 3085 _Must_inspect_result_ 3086 __drv_maxIRQL(DISPATCH_LEVEL) 3087 NTSTATUS 3088 STDCALL 3089 WDFEXPORT(WdfRequestForwardToIoQueue)( 3090 __in 3091 PWDF_DRIVER_GLOBALS DriverGlobals, 3092 __in 3093 WDFREQUEST Request, 3094 __in 3095 WDFQUEUE DestinationQueue 3096 ) 3097 3098 /*++ 3099 3100 Routine Description: 3101 3102 Forward a request presented on one queue to another driver 3103 managed queue. 3104 3105 A request may only be forwarded from a queues dispatch routine. 3106 3107 If the request is successfully forwarded to the DestinationQueue, it 3108 is no longer owned by the driver, but by the DestinationQueue. 3109 3110 Both the source queue and destination queue should be part of the 3111 same device. 3112 3113 The driver gets ownership of the request when it receives it 3114 from the DestinationQueue through EvtIo callback, or WdfIoQueueRetrieveNextRequest. 3115 3116 Arguments: 3117 3118 3119 Request - Request object to forward. 3120 3121 DestinationQueue - Queue that is to receive the request. 3122 3123 Returns: 3124 3125 STATUS_SUCCESS - Request was forwarded to Queue and driver no 3126 longer owns it. 3127 3128 !STATUS_SUCCESS - Request was not forwarded to the Queue, and 3129 the driver still owns the request and is responsible 3130 for either completing it, or eventually successfully 3131 forwarding it to a Queue. 3132 --*/ 3133 3134 { 3135 PFX_DRIVER_GLOBALS fxDriverGlobals; 3136 PFX_DRIVER_GLOBALS cxDriverGlobals; 3137 FxRequest* request; 3138 FxIoQueue* queue; 3139 NTSTATUS status; 3140 3141 cxDriverGlobals = GetFxDriverGlobals(DriverGlobals); 3142 3143 // 3144 // Validate destination queue handle 3145 // 3146 FxObjectHandleGetPtrAndGlobals(cxDriverGlobals, 3147 DestinationQueue, 3148 FX_TYPE_QUEUE, 3149 (PVOID*)&queue, 3150 &fxDriverGlobals); 3151 3152 // 3153 // Validate request object handle 3154 // 3155 FxObjectHandleGetPtr(fxDriverGlobals, 3156 Request, 3157 FX_TYPE_REQUEST, 3158 (PVOID*)&request); 3159 3160 // 3161 // If present, let the queue do the heavy lifting. 3162 // 3163 if (request->GetCurrentQueue() != NULL) { 3164 status = request->GetCurrentQueue()->ForwardRequest(queue, request); 3165 goto Done; 3166 } 3167 3168 // 3169 // Basic verification. 3170 // 3171 status = VerifyWdfRequestForwardToIoQueue(fxDriverGlobals, request); 3172 if (!NT_SUCCESS(status)) { 3173 goto Done; 3174 } 3175 3176 // 3177 // OK, queue this request. 3178 // 3179 status = queue->QueueDriverCreatedRequest(request, FALSE); 3180 3181 Done: 3182 return status; 3183 } 3184 3185 _Must_inspect_result_ 3186 NTSTATUS 3187 FX_VF_FUNCTION(VerifyWdfRequestForwardToParentDeviceIoQueue) ( 3188 _In_ PFX_DRIVER_GLOBALS fxDriverGlobals, 3189 _In_ FxRequest* request 3190 ) 3191 { 3192 NTSTATUS status; 3193 FxIrp* irp; 3194 3195 PAGED_CODE_LOCKED(); 3196 3197 // 3198 // * Is request I/O allocated but without a queue? This should not happen. 3199 // * Is WDF driver v1.9 or below trying to use this feature? We don't allow it. 3200 // 3201 if (request->IsAllocatedDriver() == FALSE || 3202 fxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,11) == FALSE) { 3203 status = STATUS_INVALID_DEVICE_REQUEST; 3204 DoTraceLevelMessage(fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 3205 "WDFREQUEST %p doesn't belong to any queue, %!STATUS!", 3206 request->GetHandle(), status); 3207 FxVerifierDbgBreakPoint(fxDriverGlobals); 3208 goto Done; 3209 } 3210 3211 // 3212 // Make sure current IRP stack location is valid. 3213 // 3214 status = request->VerifyRequestCanBeCompleted(fxDriverGlobals); 3215 if (!NT_SUCCESS(status)) { 3216 goto Done; 3217 } 3218 3219 // 3220 // Make sure IRP has space for at least another stack location. 3221 // 3222 irp = request->GetFxIrp(); 3223 3224 ASSERT(irp->GetIrp() != NULL); 3225 3226 if (irp->GetCurrentIrpStackLocationIndex() <= 1) { 3227 status = STATUS_INVALID_DEVICE_REQUEST; 3228 DoTraceLevelMessage(fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 3229 "IRP %p of WDFREQUEST %p doesn't enough stack " 3230 "locations, %!STATUS!", 3231 irp, request->GetHandle(), status); 3232 FxVerifierDbgBreakPoint(fxDriverGlobals); 3233 goto Done; 3234 } 3235 3236 Done: 3237 return status; 3238 } 3239 3240 _Must_inspect_result_ 3241 __drv_maxIRQL(DISPATCH_LEVEL) 3242 NTSTATUS 3243 STDCALL 3244 WDFEXPORT(WdfRequestForwardToParentDeviceIoQueue)( 3245 __in 3246 PWDF_DRIVER_GLOBALS DriverGlobals, 3247 __in 3248 WDFREQUEST Request, 3249 __in 3250 WDFQUEUE ParentDeviceQueue, 3251 __in 3252 PWDF_REQUEST_FORWARD_OPTIONS ForwardOptions 3253 ) 3254 3255 /*++ 3256 3257 Routine Description: 3258 3259 Forward a request presented on one queue to parent Device queue. 3260 3261 A request may only be forwarded from a queues dispatch routine. 3262 3263 If the request is successfully forwarded to the ParentDeviceQueue, it 3264 is no longer owned by the driver, but by the ParentDeviceQueue. 3265 3266 The driver gets ownership of the request when it receives it 3267 from the DestinationQueue through EvtIo callback, or WdfIoQueueRetrieveNextRequest. 3268 3269 Arguments: 3270 3271 3272 Request - Request object to forward. 3273 3274 ParentDeviceQueue - Queue that is to receive the request. 3275 3276 ForwardOptions - A pointer to a caller-allocated WDF_REQUEST_FORWARD_OPTIONS 3277 structure 3278 3279 Returns: 3280 3281 STATUS_SUCCESS - Request was forwarded to Queue and driver no 3282 longer owns it. 3283 3284 !STATUS_SUCCESS - Request was not forwarded to the Queue, and 3285 the driver still owns the request and is responsible 3286 for either completing it, or eventually successfully 3287 forwarding it to a Queue. 3288 --*/ 3289 3290 { 3291 PFX_DRIVER_GLOBALS fxDriverGlobals; 3292 NTSTATUS status; 3293 FxRequest* request; 3294 FxIoQueue* queue; 3295 3296 // 3297 // Validate destination queue handle 3298 // 3299 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 3300 ParentDeviceQueue, 3301 FX_TYPE_QUEUE, 3302 (PVOID*)&queue, 3303 &fxDriverGlobals); 3304 3305 // 3306 // Validate request object handle 3307 // 3308 FxObjectHandleGetPtr(fxDriverGlobals, 3309 Request, 3310 FX_TYPE_REQUEST, 3311 (PVOID*)&request); 3312 FxPointerNotNull(fxDriverGlobals, ForwardOptions); 3313 3314 if (ForwardOptions->Size != sizeof(WDF_REQUEST_FORWARD_OPTIONS)) { 3315 // 3316 // Size is wrong, bale out 3317 // 3318 status = STATUS_INFO_LENGTH_MISMATCH; 3319 DoTraceLevelMessage(fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR, 3320 "ForwardOptions %p Size incorrect, expected %d, " 3321 "got %d, %!STATUS!", 3322 ForwardOptions, sizeof(WDF_REQUEST_FORWARD_OPTIONS), 3323 ForwardOptions->Size, 3324 status); 3325 3326 goto Done; 3327 } 3328 3329 if ((ForwardOptions->Flags & ~WDF_REQUEST_FORWARD_OPTION_SEND_AND_FORGET) != 0) { 3330 // 3331 // Invalid flag 3332 // 3333 status = STATUS_INVALID_PARAMETER; 3334 DoTraceLevelMessage(fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR, 3335 "ForwardOptions %p Flags 0x%x invalid, " 3336 "valid mask is 0x%x, %!STATUS!", 3337 ForwardOptions, ForwardOptions->Flags, 3338 WDF_REQUEST_FORWARD_OPTION_SEND_AND_FORGET, 3339 status); 3340 3341 goto Done; 3342 } 3343 3344 // 3345 // If present, let the queue do the heavy lifting. 3346 // 3347 if (request->GetCurrentQueue() != NULL) { 3348 status = request->GetCurrentQueue()->ForwardRequestToParent( 3349 queue, 3350 request, 3351 ForwardOptions); 3352 goto Done; 3353 } 3354 3355 // 3356 // Basic verification. 3357 // 3358 status = VerifyWdfRequestForwardToParentDeviceIoQueue(fxDriverGlobals, 3359 request); 3360 if (!NT_SUCCESS(status)) { 3361 goto Done; 3362 } 3363 3364 // 3365 // OK, queue this request. 3366 // 3367 status = queue->QueueDriverCreatedRequest(request, TRUE); 3368 3369 Done: 3370 return status; 3371 } 3372 3373 _Must_inspect_result_ 3374 __drv_maxIRQL(DISPATCH_LEVEL) 3375 NTSTATUS 3376 STDCALL 3377 WDFEXPORT(WdfRequestRequeue)( 3378 __in 3379 PWDF_DRIVER_GLOBALS DriverGlobals, 3380 __in 3381 WDFREQUEST Request 3382 ) 3383 3384 /*++ 3385 3386 Routine Description: 3387 3388 Requeue the request - only allowed if the queue is a manual queue. 3389 3390 Arguments: 3391 3392 Request - Request to requeue 3393 3394 Returns: 3395 3396 NTSTATUS 3397 3398 --*/ 3399 3400 { 3401 PFX_DRIVER_GLOBALS pFxDriverGlobals; 3402 FxRequest* pRequest; 3403 3404 // 3405 // Validate request object handle 3406 // 3407 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 3408 Request, 3409 FX_TYPE_REQUEST, 3410 (PVOID*)&pRequest, 3411 &pFxDriverGlobals); 3412 3413 #if FX_VERBOSE_TRACE 3414 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 3415 "Enter: WDFREQUEST 0x%p", Request); 3416 #endif // FX_VERBOSE_TRACE 3417 3418 // 3419 // GetCurrentQueue may return NULL if the request is driver created request 3420 // or the if the call is made in the context of InProcessContextCallback. 3421 // 3422 if (pRequest->GetCurrentQueue() == NULL) { 3423 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 3424 "WDFREQUEST %p doesn't belong to any queue %!STATUS!", 3425 Request, STATUS_INVALID_DEVICE_REQUEST); 3426 FxVerifierDbgBreakPoint(pFxDriverGlobals); 3427 return STATUS_INVALID_DEVICE_REQUEST; 3428 } 3429 3430 return pRequest->GetCurrentQueue()->Requeue(pRequest); 3431 } 3432 3433 __drv_maxIRQL(DISPATCH_LEVEL) 3434 VOID 3435 STDCALL 3436 WDFEXPORT(WdfRequestMarkCancelable)( 3437 __in 3438 PWDF_DRIVER_GLOBALS DriverGlobals, 3439 __in 3440 WDFREQUEST Request, 3441 __in 3442 PFN_WDF_REQUEST_CANCEL EvtRequestCancel 3443 ) 3444 3445 /*++ 3446 3447 Routine Description: 3448 3449 Mark the specified request as cancelable 3450 3451 Arguments: 3452 3453 Request - Request to mark as cancelable. 3454 3455 EvtRequestCancel - cancel routine to be invoked when the 3456 request is cancelled. 3457 3458 Returns: 3459 3460 None 3461 3462 --*/ 3463 3464 { 3465 PFX_DRIVER_GLOBALS pFxDriverGlobals; 3466 FxRequest* pRequest; 3467 NTSTATUS status; 3468 3469 // 3470 // Validate request object handle 3471 // 3472 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 3473 Request, 3474 FX_TYPE_REQUEST, 3475 (PVOID*)&pRequest, 3476 &pFxDriverGlobals); 3477 3478 FxPointerNotNull(pFxDriverGlobals, EvtRequestCancel); 3479 3480 #if FX_VERBOSE_TRACE 3481 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 3482 "Enter: WDFREQUEST 0x%p", Request); 3483 #endif // FX_VERBOSE_TRACE 3484 3485 if (pRequest->GetCurrentQueue() == NULL) { 3486 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 3487 "WDFREQUEST %p doesn't belong to any queue", 3488 Request); 3489 FxVerifierDbgBreakPoint(pFxDriverGlobals); 3490 return; 3491 } 3492 3493 status = pRequest->GetCurrentQueue()->RequestCancelable(pRequest, 3494 TRUE, 3495 EvtRequestCancel, 3496 FALSE); 3497 UNREFERENCED_PARAMETER(status); //for fre build 3498 ASSERT(status == STATUS_SUCCESS); 3499 3500 } 3501 3502 _Must_inspect_result_ 3503 __drv_maxIRQL(DISPATCH_LEVEL) 3504 NTSTATUS 3505 STDCALL 3506 WDFEXPORT(WdfRequestMarkCancelableEx)( 3507 __in 3508 PWDF_DRIVER_GLOBALS DriverGlobals, 3509 __in 3510 WDFREQUEST Request, 3511 __in 3512 PFN_WDF_REQUEST_CANCEL EvtRequestCancel 3513 ) 3514 3515 /*++ 3516 3517 Routine Description: 3518 3519 Mark the specified request as cancelable. Do not call the specified cancel 3520 routine if IRP is already cancelled but instead return STATUS_CANCELLED. 3521 Caller is responsible for completing the request with STATUS_CANCELLED. 3522 3523 Arguments: 3524 3525 Request - Request to mark as cancelable. 3526 3527 EvtRequestCancel - cancel routine to be invoked when the 3528 request is cancelled. 3529 3530 Returns: 3531 3532 STATUS_SUCCESS - The request has been marked cancelable. 3533 STATUS_CANCELLED - The IRP is already cancelled. 3534 NTSTATUS - Other values are possible when verifier is enabled. 3535 3536 --*/ 3537 3538 { 3539 PFX_DRIVER_GLOBALS pFxDriverGlobals; 3540 FxRequest* pRequest; 3541 NTSTATUS status; 3542 3543 // 3544 // Validate request object handle 3545 // 3546 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 3547 Request, 3548 FX_TYPE_REQUEST, 3549 (PVOID*)&pRequest, 3550 &pFxDriverGlobals); 3551 3552 FxPointerNotNull(pFxDriverGlobals, EvtRequestCancel); 3553 3554 #if FX_VERBOSE_TRACE 3555 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 3556 "Enter: WDFREQUEST 0x%p", Request); 3557 #endif // FX_VERBOSE_TRACE 3558 3559 if (pRequest->GetCurrentQueue() == NULL) { 3560 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 3561 "WDFREQUEST %p doesn't belong to any queue %!STATUS!", 3562 Request, STATUS_INVALID_DEVICE_REQUEST); 3563 FxVerifierDbgBreakPoint(pFxDriverGlobals); 3564 return STATUS_INVALID_DEVICE_REQUEST; 3565 } 3566 3567 status = pRequest->GetCurrentQueue()->RequestCancelable(pRequest, 3568 TRUE, 3569 EvtRequestCancel, 3570 TRUE); 3571 3572 ASSERT(status == STATUS_SUCCESS || status == STATUS_CANCELLED); 3573 return status; 3574 } 3575 3576 _Must_inspect_result_ 3577 __drv_maxIRQL(DISPATCH_LEVEL) 3578 NTSTATUS 3579 STDCALL 3580 WDFEXPORT(WdfRequestUnmarkCancelable)( 3581 __in 3582 PWDF_DRIVER_GLOBALS DriverGlobals, 3583 __in 3584 WDFREQUEST Request 3585 ) 3586 3587 /*++ 3588 3589 Routine Description: 3590 3591 Unmark the specified request as cancelable 3592 3593 Arguments: 3594 3595 Request - Request to unmark as cancelable. 3596 3597 Returns: 3598 3599 NTSTATUS 3600 3601 --*/ 3602 3603 { 3604 PFX_DRIVER_GLOBALS pFxDriverGlobals; 3605 FxRequest* pRequest; 3606 3607 // 3608 // Validate request object handle 3609 // 3610 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 3611 Request, 3612 FX_TYPE_REQUEST, 3613 (PVOID*)&pRequest, 3614 &pFxDriverGlobals); 3615 3616 #if FX_VERBOSE_TRACE 3617 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 3618 "Enter: WDFREQUEST 0x%p", Request); 3619 #endif // FX_VERBOSE_TRACE 3620 3621 if (pRequest->GetCurrentQueue() == NULL) { 3622 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 3623 "WDFREQUEST %p doesn't belong to any queue %!STATUS!", 3624 Request, STATUS_INVALID_DEVICE_REQUEST); 3625 FxVerifierDbgBreakPoint(pFxDriverGlobals); 3626 return STATUS_INVALID_DEVICE_REQUEST; 3627 } 3628 3629 return pRequest->GetCurrentQueue()->RequestCancelable(pRequest, 3630 FALSE, 3631 NULL, 3632 FALSE); 3633 } 3634 3635 _Must_inspect_result_ 3636 NTSTATUS 3637 FX_VF_FUNCTION(VerifyWdfRequestIsCanceled)( 3638 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, 3639 _In_ FxRequest* pRequest 3640 ) 3641 { 3642 NTSTATUS status; 3643 KIRQL irql; 3644 3645 PAGED_CODE_LOCKED(); 3646 3647 pRequest->Lock(&irql); 3648 3649 status = pRequest->VerifyRequestIsDriverOwned(FxDriverGlobals); 3650 if (NT_SUCCESS(status)) { 3651 status = pRequest->VerifyRequestIsNotCancelable(FxDriverGlobals); 3652 } 3653 3654 pRequest->Unlock(irql); 3655 return status; 3656 } 3657 3658 _Must_inspect_result_ 3659 __drv_maxIRQL(DISPATCH_LEVEL) 3660 BOOLEAN 3661 STDCALL 3662 WDFEXPORT(WdfRequestIsCanceled)( 3663 __in 3664 PWDF_DRIVER_GLOBALS DriverGlobals, 3665 __in 3666 WDFREQUEST Request 3667 ) 3668 3669 /*++ 3670 3671 Routine Description: 3672 3673 Check to see if the request is cancelled by the I/O manager. 3674 This call is valid only on a driver owned non-cancelable request. 3675 3676 Arguments: 3677 3678 Request - Request being checked. 3679 3680 Returns: 3681 3682 BOOLEAN 3683 3684 --*/ 3685 3686 { 3687 PFX_DRIVER_GLOBALS pFxDriverGlobals; 3688 FxRequest* pRequest; 3689 NTSTATUS status; 3690 3691 // 3692 // Validate request object handle 3693 // 3694 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 3695 Request, 3696 FX_TYPE_REQUEST, 3697 (PVOID*)&pRequest, 3698 &pFxDriverGlobals); 3699 status = VerifyWdfRequestIsCanceled(pRequest->GetDriverGlobals(), pRequest); 3700 if (!NT_SUCCESS(status)) { 3701 return FALSE; 3702 } 3703 3704 return pRequest->IsCancelled(); 3705 } 3706 3707 __drv_maxIRQL(DISPATCH_LEVEL) 3708 VOID 3709 STDCALL 3710 WDFEXPORT(WdfRequestStopAcknowledge)( 3711 __in 3712 PWDF_DRIVER_GLOBALS DriverGlobals, 3713 __in 3714 WDFREQUEST Request, 3715 __in 3716 BOOLEAN Requeue 3717 ) 3718 3719 /*++ 3720 3721 Routine Description: 3722 3723 The driver calls this to acknowledge that it is no longer 3724 attempting to perform I/O on the request which was provided in 3725 the EvtIoStop event callback notification. 3726 3727 The device driver must arrange to no longer touch any hardware 3728 resources before making this call. 3729 3730 Arguments: 3731 3732 Request - Request being stopped 3733 3734 Requeue - True if the request is to be placed back on the front of the queue, 3735 and re-delivered to the device driver on resume. 3736 3737 Returns: 3738 3739 None 3740 3741 --*/ 3742 3743 { 3744 FxRequest* pRequest; 3745 PFX_DRIVER_GLOBALS pFxDriverGlobals; 3746 3747 // 3748 // Validate request object handle 3749 // 3750 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 3751 Request, 3752 FX_TYPE_REQUEST, 3753 (PVOID*)&pRequest, 3754 &pFxDriverGlobals); 3755 3756 #if FX_VERBOSE_TRACE 3757 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 3758 "Enter: WDFREQUEST 0x%p", Request); 3759 #endif // FX_VERBOSE_TRACE 3760 3761 pRequest->StopAcknowledge(Requeue); 3762 } 3763 3764 3765 __drv_maxIRQL(DISPATCH_LEVEL) 3766 BOOLEAN 3767 STDCALL 3768 WDFEXPORT(WdfRequestIsReserved)( 3769 __in 3770 PWDF_DRIVER_GLOBALS DriverGlobals, 3771 __in 3772 WDFREQUEST Request 3773 ) 3774 /*++ 3775 3776 Routine Description: 3777 This is used to determine if a Request is a reserved request. Reserved 3778 Requests are used for forward progress. 3779 3780 Arguments: 3781 3782 Request - Request being checked 3783 3784 3785 Returns: 3786 3787 BOOLEAN 3788 3789 --*/ 3790 3791 { 3792 FxRequest* pRequest; 3793 PFX_DRIVER_GLOBALS pFxDriverGlobals; 3794 3795 // 3796 // Validate request object handle 3797 // 3798 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 3799 Request, 3800 FX_TYPE_REQUEST, 3801 (PVOID*)&pRequest, 3802 &pFxDriverGlobals); 3803 3804 return pRequest->IsReserved(); 3805 } 3806 3807 3808 } // extern "C" the whole file 3809