[ros-diffs] [tkreuzer] 56593: [WIN32K] - Mark bitmap as API bitmap in NtGdiCreateDIBSection - Mark palette as DIB section palette in NtGdiCreateDIBSection - Set biXPelsPerMeter to 0 instead of using the bitmap...

tkreuzer at svn.reactos.org tkreuzer at svn.reactos.org
Wed May 16 14:13:28 UTC 2012


Author: tkreuzer
Date: Wed May 16 14:13:26 2012
New Revision: 56593

URL: http://svn.reactos.org/svn/reactos?rev=56593&view=rev
Log:
[WIN32K]
- Mark bitmap as API bitmap in NtGdiCreateDIBSection
- Mark palette as DIB section palette in NtGdiCreateDIBSection
- Set biXPelsPerMeter to 0 instead of using the bitmap dimentions
- Check BITMAPINFO parameters in GreGetDIBits
- Handle case when requested bit depth doesn't match actual one in GreGetDIBits
- Use maximum BITMAPINFO size in NtGdiGetDIBitsInternal
- Verify header size in NtGdiGetDIBitsInternal
- Misc code improvements

Modified:
    branches/dib_rewrite/win32ss/gdi/ntgdi/dibitmap.c

Modified: branches/dib_rewrite/win32ss/gdi/ntgdi/dibitmap.c
URL: http://svn.reactos.org/svn/reactos/branches/dib_rewrite/win32ss/gdi/ntgdi/dibitmap.c?rev=56593&r1=56592&r2=56593&view=diff
==============================================================================
--- branches/dib_rewrite/win32ss/gdi/ntgdi/dibitmap.c [iso-8859-1] (original)
+++ branches/dib_rewrite/win32ss/gdi/ntgdi/dibitmap.c [iso-8859-1] Wed May 16 14:13:26 2012
@@ -530,6 +530,12 @@
         /* Return the base address if requested */
         if (ppvBits) *ppvBits = psurfDIBSection->SurfObj.pvBits;
 
+        /* Mark as API bitmap */
+        psurfDIBSection->flags |= API_BITMAP;
+
+        /* Mark the palette as a DIB section palette */
+        psurfDIBSection->ppal->flFlags |= PAL_DIBSECTION;
+
         /* Save the handle and unlock the bitmap */
         hbmp = psurfDIBSection->BaseObject.hHmgr;
         SURFACE_UnlockSurface(psurfDIBSection);
@@ -697,7 +703,7 @@
     HANDLE hSecure;
     HBITMAP hbmp;
 
-__debugbreak();
+//__debugbreak();
 
     if (fInit & CBM_INIT)
     {
@@ -772,24 +778,16 @@
     pbmi->bmiHeader.biPlanes = 1;
     pbmi->bmiHeader.biCompression = SURFACE_iCompression(psurf);
     pbmi->bmiHeader.biSizeImage = psurf->SurfObj.cjBits;
-    pbmi->bmiHeader.biXPelsPerMeter = psurf->sizlDim.cx;
-    pbmi->bmiHeader.biYPelsPerMeter = psurf->sizlDim.cy;
-
-    /* Check if the caller requests a color table */
-    if (pbmi->bmiHeader.biBitCount != 0)
-    {
-        /* Synthesize a color table */
-        __debugbreak();
-    }
+    pbmi->bmiHeader.biXPelsPerMeter = 0;
+    pbmi->bmiHeader.biYPelsPerMeter = 0;
+    pbmi->bmiHeader.biBitCount = gajBitsPerFormat[psurf->SurfObj.iBitmapFormat];
+
+    /* Set the number of colors */
+    if (pbmi->bmiHeader.biBitCount <= 8)
+        pbmi->bmiHeader.biClrUsed = 1 << pbmi->bmiHeader.biBitCount;
     else
-    {
-        /* Just return the bit depth */
-        pbmi->bmiHeader.biBitCount =
-            gajBitsPerFormat[psurf->SurfObj.iBitmapFormat];
-    }
-
-    /* Set the number of colors */
-    pbmi->bmiHeader.biClrUsed = 1 << pbmi->bmiHeader.biBitCount;
+        pbmi->bmiHeader.biClrUsed = 0;
+
     pbmi->bmiHeader.biClrImportant = pbmi->bmiHeader.biClrUsed;
 
     if (pbmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
@@ -828,12 +826,31 @@
     _In_ UINT cjMaxInfo)
 {
     PDC pdc;
-    PSURFACE psurf;
+    PSURFACE psurfBmp;
     ULONG iCompression, cBitsPixel, cjLine;
     LONG lDeltaDst;
     PBYTE pjSrc;
     INT iResult = 0;
 
+    /* Check bitmap info */
+    if ((pbmi->bmiHeader.biCompression >= BI_JPEG) ||
+        (pbmi->bmiHeader.biWidth <= 0) ||
+        (pbmi->bmiHeader.biHeight == 0))
+    {
+        return 0;
+    }
+
+    /* Check if we have a proper bit count value */
+    if ((pbmi->bmiHeader.biBitCount != 1) &&
+        (pbmi->bmiHeader.biBitCount != 4) &&
+        (pbmi->bmiHeader.biBitCount != 8) &&
+        (pbmi->bmiHeader.biBitCount != 16) &&
+        (pbmi->bmiHeader.biBitCount != 24) &&
+        (pbmi->bmiHeader.biBitCount != 32))
+    {
+        return 0;
+    }
+
     /* Lock the DC */
     pdc = DC_LockDc(hdc);
     if (!pdc)
@@ -842,35 +859,56 @@
     }
 
     /* Lock the bitmap */
-    psurf = SURFACE_ShareLockSurface(hbm);
-    if (!psurf)
-    {
-
+    psurfBmp = SURFACE_ShareLockSurface(hbm);
+    if (!psurfBmp)
+    {
+        DC_UnlockDc(pdc);
         return 0;
     }
 
+    /* Check if the bitmap is compatile with the dc */
+    if (!DC_bIsBitmapCompatible(pdc, psurfBmp))
+    {
+        /* Dereference the bitmap, unlock the DC and fail. */
+        SURFACE_ShareUnlockSurface(psurfBmp);
+        DC_UnlockDc(pdc);
+        return 0;
+    }
+
+    /* Calculate width of one dest line */
+    lDeltaDst = WIDTH_BYTES_ALIGN32(pbmi->bmiHeader.biWidth,
+                                    pbmi->bmiHeader.biBitCount);
+
+    /* Calculate the image size */
+    pbmi->bmiHeader.biSizeImage = lDeltaDst * abs(pbmi->bmiHeader.biHeight);
+
+    /* Set planes to 1 */
+    pbmi->bmiHeader.biPlanes = 1;
+
     /* Check if there is anything to do */
-    if (iStartScan < (ULONG)psurf->SurfObj.sizlBitmap.cy)
-    {
+    if (pjBits == NULL)
+    {
+        /* Nothing to copy, but we had success */
+        iResult = 1;
+    }
+    else if (iStartScan < (ULONG)psurfBmp->SurfObj.sizlBitmap.cy)
+    {
+        /* Calculate the maximum number of scan lines to be copied */
+        cScans = min(cScans, psurfBmp->SurfObj.sizlBitmap.cy - iStartScan);
+        cScans = min(cScans, cjMaxBits / lDeltaDst);
+
         /* Get the bit depth of the bitmap */
-        cBitsPixel = gajBitsPerFormat[psurf->SurfObj.iBitmapFormat];
+        cBitsPixel = gajBitsPerFormat[psurfBmp->SurfObj.iBitmapFormat];
 
         /* Get the compression of the bitmap */
-        iCompression = SURFACE_iCompression(psurf);
+        iCompression = SURFACE_iCompression(psurfBmp);
 
         /* Check if the requested format matches the actual one */
         if ((cBitsPixel == pbmi->bmiHeader.biBitCount) &&
             (iCompression == pbmi->bmiHeader.biCompression))
         {
-            /* Calculate width of one dest line */
-            lDeltaDst = WIDTH_BYTES_ALIGN32(pbmi->bmiHeader.biWidth, cBitsPixel);
-
-            /* Calculate the maximum number of scan lines to be copied */
-            cScans = min(cScans, psurf->SurfObj.sizlBitmap.cy - iStartScan);
-            cScans = min(cScans, cjMaxBits / lDeltaDst);
-
             /* Calculate the maximum length of a line */
-            cjLine = min(lDeltaDst, abs(psurf->SurfObj.lDelta));
+            cjLine = min(lDeltaDst, abs(psurfBmp->SurfObj.lDelta));
 
             /* Check for top-down bitmaps */
             if (pbmi->bmiHeader.biHeight > 0)
@@ -881,8 +919,8 @@
             }
 
             /* Calculate the start address from where to copy */
-            pjSrc = psurf->SurfObj.pvScan0;
-            pjSrc += iStartScan * psurf->SurfObj.lDelta;
+            pjSrc = psurfBmp->SurfObj.pvScan0;
+            pjSrc += iStartScan * psurfBmp->SurfObj.lDelta;
 
             /* Save number of copied scans */
             iResult = cScans;
@@ -894,7 +932,7 @@
                 RtlCopyMemory(pjBits, pjSrc, cjLine);
 
                 /* go to the next scan line */
-                pjSrc += psurf->SurfObj.lDelta;
+                pjSrc += psurfBmp->SurfObj.lDelta;
                 pjBits += lDeltaDst;
             }
 
@@ -904,7 +942,42 @@
         }
         else
         {
-            __debugbreak();
+            RECTL rclDest = {0, 0, pbmi->bmiHeader.biWidth - 1, cScans -1};
+            POINTL ptlSrc = {0, iStartScan};
+            EXLATEOBJ exlo;
+            PSURFACE psurfDIB;
+
+            /* Create a DIB surface */
+            psurfDIB = DibCreateDIBSurface(pbmi,
+                                           pdc,
+                                           iUsage,
+                                           0,
+                                           pjBits,
+                                           cjMaxBits);
+            if (psurfDIB)
+            {
+                /* Initialize XLATEOBJ */
+                EXLATEOBJ_vInitialize(&exlo,
+                                      psurfDIB->ppal,
+                                      psurfBmp->ppal,
+                                      RGB(0xff, 0xff, 0xff),
+                                      pdc->pdcattr->crBackgroundClr,
+                                      pdc->pdcattr->crForegroundClr);
+
+                EngCopyBits(&psurfDIB->SurfObj,
+                            &psurfBmp->SurfObj,
+                            NULL,
+                            &exlo.xlo,
+                            &rclDest,
+                            &ptlSrc);
+
+                /* Cleanup */
+                EXLATEOBJ_vCleanup(&exlo);
+                GDIOBJ_vDeleteObject(&psurfDIB->BaseObject);
+
+                /* Return the number of copied scan lnes */
+                iResult = cScans;
+            }
         }
     }
     else
@@ -913,9 +986,8 @@
         iResult = 0;
     }
 
-    /* Unlock the bitmap surface */
-    SURFACE_ShareUnlockSurface(psurf);
-
+    /* Unlock the bitmap surface and the DC */
+    SURFACE_ShareUnlockSurface(psurfBmp);
     DC_UnlockDc(pdc);
 
     return iResult;
@@ -936,7 +1008,10 @@
 {
     PBITMAPINFO pbmi;
     HANDLE hSecure;
-    INT iResult;
+    INT iResult = 0;
+
+    /* Check for bad iUsage */
+    if (iUsage > 2) return 0;
 
     /* Check if the size of the bitmap info is large enough */
     if (cjMaxInfo < sizeof(BITMAPINFOHEADER))
@@ -944,37 +1019,53 @@
         return 0;
     }
 
+    /* Use maximum size */
+    cjMaxInfo = min(cjMaxInfo, sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD));
+
+    /* Allocate a buffer the bitmapinfo */
+    pbmi = ExAllocatePoolWithTag(PagedPool, cjMaxInfo, GDITAG_BITMAPINFO);
+    if (!pbmi)
+    {
+        /* Fail */
+        return 0;
+    }
+
+    /* Use SEH */
+    _SEH2_TRY
+    {
+        /* Probe and copy the BITMAPINFO */
+        ProbeForWrite(pbmiUser, cjMaxInfo, 1);
+        RtlCopyMemory(pbmi, pbmiUser, cjMaxInfo);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        _SEH2_YIELD(goto cleanup;)
+    }
+    _SEH2_END;
+
+    /* Check if the header size is large enough */
+    if ((pbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER)) ||
+        (pbmi->bmiHeader.biSize > cjMaxInfo))
+    {
+        iResult = 0;
+        goto cleanup;
+    }
+
+    /* Check if the caller provided bitmap bits */
     if (pjBits)
     {
+        /* Secure the user mode memory */
         hSecure = EngSecureMem(pjBits, cjMaxBits);
         if (!hSecure)
         {
-            return 0;
-        }
-    }
-
-    pbmi = ExAllocatePoolWithTag(PagedPool, cjMaxInfo, GDITAG_BITMAPINFO);
-    if (!pbmi)
-    {
-        __debugbreak();
-    }
-
-    _SEH2_TRY
-    {
-        ProbeForWrite(pbmiUser, cjMaxInfo, 1);
-        RtlCopyMemory(pbmi, pbmiUser, cjMaxInfo);
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        __debugbreak();
-    }
-    _SEH2_END;
-
-    // FIXME: check pbmi size
-
-    if (pjBits)
-    {
-        /* Call the internal functiomn */
+            goto cleanup;
+        }
+    }
+
+    /* Check if the bitcount member is initialized */
+    if (pbmi->bmiHeader.biBitCount != 0)
+    {
+        /* Call the internal function */
         iResult = GreGetDIBits(hdc,
                                hbm,
                                iStartScan,
@@ -985,23 +1076,35 @@
                                cjMaxBits,
                                cjMaxInfo);
     }
+    else if (pjBits == NULL)
+    {
+        /* Just get the BITMAPINFO */
+        iResult = GreGetDIBitmapInfo(hbm, pbmi, iUsage, cjMaxInfo);
+    }
     else
     {
-        iResult = GreGetDIBitmapInfo(hbm, pbmi, iUsage, cjMaxInfo);
-    }
-
-    _SEH2_TRY
-    {
-        RtlCopyMemory(pbmiUser, pbmi, cjMaxInfo);
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-    }
-    _SEH2_END;
-
-
+        /* This combination is not valid */
+        iResult = 0;
+    }
+
+    /* Check for success */
+    if (iResult)
+    {
+        /* Use SEH to copy back to user mode */
+        _SEH2_TRY
+        {
+            /* Buffer is already probed, copy the data back */
+            RtlCopyMemory(pbmiUser, pbmi, cjMaxInfo);
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+        }
+        _SEH2_END;
+    }
+
+cleanup:
+    if (hSecure) EngUnsecureMem(hSecure);
     ExFreePoolWithTag(pbmi, GDITAG_BITMAPINFO);
-
 
     return iResult;
 }
@@ -1269,7 +1372,7 @@
 
 BITMAPINFO*
 FASTCALL
-DIB_ConvertBitmapInfo(CONST BITMAPINFO* pbmi, DWORD Usage)
+_DIB_ConvertBitmapInfo(CONST BITMAPINFO* pbmi, DWORD Usage)
 {
     __debugbreak();
     return 0;
@@ -1277,7 +1380,7 @@
 
 VOID
 FASTCALL
-DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
+_DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
 {
     if(converted != orig)
         ExFreePoolWithTag(converted, TAG_DIB);




More information about the Ros-diffs mailing list