home *** CD-ROM | disk | FTP | other *** search
- /*
- ATOMWALK.C -- Shows every atom in the system
-
- From Chapter 5 of "Undocumented Windows" (Addison-Wesley 1992)
- by Andrew Schulman, Dave Maxey and Matt Pietrek
-
- Build using: WINIOBC ATOMWALK HANDLES (for Borland C++ v3.00)
- WINIOMS ATOMWALK HANDLES (for Microsoft C/SDK)
-
- For each atom table in this system <--- this is the hard part
- If it's the Global Atom Table, identify it
- For each entry in hash table
- If entry is in use
- Maybe show entry number
- For each atom in this bucket
- Print atom handle, atom string
- */
-
- #include <windows.h>
- #include <stdlib.h>
- #include <string.h>
- #include <dos.h>
- #include "toolhelp.h"
- #include "winio.h"
- #include "handles.h"
-
- /* from WINEXP.H */
- /* atom manager internals */
- #define ATOMSTRUC struct atomstruct
- typedef ATOMSTRUC *PATOM;
- typedef ATOMSTRUC {
- PATOM chain;
- WORD usage; /* Atoms are usage counted. */
- BYTE len; /* length of ASCIZ name string */
- BYTE name; /* beginning of ASCIZ name string */
- } ATOMENTRY;
-
- typedef struct {
- int numEntries;
- PATOM pAtom[ 1 ];
- } ATOMTABLE;
-
- /* identical to documented (but discouraged) GetAtomHandle() */
- #define AtomToHandle(atom) ((WORD) (atom) << 2) /* overflow */
-
- #define HandleToAtom(handle) (0xC000 | ((handle) >> 2))
-
- /* NULL segment at offset 0 in a data segment with
- atom table or local heap */
- typedef struct {
- WORD wMustBeZero;
- DWORD dwOldSSSP;
- WORD pLocalHeap;
- WORD pAtomTable;
- WORD pStackTop;
- WORD pStackMin;
- WORD pStackBottom;
- } INSTDATA;
-
- /* There is no signature for atom tables, so seeing if you found one
- is tricky, and perhaps only probabilistically correct. To be
- an atom table, there _must_ be a local heap (the atoms themselves
- are items in the local heap). We can test for a correct local
- heap. There must also be a valid NULL segment block at offset 0 */
- ATOMTABLE far *GetAtomTable(GLOBALENTRY *pge)
- {
- extern DWORD FAR PASCAL GetSelectorLimit(WORD sel);
- if ((pge->wType == GT_DGROUP) ||
- (pge->wType == GT_DATA) ||
- (pge->wType == GT_UNKNOWN)) // GlobalAllocs are GT_UNKNOWN
- {
- WORD sel = GlobalHandleToSel(pge->hBlock);
- INSTDATA far *lpInstData = MK_FP(sel, 0);
- DWORD limit = GetSelectorLimit(sel);
- if (verr(sel) &&
- (limit > 16) &&
- (lpInstData->wMustBeZero == 0) &&
- (lpInstData->pLocalHeap != 0) &&
- (lpInstData->pLocalHeap < (WORD) limit) &&
- (lpInstData->pAtomTable != 0) &&
- (lpInstData->pAtomTable < (WORD) limit) &&
- IsValidLocalHeap(MK_FP(sel, lpInstData->pLocalHeap)))
- {
- return MK_FP(sel, lpInstData->pAtomTable);
- }
- }
-
- /* still here */
- return 0L;
- }
-
- WORD FAR PASCAL BasedGetAtomName(WORD wSeg,
- WORD wAtom, LPSTR lpszBuf, int cbBuf)
- {
- WORD retval;
- _asm push ds
- _asm mov ds, wSeg
- retval = GetAtomName(wAtom, lpszBuf, cbBuf);
- _asm pop ds
- return retval;
- }
-
- ATOM BasedFindAtom(WORD wSeg, LPSTR lpsz)
- {
- ATOM retval;
- _asm push ds
- _asm mov ds, wSeg
- retval = FindAtom(lpsz);
- _asm pop ds
- return retval;
- }
-
- static BOOL show_bucket = FALSE;
-
- WORD print_bucket(WORD hash, ATOMENTRY far *pa)
- {
- WORD num_atoms = 0;
- WORD seg = FP_SEG(pa);
- WORD ofs = FP_OFF(pa);
- if (show_bucket)
- printf("Bucket %u\n", hash);
- for (;;) // print everything that hashes to this bucket
- {
- num_atoms++;
- printf(" %04x %Fs\n", HandleToAtom(FP_OFF(pa)), &pa->name);
- #define PARANOID
- #ifdef PARANOID
- if (HandleToAtom(ofs) != BasedFindAtom(seg, &pa->name))
- fail("Something wrong!");
- #endif
- if ((ofs = (WORD) pa->chain) != 0)
- pa = MK_FP(seg, ofs); // follow linked list
- else
- break;
- }
- return num_atoms;
- }
-
- main(int argc, char *argv[])
- {
- ATOMTABLE far *lpAtomTable;
- GLOBALENTRY ge;
- HANDLE hUser;
- WORD num_atoms;
- int ok;
-
- if (argc >= 2)
- if (strcmp(strupr(argv[1]), "-BUCKET") == 0)
- show_bucket = TRUE;
-
- winio_about("ATOMWALK"
- "\nShows every atom in the system"
- "\nUsage: ATOMWALK [-BUCKET]"
- "\n\nFrom Chapter 5 of"
- "\n\"Undocumented Windows\" (Addison-Wesley, 1992)"
- "\nby Andrew Schulman, David Maxey and Matt Pietrek"
- );
-
- hUser = GetModuleHandle("USER");
- ge.dwSize = sizeof(ge);
- winio_setbusy();
- winio_setpaint(__hMainWnd, FALSE);
- ok = GlobalFirst(&ge, GLOBAL_ALL);
- while (ok)
- {
- // for Atom Table structure, see WINEXP.H
- if (lpAtomTable = GetAtomTable(&ge))
- {
- char owner[128];
- int i;
- PATOM far *pa;
- WORD sel = FP_SEG(lpAtomTable);
- GetModuleFileName(ge.hOwner, owner, 128);
- if ((ge.hOwner == hUser) && (ge.wType != GT_DGROUP))
- printf("GLOBAL ==> "); // identify Global Atom Table
- printf("%04x (%s)\n", sel, owner);
- num_atoms = 0;
- for (i=0, pa=(PATOM far *) &lpAtomTable->pAtom;
- i<lpAtomTable->numEntries;
- i++, pa++)
- {
- if (*pa != 0)
- num_atoms +=
- print_bucket(i, MK_FP(sel, (*((WORD FAR *) pa))));
- }
- printf("%u hashtab entries, %u atoms\n\n",
- lpAtomTable->numEntries, num_atoms);
- printf("\n");
- }
-
- ok = GlobalNext(&ge, GLOBAL_ALL);
- }
-
- winio_setpaint(__hMainWnd, TRUE);
- winio_resetbusy();
- return 0;
- }
-
-