- Fix DCE list entry handling
CORE-8669 #resolve

svn path=/trunk/; revision=64868
This commit is contained in:
Thomas Faber 2014-10-21 14:28:16 +00:00
parent 268d1c62fe
commit 7b84cd051b
2 changed files with 67 additions and 129 deletions

View file

@ -44,7 +44,7 @@ typedef struct tagDCE
INIT_FUNCTION NTSTATUS NTAPI InitDCEImpl(VOID);
PDCE FASTCALL DceAllocDCE(PWND Window, DCE_TYPE Type);
HWND FASTCALL IntWindowFromDC(HDC hDc);
PDCE FASTCALL DceFreeDCE(PDCE dce, BOOLEAN Force);
void FASTCALL DceFreeDCE(PDCE dce, BOOLEAN Force);
void FASTCALL DceEmptyCache(void);
VOID FASTCALL DceResetActiveDCEs(PWND Window);
void FASTCALL DceFreeClassDCE(HDC);

View file

@ -51,15 +51,16 @@ DCE*
FASTCALL
DceGetDceFromDC(HDC hdc)
{
LIST_ENTRY* Entry = LEDce.Flink;
PLIST_ENTRY ListEntry;
DCE* dce;
while (Entry != &LEDce)
ListEntry = LEDce.Flink;
while (ListEntry != &LEDce)
{
dce = CONTAINING_RECORD(Entry, DCE, List);
dce = CONTAINING_RECORD(ListEntry, DCE, List);
ListEntry = ListEntry->Flink;
if (dce->hDC == hdc)
return dce;
Entry = Entry->Flink;
}
return NULL;
@ -247,7 +248,7 @@ noparent:
if (Dce->hrgnClip != NULL)
RgnClip = REGION_LockRgn(Dce->hrgnClip);
if (RgnClip)
{
IntGdiCombineRgn(RgnVisible, RgnVisible, RgnClip, RGN_AND);
@ -330,18 +331,16 @@ DceReleaseDC(DCE* dce, BOOL EndPaint)
#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
ListEntry = LEDce.Flink;
while (ListEntry != &LEDce)
{
pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
ListEntry = ListEntry->Flink;
if (!(pDCE->DCXFlags & DCX_DCEBUSY))
{ /* Free the unused cache DCEs. */
pDCE = DceFreeDCE(pDCE, TRUE);
if (!pDCE) break;
continue;
DceFreeDCE(pDCE, TRUE);
}
}
while (pLE != &LEDce );
}
#endif
}
@ -359,7 +358,7 @@ UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
BOOL bUpdateVisRgn = TRUE;
HDC hDC = NULL;
PPROCESSINFO ppi;
PLIST_ENTRY pLE;
PLIST_ENTRY ListEntry;
if (NULL == Wnd)
{
@ -463,15 +462,11 @@ UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
DCE* DceEmpty = NULL;
DCE* DceUnused = NULL;
KeEnterCriticalRegion();
pLE = LEDce.Flink;
Dce = CONTAINING_RECORD(pLE, DCE, List);
do
ListEntry = LEDce.Flink;
while (ListEntry != &LEDce)
{
// The reason for this you may ask?
// Well, it seems ReactOS calls GetDC without first creating a desktop DC window!
// Need to test for null here. Not sure if this is a bug or a feature.
// First time use hax, need to use DceAllocDCE during window display init.
if (!Dce) break;
Dce = CONTAINING_RECORD(ListEntry, DCE, List);
ListEntry = ListEntry->Flink;
//
// The way I understand this, you can have more than one DC per window.
// Only one Owned if one was requested and saved and one Cached.
@ -490,10 +485,7 @@ UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
break;
}
}
pLE = Dce->List.Flink;
Dce = CONTAINING_RECORD(pLE, DCE, List);
}
while (pLE != &LEDce);
KeLeaveCriticalRegion();
Dce = (DceEmpty == NULL) ? DceUnused : DceEmpty;
@ -510,20 +502,19 @@ UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
else // If we are here, we are POWNED or having CLASS.
{
KeEnterCriticalRegion();
pLE = LEDce.Flink;
Dce = CONTAINING_RECORD(pLE, DCE, List);
do
{ // Check for Window handle than HDC match for CLASS.
ListEntry = LEDce.Flink;
while (ListEntry != &LEDce)
{
Dce = CONTAINING_RECORD(ListEntry, DCE, List);
ListEntry = ListEntry->Flink;
// Check for Window handle than HDC match for CLASS.
if (Dce->hwndCurrent == Wnd->head.h)
{
bUpdateVisRgn = FALSE;
break;
}
if (Dce->hDC == hDC) break;
pLE = Dce->List.Flink;
Dce = CONTAINING_RECORD(pLE, DCE, List);
}
while (pLE != &LEDce);
KeLeaveCriticalRegion();
if ( (Flags & (DCX_INTERSECTRGN|DCX_EXCLUDERGN)) &&
@ -554,11 +545,8 @@ UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
* 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 (pLE != &LEDce)
{
RemoveEntryList(&Dce->List);
InsertHeadList(&LEDce, &Dce->List);
}
RemoveEntryList(&Dce->List);
InsertHeadList(&LEDce, &Dce->List);
/* Introduced in rev 6691 and modified later. */
if ( (Flags & DCX_INTERSECTUPDATE) && !ClipRegion )
@ -637,17 +625,13 @@ UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
/***********************************************************************
* DceFreeDCE
*/
PDCE FASTCALL
void FASTCALL
DceFreeDCE(PDCE pdce, BOOLEAN Force)
{
DCE *ret;
PLIST_ENTRY pLE;
BOOL Hit = FALSE;
if (NULL == pdce) return NULL;
pLE = pdce->List.Flink;
ret = CONTAINING_RECORD(pLE, DCE, List);
ASSERT(pdce != NULL);
if (NULL == pdce) return;
pdce->DCXFlags |= DCX_INDESTROY;
@ -683,18 +667,10 @@ DceFreeDCE(PDCE pdce, BOOLEAN Force)
RemoveEntryList(&pdce->List);
if (IsListEmpty(&pdce->List))
{
ERR("List is Empty! DCE! -> %p\n" , pdce);
return NULL;
}
ExFreePoolWithTag(pdce, USERTAG_DCE);
DCECount--;
TRACE("Freed DCE's! %d \n", DCECount);
return ret;
}
/***********************************************************************
@ -706,7 +682,7 @@ void FASTCALL
DceFreeWindowDCE(PWND Window)
{
PDCE pDCE;
PLIST_ENTRY pLE;
PLIST_ENTRY ListEntry;
if (DCECount <= 0)
{
@ -714,20 +690,11 @@ DceFreeWindowDCE(PWND Window)
return;
}
pLE = LEDce.Flink;
pDCE = CONTAINING_RECORD(pLE, DCE, List);
do
ListEntry = LEDce.Flink;
while (ListEntry != &LEDce)
{
if (!pDCE)
{
ERR("FreeWindowDCE No DCE Pointer!\n");
break;
}
if (IsListEmpty(&pDCE->List))
{
ERR("FreeWindowDCE List is Empty!!!!\n");
break;
}
pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
ListEntry = ListEntry->Flink;
if ( pDCE->hwndCurrent == Window->head.h &&
!(pDCE->DCXFlags & DCX_DCEEMPTY) )
{
@ -755,8 +722,7 @@ DceFreeWindowDCE(PWND Window)
}
else if (Window->pcls->style & CS_OWNDC) /* Owned DCE */
{
pDCE = DceFreeDCE(pDCE, FALSE);
if (!pDCE) break;
DceFreeDCE(pDCE, FALSE);
continue;
}
else
@ -785,76 +751,61 @@ DceFreeWindowDCE(PWND Window)
pDCE->pwndOrg = pDCE->pwndClip = NULL;
}
}
pLE = pDCE->List.Flink;
pDCE = CONTAINING_RECORD(pLE, DCE, List);
}
while (pLE != &LEDce);
}
void FASTCALL
DceFreeClassDCE(HDC hDC)
{
PDCE pDCE;
PLIST_ENTRY pLE;
pLE = LEDce.Flink;
pDCE = CONTAINING_RECORD(pLE, DCE, List);
PLIST_ENTRY ListEntry;
do
ListEntry = LEDce.Flink;
while (ListEntry != &LEDce)
{
if(!pDCE) break;
pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
ListEntry = ListEntry->Flink;
if (pDCE->hDC == hDC)
{
pDCE = DceFreeDCE(pDCE, TRUE); // Might have gone cheap!
if (!pDCE) break;
continue;
DceFreeDCE(pDCE, TRUE); // Might have gone cheap!
}
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);
PLIST_ENTRY ListEntry;
do
ListEntry = LEDce.Flink;
while (ListEntry != &LEDce)
{
if(!pDCE) break;
pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
ListEntry = ListEntry->Flink;
if (pDCE->ptiOwner == pti)
{
if (pDCE->DCXFlags & DCX_CACHE)
{
pDCE = DceFreeDCE(pDCE, TRUE);
if (!pDCE) break;
continue;
DceFreeDCE(pDCE, TRUE);
}
}
pLE = pDCE->List.Flink;
pDCE = CONTAINING_RECORD(pLE, DCE, List);
}
while (pLE != &LEDce);
}
VOID FASTCALL
DceEmptyCache(VOID)
{
PDCE pDCE;
PLIST_ENTRY pLE;
pLE = LEDce.Flink;
pDCE = CONTAINING_RECORD(pLE, DCE, List);
PLIST_ENTRY ListEntry;
do
ListEntry = LEDce.Flink;
while (ListEntry != &LEDce)
{
if(!pDCE) break;
pDCE = DceFreeDCE(pDCE, TRUE);
if(!pDCE) break;
pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
ListEntry = ListEntry->Flink;
DceFreeDCE(pDCE, TRUE);
}
while (pLE != &LEDce);
}
VOID FASTCALL
@ -865,19 +816,18 @@ DceResetActiveDCEs(PWND Window)
PWND CurrentWindow;
INT DeltaX;
INT DeltaY;
PLIST_ENTRY pLE;
PLIST_ENTRY ListEntry;
if (NULL == Window)
{
return;
}
pLE = LEDce.Flink;
pDCE = CONTAINING_RECORD(pLE, DCE, List);
do
ListEntry = LEDce.Flink;
while (ListEntry != &LEDce)
{
if(!pDCE) break;
if(pLE == &LEDce) break;
pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
ListEntry = ListEntry->Flink;
if (0 == (pDCE->DCXFlags & (DCX_DCEEMPTY|DCX_INDESTROY)))
{
if (Window->head.h == pDCE->hwndCurrent)
@ -892,8 +842,6 @@ DceResetActiveDCEs(PWND Window)
CurrentWindow = UserGetWindowObject(pDCE->hwndCurrent);
if (NULL == CurrentWindow)
{
pLE = pDCE->List.Flink;
pDCE = CONTAINING_RECORD(pLE, DCE, List);
continue;
}
}
@ -901,8 +849,6 @@ DceResetActiveDCEs(PWND Window)
if (!GreIsHandleValid(pDCE->hDC) ||
(dc = DC_LockDc(pDCE->hDC)) == NULL)
{
pLE = pDCE->List.Flink;
pDCE = CONTAINING_RECORD(pLE, DCE, List);
continue;
}
if (Window == CurrentWindow || IntIsChildWindow(Window, CurrentWindow))
@ -937,23 +883,21 @@ DceResetActiveDCEs(PWND Window)
DceUpdateVisRgn(pDCE, CurrentWindow, pDCE->DCXFlags);
IntGdiSetHookFlags(pDCE->hDC, DCHF_VALIDATEVISRGN);
}
pLE = pDCE->List.Flink;
pDCE = CONTAINING_RECORD(pLE, DCE, List);
}
while (pLE != &LEDce);
}
HWND FASTCALL
IntWindowFromDC(HDC hDc)
{
DCE *Dce;
PLIST_ENTRY pLE;
PLIST_ENTRY ListEntry;
HWND Ret = NULL;
pLE = LEDce.Flink;
Dce = CONTAINING_RECORD(pLE, DCE, List);
do
ListEntry = LEDce.Flink;
while (ListEntry != &LEDce)
{
Dce = CONTAINING_RECORD(ListEntry, DCE, List);
ListEntry = ListEntry->Flink;
if (Dce->hDC == hDc)
{
if (Dce->DCXFlags & DCX_INDESTROY)
@ -962,10 +906,7 @@ IntWindowFromDC(HDC hDc)
Ret = Dce->hwndCurrent;
break;
}
pLE = Dce->List.Flink;
Dce = CONTAINING_RECORD(pLE, DCE, List);
}
while (pLE != &LEDce);
return Ret;
}
@ -973,25 +914,22 @@ INT FASTCALL
UserReleaseDC(PWND Window, HDC hDc, BOOL EndPaint)
{
PDCE dce;
PLIST_ENTRY pLE;
PLIST_ENTRY ListEntry;
INT nRet = 0;
BOOL Hit = FALSE;
TRACE("%p %p\n", Window, hDc);
pLE = LEDce.Flink;
dce = CONTAINING_RECORD(pLE, DCE, List);
do
ListEntry = LEDce.Flink;
while (ListEntry != &LEDce)
{
if(!dce) break;
dce = CONTAINING_RECORD(ListEntry, DCE, List);
ListEntry = ListEntry->Flink;
if (dce->hDC == hDc)
{
Hit = TRUE;
break;
}
pLE = dce->List.Flink;
dce = CONTAINING_RECORD(pLE, DCE, List);
}
while (pLE != &LEDce );
if ( Hit && (dce->DCXFlags & DCX_DCEBUSY))
{