/*** *dllcrt0.c - C runtime initialization routine for a DLL with linked-in C R-T * * Copyright (c) 1989-1997, 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. * *******************************************************************************/ #ifdef _WIN32 #ifndef CRTDLL #include #include #include #include #include #include #include #include #define _DECL_DLLMAIN /* enable prototypes for DllMain and _CRT_INIT */ #include #include #include #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 = NULL; /* points to environment block */ wchar_t *_wenvptr = NULL; /* points to wide environment block */ void (__cdecl * _aexit_rtn)(int) = _exit; /* RT message return procedure */ /* * _error_mode and _apptype, together, determine how error messages are * written out. */ int __error_mode = _OUT_TO_DEFAULT; int __app_type = _UNKNOWN_APP; /* * User routine DllMain is called on all notifications */ extern BOOL WINAPI DllMain( HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved ) ; /* _pRawDllMain MUST be a common variable, not extern nor initialized! */ BOOL (WINAPI *_pRawDllMain)(HANDLE, DWORD, LPVOID); /*** *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 or termination. * For the multi-threaded run-time library, it also cleans up the * multi-threading locks on DLL termination. * *Entry: * *Exit: * *NOTES: * This routine must be the entry point for the DLL. * *******************************************************************************/ BOOL WINAPI _CRT_INIT( HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved ) { /* * Start-up code only gets executed when the process is initialized */ if ( dwReason == DLL_PROCESS_ATTACH ) { /* * Get the full Win32 version */ _osver = GetVersion(); #ifdef _MT if ( !_heap_init(1) ) /* initialize heap */ #else /* _MT */ if ( !_heap_init(0) ) /* initialize heap */ #endif /* _MT */ return FALSE; /* fail to load DLL */ _winminor = (_osver >> 8) & 0x00FF ; _winmajor = _osver & 0x00FF ; _winver = (_winmajor << 8) + _winminor; _osver = (_osver >> 16) & 0x00FFFF ; #ifdef _MT if(!_mtinit()) /* initialize multi-thread */ { _heap_term(); /* heap is now invalid! */ return FALSE; /* fail to load DLL */ } #endif /* _MT */ _acmdln = (char *)GetCommandLineA(); _aenvptr = (char *)__crtGetEnvironmentStringsA(); _ioinit(); /* initialize lowio */ _setargv(); /* get cmd line info */ _setenvp(); /* get environ info */ _cinit(); /* do C data initialize */ /* * increment flag to indicate process attach notification * has been received */ __proc_attached++; } else if ( dwReason == DLL_PROCESS_DETACH ) { if ( __proc_attached > 0 ) { __proc_attached--; /* * Any basic clean-up code that goes here must be duplicated * below in _DllMainCRTStartup for the case where the user's * DllMain() routine fails on a Process Attach notification. * This does not include calling user C++ destructors, etc. */ if ( _C_Termination_Done == FALSE ) _cexit(); #ifdef _DEBUG /* Dump all memory leaks */ if (_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & _CRTDBG_LEAK_CHECK_DF) _CrtDumpMemoryLeaks(); #endif /* _DEBUG */ /* Shut down lowio */ _ioterm(); #ifdef _MT _mtterm(); #endif /* _MT */ /* This should be the last thing the C run-time does */ _heap_term(); /* heap is now invalid! */ } else /* no prior process attach, just return */ return FALSE; } #ifdef _MT else if ( dwReason == DLL_THREAD_DETACH ) { _freeptd(NULL); /* free up per-thread CRT data */ } #endif /* _MT */ return TRUE ; } /*** *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 is the preferred entry point. _CRT_INIT may also be * used, or the user may supply his/her own entry and call _CRT_INIT * from within it, but this is not the preferred method. * *******************************************************************************/ BOOL WINAPI _DllMainCRTStartup( HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved ) { BOOL retcode = TRUE; /* * If this is a process detach notification, check that there has * has been a prior process attach notification. */ if ( (dwReason == DLL_PROCESS_DETACH) && (__proc_attached == 0) ) /* * no prior process attach notification. just return * without doing anything. */ return FALSE; if ( dwReason == DLL_PROCESS_ATTACH || dwReason == DLL_THREAD_ATTACH ) { if ( _pRawDllMain ) retcode = (*_pRawDllMain)(hDllHandle, dwReason, lpreserved); if ( retcode ) retcode = _CRT_INIT(hDllHandle, dwReason, lpreserved); if ( !retcode ) return FALSE; } retcode = DllMain(hDllHandle, dwReason, lpreserved); if ( (dwReason == DLL_PROCESS_ATTACH) && !retcode ) /* * The user's DllMain routine returned failure, the C runtime * needs to be cleaned up. Do this by calling _CRT_INIT again, * this time imitating DLL_PROCESS_DETACH. Note this will also * clear the __proc_attached flag so the cleanup will not be * repeated upon receiving the real process detach notification. */ _CRT_INIT(hDllHandle, DLL_PROCESS_DETACH, lpreserved); if ( (dwReason == DLL_PROCESS_DETACH) || (dwReason == DLL_THREAD_DETACH) ) { if ( _CRT_INIT(hDllHandle, dwReason, lpreserved) == FALSE ) retcode = FALSE ; if ( retcode && _pRawDllMain ) retcode = (*_pRawDllMain)(hDllHandle, dwReason, lpreserved); } 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 __cdecl _amsg_exit ( int rterrnum ) { if ( (__error_mode == _OUT_TO_STDERR) || ((__error_mode == _OUT_TO_DEFAULT) && (__app_type == _CONSOLE_APP)) ) _FF_MSGBANNER(); /* write run-time error banner */ _NMSG_WRITE(rterrnum); /* write message */ _aexit_rtn(255); /* normally _exit(255) */ } #endif /* CRTDLL */ #else /* _WIN32 */ #include #include #include #include #include #include #include /* * User routine DllMain is called on all notifications */ OSErr _DllInit(InitBlockPtr pinitBlk); void _DllExit(void); void _CALLTYPE1 _cexit (void); /*** *OSErr _DllMainCRTStartup(void) - * 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". * *Entry: * *Exit: * *NOTES: * This routine is the preferred entry point. * *******************************************************************************/ OSErr _DllMainCRTStartup(InitBlockPtr pinitBlk) { OSErr ret; __cinit(); //return the user routine value ret = _DllInit(pinitBlk); return ret ; } /*** *OSErr _DllMainCRTExit(void) - * C Run-Time termination for a DLL linked with a C run-time library. * *Purpose: * This routine does the C run-time termination * and then calls the user code notification handler "DllExit". * *Entry: * *Exit: * *NOTES: * This routine is the preferred entry point. * *******************************************************************************/ void _DllMainCRTExit() { //currently don't care the return value user routine returns //we could return user returns if this is an issue _DllExit(); _cexit(); } #endif /* _WIN32 */