From d4956a2ba2816ed0e3d24d8e4649525d1f2fc014 Mon Sep 17 00:00:00 2001 From: Fredrik Orderud Date: Thu, 15 Feb 2024 09:18:14 +0100 Subject: [PATCH 01/10] Add new "MouseMirror" driver project based on the TailLight driver. --- MouseMirror/.gitignore | 1 + MouseMirror/CppAllocator.hpp | 24 +++ MouseMirror/INSTALL_TailLight.bat | 12 ++ MouseMirror/TailLight.h | 63 ++++++++ MouseMirror/TailLight.inx | Bin 0 -> 6196 bytes MouseMirror/TailLight.mof | 21 +++ MouseMirror/TailLight.vcxproj | 131 ++++++++++++++++ MouseMirror/UNINSTALL_TailLight.bat | 16 ++ MouseMirror/device.cpp | 206 ++++++++++++++++++++++++ MouseMirror/device.h | 13 ++ MouseMirror/driver.cpp | 39 +++++ MouseMirror/driver.h | 24 +++ MouseMirror/eventlog.cpp | 66 ++++++++ MouseMirror/eventlog.h | 9 ++ MouseMirror/messages.mc | 23 +++ MouseMirror/module.rc | 27 ++++ MouseMirror/vfeature.cpp | 235 ++++++++++++++++++++++++++++ MouseMirror/vfeature.h | 14 ++ MouseMirror/wmi.cpp | 107 +++++++++++++ MouseMirror/wmi.h | 11 ++ 20 files changed, 1042 insertions(+) create mode 100644 MouseMirror/.gitignore create mode 100644 MouseMirror/CppAllocator.hpp create mode 100644 MouseMirror/INSTALL_TailLight.bat create mode 100644 MouseMirror/TailLight.h create mode 100644 MouseMirror/TailLight.inx create mode 100644 MouseMirror/TailLight.mof create mode 100644 MouseMirror/TailLight.vcxproj create mode 100644 MouseMirror/UNINSTALL_TailLight.bat create mode 100644 MouseMirror/device.cpp create mode 100644 MouseMirror/device.h create mode 100644 MouseMirror/driver.cpp create mode 100644 MouseMirror/driver.h create mode 100644 MouseMirror/eventlog.cpp create mode 100644 MouseMirror/eventlog.h create mode 100644 MouseMirror/messages.mc create mode 100644 MouseMirror/module.rc create mode 100644 MouseMirror/vfeature.cpp create mode 100644 MouseMirror/vfeature.h create mode 100644 MouseMirror/wmi.cpp create mode 100644 MouseMirror/wmi.h diff --git a/MouseMirror/.gitignore b/MouseMirror/.gitignore new file mode 100644 index 0000000..ed9806c --- /dev/null +++ b/MouseMirror/.gitignore @@ -0,0 +1 @@ +/x64 diff --git a/MouseMirror/CppAllocator.hpp b/MouseMirror/CppAllocator.hpp new file mode 100644 index 0000000..bf175b4 --- /dev/null +++ b/MouseMirror/CppAllocator.hpp @@ -0,0 +1,24 @@ +#pragma once + +/* This codes assumes that POOL_TAG have already been defined if building in kernel-mode. */ + +#ifdef _KERNEL_MODE +void* operator new (size_t size) noexcept { + // allocate in non-paged pool (will always reside in RAM) + return ExAllocatePool2(POOL_FLAG_NON_PAGED, size, POOL_TAG); +} + +void* operator new[] (size_t size) noexcept { + // allocate in non-paged pool (will always reside in RAM) + return ExAllocatePool2(POOL_FLAG_NON_PAGED, size, POOL_TAG); +} + +void operator delete (void *ptr, size_t /*size*/) noexcept { + return ExFreePool(ptr); +} + +void operator delete[] (void* ptr) noexcept { + return ExFreePool(ptr); +} + +#endif // _KERNEL_MODE diff --git a/MouseMirror/INSTALL_TailLight.bat b/MouseMirror/INSTALL_TailLight.bat new file mode 100644 index 0000000..2309e5f --- /dev/null +++ b/MouseMirror/INSTALL_TailLight.bat @@ -0,0 +1,12 @@ +@echo off +:: Goto current directory +cd /d "%~dp0" + +:: Use DevCon for installation, since it allows providing HWID +devcon /r install TailLight.inf "HID\VID_045E&PID_082A&MI_01&Col05" + +:: Use PnpUtil for installation (succeeds but driver isn't loaded) +::devgen /add /bus ROOT /hardwareid "HID\VID_045E&PID_082A&MI_01&Col05" +::PNPUTIL /add-driver TailLight.inf /install /reboot + +pause diff --git a/MouseMirror/TailLight.h b/MouseMirror/TailLight.h new file mode 100644 index 0000000..4df88a9 --- /dev/null +++ b/MouseMirror/TailLight.h @@ -0,0 +1,63 @@ +#pragma once + +/** Tail-light feature report as observed in USBPcap/Wireshark. */ +struct TailLightReport { + TailLightReport() { + } + + void SetColor(ULONG Color) { + Red = (Color) & 0xFF; // red; + Green = (Color >> 8) & 0xFF; // green + Blue = (Color >> 16) & 0xFF; // blue + } + + ULONG GetColor() const { + return (Blue << 16) | (Green << 8) | Red; + } + +#ifdef _KERNEL_MODE + bool IsValid() const { + if (ReportId != 36) {// 0x24 + KdPrint(("TailLight: TailLightReport: Unsupported report id %d\n", ReportId)); + return false; + } + + if ((Unknown1 != 0xB2) || (Unknown2 != 0x03)) { + KdPrint(("TailLight: TailLightReport: Unknown control Code 0x%x 0x%x\n", Unknown1, Unknown2)); + return false; + } + + return true; + } +#endif + +#ifdef _KERNEL_MODE + bool SafetyCheck() { + // RGB check + unsigned int color_sum = Red + Green + Blue; + if (color_sum > 2 * 256) { + KdPrint(("TailLight: Color saturation %u exceeded 512 threshold. Reseting color to RED to signal error\n", color_sum)); + Red = 255; + Green = 0; + Blue = 0; + return false; + } + + return true; + } +#endif + + //report ID of the collection to which the control request is sent + UCHAR ReportId = 36; // (0x24) + + // control codes (user-defined) + UCHAR Unknown1 = 0xB2; // magic value + UCHAR Unknown2 = 0x03; // magic value + + UCHAR Red = 0; + UCHAR Green = 0; + UCHAR Blue = 0; + + UCHAR padding[67] = {}; +}; +static_assert(sizeof(TailLightReport) == 73); diff --git a/MouseMirror/TailLight.inx b/MouseMirror/TailLight.inx new file mode 100644 index 0000000000000000000000000000000000000000..d2d4bd757d8f0672b5be95e585394070e670d9bc GIT binary patch literal 6196 zcmd6r{ZHFQ7{~ADN&6oxR4TePl+bpxV@v}=TT}vwq+@NFqBJCwEhHHZqgB;^ecR`I zkB_qxlfF!qDl4(?{Jg)P|NUpx-ErT!@43Ep-?&wmxTb5nQ`dJp{GYhjZp_}XJ7@K` z>vB(A%6;rE+=%B>H*h^SWd97jG3y~aiCb{nZr43>w|MTc+XrVc;}JL=u=f{qPQmU1 zcj&1dL*Wu0iL1IL{*7yTMY-x8vVWI1;+nv%3%n#Vx)oPJqdR`3otN%c|29zg-M?u- z?*v@QeBt@8xjA=ZN`_tRaf3Iaw22mNBum|zdxCzo+)nZRWB1IzUvux=io56TgIDFL zjpP--bBqQR_Nv%cd#~IN*s06Y5|`jQUe6x5E5NkfdoRO2vJSDyDSOgcQg5Tjm{p(a z)YW-^;e8}eweicyTR-70+&_Tq0B<_g*bAODJFR89$}(**huG;6F!JD9NpvhiO|Y`S zK9Y=xoFRLEBB4Av0ITZXnm20DNr6}7#E7Y}K4;&&BbXjmHbAP**NV;tIb>iC=z#Z5F3&^I^|S z$4jV~%4tPHUX!`f9Bg?RrQL1dtu`G|_f(@=)Dl&oEq9ar3_B0pG9J81{B3)PD$ko( zq7U@_f=5+dqTR~la$1Kdk=exTAX*)GTzHFHKFBX4cI0X68H%S}bngNcvc`035p!*P zJV{*`l72*<#e6jSzm#Nq$jA`6FH2x1c`Rbr!>p2gDLusF^2+)jCza`Iu@Y*~*Oz5& ze0fYhtB;th71q}ItwN~J%OC3=GOv~SaXQ8n>-s&z?<1cpd93Ka=;aSVT9oFg>=RX* z96}v7St6ZCds@CIf#txWuj%K$d#h6gZ+*FFQV+@Vi}o$P`H+RnbSqMby2>ME@LPV8 z)1;#L;3SvBvu$`CAM=&spFYeG#i6)DZ*y)EjGs_G_B zE%(%~clqC8RpZ?@Zv`{&Be{XD>Plnmk*5}9o2FO;yG{n|`nuf!PhGZ|(c6NSI^(&o zb+V*Z{VQFk=}DFYx5uvqP2EL(=SseObZqzzDS6*!www1;*1S6^@#p7N&_myE%yVB~ zjZ%eDH;Ub^LN(SzQZ^TuF3Mf2XEwnpVl-pEqmQmI!K=@%@VpF-W$q7{^DFe@4W4uY zc*wJ^3afh_{vq!+u)O;4efHk_8Ykaw(toU9Z{ou}4<`?|d}MA?2Ni)$_Z9NaBLL7F1I_Bvnzf0DVU-s3c93<9BQ#gGewSt$w2K?m3b6~|!CkxG;ZC`^X zDZKKyngQdP2T zDDEC*UKORHr;glDE}SHP_BL7YS=>Ypn^;B9vuQQSCsfKk=J5^U z;c<4aabIA)%C&?yt3HBzSgGgtR*}5M34b<>>~jn0XIFXUkvtYUhK?;2rd4(KSDU070Or{&eMjgvM%DO>=tlYzM z@uXDF_4*DObL;CmJK0pHXg{HX&6?*9Jj``IYh@Kcxe}%Wn*$ARcI-^sEsq;*SIlH( zhq6c~tpAtK#kfq#@JWf3+xh~aY&|ROr>b}hULJjC`JAj)MLMAFtMW(wb*QPbxA9Q- z>TD#Kd7!t*b=m$mPKI&nc#-vwIqvE^QSt-o*%0ZpU)1R?wc&_3A7=im!}Ek}KK4Ck z6?lEInLSHbjmYZ}=B5-W^u2Keea%yQs(U&E~t77xxCqv5s`yMulwSn||bQ1ORF!`B|hP716 zE8l-6G3`rPnS|?13r)C9Vu+uxmP>hEH=hP9`zAN3SAGiJCgN-o-Ga+3z4BQ3*)?F9 z4MPlT>e(lfTU6d>#9)(Hlx{CP7vTh6Z|G&ZG-25#`vf}ExnQ{Yf7wU<(6BYtP1A|7 zn8z$W7wH6fLTr5ev^S|)kVoG;6aSS_6*@+4!s<;nAz3Dr&1tHQsgM0raBT*XrTzoX Cr{ + + + + Debug + x64 + + + Release + x64 + + + + {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5} + $(MSBuildProjectName) + 1 + Debug + Win32 + + + + Windows10 + False + Universal + KMDF + WindowsKernelModeDriver10.0 + Driver + + + Windows10 + True + Universal + KMDF + WindowsKernelModeDriver10.0 + Driver + + + + + + + + + + + "$(IntDir)\TailLight.bmf" + + + $(IntDir)\TailLightmof.h + + + + true + + + true + + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\hidparse.lib + + + %(PreprocessorDefinitions) + + + + + %(PreprocessorDefinitions) + + + %(PreprocessorDefinitions) + + + sha256 + + + copy *.bat $(PackageDir) +copy "C:\Program Files (x86)\Windows Kits\10\tools\$(WDKBuildFolder)\x64\dev*.exe" $(PackageDir) +copy ..\TailLight.ps1 $(OutDir) + + + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\hidparse.lib + + + %(PreprocessorDefinitions) + + + + + %(PreprocessorDefinitions) + + + %(PreprocessorDefinitions) + + + sha256 + + + copy *.bat $(PackageDir) +copy "C:\Program Files (x86)\Windows Kits\10\tools\$(WDKBuildFolder)\x64\dev*.exe" $(PackageDir) +copy ..\TailLight.ps1 $(OutDir) + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MouseMirror/UNINSTALL_TailLight.bat b/MouseMirror/UNINSTALL_TailLight.bat new file mode 100644 index 0000000..0fc2a8d --- /dev/null +++ b/MouseMirror/UNINSTALL_TailLight.bat @@ -0,0 +1,16 @@ +@echo off +:: Goto current directory +cd /d "%~dp0" + +:: delete the devnode +devcon /r remove "HID\VID_045E&PID_082A&MI_01&Col05" +:: TODO: Switch to PNPUTIL in Win11 21H2 +::PNPUTIL /remove-device /deviceid "HID\VID_045E&PID_082A&MI_01&Col05" + +:: uninstall driver +PNPUTIL /delete-driver TailLight.inf /uninstall /force /reboot + +:: Delete TailLightDeviceInformation WMI class security descriptor +reg delete "HKLM\SYSTEM\CurrentControlSet\Control\WMI\Security" /v "07982702-2086-4B83-9444-34989BB10554" /f + +pause diff --git a/MouseMirror/device.cpp b/MouseMirror/device.cpp new file mode 100644 index 0000000..89aad26 --- /dev/null +++ b/MouseMirror/device.cpp @@ -0,0 +1,206 @@ +#include "driver.h" +#include + +EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL EvtIoDeviceControlFilter; + + +VOID EvtSetBlackTimer(_In_ WDFTIMER Timer) { + KdPrint(("TailLight: EvtSetBlackTimer begin\n")); + + WDFDEVICE device = (WDFDEVICE)WdfTimerGetParentObject(Timer); + NT_ASSERTMSG("EvtSetBlackTimer device NULL\n", device); + + NTSTATUS status = SetFeatureColor(device, 0); + if (!NT_SUCCESS(status)) { + KdPrint(("TailLight: EvtSetBlackTimer failure NTSTATUS=0x%x\n", status)); + return; + } + + KdPrint(("TailLight: EvtSetBlackTimer end\n")); +} + +NTSTATUS EvtSelfManagedIoInit(WDFDEVICE device) { + // Initialize tail-light to black to have control over HW state + WDF_TIMER_CONFIG timerCfg = {}; + WDF_TIMER_CONFIG_INIT(&timerCfg, EvtSetBlackTimer); + + WDF_OBJECT_ATTRIBUTES attribs = {}; + WDF_OBJECT_ATTRIBUTES_INIT(&attribs); + attribs.ParentObject = device; + attribs.ExecutionLevel = WdfExecutionLevelPassive; // required to access HID functions + + WDFTIMER timer = nullptr; + NTSTATUS status = WdfTimerCreate(&timerCfg, &attribs, &timer); + if (!NT_SUCCESS(status)) { + KdPrint(("WdfTimerCreate failed 0x%x\n", status)); + return status; + } + + status = WdfTimerStart(timer, 0); // no wait + if (!NT_SUCCESS(status)) { + KdPrint(("WdfTimerStart failed 0x%x\n", status)); + return status; + } + + return status; +} + + +NTSTATUS EvtDriverDeviceAdd(_In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit) +/*++ +Routine Description: + EvtDriverDeviceAdd is called by the framework in response to AddDevice + call from the PnP manager. We create and initialize a device object to + represent to be part of the device stack as a filter. + +Arguments: + Driver - Handle to a framework driver object created in DriverEntry + + DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. +--*/ +{ + UNREFERENCED_PARAMETER(Driver); + + // Configure the device as a filter driver + WdfFdoInitSetFilter(DeviceInit); + + { + // register PnP callbacks (must be done before WdfDeviceCreate) + WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerCallbacks; + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerCallbacks); + PnpPowerCallbacks.EvtDeviceSelfManagedIoInit = EvtSelfManagedIoInit; + WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &PnpPowerCallbacks); + } + + WDFDEVICE device = 0; + { + // create device + WDF_OBJECT_ATTRIBUTES attributes = {}; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT); + + NTSTATUS status = WdfDeviceCreate(&DeviceInit, &attributes, &device); + if (!NT_SUCCESS(status)) { + KdPrint(("TailLight: WdfDeviceCreate, Error %x\n", status)); + return status; + } + } + + // Driver Framework always zero initializes an objects context memory + DEVICE_CONTEXT* deviceContext = WdfObjectGet_DEVICE_CONTEXT(device); + + { + // initialize DEVICE_CONTEXT struct with PdoName + + // In order to send ioctls to our PDO, we have open to open it + // by name so that we have a valid filehandle (fileobject). + // When we send ioctls using the IoTarget, framework automatically + // sets the filobject in the stack location. + WDF_OBJECT_ATTRIBUTES attributes = {}; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = device; // auto-delete with device + + WDFMEMORY memory = 0; + NTSTATUS status = WdfDeviceAllocAndQueryProperty(device, + DevicePropertyPhysicalDeviceObjectName, + NonPagedPoolNx, + &attributes, + &memory); + + if (!NT_SUCCESS(status)) { + KdPrint(("TailLight: WdfDeviceAllocAndQueryProperty failed 0x%x\n", status)); + return STATUS_UNSUCCESSFUL; + } + + // initialize pDeviceContext->PdoName based on memory + size_t bufferLength = 0; + deviceContext->PdoName.Buffer = (WCHAR*)WdfMemoryGetBuffer(memory, &bufferLength); + if (deviceContext->PdoName.Buffer == NULL) + return STATUS_UNSUCCESSFUL; + + deviceContext->PdoName.MaximumLength = (USHORT)bufferLength; + deviceContext->PdoName.Length = (USHORT)bufferLength - sizeof(UNICODE_NULL); + + KdPrint(("TailLight: PdoName: %wZ\n", deviceContext->PdoName)); // outputs "\Device\00000083 + } + + { + // create queue for filtering + WDF_IO_QUEUE_CONFIG queueConfig = {}; + WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); // don't synchronize + //queueConfig.EvtIoRead // pass-through read requests + //queueConfig.EvtIoWrite // pass-through write requests + queueConfig.EvtIoDeviceControl = EvtIoDeviceControlFilter; // filter IOCTL requests + + WDFQUEUE queue = 0; // auto-deleted when parent is deleted + NTSTATUS status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue); + + if (!NT_SUCCESS(status)) { + KdPrint(("TailLight: WdfIoQueueCreate failed 0x%x\n", status)); + return status; + } + } + + // Initialize WMI provider + NTSTATUS status = WmiInitialize(device); + if (!NT_SUCCESS(status)) { + KdPrint(("TailLight: Error initializing WMI 0x%x\n", status)); + return status; + } + + return status; +} + + +VOID EvtIoDeviceControlFilter( + _In_ WDFQUEUE Queue, + _In_ WDFREQUEST Request, + _In_ size_t OutputBufferLength, + _In_ size_t InputBufferLength, + _In_ ULONG IoControlCode +) +/*++ +Routine Description: + This event callback function is called when the driver receives an + + (KMDF) IOCTL_HID_Xxx code when handling IRP_MJ_INTERNAL_DEVICE_CONTROL + (UMDF) IOCTL_HID_Xxx, IOCTL_UMDF_HID_Xxx when handling IRP_MJ_DEVICE_CONTROL + +Arguments: + Queue - A handle to the queue object that is associated with the I/O request + + Request - A handle to a framework request object. + + OutputBufferLength - The length, in bytes, of the request's output buffer, + if an output buffer is available. + + InputBufferLength - The length, in bytes, of the request's input buffer, if + an input buffer is available. + + IoControlCode - The driver or system defined IOCTL associated with the request +--*/ +{ + UNREFERENCED_PARAMETER(OutputBufferLength); + + //KdPrint(("TailLight: EvtIoDeviceControl (IoControlCode=0x%x, InputBufferLength=%Iu)\n", IoControlCode, InputBufferLength)); + + WDFDEVICE device = WdfIoQueueGetDevice(Queue); + + NTSTATUS status = STATUS_SUCCESS; //unhandled + switch (IoControlCode) { + case IOCTL_HID_SET_FEATURE: // 0xb0191 + status = SetFeatureFilter(device, Request, InputBufferLength); + break; + } + // No NT_SUCCESS(status) check here since we don't want to fail blocked calls + + // Forward the request down the driver stack + WDF_REQUEST_SEND_OPTIONS options = {}; + WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); + + BOOLEAN ret = WdfRequestSend(Request, WdfDeviceGetIoTarget(device), &options); + if (ret == FALSE) { + status = WdfRequestGetStatus(Request); + KdPrint(("TailLight: WdfRequestSend failed with status: 0x%x\n", status)); + WdfRequestComplete(Request, status); + } +} diff --git a/MouseMirror/device.h b/MouseMirror/device.h new file mode 100644 index 0000000..78543c2 --- /dev/null +++ b/MouseMirror/device.h @@ -0,0 +1,13 @@ +#pragma once + +/** Driver-specific struct for storing instance-specific data. */ +typedef struct _DEVICE_CONTEXT { + UNICODE_STRING PdoName; + WDFWMIINSTANCE WmiInstance; +} DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE(DEVICE_CONTEXT) + +WDF_DECLARE_CONTEXT_TYPE(TailLightDeviceInformation) + +EVT_WDF_DEVICE_CONTEXT_CLEANUP EvtDeviceContextCleanup; diff --git a/MouseMirror/driver.cpp b/MouseMirror/driver.cpp new file mode 100644 index 0000000..bfc94e4 --- /dev/null +++ b/MouseMirror/driver.cpp @@ -0,0 +1,39 @@ +#include "driver.h" + +/** Driver entry point. + Initialize the framework and register driver event handlers. */ +NTSTATUS DriverEntry( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING RegistryPath + ) +{ + KdPrint(("TailLight: DriverEntry - WDF version built on %s %s\n", __DATE__, __TIME__)); + + WDF_DRIVER_CONFIG params = {}; + WDF_DRIVER_CONFIG_INIT(/*out*/¶ms, EvtDriverDeviceAdd); + params.EvtDriverUnload = EvtDriverUnload; + + // Create the framework WDFDRIVER object, with the handle to it returned in Driver. + NTSTATUS status = WdfDriverCreate(DriverObject, + RegistryPath, + WDF_NO_OBJECT_ATTRIBUTES, + ¶ms, + WDF_NO_HANDLE); // [out] + if (!NT_SUCCESS(status)) { + // Framework will automatically cleanup on error Status return + KdPrint(("TailLight: Error Creating WDFDRIVER 0x%x\n", status)); + } + + return status; +} + + +/** Driver unload callback. + Used to perform operations that must take place before the driver is unloaded. */ +VOID EvtDriverUnload( + _In_ WDFDRIVER Driver + ) +{ + UNREFERENCED_PARAMETER(Driver); + KdPrint(("TailLight: DriverUnload.\n")); +} diff --git a/MouseMirror/driver.h b/MouseMirror/driver.h new file mode 100644 index 0000000..a14e0a9 --- /dev/null +++ b/MouseMirror/driver.h @@ -0,0 +1,24 @@ +#include +#include +#define NTSTRSAFE_LIB +#include +#include +#include + +// Generated WMI class definitions (from TailLight.mof) +#include "TailLightmof.h" + +#include "device.h" +#include "wmi.h" +#include "vfeature.h" + + +/** Memory allocation tag name (for debugging leaks). */ +static constexpr ULONG POOL_TAG = 'ffly'; + +extern "C" +DRIVER_INITIALIZE DriverEntry; + +EVT_WDF_DRIVER_UNLOAD EvtDriverUnload; + +EVT_WDF_DRIVER_DEVICE_ADD EvtDriverDeviceAdd; diff --git a/MouseMirror/eventlog.cpp b/MouseMirror/eventlog.cpp new file mode 100644 index 0000000..5b166d5 --- /dev/null +++ b/MouseMirror/eventlog.cpp @@ -0,0 +1,66 @@ +#include "eventlog.h" + + +constexpr USHORT IO_ERROR_LOG_PACKET_size() { + // TODO: Try stripping off the DumpData[1] member and padding at the end + // return offsetof(IO_ERROR_LOG_PACKET, DumpData); + return sizeof(IO_ERROR_LOG_PACKET); // -8; +} + + +void WriteToSystemLog(WDFDEVICE Device, NTSTATUS MessageId, WCHAR* InsertionStr1, WCHAR* InsertionStr2) { + // determine length of each insertion string + UCHAR InsertionStr1Len = 0; + if (InsertionStr1) + InsertionStr1Len = sizeof(WCHAR)*(UCHAR)(wcslen(InsertionStr1)+1); // in bytes (incl. null-termination) + UCHAR InsertionStr2Len = 0; + if (InsertionStr2) + InsertionStr2Len = sizeof(WCHAR)*(UCHAR)(wcslen(InsertionStr2)+1); // in bytes (incl. null-termination) + + + USHORT total_size = IO_ERROR_LOG_PACKET_size() + InsertionStr1Len + InsertionStr2Len; + if (total_size > ERROR_LOG_MAXIMUM_SIZE) { + // overflow check + KdPrint(("FireFly: IoAllocateErrorLogEntry too long message.\n")); + return; + } + + // Log an informational event with the caller name + DEVICE_OBJECT* dev_object = WdfDeviceWdmGetDeviceObject(Device); + auto* entry = (IO_ERROR_LOG_PACKET*)IoAllocateErrorLogEntry(dev_object, static_cast(total_size)); + if (!entry) { + KdPrint(("FireFly: IoAllocateErrorLogEntry allocation failure.\n")); + return; + } + + entry->MajorFunctionCode = 0; // (optional) + entry->RetryCount = 0; + entry->DumpDataSize = 0; + entry->NumberOfStrings = 0; + if (InsertionStr1Len) + entry->NumberOfStrings++; + if (InsertionStr2Len) + entry->NumberOfStrings++; + entry->StringOffset = IO_ERROR_LOG_PACKET_size(); // insertion string offsets + entry->EventCategory = 0; // TBD + entry->ErrorCode = MessageId; + entry->UniqueErrorValue = 0; // driver-specific code (optional) + entry->FinalStatus = 0; // user-space error code (optional) + entry->SequenceNumber = 0; // IRP sequence (optional) + entry->IoControlCode = 0; // (optional) + entry->DeviceOffset.QuadPart = 0; // offset in device where error occured (optional) + + BYTE* dest = (BYTE*)entry + entry->StringOffset; + if (InsertionStr1Len) { + RtlCopyMemory(/*dst*/dest, /*src*/InsertionStr1, InsertionStr1Len); + dest += InsertionStr1Len; + } + if (InsertionStr2Len) { + RtlCopyMemory(/*dst*/dest, /*src*/InsertionStr2, InsertionStr2Len); + dest += InsertionStr2Len; + } + + // Write to windows system log. + // The function will take over ownership of the object. + IoWriteErrorLogEntry(entry); +} diff --git a/MouseMirror/eventlog.h b/MouseMirror/eventlog.h new file mode 100644 index 0000000..7ef8463 --- /dev/null +++ b/MouseMirror/eventlog.h @@ -0,0 +1,9 @@ +#pragma once +#include +#include +#include "messages.h" // driver-specific MessageId values + + +/** Write to the Windows Event Viewer "System" log. + InsertionStr1 is a null-terminated string. */ +void WriteToSystemLog(WDFDEVICE Device, NTSTATUS MessageId, WCHAR* InsertionStr1, WCHAR* InsertionStr2); diff --git a/MouseMirror/messages.mc b/MouseMirror/messages.mc new file mode 100644 index 0000000..8748427 --- /dev/null +++ b/MouseMirror/messages.mc @@ -0,0 +1,23 @@ +;#ifndef __MESSAGES_H__ +;#define __MESSAGES_H__ + +MessageIdTypedef=NTSTATUS + +SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS + Informational=0x1:STATUS_SEVERITY_INFORMATIONAL + Warning=0x2:STATUS_SEVERITY_WARNING + Error=0x3:STATUS_SEVERITY_ERROR + ) + +FacilityNames=(System=0x0 + RpcRuntime=0x2:FACILITY_RPC_RUNTIME + RpcStubs=0x3:FACILITY_RPC_STUBS + Io=0x4:FACILITY_IO_ERROR_CODE + ) + + +MessageId=0x0001 Facility=Io Severity=Error SymbolicName=TailLight_SAFETY +Language=English +Color (%2) exceeded safety threshold. Resetting color to (%3) to indicate failure. +. +;#endif // __MESSAGES_H__ diff --git a/MouseMirror/module.rc b/MouseMirror/module.rc new file mode 100644 index 0000000..31a3a8f --- /dev/null +++ b/MouseMirror/module.rc @@ -0,0 +1,27 @@ +#include + +// Required defines +#ifdef _DEBUG +#define VER_FILEFLAGS VS_FF_DEBUG +#else +#define VER_FILEFLAGS 0 +#endif +#define VER_FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#define VER_FILEOS VOS_NT_WINDOWS32 + +#define VER_PRODUCTVERSION 0,0,0,0 +#define VER_PRODUCTVERSION_STR "0.0.0" +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_COMPANYNAME_STR "" // doesn't show up in file properties +#define VER_FILEDESCRIPTION_STR "IntelliMouse TailLight filter driver" +#define VER_INTERNALNAME_STR "" // doesn't show up in file properties +#define VER_LEGALCOPYRIGHT_STR L"\251 IntelliMouse sample project" +#define VER_ORIGINALFILENAME_STR "TailLight.sys" +#define VER_PRODUCTNAME_STR "TailLight" + +#include + +#include "messages.rc" + +TailLightWMI MOFDATA TailLight.bmf diff --git a/MouseMirror/vfeature.cpp b/MouseMirror/vfeature.cpp new file mode 100644 index 0000000..2db51cc --- /dev/null +++ b/MouseMirror/vfeature.cpp @@ -0,0 +1,235 @@ +#include "driver.h" +#include +#include +#include "eventlog.h" +#include "CppAllocator.hpp" + + +/** RAII wrapper of PHIDP_PREPARSED_DATA. */ +class PHIDP_PREPARSED_DATA_Wrap { +public: + PHIDP_PREPARSED_DATA_Wrap(size_t size) { + m_ptr = new BYTE[size]; + } + ~PHIDP_PREPARSED_DATA_Wrap() { + if (m_ptr) { + delete[] m_ptr; + m_ptr = nullptr; + } + } + + operator PHIDP_PREPARSED_DATA () const { + return (PHIDP_PREPARSED_DATA)m_ptr; + } + +private: + BYTE* m_ptr = nullptr; +}; + +/** RAII wrapper of WDFIOTARGET. */ +class WDFIOTARGET_Wrap { +public: + WDFIOTARGET_Wrap() { + } + ~WDFIOTARGET_Wrap() { + if (m_obj != NULL) { + WdfObjectDelete(m_obj); + } + } + + operator WDFIOTARGET () const { + return m_obj; + } + WDFIOTARGET* operator & () { + return &m_obj; + } + +private: + WDFIOTARGET m_obj = NULL; +}; + + +NTSTATUS SetFeatureColor ( + _In_ WDFDEVICE Device, + _In_ ULONG Color + ) +/*++ + This routine sets the HID feature by sending HID ioctls to our device. + These IOCTLs will be handled by HIDUSB and converted into USB requests + and send to the device. +--*/ +{ + KdPrint(("TailLight: SetFeatureColor\n")); + + WDFIOTARGET_Wrap hidTarget; + { + // open "hidTarget" using PdoName + NTSTATUS status = WdfIoTargetCreate(Device, WDF_NO_OBJECT_ATTRIBUTES, &hidTarget); + if (!NT_SUCCESS(status)) { + KdPrint(("TailLight: WdfIoTargetCreate failed 0x%x\n", status)); + return status; + } + + // open in write-only mode + DEVICE_CONTEXT* deviceContext = WdfObjectGet_DEVICE_CONTEXT(Device); + WDF_IO_TARGET_OPEN_PARAMS openParams = {}; + WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME(&openParams, &deviceContext->PdoName, FILE_WRITE_ACCESS); + + // We will let the framework to respond automatically to the pnp + // state changes of the target by closing and opening the handle. + openParams.ShareAccess = FILE_SHARE_WRITE | FILE_SHARE_READ; + + status = WdfIoTargetOpen(hidTarget, &openParams); + if (!NT_SUCCESS(status)) { + KdPrint(("TailLight: WdfIoTargetOpen failed 0x%x\n", status)); + return status; + } + } + + HID_COLLECTION_INFORMATION collectionInfo = {}; + { + // populate "collectionInformation" + WDF_MEMORY_DESCRIPTOR collectionInfoDesc = {}; + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&collectionInfoDesc, &collectionInfo, sizeof(HID_COLLECTION_INFORMATION)); + + NTSTATUS status = WdfIoTargetSendIoctlSynchronously(hidTarget, + NULL, + IOCTL_HID_GET_COLLECTION_INFORMATION, + NULL, + &collectionInfoDesc, + NULL, + NULL); + + KdPrint(("TailLight: ProductID=%x, VendorID=%x, VersionNumber=%u, DescriptorSize=%u\n", collectionInfo.ProductID, collectionInfo.VendorID, collectionInfo.VersionNumber, collectionInfo.DescriptorSize)); + + if (!NT_SUCCESS(status)) { + KdPrint(("TailLight: WdfIoTargetSendIoctlSynchronously1 failed 0x%x\n", status)); + return status; + } + } + + PHIDP_PREPARSED_DATA_Wrap preparsedData(collectionInfo.DescriptorSize); + if (!preparsedData) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + { + // populate "preparsedData" + WDF_MEMORY_DESCRIPTOR preparsedDataDesc = {}; + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&preparsedDataDesc, static_cast(preparsedData), collectionInfo.DescriptorSize); + + NTSTATUS status = WdfIoTargetSendIoctlSynchronously(hidTarget, + NULL, + IOCTL_HID_GET_COLLECTION_DESCRIPTOR, // same as HidD_GetPreparsedData in user-mode + NULL, + &preparsedDataDesc, + NULL, + NULL); + + if (!NT_SUCCESS(status)) { + KdPrint(("TailLight: WdfIoTargetSendIoctlSynchronously2 failed 0x%x\n", status)); + return status; + } + } + + { + // get capabilities + HIDP_CAPS caps = {}; + NTSTATUS status = HidP_GetCaps(preparsedData, &caps); + if (!NT_SUCCESS(status)) { + return status; + } + + //KdPrint(("TailLight: Usage=%x, UsagePage=%x\n", caps.Usage, caps.UsagePage)); + + if (caps.FeatureReportByteLength != sizeof(TailLightReport)) { + KdPrint(("TailLight: FeatureReportByteLength mismatch (%u, %Iu).\n", caps.FeatureReportByteLength, sizeof(TailLightReport))); + return status; + } + } + + // Create a report to send to the device. + TailLightReport report; + report.SetColor(Color); + + { + // send TailLightReport to device + WDF_MEMORY_DESCRIPTOR reportDesc = {}; + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&reportDesc, &report, sizeof(report)); + NTSTATUS status = WdfIoTargetSendIoctlSynchronously(hidTarget, + NULL, + IOCTL_HID_SET_FEATURE, // 0xb0191 + &reportDesc, + NULL, + NULL, + NULL); + if (!NT_SUCCESS(status)) { + KdPrint(("TailLight: WdfIoTargetSendIoctlSynchronously3 failed 0x%x\n", status)); + return status; + } + } + + return STATUS_SUCCESS; +} + + +NTSTATUS SetFeatureFilter( + _In_ WDFDEVICE Device, + _In_ WDFREQUEST Request, + _In_ size_t InputBufferLength +) +/*++ +Routine Description: + Handles IOCTL_HID_SET_FEATURE for all the collection. + For control collection (custom defined collection) it handles + the user-defined control codes for sideband communication + +Arguments: + QueueContext - The object context associated with the queue + + Request - Pointer to Request Packet. +--*/ +{ + KdPrint(("TailLight: SetFeatureFilter\n")); + DEVICE_CONTEXT* deviceContext = WdfObjectGet_DEVICE_CONTEXT(Device); + + if (InputBufferLength != sizeof(TailLightReport)) { + KdPrint(("TailLight: SetFeatureFilter: Incorrect InputBufferLength\n")); + return STATUS_BUFFER_TOO_SMALL; + } + + TailLightReport* packet = nullptr; + NTSTATUS status = WdfRequestRetrieveInputBuffer(Request, sizeof(TailLightReport), (void**)&packet, NULL); + if (!NT_SUCCESS(status) || !packet) { + KdPrint(("TailLight: WdfRequestRetrieveInputBuffer failed 0x%x, packet=0x%p\n", status, packet)); + return status; + } + + if (!packet->IsValid()) { + // If collection ID is not for control collection then handle + // this request just as you would for a regular collection. + return STATUS_INVALID_PARAMETER; + } + + // capture color before safety adjustments + UCHAR r = packet->Red; + UCHAR g = packet->Green; + UCHAR b = packet->Blue; + // Enforce safety limits (sets color to RED on failure) + if (!packet->SafetyCheck()) { + // log safety violation to Windows Event Viewer "System" log + WCHAR color_requested[16] = {}; + swprintf_s(color_requested, L"%u,%u,%u", r, g, b); + WCHAR color_adjusted[16] = {}; + swprintf_s(color_adjusted, L"%u,%u,%u", packet->Red, packet->Green, packet->Blue); + + WriteToSystemLog(Device, TailLight_SAFETY, color_requested, color_adjusted); + status = STATUS_CONTENT_BLOCKED; + } + + // update last written color + TailLightDeviceInformation* pInfo = WdfObjectGet_TailLightDeviceInformation(deviceContext->WmiInstance); + pInfo->TailLight = packet->GetColor(); + + return status; +} diff --git a/MouseMirror/vfeature.h b/MouseMirror/vfeature.h new file mode 100644 index 0000000..a73039a --- /dev/null +++ b/MouseMirror/vfeature.h @@ -0,0 +1,14 @@ +#pragma once +#include "TailLight.h" + + +NTSTATUS SetFeatureColor ( + _In_ WDFDEVICE Device, + _In_ ULONG Color + ); + +NTSTATUS SetFeatureFilter( + _In_ WDFDEVICE Device, + _In_ WDFREQUEST Request, + _In_ size_t InputBufferLength +); diff --git a/MouseMirror/wmi.cpp b/MouseMirror/wmi.cpp new file mode 100644 index 0000000..69a2bc2 --- /dev/null +++ b/MouseMirror/wmi.cpp @@ -0,0 +1,107 @@ +#include "driver.h" + + +// Register our GUID and Datablock generated from the TailLight.mof file. +NTSTATUS WmiInitialize(_In_ WDFDEVICE Device) +{ + DECLARE_CONST_UNICODE_STRING(mofRsrcName, MOFRESOURCENAME); + + NTSTATUS status = WdfDeviceAssignMofResourceName(Device, &mofRsrcName); + if (!NT_SUCCESS(status)) { + KdPrint(("TailLight: Error in WdfDeviceAssignMofResourceName %x\n", status)); + return status; + } + + WDF_WMI_PROVIDER_CONFIG providerConfig = {}; + WDF_WMI_PROVIDER_CONFIG_INIT(&providerConfig, &TailLightDeviceInformation_GUID); + providerConfig.MinInstanceBufferSize = sizeof(TailLightDeviceInformation); + + WDF_WMI_INSTANCE_CONFIG instanceConfig = {}; + WDF_WMI_INSTANCE_CONFIG_INIT_PROVIDER_CONFIG(&instanceConfig, &providerConfig); + instanceConfig.Register = TRUE; + instanceConfig.EvtWmiInstanceQueryInstance = EvtWmiInstanceQueryInstance; + instanceConfig.EvtWmiInstanceSetInstance = EvtWmiInstanceSetInstance; + instanceConfig.EvtWmiInstanceSetItem = EvtWmiInstanceSetItem; + + WDF_OBJECT_ATTRIBUTES woa = {}; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&woa, TailLightDeviceInformation); + + WDFWMIINSTANCE WmiInstance = 0; + status = WdfWmiInstanceCreate(Device, &instanceConfig, &woa, &WmiInstance); + if (!NT_SUCCESS(status)) { + KdPrint(("TailLight: WdfWmiInstanceCreate error %x\n", status)); + return status; + } + + DEVICE_CONTEXT* deviceContext = WdfObjectGet_DEVICE_CONTEXT(Device); + deviceContext->WmiInstance = WmiInstance; + + return status; +} + +NTSTATUS EvtWmiInstanceQueryInstance( + _In_ WDFWMIINSTANCE WmiInstance, + _In_ ULONG OutBufferSize, + _Out_writes_bytes_to_(OutBufferSize, *BufferUsed) PVOID OutBuffer, + _Out_ PULONG BufferUsed + ) +{ + UNREFERENCED_PARAMETER(OutBufferSize); // mininum buffer size already checked by WDF + + KdPrint(("TailLight: WMI QueryInstance\n")); + + TailLightDeviceInformation* pInfo = WdfObjectGet_TailLightDeviceInformation(WmiInstance); + RtlCopyMemory(/*dst*/OutBuffer, /*src*/pInfo, sizeof(*pInfo)); + *BufferUsed = sizeof(*pInfo); + + KdPrint(("TailLight: WMI QueryInstance completed\n")); + return STATUS_SUCCESS; +} + +NTSTATUS EvtWmiInstanceSetInstance( + _In_ WDFWMIINSTANCE WmiInstance, + _In_ ULONG InBufferSize, + _In_reads_bytes_(InBufferSize) PVOID InBuffer + ) +{ + UNREFERENCED_PARAMETER(InBufferSize); // mininum buffer size already checked by WDF + + KdPrint(("TailLight: WMI SetInstance\n")); + + TailLightDeviceInformation* pInfo = WdfObjectGet_TailLightDeviceInformation(WmiInstance); + RtlCopyMemory(/*dst*/pInfo, /*src*/InBuffer, sizeof(*pInfo)); + + // call SetFeatureColor to trigger tail-light update + NTSTATUS status = SetFeatureColor(WdfWmiInstanceGetDevice(WmiInstance), pInfo->TailLight); + + KdPrint(("TailLight: WMI SetInstance completed\n")); + return status; +} + +NTSTATUS EvtWmiInstanceSetItem( + _In_ WDFWMIINSTANCE WmiInstance, + _In_ ULONG DataItemId, + _In_ ULONG InBufferSize, + _In_reads_bytes_(InBufferSize) PVOID InBuffer + ) +{ + KdPrint(("TailLight: WMI SetItem\n")); + + TailLightDeviceInformation* pInfo = WdfObjectGet_TailLightDeviceInformation(WmiInstance); + NTSTATUS status = STATUS_SUCCESS; + + if (DataItemId == TailLightDeviceInformation_TailLight_ID) { + if (InBufferSize < TailLightDeviceInformation_TailLight_SIZE) + return STATUS_BUFFER_TOO_SMALL; + + pInfo->TailLight = *(ULONG*)InBuffer; + + // call SetFeatureColor to trigger tail-light update + status = SetFeatureColor(WdfWmiInstanceGetDevice(WmiInstance), pInfo->TailLight); + } else { + return STATUS_INVALID_DEVICE_REQUEST; + } + + KdPrint(("TailLight: WMI SetItem completed\n")); + return status; +} diff --git a/MouseMirror/wmi.h b/MouseMirror/wmi.h new file mode 100644 index 0000000..b41caf5 --- /dev/null +++ b/MouseMirror/wmi.h @@ -0,0 +1,11 @@ +// Where they are described. +#define MOFRESOURCENAME L"TailLightWMI" + +// Initialize WMI provider +NTSTATUS WmiInitialize(_In_ WDFDEVICE Device); + +EVT_WDF_WMI_INSTANCE_QUERY_INSTANCE EvtWmiInstanceQueryInstance; + +EVT_WDF_WMI_INSTANCE_SET_INSTANCE EvtWmiInstanceSetInstance; + +EVT_WDF_WMI_INSTANCE_SET_ITEM EvtWmiInstanceSetItem; From b0765d200bed667465d1021798d22e2b289ad685 Mon Sep 17 00:00:00 2001 From: Fredrik Orderud Date: Thu, 15 Feb 2024 09:20:23 +0100 Subject: [PATCH 02/10] Rename files to MouseMirror. --- ...NSTALL_TailLight.bat => INSTALL_MouseMirror.bat} | 0 MouseMirror/{TailLight.h => MouseMirror.h} | 0 MouseMirror/{TailLight.inx => MouseMirror.inx} | Bin MouseMirror/{TailLight.mof => MouseMirror.mof} | 0 .../{TailLight.vcxproj => MouseMirror.vcxproj} | 0 ...TALL_TailLight.bat => UNINSTALL_MouseMirror.bat} | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename MouseMirror/{INSTALL_TailLight.bat => INSTALL_MouseMirror.bat} (100%) rename MouseMirror/{TailLight.h => MouseMirror.h} (100%) rename MouseMirror/{TailLight.inx => MouseMirror.inx} (100%) rename MouseMirror/{TailLight.mof => MouseMirror.mof} (100%) rename MouseMirror/{TailLight.vcxproj => MouseMirror.vcxproj} (100%) rename MouseMirror/{UNINSTALL_TailLight.bat => UNINSTALL_MouseMirror.bat} (100%) diff --git a/MouseMirror/INSTALL_TailLight.bat b/MouseMirror/INSTALL_MouseMirror.bat similarity index 100% rename from MouseMirror/INSTALL_TailLight.bat rename to MouseMirror/INSTALL_MouseMirror.bat diff --git a/MouseMirror/TailLight.h b/MouseMirror/MouseMirror.h similarity index 100% rename from MouseMirror/TailLight.h rename to MouseMirror/MouseMirror.h diff --git a/MouseMirror/TailLight.inx b/MouseMirror/MouseMirror.inx similarity index 100% rename from MouseMirror/TailLight.inx rename to MouseMirror/MouseMirror.inx diff --git a/MouseMirror/TailLight.mof b/MouseMirror/MouseMirror.mof similarity index 100% rename from MouseMirror/TailLight.mof rename to MouseMirror/MouseMirror.mof diff --git a/MouseMirror/TailLight.vcxproj b/MouseMirror/MouseMirror.vcxproj similarity index 100% rename from MouseMirror/TailLight.vcxproj rename to MouseMirror/MouseMirror.vcxproj diff --git a/MouseMirror/UNINSTALL_TailLight.bat b/MouseMirror/UNINSTALL_MouseMirror.bat similarity index 100% rename from MouseMirror/UNINSTALL_TailLight.bat rename to MouseMirror/UNINSTALL_MouseMirror.bat From 94bfc1f05fefcb020b715d89469162e98a117808 Mon Sep 17 00:00:00 2001 From: Fredrik Orderud Date: Thu, 15 Feb 2024 09:24:00 +0100 Subject: [PATCH 03/10] Full-text string replacement of "TailLight" with "MouseMirror". --- MouseMirror/INSTALL_MouseMirror.bat | 4 +-- MouseMirror/MouseMirror.h | 12 ++++---- MouseMirror/MouseMirror.inx | Bin 6196 -> 6308 bytes MouseMirror/MouseMirror.mof | 6 ++-- MouseMirror/MouseMirror.vcxproj | 14 ++++----- MouseMirror/UNINSTALL_MouseMirror.bat | 4 +-- MouseMirror/device.cpp | 20 ++++++------ MouseMirror/device.h | 2 +- MouseMirror/driver.cpp | 6 ++-- MouseMirror/driver.h | 4 +-- MouseMirror/messages.mc | 2 +- MouseMirror/module.rc | 8 ++--- MouseMirror/vfeature.cpp | 42 +++++++++++++------------- MouseMirror/vfeature.h | 2 +- MouseMirror/wmi.cpp | 40 ++++++++++++------------ MouseMirror/wmi.h | 2 +- 16 files changed, 84 insertions(+), 84 deletions(-) diff --git a/MouseMirror/INSTALL_MouseMirror.bat b/MouseMirror/INSTALL_MouseMirror.bat index 2309e5f..868c224 100644 --- a/MouseMirror/INSTALL_MouseMirror.bat +++ b/MouseMirror/INSTALL_MouseMirror.bat @@ -3,10 +3,10 @@ cd /d "%~dp0" :: Use DevCon for installation, since it allows providing HWID -devcon /r install TailLight.inf "HID\VID_045E&PID_082A&MI_01&Col05" +devcon /r install MouseMirror.inf "HID\VID_045E&PID_082A&MI_01&Col05" :: Use PnpUtil for installation (succeeds but driver isn't loaded) ::devgen /add /bus ROOT /hardwareid "HID\VID_045E&PID_082A&MI_01&Col05" -::PNPUTIL /add-driver TailLight.inf /install /reboot +::PNPUTIL /add-driver MouseMirror.inf /install /reboot pause diff --git a/MouseMirror/MouseMirror.h b/MouseMirror/MouseMirror.h index 4df88a9..ea3b5b3 100644 --- a/MouseMirror/MouseMirror.h +++ b/MouseMirror/MouseMirror.h @@ -1,8 +1,8 @@ #pragma once /** Tail-light feature report as observed in USBPcap/Wireshark. */ -struct TailLightReport { - TailLightReport() { +struct MouseMirrorReport { + MouseMirrorReport() { } void SetColor(ULONG Color) { @@ -18,12 +18,12 @@ struct TailLightReport { #ifdef _KERNEL_MODE bool IsValid() const { if (ReportId != 36) {// 0x24 - KdPrint(("TailLight: TailLightReport: Unsupported report id %d\n", ReportId)); + KdPrint(("MouseMirror: MouseMirrorReport: Unsupported report id %d\n", ReportId)); return false; } if ((Unknown1 != 0xB2) || (Unknown2 != 0x03)) { - KdPrint(("TailLight: TailLightReport: Unknown control Code 0x%x 0x%x\n", Unknown1, Unknown2)); + KdPrint(("MouseMirror: MouseMirrorReport: Unknown control Code 0x%x 0x%x\n", Unknown1, Unknown2)); return false; } @@ -36,7 +36,7 @@ struct TailLightReport { // RGB check unsigned int color_sum = Red + Green + Blue; if (color_sum > 2 * 256) { - KdPrint(("TailLight: Color saturation %u exceeded 512 threshold. Reseting color to RED to signal error\n", color_sum)); + KdPrint(("MouseMirror: Color saturation %u exceeded 512 threshold. Reseting color to RED to signal error\n", color_sum)); Red = 255; Green = 0; Blue = 0; @@ -60,4 +60,4 @@ struct TailLightReport { UCHAR padding[67] = {}; }; -static_assert(sizeof(TailLightReport) == 73); +static_assert(sizeof(MouseMirrorReport) == 73); diff --git a/MouseMirror/MouseMirror.inx b/MouseMirror/MouseMirror.inx index d2d4bd757d8f0672b5be95e585394070e670d9bc..790b42a9aa1dc088d822add4000249c008fd840a 100644 GIT binary patch delta 804 zcmdmDu*7hJh^Q|^K0_%(F+(bYFGD6n5fJ7x6m3-HWx_5q*_ml84jE2nZ|pLgQ<>#) z88?+x5xb_z$5|V3$V9UB+G2G!gC5W$l|anPzy-$9Ku=-u-sFw!!jtvbi*T5~k^MIg znY|qSIAlO37I4lp#%dpf4ub+1W0jq}kV{$;qyoEax1g*%A^$Aoa>nki&0o2U87U8} z%>_JcEZA)Thvh5*4SlSx$K&gl0@6546ctRxA=54R8i!1~kTy;k#mP^Err?n66vkoV J=2nsQ%mCVdwQ&Fd delta 640 zcmZ2txW!>_0WF{AK z$zw6)wVUzlKjHzq0CATpnrtoB}UfsNsN0J4L;_Cv|>KOLnaJ!?R lG!_#I1yiwzz7~9qO;ku5i>S6RwgmE37>fy;zlyA91^{X@k@Elm diff --git a/MouseMirror/MouseMirror.mof b/MouseMirror/MouseMirror.mof index dd80641..0a5c979 100644 --- a/MouseMirror/MouseMirror.mof +++ b/MouseMirror/MouseMirror.mof @@ -7,9 +7,9 @@ [Dynamic, Provider("WMIProv"), WMI, - Description("TailLight driver information"), + Description("MouseMirror driver information"), guid("{07982702-2086-4B83-9444-34989BB10554}")] -class TailLightDeviceInformation { +class MouseMirrorDeviceInformation { [key, read] string InstanceName; @@ -17,5 +17,5 @@ class TailLightDeviceInformation { boolean Active; [WmiDataId(1), read, write, Description("Tail-light in RGB COLORREF format.")] - uint32 TailLight; + uint32 MouseMirror; }; diff --git a/MouseMirror/MouseMirror.vcxproj b/MouseMirror/MouseMirror.vcxproj index f381dc5..bfabab0 100644 --- a/MouseMirror/MouseMirror.vcxproj +++ b/MouseMirror/MouseMirror.vcxproj @@ -42,11 +42,11 @@ - - "$(IntDir)\TailLight.bmf" + + "$(IntDir)\MouseMirror.bmf" - - $(IntDir)\TailLightmof.h + + $(IntDir)\MouseMirrormof.h @@ -76,7 +76,7 @@ copy *.bat $(PackageDir) copy "C:\Program Files (x86)\Windows Kits\10\tools\$(WDKBuildFolder)\x64\dev*.exe" $(PackageDir) -copy ..\TailLight.ps1 $(OutDir) +copy ..\MouseMirror.ps1 $(OutDir) @@ -100,7 +100,7 @@ copy ..\TailLight.ps1 $(OutDir) copy *.bat $(PackageDir) copy "C:\Program Files (x86)\Windows Kits\10\tools\$(WDKBuildFolder)\x64\dev*.exe" $(PackageDir) -copy ..\TailLight.ps1 $(OutDir) +copy ..\MouseMirror.ps1 $(OutDir) @@ -120,7 +120,7 @@ copy ..\TailLight.ps1 $(OutDir) - + diff --git a/MouseMirror/UNINSTALL_MouseMirror.bat b/MouseMirror/UNINSTALL_MouseMirror.bat index 0fc2a8d..040ce42 100644 --- a/MouseMirror/UNINSTALL_MouseMirror.bat +++ b/MouseMirror/UNINSTALL_MouseMirror.bat @@ -8,9 +8,9 @@ devcon /r remove "HID\VID_045E&PID_082A&MI_01&Col05" ::PNPUTIL /remove-device /deviceid "HID\VID_045E&PID_082A&MI_01&Col05" :: uninstall driver -PNPUTIL /delete-driver TailLight.inf /uninstall /force /reboot +PNPUTIL /delete-driver MouseMirror.inf /uninstall /force /reboot -:: Delete TailLightDeviceInformation WMI class security descriptor +:: Delete MouseMirrorDeviceInformation WMI class security descriptor reg delete "HKLM\SYSTEM\CurrentControlSet\Control\WMI\Security" /v "07982702-2086-4B83-9444-34989BB10554" /f pause diff --git a/MouseMirror/device.cpp b/MouseMirror/device.cpp index 89aad26..597720f 100644 --- a/MouseMirror/device.cpp +++ b/MouseMirror/device.cpp @@ -5,18 +5,18 @@ EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL EvtIoDeviceControlFilter; VOID EvtSetBlackTimer(_In_ WDFTIMER Timer) { - KdPrint(("TailLight: EvtSetBlackTimer begin\n")); + KdPrint(("MouseMirror: EvtSetBlackTimer begin\n")); WDFDEVICE device = (WDFDEVICE)WdfTimerGetParentObject(Timer); NT_ASSERTMSG("EvtSetBlackTimer device NULL\n", device); NTSTATUS status = SetFeatureColor(device, 0); if (!NT_SUCCESS(status)) { - KdPrint(("TailLight: EvtSetBlackTimer failure NTSTATUS=0x%x\n", status)); + KdPrint(("MouseMirror: EvtSetBlackTimer failure NTSTATUS=0x%x\n", status)); return; } - KdPrint(("TailLight: EvtSetBlackTimer end\n")); + KdPrint(("MouseMirror: EvtSetBlackTimer end\n")); } NTSTATUS EvtSelfManagedIoInit(WDFDEVICE device) { @@ -80,7 +80,7 @@ Routine Description: NTSTATUS status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { - KdPrint(("TailLight: WdfDeviceCreate, Error %x\n", status)); + KdPrint(("MouseMirror: WdfDeviceCreate, Error %x\n", status)); return status; } } @@ -107,7 +107,7 @@ Routine Description: &memory); if (!NT_SUCCESS(status)) { - KdPrint(("TailLight: WdfDeviceAllocAndQueryProperty failed 0x%x\n", status)); + KdPrint(("MouseMirror: WdfDeviceAllocAndQueryProperty failed 0x%x\n", status)); return STATUS_UNSUCCESSFUL; } @@ -120,7 +120,7 @@ Routine Description: deviceContext->PdoName.MaximumLength = (USHORT)bufferLength; deviceContext->PdoName.Length = (USHORT)bufferLength - sizeof(UNICODE_NULL); - KdPrint(("TailLight: PdoName: %wZ\n", deviceContext->PdoName)); // outputs "\Device\00000083 + KdPrint(("MouseMirror: PdoName: %wZ\n", deviceContext->PdoName)); // outputs "\Device\00000083 } { @@ -135,7 +135,7 @@ Routine Description: NTSTATUS status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue); if (!NT_SUCCESS(status)) { - KdPrint(("TailLight: WdfIoQueueCreate failed 0x%x\n", status)); + KdPrint(("MouseMirror: WdfIoQueueCreate failed 0x%x\n", status)); return status; } } @@ -143,7 +143,7 @@ Routine Description: // Initialize WMI provider NTSTATUS status = WmiInitialize(device); if (!NT_SUCCESS(status)) { - KdPrint(("TailLight: Error initializing WMI 0x%x\n", status)); + KdPrint(("MouseMirror: Error initializing WMI 0x%x\n", status)); return status; } @@ -181,7 +181,7 @@ Routine Description: { UNREFERENCED_PARAMETER(OutputBufferLength); - //KdPrint(("TailLight: EvtIoDeviceControl (IoControlCode=0x%x, InputBufferLength=%Iu)\n", IoControlCode, InputBufferLength)); + //KdPrint(("MouseMirror: EvtIoDeviceControl (IoControlCode=0x%x, InputBufferLength=%Iu)\n", IoControlCode, InputBufferLength)); WDFDEVICE device = WdfIoQueueGetDevice(Queue); @@ -200,7 +200,7 @@ Routine Description: BOOLEAN ret = WdfRequestSend(Request, WdfDeviceGetIoTarget(device), &options); if (ret == FALSE) { status = WdfRequestGetStatus(Request); - KdPrint(("TailLight: WdfRequestSend failed with status: 0x%x\n", status)); + KdPrint(("MouseMirror: WdfRequestSend failed with status: 0x%x\n", status)); WdfRequestComplete(Request, status); } } diff --git a/MouseMirror/device.h b/MouseMirror/device.h index 78543c2..20997cb 100644 --- a/MouseMirror/device.h +++ b/MouseMirror/device.h @@ -8,6 +8,6 @@ typedef struct _DEVICE_CONTEXT { WDF_DECLARE_CONTEXT_TYPE(DEVICE_CONTEXT) -WDF_DECLARE_CONTEXT_TYPE(TailLightDeviceInformation) +WDF_DECLARE_CONTEXT_TYPE(MouseMirrorDeviceInformation) EVT_WDF_DEVICE_CONTEXT_CLEANUP EvtDeviceContextCleanup; diff --git a/MouseMirror/driver.cpp b/MouseMirror/driver.cpp index bfc94e4..836d301 100644 --- a/MouseMirror/driver.cpp +++ b/MouseMirror/driver.cpp @@ -7,7 +7,7 @@ NTSTATUS DriverEntry( _In_ PUNICODE_STRING RegistryPath ) { - KdPrint(("TailLight: DriverEntry - WDF version built on %s %s\n", __DATE__, __TIME__)); + KdPrint(("MouseMirror: DriverEntry - WDF version built on %s %s\n", __DATE__, __TIME__)); WDF_DRIVER_CONFIG params = {}; WDF_DRIVER_CONFIG_INIT(/*out*/¶ms, EvtDriverDeviceAdd); @@ -21,7 +21,7 @@ NTSTATUS DriverEntry( WDF_NO_HANDLE); // [out] if (!NT_SUCCESS(status)) { // Framework will automatically cleanup on error Status return - KdPrint(("TailLight: Error Creating WDFDRIVER 0x%x\n", status)); + KdPrint(("MouseMirror: Error Creating WDFDRIVER 0x%x\n", status)); } return status; @@ -35,5 +35,5 @@ VOID EvtDriverUnload( ) { UNREFERENCED_PARAMETER(Driver); - KdPrint(("TailLight: DriverUnload.\n")); + KdPrint(("MouseMirror: DriverUnload.\n")); } diff --git a/MouseMirror/driver.h b/MouseMirror/driver.h index a14e0a9..ddd3670 100644 --- a/MouseMirror/driver.h +++ b/MouseMirror/driver.h @@ -5,8 +5,8 @@ #include #include -// Generated WMI class definitions (from TailLight.mof) -#include "TailLightmof.h" +// Generated WMI class definitions (from MouseMirror.mof) +#include "MouseMirrormof.h" #include "device.h" #include "wmi.h" diff --git a/MouseMirror/messages.mc b/MouseMirror/messages.mc index 8748427..3f7a88b 100644 --- a/MouseMirror/messages.mc +++ b/MouseMirror/messages.mc @@ -16,7 +16,7 @@ FacilityNames=(System=0x0 ) -MessageId=0x0001 Facility=Io Severity=Error SymbolicName=TailLight_SAFETY +MessageId=0x0001 Facility=Io Severity=Error SymbolicName=MouseMirror_SAFETY Language=English Color (%2) exceeded safety threshold. Resetting color to (%3) to indicate failure. . diff --git a/MouseMirror/module.rc b/MouseMirror/module.rc index 31a3a8f..fd8b457 100644 --- a/MouseMirror/module.rc +++ b/MouseMirror/module.rc @@ -14,14 +14,14 @@ #define VER_FILETYPE VFT_DRV #define VER_FILESUBTYPE VFT2_DRV_SYSTEM #define VER_COMPANYNAME_STR "" // doesn't show up in file properties -#define VER_FILEDESCRIPTION_STR "IntelliMouse TailLight filter driver" +#define VER_FILEDESCRIPTION_STR "IntelliMouse MouseMirror filter driver" #define VER_INTERNALNAME_STR "" // doesn't show up in file properties #define VER_LEGALCOPYRIGHT_STR L"\251 IntelliMouse sample project" -#define VER_ORIGINALFILENAME_STR "TailLight.sys" -#define VER_PRODUCTNAME_STR "TailLight" +#define VER_ORIGINALFILENAME_STR "MouseMirror.sys" +#define VER_PRODUCTNAME_STR "MouseMirror" #include #include "messages.rc" -TailLightWMI MOFDATA TailLight.bmf +MouseMirrorWMI MOFDATA MouseMirror.bmf diff --git a/MouseMirror/vfeature.cpp b/MouseMirror/vfeature.cpp index 2db51cc..2c7353a 100644 --- a/MouseMirror/vfeature.cpp +++ b/MouseMirror/vfeature.cpp @@ -59,14 +59,14 @@ NTSTATUS SetFeatureColor ( and send to the device. --*/ { - KdPrint(("TailLight: SetFeatureColor\n")); + KdPrint(("MouseMirror: SetFeatureColor\n")); WDFIOTARGET_Wrap hidTarget; { // open "hidTarget" using PdoName NTSTATUS status = WdfIoTargetCreate(Device, WDF_NO_OBJECT_ATTRIBUTES, &hidTarget); if (!NT_SUCCESS(status)) { - KdPrint(("TailLight: WdfIoTargetCreate failed 0x%x\n", status)); + KdPrint(("MouseMirror: WdfIoTargetCreate failed 0x%x\n", status)); return status; } @@ -81,7 +81,7 @@ NTSTATUS SetFeatureColor ( status = WdfIoTargetOpen(hidTarget, &openParams); if (!NT_SUCCESS(status)) { - KdPrint(("TailLight: WdfIoTargetOpen failed 0x%x\n", status)); + KdPrint(("MouseMirror: WdfIoTargetOpen failed 0x%x\n", status)); return status; } } @@ -100,10 +100,10 @@ NTSTATUS SetFeatureColor ( NULL, NULL); - KdPrint(("TailLight: ProductID=%x, VendorID=%x, VersionNumber=%u, DescriptorSize=%u\n", collectionInfo.ProductID, collectionInfo.VendorID, collectionInfo.VersionNumber, collectionInfo.DescriptorSize)); + KdPrint(("MouseMirror: ProductID=%x, VendorID=%x, VersionNumber=%u, DescriptorSize=%u\n", collectionInfo.ProductID, collectionInfo.VendorID, collectionInfo.VersionNumber, collectionInfo.DescriptorSize)); if (!NT_SUCCESS(status)) { - KdPrint(("TailLight: WdfIoTargetSendIoctlSynchronously1 failed 0x%x\n", status)); + KdPrint(("MouseMirror: WdfIoTargetSendIoctlSynchronously1 failed 0x%x\n", status)); return status; } } @@ -127,7 +127,7 @@ NTSTATUS SetFeatureColor ( NULL); if (!NT_SUCCESS(status)) { - KdPrint(("TailLight: WdfIoTargetSendIoctlSynchronously2 failed 0x%x\n", status)); + KdPrint(("MouseMirror: WdfIoTargetSendIoctlSynchronously2 failed 0x%x\n", status)); return status; } } @@ -140,20 +140,20 @@ NTSTATUS SetFeatureColor ( return status; } - //KdPrint(("TailLight: Usage=%x, UsagePage=%x\n", caps.Usage, caps.UsagePage)); + //KdPrint(("MouseMirror: Usage=%x, UsagePage=%x\n", caps.Usage, caps.UsagePage)); - if (caps.FeatureReportByteLength != sizeof(TailLightReport)) { - KdPrint(("TailLight: FeatureReportByteLength mismatch (%u, %Iu).\n", caps.FeatureReportByteLength, sizeof(TailLightReport))); + if (caps.FeatureReportByteLength != sizeof(MouseMirrorReport)) { + KdPrint(("MouseMirror: FeatureReportByteLength mismatch (%u, %Iu).\n", caps.FeatureReportByteLength, sizeof(MouseMirrorReport))); return status; } } // Create a report to send to the device. - TailLightReport report; + MouseMirrorReport report; report.SetColor(Color); { - // send TailLightReport to device + // send MouseMirrorReport to device WDF_MEMORY_DESCRIPTOR reportDesc = {}; WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&reportDesc, &report, sizeof(report)); NTSTATUS status = WdfIoTargetSendIoctlSynchronously(hidTarget, @@ -164,7 +164,7 @@ NTSTATUS SetFeatureColor ( NULL, NULL); if (!NT_SUCCESS(status)) { - KdPrint(("TailLight: WdfIoTargetSendIoctlSynchronously3 failed 0x%x\n", status)); + KdPrint(("MouseMirror: WdfIoTargetSendIoctlSynchronously3 failed 0x%x\n", status)); return status; } } @@ -190,18 +190,18 @@ Routine Description: Request - Pointer to Request Packet. --*/ { - KdPrint(("TailLight: SetFeatureFilter\n")); + KdPrint(("MouseMirror: SetFeatureFilter\n")); DEVICE_CONTEXT* deviceContext = WdfObjectGet_DEVICE_CONTEXT(Device); - if (InputBufferLength != sizeof(TailLightReport)) { - KdPrint(("TailLight: SetFeatureFilter: Incorrect InputBufferLength\n")); + if (InputBufferLength != sizeof(MouseMirrorReport)) { + KdPrint(("MouseMirror: SetFeatureFilter: Incorrect InputBufferLength\n")); return STATUS_BUFFER_TOO_SMALL; } - TailLightReport* packet = nullptr; - NTSTATUS status = WdfRequestRetrieveInputBuffer(Request, sizeof(TailLightReport), (void**)&packet, NULL); + MouseMirrorReport* packet = nullptr; + NTSTATUS status = WdfRequestRetrieveInputBuffer(Request, sizeof(MouseMirrorReport), (void**)&packet, NULL); if (!NT_SUCCESS(status) || !packet) { - KdPrint(("TailLight: WdfRequestRetrieveInputBuffer failed 0x%x, packet=0x%p\n", status, packet)); + KdPrint(("MouseMirror: WdfRequestRetrieveInputBuffer failed 0x%x, packet=0x%p\n", status, packet)); return status; } @@ -223,13 +223,13 @@ Routine Description: WCHAR color_adjusted[16] = {}; swprintf_s(color_adjusted, L"%u,%u,%u", packet->Red, packet->Green, packet->Blue); - WriteToSystemLog(Device, TailLight_SAFETY, color_requested, color_adjusted); + WriteToSystemLog(Device, MouseMirror_SAFETY, color_requested, color_adjusted); status = STATUS_CONTENT_BLOCKED; } // update last written color - TailLightDeviceInformation* pInfo = WdfObjectGet_TailLightDeviceInformation(deviceContext->WmiInstance); - pInfo->TailLight = packet->GetColor(); + MouseMirrorDeviceInformation* pInfo = WdfObjectGet_MouseMirrorDeviceInformation(deviceContext->WmiInstance); + pInfo->MouseMirror = packet->GetColor(); return status; } diff --git a/MouseMirror/vfeature.h b/MouseMirror/vfeature.h index a73039a..705250f 100644 --- a/MouseMirror/vfeature.h +++ b/MouseMirror/vfeature.h @@ -1,5 +1,5 @@ #pragma once -#include "TailLight.h" +#include "MouseMirror.h" NTSTATUS SetFeatureColor ( diff --git a/MouseMirror/wmi.cpp b/MouseMirror/wmi.cpp index 69a2bc2..e145117 100644 --- a/MouseMirror/wmi.cpp +++ b/MouseMirror/wmi.cpp @@ -1,20 +1,20 @@ #include "driver.h" -// Register our GUID and Datablock generated from the TailLight.mof file. +// Register our GUID and Datablock generated from the MouseMirror.mof file. NTSTATUS WmiInitialize(_In_ WDFDEVICE Device) { DECLARE_CONST_UNICODE_STRING(mofRsrcName, MOFRESOURCENAME); NTSTATUS status = WdfDeviceAssignMofResourceName(Device, &mofRsrcName); if (!NT_SUCCESS(status)) { - KdPrint(("TailLight: Error in WdfDeviceAssignMofResourceName %x\n", status)); + KdPrint(("MouseMirror: Error in WdfDeviceAssignMofResourceName %x\n", status)); return status; } WDF_WMI_PROVIDER_CONFIG providerConfig = {}; - WDF_WMI_PROVIDER_CONFIG_INIT(&providerConfig, &TailLightDeviceInformation_GUID); - providerConfig.MinInstanceBufferSize = sizeof(TailLightDeviceInformation); + WDF_WMI_PROVIDER_CONFIG_INIT(&providerConfig, &MouseMirrorDeviceInformation_GUID); + providerConfig.MinInstanceBufferSize = sizeof(MouseMirrorDeviceInformation); WDF_WMI_INSTANCE_CONFIG instanceConfig = {}; WDF_WMI_INSTANCE_CONFIG_INIT_PROVIDER_CONFIG(&instanceConfig, &providerConfig); @@ -24,12 +24,12 @@ NTSTATUS WmiInitialize(_In_ WDFDEVICE Device) instanceConfig.EvtWmiInstanceSetItem = EvtWmiInstanceSetItem; WDF_OBJECT_ATTRIBUTES woa = {}; - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&woa, TailLightDeviceInformation); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&woa, MouseMirrorDeviceInformation); WDFWMIINSTANCE WmiInstance = 0; status = WdfWmiInstanceCreate(Device, &instanceConfig, &woa, &WmiInstance); if (!NT_SUCCESS(status)) { - KdPrint(("TailLight: WdfWmiInstanceCreate error %x\n", status)); + KdPrint(("MouseMirror: WdfWmiInstanceCreate error %x\n", status)); return status; } @@ -48,13 +48,13 @@ NTSTATUS EvtWmiInstanceQueryInstance( { UNREFERENCED_PARAMETER(OutBufferSize); // mininum buffer size already checked by WDF - KdPrint(("TailLight: WMI QueryInstance\n")); + KdPrint(("MouseMirror: WMI QueryInstance\n")); - TailLightDeviceInformation* pInfo = WdfObjectGet_TailLightDeviceInformation(WmiInstance); + MouseMirrorDeviceInformation* pInfo = WdfObjectGet_MouseMirrorDeviceInformation(WmiInstance); RtlCopyMemory(/*dst*/OutBuffer, /*src*/pInfo, sizeof(*pInfo)); *BufferUsed = sizeof(*pInfo); - KdPrint(("TailLight: WMI QueryInstance completed\n")); + KdPrint(("MouseMirror: WMI QueryInstance completed\n")); return STATUS_SUCCESS; } @@ -66,15 +66,15 @@ NTSTATUS EvtWmiInstanceSetInstance( { UNREFERENCED_PARAMETER(InBufferSize); // mininum buffer size already checked by WDF - KdPrint(("TailLight: WMI SetInstance\n")); + KdPrint(("MouseMirror: WMI SetInstance\n")); - TailLightDeviceInformation* pInfo = WdfObjectGet_TailLightDeviceInformation(WmiInstance); + MouseMirrorDeviceInformation* pInfo = WdfObjectGet_MouseMirrorDeviceInformation(WmiInstance); RtlCopyMemory(/*dst*/pInfo, /*src*/InBuffer, sizeof(*pInfo)); // call SetFeatureColor to trigger tail-light update - NTSTATUS status = SetFeatureColor(WdfWmiInstanceGetDevice(WmiInstance), pInfo->TailLight); + NTSTATUS status = SetFeatureColor(WdfWmiInstanceGetDevice(WmiInstance), pInfo->MouseMirror); - KdPrint(("TailLight: WMI SetInstance completed\n")); + KdPrint(("MouseMirror: WMI SetInstance completed\n")); return status; } @@ -85,23 +85,23 @@ NTSTATUS EvtWmiInstanceSetItem( _In_reads_bytes_(InBufferSize) PVOID InBuffer ) { - KdPrint(("TailLight: WMI SetItem\n")); + KdPrint(("MouseMirror: WMI SetItem\n")); - TailLightDeviceInformation* pInfo = WdfObjectGet_TailLightDeviceInformation(WmiInstance); + MouseMirrorDeviceInformation* pInfo = WdfObjectGet_MouseMirrorDeviceInformation(WmiInstance); NTSTATUS status = STATUS_SUCCESS; - if (DataItemId == TailLightDeviceInformation_TailLight_ID) { - if (InBufferSize < TailLightDeviceInformation_TailLight_SIZE) + if (DataItemId == MouseMirrorDeviceInformation_MouseMirror_ID) { + if (InBufferSize < MouseMirrorDeviceInformation_MouseMirror_SIZE) return STATUS_BUFFER_TOO_SMALL; - pInfo->TailLight = *(ULONG*)InBuffer; + pInfo->MouseMirror = *(ULONG*)InBuffer; // call SetFeatureColor to trigger tail-light update - status = SetFeatureColor(WdfWmiInstanceGetDevice(WmiInstance), pInfo->TailLight); + status = SetFeatureColor(WdfWmiInstanceGetDevice(WmiInstance), pInfo->MouseMirror); } else { return STATUS_INVALID_DEVICE_REQUEST; } - KdPrint(("TailLight: WMI SetItem completed\n")); + KdPrint(("MouseMirror: WMI SetItem completed\n")); return status; } diff --git a/MouseMirror/wmi.h b/MouseMirror/wmi.h index b41caf5..4c77d21 100644 --- a/MouseMirror/wmi.h +++ b/MouseMirror/wmi.h @@ -1,5 +1,5 @@ // Where they are described. -#define MOFRESOURCENAME L"TailLightWMI" +#define MOFRESOURCENAME L"MouseMirrorWMI" // Initialize WMI provider NTSTATUS WmiInitialize(_In_ WDFDEVICE Device); From baa57e651cf497329ae224a0492999d4e2b17d0c Mon Sep 17 00:00:00 2001 From: Fredrik Orderud Date: Thu, 15 Feb 2024 09:25:09 +0100 Subject: [PATCH 04/10] Add MouseMirror project to solution. Make project GUID unique. --- IntelliMouse.sln | 8 ++++++++ MouseMirror/MouseMirror.vcxproj | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/IntelliMouse.sln b/IntelliMouse.sln index bd32c3e..0dd1781 100644 --- a/IntelliMouse.sln +++ b/IntelliMouse.sln @@ -9,6 +9,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TailLight", "TailLight\Tail EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "flicker", "flicker\flicker.vcxproj", "{BB81C655-EEF5-434F-BB2A-4B8D1358ECE4}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MouseMirror", "MouseMirror\MouseMirror.vcxproj", "{42A4140E-4EF5-4502-BE9F-A33D6C0FC5E7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -29,6 +31,12 @@ Global {BB81C655-EEF5-434F-BB2A-4B8D1358ECE4}.Debug|x64.Build.0 = Debug|x64 {BB81C655-EEF5-434F-BB2A-4B8D1358ECE4}.Release|x64.ActiveCfg = Release|x64 {BB81C655-EEF5-434F-BB2A-4B8D1358ECE4}.Release|x64.Build.0 = Release|x64 + {42A4140E-4EF5-4502-BE9F-A33D6C0FC5E7}.Debug|x64.ActiveCfg = Debug|x64 + {42A4140E-4EF5-4502-BE9F-A33D6C0FC5E7}.Debug|x64.Build.0 = Debug|x64 + {42A4140E-4EF5-4502-BE9F-A33D6C0FC5E7}.Debug|x64.Deploy.0 = Debug|x64 + {42A4140E-4EF5-4502-BE9F-A33D6C0FC5E7}.Release|x64.ActiveCfg = Release|x64 + {42A4140E-4EF5-4502-BE9F-A33D6C0FC5E7}.Release|x64.Build.0 = Release|x64 + {42A4140E-4EF5-4502-BE9F-A33D6C0FC5E7}.Release|x64.Deploy.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/MouseMirror/MouseMirror.vcxproj b/MouseMirror/MouseMirror.vcxproj index bfabab0..07c00b0 100644 --- a/MouseMirror/MouseMirror.vcxproj +++ b/MouseMirror/MouseMirror.vcxproj @@ -11,7 +11,7 @@ - {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5} + {42A4140E-4EF5-4502-BE9F-A33D6C0FC5E7} $(MSBuildProjectName) 1 Debug From 06aeee1dbb90cb81a07713037f8aa3b9398e44a3 Mon Sep 17 00:00:00 2001 From: Fredrik Orderud Date: Thu, 15 Feb 2024 09:30:55 +0100 Subject: [PATCH 05/10] Strip away tail-light specific stuff. --- MouseMirror/CppAllocator.hpp | 24 ---- MouseMirror/MouseMirror.h | 62 --------- MouseMirror/MouseMirror.vcxproj | 8 -- MouseMirror/device.cpp | 109 +-------------- MouseMirror/driver.h | 1 - MouseMirror/eventlog.cpp | 66 --------- MouseMirror/eventlog.h | 9 -- MouseMirror/messages.mc | 23 ---- MouseMirror/module.rc | 2 - MouseMirror/vfeature.cpp | 235 -------------------------------- MouseMirror/vfeature.h | 14 -- MouseMirror/wmi.cpp | 8 +- 12 files changed, 2 insertions(+), 559 deletions(-) delete mode 100644 MouseMirror/CppAllocator.hpp delete mode 100644 MouseMirror/eventlog.cpp delete mode 100644 MouseMirror/eventlog.h delete mode 100644 MouseMirror/messages.mc delete mode 100644 MouseMirror/vfeature.cpp delete mode 100644 MouseMirror/vfeature.h diff --git a/MouseMirror/CppAllocator.hpp b/MouseMirror/CppAllocator.hpp deleted file mode 100644 index bf175b4..0000000 --- a/MouseMirror/CppAllocator.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -/* This codes assumes that POOL_TAG have already been defined if building in kernel-mode. */ - -#ifdef _KERNEL_MODE -void* operator new (size_t size) noexcept { - // allocate in non-paged pool (will always reside in RAM) - return ExAllocatePool2(POOL_FLAG_NON_PAGED, size, POOL_TAG); -} - -void* operator new[] (size_t size) noexcept { - // allocate in non-paged pool (will always reside in RAM) - return ExAllocatePool2(POOL_FLAG_NON_PAGED, size, POOL_TAG); -} - -void operator delete (void *ptr, size_t /*size*/) noexcept { - return ExFreePool(ptr); -} - -void operator delete[] (void* ptr) noexcept { - return ExFreePool(ptr); -} - -#endif // _KERNEL_MODE diff --git a/MouseMirror/MouseMirror.h b/MouseMirror/MouseMirror.h index ea3b5b3..6f70f09 100644 --- a/MouseMirror/MouseMirror.h +++ b/MouseMirror/MouseMirror.h @@ -1,63 +1 @@ #pragma once - -/** Tail-light feature report as observed in USBPcap/Wireshark. */ -struct MouseMirrorReport { - MouseMirrorReport() { - } - - void SetColor(ULONG Color) { - Red = (Color) & 0xFF; // red; - Green = (Color >> 8) & 0xFF; // green - Blue = (Color >> 16) & 0xFF; // blue - } - - ULONG GetColor() const { - return (Blue << 16) | (Green << 8) | Red; - } - -#ifdef _KERNEL_MODE - bool IsValid() const { - if (ReportId != 36) {// 0x24 - KdPrint(("MouseMirror: MouseMirrorReport: Unsupported report id %d\n", ReportId)); - return false; - } - - if ((Unknown1 != 0xB2) || (Unknown2 != 0x03)) { - KdPrint(("MouseMirror: MouseMirrorReport: Unknown control Code 0x%x 0x%x\n", Unknown1, Unknown2)); - return false; - } - - return true; - } -#endif - -#ifdef _KERNEL_MODE - bool SafetyCheck() { - // RGB check - unsigned int color_sum = Red + Green + Blue; - if (color_sum > 2 * 256) { - KdPrint(("MouseMirror: Color saturation %u exceeded 512 threshold. Reseting color to RED to signal error\n", color_sum)); - Red = 255; - Green = 0; - Blue = 0; - return false; - } - - return true; - } -#endif - - //report ID of the collection to which the control request is sent - UCHAR ReportId = 36; // (0x24) - - // control codes (user-defined) - UCHAR Unknown1 = 0xB2; // magic value - UCHAR Unknown2 = 0x03; // magic value - - UCHAR Red = 0; - UCHAR Green = 0; - UCHAR Blue = 0; - - UCHAR padding[67] = {}; -}; -static_assert(sizeof(MouseMirrorReport) == 73); diff --git a/MouseMirror/MouseMirror.vcxproj b/MouseMirror/MouseMirror.vcxproj index 07c00b0..84e2689 100644 --- a/MouseMirror/MouseMirror.vcxproj +++ b/MouseMirror/MouseMirror.vcxproj @@ -106,8 +106,6 @@ copy ..\MouseMirror.ps1 $(OutDir) - - @@ -116,16 +114,10 @@ copy ..\MouseMirror.ps1 $(OutDir) - - - - - - \ No newline at end of file diff --git a/MouseMirror/device.cpp b/MouseMirror/device.cpp index 597720f..bfccc3b 100644 --- a/MouseMirror/device.cpp +++ b/MouseMirror/device.cpp @@ -1,50 +1,6 @@ #include "driver.h" #include -EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL EvtIoDeviceControlFilter; - - -VOID EvtSetBlackTimer(_In_ WDFTIMER Timer) { - KdPrint(("MouseMirror: EvtSetBlackTimer begin\n")); - - WDFDEVICE device = (WDFDEVICE)WdfTimerGetParentObject(Timer); - NT_ASSERTMSG("EvtSetBlackTimer device NULL\n", device); - - NTSTATUS status = SetFeatureColor(device, 0); - if (!NT_SUCCESS(status)) { - KdPrint(("MouseMirror: EvtSetBlackTimer failure NTSTATUS=0x%x\n", status)); - return; - } - - KdPrint(("MouseMirror: EvtSetBlackTimer end\n")); -} - -NTSTATUS EvtSelfManagedIoInit(WDFDEVICE device) { - // Initialize tail-light to black to have control over HW state - WDF_TIMER_CONFIG timerCfg = {}; - WDF_TIMER_CONFIG_INIT(&timerCfg, EvtSetBlackTimer); - - WDF_OBJECT_ATTRIBUTES attribs = {}; - WDF_OBJECT_ATTRIBUTES_INIT(&attribs); - attribs.ParentObject = device; - attribs.ExecutionLevel = WdfExecutionLevelPassive; // required to access HID functions - - WDFTIMER timer = nullptr; - NTSTATUS status = WdfTimerCreate(&timerCfg, &attribs, &timer); - if (!NT_SUCCESS(status)) { - KdPrint(("WdfTimerCreate failed 0x%x\n", status)); - return status; - } - - status = WdfTimerStart(timer, 0); // no wait - if (!NT_SUCCESS(status)) { - KdPrint(("WdfTimerStart failed 0x%x\n", status)); - return status; - } - - return status; -} - NTSTATUS EvtDriverDeviceAdd(_In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit) /*++ @@ -64,14 +20,6 @@ Routine Description: // Configure the device as a filter driver WdfFdoInitSetFilter(DeviceInit); - { - // register PnP callbacks (must be done before WdfDeviceCreate) - WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerCallbacks; - WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerCallbacks); - PnpPowerCallbacks.EvtDeviceSelfManagedIoInit = EvtSelfManagedIoInit; - WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &PnpPowerCallbacks); - } - WDFDEVICE device = 0; { // create device @@ -129,7 +77,7 @@ Routine Description: WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); // don't synchronize //queueConfig.EvtIoRead // pass-through read requests //queueConfig.EvtIoWrite // pass-through write requests - queueConfig.EvtIoDeviceControl = EvtIoDeviceControlFilter; // filter IOCTL requests + // queueConfig.EvtIoDeviceControl // pass-through IOCTL requests WDFQUEUE queue = 0; // auto-deleted when parent is deleted NTSTATUS status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue); @@ -149,58 +97,3 @@ Routine Description: return status; } - - -VOID EvtIoDeviceControlFilter( - _In_ WDFQUEUE Queue, - _In_ WDFREQUEST Request, - _In_ size_t OutputBufferLength, - _In_ size_t InputBufferLength, - _In_ ULONG IoControlCode -) -/*++ -Routine Description: - This event callback function is called when the driver receives an - - (KMDF) IOCTL_HID_Xxx code when handling IRP_MJ_INTERNAL_DEVICE_CONTROL - (UMDF) IOCTL_HID_Xxx, IOCTL_UMDF_HID_Xxx when handling IRP_MJ_DEVICE_CONTROL - -Arguments: - Queue - A handle to the queue object that is associated with the I/O request - - Request - A handle to a framework request object. - - OutputBufferLength - The length, in bytes, of the request's output buffer, - if an output buffer is available. - - InputBufferLength - The length, in bytes, of the request's input buffer, if - an input buffer is available. - - IoControlCode - The driver or system defined IOCTL associated with the request ---*/ -{ - UNREFERENCED_PARAMETER(OutputBufferLength); - - //KdPrint(("MouseMirror: EvtIoDeviceControl (IoControlCode=0x%x, InputBufferLength=%Iu)\n", IoControlCode, InputBufferLength)); - - WDFDEVICE device = WdfIoQueueGetDevice(Queue); - - NTSTATUS status = STATUS_SUCCESS; //unhandled - switch (IoControlCode) { - case IOCTL_HID_SET_FEATURE: // 0xb0191 - status = SetFeatureFilter(device, Request, InputBufferLength); - break; - } - // No NT_SUCCESS(status) check here since we don't want to fail blocked calls - - // Forward the request down the driver stack - WDF_REQUEST_SEND_OPTIONS options = {}; - WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); - - BOOLEAN ret = WdfRequestSend(Request, WdfDeviceGetIoTarget(device), &options); - if (ret == FALSE) { - status = WdfRequestGetStatus(Request); - KdPrint(("MouseMirror: WdfRequestSend failed with status: 0x%x\n", status)); - WdfRequestComplete(Request, status); - } -} diff --git a/MouseMirror/driver.h b/MouseMirror/driver.h index ddd3670..5b12c74 100644 --- a/MouseMirror/driver.h +++ b/MouseMirror/driver.h @@ -10,7 +10,6 @@ #include "device.h" #include "wmi.h" -#include "vfeature.h" /** Memory allocation tag name (for debugging leaks). */ diff --git a/MouseMirror/eventlog.cpp b/MouseMirror/eventlog.cpp deleted file mode 100644 index 5b166d5..0000000 --- a/MouseMirror/eventlog.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "eventlog.h" - - -constexpr USHORT IO_ERROR_LOG_PACKET_size() { - // TODO: Try stripping off the DumpData[1] member and padding at the end - // return offsetof(IO_ERROR_LOG_PACKET, DumpData); - return sizeof(IO_ERROR_LOG_PACKET); // -8; -} - - -void WriteToSystemLog(WDFDEVICE Device, NTSTATUS MessageId, WCHAR* InsertionStr1, WCHAR* InsertionStr2) { - // determine length of each insertion string - UCHAR InsertionStr1Len = 0; - if (InsertionStr1) - InsertionStr1Len = sizeof(WCHAR)*(UCHAR)(wcslen(InsertionStr1)+1); // in bytes (incl. null-termination) - UCHAR InsertionStr2Len = 0; - if (InsertionStr2) - InsertionStr2Len = sizeof(WCHAR)*(UCHAR)(wcslen(InsertionStr2)+1); // in bytes (incl. null-termination) - - - USHORT total_size = IO_ERROR_LOG_PACKET_size() + InsertionStr1Len + InsertionStr2Len; - if (total_size > ERROR_LOG_MAXIMUM_SIZE) { - // overflow check - KdPrint(("FireFly: IoAllocateErrorLogEntry too long message.\n")); - return; - } - - // Log an informational event with the caller name - DEVICE_OBJECT* dev_object = WdfDeviceWdmGetDeviceObject(Device); - auto* entry = (IO_ERROR_LOG_PACKET*)IoAllocateErrorLogEntry(dev_object, static_cast(total_size)); - if (!entry) { - KdPrint(("FireFly: IoAllocateErrorLogEntry allocation failure.\n")); - return; - } - - entry->MajorFunctionCode = 0; // (optional) - entry->RetryCount = 0; - entry->DumpDataSize = 0; - entry->NumberOfStrings = 0; - if (InsertionStr1Len) - entry->NumberOfStrings++; - if (InsertionStr2Len) - entry->NumberOfStrings++; - entry->StringOffset = IO_ERROR_LOG_PACKET_size(); // insertion string offsets - entry->EventCategory = 0; // TBD - entry->ErrorCode = MessageId; - entry->UniqueErrorValue = 0; // driver-specific code (optional) - entry->FinalStatus = 0; // user-space error code (optional) - entry->SequenceNumber = 0; // IRP sequence (optional) - entry->IoControlCode = 0; // (optional) - entry->DeviceOffset.QuadPart = 0; // offset in device where error occured (optional) - - BYTE* dest = (BYTE*)entry + entry->StringOffset; - if (InsertionStr1Len) { - RtlCopyMemory(/*dst*/dest, /*src*/InsertionStr1, InsertionStr1Len); - dest += InsertionStr1Len; - } - if (InsertionStr2Len) { - RtlCopyMemory(/*dst*/dest, /*src*/InsertionStr2, InsertionStr2Len); - dest += InsertionStr2Len; - } - - // Write to windows system log. - // The function will take over ownership of the object. - IoWriteErrorLogEntry(entry); -} diff --git a/MouseMirror/eventlog.h b/MouseMirror/eventlog.h deleted file mode 100644 index 7ef8463..0000000 --- a/MouseMirror/eventlog.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include -#include -#include "messages.h" // driver-specific MessageId values - - -/** Write to the Windows Event Viewer "System" log. - InsertionStr1 is a null-terminated string. */ -void WriteToSystemLog(WDFDEVICE Device, NTSTATUS MessageId, WCHAR* InsertionStr1, WCHAR* InsertionStr2); diff --git a/MouseMirror/messages.mc b/MouseMirror/messages.mc deleted file mode 100644 index 3f7a88b..0000000 --- a/MouseMirror/messages.mc +++ /dev/null @@ -1,23 +0,0 @@ -;#ifndef __MESSAGES_H__ -;#define __MESSAGES_H__ - -MessageIdTypedef=NTSTATUS - -SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS - Informational=0x1:STATUS_SEVERITY_INFORMATIONAL - Warning=0x2:STATUS_SEVERITY_WARNING - Error=0x3:STATUS_SEVERITY_ERROR - ) - -FacilityNames=(System=0x0 - RpcRuntime=0x2:FACILITY_RPC_RUNTIME - RpcStubs=0x3:FACILITY_RPC_STUBS - Io=0x4:FACILITY_IO_ERROR_CODE - ) - - -MessageId=0x0001 Facility=Io Severity=Error SymbolicName=MouseMirror_SAFETY -Language=English -Color (%2) exceeded safety threshold. Resetting color to (%3) to indicate failure. -. -;#endif // __MESSAGES_H__ diff --git a/MouseMirror/module.rc b/MouseMirror/module.rc index fd8b457..8bb539a 100644 --- a/MouseMirror/module.rc +++ b/MouseMirror/module.rc @@ -22,6 +22,4 @@ #include -#include "messages.rc" - MouseMirrorWMI MOFDATA MouseMirror.bmf diff --git a/MouseMirror/vfeature.cpp b/MouseMirror/vfeature.cpp deleted file mode 100644 index 2c7353a..0000000 --- a/MouseMirror/vfeature.cpp +++ /dev/null @@ -1,235 +0,0 @@ -#include "driver.h" -#include -#include -#include "eventlog.h" -#include "CppAllocator.hpp" - - -/** RAII wrapper of PHIDP_PREPARSED_DATA. */ -class PHIDP_PREPARSED_DATA_Wrap { -public: - PHIDP_PREPARSED_DATA_Wrap(size_t size) { - m_ptr = new BYTE[size]; - } - ~PHIDP_PREPARSED_DATA_Wrap() { - if (m_ptr) { - delete[] m_ptr; - m_ptr = nullptr; - } - } - - operator PHIDP_PREPARSED_DATA () const { - return (PHIDP_PREPARSED_DATA)m_ptr; - } - -private: - BYTE* m_ptr = nullptr; -}; - -/** RAII wrapper of WDFIOTARGET. */ -class WDFIOTARGET_Wrap { -public: - WDFIOTARGET_Wrap() { - } - ~WDFIOTARGET_Wrap() { - if (m_obj != NULL) { - WdfObjectDelete(m_obj); - } - } - - operator WDFIOTARGET () const { - return m_obj; - } - WDFIOTARGET* operator & () { - return &m_obj; - } - -private: - WDFIOTARGET m_obj = NULL; -}; - - -NTSTATUS SetFeatureColor ( - _In_ WDFDEVICE Device, - _In_ ULONG Color - ) -/*++ - This routine sets the HID feature by sending HID ioctls to our device. - These IOCTLs will be handled by HIDUSB and converted into USB requests - and send to the device. ---*/ -{ - KdPrint(("MouseMirror: SetFeatureColor\n")); - - WDFIOTARGET_Wrap hidTarget; - { - // open "hidTarget" using PdoName - NTSTATUS status = WdfIoTargetCreate(Device, WDF_NO_OBJECT_ATTRIBUTES, &hidTarget); - if (!NT_SUCCESS(status)) { - KdPrint(("MouseMirror: WdfIoTargetCreate failed 0x%x\n", status)); - return status; - } - - // open in write-only mode - DEVICE_CONTEXT* deviceContext = WdfObjectGet_DEVICE_CONTEXT(Device); - WDF_IO_TARGET_OPEN_PARAMS openParams = {}; - WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME(&openParams, &deviceContext->PdoName, FILE_WRITE_ACCESS); - - // We will let the framework to respond automatically to the pnp - // state changes of the target by closing and opening the handle. - openParams.ShareAccess = FILE_SHARE_WRITE | FILE_SHARE_READ; - - status = WdfIoTargetOpen(hidTarget, &openParams); - if (!NT_SUCCESS(status)) { - KdPrint(("MouseMirror: WdfIoTargetOpen failed 0x%x\n", status)); - return status; - } - } - - HID_COLLECTION_INFORMATION collectionInfo = {}; - { - // populate "collectionInformation" - WDF_MEMORY_DESCRIPTOR collectionInfoDesc = {}; - WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&collectionInfoDesc, &collectionInfo, sizeof(HID_COLLECTION_INFORMATION)); - - NTSTATUS status = WdfIoTargetSendIoctlSynchronously(hidTarget, - NULL, - IOCTL_HID_GET_COLLECTION_INFORMATION, - NULL, - &collectionInfoDesc, - NULL, - NULL); - - KdPrint(("MouseMirror: ProductID=%x, VendorID=%x, VersionNumber=%u, DescriptorSize=%u\n", collectionInfo.ProductID, collectionInfo.VendorID, collectionInfo.VersionNumber, collectionInfo.DescriptorSize)); - - if (!NT_SUCCESS(status)) { - KdPrint(("MouseMirror: WdfIoTargetSendIoctlSynchronously1 failed 0x%x\n", status)); - return status; - } - } - - PHIDP_PREPARSED_DATA_Wrap preparsedData(collectionInfo.DescriptorSize); - if (!preparsedData) { - return STATUS_INSUFFICIENT_RESOURCES; - } - - { - // populate "preparsedData" - WDF_MEMORY_DESCRIPTOR preparsedDataDesc = {}; - WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&preparsedDataDesc, static_cast(preparsedData), collectionInfo.DescriptorSize); - - NTSTATUS status = WdfIoTargetSendIoctlSynchronously(hidTarget, - NULL, - IOCTL_HID_GET_COLLECTION_DESCRIPTOR, // same as HidD_GetPreparsedData in user-mode - NULL, - &preparsedDataDesc, - NULL, - NULL); - - if (!NT_SUCCESS(status)) { - KdPrint(("MouseMirror: WdfIoTargetSendIoctlSynchronously2 failed 0x%x\n", status)); - return status; - } - } - - { - // get capabilities - HIDP_CAPS caps = {}; - NTSTATUS status = HidP_GetCaps(preparsedData, &caps); - if (!NT_SUCCESS(status)) { - return status; - } - - //KdPrint(("MouseMirror: Usage=%x, UsagePage=%x\n", caps.Usage, caps.UsagePage)); - - if (caps.FeatureReportByteLength != sizeof(MouseMirrorReport)) { - KdPrint(("MouseMirror: FeatureReportByteLength mismatch (%u, %Iu).\n", caps.FeatureReportByteLength, sizeof(MouseMirrorReport))); - return status; - } - } - - // Create a report to send to the device. - MouseMirrorReport report; - report.SetColor(Color); - - { - // send MouseMirrorReport to device - WDF_MEMORY_DESCRIPTOR reportDesc = {}; - WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&reportDesc, &report, sizeof(report)); - NTSTATUS status = WdfIoTargetSendIoctlSynchronously(hidTarget, - NULL, - IOCTL_HID_SET_FEATURE, // 0xb0191 - &reportDesc, - NULL, - NULL, - NULL); - if (!NT_SUCCESS(status)) { - KdPrint(("MouseMirror: WdfIoTargetSendIoctlSynchronously3 failed 0x%x\n", status)); - return status; - } - } - - return STATUS_SUCCESS; -} - - -NTSTATUS SetFeatureFilter( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request, - _In_ size_t InputBufferLength -) -/*++ -Routine Description: - Handles IOCTL_HID_SET_FEATURE for all the collection. - For control collection (custom defined collection) it handles - the user-defined control codes for sideband communication - -Arguments: - QueueContext - The object context associated with the queue - - Request - Pointer to Request Packet. ---*/ -{ - KdPrint(("MouseMirror: SetFeatureFilter\n")); - DEVICE_CONTEXT* deviceContext = WdfObjectGet_DEVICE_CONTEXT(Device); - - if (InputBufferLength != sizeof(MouseMirrorReport)) { - KdPrint(("MouseMirror: SetFeatureFilter: Incorrect InputBufferLength\n")); - return STATUS_BUFFER_TOO_SMALL; - } - - MouseMirrorReport* packet = nullptr; - NTSTATUS status = WdfRequestRetrieveInputBuffer(Request, sizeof(MouseMirrorReport), (void**)&packet, NULL); - if (!NT_SUCCESS(status) || !packet) { - KdPrint(("MouseMirror: WdfRequestRetrieveInputBuffer failed 0x%x, packet=0x%p\n", status, packet)); - return status; - } - - if (!packet->IsValid()) { - // If collection ID is not for control collection then handle - // this request just as you would for a regular collection. - return STATUS_INVALID_PARAMETER; - } - - // capture color before safety adjustments - UCHAR r = packet->Red; - UCHAR g = packet->Green; - UCHAR b = packet->Blue; - // Enforce safety limits (sets color to RED on failure) - if (!packet->SafetyCheck()) { - // log safety violation to Windows Event Viewer "System" log - WCHAR color_requested[16] = {}; - swprintf_s(color_requested, L"%u,%u,%u", r, g, b); - WCHAR color_adjusted[16] = {}; - swprintf_s(color_adjusted, L"%u,%u,%u", packet->Red, packet->Green, packet->Blue); - - WriteToSystemLog(Device, MouseMirror_SAFETY, color_requested, color_adjusted); - status = STATUS_CONTENT_BLOCKED; - } - - // update last written color - MouseMirrorDeviceInformation* pInfo = WdfObjectGet_MouseMirrorDeviceInformation(deviceContext->WmiInstance); - pInfo->MouseMirror = packet->GetColor(); - - return status; -} diff --git a/MouseMirror/vfeature.h b/MouseMirror/vfeature.h deleted file mode 100644 index 705250f..0000000 --- a/MouseMirror/vfeature.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include "MouseMirror.h" - - -NTSTATUS SetFeatureColor ( - _In_ WDFDEVICE Device, - _In_ ULONG Color - ); - -NTSTATUS SetFeatureFilter( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request, - _In_ size_t InputBufferLength -); diff --git a/MouseMirror/wmi.cpp b/MouseMirror/wmi.cpp index e145117..32fd94e 100644 --- a/MouseMirror/wmi.cpp +++ b/MouseMirror/wmi.cpp @@ -71,11 +71,8 @@ NTSTATUS EvtWmiInstanceSetInstance( MouseMirrorDeviceInformation* pInfo = WdfObjectGet_MouseMirrorDeviceInformation(WmiInstance); RtlCopyMemory(/*dst*/pInfo, /*src*/InBuffer, sizeof(*pInfo)); - // call SetFeatureColor to trigger tail-light update - NTSTATUS status = SetFeatureColor(WdfWmiInstanceGetDevice(WmiInstance), pInfo->MouseMirror); - KdPrint(("MouseMirror: WMI SetInstance completed\n")); - return status; + return STATUS_SUCCESS; } NTSTATUS EvtWmiInstanceSetItem( @@ -95,9 +92,6 @@ NTSTATUS EvtWmiInstanceSetItem( return STATUS_BUFFER_TOO_SMALL; pInfo->MouseMirror = *(ULONG*)InBuffer; - - // call SetFeatureColor to trigger tail-light update - status = SetFeatureColor(WdfWmiInstanceGetDevice(WmiInstance), pInfo->MouseMirror); } else { return STATUS_INVALID_DEVICE_REQUEST; } From 590d68db454e3b8abd8054fa2ddbce88521a896e Mon Sep 17 00:00:00 2001 From: Fredrik Orderud Date: Thu, 15 Feb 2024 09:34:11 +0100 Subject: [PATCH 06/10] Switch to a unique WMI class GUID. --- MouseMirror/MouseMirror.inx | Bin 6308 -> 6308 bytes MouseMirror/MouseMirror.mof | 2 +- MouseMirror/UNINSTALL_MouseMirror.bat | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MouseMirror/MouseMirror.inx b/MouseMirror/MouseMirror.inx index 790b42a9aa1dc088d822add4000249c008fd840a..280e0b25b396d10e2debb1c1ed9c3782cba51f45 100644 GIT binary patch delta 84 zcmZ2txWsV73SM_h26G@ZWiVlIWpH6IX3%9Y1ClNbZa|g^g9T8=707Y~s&Qhl1hQO# ZqE0}07a-4w!5OH+38>b1^LyT{TmWH{4fOy3 delta 84 zcmZ2txWsV73SM^u26F~W1`7rwAZ-97b%EFb$TtJBOc Date: Thu, 15 Feb 2024 09:36:24 +0100 Subject: [PATCH 07/10] Switch to "Mouse" driver class and run on top of "msmouse". --- MouseMirror/MouseMirror.inx | Bin 6308 -> 6326 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/MouseMirror/MouseMirror.inx b/MouseMirror/MouseMirror.inx index 280e0b25b396d10e2debb1c1ed9c3782cba51f45..212384cb99afe281545f2e312be7dfd598141f73 100644 GIT binary patch delta 224 zcmZ2txXo~b9V4eNLq0<(Loq|@WM4*UcN2yb24e;@hExViAeqLX3uGBH7%`XvS%yHE z4CL!FBmrfTfjnIX0|pBqHUO$f0?HTyS;j!pV)J^&k1V3OKx1=Z#xv+KWHRJ2q)pz) eCW~b0WwyCQsk3Jn-MoWch=~}*oBwhy=K}z*Rxo@3 delta 250 zcmdmHxWsUS9b>%*gC~OvgEK=8Ln1>l5b`o`A@ST9Lc#L34Al(g3?>YwKvjl7Rw9D| zgDzMkg~1reG6cdDuvij<8ABRFDp1S-2tn$S87zTh8c?q}P)#C3E!d6#h9ZW1hO*7u z86UF Date: Thu, 15 Feb 2024 09:40:41 +0100 Subject: [PATCH 08/10] Add WMI parameters for mouse movement mirroring. --- MouseMirror.ps1 | 17 +++++++++++++++++ MouseMirror/MouseMirror.mof | 7 +++++-- MouseMirror/wmi.cpp | 11 ++++++++--- 3 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 MouseMirror.ps1 diff --git a/MouseMirror.ps1 b/MouseMirror.ps1 new file mode 100644 index 0000000..7a0bf41 --- /dev/null +++ b/MouseMirror.ps1 @@ -0,0 +1,17 @@ +# Get IntelliMouse WMI object +# HW drivers reside in the "root\wmi" namespace (https://learn.microsoft.com/en-us/windows/win32/wmicoreprov/wdm-provider) +$mouse = Get-CimInstance -Namespace root\WMI -Class MouseMirrorDeviceInformation + +Write-Host("IntelliMouse device:") + +Write-Host(" InstanceName: {0}" -f $mouse.InstanceName) + +# check if mouse is active +Write-Host(" Active: {0}" -f $mouse.Active) + +Write-Host("Enabling mirroring of mouse movement...") +$mouse.FlipLeftRight = $true +$mouse.FlipUpDown = $true + +Write-Host("Storing changes...") +Set-CimInstance -CimInstance $mouse diff --git a/MouseMirror/MouseMirror.mof b/MouseMirror/MouseMirror.mof index 793ad73..d02a8b7 100644 --- a/MouseMirror/MouseMirror.mof +++ b/MouseMirror/MouseMirror.mof @@ -16,6 +16,9 @@ class MouseMirrorDeviceInformation { [read] boolean Active; - [WmiDataId(1), read, write, Description("Tail-light in RGB COLORREF format.")] - uint32 MouseMirror; + [WmiDataId(1), read, write, Description("Horizontal mirroring of mouse cursor movement")] + boolean FlipLeftRight; + + [WmiDataId(2), read, write, Description("Vertical mirroring of mouse cursor movement")] + boolean FlipUpDown; }; diff --git a/MouseMirror/wmi.cpp b/MouseMirror/wmi.cpp index 32fd94e..8eb22f5 100644 --- a/MouseMirror/wmi.cpp +++ b/MouseMirror/wmi.cpp @@ -87,11 +87,16 @@ NTSTATUS EvtWmiInstanceSetItem( MouseMirrorDeviceInformation* pInfo = WdfObjectGet_MouseMirrorDeviceInformation(WmiInstance); NTSTATUS status = STATUS_SUCCESS; - if (DataItemId == MouseMirrorDeviceInformation_MouseMirror_ID) { - if (InBufferSize < MouseMirrorDeviceInformation_MouseMirror_SIZE) + if (DataItemId == MouseMirrorDeviceInformation_FlipLeftRight_ID) { + if (InBufferSize < MouseMirrorDeviceInformation_FlipLeftRight_SIZE) return STATUS_BUFFER_TOO_SMALL; - pInfo->MouseMirror = *(ULONG*)InBuffer; + pInfo->FlipLeftRight = *(BOOLEAN*)InBuffer; + } else if (DataItemId == MouseMirrorDeviceInformation_FlipUpDown_ID) { + if (InBufferSize < MouseMirrorDeviceInformation_FlipUpDown_SIZE) + return STATUS_BUFFER_TOO_SMALL; + + pInfo->FlipUpDown = *(BOOLEAN*)InBuffer; } else { return STATUS_INVALID_DEVICE_REQUEST; } From a726e010af4fc56a22794d3a02516f7a5fcf7417 Mon Sep 17 00:00:00 2001 From: Fredrik Orderud Date: Thu, 15 Feb 2024 09:45:53 +0100 Subject: [PATCH 09/10] Implement filtering of mouse events to mirror mouse movement. --- MouseMirror/device.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++ MouseMirror/device.h | 2 + 2 files changed, 93 insertions(+) diff --git a/MouseMirror/device.cpp b/MouseMirror/device.cpp index bfccc3b..3f40cec 100644 --- a/MouseMirror/device.cpp +++ b/MouseMirror/device.cpp @@ -1,6 +1,8 @@ #include "driver.h" #include +EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL EvtIoDeviceControlInternalFilter; + NTSTATUS EvtDriverDeviceAdd(_In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit) /*++ @@ -78,6 +80,7 @@ Routine Description: //queueConfig.EvtIoRead // pass-through read requests //queueConfig.EvtIoWrite // pass-through write requests // queueConfig.EvtIoDeviceControl // pass-through IOCTL requests + queueConfig.EvtIoInternalDeviceControl = EvtIoDeviceControlInternalFilter; // filter internal IOCTLs WDFQUEUE queue = 0; // auto-deleted when parent is deleted NTSTATUS status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue); @@ -97,3 +100,91 @@ Routine Description: return status; } + +VOID MouFilter_ServiceCallback( + _In_ DEVICE_OBJECT* DeviceObject, + _In_ MOUSE_INPUT_DATA* InputDataStart, + _In_ MOUSE_INPUT_DATA* InputDataEnd, + _Inout_ ULONG* InputDataConsumed +) { + //KdPrint(("MouseMirror: MouFilter_ServiceCallback (packages=%u\n", InputDataEnd - InputDataStart)); + + WDFDEVICE device = WdfWdmDeviceGetWdfDeviceHandle(DeviceObject); + DEVICE_CONTEXT* deviceContext = WdfObjectGet_DEVICE_CONTEXT(device); + MouseMirrorDeviceInformation* pInfo = WdfObjectGet_MouseMirrorDeviceInformation(deviceContext->WmiInstance); + + // mirror mouse events in queue + for (MOUSE_INPUT_DATA* id = InputDataStart; id != InputDataEnd; ++id) { + if (pInfo->FlipLeftRight) + id->LastX = -InputDataStart->LastX; + + if (pInfo->FlipUpDown) + id->LastY = -InputDataStart->LastY; + } + + // UpperConnectData must be called at DISPATCH + (*(PSERVICE_CALLBACK_ROUTINE)deviceContext->UpperConnectData.ClassService) + (deviceContext->UpperConnectData.ClassDeviceObject, InputDataStart, InputDataEnd, InputDataConsumed); +} + +VOID EvtIoDeviceControlInternalFilter( + _In_ WDFQUEUE Queue, + _In_ WDFREQUEST Request, + _In_ size_t OutputBufferLength, + _In_ size_t InputBufferLength, + _In_ ULONG IoControlCode +) { + UNREFERENCED_PARAMETER(OutputBufferLength); + UNREFERENCED_PARAMETER(InputBufferLength); + + //KdPrint(("MouseMirror: EvtIoDeviceControlInternal (IoControlCode=0x%x, InputBufferLength=%Iu)\n", IoControlCode, InputBufferLength)); + + WDFDEVICE device = WdfIoQueueGetDevice(Queue); + DEVICE_CONTEXT* deviceContext = WdfObjectGet_DEVICE_CONTEXT(device); + + NTSTATUS status = STATUS_SUCCESS; //unhandled + switch (IoControlCode) { + case IOCTL_INTERNAL_MOUSE_CONNECT: + { + KdPrint(("MouseMirror: IOCTL_INTERNAL_MOUSE_CONNECT\n")); + + // Only allow one connection + if (deviceContext->UpperConnectData.ClassService != NULL) { + status = STATUS_SHARING_VIOLATION; + break; + } + + CONNECT_DATA* connectData = nullptr; + size_t length = 0; + status = WdfRequestRetrieveInputBuffer(Request, sizeof(CONNECT_DATA), (void**)&connectData, &length); + if (!NT_SUCCESS(status)) { + KdPrint(("MouseMirror: WdfRequestRetrieveInputBuffer failed %x\n", status)); + break; + } + + // Copy the connection parameters to the device context. + deviceContext->UpperConnectData = *connectData; + + // attach to the report chain to intercept mouse packets + connectData->ClassDeviceObject = WdfDeviceWdmGetDeviceObject(device); + connectData->ClassService = MouFilter_ServiceCallback; + } + break; + + case IOCTL_INTERNAL_MOUSE_DISCONNECT: + status = STATUS_NOT_IMPLEMENTED; // according to https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/kbdmou/ni-kbdmou-ioctl_internal_mouse_disconnect + break; + } + // No NT_SUCCESS(status) check here since we don't want to fail blocked calls + + // Forward the request down the driver stack + WDF_REQUEST_SEND_OPTIONS options = {}; + WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); + + BOOLEAN ret = WdfRequestSend(Request, WdfDeviceGetIoTarget(device), &options); + if (ret == FALSE) { + status = WdfRequestGetStatus(Request); + KdPrint(("MouseMirror: WdfRequestSend failed with status: 0x%x\n", status)); + WdfRequestComplete(Request, status); + } +} diff --git a/MouseMirror/device.h b/MouseMirror/device.h index 20997cb..6a3b70e 100644 --- a/MouseMirror/device.h +++ b/MouseMirror/device.h @@ -1,9 +1,11 @@ #pragma once +#include /** Driver-specific struct for storing instance-specific data. */ typedef struct _DEVICE_CONTEXT { UNICODE_STRING PdoName; WDFWMIINSTANCE WmiInstance; + CONNECT_DATA UpperConnectData; // callback to intercept mouse packets } DEVICE_CONTEXT; WDF_DECLARE_CONTEXT_TYPE(DEVICE_CONTEXT) From bd1e47b6d717eff80eb97030be17acde35ea1f84 Mon Sep 17 00:00:00 2001 From: Fredrik Orderud Date: Thu, 15 Feb 2024 09:51:47 +0100 Subject: [PATCH 10/10] Update USB identifiers to the actual IntelliMouse "mouse" device Microsoft IntelliMouse is a composite device that exposes multiple interfaces, including the mouse and tail-light. This changes the driver to attach towards the mouse instead of the tail-light. --- MouseMirror/INSTALL_MouseMirror.bat | 4 ++-- MouseMirror/MouseMirror.inx | Bin 6326 -> 6326 bytes MouseMirror/UNINSTALL_MouseMirror.bat | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MouseMirror/INSTALL_MouseMirror.bat b/MouseMirror/INSTALL_MouseMirror.bat index 868c224..a961b15 100644 --- a/MouseMirror/INSTALL_MouseMirror.bat +++ b/MouseMirror/INSTALL_MouseMirror.bat @@ -3,10 +3,10 @@ cd /d "%~dp0" :: Use DevCon for installation, since it allows providing HWID -devcon /r install MouseMirror.inf "HID\VID_045E&PID_082A&MI_01&Col05" +devcon /r install MouseMirror.inf "HID\VID_045E&PID_082A&MI_00&Col01" :: Use PnpUtil for installation (succeeds but driver isn't loaded) -::devgen /add /bus ROOT /hardwareid "HID\VID_045E&PID_082A&MI_01&Col05" +::devgen /add /bus ROOT /hardwareid "HID\VID_045E&PID_082A&MI_00&Col01" ::PNPUTIL /add-driver MouseMirror.inf /install /reboot pause diff --git a/MouseMirror/MouseMirror.inx b/MouseMirror/MouseMirror.inx index 212384cb99afe281545f2e312be7dfd598141f73..52880a15f2cd720ee8bfea861b6eaba30ec0d09e 100644 GIT binary patch delta 26 hcmdmHxXo~b3>&WjgBpV~Lq0&W@gBpV~Lq0