From 9e45225f04f17f4fb5ba448508b82c6b7c78047b Mon Sep 17 00:00:00 2001 From: Peter Oberndorfer 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"]+\" share|shar|sha { return tSHARE; } locals|local|loca|loc { return tLOCAL; } class|clas|cla { return tCLASS; } +gdiobj|gdi { return tGDIOBJ; } process|proces|proce|proc { return tPROCESS; } threads|thread|threa|thre|thr|th { return tTHREAD; } 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