home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l430 / 1.ddi / CHAP5.ZIP / ATOMWALK.C next >
Encoding:
C/C++ Source or Header  |  1992-06-08  |  5.8 KB  |  199 lines

  1. /*
  2.     ATOMWALK.C -- Shows every atom in the system
  3.  
  4.     From Chapter 5 of "Undocumented Windows" (Addison-Wesley 1992)
  5.     by Andrew Schulman, Dave Maxey and Matt Pietrek
  6.  
  7.     Build using: WINIOBC ATOMWALK HANDLES (for Borland C++ v3.00)
  8.                  WINIOMS ATOMWALK HANDLES (for Microsoft C/SDK)
  9.  
  10. For each atom table in this system  <--- this is the hard part
  11.     If it's the Global Atom Table, identify it
  12.     For each entry in hash table
  13.         If entry is in use
  14.             Maybe show entry number
  15.             For each atom in this bucket
  16.                 Print atom handle, atom string
  17. */
  18.  
  19. #include <windows.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <dos.h>
  23. #include "toolhelp.h"
  24. #include "winio.h"
  25. #include "handles.h"
  26.  
  27. /* from WINEXP.H */
  28. /* atom manager internals */
  29. #define ATOMSTRUC struct atomstruct
  30. typedef ATOMSTRUC *PATOM;
  31. typedef ATOMSTRUC {
  32.     PATOM chain;
  33.     WORD  usage;             /* Atoms are usage counted. */
  34.     BYTE  len;               /* length of ASCIZ name string */
  35.     BYTE  name;              /* beginning of ASCIZ name string */
  36. } ATOMENTRY;
  37.  
  38. typedef struct {
  39.     int     numEntries;
  40.     PATOM   pAtom[ 1 ];
  41. } ATOMTABLE;
  42.  
  43. /* identical to documented (but discouraged) GetAtomHandle() */
  44. #define AtomToHandle(atom)      ((WORD) (atom) << 2)   /* overflow */
  45.  
  46. #define HandleToAtom(handle)    (0xC000 | ((handle) >> 2))
  47.  
  48. /* NULL segment at offset 0 in a data segment with 
  49.    atom table or local heap */
  50. typedef struct {
  51.     WORD wMustBeZero;
  52.     DWORD dwOldSSSP;
  53.     WORD pLocalHeap;
  54.     WORD pAtomTable;
  55.     WORD pStackTop;
  56.     WORD pStackMin;
  57.     WORD pStackBottom;
  58.     } INSTDATA;
  59.  
  60. /* There is no signature for atom tables, so seeing if you found one
  61.    is tricky, and perhaps only probabilistically correct.  To be
  62.    an atom table, there _must_ be a local heap (the atoms themselves
  63.    are items in the local heap).  We can test for a correct local 
  64.    heap.  There must also be a valid NULL segment block at offset 0 */
  65. ATOMTABLE far *GetAtomTable(GLOBALENTRY *pge)
  66. {
  67.     extern DWORD FAR PASCAL GetSelectorLimit(WORD sel);
  68.     if ((pge->wType == GT_DGROUP) || 
  69.         (pge->wType == GT_DATA) ||
  70.         (pge->wType == GT_UNKNOWN))     // GlobalAllocs are GT_UNKNOWN
  71.     {
  72.         WORD sel = GlobalHandleToSel(pge->hBlock);
  73.         INSTDATA far *lpInstData = MK_FP(sel, 0);
  74.         DWORD limit = GetSelectorLimit(sel);
  75.         if (verr(sel) &&
  76.             (limit > 16) &&
  77.             (lpInstData->wMustBeZero == 0) &&
  78.             (lpInstData->pLocalHeap != 0) &&
  79.             (lpInstData->pLocalHeap < (WORD) limit) &&
  80.             (lpInstData->pAtomTable != 0) &&
  81.             (lpInstData->pAtomTable < (WORD) limit) &&
  82.             IsValidLocalHeap(MK_FP(sel, lpInstData->pLocalHeap)))
  83.         {
  84.             return MK_FP(sel, lpInstData->pAtomTable);
  85.         }
  86.     }
  87.  
  88.     /* still here */
  89.     return 0L;
  90. }
  91.  
  92. WORD FAR PASCAL BasedGetAtomName(WORD wSeg, 
  93.     WORD wAtom, LPSTR lpszBuf, int cbBuf)
  94. {
  95.     WORD retval;
  96.     _asm push ds
  97.     _asm mov ds, wSeg
  98.     retval = GetAtomName(wAtom, lpszBuf, cbBuf);
  99.     _asm pop ds
  100.     return retval;
  101. }
  102.  
  103. ATOM BasedFindAtom(WORD wSeg, LPSTR lpsz)
  104. {
  105.     ATOM retval;
  106.     _asm push ds
  107.     _asm mov ds, wSeg
  108.     retval = FindAtom(lpsz);
  109.     _asm pop ds
  110.     return retval;
  111. }
  112.  
  113. static BOOL show_bucket = FALSE;
  114.  
  115. WORD print_bucket(WORD hash, ATOMENTRY far *pa)
  116. {
  117.     WORD num_atoms = 0;
  118.     WORD seg = FP_SEG(pa);
  119.     WORD ofs = FP_OFF(pa);
  120.     if (show_bucket)
  121.         printf("Bucket %u\n", hash);
  122.     for (;;)    // print everything that hashes to this bucket
  123.     {
  124.         num_atoms++;
  125.         printf("   %04x   %Fs\n", HandleToAtom(FP_OFF(pa)), &pa->name);
  126. #define PARANOID        
  127. #ifdef PARANOID
  128.         if (HandleToAtom(ofs) != BasedFindAtom(seg, &pa->name))
  129.             fail("Something wrong!");
  130. #endif
  131.         if ((ofs = (WORD) pa->chain) != 0)
  132.             pa = MK_FP(seg, ofs);       // follow linked list
  133.         else 
  134.             break;
  135.     }
  136.     return num_atoms;
  137. }
  138.  
  139. main(int argc, char *argv[])
  140. {
  141.     ATOMTABLE far *lpAtomTable;
  142.     GLOBALENTRY ge;
  143.     HANDLE hUser;
  144.     WORD num_atoms;
  145.     int ok;
  146.     
  147.     if (argc >= 2)
  148.         if (strcmp(strupr(argv[1]), "-BUCKET") == 0)
  149.             show_bucket = TRUE;
  150.     
  151.     winio_about("ATOMWALK"
  152.         "\nShows every atom in the system"
  153.         "\nUsage: ATOMWALK [-BUCKET]"
  154.         "\n\nFrom Chapter 5 of"
  155.         "\n\"Undocumented Windows\" (Addison-Wesley, 1992)"
  156.         "\nby Andrew Schulman, David Maxey and Matt Pietrek"
  157.         );
  158.     
  159.     hUser = GetModuleHandle("USER");
  160.     ge.dwSize = sizeof(ge);
  161.     winio_setbusy();
  162.     winio_setpaint(__hMainWnd, FALSE);
  163.     ok = GlobalFirst(&ge, GLOBAL_ALL);
  164.     while (ok)
  165.     {
  166.         // for Atom Table structure, see WINEXP.H
  167.         if (lpAtomTable = GetAtomTable(&ge))
  168.         {
  169.             char owner[128];
  170.             int i;
  171.             PATOM far *pa;
  172.             WORD sel = FP_SEG(lpAtomTable);
  173.             GetModuleFileName(ge.hOwner, owner, 128);
  174.             if ((ge.hOwner == hUser) && (ge.wType != GT_DGROUP))
  175.                 printf("GLOBAL ==> ");  // identify Global Atom Table
  176.             printf("%04x (%s)\n", sel, owner);
  177.             num_atoms = 0;
  178.             for (i=0, pa=(PATOM far *) &lpAtomTable->pAtom; 
  179.                  i<lpAtomTable->numEntries; 
  180.                  i++, pa++)
  181.             {
  182.                 if (*pa != 0)
  183.                     num_atoms +=
  184.                         print_bucket(i, MK_FP(sel, (*((WORD FAR *) pa))));
  185.             }
  186.             printf("%u hashtab entries, %u atoms\n\n",
  187.                 lpAtomTable->numEntries, num_atoms);
  188.             printf("\n");
  189.         }
  190.             
  191.         ok = GlobalNext(&ge, GLOBAL_ALL);
  192.     }
  193.     
  194.     winio_setpaint(__hMainWnd, TRUE);
  195.     winio_resetbusy();
  196.     return 0;
  197. }
  198.  
  199.