1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxIoTargetSelf.cpp
8 
9 Abstract:
10 
11     This module implements the IO Target APIs
12 
13 Author:
14 
15 
16 
17 
18 Environment:
19 
20     Both kernel and user mode
21 
22 Revision History:
23 
24 --*/
25 
26 
27 #include "../fxtargetsshared.hpp"
28 
29 extern "C" {
30 #if defined(EVENT_TRACING)
31 #include "FxIoTargetSelf.tmh"
32 #endif
33 }
34 
FxIoTargetSelf(_In_ PFX_DRIVER_GLOBALS FxDriverGlobals,_In_ USHORT ObjectSize)35 FxIoTargetSelf::FxIoTargetSelf(
36     _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
37     _In_ USHORT ObjectSize
38     ) :
39     FxIoTarget(FxDriverGlobals, ObjectSize, FX_TYPE_IO_TARGET_SELF),
40     m_DispatchQueue(NULL)
41 {
42 }
43 
~FxIoTargetSelf()44 FxIoTargetSelf::~FxIoTargetSelf()
45 {
46 }
47 
48 FxIoQueue*
GetDispatchQueue(UCHAR MajorFunction)49 FxIoTargetSelf::GetDispatchQueue(
50     UCHAR MajorFunction
51     )
52 /*++
53 Routine Description:
54     Returns a pointer to the queue to which an IO sent to the Self
55     io target must be sent to
56 
57 Arguments:
58 
59     MajorFunction - IRP_MJ_READ, IRP_MJ_WRITE, or IRP_MJ_DEVICE_CONTROL
60 
61 Returns:
62 
63     FxIoQueue*
64 
65 --*/
66 {
67     if (m_DispatchQueue != NULL) {
68         return m_DispatchQueue;
69     }
70 
71     return m_Device->m_PkgIo->GetDispatchQueue(MajorFunction);
72 }
73 
74 VOID
Send(_In_ MdIrp Irp)75 FxIoTargetSelf::Send(
76     _In_ MdIrp Irp
77     )
78 /*++
79 Routine Description:
80     send an MdIrp to the Self IO Target.
81 
82 Arguments:
83 
84     MdIrp for IRP_MJ_READ, IRP_MJ_WRITE, or IRP_MJ_DEVICE_CONTROL
85 
86 Returns:
87 
88     VOID
89 
90 Implementation Note:
91 
92     Function body inspired by WdfDeviceWdmDispatchIrpToIoQueue API.
93 
94 --*/
95 {
96     FxIrp irp(Irp);
97     FxIoQueue* queue;
98     NTSTATUS status;
99     UCHAR majorFunction;
100     FxIoInCallerContext* ioInCallerCtx;
101 
102 #if (FX_CORE_MODE == FX_CORE_USER_MODE)
103 
104     //
105     // Prepare the request to forward to the inteternal target.
106     //
107     (static_cast<IWudfIoIrp2*>(Irp))->PrepareToForwardToSelf();
108 
109 #else
110     //
111     // Set Next Stack Location
112     //
113     irp.SetNextIrpStackLocation();
114 
115     //
116     // Set Device Object.
117     //
118     irp.SetCurrentDeviceObject(m_Device->GetDeviceObject());
119 #endif
120 
121     majorFunction = irp.GetMajorFunction();
122 
123     //
124     // Retrieve Queue
125     //
126     queue = GetDispatchQueue(majorFunction);
127 
128     if (queue == NULL) {
129         DoTraceLevelMessage(
130             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
131             "Send WDFIOTARGET %p, No Dispatch Queue Found for Major Function %d",
132             GetObjectHandle(), majorFunction);
133         status = STATUS_INVALID_DEVICE_STATE;
134         goto Fail;
135     }
136 
137     //
138     // Only read/writes/ctrls/internal_ctrls IRPs are allowed to be sent to
139     // Self IO Target
140     //
141     if (m_Device->GetDispatchPackage(majorFunction) != m_Device->m_PkgIo) {
142         status = STATUS_INVALID_PARAMETER;
143         DoTraceLevelMessage(
144                 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
145                 "Only Read/Write/Control/Internal-Control IRPs can be "
146                 "forwarded to Self IO Target 0x%p, %!IRPMJ!, "
147                 "IRP_MN %x, Device 0x%p, %!STATUS!",
148                  GetHandle(), majorFunction, irp.GetMinorFunction(),
149                  m_Device->GetObjectHandle(), status);
150         FxVerifierDbgBreakPoint(GetDriverGlobals());
151         goto Fail;
152     }
153 
154     //
155     // Retrieve the InContextCallback function
156     //
157     ioInCallerCtx = m_Device->m_PkgIo->GetIoInCallerContextCallback(
158                                             queue->GetCxDeviceInfo());
159 
160     //
161     // DispatchStep2 will convert the IRP into a WDFREQUEST, queue it and if
162     // possible dispatch the request to the driver.
163     // If a failure occurs, DispatchStep2 completes teh Irp
164     //
165     (VOID) m_Device->m_PkgIo->DispatchStep2(Irp, ioInCallerCtx, queue);
166     return;
167 
168 Fail:
169 
170     irp.SetStatus(status);
171     irp.SetInformation(0);
172     irp.CompleteRequest(IO_NO_INCREMENT);
173 
174     return;
175 }
176 
177