gdi32: Do not allow to create too large device dependent bitmaps like Windows does. Take 3

Dmitry Timoshkov dmitry at codeweavers.com
Tue Jan 15 04:45:17 CST 2008


Hello,

thanks to Robert Shearman for spotting a typo in previous attempt(s).
--

this patch should fix the problem reported in the bug 11140.

While fixing this I removed a redundant indentation level in
CreateCompatibleBitmap, if you would prefer that as a separate
patch please let me know.

Changelog:
    gdi32: Do not allow to create too large device dependent bitmaps
    like Windows does.
---
 dlls/gdi32/bitmap.c       |  118 +++++++++++++++++++++++----------------------
 dlls/gdi32/tests/bitmap.c |   18 +++++++
 2 files changed, 79 insertions(+), 57 deletions(-)

diff --git a/dlls/gdi32/bitmap.c b/dlls/gdi32/bitmap.c
index 3355541..55b3236 100644
--- a/dlls/gdi32/bitmap.c
+++ b/dlls/gdi32/bitmap.c
@@ -136,79 +136,71 @@ HBITMAP WINAPI CreateCompatibleBitmap( HDC hdc, INT width, INT height)
 
     TRACE("(%p,%d,%d) =\n", hdc, width, height);
 
-    if ((width >= 0x10000) || (height >= 0x10000))
+    if (!(dc = DC_GetDCPtr(hdc))) return 0;
+
+    if (GDIMAGIC( dc->header.wMagic ) != MEMORY_DC_MAGIC)
     {
-        FIXME("got bad width %d or height %d, please look for reason\n",
-              width, height);
+        hbmpRet = CreateBitmap(width, height,
+                               GetDeviceCaps(hdc, PLANES),
+                               GetDeviceCaps(hdc, BITSPIXEL),
+                               NULL);
     }
-    else
+    else  /* Memory DC */
     {
-        if (!(dc = DC_GetDCPtr(hdc))) return 0;
+        BITMAPOBJ *bmp = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC );
 
-        if (GDIMAGIC( dc->header.wMagic ) != MEMORY_DC_MAGIC)
+        if (!bmp->dib)
         {
+            /* A device-dependent bitmap is selected in the DC */
             hbmpRet = CreateBitmap(width, height,
-                                   GetDeviceCaps(hdc, PLANES),
-                                   GetDeviceCaps(hdc, BITSPIXEL),
+                                   bmp->bitmap.bmPlanes,
+                                   bmp->bitmap.bmBitsPixel,
                                    NULL);
         }
-        else  /* Memory DC */
+        else
         {
-            BITMAPOBJ *bmp = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC );
-
-            if (!bmp->dib)
-            {
-                /* A device-dependent bitmap is selected in the DC */
-                hbmpRet = CreateBitmap(width, height,
-                                       bmp->bitmap.bmPlanes,
-                                       bmp->bitmap.bmBitsPixel,
-                                       NULL);
-            }
-            else
-            {
-                /* A DIB section is selected in the DC */
-                BITMAPINFO *bi;
-                void *bits;
+            /* A DIB section is selected in the DC */
+            BITMAPINFO *bi;
+            void *bits;
 
-                /* Allocate memory for a BITMAPINFOHEADER structure and a
-                   color table. The maximum number of colors in a color table
-                   is 256 which corresponds to a bitmap with depth 8.
-                   Bitmaps with higher depths don't have color tables. */
-                bi = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
+            /* Allocate memory for a BITMAPINFOHEADER structure and a
+               color table. The maximum number of colors in a color table
+               is 256 which corresponds to a bitmap with depth 8.
+               Bitmaps with higher depths don't have color tables. */
+            bi = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
 
-                if (bi)
+            if (bi)
+            {
+                bi->bmiHeader.biSize          = sizeof(bi->bmiHeader);
+                bi->bmiHeader.biWidth         = width;
+                bi->bmiHeader.biHeight        = height;
+                bi->bmiHeader.biPlanes        = bmp->dib->dsBmih.biPlanes;
+                bi->bmiHeader.biBitCount      = bmp->dib->dsBmih.biBitCount;
+                bi->bmiHeader.biCompression   = bmp->dib->dsBmih.biCompression;
+                bi->bmiHeader.biSizeImage     = 0;
+                bi->bmiHeader.biXPelsPerMeter = bmp->dib->dsBmih.biXPelsPerMeter;
+                bi->bmiHeader.biYPelsPerMeter = bmp->dib->dsBmih.biYPelsPerMeter;
+                bi->bmiHeader.biClrUsed       = bmp->dib->dsBmih.biClrUsed;
+                bi->bmiHeader.biClrImportant  = bmp->dib->dsBmih.biClrImportant;
+
+                if (bi->bmiHeader.biCompression == BI_BITFIELDS)
+                {
+                    /* Copy the color masks */
+                    CopyMemory(bi->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD));
+                }
+                else if (bi->bmiHeader.biBitCount <= 8)
                 {
-                    bi->bmiHeader.biSize          = sizeof(bi->bmiHeader);
-                    bi->bmiHeader.biWidth         = width;
-                    bi->bmiHeader.biHeight        = height;
-                    bi->bmiHeader.biPlanes        = bmp->dib->dsBmih.biPlanes;
-                    bi->bmiHeader.biBitCount      = bmp->dib->dsBmih.biBitCount;
-                    bi->bmiHeader.biCompression   = bmp->dib->dsBmih.biCompression;
-                    bi->bmiHeader.biSizeImage     = 0;
-                    bi->bmiHeader.biXPelsPerMeter = bmp->dib->dsBmih.biXPelsPerMeter;
-                    bi->bmiHeader.biYPelsPerMeter = bmp->dib->dsBmih.biYPelsPerMeter;
-                    bi->bmiHeader.biClrUsed       = bmp->dib->dsBmih.biClrUsed;
-                    bi->bmiHeader.biClrImportant  = bmp->dib->dsBmih.biClrImportant;
-
-                    if (bi->bmiHeader.biCompression == BI_BITFIELDS)
-                    {
-                        /* Copy the color masks */
-                        CopyMemory(bi->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD));
-                    }
-                    else if (bi->bmiHeader.biBitCount <= 8)
-                    {
-                        /* Copy the color table */
-                        GetDIBColorTable(hdc, 0, 256, bi->bmiColors);
-                    }
-
-                    hbmpRet = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, &bits, NULL, 0);
-                    HeapFree(GetProcessHeap(), 0, bi);
+                    /* Copy the color table */
+                    GetDIBColorTable(hdc, 0, 256, bi->bmiColors);
                 }
+
+                hbmpRet = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, &bits, NULL, 0);
+                HeapFree(GetProcessHeap(), 0, bi);
             }
-            GDI_ReleaseObj(dc->hBitmap);
         }
-        DC_ReleaseDCPtr( dc );
+        GDI_ReleaseObj(dc->hBitmap);
     }
+    DC_ReleaseDCPtr( dc );
 
     TRACE("\t\t%p\n", hbmpRet);
     return hbmpRet;
@@ -242,6 +234,12 @@ HBITMAP WINAPI CreateBitmapIndirect( const BITMAP *bmp )
         return NULL;
     }
 
+    if (bmp->bmWidth > 0x7ffffff || bmp->bmHeight > 0x7ffffff)
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return 0;
+    }
+
     bm = *bmp;
 
     if (!bm.bmWidth || !bm.bmHeight)
@@ -278,6 +276,12 @@ HBITMAP WINAPI CreateBitmapIndirect( const BITMAP *bmp )
 
     /* Windows ignores the provided bm.bmWidthBytes */
     bm.bmWidthBytes = BITMAP_GetWidthBytes( bm.bmWidth, bm.bmBitsPixel );
+    /* XP doesn't allow to create bitmaps larger than 128 Mb */
+    if (bm.bmHeight * bm.bmWidthBytes > 128 * 1024 * 1024)
+    {
+        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+        return 0;
+    }
 
       /* Create the BITMAPOBJ */
     bmpobj = GDI_AllocObject( sizeof(BITMAPOBJ), BITMAP_MAGIC,
diff --git a/dlls/gdi32/tests/bitmap.c b/dlls/gdi32/tests/bitmap.c
index eb6c09d..573fe56 100644
--- a/dlls/gdi32/tests/bitmap.c
+++ b/dlls/gdi32/tests/bitmap.c
@@ -25,6 +25,7 @@
 
 #include "windef.h"
 #include "winbase.h"
+#include "winerror.h"
 #include "wingdi.h"
 #include "winuser.h"
 #include "mmsystem.h"
@@ -966,6 +967,23 @@ static void test_bitmap(void)
     hdc = CreateCompatibleDC(0);
     assert(hdc != 0);
 
+    SetLastError(0xdeadbeef);
+    hbmp = CreateBitmap(0x7ffffff, 1, 1, 1, NULL);
+    ok(hbmp != 0, "CreateBitmap should not fail\n");
+    DeleteObject(hbmp);
+
+    SetLastError(0xdeadbeef);
+    hbmp = CreateBitmap(0x7ffffff, 9, 1, 1, NULL);
+    ok(!hbmp, "CreateBitmap should fail\n");
+    ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY,
+       "expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    hbmp = CreateBitmap(0x7ffffff + 1, 1, 1, 1, NULL);
+    ok(!hbmp, "CreateBitmap should fail\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER,
+       "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
+
     hbmp = CreateBitmap(15, 15, 1, 1, NULL);
     assert(hbmp != NULL);
 
-- 
1.5.3.8






More information about the wine-patches mailing list