mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 19:21:38 +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
2716
sdk/lib/drivers/wdf/shared/targets/general/fxiotarget.cpp
Normal file
2716
sdk/lib/drivers/wdf/shared/targets/general/fxiotarget.cpp
Normal file
File diff suppressed because it is too large
Load diff
2012
sdk/lib/drivers/wdf/shared/targets/general/fxiotargetapi.cpp
Normal file
2012
sdk/lib/drivers/wdf/shared/targets/general/fxiotargetapi.cpp
Normal file
File diff suppressed because it is too large
Load diff
825
sdk/lib/drivers/wdf/shared/targets/general/fxiotargetremote.cpp
Normal file
825
sdk/lib/drivers/wdf/shared/targets/general/fxiotargetremote.cpp
Normal file
|
@ -0,0 +1,825 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxIoTargetRemote.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Author:
|
||||
|
||||
Environment:
|
||||
|
||||
Both kernel and user mode
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "..\FxTargetsShared.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxIoTargetRemote.tmh"
|
||||
}
|
||||
|
||||
#include <initguid.h>
|
||||
#include "wdmguid.h"
|
||||
|
||||
|
||||
FxIoTargetRemote::FxIoTargetRemote(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals
|
||||
) :
|
||||
FxIoTarget(FxDriverGlobals, sizeof(FxIoTargetRemote)),
|
||||
m_EvtQueryRemove(FxDriverGlobals),
|
||||
m_EvtRemoveCanceled(FxDriverGlobals),
|
||||
m_EvtRemoveComplete(FxDriverGlobals)
|
||||
{
|
||||
|
||||
//
|
||||
// No automatic state changes based on the pnp state changes of our own
|
||||
// device stack. The one exception is remove where we need to shut
|
||||
// everything down.
|
||||
//
|
||||
m_InStack = FALSE;
|
||||
|
||||
m_ClearedPointers = NULL;
|
||||
m_OpenState = FxIoTargetRemoteOpenStateClosed;
|
||||
|
||||
m_TargetHandle = NULL;
|
||||
|
||||
m_EvtQueryRemove.m_Method = NULL;
|
||||
m_EvtRemoveCanceled.m_Method = NULL;
|
||||
m_EvtRemoveComplete.m_Method = NULL;
|
||||
|
||||
#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
|
||||
m_TargetNotifyHandle = NULL;
|
||||
#else (FX_CORE_MODE == FX_CORE_USER_MODE)
|
||||
m_TargetNotifyHandle = WUDF_TARGET_CONTEXT_INVALID;
|
||||
|
||||
m_pIoDispatcher = NULL;
|
||||
m_pRemoteDispatcher = NULL;
|
||||
m_NotificationCallback = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
FxIoTargetRemote::~FxIoTargetRemote()
|
||||
{
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxIoTargetRemote::_Create(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in PWDF_OBJECT_ATTRIBUTES Attributes,
|
||||
__in CfxDeviceBase* Device,
|
||||
__out FxIoTargetRemote** Target
|
||||
)
|
||||
{
|
||||
FxIoTargetRemote* pTarget;
|
||||
FxObject* pParent;
|
||||
WDFOBJECT hTarget;
|
||||
NTSTATUS status;
|
||||
|
||||
*Target = NULL;
|
||||
|
||||
if (Attributes == NULL || Attributes->ParentObject == NULL) {
|
||||
pParent = Device;
|
||||
}
|
||||
else {
|
||||
CfxDeviceBase* pSearchDevice;
|
||||
|
||||
FxObjectHandleGetPtr(FxDriverGlobals,
|
||||
Attributes->ParentObject,
|
||||
FX_TYPE_OBJECT,
|
||||
(PVOID*) &pParent);
|
||||
|
||||
pSearchDevice = FxDeviceBase::_SearchForDevice(pParent, NULL);
|
||||
|
||||
if (pSearchDevice == NULL) {
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Attributes->ParentObject 0x%p must have WDFDEVICE as an "
|
||||
"eventual ancestor, %!STATUS!",
|
||||
Attributes->ParentObject, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
else if (pSearchDevice != Device) {
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Attributes->ParentObject 0x%p ancestor is WDFDEVICE %p, but "
|
||||
"not the same WDFDEVICE 0x%p passed to WdfIoTargetCreate, "
|
||||
"%!STATUS!",
|
||||
Attributes->ParentObject, pSearchDevice->GetHandle(),
|
||||
Device->GetHandle(), status);
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
pTarget = new (FxDriverGlobals, Attributes)
|
||||
FxIoTargetRemote(FxDriverGlobals);
|
||||
|
||||
if (pTarget == NULL) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not allocate memory for target, %!STATUS!", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// initialize the new target
|
||||
//
|
||||
status = pTarget->InitRemote(Device);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Commit and apply the attributes
|
||||
//
|
||||
status = pTarget->Commit(Attributes, &hTarget, pParent);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
*Target = pTarget;
|
||||
}
|
||||
else {
|
||||
//
|
||||
// This will properly clean up the target's state and free it
|
||||
//
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Commit failed for target, %!STATUS!", status);
|
||||
pTarget->DeleteFromFailedCreate();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FxIoTargetRemote::InitRemote(
|
||||
__in FxDeviceBase* Device
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
//
|
||||
// do the base class mode-specific initialization
|
||||
//
|
||||
status = __super::InitModeSpecific(Device);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Do mode-specific initilialization
|
||||
//
|
||||
status = InitRemoteModeSpecific(Device);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
m_Driver = Device->GetDriver();
|
||||
|
||||
SetDeviceBase(Device);
|
||||
m_InStackDevice = Device->GetDeviceObject();
|
||||
|
||||
(void) Device->AddIoTarget(this);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxIoTargetRemote::Open(
|
||||
__in PWDF_IO_TARGET_OPEN_PARAMS OpenParams
|
||||
)
|
||||
{
|
||||
FxIoTargetRemoveOpenParams params, *pParams;
|
||||
UNICODE_STRING name;
|
||||
LIST_ENTRY pended;
|
||||
WDF_IO_TARGET_OPEN_TYPE type;
|
||||
NTSTATUS status;
|
||||
BOOLEAN close, reopen;
|
||||
PVOID pEa;
|
||||
ULONG eaLength;
|
||||
KIRQL irql;
|
||||
|
||||
RtlZeroMemory(&name, sizeof(name));
|
||||
close = FALSE;
|
||||
reopen = OpenParams->Type == WdfIoTargetOpenReopen ? TRUE : FALSE;
|
||||
|
||||
pEa = NULL;
|
||||
eaLength = 0;
|
||||
|
||||
//
|
||||
// We only support reopening using stored settings when we open by name
|
||||
//
|
||||
if (reopen && m_OpenParams.OpenType != WdfIoTargetOpenByName) {
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Reopen only supported if the open type is WdfIoTargetOpenByName WDFIOTARGET %p %!STATUS!",
|
||||
GetObjectHandle(), status);
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Must preallocate all settings now
|
||||
//
|
||||
if (reopen) {
|
||||
//
|
||||
// convert the type into the type used for the previous open
|
||||
//
|
||||
type = m_OpenParams.OpenType;
|
||||
pParams = &m_OpenParams;
|
||||
}
|
||||
else {
|
||||
type = OpenParams->Type;
|
||||
pParams = ¶ms;
|
||||
|
||||
if (OpenParams->Type == WdfIoTargetOpenByName) {
|
||||
|
||||
status = FxDuplicateUnicodeString(GetDriverGlobals(),
|
||||
&OpenParams->TargetDeviceName,
|
||||
&name);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not allocate memory for target name for WDFIOTARGET %p",
|
||||
GetObjectHandle());
|
||||
goto Done;
|
||||
}
|
||||
if (OpenParams->EaBuffer != NULL && OpenParams->EaBufferLength > 0) {
|
||||
|
||||
pEa = FxPoolAllocate(GetDriverGlobals(),
|
||||
PagedPool,
|
||||
OpenParams->EaBufferLength);
|
||||
|
||||
if (pEa == NULL) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not allocate memory for target name "
|
||||
"for WDFIOTARGET %p", GetObjectHandle());
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto Done;
|
||||
}
|
||||
else {
|
||||
eaLength = OpenParams->EaBufferLength;
|
||||
RtlCopyMemory(pEa, OpenParams->EaBuffer, eaLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Lock(&irql);
|
||||
|
||||
if (m_State == WdfIoTargetDeleted) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Opening WDFIOTARGET %p which is removed, state %d",
|
||||
GetObjectHandle(), m_State);
|
||||
status = STATUS_INVALID_DEVICE_STATE;
|
||||
}
|
||||
else if (m_OpenState != FxIoTargetRemoteOpenStateClosed) {
|
||||
//
|
||||
// We are either open or are opening
|
||||
//
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Opening an already open WDFIOTARGET %p, open state %d",
|
||||
GetObjectHandle(), m_OpenState);
|
||||
status = STATUS_INVALID_DEVICE_STATE;
|
||||
}
|
||||
else {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"Opening WDFIOTARGET %p", GetObjectHandle());
|
||||
|
||||
//
|
||||
// Clear the event so that if something is waiting on the state
|
||||
// transition, they will block until we are done.
|
||||
//
|
||||
m_OpenedEvent.Clear();
|
||||
|
||||
m_OpenState = FxIoTargetRemoteOpenStateOpening;
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
Unlock(irql);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
ASSERT(m_TargetFileObject == NULL);
|
||||
ASSERT(m_TargetDevice == NULL);
|
||||
ASSERT(m_TargetPdo == NULL);
|
||||
ASSERT(m_TargetHandle == NULL);
|
||||
|
||||
//
|
||||
// m_TargetNotifyHandle can be a valid value if the caller has previously
|
||||
// opened the target, received a query remove, then a cancel remove, and
|
||||
// is now reopening the target.
|
||||
//
|
||||
UnregisterForPnpNotification(m_TargetNotifyHandle);
|
||||
ResetTargetNotifyHandle();
|
||||
|
||||
//
|
||||
// Only clear the open parameters if we are not attempting a reopen.
|
||||
//
|
||||
if (reopen == FALSE) {
|
||||
m_OpenParams.Clear();
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case WdfIoTargetOpenUseExistingDevice:
|
||||
KMDF_ONLY_CODE_PATH_ASSERT();
|
||||
|
||||
//
|
||||
// OpenParams must be non NULL b/c we can't reopen a target with a
|
||||
// previous device object.
|
||||
//
|
||||
ASSERT(OpenParams->Type == WdfIoTargetOpenUseExistingDevice);
|
||||
|
||||
m_TargetDevice = (MdDeviceObject) OpenParams->TargetDeviceObject;
|
||||
m_TargetFileObject = (MdFileObject) OpenParams->TargetFileObject;
|
||||
m_TargetHandle = NULL;
|
||||
|
||||
//
|
||||
// By taking a manual reference here, we simplify the code in
|
||||
// FxIoTargetRemote::Close where we can assume there is an outstanding
|
||||
// reference on the PFILE_OBJECT at all times as long as we have a non
|
||||
// NULL pointer.
|
||||
//
|
||||
if (m_TargetFileObject != NULL) {
|
||||
Mx::MxReferenceObject(m_TargetFileObject);
|
||||
}
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
break;
|
||||
|
||||
case WdfIoTargetOpenLocalTargetByFile:
|
||||
UMDF_ONLY_CODE_PATH_ASSERT();
|
||||
|
||||
status = OpenLocalTargetByFile(OpenParams);
|
||||
break;
|
||||
|
||||
case WdfIoTargetOpenByName:
|
||||
//
|
||||
// Only capture the open parameters if we are not reopening.
|
||||
//
|
||||
if (reopen == FALSE) {
|
||||
pParams->Set(OpenParams, &name, pEa, eaLength);
|
||||
}
|
||||
|
||||
status = OpenTargetHandle(OpenParams, pParams);
|
||||
if (NT_SUCCESS(status)) {
|
||||
if (reopen == FALSE) {
|
||||
m_OpenParams.Set(OpenParams, &name, pEa, eaLength);
|
||||
|
||||
//
|
||||
// Setting pEa to NULL stops it from being freed later.
|
||||
// Zeroing out name stops it from being freed later.
|
||||
//
|
||||
pEa = NULL;
|
||||
RtlZeroMemory(&name, sizeof(name));
|
||||
}
|
||||
}
|
||||
else {
|
||||
close = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
InitializeListHead(&pended);
|
||||
|
||||
//
|
||||
// Get Target file object for KMDF. Noop for UMDF.
|
||||
//
|
||||
if (NT_SUCCESS(status)) {
|
||||
status = GetTargetDeviceRelations(&close);
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status) && CanRegisterForPnpNotification()) {
|
||||
if (reopen == FALSE) {
|
||||
//
|
||||
// Set the values before the register so that if a notification
|
||||
// comes in before the register returns, we have a function to call.
|
||||
//
|
||||
m_EvtQueryRemove.m_Method = OpenParams->EvtIoTargetQueryRemove;
|
||||
m_EvtRemoveCanceled.m_Method = OpenParams->EvtIoTargetRemoveCanceled;
|
||||
m_EvtRemoveComplete.m_Method = OpenParams->EvtIoTargetRemoveComplete;
|
||||
}
|
||||
|
||||
status = RegisterForPnpNotification();
|
||||
|
||||
//
|
||||
// Even if we can't register, we still are successful in opening
|
||||
// up the device and we will proceed from there.
|
||||
//
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p, could not register pnp notification, %!STATUS! not "
|
||||
"treated as an error", GetObjectHandle(), status);
|
||||
|
||||
m_EvtQueryRemove.m_Method = NULL;
|
||||
m_EvtRemoveCanceled.m_Method = NULL;
|
||||
m_EvtRemoveComplete.m_Method = NULL;
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// UMDF only. Bind handle to remote dispatcher.
|
||||
//
|
||||
#if (FX_CORE_MODE == FX_CORE_USER_MODE)
|
||||
if (NT_SUCCESS(status) && type != WdfIoTargetOpenLocalTargetByFile) {
|
||||
status = BindToHandle();
|
||||
if (!NT_SUCCESS(status)) {
|
||||
close = TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Lock(&irql);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
|
||||
#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
|
||||
m_TargetStackSize = m_TargetDevice->StackSize;
|
||||
m_TargetIoType = GetTargetIoType();
|
||||
#endif
|
||||
|
||||
m_OpenState = FxIoTargetRemoteOpenStateOpen;
|
||||
|
||||
//
|
||||
// Set our state to started. This will also resend any pended requests
|
||||
// due to a query remove.
|
||||
//
|
||||
status = GotoStartState(&pended, FALSE);
|
||||
|
||||
//
|
||||
// We could not successfully start, close back down
|
||||
//
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p could not transition to started state, %!STATUS!",
|
||||
GetObjectHandle(), status);
|
||||
|
||||
close = TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_OpenState = FxIoTargetRemoteOpenStateClosed;
|
||||
}
|
||||
|
||||
//
|
||||
// No matter what, indicate to any waiters that our state change has
|
||||
// completed.
|
||||
//
|
||||
m_OpenedEvent.Set();
|
||||
|
||||
Unlock(irql);
|
||||
|
||||
Done:
|
||||
//
|
||||
// Resubmit any reads that were pended until now.
|
||||
//
|
||||
if (NT_SUCCESS(status)) {
|
||||
SubmitPendedRequests(&pended);
|
||||
}
|
||||
else if (close) {
|
||||
Close(FxIoTargetRemoteCloseReasonPlainClose);
|
||||
}
|
||||
|
||||
if (name.Buffer != NULL) {
|
||||
FxPoolFree(name.Buffer);
|
||||
}
|
||||
|
||||
if (pEa != NULL) {
|
||||
FxPoolFree(pEa);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
FxIoTargetRemote::Close(
|
||||
__in FxIoTargetRemoteCloseReason Reason
|
||||
)
|
||||
{
|
||||
FxIoTargetClearedPointers pointers;
|
||||
MdTargetNotifyHandle pNotifyHandle;
|
||||
SINGLE_LIST_ENTRY sent;
|
||||
LIST_ENTRY pended;
|
||||
WDF_IO_TARGET_STATE removeState;
|
||||
KIRQL irql;
|
||||
BOOLEAN wait;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
|
||||
pFxDriverGlobals = GetDriverGlobals();
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"enter: WDFIOTARGET %p, reason %d", GetObjectHandle(), Reason);
|
||||
|
||||
RtlZeroMemory(&pointers, sizeof(pointers));
|
||||
pNotifyHandle = NULL;
|
||||
|
||||
sent.Next = NULL;
|
||||
InitializeListHead(&pended);
|
||||
|
||||
wait = FALSE;
|
||||
|
||||
//
|
||||
// Pick a value that is not used anywhere in the function and make sure that
|
||||
// we have changed it, before we go to the Remove state
|
||||
//
|
||||
#pragma prefast(suppress: __WARNING_UNUSED_SCALAR_ASSIGNMENT, "PFD is warning that the following assignement is unused. Suppress it to prevent changing any logic.")
|
||||
removeState = WdfIoTargetStarted;
|
||||
|
||||
CheckState:
|
||||
Lock(&irql);
|
||||
|
||||
//
|
||||
// If we are in the process of opening the target, wait for that to finish.
|
||||
//
|
||||
if (m_OpenState == FxIoTargetRemoteOpenStateOpening) {
|
||||
Unlock(irql);
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"Closing WDFIOTARGET %p which is opening, waiting on event %p",
|
||||
GetObjectHandle(), m_OpenedEvent.GetEvent());
|
||||
|
||||
m_OpenedEvent.EnterCRAndWaitAndLeave();
|
||||
|
||||
//
|
||||
// Jump back to the top and recheck
|
||||
//
|
||||
goto CheckState;
|
||||
}
|
||||
|
||||
if (Reason == FxIoTargetRemoteCloseReasonDelete) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"Closing WDFIOTARGET %p, reason: delete", GetObjectHandle());
|
||||
|
||||
removeState = WdfIoTargetDeleted;
|
||||
}
|
||||
else if (m_OpenState == FxIoTargetRemoteOpenStateOpen) {
|
||||
if (Reason == FxIoTargetRemoteCloseReasonQueryRemove) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"Closing WDFIOTARGET %p, reason: query remove",
|
||||
GetObjectHandle());
|
||||
//
|
||||
// Not really being removed, but that is what the API name is...
|
||||
//
|
||||
removeState = WdfIoTargetClosedForQueryRemove;
|
||||
}
|
||||
else {
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"Closing WDFIOTARGET %p, reason: close", GetObjectHandle());
|
||||
|
||||
if (pFxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,9)) {
|
||||
removeState = WdfIoTargetClosed;
|
||||
}
|
||||
else {
|
||||
removeState = WdfIoTargetClosedForQueryRemove;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Either way, we are no longer open for business
|
||||
//
|
||||
m_OpenState = FxIoTargetRemoteOpenStateClosed;
|
||||
}
|
||||
else {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"Closing WDFIOTARGET %p which is not open", GetObjectHandle());
|
||||
|
||||
//
|
||||
// We are not opened, so treat this as a cleanup
|
||||
//
|
||||
removeState = WdfIoTargetClosed;
|
||||
}
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p: fileobj %p, devobj %p, handle %p, notify handle %I64d",
|
||||
GetObjectHandle(), m_TargetFileObject,
|
||||
m_TargetDevice, m_TargetHandle, (UINT64)m_TargetNotifyHandle);
|
||||
|
||||
if (Reason != FxIoTargetRemoteCloseReasonQueryRemove) {
|
||||
//
|
||||
// If we are closing for a query remove, we want to keep the handle
|
||||
// around so that we can be notified of the final close or if the close
|
||||
// was canceled.
|
||||
//
|
||||
pNotifyHandle = m_TargetNotifyHandle;
|
||||
ResetTargetNotifyHandle();
|
||||
}
|
||||
|
||||
ASSERT(removeState != WdfIoTargetStarted);
|
||||
m_ClearedPointers = &pointers;
|
||||
GotoRemoveState(removeState, &pended, &sent, FALSE, &wait);
|
||||
|
||||
Unlock(irql);
|
||||
|
||||
UnregisterForPnpNotification(pNotifyHandle);
|
||||
|
||||
//
|
||||
// Complete any requests we might have pulled off of our lists
|
||||
//
|
||||
CompletePendedRequestList(&pended);
|
||||
_CancelSentRequests(&sent);
|
||||
|
||||
//
|
||||
// We were just removed, wait for any I/O to complete back if necessary.
|
||||
//
|
||||
if (wait) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p, waiting for stop to complete", GetObjectHandle());
|
||||
|
||||
WaitForSentIoToComplete();
|
||||
}
|
||||
|
||||
switch (Reason) {
|
||||
case FxIoTargetRemoteCloseReasonQueryRemove:
|
||||
//
|
||||
// m_OpenParams is needed for reopen on canceled query remove
|
||||
//
|
||||
DO_NOTHING();
|
||||
break;
|
||||
|
||||
case FxIoTargetRemoteCloseReasonDelete:
|
||||
m_OpenParams.Clear();
|
||||
break;
|
||||
|
||||
default:
|
||||
//
|
||||
// If this object is not about to be deleted, we need to revert some
|
||||
// of the state that just changed.
|
||||
//
|
||||
m_SentIoEvent.Clear();
|
||||
break;
|
||||
}
|
||||
|
||||
if (removeState == WdfIoTargetDeleted) {
|
||||
WaitForDisposeEvent();
|
||||
}
|
||||
|
||||
//
|
||||
// Finally, close down our handle and pointers
|
||||
//
|
||||
if (pointers.TargetPdo != NULL) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_INFORMATION, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p derefing PDO %p on close",
|
||||
GetObjectHandle(), pointers.TargetPdo);
|
||||
|
||||
Mx::MxDereferenceObject(pointers.TargetPdo);
|
||||
}
|
||||
|
||||
if (pointers.TargetFileObject != NULL) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_INFORMATION, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p derefing FileObj %p on close",
|
||||
GetObjectHandle(), pointers.TargetFileObject);
|
||||
Mx::MxDereferenceObject(pointers.TargetFileObject);
|
||||
|
||||
#if (FX_CORE_MODE == FX_CORE_USER_MODE)
|
||||
CloseWdfFileObject(pointers.TargetFileObject);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (FX_CORE_MODE == FX_CORE_USER_MODE)
|
||||
UnbindHandle(&pointers);
|
||||
#endif
|
||||
|
||||
if (pointers.TargetHandle != NULL) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_INFORMATION, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p closing handle %p on close",
|
||||
GetObjectHandle(), pointers.TargetHandle);
|
||||
Mx::MxClose(pointers.TargetHandle);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
FxIoTargetRemote::ClearTargetPointers(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p cleared pointers %p state %!WDF_IO_TARGET_STATE!,"
|
||||
" open state %d, pdo %p, fileobj %p, handle %p",
|
||||
GetObjectHandle(), m_ClearedPointers, m_State, m_OpenState, m_TargetPdo,
|
||||
m_TargetFileObject, m_TargetHandle);
|
||||
|
||||
//
|
||||
// Check to see if the caller who is changing state wants these pointer
|
||||
// values before they being cleared out.
|
||||
//
|
||||
if (m_ClearedPointers != NULL) {
|
||||
m_ClearedPointers->TargetPdo = m_TargetPdo;
|
||||
m_ClearedPointers->TargetFileObject = m_TargetFileObject;
|
||||
m_ClearedPointers->TargetHandle = m_TargetHandle;
|
||||
m_ClearedPointers = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// m_TargetHandle is only an FxIoTargetRemote field, clear it now
|
||||
//
|
||||
m_TargetHandle = NULL;
|
||||
|
||||
//
|
||||
// m_TargetPdo and m_TargetFileObject will be cleared in the following call.
|
||||
//
|
||||
// m_TargetNotifyHandle is not cleared in the following call and is left
|
||||
// valid because we want to receive the notification about query remove being
|
||||
// canceled or completing. When we receive either of those notifications,
|
||||
// m_TargetNotifyHandle will be freed then.
|
||||
//
|
||||
__super::ClearTargetPointers();
|
||||
}
|
||||
|
||||
VOID
|
||||
FxIoTargetRemote::Remove(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
//
|
||||
// Close is the same as remove in this object
|
||||
//
|
||||
Close(FxIoTargetRemoteCloseReasonDelete);
|
||||
|
||||
//
|
||||
// Do mode-specific work
|
||||
//
|
||||
RemoveModeSpecific();
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxIoTargetRemoveOpenParams::Clear(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (EaBuffer != NULL) {
|
||||
FxPoolFree(EaBuffer);
|
||||
}
|
||||
|
||||
if (TargetDeviceName.Buffer != NULL) {
|
||||
FxPoolFree(TargetDeviceName.Buffer);
|
||||
}
|
||||
|
||||
RtlZeroMemory(this, sizeof(FxIoTargetRemoveOpenParams));
|
||||
}
|
||||
|
||||
VOID
|
||||
FxIoTargetRemoveOpenParams::Set(
|
||||
__in PWDF_IO_TARGET_OPEN_PARAMS OpenParams,
|
||||
__in PUNICODE_STRING Name,
|
||||
__in PVOID Ea,
|
||||
__in ULONG EaLength
|
||||
)
|
||||
{
|
||||
OpenType = WdfIoTargetOpenByName;
|
||||
|
||||
EaBuffer = Ea;
|
||||
EaBufferLength = EaLength;
|
||||
|
||||
RtlCopyMemory(&TargetDeviceName, Name, sizeof(UNICODE_STRING));
|
||||
|
||||
DesiredAccess = OpenParams->DesiredAccess;
|
||||
FileAttributes = OpenParams->FileAttributes;
|
||||
ShareAccess = OpenParams->ShareAccess;
|
||||
CreateDisposition = OpenParams->CreateDisposition;
|
||||
CreateOptions = OpenParams->CreateOptions;
|
||||
|
||||
if (OpenParams->AllocationSize != NULL) {
|
||||
AllocationSize.QuadPart = *(OpenParams->AllocationSize);
|
||||
AllocationSizePointer = &AllocationSize;
|
||||
}
|
||||
else {
|
||||
AllocationSizePointer = NULL;
|
||||
}
|
||||
}
|
176
sdk/lib/drivers/wdf/shared/targets/general/fxiotargetself.cpp
Normal file
176
sdk/lib/drivers/wdf/shared/targets/general/fxiotargetself.cpp
Normal file
|
@ -0,0 +1,176 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxIoTargetSelf.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements the IO Target APIs
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Both kernel and user mode
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#include "..\FxTargetsShared.hpp"
|
||||
|
||||
extern "C" {
|
||||
#if defined(EVENT_TRACING)
|
||||
#include "FxIoTargetSelf.tmh"
|
||||
#endif
|
||||
}
|
||||
|
||||
FxIoTargetSelf::FxIoTargetSelf(
|
||||
_In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
_In_ USHORT ObjectSize
|
||||
) :
|
||||
FxIoTarget(FxDriverGlobals, ObjectSize, FX_TYPE_IO_TARGET_SELF),
|
||||
m_DispatchQueue(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
FxIoTargetSelf::~FxIoTargetSelf()
|
||||
{
|
||||
}
|
||||
|
||||
FxIoQueue*
|
||||
FxIoTargetSelf::GetDispatchQueue(
|
||||
UCHAR MajorFunction
|
||||
)
|
||||
/*++
|
||||
Routine Description:
|
||||
Returns a pointer to the queue to which an IO sent to the Self
|
||||
io target must be sent to
|
||||
|
||||
Arguments:
|
||||
|
||||
MajorFunction - IRP_MJ_READ, IRP_MJ_WRITE, or IRP_MJ_DEVICE_CONTROL
|
||||
|
||||
Returns:
|
||||
|
||||
FxIoQueue*
|
||||
|
||||
--*/
|
||||
{
|
||||
if (m_DispatchQueue != NULL) {
|
||||
return m_DispatchQueue;
|
||||
}
|
||||
|
||||
return m_Device->m_PkgIo->GetDispatchQueue(MajorFunction);
|
||||
}
|
||||
|
||||
VOID
|
||||
FxIoTargetSelf::Send(
|
||||
_In_ MdIrp Irp
|
||||
)
|
||||
/*++
|
||||
Routine Description:
|
||||
send an MdIrp to the Self IO Target.
|
||||
|
||||
Arguments:
|
||||
|
||||
MdIrp for IRP_MJ_READ, IRP_MJ_WRITE, or IRP_MJ_DEVICE_CONTROL
|
||||
|
||||
Returns:
|
||||
|
||||
VOID
|
||||
|
||||
Implementation Note:
|
||||
|
||||
Function body inspired by WdfDeviceWdmDispatchIrpToIoQueue API.
|
||||
|
||||
--*/
|
||||
{
|
||||
FxIrp irp(Irp);
|
||||
FxIoQueue* queue;
|
||||
NTSTATUS status;
|
||||
UCHAR majorFunction;
|
||||
FxIoInCallerContext* ioInCallerCtx;
|
||||
|
||||
#if (FX_CORE_MODE == FX_CORE_USER_MODE)
|
||||
|
||||
//
|
||||
// Prepare the request to forward to the inteternal target.
|
||||
//
|
||||
(static_cast<IWudfIoIrp2*>(Irp))->PrepareToForwardToSelf();
|
||||
|
||||
#else
|
||||
//
|
||||
// Set Next Stack Location
|
||||
//
|
||||
irp.SetNextIrpStackLocation();
|
||||
|
||||
//
|
||||
// Set Device Object.
|
||||
//
|
||||
irp.SetCurrentDeviceObject(m_Device->GetDeviceObject());
|
||||
#endif
|
||||
|
||||
majorFunction = irp.GetMajorFunction();
|
||||
|
||||
//
|
||||
// Retrieve Queue
|
||||
//
|
||||
queue = GetDispatchQueue(majorFunction);
|
||||
|
||||
if (queue == NULL) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Send WDFIOTARGET %p, No Dispatch Queue Found for Major Function %d",
|
||||
GetObjectHandle(), majorFunction);
|
||||
status = STATUS_INVALID_DEVICE_STATE;
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
//
|
||||
// Only read/writes/ctrls/internal_ctrls IRPs are allowed to be sent to
|
||||
// Self IO Target
|
||||
//
|
||||
if (m_Device->GetDispatchPackage(majorFunction) != m_Device->m_PkgIo) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Only Read/Write/Control/Internal-Control IRPs can be "
|
||||
"forwarded to Self IO Target 0x%p, %!IRPMJ!, "
|
||||
"IRP_MN %x, Device 0x%p, %!STATUS!",
|
||||
GetHandle(), majorFunction, irp.GetMinorFunction(),
|
||||
m_Device->GetObjectHandle(), status);
|
||||
FxVerifierDbgBreakPoint(GetDriverGlobals());
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve the InContextCallback function
|
||||
//
|
||||
ioInCallerCtx = m_Device->m_PkgIo->GetIoInCallerContextCallback(
|
||||
queue->GetCxDeviceInfo());
|
||||
|
||||
//
|
||||
// DispatchStep2 will convert the IRP into a WDFREQUEST, queue it and if
|
||||
// possible dispatch the request to the driver.
|
||||
// If a failure occurs, DispatchStep2 completes teh Irp
|
||||
//
|
||||
(VOID) m_Device->m_PkgIo->DispatchStep2(Irp, ioInCallerCtx, queue);
|
||||
return;
|
||||
|
||||
Fail:
|
||||
|
||||
irp.SetStatus(status);
|
||||
irp.SetInformation(0);
|
||||
irp.CompleteRequest(IO_NO_INCREMENT);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -0,0 +1,658 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxIoTargetRemoteUm.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Author:
|
||||
|
||||
Environment:
|
||||
|
||||
user mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "..\..\FxTargetsShared.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxIoTargetRemoteUm.tmh"
|
||||
}
|
||||
|
||||
#include <initguid.h>
|
||||
#include "wdmguid.h"
|
||||
|
||||
NTSTATUS
|
||||
FxIoTargetRemote::InitRemoteModeSpecific(
|
||||
__in FxDeviceBase* Device
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
HRESULT hr;
|
||||
IWudfDeviceStack* devStack;
|
||||
|
||||
devStack = Device->GetDeviceObject()->GetDeviceStackInterface();
|
||||
|
||||
//
|
||||
// Event initialization can fail in UM so initialize it now instead of in
|
||||
// constructor.
|
||||
//
|
||||
status = m_OpenedEvent.Initialize();
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Failed to initialize m_OpenedEvent, %!STATUS!", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Create remote dispatcher.
|
||||
// This calls directly into the Host to create.
|
||||
// For most IoTargets the dispatcher is hidden from the Fx, but
|
||||
// for the RemoteTarget, we need to directly dispatch I/O to
|
||||
// a win32 handle, regardless of what dispatch method the device
|
||||
// is set to use in it's INF.
|
||||
//
|
||||
hr = devStack->CreateRemoteDispatcher(&m_pIoDispatcher,
|
||||
&m_pRemoteDispatcher);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
status = FxDevice::NtStatusFromHr(devStack, hr);
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Failed to Create RemoteDispatcher, %!STATUS!", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxIoTargetRemote::RemoveModeSpecific(
|
||||
VOID
|
||||
)
|
||||
|
||||
{
|
||||
//
|
||||
// Delete callback object
|
||||
//
|
||||
if (m_NotificationCallback != NULL) {
|
||||
delete m_NotificationCallback;
|
||||
m_NotificationCallback = NULL;
|
||||
}
|
||||
|
||||
SAFE_RELEASE(m_pIoDispatcher);
|
||||
SAFE_RELEASE(m_pRemoteDispatcher);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FxIoTargetRemote::OpenTargetHandle(
|
||||
_In_ PWDF_IO_TARGET_OPEN_PARAMS OpenParams,
|
||||
_Inout_ FxIoTargetRemoveOpenParams* pParams
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
HRESULT hr = S_OK;
|
||||
HANDLE hTarget;
|
||||
ULONG flagsAndAttributes;
|
||||
|
||||
FX_VERIFY_WITH_NAME(INTERNAL,
|
||||
VERIFY(INVALID_HANDLE_VALUE == m_pRemoteDispatcher->GetHandle()),
|
||||
GetDriverGlobals()->Public.DriverName);
|
||||
|
||||
//
|
||||
// UMDF 1.11 allowed following fields to be set by caller.
|
||||
// DWORD dwDesiredAccess
|
||||
// typedef struct _UMDF_IO_TARGET_OPEN_PARAMS
|
||||
// {
|
||||
// DWORD dwShareMode; //
|
||||
// DWORD dwCreationDisposition;
|
||||
// DWORD dwFlagsAndAttributes;
|
||||
// } UMDF_IO_TARGET_OPEN_PARAMS;
|
||||
//
|
||||
//
|
||||
// We always use overlapped I/O
|
||||
//
|
||||
flagsAndAttributes = pParams->FileAttributes | FILE_FLAG_OVERLAPPED;
|
||||
|
||||
hTarget = CreateFile(pParams->TargetDeviceName.Buffer,
|
||||
pParams->DesiredAccess, // dwDesiredAccess
|
||||
pParams->ShareAccess, // dwShareMode
|
||||
NULL, // lpSecurityAttributes
|
||||
pParams->CreateDisposition, // dwCreationDisposition
|
||||
flagsAndAttributes, // dwFlagsAndAttributes
|
||||
NULL);
|
||||
|
||||
if (INVALID_HANDLE_VALUE == hTarget) {
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
status = m_Device->NtStatusFromHr(hr);
|
||||
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"CreateFile for WDFIOTARGET %p returned status %!STATUS!",
|
||||
GetObjectHandle(), status);
|
||||
|
||||
FX_VERIFY_WITH_NAME(INTERNAL, VERIFY(FAILED(hr)), GetDriverGlobals()->Public.DriverName);
|
||||
}
|
||||
else {
|
||||
m_TargetHandle = hTarget;
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
HANDLE
|
||||
FxIoTargetRemote::GetTargetHandle(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
HRESULT hrQi;
|
||||
IWudfFile2* pFile;
|
||||
HANDLE handle = m_TargetHandle;
|
||||
|
||||
if (m_OpenParams.OpenType == WdfIoTargetOpenLocalTargetByFile) {
|
||||
if (m_TargetFileObject == NULL) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p has no target file object, could not get handle",
|
||||
GetObjectHandle());
|
||||
}
|
||||
else {
|
||||
ASSERT(m_TargetHandle == NULL);
|
||||
|
||||
hrQi = m_TargetFileObject->QueryInterface(IID_IWudfFile2, (PVOID*)&pFile);
|
||||
FX_VERIFY(INTERNAL, CHECK_QI(hrQi, pFile));
|
||||
pFile->Release();
|
||||
|
||||
handle = pFile->GetWeakRefHandle();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Normalize the invalid handle value returned by CreateFile in host
|
||||
// to what's expected by the WdfIoTargetWdmGetTargetFileHandle caller.
|
||||
//
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
handle = NULL;
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FxIoTargetRemote::BindToHandle(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
HRESULT hr;
|
||||
|
||||
//
|
||||
// Tell the RemoteDispatcher to bind to the new handle.
|
||||
//
|
||||
hr = m_pRemoteDispatcher->BindToHandle(m_TargetHandle);
|
||||
if (FAILED(hr)) {
|
||||
status = m_Device->NtStatusFromHr(hr);
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p could not bind remote dispatcher to new handle, "
|
||||
"%!STATUS!", GetObjectHandle(), status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
FxIoTargetRemote::UnbindHandle(
|
||||
_In_ FxIoTargetClearedPointers* TargetPointers
|
||||
)
|
||||
{
|
||||
if (NULL != m_pRemoteDispatcher) {
|
||||
//
|
||||
// Close the handle we gave to the RemoteDispatcher
|
||||
//
|
||||
// NOTE: IWudfRemoteDispatcher::CloseHandle can be safely called even if
|
||||
// we've not previously given it a handle. In this case, it does
|
||||
// nothing.
|
||||
//
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p Unbinding RemoteDispatcher %p to handle %p on close",
|
||||
GetObjectHandle(), m_pRemoteDispatcher, TargetPointers->TargetHandle);
|
||||
|
||||
m_pRemoteDispatcher->CloseHandle();
|
||||
|
||||
//
|
||||
// Host closes the handle in CloseHandle call above so set the handle
|
||||
// in TargetPointers to NULL.
|
||||
//
|
||||
TargetPointers->TargetHandle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FxIoTargetRemote::GetTargetDeviceRelations(
|
||||
_Inout_ BOOLEAN* Close
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(Close);
|
||||
|
||||
//
|
||||
// Not needed for UMDF
|
||||
//
|
||||
DO_NOTHING();
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FxIoTargetRemote::RegisterForPnpNotification(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
HRESULT hr;
|
||||
FxIoTargetRemoteNotificationCallback* callback;
|
||||
|
||||
UNREFERENCED_PARAMETER(hr);
|
||||
|
||||
//
|
||||
// Allocate callback object
|
||||
//
|
||||
if (m_NotificationCallback == NULL) {
|
||||
callback = new (GetDriverGlobals())
|
||||
FxIoTargetRemoteNotificationCallback(GetDriverGlobals(), this);
|
||||
|
||||
if (callback == NULL) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p could not allocate resources for "
|
||||
"notification registration, %!STATUS!",
|
||||
GetObjectHandle(), status);
|
||||
return status;
|
||||
}
|
||||
|
||||
m_NotificationCallback = callback;
|
||||
}
|
||||
|
||||
//
|
||||
// Register for Target Device Change notifications
|
||||
// These notifications will arrive asynchronously.
|
||||
//
|
||||
IWudfDeviceStack * pDevStack = m_Device->GetDeviceStack();
|
||||
|
||||
hr = pDevStack->RegisterTargetDeviceNotification(
|
||||
static_cast<IWudfTargetCallbackDeviceChange *> (m_NotificationCallback),
|
||||
m_TargetHandle,
|
||||
&m_TargetNotifyHandle);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
if (m_NotificationCallback != NULL) {
|
||||
delete m_NotificationCallback;
|
||||
m_NotificationCallback = NULL;
|
||||
}
|
||||
|
||||
status = m_Device->NtStatusFromHr(hr);
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p failed to register for Pnp notification, %!STATUS!",
|
||||
GetObjectHandle(), status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p registered for Pnp notification, %!STATUS!",
|
||||
GetObjectHandle(), status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxIoTargetRemote::UnregisterForPnpNotification(
|
||||
_In_ MdTargetNotifyHandle NotifyHandle
|
||||
)
|
||||
{
|
||||
//
|
||||
// check if we previously registered
|
||||
//
|
||||
if (NotifyHandle == WUDF_TARGET_CONTEXT_INVALID) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Unregister.
|
||||
//
|
||||
IWudfDeviceStack * pDevStack = m_Device->GetDeviceStack();
|
||||
pDevStack->UnregisterTargetDeviceNotification(NotifyHandle);
|
||||
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FxIoTargetRemote::OpenLocalTargetByFile(
|
||||
_In_ PWDF_IO_TARGET_OPEN_PARAMS OpenParams
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
//
|
||||
// OpenParams must be non NULL b/c we can't reopen a target with a
|
||||
// previous device object.
|
||||
//
|
||||
ASSERT(OpenParams->Type == WdfIoTargetOpenLocalTargetByFile);
|
||||
m_OpenParams.OpenType = OpenParams->Type;
|
||||
|
||||
//
|
||||
// Create a file object. This is UM-specific feature, where host opens
|
||||
// the reflector control device (optionally supplying the reference string
|
||||
// provided by caller). If there are lower device drivers in the um stack,
|
||||
// host sends them IRP_MJ_CREATE as well. The lower drivers in kernel see
|
||||
// IRP_MJ_CREATE as well as a result of opening the reflector control
|
||||
// object.
|
||||
// Note that m_TargetDevice is already set to next lower device during init.
|
||||
//
|
||||
status = CreateWdfFileObject(&OpenParams->FileName,
|
||||
&m_TargetFileObject);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Failed to create WDF File Object, %!STATUS!", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Target handle is not used in this type of open.
|
||||
//
|
||||
m_TargetHandle = NULL;
|
||||
|
||||
//
|
||||
// By taking a manual reference here, we simplify the code in
|
||||
// FxIoTargetRemote::Close where we can assume there is an outstanding
|
||||
// reference on the WDM file object at all times as long as we have a non
|
||||
// NULL pointer.
|
||||
//
|
||||
if (m_TargetFileObject != NULL) {
|
||||
Mx::MxReferenceObject(m_TargetFileObject);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FxIoTargetRemote::CreateWdfFileObject(
|
||||
_In_opt_ PUNICODE_STRING FileName,
|
||||
_Out_ MdFileObject* FileObject
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
NTSTATUS status;
|
||||
MdFileObject wdmFileObject = NULL;
|
||||
|
||||
FX_VERIFY_WITH_NAME(DRIVER(BadArgument, TODO), CHECK_NOT_NULL(FileObject),
|
||||
GetDriverGlobals()->Public.DriverName);
|
||||
|
||||
*FileObject = NULL;
|
||||
|
||||
hr = m_Device->GetDeviceStack()->CreateWdfFile(
|
||||
m_Device->GetDeviceObject(),
|
||||
m_Device->GetAttachedDevice(),
|
||||
FileName->Buffer,
|
||||
&wdmFileObject
|
||||
);
|
||||
if (SUCCEEDED(hr)) {
|
||||
*FileObject = wdmFileObject;
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
status = m_Device->NtStatusFromHr(hr);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxIoTargetRemote::CloseWdfFileObject(
|
||||
_In_ MdFileObject FileObject
|
||||
)
|
||||
{
|
||||
m_Device->GetDeviceStack()->CloseFile(FileObject);
|
||||
SAFE_RELEASE(FileObject);
|
||||
}
|
||||
|
||||
BOOL
|
||||
__stdcall
|
||||
FxIoTargetRemoteNotificationCallback::OnQueryRemove(
|
||||
_In_ WUDF_TARGET_CONTEXT RegistrationID
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxIoTargetRemote* pThis;
|
||||
NTSTATUS status;
|
||||
BOOLEAN bStatus;
|
||||
|
||||
pThis = m_RemoteTarget;
|
||||
|
||||
//
|
||||
// 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(m_RemoteTarget);
|
||||
|
||||
pFxDriverGlobals = pThis->GetDriverGlobals();
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
bStatus = TRUE;
|
||||
|
||||
if (GetRegistrationId() != RegistrationID) {
|
||||
//
|
||||
// By design, we can get notification callbacks even after we have
|
||||
// unregistered for notifications. This can happen if there were
|
||||
// callbacks already in flight before we unregistered. In this case, we
|
||||
// simply succeed on query-remove. Since we have already unregistered,
|
||||
// there is no reason for us to fail query-remove.
|
||||
//
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGIOTARGET,
|
||||
"QueryRemove callback was for an old registration, ignoring.");
|
||||
|
||||
bStatus = TRUE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
|
||||
"WDFIOTARGET %p: query remove notification",
|
||||
m_RemoteTarget->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);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
bStatus = FALSE;
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
pThis->RELEASE(m_RemoteTarget);
|
||||
|
||||
return bStatus;
|
||||
}
|
||||
|
||||
VOID
|
||||
__stdcall
|
||||
FxIoTargetRemoteNotificationCallback::OnRemoveComplete(
|
||||
_In_ WUDF_TARGET_CONTEXT RegistrationID
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxIoTargetRemote* pThis;
|
||||
|
||||
pThis = m_RemoteTarget;
|
||||
|
||||
//
|
||||
// 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(m_RemoteTarget);
|
||||
|
||||
pFxDriverGlobals = pThis->GetDriverGlobals();
|
||||
|
||||
if (GetRegistrationId() != RegistrationID) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGIOTARGET,
|
||||
"RemoveComplete callback was for an old registration, ignoring.");
|
||||
|
||||
goto exit;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
pThis->RELEASE(m_RemoteTarget);
|
||||
}
|
||||
|
||||
VOID
|
||||
__stdcall
|
||||
FxIoTargetRemoteNotificationCallback::OnRemoveCanceled(
|
||||
_In_ WUDF_TARGET_CONTEXT RegistrationID
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxIoTargetRemote* pThis;
|
||||
NTSTATUS status;
|
||||
|
||||
pThis = m_RemoteTarget;
|
||||
|
||||
//
|
||||
// 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(m_RemoteTarget);
|
||||
|
||||
pFxDriverGlobals = pThis->GetDriverGlobals();
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
if (GetRegistrationId() != RegistrationID) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGIOTARGET,
|
||||
"RemoveCanceled callback was for an old registration, ignoring.");
|
||||
|
||||
goto exit;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
UNREFERENCED_PARAMETER(status);
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
pThis->RELEASE(m_RemoteTarget);
|
||||
}
|
||||
|
||||
VOID
|
||||
__stdcall
|
||||
FxIoTargetRemoteNotificationCallback::OnCustomEvent(
|
||||
_In_ WUDF_TARGET_CONTEXT RegistrationID,
|
||||
_In_ REFGUID Event,
|
||||
_In_reads_bytes_(DataSize) BYTE * Data,
|
||||
_In_ DWORD DataSize,
|
||||
_In_ DWORD NameBufferOffset
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(RegistrationID);
|
||||
UNREFERENCED_PARAMETER(Event);
|
||||
UNREFERENCED_PARAMETER(Data);
|
||||
UNREFERENCED_PARAMETER(DataSize);
|
||||
UNREFERENCED_PARAMETER(NameBufferOffset);
|
||||
|
||||
//
|
||||
// UMDF 2.0 doesn't yet support custom event. Ignore the event.
|
||||
//
|
||||
DO_NOTHING();
|
||||
|
||||
return;
|
||||
}
|
||||
|
315
sdk/lib/drivers/wdf/shared/targets/general/um/fxiotargetum.cpp
Normal file
315
sdk/lib/drivers/wdf/shared/targets/general/um/fxiotargetum.cpp
Normal file
|
@ -0,0 +1,315 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxIoTargetUm.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 "FxIoTargetUm.tmh"
|
||||
#endif
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxIoTarget::InitModeSpecific(
|
||||
__in CfxDeviceBase* Device
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
//
|
||||
// FxCREvent can fail in UMDF so it is initialized outside of constuctor
|
||||
// for UMDF. It always succeeds for KMDF so it gets initialized in
|
||||
// event's constructor.
|
||||
//
|
||||
|
||||
status = m_SentIoEvent.Initialize(SynchronizationEvent, FALSE);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR,
|
||||
TRACINGIOTARGET,
|
||||
"Could not initialize m_SentIoEvent event for "
|
||||
"WFIOTARGET %p, %!STATUS!",
|
||||
GetObjectHandle(), status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = m_DisposeEventUm.Initialize();
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR,
|
||||
TRACINGIOTARGET,
|
||||
"Could not initialize m_DisposeEventUm event for "
|
||||
"WFIOTARGET %p, %!STATUS!",
|
||||
GetObjectHandle(), status);
|
||||
return status;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_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;
|
||||
NTSTATUS status;
|
||||
ULONG ioLength;
|
||||
FxIrp* irp;
|
||||
PVOID buffer;
|
||||
|
||||
UNREFERENCED_PARAMETER(FileObject);
|
||||
|
||||
ASSERT(MajorCode == IRP_MJ_WRITE || MajorCode == IRP_MJ_READ);
|
||||
|
||||
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);
|
||||
|
||||
//
|
||||
// Setup irp stack
|
||||
//
|
||||
irp = Request->GetSubmitFxIrp();
|
||||
irp->ClearNextStackLocation();
|
||||
|
||||
//
|
||||
// copy File object and flags
|
||||
//
|
||||
CopyFileObjectAndFlags(Request);
|
||||
|
||||
irp->SetMajorFunction(MajorCode);
|
||||
pContext->m_MajorFunction = MajorCode;
|
||||
|
||||
ioLength = IoBuffer->GetBufferLength();
|
||||
|
||||
status = IoBuffer->GetBuffer(&buffer);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not retrieve i/o buffer, %!STATUS!",
|
||||
status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Since we don't support buffer transformations (buffered->Direct->Neither)
|
||||
// we are analogous to "Neither" method in KMDF
|
||||
// in which case we just set the Irp buffer to the buffer that is passed in
|
||||
//
|
||||
if (IRP_MJ_READ == MajorCode) {
|
||||
pContext->SwapIrpBuffer(Request,
|
||||
0,
|
||||
NULL,
|
||||
ioLength,
|
||||
buffer);
|
||||
|
||||
irp->GetIoIrp()->SetReadParametersForNextStackLocation(
|
||||
ioLength,
|
||||
DeviceOffset,
|
||||
0
|
||||
);
|
||||
}
|
||||
else if (IRP_MJ_WRITE == MajorCode) {
|
||||
pContext->SwapIrpBuffer(Request,
|
||||
ioLength,
|
||||
buffer,
|
||||
0,
|
||||
NULL);
|
||||
irp->GetIoIrp()->SetWriteParametersForNextStackLocation(
|
||||
ioLength,
|
||||
DeviceOffset,
|
||||
0
|
||||
);
|
||||
}
|
||||
/*
|
||||
else if (WdfRequestQueryInformation == RequestType)
|
||||
{
|
||||
pContext->SwapIrpBuffer(pRequest,
|
||||
0,
|
||||
NULL,
|
||||
ioLength,
|
||||
buffer);
|
||||
}
|
||||
else if (WdfRequestSetInformation == RequestType)
|
||||
{
|
||||
pContext->SwapIrpBuffer(pRequest,
|
||||
ioLength,
|
||||
buffer,
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
*/
|
||||
else {
|
||||
pContext->SwapIrpBuffer(Request, 0, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
Request->VerifierSetFormatted();
|
||||
}
|
||||
else {
|
||||
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;
|
||||
ULONG inLength, outLength;
|
||||
FxIrp* irp;
|
||||
PVOID inputBuffer;
|
||||
PVOID outputBuffer;
|
||||
|
||||
UNREFERENCED_PARAMETER(FileObject);
|
||||
|
||||
irp = Request->GetSubmitFxIrp();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
inLength = InputBuffer->GetBufferLength();
|
||||
outLength = OutputBuffer->GetBufferLength();
|
||||
|
||||
//
|
||||
// Capture irp buffers in context and set driver-provided buffers in the irp
|
||||
//
|
||||
status = InputBuffer->GetBuffer(&inputBuffer);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not retrieve input buffer, %!STATUS!",
|
||||
status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = OutputBuffer->GetBuffer(&outputBuffer);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
|
||||
"Could not retrieve output buffer, %!STATUS!",
|
||||
status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Save away any references to IFxMemory pointers that are passed
|
||||
//
|
||||
pContext->StoreAndReferenceMemory(InputBuffer);
|
||||
pContext->StoreAndReferenceOtherMemory(OutputBuffer);
|
||||
pContext->m_MajorFunction = IRP_MJ_DEVICE_CONTROL;
|
||||
|
||||
//
|
||||
// Format next stack location
|
||||
//
|
||||
irp->ClearNextStackLocation();
|
||||
irp->SetMajorFunction(IRP_MJ_DEVICE_CONTROL);
|
||||
|
||||
//
|
||||
// copy File object and flags
|
||||
//
|
||||
CopyFileObjectAndFlags(Request);
|
||||
|
||||
irp->GetIoIrp()->SetDeviceIoControlParametersForNextStackLocation(
|
||||
Ioctl,
|
||||
inLength,
|
||||
outLength
|
||||
);
|
||||
|
||||
pContext->SwapIrpBuffer(Request,
|
||||
InputBuffer->GetBufferLength(),
|
||||
inputBuffer,
|
||||
OutputBuffer->GetBufferLength(),
|
||||
outputBuffer);
|
||||
exit:
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
Request->VerifierSetFormatted();
|
||||
}
|
||||
else {
|
||||
Request->ContextReleaseAndRestore();
|
||||
}
|
||||
|
||||
return status;;
|
||||
}
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue