#ifndef _POSIX_ /* not built for POSIX */ #ifndef CRTDLL /* not built for CRTDLL */ /*** *dllcrt0.c - C runtime initialization routine for a DLL with linked-in C R-T * * Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved. * *Purpose: * This the startup routine for a DLL which is linked with its own * C run-time code. It is similar to the routine _mainCRTStartup() * in the file CRT0.C, except that there is no main() in a DLL. * *Revision History: * 05-04-92 SKS Based on CRT0.C (start-up code for EXE's) * 08-26-92 SKS Add _osver, _winver, _winmajor, _winminor * 09-16-92 SKS This module used to be enabled only in LIBCMT.LIB, * but it is now enabled for LIBC.LIB as well! * 09-29-92 SKS _CRT_INIT needs to be WINAPI, not cdecl * 10-16-92 SKS Call _heap_init before _mtinit (fix copied from CRT0.C) * 10-24-92 SKS Call to _mtdeletelocks() must be under #ifdef MTHREAD! * 04-16-93 SKS Call _mtterm instead of _mtdeletelocks on * PROCESS_DETACH to do all multi-thread cleanup * It will call _mtdeletelocks and free up the TLS index. * 04-27-93 GJF Removed support for _RT_STACK, _RT_INTDIV, * _RT_INVALDISP and _RT_NONCONT. * 05-11-93 SKS Add _DllMainCRTStartup to co-exist with _CRT_INIT * _mtinit now returns 0 or 1, no longer calls _amsg_exit * Delete obsolete variable _atopsp * 06-03-93 GJF Added __proc_attached flag. * 06-08-93 SKS Clean up failure handling in _CRT_INIT * 12-13-93 SKS Free up per-thread CRT data on DLL_THREAD_DETACH * using a call to _freeptd() in _CRT_INIT() * *******************************************************************************/ #include #include #include #include #include #include #include #define _DECL_DLLMAIN /* enable prototypes for DllMain and _CRT_INIT */ #include /* * 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 */ /* * User routine DllMain is called on all notifications */ extern BOOL WINAPI DllMain( HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved ) ; /*** *BOOL WINAPI _CRT_INIT(hDllHandle, dwReason, lpreserved) - C Run-Time * initialization for a DLL linked with a C run-time library. * *Purpose: * This routine does the C run-time initialization. * For the multi-threaded run-time library, it also cleans up the * multi-threading locks on DLL termination. * *Entry: * *Exit: * *NOTES: * This routine should either be the entry-point for the DLL * or else be called by the entry-point routine for the DLL. * *******************************************************************************/ BOOL WINAPI _CRT_INIT( HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved ) { switch (dwReason) { case DLL_PROCESS_DETACH: /* * make sure there has been prior process attach * notification! */ if ( __proc_attached > 0 ) { __proc_attached--; if ( _C_Termination_Done == FALSE ) { /* do exit() time clean-up */ _cexit(); } #ifdef MTHREAD /* delete MT locks, free TLS index, etc. */ _mtterm(); #endif if (_aenvptr) { FreeEnvironmentStrings(_aenvptr); _aenvptr=NULL; } return TRUE; } else { /* no prior process attach, just return */ return FALSE; } #ifdef MTHREAD case DLL_THREAD_DETACH: _freeptd(NULL); /* free up per-thread CRT data */ case DLL_THREAD_ATTACH: return TRUE; #endif case DLL_PROCESS_ATTACH: /* * increment flag to indicate process attach notification has been * received */ __proc_attached++; _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 */ FreeEnvironmentStrings(_aenvptr); return FALSE; /* fail to load DLL */ } #endif _ioinit(); /* initialize lowio */ _setargv(); /* get cmd line info */ _setenvp(); /* get environ info */ _cinit(); /* do C data initialize */ return TRUE; /* initialization succeeded */ } } /*** *BOOL WINAPI _DllMainCRTStartup(hDllHandle, dwReason, lpreserved) - * C Run-Time initialization for a DLL linked with a C run-time library. * *Purpose: * This routine does the C run-time initialization or termination * and then calls the user code notification handler "DllMain". * For the multi-threaded run-time library, it also cleans up the * multi-threading locks on DLL termination. * *Entry: * *Exit: * *NOTES: * This routine should be the entry point for the DLL if * the user is not supplying one and calling _CRT_INIT. * *******************************************************************************/ BOOL WINAPI _DllMainCRTStartup( HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved ) { BOOL retcode = TRUE; /* * If this is a process attach notification, increment the process * attached flag. If this is a process detach notification, check * that there has been a prior process attach notification. */ if ( dwReason == DLL_PROCESS_ATTACH ) __proc_attached++; else if ( dwReason == DLL_PROCESS_DETACH ) { if ( __proc_attached > 0 ) __proc_attached--; else /* * no prior process attach notification. just return * without doing anything. */ return FALSE; } if ( dwReason == DLL_PROCESS_ATTACH || dwReason == DLL_THREAD_ATTACH ) retcode = _CRT_INIT(hDllHandle, dwReason, lpreserved); if ( retcode ) retcode = DllMain(hDllHandle, dwReason, lpreserved); /* * If _CRT_INIT successfully handles a Process Attach notification * but the user's DllMain routine returns failure, we need to do * clean-up of the C run-time similar to what _CRT_INIT does on a * Process Detach Notification. */ if ( retcode == FALSE && dwReason == DLL_PROCESS_ATTACH ) { /* Failure to attach DLL - must clean up C run-time */ #ifdef MTHREAD _mtterm(); #endif if (_aenvptr) { FreeEnvironmentStrings(_aenvptr); _aenvptr=NULL; } } if ( dwReason == DLL_PROCESS_DETACH || dwReason == DLL_THREAD_DETACH ) { if ( _CRT_INIT(hDllHandle, dwReason, lpreserved) == FALSE ) retcode = FALSE ; } return retcode ; } /*** *_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 */ #endif /* _POSIX_ */