/* * DOSINFO.CPP - Contains DOS memory management functions. * Copyright (C) 1998, 1999 Prashant TR * * Special thanks to Al Williams. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * See the file COPYING.TR for more details. */ // ID for this file. #define _DOSINFO_CC_ #include "dosinfo.h" int errflag = 0; FILE *fp; char cmdline[20]; char output[256]; unsigned short dossegs[10]; // Write any string to the file and check for successfulness. void writestring(const char *string) { if (fprintf(fp, "%s", string) == EOF) { errflag = 2; checkerrors(); } } void writememinfo() { union REGS regs; struct SREGS segs; unsigned short *peekptr; unsigned char *mcbptr; union { char *byte; unsigned far *word; } ptr; char string[80], name[9], *mcbinfo; unsigned umbactive, blockid=0; /* Assume DOS 5.00 or better. */ writestring("\nDOS MEMORY ALLOCATION INFORMATION :\n\n"); // Write to file. writestring("------------------------------------------------------------------------------\n"); writestring("Segment Owner Name Size (HEX) Size (Decimal) Parent Process ID\n"); writestring("------- ----- ---- ---------- -------------- -----------------\n"); // To get DOS Memory Allocation list. regs.x.ax = 0x5802; int86(0x21, ®s, ®s); umbactive = regs.h.al; regs.x.ax = 0x5803; regs.x.bx = 1; int86(0x21, ®s, ®s); // Get magic address. regs.h.ah = 0x52; segread(&segs); int86x(0x21, ®s, ®s, &segs); // Get pointer to segment of 1st MCB. peekptr = (unsigned short *)MK_FP(segs.es, regs.x.bx - 2); mcbptr = (unsigned char *)MK_FP(*peekptr, 0); do { unsigned short seg, owner, size, ppid; unsigned long bytesize; ptr.byte = mcbptr; mcbinfo = mcbptr; seg = FP_SEG(mcbptr) + 1; blockid = *ptr.byte++; owner = *ptr.word++; size = *ptr.word++; // Convert to size to bytes. bytesize = (unsigned long)(size + 1) * 0x10; // Skip to actual memory block. ptr.byte += 11; ppid = 0xffff; if (*ptr.word == 0x20cd) { int f; for(f = 0; f <= 7; f++) name[f] = mcbinfo[8+f]; name[8] = 0; ppid = ptr.word[11]; } else { strcpy(name, ""); if (owner == 8) { if (mcbinfo[8] == 'S') { if (mcbinfo[9] == 'C') strcpy(name, "DOS Code"); else if (mcbinfo[9] == 'D') strcpy(name, "DOS Data"); } else strcat(name, "MS-DOS"); } else strcpy(name, "DATA"); } if ((owner) && (ppid != 0xffff)) sprintf(output," %04X %04X %8s %05lX %07lu %04X\n", seg, owner, name, bytesize, bytesize, ppid); else if (owner) sprintf(output," %04X %04X %8s %05lX %07lu\n", seg, owner, name, bytesize, bytesize); else sprintf(output," %04X %05lX %07lu\n", seg, bytesize, bytesize); writestring(output); mcbptr = (unsigned char *)MK_FP(FP_SEG(mcbptr) + size + 1, 0); } while (blockid != 0x5a); // Set back UMB state. regs.x.ax = 0x5803; regs.x.bx = umbactive; int86(0x21, ®s, ®s); writestring("------------------------------------------------------------------------------\n"); } void writedevinfo() { union REGS regs; struct SREGS segs; char string[80],name[9],lastblock[9]="A: "; int flags,i,temp; writestring("------------------------------------------------------------------------------\n"); writestring("DOS DEVICE DRIVERS INFORMATION :\n"); // Write to file. writestring("------------------------------------------------------------------------------\n"); writestring(" Address Driver Name Driver flags\n"); writestring(" ------- ----------- ------------\n"); // To get device driver list. regs.h.ah = 0x52; segread(&segs); int86x(0x21, ®s, ®s, &segs); regs.x.bx += 0x22; // Assume DOS version > 2. do { flags = *(unsigned short *)MK_FP(segs.es, regs.x.bx + 4); for(i = 0; i <= 8; i++) name[i]=*(char *)MK_FP(segs.es, regs.x.bx + 10 + i); name[8]='\0'; sprintf(output," %04X:%04X %s " "%04X\n", segs.es, regs.x.bx, (flags&0x8000) ? name : lastblock, flags); if (!(flags & 0x8000)) { if (lastblock[0] == 'A') dossegs[1] = segs.es; lastblock[0]++; } else { if (!strnicmp(name, "nul", 3)) dossegs[0] = segs.es; else if (!strnicmp(name, "con", 3)) dossegs[2] = segs.es; else if (!strnicmp(name, "clock$", 6)) dossegs[3] = segs.es; else if (!strnicmp(name, "com1", 4)) dossegs[4] = segs.es; else if (!strnicmp(name, "lpt1", 4)) dossegs[5] = segs.es; } writestring(output); temp = segs.es; segs.es = *(unsigned short *)MK_FP(segs.es, regs.x.bx + 2); regs.x.bx = *(unsigned short *)MK_FP(temp, regs.x.bx); } while (regs.x.bx != 0xffff); writestring("------------------------------------------------------------------------------\n"); } void writeconfiginfo() { union REGS regs; struct SREGS segs; writestring("\nDOS CONFIGURATION & OTHER INFORMATION :\n\n"); // Write to file. regs.x.ax = 0x3000; int86(0x21, ®s, ®s); sprintf(output, "\tDOS Version returned : %d.%02d\n", regs.h.al, regs.h.ah); writestring(output); regs.x.ax = 0x3306; int86(0x21, ®s, ®s); sprintf(output, "\tTrue DOS version : %d.%02d\n", regs.h.bl, regs.h.bh); writestring(output); sprintf(output, "\tDOS Revision : %d\n", regs.h.dl); writestring(output); sprintf(output, "\tDOS Installed in ROM : %s\n", (regs.h.dh & 0x8) ? "Yes" : "No"); writestring(output); sprintf(output, "\tDOS Installed in HMA : %s\n", (regs.h.dh & 0x10) ? "Yes" : "No"); writestring(output); regs.x.ax = 0x3305; int86(0x21, ®s, ®s); sprintf(output, "\tDOS Boot drive : %c\n", regs.h.dl + 'A' - 1); writestring(output); regs.x.ax = 0x1203; segread(&segs); int86x(0x2f, ®s, ®s, &segs); sprintf(output, "\tDOS Internal Data Segment : %04Xh\n", segs.ds); writestring(output); regs.x.ax = 0x5800; int86(0x21, ®s, ®s); sprintf(output, "\tMemory Allocation Strategy : %s\n", (!regs.x.ax) ? "Low Memory 1st fit" : (regs.x.ax == 1) ? "Low Memory Best fit" : (regs.x.ax == 2) ? "Low Memory Last fit" : (regs.x.ax == 0x40) ? "High Memory 1st fit" : (regs.x.ax == 0x41) ? "High Memory Best fit" : (regs.x.ax == 0x43) ? "High Memory Last fit" : (regs.x.ax == 0x80) ? "1st fit, high, then low memory" : (regs.x.ax == 0x81) ? "Best fit, high, then low memory" : (regs.x.ax == 0x82) ? "Last fit, high, then low memory" : "Unknown"); writestring(output); regs.h.ah = 0x52; segread(&segs); int86x(0x21, ®s, ®s, &segs); sprintf(output, "\tPointer to Internal data : %04X:%04X\n", segs.es, regs.x.bx); writestring(output); regs.h.ah = 0x34; segread(&segs); int86x(0x21, ®s, ®s, &segs); sprintf(output, "\tINDOS flag : %04X:%04X\n", segs.es, regs.x.bx); writestring(output); regs.x.ax = 0x5d06; segread(&segs); int86x(0x21, ®s, ®s, &segs); sprintf(output, "\tCritical Error flag : %04X:%04X\n", segs.ds, regs.x.si); writestring(output); regs.h.ah = 0x52; segread(&segs); int86x(0x21, ®s, ®s, &segs); // Get pointer to segment of 1st MCB. sprintf(output, "\tMemory Control Block Segment (MCB) : %04Xh\n", *(unsigned short *)MK_FP(segs.es, regs.x.bx-2)); writestring(output); } int sysinfo() { // Create output file. if ((fp = fopen("dosinfo.txt", "w")) == NULL) { errflag = 1; checkerrors(); } // Get DOS information. writeconfiginfo(); writedevinfo(); writememinfo(); fclose(fp); return 0; } void open_stderr() { fclose(stdout); fclose(&_streams[2]); if (fopen("nul", "wb") == NULL) exit(0x7f); if (fopen("nul", "wb") == NULL) exit(0x7f); if ((stderr = fopen("errors.$$$", "ab")) == NULL) exit(0x7f); } void get_cmdline() { if ((fp = fopen("cmdline.$$$", "rb")) == NULL) exit (0x7f); if (fscanf(fp, "%s", cmdline) != 1) { fclose(fp); exit (0x7f); } fclose(fp); unlink("cmdline.$$$"); } #pragma argsused int main(int argc, char **argv) { open_stderr(); get_cmdline(); if (!strcmp(cmdline, "sysinfo")) return (sysinfo()); return 0; }