Author: jimtabor Date: Thu Jan 28 02:00:09 2010 New Revision: 45293
URL: http://svn.reactos.org/svn/reactos?rev=45293&view=rev Log: [Win32k] - Add back removed window dce support routine. Fixed list handling and implemented thread cleanup for dces.
Modified: trunk/reactos/subsystems/win32/win32k/include/dce.h trunk/reactos/subsystems/win32/win32k/main/dllmain.c trunk/reactos/subsystems/win32/win32k/ntuser/painting.c trunk/reactos/subsystems/win32/win32k/ntuser/vis.c trunk/reactos/subsystems/win32/win32k/ntuser/windc.c trunk/reactos/subsystems/win32/win32k/ntuser/window.c
Modified: trunk/reactos/subsystems/win32/win32k/include/dce.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/dce.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/dce.h [iso-8859-1] Thu Jan 28 02:00:09 2010 @@ -61,5 +61,7 @@ VOID FASTCALL DceResetActiveDCEs(PWINDOW_OBJECT Window); void FASTCALL DceFreeClassDCE(HDC); HWND FASTCALL UserGethWnd(HDC,PWNDOBJ*); +void FASTCALL DceFreeWindowDCE(PWINDOW_OBJECT); +void FASTCALL DceFreeThreadDCE(PTHREADINFO);
#endif /* _WIN32K_DCE_H */
Modified: trunk/reactos/subsystems/win32/win32k/main/dllmain.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/mai... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/main/dllmain.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/main/dllmain.c [iso-8859-1] Thu Jan 28 02:00:09 2010 @@ -288,6 +288,7 @@ DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
Win32Thread->TIF_flags |= TIF_INCLEANUP; + DceFreeThreadDCE(Win32Thread); HOOK_DestroyThreadHooks(Thread); UnregisterThreadHotKeys(Thread); /* what if this co_ func crash in umode? what will clean us up then? */
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/painting.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/painting.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/painting.c [iso-8859-1] Thu Jan 28 02:00:09 2010 @@ -1111,8 +1111,6 @@ END_CLEANUP; }
- - static INT FASTCALL UserScrollDC(HDC hDC, INT dx, INT dy, const RECTL *prcScroll, @@ -1207,9 +1205,6 @@
return Result; } - - -
/* * NtUserScrollDC @@ -1217,10 +1212,15 @@ * Status * @implemented */ - BOOL APIENTRY -NtUserScrollDC(HDC hDC, INT dx, INT dy, const RECT *prcUnsafeScroll, - const RECT *prcUnsafeClip, HRGN hrgnUpdate, LPRECT prcUnsafeUpdate) +NtUserScrollDC( + HDC hDC, + INT dx, + INT dy, + const RECT *prcUnsafeScroll, + const RECT *prcUnsafeClip, + HRGN hrgnUpdate, + LPRECT prcUnsafeUpdate) { DECLARE_RETURN(DWORD); RECTL rcScroll, rcClip, rcUpdate; @@ -1258,10 +1258,13 @@ RETURN(FALSE); }
- Result = UserScrollDC(hDC, dx, dy, - prcUnsafeScroll? &rcScroll : 0, - prcUnsafeClip? &rcClip : 0, hrgnUpdate, - prcUnsafeUpdate? &rcUpdate : NULL); + Result = UserScrollDC( hDC, + dx, + dy, + prcUnsafeScroll? &rcScroll : 0, + prcUnsafeClip? &rcClip : 0, + hrgnUpdate, + prcUnsafeUpdate? &rcUpdate : NULL); if(Result == ERROR) { /* FIXME: Only if hRgnUpdate is invalid we should SetLastError(ERROR_INVALID_HANDLE) */ @@ -1303,8 +1306,15 @@ */
DWORD APIENTRY -NtUserScrollWindowEx(HWND hWnd, INT dx, INT dy, const RECT *prcUnsafeScroll, - const RECT *prcUnsafeClip, HRGN hrgnUpdate, LPRECT prcUnsafeUpdate, UINT flags) +NtUserScrollWindowEx( + HWND hWnd, + INT dx, + INT dy, + const RECT *prcUnsafeScroll, + const RECT *prcUnsafeClip, + HRGN hrgnUpdate, + LPRECT prcUnsafeUpdate, + UINT flags) { RECTL rcScroll, rcClip, rcCaret, rcUpdate; INT Result; @@ -1378,7 +1388,14 @@ rcCaret = rcScroll; hwndCaret = co_IntFixCaret(Window, &rcCaret, flags);
- Result = UserScrollDC(hDC, dx, dy, &rcScroll, &rcClip, hrgnOwn, prcUnsafeUpdate? &rcUpdate : NULL); + Result = UserScrollDC( hDC, + dx, + dy, + &rcScroll, + &rcClip, + hrgnOwn, + prcUnsafeUpdate? &rcUpdate : NULL); + UserReleaseDC(Window, hDC, FALSE);
/*
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/vis.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/vis.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/vis.c [iso-8859-1] Thu Jan 28 02:00:09 2010 @@ -47,6 +47,8 @@ return NULL; }
+ VisRgn = NULL; + if (ClientArea) { VisRgn = IntSysCreateRectRgnIndirect(&Window->Wnd->rcClient); @@ -71,13 +73,14 @@ CurrentWindow->state & WINDOWSTATUS_DESTROYED ) { DPRINT1("ATM the Current Window or Parent is dead!\n"); + if (VisRgn) REGION_FreeRgnByHandle(VisRgn); return NULL; }
CurrentWnd = CurrentWindow->Wnd; if (!CurrentWnd || !(CurrentWnd->style & WS_VISIBLE)) { - REGION_FreeRgnByHandle(VisRgn); + if (VisRgn) REGION_FreeRgnByHandle(VisRgn); return NULL; }
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/windc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/windc.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/windc.c [iso-8859-1] Thu Jan 28 02:00:09 2010 @@ -19,9 +19,10 @@ /* GLOBALS *******************************************************************/
/* NOTE - I think we should store this per window station (including gdi objects) */ - -static PDCE FirstDce = NULL; -//static INT DCECount = 0; // Count of DCE in system. +/* Answer: No, use the DCE pMonitor to compare with! */ + +static LIST_ENTRY LEDce; +static INT DCECount = 0; // Count of DCE in system.
#define DCX_CACHECOMPAREMASK (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | \ DCX_NORESETATTRS | DCX_LOCKWINDOWUPDATE | \ @@ -51,6 +52,7 @@ defaultDCstate->pdcattr = &defaultDCstate->dcattr; DC_vCopyState(dc, defaultDCstate, TRUE); DC_UnlockDc( dc ); + InitializeListHead(&LEDce); } return hDC; } @@ -90,7 +92,8 @@ ExFreePoolWithTag(pDce, TAG_PDCE); return NULL; } - + DCECount++; + DPRINT("Alloc DCE's! %d\n",DCECount); pDce->hwndCurrent = (Window ? Window->hSelf : NULL); pDce->pwndOrg = Wnd; pDce->pwndClip = Wnd; @@ -99,15 +102,7 @@ pDce->hrgnSavedVis = NULL; pDce->ppiOwner = NULL;
- KeEnterCriticalRegion(); - if (FirstDce == NULL) - { - FirstDce = pDce; - InitializeListHead(&FirstDce->List); - } - else - InsertTailList(&FirstDce->List, &pDce->List); - KeLeaveCriticalRegion(); + InsertTailList(&LEDce, &pDce->List);
DCU_SetDcUndeletable(pDce->hDC);
@@ -204,7 +199,6 @@ }
/* restore previous visible region */ - if ((dce->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) && ((dce->DCXFlags & DCX_CACHE) || EndPaint)) { @@ -213,30 +207,48 @@
if (dce->DCXFlags & DCX_CACHE) { - if (!(dce->DCXFlags & DCX_NORESETATTRS)) - { - /* make the DC clean so that SetDCState doesn't try to update the vis rgn */ - IntGdiSetHookFlags(dce->hDC, DCHF_VALIDATEVISRGN); - - // Clean the DC - if (!IntGdiCleanDC(dce->hDC)) return 0; - - if (dce->DCXFlags & DCX_DCEDIRTY) - { - /* don't keep around invalidated entries - * because SetDCState() disables hVisRgn updates - * by removing dirty bit. */ - dce->hwndCurrent = 0; - dce->DCXFlags &= DCX_CACHE; - dce->DCXFlags |= DCX_DCEEMPTY; - } - } - dce->DCXFlags &= ~DCX_DCEBUSY; - DPRINT("Exit!!!!! DCX_CACHE!!!!!! hDC-> %x \n", dce->hDC); - if (!IntGdiSetDCOwnerEx( dce->hDC, GDI_OBJ_HMGR_NONE, FALSE)) - return 0; - dce->ptiOwner = NULL; // Reset ownership. - dce->ppiOwner = NULL; + if (!(dce->DCXFlags & DCX_NORESETATTRS)) + { + /* make the DC clean so that SetDCState doesn't try to update the vis rgn */ + IntGdiSetHookFlags(dce->hDC, DCHF_VALIDATEVISRGN); + + // Clean the DC + if (!IntGdiCleanDC(dce->hDC)) return 0; + + if (dce->DCXFlags & DCX_DCEDIRTY) + { + /* don't keep around invalidated entries + * because SetDCState() disables hVisRgn updates + * by removing dirty bit. */ + dce->hwndCurrent = 0; + dce->DCXFlags &= DCX_CACHE; + dce->DCXFlags |= DCX_DCEEMPTY; + } + } + dce->DCXFlags &= ~DCX_DCEBUSY; + DPRINT("Exit!!!!! DCX_CACHE!!!!!! hDC-> %x \n", dce->hDC); + if (!IntGdiSetDCOwnerEx( dce->hDC, GDI_OBJ_HMGR_NONE, FALSE)) + return 0; + dce->ptiOwner = NULL; // Reset ownership. + dce->ppiOwner = NULL; + +#if 0 // Need to research and fix before this is a "growing" issue. + if (++DCECache > 32) + { + pLE = LEDce.Flink; + pDCE = CONTAINING_RECORD(pLE, DCE, List); + do + { + if (!(pDCE->DCXFlags & DCX_DCEBUSY)) + { /* Free the unused cache DCEs. */ + pDCE = DceFreeDCE(pDCE, TRUE); + if (!pDCE) break; + continue; + } + } + while (pLE != &LEDce ); + } +#endif } return 1; // Released! } @@ -335,6 +347,7 @@ PWND Wnd = NULL; HDC hDC = NULL; PPROCESSINFO ppi; + PLIST_ENTRY pLE;
if (NULL == Window) { @@ -445,7 +458,8 @@ DCE* DceEmpty = NULL; DCE* DceUnused = NULL; KeEnterCriticalRegion(); - Dce = FirstDce; + pLE = LEDce.Flink; + Dce = CONTAINING_RECORD(pLE, DCE, List); do { // The reason for this you may ask? @@ -471,8 +485,10 @@ break; } } - Dce = (PDCE)Dce->List.Flink; - } while (Dce != FirstDce); + pLE = Dce->List.Flink; + Dce = CONTAINING_RECORD(pLE, DCE, List); + } + while (pLE != &LEDce); KeLeaveCriticalRegion();
Dce = (DceEmpty == NULL) ? DceUnused : DceEmpty; @@ -488,14 +504,17 @@ else // If we are here, we are POWNED or having CLASS. { KeEnterCriticalRegion(); - Dce = FirstDce; + pLE = LEDce.Flink; + Dce = CONTAINING_RECORD(pLE, DCE, List); do { // Check for Window handle than HDC match for CLASS. if ((Dce->hwndCurrent == Window->hSelf) || (Dce->hDC == hDC)) break; - Dce = (PDCE)Dce->List.Flink; - } while (Dce != FirstDce); + pLE = Dce->List.Flink; + Dce = CONTAINING_RECORD(pLE, DCE, List); + } + while (pLE != &LEDce); KeLeaveCriticalRegion();
if ( (Flags & (DCX_INTERSECTRGN|DCX_EXCLUDERGN)) && @@ -526,11 +545,10 @@ http://www.reactos.org/archives/public/ros-dev/2008-July/010498.html http://www.reactos.org/archives/public/ros-dev/2008-July/010499.html */ - if ((Dce != FirstDce)) + if (pLE != &LEDce) { RemoveEntryList(&Dce->List); - InsertHeadList(&FirstDce->List, &Dce->List); - FirstDce = Dce; + InsertHeadList(&LEDce, &Dce->List); }
/* Introduced in rev 6691 and modified later. */ @@ -595,15 +613,13 @@ DceFreeDCE(PDCE pdce, BOOLEAN Force) { DCE *ret; + PLIST_ENTRY pLE; BOOL Hit = FALSE;
if (NULL == pdce) return NULL;
- ret = (PDCE) pdce->List.Flink; - -#if 0 /* FIXME */ - SetDCHook(pdce->hDC, NULL, 0L); -#endif + pLE = pdce->List.Flink; + ret = CONTAINING_RECORD(pLE, DCE, List);
if (Force && !GDIOBJ_OwnedByCurrentProcess(pdce->hDC)) { @@ -625,6 +641,7 @@ if (pdce->hrgnClip && ! (pdce->DCXFlags & DCX_KEEPCLIPRGN)) { REGION_FreeRgnByHandle(pdce->hrgnClip); + pdce->hrgnClip = NULL; }
RemoveEntryList(&pdce->List); @@ -632,47 +649,158 @@ if (IsListEmpty(&pdce->List)) { DPRINT1("List is Empty! DCE! -> %x\n" , pdce); - FirstDce = NULL; - ret = NULL; + return NULL; }
ExFreePoolWithTag(pdce, TAG_PDCE);
+ DCECount--; + DPRINT("Freed DCE's! %d \n", DCECount); + return ret; +} + +/*********************************************************************** + * DceFreeWindowDCE + * + * Remove owned DCE and reset unreleased cache DCEs. + */ +void FASTCALL +DceFreeWindowDCE(PWINDOW_OBJECT Window) +{ + PDCE pDCE; + PLIST_ENTRY pLE; + + if (DCECount <= 0) + { + DPRINT1("No Entry!\n"); + return; + } + + pLE = LEDce.Flink; + pDCE = CONTAINING_RECORD(pLE, DCE, List); + do + { + if (!pDCE) break; + if (IsListEmpty(&pDCE->List)) break; + if (pDCE->hwndCurrent == Window->hSelf) + { + if (!(pDCE->DCXFlags & DCX_CACHE)) /* owned or Class DCE*/ + { + if (Window->Wnd->pcls->style & CS_CLASSDC) /* Test Class first */ + { + if (pDCE->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) /* Class DCE*/ + DceDeleteClipRgn(pDCE); + // Update and reset Vis Rgn and clear the dirty bit. + // Should release VisRgn than reset it to default. + DceUpdateVisRgn(pDCE, Window, pDCE->DCXFlags); + pDCE->DCXFlags = DCX_DCEEMPTY|DCX_CACHE; + pDCE->hwndCurrent = 0; + + DPRINT("POWNED DCE going Cheap!! DCX_CACHE!! hDC-> %x \n", pDCE->hDC); + if (!IntGdiSetDCOwnerEx( pDCE->hDC, GDI_OBJ_HMGR_NONE, FALSE)) + return; + /* Do not change owner so thread can clean up! */ + } + else if (Window->Wnd->pcls->style & CS_OWNDC) /* owned DCE*/ + { + pDCE = DceFreeDCE(pDCE, FALSE); + if (!pDCE) break; + continue; + } + else + { + ASSERT(FALSE); + } + } + else + { + if (pDCE->DCXFlags & DCX_DCEBUSY) /* shared cache DCE */ + { + /* FIXME: AFAICS we are doing the right thing here so + * this should be a DPRINT. But this is best left as an ERR + * because the 'application error' is likely to come from + * another part of Wine (i.e. it's our fault after all). + * We should change this to DPRINT when ReactOS is more stable + * (for 1.0?). + */ + DPRINT1("[%p] GetDC() without ReleaseDC()!\n", Window->hSelf); + DceReleaseDC(pDCE, FALSE); + } + pDCE->DCXFlags |= DCX_DCEEMPTY; + pDCE->hwndCurrent = 0; + } + } + pLE = pDCE->List.Flink; + pDCE = CONTAINING_RECORD(pLE, DCE, List); + } + while (pLE != &LEDce); }
void FASTCALL DceFreeClassDCE(HDC hDC) { - PDCE pDCE = FirstDce; - KeEnterCriticalRegion(); + PDCE pDCE; + PLIST_ENTRY pLE; + pLE = LEDce.Flink; + pDCE = CONTAINING_RECORD(pLE, DCE, List); + do { if(!pDCE) break; if (pDCE->hDC == hDC) { - pDCE = DceFreeDCE(pDCE, FALSE); - if(!pDCE) break; + pDCE = DceFreeDCE(pDCE, TRUE); // Might have gone cheap! + if (!pDCE) break; continue; } - pDCE = (PDCE)pDCE->List.Flink; - } while (pDCE != FirstDce); - KeLeaveCriticalRegion(); + pLE = pDCE->List.Flink; + pDCE = CONTAINING_RECORD(pLE, DCE, List); + } + while (pLE != &LEDce); +} + +void FASTCALL +DceFreeThreadDCE(PTHREADINFO pti) +{ + PDCE pDCE; + PLIST_ENTRY pLE; + pLE = LEDce.Flink; + pDCE = CONTAINING_RECORD(pLE, DCE, List); + + do + { + if(!pDCE) break; + if (pDCE->ptiOwner == pti) + { + if (pDCE->DCXFlags & DCX_CACHE) + { + pDCE = DceFreeDCE(pDCE, TRUE); + if (!pDCE) break; + continue; + } + } + pLE = pDCE->List.Flink; + pDCE = CONTAINING_RECORD(pLE, DCE, List); + } + while (pLE != &LEDce); }
VOID FASTCALL DceEmptyCache(VOID) { - PDCE pDCE = FirstDce; - KeEnterCriticalRegion(); + PDCE pDCE; + PLIST_ENTRY pLE; + pLE = LEDce.Flink; + pDCE = CONTAINING_RECORD(pLE, DCE, List); + do { if(!pDCE) break; pDCE = DceFreeDCE(pDCE, TRUE); if(!pDCE) break; - } while (pDCE != FirstDce); - KeLeaveCriticalRegion(); - FirstDce = NULL; + } + while (pLE != &LEDce); }
VOID FASTCALL @@ -683,16 +811,19 @@ PWINDOW_OBJECT CurrentWindow; INT DeltaX; INT DeltaY; + PLIST_ENTRY pLE;
if (NULL == Window) { return; } - pDCE = FirstDce; + pLE = LEDce.Flink; + pDCE = CONTAINING_RECORD(pLE, DCE, List); if(!pDCE) return; // Another null test! do { if(!pDCE) break; + if(pLE == &LEDce) break; if (0 == (pDCE->DCXFlags & DCX_DCEEMPTY)) { if (Window->hSelf == pDCE->hwndCurrent) @@ -704,7 +835,8 @@ CurrentWindow = UserGetWindowObject(pDCE->hwndCurrent); if (NULL == CurrentWindow) { - pDCE = (PDCE) pDCE->List.Flink; + pLE = pDCE->List.Flink; + pDCE = CONTAINING_RECORD(pLE, DCE, List); continue; } } @@ -712,7 +844,8 @@ if (!GDIOBJ_ValidateHandle(pDCE->hDC, GDI_OBJECT_TYPE_DC) || (dc = DC_LockDc(pDCE->hDC)) == NULL) { - pDCE = (PDCE) pDCE->List.Flink; + pLE = pDCE->List.Flink; + pDCE = CONTAINING_RECORD(pLE, DCE, List); continue; } if (Window == CurrentWindow || IntIsChildWindow(Window, CurrentWindow)) @@ -751,17 +884,21 @@ // UserDerefObject(CurrentWindow); } } - pDCE =(PDCE) pDCE->List.Flink; - } while (pDCE != FirstDce); + pLE = pDCE->List.Flink; + pDCE = CONTAINING_RECORD(pLE, DCE, List); + } + while (pLE != &LEDce); }
HWND FASTCALL IntWindowFromDC(HDC hDc) { DCE *Dce; + PLIST_ENTRY pLE; HWND Ret = NULL; - KeEnterCriticalRegion(); - Dce = FirstDce; + + pLE = LEDce.Flink; + Dce = CONTAINING_RECORD(pLE, DCE, List); do { if(Dce->hDC == hDc) @@ -769,9 +906,10 @@ Ret = Dce->hwndCurrent; break; } - Dce = (PDCE)Dce->List.Flink; - } while (Dce != FirstDce); - KeLeaveCriticalRegion(); + pLE = Dce->List.Flink; + Dce = CONTAINING_RECORD(pLE, DCE, List); + } + while (pLE != &LEDce); return Ret; }
@@ -779,12 +917,13 @@ UserReleaseDC(PWINDOW_OBJECT Window, HDC hDc, BOOL EndPaint) { PDCE dce; + PLIST_ENTRY pLE; INT nRet = 0; BOOL Hit = FALSE;
DPRINT("%p %p\n", Window, hDc); - dce = FirstDce; - KeEnterCriticalRegion(); + pLE = LEDce.Flink; + dce = CONTAINING_RECORD(pLE, DCE, List); do { if(!dce) break; @@ -793,11 +932,10 @@ Hit = TRUE; break; } - - dce = (PDCE) dce->List.Flink; - } - while (dce != FirstDce ); - KeLeaveCriticalRegion(); + pLE = dce->List.Flink; + dce = CONTAINING_RECORD(pLE, DCE, List); + } + while (pLE != &LEDce );
if ( Hit && (dce->DCXFlags & DCX_DCEBUSY)) {
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/window.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/window.c [iso-8859-1] Thu Jan 28 02:00:09 2010 @@ -478,6 +478,7 @@ Window->SystemMenu = (HMENU)0; }
+ DceFreeWindowDCE(Window); /* Always do this to catch orphaned DCs */ #if 0 /* FIXME */
WINPROC_FreeProc(Window->winproc, WIN_PROC_WINDOW);