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