mirror of
https://github.com/ProjectDreamland/area51.git
synced 2024-11-01 03:01:49 +01:00
476 lines
11 KiB
C
476 lines
11 KiB
C
/***
|
|
*crt0.c - C runtime initialization routine
|
|
*
|
|
* Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
|
|
*
|
|
*Purpose:
|
|
* This the actual startup routine for apps. It calls the user's main
|
|
* routine [w]main() or [w]WinMain after performing C Run-Time Library
|
|
* initialization.
|
|
*
|
|
* (With ifdef's, this source file also provides the source code for
|
|
* wcrt0.c, the startup routine for console apps with wide characters,
|
|
* wincrt0.c, the startup routine for Windows apps, and wwincrt0.c,
|
|
* the startup routine for Windows apps with wide characters.)
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#ifdef _WIN32
|
|
|
|
#ifndef CRTDLL
|
|
|
|
#include <cruntime.h>
|
|
#include <dos.h>
|
|
#include <internal.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <rterr.h>
|
|
#include <windows.h>
|
|
#include <awint.h>
|
|
#include <tchar.h>
|
|
#include <dbgint.h>
|
|
|
|
void x_Init ( void );
|
|
void x_Kill ( void );
|
|
|
|
/*
|
|
* wWinMain is not yet defined in winbase.h. When it is, this should be
|
|
* removed.
|
|
*/
|
|
|
|
int
|
|
WINAPI
|
|
wWinMain(
|
|
HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPWSTR lpCmdLine,
|
|
int nShowCmd
|
|
);
|
|
|
|
#ifdef WPRFLAG
|
|
_TUCHAR * __cdecl _wwincmdln(void);
|
|
#else /* WPRFLAG */
|
|
_TUCHAR * __cdecl _wincmdln(void);
|
|
#endif /* WPRFLAG */
|
|
|
|
/*
|
|
* command line, environment, and a few other globals
|
|
*/
|
|
|
|
#ifdef WPRFLAG
|
|
wchar_t *_wcmdln; /* points to wide command line */
|
|
#else /* WPRFLAG */
|
|
char *_acmdln; /* points to command line */
|
|
#endif /* WPRFLAG */
|
|
|
|
char *_aenvptr = NULL; /* points to environment block */
|
|
wchar_t *_wenvptr = NULL; /* points to wide environment block */
|
|
|
|
|
|
void (__cdecl * _aexit_rtn)(int) = _exit; /* RT message return procedure */
|
|
|
|
static void __cdecl fast_error_exit(int); /* Error exit via ExitProcess */
|
|
|
|
/*
|
|
* _error_mode and _apptype, together, determine how error messages are
|
|
* written out.
|
|
*/
|
|
int __error_mode = _OUT_TO_DEFAULT;
|
|
#ifdef _WINMAIN_
|
|
int __app_type = _GUI_APP;
|
|
#else /* _WINMAIN_ */
|
|
int __app_type = _CONSOLE_APP;
|
|
#endif /* _WINMAIN_ */
|
|
|
|
|
|
/***
|
|
*BaseProcessStartup(PVOID Peb)
|
|
*
|
|
*Purpose:
|
|
* This routine does the C runtime initialization, calls main(), and
|
|
* then exits. It never returns.
|
|
*
|
|
*Entry:
|
|
* PVOID Peb - pointer to Win32 Process Environment Block (not used)
|
|
*
|
|
*Exit:
|
|
* This function never returns.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#ifdef _WINMAIN_
|
|
|
|
#ifdef WPRFLAG
|
|
void wWinMainCRTStartup(
|
|
#else /* WPRFLAG */
|
|
void WinMainCRTStartup(
|
|
#endif /* WPRFLAG */
|
|
|
|
#else /* _WINMAIN_ */
|
|
|
|
#ifdef WPRFLAG
|
|
void wmainCRTStartup(
|
|
#else /* WPRFLAG */
|
|
void mainCRTStartup(
|
|
#endif /* WPRFLAG */
|
|
|
|
#endif /* _WINMAIN_ */
|
|
void
|
|
)
|
|
|
|
{
|
|
int mainret;
|
|
|
|
#ifdef _WINMAIN_
|
|
_TUCHAR *lpszCommandLine;
|
|
STARTUPINFO StartupInfo;
|
|
#endif /* _WINMAIN_ */
|
|
|
|
/*
|
|
* Get the full Win32 version
|
|
*/
|
|
_osver = GetVersion();
|
|
|
|
_winminor = (_osver >> 8) & 0x00FF ;
|
|
_winmajor = _osver & 0x00FF ;
|
|
_winver = (_winmajor << 8) + _winminor;
|
|
_osver = (_osver >> 16) & 0x00FFFF ;
|
|
|
|
#ifdef _MT
|
|
if ( !_heap_init(1) ) /* initialize heap */
|
|
#else /* _MT */
|
|
if ( !_heap_init(0) ) /* initialize heap */
|
|
#endif /* _MT */
|
|
fast_error_exit(_RT_HEAPINIT); /* write message and die */
|
|
|
|
#ifdef _MT
|
|
if( !_mtinit() ) /* initialize multi-thread */
|
|
fast_error_exit(_RT_THREAD); /* write message and die */
|
|
#endif /* _MT */
|
|
|
|
/*
|
|
* Guard the remainder of the initialization code and the call
|
|
* to user's main, or WinMain, function in a __try/__except
|
|
* statement.
|
|
*/
|
|
|
|
__try {
|
|
|
|
_ioinit(); /* initialize lowio */
|
|
|
|
#ifdef WPRFLAG
|
|
/* get wide cmd line info */
|
|
_wcmdln = (wchar_t *)__crtGetCommandLineW();
|
|
|
|
/* get wide environ info */
|
|
_wenvptr = (wchar_t *)__crtGetEnvironmentStringsW();
|
|
|
|
_wsetargv();
|
|
_wsetenvp();
|
|
#else /* WPRFLAG */
|
|
/* get cmd line info */
|
|
_acmdln = (char *)GetCommandLineA();
|
|
|
|
/* get environ info */
|
|
_aenvptr = (char *)__crtGetEnvironmentStringsA();
|
|
|
|
_setargv();
|
|
_setenvp();
|
|
#endif /* WPRFLAG */
|
|
|
|
x_Init();
|
|
|
|
_cinit(); /* do C data initialize */
|
|
|
|
#ifdef _WINMAIN_
|
|
|
|
StartupInfo.dwFlags = 0;
|
|
GetStartupInfo( &StartupInfo );
|
|
|
|
#ifdef WPRFLAG
|
|
lpszCommandLine = _wwincmdln();
|
|
mainret = wWinMain(
|
|
#else /* WPRFLAG */
|
|
lpszCommandLine = _wincmdln();
|
|
mainret = WinMain(
|
|
#endif /* WPRFLAG */
|
|
GetModuleHandleA(NULL),
|
|
NULL,
|
|
lpszCommandLine,
|
|
StartupInfo.dwFlags & STARTF_USESHOWWINDOW
|
|
? StartupInfo.wShowWindow
|
|
: SW_SHOWDEFAULT
|
|
);
|
|
#else /* _WINMAIN_ */
|
|
|
|
#ifdef WPRFLAG
|
|
__winitenv = _wenviron;
|
|
mainret = wmain(__argc, __wargv, _wenviron);
|
|
#else /* WPRFLAG */
|
|
__initenv = _environ;
|
|
mainret = main(__argc, __argv, _environ);
|
|
#endif /* WPRFLAG */
|
|
|
|
#endif /* _WINMAIN_ */
|
|
exit(mainret);
|
|
}
|
|
__except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
|
|
{
|
|
/*
|
|
* Should never reach here
|
|
*/
|
|
_exit( GetExceptionCode() );
|
|
|
|
} /* end of try - except */
|
|
|
|
x_Kill();
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
*_amsg_exit(rterrnum) - Fast exit fatal errors
|
|
*
|
|
*Purpose:
|
|
* Exit the program with error code of 255 and appropriate error
|
|
* message.
|
|
*
|
|
*Entry:
|
|
* int rterrnum - error message number (amsg_exit only).
|
|
*
|
|
*Exit:
|
|
* Calls exit() (for integer divide-by-0) or _exit() indirectly
|
|
* through _aexit_rtn [amsg_exit].
|
|
* For multi-thread: calls _exit() function
|
|
*
|
|
*Exceptions:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
void __cdecl _amsg_exit (
|
|
int rterrnum
|
|
)
|
|
{
|
|
#ifdef _WINMAIN_
|
|
if ( __error_mode == _OUT_TO_STDERR )
|
|
#else /* _WINMAIN_ */
|
|
if ( __error_mode != _OUT_TO_MSGBOX )
|
|
#endif /* _WINMAIN_ */
|
|
_FF_MSGBANNER(); /* write run-time error banner */
|
|
|
|
_NMSG_WRITE(rterrnum); /* write message */
|
|
_aexit_rtn(255); /* normally _exit(255) */
|
|
}
|
|
|
|
/***
|
|
*fast_error_exit(rterrnum) - Faster exit fatal errors
|
|
*
|
|
*Purpose:
|
|
* Exit the process with error code of 255 and appropriate error
|
|
* message.
|
|
*
|
|
*Entry:
|
|
* int rterrnum - error message number (amsg_exit only).
|
|
*
|
|
*Exit:
|
|
* Calls ExitProcess.
|
|
*
|
|
*Exceptions:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
static void __cdecl fast_error_exit (
|
|
int rterrnum
|
|
)
|
|
{
|
|
#ifdef _WINMAIN_
|
|
if ( __error_mode == _OUT_TO_STDERR )
|
|
#else /* _WINMAIN_ */
|
|
if ( __error_mode != _OUT_TO_MSGBOX )
|
|
#endif /* _WINMAIN_ */
|
|
_FF_MSGBANNER(); /* write run-time error banner */
|
|
|
|
_NMSG_WRITE(rterrnum); /* write message */
|
|
ExitProcess(255); /* normally _exit(255) */
|
|
}
|
|
|
|
#ifndef WPRFLAG
|
|
|
|
|
|
#endif /* WPRFLAG */
|
|
|
|
#endif /* CRTDLL */
|
|
|
|
#else /* _WIN32 */
|
|
|
|
#include <cruntime.h>
|
|
#include <internal.h>
|
|
#include <stdlib.h>
|
|
#include <msdos.h>
|
|
#include <string.h>
|
|
#include <setjmp.h>
|
|
#include <dbgint.h>
|
|
#include <macos\types.h>
|
|
#include <macos\segload.h>
|
|
#include <macos\gestalte.h>
|
|
#include <macos\osutils.h>
|
|
#include <macos\traps.h>
|
|
#include <mpw.h>
|
|
|
|
static void __cdecl Inherit(void); /* local function */
|
|
|
|
int __cdecl main(int, char **, char **); /*generated by compiler*/
|
|
|
|
unsigned long _GetShellStack(void);
|
|
|
|
static char * __cdecl _p2cstr_internal ( unsigned char * str );
|
|
|
|
extern MPWBLOCK * _pMPWBlock;
|
|
extern int __argc;
|
|
extern char **__argv;
|
|
|
|
/***
|
|
*__crt0()
|
|
*
|
|
*Purpose:
|
|
* This routine does the C runtime initialization, calls main(), and
|
|
* then exits. It never returns.
|
|
*
|
|
*Entry:
|
|
*
|
|
*Exit:
|
|
* This function never returns.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
void __cdecl __crt0 (
|
|
)
|
|
{
|
|
int mainret;
|
|
char szPgmName[32];
|
|
char *pArg;
|
|
char *argv[2];
|
|
|
|
#ifndef _M_MPPC
|
|
void *pv;
|
|
|
|
/* This is the magic stuff that MPW tools do to get info from MPW*/
|
|
|
|
pv = (void *)*(int *)0x316;
|
|
if (pv != NULL && !((int)pv & 1) && *(int *)pv == 'MPGM') {
|
|
pv = (void *)*++(int *)pv;
|
|
if (pv != NULL && *(short *)pv == 'SH') {
|
|
_pMPWBlock = (MPWBLOCK *)pv;
|
|
}
|
|
}
|
|
|
|
#endif /* _M_MPPC */
|
|
|
|
_environ = NULL;
|
|
if (_pMPWBlock == NULL) {
|
|
__argc = 1;
|
|
memcpy(szPgmName, (char *)0x910, sizeof(szPgmName));
|
|
pArg = _p2cstr_internal(szPgmName);
|
|
argv[0] = pArg;
|
|
argv[1] = NULL;
|
|
__argv = argv;
|
|
|
|
#ifndef _M_MPPC
|
|
_shellStack = 0; /* force ExitToShell */
|
|
#endif /* _M_MPPC */
|
|
}
|
|
#ifndef _M_MPPC
|
|
else {
|
|
_shellStack = _GetShellStack(); //return current a6, or first a6
|
|
_shellStack += 4; //a6 + 4 is the stack pointer we want
|
|
__argc = _pMPWBlock->argc;
|
|
__argv = _pMPWBlock->argv;
|
|
|
|
Inherit(); /* Inherit file handles - env is set up by _envinit if needed */
|
|
}
|
|
#endif /* _M_MPPC */
|
|
|
|
/*
|
|
* call run time initializer
|
|
*/
|
|
__cinit();
|
|
|
|
mainret = main(__argc, __argv, _environ);
|
|
exit(mainret);
|
|
}
|
|
|
|
|
|
#ifndef _M_MPPC
|
|
/***
|
|
*Inherit() - obtain and process info on inherited file handles.
|
|
*
|
|
*Purpose:
|
|
*
|
|
* Locates and interprets MPW std files. For files we just save the
|
|
* file handles. For the console we save the device table address so
|
|
* we can do console I/O. In the latter case, FDEV is set in the _osfile
|
|
* array.
|
|
*
|
|
*Entry:
|
|
* Address of MPW param table
|
|
*
|
|
*Exit:
|
|
* No return value.
|
|
*
|
|
*Exceptions:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
static void __cdecl Inherit (
|
|
void
|
|
)
|
|
{
|
|
MPWFILE *pFile;
|
|
int i;
|
|
pFile = _pMPWBlock->pFile;
|
|
if (pFile == NULL) {
|
|
return;
|
|
}
|
|
for (i = 0; i < 3; i++) {
|
|
switch ((pFile->pDevice)->name) {
|
|
case 'ECON':
|
|
_osfile[i] |= FDEV | FOPEN;
|
|
_osfhnd[i] = (int)pFile;
|
|
break;
|
|
|
|
case 'FSYS':
|
|
_osfile[i] |= FOPEN;
|
|
_osfhnd[i] = (*(pFile->ppFInfo))->ioRefNum;
|
|
break;
|
|
}
|
|
pFile++;
|
|
}
|
|
}
|
|
|
|
#endif /* _M_MPPC */
|
|
|
|
|
|
|
|
static char * __cdecl _p2cstr_internal (
|
|
unsigned char * str
|
|
)
|
|
{
|
|
unsigned char *pchSrc;
|
|
unsigned char *pchDst;
|
|
int cch;
|
|
|
|
if ( str && *str ) {
|
|
pchDst = str;
|
|
pchSrc = str + 1;
|
|
|
|
for ( cch=*pchDst; cch; --cch ) {
|
|
*pchDst++ = *pchSrc++;
|
|
}
|
|
|
|
*pchDst = '\0';
|
|
}
|
|
|
|
return( str );
|
|
}
|
|
|
|
#endif /* _WIN32 */
|