WindowsXP-SP1/windows/advcore/gdiplus/gpexts/gpexts.cxx
2020-09-30 16:53:49 +02:00

261 lines
6.9 KiB
C++

/******************************Module*Header*******************************\
* Module Name: gpexts.cxx
*
* This file is for debugging tools and extensions.
*
* Created: 05-14-99
* Author: Adrian Secchia
*
* Copyright (c) 1990 Microsoft Corporation
\**************************************************************************/
#include "precomp.hxx"
extern "C" {
#include <excpt.h>
#include <ntstatus.h>
#include <wdbgexts.h>
};
/***************************************************************************\
* Global variables
\***************************************************************************/
WINDBG_EXTENSION_APIS ExtensionApis;
EXT_API_VERSION ApiVersion = { (GPVER_PRODUCTVERSION_W >> 8), (GPVER_PRODUCTVERSION_W & 0xff), EXT_API_VERSION_NUMBER64, 0 };
USHORT SavedMajorVersion;
USHORT SavedMinorVersion;
DllInit(
HANDLE hModule,
DWORD dwReason,
DWORD dwReserved
)
{
switch (dwReason) {
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_PROCESS_ATTACH:
break;
}
return TRUE;
}
VOID
WinDbgExtensionDllInit(
PWINDBG_EXTENSION_APIS64 lpExtensionApis, // 64Bit Change
USHORT MajorVersion,
USHORT MinorVersion
)
{
ExtensionApis = *lpExtensionApis;
SavedMajorVersion = MajorVersion;
SavedMinorVersion = MinorVersion;
return;
}
VOID
CheckVersion(
VOID
)
{
}
LPEXT_API_VERSION
ExtensionApiVersion(
VOID
)
{
return &ApiVersion;
}
char *gaszHelpCli[] = {
"=======================================================================\n"
,"GPEXTS client debugger extentions:\n"
,"-----------------------------------------------------------------------\n"
,"GDI+ UM debugger extensions\n"
,"dgraphics: dumps a Graphics structure\n"
,"dgpgraphics: dumps a GpGraphics structure\n"
,"dmh: dumps gdi+ memory header for memory tracking\n"
,"=======================================================================\n"
,NULL
};
DECLARE_API(help)
{
char **ppsz = gaszHelpCli;
while (*ppsz)
dprintf(*ppsz++);
}
char *gaszStatus[] = {
"Ok"
,"GenericError"
,"InvalidParameter"
,"OutOfMemory"
,"ObjectBusy"
,"InsufficientBuffer"
,"NotImplemented"
,"Win32Error"
,NULL
};
DECLARE_API(dgraphics)
{
ULONG Size;
using namespace Gdiplus;
GPOBJECT(Gdiplus::Graphics, g);
PARSE_POINTER(dgraphics_help);
ReadMemory(arg, g, sizeof(Gdiplus::Graphics), &Size);
dprintf("Graphics\n");
dprintf("GpGraphics *nativeGraphics %p\n", g->nativeGraphics);
dprintf("Status lastResult %s (%d)\n", gaszStatus[g->lastResult], g->lastResult);
return;
dgraphics_help:
dprintf("Usage: dgraphics [-?] graphics\n");
}
char *gaszGraphicsType[] = {
"GraphicsBitmap"
,"GraphicsScreen"
,"GraphicsMetafile"
,NULL
};
DECLARE_API(dgpgraphics)
{
ULONG Size;
GPOBJECT(GpGraphics, g);
PARSE_POINTER(dgpgraphics_help);
ReadMemory(arg, g, sizeof(GpGraphics), &Size);
dprintf("GpGraphics\n");
dprintf("GpLockable Lockable.LockCount %ld\n", g->Lockable.LockCount);
dprintf("BOOL Valid %s\n", (g->Tag == ObjectTagGraphics)?"True":"False");
dprintf("GpRect SurfaceBounds (%#lx, %#lx, %#lx, %#lx)\n",
g->SurfaceBounds.X,
g->SurfaceBounds.Y,
g->SurfaceBounds.Width,
g->SurfaceBounds.Height);
dprintf("DpBitmap *Surface %p\n", g->Surface);
dprintf("GpMetafile *Metafile %p\n", g->Metafile);
dprintf("GraphicsType Type %s (%d)\n", gaszGraphicsType[g->Type], g->Type);
dprintf("GpDevice *Device %p\n", g->Device);
dprintf("DpDriver *Driver %p\n", g->Driver);
dprintf("DpContext *Context %p\n", g->Context);
dprintf("&DpContext BottomContext %p\n", GPOFFSETOF(g->BottomContext));
dprintf("&DpRegion WindowClip %p\n", GPOFFSETOF(g->WindowClip));
return;
dgpgraphics_help:
dprintf("Usage: dgpgraphics [-?] graphics\n");
return;
}
// copied from Engine\runtime\standalone\mem.cpp
enum AllocTrackHeaderFlags
{
MemoryAllocated = 0x00000001,
MemoryFreed = 0x00000002, // useful in catching double frees
APIAllocation = 0x00000004
};
struct AllocTrackHeader {
struct AllocTrackHeader *flink;
struct AllocTrackHeader *blink;
DWORD size;
DWORD caller_address;
DWORD flags;
#if DBROWN
char *callerFileName;
INT callerLineNumber;
#endif
};
DECLARE_API(dmh)
{
ULONG Size;
BOOL bRecursive = FALSE;
BOOL bFLink = FALSE;
BOOL bBLink = FALSE;
BOOL bCount = FALSE;
BOOL bAPI = FALSE;
int count = 0;
GPOBJECT(AllocTrackHeader, hdr);
PARSE_POINTER(dmh_help);
if(parse_iFindSwitch(tokens, ntok, 'r')!=-1) { bRecursive = TRUE; }
if(parse_iFindSwitch(tokens, ntok, 'f')!=-1) { bFLink = TRUE; }
if(parse_iFindSwitch(tokens, ntok, 'b')!=-1) { bBLink = TRUE; }
if(parse_iFindSwitch(tokens, ntok, 'c')!=-1) { bCount = TRUE; }
if(parse_iFindSwitch(tokens, ntok, 'a')!=-1) { bAPI = TRUE; }
do {
ReadMemory(arg, hdr, sizeof(AllocTrackHeader), &Size);
if( !bAPI || (hdr->flags & APIAllocation) )
{
if(!bCount) {
dprintf("GPMEM Block (%p)\n", arg);
dprintf("FLink 0x%p\n", hdr->flink);
dprintf("BLink 0x%p\n", hdr->blink);
dprintf("size 0x%p\n", hdr->size);
dprintf("Allocation callsite 0x%p\n", hdr->caller_address);
dprintf("Flags 0x%p ", hdr->flags);
if(hdr->flags & APIAllocation) {dprintf("API");}
dprintf("\n");
}
count++;
}
arg = (UINT_PTR)(hdr->flink);
if(bBLink) arg = (UINT_PTR)(hdr->blink);
} while( bRecursive && arg );
if(bRecursive) {
dprintf("Total: %d\n", count);
}
return;
dmh_help:
dprintf("Usage: dmh [-?] [-rfbca] memoryblock\n");
dprintf(" FLink and BLink are forward and backward memory links in the\n"
" double linked list of tracked allocations\n");
dprintf(" Size is the amount of memory in this allocation\n");
dprintf(" Allocation Callsite is the return address of the GpMalloc call that\n"
" allocated this memory block. Unassemble to find the symbol\n");
dprintf(" The tracked memory list head is at gdiplus!gpmemAllocList\n");
dprintf(" -r recursive - default FLink \n");
dprintf(" -f follow FLink (only useful with -r)\n");
dprintf(" -b follow BLink (only useful with -r, will override -f)\n");
dprintf(" -c Suppress output, only display the count. Only useful with -r\n");
dprintf(" -a Only display blocks with the API flag set.\n");
return;
}