home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / msysjour / vol07 / 08 / paging / pagewalk.c < prev    next >
Text File  |  1992-12-01  |  6KB  |  238 lines

  1. /*
  2. PAGEWALK.C
  3. from December 1992 Microsoft Systems Journal
  4. Andrew Schulman
  5. */
  6.  
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <dos.h>
  11. #include "dpmishel.h"
  12. #include "protmode.h"
  13.  
  14. static DWORD far *pagedir = (DWORD far *) 0;
  15.  
  16. void fail(char *s)
  17. {
  18.     if (pagedir)
  19.         free_mapped_linear(pagedir);
  20.     puts(s);
  21.     _dos_exit(1);
  22. }
  23.  
  24. DWORD axtol(char *s)
  25. {
  26.     DWORD ret;
  27.     if (s[0]=='0' && s[1]=='x')
  28.     {
  29.         sscanf(s+2, "%08lx", &ret);
  30.         return ret;
  31.     }
  32.     else
  33.         return atol(s);
  34. }
  35.  
  36. /* from VMM.INC */
  37. #define PG_TYPE         0xE000
  38.  
  39. char *page_type[] = {
  40.     "VM     ",
  41.     "SYS    ",
  42.     "Rsrv1  ",
  43.     "Private",
  44.     "Rsrv2  ",
  45.     "Relock ",
  46.     "Inst   ",
  47.     "Hooked ",
  48.     "Ignore ",
  49.     } ;
  50.  
  51. char *desc(WORD bits)
  52. {
  53.     static char buf[80];
  54.     sprintf(buf, "%s %s %s %s %s %s",
  55.         page_type[bits >> 9],   // avail
  56.         bits & 64 ? "dirty" : "clean",
  57.         bits & 32 ? "acc" : "ntacc",
  58.         bits & 4 ? "user" : "supr",
  59.         bits & 2 ? "writ" : "rdonly",
  60.         bits & 1 ? "pres" : "ntpres");
  61.     return buf;
  62. }
  63.  
  64. int iswin3e(void)
  65. {
  66.     WORD maj=0, min=0;
  67.     _asm {
  68.         mov ax, 1600h
  69.         int 2fh
  70.         mov byte ptr maj, al
  71.         mov byte ptr min, ah
  72.         }
  73.     return ((maj > 1) && (maj != 0x80));
  74. }
  75.  
  76. static char *help = "usage: pagewalk "
  77.             "[-noyawn -linphys -physmeg [0x]n -linmeg [0x]n -verbose]" ;
  78.  
  79. int no_yawn = 0;        // omit boring details
  80. int only_linphys = 0;   // only show when linear==physical
  81. int only_physmeg = 0;   // only show when physaddr==meg x
  82. WORD phys_meg = 0;
  83. int only_linmeg = 0;    // only show when linaddr==meg x
  84. WORD lin_meg = 0;
  85. int verbose = 0;        // show CR3, page dir phys addr
  86. int only_phys = 0;      // only show lin addr with specific phys addr
  87. DWORD want_phys;
  88.  
  89. int v86_main(int argc, char *argv[])
  90. {
  91.     int i;
  92.  
  93.     puts("PAGEWALK -- Walk Windows Enhanced Mode Page Tables");
  94.     puts("by Andrew Schulman; December 1992 Microsoft Systems Journal");
  95.     puts("");
  96.  
  97.     for (i=1; i<argc; i++)
  98.         if (argv[i][0] == '-' ||
  99.             argv[i][0] == '/')
  100.         {
  101.             char *s = strupr(&argv[i][1]);
  102.             if (strcmp(s, "NOYAWN") == 0)
  103.                 no_yawn++;
  104.             else if (strcmp(s, "VERBOSE") == 0)
  105.                 verbose++;
  106.             else if (strcmp(s, "LINPHYS") == 0)
  107.                 only_linphys++;
  108.             else if (strcmp(s, "PHYSMEG") == 0)
  109.             {
  110.                 only_physmeg++;
  111.                 phys_meg = axtol(argv[++i]);
  112.             }
  113.             else if (strcmp(s, "LINMEG") == 0)
  114.             {
  115.                 only_linmeg++;
  116.                 lin_meg = axtol(argv[++i]);
  117.             }
  118.             else if (strcmp(s, "PHYS") == 0)
  119.             {
  120.                 only_phys++;
  121.                 want_phys = axtol(argv[++i]);
  122.             }
  123.             else
  124.                 fail(help);
  125.         }
  126.  
  127.     if (! iswin3e())
  128.         fail("This program requires Microsoft Windows 3 Enhanced mode");
  129.  
  130.     return 0;
  131. }
  132.  
  133. void do_page(int pgtab, int page, DWORD pg)
  134. {
  135.     static DWORD previous = -1;
  136.     DWORD physaddr, linaddr;
  137.     WORD attrib;
  138.  
  139.     if (ctrl_c_hit)
  140.         fail("Ctrl-C detected");
  141.  
  142.     linaddr = ((DWORD) pgtab << 22) + ((DWORD) page << 12);
  143.     physaddr = pg & ~4095;
  144.     attrib = pg & 4095;
  145.  
  146.     // if they only want specific linear megabyte
  147.     if (only_linmeg && linaddr>>20 != lin_meg)
  148.         return;
  149.  
  150.     // if they just want linear==physical
  151.     if (only_linphys && linaddr!=physaddr)
  152.         return;
  153.  
  154.     // if they only want specific physical physical address
  155.     if (only_phys && physaddr!=want_phys)
  156.         return;
  157.  
  158.     // if they only want specific physical megabyte
  159.     if (only_physmeg)
  160.         if ((physaddr>>20 != phys_meg) ||
  161.             ((attrib & 1) == 0))    // not present
  162.             return;
  163.  
  164.     // see if it's uninteresting
  165.     if (no_yawn &&
  166.         ((pg - 0x1000 == previous) ||  // increasing
  167.          (pg + 0x1000 == previous) ||  // decreasing
  168.          (pg == previous)))            // identical
  169.     {
  170.         previous = pg;
  171.         return;
  172.     }
  173.     else
  174.         previous = pg;
  175.  
  176.     printf("%08lX (%03X/%03X)   ", linaddr, pgtab, page);
  177.  
  178.     if (attrib & 1)     // present bit
  179.         printf("%08lX%c   %s\n",
  180.             physaddr,
  181.             (linaddr==physaddr) ? '*' : ' ',
  182.             desc(attrib));
  183.     else
  184.         printf("            not present: %08lX\n", pg);
  185. }
  186.  
  187. void do_pagetab(int pgtab)
  188. {
  189.     DWORD far *pagetbl;
  190.     DWORD far *pp;
  191.     int page;
  192.  
  193.     if (verbose)
  194.     {
  195.         DWORD physaddr = pagedir[pgtab] & ~4095;
  196.         printf("\n               %03X   %08lX\n\n", pgtab, physaddr);
  197.     }
  198.  
  199.     if (pagetbl = get_pagetab(pagedir, pgtab))
  200.     {
  201.         for (page=0, pp=pagetbl; page<1024; page++, pp++)
  202.             if (*pp)     // something to display
  203.                 do_page(pgtab, page, *pp);
  204.     }
  205.     else
  206.         printf("can't map page table #%04x\n", pgtab);
  207. }
  208.  
  209. int pmode_main(int argc, char *argv[])
  210. {
  211.     int pgtab;
  212.  
  213.     /* DWORD far *pagedir; */
  214.     pagedir = get_pagedir();
  215.  
  216.     printf("linear (dir/entry)   physical\n");
  217.     printf("------------------   --------\n");
  218.  
  219.     // if they only want linaddr for specific meg
  220.     if (only_linmeg)
  221.     {
  222.         do_pagetab(lin_meg / 4);    // each pagetab has 4 meg
  223.         goto done;
  224.     }
  225.  
  226.     if (verbose)
  227.         printf("CR3                  %08lX\n", pagedir_phys);
  228.  
  229.     for (pgtab=0; pgtab<1024; pgtab++)  // for each possible page table
  230.         if (pagedir[pgtab] & 1)     // present bit
  231.             do_pagetab(pgtab);
  232.  
  233. done:
  234.     free_mapped_linear(pagedir);
  235.     return 0;
  236. }
  237.  
  238.