From: Timo Kreuzer Date: Sat, 1 May 2010 13:02:46 +0000 (+0000) Subject: [GDI32] X-Git-Tag: backups/header-work@57446~33^2~14 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=f4fd1abac0c5ba778bfa2c7c815fa4e67c6a0a50;hp=18af76559c7d830268d70cf1c974ebe1a89077da [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 --- diff --git a/reactos/dll/win32/gdi32/include/gdi32p.h b/reactos/dll/win32/gdi32/include/gdi32p.h index f45a0ddd171..5cc09870a94 100644 --- a/reactos/dll/win32/gdi32/include/gdi32p.h +++ b/reactos/dll/win32/gdi32/include/gdi32p.h @@ -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 */ diff --git a/reactos/dll/win32/gdi32/objects/dc.c b/reactos/dll/win32/gdi32/objects/dc.c index 2d90f60cdac..ddc33e501f1 100644 --- a/reactos/dll/win32/gdi32/objects/dc.c +++ b/reactos/dll/win32/gdi32/objects/dc.c @@ -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))) + + if (!(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; + PGDIBSOBJECT pgO; + + pgO = GdiAllocBatchCommand(hDC, GdiBCSelObj); + if (pgO) + { + pgO->hgdiobj = hGdiObj; + return hOldObj; + } } -#endif + // default for select object font return NtGdiSelectFont(hDC, hGdiObj); diff --git a/reactos/dll/win32/gdi32/objects/region.c b/reactos/dll/win32/gdi32/objects/region.c index 3e2b7fe5b65..b8d70772dcf 100644 --- a/reactos/dll/win32/gdi32/objects/region.c +++ b/reactos/dll/win32/gdi32/objects/region.c @@ -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); }