PATCH: handle NULL XImage in GetBitmapBits

Marcus Meissner marcus at jet.franken.de
Tue Dec 13 02:43:15 CST 2005


On Mon, Dec 12, 2005 at 05:42:57PM +0100, Alexandre Julliard wrote:
> Marcus Meissner <marcus at jet.franken.de> writes:
> 
> > Hi,
> >
> > This fixes bug 4034.
> > XGetImage() returns NULL since we can pass a 0 height value. (298 bytes
> > vs 320 byte wide image).
> 
> This shouldn't happen, the height should have been checked in
> GetBitmapBits already. There's something wrong here...

Yes.

trace:bitmap:DIB_CreateDIBSection format (95,1), planes 1, bpp 32, size 0, RGB
trace:bitmap:CreateBitmapIndirect 95x1, 16777216 colors returning 0x3754
trace:bitmap:X11DRV_DIB_DoProtectDIBSection Changed protection from 4 to 4
trace:bitmap:GetBitmapBits (0x3754, 286, 0x5a22d750) 95(286 bytes)x1 16777216 colors fetched height: 1
trace:bitmap:GetBitmapBits Calling device specific BitmapBits
	bmWidthBytes is 286.

trace:x11drv:X11DRV_GetBitmapBits (bmp=0x3754, buffer=0x5a22d750, count=0x11e)
trace:x11drv:X11DRV_GetBitmapBits (widthbytes=380, height=0, oldheight=1)

	bmWidthBytes is 380.

This is the same bitmap...

In GDI it is got like this:
	bitmap = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );

In X11DRV like this:
	GetObjectW( hbitmap, sizeof(bitmap), &bitmap ))

The later calls into gdi/bitmap.c to get the bitmap data, while
the first one does not.

The problem here is that the specific bitmap is actually a DIB,
and GDI GetBitmapBits() uses the "bitmap" part of the BITMAP object,
but should have used the "dib" part for the information.

I would suggest something along the lines of this patch:

Ciao, Marcus

Changelog:
	In GetBitmapBits() handle the correct bitmap information
	when a DIB is used.

Index: dlls/gdi/bitmap.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/bitmap.c,v
retrieving revision 1.9
diff -u -r1.9 bitmap.c
--- dlls/gdi/bitmap.c	29 Nov 2005 11:06:17 -0000	1.9
+++ dlls/gdi/bitmap.c	13 Dec 2005 08:37:19 -0000
@@ -303,14 +303,20 @@
     LPVOID bits)       /* [out] Pointer to buffer to receive bits */
 {
     BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
+    BITMAP bitmap;
     LONG height, ret;
 
     if (!bmp) return 0;
 
+    if (!GetObjectW(hbitmap, sizeof(bitmap), &bitmap)) {
+        GDI_ReleaseObj( hbitmap );
+        return 0;
+    }
+
     /* If the bits vector is null, the function should return the read size */
     if(bits == NULL)
     {
-        ret = bmp->bitmap.bmWidthBytes * bmp->bitmap.bmHeight;
+        ret = bitmap.bmWidthBytes * bitmap.bmHeight;
         goto done;
     }
 
@@ -320,9 +326,9 @@
     }
 
     /* Only get entire lines */
-    height = count / bmp->bitmap.bmWidthBytes;
-    if (height > bmp->bitmap.bmHeight) height = bmp->bitmap.bmHeight;
-    count = height * bmp->bitmap.bmWidthBytes;
+    height = count / bitmap.bmWidthBytes;
+    if (height > bitmap.bmHeight) height = bitmap.bmHeight;
+    count = height * bitmap.bmWidthBytes;
     if (count == 0)
       {
 	WARN("Less than one entire line requested\n");
@@ -331,9 +337,9 @@
       }
 
 
-    TRACE("(%p, %ld, %p) %dx%d %d colors fetched height: %ld\n",
-          hbitmap, count, bits, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
-          1 << bmp->bitmap.bmBitsPixel, height );
+    TRACE("(%p, %ld, %p) %d(%d bytes)x%d %d colors fetched height: %ld\n",
+          hbitmap, count, bits, bitmap.bmWidth, bitmap.bmWidthBytes,
+          bitmap.bmHeight, 1 << bitmap.bmBitsPixel, height );
 
     if(bmp->funcs && bmp->funcs->pGetBitmapBits)
     {



More information about the wine-patches mailing list