[GDI] GetObject fails on buffer=NULL

Kelly Leahy kellyleahy at swbell.net
Fri Jun 6 15:28:22 CDT 2003


Programmer: Kelly Leahy (kellyleahy at swbell.net)

Changelog:
  - Added support for PSDK GetObject functionality when buffer = NULL.
  - Fixed problems with GetObject when count = 0 and buffer = NULL.

Description:
  Under the PSDK description of GetObject (Win32 GDI), the functionality when
 the buffer parameter is NULL is described such that GetObject should return
 the number of bytes required for the buffer.  Under the current CVS version
 of wine, GetObject returns ERROR_INVALID_HANDLE when count = 0, or will cause
 an access violation (null pointer exception) when buffer = NULL and count <>
 0.  The GDI implementation (at least on XP, where I tested it) will work with
 buffer = NULL, regardless of the value of count.  For this reason, I've
 changed the functionality of wine's implementation to the following:

GetObject:
  - if count = 0 and buffer <> NULL then return 0.
  - if buffer = NULL and GetObject is supported on the handle, return the 
       size of the buffer required to accomodate the results of the call.
  - if buffer <> NULL and count is large enough to accomodate the results,
       process the call normally.

GetObject16: same as GetObject, except using the 'results' structures for 
  16-bit windows (like LOGFONT16, for instance).

The patch: (replaces the patch I sent out earlier today)

Index: include/gdi.h
===================================================================
RCS file: /home/wine/wine/include/gdi.h,v
retrieving revision 1.78
diff -u -r1.78 gdi.h
--- include/gdi.h	21 May 2003 18:28:49 -0000	1.78
+++ include/gdi.h	6 Jun 2003 19:27:40 -0000
@@ -52,6 +52,10 @@
 
 #define GDIMAGIC(magic) ((magic) & ~(OBJECT_PRIVATE|OBJECT_NOSYSTEM))
 
+/* pGetObjectSize added 6/4/2003 in order to support GetObject with NULL 
buffer
+ *  - according to PSDK this should return the size of the buffer required to
+ *    the call of GetObject.
+ */
 struct gdi_obj_funcs
 {
     HGDIOBJ (*pSelectObject)( HGDIOBJ handle, void *obj, HDC hdc );
@@ -60,6 +64,9 @@
     INT     (*pGetObjectW)( HGDIOBJ handle, void *obj, INT count, LPVOID 
buffer );
     BOOL    (*pUnrealizeObject)( HGDIOBJ handle, void *obj );
     BOOL    (*pDeleteObject)( HGDIOBJ handle, void *obj );
+    INT     (*pGetObjectSizeA)( HGDIOBJ handle, void *obj );
+    INT     (*pGetObjectSizeW)( HGDIOBJ handle, void *obj );
+    INT     (*pGetObjectSize16)( HGDIOBJ handle, void *obj );
 };
 
 typedef struct tagGDIOBJHDR
Index: objects/bitmap.c
===================================================================
RCS file: /home/wine/wine/objects/bitmap.c,v
retrieving revision 1.56
diff -u -r1.56 bitmap.c
--- objects/bitmap.c	13 May 2003 23:56:12 -0000	1.56
+++ objects/bitmap.c	6 Jun 2003 19:27:43 -0000
@@ -36,15 +36,20 @@
 static INT BITMAP_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID 
buffer );
 static INT BITMAP_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID 
buffer );
 static BOOL BITMAP_DeleteObject( HGDIOBJ handle, void *obj );
+static INT BITMAP_GetObjectSize( HGDIOBJ handle, void *obj );
+static INT BITMAP_GetObjectSize16( HGDIOBJ handle, void *obj );
 
 static const struct gdi_obj_funcs bitmap_funcs =
 {
-    BITMAP_SelectObject,  /* pSelectObject */
-    BITMAP_GetObject16,   /* pGetObject16 */
-    BITMAP_GetObject,     /* pGetObjectA */
-    BITMAP_GetObject,     /* pGetObjectW */
-    NULL,                 /* pUnrealizeObject */
-    BITMAP_DeleteObject   /* pDeleteObject */
+    BITMAP_SelectObject,   /* pSelectObject */
+    BITMAP_GetObject16,    /* pGetObject16 */
+    BITMAP_GetObject,      /* pGetObjectA */
+    BITMAP_GetObject,      /* pGetObjectW */
+    NULL,                  /* pUnrealizeObject */
+    BITMAP_DeleteObject,   /* pDeleteObject */
+    BITMAP_GetObjectSize,  /* pGetObjectSizeA */
+    BITMAP_GetObjectSize,  /* pGetObjectSizeW */
+    BITMAP_GetObjectSize16 /* pGetObjectSize16 */
 };
 
 /***********************************************************************
@@ -573,6 +578,25 @@
 	memcpy( buffer, &bmp->bitmap, count );
 	return count;
     }
+}
+
+
+/******************************************************************************
+ *           BITMAP_GetObjectSize
+ */
+static INT BITMAP_GetObjectSize( HGDIOBJ handle, void *obj )
+{
+    BITMAPOBJ *bmp = obj;
+    return (bmp->dib) ? sizeof(DIBSECTION) : sizeof(BITMAP);
+}
+
+
+/******************************************************************************
+ *           BITMAP_GetObjectSize16
+ */
+static INT BITMAP_GetObjectSize16( HGDIOBJ handle, void *obj )
+{
+    return sizeof(BITMAP16);
 }
 
 
Index: objects/brush.c
===================================================================
RCS file: /home/wine/wine/objects/brush.c,v
retrieving revision 1.34
diff -u -r1.34 brush.c
--- objects/brush.c	22 Nov 2002 22:16:53 -0000	1.34
+++ objects/brush.c	6 Jun 2003 19:27:44 -0000
@@ -44,15 +44,20 @@
 static INT BRUSH_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID 
buffer );
 static INT BRUSH_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID 
buffer );
 static BOOL BRUSH_DeleteObject( HGDIOBJ handle, void *obj );
+static INT BRUSH_GetObjectSize( HGDIOBJ handle, void *obj );
+static INT BRUSH_GetObjectSize16( HGDIOBJ handle, void *obj );
 
 static const struct gdi_obj_funcs brush_funcs =
 {
-    BRUSH_SelectObject,  /* pSelectObject */
-    BRUSH_GetObject16,   /* pGetObject16 */
-    BRUSH_GetObject,     /* pGetObjectA */
-    BRUSH_GetObject,     /* pGetObjectW */
-    NULL,                /* pUnrealizeObject */
-    BRUSH_DeleteObject   /* pDeleteObject */
+    BRUSH_SelectObject,   /* pSelectObject */
+    BRUSH_GetObject16,    /* pGetObject16 */
+    BRUSH_GetObject,      /* pGetObjectA */
+    BRUSH_GetObject,      /* pGetObjectW */
+    NULL,                 /* pUnrealizeObject */
+    BRUSH_DeleteObject,   /* pDeleteObject */
+    BRUSH_GetObjectSize,  /* pGetObjectSizeA */
+    BRUSH_GetObjectSize,  /* pGetObjectSizeW */
+    BRUSH_GetObjectSize16 /* pGetObjectSize16 */
 };
 
 static HGLOBAL16 dib_copy(BITMAPINFO *info, UINT coloruse)
@@ -355,6 +360,24 @@
     if (count > sizeof(brush->logbrush)) count = sizeof(brush->logbrush);
     memcpy( buffer, &brush->logbrush, count );
     return count;
+}
+
+
+/***********************************************************************
+ *           BRUSH_GetObjectSize
+ */
+static INT BRUSH_GetObjectSize( HGDIOBJ handle, void *obj )
+{
+    return sizeof(LOGBRUSH);
+}
+
+
+/***********************************************************************
+ *           BRUSH_GetObjectSize16
+ */
+static INT BRUSH_GetObjectSize16( HGDIOBJ handle, void *obj )
+{
+    return sizeof(LOGBRUSH16);
 }
 
 
Index: objects/dc.c
===================================================================
RCS file: /home/wine/wine/objects/dc.c,v
retrieving revision 1.95
diff -u -r1.95 dc.c
--- objects/dc.c	19 May 2003 23:23:50 -0000	1.95
+++ objects/dc.c	6 Jun 2003 19:27:47 -0000
@@ -42,7 +42,10 @@
     NULL,             /* pGetObjectA */
     NULL,             /* pGetObjectW */
     NULL,             /* pUnrealizeObject */
-    DC_DeleteObject   /* pDeleteObject */
+    DC_DeleteObject,  /* pDeleteObject */
+    NULL,             /* pGetObjectSizeA */
+    NULL,             /* pGetObjectSizeW */
+    NULL              /* pGetObjectSize16 */
 };
 
 /***********************************************************************
Index: objects/font.c
===================================================================
RCS file: /home/wine/wine/objects/font.c,v
retrieving revision 1.98
diff -u -r1.98 font.c
--- objects/font.c	19 May 2003 23:24:30 -0000	1.98
+++ objects/font.c	6 Jun 2003 19:27:52 -0000
@@ -40,15 +40,21 @@
 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID 
buffer );
 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID 
buffer );
 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
+static INT FONT_GetObjectSizeA( HGDIOBJ handle, void *obj );
+static INT FONT_GetObjectSizeW( HGDIOBJ handle, void *obj );
+static INT FONT_GetObjectSize16( HGDIOBJ handle, void *obj );
 
 static const struct gdi_obj_funcs font_funcs =
 {
-    FONT_SelectObject,  /* pSelectObject */
-    FONT_GetObject16,   /* pGetObject16 */
-    FONT_GetObjectA,    /* pGetObjectA */
-    FONT_GetObjectW,    /* pGetObjectW */
-    NULL,               /* pUnrealizeObject */
-    FONT_DeleteObject   /* pDeleteObject */
+    FONT_SelectObject,    /* pSelectObject */
+    FONT_GetObject16,     /* pGetObject16 */
+    FONT_GetObjectA,      /* pGetObjectA */
+    FONT_GetObjectW,      /* pGetObjectW */
+    NULL,                 /* pUnrealizeObject */
+    FONT_DeleteObject,    /* pDeleteObject */
+    FONT_GetObjectSizeA,  /* pGetObjectSizeA */
+    FONT_GetObjectSizeW,  /* pGetObjectSizeW */
+    FONT_GetObjectSize16  /* pGetObjectSize16 */
 };
 
 #define ENUM_UNICODE	0x00000001
@@ -463,6 +469,7 @@
     return count;
 }
 
+
 /***********************************************************************
  *           FONT_GetObjectA
  */
@@ -479,6 +486,7 @@
     return count;
 }
 
+
 /***********************************************************************
  *           FONT_GetObjectW
  */
@@ -499,6 +507,33 @@
 {
     WineEngDestroyFontInstance( handle );
     return GDI_FreeObject( handle, obj );
+}
+
+
+/***********************************************************************
+ *           FONT_GetObjectSizeA
+ */
+static INT FONT_GetObjectSizeA( HGDIOBJ handle, void *obj )
+{
+    return sizeof(LOGFONTA);
+}
+
+
+/***********************************************************************
+ *           FONT_GetObjectSizeW
+ */
+static INT FONT_GetObjectSizeW( HGDIOBJ handle, void *obj )
+{
+    return sizeof(LOGFONTW);
+}
+
+
+/***********************************************************************
+ *           FONT_GetObjectSize16
+ */
+static INT FONT_GetObjectSize16( HGDIOBJ handle, void *obj )
+{
+    return sizeof(LOGFONT16);
 }
 
 
Index: objects/gdiobj.c
===================================================================
RCS file: /home/wine/wine/objects/gdiobj.c,v
retrieving revision 1.87
diff -u -r1.87 gdiobj.c
--- objects/gdiobj.c	21 May 2003 18:28:49 -0000	1.87
+++ objects/gdiobj.c	6 Jun 2003 19:27:55 -0000
@@ -919,11 +919,13 @@
     INT16 result = 0;
 
     TRACE("%p %d %p\n", handle, count, buffer );
-    if (!count) return 0;
+    if (!count && buffer) return 0;
 
     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
 
-    if (ptr->funcs && ptr->funcs->pGetObject16)
+    if (!buffer && ptr->funcs && ptr->funcs->pGetObjectSize16)
+        result = ptr->funcs->pGetObjectSize16( handle, ptr );
+    else if (buffer && ptr->funcs && ptr->funcs->pGetObject16)
         result = ptr->funcs->pGetObject16( handle, ptr, count, buffer );
     else
         SetLastError( ERROR_INVALID_HANDLE );
@@ -941,11 +943,13 @@
     GDIOBJHDR * ptr;
     INT result = 0;
     TRACE("%p %d %p\n", handle, count, buffer );
-    if (!count) return 0;
+    if (!count && buffer) return 0;
 
     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
 
-    if (ptr->funcs && ptr->funcs->pGetObjectA)
+    if (!buffer && ptr->funcs && ptr->funcs->pGetObjectSizeA)
+        result = ptr->funcs->pGetObjectSizeA( handle, ptr );
+    else if (buffer && ptr->funcs && ptr->funcs->pGetObjectA)
         result = ptr->funcs->pGetObjectA( handle, ptr, count, buffer );
     else
         SetLastError( ERROR_INVALID_HANDLE );
@@ -962,11 +966,13 @@
     GDIOBJHDR * ptr;
     INT result = 0;
     TRACE("%p %d %p\n", handle, count, buffer );
-    if (!count) return 0;
+    if (!count && buffer) return 0;
 
     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
 
-    if (ptr->funcs && ptr->funcs->pGetObjectW)
+    if (!buffer && ptr->funcs && ptr->funcs->pGetObjectSizeW) 
+        result = ptr->funcs->pGetObjectSizeW( handle, ptr );
+    else if (buffer && ptr->funcs && ptr->funcs->pGetObjectW)
         result = ptr->funcs->pGetObjectW( handle, ptr, count, buffer );
     else
         SetLastError( ERROR_INVALID_HANDLE );
Index: objects/palette.c
===================================================================
RCS file: /home/wine/wine/objects/palette.c,v
retrieving revision 1.55
diff -u -r1.55 palette.c
--- objects/palette.c	1 Feb 2003 00:36:38 -0000	1.55
+++ objects/palette.c	6 Jun 2003 19:27:57 -0000
@@ -41,6 +41,7 @@
 static INT PALETTE_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID 
buffer );
 static BOOL PALETTE_UnrealizeObject( HGDIOBJ handle, void *obj );
 static BOOL PALETTE_DeleteObject( HGDIOBJ handle, void *obj );
+static INT PALETTE_GetObjectSize( HGDIOBJ handle, void *obj );
 
 static const struct gdi_obj_funcs palette_funcs =
 {
@@ -49,7 +50,10 @@
     PALETTE_GetObject,        /* pGetObjectA */
     PALETTE_GetObject,        /* pGetObjectW */
     PALETTE_UnrealizeObject,  /* pUnrealizeObject */
-    PALETTE_DeleteObject      /* pDeleteObject */
+    PALETTE_DeleteObject,     /* pDeleteObject */
+    PALETTE_GetObjectSize,    /* pGetObjectSizeA */
+    PALETTE_GetObjectSize,    /* pGetObjectSizeW */
+    PALETTE_GetObjectSize     /* pGetObjectSize16 */
 };
 
 /* Pointers to USER implementation of SelectPalette/RealizePalette */
@@ -628,6 +632,14 @@
     if (count > sizeof(WORD)) count = sizeof(WORD);
     memcpy( buffer, &palette->logpalette.palNumEntries, count );
     return count;
+}
+
+/***********************************************************************
+ *           PALETTE_GetObjectSize
+ */
+static INT PALETTE_GetObjectSize( HGDIOBJ handle, void *obj )
+{
+    return sizeof(WORD);
 }
 
 
Index: objects/pen.c
===================================================================
RCS file: /home/wine/wine/objects/pen.c,v
retrieving revision 1.22
diff -u -r1.22 pen.c
--- objects/pen.c	21 Nov 2002 21:50:04 -0000	1.22
+++ objects/pen.c	6 Jun 2003 19:27:58 -0000
@@ -41,15 +41,20 @@
 static HGDIOBJ PEN_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
 static INT PEN_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID 
buffer );
 static INT PEN_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID buffer 
);
+static INT PEN_GetObjectSize( HGDIOBJ handle, void *obj );
+static INT PEN_GetObjectSize16( HGDIOBJ handle, void *obj );
 
 static const struct gdi_obj_funcs pen_funcs =
 {
-    PEN_SelectObject,  /* pSelectObject */
-    PEN_GetObject16,   /* pGetObject16 */
-    PEN_GetObject,     /* pGetObjectA */
-    PEN_GetObject,     /* pGetObjectW */
-    NULL,              /* pUnrealizeObject */
-    GDI_FreeObject     /* pDeleteObject */
+    PEN_SelectObject,   /* pSelectObject */
+    PEN_GetObject16,    /* pGetObject16 */
+    PEN_GetObject,      /* pGetObjectA */
+    PEN_GetObject,      /* pGetObjectW */
+    NULL,               /* pUnrealizeObject */
+    GDI_FreeObject,     /* pDeleteObject */
+    PEN_GetObjectSize,  /* pGetObjectSize */
+    PEN_GetObjectSize,  /* pGetObjectSize */
+    PEN_GetObjectSize16 /* pGetObjectSize16 */
 };
 
 
@@ -170,4 +175,22 @@
     if (count > sizeof(pen->logpen)) count = sizeof(pen->logpen);
     memcpy( buffer, &pen->logpen, count );
     return count;
+}
+
+
+/***********************************************************************
+ *           PEN_GetObjectSize
+ */
+static INT PEN_GetObjectSize( HGDIOBJ handle, void *obj )
+{
+  return sizeof(LOGPEN);
+}
+
+
+/***********************************************************************
+ *           PEN_GetObjectSize
+ */
+static INT PEN_GetObjectSize16( HGDIOBJ handle, void *obj )
+{
+  return sizeof(LOGPEN16);
 }
Index: objects/region.c
===================================================================
RCS file: /home/wine/wine/objects/region.c,v
retrieving revision 1.55
diff -u -r1.55 region.c
--- objects/region.c	19 May 2003 19:03:19 -0000	1.55
+++ objects/region.c	6 Jun 2003 19:28:04 -0000
@@ -128,7 +128,10 @@
     NULL,                 /* pGetObjectA */
     NULL,                 /* pGetObjectW */
     NULL,                 /* pUnrealizeObject */
-    REGION_DeleteObject   /* pDeleteObject */
+    REGION_DeleteObject,  /* pDeleteObject */
+    NULL,                 /* pGetObjectSizeA */
+    NULL,                 /* pGetObjectSizeW */
+    NULL                  /* pGetObjectSize16 */
 };
 
 /*  1 if two RECTs overlap.




More information about the wine-patches mailing list