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 + -
显示快捷键?