From 6ee40a363b04be26bfd4d39e90fa9d067ced9b83 Mon Sep 17 00:00:00 2001 From: Dmitry Fleytman Date: Sun, 16 Feb 2014 17:30:45 +0200 Subject: [PATCH] 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 --- UsbDk/ControlDevice.cpp | 57 +++++- UsbDk/ControlDevice.h | 14 +- UsbDk/Device.h | 29 --- UsbDk/Driver.cpp | 61 +----- UsbDk/Driver.h | 3 - UsbDk/Filter.cpp | 41 ---- UsbDk/Filter.h | 17 -- UsbDk/{Device.cpp => FilterDevice.cpp} | 259 +++++++++++++------------ UsbDk/FilterDevice.h | 56 ++++++ UsbDk/Trace.h | 1 + UsbDk/UsbDk.vcxproj | 6 +- UsbDk/UsbDk.vcxproj.filters | 18 +- UsbDk/WdfWorkitem.cpp | 4 +- UsbDk/WdfWorkitem.h | 8 +- 14 files changed, 276 insertions(+), 298 deletions(-) delete mode 100644 UsbDk/Device.h delete mode 100644 UsbDk/Filter.cpp delete mode 100644 UsbDk/Filter.h rename UsbDk/{Device.cpp => FilterDevice.cpp} (50%) create mode 100644 UsbDk/FilterDevice.h diff --git a/UsbDk/ControlDevice.cpp b/UsbDk/ControlDevice.cpp index 5273268..eac91fa 100644 --- a/UsbDk/ControlDevice.cpp +++ b/UsbDk/ControlDevice.cpp @@ -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::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; + if (m_UsbDkControlDevice == nullptr) + { + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_CONTROLDEVICE, "%!FUNC! Cannot allocate control device holder"); + return false; + } + + return true; } diff --git a/UsbDk/ControlDevice.h b/UsbDk/ControlDevice.h index 4e54278..6050889 100644 --- a/UsbDk/ControlDevice.h +++ b/UsbDk/ControlDevice.h @@ -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 m_DeviceQueue; + static CRefCountingHolder *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); diff --git a/UsbDk/Device.h b/UsbDk/Device.h deleted file mode 100644 index aacb82d..0000000 --- a/UsbDk/Device.h +++ /dev/null @@ -1,29 +0,0 @@ -/* -* UsbDk filter/redirector driver -* -* Copyright (c) 2013 Red Hat, Inc. -* -* Authors: -* Dmitry Fleytman -* -*/ - -#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) diff --git a/UsbDk/Driver.cpp b/UsbDk/Driver.cpp index 3389e62..e3c60f2 100644 --- a/UsbDk/Driver.cpp +++ b/UsbDk/Driver.cpp @@ -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 *g_UsbDkControlDevice; - NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, @@ -60,14 +59,14 @@ DriverEntry( return status; } - g_UsbDkControlDevice = new CRefCountingHolder; - 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; diff --git a/UsbDk/Driver.h b/UsbDk/Driver.h index c119eb1..a0b10e7 100644 --- a/UsbDk/Driver.h +++ b/UsbDk/Driver.h @@ -19,7 +19,6 @@ extern "C" #include } -#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(); diff --git a/UsbDk/Filter.cpp b/UsbDk/Filter.cpp deleted file mode 100644 index 4d95f02..0000000 --- a/UsbDk/Filter.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* -* UsbDk filter/redirector driver -* -* Copyright (c) 2013 Red Hat, Inc. -* -* Authors: -* Dmitry Fleytman -* -*/ - -#include "Filter.h" -#include "DeviceAccess.h" -#include "trace.h" -#include "filter.tmh" - -extern "C" -{ - #include - #include - #include -} - -BOOLEAN -UsbDkShouldAttach(_In_ WDFDEVICE device) -{ - PAGED_CODE(); - - CObjHolder devAccess(CDeviceAccess::GetDeviceAccess(device)); - if (devAccess) - { - CObjHolder hwIDs(devAccess->GetHardwareIdProperty()); - if (hwIDs) - { - hwIDs->Dump(); - return hwIDs->Match(L"USB\\ROOT_HUB") || - hwIDs->Match(L"USB\\ROOT_HUB20"); - } - } - - return FALSE; -} diff --git a/UsbDk/Filter.h b/UsbDk/Filter.h deleted file mode 100644 index c664759..0000000 --- a/UsbDk/Filter.h +++ /dev/null @@ -1,17 +0,0 @@ -/* -* UsbDk filter/redirector driver -* -* Copyright (c) 2013 Red Hat, Inc. -* -* Authors: -* Dmitry Fleytman -* -*/ - -#pragma once - -#include -#include - -BOOLEAN -UsbDkShouldAttach(_In_ WDFDEVICE device); diff --git a/UsbDk/Device.cpp b/UsbDk/FilterDevice.cpp similarity index 50% rename from UsbDk/Device.cpp rename to UsbDk/FilterDevice.cpp index 76f53cf..cf3aa45 100644 --- a/UsbDk/Device.cpp +++ b/UsbDk/FilterDevice.cpp @@ -1,27 +1,71 @@ -/* -* UsbDk filter/redirector driver -* -* Copyright (c) 2013 Red Hat, Inc. -* -* Authors: -* Dmitry Fleytman -* -*/ - -#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 +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 pdoAccess(CDeviceAccess::GetDeviceAccess(Ctx->ClonedPdo)); + CObjHolder 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 devAccess(CDeviceAccess::GetDeviceAccess(m_Device)); + if (devAccess) + { + CObjHolder hwIDs(devAccess->GetHardwareIdProperty()); + if (hwIDs) + { + hwIDs->Dump(); + return hwIDs->Match(L"USB\\ROOT_HUB") || + hwIDs->Match(L"USB\\ROOT_HUB20"); + } + } + + return false; +} diff --git a/UsbDk/FilterDevice.h b/UsbDk/FilterDevice.h new file mode 100644 index 0000000..ab34871 --- /dev/null +++ b/UsbDk/FilterDevice.h @@ -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 +{ +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(This)->QDRPostProcessWi(); } + void CUsbDkFilterDevice::QDRPostProcessWi(); + + bool ShouldAttach(); + + CWdfWorkitem m_QDRCompletionWorkItem; + + PIRP m_QDRIrp = nullptr; + PDEVICE_OBJECT m_ClonedPdo = nullptr; + CUsbDkControlDevice *m_ControlDevice = nullptr; +}; diff --git a/UsbDk/Trace.h b/UsbDk/Trace.h index 23e3d0f..318ea29 100644 --- a/UsbDk/Trace.h +++ b/UsbDk/Trace.h @@ -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) \ ) diff --git a/UsbDk/UsbDk.vcxproj b/UsbDk/UsbDk.vcxproj index 7453d2a..3d9294d 100644 --- a/UsbDk/UsbDk.vcxproj +++ b/UsbDk/UsbDk.vcxproj @@ -52,10 +52,9 @@ - - + @@ -65,10 +64,9 @@ - - + diff --git a/UsbDk/UsbDk.vcxproj.filters b/UsbDk/UsbDk.vcxproj.filters index 1a25d52..9859c23 100644 --- a/UsbDk/UsbDk.vcxproj.filters +++ b/UsbDk/UsbDk.vcxproj.filters @@ -19,9 +19,6 @@ - - Header Files - Header Files @@ -31,9 +28,6 @@ Header Files - - Header Files - Header Files @@ -61,14 +55,11 @@ Header Files + + Header Files + - - Source Files - - - Source Files - Source Files @@ -93,5 +84,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/UsbDk/WdfWorkitem.cpp b/UsbDk/WdfWorkitem.cpp index f6f2839..52309b4 100644 --- a/UsbDk/WdfWorkitem.cpp +++ b/UsbDk/WdfWorkitem.cpp @@ -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); diff --git a/UsbDk/WdfWorkitem.h b/UsbDk/WdfWorkitem.h index f8f01bf..fe4d30b 100644 --- a/UsbDk/WdfWorkitem.h +++ b/UsbDk/WdfWorkitem.h @@ -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;