Huw Davies : gdi32: Add a helper to sanitize a BITMAPINFO structure.

Alexandre Julliard julliard at winehq.org
Fri Jul 22 10:16:00 CDT 2011


Module: wine
Branch: master
Commit: 6ce6f890bef2257af50a78e7deee86bdce052189
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=6ce6f890bef2257af50a78e7deee86bdce052189

Author: Huw Davies <huw at codeweavers.com>
Date:   Fri Jul 22 15:09:58 2011 +0100

gdi32: Add a helper to sanitize a BITMAPINFO structure.

---

 dlls/gdi32/dib.c |   83 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c
index 7e5354b..85a8992 100644
--- a/dlls/gdi32/dib.c
+++ b/dlls/gdi32/dib.c
@@ -136,6 +136,79 @@ int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
     return -1;
 }
 
+/*******************************************************************************************
+ *  Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
+ */
+static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *info, UINT coloruse )
+{
+    LONG width, height;
+    WORD planes, bpp;
+    DWORD compr, size;
+    void *src_colors = (char *)info + info->bmiHeader.biSize;
+    unsigned int colors;
+    int bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size );
+
+    if (bitmap_type == -1) return FALSE;
+
+    colors = (bpp > 8) ? 0 : 1 << bpp;
+
+    if (bitmap_type == 1)
+    {
+        dst->bmiHeader                 = info->bmiHeader;
+        dst->bmiHeader.biSize          = sizeof(dst->bmiHeader);
+
+        if (info->bmiHeader.biClrUsed) colors = info->bmiHeader.biClrUsed;
+
+        if (info->bmiHeader.biCompression == BI_BITFIELDS)
+            /* bitfields are always at bmiColors even in larger structures */
+            memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
+        else if (colors)
+        {
+            unsigned int size;
+
+            if (coloruse == DIB_PAL_COLORS)
+                size = colors * sizeof(WORD);
+            else
+                size = colors * sizeof(RGBQUAD);
+            memcpy( dst->bmiColors, src_colors, size );
+        }
+    }
+    else
+    {
+        dst->bmiHeader.biSize          = sizeof(dst->bmiHeader);
+        dst->bmiHeader.biWidth         = width;
+        dst->bmiHeader.biHeight        = height;
+        dst->bmiHeader.biPlanes        = planes;
+        dst->bmiHeader.biBitCount      = bpp;
+        dst->bmiHeader.biCompression   = compr;
+        dst->bmiHeader.biSizeImage     = size;
+        dst->bmiHeader.biXPelsPerMeter = 0;
+        dst->bmiHeader.biYPelsPerMeter = 0;
+        dst->bmiHeader.biClrUsed       = 0;
+        dst->bmiHeader.biClrImportant  = 0;
+
+        if (colors)
+        {
+            if (coloruse == DIB_PAL_COLORS)
+                memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
+            else
+            {
+                unsigned int i;
+                RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
+                for (i = 0; i < colors; i++)
+                {
+                    dst->bmiColors[i].rgbRed      = triple[i].rgbtRed;
+                    dst->bmiColors[i].rgbGreen    = triple[i].rgbtGreen;
+                    dst->bmiColors[i].rgbBlue     = triple[i].rgbtBlue;
+                    dst->bmiColors[i].rgbReserved = 0;
+                }
+            }
+        }
+    }
+
+    return TRUE;
+}
+
 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
                            INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
@@ -256,6 +329,8 @@ INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
     BOOL delete_hdc = FALSE;
     PHYSDEV physdev;
     BITMAPOBJ *bitmap;
+    char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
+    BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
     INT result = 0;
 
     if (coloruse == DIB_RGB_COLORS && !dc)
@@ -276,10 +351,14 @@ INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
         return 0;
     }
 
+    if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse )) goto done;
+
     physdev = GET_DC_PHYSDEV( dc, pSetDIBits );
-    if (BITMAP_SetOwnerDC( hbitmap, physdev ))
-        result = physdev->funcs->pSetDIBits( physdev, hbitmap, startscan, lines, bits, info, coloruse );
+    if (!BITMAP_SetOwnerDC( hbitmap, physdev )) goto done;
 
+    result = physdev->funcs->pSetDIBits( physdev, hbitmap, startscan, lines, bits, src_info, coloruse );
+
+done:
     GDI_ReleaseObj( hbitmap );
     release_dc_ptr( dc );
     if (delete_hdc) DeleteDC(hdc);




More information about the wine-cvs mailing list