home *** CD-ROM | disk | FTP | other *** search
- /*
- * SHOWEXE displays information about the EXE file named on the
- * command line. It can handle both the DOS and the OS/2 formats.
- * If output is not redirected, it pauses after each section.
- * Written by David A. Schmitt.
- */
- #include <stdio.h>
- extern far pascal VioScrollUp();
- extern far pascal VioWrtCharStr();
- extern far pascal VioWrtNAttr();
- extern char *malloc();
-
- extern void pause();
- extern void cls();
- /**
- *
- * Old executable header, used by DOS
- *
- */
- struct EXE_DOS
- {
- unsigned short e_magic; /* magic number 0x5A4D */
- unsigned short e_cblp; /* bytes in last page */
- unsigned short e_cp; /* 512-byte pages in file */
- unsigned short e_crlc; /* number of relocations */
- unsigned short e_cparhdr; /* paragraphs in header */
- unsigned short e_minalloc; /* minimum extra paragraphs */
- unsigned short e_maxalloc; /* maximum extra paragraphs */
- unsigned short e_ss; /* initial SS value */
- unsigned short e_sp; /* initial SP value */
- unsigned short e_csum; /* checksum */
- unsigned short e_ip; /* initial IP value */
- unsigned short e_cs; /* initial CS value */
- unsigned short e_lfarlc; /* file address of reloc table */
- unsigned short e_ovno; /* overlay number */
- unsigned short e_res1[4]; /* reserved */
- unsigned short e_oemid; /* OEM identifier */
- unsigned short e_oeminfo; /* OEM information */
- unsigned short e_res2[10]; /* reserved */
- unsigned long e_lfanew; /* file address of new header */
- };
- /**
- *
- * Structure of DOS relocation items
- *
- */
- struct REL
- {
- unsigned short offset;
- unsigned short segment;
- };
- /**/
- /**
- *
- * New executable header, used by OS/2
- *
- */
- struct EXE_OS2
- {
- unsigned short ne_magic; /* magic number 0x454E */
- unsigned char ne_ver; /* version number */
- unsigned char ne_rev; /* revision number */
- unsigned short ne_enttab; /* offset of entry table*/
- unsigned short ne_cbenttab; /* # of bytes in entry table*/
- long ne_crc; /* checksum */
- unsigned short ne_flags; /* miscellaneous flags */
- unsigned short ne_autodata; /* auto data segment number */
- unsigned short ne_heap; /* initial heap allocation */
- unsigned short ne_stack; /* initial stack allocation */
- unsigned short ne_ip; /* initial IP offset */
- unsigned short ne_cs; /* initial CS segment number*/
- unsigned short ne_sp; /* initial SP offset */
- unsigned short ne_ss; /* initial SS segment number*/
- unsigned short ne_cseg; /* number of segments */
- unsigned short ne_cmod; /* number of module references */
- unsigned short ne_cbnrestab; /* size of non-resident names*/
- unsigned short ne_segtab; /* segment table offset */
- unsigned short ne_rsrctab; /* resource table offset */
- unsigned short ne_restab; /* resident name table offset */
- unsigned short ne_modtab; /* module reference table offset*/
- unsigned short ne_imptab; /* import name table offset */
- unsigned long ne_nrestab; /* non-resident name tab offset */
- unsigned short ne_cmovent; /* number of movable entries */
- unsigned short ne_align; /* segment alignment shift count*/
- unsigned short ne_cres; /* number of resource entries */
- char resv[10]; /* reserved */
- };
- /**
- *
- * Definition of bits in ne_flags
- *
- */
- #define NENOTP 0x8000 /* not a process */
- #define NEIERR 0x2000 /* errors in image */
- #define NEFLTP 0x0080 /* floating point instructions */
- #define NEI386 0x0040 /* 80386 instructions */
- #define NEI286 0x0020 /* 80286 instructions */
- #define NEI086 0x0010 /* 8086 instructions */
- #define NEPROT 0x0008 /* protected mode only */
- #define NEPPLI 0x0004 /* per-process library initialization*/
- #define NEINST 0x0002 /* per-instance data */
- #define NESOLO 0x0001 /* solo data */
- /**
- *
- * Structure of segment table entries
- *
- */
- struct SEG
- {
- unsigned short ns_sector; /* starting sector */
- unsigned short ns_cbseg; /* segment size (in file)*/
- unsigned short ns_flags; /* segment flags */
- unsigned short ns_minalloc; /* minimum size in bytes*/
- };
- /**
- *
- * Definition of bits in ns_flags
- *
- */
- #define NSTYPE 0x0007 /* segment type mask, types are... */
- #define NSCODE 0 /* 0 for code segment */
- #define NSDATA 1 /* 1 for data segment */
- #define NSITER 0x0008 /* iterated segment */
- #define NSMOVE 0x0010 /* movable segment */
- #define NSPURE 0x0020 /* pure segment */
- #define NSPRELOAD 0x0040 /* preloaded segment */
- #define NSEXRD 0x0080 /* code segment: execute only*/
- /* data segment: read only */
- #define NSRELOC 0x0100 /* relocation information present */
- #define NSCONFORM 0x0200 /* conforming segment */
- #define NSDPL 0x0c00 /* 80286 DPL bits */
- #define SHIFTDPL 10 /* shift factor for NSDPL */
- #define NSDISCARD 0x1000 /* discardable segment */
- #define NS32BIT 0x2000 /* 32-bit segment */
- #define NSHUGE 0x4000 /* huge memory segment */
- /**/
- /**
- *
- * name main -- main program
- *
- * synopsis main(argc,argv)
- * int argc; number of arguments
- * char *argv[]; argument pointer array
- *
- * description:
- * This is the main program that displays EXE file information.
- * Upon entry, argc should be 2, and argv[1] should point to
- * the EXE file name, which must include the .EXE extension.
- *
- * The program sends its output to stdout, which can be
- * redirected to somewhere other than the system console.
- * Error output is sent to stderr, and when an error occurs
- * the program exits with a completion code of 1.
- **/
- main(argc,argv)
- int argc;
- char *argv[];
- {
- FILE *fp;
- unsigned char *p;
- int i,j,k;
- union
- {
- short w;
- char b[2];
- } word;
- struct EXE_DOS oldexe;
- struct REL rel;
- struct EXE_OS2 newexe;
- struct SEG seg;
- char b[256];
- /*
- *
- * Check file argument, open file, and read old EXE header
- *
- */
- if(argc < 2)
- {
- fprintf(stderr,"No EXE file specified\n");
- exit(1);
- }
- fp = fopen(argv[1],"rb");
- if(fp == NULL)
- {
- fprintf(stderr,"Can't open \"%s\"\n",argv[1]);
- exit(1);
- }
- if(fread((char *)(&oldexe),sizeof(struct EXE_DOS),1,fp) != 1)
- {
- fprintf(stderr,"Can't read \"%s\"\n",argv[1]);
- exit(1);
- }
- if(oldexe.e_magic != 0x5a4d)
- {
- fprintf(stderr,"\"%s\" is not an EXE file\n",argv[1]);
- exit(1);
- }
- /*
- *
- * Print DOS header information
- *
- */
- cls();
- printf("DOS EXE header information for \"%s\"...\n\n",argv[1]);
- printf("%40s: %u\n","Number of bytes in header",oldexe.e_cparhdr*16);
- printf("%40s: %u\n","Number of 512-byte pages",oldexe.e_cp);
- printf("%40s: %u\n","Number of bytes in last page",oldexe.e_cblp);
- printf("%40s: %04XH\n","Checksum",oldexe.e_csum);
- printf("%40s: %04XH\n","Minimum number of extra paragraphs",
- oldexe.e_minalloc);
- printf("%40s: %04XH\n","Maximum number of extra paragraphs",
- oldexe.e_maxalloc);
- printf("%40s: %04X:%04X\n","Starting address",oldexe.e_cs,
- oldexe.e_ip);
- printf("%40s: %04X:%04X\n","Stack address",oldexe.e_ss,
- oldexe.e_sp);
- printf("%40s: %u\n","Overlay number",oldexe.e_ovno);
- printf("%40s: %04XH\n","OEM identifier",oldexe.e_oemid);
- printf("%40s: %04XH\n","OEM information",oldexe.e_oeminfo);
- printf("%40s: %u\n","Number of relocations",oldexe.e_crlc);
- /*
- *
- * Print DOS relocation table
- *
- */
- if(oldexe.e_crlc)
- {
- pause(fp);
- printf("\n\nRelocation table at file offset %04XH...\n",
- oldexe.e_lfarlc);
- if(fseek(fp,(long)oldexe.e_lfarlc,0))
- {
- fprintf(stderr,"Can't seek to %04XH in \"%s\"\n",
- oldexe.e_lfarlc,argv[1]);
- exit(1);
- }
- for(i = 1; i <= oldexe.e_crlc; i++)
- {
- if(fread((char *)(&rel),sizeof(struct REL),1,fp) != 1)
- {
- fprintf(stderr,"Can't read \"%s\"\n",argv[1]);
- exit(1);
- }
- printf("%04X:%04X ",rel.segment,rel.offset);
- if((i % 6) == 0) printf("\n");
- }
- }
- /*
- *
- * Check if OS/2 executable, and terminate if not.
- * Otherwise, read in the OS/2 header.
- *
- */
- if(oldexe.e_lfanew == 0) exit(0);
- pause();
- printf("\n\nOS/2 EXE header information at %04XH...\n\n",
- oldexe.e_lfanew);
- if(fseek(fp,(long)oldexe.e_lfanew,0))
- {
- fprintf(stderr,"Can't seek to %04XH in \"%s\"\n",
- oldexe.e_lfanew,argv[1]);
- exit(1);
- }
- if(fread((char *)(&newexe),sizeof(struct EXE_OS2),1,fp) != 1)
- {
- fprintf(stderr,"Can't read \"%s\"\n",argv[1]);
- exit(1);
- }
- if(newexe.ne_magic != 0x454e)
- {
- fprintf(stderr,"\"%s\" is not an OS/2 EXE file\n",argv[1]);
- exit(1);
- }
- /*
- *
- * Print basic information from new EXE header
- *
- */
- printf("%40s: %08lXH\n","Checksum",newexe.ne_crc);
- printf("%40s: %u\n","Version number",newexe.ne_ver);
- printf("%40s: %u\n","Revision number",newexe.ne_rev);
- printf("%40s: %u\n","Number of segments",newexe.ne_cseg);
- printf("%40s: %04X:%04X\n","Starting address",
- newexe.ne_cs,newexe.ne_ip);
- printf("%40s: %04X:%04X\n","Stack address",newexe.ne_ss,newexe.ne_sp);
- printf("%40s: %u\n","Automatic data segment number",
- newexe.ne_autodata);
- printf("%40s: %04XH\n","Initial heap allocation in auto data",
- newexe.ne_heap);
- printf("%40s: %04XH\n","Initial stack allocation in auto data",
- newexe.ne_stack);
- printf("%40s: %04XH\n","Flags",newexe.ne_flags);
- printf("%40s? %s\n","Program or library",
- (newexe.ne_flags & NENOTP) ? "LIBRARY" : "PROGRAM");
- printf("%40s? %s\n","Errors in image",
- (newexe.ne_flags & NEIERR) ? "YES" : "NO");
- printf("%40s? %s\n","Floating point instructions",
- (newexe.ne_flags & NEFLTP) ? "YES" : "NO");
- printf("%40s? %s\n","80386 instructions",
- (newexe.ne_flags & NEI386) ? "YES" : "NO");
- printf("%40s? %s\n","80286 instructions",
- (newexe.ne_flags & NEI286) ? "YES" : "NO");
- printf("%40s? %s\n","8086 instructions",
- (newexe.ne_flags & NEI086) ? "YES" : "NO");
- printf("%40s? %s\n","Protected mode only",
- (newexe.ne_flags & NEPROT) ? "YES" : "NO");
- printf("%40s? %s\n","Per-process initialization",
- (newexe.ne_flags & NEPPLI) ? "YES" : "NO");
- printf("%40s? %s\n","Per-instance data",
- (newexe.ne_flags & NEINST) ? "YES" : "NO");
- printf("%40s? %s\n","Solo data",
- (newexe.ne_flags & NESOLO) ? "YES" : "NO");
- pause();
- /*
- *
- * Print segment table
- *
- */
- printf("\n\nSegment table at %08lXH (%08lXH + %04XH)...\n\n",
- (long)(oldexe.e_lfanew+newexe.ne_segtab),
- oldexe.e_lfanew,newexe.ne_segtab);
- printf(" FILE FILE MEMORY\n");
- printf("SEG ADDR SIZE FLAGS SIZE\n\n");
- if(fseek(fp,(long)(oldexe.e_lfanew + newexe.ne_segtab),0))
- {
- fprintf(stderr,"Can't seek to %08lXH in \"%s\"\n",
- (long)(oldexe.e_lfanew+newexe.ne_segtab),argv[1]);
- exit(1);
- }
- for(i = 1; i <= newexe.ne_cseg; i++)
- {
- if(fread((char *)(&seg),sizeof(struct SEG),1,fp) != 1)
- {
- fprintf(stderr,"Can't read \"%s\"\n",argv[1]);
- exit(1);
- }
- printf("%3d %04X %04X %04X %04X %s\n",i,
- seg.ns_sector,seg.ns_cbseg,seg.ns_flags,seg.ns_minalloc,
- (seg.ns_flags & NSTYPE) ? "Data" : "Code");
- }
- pause();
- /*
- *
- * Print imported name table
- *
- */
- if(newexe.ne_imptab)
- {
- printf("\n\n");
- printf("Imported Name Table at %08lXH (%08lXH + %04XH)...\n\n",
- (long)(oldexe.e_lfanew+newexe.ne_imptab),
- oldexe.e_lfanew,newexe.ne_imptab);
- if(fseek(fp,(long)(oldexe.e_lfanew + newexe.ne_imptab + 1),0))
- {
- fprintf(stderr,"Can't seek to %08lXH in \"%s\"\n",
- (long)(oldexe.e_lfanew+newexe.ne_imptab + 1),argv[1]);
- exit(1);
- }
- printf("INDEX NAME\n");
- printf("----- ----\n");
- for(i = newexe.ne_imptab+1; i < newexe.ne_enttab; i += j+1)
- {
- j = fgetc(fp);
- if(j == EOF)
- {
- fprintf(stderr,"Can't read \"%s\"\n",argv[1]);
- exit(1);
- }
- if(j == 0) break;
- if(fread(b,j,1,fp) != 1)
- {
- fprintf(stderr,"Can't read \"%s\"\n",argv[1]);
- exit(1);
- }
- b[j] = '\0';
- printf(" %04x %s\n",(i-newexe.ne_imptab),b);
- }
- pause();
- }
- /*
- *
- * Print Module Reference Table
- *
- */
- if(newexe.ne_cmod)
- {
- printf("\n\n");
- printf("Module Reference Table at %08lXH (%08lXH + %04XH)...\n\n",
- (long)(oldexe.e_lfanew+newexe.ne_modtab),
- oldexe.e_lfanew,newexe.ne_modtab);
- if(fseek(fp,(long)(oldexe.e_lfanew + newexe.ne_modtab),0))
- {
- fprintf(stderr,"Can't seek to %08lXH in \"%s\"\n",
- (long)(oldexe.e_lfanew+newexe.ne_modtab),argv[1]);
- exit(1);
- }
- printf("MODULE INDEX\n");
- printf("------ -----\n");
- for(i = 1; i <= newexe.ne_cmod; i++)
- {
- if(fread((char *)(&j),2,1,fp) != 1)
- {
- fprintf(stderr,"Can't read \"%s\"\n",argv[1]);
- exit(1);
- }
- printf(" %04X %04X\n",i,j);
- }
- pause();
- }
- /*
- *
- * Print Resident Name Table
- *
- */
- if(newexe.ne_restab)
- {
- printf("\n\n");
- printf("Resident Name Table at %08lXH (%08lXH + %04XH)...\n\n",
- (long)(oldexe.e_lfanew+newexe.ne_restab),
- oldexe.e_lfanew,newexe.ne_restab);
- if(fseek(fp,(long)(oldexe.e_lfanew + newexe.ne_restab),0))
- {
- fprintf(stderr,"Can't seek to %08lXH in \"%s\"\n",
- (long)(oldexe.e_lfanew+newexe.ne_restab),argv[1]);
- exit(1);
- }
- printf("ORDINAL NAME\n");
- printf("------- ----\n");
- while(i = fgetc(fp))
- {
- if((i == EOF) || (fread(b,i,1,fp) != 1))
- {
- fprintf(stderr,"Can't read \"%s\"\n",argv[1]);
- exit(1);
- }
- b[i] = '\0';
- if(fread((char *)(&j),2,1,fp) != 1)
- {
- fprintf(stderr,"Can't read \"%s\"\n",argv[1]);
- exit(1);
- }
- printf(" %04X %s\n",j,b);
- }
- pause();
- }
- /*
- *
- * Print Non-resident Name Table
- *
- */
- if(newexe.ne_nrestab)
- {
- printf("\n\nNon-resident Name Table at %08lXH...\n\n",
- newexe.ne_nrestab);
- if(fseek(fp,newexe.ne_nrestab,0))
- {
- fprintf(stderr,"Can't seek to %08lXH in \"%s\"\n",
- newexe.ne_nrestab,argv[1]);
- exit(1);
- }
- printf("ORDINAL NAME\n");
- printf("------- ----\n");
- while(i = fgetc(fp))
- {
- if((i == EOF) || (fread(b,i,1,fp) != 1))
- {
- fprintf(stderr,"Can't read \"%s\"\n",argv[1]);
- exit(1);
- }
- b[i] = '\0';
- if(fread((char *)(&j),2,1,fp) != 1)
- {
- fprintf(stderr,"Can't read \"%s\"\n",argv[1]);
- exit(1);
- }
- printf(" %04X %s\n",j,b);
- }
- pause();
- }
- /*
- *
- * Print entry table
- *
- */
- if(newexe.ne_cbenttab)
- {
- printf("\n\nEntry table at %08lXH (%08lXH + %04XH)...\n\n",
- (long)(oldexe.e_lfanew+newexe.ne_enttab),
- oldexe.e_lfanew,newexe.ne_enttab);
- if(fseek(fp,(long)(oldexe.e_lfanew + newexe.ne_enttab),0))
- {
- fprintf(stderr,"Can't seek to %08lXH in \"%s\"\n",
- (long)(oldexe.e_lfanew+newexe.ne_enttab),argv[1]);
- exit(1);
- }
- p = malloc(newexe.ne_cbenttab);
- if(p == NULL)
- {
- fprintf(stderr,"Out of memory\n");
- exit(1);
- }
- if(fread(p,newexe.ne_cbenttab,1,fp) != 1)
- {
- fprintf(stderr,"Can't read \"%s\"\n",argv[1]);
- exit(1);
- }
- printf("SEG OFFSET FLAGS\n");
- printf("--- ------ -----\n");
- for(i = 0; i < newexe.ne_cbenttab; )
- {
- j = p[i++];
- k = p[i++];
- if(k) while(j-- > 0)
- {
- if(k != 255)
- {
- word.b[0] = p[i+1];
- word.b[1] = p[i+2];
- printf("%3d %04X %02X\n",k,word.w,p[i]);
- i += 3;
- }
- else
- {
- word.b[0] = p[i+4];
- word.b[1] = p[i+5];
- printf("%3d %04X %02X\n",p[i+3],word.w,p[i]);
- i += 6;
- }
- }
- }
- }
- }
- /**/
- /**
- *
- * name pause
- *
- * synopsis pause();
- *
- * description This function checks if the standard output file
- * is the system console. If so, it displays a pause message
- * and then waits until the user presses a key.
- *
- **/
- void pause()
- {
- char reverse = 0x70;
- static char prompt[] = "Press any key to continue";
-
- if(isatty(fileno(stdout)))
- {
- VioWrtNAttr((char far *)(&reverse),80,24,0,0);
- VioWrtCharStr((char far *)prompt,sizeof(prompt)-1,24,0,0);
- getch();
- cls();
- }
- }
- /**
- *
- * name cls -- clear the screen
- *
- * synopsis cls();
- *
- * description This function clears the screen by calling the
- * VioScrollUp function in a special way. However,
- * it has not be generalized to work with display
- * modes using more than 25 lines of 80 characters each.
- *
- **/
- void cls()
- {
- short fill = 0x0720;
-
- VioScrollUp(0,0,24,79,-1,(short far *)(&fill),0);
- }