home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
msysjour
/
vol07
/
08
/
paging
/
pagewalk.c
< prev
next >
Wrap
Text File
|
1992-12-01
|
6KB
|
238 lines
/*
PAGEWALK.C
from December 1992 Microsoft Systems Journal
Andrew Schulman
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dos.h>
#include "dpmishel.h"
#include "protmode.h"
static DWORD far *pagedir = (DWORD far *) 0;
void fail(char *s)
{
if (pagedir)
free_mapped_linear(pagedir);
puts(s);
_dos_exit(1);
}
DWORD axtol(char *s)
{
DWORD ret;
if (s[0]=='0' && s[1]=='x')
{
sscanf(s+2, "%08lx", &ret);
return ret;
}
else
return atol(s);
}
/* from VMM.INC */
#define PG_TYPE 0xE000
char *page_type[] = {
"VM ",
"SYS ",
"Rsrv1 ",
"Private",
"Rsrv2 ",
"Relock ",
"Inst ",
"Hooked ",
"Ignore ",
} ;
char *desc(WORD bits)
{
static char buf[80];
sprintf(buf, "%s %s %s %s %s %s",
page_type[bits >> 9], // avail
bits & 64 ? "dirty" : "clean",
bits & 32 ? "acc" : "ntacc",
bits & 4 ? "user" : "supr",
bits & 2 ? "writ" : "rdonly",
bits & 1 ? "pres" : "ntpres");
return buf;
}
int iswin3e(void)
{
WORD maj=0, min=0;
_asm {
mov ax, 1600h
int 2fh
mov byte ptr maj, al
mov byte ptr min, ah
}
return ((maj > 1) && (maj != 0x80));
}
static char *help = "usage: pagewalk "
"[-noyawn -linphys -physmeg [0x]n -linmeg [0x]n -verbose]" ;
int no_yawn = 0; // omit boring details
int only_linphys = 0; // only show when linear==physical
int only_physmeg = 0; // only show when physaddr==meg x
WORD phys_meg = 0;
int only_linmeg = 0; // only show when linaddr==meg x
WORD lin_meg = 0;
int verbose = 0; // show CR3, page dir phys addr
int only_phys = 0; // only show lin addr with specific phys addr
DWORD want_phys;
int v86_main(int argc, char *argv[])
{
int i;
puts("PAGEWALK -- Walk Windows Enhanced Mode Page Tables");
puts("by Andrew Schulman; December 1992 Microsoft Systems Journal");
puts("");
for (i=1; i<argc; i++)
if (argv[i][0] == '-' ||
argv[i][0] == '/')
{
char *s = strupr(&argv[i][1]);
if (strcmp(s, "NOYAWN") == 0)
no_yawn++;
else if (strcmp(s, "VERBOSE") == 0)
verbose++;
else if (strcmp(s, "LINPHYS") == 0)
only_linphys++;
else if (strcmp(s, "PHYSMEG") == 0)
{
only_physmeg++;
phys_meg = axtol(argv[++i]);
}
else if (strcmp(s, "LINMEG") == 0)
{
only_linmeg++;
lin_meg = axtol(argv[++i]);
}
else if (strcmp(s, "PHYS") == 0)
{
only_phys++;
want_phys = axtol(argv[++i]);
}
else
fail(help);
}
if (! iswin3e())
fail("This program requires Microsoft Windows 3 Enhanced mode");
return 0;
}
void do_page(int pgtab, int page, DWORD pg)
{
static DWORD previous = -1;
DWORD physaddr, linaddr;
WORD attrib;
if (ctrl_c_hit)
fail("Ctrl-C detected");
linaddr = ((DWORD) pgtab << 22) + ((DWORD) page << 12);
physaddr = pg & ~4095;
attrib = pg & 4095;
// if they only want specific linear megabyte
if (only_linmeg && linaddr>>20 != lin_meg)
return;
// if they just want linear==physical
if (only_linphys && linaddr!=physaddr)
return;
// if they only want specific physical physical address
if (only_phys && physaddr!=want_phys)
return;
// if they only want specific physical megabyte
if (only_physmeg)
if ((physaddr>>20 != phys_meg) ||
((attrib & 1) == 0)) // not present
return;
// see if it's uninteresting
if (no_yawn &&
((pg - 0x1000 == previous) || // increasing
(pg + 0x1000 == previous) || // decreasing
(pg == previous))) // identical
{
previous = pg;
return;
}
else
previous = pg;
printf("%08lX (%03X/%03X) ", linaddr, pgtab, page);
if (attrib & 1) // present bit
printf("%08lX%c %s\n",
physaddr,
(linaddr==physaddr) ? '*' : ' ',
desc(attrib));
else
printf(" not present: %08lX\n", pg);
}
void do_pagetab(int pgtab)
{
DWORD far *pagetbl;
DWORD far *pp;
int page;
if (verbose)
{
DWORD physaddr = pagedir[pgtab] & ~4095;
printf("\n %03X %08lX\n\n", pgtab, physaddr);
}
if (pagetbl = get_pagetab(pagedir, pgtab))
{
for (page=0, pp=pagetbl; page<1024; page++, pp++)
if (*pp) // something to display
do_page(pgtab, page, *pp);
}
else
printf("can't map page table #%04x\n", pgtab);
}
int pmode_main(int argc, char *argv[])
{
int pgtab;
/* DWORD far *pagedir; */
pagedir = get_pagedir();
printf("linear (dir/entry) physical\n");
printf("------------------ --------\n");
// if they only want linaddr for specific meg
if (only_linmeg)
{
do_pagetab(lin_meg / 4); // each pagetab has 4 meg
goto done;
}
if (verbose)
printf("CR3 %08lX\n", pagedir_phys);
for (pgtab=0; pgtab<1024; pgtab++) // for each possible page table
if (pagedir[pgtab] & 1) // present bit
do_pagetab(pgtab);
done:
free_mapped_linear(pagedir);
return 0;
}