home *** CD-ROM | disk | FTP | other *** search
- /*
- WINWALK.C -- All purpose Windows browser
- by Matt Pietrek (with changes by Dave Maxey & Andrew Schulman)
-
- From Chapter 10 of "Undocumented Windows" (Addison-Wesley 1992)
- by Andrew Schulman, Dave Maxey and Matt Pietrek
-
- Build using: WINIOBC WINWALK (for Borland C++ v3.00)
- WINIOMS WINWALK (for Microsoft C/SDK)
-
- Copyright (c) 1992 Matt Pietrek
- */
-
- #include <windows.h>
- #include <stdio.h>
- #include <string.h>
- #include <dos.h>
- #include <ctype.h>
- #include "toolhelp.h"
- #include "winio.h"
-
- #ifndef __BORLANDC__
- #define MK_FP(a,b) ((void far *)(((unsigned long)(a) << 16) | (b)))
- #endif
-
- typedef struct _WALKFUNCTION {
- char * description; // Description of function
- void (*display_func)(void); // Pointer to display function
- WORD displayBuffSize; // Size in bytes of display buffer
- } WALKFUNCTION;
-
- void ModuleWalk(void);
- void TaskWalk(void);
- void ClassWalk(void);
- void GlobalHeapWalk(void);
-
- void GlobalHeapDoubleClickHandler(HWND, LPSTR, int);
- void MemDump(LPSTR, WORD, LPSTR, LPSTR);
- void LocalHeapWalk(WORD, LPSTR);
-
- char szModuleList[] = "Modules";
- char szTaskList[] = "Tasks";
- char szClassList[] = "Classes";
- char szGlobalHeap[] = "Global Heap";
-
- // Create an array of WALKFUNCTIONs
-
- WALKFUNCTION WalkFunctionArray[] = {
- { szModuleList, ModuleWalk, 2048 },
- { szTaskList, TaskWalk, 2048 },
- { szClassList, ClassWalk, 2048 },
- { szGlobalHeap, GlobalHeapWalk, 65535L }
- };
-
- #define WALKFUNCTIONCOUNT \
- (sizeof(WalkFunctionArray) / sizeof(WALKFUNCTION))
-
- char UnknownString[] = "<UNKNOWN>";
-
- char *GlobalEntry_Resources[] = {
- "User defined", // 0
- "Cursor", // 1
- "Bitmap", // 2
- "Icon Component", // 3
- "Menu", // 4
- "Dialog", // 5
- "String table", // 6
- "Font directory", // 7
- "Font", // 8
- "Accelerators", // 9
- "RC data", // 10
- "Error table", // 11
- "Group cursor", // 12
- UnknownString, // 13
- "Group icon", // 14
- "Name table" // 15
- };
-
- char HelpText[] =
- "WinWalk is a simple demonstration of the TOOLHELP API\n"
- "\n"
- "By clicking on the options on the main menu, it can show you:\n"
- "- The list of EXE/DLL modules in the system\n"
- "- The list of running tasks\n"
- "- The list of registered windows classes in the USER heap\n"
- "- The contents of the global heap\n"
- "\n"
- "Additionally, up to the first 1K of memory in each global\n"
- "memory block can be viewed by double clicking on the\n"
- "appropriate line in the global heap window. If the block\n"
- "selected has a local heap, an additional window is popped\n"
- "up to display the local heap\n"
- "\n"
- "The USER and GDI heaps are not shown in detail here, as\n"
- "they are shown in more detail in separate sample programs.\n";
-
- //---------------------------------------------
- // Given a "owner" handle, return back the
- // name of the module. Use TOOLHELP functions
- // To avoid undocumented methods
- //---------------------------------------------
- char *GetModuleNameFromHandle(HANDLE handle)
- {
- MODULEENTRY me;
- TASKENTRY te;
- static char name[40];
-
- me.dwSize = sizeof(me);
- if ( ModuleFindHandle(&me, handle) )
- {
- strcpy(name, me.szModule);
- return name;
- }
-
- te.dwSize = sizeof(te);
- if ( TaskFindHandle(&te, handle) )
- {
- strcpy(name, te.szModule);
- return name;
- }
-
- name[0] = 0;
- return name;
- }
-
- char *ResourceName(WORD handle)
- {
- if ( handle > GD_MAX_RESOURCE )
- return UnknownString;
- return GlobalEntry_Resources[handle];
- }
-
- char *GetGlobalBlockType(WORD type, WORD wData)
- {
- static char description[40];
-
- switch ( type )
- {
- case GT_UNKNOWN : strcpy(description, "TASK MEM ALLOCATION"); break;
- case GT_DGROUP : strcpy(description, "DGROUP"); break;
- case GT_DATA : strcpy(description, "DATA"); break;
- case GT_CODE : sprintf(description,"CODE SEG %02Xh", wData); break;
- case GT_TASK : strcpy(description, "TASK DATABASE"); break;
- case GT_RESOURCE: sprintf(description,"RESOURCE %s",
- ResourceName(wData) ); break;
- case GT_MODULE : strcpy(description, "MODULE TABLE"); break;
- case GT_FREE : strcpy(description, "FREE"); break;
- case GT_INTERNAL: strcpy(description, "INTERNAL"); break;
- case GT_SENTINEL: strcpy(description, "SENTINEL"); break;
- case GT_BURGERMASTER : strcpy(description, "BURGERMASTER"); break;
- default : strcpy(description, UnknownString);
- }
-
- return description;
- }
-
- void GlobalHeapWalk(void)
- {
- GLOBALENTRY ge;
- BOOL ok;
-
- printf("Global heap:\n"
- "(Double-click to dump block)\n"
- "HANDLE SIZE OWNER TYPE\n");
-
- ge.dwSize = sizeof(ge);
- ok = GlobalFirst(&ge, GLOBAL_ALL);
- while ( ok )
- {
- printf("%04X %5lX %-8s %s\n",
- ge.hBlock, ge.dwBlockSize,
- GetModuleNameFromHandle(ge.hOwner),
- GetGlobalBlockType(ge.wType, ge.wData));
-
- ok = GlobalNext(&ge, GLOBAL_ALL);
- }
-
- winio_setlinefn(winio_current(), GlobalHeapDoubleClickHandler);
- }
-
- void ClassWalk(void)
- {
- CLASSENTRY ce;
- BOOL ok;
-
- printf("Class list:\n");
- printf("OWNER INST NAME\n");
-
- ce.dwSize = sizeof(ce);
- ok = ClassFirst(&ce);
- while ( ok )
- {
- printf("%-8s %04X %s\n",
- GetModuleNameFromHandle(ce.hInst),
- ce.hInst, ce.szClassName);
-
- ok = ClassNext(&ce);
- }
- }
-
- void TaskWalk(void)
- {
- TASKENTRY te;
- BOOL ok;
-
- printf("Task list:\n");
- printf("NAME HTASK HMOD HINST PARENT\n");
-
- te.dwSize = sizeof(te);
- ok = TaskFirst(&te);
- while ( ok )
- {
- printf("%-8s %04X %04X %04X %s\n",
- te.szModule, te.hTask, te.hModule, te.hInst,
- GetModuleNameFromHandle(te.hTaskParent));
-
- ok = TaskNext(&te);
- }
- }
-
- void ModuleWalk(void)
- {
- MODULEENTRY me;
- BOOL ok;
-
- printf("Module list:\n");
- printf("NAME HMOD COUNT FILENAME\n");
-
- me.dwSize = sizeof(me);
- ok = ModuleFirst(&me);
- while ( ok )
- {
- printf("%-8s %04X %2u %s\n",
- me.szModule, me.hModule, me.wcUsage, me.szExePath);
-
- ok = ModuleNext(&me);
- }
- }
-
- // Returns whether a global memory block contains
- // a local heap. It does this by trying to
- // initiate a local walk of the passed in block
- BOOL ContainsLocalHeap(WORD seg)
- {
- LOCALENTRY le;
- le.dwSize = sizeof(le);
- return LocalFirst(&le, seg);
- }
-
- void LocalHeapWalk(WORD sel, LPSTR description)
- {
- GLOBALENTRY ge;
- LOCALENTRY le;
- HWND hWndNew, hWndSav;
- char buffer[120];
- char * szFlags;
- BOOL ok;
-
- // Call GlobalEntryHandle() to get the "owning" block
- ge.dwSize = sizeof(ge);
- ok = GlobalEntryHandle(&ge, sel);
-
- // Create a title for the window, create a new window,
- // and save away the old current window
- sprintf(buffer, "Local heap: %04X %s",
- sel, GetModuleNameFromHandle(ge.hOwner) );
-
- hWndNew = winio_window(buffer, 32768L, WW_HASMENU);
-
- if (!hWndNew)
- MessageBox(NULL, "Not Enough Memory", "Error",
- MB_OK | MB_ICONEXCLAMATION);
-
- hWndSav = winio_setcurrent(hWndNew);
- winio_setpaint(hWndNew, FALSE);
-
- // Print the header information
- printf("%s\n\n", description);
-
- printf("HANDLE ADDR SIZE TYPE\n");
-
- // Walk the local heap
- le.dwSize = sizeof(le);
- ok = LocalFirst(&le, sel);
- while ( ok )
- {
- switch ( le.wFlags )
- {
- case LF_FIXED: szFlags = "FIXED"; break;
- case LF_FREE: szFlags = "FREE"; break;
- case LF_MOVEABLE: szFlags = "MOVEABLE"; break;
- default: szFlags = "";
- }
-
- printf("%04X %04X %04X %s\n",
- le.hHandle, le.wAddress, le.wSize, szFlags);
-
- ok = LocalNext(&le);
- }
-
- // Turn painting back on, and put things back
- // into a sensible state of affairs
- winio_setpaint(hWndNew, TRUE);
- winio_home(hWndNew);
- winio_setcurrent(hWndSav);
- }
-
- // Define how wide the memory dump will be
- #define WIDTH 16
-
- void MemDump(LPSTR fp, WORD bytes, LPSTR addr, LPSTR description)
- {
- HWND hWndNew, hWndSav;
- LPSTR p;
- WORD i, j, c;
- char buffer[120];
-
- // Create a title for the window, create a new window,
- // and save away the old current window
- sprintf(buffer, "Dump: %Fp - %04X bytes", fp, bytes);
- hWndNew = winio_window(buffer, bytes * 5, WW_HASMENU);
-
- if (!hWndNew)
- MessageBox(NULL, "Not Enough Memory", "Error",
- MB_OK | MB_ICONEXCLAMATION);
-
- hWndSav = winio_setcurrent(hWndNew);
- winio_setpaint(hWndNew, FALSE);
- printf("%s\n\n", description);
-
- // Dense code to actually do the memory dumping
- for (i=0; i<bytes; i += WIDTH)
- {
- c = ((bytes-i) > WIDTH) ? WIDTH : bytes-i;
- printf("%04X: ", addr+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(' ');
- for (j=c, p=fp+i; j--; p++)
- putchar( isprint(*p) ? *p : '.' );
- putchar('\n');
- }
-
- // Turn painting back on, and put things back
- // into a sensible state of affairs
- winio_setpaint(hWndNew, TRUE);
- winio_home(hWndNew);
- winio_setcurrent(hWndSav);
- }
-
- void GlobalHeapDoubleClickHandler(HWND hwnd, LPSTR line, int lineNum)
- {
- WORD wSel;
- DWORD blockSize=0;
- WORD dumpSize;
- char buffer[80];
- int retVal;
-
- // Make a local copy of the line as it appears in the global
- // heap window. sscanf() in the handle and block size
- lstrcpy(buffer, line);
- retVal = sscanf(buffer, "%04X %5lX ", &wSel, &blockSize);
- dumpSize = min(blockSize, 1024L);
-
- // Verify that we got sensible values from the line
- if ( (retVal != 2) || ( dumpSize == 0 ) )
- {
- MessageBox(NULL, "Not a valid line", "Error",
- MB_OK | MB_ICONEXCLAMATION);
- return;
- }
-
- // Convert the handle to a selector we can use
- wSel = GlobalHandleToSel(wSel);
-
- // Determine if the selector is O.K. Display an error
- // message and get out if not
- _asm lar ax, wSel
- _asm jz Selector_OK
-
- MessageBox(NULL, "Selector not valid", "Error",
- MB_OK | MB_ICONEXCLAMATION);
- return;
-
- // We get here if the selector is O.K. Call MemDump
- // to create a new window and display the memory.
- // If there is a local heap in the block, display
- // it in a local heap window as well
- Selector_OK:
-
- MemDump(MK_FP(wSel, 0), dumpSize, MK_FP(wSel,0), line);
-
- if ( ContainsLocalHeap(wSel) )
- LocalHeapWalk(wSel, line);
- }
-
- void MenuHandler(HWND hwnd, WORD menuID)
- {
- HWND newWindow;
- WORD selected;
- char buffer[80];
-
- selected = menuID-1;
-
- // Create an appropriate title for the new window,
- // then create a new window with an appropriately
- // sized buffer.
- sprintf(buffer, "WinWalk: %s", WalkFunctionArray[selected].description);
- newWindow = winio_window(buffer,
- WalkFunctionArray[selected].displayBuffSize,
- WW_HASMENU);
- winio_setcurrent(newWindow);
-
- // Turn off repaints
- winio_setbusy();
- winio_setpaint(winio_current(), FALSE);
-
- // Call the appropriate display function
- WalkFunctionArray[selected].display_func();
-
- // Turn repaints back on, and position at the top of the info
- winio_setpaint(winio_current(), TRUE);
- winio_resetbusy();
- winio_home(newWindow);
- }
-
- int main(int argc, char *argv[] )
- {
- char buffer[40];
- unsigned i;
-
- winio_about("WINWALK"
- "\nAll purpose Windows browser"
- "\n\nFrom Chapter 10 of"
- "\n\"Undocumented Windows\" (Addison-Wesley, 1992)"
- "\nby Andrew Schulman, David Maxey and Matt Pietrek"
- );
-
- buffer[0] = '&';
-
- winio_defwindowsize(MAKELONG(55, 10));
-
- // Create the main menu, and assign selection handlers
- for ( i=0; i < WALKFUNCTIONCOUNT; i++)
- {
- // make a string with an '&', then a description of
- // the display that it will trigger
- strcpy(&buffer[1], WalkFunctionArray[i].description);
-
- InsertMenu(winio_hmenumain(__hMainWnd), i+1,
- MF_STRING | MF_BYPOSITION,
- i+1, buffer);
-
- winio_setmenufunc(__hMainWnd, i + 1, (MENU_FUNC) MenuHandler);
- }
-
- DrawMenuBar(__hMainWnd);
- printf(HelpText);
- return 0;
- }
-