home *** CD-ROM | disk | FTP | other *** search
- #pragma title("IDT - Find Internal Data Table")
- #pragma subtitle("Introduction")
-
- /*
- ** program: idt
- **
- ** purpose: This program finds the internal device
- ** table used by MS-DOS and reports its
- ** contents. It includes options to dump
- ** and/or display each of the various
- ** structures pointed to by the idt.
- **
- ** usage: idt
- **
- ** switches: -i = List the internal data table
- ** -p = List the physical device table
- ** -l = List the logical device table
- ** -d = List the device driver headers
- ** -m = List the memory arena
- ** -b = List buffer control blocks
- ** -f = List internal file control blocks
- ** -c = List file control blocks
- ** -v = Verbose (dump buffers)
- ** -* = Everything (except verbose)
- **
- ** notes: Much (most) of the information contained in
- ** the idt (including the method used to find
- ** it) is undocumented and subject to change
- ** and/or errors. This version will not work
- ** for versions of MS-DOS previous to 3.0.
- **
- ** Considering the wealth of information revealed
- ** in these tables, it may me a reasonable risk
- ** for an application which takes some care to
- ** utilize it - even though it is officially
- ** undocumented and will not be supported by
- ** the OS vendor (yes, you know who you are!)
- **
- ** author: Bill Parrott
- **
- ** Copyright (c) 1988, Bill Parrott
- ** All Rights Reserved
- **
- ** Use this code in any way and the information
- ** contained herein any way you like, without
- ** restriction. If you accomplish something
- ** because of what you got here, and if it makes
- ** you rich, well I just hope you'll remember
- ** who made it all possible :-). Seriously, a
- ** little credit would be nice but apart from
- ** that, have at it!
- */
-
- #define VERSION 1
- #define REVISION 0
-
- #define PROGRAMNAME "IDT"
-
- /*
- ** system includes
- */
-
- #include <stdio.h>
- #include <dos.h>
- #include <ctype.h>
- #include <assert.h>
- #include <process.h>
-
- /*
- ** site includes
- */
-
- #include <local/getargs.h>
- #include <local/what.h>
-
- #include "idt.h"
-
- #pragma subtitle("Data and Definitions")
- #pragma page()
-
- /*
- ** global data
- */
-
- IDT *idt; /* address of internal data table */
-
- /*
- ** this cell is filled by our function rather that
- ** from the idt just so we can say we really did it.
- */
-
- segment arenastart; /* start of memory arena */
-
-
- /*
- ** switch data
- */
-
- static int doidt = 0; /* list the internal data table */
- static int dopdpt = 0; /* list the physical device table */
- static int doldt = 0; /* list the logical device table */
- static int dodevhdr = 0; /* list device driver headers */
- static int doarena = 0; /* list memory arena */
- static int dobcb = 0; /* list buffer control blocks */
- static int verbose = 0; /* verbose listing (dumps buffers) */
- static int doifcb = 0; /* list internal file control blocks */
- static int dofcbt = 0; /* list file control blocks */
- static int doall = 0; /* list everything */
-
-
- /*
- ** switch table
- */
-
- ARG swtab[] =
- {
- { 'i', BOOLEAN, &doidt, "List internal data table" },
- { 'p', BOOLEAN, &dopdpt, "List physical device table" },
- { 'l', BOOLEAN, &doldt, "List logical device table" },
- { 'd', BOOLEAN, &dodevhdr, "List device driver headers" },
- { 'm', BOOLEAN, &doarena, "List memory arena" },
- { 'b', BOOLEAN, &dobcb, "List buffer control blocks" },
- { 'f', BOOLEAN, &doifcb, "List internal file control blocks" },
- { 'c', BOOLEAN, &dofcbt, "List file control blocks" },
- { 'v', BOOLEAN, &verbose, "Verbose (dump buffers)" },
- { '*', BOOLEAN, &doall, "List everything" }
- };
-
- #define TABSIZE (sizeof(swtab) / sizeof(ARG))
-
-
- /*
- ** prototypes
- */
-
- int main( int, char ** );
-
- segment findarena( void );
- segment isarena( segment, segment );
-
- void showidt( IDT far * );
- void showpdpt( PDPT far * );
- void showpdpt1( PDPT far * );
- void showldt( LDT far * );
- void showdevhdr( DEVHDR far * );
- void showdevhdr1( DEVHDR far * );
- char *trimname( char far *, int );
- void showarena( MDB far * );
- int isenv( char far * );
- int ispsp( char far * );
- void showbcb( BCB far * );
- void dumpbuffer( byte far * );
- void paragraph( byte *, word );
- void memkpy( byte *, byte far *, int );
- int memkmp( byte *, byte far *, int );
- void showifcb( CHAIN far *, int );
- void showifcb1( IFCB far * );
-
-
-
- /*
- ** "what" strings
- */
-
- static char *WhatStrings[] =
- {
- WHATVER(PROGRAMNAME,VERSION,REVISION),
- WHATWHEN,
- WHATDATE,
- WHAT("Copyright (c) 1988, Bill Parrott"),
- WHAT(" All Rights Reserved")
- };
-
- #pragma subtitle("main()")
- #pragma page()
-
- /*
- ** main (need I say more?)
- */
-
- int main( argc, argv )
-
- int argc;
- char *argv[];
-
- {
- union REGS r;
- struct SREGS s;
- IDT safeplaceforidt;
- IDT far *p;
- int i;
-
- /*
- ** signon
- */
-
- fprintf( stderr, "\n%s", &WhatStrings[0][4] );
- fprintf( stderr, "\n%s\n", &WhatStrings[3][4] );
-
- /*
- ** check for version
- */
-
- r.h.ah = 0x30;
- intdos( &r, &r );
-
- if ( r.h.al < 0 )
- {
- fprintf( stderr, "\nIncorrect version of MS-DOS.\n" );
- return ( 1 );
- }
-
-
- /*
- ** process the command line
- */
-
- argc = getargs( argc, argv, swtab, TABSIZE );
-
- if ( doall )
- doidt = dopdpt = doldt = dodevhdr =
- doarena = dobcb = doifcb = dofcbt = 1;
- else
- {
- i = doidt + dopdpt + doldt + dodevhdr +
- doarena + dobcb + doifcb + dofcbt;
-
- if ( i == 0 )
- {
- fprintf( stderr, "\nusage: idt switch(es)\n" );
- fprintf( stderr, "\n\t-i = list the internal data table" );
- fprintf( stderr, "\n\t-p = list the physical device table" );
- fprintf( stderr, "\n\t-l = list the logical device table" );
- fprintf( stderr, "\n\t-d = list the device driver headers" );
- fprintf( stderr, "\n\t-m = list the memory arena" );
- fprintf( stderr, "\n\t-b = list buffer control blocks" );
- fprintf( stderr, "\n\t-f = list internal file control blocks" );
- fprintf( stderr, "\n\t-c = list file control blocks" );
- fprintf( stderr, "\n\t-v = verbose (dump buffers)" );
- fprintf( stderr, "\n\t-* = list all tables" );
- fprintf( stderr, "\n" );
- return ( 1 );
- }
- }
-
-
- /*
- ** find the memory arena on our own first.
- */
-
- if ( (arenastart = findarena()) == 0 )
- {
- fprintf( stderr, "\n\n\a+++ Can't locate the first memory descriptor!! +++\n" );
- return ( 1 );
- }
-
-
- /*
- ** now look up the internal data table
- */
-
- segread( &s );
-
- r.h.ah = 0x52; /* magic undocumented function */
- intdosx( &r, &r, &s );
-
-
- /*
- ** get a static copy for playing with
- */
-
- idt = &safeplaceforidt;
-
- FP_SEG(p) = s.es;
- FP_OFF(p) = r.x.bx - 8;
-
- memkpy( (byte *) idt, (byte far *) p, sizeof(IDT) );
-
-
- /*
- ** process selections
- */
-
- if ( doidt )
- showidt( idt );
-
- if ( dopdpt )
- showpdpt( idt->pdpt );
-
- if ( doldt )
- showldt( idt->ldt );
-
- if ( dodevhdr )
- showdevhdr( &idt->nuldev );
-
- if ( doarena )
- showarena( idt->arena );
-
- if ( dobcb )
- showbcb( idt->bcbhead );
-
- if ( doifcb )
- showifcb( idt->ifcb, 1 );
-
- if ( dofcbt )
- showifcb( idt->fcbt, 0 );
-
-
- /*
- ** clean up
- */
-
- printf( "\n" );
-
- return ( 0 );
- }
-
- #pragma subtitle("findarena() - find start of memory arena")
- #pragma page()
-
- /*
- ** function: findarena
- **
- ** purpose: This function demonstrates a well behaved (?)
- ** technique for finding the first memory control
- ** block. It uses only information obtained from
- ** Microsoft literature and documents in this
- ** task... (hopefully freeing it from version
- ** dependancies.) We do, however, make the
- ** assumption that MS-DOS memory descriptors
- ** are ALWAYS on paragraph boundaries.
- **
- ** usage: first = findarena();
- ** segment first;
- **
- ** returns: segment of first descriptor if found,
- ** else 0.
- */
-
- segment findarena()
-
- {
- word beginsearch;
- word endsearch;
- union REGS r;
-
- /*
- ** find a place to give up the search. For further
- ** reliability, we make this the end of physical
- ** memory (as DOS knows it). Besides, the function
- ** isarena() requires it.
- */
-
- beginsearch = 0x40; /* after interrupt table */
-
- int86( 0x12, &r, &r ); /* get it from the BIOS */
- endsearch = r.x.ax << 6; /* last paragraph + 1 */
-
-
- /*
- ** find the start of the arena
- */
-
- for ( arenastart = beginsearch; arenastart < endsearch; ++arenastart )
- if ( isarena( arenastart, endsearch ) )
- break;
-
- /*
- ** check it, but it can't happen.
- */
-
- if ( arenastart >= endsearch )
- {
- fprintf( stderr, "\nSomething's REALLY screwed up, Martha!!\n" );
- return ( 0 );
- }
-
- return ( arenastart );
- }
-
- #pragma subtitle("isarena() - is segment is the arena?")
- #pragma page()
-
- /*
- ** function: isarena
- **
- ** purpose: This function determines whether the passed
- ** segment address points to the start of DOS'
- ** memory allocation arena.
- **
- ** usage: result = isarena( seg, endsearch );
- ** segment result;
- ** segment seg;
- ** segment endsearch;
- **
- ** returns: 0 if not, else segment of high memory + 1
- **
- ** notes: To perform this test, we first check to see
- ** if the paragraph appears to be a memory
- ** descriptor block. If so, add the block
- ** length to get the address of the next block.
- ** Then we check that block to see if it's a
- ** memory descriptor. If so, add the block
- ** length to get the next block, and so on
- ** until we reach the end of the arena. If
- ** any entry is not a descriptor, or if the
- ** arena does not end at exactly the end of
- ** memory then the test fails.
- **
- ** The defined value LOOPCHECK (below) is used
- ** to keep the algorithm from getting into an
- ** endless loop due to a circular link. The
- ** value chosen should be sufficiently large
- ** to keep from prematurely terminating a
- ** valid (however long) chain of MDBs.
- */
-
- #define LOOPCHECK 1024 /* should be high enuf */
-
- segment isarena( seg, endsearch )
-
- segment seg;
- segment endsearch;
-
- {
- MDB far *p;
- int i;
-
- /*
- ** check to see if it appears to be a memory descriptor.
- */
-
- FP_SEG(p) = seg;
- FP_OFF(p) = 0; /* address possible descriptor */
-
- if ( p->type != 'M' )
- return ( 0 ); /* most will fail this test */
-
-
- /*
- ** well, it looks like a duck...
- */
-
- for ( i = 0; i < LOOPCHECK; ++i )
- {
-
- FP_SEG(p) += p->length + 1; /* find next potential */
-
- if ( FP_SEG(p) > endsearch )
- return ( 0 ); /* too far */
-
- if ( p->type == 'Z' )
- break; /* found last one */
-
- if ( p->type != 'M' )
- return ( 0 ); /* false alarm */
-
- }
-
- if ( i == LOOPCHECK )
- return ( 0 ); /* circular loop? */
-
-
- /*
- ** looks like a duck, and it walks like a duck...
- */
-
- FP_SEG(p) += p->length + 1; /* last link */
-
- return ( FP_SEG(p) == endsearch ); /* quack! */
- }
-
- #pragma subtitle("showidt() - display idt")
- #pragma page()
-
- /*
- ** function: showidt
- **
- ** purpose: This function displays the contents of the
- ** internal data table upon stdout.
- **
- ** usage: void showidt( idt );
- ** IDT far *idt;
- **
- ** returns: nothing
- */
-
- void showidt( idt )
-
- IDT far *idt;
-
- {
- void far *temp;
-
- printf( "\nInternal Data Table at: %p\n", idt );
-
- printf( "\n\t%p = Current Buffer Control Block", idt->curbcb );
- printf( "\n\t%p = Start of MS-DOS Memory Arena", idt->arena );
- temp = idt->arena;
- if ( FP_SEG(temp) != arenastart )
- printf( "\n\t *** Expected %04x ***", arenastart );
- printf( "\n\t%p = Physical Drive Parameter Table", idt->pdpt );
- printf( "\n\t%p = Internal File Control Blocks", idt->ifcb );
- printf( "\n\t%p = Clock Device Driver", idt->clockdev );
- printf( "\n\t%p = Console Device Driver", idt->condev );
- printf( "\n\t %04x = Maximum Sector Size", idt->max_ssize );
- printf( "\n\t%p = Buffer Control Block List", idt->bcbhead );
- printf( "\n\t%p = Logical Device Table", idt->ldt );
- printf( "\n\t%p = File Control Block Table", idt->fcbt );
- printf( "\n\t %5u = Number of protected FCBs", idt->nprotfcbs );
- printf( "\n\t %5u = Number of Physical Drives (in PDT)", idt->nphysdrives );
- printf( "\n\t %5u = Number of Logical Drives (in LDT)", idt->nlogdrives );
- printf( "\n" );
- }
-
- #pragma subtitle("showpdpt() - display pdpt")
- #pragma page()
-
- /*
- ** function: showpdpt
- **
- ** purpose: This function displays the contents of the
- ** physical device table upon stdout.
- **
- ** usage: void showpdpt( pdpt );
- ** PDPT far *pdpt;
- **
- ** returns: nothing
- */
-
- void showpdpt( pdpt )
-
- PDPT far *pdpt;
-
- {
- printf( "\nPhysical Device Table at: %p\n", pdpt );
-
- do
- {
- showpdpt1( pdpt );
- pdpt = pdpt->nextentry;
- } while ( FP_OFF(pdpt) != 0xffff );
- }
-
-
-
- void showpdpt1( pdpt )
-
- PDPT far *pdpt;
-
- {
- printf( "\nAddress of this entry: %p\n", pdpt );
-
- printf( "\n\t %02x = Drive (%c:)", pdpt->drive, pdpt->drive + 'A' );
- printf( "\n\t %02x = Driver unit number", pdpt->dunit );
- printf( "\n\t %5u = Bytes per sector", pdpt->sectorsize );
- printf( "\n\t %3u = Sectors per cluster - 1", pdpt->clustersize );
- printf( "\n\t %02x = Cluster to sector shift", pdpt->shift );
- printf( "\n\t %5u = Number of reserved (boot) sectors", pdpt->bootsectors );
- printf( "\n\t %3u = Number of File Allocation Tables (FATs)", pdpt->fats );
- printf( "\n\t %5u = Number of root directory entries", pdpt->rootsize );
- printf( "\n\t %5u = Sector number of cluster #2 (first data cluster)", pdpt->dataoffset );
- printf( "\n\t %5u = Number of clusters + 1", pdpt->lastcluster );
- printf( "\n\t %3u = Sectors per File Allocation Table (FAT)", pdpt->fatsize );
- printf( "\n\t %5u = Sector number of root directory", pdpt->diroffset );
- printf( "\n\t%p = Address of device header", pdpt->devheader );
- printf( "\n\t %02x = Media descriptor byte", pdpt->mediabyte );
- printf( "\n\t %02x = Access flag", pdpt->accessflag );
- printf( "\n\t%p = Address of next DPT pdpt\n", pdpt->nextentry );
-
- printf( "\n\tAssociated Device Header:\n" );
-
- showdevhdr1( pdpt->devheader );
- }
-
- #pragma subtitle("showldt() - display ldt")
- #pragma page()
-
- /*
- ** function: showldt
- **
- ** purpose: This function displays the contents of the
- ** physical device table upon stdout.
- **
- ** usage: void showldt( ldt );
- ** LDT far *ldt;
- **
- ** returns: nothing
- */
-
- void showldt( ldt )
-
- LDT far *ldt;
-
- {
- int i;
-
- printf( "\nLogical Device Table at: %p\n", ldt );
-
- /*
- ** run through the table
- */
-
- for ( i = 0; i < idt->nlogdrives; ++i, ++ldt )
- {
- printf( "\n\t %c: = Logical Device", i + 'A' );
- printf( "\n\t%p = Entry address", ldt );
- printf( "\n\tDirectory = %Fs", ldt->currentdir );
- printf( "\n\t %02x = Code (?)", ldt->code );
- printf( "\n\t%p = Address of associated physical device entry", ldt->pdpt );
- if ( ldt->pdpt )
- printf( " (Drive %c:)", ldt->pdpt->drive + 'A' );
- printf( "\n\t %5u = Current directory sector", ldt->curdir );
- printf( "\n\t %04x = Flag (?)\n", ldt->flag );
- }
- }
-
- #pragma subtitle("showdevhdr() - display device headers")
- #pragma page()
-
- /*
- ** function: showdevhdr
- **
- ** purpose: This function displays the contents of the
- ** all device driver headers.
- **
- ** usage: void showdevhdr( devhdr );
- ** DEVHDR far *devhdr;
- **
- ** returns: nothing
- */
-
- void showdevhdr( devhdr )
-
- DEVHDR far *devhdr;
-
- {
- printf( "\nDevice Headers begin at: %p\n", devhdr );
-
- do
- {
- showdevhdr1( devhdr );
- devhdr = devhdr->nextheader;
- } while ( FP_OFF(devhdr) != 0xffff );
- }
-
-
-
- void showdevhdr1( devhdr )
-
- DEVHDR far *devhdr;
-
- {
- void far *p;
- word attr;
-
- attr = devhdr->attributes;
-
- printf( "\n\t%p = Address of this Device Header", devhdr );
- if ( attr & 0x8000 )
- {
- printf( "\n\t * Character Device" );
- printf( "\n\t%9s = Device Name", trimname( devhdr->devname, 8 ) );
- }
- else
- {
- printf( "\n\t * Block Device" );
- printf( "\n\t %3u = Number of units", (byte) devhdr->devname[0] );
- }
- printf( "\n\t%p = Address of next device header", devhdr->nextheader );
- printf( "\n\t %04x = Device attributes", attr );
- if ( attr & 0x8000 )
- {
- if ( attr & 0x4000 )
- printf( "\n\t - Supports IOCTL strings" );
- if ( attr & 0x2000 )
- printf( "\n\t - Supports output until busy" );
- if ( attr & 0x0800 )
- printf( "\n\t - Understands open/close" );
- if ( attr & 0x0040 )
- printf( "\n\t - Supports IOCTL functions" );
- if ( attr & 0x0010 )
- printf( "\n\t - Is special device" );
- if ( attr & 0x0008 )
- printf( "\n\t - Is clock device" );
- if ( attr & 0x0004 )
- printf( "\n\t - Is null device" );
- if ( attr & 0x0002 )
- printf( "\n\t - Is console output device" );
- if ( attr & 0x0001 ) /* paying attention? */
- printf( "\n\t - Is console input device" );
- if ( attr & 0x17a0 )
- printf( "\n\t * Has unidentified bit(s) set" );
- }
- else
- {
- if ( attr & 0x4000 )
- printf( "\n\t - Supports IOCTL strings" );
- if ( attr & 0x2000 )
- printf( "\n\t - Uses FAT id byte to find type" );
- if ( attr & 0x0800 )
- printf( "\n\t - Understands open/close" );
- if ( attr & 0x0040 )
- printf( "\n\t - Supports IOCTL functions" );
- if ( attr & 0x0010 )
- printf( "\n\t - Is special device" );
- if ( attr & 0x17af )
- printf( "\n\t * Has unidentified bit(s) set" );
- }
- FP_SEG(p) = FP_SEG(devhdr);
- FP_OFF(p) = devhdr->strategy;
- printf( "\n\t%p = Strategy entry point", p );
- FP_OFF(p) = devhdr->intrupt;
- printf( "\n\t%p = Driver interrupt entry point\n", p );
- }
-
-
-
- char *trimname( name, len )
-
- char far *name;
- int len;
-
- {
- static char buff[9];
- int i;
-
- assert( len <= 8 );
-
- for ( i = 0; i < len; ++i )
- if ( isprint( *name ) && (*name != ' ') )
- buff[i] = *name++;
- else
- break;
-
- buff[i] = '\0';
-
- return ( buff );
- }
-
- #pragma subtitle("showarena() - display memory arena")
- #pragma page()
-
- /*
- ** function: showarena
- **
- ** purpose: This function displays the contents of the
- ** memory arena.
- **
- ** usage: void showarena( arena );
- ** MDB far *arena;
- **
- ** returns: nothing
- */
-
- void showarena( arena )
-
- MDB far *arena;
-
- {
- double kbytes;
- void far *mem;
- int done;
-
- printf( "\nMemory Arena begins at: %p\n", arena );
-
- if ( arena->type != 'M' )
- {
- printf( "\n\t+++ Memory arena not found +++\n" );
- return;
- }
-
- done = 0;
-
- while ( !done )
- {
- mem = arena;
- ++FP_SEG(mem);
-
- printf( "\n\t%04x paragraphs ", arena->length );
- kbytes = (double) arena->length / 64.0;
- printf( "(%6.2f KB)", kbytes );
- printf( " at %p,", arena );
- printf( " Owner=%04x,", arena->owner );
-
- if ( arena->owner == NULL )
- printf( " Free" );
-
- if ( arena->type == 'M' )
- if ( ispsp( mem ) )
- printf( " PSP" );
- else
- if ( isenv( mem ) )
- printf( " Environment" );
- else
- printf( " Data" );
-
- if ( done = (arena->type == 'Z') )
- printf( " [Last Block]" );
-
- FP_SEG(arena) += arena->length + 1;
- }
-
- printf( "\n" );
- }
-
- #pragma subtitle("ispsp() - see if block is a PSP")
- #pragma page()
-
- /*
- ** function: ispsp
- **
- ** purpose: This functions checks a block of memory to
- ** see if it looks like a program segment prefix.
- **
- ** usage: result = ispsp( p );
- ** int result;
- ** char far *;
- **
- ** returns: 0 if not PSP.
- **
- ** notes: The following tests are performed before a
- ** segment qualifies as a PSP:
- **
- ** 1) The word at offset 00h must contain an
- ** INT 20h instruction.
- ** 2) The word at offset 50h must contain an
- ** INT 21h instruction.
- ** 3) The byte at offset 52h must contain a
- ** RETF (far return) instruction.
- ** 4) The owner of the DOS memory block
- ** containing the PSP-elect must be the
- ** PSP itself.
- */
-
- int ispsp( p )
-
- char far *p;
-
- {
- PSP far *psp;
-
- /*
- ** check PSP contents
- */
-
- psp = (PSP far *) p;
-
- if ( psp->wmboot != 0x20cd ) /* test 1 */
- return ( 0 );
-
- if ( psp->int21 != 0x21cd ) /* test 2 */
- return ( 0 );
-
- if ( psp->farret != 0xcb ) /* test 3 */
- return ( 0 );
-
- /*
- ** external test
- */
-
- --FP_SEG(p);
- FP_OFF(p) = 0; /* test 4 */
-
- return ( FP_SEG(psp) == ((MDB far *) p)->owner );
-
- }
-
- #pragma subtitle("isenv() - see if block is environment")
- #pragma page()
-
- /*
- ** function: isenv
- **
- ** purpose: This functions checks a block of memory to
- ** see if it looks like an environment segment.
- **
- ** usage: result = isenv( p );
- ** int result;
- ** char far *;
- **
- ** returns: 0 if not environment.
- **
- ** notes: If the block begins with a series of 1
- ** or more alphanumeric characters followed
- ** immediately by an equal '=' followed
- ** immediately by a string of displayable
- ** ASCII characters followed immediately by
- ** a null (0) byte, then it is assumed to be
- ** an environment block. Ditto.
- */
-
- int isenv( p )
-
- char far *p;
-
- {
- char far *q;
-
- /*
- ** check for a string of the form:
- **
- ** <alphanumeric> <equal> <text> <NULL>
- **
- ** where:
- ** <alphanumeric> : <alpha> | <numeric>
- ** <alpha> : <uppercase> | <lowercase>
- ** <uppercase> : A,B,C,...,Z
- ** <lowercase> : a,b,c,...,z
- ** <numeric> : 0,1,2,...,9
- ** <equal> : =
- ** <text> : [0x20..0x7e]
- ** <NULL> : '\0'
- */
-
- q = p;
- while ( isalnum( *p ) )
- ++p;
-
- if ( p == q )
- return ( 0 ); /* require at least one char */
-
- if ( *p++ != '=' )
- return ( 0 ); /* no = */
-
- q = p;
- while ( isprint( *p ) )
- ++p;
-
- if ( *p != '\0')
- return ( 0 ); /* '\0' missing at the end */
-
- return ( !(p == q) );
- }
-
- #pragma subtitle("showbcb() - display memory bcb")
- #pragma page()
-
- /*
- ** function: showbcb
- **
- ** purpose: This function displays the contents of the
- ** buffer control blocks.
- **
- ** usage: void showbcb( bcb );
- ** BCB far *bcb;
- **
- ** returns: nothing
- */
-
- void showbcb( bcb )
-
- BCB far *bcb;
-
- {
- int done;
- BCB far *p;
-
- printf( "\nBuffer control blocks begin at: %p\n", bcb );
-
- done = 0;
-
- while ( !done )
- {
- p = bcb->nextbcb;
-
- printf( "\n\t%p = Address of this control block", bcb );
- if ( bcb == idt->curbcb )
- printf( " (Current Buffer)" );
- printf( "\n\t%p = Next control block", p );
- printf( "\n\t %02x = Action code", bcb->action );
- printf( "\n\t %5u = Logical sector number", bcb->logsec );
- printf( "\n\t %3u = Number of FATs", bcb->nfats );
- printf( "\n\t %3u = Sectors per FAT", bcb->sectorsperfat );
- printf( "\n\t%p = Associated physical device parameters (%c:)", bcb->pdpt, bcb->pdpt->drive + 'A' );
- printf( "\n\t%p = Buffer address\n", bcb->buffer );
-
- if ( verbose )
- dumpbuffer( bcb->buffer );
-
- if ( !(done = (FP_OFF(p) == 0xffff)) )
- bcb = p;
- }
-
- printf( "\n" );
- }
-
- #pragma subtitle("dumpbuffer() - hex dump a buffer")
- #pragma page()
-
- /*
- ** function: dumpbuffer
- **
- ** purpose: This function is called to produce a hex
- ** dump of the addressed buffer. It will
- ** always dump 512 bytes, however it will
- ** abbreviate the dump if possible by not
- ** displaying consecutive duplicate paragraphs.
- **
- ** usage: void dumpbuffer( p );
- ** byte far *p;
- **
- ** returns: nothing
- */
-
- void dumpbuffer( p )
-
- byte far *p;
-
- {
- byte lastpara[16];
- int sameaslast;
- int para;
-
- printf( "\n\tBuffer Contents:\n" );
-
- for ( sameaslast = para = 0; para < 32; ++para, p += 16 )
- {
- if ( para && (para < 31) )
- {
- if ( memkmp( lastpara, p, 16 ) )
- {
- memkpy( lastpara, p, 16 );
- paragraph( lastpara, para << 4 );
- sameaslast = 0;
- }
- else
- if ( !sameaslast++ )
- printf( "\n\t =======" );
- }
- else
- {
- memkpy( lastpara, p, 16 );
- paragraph( lastpara, para << 4 );
- }
- }
-
- printf( "\n" );
- }
-
-
-
- void paragraph( p, o )
-
- byte *p;
- word o;
-
- {
- int x;
-
- printf( "\n\t%04x:", o );
-
- /*
- ** hex part of dump
- */
-
- for ( x = 0; x < 16; ++x )
- printf( " %02x", p[x] );
-
- /*
- ** show ASCII for fun
- */
-
- printf( " " );
-
- for ( x = 0; x < 16; ++x )
- printf( "%c", isprint( p[x] ) ? p[x] : '.' );
- }
-
- #pragma subtitle("memk..() - near/far memory functions")
- #pragma page()
-
- /*
- ** function: memkpy
- **
- ** purpose: This function if used to copy data from
- ** far memory to near memory. Is is similar
- ** to memcpy().
- **
- ** usage: void memkpy( dest, src, len );
- ** byte *dest;
- ** byte far *src;
- ** int len;
- **
- ** returns: nothing
- */
-
- void memkpy( d, s, l )
-
- byte *d;
- byte far *s;
- int l;
-
- {
- while ( l-- )
- *d++ = *s++;
- }
-
-
-
- /*
- ** function: memkmp
- **
- ** purpose: This function if used to compare data in
- ** far memory to data in near memory. It is
- ** similar to memkmp().
- **
- ** usage: void memkmp( p1, p2, len );
- ** byte *p1;
- ** byte far *p2;
- ** int len;
- **
- ** returns: nothing
- */
-
- int memkmp( d, s, l )
-
- byte *d;
- byte far *s;
- int l;
-
- {
- if ( !l )
- return ( 0 );
-
- while ( --l && ( *d == *s ) )
- ++d, ++s;
-
- return ( *d - *s );
- }
-
- #pragma subtitle("showifcb() - display internal fcbs")
- #pragma page()
-
- /*
- ** function: showifcb
- **
- ** purpose: This function displays the contents of the
- ** internal file control block chain.
- **
- ** usage: void showifcb( chain, flag );
- ** CHAIN far *chain;
- ** int flag; (* 1 if ifcb, 0 if fcbt *)
- **
- ** returns: nothing
- */
-
- void showifcb( chain, flag )
-
- CHAIN far *chain;
- int flag;
-
- {
- CHAIN far *c;
- IFCB far *ifcb;
- int nifcbs;
- int nlinks;
- int done;
- int i;
-
- /*
- ** get some basic information
- */
-
- c = chain;
-
- nlinks = nifcbs = done = 0;
-
- do
- {
- nifcbs += c->nentries;
- ++nlinks;
- c = c->nextchain;
- } while ( FP_OFF(c) != 0xffff );
-
- if ( flag )
- printf( "\nInternal File Control Block Chain at %p contains", chain );
- else
- printf( "\nFile Control Block Chain at %p contains", chain );
-
- if ( nlinks > 1 )
- printf( "\n%d links with a total of %d internal file control blocks.\n", nlinks, nifcbs );
- else
- printf( "\n1 link with %d internal file control blocks.\n", nifcbs );
-
-
- /*
- ** now give the details
- */
-
- c = chain;
-
- do
- {
- if ( nlinks > 1 )
- printf( "\nLink at %p contains %d blocks\n", c, c->nentries );
-
- ifcb = (IFCB far *) c;
- FP_OFF(ifcb) += sizeof(CHAIN);
-
- for ( i = 0; i < c->nentries; ++i )
- showifcb1( &ifcb[i] );
-
- c = c->nextchain;
- } while ( FP_OFF(c) != 0xffff );
-
- printf( "\n" );
- }
-
-
-
-
- #define MO (ifcb->filedate.month)
- #define DA (ifcb->filedate.day)
- #define YR (ifcb->filedate.year + 1980)
-
- #define HR (ifcb->filetime.hour)
- #define MIN (ifcb->filetime.minute)
- #define SEC (ifcb->filetime.second * 2)
-
- void showifcb1( ifcb )
-
- IFCB far *ifcb;
-
- {
- word attr;
- int i;
- static char *openmode[4] =
- { "Read", "Write", "Read/Write", "Unknown Mode" };
- static char flag[] = "??ADVSHR";
-
- printf( "\n\t %p = Address of this control block", ifcb );
-
- if ( ifcb->filename[0] == 0 )
- {
- printf( " (NEVER USED)\n" );
- return;
- }
-
- printf( "\n\t %5u = Number of opens", ifcb->nopens );
- if ( ifcb->nopens == 0 )
- {
- printf( " (NOT OPEN)" );
-
- if ( !verbose )
- {
- printf( "\n" );
- return;
- }
- }
-
- printf( "\n\t %04x = Open mode (%s)", ifcb->mode, openmode[ifcb->mode & 3] );
- printf( "\n\t %04x = PSP of owner", ifcb->owner );
-
- printf( "\n\t %04x = Device attributes", attr = ifcb->devattr );
- if ( attr & 0x0080 )
- {
- printf( "\n\t - Opened as device" );
- if ( attr & 0x4000 )
- printf( "\n\t - Processes control strings" );
- else
- printf( "\n\t - Cannot process control strings" );
- if ( attr & 0x2000 )
- printf( "\n\t - Supports output until busy" );
- else /* if u cn rd ths u cn gt a gd jb! */
- printf( "\n\t - Doesn't support output until busy" );
- if ( attr & 0x0800 )
- printf( "\n\t - Understands open/close" );
- else
- printf( "\n\t - Doesn't understand open/close" );
- if ( attr & 0x0040 )
- printf( "\n\t - Ready" );
- else
- printf( "\n\t - Not ready" );
- if ( attr & 0x0020 )
- printf( "\n\t - Raw" );
- else
- printf( "\n\t - Cooked" );
- if ( attr & 0x0010 )
- printf( "\n\t - Special device" );
- if ( attr & 0x0008 )
- printf( "\n\t - Clock device" );
- if ( attr & 0x0004 )
- printf( "\n\t - Null device" );
- if ( attr & 0x0002 )
- printf( "\n\t - Console output device" );
- if ( attr & 0x0001 )
- printf( "\n\t - Console input device" );
- if ( attr & 0x9700 )
- printf( "\n\t - ?? (%04x)", attr & 0x9700 );
- }
- else
- {
- printf( "\n\t - Opened as file" );
- if ( attr & 0x0040 )
- printf( "\n\t - Not written to" );
- else
- printf( "\n\t - Written to" );
- printf( "\n\t - On drive %c:", (attr & 0x002f) + 'A' );
- if ( attr & 0xff00 )
- printf( "\n\t - ?? (%04x)", attr & 0xff00 );
- }
-
- if ( attr & 0x0080 )
- {
- printf( "\n\t '%8.8Fs' = Device name", ifcb->filename );
- printf( "\n\t %p = Driver header address", ifcb->pdpt );
- }
- else
- {
- printf( "\n\t'%8.8Fs.%3.3Fs' = File name", ifcb->filename, ifcb->fileext );
- printf( "\n\t %2d/%02d/%04d = File date", MO, DA, YR );
- printf( "\n\t %2d:%02d:%02d = File time", HR, MIN, SEC );
- printf( "\n\t %02x = Attribute (flags) byte", ifcb->fileattr );
- if ( ifcb->fileattr )
- {
- printf( " [" );
- for ( i = 0; i < 8; ++i )
- if ( ifcb->fileattr & (0x80 >> i) )
- printf( "%c", flag[i] );
- else
- printf( "%c", '-' );
- printf( "]" );
- }
- printf( "\n\t %5u = First cluster in file", ifcb->firstcluster );
- printf( "\n\t %5u = Number of clusters in file", ifcb->nclusters );
- printf( "\n\t %5u = Current cluster", ifcb->curcluster );
- printf( "\n\t %10lu = File size (bytes)", ifcb->filesize );
- printf( "\n\t %10lu = Current file position", ifcb->filepos );
- printf( "\n\t %5u = Sector in directory containing file's entry", ifcb->dirsector );
- printf( "\n\t %2u = Index of directory entry in sector", ifcb->dirindex );
- printf( "\n\t %p = Associated physical device parameters (%c:)", ifcb->pdpt, ifcb->pdpt->drive + 'A' );
- }
-
- printf( "\n" );
- }
-
-