mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:12:59 +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
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;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue