mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 02:45:41 +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
|
@ -0,0 +1,433 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxIoTargetAPIKm.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements the IO Target APIs
|
||||
|
||||
Author:
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "..\..\FxTargetsShared.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxIoTargetAPIKm.tmh"
|
||||
}
|
||||
|
||||
//
|
||||
// Extern the entire file
|
||||
//
|
||||
extern "C" {
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
PDEVICE_OBJECT
|
||||
WDFEXPORT(WdfIoTargetWdmGetTargetDeviceObject)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFIOTARGET IoTarget
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Returns the PDEVICE_OBJECT. This is the device which PIRPs are sent to.
|
||||
This is not necessarily the PDEVICE_OBJECT that WDFDEVICE is attached to.
|
||||
|
||||
Arguments:
|
||||
IoTarget - target whose WDM device object is being returned
|
||||
|
||||
Return Value:
|
||||
valid PDEVICE_OBJECT or NULL on failure
|
||||
|
||||
--*/
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxIoTarget* pTarget;
|
||||
PDEVICE_OBJECT pDevice;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
IoTarget,
|
||||
FX_TYPE_IO_TARGET,
|
||||
(PVOID*) &pTarget,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"enter WDFIOTARGET 0x%p", IoTarget);
|
||||
|
||||
pDevice = pTarget->GetTargetDevice();
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"exit WDFIOTARGET 0x%p, WDM DevObj 0x%p", IoTarget, pDevice);
|
||||
|
||||
return pDevice;
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
PDEVICE_OBJECT
|
||||
WDFEXPORT(WdfIoTargetWdmGetTargetPhysicalDevice)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFIOTARGET IoTarget
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Returns the PDO for the target itself. This is not necessarily the same
|
||||
PDO as the WDFDEVICE that owns the target. Not all targets have a PDO since
|
||||
you can open a legacy non pnp PDEVICE_OBJECT which does not have one.
|
||||
|
||||
Arguments:
|
||||
IoTarget - target whose PDO is being returned
|
||||
|
||||
Return Value:
|
||||
A valid PDEVICE_OBJECT or NULL upon success
|
||||
|
||||
--*/
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxIoTarget* pTarget;
|
||||
PDEVICE_OBJECT pPdo;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
IoTarget,
|
||||
FX_TYPE_IO_TARGET,
|
||||
(PVOID*) &pTarget,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"enter WDFIOTARGET 0x%p", IoTarget);
|
||||
|
||||
pPdo = pTarget->GetTargetPDO();
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"exit WDFIOTARGET 0x%p, WDM PDO 0x%p", IoTarget, pPdo);
|
||||
|
||||
return pPdo;
|
||||
}
|
||||
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
PFILE_OBJECT
|
||||
WDFEXPORT(WdfIoTargetWdmGetTargetFileObject)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFIOTARGET IoTarget
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Returns the PFILE_OBJECT associated with the target. Not all targets have
|
||||
an underlying file object so NULL is a valid and successful return value.
|
||||
|
||||
Arguments:
|
||||
IoTarget - the target whose fileobject is being returned
|
||||
|
||||
Return Value:
|
||||
a valid PFILE_OBJECT or NULL upon success
|
||||
|
||||
--*/
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxIoTarget* pTarget;
|
||||
MdFileObject pFile;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
IoTarget,
|
||||
FX_TYPE_IO_TARGET,
|
||||
(PVOID*) &pTarget,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"enter WDFIOTARGET 0x%p", IoTarget);
|
||||
|
||||
pFile = pTarget->GetTargetFileObject();
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"exit WDFIOTARGET 0x%p, WDM FileObj 0x%p", IoTarget, pFile);
|
||||
|
||||
return pFile;
|
||||
}
|
||||
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfIoTargetQueryForInterface)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFIOTARGET IoTarget,
|
||||
__in
|
||||
LPCGUID InterfaceType,
|
||||
__out
|
||||
PINTERFACE Interface,
|
||||
__in
|
||||
USHORT Size,
|
||||
__in
|
||||
USHORT Version,
|
||||
__in_opt
|
||||
PVOID InterfaceSpecificData
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Sends a query interface pnp request to the top of the target's stack.
|
||||
|
||||
Arguments:
|
||||
IoTarget - the target which is being queried
|
||||
|
||||
InterfaceType - interface type specifier
|
||||
|
||||
Interface - Interface block which will be filled in by the component which
|
||||
responds to the query interface
|
||||
|
||||
Size - size in bytes of Interface
|
||||
|
||||
Version - version of InterfaceType being requested
|
||||
|
||||
InterfaceSpecificData - Additional data associated with Interface
|
||||
|
||||
Return Value:
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
{
|
||||
FxIoTarget* pTarget;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
PDEVICE_OBJECT pTopOfStack;
|
||||
NTSTATUS status;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
IoTarget,
|
||||
FX_TYPE_IO_TARGET,
|
||||
(PVOID*) &pTarget,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, InterfaceType);
|
||||
FxPointerNotNull(pFxDriverGlobals, Interface);
|
||||
|
||||
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
pTopOfStack = IoGetAttachedDeviceReference(pTarget->GetTargetDevice());
|
||||
ASSERT(pTopOfStack != NULL);
|
||||
|
||||
status = FxQueryInterface::_QueryForInterface(pTopOfStack,
|
||||
InterfaceType,
|
||||
Interface,
|
||||
Size,
|
||||
Version,
|
||||
InterfaceSpecificData);
|
||||
|
||||
ObDereferenceObject(pTopOfStack);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfIoTargetQueryTargetProperty)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFIOTARGET IoTarget,
|
||||
__in
|
||||
DEVICE_REGISTRY_PROPERTY DeviceProperty,
|
||||
__in
|
||||
ULONG BufferLength,
|
||||
__drv_when(BufferLength != 0, __out_bcount_part_opt(BufferLength, *ResultLength))
|
||||
__drv_when(BufferLength == 0, __out_opt)
|
||||
PVOID PropertyBuffer,
|
||||
__deref_out_range(<=,BufferLength)
|
||||
PULONG ResultLength
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Retrieves the requested device property for the given target
|
||||
|
||||
Arguments:
|
||||
IoTarget - the target whose PDO whose will be queried
|
||||
|
||||
DeviceProperty - the property being queried
|
||||
|
||||
BufferLength - length of PropertyBuffer in bytes
|
||||
|
||||
PropertyBuffer - Buffer which will receive the property being queried
|
||||
|
||||
ResultLength - if STATUS_BUFFER_TOO_SMALL is returned, then this will contain
|
||||
the required length
|
||||
|
||||
Return Value:
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
{
|
||||
DDI_ENTRY();
|
||||
|
||||
PFX_DRIVER_GLOBALS pGlobals;
|
||||
NTSTATUS status;
|
||||
FxIoTarget* pTarget;
|
||||
MdDeviceObject pPdo;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
IoTarget,
|
||||
FX_TYPE_IO_TARGET,
|
||||
(PVOID*) &pTarget,
|
||||
&pGlobals);
|
||||
|
||||
FxPointerNotNull(pGlobals, ResultLength);
|
||||
if (BufferLength > 0) {
|
||||
FxPointerNotNull(pGlobals, PropertyBuffer);
|
||||
}
|
||||
|
||||
status = FxVerifierCheckIrqlLevel(pGlobals, PASSIVE_LEVEL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
pPdo = pTarget->GetTargetPDO();
|
||||
|
||||
if (pPdo == NULL) {
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
DoTraceLevelMessage(pGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"WDFIOTARGET 0x%p has no PDO (not opened yet?), %!STATUS!",
|
||||
IoTarget, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
status = FxDevice::_GetDeviceProperty(pPdo,
|
||||
DeviceProperty,
|
||||
BufferLength,
|
||||
PropertyBuffer,
|
||||
ResultLength);
|
||||
|
||||
DoTraceLevelMessage(pGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"exit WDFIOTARGET 0x%p, Property %d, %!STATUS!",
|
||||
IoTarget, DeviceProperty, status);
|
||||
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
WDFAPI
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfIoTargetAllocAndQueryTargetProperty)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFIOTARGET IoTarget,
|
||||
__in
|
||||
DEVICE_REGISTRY_PROPERTY DeviceProperty,
|
||||
__in
|
||||
__drv_strictTypeMatch(1)
|
||||
POOL_TYPE PoolType,
|
||||
__in_opt
|
||||
PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes,
|
||||
__out
|
||||
WDFMEMORY* PropertyMemory
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Allocates and retrieves the requested device property for the given target
|
||||
|
||||
Arguments:
|
||||
IoTarget - the target whose PDO whose will be queried
|
||||
|
||||
DeviceProperty - the property being queried
|
||||
|
||||
PoolType - what type of pool to allocate
|
||||
|
||||
PropertyMemoryAttributes - attributes to associate with PropertyMemory
|
||||
|
||||
PropertyMemory - handle which will receive the property buffer
|
||||
|
||||
Return Value:
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
{
|
||||
DDI_ENTRY();
|
||||
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
NTSTATUS status;
|
||||
FxIoTarget* pTarget;
|
||||
MdDeviceObject pPdo;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
IoTarget,
|
||||
FX_TYPE_IO_TARGET,
|
||||
(PVOID*) &pTarget,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, PropertyMemory);
|
||||
|
||||
*PropertyMemory = NULL;
|
||||
|
||||
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
FxVerifierCheckNxPoolType(pFxDriverGlobals, PoolType, pFxDriverGlobals->Tag);
|
||||
|
||||
status = FxValidateObjectAttributes(pFxDriverGlobals, PropertyMemoryAttributes);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
pPdo = pTarget->GetTargetPDO();
|
||||
|
||||
if (pPdo == NULL) {
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p has no PDO (not opened yet?), %!STATUS!",
|
||||
IoTarget, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Worker function which does the 2 passes. First pass to query the size,
|
||||
// the second pass w/the correctly sized buffer.
|
||||
//
|
||||
status = FxDevice::_AllocAndQueryProperty(pFxDriverGlobals,
|
||||
NULL,
|
||||
NULL,
|
||||
pPdo,
|
||||
DeviceProperty,
|
||||
PoolType,
|
||||
PropertyMemoryAttributes,
|
||||
PropertyMemory);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"exit WDFIOTARGET 0x%p, Property %d, %!STATUS!",
|
||||
IoTarget, DeviceProperty, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
}
|
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;
|
||||
}
|
||||
|
|
@ -0,0 +1,366 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxIoTargetRemoteKm.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Author:
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "..\..\FxTargetsShared.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxIoTargetRemoteKm.tmh"
|
||||
}
|
||||
|
||||
#include <initguid.h>
|
||||
#include "wdmguid.h"
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxIoTargetRemote::_PlugPlayNotification(
|
||||
__in PVOID NotificationStructure,
|
||||
__inout_opt PVOID Context
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
PTARGET_DEVICE_REMOVAL_NOTIFICATION pNotification;
|
||||
FxIoTargetRemote* pThis;
|
||||
NTSTATUS status;
|
||||
|
||||
ASSERT(Mx::MxGetCurrentIrql() < DISPATCH_LEVEL);
|
||||
pNotification = (PTARGET_DEVICE_REMOVAL_NOTIFICATION) NotificationStructure;
|
||||
pThis = (FxIoTargetRemote*) Context;
|
||||
|
||||
//
|
||||
// In one of these callbacks, the driver may decide to delete the target.
|
||||
// If that is the case, we need to be able to return and deref the object until
|
||||
// we are done.
|
||||
//
|
||||
pThis->ADDREF(_PlugPlayNotification);
|
||||
|
||||
pFxDriverGlobals = pThis->GetDriverGlobals();
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
if (FxIsEqualGuid(&pNotification->Event, &GUID_TARGET_DEVICE_QUERY_REMOVE)) {
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p: query remove notification", pThis->GetObjectHandle());
|
||||
|
||||
//
|
||||
// Device is gracefully being removed. PnP is asking us to close down
|
||||
// the target. If there is a driver callback, there is *no* default
|
||||
// behavior. This is because we don't know what the callback is going
|
||||
// to do. For instance, the driver could reopen the target to a
|
||||
// different device in a multi-path scenario.
|
||||
//
|
||||
if (pThis->m_EvtQueryRemove.m_Method != NULL) {
|
||||
status = pThis->m_EvtQueryRemove.Invoke(pThis->GetHandle());
|
||||
}
|
||||
else {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p: query remove, default action (close for QR)",
|
||||
pThis->GetObjectHandle());
|
||||
|
||||
//
|
||||
// No callback, close it down conditionally.
|
||||
//
|
||||
pThis->Close(FxIoTargetRemoteCloseReasonQueryRemove);
|
||||
}
|
||||
}
|
||||
else if (FxIsEqualGuid(&pNotification->Event, &GUID_TARGET_DEVICE_REMOVE_COMPLETE)) {
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p: remove complete notification", pThis->GetObjectHandle());
|
||||
|
||||
//
|
||||
// The device was surprise removed, close it for good if the driver has
|
||||
// no override.
|
||||
//
|
||||
if (pThis->m_EvtRemoveComplete.m_Method != NULL) {
|
||||
pThis->m_EvtRemoveComplete.Invoke(pThis->GetHandle());
|
||||
}
|
||||
else {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p: remove complete, default action (close)",
|
||||
pThis->GetObjectHandle());
|
||||
|
||||
//
|
||||
// The device is now gone for good. Close down the target for good.
|
||||
//
|
||||
pThis->Close(FxIoTargetRemoteCloseReasonPlainClose);
|
||||
}
|
||||
}
|
||||
else if (FxIsEqualGuid(&pNotification->Event, &GUID_TARGET_DEVICE_REMOVE_CANCELLED)) {
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p: remove canceled notification", pThis->GetObjectHandle());
|
||||
|
||||
if (pThis->m_EvtRemoveCanceled.m_Method != NULL) {
|
||||
pThis->m_EvtRemoveCanceled.Invoke(pThis->GetHandle());
|
||||
}
|
||||
else {
|
||||
WDF_IO_TARGET_OPEN_PARAMS params;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p: remove canceled, default action (reopen)",
|
||||
pThis->GetObjectHandle());
|
||||
|
||||
WDF_IO_TARGET_OPEN_PARAMS_INIT_REOPEN(¶ms);
|
||||
|
||||
//
|
||||
// Attempt to reopen the target with stored settings
|
||||
//
|
||||
status = pThis->Open(¶ms);
|
||||
}
|
||||
}
|
||||
|
||||
pThis->RELEASE(_PlugPlayNotification);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FxIoTargetRemote::RegisterForPnpNotification(
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
//
|
||||
// Register for PNP notifications on the handle we just opened.
|
||||
// This will notify us of pnp state changes on the handle.
|
||||
//
|
||||
status = IoRegisterPlugPlayNotification(
|
||||
EventCategoryTargetDeviceChange,
|
||||
0,
|
||||
m_TargetFileObject,
|
||||
m_Driver->GetDriverObject(),
|
||||
_PlugPlayNotification,
|
||||
this,
|
||||
&m_TargetNotifyHandle);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxIoTargetRemote::UnregisterForPnpNotification(
|
||||
_In_ MdTargetNotifyHandle Handle
|
||||
)
|
||||
{
|
||||
if (Handle != NULL) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (FxLibraryGlobals.IoUnregisterPlugPlayNotificationEx != NULL) {
|
||||
FxLibraryGlobals.IoUnregisterPlugPlayNotificationEx(Handle);
|
||||
}
|
||||
else {
|
||||
IoUnregisterPlugPlayNotification(Handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FxIoTargetRemote::OpenTargetHandle(
|
||||
_In_ PWDF_IO_TARGET_OPEN_PARAMS OpenParams,
|
||||
_Inout_ FxIoTargetRemoveOpenParams* pParams
|
||||
)
|
||||
{
|
||||
OBJECT_ATTRIBUTES oa;
|
||||
IO_STATUS_BLOCK ioStatus;
|
||||
NTSTATUS status;
|
||||
|
||||
InitializeObjectAttributes(&oa,
|
||||
&pParams->TargetDeviceName,
|
||||
OBJ_KERNEL_HANDLE,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
status = ZwCreateFile(&m_TargetHandle,
|
||||
pParams->DesiredAccess,
|
||||
&oa,
|
||||
&ioStatus,
|
||||
pParams->AllocationSizePointer,
|
||||
pParams->FileAttributes,
|
||||
pParams->ShareAccess,
|
||||
pParams->CreateDisposition,
|
||||
pParams->CreateOptions,
|
||||
pParams->EaBuffer,
|
||||
pParams->EaBufferLength);
|
||||
|
||||
OpenParams->FileInformation = (ULONG)ioStatus.Information;
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_WARNING, TRACINGIOTARGET,
|
||||
"ZwCreateFile for WDFIOTARGET %p returned status %!STATUS!, info 0x%x",
|
||||
GetObjectHandle(), status, (ULONG) ioStatus.Information);
|
||||
|
||||
//
|
||||
// The open operation was successful. Dereference the file handle and
|
||||
// obtain a pointer to the device object for the handle.
|
||||
//
|
||||
status = ObReferenceObjectByHandle(
|
||||
m_TargetHandle,
|
||||
pParams->DesiredAccess,
|
||||
*IoFileObjectType,
|
||||
KernelMode,
|
||||
(PVOID*) &m_TargetFileObject,
|
||||
NULL);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
m_TargetDevice = IoGetRelatedDeviceObject(m_TargetFileObject);
|
||||
|
||||
if (m_TargetDevice == NULL) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p, could not convert filobj %p to devobj",
|
||||
GetObjectHandle(), m_TargetFileObject);
|
||||
|
||||
status = STATUS_NO_SUCH_DEVICE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p, could not convert handle %p to fileobject, "
|
||||
"status %!STATUS!",
|
||||
GetObjectHandle(), m_TargetHandle, status);
|
||||
}
|
||||
}
|
||||
else {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"ZwCreateFile for WDFIOTARGET %p returned status %!STATUS!, info 0x%x",
|
||||
GetObjectHandle(), status, (ULONG) ioStatus.Information);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FxIoTargetRemote::GetTargetDeviceRelations(
|
||||
_Inout_ BOOLEAN* Close
|
||||
)
|
||||
{
|
||||
PDEVICE_OBJECT pTopOfStack;
|
||||
FxAutoIrp irp(NULL);
|
||||
PIRP pIrp;
|
||||
NTSTATUS status;
|
||||
|
||||
pTopOfStack = IoGetAttachedDeviceReference(m_TargetDevice);
|
||||
|
||||
pIrp = IoAllocateIrp(pTopOfStack->StackSize, FALSE);
|
||||
|
||||
if (pIrp != NULL) {
|
||||
PIO_STACK_LOCATION stack;
|
||||
|
||||
irp.SetIrp(pIrp);
|
||||
|
||||
stack = irp.GetNextIrpStackLocation();
|
||||
stack->MajorFunction = IRP_MJ_PNP;
|
||||
stack->MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
|
||||
stack->Parameters.QueryDeviceRelations.Type = TargetDeviceRelation;
|
||||
|
||||
//
|
||||
// Initialize the status to error in case the bus driver decides not
|
||||
// to set it correctly.
|
||||
//
|
||||
irp.SetStatus(STATUS_NOT_SUPPORTED);
|
||||
|
||||
status = irp.SendIrpSynchronously(pTopOfStack);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
PDEVICE_RELATIONS pRelations;
|
||||
|
||||
pRelations = (PDEVICE_RELATIONS) irp.GetInformation();
|
||||
|
||||
ASSERT(pRelations != NULL);
|
||||
|
||||
//
|
||||
// m_TargetPdo was referenced by the bus driver, it will be
|
||||
// dereferenced when the target is closed.
|
||||
//
|
||||
m_TargetPdo = pRelations->Objects[0];
|
||||
|
||||
//
|
||||
// We, as the caller, are responsible for freeing the relations
|
||||
// that the bus driver allocated.
|
||||
//
|
||||
ExFreePool(pRelations);
|
||||
}
|
||||
else {
|
||||
//
|
||||
// Could not retrieve the PDO pointer, error handled later
|
||||
//
|
||||
DO_NOTHING();
|
||||
}
|
||||
}
|
||||
else {
|
||||
//
|
||||
// Could not even allocate an irp, failure.
|
||||
//
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Unable to allocate memory for IRP WDFIOTARGET %p, %!STATUS!",
|
||||
GetObjectHandle(), status);
|
||||
}
|
||||
|
||||
//
|
||||
// Only fail the open if we cannot allocate an irp or if the lower
|
||||
// driver could not allocate a relations.
|
||||
//
|
||||
if (status == STATUS_INSUFFICIENT_RESOURCES) {
|
||||
*Close = TRUE;
|
||||
}
|
||||
else {
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Remove the reference taken by IoGetAttachedDeviceReference
|
||||
//
|
||||
ObDereferenceObject(pTopOfStack);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue