mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 05:52:56 +00:00
[GDI32]
- Fix pointer arithmetics in the gdi batch code (&pTeb->GdiTebBatch.Buffer[0] is a PULONG, but pTeb->GdiTebBatch.Offset is a byte offset) - To prevent this from happening again, refactor the code to use one common routine GdiAllocBatchCommand to do most of the stuff. - Reenable gdi batch for SelectObject - Fixes gdi handle leak, causes some drawing problems in Acrobat reader, but those are less critical and I'll investigate those. svn path=/trunk/; revision=47074
This commit is contained in:
parent
18af76559c
commit
f4fd1abac0
3 changed files with 107 additions and 36 deletions
|
@ -292,4 +292,91 @@ int FASTCALL DocumentEventEx(PVOID,HANDLE,HDC,int,ULONG,PVOID,ULONG,PVOID);
|
||||||
BOOL FASTCALL EndPagePrinterEx(PVOID,HANDLE);
|
BOOL FASTCALL EndPagePrinterEx(PVOID,HANDLE);
|
||||||
BOOL FASTCALL LoadTheSpoolerDrv(VOID);
|
BOOL FASTCALL LoadTheSpoolerDrv(VOID);
|
||||||
|
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
PVOID
|
||||||
|
GdiAllocBatchCommand(
|
||||||
|
HDC hdc,
|
||||||
|
USHORT Cmd)
|
||||||
|
{
|
||||||
|
PTEB pTeb;
|
||||||
|
ULONG ulSize;
|
||||||
|
PGDIBATCHHDR pHdr;
|
||||||
|
|
||||||
|
/* Get a pointer to the TEB */
|
||||||
|
pTeb = NtCurrentTeb();
|
||||||
|
|
||||||
|
/* Check if we have a valid environment */
|
||||||
|
if (!pTeb || !pTeb->Win32ThreadInfo) return NULL;
|
||||||
|
|
||||||
|
/* Do we use a DC? */
|
||||||
|
if (hdc)
|
||||||
|
{
|
||||||
|
/* If the batch DC is NULL, we set this one as the new one */
|
||||||
|
if (!pTeb->GdiTebBatch.HDC) pTeb->GdiTebBatch.HDC = hdc;
|
||||||
|
|
||||||
|
/* If not, check if the batch DC equal to our DC */
|
||||||
|
else if (pTeb->GdiTebBatch.HDC != hdc) return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the size of the entry */
|
||||||
|
switch(Cmd)
|
||||||
|
{
|
||||||
|
case GdiBCPatBlt:
|
||||||
|
ulSize = 0;
|
||||||
|
break;
|
||||||
|
case GdiBCPolyPatBlt:
|
||||||
|
ulSize = 0;
|
||||||
|
break;
|
||||||
|
case GdiBCTextOut:
|
||||||
|
ulSize = 0;
|
||||||
|
break;
|
||||||
|
case GdiBCExtTextOut:
|
||||||
|
ulSize = 0;
|
||||||
|
break;
|
||||||
|
case GdiBCSetBrushOrg:
|
||||||
|
ulSize = 0;
|
||||||
|
break;
|
||||||
|
case GdiBCExtSelClipRgn:
|
||||||
|
ulSize = 0;
|
||||||
|
break;
|
||||||
|
case GdiBCSelObj:
|
||||||
|
ulSize = sizeof(GDIBSOBJECT);
|
||||||
|
break;
|
||||||
|
case GdiBCDelRgn:
|
||||||
|
ulSize = sizeof(GDIBSOBJECT);
|
||||||
|
break;
|
||||||
|
case GdiBCDelObj:
|
||||||
|
ulSize = sizeof(GDIBSOBJECT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unsupported operation */
|
||||||
|
if (ulSize == 0) return NULL;
|
||||||
|
|
||||||
|
/* Check if the buffer is full */
|
||||||
|
if ((pTeb->GdiBatchCount >= GDI_BatchLimit) ||
|
||||||
|
((pTeb->GdiTebBatch.Offset + ulSize) > GDIBATCHBUFSIZE))
|
||||||
|
{
|
||||||
|
/* Call win32k, the kernel will call NtGdiFlushUserBatch to flush
|
||||||
|
the current batch */
|
||||||
|
NtGdiFlush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the head of the entry */
|
||||||
|
pHdr = (PVOID)((PUCHAR)pTeb->GdiTebBatch.Buffer + pTeb->GdiTebBatch.Offset);
|
||||||
|
|
||||||
|
/* Update Offset and batch count */
|
||||||
|
pTeb->GdiTebBatch.Offset += ulSize;
|
||||||
|
pTeb->GdiBatchCount++;
|
||||||
|
|
||||||
|
/* Fill in the core fields */
|
||||||
|
pHdr->Cmd = Cmd;
|
||||||
|
pHdr->Size = ulSize;
|
||||||
|
|
||||||
|
return pHdr;
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -1540,7 +1540,6 @@ SelectObject(HDC hDC,
|
||||||
PDC_ATTR pDc_Attr;
|
PDC_ATTR pDc_Attr;
|
||||||
HGDIOBJ hOldObj = NULL;
|
HGDIOBJ hOldObj = NULL;
|
||||||
UINT uType;
|
UINT uType;
|
||||||
// PTEB pTeb;
|
|
||||||
|
|
||||||
if(!GdiGetHandleUserData(hDC, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
|
if(!GdiGetHandleUserData(hDC, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
|
||||||
{
|
{
|
||||||
|
@ -1582,29 +1581,23 @@ SelectObject(HDC hDC,
|
||||||
case GDI_OBJECT_TYPE_FONT:
|
case GDI_OBJECT_TYPE_FONT:
|
||||||
hOldObj = pDc_Attr->hlfntNew;
|
hOldObj = pDc_Attr->hlfntNew;
|
||||||
if (hOldObj == hGdiObj) return hOldObj;
|
if (hOldObj == hGdiObj) return hOldObj;
|
||||||
#if 0
|
|
||||||
pDc_Attr->ulDirty_ &= ~SLOW_WIDTHS;
|
pDc_Attr->ulDirty_ &= ~SLOW_WIDTHS;
|
||||||
pDc_Attr->ulDirty_ |= DIRTY_CHARSET;
|
pDc_Attr->ulDirty_ |= DIRTY_CHARSET;
|
||||||
pDc_Attr->hlfntNew = hGdiObj;
|
pDc_Attr->hlfntNew = hGdiObj;
|
||||||
pTeb = NtCurrentTeb();
|
|
||||||
if (((pTeb->GdiTebBatch.HDC == 0) ||
|
|
||||||
(pTeb->GdiTebBatch.HDC == hDC)) &&
|
|
||||||
((pTeb->GdiTebBatch.Offset + sizeof(GDIBSOBJECT)) <= GDIBATCHBUFSIZE) &&
|
|
||||||
(!(pDc_Attr->ulDirty_ & DC_DIBSECTION)))
|
|
||||||
{
|
|
||||||
PGDIBSOBJECT pgO = (PGDIBSOBJECT)(&pTeb->GdiTebBatch.Buffer[0] +
|
|
||||||
pTeb->GdiTebBatch.Offset);
|
|
||||||
pgO->gbHdr.Cmd = GdiBCSelObj;
|
|
||||||
pgO->gbHdr.Size = sizeof(GDIBSOBJECT);
|
|
||||||
pgO->hgdiobj = hGdiObj;
|
|
||||||
|
|
||||||
pTeb->GdiTebBatch.Offset += sizeof(GDIBSOBJECT);
|
if (!(pDc_Attr->ulDirty_ & DC_DIBSECTION))
|
||||||
pTeb->GdiTebBatch.HDC = hDC;
|
{
|
||||||
pTeb->GdiBatchCount++;
|
PGDIBSOBJECT pgO;
|
||||||
if (pTeb->GdiBatchCount >= GDI_BatchLimit) NtGdiFlush();
|
|
||||||
return hOldObj;
|
pgO = GdiAllocBatchCommand(hDC, GdiBCSelObj);
|
||||||
|
if (pgO)
|
||||||
|
{
|
||||||
|
pgO->hgdiobj = hGdiObj;
|
||||||
|
return hOldObj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
// default for select object font
|
// default for select object font
|
||||||
return NtGdiSelectFont(hDC, hGdiObj);
|
return NtGdiSelectFont(hDC, hGdiObj);
|
||||||
|
|
||||||
|
|
|
@ -109,23 +109,14 @@ DeleteRegion( HRGN hRgn )
|
||||||
if ((GdiGetHandleUserData((HGDIOBJ) hRgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr)) &&
|
if ((GdiGetHandleUserData((HGDIOBJ) hRgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr)) &&
|
||||||
( Rgn_Attr != NULL ))
|
( Rgn_Attr != NULL ))
|
||||||
{
|
{
|
||||||
PTEB pTeb = NtCurrentTeb();
|
PGDIBSOBJECT pgO;
|
||||||
if (pTeb->Win32ThreadInfo != NULL)
|
|
||||||
{
|
pgO = GdiAllocBatchCommand(NULL, GdiBCDelRgn);
|
||||||
if ((pTeb->GdiTebBatch.Offset + sizeof(GDIBSOBJECT)) <= GDIBATCHBUFSIZE)
|
if (pgO)
|
||||||
{
|
{
|
||||||
PGDIBSOBJECT pgO = (PGDIBSOBJECT)(&pTeb->GdiTebBatch.Buffer[0] +
|
pgO->hgdiobj = (HGDIOBJ)hRgn;
|
||||||
pTeb->GdiTebBatch.Offset);
|
return TRUE;
|
||||||
pgO->gbHdr.Cmd = GdiBCDelRgn;
|
}
|
||||||
pgO->gbHdr.Size = sizeof(GDIBSOBJECT);
|
|
||||||
pgO->hgdiobj = (HGDIOBJ)hRgn;
|
|
||||||
|
|
||||||
pTeb->GdiTebBatch.Offset += sizeof(GDIBSOBJECT);
|
|
||||||
pTeb->GdiBatchCount++;
|
|
||||||
if (pTeb->GdiBatchCount >= GDI_BatchLimit) NtGdiFlush();
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return NtGdiDeleteObjectApp((HGDIOBJ) hRgn);
|
return NtGdiDeleteObjectApp((HGDIOBJ) hRgn);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue