trplddsx.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 622 行 · 第 1/2 页
C
622 行
}
static char *CopyEnv( void )
{
char __far *envarea;
uint_16 envsize;
#ifdef __OSI__
{
extern char *_EnvPtr;
envarea = _EnvPtr;
}
#else
envarea = MK_FP( *(addr_seg __far *)MK_FP( _psp, PSP_ENVSEG_OFF ), 0 );
#endif
envsize = EnvAreaSize( envarea );
PMData->envseg.a = DPMIAllocateDOSMemoryBlock( _NBPARAS( envsize ) );
if( PMData->envseg.s.pm == 0 ) {
return( TC_ERR_OUT_OF_DOS_MEMORY );
}
_fmemcpy( MK_PM( PMData->envseg.s.rm, 0 ), envarea, envsize );
return( NULL );
}
static char *SetTrapHandler( void )
{
char dummy;
long result;
descriptor desc;
version_info ver;
PMData->vecttable1[DOS4G_COMM_VECTOR].s.segment = RMData.s.rm;
PMData->vecttable1[DOS4G_COMM_VECTOR].s.offset = RM_OFF( Interrupt15 );
PMData->vecttable2[DOS4G_COMM_VECTOR].s.segment = RMData.s.rm;
PMData->vecttable2[DOS4G_COMM_VECTOR].s.offset = RM_OFF( Interrupt15 );
if( IntrState == IS_NONE ) {
DPMIGetVersion( &ver );
if( (ver.major_version >= 1 || ver.minor_version > 90) || DPMICheck == 2 ) {
RawPMtoRMSwitchAddr = DPMIRawPMtoRMAddr();
PMData->switchaddr.a= DPMIRawRMtoPMAddr();
}
if( RawPMtoRMSwitchAddr == 0
|| PMData->switchaddr.a == 0
|| DPMICheck == 1 ) {
IntrState = IS_RATIONAL;
} else {
PMData->saveaddr.a = DPMISavePMStateAddr();
PMData->savesize = DPMISaveStateSize();
if( PMData->savesize == 0 ) {
PMData->saveseg.a = 0;
} else {
PMData->saveseg.a = DPMIAllocateDOSMemoryBlock(
_NBPARAS(PMData->savesize*2) );
if( PMData->saveseg.s.pm == 0 ) {
return( TC_ERR_OUT_OF_DOS_MEMORY );
}
}
PMData->othersaved = FALSE;
result = DPMIAllocateLDTDescriptors( 1 );
if( result < 0 ) {
return( TC_ERR_CANT_LOAD_TRAP );
}
DPMIGetDescriptor( FP_SEG( PMData ), &desc );
PMData->pmode_cs = (unsigned_16)result;
desc.xtype.use32 = 0;
desc.type.execute = 1;
DPMISetDescriptor( PMData->pmode_cs, &desc );
PMData->pmode_eip = RM_OFF( BackFromRealMode );
PMData->pmode_ds = FP_SEG( &PMData );
PMData->pmode_es = PMData->pmode_ds;
PMData->pmode_ss = FP_SEG( &dummy );
IntrState = IS_DPMI;
}
}
if( IntrState == IS_RATIONAL ) {
MySetRMVector( TRAP_VECTOR, RMData.s.rm, RM_OFF( RMTrapHandler ) );
}
return( NULL );
}
static bool CallTrapInit( char *parm, char *errmsg, trap_version *trap_ver )
{
_Packed struct {
unsigned_16 remote;
unsigned_16 retcode;
trap_version version;
addr32_off errmsg_off;
} __far *callstruct;
callstruct = (void __far *)PMData->parmarea;
callstruct->remote = trap_ver->remote;
if( parm == NULL ) parm = "";
_fstrcpy( (char _far *)&callstruct[ 1 ], parm );
callstruct->errmsg_off = sizeof( *callstruct ) + strlen( parm ) + 1;
GoToRealMode( RMTrapInit );
*trap_ver = callstruct->version;
_fstrcpy( errmsg, (uint_8 __far *)callstruct + callstruct->errmsg_off );
return( *errmsg == NULLCHAR );
}
static char *ReadInTrap( tiny_handle_t fh )
{
dos_exe_header hdr;
memptr relocbuff[ NUM_BUFF_RELOCS ];
unsigned relocnb;
unsigned imagesize;
unsigned hdrsize;
rm_call_struct read;
unsigned offset;
if( TINY_ERROR( TinyRead( fh, &hdr, sizeof( hdr ) ) ) ) {
return( TC_ERR_CANT_LOAD_TRAP );
}
if( hdr.signature != DOS_SIGNATURE ) {
return( TC_ERR_BAD_TRAP_FILE );
}
hdrsize = hdr.hdr_size * 16;
imagesize = (hdr.file_size * 0x200) - (-hdr.mod_size & 0x1ff) - hdrsize;
TrapMem.a = DPMIAllocateDOSMemoryBlock( _NBPARAS( imagesize ) + hdr.min_16 );
if( TrapMem.s.pm == 0 ) {
return( TC_ERR_OUT_OF_DOS_MEMORY );
}
TinySeek( fh, hdrsize, TIO_SEEK_SET );
memset( &read, 0, sizeof( read ) );
offset = 0;
for( ;; ) {
read.ss = RMData.s.rm;
read.sp = offsetof( rm_data, stack ) + STACK_SIZE;
read.edx = offset;
read.ebx = fh;
read.ds = TrapMem.s.rm;
read.ecx = imagesize - offset;
read.eax = 0x3f00;
#if 1
relocnb = DPMISimulateRealModeInterrupt( 0x21, 0, 0, &read );
if( (read.flags & 1) || (unsigned_16)read.eax == 0 ) {
return( TC_ERR_CANT_LOAD_TRAP );
}
#else
read.eax = TinyRead( fh, (void *)((TrapMem.s.rm << 4) + offset), imagesize - offset );
if( (signed_32)read.eax < 0 ) {
return( TC_ERR_CANT_LOAD_TRAP );
}
#endif
offset += (unsigned_16)read.eax;
if( offset == imagesize ) break;
}
TinySeek( fh, hdr.reloc_offset, TIO_SEEK_SET );
for( relocnb = NUM_BUFF_RELOCS; hdr.num_relocs > 0;
--hdr.num_relocs, ++relocnb ) {
if( relocnb >= NUM_BUFF_RELOCS ) {
if( TINY_ERROR( TinyRead( fh, relocbuff, sizeof( memptr ) *
NUM_BUFF_RELOCS ) ) ) {
return( TC_ERR_CANT_LOAD_TRAP );
}
relocnb = 0;
}
*(addr_seg __far *)MK_PM( TrapMem.s.rm + relocbuff[ relocnb ].s.segment,
relocbuff[ relocnb ].s.offset ) += TrapMem.s.rm;
}
return( NULL );
}
static unsigned DoTrapAccess( unsigned num_in_mx, mx_entry *mx_in, unsigned num_out_mx,
mx_entry *mx_out )
{
uint_8 __far *msgptr;
unsigned j;
struct {
mx_entry16 in;
mx_entry16 out;
unsigned_16 retlen;
} __far *callstruct;
unsigned len;
unsigned copy;
callstruct = (void __far *)PMData->parmarea;
msgptr = (void __far *)&callstruct[1];
callstruct->in.ptr.s.segment = RMData.s.rm;
callstruct->in.ptr.s.offset = (unsigned)msgptr - (unsigned)PMData;
callstruct->in.len = 0;
for( j = 0; j < num_in_mx; ++j ) {
_fmemcpy( msgptr, mx_in[ j ].ptr, mx_in[ j ].len );
callstruct->in.len += mx_in[ j ].len;
msgptr += mx_in[ j ].len;
}
callstruct->out.len = 0;
if( mx_out != NULL ) {
callstruct->out.ptr.s.segment = RMData.s.rm;
callstruct->out.ptr.s.offset = (unsigned)msgptr - (unsigned)PMData;
for( j = 0; j < num_out_mx; ++j ) {
callstruct->out.len += mx_out[ j ].len;
}
} else {
callstruct->out.ptr.a = 0;
}
GoToRealMode( RMTrapAccess );
if( callstruct->retlen == (unsigned_16)REQUEST_FAILED ) {
return( REQUEST_FAILED );
}
if( mx_out != NULL ) {
/* msgptr is pointing at the start of the output buffer */
j = 0;
for( len = callstruct->retlen; len != 0; len -= copy ) {
copy = len;
if( copy > mx_out[ j ].len ) copy = mx_out[ j ].len;
_fmemcpy( mx_out[ j ].ptr, msgptr, copy );
++j;
msgptr += copy;
}
} else {
callstruct->retlen = 0;
}
if( *(access_req *)mx_in->ptr == REQ_CONNECT ) {
if( ( (connect_ret *)mx_out->ptr )->max_msg_size > MAX_MSG_SIZE ) {
( (connect_ret *)mx_out->ptr )->max_msg_size = MAX_MSG_SIZE;
}
}
return( callstruct->retlen );
}
char *LoadTrap( char *trapbuff, char *buff, trap_version *trap_ver )
{
char *err;
char *parm;
char *end;
handle dh;
trap_file_header __far *head;
char init_error[256];
if( trapbuff == NULL ) {
trapbuff = DEFAULT_TRP_NAME;
}
end = strchr( trapbuff, PARM_SEPARATOR );
if( end == NULL ) {
end = &trapbuff[ strlen( trapbuff ) ];
parm = end;
} else {
parm = end + 1;
}
dh = PathOpen( trapbuff, end - trapbuff, DEFAULT_TRP_EXT );
if( dh == NIL_HANDLE ) {
sprintf( buff, TC_ERR_CANT_LOAD_TRAP, trapbuff );
return( buff );
}
err = ReadInTrap( GetSystemHandle( dh ) );
FileClose( dh );
if( err != NULL ) {
sprintf( buff, TC_ERR_CANT_LOAD_TRAP, trapbuff );
KillTrap();
return( buff );
}
err = SetTrapHandler();
if( err != NULL ) {
KillTrap();
return( err );
}
err = CopyEnv();
if( err != NULL ) {
KillTrap();
return( err );
}
head = MK_PM( TrapMem.s.rm, 0 );
if( head->sig != TRAP_SIGNATURE ) {
KillTrap();
strcpy( buff, TC_ERR_WRONG_TRAP_VERSION );
return( buff );
}
PMData->initfunc.s.offset = head->init;
PMData->reqfunc.s.offset = head->req;
PMData->finifunc.s.offset = head->fini;
PMData->initfunc.s.segment = TrapMem.s.rm;
PMData->reqfunc.s.segment = TrapMem.s.rm;
PMData->finifunc.s.segment = TrapMem.s.rm;
if( !CallTrapInit( parm, init_error, trap_ver ) ) {
KillTrap();
strcpy( buff, init_error );
return( buff );
}
if( !TrapVersionOK( *trap_ver ) ) {
KillTrap();
strcpy( buff, TC_ERR_WRONG_TRAP_VERSION );
return( buff );
}
TrapVer = *trap_ver;
ReqFunc = DoTrapAccess;
return( NULL );
}
void KillTrap( void )
{
if( IntrState != IS_NONE ) {
GoToRealMode( RMTrapFini );
IntrState = IS_NONE;
}
if( TrapMem.s.pm != 0 ) {
DPMIFreeDOSMemoryBlock( TrapMem.s.pm );
}
if( PMData->envseg.s.pm != 0 ) {
DPMIFreeDOSMemoryBlock( PMData->envseg.s.pm );
}
if( PMData->saveseg.s.pm != 0 ) {
DPMIFreeDOSMemoryBlock( PMData->saveseg.s.pm );
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?