home *** CD-ROM | disk | FTP | other *** search
- /*
- GDIWALK.C -- GDI Local heap object browser
-
- Copyright (c) Dave Maxey 1992
-
- From Chapter 8 of "Undocumented Windows" (Addison-Wesley 1992)
- by Andrew Schulman, Dave Maxey and Matt Pietrek
-
- Build using: WINIOBC GDIWALK (for Borland C++ v3.00)
- WINIOMS GDIWALK (for Microsoft C/SDK)
- */
-
- #include <windows.h>
- #include <ctype.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <string.h>
- #include <dos.h>
- #include "toolhelp.h"
- #include "winio.h"
- #include "gdiobj.h"
-
- #ifndef __BORLANDC__
- #define MK_FP(a,b) ((void far *)(((unsigned long)(a) << 16) | (b)))
- #else
- #define asm _asm
- #endif
-
- typedef struct _LINESTOHEAP
- {
- WORD wHeap;
- int nFirstLine, nLastLine;
- } LINESTOHEAP;
-
- void WalkOneGDIHeap(WORD seg);
- void GDIHeapWalk(void);
- BOOL ContainsLocalHeap(WORD seg);
- void MainWndLine(HWND hwnd, LPSTR line, int lineNum);
- void OtherWndLine(HWND hwnd, LPSTR line, int lineNum);
- void DumpBlock(WORD wSel, WORD wOfs, WORD wBytes);
- void DumpPen(WORD wSel, WORD wOfs, WORD wBytes);
- void DumpBrush(WORD wSel, WORD wOfs, WORD wBytes);
- void DumpFont(WORD wSel, WORD wOfs, WORD wBytes);
- void DumpPalette(WORD wSel, WORD wOfs, WORD wBytes);
- void DumpBitmap(WORD wSel, WORD wOfs, WORD wBytes);
- void DumpRegion(WORD wSel, WORD wOfs, WORD wBytes);
- void DumpDC(WORD wSel, WORD wOfs, WORD wBytes);
- void DumpDisabledDC(WORD wSel, WORD wOfs, WORD wBytes);
- void DumpMetaDC(WORD wSel, WORD wOfs, WORD wBytes);
- void DumpMetaFile(WORD wSel, WORD wOfs, WORD wBytes);
- BOOL FarLocalSize(WORD wSel, WORD wH, WORD *pOfs, WORD *pSize);
- WORD MyGDIBlockType(WORD wSeg, WORD wOfs, WORD wType);
-
- #define ID_REFRESH 1
- #define MAXHEAPS 16
-
- LINESTOHEAP ltoh[MAXHEAPS] = {0};
-
- char szTitle[] = "GDI Heap Walker";
- char UnknownString[] = "<UNKNOWN>";
- int nLineNum = 0;
- int nHeaps;
- BOOL bDebug, b31;
-
- char *GDIBlockType[] =
- {
- "NORMAL", // 0
- "Pen", // 1
- "Brush", // 2
- "Font", // 3
- "Palette", // 4
- "Bitmap", // 5
- "Region", // 6
- "DC", // 7
- "Disabled DC", // 8
- "Meta DC", // 9
- "Metafile", // 10
- "Metafile DC" // 11
- };
-
- #define BLOCKTYPES (sizeof(GDIBlockType) / sizeof(char *))
-
-
- typedef void (* fnDUMP)(WORD wSel, WORD wOfs, WORD wBytes);
-
- fnDUMP fnDump[] =
- { DumpBlock, DumpPen, DumpBrush, DumpFont, DumpPalette, DumpBitmap,
- DumpRegion, DumpDC, DumpDisabledDC, DumpMetaDC, DumpMetaFile,
- DumpDC, DumpBlock };
-
- #define WINDOWSIZE(y, x) \
- ((DWORD) ((DWORD) ((unsigned)(y)) << 16) | ((unsigned)(x)))
-
- POINT pntSize[] = {
- { 76, -1 },
- { 44, 9 },
- { 46, 13 },
- { 45, 21 },
- { 50, 10 },
- { 48, 9 },
- { 76, -1 },
- { 47, 25 },
- { 47, 10 },
- { 50, 25 },
- { 50, 10 },
- { 47, 25 },
- { 76, -1 }
- };
-
- typedef struct {
- char *szField;
- int iType;
- } HFIELD;
-
- HFIELD hfld[] = {
- { "hMetaFile", 10 }, { "hrgnClip", 6 }, { "hLPen", 1 },
- { "hLBrush", 2 }, { "hLFont", 3 }, { "hBitmap", 5 },
- { "dchPal", 4 }, { "hrgnVisSave", 6 }, { "hdc", 7 } };
-
- #define MAXHFIELDS (sizeof(hfld) / sizeof(HFIELD))
-
- WORD verr(WORD sel)
- {
- _asm mov ax, 1
- _asm verr word ptr sel
- _asm je short ok
- _asm dec ax
- ok:;
- }
-
- WORD lsl(WORD wSel)
- {
- _asm sub ax, ax
- _asm lsl ax, wSel
- }
-
-
- void DumpHeader(LPGDIOBJHDR goh)
- {
- if (b31)
- {
- printf(
- "GDIOBJHDR:\n"
- "\thNext\t\t: %04X\n"
- "\twMagic\t\t: %04X (\"%c%c\")\n"
- "\tdwCount\t\t: %ld\n"
- "\twMetaList\t: %04X\n",
- goh->hNext, goh->wMagic,
- goh->wMagic & 0xff, goh->wMagic >> 8,
- goh->dwCount, goh->wMetaList);
- if (bDebug)
- printf(
- "\twSelCount\t: %d\n"
- "\thOwner\t\t: %04X\n",
- ((LPGDIOBJDBG) goh)->wSelCount,
- ((LPGDIOBJDBG) goh)->hOwner);
- }
- else
- {
- printf(
- "GDIOBJHDR:\n"
- "\twFlags\t\t: %04X\n"
- "\twObjType\t: %d\n"
- "\tdwCount\t\t: %ld\n"
- "\twMetaList\t: %04X\n",
- goh->hNext, goh->wMagic & 0xff,
- goh->dwCount, goh->wMetaList);
- }
-
- }
-
- void DumpPen(WORD wSel, WORD wOfs, WORD wBytes)
- {
- LPPENOBJ fp = (LPPENOBJ) MK_FP(wSel, wOfs);
-
- DumpHeader((LPGDIOBJHDR) &(fp->header));
- if (bDebug && b31) (DWORD) fp += 4;
- printf(
- "LOGPEN:\n"
- "\tlopnStyle\t: %04X\n"
- "\tlopnWidth\t: (%d, %d)\n"
- "\tlopnColor\t: %08lX\n",
- fp->logpen.lopnStyle,
- fp->logpen.lopnWidth.x,
- fp->logpen.lopnWidth.y,
- fp->logpen.lopnColor);
- }
-
- void DumpBrush(WORD wSel, WORD wOfs, WORD wBytes)
- {
- LPBRUSHOBJ fp = (LPBRUSHOBJ) MK_FP(wSel, wOfs);
-
- DumpHeader((LPGDIOBJHDR) &(fp->header));
- if (bDebug && b31) (DWORD) fp += 4;
- printf(
- "LOGBRUSH:\n"
- "\tlbStyle\t\t: %04X\n"
- "\tlbColor\t\t: %08lX\n"
- "\tlbHatch\t\t: %04X\n",
- fp->logbrush.lbStyle,
- fp->logbrush.lbColor,
- fp->logbrush.lbHatch);
- printf("crHatchBk\t\t: %08lX\n", fp->crHatchBk);
- }
-
- void DumpFont(WORD wSel, WORD wOfs, WORD wBytes)
- {
- LPFONTOBJ fp = (LPFONTOBJ) MK_FP(wSel, wOfs);
-
- DumpHeader((LPGDIOBJHDR) &(fp->header));
- if (bDebug && b31) (DWORD) fp += 4;
- printf(
- "LOGFONT:\n"
- "\tlfHeight\t: %d\n"
- "\tlfWidth\t\t: %d\n"
- "\tlfEscapement\t: %d\n"
- "\tlfOrientation\t: %d\n"
- "\tlfWeight\t: %d\n"
- "\tlfItalic\t: %d\n"
- "\tlfUnderline\t: %d\n"
- "\tlfStrikeOut\t: %d\n"
- "\tlfCharSet\t: %d\n"
- "\tlfOutPrecision\t: %d\n"
- "\tlfClipPrecision\t: %d\n"
- "\tlfQuality\t: %d\n"
- "\tlfPitchAndFamily: %04X\n"
- "\tlfFaceName\t: %Fs\n",
- fp->logfont.lfHeight,
- fp->logfont.lfWidth,
- fp->logfont.lfEscapement,
- fp->logfont.lfOrientation,
- fp->logfont.lfWeight,
- fp->logfont.lfItalic,
- fp->logfont.lfUnderline,
- fp->logfont.lfStrikeOut,
- fp->logfont.lfCharSet,
- fp->logfont.lfOutPrecision,
- fp->logfont.lfClipPrecision,
- fp->logfont.lfQuality,
- fp->logfont.lfPitchAndFamily,
- (LPSTR) &(fp->logfont.lfFaceName));
- }
-
- void DumpPalette(WORD wSel, WORD wOfs, WORD wBytes)
- {
- WORD i;
- LPPALETTEOBJ fp = (LPPALETTEOBJ) MK_FP(wSel, wOfs);
-
- DumpHeader((LPGDIOBJHDR) &(fp->header));
- if (bDebug && b31) (DWORD) fp += 4;
- printf(
- "LOGPALETTE:\n"
- "\tpalVersion\t: %4X\n"
- "\tpalNumEntries\t: %d\n",
- fp->logpalette.palVersion,
- fp->logpalette.palNumEntries);
- for (i = 0; i < fp->logpalette.palNumEntries; i++)
- printf("\tpalPalEntry[%d]\t: %08lX\n",
- i, *((DWORD FAR *) &(fp->logpalette.palPalEntry[i])));
- }
-
- void DumpBitmap(WORD wSel, WORD wOfs, WORD wBytes)
- {
- LPBITMAPOBJ fp = (LPBITMAPOBJ) MK_FP(wSel, wOfs);
-
- printf("Lines marked '->' may be double clicked\nfor expansion\n\n");
- DumpHeader((LPGDIOBJHDR) &(fp->header));
- if (bDebug) (DWORD) fp += 4;
- printf(
- "LOGBITMAP:\n"
- "\thmemBitmap\t: %04X\n"
- "\tbSelected\t: %04X\n"
- "\th0E\t\t: %04X\n",
- fp->hmemBitmap,
- fp->bSelected,
- fp->h0E);
- }
-
- void DumpRegion(WORD wSel, WORD wOfs, WORD wBytes)
- {
- DumpBlock(wSel, wOfs, wBytes);
- }
-
- void DumpDC(WORD wSel, WORD wOfs, WORD wBytes)
- {
- LPDC fp = (LPDC) MK_FP(wSel, wOfs);
-
- printf("Lines marked '->' may be double clicked\nfor expansion\n\n");
- DumpHeader((LPGDIOBJHDR) &(fp->header));
- if (bDebug && b31) (DWORD) fp += 4;
- printf(
- "DC:\n"
- "\tbyFlags\t\t: %02X\n"
- "\tbyFlags2\t: %02X\n"
- "->\thMetaFile\t: %04X\n"
- "->\thrgnClip\t: %04X\n"
- "\thPDevice\t: %04X\n"
- "->\thLPen\t\t: %04X\n"
- "->\thLBrush\t\t: %04X\n"
- "->\thLFont\t\t: %04X\n"
- "->\thBitmap\t\t: %04X\n"
- "->\tdchPal\t\t: %04X\n"
- "\thLDevice\t: %04X\n"
- "\thRaoClip\t: %04X\n"
- "\thPDeviceBlock\t: %04X\n"
- "\thPPen\t\t: %04X\n"
- "\thPBrush\t\t: %04X\n"
- "\thPFontTrans\t: %04X\n"
- "\thPFont\t\t: %04X\n"
- "\tlpPDevice\t: %Fp\n"
- "\tpLDevice\t: %04X\n"
- "\tpRaoClip\t: %04X\n",
- fp->byFlags, fp->byFlags2, fp->hMetaFile, fp->hrgnClip,
- fp->hPDevice, fp->hLPen, fp->hLBrush, fp->hLFont,
- fp->hBitmap, fp->dchPal, fp->hLDevice, fp->hRaoClip,
- fp->hPDeviceBlock, fp->hPPen, fp->hPBrush, fp->hPFontTrans,
- fp->hPFont, fp->lpPDevice, fp->pLDevice,
- fp->pRaoClip);
-
- printf(
- "\tpPDeviceBlock\t: %04X\n"
- "\tpPPen\t\t: %04X\n"
- "\tpPBrush\t\t: %04X\n"
- "\tpPFontTrans\t: %04X\n"
- "\tlpPFont\t\t: %Fp\n"
- "\tnPFTIndex\t: %04X\n"
- "\tfnTransform\t: %Fp\n"
- "\twROP2\t\t: %04X\n"
- "\twBkMode\t\t: %04X\n"
- "\tdwBkColor\t: %08lX\n"
- "\tdwTextColor\t: %08lX\n"
- "\tnTBreakExtra\t: %d\n"
- "\tnBreakExtra\t: %d\n"
- "\twBreakErr\t: %04X\n"
- "\tnBreakRem\t: %d\n"
- "\tnBreakCount\t: %d\n"
- "\tnCharExtra\t: %d\n"
- "\tcrLbkColor\t: %08lX\n"
- "\tcrLTextColor\t: %08lX\n"
- "\tLCursPosX\t: %d\n"
- "\tLCursPosY\t: %d\n",
- fp->pPDeviceBlock, fp->pPPen, fp->pPBrush, fp->pPFontTrans,
- fp->lpPFont, fp->nPFTIndex, fp->Transform, fp->wROP2,
- fp->wBkMode, fp->dwBkColor, fp->dwTextColor, fp->nTBreakExtra,
- fp->nBreakExtra, fp->wBreakErr, fp->nBreakRem, fp->nBreakCount,
- fp->nCharExtra, fp->crLbkColor, fp->crLTextColor, fp->LCursPosX,
- fp->LCursPosY);
-
- printf(
- "\tWndOrgX\t\t: %d\n"
- "\tWndOrgX\t\t: %d\n"
- "\tWndExtX\t\t: %d\n"
- "\tWndExtY\t\t: %d\n"
- "\tVportOrgX\t: %d\n"
- "\tVportOrgY\t: %d\n"
- "\tVportExtX\t: %d\n"
- "\tVportExtY\t: %d\n"
- "\tUserVptOrgX\t: %d\n"
- "\tUserVptOrgY\t: %d\n"
- "\twMapMode\t: %04X\n"
- "\twXFormFlags\t: %04X\n"
- "\twRelAbs\t\t: %04X\n"
- "\twPolyFillMode\t: %04X\n"
- "\twStretchBltMode\t: %04X\n"
- "\tbyPlanes\t: %d\n"
- "\tbyBitsPix\t: %d\n"
- "\twPenWidth\t: %d\n"
- "\twPenHeight\t: %d\n"
- "\twTextAlign\t: %04X\n"
- "\tdwMapperFlags\t: %08lX\n",
- fp->WndOrgX, fp->WndOrgX, fp->WndExtX, fp->WndExtY,
- fp->VportOrgX, fp->VportOrgY, fp->VportExtX, fp->VportExtY,
- fp->UserVptOrgX, fp->UserVptOrgY, fp->wMapMode, fp->wXFormFlags,
- fp->wRelAbs, fp->wPolyFillMode, fp->wStretchBltMode, fp->byPlanes,
- fp->byBitsPix, fp->wPenWidth, fp->wPenHeight, fp->wTextAlign,
- fp->dwMapperFlags);
-
- printf(
- "\twBrushOrgX\t: %d\n"
- "\twBrushOrgY\t: %d\n"
- "\twFontAspectX\t: %d\n"
- "\twFontAspectY\t: %d\n"
- "\thFontWeights\t: %d\n"
- "\twDCSaveLevel\t: %d\n"
- "\twcDCLocks\t: %d\n"
- "->\thVisRgn\t\t: %04X\n"
- "\twDCOrgX\t\t: %d\n"
- "\twDCOrgY\t\t: %d\n"
- "\tlpfnPrint\t: %Fp\n"
- "\twDCLogAtom\t: %04X\n"
- "\twDCPhysAtom\t: %04X\n"
- "\twDCFileAtom\t: %04X\n"
- "\twPostScaleX\t: %d\n"
- "\twPostScaleY\t: %d\n",
- fp->wBrushOrgX, fp->wBrushOrgY,
- fp->wFontAspectX, fp->wFontAspectY,
- fp->hFontWeights, fp->wDCSaveLevel,
- fp->wcDCLocks, fp->hVisRgn,
- fp->wDCOrgX, fp->wDCOrgY, fp->lpfnPrint, fp->wDCLogAtom,
- fp->wDCPhysAtom, fp->wDCFileAtom,
- fp->wPostScaleX, fp->wPostScaleY);
- if (b31)
- {
- printf(
- "\trectBounds\t: (%d, %d, %d, %d)\n"
- "\trectLVB\t\t: (%d, %d, %d, %d)\n"
- "\tlpfnNotify\t: %Fp\n"
- "\tlpHookData\t: %Fp\n"
- "\twDCGlobFlags\t: %04X\n",
- fp->dc_tail.tail_3_1.rectBounds.left,
- fp->dc_tail.tail_3_1.rectBounds.top,
- fp->dc_tail.tail_3_1.rectBounds.right,
- fp->dc_tail.tail_3_1.rectBounds.bottom,
- fp->dc_tail.tail_3_1.rectLVB.left,
- fp->dc_tail.tail_3_1.rectLVB.top,
- fp->dc_tail.tail_3_1.rectLVB.right,
- fp->dc_tail.tail_3_1.rectLVB.bottom,
- fp->dc_tail.tail_3_1.lpfnNotify,
- fp->dc_tail.tail_3_1.lpHookData,
- fp->dc_tail.tail_3_1.wDCGlobFlags);
- if (bDebug)
- printf(
- "\thDCNext\t\t: %04X\n",
- fp->dc_tail.tail_3_1.hDCNext);
- }
- else
- {
- printf(
- "\twB4\t\t: %04X\n"
- "\trectB6\t\t: (%d, %d, %d, %d)\n"
- "\twDCGlobFlags\t: %04X\n"
- "\twC0\t\t: %04X\n",
- fp->dc_tail.tail_3_0.wB4,
- fp->dc_tail.tail_3_0.rectB6.left,
- fp->dc_tail.tail_3_0.rectB6.top,
- fp->dc_tail.tail_3_0.rectB6.right,
- fp->dc_tail.tail_3_0.rectB6.bottom,
- fp->dc_tail.tail_3_0.wDCGlobFlags,
- fp->dc_tail.tail_3_0.wC0);
- }
- }
-
- void DumpDisabledDC(WORD wSel, WORD wOfs, WORD wBytes)
- {
- DumpBlock(wSel, wOfs, wBytes);
- }
-
- void DumpMetaDC(WORD wSel, WORD wOfs, WORD wBytes)
- {
- DumpBlock(wSel, wOfs, wBytes);
- }
-
-
-
- void DumpMetaFile(WORD wSel, WORD wOfs, WORD wBytes)
- {
- DumpBlock(wSel, wOfs, wBytes);
- }
-
-
- #define WIDTH 16
-
- void DumpBlock(WORD wSel, WORD wOfs, WORD wBytes)
- {
- LPSTR fp, p;
- WORD i, j, c;
-
- fp = MK_FP(wSel, wOfs);
-
- for (i=0; i<wBytes; i += WIDTH)
- {
- c = ((wBytes-i) > WIDTH) ? WIDTH : wBytes-i;
- printf("%04X | ", i);
- for (j=c, p=fp+i; j--; p++)
- printf("%02X ", (unsigned char) *p);
- for (j=WIDTH-c; j--; ) // pad out on last line
- printf(" ");
- putchar('|'); putchar(' ');
- for (j=c, p=fp+i; j--; p++)
- putchar( isprint(*p) ? *p : '.' );
- putchar('\n');
- }
- }
-
-
- void DispatchDump(char *typ, WORD wH, WORD wSel, WORD wOfs, WORD wBytes)
- {
- WORD wLimit;
- char buf[80];
- HWND hwndNew, hwndSav;
- int i;
- DWORD dwSave;
-
- wSel &= ~3;
- wSel |= 1;
-
- if (! verr(wSel))
- {
- winio_warn(FALSE, "GDI Walker", "%04x no longer valid\n", wSel);
- return;
- }
- if ((wLimit = lsl(wSel)) < wOfs)
- {
- winio_warn(FALSE, "GDI Walker",
- "Start offs %04X is outside selector %04X limit of %04X\n",
- wOfs, wSel, wLimit);
- return;
- }
- if ((wLimit + 1) < (wBytes + wOfs))
- {
- winio_warn(FALSE, "GDI Walker",
- "Selector %04X limit is %04X, length of dump adjusted\n",
- wSel, wLimit);
- wBytes = wLimit - wOfs + 1;
- }
-
- for (i = 0; i < BLOCKTYPES; i++)
- if (strcmp(typ, GDIBlockType[i]) == 0) break;
-
- sprintf(buf, "%s handle %04X @ %04X:%04X for %d bytes",
- typ, wH, wSel, wOfs, wBytes);
-
- if ((hwndNew = FindWindow(NULL, buf)) != NULL)
- {
- ShowWindow(hwndNew, SW_RESTORE);
- BringWindowToTop(hwndNew);
- return;
- }
-
- // Use the table entry for window size. If the entry has a
- // y size of -1, it means it is a dump, and we use the amount
- // of data to display to determine the y size.
- dwSave = winio_defwindowsize(
- WINDOWSIZE( ((pntSize[i].y == -1)
- ? min(20, (wBytes + 15) / 16) : pntSize[i].y),
- pntSize[i].x));
-
- if (! (hwndNew = winio_window(buf, min(wBytes * 20, 1024), WW_HASMENU)))
- {
- winio_warn(FALSE, "Dump", "Insufficient resources!");
- return;
- }
-
- winio_defwindowsize(dwSave);
-
- hwndSav = winio_setcurrent(hwndNew);
-
- winio_setpaint(hwndNew, FALSE);
-
- // there is an extra entry in the fnDump table to allow for when
- // the type was not in the GDIBlockType table
- (* (fnDump[i]))(wSel, wOfs, wBytes);
-
- winio_setlinefn(hwndNew, OtherWndLine);
- winio_setpaint(hwndNew, TRUE);
- winio_home(hwndNew);
- winio_setcurrent(hwndSav);
-
- // GDIHeapWalk();
- }
-
-
- void MainWndLine(HWND hwnd, LPSTR line, int lineNum)
- {
- WORD wSel, wH, wOfs, wBytes;
- char typ[20];
- char buf[80];
- int i;
-
- for (i = 0; i < nHeaps; i++)
- if (lineNum < ltoh[i].nFirstLine)
- return;
- else
- if (lineNum < ltoh[i].nLastLine)
- break;
-
- wSel = ltoh[i].wHeap;
-
- lstrcpy(buf, line);
-
- if (sscanf(buf, "%04X %04X %04X %s", &wH, &wOfs, &wBytes, &typ) < 1)
- return;
-
- DispatchDump(typ, wH, wSel, wOfs, wBytes);
- }
-
-
-
- void OtherWndLine(HWND hwnd, LPSTR line, int lineNum)
- {
- WORD wSel, wH, wOfs, wBytes;
- char typ[20];
- char buf[80];
- int i;
-
- if ((*line++ != '-') || (*line++ != '>')) return;
-
- GetWindowText(hwnd, (LPSTR) &buf, sizeof(buf));
- sscanf(buf, "%s handle %04X @ %04X:%04X for %d bytes",
- &typ, &wH, &wSel, &wOfs, &wBytes);
-
- lstrcpy(buf, line);
-
- if (sscanf(buf, " %s : %04X", &typ, &wH) < 1)
- return;
-
- if (! wH)
- {
- winio_warn(FALSE, szTitle, "NULL handle!");
- return;
- }
-
- for (i = 0; i < MAXHFIELDS; i++)
- if (strcmp(hfld[i].szField, typ) == 0)
- break;
- if (i == MAXHFIELDS) return;
-
- if (! FarLocalSize(wSel, wH, &wOfs, &wBytes))
- {
- winio_warn(FALSE, szTitle, "Handle %04X in GDI heap %04X\n"
- "is no longer valid.", wH, wSel);
- GDIHeapWalk();
- }
- else
- DispatchDump(GDIBlockType[hfld[i].iType], wH, wSel, wOfs, wBytes);
- }
-
-
-
- char *GetGDIBlockType(WORD type)
- {
- // only default GDI local heap gets ToolHelp GDI subtypes;
- // use signatures to show for the rest?
-
- if ( type <= (BLOCKTYPES - 1) /* LT_GDI_MAX */ )
- return GDIBlockType[type];
-
- if ( type == 0xFF )
- return "FREE";
-
- return UnknownString;
- }
-
- void WalkOneGDIHeap(WORD seg)
- {
- LOCALENTRY le;
- BOOL ok;
-
- if (! seg) return;
-
- seg &= 0xfffc;
- seg |= 1;
-
- printf(
- "GDI heap in segment %04xh:\n"
- "(Double-click to view a block)\n"
- "HANDLE ADDR SIZE TYPE\n",
- seg);
- nLineNum += 4;
-
- ltoh[nHeaps].wHeap = seg;
- ltoh[nHeaps].nFirstLine = nLineNum;
-
- le.dwSize = sizeof(le);
- ok = LocalFirst(&le, seg);
-
- while ( ok )
- {
- nLineNum++;
- printf
- (
- "%04X %04X %04X %s\n",
- le.hHandle, le.wAddress, le.wSize,
- GetGDIBlockType(MyGDIBlockType(seg, le.wAddress, le.wType))
- );
-
- ok = LocalNext(&le);
- }
- ltoh[nHeaps++].nLastLine = nLineNum;
- printf("\n");
- nLineNum++;
- }
-
- void GDIHeapWalk(void)
- {
- GLOBALENTRY ge;
- BOOL ok;
- HANDLE hGDI = GetModuleHandle("GDI");
- SYSHEAPINFO shi;
-
- winio_clear(__hMainWnd);
-
- // Turn off repaints to minimize Heisenberg effects on heap
-
- winio_setbusy();
- winio_setpaint(__hMainWnd, FALSE);
-
- nHeaps = 0;
- nLineNum = 0;
- SystemHeapInfo(&shi);
- WalkOneGDIHeap(shi.hGDISegment);
- printf("\n");
- ge.dwSize = sizeof(ge);
- ok = GlobalFirst(&ge, GLOBAL_ALL);
-
- while ( ok )
- {
- if (ge.hOwner == hGDI)
- {
- if (ContainsLocalHeap(ge.hBlock) &&
- (ge.hBlock != shi.hGDISegment))
- {
- WalkOneGDIHeap(ge.hBlock);
- printf("\n");
- }
- }
- ok = GlobalNext(&ge, GLOBAL_ALL);
- }
-
- // Turn repaints back on, and position at the top of the info
- winio_setpaint(__hMainWnd, TRUE);
- winio_resetbusy();
- winio_home(__hMainWnd);
- }
-
-
- int main(int argc, char *argv[] )
- {
- b31 = HIBYTE(GetVersion());
- bDebug = GetSystemMetrics(SM_DEBUG);
-
- winio_about("GDIWALK"
- "\nGDI Local heap object browser"
- "\n\nFrom Chapter 8 of"
- "\n\"Undocumented Windows\" (Addison-Wesley, 1992)"
- "\nby Andrew Schulman, David Maxey and Matt Pietrek"
- );
-
- winio_settitle(__hMainWnd, szTitle);
- winio_setbufsize(__hMainWnd, (WORD) 65530, FALSE);
- GDIHeapWalk();
- winio_setmenufunc(__hMainWnd, ID_REFRESH, (MENU_FUNC) GDIHeapWalk);
- InsertMenu(winio_hmenumain(__hMainWnd), 1,
- MF_ENABLED | MF_STRING | MF_BYPOSITION,
- ID_REFRESH, "&Refresh!");
- DrawMenuBar(__hMainWnd);
- winio_setlinefn(__hMainWnd, MainWndLine);
-
- return 0;
- }
-
- // We can rely on ToolHelp to tell us whether a block contains a
- // valid local heap; all the homebrew validity checks are not needed here
- BOOL ContainsLocalHeap(WORD seg)
- {
- LOCALENTRY le;
- le.dwSize = sizeof(le);
- return LocalFirst(&le, seg);
- }
-
-
- BOOL FarLocalSize(WORD wSel, WORD wH, WORD *pOfs, WORD *pSize)
- {
- LOCALENTRY le;
- BOOL ok;
-
- le.dwSize = sizeof(le);
- ok = LocalFirst(&le, wSel);
-
- while (ok && (le.hHandle != wH))
- ok = LocalNext(&le);
- if (ok)
- {
- *pOfs = le.wAddress;
- *pSize = le.wSize;
- }
- return ok;
- }
-
- WORD MyGDIBlockType(WORD wSeg, WORD wOfs, WORD wType)
- {
- LPGDIOBJHDR lp = (LPGDIOBJHDR) MK_FP(wSeg, wOfs);
-
- if (wType) return wType;
-
- if (((lp->wMagic & 0x4f1f) == 0x4f1f) && ((lp->wMagic & 0x1f) == 11))
- return 11;
-
- return 0;
- }
-