mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:03:00 +00:00
[WIN32K]
- Do not make callouts to user-mode while holding a lock on GDI objects. Fixes crashes in user32_winetest:win and :msg svn path=/trunk/; revision=64189
This commit is contained in:
parent
559bf96394
commit
631f96a8a3
1 changed files with 92 additions and 47 deletions
|
@ -1230,14 +1230,13 @@ co_UserGetUpdateRgn(PWND Window, PREGION Rgn, BOOL bErase)
|
||||||
REGION_SetRectRgn(Rgn, Rect.left, Rect.top, Rect.right, Rect.bottom);
|
REGION_SetRectRgn(Rgn, Rect.left, Rect.top, Rect.right, Rect.bottom);
|
||||||
RegionType = IntGdiCombineRgn(Rgn, Rgn, UpdateRgn, RGN_AND);
|
RegionType = IntGdiCombineRgn(Rgn, Rgn, UpdateRgn, RGN_AND);
|
||||||
IntGdiOffsetRgn(Rgn, -Window->rcClient.left, -Window->rcClient.top);
|
IntGdiOffsetRgn(Rgn, -Window->rcClient.left, -Window->rcClient.top);
|
||||||
|
RGNOBJAPI_Unlock(UpdateRgn);
|
||||||
|
|
||||||
if (bErase && RegionType != NULLREGION && RegionType != ERROR)
|
if (bErase && RegionType != NULLREGION && RegionType != ERROR)
|
||||||
{
|
{
|
||||||
co_UserRedrawWindow(Window, NULL, NULL, RDW_ERASENOW | RDW_NOCHILDREN);
|
co_UserRedrawWindow(Window, NULL, NULL, RDW_ERASENOW | RDW_NOCHILDREN);
|
||||||
}
|
}
|
||||||
|
|
||||||
RGNOBJAPI_Unlock(UpdateRgn);
|
|
||||||
|
|
||||||
return RegionType;
|
return RegionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1265,7 +1264,8 @@ NtUserGetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase)
|
||||||
RETURN(ERROR);
|
RETURN(ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rgn = RGNOBJAPI_Lock(hRgn, NULL);
|
/* Use a system region, we can't hold GDI locks when doing roundtrips to user mode */
|
||||||
|
Rgn = IntSysCreateRectpRgn(0, 0, 0, 0);
|
||||||
if (!Rgn)
|
if (!Rgn)
|
||||||
RETURN(ERROR);
|
RETURN(ERROR);
|
||||||
|
|
||||||
|
@ -1276,8 +1276,21 @@ NtUserGetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase)
|
||||||
RETURN(ret);
|
RETURN(ret);
|
||||||
|
|
||||||
CLEANUP:
|
CLEANUP:
|
||||||
|
if (Rgn && (_ret_ != ERROR))
|
||||||
|
{
|
||||||
|
PREGION TheRgn = RGNOBJAPI_Lock(hRgn, NULL);
|
||||||
|
if (!TheRgn)
|
||||||
|
{
|
||||||
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
||||||
|
_ret_ = ERROR;
|
||||||
|
}
|
||||||
|
IntGdiCombineRgn(TheRgn, Rgn, NULL, RGN_COPY);
|
||||||
|
RGNOBJAPI_Unlock(TheRgn);
|
||||||
|
}
|
||||||
|
|
||||||
if (Rgn)
|
if (Rgn)
|
||||||
RGNOBJAPI_Unlock(Rgn);
|
REGION_Delete(Rgn);
|
||||||
|
|
||||||
TRACE("Leave NtUserGetUpdateRgn, ret=%i\n",_ret_);
|
TRACE("Leave NtUserGetUpdateRgn, ret=%i\n",_ret_);
|
||||||
UserLeave();
|
UserLeave();
|
||||||
END_CLEANUP;
|
END_CLEANUP;
|
||||||
|
@ -1427,14 +1440,27 @@ NtUserRedrawWindow(
|
||||||
RETURN( FALSE);
|
RETURN( FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We can't hold lock on GDI obects while doing roundtrips to user mode,
|
||||||
|
* so use a copy instead */
|
||||||
if (hrgnUpdate)
|
if (hrgnUpdate)
|
||||||
{
|
{
|
||||||
RgnUpdate = RGNOBJAPI_Lock(hrgnUpdate, NULL);
|
PREGION RgnTemp;
|
||||||
|
|
||||||
|
RgnUpdate = IntSysCreateRectpRgn(0, 0, 0, 0);
|
||||||
if (!RgnUpdate)
|
if (!RgnUpdate)
|
||||||
|
{
|
||||||
|
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
RgnTemp = RGNOBJAPI_Lock(hrgnUpdate, NULL);
|
||||||
|
if (!RgnTemp)
|
||||||
{
|
{
|
||||||
EngSetLastError(ERROR_INVALID_HANDLE);
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
||||||
RETURN(FALSE);
|
RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
IntGdiCombineRgn(RgnUpdate, RgnTemp, NULL, RGN_COPY);
|
||||||
|
RGNOBJAPI_Unlock(RgnTemp);
|
||||||
}
|
}
|
||||||
|
|
||||||
UserRefObjectCo(Wnd, &Ref);
|
UserRefObjectCo(Wnd, &Ref);
|
||||||
|
@ -1450,7 +1476,7 @@ NtUserRedrawWindow(
|
||||||
|
|
||||||
CLEANUP:
|
CLEANUP:
|
||||||
if (RgnUpdate)
|
if (RgnUpdate)
|
||||||
RGNOBJAPI_Unlock(RgnUpdate);
|
REGION_Delete(RgnUpdate);
|
||||||
TRACE("Leave NtUserRedrawWindow, ret=%i\n",_ret_);
|
TRACE("Leave NtUserRedrawWindow, ret=%i\n",_ret_);
|
||||||
UserLeave();
|
UserLeave();
|
||||||
END_CLEANUP;
|
END_CLEANUP;
|
||||||
|
@ -1687,11 +1713,10 @@ NtUserScrollWindowEx(
|
||||||
INT Result;
|
INT Result;
|
||||||
PWND Window = NULL, CaretWnd;
|
PWND Window = NULL, CaretWnd;
|
||||||
HDC hDC;
|
HDC hDC;
|
||||||
PREGION RgnOwn = NULL, RgnTemp, RgnWinupd = NULL;
|
PREGION RgnUpdate = NULL, RgnTemp, RgnWinupd = NULL;
|
||||||
HWND hwndCaret;
|
HWND hwndCaret;
|
||||||
DWORD dcxflags = 0;
|
DWORD dcxflags = 0;
|
||||||
int rdw_flags;
|
int rdw_flags;
|
||||||
BOOL bOwnRgn = TRUE;
|
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
DECLARE_RETURN(DWORD);
|
DECLARE_RETURN(DWORD);
|
||||||
USER_REFERENCE_ENTRY Ref, CaretRef;
|
USER_REFERENCE_ENTRY Ref, CaretRef;
|
||||||
|
@ -1743,17 +1768,26 @@ NtUserScrollWindowEx(
|
||||||
RETURN(NULLREGION);
|
RETURN(NULLREGION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We must use a copy of the region, as we can't hold an exclusive lock
|
||||||
|
* on it while doing callouts to user-mode */
|
||||||
|
RgnUpdate = IntSysCreateRectpRgn(0, 0, 0, 0);
|
||||||
|
if(!RgnUpdate)
|
||||||
|
{
|
||||||
|
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
RETURN(ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
if (hrgnUpdate)
|
if (hrgnUpdate)
|
||||||
{
|
{
|
||||||
RgnOwn = RGNOBJAPI_Lock(hrgnUpdate, NULL);
|
RgnTemp = RGNOBJAPI_Lock(hrgnUpdate, NULL);
|
||||||
if (!RgnOwn)
|
if (!RgnTemp)
|
||||||
{
|
{
|
||||||
RETURN(ERROR);
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
||||||
}
|
RETURN(ERROR);
|
||||||
bOwnRgn = FALSE;
|
}
|
||||||
|
IntGdiCombineRgn(RgnUpdate, RgnTemp, NULL, RGN_COPY);
|
||||||
|
RGNOBJAPI_Unlock(RgnTemp);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
RgnOwn = IntSysCreateRectpRgn(0, 0, 0, 0);
|
|
||||||
|
|
||||||
/* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
|
/* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
|
||||||
if (flags & SW_SCROLLWNDDCE)
|
if (flags & SW_SCROLLWNDDCE)
|
||||||
|
@ -1788,9 +1822,9 @@ NtUserScrollWindowEx(
|
||||||
Result = UserScrollDC( hDC,
|
Result = UserScrollDC( hDC,
|
||||||
dx,
|
dx,
|
||||||
dy,
|
dy,
|
||||||
&rcScroll,
|
&rcScroll,
|
||||||
&rcClip,
|
&rcClip,
|
||||||
RgnOwn,
|
RgnUpdate,
|
||||||
prcUnsafeUpdate? &rcUpdate : NULL);
|
prcUnsafeUpdate? &rcUpdate : NULL);
|
||||||
|
|
||||||
UserReleaseDC(Window, hDC, FALSE);
|
UserReleaseDC(Window, hDC, FALSE);
|
||||||
|
@ -1801,29 +1835,32 @@ NtUserScrollWindowEx(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
RgnTemp = IntSysCreateRectpRgn(0, 0, 0, 0);
|
RgnTemp = IntSysCreateRectpRgn(0, 0, 0, 0);
|
||||||
if (RgnTemp)
|
if (!RgnTemp)
|
||||||
{
|
{
|
||||||
if (co_UserGetUpdateRgn(Window, RgnTemp, FALSE) != NULLREGION)
|
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
{
|
RETURN(ERROR);
|
||||||
PREGION RgnClip = IntSysCreateRectpRgnIndirect(&rcClip);
|
|
||||||
if (RgnClip)
|
|
||||||
{
|
|
||||||
if (!bOwnRgn)
|
|
||||||
{
|
|
||||||
RgnWinupd = IntSysCreateRectpRgn( 0, 0, 0, 0);
|
|
||||||
IntGdiCombineRgn( RgnWinupd, RgnTemp, 0, RGN_COPY);
|
|
||||||
}
|
|
||||||
IntGdiOffsetRgn(RgnTemp, dx, dy);
|
|
||||||
IntGdiCombineRgn(RgnTemp, RgnTemp, RgnClip, RGN_AND);
|
|
||||||
if (!bOwnRgn)
|
|
||||||
IntGdiCombineRgn( RgnWinupd, RgnWinupd, RgnTemp, RGN_OR );
|
|
||||||
co_UserRedrawWindow(Window, NULL, RgnTemp, rdw_flags );
|
|
||||||
REGION_Delete(RgnClip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
REGION_Delete(RgnTemp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (co_UserGetUpdateRgn(Window, RgnTemp, FALSE) != NULLREGION)
|
||||||
|
{
|
||||||
|
PREGION RgnClip = IntSysCreateRectpRgnIndirect(&rcClip);
|
||||||
|
if (RgnClip)
|
||||||
|
{
|
||||||
|
if (hrgnUpdate)
|
||||||
|
{
|
||||||
|
RgnWinupd = IntSysCreateRectpRgn( 0, 0, 0, 0);
|
||||||
|
IntGdiCombineRgn( RgnWinupd, RgnTemp, 0, RGN_COPY);
|
||||||
|
}
|
||||||
|
IntGdiOffsetRgn(RgnTemp, dx, dy);
|
||||||
|
IntGdiCombineRgn(RgnTemp, RgnTemp, RgnClip, RGN_AND);
|
||||||
|
if (hrgnUpdate)
|
||||||
|
IntGdiCombineRgn( RgnWinupd, RgnWinupd, RgnTemp, RGN_OR );
|
||||||
|
co_UserRedrawWindow(Window, NULL, RgnTemp, rdw_flags );
|
||||||
|
REGION_Delete(RgnClip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
REGION_Delete(RgnTemp);
|
||||||
|
|
||||||
if (flags & SW_SCROLLCHILDREN)
|
if (flags & SW_SCROLLCHILDREN)
|
||||||
{
|
{
|
||||||
PWND Child;
|
PWND Child;
|
||||||
|
@ -1854,7 +1891,7 @@ NtUserScrollWindowEx(
|
||||||
|
|
||||||
if (flags & (SW_INVALIDATE | SW_ERASE))
|
if (flags & (SW_INVALIDATE | SW_ERASE))
|
||||||
{
|
{
|
||||||
co_UserRedrawWindow(Window, NULL, RgnOwn, rdw_flags |
|
co_UserRedrawWindow(Window, NULL, RgnUpdate, rdw_flags |
|
||||||
((flags & SW_ERASE) ? RDW_ERASENOW : 0) |
|
((flags & SW_ERASE) ? RDW_ERASENOW : 0) |
|
||||||
((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0));
|
((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0));
|
||||||
}
|
}
|
||||||
|
@ -1893,19 +1930,27 @@ NtUserScrollWindowEx(
|
||||||
RETURN(Result);
|
RETURN(Result);
|
||||||
|
|
||||||
CLEANUP:
|
CLEANUP:
|
||||||
if (RgnWinupd && !bOwnRgn)
|
if (hrgnUpdate && (Result != ERROR))
|
||||||
{
|
{
|
||||||
IntGdiCombineRgn( RgnOwn, RgnOwn, RgnWinupd, RGN_OR);
|
/* Give everything back to the caller */
|
||||||
REGION_Delete(RgnWinupd);
|
RgnTemp = RGNOBJAPI_Lock(hrgnUpdate, NULL);
|
||||||
|
/* The handle should still be valid */
|
||||||
|
ASSERT(RgnTemp);
|
||||||
|
if (RgnWinupd)
|
||||||
|
IntGdiCombineRgn(RgnTemp, RgnUpdate, RgnWinupd, RGN_OR);
|
||||||
|
else
|
||||||
|
IntGdiCombineRgn(RgnTemp, RgnUpdate, NULL, RGN_COPY);
|
||||||
|
RGNOBJAPI_Unlock(RgnTemp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RgnOwn && !hrgnUpdate)
|
if (RgnWinupd)
|
||||||
{
|
{
|
||||||
REGION_Delete(RgnOwn);
|
REGION_Delete(RgnWinupd);
|
||||||
}
|
}
|
||||||
else if (RgnOwn)
|
|
||||||
|
if (RgnUpdate)
|
||||||
{
|
{
|
||||||
RGNOBJAPI_Unlock(RgnOwn);
|
REGION_Delete(RgnUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Window)
|
if (Window)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue