home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet MPEG Audio Archive
/
IMAA.mdf
/
util
/
dos
/
l3v100n
/
rsx
/
source
/
cdosx32.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-19
|
12KB
|
465 lines
/* This file is CDOSX32.C
**
** contains :
**
** - int21 handler
**
** Copyright (c) Rainer Schnitker 92 93
*/
#include <stdio.h>
#include <io.h>
#include "DPMI.H"
#include "PROCESS.H"
#include "START32.H"
#include "CDOSX32.H"
#include "COPY32.H"
#include "TERMIO.H"
#include "DOSERRNO.H"
static char iobuffer[IOBUF_SIZE + 3]; /* I/O buffer for real-mode operations */
char *iobuf = iobuffer;
TRANSLATION tr; /* registers set for mode-switching */
static DWORD user_dta; /* prot-mode DTA address */
extern WORD _psp; /* PSP after protected mode switch */
static void illegal_param(void)
{
puts("Illegal Parameter in syscall");
send_signal(npz, SIGSEGV);
EAX = EMX_EINTR;
}
#define TEST_ILLEGAL( OFFSET , LENGHT ) \
if ( OFFSET < 0x1000L || OFFSET + LENGHT >= npz->membytes ) { \
illegal_param(); \
return CARRY_ON; \
}
void align_iobuf(void)
{
iobuf = (char *) ((unsigned) (iobuf + 3) & ~3);
}
static void put_regs(void)
{
tr.eax = EAX;
tr.ebx = EBX;
tr.ecx = ECX;
tr.edx = EDX;
tr.flags = FLAGS & ~1;
}
static void get_regs(void)
{
EAX = tr.eax;
EBX = tr.ebx;
ECX = tr.ecx;
EDX = tr.edx;
FLAGS = tr.flags;
}
static char rm_stack[512];
unsigned real_mode_stack = (unsigned) (rm_stack + 510);
/* call Real-Mode INT0x21 */
int realdos(void)
{
/* int rsp; */
/* tr.sp = (WORD) & rsp - 40; */
tr.eax &= 0xFFFF;
tr.cs = cs16real;
tr.ds = tr.ss = tr.es = tr.fs = tr.gs = ds16real;
tr.sp = real_mode_stack;
/* DPMI-Call to Real-Mode DOS */
SimulateRMint(0x21, 0, 0, &tr);
/* return Carry-bit */
return (tr.flags & 1);
}
/*
** INT 0x21 handler returns:
**
** CARRY_ON : error, set carry-bit, errno in eax
** CARRY_OFF: no error, clear carry-bit
** CARRY_NON: carry-bit set by realdos -> dos error code in ax,
** translate ax to errno
*/
int int21normal(void)
{
int i;
char rAH, rAL;
rAH = (BYTE) (AX >> 8);
rAL = (BYTE) EAX;
switch (rAH) {
/************ register based functions ***************/
/* no changes needed - only ax,dx,flags (bx,cx) used */
case 0x01: /* read char */
case 0x02: /* write char */
case 0x03: /* read char stdaux */
case 0x04: /* write char stdaux */
case 0x05: /* read char prn */
case 0x06: /* con output&input */
case 0x07: /* char input & echo */
case 0x08: /* char output & echo */
case 0x0b: /* get stdin stat */
case 0x0c: /* flush buffer & read std input */
case 0x0d: /* disk reset */
case 0x0e: /* select drive */
case 0x19: /* get drive */
case 0x2a: /* get system date (cx) */
case 0x2b: /* set system date (cx) */
case 0x2c: /* get time (cx) */
case 0x2d: /* set time (cx) */
case 0x2e: /* set verify */
case 0x30: /* get DOS version (bx) */
case 0x33: /* extended break check */
case 0x36: /* get free disk space (bx,cx) */
case 0x37: /* get&set switch char */
case 0x3e: /* close file (bx) */
case 0x45: /* dup file (bx) */
case 0x46: /* dup2 file */
case 0x54: /* get verify flag */
case 0x57: /* get file state (bx,cx) */
case 0x5c: /* un-&lock file */
case 0x66: /* code page */
case 0x68: /* fflush file */
if (rAH == 0x3E && EBX < 3) {
EAX = 0;
return CARRY_OFF;
}
put_regs();
realdos();
get_regs();
return CARRY_NON;
case 0x42: /* lseek file */
put_regs();
if (npz->p_flags & PF_EMX_FILE) {
/* convert edx to cx:dx */
tr.ecx = tr.edx >> 16;
tr.edx &= 0xffff;
}
if (realdos())
EAX = tr.eax; /* dos error code */
else {
if (npz->p_flags & PF_EMX_FILE) {
EAX = (tr.edx << 16) | (WORD) tr.eax;
FLAGS = tr.flags;
}
else get_regs();
}
return CARRY_NON;
case 0x44: /* IOCTL */
switch (rAL) {
case 0x00: /* get device info */
case 0x01: /* set device info */
case 0x06: /* get input status */
case 0x07: /* get output status */
case 0x08: /* check block device remove */
case 0x09: /* check block device remote */
case 0x0a: /* check handle remote */
case 0x0b: /* set sharing */
case 0x0e: /* get log drive map */
case 0x0f: /* set log drive map */
case 0x10: /* query ioctl handle */
case 0x11: /* query ioctl drive */
put_regs();
realdos();
get_regs();
return CARRY_NON;
default:
EAX = EMX_EIO;
return CARRY_ON;
}
/***** some special handling *****/
case 0x1a: /* SET DTA */
TEST_ILLEGAL(EDX, 2);
user_dta = EDX;
tr.eax = 0x1a00;
tr.edx = (DWORD) (WORD) iobuf;
realdos();
return CARRY_OFF;
case 0x2f: /* GET DTA */
EBX = user_dta;
return CARRY_OFF;
case 0x62: /* GET PSP */
EBX = (DWORD) _psp;
return CARRY_OFF;
/*********** ASCiiZero functions ***********/
/* copy name -> real_buffer , call realdos */
case 0x09: /* string to output */
TEST_ILLEGAL(EDX, 2);
getstr32_16(DS, EDX, iobuf, '$');
tr.eax = EAX;
tr.edx = (DWORD) (WORD) iobuf;
realdos();
return CARRY_NON;
case 0x39: /* MKDIR name */
case 0x3a: /* RMDIR name */
case 0x3b: /* CHDIR name */
case 0x3c: /* CREATE name */
case 0x3d: /* OPEN name */
case 0x41: /* UNLINK name */
case 0x43: /* ATTRIB name */
case 0x5b: /* CREATE New file */
TEST_ILLEGAL(EDX, 2);
if (rAH == 0x3c) /* fix umask bug */
ECX &= ~1L;
put_regs();
strcpy32_16(DS, EDX, iobuf);
tr.edx = (DWORD) (WORD) iobuf;
realdos();
get_regs();
return CARRY_NON;
case 0x56: /* RENAME oldname name (strlen < 1024) */
TEST_ILLEGAL(EDX, 2);
TEST_ILLEGAL(EDI, 2);
put_regs();
strcpy32_16(DS, EDX, iobuf);
strcpy32_16(DS, EDI, iobuf + 1024);
tr.edx = (DWORD) (WORD) iobuf;
tr.edi = (DWORD) ((WORD) iobuf + 1024);
realdos();
get_regs();
return CARRY_NON;
case 0x5a: /* CREATE TEMP name */
TEST_ILLEGAL(EDX, 2);
put_regs();
strcpy32_16(DS, EDX, iobuf);
tr.edx = (DWORD) (WORD) iobuf;
if (!realdos())
strcpy16_32(DS, EDX, iobuf);
get_regs();
return CARRY_NON;
case 0x6c: /* EXTENDED OPEN/CREATE file */
TEST_ILLEGAL(ESI, 2);
put_regs();
strcpy32_16(DS, ESI, iobuf);
tr.esi = (DWORD) (WORD) iobuf;
realdos();
get_regs();
return CARRY_NON;
/********** buffer functions *********/
/* copy data before or after realdos */
case 0x0a: /* BUFFERED INPUT */
{
BYTE no_chars;
TEST_ILLEGAL(EDX, 4);
put_regs();
no_chars = (BYTE) read32(DS, EDX);
iobuf[0] = no_chars;/* no of chars */
tr.edx = (DWORD) (WORD) iobuf;
realdos();
cpy16_32(DS, EDX, iobuf, (DWORD) no_chars + 2); /* copy of chars */
return CARRY_OFF;
}
case 0x3f: /* READ from file */
{
long count;
DWORD off_edx, bytes;
if ((npz->p_flags & PF_DJGPP_FILE) && EDX == 0) {
printf("read.o not ok ; run DPMIFIX from DJGPP 1.10\n");
EAX = EMX_EIO;
return CARRY_ON;
}
TEST_ILLEGAL(EDX, ECX);
if (ECX == 0) { /* some prgs(ld) use 0 */
EAX = 0;
return CARRY_OFF;
}
if ((npz->p_flags & PF_TERMIO) && EBX == 0) { /* termio */
if ((i = termio_read(DS, EDX, CX)) < 0) {
EAX = (long) -i;
return CARRY_ON;
} else {
EAX = (DWORD) i;
return CARRY_OFF;
}
}
count = ECX;
off_edx = EDX;
tr.ebx = EBX;
tr.edx = (DWORD) (WORD) iobuf;
tr.flags = FLAGS & ~1;
while (count > 0) { /* bytes left */
tr.ecx = (count <= IOBUF_SIZE) ? count : (DWORD) IOBUF_SIZE;
if (npz->p_flags & PF_DJGPP_FILE) {
bytes = tr.ecx;
if ((i = read(BX, iobuf, (WORD) tr.ecx)) == -1) {
EAX = (DWORD) doserror_to_errno(_doserrno);
return CARRY_ON;
}
tr.eax = (DWORD) i;
tr.ecx = bytes;
}
else {
tr.eax = 0x3f00;
if (realdos()) {
EAX = tr.eax;
FLAGS = tr.flags;
return CARRY_NON;
}
}
cpy16_32(DS, off_edx, iobuf, tr.eax);
count -= tr.eax;/* sub read bytes */
if ((WORD) tr.eax < (WORD) tr.ecx)
break;
off_edx += tr.ecx; /* seek user32_buf */
}
EAX = ECX - count;
return CARRY_OFF;
}
case 0x40: /* WRITE to file */
{
long count;
DWORD off_edx, bytes;
TEST_ILLEGAL(EDX, ECX);
count = ECX;
off_edx = EDX;
tr.ebx = EBX;
tr.edx = (DWORD) (WORD) iobuf;
tr.flags = FLAGS & ~1;
while (count > 0) {
tr.ecx = (count <= IOBUF_SIZE) ? count : (DWORD) IOBUF_SIZE;
cpy32_16(DS, off_edx, iobuf, tr.ecx);
if (npz->p_flags & PF_DJGPP_FILE) {
bytes = tr.ecx;
if ((i = write(BX, iobuf, (WORD) tr.ecx)) == -1) {
EAX = (DWORD) doserror_to_errno(_doserrno);
return CARRY_ON;
}
tr.eax = (DWORD) i;
tr.ecx = bytes;
}
else {
tr.eax = 0x4000;
if (realdos()) {
EAX = tr.eax;
FLAGS = tr.flags;
return CARRY_NON;
}
}
count -= tr.eax;
if ((WORD) tr.ecx != (WORD) tr.eax)
break;
off_edx += tr.ecx; /* seek user32_buf */
}
EAX = ECX - count;
return CARRY_OFF;
}
case 0x47: /* GET CURR DIRECTORY */
TEST_ILLEGAL(ESI, 64);
put_regs();
tr.esi = (DWORD) (WORD) iobuf;
if (!realdos())
cpy16_32(DS, ESI, iobuf, 64L);
get_regs();
return CARRY_NON;
case 0x4e: /* FINDFIRST */
/* DTA: iobuf byte 0-42 , wild _string: iobuf + 64 */
if (npz->p_flags & PF_EMX_FILE) {
/* set dta address to iobuf */
user_dta = ESI;
tr.edx = (DWORD) (WORD) iobuf;
tr.eax = 0x1a00;
realdos();
}
TEST_ILLEGAL(user_dta, 43);
TEST_ILLEGAL(EDX, 2);
strcpy32_16(DS, EDX, iobuf + 64);
tr.eax = EAX;
tr.ecx = ECX;
tr.edx = (DWORD) ((WORD) iobuf + 64);
tr.flags = FLAGS & ~1;
if (realdos())
EAX = tr.eax;
else
cpy16_32(DS, user_dta, iobuf, 43);
FLAGS = tr.flags;
return CARRY_NON;
case 0x4f: /* FINDNEXT */
/* DTA: iobuf byte 0-42 */
if (npz->p_flags & PF_EMX_FILE) {
user_dta = ESI;
tr.edx = (DWORD) (WORD) iobuf;
tr.eax = 0x1a00;
/* set dta address */
realdos();
}
TEST_ILLEGAL(user_dta, 43);
/* put user dta in iobuf */
cpy32_16(DS, user_dta, iobuf, 43);
tr.eax = EAX;
tr.flags = FLAGS & ~1;
if (realdos())
EAX = tr.eax;
else
cpy16_32(DS, user_dta, iobuf, 43);
FLAGS = tr.flags;
return CARRY_NON;
/***** functions complete changed *****/
/***** need to call DPMI-functions ****/
case 0x48: /* ALLOC MEM */
case 0x49: /* FREE MEM */
EAX = EMX_EIO;
return CARRY_ON;
case 0x4a: /* RESIZE MEM */
if (npz->p_flags & PF_EMX_FILE) {
EAX = EMX_EIO;
return CARRY_ON;
}
else {
if (EAX & 0xff)
EAX = getmem(EBX, npz);
else
EAX = npz->brk_value;
if (EAX == -1)
EAX = 0;
return CARRY_OFF; /* sbrk.s didn't check carry */
}
case 0x4c:
return do_exit4c(0);
default:
printf("Warning: Not implemented DOS function ah=%02X\n", rAH);
EAX = EMX_EIO;
return CARRY_ON;
} /* switch R_AH */
}