WINEDBG: add support to interrogate gdi objects

Mike McCormack mike at codeweavers.com
Thu Jan 20 21:01:10 CST 2005


ChangeLog:
Ulrich Czekalla <ulrich at codeweavers.com>
* add support to interrogate gdi objects
-------------- next part --------------
? programs/winedbg/gdiobj.c
Index: programs/winedbg/Makefile.in
===================================================================
RCS file: /home/wine/wine/programs/winedbg/Makefile.in,v
retrieving revision 1.7
diff -u -p -r1.7 Makefile.in
--- programs/winedbg/Makefile.in	18 Oct 2004 21:27:52 -0000	1.7
+++ programs/winedbg/Makefile.in	21 Jan 2005 03:00:29 -0000
@@ -5,7 +5,7 @@ VPATH     = @srcdir@
 MODULE    = winedbg.exe
 APPMODE   = -mconsole
 IMPORTS   = dbghelp advapi32 kernel32 ntdll
-DELAYIMPORTS = user32
+DELAYIMPORTS = user32 gdi32
 
 C_SRCS = \
 	be_alpha.c \
@@ -16,6 +16,7 @@ C_SRCS = \
 	display.c \
 	expr.c \
 	gdbproxy.c \
+	gdiobj.c \
 	info.c \
 	memory.c \
 	source.c \
Index: programs/winedbg/db_disasm.c
===================================================================
RCS file: /home/wine/wine/programs/winedbg/db_disasm.c,v
retrieving revision 1.4
diff -u -p -r1.4 db_disasm.c
--- programs/winedbg/db_disasm.c	4 Jun 2004 00:59:16 -0000	1.4
+++ programs/winedbg/db_disasm.c	21 Jan 2005 03:00:31 -0000
@@ -1184,7 +1184,7 @@ static void db_read_address( ADDRESS* ad
 	}
 }
 
-static void db_task_printsym(unsigned int addr, int size)
+static void db_task_printsym(unsigned int addr, int size, BOOL detail )
 {
     ADDRESS     a;
     a.Mode   = AddrModeFlat;
@@ -1226,14 +1226,15 @@ static void db_print_address(const char 
 	       } else if (!dbg_read_memory(a1, &a2, sizeof(a2))) {
 		  dbg_printf("(invalid destination)");
 	       } else {
-                   db_task_printsym((unsigned long)a1, 0);
+                   db_task_printsym((unsigned long)a1, 0, TRUE);
                }
 	    }
 	    else
-	       db_task_printsym(addrp->disp, size);
+	       db_task_printsym(addrp->disp, size, TRUE);
 	}
 }
 
+
 /*
  * Disassemble floating-point ("escape") instruction
  * and return updated location.
@@ -1738,7 +1739,7 @@ void be_i386_disasm_one_insn(ADDRESS *ad
 		    if (seg)
 			dbg_printf("%s:0x%x",seg, displ);
 		    else
-			db_task_printsym(displ, short_addr ? WORD : LONG);
+			db_task_printsym(displ, short_addr ? WORD : LONG, TRUE);
 		    break;
 
 		case Db:
@@ -1754,7 +1755,7 @@ void be_i386_disasm_one_insn(ADDRESS *ad
 			      | ((addr->Offset + displ) & 0xffff);
 		    }
 		    else displ += addr->Offset;
-		    db_task_printsym(displ, size);
+		    db_task_printsym(displ, size, TRUE);
 		    break;
 
 		case Dl:
@@ -1768,11 +1769,8 @@ void be_i386_disasm_one_insn(ADDRESS *ad
 			get_value_inc(displ, addr, 4, TRUE);
 			displ += addr->Offset;
 		    }
-		    if( !db_display )
-		      {
-			break;
-		      }
-		    db_task_printsym( displ, size );
+		    if( db_display )
+		        db_task_printsym( displ, size, TRUE );
 		    break;
 
 		case o1:
Index: programs/winedbg/dbg.y
===================================================================
RCS file: /home/wine/wine/programs/winedbg/dbg.y,v
retrieving revision 1.19
diff -u -p -r1.19 dbg.y
--- programs/winedbg/dbg.y	22 Dec 2004 18:38:31 -0000	1.19
+++ programs/winedbg/dbg.y	21 Jan 2005 03:00:31 -0000
@@ -56,6 +56,7 @@ int yyerror(const char*);
 %token <string> tPATH tIDENTIFIER tSTRING tDEBUGSTR tINTVAR
 %token <integer> tNUM tFORMAT
 %token tSYMBOLFILE tRUN tATTACH tDETACH tNOPROCESS tMAINTENANCE tTYPE
+%token tGDIOBJ
 
 %token tCHAR tSHORT tINT tLONG tFLOAT tDOUBLE tUNSIGNED tSIGNED
 %token tSTRUCT tUNION tENUM
@@ -253,6 +254,7 @@ info_command:
     | tINFO tSYMBOL tSTRING     { symbol_info($3); }
     | tINFO tLOCAL              { symbol_info_locals(); }
     | tINFO tDISPLAY            { display_info(); }
+    | tINFO tGDIOBJ expr_rvalue { info_gdiobj( (HGDIOBJ)$3 ); }
     | tINFO tCLASS              { info_win32_class(NULL, NULL); }
     | tINFO tCLASS tSTRING     	{ info_win32_class(NULL, $3); }
     | tINFO tWND                { info_win32_window(NULL, FALSE); }
Index: programs/winedbg/debug.l
===================================================================
RCS file: /home/wine/wine/programs/winedbg/debug.l,v
retrieving revision 1.10
diff -u -p -r1.10 debug.l
--- programs/winedbg/debug.l	23 Jun 2004 00:10:03 -0000	1.10
+++ programs/winedbg/debug.l	21 Jan 2005 03:00:31 -0000
@@ -185,6 +185,7 @@ STRING     \"[^\n"]+\"
 <HELP_CMD>info|inf|in                   { return tINFO; }
 <MODE_CMD>vm86                          { return tVM86; }
 <MAINT_CMD>type                         { return tTYPE; }
+<INFO_CMD>gdi|gdiobj                    { return tGDIOBJ; }
 
 <INITIAL,SHOW_CMD>directories|directorie|directori|director|directo|direct|direc|direc|dir {
 			                  BEGIN(PATH_EXPECTED); return tDIR; }
Index: programs/winedbg/debugger.h
===================================================================
RCS file: /home/wine/wine/programs/winedbg/debugger.h,v
retrieving revision 1.24
diff -u -p -r1.24 debugger.h
--- programs/winedbg/debugger.h	6 Dec 2004 16:35:33 -0000	1.24
+++ programs/winedbg/debugger.h	21 Jan 2005 03:00:31 -0000
@@ -290,6 +290,9 @@ extern struct expr*     expr_clone(const
 extern int              expr_free(struct expr* exp);
 extern int              expr_print(const struct expr* exp);
 
+  /* gdiobj.c */
+extern void             info_gdiobj(HGDIOBJ handle);
+
   /* info.c */
 extern void             print_help(void);
 extern void             info_help(void);
--- /dev/null	2004-12-26 03:00:47.000000000 +0900
+++ programs/winedbg/gdiobj.c	2005-01-21 11:57:54.000000000 +0900
@@ -0,0 +1,348 @@
+/*
+ * Wine debugger GDI Object interrogation routines
+ *
+ * Copyright 2003 Ulrich Czekalla for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "tlhelp32.h"
+#include "debugger.h"
+#include "expr.h"
+#include "wine/windef16.h"
+#include "gdi.h"
+
+typedef struct
+{
+    WORD addr;                /* Address of the MOVEABLE block */
+    BYTE flags;               /* Flags for this block */
+    BYTE lock;                /* Lock count */
+} LOCALHANDLEENTRY;
+
+#define HANDLE_MOVEABLE(handle) (((handle) & 3) == 2)
+#define FIRST_LARGE_HANDLE 16
+#define MAX_LARGE_HANDLES ((GDI_HEAP_SIZE >> 2) - FIRST_LARGE_HANDLE)
+
+typedef struct {
+    INT size;
+    INT numRects;
+    RECT *rects;
+    RECT extents;
+} WINEREGION;
+
+/* GDI logical region object */
+typedef struct
+{
+    GDIOBJHDR   header;
+    WINEREGION  *rgn;
+} RGNOBJ;
+
+/* GDI logical brush object */
+typedef struct
+{
+    GDIOBJHDR header;
+    LOGBRUSH  logbrush;
+} BRUSHOBJ;
+
+static void *DEBUG_GDI_GetObjPtr(HGDIOBJ handle, WORD magic);
+static void DEBUG_InfoRegion(GDIOBJHDR *ptr);
+static void DEBUG_InfoBitmap(GDIOBJHDR *ptr);
+static void DEBUG_InfoBrush(GDIOBJHDR *ptr);
+
+#define GDI_HEAP_SIZE 0xffe0
+
+/***********************************************************************
+ *           info_gdiobj
+ *
+ * Print information about GDI object
+ */
+void info_gdiobj(HGDIOBJ handle)
+{
+    GDIOBJHDR gdiobj;
+    GDIOBJHDR *ptr;
+   
+    ptr = DEBUG_GDI_GetObjPtr(handle, MAGIC_DONTCARE);
+
+    if (ptr)
+    {
+        dbg_read_memory(ptr, &gdiobj, sizeof(GDIOBJHDR));
+
+        switch (GDIMAGIC(gdiobj.wMagic))
+	{
+            case REGION_MAGIC:
+                DEBUG_InfoRegion(ptr);
+                break;
+
+	    case BITMAP_MAGIC:
+                DEBUG_InfoBitmap(ptr);
+                break;
+
+	    case BRUSH_MAGIC:
+                DEBUG_InfoBrush(ptr);
+                break;
+
+            default:
+                dbg_printf("wMagic=%04x\n", GDIMAGIC(gdiobj.wMagic));
+	}
+    }
+    else
+        dbg_printf("Invalid GDI handle %p\n", handle);
+}
+
+
+/***********************************************************************
+ *           DEBUG_LOCAL_InternalLock
+ */
+static HLOCAL16 DEBUG_LOCAL_InternalLock( LPSTR heap, HLOCAL16 handle )
+{
+    if (HANDLE_MOVEABLE(handle))
+    {
+        LOCALHANDLEENTRY *pEntry;
+        LOCALHANDLEENTRY entry;
+
+        pEntry = (LOCALHANDLEENTRY *) (heap + handle);
+        dbg_read_memory(pEntry, &entry, sizeof(LOCALHANDLEENTRY));
+
+        if (entry.flags == (LMEM_DISCARDED >> 8)) return 0;
+
+        handle = entry.addr;
+    }
+
+    return handle;
+}
+
+
+/***********************************************************************
+ *           DEBUG_LOCAL_Lock
+ */
+static void *DEBUG_LOCAL_Lock( HANDLE16 ds, HLOCAL16 handle )
+{
+    void *retptr = NULL;
+
+    if (handle)
+    {
+        struct dbg_lvalue rtn;
+
+        if (symbol_get_lvalue("wine_ldt_copy", -1, &rtn, FALSE) == sglv_found)
+        {
+            char *ptr;
+            BYTE *ldt;
+            DWORD segptr;
+
+            ldt = memory_to_linear_addr(&rtn.addr);
+            segptr = MAKESEGPTR( ds, 0 );
+
+            dbg_read_memory(ldt + ((SELECTOROF(segptr) >> __AHSHIFT) * sizeof(void*)),
+                &ptr, sizeof(char*));
+            ptr += OFFSETOF(segptr);
+
+            retptr = ptr + DEBUG_LOCAL_InternalLock( ptr, handle );
+        }
+    }
+
+    return retptr;
+}
+
+
+/***********************************************************************
+ *           DEBUG_GDI_GetObjPtr
+ */
+static void *DEBUG_GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
+{
+    GDIOBJHDR *ptr = NULL;
+
+    if ((UINT_PTR)handle & 2)  /* GDI heap handle */
+    {
+        struct dbg_lvalue rtn;
+        HLOCAL16 h = LOWORD(handle);
+
+        if (symbol_get_lvalue("GDI_HeapSel", -1, &rtn, FALSE) == sglv_found)
+        {
+            void *psel;
+            WORD gdi_heapsel;
+
+            psel = memory_to_linear_addr(&rtn.addr);
+            dbg_read_memory(psel, &gdi_heapsel, sizeof(gdi_heapsel));
+
+            ptr = (GDIOBJHDR *)DEBUG_LOCAL_Lock(gdi_heapsel, h);
+            if (ptr)
+            {
+                GDIOBJHDR gdiobj;
+
+                dbg_read_memory(ptr, &gdiobj, sizeof(GDIOBJHDR));
+
+                if (((magic != MAGIC_DONTCARE) && (GDIMAGIC(gdiobj.wMagic) != magic)) ||
+                   (GDIMAGIC(gdiobj.wMagic) < FIRST_MAGIC) ||
+                   (GDIMAGIC(gdiobj.wMagic) > LAST_MAGIC))
+                {
+                    ptr = NULL;
+                }
+            }
+        }
+    }
+    else  /* large heap handle */
+    {
+        int i = ((UINT_PTR)handle >> 2) - FIRST_LARGE_HANDLE;
+        if (i >= 0 && i < MAX_LARGE_HANDLES)
+        {
+            struct dbg_lvalue rtn;
+
+            if (symbol_get_lvalue("large_handles", -1, &rtn, FALSE) == sglv_found)
+            {
+                char* large_handles = memory_to_linear_addr(&rtn.addr);
+
+                dbg_read_memory(large_handles + (i * sizeof(GDIOBJHDR*)), 
+                    &ptr, sizeof(GDIOBJHDR*));
+
+                if (ptr)
+                {
+                    GDIOBJHDR gdiobj;
+
+		    dbg_read_memory(ptr, &gdiobj, sizeof(GDIOBJHDR));
+
+                    if ((magic != MAGIC_DONTCARE) && (GDIMAGIC(gdiobj.wMagic) != magic))
+                        ptr = NULL;
+                }
+	    }
+        }
+    }
+
+    return ptr;
+}
+
+
+/***********************************************************************
+ *           DEBUG_GetRegionData
+ */
+static DWORD DEBUG_GetRegionData(GDIOBJHDR *obj, DWORD count, LPRGNDATA rgndata)
+{
+    DWORD size;
+    RGNOBJ rgnobj;
+    WINEREGION winergn;
+
+    if(!obj)
+        return 0;
+
+    dbg_read_memory(obj, &rgnobj, sizeof(RGNOBJ));
+
+    if (!rgnobj.rgn)
+        return 0;
+
+    dbg_read_memory(rgnobj.rgn, &winergn, sizeof(WINEREGION));
+
+    size = winergn.numRects * sizeof(RECT);
+
+    if(count < (size + sizeof(RGNDATAHEADER)) || rgndata == NULL)
+    {
+	if (rgndata) /* buffer is too small, signal it by return 0 */
+	    return 0;
+	else		/* user requested buffer size with rgndata NULL */
+	    return size + sizeof(RGNDATAHEADER);
+    }
+
+    rgndata->rdh.dwSize = sizeof(RGNDATAHEADER);
+    rgndata->rdh.iType = RDH_RECTANGLES;
+    rgndata->rdh.nCount = winergn.numRects;
+    rgndata->rdh.nRgnSize = size;
+    rgndata->rdh.rcBound.left = winergn.extents.left;
+    rgndata->rdh.rcBound.top = winergn.extents.top;
+    rgndata->rdh.rcBound.right = winergn.extents.right;
+    rgndata->rdh.rcBound.bottom = winergn.extents.bottom;
+
+    dbg_read_memory(winergn.rects, rgndata->Buffer, size);
+
+    return size + sizeof(RGNDATAHEADER);
+}
+
+
+/***********************************************************************
+ *           DEBUG_InfoRegion
+ */
+static void DEBUG_InfoRegion(GDIOBJHDR *ptr)
+{
+    INT i;
+    DWORD size;
+    LPRECT lprect;
+    LPRGNDATA rgndata;
+
+    size = DEBUG_GetRegionData(ptr, 0, NULL);
+
+    if (size)
+    {
+        rgndata = (LPRGNDATA) HeapAlloc(GetProcessHeap(), 0, size);
+	size = DEBUG_GetRegionData(ptr, size, rgndata);
+
+        if (size)
+        {
+            dbg_printf( "Type=0x%08lx  count=%ld\n"
+                          "rcBound=%ld,%ld-%ld,%ld\n",
+                          rgndata->rdh.iType,
+                          rgndata->rdh.nCount,
+                          rgndata->rdh.rcBound.left, rgndata->rdh.rcBound.top,
+                          rgndata->rdh.rcBound.right, rgndata->rdh.rcBound.bottom);
+
+            lprect = (LPRECT) rgndata->Buffer;
+	    for (i = 0; i < rgndata->rdh.nCount; i++)
+                dbg_printf( "Rect%d=%ld,%ld-%ld,%ld\n",
+                              i,
+                              lprect[i].left, lprect[i].top,
+                              lprect[i].right, lprect[i].bottom);
+        }
+
+	HeapFree(GetProcessHeap(), 0, rgndata);
+    }
+}
+
+
+/***********************************************************************
+ *           DEBUG_InfoBitmap
+ */
+static void DEBUG_InfoBitmap(GDIOBJHDR *ptr)
+{
+    BITMAPOBJ bmp;
+
+    if (dbg_read_memory(ptr, &bmp, sizeof(bmp)))
+    {
+        dbg_printf( "Type=0x%08x\n"
+                      "width=%d height=%d widthBytes=%d planes=%d bitsPixel=%d\n",
+                      bmp.bitmap.bmType, bmp.bitmap.bmWidth, bmp.bitmap.bmHeight,
+                      bmp.bitmap.bmWidthBytes, bmp.bitmap.bmPlanes, bmp.bitmap.bmBitsPixel);
+    }
+}
+
+
+/***********************************************************************
+ *           DEBUG_InfoBrush
+ */
+static void DEBUG_InfoBrush(GDIOBJHDR *ptr)
+{
+    BRUSHOBJ brush;
+
+    if (dbg_read_memory(ptr, &brush, sizeof(brush)))
+    {
+        dbg_printf( "lbStyle=%d lbColor=0x%08lx lbHatch=%d\n",
+            brush.logbrush.lbStyle, brush.logbrush.lbColor, brush.logbrush.lbHatch);
+    }
+}


More information about the wine-patches mailing list