home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l430 / 1.ddi / CHAP10.ZIP / WINWALK.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-07  |  12.9 KB  |  463 lines

  1. /*
  2.     WINWALK.C -- All purpose Windows browser
  3.     by Matt Pietrek (with changes by Dave Maxey & Andrew Schulman)
  4.  
  5.     From Chapter 10 of "Undocumented Windows" (Addison-Wesley 1992)
  6.     by Andrew Schulman, Dave Maxey and Matt Pietrek
  7.  
  8.     Build using: WINIOBC WINWALK (for Borland C++ v3.00)
  9.                  WINIOMS WINWALK (for Microsoft C/SDK)
  10.                      
  11.     Copyright (c) 1992 Matt Pietrek
  12. */
  13.  
  14. #include <windows.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <dos.h>
  18. #include <ctype.h>
  19. #include "toolhelp.h"
  20. #include "winio.h"
  21.  
  22. #ifndef __BORLANDC__ 
  23. #define MK_FP(a,b)  ((void far *)(((unsigned long)(a) << 16) | (b))) 
  24. #endif 
  25.  
  26. typedef struct  _WALKFUNCTION {
  27.     char *  description;            // Description of function
  28.     void    (*display_func)(void);  // Pointer to display function
  29.     WORD    displayBuffSize;        // Size in bytes of display buffer
  30. } WALKFUNCTION;
  31.  
  32. void ModuleWalk(void);
  33. void TaskWalk(void);
  34. void ClassWalk(void);
  35. void GlobalHeapWalk(void);
  36.  
  37. void GlobalHeapDoubleClickHandler(HWND, LPSTR, int);
  38. void MemDump(LPSTR, WORD, LPSTR, LPSTR);
  39. void LocalHeapWalk(WORD, LPSTR);
  40.  
  41. char szModuleList[] = "Modules";
  42. char szTaskList[]   = "Tasks";
  43. char szClassList[]  = "Classes";
  44. char szGlobalHeap[] = "Global Heap";
  45.  
  46. // Create an array of WALKFUNCTIONs
  47.  
  48. WALKFUNCTION    WalkFunctionArray[] = {
  49.     { szModuleList, ModuleWalk,     2048    },
  50.     { szTaskList,   TaskWalk,       2048    },
  51.     { szClassList,  ClassWalk,      2048    },
  52.     { szGlobalHeap, GlobalHeapWalk, 65535L  }
  53. };
  54.  
  55. #define WALKFUNCTIONCOUNT \
  56.     (sizeof(WalkFunctionArray) / sizeof(WALKFUNCTION))
  57.  
  58. char UnknownString[] = "<UNKNOWN>";
  59.  
  60. char *GlobalEntry_Resources[] = {
  61. "User defined",     // 0
  62. "Cursor",           // 1
  63. "Bitmap",           // 2
  64. "Icon Component",   // 3
  65. "Menu",             // 4
  66. "Dialog",           // 5
  67. "String table",     // 6
  68. "Font directory",   // 7
  69. "Font",             // 8
  70. "Accelerators",     // 9
  71. "RC data",          // 10
  72. "Error table",      // 11
  73. "Group cursor",     // 12
  74. UnknownString,      // 13
  75. "Group icon",       // 14
  76. "Name table"        // 15
  77. };
  78.  
  79. char HelpText[] = 
  80. "WinWalk is a simple demonstration of the TOOLHELP API\n"
  81. "\n"
  82. "By clicking on the options on the main menu, it can show you:\n"
  83. "- The list of EXE/DLL modules in the system\n"
  84. "- The list of running tasks\n"
  85. "- The list of registered windows classes in the USER heap\n"
  86. "- The contents of the global heap\n"
  87. "\n"
  88. "Additionally, up to the first 1K of memory in each global\n"
  89. "memory block can be viewed by double clicking on the\n"
  90. "appropriate line in the global heap window. If the block\n"
  91. "selected has a local heap, an additional window is popped\n"
  92. "up to display the local heap\n"
  93. "\n"
  94. "The USER and GDI heaps are not shown in detail here, as\n"
  95. "they are shown in more detail in separate sample programs.\n";
  96.  
  97. //---------------------------------------------
  98. // Given a "owner" handle, return back the
  99. // name of the module. Use TOOLHELP functions
  100. // To avoid undocumented methods
  101. //---------------------------------------------
  102. char *GetModuleNameFromHandle(HANDLE handle)
  103. {
  104.     MODULEENTRY me;
  105.     TASKENTRY   te;
  106.     static char name[40];
  107.  
  108.     me.dwSize = sizeof(me);
  109.     if ( ModuleFindHandle(&me, handle) )
  110.     {
  111.         strcpy(name, me.szModule);
  112.         return name;
  113.     }
  114.  
  115.     te.dwSize = sizeof(te);
  116.     if ( TaskFindHandle(&te, handle) )
  117.     {
  118.         strcpy(name, te.szModule);
  119.         return name;
  120.     }
  121.  
  122.     name[0] = 0;
  123.     return name;
  124. }
  125.  
  126. char *ResourceName(WORD handle)
  127. {
  128.     if ( handle > GD_MAX_RESOURCE )
  129.         return UnknownString;
  130.     return GlobalEntry_Resources[handle];
  131. }
  132.  
  133. char *GetGlobalBlockType(WORD type, WORD wData)
  134. {
  135.     static char description[40];
  136.  
  137.     switch ( type )
  138.     {
  139.         case GT_UNKNOWN : strcpy(description, "TASK MEM ALLOCATION"); break;
  140.         case GT_DGROUP  : strcpy(description, "DGROUP"); break;
  141.         case GT_DATA    : strcpy(description, "DATA"); break;
  142.         case GT_CODE    : sprintf(description,"CODE SEG %02Xh", wData); break;
  143.         case GT_TASK    : strcpy(description, "TASK DATABASE"); break;
  144.         case GT_RESOURCE: sprintf(description,"RESOURCE %s",
  145.                           ResourceName(wData) ); break;
  146.         case GT_MODULE  : strcpy(description, "MODULE TABLE"); break;
  147.         case GT_FREE    : strcpy(description, "FREE"); break;
  148.         case GT_INTERNAL: strcpy(description, "INTERNAL"); break;
  149.         case GT_SENTINEL: strcpy(description, "SENTINEL"); break;
  150.         case GT_BURGERMASTER : strcpy(description, "BURGERMASTER"); break;
  151.         default         : strcpy(description, UnknownString);
  152.     }
  153.  
  154.     return description;
  155. }
  156.  
  157. void GlobalHeapWalk(void)
  158. {
  159.     GLOBALENTRY ge;
  160.     BOOL ok;
  161.  
  162.     printf("Global heap:\n"
  163.     "(Double-click to dump block)\n"
  164.     "HANDLE   SIZE  OWNER     TYPE\n");
  165.  
  166.     ge.dwSize = sizeof(ge);
  167.     ok = GlobalFirst(&ge, GLOBAL_ALL);
  168.     while ( ok )
  169.     {
  170.         printf("%04X    %5lX  %-8s  %s\n",
  171.             ge.hBlock, ge.dwBlockSize,
  172.             GetModuleNameFromHandle(ge.hOwner),
  173.             GetGlobalBlockType(ge.wType, ge.wData));
  174.  
  175.         ok = GlobalNext(&ge, GLOBAL_ALL);
  176.     }
  177.  
  178.     winio_setlinefn(winio_current(), GlobalHeapDoubleClickHandler);
  179. }
  180.  
  181. void ClassWalk(void)
  182. {
  183.     CLASSENTRY ce;
  184.     BOOL ok;
  185.     
  186.     printf("Class list:\n");    
  187.     printf("OWNER     INST  NAME\n");
  188.  
  189.     ce.dwSize = sizeof(ce);    
  190.     ok = ClassFirst(&ce);
  191.     while ( ok )
  192.     {
  193.         printf("%-8s  %04X  %s\n",
  194.             GetModuleNameFromHandle(ce.hInst),
  195.             ce.hInst, ce.szClassName);
  196.         
  197.         ok = ClassNext(&ce);
  198.     }
  199. }
  200.  
  201. void TaskWalk(void)
  202. {
  203.     TASKENTRY te;
  204.     BOOL ok;
  205.     
  206.     printf("Task list:\n");    
  207.     printf("NAME      HTASK  HMOD  HINST  PARENT\n");
  208.         
  209.     te.dwSize = sizeof(te);
  210.     ok = TaskFirst(&te);
  211.     while ( ok )
  212.     {
  213.         printf("%-8s  %04X   %04X  %04X   %s\n",
  214.             te.szModule, te.hTask, te.hModule, te.hInst,
  215.             GetModuleNameFromHandle(te.hTaskParent));
  216.     
  217.         ok = TaskNext(&te);
  218.     }
  219. }
  220.  
  221. void ModuleWalk(void)
  222. {
  223.     MODULEENTRY me;
  224.     BOOL ok;
  225.     
  226.     printf("Module list:\n");    
  227.     printf("NAME      HMOD  COUNT FILENAME\n");
  228.         
  229.     me.dwSize = sizeof(me);    
  230.     ok = ModuleFirst(&me);
  231.     while ( ok )        
  232.     {   
  233.         printf("%-8s  %04X  %2u    %s\n",
  234.             me.szModule, me.hModule, me.wcUsage, me.szExePath);
  235.     
  236.         ok = ModuleNext(&me);
  237.     }
  238. }
  239.  
  240. // Returns whether a global memory block contains
  241. // a local heap. It does this by trying to
  242. // initiate a local walk of the passed in block
  243. BOOL ContainsLocalHeap(WORD seg)
  244. {
  245.     LOCALENTRY le;
  246.     le.dwSize = sizeof(le);
  247.     return LocalFirst(&le, seg);
  248. }
  249.  
  250. void LocalHeapWalk(WORD sel, LPSTR description)
  251. {
  252.     GLOBALENTRY ge;
  253.     LOCALENTRY le;
  254.     HWND hWndNew, hWndSav;
  255.     char buffer[120];
  256.     char * szFlags;
  257.     BOOL ok;
  258.     
  259.     // Call GlobalEntryHandle() to get the "owning" block
  260.     ge.dwSize = sizeof(ge);
  261.     ok = GlobalEntryHandle(&ge, sel);
  262.     
  263.     // Create a title for the window, create a new window,
  264.     // and save away the old current window
  265.     sprintf(buffer, "Local heap: %04X  %s",
  266.         sel, GetModuleNameFromHandle(ge.hOwner) );
  267.     
  268.     hWndNew = winio_window(buffer, 32768L, WW_HASMENU);
  269.         
  270.     if (!hWndNew)
  271.         MessageBox(NULL, "Not Enough Memory", "Error",
  272.             MB_OK | MB_ICONEXCLAMATION);
  273.     
  274.     hWndSav = winio_setcurrent(hWndNew);
  275.     winio_setpaint(hWndNew, FALSE);
  276.  
  277.     // Print the header information
  278.     printf("%s\n\n", description);
  279.  
  280.     printf("HANDLE  ADDR  SIZE  TYPE\n");
  281.     
  282.     // Walk the local heap
  283.     le.dwSize = sizeof(le);
  284.     ok = LocalFirst(&le, sel);
  285.     while ( ok )
  286.     {
  287.         switch ( le.wFlags )
  288.         {
  289.             case LF_FIXED:    szFlags = "FIXED"; break;
  290.             case LF_FREE:     szFlags = "FREE"; break;
  291.             case LF_MOVEABLE: szFlags = "MOVEABLE"; break;
  292.             default:          szFlags = "";
  293.         }
  294.         
  295.         printf("%04X    %04X  %04X  %s\n",
  296.             le.hHandle, le.wAddress, le.wSize, szFlags);
  297.  
  298.         ok = LocalNext(&le);
  299.      }
  300.  
  301.     // Turn painting back on, and put things back
  302.     // into a sensible state of affairs
  303.     winio_setpaint(hWndNew, TRUE);
  304.     winio_home(hWndNew);
  305.     winio_setcurrent(hWndSav);
  306. }
  307.  
  308. // Define how wide the memory dump will be
  309. #define WIDTH 16
  310.  
  311. void MemDump(LPSTR fp, WORD bytes, LPSTR addr, LPSTR description)
  312. {
  313.     HWND hWndNew, hWndSav;
  314.     LPSTR p;
  315.     WORD i, j, c;
  316.     char buffer[120];
  317.  
  318.     // Create a title for the window, create a new window,
  319.     // and save away the old current window
  320.     sprintf(buffer, "Dump: %Fp - %04X bytes", fp, bytes);
  321.     hWndNew = winio_window(buffer, bytes * 5, WW_HASMENU);
  322.         
  323.     if (!hWndNew)
  324.         MessageBox(NULL, "Not Enough Memory", "Error",
  325.             MB_OK | MB_ICONEXCLAMATION);
  326.     
  327.     hWndSav = winio_setcurrent(hWndNew);
  328.     winio_setpaint(hWndNew, FALSE);
  329.     printf("%s\n\n", description);
  330.     
  331.     // Dense code to actually do the memory dumping
  332.     for (i=0; i<bytes; i += WIDTH)
  333.     {
  334.         c = ((bytes-i) > WIDTH) ? WIDTH : bytes-i;
  335.         printf("%04X: ", addr+i);
  336.         for (j=c, p=fp+i; j--; p++)
  337.             printf("%02X ", (unsigned char) *p);
  338.         for (j=WIDTH-c; j--; )  // pad out on last line
  339.             printf("   ");
  340.         putchar(' ');
  341.         for (j=c, p=fp+i; j--; p++)
  342.             putchar( isprint(*p) ? *p : '.' );
  343.         putchar('\n');
  344.     }
  345.     
  346.     // Turn painting back on, and put things back
  347.     // into a sensible state of affairs
  348.     winio_setpaint(hWndNew, TRUE);
  349.     winio_home(hWndNew);
  350.     winio_setcurrent(hWndSav);
  351. }
  352.  
  353. void GlobalHeapDoubleClickHandler(HWND hwnd, LPSTR line, int lineNum)
  354. {
  355.     WORD wSel;
  356.     DWORD blockSize=0;
  357.     WORD  dumpSize;
  358.     char buffer[80];
  359.     int retVal;
  360.     
  361.     // Make a local copy of the line as it appears in the global
  362.     // heap window. sscanf() in the handle and block size
  363.     lstrcpy(buffer, line);
  364.     retVal = sscanf(buffer, "%04X    %5lX ", &wSel, &blockSize);
  365.     dumpSize = min(blockSize, 1024L);
  366.  
  367.     // Verify that we got sensible values from the line
  368.     if ( (retVal != 2) || ( dumpSize == 0 ) )
  369.     {
  370.         MessageBox(NULL, "Not a valid line", "Error",
  371.                     MB_OK | MB_ICONEXCLAMATION);
  372.         return;
  373.     }
  374.  
  375.     // Convert the handle to a selector we can use
  376.     wSel = GlobalHandleToSel(wSel);
  377.  
  378.     // Determine if the selector is O.K. Display an error
  379.     // message and get out if not
  380.     _asm     lar     ax, wSel
  381.     _asm     jz      Selector_OK
  382.     
  383.     MessageBox(NULL, "Selector not valid", "Error",
  384.                 MB_OK | MB_ICONEXCLAMATION);
  385.     return;
  386.     
  387.     // We get here if the selector is O.K. Call MemDump
  388.     // to create a new window and display the memory.
  389.     // If there is a local heap in the block, display
  390.     // it in a local heap window as well
  391. Selector_OK:
  392.         
  393.     MemDump(MK_FP(wSel, 0), dumpSize, MK_FP(wSel,0), line);
  394.     
  395.     if ( ContainsLocalHeap(wSel) )
  396.         LocalHeapWalk(wSel, line);
  397. }
  398.  
  399. void MenuHandler(HWND hwnd, WORD menuID)
  400. {
  401.     HWND newWindow;
  402.     WORD selected;
  403.     char buffer[80];
  404.     
  405.     selected = menuID-1;
  406.     
  407.     // Create an appropriate title for the new window,
  408.     // then create a new window with an appropriately
  409.     // sized buffer.
  410.     sprintf(buffer, "WinWalk: %s", WalkFunctionArray[selected].description);
  411.     newWindow = winio_window(buffer,
  412.         WalkFunctionArray[selected].displayBuffSize,
  413.         WW_HASMENU);
  414.     winio_setcurrent(newWindow);
  415.  
  416.     // Turn off repaints
  417.     winio_setbusy();
  418.     winio_setpaint(winio_current(), FALSE);
  419.  
  420.     // Call the appropriate display function
  421.     WalkFunctionArray[selected].display_func();
  422.  
  423.     // Turn repaints back on, and position at the top of the info
  424.     winio_setpaint(winio_current(), TRUE);
  425.     winio_resetbusy();
  426.     winio_home(newWindow);  
  427. }
  428.  
  429. int main(int argc, char *argv[] )
  430. {
  431.     char buffer[40];
  432.     unsigned i;
  433.  
  434.     winio_about("WINWALK"
  435.         "\nAll purpose Windows browser"
  436.         "\n\nFrom Chapter 10 of"
  437.         "\n\"Undocumented Windows\" (Addison-Wesley, 1992)"
  438.         "\nby Andrew Schulman, David Maxey and Matt Pietrek"
  439.         );
  440.     
  441.     buffer[0] = '&';
  442.     
  443.     winio_defwindowsize(MAKELONG(55, 10));
  444.  
  445.     // Create the main menu, and assign selection handlers
  446.     for ( i=0; i < WALKFUNCTIONCOUNT; i++)
  447.     {
  448.         // make a string with an '&', then a description of
  449.         // the display that it will trigger
  450.         strcpy(&buffer[1], WalkFunctionArray[i].description);
  451.         
  452.         InsertMenu(winio_hmenumain(__hMainWnd), i+1,
  453.             MF_STRING | MF_BYPOSITION,
  454.             i+1, buffer);
  455.         
  456.         winio_setmenufunc(__hMainWnd, i + 1, (MENU_FUNC) MenuHandler);
  457.     }
  458.  
  459.     DrawMenuBar(__hMainWnd);
  460.     printf(HelpText);
  461.     return 0;
  462. }
  463.