1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxRequest.hpp
8 
9 Abstract:
10 
11     This is the request object for the driver frameworks.
12 
13     The request object wraps the IRP, containing persistent
14     information required by the driver frameworks.
15 
16 Author:
17 
18 
19 
20 
21 
22 Environment:
23 
24     Both kernel and user mode
25 
26 Revision History:
27 
28 --*/
29 
30 #ifndef _FXREQUEST_H_
31 #define _FXREQUEST_H_
32 
33 //
34 // Magic number to differentiate between default value and caller provided one
35 //
36 #define USE_DEFAULT_PRIORITY_BOOST ((CHAR) 0x7F)
37 
38 //
39 // This tag is used to set and clear the completion callback state as the
40 // ownership of the request transfers from I/O pkg-to-queue or queue-to-queue.
41 //
42 #define FXREQUEST_STATE_TAG (PVOID) 'tatS'
43 
44 //
45 // This tag is used when the request is added and removed from FxIrpQueue.
46 //
47 #define FXREQUEST_QUEUE_TAG (PVOID) 'ueuQ'
48 
49 //
50 // This tag is used to take a reference in the completion path.
51 //
52 #define FXREQUEST_COMPLETE_TAG (PVOID) 'pmoC'
53 
54 //
55 // Use this tag when you want to temporarily hold the object from
56 // disappearing between unlock and lock operation.
57 //
58 #define FXREQUEST_HOLD_TAG (PVOID) 'dloH'
59 
60 //
61 // This tag is used to take a reference in the completion path.
62 //
63 #define FXREQUEST_FWDPRG_TAG (PVOID) 'PdwF'
64 
65 //
66 // This tag is used to take a reference in the completion path for driver created
67 // requests that support completion operations.
68 //
69 #define FXREQUEST_DCRC_TAG (PVOID) 'CRCD'
70 
71 extern "C" {
72 #if defined(EVENT_TRACING)
73 #include "FxRequest.hpp.tmh"
74 #endif
75 }
76 
77 #if (FX_CORE_MODE == FX_CORE_USER_MODE)
78 #define WDF_REQUEST_SEND_OPTION_IMPERSONATION_FLAGS                   \
79         (WDF_REQUEST_SEND_OPTION_IMPERSONATE_CLIENT |                 \
80          WDF_REQUEST_SEND_OPTION_IMPERSONATION_IGNORE_FAILURE)
81 
82 #define FxIrpStackFlagsFromSendFlags(sendFlags)                       \
83                ((WUDFX_IRP_STACK_FLAGS)                               \
84                     ((sendFlags) & WDF_REQUEST_SEND_OPTION_IMPERSONATION_FLAGS))
85 #endif
86 
87 typedef
88 NTSTATUS
89 (*PFN_FX_QUEUE_REQUEST_COMPLETE) (
90     __in FxRequest* Request,
91     __in FxIoQueue* Queue,
92     __in_opt WDFCONTEXT Context
93     );
94 
95 struct FxRequestSystemBuffer : public IFxMemory {
96     friend FxRequest;
97 
98 public:
FxRequestSystemBufferFxRequestSystemBuffer99     FxRequestSystemBuffer(
100         VOID
101         )
102     {
103         m_Buffer = NULL;
104     }
105 
106     _Must_inspect_result_
107     virtual
108     PVOID
109     GetBuffer(
110         VOID
111         );
112 
113     virtual
114     size_t
115     GetBufferSize(
116         VOID
117         );
118 
119     _Must_inspect_result_
120     virtual
121     PMDL
122     GetMdl(
123         VOID
124         );
125 
126     virtual
127     WDFMEMORY
128     GetHandle(
129         VOID
130         );
131 
132     virtual
133     USHORT
134     GetFlags(
135         VOID
136         );
137 
138     virtual
139     PFX_DRIVER_GLOBALS
140     GetDriverGlobals(
141         VOID
142         );
143 
144     virtual
145     ULONG
146     AddRef(
147         __in PVOID Tag,
148         __in LONG Line,
149         __in_opt PSTR File
150         );
151 
152     virtual
153     ULONG
154     Release(
155         __in PVOID Tag,
156         __in LONG Line,
157         __in_opt PSTR File
158         );
159 
160     virtual
161     VOID
162     Delete(
163         VOID
164         );
165 
166     __inline
167     BOOLEAN
IsBufferSetFxRequestSystemBuffer168     IsBufferSet(
169         VOID
170         )
171     {
172         return m_Buffer != NULL ? TRUE : FALSE;
173     }
174 
175     __inline
176     VOID
ClearBufferMdlFxRequestSystemBuffer177     ClearBufferMdl(
178         VOID
179         )
180     {
181         m_Buffer = NULL;
182         m_Mdl = NULL;
183     }
184 
185 protected:
186     __inline
187     VOID
SetBufferFxRequestSystemBuffer188     SetBuffer(
189         PVOID Buffer
190         )
191     {
192         ASSERT(m_Buffer == NULL);
193         m_Buffer = Buffer;
194     }
195 
196     __inline
197     VOID
SetMdlFxRequestSystemBuffer198     SetMdl(
199         PMDL Mdl
200         )
201     {
202         ASSERT(m_Mdl == NULL);
203         m_Mdl = Mdl;
204     }
205 
206     FxRequest*
207     GetRequest(
208         VOID
209         );
210 
211 protected:
212     //
213     // The current irp stack location indicates which type to use
214     //
215     // The buffer / MDL is cached away as a copy instead of using the PIRP values
216     // directly because we want to capture the current state of the irp when
217     // returning the WDFMEMORY.  For instance, if used the PIRP value directly
218     // when implementing GetBuffer(), we are subject to the PIRP being formatted
219     // for the next stack location and changing the buffer pointer, or worse,
220     // changing the MDL value and have the resulting MDL not be mapped, and then
221     // a call to MmGetSystemAddressForMdlSafe can return NULL, and thus GetBuffer(),
222     // return NULL, which would violate the contract for GetBuffer().
223     //
224     // As an example, let's
225     // 1) the WDFREQUEST/PIRP comes in as a read on a direct io device object,
226     //    so Irp->MdlAddress = <read MDL>
227     // 2) This WDFMEMORY will return <read MDL VA> in GetBuffer()
228     // 3) the WDFREQUEST is formatted for an IOCTL which is METHOD_OUT_DIRECT
229     //    with a new output buffer.  Irp->MdlAddres = <IOCTL MDL> now.
230     // 4) This same WDFMEMORY will now return <IOCTL MDL VA> in GetBuffer()
231     //
232     // Essentialy, formatting the WDFREQUEST causes unintended side affects for
233     // the WDFMEMORYs it returns.  To eliminate those side affects, we capture
234     // the original buffer.
235     //
236     union {
237         PVOID m_Buffer;
238         PMDL m_Mdl;
239     };
240 };
241 
242 struct FxRequestOutputBuffer : public IFxMemory {
243     friend FxRequest;
244 
245 public:
FxRequestOutputBufferFxRequestOutputBuffer246     FxRequestOutputBuffer(
247         VOID
248         )
249     {
250         m_Buffer = NULL;
251     }
252 
253     virtual
254     PVOID
255     GetBuffer(
256         VOID
257         );
258 
259     virtual
260     size_t
261     GetBufferSize(
262         VOID
263         );
264 
265     _Must_inspect_result_
266     virtual
267     PMDL
268     GetMdl(
269         VOID
270         );
271 
272     virtual
273     WDFMEMORY
274     GetHandle(
275         VOID
276         );
277 
278     virtual
279     USHORT
280     GetFlags(
281         VOID
282         );
283 
284     virtual
285     PFX_DRIVER_GLOBALS
286     GetDriverGlobals(
287         VOID
288         );
289 
290     virtual
291     ULONG
292     AddRef(
293         __in PVOID Tag,
294         __in LONG Line,
295         __in_opt PSTR File
296         );
297 
298     virtual
299     ULONG
300     Release(
301         __in PVOID Tag,
302         __in LONG Line,
303         __in_opt PSTR File
304         );
305 
306     virtual
307     VOID
308     Delete(
309         VOID
310         );
311 
312     __inline
313     BOOLEAN
IsBufferSetFxRequestOutputBuffer314     IsBufferSet(
315         VOID
316         )
317     {
318         return m_Buffer != NULL ? TRUE : FALSE;
319     }
320 
321     __inline
322     VOID
ClearBufferMdlFxRequestOutputBuffer323     ClearBufferMdl(
324         VOID
325         )
326     {
327         m_Buffer = NULL;
328         m_Mdl = NULL;
329     }
330 
331 protected:
332     __inline
333     VOID
SetBufferFxRequestOutputBuffer334     SetBuffer(
335         __in PVOID Buffer
336         )
337     {
338         ASSERT(m_Buffer == NULL);
339         m_Buffer = Buffer;
340     }
341 
342     __inline
343     VOID
SetMdlFxRequestOutputBuffer344     SetMdl(
345         __in PMDL Mdl
346         )
347     {
348         ASSERT(m_Mdl == NULL);
349         m_Mdl = Mdl;
350     }
351 
352     FxRequest*
353     GetRequest(
354         VOID
355         );
356 
357 protected:
358     //
359     // The current irp stack location indicates which type to use
360     //
361     // See comments in FxRequestSystemBuffer's union for why we capture the
362     // values vs using them directly from the PIRP.
363     //
364     union {
365         PVOID m_Buffer;
366         PMDL m_Mdl;
367     };
368 };
369 
370 // begin_wpp enum
371 enum FxListEntryNames {
372     FxListEntryNameCleanup = 0,
373 
374     // this entry is used when the request is owned by the framework
375     FxListEntryQueueOwned,
376 
377     // this entry is used when the request is presented to the driver
378     FxListEntryDriverOwned,
379 
380     // this entry is used for forward progress
381     FxListEntryForwardProgress
382 };
383 
384 enum  FxRequestPowerStopState {
385     FxRequestPowerStopUnknown = 0, // Initial state
386 
387     // Set when the driver calls WdfRequestStopAcknowledge
388     FxRequestPowerStopAcknowledged = 0x1,
389 
390     // Set when the driver WdfRequestStopAcknowledge with requeue option
391     FxRequestPowerStopAcknowledgedWithRequeue = 0x2,
392 };
393 
394 // end_wpp
395 
396 class FxRequest : public FxRequestBase {
397 
398     friend FxIoTarget;
399     friend FxIoQueue;
400 
401     friend FxRequestMemory;
402     friend FxRequestOutputBuffer;
403     friend FxRequestSystemBuffer;
404     friend VOID GetTriageInfo(VOID);
405 
406 protected:
407     //
408     // This field points to the queue that the request is currently
409     // associated with.
410     //
411     FxIoQueue* m_IoQueue;
412 
413     FxRequestSystemBuffer m_SystemBuffer;
414 
415     FxRequestOutputBuffer m_OutputBuffer;
416 
417     //
418     // This is for use by the owner of the FxRequest which is FxIoQueue OR FxIoTarget
419     //
420     LIST_ENTRY m_OwnerListEntry;
421 
422     LIST_ENTRY m_OwnerListEntry2;
423 
424     //
425     // This is used by the queue to keep track of all forward progress requests
426     //
427     LIST_ENTRY m_ForwardProgressList;
428 
429     //
430     // Used when the request is a reserved request to track the queue it was
431     // originally allocated for, so that it can be returned to the forward
432     // progress queue for reuse when the request is completed.
433     //
434     FxIoQueue *m_ForwardProgressQueue;
435 
436     //
437     // Generic context exposed to other modules.
438     //
439     PVOID m_InternalContext;
440 
441     //
442     // If TRUE, the client driver has been presented with this WDFREQUEST at
443     // least once.
444     //
445     BOOLEAN m_Presented;
446 
447     //
448     // For tracking whether the driver has acknowledged power stop/purge notifications.
449     //
450     BYTE m_PowerStopState;
451 
452     //
453     // If TRUE, this is a reserved request
454     //
455     BOOLEAN   m_Reserved;
456 
457     //
458     //  If TRUE, this is used to determine how to free the request -
459     //  either to the lookaside list or using ExFreePool
460     //
461     BOOLEAN   m_ForwardRequestToParent;
462 
463 public:
464 
465     //
466     // Normally, this is available by the object implementing
467     // IFxListEntry, but currently all callers of this know they
468     // are dealing with an FxRequest*.
469     //
470     // If FxRequests must go on a general typeless list, then
471     // the IFxListEntry interface should be added to FxRequest.
472     //
473     __inline
474     PLIST_ENTRY
GetListEntry(__in FxListEntryNames Index)475     GetListEntry(
476         __in FxListEntryNames Index
477         )
478     {
479         switch (Index) {
480         case FxListEntryQueueOwned:  return &m_OwnerListEntry;
481         case FxListEntryDriverOwned:  return &m_OwnerListEntry2;
482         case FxListEntryForwardProgress: return &m_ForwardProgressList;
483         default: ASSERT(FALSE); return NULL;
484         }
485     }
486 
487     static
488     FxRequest*
_FromOwnerListEntry(__in FxListEntryNames Index,__in PLIST_ENTRY OwnerListEntry)489     _FromOwnerListEntry(
490         __in FxListEntryNames Index,
491         __in PLIST_ENTRY OwnerListEntry
492         )
493     {
494         switch (Index) {
495         case FxListEntryQueueOwned:
496             return CONTAINING_RECORD(OwnerListEntry, FxRequest, m_OwnerListEntry);
497         case FxListEntryDriverOwned:
498             return CONTAINING_RECORD(OwnerListEntry, FxRequest, m_OwnerListEntry2);
499         case FxListEntryForwardProgress:
500             return CONTAINING_RECORD(OwnerListEntry, FxRequest, m_ForwardProgressList);
501         default:
502             ASSERT(FALSE);
503             return NULL;
504         }
505     }
506 
507     __inline
508     VOID
CopyCurrentIrpStackLocationToNext(VOID)509     CopyCurrentIrpStackLocationToNext(
510         VOID
511         )
512     {
513         FxIrp* irp = GetSubmitFxIrp();
514         irp->CopyCurrentIrpStackLocationToNext();
515     }
516 
517     _Must_inspect_result_
518     NTSTATUS
519     Reuse(
520         __in PWDF_REQUEST_REUSE_PARAMS ReuseParams
521         );
522 
523     __inline
524     BOOLEAN
IsCancelled(VOID)525     IsCancelled(
526         VOID
527         )
528     {
529         return m_Irp.IsCanceled() || m_Canceled;
530     }
531 
532     __inline
533     VOID
CopyCompletionParams(__in PWDF_REQUEST_COMPLETION_PARAMS Params)534     CopyCompletionParams(
535         __in PWDF_REQUEST_COMPLETION_PARAMS Params
536         )
537     {
538         if (m_RequestContext != NULL) {
539             RtlCopyMemory(Params,
540                           &m_RequestContext->m_CompletionParams,
541                           sizeof(WDF_REQUEST_COMPLETION_PARAMS));
542         }
543         else {
544             DoTraceLevelMessage(
545                 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST,
546                 "WdfRequestGetCompletionParams will not return valid information if the"
547                 " request is not formatted using WdfIoTargetFormatxxx DDIs"
548                 );
549 
550             FxVerifierDbgBreakPoint(GetDriverGlobals());
551 
552             WDF_REQUEST_COMPLETION_PARAMS_INIT(Params);
553         }
554     }
555 
556     VOID
557     __inline
SetPresented(VOID)558     SetPresented(
559         VOID
560         )
561     {
562         //
563         // No need to synchronize setting this value with checking it because
564         // we check it in the complete path.  We will not be about to present
565         // and completing the request in 2 simultaneous contexts.
566         //
567         m_Presented = TRUE;
568     }
569 
570     VOID
571     AddIrpReference(
572         VOID
573         );
574 
575     VOID
576     ReleaseIrpReference(
577         VOID
578         );
579 
580     virtual
581     ULONG
582     AddRefOverride(
583         __in WDFOBJECT_OFFSET Offset,
584         __in PVOID Tag = NULL,
585         __in LONG Line = 0,
586         __in_opt PSTR File = NULL
587         );
588 
589     virtual
590     ULONG
591     ReleaseOverride(
592         __in WDFOBJECT_OFFSET Offset,
593         __in PVOID Tag = NULL,
594         __in LONG Line = 0,
595         __in_opt PSTR File = NULL
596         );
597 
598     __inline
599     CfxDevice*
GetDevice(VOID)600     GetDevice(
601         VOID
602     )
603     {
604         return m_Device;
605     }
606 
607     __inline
608     BOOLEAN
IsReserved()609     IsReserved(
610         )
611     {
612         return m_Reserved;
613     }
614 
615     __inline
616     VOID
SetReserved()617     SetReserved(
618         )
619     {
620         m_Reserved = TRUE;
621     }
622 
623     __inline
624     VOID
SetForwardProgressQueue(__in FxIoQueue * Queue)625     SetForwardProgressQueue(
626         __in FxIoQueue *Queue
627         )
628     {
629         m_ForwardProgressQueue = Queue;
630     }
631 
632 protected:
633     FxRequest(
634         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
635         __in MdIrp Irp,
636         __in FxRequestIrpOwnership Ownership,
637         __in FxRequestConstructorCaller Caller,
638         __in USHORT ObjectSize
639         );
640 
641     #if DBG
642     ~FxRequest(
643         VOID
644         );
645     #endif // DBG
646 
647     __inline
648     VOID
SetCurrentQueue(__in FxIoQueue * Queue)649     SetCurrentQueue(
650         __in FxIoQueue *Queue
651         )
652     {
653         m_IoQueue = Queue;
654     }
655 
656 
657     WDFMEMORY
GetMemoryHandle(__in USHORT Offset)658     GetMemoryHandle(
659         __in USHORT Offset
660         )
661     {
662         ULONG_PTR handle;
663 
664         //
665         // The offset into this object must be self relative.
666         //
667         ASSERT(*((PUSHORT) WDF_PTR_ADD_OFFSET(this, Offset)) == Offset);
668 
669         handle = (ULONG_PTR) WDF_PTR_ADD_OFFSET(this, Offset);
670 
671         //
672         // Make sure initial value has the flag bits cleared.
673         //
674         ASSERT((handle  & FxHandleFlagMask) == 0);
675 
676         //
677         // We always apply the mask.
678         //
679         handle = handle ^ FxHandleValueMask;
680 
681         //
682         // Make sure final value (before we set the flag) has the flag bits
683         // cleared.
684         //
685         ASSERT((handle  & FxHandleFlagMask) == 0);
686 
687         //
688         // This handle is an offset
689         handle |= FxHandleFlagIsOffset;
690 
691         return (WDFMEMORY) handle;
692     }
693 
694     _Must_inspect_result_
695     virtual
696     NTSTATUS
697     QueryInterface(
698         __in FxQueryInterfaceParams* Params
699         );
700 
701 public:
702     // Factory functions to create FxRequest* objects
703     _Must_inspect_result_
704     static
705     NTSTATUS
706     _CreateForPackage(
707         __in CfxDevice* Device,
708         __in PWDF_OBJECT_ATTRIBUTES RequestAttributes,
709         __in MdIrp Irp,
710         __deref_out FxRequest** Request
711         );
712 
713     _Must_inspect_result_
714     static
715     NTSTATUS
716     _Create(
717         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
718         __in_opt PWDF_OBJECT_ATTRIBUTES RequestAttributes,
719         __in_opt MdIrp Irp,
720         __in_opt FxIoTarget* Target,
721         __in FxRequestIrpOwnership Ownership,
722         __in FxRequestConstructorCaller Caller,
723         __deref_out FxRequest** Request
724         );
725 
726     _Must_inspect_result_
727     FxIoQueue*
GetCurrentQueue(VOID)728     GetCurrentQueue(
729         VOID
730         )
731     {
732         if(m_Completed) {
733             return NULL;
734         }
735 
736         return m_IoQueue;
737     }
738 
739     FxRequestCompletionState
740     SetCompletionState(
741         __in FxRequestCompletionState NewState
742         );
743 
744     VOID
745     __inline
SetStatus(__in NTSTATUS Status)746     SetStatus(
747         __in NTSTATUS Status
748         )
749     {
750         m_Irp.SetStatus(Status);
751     }
752 
753     NTSTATUS
754     SetInformation(
755         __in ULONG_PTR Information
756         );
757 
758     ULONG_PTR
759     GetInformation(
760         VOID
761         );
762 
763     KPROCESSOR_MODE
764     GetRequestorMode(
765         VOID
766         );
767 
768     __inline
769     NTSTATUS
Complete(__in NTSTATUS Status)770     Complete(
771         __in NTSTATUS Status
772     )
773     {
774         CfxDevice* const fxDevice = GetDevice();
775 
776         //
777         // Complete the current request object. Can be called directly
778         // by the FxIoQueue to complete a request.
779         //
780         // When an FxRequest is completed, it is marked as completed,
781         // removed from any CSQ it may be a member of, and any registered
782         // callback functions are called. Then the NT IRP is completed,
783         // and the reference count on the object due to the callback routine
784         // is released if a callback routine was specified.
785         //
786         // Completing a request object can cause its reference
787         // count to go to zero, thus deleting it. So the caller
788         // must either reference it explicitly, or not touch it
789         // any more after calling complete.
790         //
791 
792         DoTraceLevelMessage(
793             GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGREQUEST,
794             "Completing WDFREQUEST 0x%p for IRP 0x%p with "
795             "Information 0x%I64x, %!STATUS!",
796             GetHandle(), m_Irp.GetIrp(), m_Irp.GetInformation(), Status);
797 
798         if (fxDevice != NULL) {
799             SetPriorityBoost(fxDevice->GetDefaultPriorityBoost());
800         }
801         else {
802             SetPriorityBoost(0);
803         }
804 
805         return CompleteInternal(Status);
806     }
807 
808     __inline
809     NTSTATUS
CompleteWithInformation(__in NTSTATUS Status,__in ULONG_PTR Information)810     CompleteWithInformation(
811         __in NTSTATUS Status,
812         __in ULONG_PTR Information
813         )
814     {
815         //
816         // Complete the request object. If the status is success, get the
817         // priority boost for the owning device type, and complete the request.
818         //
819         m_Irp.SetInformation(Information);
820         return Complete(Status);
821     }
822 
823     __inline
824     NTSTATUS
CompleteWithPriority(__in NTSTATUS Status,__in CCHAR PriorityBoost)825     CompleteWithPriority(
826         __in NTSTATUS Status,
827         __in CCHAR PriorityBoost
828         )
829     {
830         //
831         // Complete the current request object. Can be called directly
832         // by the FxIoQueue to complete a request.
833         //
834         // When an FxRequest is completed, it is marked as completed,
835         // removed from any CSQ it may be a member of, and any registered
836         // callback functions are called. Then the NT IRP is completed,
837         // and the reference count on the object due to the callback routine
838         // is released if a callback routine was specified.
839         //
840         // Completing a request object can cause its reference
841         // count to go to zero, thus deleting it. So the caller
842         // must either reference it explicitly, or not touch it
843         // any more after calling complete.
844         //
845 
846         DoTraceLevelMessage(
847             GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGREQUEST,
848             "Completing WDFREQUEST 0x%p for IRP 0x%p with "
849             "Information 0x%I64x, %!STATUS!",
850             GetHandle(), m_Irp.GetIrp(), m_Irp.GetInformation(), Status);
851 
852         SetPriorityBoost(PriorityBoost);
853         return CompleteInternal(Status);
854     }
855 
856     // Do not specify argument names
857     FX_DECLARE_VF_FUNCTION(
858     VOID,
859     VerifyPreProcessSendAndForget
860     );
861 
862     VOID
863     PreProcessSendAndForget(
864         VOID
865         );
866 
867     VOID
868     PostProcessSendAndForget(
869         VOID
870         );
871 
872     NTSTATUS
873     GetStatus(
874         VOID
875         );
876 
877     _Must_inspect_result_
878     NTSTATUS
879     GetParameters(
880         __out PWDF_REQUEST_PARAMETERS Parameters
881         );
882 
883     _Must_inspect_result_
884     NTSTATUS
885     GetMemoryObject(
886         __deref_out IFxMemory** Memory,
887         __out PVOID* Buffer,
888         __out size_t* Length
889         );
890 
891     _Must_inspect_result_
892     NTSTATUS
893     GetMdl(
894         __out PMDL *pMdl
895         );
896 
897     _Must_inspect_result_
898     NTSTATUS
899     GetDeviceControlOutputMemoryObject(
900         __deref_out IFxMemory** MemoryObject,
901         __out PVOID* Buffer,
902         __out size_t* Length
903         );
904 
905     _Must_inspect_result_
906     NTSTATUS
907     GetDeviceControlOutputMdl(
908         __out PMDL *pMdl
909         );
910 
911     // Do not specify argument names
912     FX_DECLARE_VF_FUNCTION(
913     NTSTATUS,
914     VerifyProbeAndLock
915     );
916 
917     _Must_inspect_result_
918     NTSTATUS
919     ProbeAndLockForRead(
920         __in  PVOID Buffer,
921         __in  ULONG Length,
922         __deref_out FxRequestMemory** pMemoryObject
923         );
924 
925     _Must_inspect_result_
926     NTSTATUS
927     ProbeAndLockForWrite(
928         __in  PVOID Buffer,
929         __in  ULONG Length,
930         __deref_out FxRequestMemory** pMemoryObject
931         );
932 
933 #if (FX_CORE_MODE == FX_CORE_USER_MODE)
934     _Must_inspect_result_
935     NTSTATUS
936     Impersonate(
937         _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
938         _In_ PFN_WDF_REQUEST_IMPERSONATE EvtRequestImpersonate,
939         _In_opt_ PVOID Context
940         );
941 #endif
942 
943     VOID
SetImpersonationFlags(_In_ ULONG Flags)944     SetImpersonationFlags(
945         _In_ ULONG Flags
946         )
947     {
948 #if (FX_CORE_MODE == FX_CORE_USER_MODE)
949         GetSubmitFxIrp()->GetIoIrp()->SetFlagsForNextStackLocation(
950                 FxIrpStackFlagsFromSendFlags(Flags));
951 #else
952         UNREFERENCED_PARAMETER(Flags);
953 #endif
954     }
955 
956     FxIrp*
GetFxIrp(VOID)957     GetFxIrp(
958         VOID
959         )
960     {
961         return &m_Irp;
962     }
963 
964     __inline
965     FxIoQueue*
GetIoQueue(VOID)966     GetIoQueue(
967         VOID
968         )
969     {
970         return m_IoQueue;
971     }
972 
973     _Must_inspect_result_
974     NTSTATUS
GetIrp(__deref_out MdIrp * ppIrp)975     GetIrp(
976         __deref_out MdIrp* ppIrp
977         )
978     {
979         if (GetDriverGlobals()->FxVerifierIO) {
980             NTSTATUS status;
981             KIRQL irql;
982 
983             Lock(&irql);
984 
985             status = VerifyRequestIsNotCompleted(GetDriverGlobals());
986             if (!NT_SUCCESS(status)) {
987                 *ppIrp = NULL;
988                 status = STATUS_INVALID_DEVICE_REQUEST;
989             }
990             else {
991                 *ppIrp = m_Irp.GetIrp();
992             }
993 
994             Unlock(irql);
995 
996             return status;
997         }
998         else {
999             *ppIrp = m_Irp.GetIrp();
1000             return STATUS_SUCCESS;
1001         }
1002     }
1003 
1004     //
1005     // Return the FxFileObject if associated with this request
1006     //
1007     _Must_inspect_result_
1008     NTSTATUS
1009     GetFileObject(
1010         __deref_out_opt FxFileObject** pFileObject
1011         );
1012 
1013     //
1014     // Get the IoStack location of the request.
1015     //
1016     // Since this returns the pointer to the underlying IRP
1017     // IO_STACK_LOCATION, it can not be called in a situation
1018     // which the request is completed out from underneath us.
1019     //
1020     // Note: Must implemention a version for the drivers use.
1021     //       Must interact with completion events from the
1022     //       driver due to cancel as well.
1023     //
1024     //
1025     PIO_STACK_LOCATION
GetCurrentIrpStackLocation(VOID)1026     GetCurrentIrpStackLocation(
1027         VOID
1028         )
1029     {
1030         if (GetDriverGlobals()->FxVerifierIO) {
1031             PIO_STACK_LOCATION ios;
1032             KIRQL irql;
1033             NTSTATUS status;
1034 
1035             Lock(&irql);
1036             status = VerifyRequestIsNotCompleted(GetDriverGlobals());
1037             if (!NT_SUCCESS(status)) {
1038                 ios = NULL;
1039             }
1040             else {
1041                 ios = m_Irp.GetCurrentIrpStackLocation();
1042             }
1043             Unlock(irql);
1044 
1045             return ios;
1046         }
1047         else {
1048             return m_Irp.GetCurrentIrpStackLocation();
1049         }
1050     }
1051 
1052     //
1053     // The following functions are to support use of
1054     // the Cancel Safe FxIrpQueue.
1055     //
1056 
1057     // Do not specify argument names
1058     FX_DECLARE_VF_FUNCTION_P1(
1059     NTSTATUS,
1060     VerifyInsertIrpQueue,
1061         _In_ FxIrpQueue*
1062         );
1063 
1064     //
1065     // Insert the request in the supplied FxIrpQueue
1066     // and associated it with it.
1067     //
1068     _Must_inspect_result_
1069     NTSTATUS
1070     InsertTailIrpQueue(
1071         __in FxIrpQueue* IrpQueue,
1072         __out_opt ULONG*      pRequestCount
1073         );
1074 
1075     _Must_inspect_result_
1076     NTSTATUS
1077     InsertHeadIrpQueue(
1078         __in FxIrpQueue* IrpQueue,
1079         __out_opt ULONG*      pRequestCount
1080         );
1081 
1082     //
1083     // Remove it from the FxIrpQueue it is associated with.
1084     //
1085     // Returns STATUS_CANCELLED if the cancel routine has
1086     // fired and removed it from the queue first.
1087     //
1088     //
1089     _Must_inspect_result_
1090     NTSTATUS
1091     RemoveFromIrpQueue(
1092         __in FxIrpQueue* IrpQueue
1093         );
1094 
1095     //
1096     // Mark that this request is no longer on the IrpQueue
1097     //
1098     __inline
1099     VOID
MarkRemovedFromIrpQueue(VOID)1100     MarkRemovedFromIrpQueue(
1101         VOID
1102         )
1103     {
1104         m_IrpQueue = NULL;
1105         return;
1106     }
1107 
1108     //
1109     // Return the FxRequest's CsqContext address
1110     //
1111     __inline
1112     PMdIoCsqIrpContext
GetCsqContext(VOID)1113     GetCsqContext(
1114         VOID
1115         )
1116     {
1117         return &m_CsqContext;
1118     }
1119 
1120 
1121     //
1122     // Function to return an FxRequest from an FxIrpQueue
1123     //
1124     _Must_inspect_result_
1125     static
1126     FxRequest*
1127     GetNextRequest(
1128         __in FxIrpQueue*  IrpQueue
1129         );
1130 
1131     _Must_inspect_result_
1132     static
1133     NTSTATUS
1134     GetNextRequest(
1135         __in FxIrpQueue*        IrpQueue,
1136         __in_opt MdFileObject   FileObject,
1137         __in_opt FxRequest*     TagRequest,
1138         __deref_out FxRequest** ppOutRequest
1139         );
1140 
1141     //
1142     // Allow peeking at requests in the IrpQueue
1143     //
1144     _Must_inspect_result_
1145     static
1146     NTSTATUS
1147     PeekRequest(
1148         __in FxIrpQueue*         IrpQueue,
1149         __in_opt FxRequest*      TagRequest,
1150         __in_opt MdFileObject    FileObject,
1151         __out_opt PWDF_REQUEST_PARAMETERS Parameters,
1152         __deref_out FxRequest**  ppOutRequest
1153         );
1154 
1155     //
1156     // Internal function to retrieve the FxRequest
1157     // structure from a pointer to its CsqContext
1158     // member.
1159     //
1160     __inline
1161     static
1162     FxRequest*
RetrieveFromCsqContext(__in PMdIoCsqIrpContext pCsqContext)1163     RetrieveFromCsqContext(
1164         __in PMdIoCsqIrpContext pCsqContext
1165         )
1166     {
1167         return CONTAINING_RECORD(pCsqContext, FxRequest, m_CsqContext);
1168     }
1169 
1170 
1171     __inline
1172     BOOLEAN
IsInIrpQueue(__in FxIrpQueue * pIrpQueue)1173     IsInIrpQueue(
1174         __in FxIrpQueue*          pIrpQueue
1175         )
1176     {
1177         return pIrpQueue->IsIrpInQueue(GetCsqContext());
1178     }
1179 
1180 
1181     // Do not specify argument names
1182     FX_DECLARE_VF_FUNCTION_P1(
1183     NTSTATUS,
1184     VerifyStopAcknowledge,
1185         _In_ BOOLEAN
1186         );
1187 
1188     VOID
1189     StopAcknowledge(
1190         __in BOOLEAN Requeue
1191         );
1192 
1193     __inline
1194     BOOLEAN
IsPowerStopAcknowledged(VOID)1195     IsPowerStopAcknowledged(
1196         VOID
1197         )
1198     {
1199         return ((m_PowerStopState == FxRequestPowerStopAcknowledged)
1200                 ||
1201                 (m_PowerStopState == FxRequestPowerStopAcknowledgedWithRequeue))? TRUE : FALSE;
1202     }
1203 
1204     __inline
1205     BOOLEAN
IsPowerStopAcknowledgedWithRequeue(VOID)1206     IsPowerStopAcknowledgedWithRequeue(
1207         VOID
1208         )
1209     {
1210         return (m_PowerStopState == FxRequestPowerStopAcknowledgedWithRequeue) ? TRUE : FALSE;
1211     }
1212 
1213     VOID
ClearPowerStopState(VOID)1214     ClearPowerStopState(
1215         VOID
1216         )
1217     {
1218         m_PowerStopState = FxRequestPowerStopUnknown;
1219     }
1220 
1221     // Do not specify argument names
1222     FX_DECLARE_VF_FUNCTION(
1223     VOID,
1224     VerifierBreakpoint_RequestEarlyDisposeDeferred
1225     );
1226 
1227     // Do not specify argument names
1228     FX_DECLARE_VF_FUNCTION(
1229     NTSTATUS,
1230     VerifyRequestIsDriverOwned
1231     );
1232 
1233     // Do not specify argument names
1234     FX_DECLARE_VF_FUNCTION(
1235     NTSTATUS,
1236     VerifyRequestIsCancelable
1237     );
1238 
1239     // Do not specify argument names
1240     FX_DECLARE_VF_FUNCTION(
1241     NTSTATUS,
1242     VerifyRequestIsNotCancelable
1243     );
1244 
1245     // Do not specify argument names
1246     FX_DECLARE_VF_FUNCTION(
1247     NTSTATUS,
1248     VerifyRequestIsInCallerContext
1249     );
1250 
1251     // Do not specify argument names
1252     FX_DECLARE_VF_FUNCTION(
1253     NTSTATUS,
1254     VerifyRequestIsInEvtIoStopContext
1255     );
1256 
1257     // Do not specify argument names
1258     FX_DECLARE_VF_FUNCTION(
1259     NTSTATUS,
1260     VerifyRequestIsNotCompleted
1261     );
1262 
1263     // Do not specify argument names
1264     FX_DECLARE_VF_FUNCTION(
1265     NTSTATUS,
1266     VerifyRequestIsTagRequest
1267     );
1268 
1269     // Do not specify argument names
1270     FX_DECLARE_VF_FUNCTION(
1271     NTSTATUS,
1272     VerifyRequestIsAllocatedFromIo
1273     );
1274 
1275     // Do not specify argument names
1276     FX_DECLARE_VF_FUNCTION(
1277     NTSTATUS,
1278     VerifyRequestIsCurrentStackValid
1279     );
1280 
1281     // Do not specify argument names
1282     FX_DECLARE_VF_FUNCTION(
1283     NTSTATUS,
1284     VerifyRequestCanBeCompleted
1285     );
1286 
1287     VOID
1288     FreeRequest(
1289         VOID
1290         );
1291 
1292     __inline
1293     VOID
ClearFieldsForReuse(VOID)1294     ClearFieldsForReuse(
1295         VOID
1296         )
1297     {
1298         m_SystemBuffer.ClearBufferMdl();
1299         m_OutputBuffer.ClearBufferMdl();
1300 
1301         ASSERT(m_ForwardRequestToParent == FALSE);
1302 
1303         FxRequestBase::ClearFieldsForReuse(); // __super call
1304     }
1305 
1306     virtual
1307     ULONG
1308     Release(
1309         __in PVOID Tag,
1310         __in LONG Line,
1311         __in_opt PSTR File
1312     );
1313 
1314     __inline
1315     BOOLEAN
IsRequestForwardedToParent(VOID)1316     IsRequestForwardedToParent(
1317         VOID
1318         )
1319     {
1320         return m_ForwardRequestToParent;
1321     }
1322 
1323 private:
1324     FX_DECLARE_VF_FUNCTION_P1(
1325         VOID,
1326         VerifyCompleteInternal,
1327             _In_ NTSTATUS
1328             );
1329 
1330     NTSTATUS
1331     CompleteInternalReserved(
1332         __in NTSTATUS Status,
1333         __in CCHAR PriorityBoost
1334         );
1335 
1336     NTSTATUS
1337     CompleteInternal(
1338         __in NTSTATUS Status
1339         );
1340 
1341     VOID
1342     PostProcessCompletion(
1343         __in FxRequestCompletionState State,
1344         __in FxIoQueue* Queue
1345         );
1346 
1347     VOID
1348     PostProcessCompletionForReserved(
1349         __in FxRequestCompletionState State,
1350         __in FxIoQueue* Queue
1351         );
1352 
1353     VOID
1354     PreProcessCompletionForDriverRequest(
1355         __in FxRequestCompletionState State,
1356         __in FxIoQueue* Queue
1357         );
1358 
1359     VOID
1360     PostProcessCompletionForDriverRequest(
1361         __in FxRequestCompletionState State,
1362         __in FxIoQueue* Queue
1363         );
1364 
1365     static
1366     VOID
1367     CheckAssumptions(
1368         VOID
1369         );
1370 
1371     VOID
AssignMemoryBuffers(__in WDF_DEVICE_IO_TYPE IoType)1372     AssignMemoryBuffers(
1373         __in WDF_DEVICE_IO_TYPE IoType
1374     )
1375 {
1376 
1377     switch (m_Irp.GetMajorFunction()) {
1378     case IRP_MJ_DEVICE_CONTROL:
1379     case IRP_MJ_INTERNAL_DEVICE_CONTROL:
1380 
1381 
1382 
1383 
1384 
1385 
1386 
1387 
1388 
1389       switch (m_Irp.GetParameterIoctlCodeBufferMethod()) {
1390       case METHOD_BUFFERED:
1391           //
1392           // Set the buffer in the memory interface. For kernel mode,
1393           // GetOutputBuffer is same as GetSystemBuffer, but for user-mode,
1394           // host provides separate buffers, so that input buffer can only be
1395           // read, and output buffer can only be written to.
1396           //
1397           m_SystemBuffer.SetBuffer(m_Irp.GetSystemBuffer());
1398           m_OutputBuffer.SetBuffer(m_Irp.GetOutputBuffer());
1399           break;
1400 
1401       case METHOD_IN_DIRECT:
1402           //
1403           // InputBuffer is in SystemBuffer
1404           // OutputBuffer is in MdlAddress with read access
1405           //
1406           KMDF_ONLY_CODE_PATH_ASSERT();
1407           m_SystemBuffer.SetBuffer(m_Irp.GetSystemBuffer());
1408           break;
1409 
1410       case METHOD_OUT_DIRECT:
1411           //
1412           // InputBuffer is in SystemBuffer
1413           // OutputBuffer is in MdlAddress with write access
1414           //
1415           KMDF_ONLY_CODE_PATH_ASSERT();
1416           m_SystemBuffer.SetBuffer(m_Irp.GetSystemBuffer());
1417           break;
1418 
1419       case METHOD_NEITHER:
1420           //
1421           // Internal device controls are kernel mode to kernel mode, and deal
1422           // with direct unmapped pointers.
1423           //
1424           // In addition, a normal device control with
1425           // RequestorMode == KernelMode is also treated as kernel mode
1426           // to kernel mode since the I/O Manager will not generate requests
1427           // with this setting from a user mode request.
1428           //
1429           KMDF_ONLY_CODE_PATH_ASSERT();
1430           if (m_Irp.GetMajorFunction() == IRP_MJ_INTERNAL_DEVICE_CONTROL ||
1431               (m_Irp.GetRequestorMode() == KernelMode)) {
1432               m_SystemBuffer.SetBuffer(
1433                   m_Irp.GetParameterIoctlType3InputBuffer()
1434                   );
1435               m_OutputBuffer.SetBuffer(m_Irp.GetUserBuffer());
1436           }
1437           else {
1438               return;
1439           }
1440           break;
1441       }
1442       break;
1443 
1444       case IRP_MJ_READ:
1445       case IRP_MJ_WRITE:
1446           switch (IoType) {
1447           case WdfDeviceIoBuffered:
1448               m_SystemBuffer.SetBuffer(m_Irp.GetSystemBuffer());
1449               break;
1450 
1451           case WdfDeviceIoNeither:
1452               KMDF_ONLY_CODE_PATH_ASSERT();
1453               if (m_Irp.GetRequestorMode() == KernelMode) {
1454                    m_SystemBuffer.SetBuffer(m_Irp.GetUserBuffer());
1455               }
1456               else {
1457                   return;
1458               }
1459           break;
1460 
1461           default:
1462               return;
1463           }
1464           break;
1465 
1466       default:
1467           return;
1468       }
1469 
1470       if (m_SystemBuffer.IsBufferSet()) {
1471           m_RequestBaseStaticFlags |= FxRequestBaseStaticSystemBufferValid;
1472       }
1473       if (m_OutputBuffer.IsBufferSet()) {
1474           m_RequestBaseStaticFlags |= FxRequestBaseStaticOutputBufferValid;
1475       }
1476 }
1477 
1478 
1479 public:
1480     __inline
1481     VOID
SetInternalContext(PVOID Context)1482     SetInternalContext(
1483         PVOID Context
1484         )
1485     {
1486         ASSERT(NULL == m_InternalContext);
1487         m_InternalContext = Context;
1488     }
1489 
1490     __inline
1491     PVOID
GetInternalContext(VOID)1492     GetInternalContext(
1493         VOID
1494         )
1495     {
1496         PVOID context;
1497 
1498         context = m_InternalContext;
1499         m_InternalContext = NULL;
1500 
1501         return context;
1502     }
1503 };
1504 
1505 class FxRequestFromLookaside : public FxRequest {
1506 
1507 public:
1508     FxRequestFromLookaside(
1509         __in CfxDevice* Device,
1510         __in MdIrp Irp
1511         );
1512 
1513     PVOID
1514     operator new(
1515         __in size_t Size,
1516         __in CfxDevice* Device,
1517         __in_opt PWDF_OBJECT_ATTRIBUTES Attributes
1518         );
1519 
1520 protected:
1521     //
1522     // FxObject override
1523     //
1524     VOID
1525     SelfDestruct(
1526         VOID
1527         );
1528 };
1529 
1530 #endif // _FXREQUEST_H_
1531