259 lines
7.5 KiB
C
259 lines
7.5 KiB
C
#ifdef CRTDLL
|
|
/***
|
|
*crtlib.c - CRT DLL initialization and termination routine (Win32, Dosx32)
|
|
*
|
|
* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
|
|
*
|
|
*Purpose:
|
|
* This module contains initialization entry point for the CRT DLL in
|
|
* Win32 and Dosx32 environments. It also contains some of the supporting
|
|
* initialization and termination code.
|
|
*
|
|
*Revision History:
|
|
* 08-12-91 GJF Module created. Sort of.
|
|
* 01-17-92 GJF Return exception code value for RTEs corresponding
|
|
* to exceptions.
|
|
* 01-29-92 GJF Support for wildcard expansion in filenames on the
|
|
* command line.
|
|
* 02-14-92 GJF Moved file inheritance stuff to ioinit.c. Call to
|
|
* inherit() is replace by call to _ioinit().
|
|
* 08-26-92 SKS Add _osver, _winver, _winmajor, _winminor
|
|
* 09-04-92 GJF Replaced _CALLTYPE3 with WINAPI.
|
|
* 09-30-92 SRW Call _heap_init before _mtinit
|
|
* 10-19-92 SKS Add "dowildcard" parameter to GetMainArgs()
|
|
* Prepend a second "_" to name since it is internal-only
|
|
* 04-16-93 SKS Change call to _mtdeletelocks to _mtterm. _mtterm
|
|
* calls _mtdeletelocks and also frees up the TLS index.
|
|
* 04-27-93 GJF Removed support for _RT_STACK, _RT_INTDIV,
|
|
* _RT_INVALDISP and _RT_NONCONT.
|
|
* 05-11-93 SKS Change _CRTDLL_INIT to fail loading on failure to
|
|
* initialize/clean up, rather than calling _amsg_exit().
|
|
* 06-03-93 GJF Added __proc_attached flag.
|
|
* 06-07-93 GJF Incorporated SteveWo's code to call LoadLibrary, from
|
|
* crtdll.c.
|
|
* 12-14-93 SKS Add _freeptd(), which frees up the per-thread data
|
|
* maintained by the C run-time library.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include <cruntime.h>
|
|
#include <oscalls.h>
|
|
#include <dos.h>
|
|
#include <internal.h>
|
|
#include <os2dll.h>
|
|
#include <process.h>
|
|
#include <rterr.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
/*
|
|
* flag set iff _CRTDLL_INIT was called with DLL_PROCESS_ATTACH
|
|
*/
|
|
static int __proc_attached = 0;
|
|
|
|
/*
|
|
* command line, environment, and a few other globals
|
|
*/
|
|
char *_acmdln; /* points to command line */
|
|
char *_aenvptr; /* points to environment block */
|
|
|
|
void (_CALLTYPE1 * _aexit_rtn)(int) = _exit; /* RT message return procedure */
|
|
|
|
static void _CALLTYPE4 inherit(void); /* local function */
|
|
|
|
|
|
/***
|
|
*void __GetMainArgs(pargc, pargv, penvp, dowildcard) - get values for args to main()
|
|
*
|
|
*Purpose:
|
|
* This function invokes the command line parsing and copies the args
|
|
* to main back through the passsed pointers. The reason for doing
|
|
* this here, rather than having _CRTDLL_INIT do the work and exporting
|
|
* the __argc and __argv, is to support the linked-in option to have
|
|
* wildcard characters in filename arguments expanded.
|
|
*
|
|
*Entry:
|
|
* int *pargc - pointer to argc
|
|
* char ***pargv - pointer to argv
|
|
* char ***penvp - pointer to envp
|
|
* int dowildcard - flag (true means expand wildcards in cmd line)
|
|
*
|
|
*Exit:
|
|
* No return value. Values for the arguments to main() are copied through
|
|
* the passed pointers.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
|
|
void _CALLTYPE1 __GetMainArgs (
|
|
int *pargc,
|
|
char ***pargv,
|
|
char ***penvp,
|
|
int dowildcard)
|
|
{
|
|
if ( dowildcard )
|
|
__setargv(); /* do wildcard expansion after parsing args */
|
|
else
|
|
_setargv(); /* NO wildcard expansion; just parse args */
|
|
|
|
*pargc = __argc;
|
|
*pargv = __argv;
|
|
*penvp = _environ;
|
|
}
|
|
|
|
|
|
/***
|
|
*BOOL _CRTDLL_INIT(hDllHandle, dwReason, lpreserved) - C DLL initialization.
|
|
*
|
|
*Purpose:
|
|
* This routine does the C runtime initialization.
|
|
*
|
|
*Entry:
|
|
*
|
|
*Exit:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
BOOL WINAPI _CRTDLL_INIT(
|
|
HANDLE hDllHandle,
|
|
DWORD dwReason,
|
|
LPVOID lpreserved
|
|
)
|
|
{
|
|
char szDllName[ MAX_PATH ];
|
|
|
|
if ( dwReason == DLL_PROCESS_ATTACH ) {
|
|
|
|
/*
|
|
* Increment flag indicating process attach notification
|
|
* has been received.
|
|
*/
|
|
__proc_attached++;
|
|
|
|
/*
|
|
* Pin ourselves in memory since we dont clean up if we
|
|
* unload.
|
|
*/
|
|
if ( !GetModuleFileName( hDllHandle,
|
|
szDllName,
|
|
sizeof(szDllName))
|
|
)
|
|
{
|
|
strcpy(szDllName, "CRTDLL");
|
|
}
|
|
LoadLibrary(szDllName);
|
|
}
|
|
else if ( dwReason == DLL_PROCESS_DETACH ) {
|
|
/*
|
|
* if this is a process detach notification, make sure there
|
|
* has been a prior process attach notification.
|
|
*/
|
|
if ( __proc_attached > 0 )
|
|
__proc_attached--;
|
|
else
|
|
/* no prior process attach, just return */
|
|
return FALSE;
|
|
}
|
|
else if ( dwReason == DLL_THREAD_DETACH )
|
|
{
|
|
_freeptd(NULL); /* free up per-thread CRT data */
|
|
}
|
|
|
|
|
|
/*
|
|
* Only do initialization when a client process attaches to
|
|
* the DLL.
|
|
*/
|
|
if ( dwReason != DLL_PROCESS_ATTACH ) {
|
|
/*
|
|
* if a client process is detaching, make sure minimal
|
|
* runtime termination is performed and clean up our
|
|
* 'locks' (i.e., delete critical sections).
|
|
*/
|
|
if ( dwReason == DLL_PROCESS_DETACH ) {
|
|
|
|
if ( _C_Termination_Done == FALSE )
|
|
_c_exit();
|
|
#ifdef MTHREAD
|
|
_mtterm(); /* free TLS index, call _mtdeletelocks() */
|
|
#endif
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
_acmdln = (char *)GetCommandLine();
|
|
_aenvptr = (char *)GetEnvironmentStrings();
|
|
|
|
/*
|
|
* Get the full Win32 version
|
|
*/
|
|
_osversion = /* OBSOLETE */
|
|
_osver = GetVersion();
|
|
|
|
_winminor = (_osver >> 8) & 0x00FF ;
|
|
_winmajor = _osver & 0x00FF ;
|
|
_winver = (_winmajor << 8) + _winminor;
|
|
_osver = (_osver >> 16) & 0x00FFFF ;
|
|
|
|
/* --------- The following block is OBSOLETE --------- */
|
|
|
|
/*
|
|
* unpack base version info
|
|
*/
|
|
_baseversion = (_osversion & 0xFFFF0000) >> 16;
|
|
_baseminor = _baseversion & 0x00FF;
|
|
_basemajor = (_baseversion & 0xFF00) >> 8;
|
|
|
|
/*
|
|
* unpack top-level version info (Windows version)
|
|
*/
|
|
_osversion &= 0x0000FFFF;
|
|
_osmajor = _osversion & 0x00FF;
|
|
_osminor = (_osversion & 0xFF00) >> 8;
|
|
|
|
/* --------- The preceding block is OBSOLETE --------- */
|
|
|
|
_heap_init(); /* initialize heap */
|
|
#ifdef MTHREAD
|
|
if(!_mtinit()) /* initialize multi-thread */
|
|
return FALSE; /* fail DLL load on failure */
|
|
#endif
|
|
_ioinit(); /* inherit file info */
|
|
_setenvp(); /* get environ info */
|
|
|
|
_cinit(); /* do C data initialize */
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/***
|
|
*_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 _CALLTYPE1 _amsg_exit (
|
|
int rterrnum
|
|
)
|
|
{
|
|
_FF_MSGBANNER(); /* write run-time error banner */
|
|
_NMSG_WRITE(rterrnum); /* write message */
|
|
|
|
_aexit_rtn(255); /* normally _exit(255) */
|
|
}
|
|
#endif /* CRTDLL */
|