1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxRequest.cpp 8 9 Abstract: 10 11 This module implements FxRequest object 12 13 Author: 14 15 16 17 Environment: 18 19 Both kernel and user mode 20 21 Revision History: 22 23 24 --*/ 25 26 #include "coreprivshared.hpp" 27 28 // Tracing support 29 extern "C" { 30 // #include "FxRequest.tmh" 31 } 32 33 FxRequest::FxRequest( 34 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 35 __in MdIrp Irp, 36 __in FxRequestIrpOwnership Ownership, 37 __in FxRequestConstructorCaller Caller, 38 __in USHORT ObjectSize 39 ) : 40 FxRequestBase(FxDriverGlobals, 41 ObjectSize, 42 Irp, 43 Ownership, 44 Caller) 45 { 46 m_OutputBufferOffset = FIELD_OFFSET(FxRequest, m_OutputBufferOffset); 47 m_SystemBufferOffset = FIELD_OFFSET(FxRequest, m_SystemBufferOffset); 48 m_IoQueue = NULL; 49 50 m_PowerStopState = FxRequestPowerStopUnknown; 51 52 InitializeListHead(&m_OwnerListEntry); 53 InitializeListHead(&m_OwnerListEntry2); 54 InitializeListHead(&m_ForwardProgressList); 55 56 m_Presented = (Caller == FxRequestConstructorCallerIsDriver) ? TRUE : FALSE; 57 m_Reserved = FALSE; 58 m_ForwardProgressQueue = NULL; 59 m_ForwardRequestToParent = FALSE; 60 m_InternalContext = NULL; 61 } 62 63 #if DBG 64 FxRequest::~FxRequest( 65 VOID 66 ) 67 { 68 ASSERT(IsListEmpty(&m_OwnerListEntry)); 69 ASSERT(IsListEmpty(&m_OwnerListEntry2)); 70 } 71 #endif // DBG 72 73 _Must_inspect_result_ 74 NTSTATUS 75 FxRequest::_CreateForPackage( 76 __in CfxDevice* Device, 77 __in PWDF_OBJECT_ATTRIBUTES RequestAttributes, 78 __in MdIrp Irp, 79 __deref_out FxRequest** Request 80 ) 81 /*++ 82 83 Routine Description: 84 85 Creates an FxRequest object and returns its pointer to the caller. 86 87 Arguments: 88 89 Device - Pointer to FxDevice object request will be associated with 90 91 RequestAttributes - Specifies the object's attributes for the request. 92 93 Irp - Pointer to Irp 94 95 Request - Pointer to location to store the returned FxRequest pointer 96 97 Return Value: 98 99 NTSTATUS 100 101 --*/ 102 { 103 NTSTATUS status; 104 FxRequest* pRequest; 105 106 *Request = NULL; 107 108 // 109 // Allocate the new FxRequest object in the per driver tracking pool 110 // 111 pRequest = new(Device, RequestAttributes) FxRequestFromLookaside(Device, Irp); 112 113 if (pRequest == NULL) { 114 DoTraceLevelMessage( 115 Device->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 116 "Memory allocation failed %!STATUS!", 117 STATUS_INSUFFICIENT_RESOURCES); 118 return STATUS_INSUFFICIENT_RESOURCES; 119 } 120 121 // 122 // For forward progress the IRP can be NULL. 123 // 124 if (Irp != NULL) { 125 pRequest->AssignMemoryBuffers(Device->GetIoTypeForReadWriteBufferAccess()); 126 } 127 128 // 129 // Improve I/O perf by not parenting it to device. However, if verifier is 130 // turned on, the request is parented to the device to help track reference 131 // leaks. 132 // 133 if (Device->GetDriverGlobals()->FxRequestParentOptimizationOn) { 134 status = pRequest->Commit(RequestAttributes, 135 NULL, 136 NULL, 137 FALSE); 138 } 139 else { 140 status = pRequest->Commit(RequestAttributes, 141 NULL, 142 Device, 143 FALSE); 144 } 145 146 if (NT_SUCCESS(status)) { 147 *Request = pRequest; 148 } 149 else { 150 DoTraceLevelMessage( 151 Device->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 152 "Could not commit FxRequest %!STATUS!", status); 153 pRequest->DeleteFromFailedCreate(); 154 } 155 156 return status; 157 } 158 159 _Must_inspect_result_ 160 NTSTATUS 161 FxRequest::_Create( 162 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 163 __in_opt PWDF_OBJECT_ATTRIBUTES RequestAttributes, 164 __in_opt MdIrp Irp, 165 __in_opt FxIoTarget* Target, 166 __in FxRequestIrpOwnership Ownership, 167 __in FxRequestConstructorCaller Caller, 168 __deref_out FxRequest** Request 169 ) 170 { 171 WDFOBJECT hRequest; 172 NTSTATUS status; 173 FxRequest* pRequest; 174 175 *Request = NULL; 176 177 status = FxValidateObjectAttributes(FxDriverGlobals, RequestAttributes); 178 if (!NT_SUCCESS(status)) { 179 return status; 180 } 181 182 pRequest = new (FxDriverGlobals, RequestAttributes) 183 FxRequest(FxDriverGlobals, 184 Irp, 185 Ownership, 186 Caller, 187 sizeof(FxRequest)); 188 189 if (pRequest != NULL) { 190 if (Target != NULL) { 191 status = pRequest->ValidateTarget(Target); 192 } 193 194 if (NT_SUCCESS(status)) { 195 status = pRequest->Commit(RequestAttributes, &hRequest, NULL, TRUE); 196 } 197 198 if (NT_SUCCESS(status)) { 199 *Request = pRequest; 200 } 201 else { 202 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 203 "Handle create failed %!STATUS!", status); 204 205 if (Irp != NULL) { 206 // 207 // Clear the irp out of the request so that the destructor does 208 // not free it. Since we are returning failure, the caller does 209 // not expect the PIRP passed in to be freed. 210 // 211 pRequest->SetSubmitIrp(NULL, FALSE); 212 } 213 214 pRequest->DeleteFromFailedCreate(); 215 } 216 } 217 else { 218 status = STATUS_INSUFFICIENT_RESOURCES; 219 } 220 221 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 222 "Irp %p Ownership %!FxRequestIrpOwnership! FxRequest %p, status %!STATUS!", 223 Irp, Ownership, *Request, status); 224 225 return status; 226 } 227 228 NTSTATUS 229 FxRequest::SetInformation( 230 __in ULONG_PTR Information 231 ) 232 /*++ 233 234 Routine Description: 235 236 Set the IRP's IoStatus.Information field. 237 238 NOTE: If the caller calls Complete(status, information), as opposed 239 to Complete(status), the value will get overwritten. 240 241 Arguments: 242 243 Information - Information value to set 244 245 Returns: 246 247 NTSTATUS 248 249 --*/ 250 { 251 PFX_DRIVER_GLOBALS pFxDriverGlobals; 252 253 pFxDriverGlobals = GetDriverGlobals(); 254 255 if (pFxDriverGlobals->FxVerifierIO) { 256 NTSTATUS status; 257 KIRQL irql; 258 259 Lock(&irql); 260 261 status = VerifyRequestIsNotCompleted(pFxDriverGlobals); 262 if (NT_SUCCESS(status)) { 263 m_Irp.SetInformation(Information); 264 } 265 266 Unlock(irql); 267 268 return status; 269 } 270 else { 271 m_Irp.SetInformation(Information); 272 return STATUS_SUCCESS; 273 } 274 } 275 276 ULONG_PTR 277 FxRequest::GetInformation( 278 VOID 279 ) 280 /*++ 281 282 Routine Description: 283 284 Get the IRP's IoStatus.Information field. 285 286 287 Arguments: 288 289 None 290 291 Returns: 292 293 ULONG_PTR 294 295 --*/ 296 { 297 PFX_DRIVER_GLOBALS pFxDriverGlobals; 298 299 pFxDriverGlobals = GetDriverGlobals(); 300 301 // Verifier 302 if (pFxDriverGlobals->FxVerifierIO) { 303 ULONG_PTR info; 304 KIRQL irql; 305 NTSTATUS status; 306 307 Lock(&irql); 308 309 status = VerifyRequestIsNotCompleted(pFxDriverGlobals); 310 if (!NT_SUCCESS(status)) { 311 info = NULL; 312 } 313 else { 314 info = m_Irp.GetInformation(); 315 } 316 317 Unlock(irql); 318 319 return info; 320 } 321 else { 322 return m_Irp.GetInformation(); 323 } 324 } 325 326 KPROCESSOR_MODE 327 FxRequest::GetRequestorMode( 328 VOID 329 ) 330 /*++ 331 332 Routine Description: 333 Get the Irp->RequestorMode value. 334 335 Arguments: 336 None 337 338 Returns: 339 KPROCESSOR_MODE 340 341 --*/ 342 { 343 PFX_DRIVER_GLOBALS pFxDriverGlobals; 344 345 pFxDriverGlobals = GetDriverGlobals(); 346 347 if (pFxDriverGlobals->FxVerifierIO) { 348 KPROCESSOR_MODE mode; 349 KIRQL irql; 350 NTSTATUS status; 351 352 Lock(&irql); 353 354 status = VerifyRequestIsNotCompleted(pFxDriverGlobals); 355 if (!NT_SUCCESS(status)) { 356 mode = UserMode; 357 } else { 358 mode = m_Irp.GetRequestorMode(); 359 } 360 361 Unlock(irql); 362 363 return mode; 364 } 365 else { 366 return m_Irp.GetRequestorMode(); 367 } 368 } 369 370 371 VOID 372 FX_VF_METHOD(FxRequest, VerifyCompleteInternal)( 373 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, 374 _In_ NTSTATUS Status 375 ) 376 { 377 UNREFERENCED_PARAMETER(FxDriverGlobals); 378 ULONG length; 379 KIRQL irql; 380 BOOLEAN validateLength; 381 382 PAGED_CODE_LOCKED(); 383 384 Lock(&irql); 385 386 if (GetDriverGlobals()->FxVerifierIO ) { 387 (VOID) VerifyRequestIsNotCompleted(GetDriverGlobals()); 388 } else { 389 ASSERT(m_Completed == FALSE); 390 } 391 392 393 if ((m_VerifierFlags & FXREQUEST_FLAG_DRIVER_CANCELABLE) && 394 (m_VerifierFlags & FXREQUEST_FLAG_CANCELLED) == 0x0) { 395 396 // 397 // We could trace each sentence separate, but that takes up valuable 398 // room in the IFR. Instead, trace the entire "paragraph" as one 399 // message so that we have more room in the IFR. 400 // 401 DoTraceLevelMessage( 402 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 403 "Completing Cancelable WDFREQUEST %p. " 404 405 "This results in a race condition in the device driver that can " 406 "cause double completions. " 407 408 "Call WdfRequestUnmarkCancelable before WdfRequestComplete. " 409 410 "If WdfRequestUnmarkCancelable returns STATUS_CANCELLED, " 411 "do not complete the request until the EvtIoCancel handler is called. " 412 413 "The straightforward way to ensure this is to complete a canceled " 414 "request from the EvIoCancel callback.", 415 416 GetHandle() 417 ); 418 419 FxVerifierDbgBreakPoint(GetDriverGlobals()); 420 421 } 422 423 validateLength = FALSE; 424 length = 0; 425 426 switch (m_Irp.GetMajorFunction()) { 427 case IRP_MJ_READ: 428 length = m_Irp.GetParameterReadLength(); 429 validateLength = TRUE; 430 break; 431 432 case IRP_MJ_WRITE: 433 length = m_Irp.GetParameterWriteLength(); 434 validateLength = TRUE; 435 break; 436 437 case IRP_MJ_DEVICE_CONTROL: 438 if (m_Irp.GetRequestorMode() == UserMode) { 439 length = m_Irp.GetParameterIoctlOutputBufferLength(); 440 441 if (length > 0) { 442 validateLength = TRUE; 443 } 444 else { 445 // 446 // For an output length == 0, a driver can indicate the number 447 // of bytes used of the input buffer. 448 // 449 DO_NOTHING(); 450 } 451 } 452 else { 453 // 454 // If the IOCTL came from kernel mode, the same reasoning applies 455 // here as for an internal IOCTL...we don't know deterministically 456 // how to find the output buffer length. 457 // 458 DO_NOTHING(); 459 } 460 break; 461 462 case IRP_MJ_INTERNAL_DEVICE_CONTROL: 463 // 464 // Because the current stack location can use any part of the union 465 // (like Parameters.Others instead of Parameters.DeviceIoControl), we 466 // cannot deterministically figure out the output buffer length for 467 // internal IOCTLs. 468 // 469 // || || Fall through || || 470 // \/ \/ \/ \/ 471 default: 472 DO_NOTHING(); 473 } 474 475 // 476 // We shouldn't validate the information field if the status is warning 477 // because it's valid for a driver to fill partial data in the buffer 478 // and ask for large buffer size. 479 // 480 if (validateLength && 481 NT_SUCCESS(Status) && 482 m_Irp.GetInformation() > length) { 483 484 WDF_REQUEST_FATAL_ERROR_INFORMATION_LENGTH_MISMATCH_DATA data; 485 486 DoTraceLevelMessage( 487 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 488 "WDFREQUEST %p, MJ 0x%x, Information 0x%I64x is greater then " 489 "buffer length 0x%x", GetHandle(), m_Irp.GetMajorFunction(), 490 m_Irp.GetInformation(), length); 491 492 data.Request = GetHandle(); 493 data.Irp = reinterpret_cast<PIRP>(m_Irp.GetIrp()); 494 data.OutputBufferLength = length; 495 data.Information = m_Irp.GetInformation(); 496 data.MajorFunction = m_Irp.GetMajorFunction(); 497 498 FxVerifierBugCheck( 499 GetDriverGlobals(), 500 WDF_REQUEST_FATAL_ERROR, 501 WDF_REQUEST_FATAL_ERROR_INFORMATION_LENGTH_MISMATCH, 502 (ULONG_PTR) &data 503 ); 504 505 // will not get here 506 } 507 508 // Set IRP to NULL when NT IRP is completed 509 m_Completed = TRUE; 510 511 Unlock(irql); 512 } 513 514 NTSTATUS 515 FxRequest::CompleteInternal( 516 __in NTSTATUS Status 517 ) 518 519 /*++ 520 521 Routine Description: 522 523 Internal worker to complete the current request object. 524 525 This is called with the FxRequest object lock held, and 526 state validation as far as IRP completion already done. 527 528 Callers must use Complete(Status), or Complete(Status,Information) 529 530 It returns with the FxRequest object locked *released* 531 532 Arguments: 533 534 Status - Status to complete the request with 535 536 Returns: 537 538 NTSTATUS 539 540 --*/ 541 542 { 543 PFX_DRIVER_GLOBALS pFxDriverGlobals; 544 MdIrp pIrp; 545 FxRequestCompletionState state; 546 FxIoQueue* queue; 547 CfxDevice* pRefedDevice; 548 549 pFxDriverGlobals = GetDriverGlobals(); 550 queue = NULL; 551 // 552 // Store off the irp into a local variable 553 // 554 pIrp = m_Irp.GetIrp(); 555 556 // 557 // Lock is no longer required, since it's only used 558 // by verifier for already completed requests. This is a 559 // serious driver error anyway 560 // 561 562 563 VerifyCompleteInternal(pFxDriverGlobals, Status); 564 565 if (pFxDriverGlobals->FxVerifierOn == FALSE) { 566 // 567 // No lock needed in non-verifier case since this is only 568 // used to detect double completions with verifier on 569 // 570 ASSERT(m_Completed == FALSE); 571 m_Completed = TRUE; 572 } 573 574 575 576 577 578 579 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 580 581 582 583 584 585 586 587 ULONG flagsMasked = m_Irp.GetFlags() & IRP_INPUT_OPERATION; 588 if (m_Irp.GetMajorFunction()== IRP_MJ_DEVICE_CONTROL && 589 m_Irp.GetParameterIoctlCodeBufferMethod() == METHOD_BUFFERED && 590 m_Irp.GetRequestorMode() == UserMode && 591 m_Irp.GetParameterIoctlOutputBufferLength()== 0 && 592 (flagsMasked != 0)) { 593 594 DoTraceLevelMessage( 595 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 596 "Driver that handled WDFREQUEST 0x%p is requesting data to " 597 " be written back to the UserBuffer by returing a non zero value " 598 " in the Irp 0x%p Information field even though the OutputBufferLength " 599 " is zero", GetObjectHandle(), pIrp); 600 601 // 602 // We will assert only if the Information field is not zero to warn 603 // the developer that it's a bad thing to do. However, we do avoid 604 // corruption of UserBuffer on completion by clearing the flag 605 // erroneously set by the I/O manager. 606 // 607 if (m_Irp.GetInformation() != 0L) { 608 FxVerifierDbgBreakPoint(pFxDriverGlobals); 609 } 610 611 // 612 // Clear the flag to prevent the I/O manager from coping the 613 // data back from the SystemBuffer to Irp->UserBuffer 614 // 615 m_Irp.SetFlags(m_Irp.GetFlags() & (~IRP_INPUT_OPERATION)); 616 } 617 #endif 618 619 // 620 // If the status code is one of the framework facility codes, 621 // map it to a standard NTSTATUS 622 // 623 624 625 if ((Status & 0x0FFF0000) == (FACILITY_DRIVER_FRAMEWORK << 16)) { 626 DoTraceLevelMessage( 627 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 628 "Converting WDF NTSTATUS value 0x%x...", Status); 629 630 switch (Status) { 631 case STATUS_WDF_PAUSED: 632 case STATUS_WDF_BUSY: 633 Status = STATUS_DEVICE_BUSY; 634 break; 635 636 case STATUS_WDF_INTERNAL_ERROR: 637 Status = STATUS_INTERNAL_ERROR; 638 break; 639 640 case STATUS_WDF_TOO_FRAGMENTED: 641 Status = STATUS_INVALID_DEVICE_REQUEST; 642 break; 643 644 default: 645 DoTraceLevelMessage( 646 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 647 "Unknown WDF NTSTATUS 0x%x", Status); 648 Status = STATUS_INVALID_DEVICE_REQUEST; 649 break; 650 } 651 652 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 653 "... to %!STATUS!", Status); 654 } 655 656 if (IsAllocatedFromIo() == FALSE && IsCanComplete() == FALSE) { 657 FxVerifierDbgBreakPoint(pFxDriverGlobals); 658 } 659 660 // 661 // It is invalid to complete any requests on an IRPQUEUE 662 // 663 ASSERTMSG("WDFREQUEST is part of a WDFQUEUE, it could be Cancellable\n", 664 (m_IrpQueue == NULL)); 665 666 state = (FxRequestCompletionState) m_CompletionState; 667 queue = m_IoQueue; 668 669 // 670 // Some I/O request cleanup. Do not do this for driver created requests. 671 // 672 if (IsAllocatedFromIo()) { 673 // 674 // Set the completion state to none 675 // 676 m_CompletionState = FxRequestCompletionStateNone; 677 678 if (IsReserved() == FALSE) { 679 // 680 // Don't set the Queue to NULL for reserved requests. 681 // 682 m_IoQueue = NULL; 683 } 684 } 685 686 // 687 // IMPORTANT: the context must free its references before the request is 688 // completed. Any of these references could be on a memory interface that is 689 // an embedded interface in this object. If this reference 690 // is left outstanding when we check m_IrpReferenceCount below, we would 691 // bugcheck (and the driver writer would be unaware of why things are going 692 // wrong). 693 // 694 // Also, if the driver is freeing the referenced mmemory interface in its 695 // cleanup routine, we don't want an oustanding reference against it. 696 // 697 if (m_RequestContext != NULL) { 698 // 699 // m_RequestContext will be freed when the FxRequest's desctructor runs 700 // 701 m_RequestContext->ReleaseAndRestore(this); 702 } 703 704 // 705 // If the request is not presented to the driver then clear the 706 // cleanup & destroy callbacks before calling PerformEarlyDispose. 707 // 708 if (m_Presented == FALSE) { 709 ClearEvtCallbacks(); 710 } 711 712 if (IsReserved() == FALSE && IsAllocatedFromIo()) { 713 // 714 // Fire the driver supplied Cleanup callback if set 715 // 716 // This will allow the driver to release any IRP specific resources such 717 // as MDLs before we complete the IRP back to the OS, and release the 718 // process/thread reference. 719 // 720 // This is also the callback used to tell the driver the WDM IRP is going 721 // away if it has used the WDM "escape" API's to either get the IRP, or 722 // any resources it references. 723 // 724 725 // 726 // If a cleanup callback has been registered, we call it 727 // just before completing the IRP to WDM, which can cause any 728 // associated buffers, MDLs, or memory interfaces to be invalidated. 729 // 730 if (EarlyDispose() == FALSE) { 731 VerifierBreakpoint_RequestEarlyDisposeDeferred(GetDriverGlobals()); 732 } 733 734 // 735 // Now that the entire tree is disposed, we want to destroy all of the 736 // children. This will not put this object in the destroyed state. For 737 // m_IrpReferenceCount to go to zero, we need to destroy the child WDFMEMORYs 738 // that were created when we probed and locked the buffers. 739 // 740 DestroyChildren(); 741 } 742 else { 743 // 744 // We don't call cleanup callback for Reserved Requests. 745 // The driver can perform any cleanp it wants before completing the Request 746 // or before reusing the Reserved Request in its Dispatch callback. 747 748 749 750 751 752 753 DO_NOTHING(); 754 } 755 756 // 757 // If this is non-zero, indicates a reference count problem on any 758 // WDFMEMORY objects returned to the device driver from this WDFREQUEST. 759 // 760 if (m_IrpReferenceCount != 0) { 761 // 762 // NOTE: you cannot call GetBuffer or GetMdl 763 DoTraceLevelMessage( 764 pFxDriverGlobals, TRACE_LEVEL_FATAL, TRACINGREQUEST, 765 "WDFREQUEST 0x%p, PIRP 0x%p, Major Function 0x%x, completed with " 766 "outstanding references on WDFMEMORY 0x%p or 0x%p retrieved from " 767 "this request", 768 GetObjectHandle(), m_Irp.GetIrp(), m_Irp.GetMajorFunction(), 769 ((m_RequestBaseFlags & FxRequestBaseSystemMdlMapped) || 770 (m_RequestBaseStaticFlags & FxRequestBaseStaticSystemBufferValid)) ? 771 m_SystemBuffer.GetHandle() : NULL, 772 ((m_RequestBaseFlags & FxRequestBaseOutputMdlMapped) || 773 (m_RequestBaseStaticFlags & FxRequestBaseStaticOutputBufferValid)) ? 774 m_OutputBuffer.GetHandle() : NULL 775 ); 776 777 if ((m_RequestBaseFlags & FxRequestBaseSystemMdlMapped) || 778 (m_RequestBaseStaticFlags & FxRequestBaseStaticSystemBufferValid)) { 779 DoTraceLevelMessage( 780 pFxDriverGlobals, TRACE_LEVEL_FATAL, TRACINGREQUEST, 781 "WDFMEMORY 0x%p, buffer %p, PMDL %p, length %I64d bytes", 782 m_SystemBuffer.GetHandle(), m_SystemBuffer.GetBuffer(), 783 m_SystemBuffer.GetMdl(), m_SystemBuffer.GetBufferSize()); 784 } 785 786 if ((m_RequestBaseFlags & FxRequestBaseOutputMdlMapped) || 787 (m_RequestBaseStaticFlags & FxRequestBaseStaticOutputBufferValid)) { 788 DoTraceLevelMessage( 789 pFxDriverGlobals, TRACE_LEVEL_FATAL, TRACINGREQUEST, 790 "IOCTL output WDFMEMORY 0x%p, buffer %p, PMDL %p, length %I64d bytes", 791 m_OutputBuffer.GetHandle(), m_OutputBuffer.GetBuffer(), 792 m_OutputBuffer.GetMdl(), m_OutputBuffer.GetBufferSize()); 793 } 794 795 FxVerifierBugCheck(pFxDriverGlobals, 796 WDF_VERIFIER_FATAL_ERROR, 797 (ULONG_PTR) GetObjectHandle(), 798 (ULONG_PTR) m_IrpReferenceCount); 799 } 800 801 FxIrp irp(pIrp); 802 803 // 804 // Complete the NT IRP through the frameworks FxIrp 805 // 806 irp.SetStatus(Status); 807 808 ASSERT(IsCancelRoutineSet() == FALSE); 809 810 // 811 // For driver created requests we need to use two phase 812 // completion (pre and post) to detach the request from the queue before the 813 // IRP is completed, and then allow a new request to be dispatched. 814 // Note that the IRP is actually completed when the reference on this object 815 // goes to 1 (See FxRequest::Release() for more info). 816 // 817 if (IsAllocatedFromIo() == FALSE) { 818 // 819 // Do not touch the request after this call. 820 // Do not clear the request's IRP field before making this call. 821 // 822 PreProcessCompletionForDriverRequest(state, queue); 823 } 824 else { 825 // 826 // We only clear the irp from this object after PerformEarlyDispose has been 827 // called. m_SystemBuffer and m_OutputBuffer use m_Irp to return their 828 // buffers and their WDFMEMORY handles should be valid in the cleanup routine 829 // for the WDFREQUEST. We also keep m_Irp valid until after the 830 // m_IrpReferenceCount check, so we can trace out the buffers in case of 831 // error. 832 // 833 m_Irp.SetIrp(NULL); 834 835 if (irp.GetMajorFunction() == IRP_MJ_CREATE) { 836 // 837 // If this is the last handle to be closed on the device, then the call 838 // to CreateCompleted can cause the device to be deleted if the create 839 // has failed. We add a reference so that we make sure we have a device 840 // to free the request memory back to. 841 // 842 pRefedDevice = GetDevice(); 843 pRefedDevice->ADDREF(&irp); 844 845 pRefedDevice->m_PkgGeneral->CreateCompleted(&irp); 846 } 847 else { 848 pRefedDevice = NULL; 849 } 850 851 // 852 // WDM IRP is completed. 853 // 854 irp.CompleteRequest(GetPriorityBoost()); 855 856 if (IsReserved() == FALSE) { 857 PostProcessCompletion(state, queue); 858 } 859 else { 860 PostProcessCompletionForReserved(state, queue); 861 } 862 863 if (pRefedDevice != NULL) { 864 pRefedDevice->RELEASE(&irp); 865 pRefedDevice = NULL; 866 } 867 } 868 869 return Status; 870 } 871 872 873 VOID 874 FxRequest::PostProcessCompletion( 875 __in FxRequestCompletionState State, 876 __in FxIoQueue* Queue 877 ) 878 { 879 // 880 // Fire frameworks internal callback event if one is set 881 // (FxIoQueue or IoTarget's internal use) 882 // 883 if (State != FxRequestCompletionStateNone) { 884 // 885 // NOTE: This occurs after the IRP has already been released, 886 // and is only used for notification that the request 887 // has completed. 888 // 889 if (State & FxRequestCompletionStateIoPkgFlag) { 890 GetDevice()->m_PkgIo->RequestCompletedCallback(this); 891 } 892 else { 893 ASSERT(Queue != NULL); 894 Queue->RequestCompletedCallback(this); 895 //FxIoQueueToMx::RequestCompletedCallback(Queue, this); 896 } 897 898 // 899 // DeleteObject will dereference the object reference taken when the callback 900 // was registered 901 // 902 DeleteEarlyDisposedObject(); 903 } 904 else { 905 // 906 // Caller still wants the FxRequest class to be valid on return, 907 // but must call DeleteObject in order to ensure the object is 908 // no longer assigned any child objects, etc. 909 // 910 ADDREF(FXREQUEST_COMPLETE_TAG); 911 DeleteObject(); 912 } 913 } 914 915 VOID 916 FxRequest::PostProcessCompletionForReserved( 917 __in FxRequestCompletionState State, 918 __in FxIoQueue* Queue 919 ) 920 { 921 // 922 // Fire frameworks internal callback event if one is set 923 // (FxIoQueue or IoTarget's internal use) 924 // 925 if (State != FxRequestCompletionStateNone) { 926 // 927 // NOTE: This occurs after the IRP has already been released, 928 // and is only used for notification that the request 929 // has completed. 930 // 931 if (State & FxRequestCompletionStateIoPkgFlag) { 932 GetDevice()->m_PkgIo->RequestCompletedCallback(this); 933 } 934 else { 935 ASSERT(m_IoQueue == Queue); 936 Queue->RequestCompletedCallback(this); 937 } 938 } 939 else { 940 // 941 // Caller still wants the FxRequest class to be valid on return, 942 // but must call DeleteObject in order to ensure the object is 943 // no longer assigned any child objects, etc. 944 // 945 ADDREF(FXREQUEST_COMPLETE_TAG); 946 } 947 948 RELEASE(FXREQUEST_FWDPRG_TAG); 949 } 950 951 // 952 // Handles pre-process completion for driver-created-requests queued by the driver. 953 // 954 VOID 955 FxRequest::PreProcessCompletionForDriverRequest( 956 __in FxRequestCompletionState State, 957 __in FxIoQueue* Queue 958 ) 959 { 960 ASSERT(State == FxRequestCompletionStateNone || 961 State == FxRequestCompletionStateQueue); 962 // 963 // Fire frameworks internal callback (pre) event if one is set. 964 // 965 if (FxRequestCompletionStateQueue == State) { 966 // 967 // NOTE: This occurs before the IRP has already been released, 968 // and is only used to notify the queue to remove this request from this queue's 969 // internal lists. A second notification (lPostProcessCompletionForAllocatedDriver) 970 // is made after the IRP is completed. 971 // 972 Queue->PreRequestCompletedCallback(this); 973 } 974 else if (Queue != NULL){ 975 // 976 // On return from PostProcessCompletionForDriverRequest, caller (framework) 977 // will try to release the last ref. Increase the ref count so request stays alive until 978 // driver invokes WdfObjectDelete on this request. 979 // 980 ADDREF(FXREQUEST_COMPLETE_TAG); 981 } 982 983 // 984 // Let the system know that it is OK to complete this request. 985 // 986 RELEASE(FXREQUEST_DCRC_TAG); 987 } 988 989 // 990 // Handles post-process completion for driver-created-requests queued by the driver. 991 // On return the driver can delete the request with WdfObjectDelete. 992 // NOTE: request may be already gone/reused. Do not dereference this or access any of its 993 // members... its pointer is only used for logging. 994 // 995 VOID 996 FxRequest::PostProcessCompletionForDriverRequest( 997 __in FxRequestCompletionState State, 998 __in FxIoQueue* Queue 999 ) 1000 { 1001 // 1002 // NOTE: Do not touch the request object here. The request object may already be 1003 // re-used or deleted. 1004 // 1005 1006 ASSERT(State == FxRequestCompletionStateNone || 1007 State == FxRequestCompletionStateQueue); 1008 // 1009 // Fire frameworks internal callback (post) event if one is set. 1010 // 1011 if (FxRequestCompletionStateQueue == State) { 1012 // 1013 // NOTE: This occurs after the IRP has already been released, and is only used 1014 // to notify the queue to update its internal state and if appropriate, send 1015 // another request. 1016 // 1017 Queue->PostRequestCompletedCallback(this); 1018 } 1019 } 1020 1021 VOID 1022 FxRequest::FreeRequest( 1023 VOID 1024 ) 1025 /*++ 1026 1027 Routine Description: 1028 1029 This routine is called to free a reserved request or in case of Fxpkgio 1030 a non-reserved request. 1031 1032 --*/ 1033 { 1034 // 1035 // Restore any fields if necessary 1036 // 1037 if (m_RequestContext != NULL) { 1038 // 1039 // m_RequestContext will be freed when the FxRequest's destructor runs 1040 // 1041 m_RequestContext->ReleaseAndRestore(this); 1042 } 1043 1044 // 1045 // If the request is not presented to the driver then clear the 1046 // cleanup & destroy callbacks before calling PerformEarlyDispose. 1047 // 1048 if (m_Presented == FALSE) { 1049 ClearEvtCallbacks(); 1050 } 1051 1052 DeleteObject(); 1053 } 1054 1055 VOID 1056 FX_VF_METHOD(FxRequest, VerifyPreProcessSendAndForget) ( 1057 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals 1058 ) 1059 { 1060 PAGED_CODE_LOCKED(); 1061 1062 if (m_CompletionRoutine.m_Completion != NULL) { 1063 DoTraceLevelMessage( 1064 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 1065 "WDFREQUEST %p cannot send and forget will not execute completion " 1066 "routine %p", 1067 GetHandle(), m_CompletionRoutine.m_Completion); 1068 1069 FxVerifierDbgBreakPoint(FxDriverGlobals); 1070 1071 1072 1073 1074 1075 1076 1077 1078 } 1079 1080 // 1081 // You cannot fire and forget a create irp if we created a WDFFILEOBJECT 1082 // for it since you must post process the status of the create because 1083 // the create can fail in the driver to which we are sending the irp. 1084 // 1085 if ((m_Irp.GetMajorFunction() == IRP_MJ_CREATE) 1086 && 1087 (FxFileObjectClassNormalize(GetDevice()->GetFileObjectClass()) != 1088 WdfFileObjectNotRequired)) { 1089 1090 DoTraceLevelMessage( 1091 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 1092 "WDFREQUEST %p cannot send and forget a create request which " 1093 "has a WDFFILEOBJECT created for it, it must have a completion " 1094 "routine and be post processsed", GetHandle()); 1095 1096 FxVerifierDbgBreakPoint(FxDriverGlobals); 1097 } 1098 } 1099 1100 VOID 1101 FxRequest::PreProcessSendAndForget( 1102 VOID 1103 ) 1104 { 1105 VerifyPreProcessSendAndForget(GetDriverGlobals()); 1106 1107 // 1108 // To be sent and forgotten, the irp must have been presented 1109 // 1110 ASSERT(m_Presented); 1111 1112 // 1113 // To be sent and forgotten, the irp must not have a formatted IO context. 1114 // 1115 ASSERT(HasContext() == FALSE); 1116 1117 // 1118 // If the driver writer setup the next stack location using the current 1119 // stack location or did a manual IO_STACK_LOCATION copy, we do not want to 1120 // skip the current stack location that their format is used by the target 1121 // driver. 1122 // 1123 if (m_NextStackLocationFormatted == FALSE) { 1124 m_Irp.SkipCurrentIrpStackLocation(); 1125 } 1126 1127 if (IsReserved() == FALSE) { 1128 1129 // 1130 // If a cleanup callback has been registered, we call it 1131 // just before sending the IRP on its way. The contract is that the cleanup 1132 // routine for a WDFREQUEST is called while the PIRP is still valid. 1133 // 1134 if (EarlyDispose() == FALSE) { 1135 VerifierBreakpoint_RequestEarlyDisposeDeferred(GetDriverGlobals()); 1136 } 1137 1138 // 1139 // Now that the entire tree is disposed, we want to destroy all of the 1140 // children. This will not put this object in the destroyed state. For 1141 // m_IrpReferenceCount to go to zero, we need to destroy the child WDFMEMORYs 1142 // that were created when we probed and locked the buffers. 1143 // 1144 DestroyChildren(); 1145 } 1146 } 1147 1148 VOID 1149 FxRequest::PostProcessSendAndForget( 1150 VOID 1151 ) 1152 { 1153 FxRequestCompletionState state; 1154 FxIoQueue* pQueue; 1155 1156 m_Irp.SetIrp(NULL); 1157 1158 // 1159 // Capture the m_IoQueue value before making any other calls. 1160 // Note: m_IoQueue could be NULL if the request is freed before it's queued. 1161 // 1162 pQueue = m_IoQueue; 1163 1164 ASSERT(m_CompletionState != FxRequestCompletionStateNone); 1165 1166 state = (FxRequestCompletionState) m_CompletionState; 1167 m_CompletionState = FxRequestCompletionStateNone; 1168 1169 // 1170 // Technically we did not complete the irp, but a send and forget is 1171 // functionally the same. We no longer own the irp. 1172 // 1173 if (IsReserved() == FALSE) { 1174 PostProcessCompletion(state, pQueue); 1175 } 1176 else { 1177 // 1178 // Release checks m_Completed flag to decide whether to return 1179 // the request to reserved pool. 1180 // 1181 m_Completed = TRUE; 1182 PostProcessCompletionForReserved(state, pQueue); 1183 } 1184 } 1185 1186 NTSTATUS 1187 FxRequest::GetStatus( 1188 VOID 1189 ) 1190 { 1191 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1192 NTSTATUS status; 1193 1194 pFxDriverGlobals = GetDriverGlobals(); 1195 1196 if (pFxDriverGlobals->FxVerifierIO) { 1197 KIRQL irql; 1198 1199 Lock(&irql); 1200 1201 1202 1203 1204 1205 1206 1207 1208 status = m_Irp.GetStatus(); 1209 1210 Unlock(irql); 1211 1212 return status; 1213 } 1214 else { 1215 return m_Irp.GetStatus(); 1216 } 1217 } 1218 1219 _Must_inspect_result_ 1220 NTSTATUS 1221 FxRequest::GetParameters( 1222 __out PWDF_REQUEST_PARAMETERS Parameters 1223 ) 1224 { 1225 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1226 1227 pFxDriverGlobals = GetDriverGlobals(); 1228 1229 // 1230 // No lock needed. Only reason this may be invalid is due 1231 // to previous completion, which is a serious driver bug 1232 // that will result in a crash anyway. 1233 // 1234 1235 if (pFxDriverGlobals->FxVerifierIO) { 1236 KIRQL irql; 1237 NTSTATUS status; 1238 1239 Lock(&irql); 1240 1241 status = VerifyRequestIsCurrentStackValid(pFxDriverGlobals); 1242 if (NT_SUCCESS(status)) { 1243 status = VerifyRequestIsNotCompleted(pFxDriverGlobals); 1244 } 1245 1246 Unlock(irql); 1247 1248 if (!NT_SUCCESS(status)) { 1249 return status; 1250 } 1251 } 1252 1253 ASSERT(Parameters->Size >= sizeof(WDF_REQUEST_PARAMETERS)); 1254 1255 // How much we copied 1256 Parameters->Size = sizeof(WDF_REQUEST_PARAMETERS); 1257 1258 1259 // Copy parameters 1260 Parameters->Type = (WDF_REQUEST_TYPE)m_Irp.GetMajorFunction(); 1261 Parameters->MinorFunction = m_Irp.GetMinorFunction(); 1262 1263 // Copy the Parameters structure which we are a subset of 1264 m_Irp.CopyParameters(Parameters); 1265 1266 if (pFxDriverGlobals->FxVerifierIO) { 1267 // 1268 // If verifier is on, and the operation is an IRP_MJ_DEVICE_CONTROL 1269 // with METHOD_NEITHER, then set Type3InputBuffer to zero since 1270 // this should not be used to pass parameters in the normal path 1271 // 1272 if((m_Irp.GetMajorFunction() == IRP_MJ_DEVICE_CONTROL) && 1273 m_Irp.GetParameterIoctlCodeBufferMethod() == METHOD_NEITHER) { 1274 Parameters->Parameters.DeviceIoControl.Type3InputBuffer = NULL; 1275 } 1276 } 1277 1278 return STATUS_SUCCESS; 1279 } 1280 1281 1282 _Must_inspect_result_ 1283 NTSTATUS 1284 FxRequest::GetMemoryObject( 1285 __deref_out IFxMemory** MemoryObject, 1286 __out PVOID* Buffer, 1287 __out size_t* Length 1288 ) 1289 { 1290 PMDL pMdl; 1291 NTSTATUS status; 1292 ULONG length; 1293 KIRQL irql; 1294 BOOLEAN mapMdl; 1295 UCHAR majorFunction; 1296 1297 status = STATUS_SUCCESS; 1298 length = 0x0; 1299 mapMdl = FALSE; 1300 irql = PASSIVE_LEVEL; 1301 majorFunction = m_Irp.GetMajorFunction(); 1302 1303 1304 // 1305 // Verifier 1306 // 1307 if (GetDriverGlobals()->FxVerifierIO) { 1308 status = VerifyRequestIsNotCompleted(GetDriverGlobals()); 1309 if (!NT_SUCCESS(status)) { 1310 goto Done; 1311 } 1312 if (m_Irp.GetRequestorMode() == UserMode 1313 && 1314 (majorFunction == IRP_MJ_WRITE || 1315 majorFunction == IRP_MJ_READ) 1316 && 1317 GetDevice()->GetIoType() == WdfDeviceIoNeither) { 1318 status = STATUS_INVALID_DEVICE_REQUEST; 1319 1320 DoTraceLevelMessage( 1321 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 1322 "Attempt to get UserMode Buffer Pointer for WDFDEVICE 0x%p, " 1323 "WDFREQUEST 0x%p, %!STATUS!", 1324 GetDevice()->GetHandle(), GetHandle(), status); 1325 1326 DoTraceLevelMessage( 1327 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 1328 "Driver must use buffered or direct I/O for this call, or use " 1329 "WdfDeviceInitSetIoInCallerContextCallback to probe and lock " 1330 "user mode memory"); 1331 1332 FxVerifierDbgBreakPoint(GetDriverGlobals()); 1333 } 1334 } 1335 1336 if ((m_RequestBaseStaticFlags & FxRequestBaseStaticSystemBufferValid) == 0x00) { 1337 Lock(&irql); 1338 } 1339 1340 // 1341 // We must dig into the IRP to get the buffer, length, and readonly status 1342 // 1343 1344 switch (majorFunction) { 1345 case IRP_MJ_DEVICE_CONTROL: 1346 case IRP_MJ_INTERNAL_DEVICE_CONTROL: 1347 length = m_Irp.GetParameterIoctlInputBufferLength(); 1348 1349 if (length == 0) { 1350 status = STATUS_BUFFER_TOO_SMALL; 1351 1352 DoTraceLevelMessage( 1353 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 1354 "WDFREQUEST %p InputBufferLength length is zero, %!STATUS!", 1355 GetObjectHandle(), status); 1356 1357 goto Done; 1358 } 1359 1360 if (m_Irp.GetParameterIoctlCodeBufferMethod() == METHOD_NEITHER) { 1361 // 1362 // Internal device controls are kernel mode to kernel mode, and deal 1363 // with direct unmapped pointers. 1364 // 1365 // In addition, a normal device control with 1366 // RequestorMode == KernelMode is also treated as kernel mode 1367 // to kernel mode since the I/O Manager will not generate requests 1368 // with this setting from a user mode request. 1369 // 1370 if ((m_Irp.GetRequestorMode() == KernelMode) || 1371 (majorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL)) { 1372 DO_NOTHING(); 1373 } 1374 else { 1375 status = STATUS_INVALID_DEVICE_REQUEST; 1376 1377 DoTraceLevelMessage( 1378 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 1379 "Attempt to get UserMode Buffer Pointer for METHOD_NEITHER " 1380 "DeviceControl 0x%x, WDFDEVICE 0x%p, WDFREQUEST 0x%p, " 1381 "%!STATUS!", 1382 m_Irp.GetParameterIoctlCode(), 1383 GetDevice()->GetHandle(), GetHandle(), status); 1384 1385 DoTraceLevelMessage( 1386 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 1387 "Driver must use METHOD_BUFFERED or METHOD_xx_DIRECT I/O for " 1388 "this call, or use WdfDeviceInitSetIoInCallerContextCallback to " 1389 "probe and lock user mode memory %!STATUS!", 1390 STATUS_INVALID_DEVICE_REQUEST); 1391 1392 goto Done; 1393 } 1394 } 1395 break; 1396 1397 case IRP_MJ_READ: 1398 length = m_Irp.GetParameterReadLength(); 1399 1400 if (GetDevice()->GetIoTypeForReadWriteBufferAccess() == WdfDeviceIoDirect) { 1401 KMDF_ONLY_CODE_PATH_ASSERT(); 1402 mapMdl = TRUE; 1403 } 1404 break; 1405 1406 case IRP_MJ_WRITE: 1407 length = m_Irp.GetParameterWriteLength(); 1408 1409 if (GetDevice()->GetIoTypeForReadWriteBufferAccess() == WdfDeviceIoDirect) { 1410 KMDF_ONLY_CODE_PATH_ASSERT(); 1411 mapMdl = TRUE; 1412 } 1413 break; 1414 1415 default: 1416 DoTraceLevelMessage( 1417 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 1418 "Unrecognized Major Function 0x%x on WDFDEVICE 0x%p WDFREQUEST 0x%p", 1419 majorFunction, GetDevice()->GetHandle(), GetHandle()); 1420 1421 FxVerifierDbgBreakPoint(GetDriverGlobals()); 1422 1423 status = STATUS_INVALID_DEVICE_REQUEST; 1424 goto Done; 1425 } 1426 1427 if (length == 0) { 1428 status = STATUS_BUFFER_TOO_SMALL; 1429 1430 DoTraceLevelMessage( 1431 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 1432 "WDFREQUEST 0x%p length is zero, %!STATUS!", 1433 GetHandle(), status); 1434 1435 goto Done; 1436 } 1437 1438 // 1439 // See if we need to map 1440 // 1441 if (mapMdl && (m_RequestBaseFlags & FxRequestBaseSystemMdlMapped) == 0x00) { 1442 pMdl = m_Irp.GetMdl(); 1443 1444 if (pMdl == NULL) { 1445 // 1446 // Zero length transfer 1447 // 1448 status = STATUS_BUFFER_TOO_SMALL; 1449 1450 DoTraceLevelMessage( 1451 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 1452 "WDFREQUEST 0x%p, direct io device, PMDL is NULL, " 1453 "%!STATUS!", GetHandle(), status); 1454 1455 ASSERT(length == 0); 1456 } 1457 else { 1458 PVOID pVA; 1459 1460 // 1461 // PagePriority may need to be a property, and/or parameter to 1462 // this call 1463 // 1464 // 1465 // Upon success, MmGetSystemAddressForMdlSafe stores the mapped 1466 // VA pointer in the pMdl and upon subsequent calls to 1467 // MmGetSystemAddressForMdlSafe, no mapping is done, just 1468 // the stored VA is returned. FxRequestSystemBuffer relies 1469 // on this behavior and, more importantly, relies on this function 1470 // to do the initial mapping so that FxRequestSystemBuffer::GetBuffer() 1471 // will not return a NULL pointer. 1472 // 1473 pVA = Mx::MxGetSystemAddressForMdlSafe(pMdl, NormalPagePriority); 1474 1475 if (pVA == NULL) { 1476 status = STATUS_INSUFFICIENT_RESOURCES; 1477 1478 DoTraceLevelMessage( 1479 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 1480 "WDFREQUEST 0x%p could not get a system address for PMDL " 1481 "0x%p, %!STATUS!", GetHandle(), pMdl, status); 1482 } 1483 else { 1484 // 1485 // System will automatically release the mapping PTE's when 1486 // the MDL is released by the I/O request 1487 // 1488 1489 1490 1491 1492 1493 m_SystemBuffer.SetMdl(m_Irp.GetMdl()); 1494 1495 m_RequestBaseFlags |= FxRequestBaseSystemMdlMapped; 1496 } 1497 } 1498 } 1499 1500 Done: 1501 if ((m_RequestBaseStaticFlags & FxRequestBaseStaticSystemBufferValid) == 0x00) { 1502 Unlock(irql); 1503 } 1504 1505 if (NT_SUCCESS(status)) { 1506 *MemoryObject = &m_SystemBuffer; 1507 1508 if (mapMdl) { 1509 *Buffer = Mx::MxGetSystemAddressForMdlSafe(m_SystemBuffer.m_Mdl, 1510 NormalPagePriority); 1511 } 1512 else { 1513 *Buffer = m_SystemBuffer.m_Buffer; 1514 } 1515 1516 *Length = length; 1517 } 1518 1519 return status; 1520 } 1521 1522 _Must_inspect_result_ 1523 NTSTATUS 1524 FxRequest::GetDeviceControlOutputMemoryObject( 1525 __deref_out IFxMemory** MemoryObject, 1526 __out PVOID* Buffer, 1527 __out size_t* Length 1528 ) 1529 /*++ 1530 1531 Routine Description: 1532 1533 Return the IRP_MJ_DEVICE_CONTROL OutputBuffer. 1534 1535 The memory buffer is valid in any thread/process context, 1536 and may be accessed at IRQL > PASSIVE_LEVEL. 1537 1538 The memory buffer is automatically released when the request 1539 is completed. 1540 1541 The memory buffer is not valid for a METHOD_NEITHER IRP_MJ_DEVICE_CONTROL, 1542 or for any request other than IRP_MJ_DEVICE_CONTROL. 1543 1544 The Memory buffer is as follows for each buffering mode: 1545 1546 METHOD_BUFFERED: 1547 1548 Irp->UserBuffer // This is actually a system address 1549 1550 METHOD_IN_DIRECT: 1551 1552 MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) 1553 1554 METHOD_OUT_DIRECT: 1555 1556 MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) 1557 1558 METHOD_NEITHER: 1559 1560 NULL. Must use WdfDeviceInitSetIoInCallerContextCallback in order 1561 to access the request in the calling threads address space before 1562 it is placed into any I/O Queues. 1563 1564 The buffer is only valid until the request is completed. 1565 1566 Arguments: 1567 1568 MemoryObject - Pointer location to return the memory object interface. 1569 1570 Buffer - Pointer location to return buffer ptr 1571 1572 Length - Pointer location to return buffer length. 1573 1574 Returns: 1575 1576 NTSTATUS 1577 1578 --*/ 1579 { 1580 size_t length; 1581 NTSTATUS status; 1582 KIRQL irql; 1583 BOOLEAN mapMdl; 1584 UCHAR majorFunction; 1585 1586 UNREFERENCED_PARAMETER(Buffer); 1587 UNREFERENCED_PARAMETER(Length); 1588 1589 status = STATUS_SUCCESS; 1590 length = 0; 1591 irql = PASSIVE_LEVEL; 1592 mapMdl = FALSE; 1593 1594 // 1595 // Verifier 1596 // 1597 if (GetDriverGlobals()->FxVerifierIO ) { 1598 status = VerifyRequestIsNotCompleted(GetDriverGlobals()); 1599 if (!NT_SUCCESS(status)) { 1600 return status; 1601 } 1602 } 1603 1604 if ((m_RequestBaseStaticFlags & FxRequestBaseStaticOutputBufferValid) == 0x00) { 1605 Lock(&irql); 1606 } 1607 1608 // 1609 // See if we already have a validated buffer 1610 // 1611 //if (m_RequestBaseFlags & FxRequestBaseOutputBufferValid) { 1612 // status = STATUS_SUCCESS; 1613 //} 1614 1615 majorFunction = m_Irp.GetMajorFunction(); 1616 1617 ASSERT(majorFunction == IRP_MJ_DEVICE_CONTROL || 1618 majorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL); 1619 1620 length = m_Irp.GetParameterIoctlOutputBufferLength(); 1621 1622 if (length == 0) { 1623 status = STATUS_BUFFER_TOO_SMALL; 1624 1625 DoTraceLevelMessage( 1626 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 1627 "WDFREQUEST 0x%p IOCTL output buffer length is zero, %!STATUS!", 1628 GetHandle(), status); 1629 1630 goto Done; 1631 } 1632 1633 switch (m_Irp.GetParameterIoctlCodeBufferMethod()) { 1634 // 1635 // InputBuffer is in SystemBuffer 1636 // OutputBuffer is in MdlAddress with read access 1637 // 1638 case METHOD_IN_DIRECT: 1639 // || || fall || || 1640 // \/ \/ through \/ \/ 1641 1642 // 1643 // InputBuffer is in SystemBuffer 1644 // OutputBuffer is in MdlAddress with read access 1645 // 1646 case METHOD_OUT_DIRECT: 1647 mapMdl = TRUE; 1648 break; 1649 1650 case METHOD_NEITHER: 1651 // 1652 // Internal device controls are kernel mode to kernel mode, and deal 1653 // with direct unmapped pointers. 1654 // 1655 // In addition, a normal device control with 1656 // RequestorMode == KernelMode is also treated as kernel mode 1657 // to kernel mode since the I/O Manager will not generate requests 1658 // with this setting from a user mode request. 1659 // 1660 if ((m_Irp.GetRequestorMode() == KernelMode) || 1661 (majorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL)) { 1662 DO_NOTHING(); 1663 } 1664 else { 1665 status = STATUS_INVALID_DEVICE_REQUEST; 1666 1667 DoTraceLevelMessage( 1668 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 1669 "Attempt to get UserMode Buffer Pointer for " 1670 "METHOD_NEITHER DeviceControl 0x%x, WDFDEVICE 0x%p, " 1671 "WDFREQUEST 0x%p, %!STATUS!", 1672 m_Irp.GetParameterIoctlCode(), 1673 GetDevice()->GetHandle(), GetObjectHandle(), status); 1674 1675 DoTraceLevelMessage( 1676 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 1677 "Driver must use METHOD_BUFFERED or METHOD_xx_DIRECT " 1678 "I/O for this call, or use " 1679 "WdfDeviceInitSetIoInCallerContextCallback to probe and " 1680 "lock user mode memory"); 1681 } 1682 break; 1683 } 1684 1685 if (mapMdl && (m_RequestBaseFlags & FxRequestBaseOutputMdlMapped) == 0x0) { 1686 PMDL pMdl; 1687 PVOID pVA; 1688 1689 1690 pMdl = m_Irp.GetMdl(); 1691 1692 if (pMdl == NULL) { 1693 // 1694 // Zero length transfer 1695 // 1696 status = STATUS_BUFFER_TOO_SMALL; 1697 1698 DoTraceLevelMessage( 1699 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 1700 "WDFREQUEST 0x%p, METHOD_IN_DIRECT IOCTL PMDL is NULL, " 1701 "%!STATUS!", GetHandle(), status); 1702 1703 ASSERT( 1704 m_Irp.GetParameterIoctlOutputBufferLength()== 0 1705 ); 1706 } 1707 else { 1708 // 1709 // PagePriority may need to be a property, and/or parameter to 1710 // this call 1711 // 1712 // 1713 // Upon success, MmGetSystemAddressForMdlSafe stores the mapped 1714 // VA pointer in the pMdl and upon subsequent calls to 1715 // MmGetSystemAddressForMdlSafe, no mapping is done, just 1716 // the stored VA is returned. FxRequestOutputBuffer relies 1717 // on this behavior and, more importantly, relies on this function 1718 // to do the initial mapping so that FxRequestOutputBuffer::GetBuffer() 1719 // will not return a NULL pointer. 1720 // 1721 pVA = Mx::MxGetSystemAddressForMdlSafe(pMdl, NormalPagePriority); 1722 1723 if (pVA == NULL) { 1724 status = STATUS_INSUFFICIENT_RESOURCES; 1725 1726 DoTraceLevelMessage( 1727 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 1728 "WDFREQUEST 0x%p could not get a system address for PMDL" 1729 "0x%p, %!STATUS!", GetHandle(), pMdl, status); 1730 } 1731 else { 1732 m_OutputBuffer.SetMdl(pMdl); 1733 m_RequestBaseFlags |= FxRequestBaseOutputMdlMapped; 1734 status = STATUS_SUCCESS; 1735 } 1736 } 1737 } 1738 1739 Done: 1740 if ((m_RequestBaseStaticFlags & FxRequestBaseStaticOutputBufferValid) == 0x00) { 1741 Unlock(irql); 1742 } 1743 1744 if (NT_SUCCESS(status)) { 1745 *MemoryObject = &m_OutputBuffer; 1746 if (mapMdl) { 1747 *Buffer = Mx::MxGetSystemAddressForMdlSafe(m_OutputBuffer.m_Mdl, 1748 NormalPagePriority); 1749 } 1750 else { 1751 *Buffer = m_OutputBuffer.m_Buffer; 1752 } 1753 *Length = length; 1754 } 1755 1756 return status; 1757 } 1758 1759 FxRequestCompletionState 1760 FxRequest::SetCompletionState( 1761 __in FxRequestCompletionState NewState 1762 ) 1763 { 1764 FxRequestCompletionState oldState; 1765 1766 // 1767 // The flag by itself should never be specified 1768 // 1769 ASSERT(NewState != FxRequestCompletionStateIoPkgFlag); 1770 1771 // 1772 // No need to lock. Only the "owner" can set the completion 1773 // callback function, and this is when under the general 1774 // FxIoQueue lock. 1775 // 1776 1777 // Request is already completed, awaiting final dereference 1778 if (m_Completed) { 1779 oldState = FxRequestCompletionStateNone; 1780 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 1781 "WDFREQUEST 0x%p has already been completed", 1782 GetHandle()); 1783 FxVerifierDbgBreakPoint(GetDriverGlobals()); 1784 } 1785 else { 1786 ASSERT(m_Irp.GetIrp() != NULL); 1787 1788 oldState = (FxRequestCompletionState) m_CompletionState; 1789 1790 m_CompletionState = (BYTE) NewState; 1791 1792 if (NewState == FxRequestCompletionStateNone && 1793 oldState != FxRequestCompletionStateNone) { 1794 // 1795 // Cancelling a callback, so release the callback reference 1796 // 1797 RELEASE(FXREQUEST_STATE_TAG); 1798 } 1799 else if (NewState != FxRequestCompletionStateNone && 1800 oldState == FxRequestCompletionStateNone) { 1801 // 1802 // Adding a callback requires a reference 1803 // 1804 ADDREF(FXREQUEST_STATE_TAG); 1805 } 1806 else { 1807 // 1808 // else we leave the current reference alone 1809 // 1810 DO_NOTHING(); 1811 } 1812 } 1813 1814 return oldState; 1815 } 1816 1817 _Must_inspect_result_ 1818 NTSTATUS 1819 FX_VF_METHOD(FxRequest, VerifyInsertIrpQueue) ( 1820 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, 1821 _In_ FxIrpQueue* IrpQueue 1822 ) 1823 { 1824 NTSTATUS status; 1825 1826 PAGED_CODE_LOCKED(); 1827 1828 // 1829 // Check to make sure we are not already in an Irp queue 1830 // 1831 if (m_IrpQueue != NULL) { 1832 status = STATUS_INTERNAL_ERROR; 1833 1834 DoTraceLevelMessage( 1835 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 1836 "Already in FxIrpQueue 0x%p WDFREQUEST 0x%p %!STATUS!", 1837 IrpQueue, GetHandle(), status); 1838 1839 FxVerifierDbgBreakPoint(FxDriverGlobals); 1840 1841 goto Done; 1842 } 1843 1844 // 1845 // If request is completed, fail. 1846 // This is because the driver can complete the request 1847 // right away in another thread while returning STATUS_PENDING 1848 // from EvtIoDefault 1849 // 1850 status = VerifyRequestIsNotCompleted(FxDriverGlobals); 1851 1852 Done: 1853 return status; 1854 } 1855 1856 _Must_inspect_result_ 1857 NTSTATUS 1858 FxRequest::InsertTailIrpQueue( 1859 __in FxIrpQueue* IrpQueue, 1860 __out_opt ULONG* pRequestCount 1861 ) 1862 { 1863 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1864 NTSTATUS status; 1865 1866 pFxDriverGlobals = GetDriverGlobals(); 1867 1868 // No locking required since only one accessor till inserted on queue 1869 1870 status = VerifyInsertIrpQueue(pFxDriverGlobals, IrpQueue); 1871 if (!NT_SUCCESS(status)) { 1872 return status; 1873 } 1874 1875 // 1876 // If a request is on an IrpQueue, it must be referenced 1877 // 1878 1879 1880 1881 1882 1883 1884 ADDREF(FXREQUEST_QUEUE_TAG); 1885 1886 ASSERT(m_Completed == FALSE); 1887 ASSERT(m_IrpQueue == NULL); 1888 1889 m_IrpQueue = IrpQueue; 1890 1891 status = IrpQueue->InsertTailRequest(m_Irp.GetIrp(), 1892 &m_CsqContext, 1893 pRequestCount); 1894 1895 // 1896 // If this insert failed, we must release the extra reference we took 1897 // 1898 if (!NT_SUCCESS(status)) { 1899 MarkRemovedFromIrpQueue(); 1900 RELEASE(FXREQUEST_QUEUE_TAG); 1901 } 1902 1903 return status; 1904 } 1905 1906 _Must_inspect_result_ 1907 NTSTATUS 1908 FxRequest::InsertHeadIrpQueue( 1909 __in FxIrpQueue* IrpQueue, 1910 __out_opt ULONG* pRequestCount 1911 ) 1912 { 1913 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1914 NTSTATUS status; 1915 1916 pFxDriverGlobals = GetDriverGlobals(); 1917 1918 // No locking required since only one accessor till inserted on queue 1919 1920 status = VerifyInsertIrpQueue(pFxDriverGlobals, IrpQueue); 1921 if (!NT_SUCCESS(status)) { 1922 return status; 1923 } 1924 1925 // 1926 // If a request is on an IrpQueue, it must be referenced 1927 // 1928 1929 1930 1931 1932 1933 1934 ADDREF(FXREQUEST_QUEUE_TAG); 1935 1936 ASSERT(m_Completed == FALSE); 1937 ASSERT(m_IrpQueue == NULL); 1938 1939 m_IrpQueue = IrpQueue; 1940 1941 status = IrpQueue->InsertHeadRequest(m_Irp.GetIrp(), 1942 &m_CsqContext, 1943 pRequestCount); 1944 1945 // 1946 // If this insert failed, we must release the extra reference we took 1947 // 1948 if (!NT_SUCCESS(status)) { 1949 MarkRemovedFromIrpQueue(); 1950 RELEASE(FXREQUEST_QUEUE_TAG); 1951 } 1952 1953 return status; 1954 } 1955 1956 // 1957 // Remove request from its IRP queue 1958 // 1959 _Must_inspect_result_ 1960 NTSTATUS 1961 FxRequest::RemoveFromIrpQueue( 1962 __in FxIrpQueue* IrpQueue 1963 ) 1964 { 1965 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1966 MdIrp pIrp; 1967 1968 pFxDriverGlobals = GetDriverGlobals(); 1969 1970 // 1971 // Cancel Safe Queues allow this request 1972 // removal to be race free even if the 1973 // request has been cancelled already. 1974 // 1975 // It signals this by returning NULL for 1976 // the Irp. 1977 // 1978 pIrp = IrpQueue->RemoveRequest(&m_CsqContext); 1979 1980 if (pIrp == NULL) { 1981 1982 // 1983 // Cancel routine removed it from the cancel 1984 // safe queue. 1985 // 1986 // The cancel handler will remove this reference 1987 // in FxIoQueue::_IrpCancelForDriver / 1988 // FxIrpQueue::_WdmCancelRoutineInternal 1989 // 1990 1991 return STATUS_CANCELLED; 1992 } 1993 else { 1994 1995 // 1996 // We retrieved the Irp from the cancel safe queue 1997 // without it having been cancelled first. 1998 // 1999 // It is no longer cancelable 2000 // 2001 if (pFxDriverGlobals->FxVerifierOn) { 2002 if (m_IrpQueue == NULL) { 2003 DoTraceLevelMessage( 2004 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2005 "WDFREQUEST 0x%p not on IrpQueue", 2006 GetHandle()); 2007 2008 FxVerifierDbgBreakPoint(pFxDriverGlobals); 2009 } 2010 } 2011 2012 MarkRemovedFromIrpQueue(); 2013 2014 RELEASE(FXREQUEST_QUEUE_TAG); 2015 2016 return STATUS_SUCCESS; 2017 } 2018 } 2019 2020 // 2021 // Function to return the next FxRequest from an FxIrpQueue 2022 // 2023 _Must_inspect_result_ 2024 FxRequest* 2025 FxRequest::GetNextRequest( 2026 __in FxIrpQueue* IrpQueue 2027 ) 2028 { 2029 MdIrp pIrp; 2030 FxRequest* pRequest; 2031 PMdIoCsqIrpContext pCsqContext; 2032 2033 pIrp = IrpQueue->GetNextRequest(&pCsqContext); 2034 2035 if (pIrp == NULL) { 2036 return NULL; 2037 } 2038 2039 // Irp is not cancellable now 2040 pRequest = FxRequest::RetrieveFromCsqContext(pCsqContext); 2041 2042 // Must tell the request it's off the queue 2043 pRequest->MarkRemovedFromIrpQueue(); 2044 2045 // Remove reference placed when on IrpQueue 2046 pRequest->RELEASE(FXREQUEST_QUEUE_TAG); 2047 2048 return pRequest; 2049 } 2050 2051 // 2052 // Function to return an FxRequest from an FxIrpQueue based 2053 // on optional context and/or file object. 2054 // 2055 _Must_inspect_result_ 2056 NTSTATUS 2057 FxRequest::GetNextRequest( 2058 __in FxIrpQueue* IrpQueue, 2059 __in_opt MdFileObject FileObject, 2060 __in_opt FxRequest* TagRequest, 2061 __deref_out FxRequest** ppOutRequest 2062 ) 2063 { 2064 NTSTATUS Status; 2065 FxRequest* pRequest; 2066 PMdIoCsqIrpContext TagCsqContext; 2067 2068 if( TagRequest != NULL ) { 2069 TagCsqContext = TagRequest->GetCsqContext(); 2070 } 2071 else { 2072 TagCsqContext = NULL; 2073 } 2074 2075 Status = IrpQueue->GetNextRequest( TagCsqContext, FileObject, &pRequest ); 2076 if( !NT_SUCCESS(Status) ) { 2077 return Status; 2078 } 2079 2080 // Irp is not cancellable now 2081 2082 // Must tell the request its off the queue 2083 pRequest->MarkRemovedFromIrpQueue(); 2084 2085 // Remove reference placed when on IrpQueue 2086 pRequest->RELEASE(FXREQUEST_QUEUE_TAG); 2087 2088 *ppOutRequest = pRequest; 2089 2090 return STATUS_SUCCESS; 2091 } 2092 2093 // 2094 // Allow peeking at requests in the IrpQueue 2095 // 2096 _Must_inspect_result_ 2097 NTSTATUS 2098 FxRequest::PeekRequest( 2099 __in FxIrpQueue* IrpQueue, 2100 __in_opt FxRequest* TagRequest, 2101 __in_opt MdFileObject FileObject, 2102 __out_opt PWDF_REQUEST_PARAMETERS Parameters, 2103 __deref_out FxRequest** ppOutRequest 2104 ) 2105 { 2106 NTSTATUS Status; 2107 2108 PMdIoCsqIrpContext TagContext = NULL; 2109 2110 // 2111 // IrpQueue::PeekRequest works with CSQ_CONTEXT 2112 // structures since this is the only value that 2113 // is valid across cancellation. 2114 // 2115 if( TagRequest != NULL ) { 2116 TagContext = TagRequest->GetCsqContext(); 2117 } 2118 2119 Status = IrpQueue->PeekRequest( 2120 TagContext, 2121 FileObject, 2122 ppOutRequest 2123 ); 2124 if(NT_SUCCESS(Status)) { 2125 2126 if( Parameters != NULL ) { 2127 Status = (*ppOutRequest)->GetParameters(Parameters); 2128 } 2129 } 2130 2131 return Status; 2132 } 2133 2134 _Must_inspect_result_ 2135 NTSTATUS 2136 FxRequest::Reuse( 2137 __in PWDF_REQUEST_REUSE_PARAMS ReuseParams 2138 ) 2139 { 2140 FxIrp currentIrp; 2141 PFX_DRIVER_GLOBALS pFxDriverGlobals = GetDriverGlobals(); 2142 2143 // 2144 // Make sure request is not pended in IoTarget. 2145 // 2146 if (pFxDriverGlobals->IsVerificationEnabled(1, 9, OkForDownLevel)) { 2147 SHORT flags; 2148 KIRQL irql; 2149 2150 Lock(&irql); 2151 flags = GetVerifierFlagsLocked(); 2152 if (flags & FXREQUEST_FLAG_SENT_TO_TARGET) { 2153 DoTraceLevelMessage( 2154 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2155 "Driver is trying to reuse WDFREQUEST 0x%p while it is still " 2156 "active on WDFIOTARGET 0x%p. ", 2157 GetTraceObjectHandle(), GetTarget()->GetHandle()); 2158 FxVerifierDbgBreakPoint(pFxDriverGlobals); 2159 } 2160 Unlock(irql); 2161 } 2162 2163 // 2164 // For drivers 1.9 and above (for maintaining backwards compatibility) 2165 // deregister previously registered completion routine. 2166 // 2167 if (pFxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,9)) { 2168 SetCompletionRoutine(NULL, NULL); 2169 } 2170 2171 currentIrp.SetIrp(m_Irp.GetIrp()); 2172 2173 if (currentIrp.GetIrp() != NULL) { 2174 // 2175 // Release all outstanding references and restore original fields in 2176 // the PIRP 2177 // 2178 if (m_RequestContext != NULL) { 2179 m_RequestContext->ReleaseAndRestore(this); 2180 } 2181 2182 if (m_IrpAllocation == REQUEST_ALLOCATED_FROM_IO) { 2183 // 2184 // An irp presented by io queue can only reset a limited state 2185 // 2186 if (ReuseParams->Flags & WDF_REQUEST_REUSE_SET_NEW_IRP) { 2187 // 2188 // Not allowed to set a new irp 2189 // 2190 return STATUS_WDF_REQUEST_INVALID_STATE; 2191 } 2192 2193 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 2194 currentIrp.SetStatus(ReuseParams->Status); 2195 currentIrp.SetCancel(FALSE); 2196 #else 2197 // 2198 // For UMDF, host sets cancel flag to false as part of Reuse(), so no 2199 // need to have a separate call for UMDF (that's why host irp doesn't 2200 // expose any interface to set this independently). 2201 2202 2203 2204 2205 // 2206 currentIrp.Reuse(ReuseParams->Status); 2207 #endif 2208 m_Completed = FALSE; 2209 m_Canceled = FALSE; 2210 2211 return STATUS_SUCCESS; 2212 } 2213 else if (m_IrpAllocation == REQUEST_ALLOCATED_DRIVER) { 2214 // 2215 // Release outstanding reference on a must complete driver request. 2216 // 2217 if (m_CanComplete && m_Completed == FALSE) { 2218 ASSERT(GetRefCnt() >= 2); 2219 2220 if (pFxDriverGlobals->FxVerifierOn) { 2221 ClearVerifierFlags(FXREQUEST_FLAG_DRIVER_OWNED); 2222 } 2223 2224 RELEASE(FXREQUEST_DCRC_TAG); 2225 } 2226 } 2227 } 2228 else { 2229 // 2230 // We should not have a m_RequestContext with anything to ReleaseAndRestore 2231 // because there is no IRP to have anything formatted off of. 2232 // 2233 DO_NOTHING(); 2234 } 2235 2236 // 2237 // This cannot be a request on a queue 2238 // 2239 ASSERT(m_CompletionState == FxRequestCompletionStateNone && 2240 m_IoQueue == NULL); 2241 2242 if (ReuseParams->Flags & WDF_REQUEST_REUSE_SET_NEW_IRP) { 2243 currentIrp.SetIrp((MdIrp)ReuseParams->NewIrp); 2244 2245 // 2246 // If we are replacing an internal irp, we must free it later. 2247 // 2248 if (m_IrpAllocation == REQUEST_ALLOCATED_INTERNAL) { 2249 MdIrp pOldIrp; 2250 2251 ASSERT(m_CanComplete == FALSE); 2252 pOldIrp = m_Irp.SetIrp(currentIrp.GetIrp()); 2253 2254 if (pOldIrp != NULL) { 2255 FxIrp oldIrp(pOldIrp); 2256 oldIrp.FreeIrp(); 2257 } 2258 } 2259 else { 2260 (void) m_Irp.SetIrp(currentIrp.GetIrp()); 2261 } 2262 2263 m_IrpAllocation = REQUEST_ALLOCATED_DRIVER; 2264 } 2265 2266 // 2267 // Only reinitialize an internal irp. If the irp is external, then its 2268 // still valid. 2269 // 2270 if (m_IrpAllocation == REQUEST_ALLOCATED_INTERNAL && currentIrp.GetIrp() != NULL) { 2271 ASSERT(m_CanComplete == FALSE); 2272 ASSERT(m_Completed == FALSE); 2273 currentIrp.Reuse(ReuseParams->Status); 2274 2275 // 2276 // For UMDF, host sets cancel flag to false as part of Reuse(), so no 2277 // need to have a separate call for UMDF (that's why host irp doesn't 2278 // expose any interface to set this independently). 2279 2280 2281 2282 2283 // 2284 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 2285 currentIrp.SetCancel(FALSE); 2286 #endif 2287 } 2288 2289 // 2290 // If necessary, reinit the request to support WdfRequestComplete. 2291 // 2292 if (ReuseParams->Flags & WDF_REQUEST_REUSE_MUST_COMPLETE) { 2293 NTSTATUS status; 2294 2295 // 2296 // WDF guarantees a successful return code when the driver calls Reuse() from its 2297 // completion routine with valid input. 2298 // 2299 2300 // 2301 // This feature can only be used from WDF v1.11 and above. 2302 // 2303 if (pFxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,11) == FALSE) { 2304 status = STATUS_INVALID_DEVICE_REQUEST; 2305 DoTraceLevelMessage( 2306 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2307 "WDFREQUEST %p doesn't belong to any queue, %!STATUS!", 2308 GetTraceObjectHandle(), status); 2309 FxVerifierDbgBreakPoint(pFxDriverGlobals); 2310 return status; 2311 } 2312 2313 // 2314 // 'must_complete' flag requires an IRP. 2315 // 2316 if (currentIrp.GetIrp() == NULL) { 2317 status = STATUS_INVALID_PARAMETER; 2318 DoTraceLevelMessage( 2319 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2320 "Driver is trying to reuse WDFREQUEST 0x%p without " 2321 "specifying an IRP with " 2322 "WDF_REQUEST_REUSE_MUST_COMPLETE flag, %!STATUS!", 2323 GetTraceObjectHandle(), status); 2324 FxVerifierDbgBreakPoint(pFxDriverGlobals); 2325 return status; 2326 } 2327 2328 // 2329 // Do not support internal IRPs. 2330 // 2331 if (m_IrpAllocation == REQUEST_ALLOCATED_INTERNAL) { 2332 status = STATUS_INVALID_DEVICE_REQUEST; 2333 DoTraceLevelMessage( 2334 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2335 "Driver is trying to reuse WDFREQUEST 0x%p holding an" 2336 "internal allocated IRP with " 2337 "WDF_REQUEST_REUSE_MUST_COMPLETE flag, %!STATUS!", 2338 GetTraceObjectHandle(), status); 2339 FxVerifierDbgBreakPoint(pFxDriverGlobals); 2340 return status; 2341 } 2342 2343 // 2344 // Ref count must be 1. 2345 // 2346 if (GetRefCnt() != 1) { 2347 status = STATUS_INVALID_DEVICE_REQUEST; 2348 DoTraceLevelMessage( 2349 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2350 "Driver is trying to reuse WDFREQUEST 0x%p with " 2351 "WDF_REQUEST_REUSE_MUST_COMPLETE flag while request is " 2352 "being referenced, reference count:%d, %!STATUS!", 2353 GetTraceObjectHandle(), GetRefCnt(), status); 2354 FxVerifierDbgBreakPoint(pFxDriverGlobals); 2355 return status; 2356 } 2357 2358 // 2359 // Make sure current IRP stack location is valid. 2360 // 2361 if (currentIrp.IsCurrentIrpStackLocationValid() == FALSE) { 2362 status = STATUS_INVALID_DEVICE_REQUEST; 2363 DoTraceLevelMessage( 2364 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2365 "IRP %p of WDFREQUEST %p doesn't have a valid" 2366 " stack location, %!STATUS!", 2367 currentIrp.GetIrp(), GetHandle(), status); 2368 FxVerifierDbgBreakPoint(pFxDriverGlobals); 2369 return status; 2370 } 2371 2372 // 2373 // This ref is removed when: 2374 // (a) the request is completed or 2375 // (b) the request is reused and old request/IRP was never sent and completed. 2376 // 2377 ADDREF(FXREQUEST_DCRC_TAG); 2378 2379 // 2380 // Note: strange why ClearFieldsForReuse() is not used all the time... just in case, 2381 // keeping old logic for compatibility. 2382 // 2383 ClearFieldsForReuse(); 2384 m_CanComplete = TRUE; 2385 2386 if (pFxDriverGlobals->FxVerifierOn) { 2387 SetVerifierFlags(FXREQUEST_FLAG_DRIVER_OWNED); 2388 } 2389 } 2390 else { 2391 m_CanComplete = FALSE; 2392 m_Completed = FALSE; 2393 m_Canceled = FALSE; 2394 2395 if (pFxDriverGlobals->FxVerifierOn) { 2396 ClearVerifierFlags(FXREQUEST_FLAG_DRIVER_OWNED); 2397 } 2398 } 2399 2400 return STATUS_SUCCESS; 2401 } 2402 2403 // 2404 // Return the FxFileObject if associated with this request 2405 // 2406 _Must_inspect_result_ 2407 NTSTATUS 2408 FxRequest::GetFileObject( 2409 __deref_out_opt FxFileObject** FileObject 2410 ) 2411 { 2412 NTSTATUS status; 2413 FxFileObject* pFileObject; 2414 CfxDevice* pDevice; 2415 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2416 2417 pFileObject = NULL; 2418 pFxDriverGlobals = GetDriverGlobals(); 2419 2420 pDevice = GetDevice(); 2421 2422 if (pFxDriverGlobals->FxVerifierIO) { 2423 KIRQL irql; 2424 *FileObject = NULL; 2425 2426 Lock(&irql); 2427 status = VerifyRequestIsNotCompleted(pFxDriverGlobals); 2428 2429 Unlock(irql); 2430 if (!NT_SUCCESS(status)) { 2431 return status; 2432 } 2433 2434 } 2435 2436 if (NULL == m_Irp.GetFileObject() && IsAllocatedDriver()) { 2437 ASSERT(TRUE == m_CanComplete); 2438 // 2439 // This is a 'must_complete' driver created request. 2440 // 2441 *FileObject = NULL; 2442 return STATUS_SUCCESS; 2443 } 2444 2445 status = FxFileObject::_GetFileObjectFromWdm( 2446 pDevice, 2447 pDevice->GetFileObjectClass(), 2448 m_Irp.GetFileObject(), 2449 &pFileObject 2450 ); 2451 2452 if (NT_SUCCESS(status) && pFileObject != NULL) { 2453 *FileObject = pFileObject; 2454 return STATUS_SUCCESS; 2455 } 2456 else if (NT_SUCCESS(status) && 2457 FxIsFileObjectOptional(pDevice->GetFileObjectClass())) { 2458 // 2459 // Driver told us that it is ok for the file object to be NULL. 2460 // 2461 *FileObject = NULL; 2462 return STATUS_SUCCESS; 2463 } 2464 else { 2465 return STATUS_INVALID_DEVICE_REQUEST; 2466 } 2467 } 2468 2469 VOID 2470 FxRequest::AddIrpReference( 2471 VOID 2472 ) 2473 /*++ 2474 2475 Routine Description: 2476 2477 Adds a reference to the IRP contained in the request. 2478 2479 This is used to check that FxRequest::Complete is not 2480 called with outstanding references to any IRP related 2481 fields such as memory buffers. 2482 2483 Arguments: 2484 2485 None 2486 2487 Return Value: 2488 2489 None 2490 2491 --*/ 2492 { 2493 PFX_DRIVER_GLOBALS pFxDriverGlobals; 2494 pFxDriverGlobals = GetDriverGlobals(); 2495 2496 if (pFxDriverGlobals->FxVerifierOn) { 2497 KIRQL irql; 2498 2499 Lock(&irql); 2500 2501 (VOID)VerifyRequestIsNotCompleted(pFxDriverGlobals); 2502 2503 Unlock(irql); 2504 } 2505 2506 InterlockedIncrement(&m_IrpReferenceCount); 2507 2508 return; 2509 } 2510 2511 VOID 2512 FxRequest::ReleaseIrpReference( 2513 VOID 2514 ) 2515 /*++ 2516 2517 Routine Description: 2518 2519 Release a reference to the IRP contained in the request. 2520 2521 Arguments: 2522 2523 None 2524 2525 Return Value: 2526 2527 None 2528 2529 --*/ 2530 { 2531 LONG count; 2532 2533 count = InterlockedDecrement(&m_IrpReferenceCount); 2534 2535 if( count < 0 ) { 2536 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, 2537 "Attempt to release an IRP reference without adding " 2538 "one first WDFREQUEST 0x%p",GetHandle()); 2539 FxVerifierDbgBreakPoint(GetDriverGlobals()); 2540 } 2541 2542 return; 2543 } 2544 2545 _Must_inspect_result_ 2546 NTSTATUS 2547 FX_VF_METHOD(FxRequest, VerifyProbeAndLock) ( 2548 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals 2549 ) 2550 { 2551 NTSTATUS status = STATUS_SUCCESS; 2552 2553 PAGED_CODE_LOCKED(); 2554 2555 MdEThread thread = m_Irp.GetThread(); 2556 2557 // 2558 // Some kernel mode drivers issue I/O without setting this 2559 // 2560 if (thread != NULL) { 2561 // 2562 // Currently DDK level headers don't let us reach into a threads 2563 // parent process, so we can't do the process level check, just 2564 // a thread level check. 2565 // 2566 if (m_Irp.GetRequestorMode() == UserMode && thread != Mx::GetCurrentEThread()) { 2567 status = STATUS_ACCESS_VIOLATION; 2568 2569 // Error, wrong process context... 2570 DoTraceLevelMessage( 2571 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2572 "Attempt to access user mode memory from the wrong process " 2573 "Irp->Tail.Overlay.Thread 0x%p, PsGetCurrentThread 0x%p, " 2574 "%!STATUS!", thread, Mx::GetCurrentEThread(), status); 2575 2576 return status; 2577 } 2578 } 2579 else { 2580 // Irp->Thread should be issued for all user mode requests 2581 ASSERT(m_Irp.GetRequestorMode() == KernelMode); 2582 } 2583 2584 return status; 2585 } 2586 2587 _Must_inspect_result_ 2588 NTSTATUS 2589 FX_VF_METHOD(FxRequest, VerifyStopAcknowledge) ( 2590 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, 2591 _In_ BOOLEAN Requeue 2592 ) 2593 { 2594 NTSTATUS status; 2595 KIRQL irql; 2596 2597 PAGED_CODE_LOCKED(); 2598 2599 Lock(&irql); 2600 2601 // 2602 // Make sure the driver is calling this function in the context 2603 // of EvtIoStop callback. 2604 // 2605 status = VerifyRequestIsInEvtIoStopContext(FxDriverGlobals); 2606 if (!NT_SUCCESS(status)) { 2607 goto Done; 2608 } 2609 2610 if (m_Completed == FALSE && Requeue) { 2611 2612 // Make sure the driver owns the request 2613 2614 status = VerifyRequestIsDriverOwned(FxDriverGlobals); 2615 if (!NT_SUCCESS(status)) { 2616 goto Done; 2617 } 2618 2619 // 2620 // Can't re-enqueue a cancelable request 2621 // 2622 status = VerifyRequestIsNotCancelable(FxDriverGlobals); 2623 if (!NT_SUCCESS(status)) { 2624 goto Done; 2625 } 2626 } 2627 2628 Done: 2629 Unlock(irql); 2630 return status; 2631 } 2632 2633 VOID 2634 FxRequest::StopAcknowledge( 2635 __in BOOLEAN Requeue 2636 ) 2637 /*++ 2638 2639 Routine Description: 2640 2641 This routine saves the acknowledgement in the request object 2642 which will be looked at and processed later by the queue 2643 dispatch event loop 2644 2645 Arguments: 2646 2647 Requeue - if TRUE, put the request back into the head 2648 of queue from which it was delivered to the driver. 2649 Return Value: 2650 2651 None 2652 2653 --*/ 2654 { 2655 NTSTATUS status; 2656 2657 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals(); 2658 2659 status = VerifyStopAcknowledge(FxDriverGlobals, Requeue); 2660 if(!NT_SUCCESS(status)) { 2661 return; 2662 } 2663 2664 if (Requeue) { 2665 m_PowerStopState = FxRequestPowerStopAcknowledgedWithRequeue; 2666 } 2667 else { 2668 m_PowerStopState = FxRequestPowerStopAcknowledged; 2669 } 2670 2671 return; 2672 } 2673 2674 ULONG 2675 FxRequest::AddRefOverride( 2676 __in WDFOBJECT_OFFSET Offset, 2677 __in PVOID Tag, 2678 __in LONG Line, 2679 __in_opt PSTR File 2680 ) 2681 { 2682 if (Offset != 0x0) { 2683 ASSERT(Offset == FIELD_OFFSET(FxRequest, m_SystemBufferOffset) || 2684 Offset == FIELD_OFFSET(FxRequest, m_OutputBufferOffset)); 2685 AddIrpReference(); 2686 return 2; 2687 } 2688 else { 2689 return FxObject::AddRef(Tag, Line, File); 2690 } 2691 } 2692 2693 ULONG 2694 FxRequest::ReleaseOverride( 2695 __in WDFOBJECT_OFFSET Offset, 2696 __in PVOID Tag, 2697 __in LONG Line, 2698 __in_opt PSTR File 2699 ) 2700 { 2701 if (Offset != 0x0) { 2702 ASSERT(Offset == FIELD_OFFSET(FxRequest, m_SystemBufferOffset) || 2703 Offset == FIELD_OFFSET(FxRequest, m_OutputBufferOffset)); 2704 ReleaseIrpReference(); 2705 return 1; 2706 } 2707 else { 2708 return FxObject::Release(Tag, Line, File); 2709 } 2710 } 2711 2712 _Must_inspect_result_ 2713 NTSTATUS 2714 FxRequest::QueryInterface( 2715 __in FxQueryInterfaceParams* Params 2716 ) 2717 { 2718 switch (Params->Type) { 2719 case FX_TYPE_REQUEST: 2720 *Params->Object = (FxRequest*) this; 2721 break; 2722 2723 case IFX_TYPE_MEMORY: 2724 if (Params->Offset == FIELD_OFFSET(FxRequest, m_SystemBufferOffset)) { 2725 *Params->Object = (IFxMemory*) &m_SystemBuffer; 2726 break; 2727 } 2728 else if (Params->Offset == FIELD_OFFSET(FxRequest, m_OutputBufferOffset)) { 2729 *Params->Object = (IFxMemory*) &m_OutputBuffer; 2730 break; 2731 } 2732 2733 // || || Fall || || 2734 // \/ \/ through \/ \/ 2735 default: 2736 return FxRequestBase::QueryInterface(Params); // __super call 2737 } 2738 2739 return STATUS_SUCCESS; 2740 } 2741 2742 VOID 2743 FX_VF_METHOD(FxRequest, VerifierBreakpoint_RequestEarlyDisposeDeferred) ( 2744 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals 2745 ) 2746 { 2747 PAGED_CODE_LOCKED(); 2748 2749 // 2750 // For backwards compatibility break only if WDF is v1.11 or above, or if 2751 // the developer/client enabled these tests on down-level drivers. 2752 // 2753 if (FxDriverGlobals->IsVerificationEnabled(1, 11, OkForDownLevel)) { 2754 DoTraceLevelMessage( 2755 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2756 "WDFREQUEST %p deferred the dispose operation. This normally " 2757 "indicates that at least one of its children asked for passive " 2758 "level disposal. This is not supported.", GetHandle()); 2759 2760 FxVerifierDbgBreakPoint(FxDriverGlobals); 2761 } 2762 } 2763 2764 _Must_inspect_result_ 2765 NTSTATUS 2766 FX_VF_METHOD(FxRequest, VerifyRequestIsDriverOwned) ( 2767 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals 2768 ) 2769 { 2770 NTSTATUS status; 2771 2772 PAGED_CODE_LOCKED(); 2773 2774 if ((m_VerifierFlags & FXREQUEST_FLAG_DRIVER_OWNED) == 0) { 2775 status = STATUS_INVALID_DEVICE_REQUEST; 2776 2777 DoTraceLevelMessage( 2778 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2779 "WDFREQUEST 0x%p is not owned by the driver, %!STATUS!", 2780 GetHandle(), status); 2781 2782 // 2783 // See if it's a tag request, since this could be a common mistake 2784 // 2785 if (m_VerifierFlags & FXREQUEST_FLAG_TAG_REQUEST) { 2786 DoTraceLevelMessage( 2787 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2788 "WDFREQUEST 0x%p has been " 2789 "used as a TagRequest in WdfIoQueueFindRequest. " 2790 "A TagRequest cannot be used until it is retrieved " 2791 "by WdfIoQueueRetrieveFoundRequest", 2792 GetHandle()); 2793 } 2794 2795 FxVerifierDbgBreakPoint(FxDriverGlobals); 2796 } 2797 else { 2798 status = STATUS_SUCCESS; 2799 } 2800 2801 return status; 2802 } 2803 2804 _Must_inspect_result_ 2805 NTSTATUS 2806 FX_VF_METHOD(FxRequest, VerifyRequestIsCancelable)( 2807 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals 2808 ) 2809 { 2810 NTSTATUS status; 2811 2812 PAGED_CODE_LOCKED(); 2813 2814 if ((m_VerifierFlags & FXREQUEST_FLAG_DRIVER_CANCELABLE) == 0) { 2815 status = STATUS_INVALID_DEVICE_REQUEST; 2816 2817 DoTraceLevelMessage( 2818 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2819 "WDFREQUEST 0x%p is not cancelable, %!STATUS!", 2820 GetHandle(), status); 2821 2822 FxVerifierDbgBreakPoint(FxDriverGlobals); 2823 } 2824 else { 2825 status = STATUS_SUCCESS; 2826 } 2827 2828 return status; 2829 } 2830 2831 _Must_inspect_result_ 2832 NTSTATUS 2833 FX_VF_METHOD(FxRequest, VerifyRequestIsNotCancelable)( 2834 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals 2835 ) 2836 { 2837 NTSTATUS status; 2838 2839 PAGED_CODE_LOCKED(); 2840 2841 if (m_VerifierFlags & FXREQUEST_FLAG_DRIVER_CANCELABLE) { 2842 status = STATUS_INVALID_DEVICE_REQUEST; 2843 2844 DoTraceLevelMessage( 2845 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2846 "WDFREQUEST 0x%p should be unmarked cancelable by calling " 2847 "WdfRequestUnmarkCancelable, %!STATUS!", 2848 GetHandle(), status); 2849 2850 FxVerifierDbgBreakPoint(FxDriverGlobals); 2851 } 2852 else { 2853 status = STATUS_SUCCESS; 2854 } 2855 2856 return status; 2857 } 2858 2859 _Must_inspect_result_ 2860 NTSTATUS 2861 FX_VF_METHOD(FxRequest, VerifyRequestIsInCallerContext)( 2862 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals 2863 ) 2864 { 2865 NTSTATUS status; 2866 2867 PAGED_CODE_LOCKED(); 2868 2869 if ((m_VerifierFlags & FXREQUEST_FLAG_DRIVER_INPROCESS_CONTEXT) == 0) { 2870 status = STATUS_INVALID_DEVICE_REQUEST; 2871 2872 DoTraceLevelMessage( 2873 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2874 "This call is valid only in EvtIoInCallerContext callback, " 2875 "WDFREQUEST 0x%p, %!STATUS!", GetHandle(), status); 2876 2877 FxVerifierDbgBreakPoint(FxDriverGlobals); 2878 } 2879 else { 2880 status = STATUS_SUCCESS; 2881 } 2882 2883 return status; 2884 } 2885 2886 _Must_inspect_result_ 2887 NTSTATUS 2888 FX_VF_METHOD(FxRequest, VerifyRequestIsInEvtIoStopContext)( 2889 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals 2890 ) 2891 { 2892 NTSTATUS status; 2893 2894 PAGED_CODE_LOCKED(); 2895 2896 if ((m_VerifierFlags & FXREQUEST_FLAG_DRIVER_IN_EVTIOSTOP_CONTEXT) == 0) { 2897 status = STATUS_INVALID_DEVICE_REQUEST; 2898 2899 DoTraceLevelMessage( 2900 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO, 2901 "This call is valid only in EvtIoStop callback, " 2902 "WDFREQUEST 0x%p, %!STATUS!", GetHandle(), status); 2903 2904 FxVerifierDbgBreakPoint(FxDriverGlobals); 2905 } 2906 else { 2907 status = STATUS_SUCCESS; 2908 } 2909 2910 return status; 2911 } 2912 2913 _Must_inspect_result_ 2914 NTSTATUS 2915 FX_VF_METHOD(FxRequest, VerifyRequestIsNotCompleted)( 2916 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals 2917 ) 2918 { 2919 NTSTATUS status; 2920 2921 PAGED_CODE_LOCKED(); 2922 2923 if (m_Completed) { 2924 status = STATUS_INTERNAL_ERROR; 2925 2926 DoTraceLevelMessage( 2927 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 2928 "WDFREQUEST 0x%p is already completed, %!STATUS!", 2929 GetHandle(), status); 2930 2931 FxVerifierDbgBreakPoint(FxDriverGlobals); 2932 } 2933 else { 2934 status = STATUS_SUCCESS; 2935 } 2936 2937 return status; 2938 } 2939 2940 _Must_inspect_result_ 2941 NTSTATUS 2942 FX_VF_METHOD(FxRequest, VerifyRequestIsTagRequest) ( 2943 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals 2944 ) 2945 { 2946 NTSTATUS status; 2947 2948 PAGED_CODE_LOCKED(); 2949 2950 // 2951 // A request that has been marked as a tag request can be retrieved 2952 // by the driver by calling WdfIoQueueRetrieveNextRequest instead of 2953 // WdfIoQueueRetrieveFoundRequest. Some drivers use multiple threads 2954 // to scan the queue, not the best design but allowed. This means that 2955 // it is possible for one thread to remove and complete a request that is 2956 // used as a tag by another thread. 2957 // 2958 if (FALSE == m_Completed && (0x0 == (m_VerifierFlags & 2959 (FXREQUEST_FLAG_TAG_REQUEST | FXREQUEST_FLAG_DRIVER_OWNED)))) { 2960 2961 status = STATUS_INVALID_PARAMETER; 2962 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO, 2963 "Request 0x%p is not returned by WdfIoQueueFindRequest, " 2964 "%!STATUS!", GetHandle(), status); 2965 FxVerifierDbgBreakPoint(FxDriverGlobals); 2966 } 2967 else { 2968 status = STATUS_SUCCESS; 2969 } 2970 2971 return status; 2972 } 2973 2974 _Must_inspect_result_ 2975 NTSTATUS 2976 FX_VF_METHOD(FxRequest, VerifyRequestIsAllocatedFromIo)( 2977 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals 2978 ) 2979 { 2980 NTSTATUS status; 2981 2982 PAGED_CODE_LOCKED(); 2983 2984 if (IsAllocatedFromIo() == FALSE) { 2985 status = STATUS_INVALID_PARAMETER; 2986 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO, 2987 "Request 0x%p was not allocated for an incoming IRP, " 2988 "%!STATUS!", GetHandle(), status); 2989 FxVerifierDbgBreakPoint(FxDriverGlobals); 2990 2991 } else { 2992 status = STATUS_SUCCESS; 2993 } 2994 2995 return status; 2996 } 2997 2998 _Must_inspect_result_ 2999 NTSTATUS 3000 FX_VF_METHOD(FxRequest, VerifyRequestIsCurrentStackValid)( 3001 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals 3002 ) 3003 { 3004 NTSTATUS status; 3005 MdIrp irp; 3006 3007 PAGED_CODE_LOCKED(); 3008 3009 // 3010 //Make sure there is an IRP. 3011 // 3012 irp = GetFxIrp()->GetIrp(); 3013 if (NULL == irp) { 3014 status = STATUS_INVALID_DEVICE_REQUEST; 3015 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 3016 "WDFREQUEST %p doesn't have an IRP, %!STATUS!", 3017 GetHandle(), status); 3018 FxVerifierDbgBreakPoint(FxDriverGlobals); 3019 goto Done; 3020 } 3021 3022 // 3023 // Validate the IRP's stack location values. 3024 // 3025 if (m_Irp.IsCurrentIrpStackLocationValid() == FALSE) { 3026 status = STATUS_INVALID_DEVICE_REQUEST; 3027 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 3028 "IRP %p of WDFREQUEST %p doesn't have a valid" 3029 " stack location, %!STATUS!", 3030 irp, GetHandle(), status); 3031 FxVerifierDbgBreakPoint(FxDriverGlobals); 3032 goto Done; 3033 } 3034 3035 status = STATUS_SUCCESS; 3036 3037 Done: 3038 return status; 3039 } 3040 3041 _Must_inspect_result_ 3042 NTSTATUS 3043 FX_VF_METHOD(FxRequest, VerifyRequestCanBeCompleted)( 3044 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals 3045 ) 3046 { 3047 NTSTATUS status; 3048 3049 PAGED_CODE_LOCKED(); 3050 3051 if (GetDriverGlobals()->IsVersionGreaterThanOrEqualTo(1,11) == FALSE) { 3052 status = VerifyRequestIsAllocatedFromIo(FxDriverGlobals); 3053 goto Done; 3054 } 3055 3056 // 3057 // Validate the IRP's stack location. 3058 // 3059 status = VerifyRequestIsCurrentStackValid(FxDriverGlobals); 3060 if (!NT_SUCCESS(status)) { 3061 goto Done; 3062 } 3063 3064 // 3065 // Note: There is no guarantees that the request has a completion routine in the current 3066 // IRP stack location; thus we cannot check for it. 3067 // 3068 3069 // 3070 // Make sure this request can be completed. 3071 // 3072 if (IsCanComplete() == FALSE) { 3073 status = STATUS_INVALID_DEVICE_REQUEST; 3074 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST, 3075 "IRP %p of WDFREQUEST %p cannot be completed, " 3076 "%!STATUS!", 3077 GetFxIrp()->GetIrp(), GetHandle(), status); 3078 FxVerifierDbgBreakPoint(FxDriverGlobals); 3079 goto Done; 3080 } 3081 3082 status = STATUS_SUCCESS; 3083 3084 Done: 3085 return status; 3086 } 3087 3088 ULONG 3089 FxRequest::Release( 3090 __in PVOID Tag, 3091 __in LONG Line, 3092 __in_opt PSTR File 3093 ) 3094 { 3095 ULONG retValue; 3096 BOOLEAN reservedRequest; 3097 BOOLEAN allocFromIo; 3098 BOOLEAN canComplete; 3099 3100 // 3101 // This may be the last ref, copy flags before calling Release(). 3102 // 3103 reservedRequest = IsReserved(); 3104 allocFromIo = IsAllocatedFromIo(); 3105 canComplete = IsCanComplete(); 3106 3107 retValue = FxRequestBase::Release(Tag, Line, File); // __super call 3108 3109 if (reservedRequest && retValue == 1 && m_Completed) { 3110 // 3111 // Reserved requests should have an associated queue all the time. 3112 // 3113 m_ForwardProgressQueue->ReturnReservedRequest(this); 3114 } 3115 else if (allocFromIo == FALSE && canComplete && retValue == 1 && m_Completed) { 3116 3117 FxRequestCompletionState state; 3118 FxIoQueue* queue; 3119 3120 // 3121 // Make a local copy before request is gone. 3122 // 3123 state = (FxRequestCompletionState) m_CompletionState; 3124 queue = m_IoQueue; 3125 3126 m_CompletionState = FxRequestCompletionStateNone; 3127 m_IoQueue = NULL; 3128 3129 // 3130 // We are now ready to complete this driver created request. 3131 // 3132 FxIrp irp(m_Irp.GetIrp()); 3133 3134 m_Irp.SetIrp(NULL); 3135 3136 irp.CompleteRequest(GetPriorityBoost()); 3137 3138 PostProcessCompletionForDriverRequest(state, queue); 3139 } 3140 3141 return retValue; 3142 } 3143 3144 FxRequestFromLookaside::FxRequestFromLookaside( 3145 __in CfxDevice* Device, 3146 __in MdIrp Irp 3147 ) : FxRequest(Device->GetDriverGlobals(), 3148 Irp, 3149 FxRequestDoesNotOwnIrp, 3150 FxRequestConstructorCallerIsFx, 3151 sizeof(FxRequestFromLookaside)) 3152 { 3153 SetDeviceBase(Device->GetDeviceBase()); 3154 } 3155 3156 PVOID 3157 FxRequestFromLookaside::operator new( 3158 __in size_t Size, 3159 __in CfxDevice* Device, 3160 __in_opt PWDF_OBJECT_ATTRIBUTES Attributes 3161 ) 3162 { 3163 UNREFERENCED_PARAMETER(Size); 3164 3165 // 3166 // Allocate out of a device specific lookaside list 3167 // 3168 return Device->AllocateRequestMemory(Attributes); 3169 } 3170 3171 VOID 3172 FxRequestFromLookaside::SelfDestruct( 3173 VOID 3174 ) 3175 { 3176 CfxDevice* pDevice; 3177 PFX_POOL_HEADER pHeader; 3178 3179 // 3180 // Store off the device in case the destructor chain sets it to NULL. 3181 // 3182 pDevice = GetDevice(); 3183 ASSERT(pDevice != NULL); 3184 3185 // 3186 // Destroy the object 3187 // 3188 // FxRequestFromLookaside::~FxRequestFromLookaside(); __REACTOS__ 3189 3190 if (IsRequestForwardedToParent()) { 3191 3192 #if FX_VERBOSE_TRACE 3193 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 3194 "Free FxRequest* %p memory", this); 3195 #endif 3196 3197 // 3198 // Remove the request from the list of outstanding requests against this 3199 // driver. 3200 // 3201 pHeader = FxObject::_CleanupPointer(GetDriverGlobals(), this); 3202 MxMemory::MxFreePool(pHeader->Base); 3203 } 3204 else { 3205 pDevice->FreeRequestMemory(this); 3206 } 3207 } 3208