UsbDk: Introduce UsbDkFilterDevice class
- Introduce filtering logic class - Make control device creation logic object oriented - Integrate control device creation with filter devices creation Signed-off-by: Dmitry Fleytman <dfleytma@redhat.com>
This commit is contained in:
parent
ac848be907
commit
6ee40a363b
14 changed files with 276 additions and 298 deletions
|
|
@ -2,6 +2,7 @@
|
|||
#include "trace.h"
|
||||
#include "ControlDevice.tmh"
|
||||
#include "Public.h"
|
||||
#include "DeviceAccess.h"
|
||||
|
||||
class CUsbDkControlDeviceInit : public CDeviceInit
|
||||
{
|
||||
|
|
@ -98,12 +99,58 @@ NTSTATUS CUsbDkControlDevice::Create(WDFDRIVER Driver)
|
|||
|
||||
m_DeviceQueue = new CUsbDkControlDeviceQueue(*this, WdfIoQueueDispatchSequential);
|
||||
status = m_DeviceQueue->Create();
|
||||
if (!NT_SUCCESS(status))
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
return status;
|
||||
FinishInitializing();
|
||||
}
|
||||
|
||||
FinishInitializing();
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
CRefCountingHolder<CUsbDkControlDevice> *CUsbDkControlDevice::m_UsbDkControlDevice = nullptr;
|
||||
|
||||
CUsbDkControlDevice* CUsbDkControlDevice::Reference(WDFDRIVER Driver)
|
||||
{
|
||||
if (!m_UsbDkControlDevice->InitialAddRef())
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR, TRACE_CONTROLDEVICE, "%!FUNC! control device already exists");
|
||||
return m_UsbDkControlDevice->Get();
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR, TRACE_CONTROLDEVICE, "%!FUNC! creating control device");
|
||||
}
|
||||
|
||||
CUsbDkControlDevice *dev = new CUsbDkControlDevice();
|
||||
if (dev == nullptr)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR, TRACE_CONTROLDEVICE, "%!FUNC! cannot allocate control device");
|
||||
m_UsbDkControlDevice->Release();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
*m_UsbDkControlDevice = dev;
|
||||
auto status = (*m_UsbDkControlDevice)->Create(Driver);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR, TRACE_CONTROLDEVICE, "%!FUNC! cannot create control device %!STATUS!", status);
|
||||
m_UsbDkControlDevice->Release();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
bool CUsbDkControlDevice::Allocate()
|
||||
{
|
||||
ASSERT(m_UsbDkControlDevice == nullptr);
|
||||
|
||||
m_UsbDkControlDevice = new CRefCountingHolder<CUsbDkControlDevice>;
|
||||
if (m_UsbDkControlDevice == nullptr)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_CONTROLDEVICE, "%!FUNC! Cannot allocate control device holder");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,17 +31,25 @@ public:
|
|||
CUsbDkControlDevice() {}
|
||||
|
||||
NTSTATUS Create(WDFDRIVER hDriver);
|
||||
|
||||
static bool Allocate();
|
||||
static void Deallocate()
|
||||
{ delete m_UsbDkControlDevice; }
|
||||
static CUsbDkControlDevice* Reference(WDFDRIVER Driver);
|
||||
static void Release()
|
||||
{ m_UsbDkControlDevice->Release(); }
|
||||
|
||||
private:
|
||||
CObjHolder<CUsbDkControlDeviceQueue> m_DeviceQueue;
|
||||
static CRefCountingHolder<CUsbDkControlDevice> *m_UsbDkControlDevice;
|
||||
};
|
||||
|
||||
typedef struct _USBDK_CONTROL_DEVICE_EXTENSION {
|
||||
|
||||
CUsbDkControlDevice UsbDkControl; // Store your control data here
|
||||
CUsbDkControlDevice *UsbDkControl; // Store your control data here
|
||||
|
||||
_USBDK_CONTROL_DEVICE_EXTENSION(const _USBDK_CONTROL_DEVICE_EXTENSION&) = delete;
|
||||
_USBDK_CONTROL_DEVICE_EXTENSION& operator= (const _USBDK_CONTROL_DEVICE_EXTENSION&) = delete;
|
||||
|
||||
} USBDK_CONTROL_DEVICE_EXTENSION, *PUSBDK_CONTROL_DEVICE_EXTENSION;
|
||||
|
||||
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(USBDK_CONTROL_DEVICE_EXTENSION, UsbDkControlGetContext)
|
||||
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(USBDK_CONTROL_DEVICE_EXTENSION, UsbDkControlGetContext);
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* UsbDk filter/redirector driver
|
||||
*
|
||||
* Copyright (c) 2013 Red Hat, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Dmitry Fleytman <dfleytma@redhat.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "public.h"
|
||||
#include "WdfWorkitem.h"
|
||||
|
||||
typedef struct _DEVICE_CONTEXT
|
||||
{
|
||||
_DEVICE_CONTEXT() = delete;
|
||||
|
||||
WDFIOTARGET IOTarget;
|
||||
PDEVICE_OBJECT ClonedPdo;
|
||||
CWdfWorkitem QDRCompletionWorkItem;
|
||||
|
||||
//IRP_MN_QUERY_DEVICE_RELATIONS IRP being processed now or NULL
|
||||
PIRP QDRIrp;
|
||||
|
||||
BOOLEAN Initialized;
|
||||
} DEVICE_CONTEXT, *PDEVICE_CONTEXT;
|
||||
|
||||
NTSTATUS UsbDkCreateDevice(_Inout_ PWDFDEVICE_INIT DeviceInit);
|
||||
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, DeviceGetContext)
|
||||
|
|
@ -10,14 +10,13 @@
|
|||
|
||||
#include "driver.h"
|
||||
#include "ControlDevice.h"
|
||||
#include "FilterDevice.h"
|
||||
#include "driver.tmh"
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text (INIT, DriverEntry)
|
||||
#endif
|
||||
|
||||
CRefCountingHolder<CUsbDkControlDevice> *g_UsbDkControlDevice;
|
||||
|
||||
NTSTATUS
|
||||
DriverEntry(
|
||||
_In_ PDRIVER_OBJECT DriverObject,
|
||||
|
|
@ -60,14 +59,14 @@ DriverEntry(
|
|||
return status;
|
||||
}
|
||||
|
||||
g_UsbDkControlDevice = new CRefCountingHolder<CUsbDkControlDevice>;
|
||||
if (g_UsbDkControlDevice == nullptr) {
|
||||
if (!CUsbDkControlDevice::Allocate())
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");
|
||||
|
||||
return status;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
|
|
@ -79,71 +78,31 @@ DriverUnload(IN WDFDRIVER Driver)
|
|||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
|
||||
|
||||
delete g_UsbDkControlDevice;
|
||||
CUsbDkControlDevice::Deallocate();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
UsbDkReferenceControlDevice(WDFDRIVER Driver)
|
||||
{
|
||||
if (!g_UsbDkControlDevice->InitialAddRef())
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "%!FUNC! control device already exists");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "%!FUNC! creating control device");
|
||||
}
|
||||
|
||||
CUsbDkControlDevice *dev = new CUsbDkControlDevice();
|
||||
if (dev == nullptr)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "%!FUNC! cannot allocate control device");
|
||||
g_UsbDkControlDevice->Release();
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
*g_UsbDkControlDevice = dev;
|
||||
auto status = (*g_UsbDkControlDevice)->Create(Driver);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "%!FUNC! cannot create control device %!STATUS!", status);
|
||||
g_UsbDkControlDevice->Release();
|
||||
return status;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
UsbDkReleaseControlDevice()
|
||||
{
|
||||
g_UsbDkControlDevice->Release();
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
UsbDkEvtDeviceAdd(
|
||||
_In_ WDFDRIVER Driver,
|
||||
_Inout_ PWDFDEVICE_INIT DeviceInit
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
UNREFERENCED_PARAMETER(Driver);
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
|
||||
|
||||
status = UsbDkCreateDevice(DeviceInit);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
auto FilterDevice = new CUsbDkFilterDevice();
|
||||
if (FilterDevice == nullptr)
|
||||
{
|
||||
status = UsbDkReferenceControlDevice(Driver);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
auto status = FilterDevice->Create(DeviceInit, Driver);
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit %!STATUS!", status);
|
||||
|
||||
return status;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ extern "C"
|
|||
#include <wdfusb.h>
|
||||
}
|
||||
|
||||
#include "device.h"
|
||||
#include "trace.h"
|
||||
|
||||
//
|
||||
|
|
@ -32,5 +31,3 @@ DRIVER_INITIALIZE DriverEntry;
|
|||
EVT_WDF_DRIVER_UNLOAD DriverUnload;
|
||||
EVT_WDF_DRIVER_DEVICE_ADD UsbDkEvtDeviceAdd;
|
||||
EVT_WDF_OBJECT_CONTEXT_CLEANUP UsbDkEvtDriverContextCleanup;
|
||||
|
||||
VOID UsbDkReleaseControlDevice();
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* UsbDk filter/redirector driver
|
||||
*
|
||||
* Copyright (c) 2013 Red Hat, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Dmitry Fleytman <dfleytma@redhat.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Filter.h"
|
||||
#include "DeviceAccess.h"
|
||||
#include "trace.h"
|
||||
#include "filter.tmh"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <ntstrsafe.h>
|
||||
#include <usb.h>
|
||||
#include <usbioctl.h>
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
UsbDkShouldAttach(_In_ WDFDEVICE device)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
CObjHolder<CDeviceAccess> devAccess(CDeviceAccess::GetDeviceAccess(device));
|
||||
if (devAccess)
|
||||
{
|
||||
CObjHolder<CRegText> hwIDs(devAccess->GetHardwareIdProperty());
|
||||
if (hwIDs)
|
||||
{
|
||||
hwIDs->Dump();
|
||||
return hwIDs->Match(L"USB\\ROOT_HUB") ||
|
||||
hwIDs->Match(L"USB\\ROOT_HUB20");
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
/*
|
||||
* UsbDk filter/redirector driver
|
||||
*
|
||||
* Copyright (c) 2013 Red Hat, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Dmitry Fleytman <dfleytma@redhat.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ntddk.h>
|
||||
#include <wdf.h>
|
||||
|
||||
BOOLEAN
|
||||
UsbDkShouldAttach(_In_ WDFDEVICE device);
|
||||
|
|
@ -1,27 +1,71 @@
|
|||
/*
|
||||
* UsbDk filter/redirector driver
|
||||
*
|
||||
* Copyright (c) 2013 Red Hat, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Dmitry Fleytman <dfleytma@redhat.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "driver.h"
|
||||
#include "Filter.h"
|
||||
#include "FilterDevice.h"
|
||||
#include "trace.h"
|
||||
#include "FilterDevice.tmh"
|
||||
#include "Public.h"
|
||||
#include "DeviceAccess.h"
|
||||
#include "device.tmh"
|
||||
#include "ControlDevice.h"
|
||||
|
||||
extern "C"
|
||||
class CUsbDkFilterDeviceInit : public CPreAllocatedDeviceInit
|
||||
{
|
||||
#include <ntstrsafe.h>
|
||||
public:
|
||||
CUsbDkFilterDeviceInit(PWDFDEVICE_INIT DeviceInit)
|
||||
{ Attach(DeviceInit); }
|
||||
|
||||
NTSTATUS Configure(PFN_WDFDEVICE_WDM_IRP_PREPROCESS QDRPreProcessCallback);
|
||||
|
||||
CUsbDkFilterDeviceInit(const CUsbDkFilterDeviceInit&) = delete;
|
||||
CUsbDkFilterDeviceInit& operator= (const CUsbDkFilterDeviceInit&) = delete;
|
||||
};
|
||||
|
||||
NTSTATUS CUsbDkFilterDeviceInit::Configure(PFN_WDFDEVICE_WDM_IRP_PREPROCESS QDRPreProcessCallback)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
SetFilter();
|
||||
return SetPreprocessCallback(QDRPreProcessCallback, IRP_MJ_PNP, IRP_MN_QUERY_DEVICE_RELATIONS);
|
||||
}
|
||||
|
||||
// {C0F2DADE-8235-4065-89A8-58DB74DDC9AC}
|
||||
DEFINE_GUID(GUID_USBDK_CLONE_PDO,
|
||||
0xc0f2dade, 0x8235, 0x4065, 0x89, 0xa8, 0x58, 0xdb, 0x74, 0xdd, 0xc9, 0xac);
|
||||
NTSTATUS CUsbDkFilterDevice::QDRPreProcess(PIRP Irp)
|
||||
{
|
||||
PDEVICE_OBJECT wdmDevice = WdfDeviceWdmGetDeviceObject(m_Device);
|
||||
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
if (BusRelations != irpStack->Parameters.QueryDeviceRelations.Type)
|
||||
{
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||
IoSetCompletionRoutineEx(wdmDevice,
|
||||
Irp,
|
||||
(PIO_COMPLETION_ROUTINE) CUsbDkFilterDevice::QDRPostProcessWrap,
|
||||
this,
|
||||
TRUE, FALSE, FALSE);
|
||||
}
|
||||
|
||||
return WdfDeviceWdmDispatchPreprocessedIrp(m_Device, Irp);
|
||||
}
|
||||
|
||||
NTSTATUS CUsbDkFilterDevice::QDRPostProcess(PIRP Irp)
|
||||
{
|
||||
if (Irp->PendingReturned)
|
||||
{
|
||||
IoMarkIrpPending(Irp);
|
||||
}
|
||||
|
||||
ASSERT(m_QDRIrp == nullptr);
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Queuing work item");
|
||||
|
||||
m_QDRIrp = Irp;
|
||||
m_QDRCompletionWorkItem.Enqueue();
|
||||
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//TODO: TEMP
|
||||
typedef struct _CONTROL_DEVICE_EXTENSION {
|
||||
} PDO_CLONE_EXTENSION, *PPDO_CLONE_EXTENSION;
|
||||
|
||||
|
|
@ -98,45 +142,43 @@ VOID UsbDkDumpHWIds(CDeviceAccess* devAcc)
|
|||
DevIDs->Dump();
|
||||
}
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VOID UsbDkQDRPostProcessWi(_In_ PVOID WdfDevice)
|
||||
void CUsbDkFilterDevice::QDRPostProcessWi()
|
||||
{
|
||||
WDFDEVICE Device = (WDFDEVICE) WdfDevice;
|
||||
PDEVICE_CONTEXT Ctx = DeviceGetContext(WdfDevice);
|
||||
ASSERT(m_QDRIrp != NULL);
|
||||
|
||||
ASSERT(Ctx->QDRIrp != NULL);
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Entry");
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");
|
||||
|
||||
PDEVICE_RELATIONS Relations = (PDEVICE_RELATIONS) Ctx->QDRIrp->IoStatus.Information;
|
||||
PDEVICE_RELATIONS Relations = (PDEVICE_RELATIONS) m_QDRIrp->IoStatus.Information;
|
||||
|
||||
if (Relations)
|
||||
{
|
||||
if (Relations->Count > 0)
|
||||
{
|
||||
Ctx->ClonedPdo = Relations->Objects[0];
|
||||
m_ClonedPdo = Relations->Objects[0];
|
||||
|
||||
{
|
||||
//TEMPORARY: To verify we see HW ids of PDO to be cloned
|
||||
CObjHolder<CDeviceAccess> pdoAccess(CDeviceAccess::GetDeviceAccess(Ctx->ClonedPdo));
|
||||
CObjHolder<CDeviceAccess> pdoAccess(CDeviceAccess::GetDeviceAccess(m_ClonedPdo));
|
||||
if (pdoAccess)
|
||||
{
|
||||
UsbDkDumpHWIds(pdoAccess);
|
||||
}
|
||||
}
|
||||
|
||||
WDFDEVICE PdoClone = UsbDkClonePdo(Device);
|
||||
WDFDEVICE PdoClone = UsbDkClonePdo(m_Device);
|
||||
|
||||
if (PdoClone != WDF_NO_HANDLE)
|
||||
{
|
||||
Relations->Objects[0] = WdfDeviceWdmGetDeviceObject(PdoClone);
|
||||
ObReferenceObject(Relations->Objects[0]);
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Replaced PDO 0x%p with 0x%p",
|
||||
Ctx->ClonedPdo, Relations->Objects[0]);
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Replaced PDO 0x%p with 0x%p",
|
||||
m_ClonedPdo, Relations->Objects[0]);
|
||||
|
||||
//TODO: Temporary to allow normal USB hub driver unload
|
||||
ObDereferenceObject(Ctx->ClonedPdo);
|
||||
ObDereferenceObject(m_ClonedPdo);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -145,135 +187,100 @@ VOID UsbDkQDRPostProcessWi(_In_ PVOID WdfDevice)
|
|||
}
|
||||
}
|
||||
|
||||
PIRP QDRIrp = Ctx->QDRIrp;
|
||||
Ctx->QDRIrp = NULL;
|
||||
auto QDRIrp = m_QDRIrp;
|
||||
m_QDRIrp = NULL;
|
||||
|
||||
IoCompleteRequest(QDRIrp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
NTSTATUS UsbDkQDRPostProcess(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ PVOID WdfDevice)
|
||||
CUsbDkFilterDevice::~CUsbDkFilterDevice()
|
||||
{
|
||||
PDEVICE_CONTEXT Ctx = DeviceGetContext(WdfDevice);
|
||||
|
||||
UNREFERENCED_PARAMETER(DeviceObject);
|
||||
|
||||
if (Irp->PendingReturned)
|
||||
if (m_ControlDevice != nullptr)
|
||||
{
|
||||
IoMarkIrpPending(Irp);
|
||||
CUsbDkControlDevice::Release();
|
||||
}
|
||||
|
||||
ASSERT(Ctx->QDRIrp == NULL);
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Queuing work item");
|
||||
|
||||
Ctx->QDRIrp = Irp;
|
||||
Ctx->QDRCompletionWorkItem.Enqueue();
|
||||
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
static NTSTATUS UsbDkQDRPreProcess(_In_ WDFDEVICE Device, _Inout_ PIRP Irp)
|
||||
{
|
||||
PDEVICE_OBJECT wdmDevice = WdfDeviceWdmGetDeviceObject(Device);
|
||||
|
||||
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
if (BusRelations != irpStack->Parameters.QueryDeviceRelations.Type)
|
||||
{
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||
IoSetCompletionRoutineEx(wdmDevice, Irp, UsbDkQDRPostProcess, Device, TRUE, FALSE, FALSE);
|
||||
}
|
||||
|
||||
return WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
UsbDkSetupFiltering(_In_ PWDFDEVICE_INIT DeviceInit)
|
||||
{
|
||||
UCHAR minorCode = IRP_MN_QUERY_DEVICE_RELATIONS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
WdfFdoInitSetFilter(DeviceInit);
|
||||
|
||||
NTSTATUS status = WdfDeviceInitAssignWdmIrpPreprocessCallback(DeviceInit,
|
||||
UsbDkQDRPreProcess,
|
||||
IRP_MJ_PNP, &minorCode, 1);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! status: %!STATUS!", status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID
|
||||
UsbDkEvtDeviceContextCleanup(_In_ WDFOBJECT DeviceObject)
|
||||
NTSTATUS CUsbDkFilterDevice::Create(PWDFDEVICE_INIT DevInit, WDFDRIVER Driver)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");
|
||||
|
||||
auto deviceContext = DeviceGetContext(DeviceObject);
|
||||
if (deviceContext->Initialized)
|
||||
{
|
||||
deviceContext->QDRCompletionWorkItem.~CWdfWorkitem();
|
||||
UsbDkReleaseControlDevice();
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
UsbDkCreateDevice(_Inout_ PWDFDEVICE_INIT DeviceInit)
|
||||
{
|
||||
WDF_OBJECT_ATTRIBUTES deviceAttributes;
|
||||
WDFDEVICE device;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");
|
||||
|
||||
auto status = UsbDkSetupFiltering(DeviceInit);
|
||||
auto status = CreateFilterDevice(DevInit);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);
|
||||
deviceAttributes.EvtCleanupCallback = UsbDkEvtDeviceContextCleanup;
|
||||
m_ControlDevice = CUsbDkControlDevice::Reference(Driver);
|
||||
return (m_ControlDevice != nullptr) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
|
||||
NTSTATUS CUsbDkFilterDevice::CreateFilterDevice(PWDFDEVICE_INIT DevInit)
|
||||
{
|
||||
CUsbDkFilterDeviceInit DeviceInit(DevInit);
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Entry");
|
||||
|
||||
auto status = DeviceInit.Configure(CUsbDkFilterDevice::QDRPreProcessWrap);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfDeviceCreate status: %!STATUS!", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (UsbDkShouldAttach(device))
|
||||
WDF_OBJECT_ATTRIBUTES attr;
|
||||
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attr, USBDK_FILTER_DEVICE_EXTENSION);
|
||||
attr.EvtCleanupCallback = CUsbDkFilterDevice::ContextCleanup;
|
||||
|
||||
status = CWdfDevice::Create(DeviceInit, attr);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
auto deviceContext = DeviceGetContext(device);
|
||||
deviceContext->IOTarget = WdfDeviceGetIoTarget(device);
|
||||
deviceContext->QDRIrp = NULL;
|
||||
deviceContext->ClonedPdo = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
new (&deviceContext->QDRCompletionWorkItem) CWdfWorkitem(device, UsbDkQDRPostProcessWi, device);
|
||||
status = deviceContext->QDRCompletionWorkItem.Create();
|
||||
if (ShouldAttach())
|
||||
{
|
||||
auto deviceContext = UsbDkFilterGetContext(m_Device);
|
||||
deviceContext->UsbDkFilter = this;
|
||||
|
||||
deviceContext->Initialized = TRUE;
|
||||
status = m_QDRCompletionWorkItem.Create(m_Device);
|
||||
|
||||
ULONG traceLevel = NT_SUCCESS(status) ? TRACE_LEVEL_INFORMATION : TRACE_LEVEL_ERROR;
|
||||
TraceEvents(traceLevel, TRACE_DEVICE, "%!FUNC! Attachment status: %!STATUS!", status);
|
||||
TraceEvents(traceLevel, TRACE_FILTERDEVICE, "%!FUNC! Attachment status: %!STATUS!", status);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = STATUS_NOT_SUPPORTED;
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Not attached");
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Not attached");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void CUsbDkFilterDevice::ContextCleanup(_In_ WDFOBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Entry");
|
||||
|
||||
auto deviceContext = UsbDkFilterGetContext(DeviceObject);
|
||||
delete deviceContext->UsbDkFilter;
|
||||
}
|
||||
|
||||
bool CUsbDkFilterDevice::ShouldAttach()
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
CObjHolder<CDeviceAccess> devAccess(CDeviceAccess::GetDeviceAccess(m_Device));
|
||||
if (devAccess)
|
||||
{
|
||||
CObjHolder<CRegText> hwIDs(devAccess->GetHardwareIdProperty());
|
||||
if (hwIDs)
|
||||
{
|
||||
hwIDs->Dump();
|
||||
return hwIDs->Match(L"USB\\ROOT_HUB") ||
|
||||
hwIDs->Match(L"USB\\ROOT_HUB20");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
56
UsbDk/FilterDevice.h
Normal file
56
UsbDk/FilterDevice.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#pragma once
|
||||
|
||||
#include "ntddk.h"
|
||||
#include "wdf.h"
|
||||
#include "WdfDevice.h"
|
||||
#include "WdfWorkitem.h"
|
||||
#include "Alloc.h"
|
||||
#include "UsbDkUtil.h"
|
||||
|
||||
class CUsbDkControlDevice;
|
||||
class CUsbDkFilterDevice;
|
||||
|
||||
typedef struct _USBDK_FILTER_DEVICE_EXTENSION {
|
||||
|
||||
CUsbDkFilterDevice *UsbDkFilter;
|
||||
|
||||
_USBDK_FILTER_DEVICE_EXTENSION(const _USBDK_FILTER_DEVICE_EXTENSION&) = delete;
|
||||
_USBDK_FILTER_DEVICE_EXTENSION& operator= (const _USBDK_FILTER_DEVICE_EXTENSION&) = delete;
|
||||
|
||||
} USBDK_FILTER_DEVICE_EXTENSION, *PUSBDK_FILTER_DEVICE_EXTENSION;
|
||||
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(USBDK_FILTER_DEVICE_EXTENSION, UsbDkFilterGetContext);
|
||||
|
||||
class CUsbDkFilterDevice : private CWdfDevice, public CAllocatable<NonPagedPool, 'DFHR'>
|
||||
{
|
||||
public:
|
||||
CUsbDkFilterDevice()
|
||||
: m_QDRCompletionWorkItem(CUsbDkFilterDevice::QDRPostProcessWiWrap, this)
|
||||
{}
|
||||
|
||||
~CUsbDkFilterDevice();
|
||||
|
||||
NTSTATUS Create(PWDFDEVICE_INIT DevInit, WDFDRIVER Driver);
|
||||
NTSTATUS CreateFilterDevice(PWDFDEVICE_INIT DevInit);
|
||||
private:
|
||||
static void ContextCleanup(_In_ WDFOBJECT DeviceObject);
|
||||
|
||||
static NTSTATUS QDRPreProcessWrap(_In_ WDFDEVICE Device, _Inout_ PIRP Irp)
|
||||
{ return UsbDkFilterGetContext(Device)->UsbDkFilter->QDRPreProcess(Irp); }
|
||||
NTSTATUS QDRPreProcess(PIRP Irp);
|
||||
|
||||
static NTSTATUS QDRPostProcessWrap(_In_ PDEVICE_OBJECT, _In_ PIRP Irp, _In_ CUsbDkFilterDevice *This)
|
||||
{ return This->QDRPostProcess(Irp); }
|
||||
NTSTATUS QDRPostProcess(PIRP Irp);
|
||||
|
||||
static VOID CUsbDkFilterDevice::QDRPostProcessWiWrap(_In_ PVOID This)
|
||||
{ static_cast<CUsbDkFilterDevice*>(This)->QDRPostProcessWi(); }
|
||||
void CUsbDkFilterDevice::QDRPostProcessWi();
|
||||
|
||||
bool ShouldAttach();
|
||||
|
||||
CWdfWorkitem m_QDRCompletionWorkItem;
|
||||
|
||||
PIRP m_QDRIrp = nullptr;
|
||||
PDEVICE_OBJECT m_ClonedPdo = nullptr;
|
||||
CUsbDkControlDevice *m_ControlDevice = nullptr;
|
||||
};
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
WPP_DEFINE_BIT(TRACE_DEVACCESS) \
|
||||
WPP_DEFINE_BIT(TRACE_REGTEXT) \
|
||||
WPP_DEFINE_BIT(TRACE_CONTROLDEVICE) \
|
||||
WPP_DEFINE_BIT(TRACE_FILTERDEVICE) \
|
||||
WPP_DEFINE_BIT(TRACE_WDFDEVICE) \
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -52,10 +52,9 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ControlDevice.cpp" />
|
||||
<ClCompile Include="Device.cpp" />
|
||||
<ClCompile Include="DeviceAccess.cpp" />
|
||||
<ClCompile Include="Driver.cpp" />
|
||||
<ClCompile Include="Filter.cpp" />
|
||||
<ClCompile Include="FilterDevice.cpp" />
|
||||
<ClCompile Include="Irp.cpp" />
|
||||
<ClCompile Include="MemoryBuffer.cpp" />
|
||||
<ClCompile Include="RegText.cpp" />
|
||||
|
|
@ -65,10 +64,9 @@
|
|||
<ItemGroup>
|
||||
<ClInclude Include="Alloc.h" />
|
||||
<ClInclude Include="ControlDevice.h" />
|
||||
<ClInclude Include="Device.h" />
|
||||
<ClInclude Include="DeviceAccess.h" />
|
||||
<ClInclude Include="Driver.h" />
|
||||
<ClInclude Include="Filter.h" />
|
||||
<ClInclude Include="FilterDevice.h" />
|
||||
<ClInclude Include="Irp.h" />
|
||||
<ClInclude Include="MemoryBuffer.h" />
|
||||
<ClInclude Include="Public.h" />
|
||||
|
|
|
|||
|
|
@ -19,9 +19,6 @@
|
|||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Device.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Driver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -31,9 +28,6 @@
|
|||
<ClInclude Include="Trace.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Filter.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="WdfWorkitem.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -61,14 +55,11 @@
|
|||
<ClInclude Include="UsbDkUtil.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FilterDevice.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Filter.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Device.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Driver.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -93,5 +84,8 @@
|
|||
<ClCompile Include="WdfDevice.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FilterDevice.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -21,14 +21,14 @@ VOID CWdfWorkitem::Callback(_In_ WDFWORKITEM WorkItem)
|
|||
ctx->workItem->m_Payload(ctx->workItem->m_PayloadCtx);
|
||||
}
|
||||
|
||||
NTSTATUS CWdfWorkitem::Create()
|
||||
NTSTATUS CWdfWorkitem::Create(WDFOBJECT parent)
|
||||
{
|
||||
WDF_OBJECT_ATTRIBUTES attributes;
|
||||
WDF_WORKITEM_CONFIG workitemConfig;
|
||||
|
||||
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
|
||||
WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attributes, WdfWorkItemContext);
|
||||
attributes.ParentObject = m_hParent;
|
||||
attributes.ParentObject = parent;
|
||||
WDF_WORKITEM_CONFIG_INIT(&workitemConfig, Callback);
|
||||
|
||||
auto status = WdfWorkItemCreate(&workitemConfig, &attributes, &m_hWorkItem);
|
||||
|
|
|
|||
|
|
@ -11,9 +11,8 @@ private:
|
|||
typedef VOID(*PayloadFunc)(PVOID Ctx);
|
||||
|
||||
public:
|
||||
CWdfWorkitem(_In_ WDFOBJECT parent, PayloadFunc payload, PVOID payloadCtx)
|
||||
: m_hParent(parent)
|
||||
, m_Payload(payload)
|
||||
CWdfWorkitem(PayloadFunc payload, PVOID payloadCtx)
|
||||
: m_Payload(payload)
|
||||
, m_PayloadCtx(payloadCtx)
|
||||
{}
|
||||
|
||||
|
|
@ -22,12 +21,11 @@ public:
|
|||
|
||||
~CWdfWorkitem();
|
||||
|
||||
NTSTATUS Create();
|
||||
NTSTATUS Create(WDFOBJECT parent);
|
||||
VOID Enqueue();
|
||||
|
||||
private:
|
||||
WDFWORKITEM m_hWorkItem = WDF_NO_HANDLE;
|
||||
WDFOBJECT m_hParent = WDF_NO_HANDLE;
|
||||
static VOID Callback(_In_ WDFWORKITEM WorkItem);
|
||||
|
||||
PayloadFunc m_Payload;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue