[GDI32]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 1 May 2010 13:02:46 +0000 (13:02 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 1 May 2010 13:02:46 +0000 (13:02 +0000)
- 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

reactos/dll/win32/gdi32/include/gdi32p.h
reactos/dll/win32/gdi32/objects/dc.c
reactos/dll/win32/gdi32/objects/region.c

index f45a0dd..5cc0987 100644 (file)
@@ -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 */
index 2d90f60..ddc33e5 100644 (file)
@@ -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);
 
index 3e2b7fe..b8d7077 100644 (file)
@@ -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);
 }