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_
__drv_maxIRQL(DISPATCH_LEVEL)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_
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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_
__drv_maxIRQL(DISPATCH_LEVEL)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
FX_VF_FUNCTION(VerifyRequestComplete)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
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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_
__drv_maxIRQL(DISPATCH_LEVEL)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_
__drv_maxIRQL(DISPATCH_LEVEL)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_
__drv_maxIRQL(DISPATCH_LEVEL)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_
__drv_maxIRQL(DISPATCH_LEVEL)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_
__drv_maxIRQL(PASSIVE_LEVEL)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_
__drv_maxIRQL(PASSIVE_LEVEL)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_
__drv_maxIRQL(DISPATCH_LEVEL)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_
__drv_maxIRQL(DISPATCH_LEVEL)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
CheckUnionAssumptions(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_
__drv_maxIRQL(DISPATCH_LEVEL)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_
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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_
__drv_maxIRQL(APC_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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_
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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_
__drv_maxIRQL(PASSIVE_LEVEL)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_
__drv_maxIRQL(PASSIVE_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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
FX_VF_FUNCTION(VerifyWdfRequestForwardToIoQueue)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_
__drv_maxIRQL(DISPATCH_LEVEL)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
FX_VF_FUNCTION(VerifyWdfRequestForwardToParentDeviceIoQueue)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_
__drv_maxIRQL(DISPATCH_LEVEL)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_
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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_
__drv_maxIRQL(DISPATCH_LEVEL)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_
__drv_maxIRQL(DISPATCH_LEVEL)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
FX_VF_FUNCTION(VerifyWdfRequestIsCanceled)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_
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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
__drv_maxIRQL(DISPATCH_LEVEL)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