mirror of
https://github.com/reactos/reactos.git
synced 2025-03-10 10:14:44 +00:00
659 lines
18 KiB
C++
659 lines
18 KiB
C++
![]() |
/*++
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|