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