1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxIoTargetUm.cpp
8 
9 Abstract:
10 
11     This module implements the IO Target APIs
12 
13 Author:
14 
15 Environment:
16 
17     kernel mode only
18 
19 Revision History:
20 
21 --*/
22 
23 
24 #include "..\..\FxTargetsShared.hpp"
25 
26 extern "C" {
27 #if defined(EVENT_TRACING)
28 #include "FxIoTargetUm.tmh"
29 #endif
30 }
31 
32 _Must_inspect_result_
33 NTSTATUS
34 FxIoTarget::InitModeSpecific(
35     __in CfxDeviceBase* Device
36     )
37 {
38     NTSTATUS status;
39 
40     //
41     // FxCREvent can fail in UMDF so it is initialized outside of constuctor
42     // for UMDF. It always succeeds for KMDF so it gets initialized in
43     // event's constructor.
44     //
45 
46     status = m_SentIoEvent.Initialize(SynchronizationEvent, FALSE);
47     if (!NT_SUCCESS(status)) {
48         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR,
49                             TRACINGIOTARGET,
50                             "Could not initialize m_SentIoEvent event for "
51                             "WFIOTARGET %p, %!STATUS!",
52                             GetObjectHandle(), status);
53         return status;
54     }
55 
56     status = m_DisposeEventUm.Initialize();
57     if (!NT_SUCCESS(status)) {
58         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR,
59                             TRACINGIOTARGET,
60                             "Could not initialize m_DisposeEventUm event for "
61                             "WFIOTARGET %p, %!STATUS!",
62                             GetObjectHandle(), status);
63         return status;
64     }
65 
66     return STATUS_SUCCESS;
67 }
68 
69 _Must_inspect_result_
70 NTSTATUS
71 FxIoTarget::FormatIoRequest(
72     __inout FxRequestBase* Request,
73     __in UCHAR MajorCode,
74     __in FxRequestBuffer* IoBuffer,
75     __in_opt PLONGLONG DeviceOffset,
76     __in_opt FxFileObject* FileObject
77     )
78 {
79     FxIoContext* pContext;
80     NTSTATUS status;
81     ULONG ioLength;
82     FxIrp* irp;
83     PVOID buffer;
84 
85     UNREFERENCED_PARAMETER(FileObject);
86 
87     ASSERT(MajorCode == IRP_MJ_WRITE || MajorCode == IRP_MJ_READ);
88 
89     status = Request->ValidateTarget(this);
90     if (!NT_SUCCESS(status)) {
91         return status;
92     }
93 
94     if (Request->HasContextType(FX_RCT_IO)) {
95         pContext = (FxIoContext*) Request->GetContext();
96     }
97     else {
98         pContext = new(GetDriverGlobals()) FxIoContext();
99         if (pContext == NULL) {
100             DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
101                                 "could not allocate context for request");
102 
103             return STATUS_INSUFFICIENT_RESOURCES;
104         }
105 
106         //
107         // Since we can error out and return, remember the allocation before
108         // we do anything so we can free it later.
109         //
110         Request->SetContext(pContext);
111     }
112 
113     //
114     // Save away any references to IFxMemory pointers that are passed
115     //
116     pContext->StoreAndReferenceMemory(IoBuffer);
117 
118     //
119     // Setup irp stack
120     //
121     irp = Request->GetSubmitFxIrp();
122     irp->ClearNextStackLocation();
123 
124     //
125     // copy File object and flags
126     //
127     CopyFileObjectAndFlags(Request);
128 
129     irp->SetMajorFunction(MajorCode);
130     pContext->m_MajorFunction = MajorCode;
131 
132     ioLength = IoBuffer->GetBufferLength();
133 
134     status = IoBuffer->GetBuffer(&buffer);
135     if (!NT_SUCCESS(status)) {
136         DoTraceLevelMessage(
137             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
138             "Could not retrieve i/o buffer, %!STATUS!",
139             status);
140         goto exit;
141     }
142 
143     //
144     // Since we don't support buffer transformations (buffered->Direct->Neither)
145     // we are analogous to "Neither" method in KMDF
146     // in which case we just set the Irp buffer to the buffer that is passed in
147     //
148     if (IRP_MJ_READ == MajorCode) {
149         pContext->SwapIrpBuffer(Request,
150                                 0,
151                                 NULL,
152                                 ioLength,
153                                 buffer);
154 
155         irp->GetIoIrp()->SetReadParametersForNextStackLocation(
156                     ioLength,
157                     DeviceOffset,
158                     0
159                     );
160     }
161     else if (IRP_MJ_WRITE == MajorCode) {
162         pContext->SwapIrpBuffer(Request,
163                                 ioLength,
164                                 buffer,
165                                 0,
166                                 NULL);
167         irp->GetIoIrp()->SetWriteParametersForNextStackLocation(
168                     ioLength,
169                     DeviceOffset,
170                     0
171                     );
172     }
173     /*
174     else if (WdfRequestQueryInformation == RequestType)
175     {
176         pContext->SwapIrpBuffer(pRequest,
177                                 0,
178                                 NULL,
179                                 ioLength,
180                                 buffer);
181     }
182     else if (WdfRequestSetInformation == RequestType)
183     {
184         pContext->SwapIrpBuffer(pRequest,
185                                 ioLength,
186                                 buffer,
187                                 0,
188                                 NULL);
189     }
190     */
191     else {
192         pContext->SwapIrpBuffer(Request, 0, NULL, 0, NULL);
193     }
194 
195 exit:
196 
197     if (NT_SUCCESS(status)) {
198         Request->VerifierSetFormatted();
199     }
200     else {
201         Request->ContextReleaseAndRestore();
202     }
203 
204     return status;
205 }
206 
207 _Must_inspect_result_
208 NTSTATUS
209 FxIoTarget::FormatIoctlRequest(
210     __in FxRequestBase* Request,
211     __in ULONG Ioctl,
212     __in BOOLEAN Internal,
213     __in FxRequestBuffer* InputBuffer,
214     __in FxRequestBuffer* OutputBuffer,
215     __in_opt FxFileObject* FileObject
216     )
217 {
218     FxIoContext* pContext;
219     NTSTATUS status;
220     ULONG inLength, outLength;
221     FxIrp* irp;
222     PVOID inputBuffer;
223     PVOID outputBuffer;
224 
225     UNREFERENCED_PARAMETER(FileObject);
226 
227     irp = Request->GetSubmitFxIrp();
228 
229     status = Request->ValidateTarget(this);
230     if (!NT_SUCCESS(status)) {
231         return status;
232     }
233 
234     if (Request->HasContextType(FX_RCT_IO)) {
235         pContext = (FxIoContext*) Request->GetContext();
236     }
237     else {
238         pContext = new(GetDriverGlobals()) FxIoContext();
239         if (pContext == NULL) {
240             DoTraceLevelMessage(
241                 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
242                 "Could not allocate context for request");
243 
244             return STATUS_INSUFFICIENT_RESOURCES;
245         }
246 
247         Request->SetContext(pContext);
248     }
249 
250     inLength = InputBuffer->GetBufferLength();
251     outLength = OutputBuffer->GetBufferLength();
252 
253     //
254     // Capture irp buffers in context and set driver-provided buffers in the irp
255     //
256     status = InputBuffer->GetBuffer(&inputBuffer);
257     if (!NT_SUCCESS(status)) {
258         DoTraceLevelMessage(
259             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
260             "Could not retrieve input buffer, %!STATUS!",
261             status);
262         goto exit;
263     }
264 
265     status = OutputBuffer->GetBuffer(&outputBuffer);
266     if (!NT_SUCCESS(status)) {
267         DoTraceLevelMessage(
268             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
269             "Could not retrieve output buffer, %!STATUS!",
270             status);
271         goto exit;
272     }
273 
274     //
275     // Save away any references to IFxMemory pointers that are passed
276     //
277     pContext->StoreAndReferenceMemory(InputBuffer);
278     pContext->StoreAndReferenceOtherMemory(OutputBuffer);
279     pContext->m_MajorFunction = IRP_MJ_DEVICE_CONTROL;
280 
281     //
282     // Format next stack location
283     //
284     irp->ClearNextStackLocation();
285     irp->SetMajorFunction(IRP_MJ_DEVICE_CONTROL);
286 
287     //
288     // copy File object and flags
289     //
290     CopyFileObjectAndFlags(Request);
291 
292     irp->GetIoIrp()->SetDeviceIoControlParametersForNextStackLocation(
293                     Ioctl,
294                     inLength,
295                     outLength
296                     );
297 
298     pContext->SwapIrpBuffer(Request,
299                             InputBuffer->GetBufferLength(),
300                             inputBuffer,
301                             OutputBuffer->GetBufferLength(),
302                             outputBuffer);
303 exit:
304 
305     if (NT_SUCCESS(status)) {
306         Request->VerifierSetFormatted();
307     }
308     else {
309         Request->ContextReleaseAndRestore();
310     }
311 
312     return status;;
313 }
314 
315 
316