ReactOS  0.4.15-dev-3207-ga415bd4
fxiotargetkm.cpp
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7  FxIoTargetKm.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 "FxIoTargetKm.tmh"
29 #endif
30 }
31 
36  __in UCHAR MajorCode,
37  __in FxRequestBuffer* IoBuffer,
40  )
41 {
42  FxIoContext* pContext;
43  PVOID pBuffer;
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) {
108  case WdfDeviceIoBuffered:
110 
111  if (ioLength != 0) {
112 
113 
114  if ((pContext->m_BufferToFreeLength >= ioLength) &&
115  (pContext->m_BufferToFree != NULL)) {
116  irp->SetSystemBuffer(pContext->m_BufferToFree);
117  setBufferAndLength = FALSE;
118  }
119  else {
120  irp->SetSystemBuffer(FxPoolAllocate(GetDriverGlobals(),
121  NonPagedPool,
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;
184  case WdfDeviceIoDirect:
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  }
213  case WdfDeviceIoNeither:
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 
256  irp->SetNextParameterWriteLength(ioLength);
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 
279 NTSTATUS
282  __in ULONG Ioctl,
287  )
288 {
289  FxIoContext* pContext;
291  PVOID pBuffer;
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)) {
369  irp->SetSystemBuffer(pContext->m_BufferToFree);
370  setBufferAndLength = FALSE;
371  }
372  else {
373  irp->SetSystemBuffer(FxPoolAllocate(GetDriverGlobals(),
374  NonPagedPool,
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 
VOID SetMajorFunction(__in UCHAR MajorFunction)
Definition: fxirpum.cpp:905
VOID SetParameterIoctlType3InputBuffer(__in PVOID Type3InputBuffer)
Definition: fxirpum.cpp:1175
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define METHOD_DIRECT_TO_HARDWARE
#define _In_opt_
Definition: ms_sal.h:309
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ WDFREQUEST _In_opt_ WDFFILEOBJECT _Inout_opt_ PWDF_REQUEST_PARAMETERS Parameters
Definition: wdfio.h:863
#define METHOD_FROM_CTL_CODE(ctrlCode)
PMDL m_MdlToFree
Definition: fxiotarget.hpp:94
#define __in_opt
Definition: dbghelp.h:38
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG DeviceOffset
Definition: wdfiotarget.h:859
WDFCASSERT(sizeof(WDF_DRIVER_CONFIG_V1_0)==sizeof(WDF_DRIVER_CONFIG_V1_1))
LONG NTSTATUS
Definition: precomp.h:26
__inline VOID CopyFileObjectAndFlags(__in FxRequestBase *Request)
Definition: fxiotarget.hpp:743
Definition: fxirp.hpp:28
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
#define METHOD_DIRECT_FROM_HARDWARE
VOID SetUserBuffer(__in PVOID Value)
Definition: fxirpum.cpp:1341
struct _IO_STACK_LOCATION::@3728::@3733 Write
size_t m_BufferToFreeLength
Definition: fxiotarget.hpp:102
#define STATUS_INVALID_DEVICE_STATE
Definition: udferr_usr.h:178
_Must_inspect_result_ __in WDFIOTARGET __in_opt WDFREQUEST __in ULONG Ioctl
UCHAR m_MajorFunction
Definition: fxiotarget.hpp:114
__GNU_EXTENSION typedef __int64 * PLONGLONG
Definition: ntbasedef.h:382
WDFIOTARGET GetHandle(VOID)
Definition: fxiotarget.hpp:307
PMDL * GetMdlAddressPointer()
Definition: fxirpum.cpp:1323
VOID SetParameterIoctlOutputBufferLength(__in ULONG OutputBufferLength)
Definition: fxirpum.cpp:1532
#define METHOD_NEITHER
Definition: nt_native.h:597
#define FALSE
Definition: types.h:117
_Must_inspect_result_ NTSTATUS FormatIoRequest(__inout FxRequestBase *Request, __in UCHAR MajorCode, __in FxRequestBuffer *IoBuffer, __in_opt PLONGLONG StartingOffset, __in_opt FxFileObject *FileObject=NULL)
unsigned char BOOLEAN
PVOID pBuffer
VOID ClearNextStackLocation(VOID)
Definition: fxirpum.cpp:1581
VOID SetSystemBuffer(__in PVOID Value)
Definition: fxirpum.cpp:1313
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:859
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:949
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
VOID SetParameterIoctlInputBufferLength(__in ULONG InputBufferLength)
Definition: fxirpum.cpp:1166
#define IRP_MJ_INTERNAL_DEVICE_CONTROL
VOID SetNextParameterWriteLength(__in ULONG IoLength)
Definition: fxirpum.cpp:1398
unsigned char UCHAR
Definition: xmlstorage.h:181
VOID SetNextParameterWriteByteOffsetQuadPart(__in LONGLONG DeviceOffset)
Definition: fxirpum.cpp:1385
VOID SetBufferAndLength(__in PVOID Buffer, __in size_t BufferLength, __in BOOLEAN CopyBackToBuffer)
BOOLEAN m_UnlockPages
Definition: fxiotarget.hpp:105
_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)
UCHAR m_TargetIoType
Definition: fxiotarget.hpp:947
#define __inout
Definition: dbghelp.h:50
virtual VOID StoreAndReferenceMemory(__in FxRequestBuffer *Buffer)
#define _Must_inspect_result_
Definition: ms_sal.h:558
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
PVOID GetSystemBuffer()
Definition: fxirpum.cpp:543
PVOID m_BufferToFree
Definition: fxiotarget.hpp:91
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
#define METHOD_BUFFERED
Definition: nt_native.h:594
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NULL
Definition: types.h:112
UCHAR majorFunction
#define IRP_MJ_READ
Definition: rdpdr.c:46
VOID SetParameterIoctlCode(__in ULONG DeviceIoControlCode)
Definition: fxirpum.cpp:1157
unsigned int ULONG
Definition: retypes.h:1
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
VOID CaptureState(__in FxIrp *Irp)
struct _IO_STACK_LOCATION::@3728::@3732 Read
BOOLEAN m_CopyBackToBuffer
Definition: fxiotarget.hpp:104
void FxPoolFree(__in_xcount(ptr is at an offset from AllocationStart) PVOID ptr)
Definition: wdfpool.cpp:361
#define __in
Definition: dbghelp.h:35
static SERVICE_STATUS status
Definition: service.c:31
size_t m_MdlToFreeSize
Definition: fxiotarget.hpp:103
#define TRACINGIOTARGET
Definition: dbgtrace.h:72
FxIrp * irp
VOID StoreAndReferenceOtherMemory(__in FxRequestBuffer *Buffer)
Definition: fxiotarget.hpp:44
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
Definition: ps.c:97