From 6c1875c84af2bad27e8bdbea6ebccccb980ea66e Mon Sep 17 00:00:00 2001 From: Michael Sleman Date: Sat, 4 Apr 2026 01:44:42 -0400 Subject: [PATCH] Fix StylusPointPropertyInfo crash from invalid HID min/max values Some touch digitizers (e.g. Surface Pro 9, Snapdragon ARM devices) report HID descriptors where Logical Maximum is less than Logical Minimum (commonly 0xFF interpreted as signed -1). The StylusPointPropertyInfo constructor throws an ArgumentException when maximum < minimum, crashing the application. Fix by swapping min/max when inverted at both call sites: - WM_POINTER stack: PointerStylusPointPropertyInfoHelper.CreatePropertyInfo - WISP stack: PenContext.InitStylusPointDescription Fixes #7069, #8435, #8826 --- .../PointerStylusPointPropertyInfoHelper.cs | 18 +++++++++++++++--- .../Windows/Input/Stylus/Wisp/PenContext.cs | 8 ++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Stylus/Pointer/PointerStylusPointPropertyInfoHelper.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Stylus/Pointer/PointerStylusPointPropertyInfoHelper.cs index 0790bef4187..edf75cc9079 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Stylus/Pointer/PointerStylusPointPropertyInfoHelper.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Stylus/Pointer/PointerStylusPointPropertyInfoHelper.cs @@ -64,6 +64,18 @@ internal static StylusPointPropertyInfo CreatePropertyInfo(UnsafeNativeMethods.P { StylusPointProperty stylusProp = new StylusPointProperty(propGuid, StylusPointPropertyIds.IsKnownButton(propGuid)); + int logicalMin = prop.logicalMin; + int logicalMax = prop.logicalMax; + + // Some touch digitizers report HID descriptors with invalid min/max values + // (e.g. Logical Minimum 0, Logical Maximum -1 from unsigned 0xFF interpreted + // as signed). Swap them so the StylusPointPropertyInfo constructor does not + // throw an ArgumentException. See dotnet/wpf#7069, #8435, and #8826. + if (logicalMax < logicalMin) + { + (logicalMin, logicalMax) = (logicalMax, logicalMin); + } + // Set Units StylusPointPropertyUnit? unit = StylusPointPropertyUnitHelper.FromPointerUnit(prop.unit); @@ -88,14 +100,14 @@ internal static StylusPointPropertyInfo CreatePropertyInfo(UnsafeNativeMethods.P // Calculated resolution is a scaling factor from logical units into the physical space // at the given exponentiation. resolution = - (prop.logicalMax - prop.logicalMin) / ((prop.physicalMax - prop.physicalMin) * exponent); + (logicalMax - logicalMin) / ((prop.physicalMax - prop.physicalMin) * exponent); } } result = new StylusPointPropertyInfo( stylusProp, - prop.logicalMin, - prop.logicalMax, + logicalMin, + logicalMax, unit.Value, resolution); } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Stylus/Wisp/PenContext.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Stylus/Wisp/PenContext.cs index e01cb4672f2..d319002efa1 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Stylus/Wisp/PenContext.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Stylus/Wisp/PenContext.cs @@ -115,6 +115,14 @@ private void InitStylusPointDescription() float res; _pimcContext.GetPacketPropertyInfo(i, out guid, out min, out max, out units, out res); // Calls Unmanaged code - SecurityCritical with SUC. + // Some touch digitizers report HID descriptors with min greater than max. + // Swap them so the StylusPointPropertyInfo constructor does not throw an + // ArgumentException. See dotnet/wpf#7069, #8435, and #8826. + if (max < min) + { + (min, max) = (max, min); + } + if (pressureIndex == -1 && guid == StylusPointPropertyIds.NormalPressure) { pressureIndex = i;