From 2bb75053c6577d9fb9288e53d9b3ba2f11ecf3c4 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sun, 18 Jan 2026 04:00:36 +0800 Subject: [PATCH] Fix device cleanup to run on device disable The cleanup callback was incorrectly registered on the driver object instead of the device object. This meant that when disabling the device in Device Manager, FrameworkArgbEvtDriverContextCleanup was never called (it only runs on driver unload, not device disable). Additionally, the driver cleanup was calling GetDeviceContext() on a WDFDRIVER object, which is incorrect - that function is for WDFDEVICE. Changes: - Add FrameworkArgbEvtDeviceCleanup callback for device-level cleanup - Register it on the device attributes in FrameworkArgbCreateDevice - Move EC handle cleanup from driver to device cleanup - Keep only WPP tracing cleanup in driver cleanup This fixes issues when disabling the device while Windows Dynamic Lighting is using it (timer keeps firing, reboot popup, etc). Co-Authored-By: Claude Opus 4.5 --- FrameworkArgb/Device.c | 37 +++++++++++++++++++++++++++++++++++++ FrameworkArgb/Device.h | 1 + FrameworkArgb/Driver.c | 15 +++++---------- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/FrameworkArgb/Device.c b/FrameworkArgb/Device.c index 3f24c0a..2943959 100644 --- a/FrameworkArgb/Device.c +++ b/FrameworkArgb/Device.c @@ -314,6 +314,7 @@ Return Value: WdfFdoInitSetFilter(DeviceInit); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); + deviceAttributes.EvtCleanupCallback = FrameworkArgbEvtDeviceCleanup; status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); @@ -735,3 +736,39 @@ Return Value: return status; } + +VOID +FrameworkArgbEvtDeviceCleanup( + _In_ WDFOBJECT DeviceObject +) +/*++ +Routine Description: + + Free all the resources allocated for the device. + Called when the device is removed or disabled. + +Arguments: + + DeviceObject - handle to a WDF Device object. + +Return Value: + + VOID. + +--*/ +{ + PDEVICE_CONTEXT DeviceContext; + + TraceInformation("%!FUNC! Entry"); + + DeviceContext = GetDeviceContext(DeviceObject); + + // Close handle to EC driver + if (DeviceContext && DeviceContext->CrosEcHandle && DeviceContext->CrosEcHandle != INVALID_HANDLE_VALUE) { + CloseHandle(DeviceContext->CrosEcHandle); + DeviceContext->CrosEcHandle = INVALID_HANDLE_VALUE; + TraceInformation("%!FUNC! Closed CrosEc Handle"); + } + + TraceInformation("%!FUNC! Exit"); +} diff --git a/FrameworkArgb/Device.h b/FrameworkArgb/Device.h index 302346c..d6fe159 100644 --- a/FrameworkArgb/Device.h +++ b/FrameworkArgb/Device.h @@ -27,6 +27,7 @@ typedef UCHAR HID_REPORT_DESCRIPTOR, * PHID_REPORT_DESCRIPTOR; DRIVER_INITIALIZE DriverEntry; EVT_WDF_DRIVER_DEVICE_ADD EvtDeviceAdd; EVT_WDF_TIMER EvtTimerFunc; +EVT_WDF_OBJECT_CONTEXT_CLEANUP FrameworkArgbEvtDeviceCleanup; #define MAX_LAMPARRAY_LAMP_COUNT 256 //#define LAMPARRAY_WIDTH 80000 // 80mm diff --git a/FrameworkArgb/Driver.c b/FrameworkArgb/Driver.c index b78e86b..60100dd 100644 --- a/FrameworkArgb/Driver.c +++ b/FrameworkArgb/Driver.c @@ -145,6 +145,8 @@ FrameworkArgbEvtDriverContextCleanup( Routine Description: Free all the resources allocated in DriverEntry. + Note: Device-specific cleanup (like EC handle) is done in + FrameworkArgbEvtDeviceCleanup, not here. Arguments: @@ -156,19 +158,10 @@ Return Value: --*/ { - PDEVICE_CONTEXT DeviceContext; + UNREFERENCED_PARAMETER(DriverObject); TraceInformation("%!FUNC! Entry"); - DeviceContext = GetDeviceContext(DriverObject); - // Close handle to EC driver - if (DeviceContext && DeviceContext->CrosEcHandle && DeviceContext->CrosEcHandle != INVALID_HANDLE_VALUE) { - CloseHandle(DeviceContext->CrosEcHandle); - DeviceContext->CrosEcHandle = INVALID_HANDLE_VALUE; - TraceError("%!FUNC! Failed to close CrosEc Handle"); - } - TraceInformation("%!FUNC! Closed CrosEc Handle"); - // // Stop WPP Tracing // @@ -177,4 +170,6 @@ Return Value: #else WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject)); #endif + + TraceInformation("%!FUNC! Exit"); }