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