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

Check for the return value of native SetParent calls in Control class #2262

Merged
merged 11 commits into from
Dec 4, 2019

Conversation

chenxinyanc
Copy link
Contributor

@chenxinyanc chenxinyanc commented Nov 1, 2019

Fixes #2163

Proposed changes

  • Check for the return value and GetLastError in RecreateHandleCore and SetParentHandle methods.
  • Did not add the UT for this yet, because when Control.CreateHandle calls Application.ParkHandle, it does not specify the DPI awareness (DPI_AWARENESS_CONTEXT_UNSPECIFIED), so ParkHandle will choose a parking window for UNSPECIFIED awareness context. When constructing the parking window for UNSPECIFIED context, the DPI awareness of current thread will be used (e.g. PerMonitorV2). This will causes the subsequently parked window uses the very same DPI awareness setting, regardless of their owning thread's current DPI awareness at the point of control instance / handle construction.
    • I'm not sure whether it's by design or not, but perhaps we need to specify the DPI awareness explicitly when calling ParkHandle in CreateHandle method.
    • Nevertheless, I've tested the behavior with https://github.com/chenxinyanc/WinFormSetParentTest and it throws Win32Exception accordingly.

Customer Impact

Regression?

  • Yes / No

Risk

Screenshots

Before

After

Test methodology

Accessibility testing

Test environment(s)

Microsoft Reviewers: Open in CodeFlow

@chenxinyanc chenxinyanc requested a review from a team as a code owner November 1, 2019 11:48
@dnfclas
Copy link

dnfclas commented Nov 1, 2019

CLA assistant check
All CLA requirements met.

@codecov
Copy link

codecov bot commented Nov 1, 2019

Codecov Report

Merging #2262 into master will decrease coverage by 0.01755%.
The diff coverage is 40%.

@@                 Coverage Diff                 @@
##              master       #2262         +/-   ##
===================================================
- Coverage   29.45241%   29.43485%   -0.01756%     
===================================================
  Files           1005         945         -60     
  Lines         259629      266565       +6936     
  Branches       36855       37943       +1088     
===================================================
+ Hits           76467       78463       +1996     
- Misses        178224      182909       +4685     
- Partials        4938        5193        +255
Flag Coverage Δ
#Debug 29.43485% <40%> (-0.01756%) ⬇️
#production 29.43485% <40%> (-0.01756%) ⬇️
#test 100% <ø> (ø) ⬆️

Copy link
Member

@RussKie RussKie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You must sign CLA before we can accept the submission.
Few stylistic issues

src/System.Windows.Forms/src/Resources/SR.resx Outdated Show resolved Hide resolved
@@ -919,7 +919,10 @@ internal unsafe void InPlaceActivate(Ole32.OLEIVERB verb)
// If it doesn't, that means that the host
// won't reflect messages back to us.
HWNDParent = hwndParent;
User32.SetParent(new HandleRef(_control, _control.Handle), hwndParent);
if (User32.SetParent(new HandleRef(_control, _control.Handle), hwndParent) == IntPtr.Zero)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hughbe look like we overlooked an overload public static IntPtr SetParent(IHandle hWndChild, IHandle hWndChildNewParent)

@ghost ghost added the 📭 waiting-author-feedback The team requires more information from the author label Nov 4, 2019
@ghost ghost removed the 📭 waiting-author-feedback The team requires more information from the author label Nov 4, 2019
@chenxinyanc chenxinyanc force-pushed the xinyan-sp branch 2 times, most recently from 36db571 to aa97eb0 Compare November 6, 2019 06:57
@chenxinyanc
Copy link
Contributor Author

chenxinyanc commented Nov 6, 2019

The test seems to get stuck on CI pipeline for 57min… Weird.

RussKie
RussKie previously approved these changes Nov 8, 2019
@RussKie
Copy link
Member

RussKie commented Nov 8, 2019

@JeremyKuhne could you please review as well?

@RussKie RussKie requested a review from JeremyKuhne November 8, 2019 06:24
@@ -9969,14 +9994,22 @@ internal virtual void RecreateHandleCore()
}
finally
{
if (parentHandle.Handle != IntPtr.Zero // the parent was not null
&& (FromHandle(parentHandle.Handle) == null || _parent == null) // but wasnt a windows forms window
if (recreationSuccessful
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we're dependent on recreationSuccessful this try ... finally can move to wrap the block above that I suggested to move. It would look something like this:

// Do the main work of recreating the handle
DestroyHandle();
CreateHandle();
SetState(States.Recreate, false);

try
{
    // Inform children that their parent's handle has recreated.

    // ...
}
finally
{
    // If there is a parent window that isn't a WinForms window we need to reparent manually.
    // If the parent was a WinForms Control, CreateControl will have taken care of this.
    if (parentHandle.Handle != IntPtr.Zero

    //  ...

Copy link
Contributor Author

@chenxinyanc chenxinyanc Nov 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm moving re-parenting Win32 window part outside the finally block, as we should not expect to recover anything / keep anything consistent from ThreadAbortException in the main thread, and this can reduce 1 level of nesting try block.

However, I'm keeping the CreateHandle and DestroyHandle part inside try block, as we can still try our best to keep the states (States.Created, States.Recreate, Parent value of the controls in controlSnapshot) consistent when there is an Exception.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that there are no ThreadAbortException throws in Core. (@RussKie, not sure if you knew this.)

To simplify the code for these flags it would be worth looking at creating ref struct disposables that set and clear specified flags. Pattern dispose and the new syntax for using can help us reduce nesting and cognitive overload on some of our try .. finally blocks. (And it is efficient when using structs like this as there are no heap allocations.)

@RussKie RussKie added the 📭 waiting-author-feedback The team requires more information from the author label Nov 11, 2019
@ghost ghost removed the 📭 waiting-author-feedback The team requires more information from the author label Nov 11, 2019
@RussKie RussKie added the waiting-review This item is waiting on review by one or more members of team label Nov 11, 2019
RussKie
RussKie previously approved these changes Nov 14, 2019
JeremyKuhne
JeremyKuhne previously approved these changes Dec 3, 2019
Copy link
Member

@JeremyKuhne JeremyKuhne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@RussKie RussKie added 📭 waiting-author-feedback The team requires more information from the author and removed waiting-review This item is waiting on review by one or more members of team labels Dec 4, 2019
@chenxinyanc chenxinyanc dismissed stale reviews from JeremyKuhne and RussKie via 4ac0fed December 4, 2019 03:23
@ghost ghost removed the 📭 waiting-author-feedback The team requires more information from the author label Dec 4, 2019
@RussKie RussKie merged commit 4b4f8cf into dotnet:master Dec 4, 2019
@ghost ghost added this to the 5.0 milestone Dec 4, 2019
dreddy-work added a commit that referenced this pull request Apr 15, 2021
…ramework.

Without these changes, on PMv2 applications, We might be ending up with wrong
Dpiawareness than the requested for windows and some times, might endup failing to parent because
of inconsitance DpIcontexts.

#2262 addressed for catching the failure
but still applications may be still creating wrong DPIawareness windows.
dreddy-work added a commit that referenced this pull request May 21, 2021
* Seems this changes was missed from Day 1 and a regression from .NET framework.

Without these changes, on PMv2 applications, We might be ending up with wrong
Dpiawareness than the requested for windows and some times, might endup failing to parent because
of inconsitance DpIcontexts.

#2262 addressed for catching the failure
but still applications may be still creating wrong DPIawareness windows.
@RussKie
Copy link
Member

RussKie commented Nov 2, 2021

This change appears to have caused a regression reported in #6093

RussKie added a commit to RussKie/winforms that referenced this pull request Nov 3, 2021
…orm recreates handle

Fixes dotnet#6093

Fix the regression introduced in dotnet#2262.
RussKie added a commit to RussKie/winforms that referenced this pull request Nov 3, 2021
…orm recreates handle

Fixes dotnet#6093

Fix the regression introduced in dotnet#2262.
RussKie added a commit to RussKie/winforms that referenced this pull request Nov 3, 2021
…orm recreates handle

Fixes dotnet#6093

Fix the regression introduced in dotnet#2262.
RussKie added a commit to RussKie/winforms that referenced this pull request Nov 4, 2021
…orm recreates handle

Fixes dotnet#6093

Fix the regression introduced in dotnet#2262.
RussKie added a commit to RussKie/winforms that referenced this pull request Nov 4, 2021
…orm recreates handle

Fixes dotnet#6093

Fix the regression introduced in dotnet#2262, which added a check to the method
handling recreation of a control handle to verify that the control is
created before any child controls can be re-parented on to it.

However it was missed that DestroyHandle() method resets the state (i.e.
removes Created state), but CreateHandle() method doesn't set the state
back.
RussKie added a commit to RussKie/winforms that referenced this pull request Nov 4, 2021
…orm recreates handle

Fixes dotnet#6093

Fix the regression introduced in dotnet#2262, which added a check to the method
handling recreation of a control handle to verify that the control is
created before any child controls can be re-parented on to it.

However it was missed that DestroyHandle() method resets the state (i.e.
removes Created state), but CreateHandle() method doesn't set the state
back.
@ghost ghost locked as resolved and limited conversation to collaborators Feb 3, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

The return value of UnsafeNativeMethods.SetParent should be properly checked
6 participants