mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 10:01:43 +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 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 */
|
||||
|
|
|
@ -1540,7 +1540,6 @@ SelectObject(HDC hDC,
|
|||
PDC_ATTR pDc_Attr;
|
||||
HGDIOBJ hOldObj = NULL;
|
||||
UINT uType;
|
||||
// PTEB pTeb;
|
||||
|
||||
if(!GdiGetHandleUserData(hDC, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
|
||||
{
|
||||
|
@ -1582,29 +1581,23 @@ SelectObject(HDC hDC,
|
|||
case GDI_OBJECT_TYPE_FONT:
|
||||
hOldObj = pDc_Attr->hlfntNew;
|
||||
if (hOldObj == hGdiObj) return hOldObj;
|
||||
#if 0
|
||||
|
||||
pDc_Attr->ulDirty_ &= ~SLOW_WIDTHS;
|
||||
pDc_Attr->ulDirty_ |= DIRTY_CHARSET;
|
||||
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);
|
||||
pTeb->GdiTebBatch.HDC = hDC;
|
||||
pTeb->GdiBatchCount++;
|
||||
if (pTeb->GdiBatchCount >= GDI_BatchLimit) NtGdiFlush();
|
||||
return hOldObj;
|
||||
if (!(pDc_Attr->ulDirty_ & DC_DIBSECTION))
|
||||
{
|
||||
PGDIBSOBJECT pgO;
|
||||
|
||||
pgO = GdiAllocBatchCommand(hDC, GdiBCSelObj);
|
||||
if (pgO)
|
||||
{
|
||||
pgO->hgdiobj = hGdiObj;
|
||||
return hOldObj;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// default for select object font
|
||||
return NtGdiSelectFont(hDC, hGdiObj);
|
||||
|
||||
|
|
|
@ -109,23 +109,14 @@ DeleteRegion( HRGN hRgn )
|
|||
if ((GdiGetHandleUserData((HGDIOBJ) hRgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr)) &&
|
||||
( Rgn_Attr != NULL ))
|
||||
{
|
||||
PTEB pTeb = NtCurrentTeb();
|
||||
if (pTeb->Win32ThreadInfo != NULL)
|
||||
{
|
||||
if ((pTeb->GdiTebBatch.Offset + sizeof(GDIBSOBJECT)) <= GDIBATCHBUFSIZE)
|
||||
{
|
||||
PGDIBSOBJECT pgO = (PGDIBSOBJECT)(&pTeb->GdiTebBatch.Buffer[0] +
|
||||
pTeb->GdiTebBatch.Offset);
|
||||
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;
|
||||
}
|
||||
}
|
||||
PGDIBSOBJECT pgO;
|
||||
|
||||
pgO = GdiAllocBatchCommand(NULL, GdiBCDelRgn);
|
||||
if (pgO)
|
||||
{
|
||||
pgO->hgdiobj = (HGDIOBJ)hRgn;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return NtGdiDeleteObjectApp((HGDIOBJ) hRgn);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue