Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent NULL HWND's from being parented under SystemResources listener windows #2100

Merged

Conversation

vatsan-madhavan
Copy link
Member

@vatsan-madhavan vatsan-madhavan commented Oct 23, 2019

Addresses #2089

When an HwndHost receives SourceChanged event, it goes through BuildOrReparentWindow. When the hosted window is invisible, it is usually reparented under a temporary windows maintained by WPF in the SystemResources class, until later on the window can be rebuilt and parented back to a valid parent.

There is a latent bug in this logic where in NULL HWND's are attempted to be parented to SystemResources managed temporary windows. This bug goes back quite a while (.NET 4.5 likely). WPF seems to ignore the return value from kernel32!SetParent and not deal with this failure. This has not been a crashing failure until now.

Starting .NET 4.8, there have been some changes to this codepath that has resulted in the current bug becoming a crash. In addition to calling kernel32!SetParent on a NULL HWND, WPF attempts to obtain a DPI-specific parking-window. This process of querying a DPI-specific parking window fails because WPF is unable to use the DPI_AWARENESS_CONTEXT value returned by the system for (HWND)nullptr.

The only necessary part of this fix is in HwndHost: WPF should not attempt to reparent the hosted window under a parking-window if the hosted window is (HWND)nullptr. This only requires a simple check : else if (_hwnd.Handle != IntPtr.Zero)). All other changes in SystemResources and HwndHost are defensive improvements.

SystemResources.EnsureResourceChangeListener(HwndDpiInfo) can attempt to create a parking-window corresponding to DPI_AWARENESS_CONTEXT_VALUE that is invalid/meaningless. This should not be allowed. A few additional checks are added to ensure this. Further, GetDpiAwarenessCompatibleNotificationWindow is augmented to be more defensive.

Also, variant of EnsureResourceChangeListener is dead code - it is being removed.

If for some unknown reason SystemResources.GetDpiAwarenessCompatibleNotificationWindow fails and returns null to HwndHost.BuildOrReparentWindow, WPF will fail to reparent the hosted window, and it will be 'lost'. This seems very unlikely - I have added a Trace to ensure that we can debug this situation if it does occur.

…uildOrReparentWindow`. When the hosted window is invisible, it is usually reparented under a temporary windows maintained by WPF in the `SystemResources `class, until later on the window can be rebuilt and parented back to a valid parent.

There is a latent bug in this logic where in `NULL ` `HWND's `are attempted to be parented to `SystemResources `managed temporary windows. This bug goes back quite a while (.NET 4.5 likely). WPF seems to ignore the return value from `kernel32!SetParent` and not deal with this failure. This has not been a crashing failure until now.

Starting .NET 4.8, there have been some changes to this codepath that has resulted in the current bug becoming a crash. In addition to calling `kernel32!SetParent` on a `NULL` `HWND`, WPF attempts to obtain a DPI-specific parking-window. This process of querying a DPI-specific parking window fails because WPF is unable to use the `DPI_AWARENESS_CONTEXT` value returned by the system for `(HWND)nullptr`.

The only necessary part of this fix is in `HwndHost`: WPF should not attempt to reparent the hosted window under a parking-window if the hosted window is `(HWND)nullptr`. This only requires a simple check : `else if (_hwnd.Handle != IntPtr.Zero)`). All other changes in `SystemResources` and `HwndHost` are defensive improvements.

`SystemResources.EnsureResourceChangeListener(HwndDpiInfo)` can attempt to create a parking-window corresponding to `DPI_AWARENESS_CONTEXT_VALUE` that is invalid/meaningless. This should not be allowed. A few additional checks are added to ensure this. Further, `GetDpiAwarenessCompatibleNotificationWindow` is augmented to be more defensive.

Also, variant of `EnsureResourceChangeListener`  is dead code - it is being removed.

If for some unknown reason `SystemResources.GetDpiAwarenessCompatibleNotificationWindow`  fails and returns `null` to `HwndHost.BuildOrReparentWindow`, WPF will fail to reparent the hosted window, and it will be 'lost'. This seems very unlikely - I have added a Trace to ensure that we can debug this situation if it does occur.
@ghost ghost requested a review from rladuca October 23, 2019 22:39
@ghost ghost added the PR metadata: Label to tag PRs, to facilitate with triage label Oct 23, 2019
@ghost ghost requested a review from SamBent October 23, 2019 22:39
@vatsan-madhavan vatsan-madhavan added this to the 5.0 milestone Oct 23, 2019
@vatsan-madhavan vatsan-madhavan self-assigned this Oct 23, 2019
@vatsan-madhavan vatsan-madhavan added issue-type-netfx-port Ports from .NET Framework Bug Product bug (most likely) labels Oct 23, 2019
@vatsan-madhavan vatsan-madhavan merged commit 3e5f11e into dotnet:master Oct 25, 2019
@vatsan-madhavan vatsan-madhavan deleted the systemresources-hwnd-fixup branch October 25, 2019 05:53
@ghost ghost locked as resolved and limited conversation to collaborators Apr 14, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug Product bug (most likely) issue-type-netfx-port Ports from .NET Framework PR metadata: Label to tag PRs, to facilitate with triage
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants