mirror of
https://github.com/reactos/reactos.git
synced 2025-03-10 18:24:02 +00:00
270 lines
5.7 KiB
C++
270 lines
5.7 KiB
C++
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
FxIoTarget.hpp
|
|
|
|
Abstract:
|
|
|
|
Encapsulation of the target to which FxRequest are sent to. For example,
|
|
an FxTarget could represent the next device object in the pnp stack.
|
|
Derivations from this class could include bus specific formatters or device
|
|
objects outside of the pnp stack of the device.
|
|
|
|
Author:
|
|
|
|
|
|
|
|
Environment:
|
|
|
|
Kernel mode only
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#ifndef _FXIOTARGETKM_H_
|
|
#define _FXIOTARGETKM_H_
|
|
|
|
__inline
|
|
FxIoContext::FxIoContext(
|
|
VOID
|
|
) :
|
|
FxRequestContext(FX_RCT_IO),
|
|
m_MdlToFree(NULL),
|
|
m_OriginalMdl(NULL),
|
|
m_BufferToFree(NULL),
|
|
m_OriginalSystemBuffer(NULL),
|
|
m_OriginalUserBuffer(NULL),
|
|
m_OtherMemory(NULL),
|
|
m_CopyBackToBuffer(FALSE),
|
|
m_UnlockPages(FALSE),
|
|
m_RestoreState(FALSE),
|
|
m_BufferToFreeLength(0),
|
|
m_MdlToFreeSize(0)
|
|
{
|
|
}
|
|
|
|
__inline
|
|
FxIoContext::~FxIoContext(
|
|
VOID
|
|
)
|
|
{
|
|
//
|
|
// Free the buffer allocated for the request, reset m_CopyBackToBuffer
|
|
// to FALSE.
|
|
// NOTE: We delay the freeing of the buffer on purpose.
|
|
//
|
|
ClearBuffer();
|
|
|
|
//
|
|
// Free the MDL allocated for the request
|
|
//
|
|
if (m_MdlToFree != NULL) {
|
|
//
|
|
// Being defensive here, MmUnlockPages should have been done in
|
|
// ReleaseAndRestore.
|
|
//
|
|
if (m_UnlockPages) {
|
|
MmUnlockPages(m_MdlToFree);
|
|
m_UnlockPages = FALSE;
|
|
}
|
|
|
|
FxMdlFree(m_DriverGlobals, m_MdlToFree);
|
|
m_MdlToFree = NULL;
|
|
}
|
|
}
|
|
|
|
__inline
|
|
VOID
|
|
FxIoContext::ReleaseAndRestore(
|
|
__in FxRequestBase* Request
|
|
)
|
|
{
|
|
FxIrp* irp = NULL;
|
|
|
|
irp = Request->GetSubmitFxIrp();
|
|
|
|
if (m_RestoreState) {
|
|
irp->SetSystemBuffer(m_OriginalSystemBuffer);
|
|
irp->SetUserBuffer(m_OriginalUserBuffer);
|
|
irp->SetMdlAddress(m_OriginalMdl);
|
|
irp->SetFlags(m_OriginalFlags);
|
|
m_OriginalSystemBuffer = NULL;
|
|
m_OriginalUserBuffer = NULL;
|
|
m_OriginalMdl = NULL;
|
|
m_OriginalFlags = NULL;
|
|
|
|
m_RestoreState = FALSE;
|
|
}
|
|
|
|
//
|
|
// If there was a buffer present don't free the buffer here so that
|
|
// it can be reused for any request with the same size.
|
|
// Similarly if there was an MDL to be freed unlock the pages but dont free
|
|
// the Mdl so that it can be reused.
|
|
//
|
|
if (m_MdlToFree != NULL) {
|
|
if (m_UnlockPages) {
|
|
MmUnlockPages(m_MdlToFree);
|
|
m_UnlockPages = FALSE;
|
|
}
|
|
|
|
|
|
m_DriverGlobals = Request->GetDriverGlobals();
|
|
}
|
|
|
|
//
|
|
// Release the 2ndary buffer if we have an outstanding reference
|
|
//
|
|
if (m_OtherMemory != NULL) {
|
|
m_OtherMemory->RELEASE(this);
|
|
m_OtherMemory = NULL;
|
|
}
|
|
|
|
//
|
|
// Release the other buffer and all __super related fields
|
|
//
|
|
__super::ReleaseAndRestore(Request);
|
|
}
|
|
|
|
__inline
|
|
VOID
|
|
FxIoContext::ClearBuffer(
|
|
VOID
|
|
)
|
|
{
|
|
if (m_BufferToFree != NULL) {
|
|
FxPoolFree(m_BufferToFree);
|
|
m_BufferToFree = NULL;
|
|
}
|
|
|
|
m_BufferToFreeLength = 0;
|
|
m_CopyBackToBuffer = FALSE;
|
|
}
|
|
|
|
__inline
|
|
VOID
|
|
FxIoContext::CopyParameters(
|
|
__in FxRequestBase* Request
|
|
)
|
|
{
|
|
switch (m_MajorFunction) {
|
|
case IRP_MJ_WRITE:
|
|
m_CompletionParams.Parameters.Write.Length =
|
|
m_CompletionParams.IoStatus.Information;
|
|
break;
|
|
|
|
case IRP_MJ_READ:
|
|
m_CompletionParams.Parameters.Read.Length =
|
|
m_CompletionParams.IoStatus.Information;
|
|
break;
|
|
|
|
case IRP_MJ_DEVICE_CONTROL:
|
|
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
|
|
m_CompletionParams.Parameters.Ioctl.Output.Length =
|
|
m_CompletionParams.IoStatus.Information;
|
|
break;
|
|
|
|
default:
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
if (m_BufferToFree == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (m_CopyBackToBuffer) {
|
|
FxIrp* irp = Request->GetSubmitFxIrp();
|
|
|
|
if (irp->GetUserBuffer() != NULL) {
|
|
//
|
|
// UserBuffer contains the caller's original output buffer.
|
|
// Copy the results back into the original buffer.
|
|
//
|
|
if (m_MajorFunction == IRP_MJ_DEVICE_CONTROL ||
|
|
m_MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) {
|
|
ASSERT(irp->GetInformation() <= m_BufferToFreeLength);
|
|
}
|
|
|
|
RtlCopyMemory(irp->GetUserBuffer(),
|
|
m_BufferToFree,
|
|
irp->GetInformation());
|
|
m_CopyBackToBuffer = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
__inline
|
|
VOID
|
|
FxIoContext::CaptureState(
|
|
__in FxIrp* Irp
|
|
)
|
|
{
|
|
m_RestoreState = TRUE;
|
|
m_OriginalSystemBuffer = Irp->GetSystemBuffer();
|
|
m_OriginalUserBuffer = Irp->GetUserBuffer();
|
|
m_OriginalMdl = Irp->GetMdl();
|
|
m_OriginalFlags = Irp->GetFlags();
|
|
}
|
|
|
|
__inline
|
|
VOID
|
|
FxIoContext::SetBufferAndLength(
|
|
__in PVOID Buffer,
|
|
__in size_t BufferLength,
|
|
__in BOOLEAN CopyBackToBuffer
|
|
)
|
|
{
|
|
PVOID pOldBuffer;
|
|
|
|
pOldBuffer = m_BufferToFree;
|
|
m_BufferToFree = Buffer;
|
|
m_BufferToFreeLength = BufferLength;
|
|
m_CopyBackToBuffer = CopyBackToBuffer;
|
|
|
|
if (pOldBuffer != NULL) {
|
|
FxPoolFree(pOldBuffer);
|
|
}
|
|
}
|
|
|
|
|
|
__inline
|
|
_Must_inspect_result_
|
|
NTSTATUS
|
|
FxIoTarget::InitModeSpecific(
|
|
__in CfxDeviceBase* Device
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(Device);
|
|
|
|
DO_NOTHING();
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
__inline
|
|
BOOLEAN
|
|
FxIoTarget::HasValidStackSize(
|
|
VOID
|
|
)
|
|
{
|
|
return (m_TargetStackSize == 0 ? FALSE : TRUE);
|
|
}
|
|
|
|
__inline
|
|
VOID
|
|
FxIoTarget::Send(
|
|
_In_ MdIrp Irp
|
|
)
|
|
{
|
|
//
|
|
// Ignore the return value because once we have sent the request, we
|
|
// want all processing to be done in the completion routine.
|
|
//
|
|
(void) IoCallDriver(m_TargetDevice, Irp);
|
|
}
|
|
|
|
#endif // _FXIOTARGETKM_H_
|