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