rendered paste bodyFrom 9e45225f04f17f4fb5ba448508b82c6b7c78047b Mon Sep 17 00:00:00 2001
From: Peter Oberndorfer <kumbayo84@arcor.de>
Date: Tue, 19 Dec 2006 21:23:34 +0100
Subject: [PATCH] winedbg: remote gdi object debugging
---
programs/winedbg/dbg.y | 4 +-
programs/winedbg/debug.l | 1 +
programs/winedbg/debugger.h | 1 +
programs/winedbg/info.c | 248 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 253 insertions(+), 1 deletions(-)
diff --git a/programs/winedbg/dbg.y b/programs/winedbg/dbg.y
index 0c225e1..8578543 100644
--- a/programs/winedbg/dbg.y
+++ b/programs/winedbg/dbg.y
@@ -53,7 +53,7 @@ static int dbg_error(const char*);
%token tCONT tPASS tSTEP tLIST tNEXT tQUIT tHELP tBACKTRACE tALL tINFO tUP tDOWN
%token tENABLE tDISABLE tBREAK tHBREAK tWATCH tDELETE tSET tPRINT tEXAM
%token tABORT tECHO
-%token tCLASS tMAPS tSTACK tSEGMENTS tSYMBOL tREGS tALLREGS tWND tQUEUE tLOCAL tEXCEPTION
+%token tCLASS tGDIOBJ tMAPS tSTACK tSEGMENTS tSYMBOL tREGS tALLREGS tWND tQUEUE tLOCAL tEXCEPTION
%token tPROCESS tTHREAD tMODREF tEOL tEOF
%token tFRAME tSHARE tCOND tDISPLAY tUNDISPLAY tDISASSEMBLE
%token tSTEPI tNEXTI tFINISH tSHOW tDIR tWHATIS tSOURCE
@@ -271,6 +271,7 @@ info_command:
| tINFO tDISPLAY { display_info(); }
| tINFO tCLASS { info_win32_class(NULL, NULL); }
| tINFO tCLASS tSTRING { info_win32_class(NULL, $3); }
+ | tINFO tGDIOBJ { info_gdiobj();}
| tINFO tWND { info_win32_window(NULL, FALSE); }
| tINFO tWND expr_rvalue { info_win32_window((HWND)$3, FALSE); }
| tINFO '*' tWND { info_win32_window(NULL, TRUE); }
@@ -281,6 +282,7 @@ info_command:
| tINFO tEXCEPTION expr_rvalue { info_win32_exceptions($3); }
| tINFO tMAPS { info_win32_virtual(dbg_curr_pid); }
| tINFO tMAPS expr_rvalue { info_win32_virtual($3); }
+ | tINFO tIDENTIFIER { dbg_printf("Undefined info command \"%s\", use \"help info\" to get a list\n", $2); }
;
maintenance_command:
diff --git a/programs/winedbg/debug.l b/programs/winedbg/debug.l
index 451c96d..847f92b 100644
--- a/programs/winedbg/debug.l
+++ b/programs/winedbg/debug.l
@@ -184,6 +184,7 @@ STRING \"[^\n"]+\"
<INFO_CMD>share|shar|sha { return tSHARE; }
<INFO_CMD>locals|local|loca|loc { return tLOCAL; }
<INFO_CMD>class|clas|cla { return tCLASS; }
+<INFO_CMD>gdiobj|gdi { return tGDIOBJ; }
<INFO_CMD>process|proces|proce|proc { return tPROCESS; }
<INFO_CMD>threads|thread|threa|thre|thr|th { return tTHREAD; }
<INFO_CMD>exception|except|exc|ex { return tEXCEPTION; }
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h
index 6e4c010..e3006d1 100644
--- a/programs/winedbg/debugger.h
+++ b/programs/winedbg/debugger.h
@@ -334,6 +334,7 @@ extern void info_win32_excep
extern void info_win32_virtual(DWORD pid);
extern void info_win32_segments(DWORD start, int length);
extern void info_wine_dbg_channel(BOOL add, const char* chnl, const char* name);
+extern void info_gdiobj(void);
/* memory.c */
extern BOOL memory_read_value(const struct dbg_lvalue* lvalue, DWORD size, void* result);
diff --git a/programs/winedbg/info.c b/programs/winedbg/info.c
index c5b7b1e..bfaf728 100644
--- a/programs/winedbg/info.c
+++ b/programs/winedbg/info.c
@@ -32,6 +32,139 @@
#include "tlhelp32.h"
#include "wine/debug.h"
+#define GDI_HEAP_SIZE 0xffe0
+#define GDI_FIRST_LARGE_HANDLE 16
+#define GDI_MAX_LARGE_HANDLES ((GDI_HEAP_SIZE >> 2) - GDI_FIRST_LARGE_HANDLE)
+
+ /* GDI objects magic numbers */
+#define FIRST_MAGIC 0x4f47
+#define PEN_MAGIC 0x4f47
+#define BRUSH_MAGIC 0x4f48
+#define FONT_MAGIC 0x4f49
+#define PALETTE_MAGIC 0x4f4a
+#define BITMAP_MAGIC 0x4f4b
+#define REGION_MAGIC 0x4f4c
+#define DC_MAGIC 0x4f4d
+#define DISABLED_DC_MAGIC 0x4f4e
+#define META_DC_MAGIC 0x4f4f
+#define METAFILE_MAGIC 0x4f50
+#define METAFILE_DC_MAGIC 0x4f51
+#define ENHMETAFILE_MAGIC 0x4f52
+#define ENHMETAFILE_DC_MAGIC 0x4f53
+#define MEMORY_DC_MAGIC 0x4f54
+#define EXT_PEN_MAGIC 0x4f55
+#define LAST_MAGIC 0x4f55
+
+#define MAGIC_DONTCARE 0xffff
+
+/* GDI constants for making objects private/system (naming undoc. !) */
+#define OBJECT_PRIVATE 0x2000
+#define OBJECT_NOSYSTEM 0x8000
+
+#define GDIMAGIC(magic) ((magic) & ~(OBJECT_PRIVATE|OBJECT_NOSYSTEM))
+
+struct hdc_list
+{
+ HDC hdc;
+ struct hdc_list *next;
+};
+
+typedef struct tagGDIOBJHDR
+{
+ WORD wMagic;
+ DWORD dwCount;
+ const struct gdi_obj_funcs *funcs;
+ struct hdc_list *hdcs;
+} GDIOBJHDR;
+
+typedef struct { int opaque; } *PHYSDEV; /* PHYSDEV is an opaque pointer */
+typedef LRESULT (CALLBACK *FARPROC16)();
+typedef unsigned short BOOL16;
+typedef unsigned short HDC16;//no idea if this is right
+typedef BOOL16 (CALLBACK *DCHOOKPROC)(HDC16,WORD,DWORD,LPARAM);
+typedef struct tagDC
+{
+ GDIOBJHDR header;
+ HDC hSelf; /* Handle to this DC */
+ const struct tagDC_FUNCS *funcs; /* DC function table */
+ PHYSDEV physDev; /* Physical device (driver-specific) */
+ INT saveLevel;
+ HDC saved_dc;
+ DWORD dwHookData;
+ FARPROC16 hookProc; /* the original SEGPTR ... */
+ DCHOOKPROC hookThunk; /* ... and the thunk to call it */
+
+ INT wndOrgX; /* Window origin */
+ INT wndOrgY;
+ INT wndExtX; /* Window extent */
+ INT wndExtY;
+ INT vportOrgX; /* Viewport origin */
+ INT vportOrgY;
+ INT vportExtX; /* Viewport extent */
+ INT vportExtY;
+ FLOAT miterLimit;
+
+ int flags;
+ DWORD layout;
+ HRGN hClipRgn; /* Clip region (may be 0) */
+ HRGN hMetaRgn; /* Meta region (may be 0) */
+ HRGN hMetaClipRgn; /* Intersection of meta and clip regions (may be 0) */
+ HRGN hVisRgn; /* Visible region (must never be 0) */
+ HPEN hPen;
+ HBRUSH hBrush;
+ HFONT hFont;
+ HBITMAP hBitmap;
+ HANDLE hDevice;
+ HPALETTE hPalette;
+
+// GdiFont *gdiFont;
+// GdiPath path;
+//
+// WORD ROPmode;
+// WORD polyFillMode;
+// WORD stretchBltMode;
+// WORD relAbsMode;
+// WORD backgroundMode;
+// COLORREF backgroundColor;
+// COLORREF textColor;
+// COLORREF dcBrushColor;
+// COLORREF dcPenColor;
+// short brushOrgX;
+// short brushOrgY;
+//
+// WORD textAlign; /* Text alignment from SetTextAlign() */
+// INT charExtra; /* Spacing from SetTextCharacterExtra() */
+// INT breakExtra; /* breakTotalExtra / breakCount */
+// INT breakRem; /* breakTotalExtra % breakCount */
+// INT MapMode;
+// INT GraphicsMode; /* Graphics mode */
+// ABORTPROC pAbortProc; /* AbortProc for Printing */
+// ABORTPROC16 pAbortProc16;
+// INT CursPosX; /* Current position */
+// INT CursPosY;
+// INT ArcDirection;
+// XFORM xformWorld2Wnd; /* World-to-window transformation */
+// XFORM xformWorld2Vport; /* World-to-viewport transformation */
+// XFORM xformVport2World; /* Inverse of the above transformation */
+// BOOL vport2WorldValid; /* Is xformVport2World valid? */
+// RECT BoundsRect; /* Current bounding rect */
+//
+// struct saved_visrgn *saved_visrgn;
+} DC;
+
+typedef struct tagBITMAPOBJ
+{
+ GDIOBJHDR header;
+ BITMAP bitmap;
+ SIZE size; /* For SetBitmapDimension() */
+ const struct DC_FUNCTIONS *funcs; /* DC function table */
+ /* For device-independent bitmaps: */
+ DIBSECTION *dib;
+// SEGPTR segptr_bits; /* segptr to DIB bits */
+// RGBQUAD *color_table; /* DIB color table if <= 8bpp */
+// UINT nb_colors; /* number of colors in table */
+} BITMAPOBJ;
+
WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
/***********************************************************************
@@ -730,3 +863,118 @@ void info_wine_dbg_channel(BOOL turn_on,
if (!done) dbg_printf("Unable to find debug channel %s\n", name);
else WINE_TRACE("Changed %d channel instances\n", done);
}
+
+static const char * magic_to_text(WORD magic)
+{
+ static char buffer[50];
+ switch(magic)
+ {
+ case PEN_MAGIC: return "PEN ";
+ case BRUSH_MAGIC: return "BRUSH ";
+ case FONT_MAGIC: return "FONT ";
+ case PALETTE_MAGIC: return "PALETTE ";
+ case BITMAP_MAGIC: return "BITMAP ";
+ case REGION_MAGIC: return "REGION ";
+ case DC_MAGIC: return "DC ";
+ case DISABLED_DC_MAGIC: return "DISABLED_DC ";
+ case META_DC_MAGIC: return "META_DC ";
+ case METAFILE_MAGIC: return "PENMETAFILE ";
+ case METAFILE_DC_MAGIC: return "METAFILE_DC ";
+ case ENHMETAFILE_MAGIC: return "ENHMETAFILE ";
+ case ENHMETAFILE_DC_MAGIC: return "ENHMETAFILE_DC ";
+ case MEMORY_DC_MAGIC: return "MEMORY_DC ";
+ case EXT_PEN_MAGIC: return "EXT_PEN ";
+ default:
+ sprintf(buffer, "unknown 0x%02x ", magic);
+ return buffer;
+ }
+}
+
+void info_dc(DC* dc)
+{
+ /* for now only print the bitmap brush font and palette */
+ dbg_printf("hBitmap %p", dc->hBitmap);
+ dbg_printf(" hPen %p hBrush %p hFont %p hPalette %p", dc->hPen, dc->hBrush, dc->hFont, dc->hPalette);
+}
+
+void info_bitmap(BITMAPOBJ* bmp)
+{
+ /* for now only print the bitmap size */
+ dbg_printf("Size: %d x %d, %d Bit", bmp->bitmap.bmWidth, bmp->bitmap.bmHeight, bmp->bitmap.bmBitsPixel);
+}
+
+
+void info_gdiobj(void)
+{
+ void* addr;
+ GDIOBJHDR* local[GDI_MAX_LARGE_HANDLES];
+ int i;
+ SYMBOL_INFO sym;
+
+ sym.SizeOfStruct = sizeof(sym);
+ sym.MaxNameLen = 0;
+
+ if(!SymFromName(dbg_curr_process->handle, "gdi32!large_handles", &sym))
+ {
+ dbg_printf("Could not get table of GDI objects in target process\n");
+ return;
+ }
+ addr = (void *) sym.Address;
+ dbg_printf("\narray handle pointer type count\n");
+
+ dbg_read_memory(addr, &local, sizeof(local));
+ for(i = 0; i < GDI_MAX_LARGE_HANDLES; i++)
+ {
+ if(local[i] != 0)
+ {//i = ((UINT_PTR)handle >> 2) - FIRST_LARGE_HANDLE
+ GDIOBJHDR tmp;
+ dbg_printf("0x%04x, 0x%04x, %p ", i, (i + GDI_FIRST_LARGE_HANDLE)<<2, local[i]);
+ if(dbg_read_memory(local[i], &tmp, sizeof(tmp)))
+ {
+ dbg_printf("%s", magic_to_text(GDIMAGIC(tmp.wMagic)));
+// printf("magic: 0x%x ", GDIMAGIC(tmp.wMagic));
+ dbg_printf("%2d ", tmp.dwCount & ~0x80000000);
+ if(tmp.wMagic & OBJECT_PRIVATE)
+ dbg_printf("private ");
+ if(tmp.wMagic & OBJECT_NOSYSTEM)
+ dbg_printf("nosystem ");
+ if(tmp.dwCount & 0x80000000)
+ dbg_printf("(marked for deletion)");
+// dbg_printf("funcs: 0x%x ", tmp.funcs);
+ if(tmp.hdcs)
+ {
+ struct hdc_list tmp_list;
+ dbg_printf("hdcs: ");
+ dbg_read_memory(tmp.hdcs, &tmp_list, sizeof(tmp_list));
+ while(tmp_list.next)
+ {
+ printf("0x%04x ", tmp_list.hdc);
+ dbg_read_memory(tmp_list.next, &tmp_list, sizeof(tmp_list));
+ }
+ }
+ if(GDIMAGIC(tmp.wMagic) == DC_MAGIC ||
+ GDIMAGIC(tmp.wMagic) == MEMORY_DC_MAGIC)
+ {
+ DC dc_tmp;
+ if(dbg_read_memory(local[i], &dc_tmp, sizeof(dc_tmp)))
+ info_dc(&dc_tmp);
+ else
+ dbg_printf("could not read DC memory\n");
+ }
+ else if (GDIMAGIC(tmp.wMagic) == BITMAP_MAGIC)
+ {
+ BITMAPOBJ bmp_tmp;
+ if(dbg_read_memory(local[i], &bmp_tmp, sizeof(bmp_tmp)))
+ info_bitmap(&bmp_tmp);
+ else
+ dbg_printf("could not read BITMAP memory\n");
+ }
+ dbg_printf("\n");
+ }
+ else
+ dbg_printf("unreadable???\n");
+ }
+
+ }
+}
+
--
1.4.4