From ede832f809f2d26d2e1f46021ded028df54ade1c Mon Sep 17 00:00:00 2001 From: William Zujkowski Date: Sun, 5 Apr 2026 13:21:49 -0400 Subject: [PATCH] Fix DwmIsCompositionEnabled crash on Mono/wine-mono The P/Invoke for DwmIsCompositionEnabled used PreserveSig = false, which transforms the native signature from: HRESULT DwmIsCompositionEnabled(BOOL *pfEnabled) to: bool DwmIsCompositionEnabled(void) This works on .NET Framework/CoreCLR but crashes on Mono and wine-mono, which don't support PreserveSig = false for DllImports. The marshalling is skipped, so dwmapi receives a garbage pointer instead of a valid BOOL*, causing an access violation. Fix: change to PreserveSig = true with an explicit out parameter, matching the pattern already used by DwmGetColorizationColor in the same file. The public wrapper now checks the HRESULT before returning the value. This fixes WPF applications crashing on minimize/restore when running under Wine on Linux, which affects tools like EQLogParser. Fixes: #4166 --- .../System/Windows/Standard/NativeMethods.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Standard/NativeMethods.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Standard/NativeMethods.cs index 8497ff393db..30411317953 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Standard/NativeMethods.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Standard/NativeMethods.cs @@ -2506,9 +2506,8 @@ public static IntPtr CreateWindowEx( [DllImport("dwmapi.dll", EntryPoint = "DwmExtendFrameIntoClientArea", PreserveSig = true, SetLastError = true)] private static extern HRESULT _DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS pMarInset); - [DllImport("dwmapi.dll", EntryPoint = "DwmIsCompositionEnabled", PreserveSig = false)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool _DwmIsCompositionEnabled(); + [DllImport("dwmapi.dll", EntryPoint = "DwmIsCompositionEnabled", PreserveSig = true)] + private static extern HRESULT _DwmIsCompositionEnabled([Out, MarshalAs(UnmanagedType.Bool)] out bool pfEnabled); [DllImport("dwmapi.dll", EntryPoint = "DwmGetColorizationColor", PreserveSig = true)] private static extern HRESULT _DwmGetColorizationColor(out uint pcrColorization, [Out, MarshalAs(UnmanagedType.Bool)] out bool pfOpaqueBlend); @@ -2564,7 +2563,12 @@ public static bool DwmIsCompositionEnabled() { return false; } - return _DwmIsCompositionEnabled(); + + // Use PreserveSig = true with explicit out parameter to avoid + // marshalling issues on Mono/wine-mono, which does not support + // PreserveSig = false for DllImports. See dotnet/wpf#4166. + HRESULT hr = _DwmIsCompositionEnabled(out bool enabled); + return hr == HRESULT.S_OK && enabled; } [DllImport("dwmapi.dll")]