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