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  
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  
44  FxIoTargetSelf::~FxIoTargetSelf()
45  {
46  }
47  
48  FxIoQueue*
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
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