wininit.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 593 行 · 第 1/2 页

C
593
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Win386 Supervisor 32-bit DPMI mode startup code (16-bit).
*
****************************************************************************/


#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <io.h>
#include <fcntl.h>
#ifndef DLL32
#include <stdarg.h>
#else
typedef char __far *va_list[1];
#define va_start(ap,pn) ((ap)[0]=(char __far*)&pn+((sizeof(pn)+1)&~1),(void)0)
#define va_arg(ap,type) ((ap)[0]+=((sizeof(type)+1)&~1),\
                        (*(type __far *)((ap)[0]-((sizeof(type)+1)&~1))))
#define va_end(ap)      ((ap)[0]=0,(void)0)
#endif

#include <dos.h>
#include <share.h>
#include <sys/stat.h>
#include <windows.h>
#include "winext.h"
#include "watcom.h"
#include "tinyio.h"
#include "wdebug.h"
#include "dpmi.h"

// define FLAT to 1 to get flat address space for entire memory
#define FLAT    1

#define READSIZE        (0x8000)
#define FPU_AREA        0x40            // offset into stack for fpu

struct  fpu_area {
    unsigned short      control_word;
    unsigned short      unused1;
    unsigned short      status_word;
    unsigned short      unused2;
    unsigned short      tag_word;
    unsigned short      unused3;
    unsigned long       ip_offset;
    unsigned short      cs_selector;
    unsigned short      unused4;
    unsigned long       data_operand_offset;
    unsigned short      operand_selector;
    unsigned short      unused5;
    unsigned short      fpregs[5*8];
};


extern void BreakPoint();
#pragma aux BreakPoint = "int 3";

struct wstart_vars {
    WORD        thishandle;
    WORD        prevhandle;
    DWORD       cmdline;
    WORD        cmdshow;
    WORD        _no87;
    WORD        _A000H;
    WORD        _B000H;
    WORD        _B800H;
    WORD        _C000H;
    WORD        _D000H;
    WORD        _E000H;
    WORD        _F000H;
    addr_48     CodeSelectorBase;
    addr_48     DataSelectorBase;
    addr_48     _32BitCallBackAddr;
    addr_48     _DLLEntryAddr;
    addr_48     _WEPAddr;
    void        (FAR *_16BitCallBackAddr)();
    addr_48     gluertns[5];
};

extern DWORD far deadbeef;
extern WORD     InDebugger;
extern WORD     _A000H;
extern WORD     _B000H;
extern WORD     _B800H;
extern WORD     _C000H;
extern WORD     _D000H;
extern WORD     _E000H;
extern WORD     _F000H;
extern WORD     DataSelector;
extern WORD     StackSelector;
extern DWORD    DataHandle;
extern DWORD    CodeSelectorBase;
extern DWORD    DataSelectorBase;
extern WORD     MyDataSelector;
extern DWORD    BaseAddr;
extern DWORD    CodeLoadAddr;
extern addr_48  CodeEntry;
extern addr_48  _32BitCallBackAddr;
extern DWORD    _DLLEntryAddr;
extern DWORD    _WEPAddr;
extern DWORD    ReturnCode;
extern DWORD    SaveSP;
extern DWORD    StackSize;
extern DWORD    EDataAddr;              // end of loaded code+data
extern WORD     _no87;
extern WORD     DPL,Has87,HasWGod;

extern void     FAR __CallBack();
void GetDataSelectorInfo( void );
WORD InitFlatAddrSpace( DWORD baseaddr, DWORD len );

#define Align4K( x ) (((x)+0xfffL) & ~0xfffL )

static char     outOfSelectors[] = "Out of selectors";

/*
 * dwordToStr - convert a DWORD to a string (base 10)
 */
static char _FAR *dwordToStr( DWORD value )
{
    static char buff[16];
    int         i;

    i = 15;
    buff[i] = 0;
    do {
        --i;
        buff[i] = (value % 10) + '0';
        value /= 10;
    } while( value != 0 );
    return( &buff[i] );

} /* dwordToStr */

/*
 * Init32BitTask - load and initialize the 32-bit application
 */
int Init32BitTask( HINSTANCE thishandle, HINSTANCE prevhandle, LPSTR cmdline,
                    int cmdshow )
{
    WORD                i,amount,bytes_read,j;
    WORD                sel;
    int                 handle;
    tiny_ret_t          rc;
    DWORD               size,currsize,curroff,minmem,maxmem;
    DWORD               relsize,exelen;
    struct wstart_vars  far *dataptr;
    void                far *aliasptr;
    DWORD               far *relptr;
    struct fpu_area     far *fpuptr;
    rex_exe             exe;
    exe_data            exedat;
    char                file[128];
    DWORD               flags;
    version_info        vi;
    DWORD               file_header_size;
    BOOL                tried_global_compact;
    DWORD               save_maxmem;
    DWORD               adata[2];

    flags = GetWinFlags();
    /*
     * verify that we are running on a 32-bit DPMI
     */
    _fDPMIGetVersion( &vi );
    if( !(vi.flags & VERSION_80386) ) {
        MessageBox( NULL, "Not running on a 386 DPMI implementation",MsgTitle,
                        MB_OK | MB_ICONHAND | MB_TASKMODAL );
        return( FALSE );
    }

    /*
     * get exe to load
     */
    GetModuleFileName( thishandle, file, 128 );
    rc = _fTinyOpen( file, TIO_READ );
    if( TINY_ERROR( rc ) ) {
        return( Fini( 2, (char _FAR *)"Error opening file",
                    (char _FAR *)file) );
    }
    handle = TINY_INFO( rc );

    _TinySeek( handle, (DWORD) 0x38, TIO_SEEK_START );
    _fTinyRead( handle, &exelen, sizeof( DWORD ) );
    _TinySeek( handle, exelen, TIO_SEEK_START );

    /*
     * check if we are being run by the debugger.  When the debugger
     * sees the 'DEADBEEF' bytes at the start of the code segment
     * (see begin.asm), it swaps them to be BEEFDEAD.  The debugger
     * then tells us to go, and if we see that we have BEEFDEAD,
     * we execute a breakpoint just before we call our 32-bit code.
     * Then the debugger traces a single instruction and it looks to
     * the user like the start of his/her code is the start of
     * the application.
     */
    if( deadbeef == 0xBEEFDEAD ) {
        InDebugger = 0;
    } else {
        InDebugger = 1;
    }
    DPL = (CS() & 0x03) << 5;   /* our privilege level */

    /*
     * validate header signature
     */
    _fTinyRead( handle, &exe, sizeof( rex_exe ) );
//    BreakPoint();
    if( !(exe.sig[0] == 'M' && exe.sig[1] == 'Q') ) {
        return( Fini( 1,(char _FAR *)"Invalid EXE" ) );
    }
    file_header_size = (DWORD) exe.file_header * 16L;
    /*
     * exe.one is supposed to always contain a 1 for a .REX file.
     * However, to allow relocation tables bigger than 64K, the
     * we extended the linker to have the .one field contain the
     * number of full 64K chunks of relocations, minus 1.
     */
    file_header_size += (exe.one-1)*0x10000L*16L;

    /*
     * get exe data - data start and stack start
     */
    _TinySeek( handle, exelen + file_header_size + (long) exe.initial_eip, TIO_SEEK_START );
    _fTinyRead( handle, &exedat, sizeof( exe_data ) );
    /*
     * get file size
     */
    size = (long) exe.file_size2 * 512L;
    if( exe.file_size1 > 0 ) {
        size += (long) exe.file_size1 - 512L;
    }

    /*
     * get stack size
     */
    StackSize = Align4K( exe.initial_esp - ((exedat.stackstart+15) & ~15ul) );
    if( StackSize < 0x1000 ) {
        StackSize = 0x1000;
    }

    /*
     * get minimum/maximum amounts of heap, then add in exe size
     * to get total area
     */
//    BreakPoint();
    minmem = (DWORD) exe.min_data *(DWORD) 4096L;
    if( exe.max_data == (WORD)-1 ) {
        maxmem = 4096L;
    } else {
        maxmem = (DWORD) exe.max_data*4096L;
    }
    minmem = Align4K( minmem + size + 0x10000ul );
    maxmem = Align4K( maxmem + size + 0x10000ul );
    if( minmem > maxmem ) {
        maxmem = minmem;
    }

    /*
     * get memory to load file
     */
    tried_global_compact = FALSE;
    save_maxmem = maxmem;
    for(;;) {
        i = DPMIGet32( adata, maxmem );
        if( i != 5 )  break;
        if( maxmem == minmem ) {
            if( tried_global_compact ) {
                return( Fini( 3,
                  (char _FAR *)"Not enough memory for application\n(minimum ",

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?