mirror of
https://github.com/reactos/reactos.git
synced 2025-08-07 05:52:57 +00:00
[WDF] Add Windows Driver Framework files
Takern from Microsoft GitHub repo:
d9c6040fe9
Licensed under MIT
This commit is contained in:
parent
545df81502
commit
8a978a179f
475 changed files with 285099 additions and 0 deletions
524
sdk/lib/drivers/wdf/shared/targets/general/km/fxiotargetkm.cpp
Normal file
524
sdk/lib/drivers/wdf/shared/targets/general/km/fxiotargetkm.cpp
Normal file
|
@ -0,0 +1,524 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxIoTargetKm.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements the IO Target APIs
|
||||
|
||||
Author:
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#include "..\..\FxTargetsShared.hpp"
|
||||
|
||||
extern "C" {
|
||||
#if defined(EVENT_TRACING)
|
||||
#include "FxIoTargetKm.tmh"
|
||||
#endif
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxIoTarget::FormatIoRequest(
|
||||
__inout FxRequestBase* Request,
|
||||
__in UCHAR MajorCode,
|
||||
__in FxRequestBuffer* IoBuffer,
|
||||
__in_opt PLONGLONG DeviceOffset,
|
||||
_In_opt_ FxFileObject* FileObject
|
||||
)
|
||||
{
|
||||
FxIoContext* pContext;
|
||||
PVOID pBuffer;
|
||||
NTSTATUS status;
|
||||
ULONG ioLength;
|
||||
BOOLEAN freeSysBuf;
|
||||
BOOLEAN setBufferAndLength;
|
||||
FxIrp* irp;
|
||||
|
||||
UNREFERENCED_PARAMETER(FileObject);
|
||||
|
||||
ASSERT(MajorCode == IRP_MJ_WRITE || MajorCode == IRP_MJ_READ);
|
||||
|
||||
freeSysBuf = FALSE;
|
||||
pBuffer = NULL;
|
||||
|
||||
status = Request->ValidateTarget(this);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (Request->HasContextType(FX_RCT_IO)) {
|
||||
pContext = (FxIoContext*) Request->GetContext();
|
||||
}
|
||||
else {
|
||||
pContext = new(GetDriverGlobals()) FxIoContext();
|
||||
if (pContext == NULL) {
|
||||
DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"could not allocate context for request");
|
||||
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Since we can error out and return, remember the allocation before
|
||||
// we do anything so we can free it later.
|
||||
//
|
||||
Request->SetContext(pContext);
|
||||
}
|
||||
|
||||
//
|
||||
// Save away any references to IFxMemory pointers that are passed
|
||||
//
|
||||
pContext->StoreAndReferenceMemory(IoBuffer);
|
||||
|
||||
irp = Request->GetSubmitFxIrp();
|
||||
irp->ClearNextStackLocation();
|
||||
|
||||
CopyFileObjectAndFlags(Request);
|
||||
|
||||
//
|
||||
// Note that by convention "Set" methods of FxIrp apply to next stack
|
||||
// location unless specified otherwise in the name.
|
||||
//
|
||||
irp->SetMajorFunction(MajorCode);
|
||||
pContext->m_MajorFunction = MajorCode;
|
||||
|
||||
//
|
||||
// Anytime we return here and we allocated the context above, the context
|
||||
// will be freed when the FxRequest is freed or reformatted.
|
||||
//
|
||||
|
||||
ioLength = IoBuffer->GetBufferLength();
|
||||
|
||||
pContext->CaptureState(irp);
|
||||
|
||||
switch (m_TargetIoType) {
|
||||
case WdfDeviceIoBuffered:
|
||||
irp->SetUserBuffer(NULL);
|
||||
|
||||
if (ioLength != 0) {
|
||||
|
||||
|
||||
if ((pContext->m_BufferToFreeLength >= ioLength) &&
|
||||
(pContext->m_BufferToFree != NULL)) {
|
||||
irp->SetSystemBuffer(pContext->m_BufferToFree);
|
||||
setBufferAndLength = FALSE;
|
||||
}
|
||||
else {
|
||||
irp->SetSystemBuffer(FxPoolAllocate(GetDriverGlobals(),
|
||||
NonPagedPool,
|
||||
ioLength));
|
||||
if (irp->GetSystemBuffer() == NULL) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not allocate common buffer");
|
||||
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
break;
|
||||
}
|
||||
|
||||
setBufferAndLength = TRUE;
|
||||
freeSysBuf = TRUE;
|
||||
}
|
||||
|
||||
status = IoBuffer->GetBuffer(&pBuffer);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not retrieve io buffer, %!STATUS!", status);
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// If its a write, copy into the double buffer now, otherwise,
|
||||
// no copy into the buffer is needed for a read.
|
||||
//
|
||||
if (MajorCode == IRP_MJ_WRITE) {
|
||||
if (pBuffer != NULL) {
|
||||
RtlCopyMemory(irp->GetSystemBuffer(),
|
||||
pBuffer,
|
||||
ioLength);
|
||||
}
|
||||
}
|
||||
else {
|
||||
irp->SetUserBuffer(pBuffer);
|
||||
}
|
||||
|
||||
//
|
||||
// On reads, copy back to the double buffer after the read has
|
||||
// completed.
|
||||
//
|
||||
if (setBufferAndLength) {
|
||||
pContext->SetBufferAndLength(irp->GetSystemBuffer(),
|
||||
ioLength,
|
||||
(MajorCode == IRP_MJ_READ) ? TRUE : FALSE);
|
||||
|
||||
freeSysBuf = FALSE; // FxIoContext will free the buffer.
|
||||
}
|
||||
else {
|
||||
pContext->m_CopyBackToBuffer = MajorCode == IRP_MJ_READ ?
|
||||
TRUE : FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//
|
||||
// This field was captured and will be restored by the context
|
||||
// later.
|
||||
//
|
||||
irp->SetSystemBuffer(NULL);
|
||||
}
|
||||
break;
|
||||
case WdfDeviceIoDirect:
|
||||
{
|
||||
BOOLEAN reuseMdl;
|
||||
|
||||
reuseMdl = FALSE;
|
||||
|
||||
if (pContext->m_MdlToFree != NULL) {
|
||||
reuseMdl = TRUE;
|
||||
}
|
||||
|
||||
status = IoBuffer->GetOrAllocateMdl(
|
||||
GetDriverGlobals(),
|
||||
irp->GetMdlAddressPointer(),
|
||||
&pContext->m_MdlToFree,
|
||||
&pContext->m_UnlockPages,
|
||||
(MajorCode == IRP_MJ_READ) ? IoWriteAccess : IoReadAccess,
|
||||
reuseMdl,
|
||||
&pContext->m_MdlToFreeSize
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not retrieve io buffer as a PMDL, %!STATUS!",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WdfDeviceIoNeither:
|
||||
//
|
||||
// Neither MDL nor buffered
|
||||
//
|
||||
status = IoBuffer->GetBuffer(&pBuffer);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
irp->SetUserBuffer(pBuffer);
|
||||
}
|
||||
else {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not retrieve io buffer as a PVOID, %!STATUS!",
|
||||
status);
|
||||
}
|
||||
break;
|
||||
|
||||
case WdfDeviceIoUndefined:
|
||||
default:
|
||||
status = STATUS_INVALID_DEVICE_STATE;
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Trying to format closed WDFIOTARGET %p, %!STATUS!",
|
||||
GetHandle(), status);
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// We are assuming the read and write parts of the Parameters union
|
||||
// are at the same offset. If this is FALSE, WDFCASSERT will not allow
|
||||
// this file to compile, so keep these WDFCASSERTs here as long as the
|
||||
// assumption is being made.
|
||||
//
|
||||
WDFCASSERT(FIELD_OFFSET(IO_STACK_LOCATION, Parameters.Write.ByteOffset)
|
||||
==
|
||||
FIELD_OFFSET(IO_STACK_LOCATION, Parameters.Read.ByteOffset));
|
||||
|
||||
WDFCASSERT(FIELD_OFFSET(IO_STACK_LOCATION, Parameters.Write.Length)
|
||||
==
|
||||
FIELD_OFFSET(IO_STACK_LOCATION, Parameters.Read.Length));
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
|
||||
irp->SetNextParameterWriteLength(ioLength);
|
||||
if (DeviceOffset != NULL) {
|
||||
irp->SetNextParameterWriteByteOffsetQuadPart(*DeviceOffset);
|
||||
}
|
||||
else {
|
||||
irp->SetNextParameterWriteByteOffsetQuadPart(0);
|
||||
}
|
||||
|
||||
Request->VerifierSetFormatted();
|
||||
}
|
||||
else {
|
||||
if (freeSysBuf) {
|
||||
FxPoolFree(irp->GetSystemBuffer());
|
||||
irp->SetSystemBuffer(NULL);
|
||||
}
|
||||
|
||||
Request->ContextReleaseAndRestore();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxIoTarget::FormatIoctlRequest(
|
||||
__in FxRequestBase* Request,
|
||||
__in ULONG Ioctl,
|
||||
__in BOOLEAN Internal,
|
||||
__in FxRequestBuffer* InputBuffer,
|
||||
__in FxRequestBuffer* OutputBuffer,
|
||||
_In_opt_ FxFileObject* FileObject
|
||||
)
|
||||
{
|
||||
FxIoContext* pContext;
|
||||
NTSTATUS status;
|
||||
PVOID pBuffer;
|
||||
ULONG inLength, outLength;
|
||||
BOOLEAN freeSysBuf;
|
||||
BOOLEAN setBufferAndLength;
|
||||
FxIrp* irp;
|
||||
|
||||
UNREFERENCED_PARAMETER(FileObject);
|
||||
|
||||
irp = Request->GetSubmitFxIrp();
|
||||
freeSysBuf = FALSE;
|
||||
|
||||
status = Request->ValidateTarget(this);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (Request->HasContextType(FX_RCT_IO)) {
|
||||
pContext = (FxIoContext*) Request->GetContext();
|
||||
}
|
||||
else {
|
||||
pContext = new(GetDriverGlobals()) FxIoContext();
|
||||
if (pContext == NULL) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not allocate context for request");
|
||||
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Request->SetContext(pContext);
|
||||
}
|
||||
|
||||
pContext->CaptureState(irp);
|
||||
|
||||
irp->ClearNextStackLocation();
|
||||
|
||||
//
|
||||
// Save away any references to IFxMemory pointers that are passed
|
||||
//
|
||||
pContext->StoreAndReferenceMemory(InputBuffer);
|
||||
pContext->StoreAndReferenceOtherMemory(OutputBuffer);
|
||||
|
||||
UCHAR majorFunction;
|
||||
if (Internal) {
|
||||
majorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
|
||||
}
|
||||
else {
|
||||
majorFunction = IRP_MJ_DEVICE_CONTROL;
|
||||
}
|
||||
|
||||
irp->SetMajorFunction(majorFunction);
|
||||
|
||||
pContext->m_MajorFunction = majorFunction;
|
||||
|
||||
CopyFileObjectAndFlags(Request);
|
||||
|
||||
inLength = InputBuffer->GetBufferLength();
|
||||
outLength = OutputBuffer->GetBufferLength();
|
||||
|
||||
irp->SetParameterIoctlCode(Ioctl);
|
||||
irp->SetParameterIoctlInputBufferLength(inLength);
|
||||
irp->SetParameterIoctlOutputBufferLength(outLength);
|
||||
|
||||
|
||||
//
|
||||
// Anytime we return here and we allocated the context above, the context
|
||||
// will be freed when the FxRequest is freed or reformatted.
|
||||
//
|
||||
switch (METHOD_FROM_CTL_CODE(Ioctl)) {
|
||||
case METHOD_BUFFERED:
|
||||
|
||||
if (inLength != 0 || outLength != 0) {
|
||||
ULONG allocationLength;
|
||||
|
||||
allocationLength = (inLength > outLength ? inLength : outLength);
|
||||
|
||||
if ((pContext->m_BufferToFreeLength >= allocationLength) &&
|
||||
(pContext->m_BufferToFree != NULL)) {
|
||||
irp->SetSystemBuffer(pContext->m_BufferToFree);
|
||||
setBufferAndLength = FALSE;
|
||||
}
|
||||
else {
|
||||
irp->SetSystemBuffer(FxPoolAllocate(GetDriverGlobals(),
|
||||
NonPagedPool,
|
||||
allocationLength));
|
||||
if (irp->GetSystemBuffer() == NULL) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not allocate common buffer");
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
break;
|
||||
}
|
||||
setBufferAndLength = TRUE;
|
||||
freeSysBuf = TRUE;
|
||||
}
|
||||
|
||||
status = InputBuffer->GetBuffer(&pBuffer);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not retrieve input buffer, %!STATUS!",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pBuffer != NULL) {
|
||||
RtlCopyMemory(irp->GetSystemBuffer(),
|
||||
pBuffer,
|
||||
inLength);
|
||||
}
|
||||
|
||||
status = OutputBuffer->GetBuffer(&pBuffer);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not retrieve output buffer, %!STATUS!",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
|
||||
irp->SetUserBuffer(pBuffer);
|
||||
if (setBufferAndLength) {
|
||||
pContext->SetBufferAndLength(irp->GetSystemBuffer(),
|
||||
allocationLength,
|
||||
outLength > 0 ? TRUE : FALSE);
|
||||
freeSysBuf = FALSE; // FxIoContext will free the buffer.
|
||||
} else {
|
||||
pContext->m_CopyBackToBuffer = outLength > 0 ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
//
|
||||
// These fields were captured and will be restored by the context
|
||||
// later.
|
||||
//
|
||||
irp->SetUserBuffer(NULL);
|
||||
irp->SetSystemBuffer(NULL);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case METHOD_DIRECT_TO_HARDWARE: // METHOD_IN_DIRECT
|
||||
case METHOD_DIRECT_FROM_HARDWARE: // METHOD_OUT_DIRECT
|
||||
{
|
||||
BOOLEAN reuseMdl;
|
||||
|
||||
reuseMdl = FALSE;
|
||||
|
||||
status = InputBuffer->GetBuffer(&pBuffer);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not retrieve input buffer as a PVOID, %!STATUS!",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
|
||||
irp->SetSystemBuffer(pBuffer);
|
||||
|
||||
//
|
||||
// NOTE: There is no need to compare the operation type since that
|
||||
// applies only to the Pages locked in memory and not the MDL data
|
||||
// structure itself per se.
|
||||
// Also, note that if the size of the Outbuf need not be equal to the
|
||||
// size of the MdlToFree as long as the number of page entries match.
|
||||
//
|
||||
if (pContext->m_MdlToFree != NULL) {
|
||||
reuseMdl = TRUE;
|
||||
}
|
||||
|
||||
status = OutputBuffer->GetOrAllocateMdl(
|
||||
GetDriverGlobals(),
|
||||
irp->GetMdlAddressPointer(),
|
||||
&pContext->m_MdlToFree,
|
||||
&pContext->m_UnlockPages,
|
||||
(METHOD_FROM_CTL_CODE(Ioctl) == METHOD_DIRECT_TO_HARDWARE) ? IoReadAccess : IoWriteAccess,
|
||||
reuseMdl,
|
||||
&pContext->m_MdlToFreeSize
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not retrieve output buffer as a PMDL, %!STATUS!",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case METHOD_NEITHER:
|
||||
status = OutputBuffer->GetBuffer(&pBuffer);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not retrieve output buffer as a PVOID, %!STATUS!",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
|
||||
irp->SetUserBuffer(pBuffer);
|
||||
|
||||
status = InputBuffer->GetBuffer(&pBuffer);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not retrieve input buffer as a PVOID, %!STATUS!",
|
||||
status);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
irp->SetParameterIoctlType3InputBuffer(pBuffer);
|
||||
break;
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
Request->VerifierSetFormatted();
|
||||
}
|
||||
else {
|
||||
if (freeSysBuf) {
|
||||
FxPoolFree(irp->GetSystemBuffer());
|
||||
irp->SetSystemBuffer(NULL);
|
||||
}
|
||||
|
||||
Request->ContextReleaseAndRestore();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue