Author: tkreuzer Date: Sat May 1 15:02:46 2010 New Revision: 47074
URL: http://svn.reactos.org/svn/reactos?rev=47074&view=rev Log: [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.
Modified: trunk/reactos/dll/win32/gdi32/include/gdi32p.h trunk/reactos/dll/win32/gdi32/objects/dc.c trunk/reactos/dll/win32/gdi32/objects/region.c
Modified: trunk/reactos/dll/win32/gdi32/include/gdi32p.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdi32/include/gdi... ============================================================================== --- trunk/reactos/dll/win32/gdi32/include/gdi32p.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdi32/include/gdi32p.h [iso-8859-1] Sat May 1 15:02:46 2010 @@ -292,4 +292,91 @@ 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 */
Modified: trunk/reactos/dll/win32/gdi32/objects/dc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdi32/objects/dc.... ============================================================================== --- trunk/reactos/dll/win32/gdi32/objects/dc.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdi32/objects/dc.c [iso-8859-1] Sat May 1 15:02:46 2010 @@ -1540,7 +1540,6 @@ 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 @@ 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);
Modified: trunk/reactos/dll/win32/gdi32/objects/region.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdi32/objects/reg... ============================================================================== --- trunk/reactos/dll/win32/gdi32/objects/region.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdi32/objects/region.c [iso-8859-1] Sat May 1 15:02:46 2010 @@ -109,23 +109,14 @@ 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); }