1 /*++ 2 3 Copyright (c) Microsoft Corporation. All rights reserved. 4 5 Module Name: 6 7 FxIoTarget.hpp 8 9 Abstract: 10 11 Encapsulation of the target to which FxRequest are sent to. For example, 12 an FxTarget could represent the next device object in the pnp stack. 13 Derivations from this class could include bus specific formatters or device 14 objects outside of the pnp stack of the device. 15 16 Author: 17 18 19 20 Environment: 21 22 Kernel mode only 23 24 Revision History: 25 26 --*/ 27 28 #ifndef _FXIOTARGETKM_H_ 29 #define _FXIOTARGETKM_H_ 30 31 __inline 32 FxIoContext::FxIoContext( 33 VOID 34 ) : 35 FxRequestContext(FX_RCT_IO), 36 m_MdlToFree(NULL), 37 m_OriginalMdl(NULL), 38 m_BufferToFree(NULL), 39 m_OriginalSystemBuffer(NULL), 40 m_OriginalUserBuffer(NULL), 41 m_OtherMemory(NULL), 42 m_CopyBackToBuffer(FALSE), 43 m_UnlockPages(FALSE), 44 m_RestoreState(FALSE), 45 m_BufferToFreeLength(0), 46 m_MdlToFreeSize(0) 47 { 48 } 49 50 __inline 51 FxIoContext::~FxIoContext( 52 VOID 53 ) 54 { 55 // 56 // Free the buffer allocated for the request, reset m_CopyBackToBuffer 57 // to FALSE. 58 // NOTE: We delay the freeing of the buffer on purpose. 59 // 60 ClearBuffer(); 61 62 // 63 // Free the MDL allocated for the request 64 // 65 if (m_MdlToFree != NULL) { 66 // 67 // Being defensive here, MmUnlockPages should have been done in 68 // ReleaseAndRestore. 69 // 70 if (m_UnlockPages) { 71 MmUnlockPages(m_MdlToFree); 72 m_UnlockPages = FALSE; 73 } 74 75 FxMdlFree(m_DriverGlobals, m_MdlToFree); 76 m_MdlToFree = NULL; 77 } 78 } 79 80 __inline 81 VOID 82 FxIoContext::ReleaseAndRestore( 83 __in FxRequestBase* Request 84 ) 85 { 86 FxIrp* irp = NULL; 87 88 irp = Request->GetSubmitFxIrp(); 89 90 if (m_RestoreState) { 91 irp->SetSystemBuffer(m_OriginalSystemBuffer); 92 irp->SetUserBuffer(m_OriginalUserBuffer); 93 irp->SetMdlAddress(m_OriginalMdl); 94 irp->SetFlags(m_OriginalFlags); 95 m_OriginalSystemBuffer = NULL; 96 m_OriginalUserBuffer = NULL; 97 m_OriginalMdl = NULL; 98 m_OriginalFlags = NULL; 99 100 m_RestoreState = FALSE; 101 } 102 103 // 104 // If there was a buffer present don't free the buffer here so that 105 // it can be reused for any request with the same size. 106 // Similarly if there was an MDL to be freed unlock the pages but dont free 107 // the Mdl so that it can be reused. 108 // 109 if (m_MdlToFree != NULL) { 110 if (m_UnlockPages) { 111 MmUnlockPages(m_MdlToFree); 112 m_UnlockPages = FALSE; 113 } 114 115 116 m_DriverGlobals = Request->GetDriverGlobals(); 117 } 118 119 // 120 // Release the 2ndary buffer if we have an outstanding reference 121 // 122 if (m_OtherMemory != NULL) { 123 m_OtherMemory->RELEASE(this); 124 m_OtherMemory = NULL; 125 } 126 127 // 128 // Release the other buffer and all __super related fields 129 // 130 FxRequestContext::ReleaseAndRestore(Request); // __super call 131 } 132 133 __inline 134 VOID 135 FxIoContext::ClearBuffer( 136 VOID 137 ) 138 { 139 if (m_BufferToFree != NULL) { 140 FxPoolFree(m_BufferToFree); 141 m_BufferToFree = NULL; 142 } 143 144 m_BufferToFreeLength = 0; 145 m_CopyBackToBuffer = FALSE; 146 } 147 148 __inline 149 VOID 150 FxIoContext::CopyParameters( 151 __in FxRequestBase* Request 152 ) 153 { 154 switch (m_MajorFunction) { 155 case IRP_MJ_WRITE: 156 m_CompletionParams.Parameters.Write.Length = 157 m_CompletionParams.IoStatus.Information; 158 break; 159 160 case IRP_MJ_READ: 161 m_CompletionParams.Parameters.Read.Length = 162 m_CompletionParams.IoStatus.Information; 163 break; 164 165 case IRP_MJ_DEVICE_CONTROL: 166 case IRP_MJ_INTERNAL_DEVICE_CONTROL: 167 m_CompletionParams.Parameters.Ioctl.Output.Length = 168 m_CompletionParams.IoStatus.Information; 169 break; 170 171 default: 172 ASSERT(FALSE); 173 } 174 175 if (m_BufferToFree == NULL) { 176 return; 177 } 178 179 if (m_CopyBackToBuffer) { 180 FxIrp* irp = Request->GetSubmitFxIrp(); 181 182 if (irp->GetUserBuffer() != NULL) { 183 // 184 // UserBuffer contains the caller's original output buffer. 185 // Copy the results back into the original buffer. 186 // 187 if (m_MajorFunction == IRP_MJ_DEVICE_CONTROL || 188 m_MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) { 189 ASSERT(irp->GetInformation() <= m_BufferToFreeLength); 190 } 191 192 RtlCopyMemory(irp->GetUserBuffer(), 193 m_BufferToFree, 194 irp->GetInformation()); 195 m_CopyBackToBuffer = FALSE; 196 } 197 } 198 } 199 200 __inline 201 VOID 202 FxIoContext::CaptureState( 203 __in FxIrp* Irp 204 ) 205 { 206 m_RestoreState = TRUE; 207 m_OriginalSystemBuffer = Irp->GetSystemBuffer(); 208 m_OriginalUserBuffer = Irp->GetUserBuffer(); 209 m_OriginalMdl = Irp->GetMdl(); 210 m_OriginalFlags = Irp->GetFlags(); 211 } 212 213 __inline 214 VOID 215 FxIoContext::SetBufferAndLength( 216 __in PVOID Buffer, 217 __in size_t BufferLength, 218 __in BOOLEAN CopyBackToBuffer 219 ) 220 { 221 PVOID pOldBuffer; 222 223 pOldBuffer = m_BufferToFree; 224 m_BufferToFree = Buffer; 225 m_BufferToFreeLength = BufferLength; 226 m_CopyBackToBuffer = CopyBackToBuffer; 227 228 if (pOldBuffer != NULL) { 229 FxPoolFree(pOldBuffer); 230 } 231 } 232 233 234 __inline 235 _Must_inspect_result_ 236 NTSTATUS 237 FxIoTarget::InitModeSpecific( 238 __in CfxDeviceBase* Device 239 ) 240 { 241 UNREFERENCED_PARAMETER(Device); 242 243 DO_NOTHING(); 244 245 return STATUS_SUCCESS; 246 } 247 248 __inline 249 BOOLEAN 250 FxIoTarget::HasValidStackSize( 251 VOID 252 ) 253 { 254 return (m_TargetStackSize == 0 ? FALSE : TRUE); 255 } 256 257 __inline 258 VOID 259 FxIoTarget::Send( 260 _In_ MdIrp Irp 261 ) 262 { 263 // 264 // Ignore the return value because once we have sent the request, we 265 // want all processing to be done in the completion routine. 266 // 267 (void) IoCallDriver(m_TargetDevice, Irp); 268 } 269 270 #endif // _FXIOTARGETKM_H_ 271