ReactOS 0.4.15-dev-7924-g5949c20
fxiotargetkm.cpp
Go to the documentation of this file.
1/*++
2
3Copyright (c) Microsoft Corporation
4
5Module Name:
6
7 FxIoTargetKm.cpp
8
9Abstract:
10
11 This module implements the IO Target APIs
12
13Author:
14
15Environment:
16
17 kernel mode only
18
19Revision History:
20
21--*/
22
23
24#include "../../fxtargetsshared.hpp"
25
26extern "C" {
27#if defined(EVENT_TRACING)
28#include "FxIoTargetKm.tmh"
29#endif
30}
31
36 __in UCHAR MajorCode,
37 __in FxRequestBuffer* IoBuffer,
40 )
41{
42 FxIoContext* pContext;
45 ULONG ioLength;
46 BOOLEAN freeSysBuf;
47 BOOLEAN setBufferAndLength;
48 FxIrp* irp;
49
51
52 ASSERT(MajorCode == IRP_MJ_WRITE || MajorCode == IRP_MJ_READ);
53
54 freeSysBuf = FALSE;
55 pBuffer = NULL;
56
57 status = Request->ValidateTarget(this);
58 if (!NT_SUCCESS(status)) {
59 return status;
60 }
61
62 if (Request->HasContextType(FX_RCT_IO)) {
63 pContext = (FxIoContext*) Request->GetContext();
64 }
65 else {
66 pContext = new(GetDriverGlobals()) FxIoContext();
67 if (pContext == NULL) {
69 "could not allocate context for request");
70
72 }
73
74 //
75 // Since we can error out and return, remember the allocation before
76 // we do anything so we can free it later.
77 //
78 Request->SetContext(pContext);
79 }
80
81 //
82 // Save away any references to IFxMemory pointers that are passed
83 //
84 pContext->StoreAndReferenceMemory(IoBuffer);
85
86 irp = Request->GetSubmitFxIrp();
88
90
91 //
92 // Note that by convention "Set" methods of FxIrp apply to next stack
93 // location unless specified otherwise in the name.
94 //
95 irp->SetMajorFunction(MajorCode);
96 pContext->m_MajorFunction = MajorCode;
97
98 //
99 // Anytime we return here and we allocated the context above, the context
100 // will be freed when the FxRequest is freed or reformatted.
101 //
102
103 ioLength = IoBuffer->GetBufferLength();
104
105 pContext->CaptureState(irp);
106
107 switch (m_TargetIoType) {
110
111 if (ioLength != 0) {
112
113
114 if ((pContext->m_BufferToFreeLength >= ioLength) &&
115 (pContext->m_BufferToFree != NULL)) {
117 setBufferAndLength = FALSE;
118 }
119 else {
120 irp->SetSystemBuffer(FxPoolAllocate(GetDriverGlobals(),
122 ioLength));
123 if (irp->GetSystemBuffer() == NULL) {
126 "Could not allocate common buffer");
127
129 break;
130 }
131
132 setBufferAndLength = TRUE;
133 freeSysBuf = TRUE;
134 }
135
136 status = IoBuffer->GetBuffer(&pBuffer);
137
138 if (!NT_SUCCESS(status)) {
141 "Could not retrieve io buffer, %!STATUS!", status);
142 break;
143 }
144
145 //
146 // If its a write, copy into the double buffer now, otherwise,
147 // no copy into the buffer is needed for a read.
148 //
149 if (MajorCode == IRP_MJ_WRITE) {
150 if (pBuffer != NULL) {
152 pBuffer,
153 ioLength);
154 }
155 }
156 else {
158 }
159
160 //
161 // On reads, copy back to the double buffer after the read has
162 // completed.
163 //
164 if (setBufferAndLength) {
166 ioLength,
167 (MajorCode == IRP_MJ_READ) ? TRUE : FALSE);
168
169 freeSysBuf = FALSE; // FxIoContext will free the buffer.
170 }
171 else {
172 pContext->m_CopyBackToBuffer = MajorCode == IRP_MJ_READ ?
173 TRUE : FALSE;
174 }
175 }
176 else {
177 //
178 // This field was captured and will be restored by the context
179 // later.
180 //
182 }
183 break;
185 {
186 BOOLEAN reuseMdl;
187
188 reuseMdl = FALSE;
189
190 if (pContext->m_MdlToFree != NULL) {
191 reuseMdl = TRUE;
192 }
193
194 status = IoBuffer->GetOrAllocateMdl(
197 &pContext->m_MdlToFree,
198 &pContext->m_UnlockPages,
199 (MajorCode == IRP_MJ_READ) ? IoWriteAccess : IoReadAccess,
200 reuseMdl,
201 &pContext->m_MdlToFreeSize
202 );
203
204 if (!NT_SUCCESS(status)) {
207 "Could not retrieve io buffer as a PMDL, %!STATUS!",
208 status);
209 break;
210 }
211 break;
212 }
214 //
215 // Neither MDL nor buffered
216 //
217 status = IoBuffer->GetBuffer(&pBuffer);
218
219 if (NT_SUCCESS(status)) {
221 }
222 else {
225 "Could not retrieve io buffer as a PVOID, %!STATUS!",
226 status);
227 }
228 break;
229
231 default:
235 "Trying to format closed WDFIOTARGET %p, %!STATUS!",
236 GetHandle(), status);
237 break;
238 }
239
240 //
241 // We are assuming the read and write parts of the Parameters union
242 // are at the same offset. If this is FALSE, WDFCASSERT will not allow
243 // this file to compile, so keep these WDFCASSERTs here as long as the
244 // assumption is being made.
245 //
247 ==
249
251 ==
253
254 if (NT_SUCCESS(status)) {
255
257 if (DeviceOffset != NULL) {
259 }
260 else {
262 }
263
264 Request->VerifierSetFormatted();
265 }
266 else {
267 if (freeSysBuf) {
270 }
271
272 Request->ContextReleaseAndRestore();
273 }
274
275 return status;
276}
277
287 )
288{
289 FxIoContext* pContext;
292 ULONG inLength, outLength;
293 BOOLEAN freeSysBuf;
294 BOOLEAN setBufferAndLength;
295 FxIrp* irp;
296
298
299 irp = Request->GetSubmitFxIrp();
300 freeSysBuf = FALSE;
301
302 status = Request->ValidateTarget(this);
303 if (!NT_SUCCESS(status)) {
304 return status;
305 }
306
307 if (Request->HasContextType(FX_RCT_IO)) {
308 pContext = (FxIoContext*) Request->GetContext();
309 }
310 else {
311 pContext = new(GetDriverGlobals()) FxIoContext();
312 if (pContext == NULL) {
315 "Could not allocate context for request");
316
318 }
319
320 Request->SetContext(pContext);
321 }
322
323 pContext->CaptureState(irp);
324
326
327 //
328 // Save away any references to IFxMemory pointers that are passed
329 //
332
334 if (Internal) {
336 }
337 else {
339 }
340
342
343 pContext->m_MajorFunction = majorFunction;
344
346
347 inLength = InputBuffer->GetBufferLength();
348 outLength = OutputBuffer->GetBufferLength();
349
353
354
355 //
356 // Anytime we return here and we allocated the context above, the context
357 // will be freed when the FxRequest is freed or reformatted.
358 //
359 switch (METHOD_FROM_CTL_CODE(Ioctl)) {
360 case METHOD_BUFFERED:
361
362 if (inLength != 0 || outLength != 0) {
363 ULONG allocationLength;
364
365 allocationLength = (inLength > outLength ? inLength : outLength);
366
367 if ((pContext->m_BufferToFreeLength >= allocationLength) &&
368 (pContext->m_BufferToFree != NULL)) {
370 setBufferAndLength = FALSE;
371 }
372 else {
373 irp->SetSystemBuffer(FxPoolAllocate(GetDriverGlobals(),
375 allocationLength));
376 if (irp->GetSystemBuffer() == NULL) {
379 "Could not allocate common buffer");
381 break;
382 }
383 setBufferAndLength = TRUE;
384 freeSysBuf = TRUE;
385 }
386
387 status = InputBuffer->GetBuffer(&pBuffer);
388 if (!NT_SUCCESS(status)) {
391 "Could not retrieve input buffer, %!STATUS!",
392 status);
393 break;
394 }
395
396 if (pBuffer != NULL) {
398 pBuffer,
399 inLength);
400 }
401
402 status = OutputBuffer->GetBuffer(&pBuffer);
403 if (!NT_SUCCESS(status)) {
406 "Could not retrieve output buffer, %!STATUS!",
407 status);
408 break;
409 }
410
412 if (setBufferAndLength) {
414 allocationLength,
415 outLength > 0 ? TRUE : FALSE);
416 freeSysBuf = FALSE; // FxIoContext will free the buffer.
417 } else {
418 pContext->m_CopyBackToBuffer = outLength > 0 ? TRUE : FALSE;
419 }
420
421 }
422 else {
423 //
424 // These fields were captured and will be restored by the context
425 // later.
426 //
429 }
430
431 break;
432
433 case METHOD_DIRECT_TO_HARDWARE: // METHOD_IN_DIRECT
434 case METHOD_DIRECT_FROM_HARDWARE: // METHOD_OUT_DIRECT
435 {
436 BOOLEAN reuseMdl;
437
438 reuseMdl = FALSE;
439
440 status = InputBuffer->GetBuffer(&pBuffer);
441 if (!NT_SUCCESS(status)) {
444 "Could not retrieve input buffer as a PVOID, %!STATUS!",
445 status);
446 break;
447 }
448
450
451 //
452 // NOTE: There is no need to compare the operation type since that
453 // applies only to the Pages locked in memory and not the MDL data
454 // structure itself per se.
455 // Also, note that if the size of the Outbuf need not be equal to the
456 // size of the MdlToFree as long as the number of page entries match.
457 //
458 if (pContext->m_MdlToFree != NULL) {
459 reuseMdl = TRUE;
460 }
461
462 status = OutputBuffer->GetOrAllocateMdl(
465 &pContext->m_MdlToFree,
466 &pContext->m_UnlockPages,
468 reuseMdl,
469 &pContext->m_MdlToFreeSize
470 );
471
472 if (!NT_SUCCESS(status)) {
475 "Could not retrieve output buffer as a PMDL, %!STATUS!",
476 status);
477 break;
478 }
479 break;
480 }
481
482 case METHOD_NEITHER:
483 status = OutputBuffer->GetBuffer(&pBuffer);
484
485 if (!NT_SUCCESS(status)) {
488 "Could not retrieve output buffer as a PVOID, %!STATUS!",
489 status);
490 break;
491 }
492
494
495 status = InputBuffer->GetBuffer(&pBuffer);
496
497 if (!NT_SUCCESS(status)) {
500 "Could not retrieve input buffer as a PVOID, %!STATUS!",
501 status);
502
503 break;
504 }
505
507 break;
508 }
509
510 if (NT_SUCCESS(status)) {
511 Request->VerifierSetFormatted();
512 }
513 else {
514 if (freeSysBuf) {
517 }
518
519 Request->ContextReleaseAndRestore();
520 }
521
522 return status;
523}
524
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
UCHAR m_TargetIoType
Definition: fxiotarget.hpp:947
__inline VOID CopyFileObjectAndFlags(__in FxRequestBase *Request)
Definition: fxiotarget.hpp:743
_Must_inspect_result_ NTSTATUS FormatIoctlRequest(__in FxRequestBase *Request, __in ULONG Ioctl, __in BOOLEAN Internal, __in FxRequestBuffer *InputBuffer, __in FxRequestBuffer *OutputBuffer, __in_opt FxFileObject *FileObject=NULL)
_Must_inspect_result_ NTSTATUS FormatIoRequest(__inout FxRequestBase *Request, __in UCHAR MajorCode, __in FxRequestBuffer *IoBuffer, __in_opt PLONGLONG StartingOffset, __in_opt FxFileObject *FileObject=NULL)
Definition: fxirp.hpp:28
PMDL * GetMdlAddressPointer()
Definition: fxirpum.cpp:1323
VOID SetSystemBuffer(__in PVOID Value)
Definition: fxirpum.cpp:1313
VOID SetMajorFunction(__in UCHAR MajorFunction)
Definition: fxirpum.cpp:905
VOID SetParameterIoctlCode(__in ULONG DeviceIoControlCode)
Definition: fxirpum.cpp:1157
PVOID GetSystemBuffer()
Definition: fxirpum.cpp:543
VOID SetNextParameterWriteLength(__in ULONG IoLength)
Definition: fxirpum.cpp:1398
VOID SetParameterIoctlInputBufferLength(__in ULONG InputBufferLength)
Definition: fxirpum.cpp:1166
VOID SetParameterIoctlType3InputBuffer(__in PVOID Type3InputBuffer)
Definition: fxirpum.cpp:1175
VOID SetUserBuffer(__in PVOID Value)
Definition: fxirpum.cpp:1341
VOID SetParameterIoctlOutputBufferLength(__in ULONG OutputBufferLength)
Definition: fxirpum.cpp:1532
VOID ClearNextStackLocation(VOID)
Definition: fxirpum.cpp:1581
VOID SetNextParameterWriteByteOffsetQuadPart(__in LONGLONG DeviceOffset)
Definition: fxirpum.cpp:1385
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
#define __in
Definition: dbghelp.h:35
#define __inout
Definition: dbghelp.h:50
#define __in_opt
Definition: dbghelp.h:38
#define TRACINGIOTARGET
Definition: dbgtrace.h:72
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define NonPagedPool
Definition: env_spec_w32.h:307
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
_Must_inspect_result_ __in WDFIOTARGET __in_opt WDFREQUEST __in ULONG Ioctl
void FxPoolFree(__in_xcount(ptr is at an offset from AllocationStart) PVOID ptr)
Definition: wdfpool.cpp:361
UCHAR majorFunction
FxIrp * irp
@ Internal
Definition: hwresource.cpp:137
#define ASSERT(a)
Definition: mode.c:44
#define _Must_inspect_result_
Definition: ms_sal.h:558
#define _In_opt_
Definition: ms_sal.h:309
#define METHOD_NEITHER
Definition: nt_native.h:597
#define METHOD_BUFFERED
Definition: nt_native.h:594
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
__GNU_EXTENSION typedef __int64 * PLONGLONG
Definition: ntbasedef.h:382
PVOID pBuffer
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
PVOID m_BufferToFree
Definition: fxiotarget.hpp:91
VOID StoreAndReferenceOtherMemory(__in FxRequestBuffer *Buffer)
Definition: fxiotarget.hpp:44
UCHAR m_MajorFunction
Definition: fxiotarget.hpp:114
PMDL m_MdlToFree
Definition: fxiotarget.hpp:94
BOOLEAN m_UnlockPages
Definition: fxiotarget.hpp:105
BOOLEAN m_CopyBackToBuffer
Definition: fxiotarget.hpp:104
size_t m_MdlToFreeSize
Definition: fxiotarget.hpp:103
VOID SetBufferAndLength(__in PVOID Buffer, __in size_t BufferLength, __in BOOLEAN CopyBackToBuffer)
size_t m_BufferToFreeLength
Definition: fxiotarget.hpp:102
VOID CaptureState(__in FxIrp *Irp)
virtual VOID StoreAndReferenceMemory(__in FxRequestBuffer *Buffer)
struct _IO_STACK_LOCATION::@3978::@3983 Write
struct _IO_STACK_LOCATION::@3978::@3982 Read
Definition: ps.c:97
#define GetHandle(h)
Definition: treelist.c:116
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_STATE
Definition: udferr_usr.h:178
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define WDFCASSERT(c)
Definition: wdfassert.h:93
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
@ WdfDeviceIoNeither
Definition: wdfdevice.h:451
@ WdfDeviceIoUndefined
Definition: wdfdevice.h:450
@ WdfDeviceIoBuffered
Definition: wdfdevice.h:452
@ WdfDeviceIoDirect
Definition: wdfdevice.h:453
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ WDFREQUEST _In_opt_ WDFFILEOBJECT _Inout_opt_ PWDF_REQUEST_PARAMETERS Parameters
Definition: wdfio.h:869
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG DeviceOffset
Definition: wdfiotarget.h:865
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
#define METHOD_DIRECT_FROM_HARDWARE
#define METHOD_FROM_CTL_CODE(ctrlCode)
#define IRP_MJ_INTERNAL_DEVICE_CONTROL
#define METHOD_DIRECT_TO_HARDWARE
@ IoReadAccess
Definition: ketypes.h:863
@ IoWriteAccess
Definition: ketypes.h:864
unsigned char UCHAR
Definition: xmlstorage.h:181