int _LibMain( int hdll, int reason, void *reserved ) { thread_data *tdata; int rc = 0; switch( reason ) { case DLL_THREAD_ATTACH: tdata = ( thread_data * )RdosAllocateMem( __ThreadDataSize ); if( tdata ) { memset( tdata, 0, __ThreadDataSize ); tdata->__data_size = __ThreadDataSize; __RdosAddThread( tdata ); } break; case DLL_PROCESS_ATTACH: __InitRtns( INIT_PRIORITY_THREAD ); tdata = ( thread_data * )RdosAllocateMem( __ThreadDataSize ); memset( tdata, 0, __ThreadDataSize ); tdata->__data_size = __ThreadDataSize; __InitThreadData( tdata ); __RdosInit( 1, tdata, hdll ); __InitRtns( 255 ); __CommonInit(); __sig_init_rtn(); if( !__RdosThreadInit() ) return( -1 ); __InitMultipleThread(); rc = LibMain( hdll, reason, reserved ); if( !rc ) { __FiniRtns( 0, 255 ); } break; case DLL_THREAD_DETACH: __RdosRemoveThread(); break; case DLL_PROCESS_DETACH: __FiniRtns( 0, FINI_PRIORITY_EXIT - 1 ); __RdosRemoveThread(); RdosFreeMem( __FirstThreadData ); __FirstThreadData = NULL; break; } return( rc ); }
_WCRTLINK void _UnloadCLib( void ) { (*__int23_exit)(); __FiniRtns( FINI_PRIORITY_EXIT, 255 ); (*__int23_exit)(); (*__FPE_handler_exit)(); __FiniRtns( 0, FINI_PRIORITY_EXIT-1 ); }
_WCRTLINK _WCNORETURN void exit( int status ) { #ifdef DEFAULT_WINDOWING if( _WindowsExitRtn != NULL ) { // JBS 27-JUL-98 _WindowsExitRtn(); } #endif #if defined(__WINDOWS_386__) if( __Is_DLL ) { _exit( status ); // never return } #elif defined(__NT__) || defined(__WARP__) (*__int23_exit)(); if( __Is_DLL ) { if( __process_fini != NULL ) { (*__process_fini)( FINI_PRIORITY_EXIT, 255 ); } _exit( status ); // never return } #elif defined(__DOS__) || defined(__OS2__) || defined(__WINDOWS_286__) (*__int23_exit)(); #endif __FiniRtns( FINI_PRIORITY_EXIT, 255 ); _exit( status ); // never return }
/***************************************************************************** // __exit should ensure that __deinit_environment is // called at termination. *****************************************************************************/ _NORETURN void __exit( unsigned rc ) { __FiniRtns( 0, InitFiniLevel ); /* * Netware has own _exit procedure */ _exit( rc ); // never return }
_WCRTLINK void __exit( unsigned ret_code ) { __FiniRtns( 0, FINI_PRIORITY_EXIT-1 ); _asm { mov eax, -1 int 0x40 } }
_WCRTLINK void __exit( unsigned ret_code ) /*****************************************/ { __FiniRtns( 0, FINI_PRIORITY_EXIT-1 ); #ifdef __SW_BD RetCode = ret_code; longjmp( JmpBuff, 1 ); #else DosExit( EXIT_PROCESS, ret_code ); #endif }
/***************************************************************************** // free runtime environemnt. *****************************************************************************/ int __deinit_environment( void * reserved ) { /* // a. clear the multiple thread handlers // b. call registered library cleanup routines // c. free up all remaining per thread data // d. free up first thread data */ __FiniMultipleThread(); __FiniRtns( 0, InitFiniLevel); //__RemoveAllThreadData(); return 0; }
void __CommonTerm( void ) { struct _heapinfo hinfo; void _WCNEAR *moffs; /* Run the normal termination first. */ (*__int23_exit)(); __FiniRtns( FINI_PRIORITY_EXIT, 255 ); (*__int23_exit)(); __FiniRtns( 0, FINI_PRIORITY_EXIT-1 ); /* Now try to free "forgotten" memory. */ hinfo._pentry = NULL; for( ;; ) { if( _heapwalk( &hinfo ) != _HEAPOK ) break; if( hinfo._useflag ) { moffs = (void _WCNEAR *)FP_OFF( hinfo._pentry ); free( (char *)moffs + sizeof( void * ) ); } } /* Return freed memory back to the OS. */ _heapshrink(); }
_WCRTLINK _NORETURN void __exit( unsigned ret_code ) { __OS2Fini(); // must be done before following finalizers get called if( __Is_DLL ) { if( __process_fini != NULL ) { (*__process_fini)( 0, FINI_PRIORITY_EXIT - 1 ); } } else { __FiniRtns( 0, FINI_PRIORITY_EXIT - 1 ); __shutdown_stack_checking(); } DosExit( EXIT_PROCESS, ret_code ); // never return }
_WCRTLINK void __exit( unsigned ret_code ) { __FiniRtns( 0, FINI_PRIORITY_EXIT - 1 ); sys_exit( ret_code ); }
unsigned _LibMain( unsigned hmod, unsigned termination ) /******************************************************/ { static int processes; unsigned rc; if( termination != 0 ) { // If we're running with single DGROUP and tried to load // twice, do not run any termination code! Also reset the // process counter so that the already loaded DLL can // terminate properly if( processes > 1 ) { --processes; return( 0 ); } rc = LibMain( hmod, termination ); --processes; #ifdef __SW_BR __FiniRtns( 0, 255 ); #else if( _LpwCmdLine ) { lib_free( _LpwCmdLine ); _LpwCmdLine = NULL; } if( _LpwPgmName ) { lib_free( _LpwPgmName ); _LpwPgmName = NULL; } __FiniRtns( FINI_PRIORITY_EXIT, 255 ); // calls to free memory have to be done before semaphores closed __FreeInitThreadData( __FirstThreadData ); __OS2Fini(); // must be done before following finalizers get called __FiniRtns( 0, FINI_PRIORITY_EXIT - 1 ); __shutdown_stack_checking(); #endif return( rc ); } ++processes; if( processes > 1 ) { if( __disallow_single_dgroup(hmod) ) { return( 0 ); } } __hmodule = hmod; #ifdef __SW_BR { static char fname[_MAX_PATH]; static wchar_t wfname[_MAX_PATH]; __Is_DLL = 1; __InitRtns( 255 ); DosQueryModuleName( hmod, sizeof( fname ), fname ); _LpDllName = fname; _LpwDllName = wfname; _atouni( _LpwDllName, _LpDllName ); } #else { PTIB pptib; PPIB pppib; unsigned i; DosGetInfoBlocks( &pptib, &pppib ); _RWD_Envptr = pppib->pib_pchenv; _LpCmdLine = pppib->pib_pchcmd; while( *_LpCmdLine ) { // skip over program name _LpCmdLine++; } _LpCmdLine++; _LpwCmdLine = lib_malloc( (strlen( _LpCmdLine ) + 1) * sizeof( wchar_t ) ); _atouni( _LpwCmdLine, _LpCmdLine ); { // ugly stuff to deal with two copies of .exe name in the // environment space. apparently the OS fullpath name is // just before this one in the environment space char *cmd_path; cmd_path = pppib->pib_pchcmd; for( cmd_path -= 2; *cmd_path != '\0'; --cmd_path ); ++cmd_path; _LpPgmName = cmd_path; _LpwPgmName = lib_malloc( (strlen( _LpPgmName ) + 1) * sizeof( wchar_t ) ); _atouni( _LpwPgmName, _LpPgmName ); } __InitRtns( INIT_PRIORITY_THREAD ); if( __InitThreadProcessing() == NULL ) return( 0 ); __OS2Init( TRUE, __AllocInitThreadData( NULL ) ); for( i = 2; i <= __MaxThreads; i++ ) { if( !__OS2AddThread( i, NULL ) ) { return( 0 ); } } __InitRtns( INIT_PRIORITY_EXIT - 1 ); __InitMultipleThread(); { static char fname[_MAX_PATH]; static wchar_t wfname[_MAX_PATH]; DosQueryModuleName( hmod, sizeof( fname ), fname ); _LpDllName = fname; _LpwDllName = wfname; _atouni( _LpwDllName, _LpDllName ); } __InitRtns( 255 ); } #endif __CommonInit(); #ifndef __SW_BR /* allocate alternate stack for F77 */ __ASTACKPTR = (char *)_STACKLOW + __ASTACKSIZ; #endif return( LibMain( hmod, termination ) ); }
/* Exit the C runtime library to clean up and free all allocated memory */ void _CEXPORT TerminateLibC( void ) { __FiniRtns( 0, FINI_PRIORITY_EXIT-1 ); __FreeAllHeaps(); }
void _WCI86FAR __FFiniRtns( unsigned min_limit, unsigned max_limit ) { __FiniRtns( min_limit, max_limit ); }
_WCRTLINK _NORETURN void __exit( unsigned ret_code ) { __FiniRtns( 0, FINI_PRIORITY_EXIT - 1 ); _sys_exit( ret_code ); // never return }
int APIENTRY _LibMain( HANDLE hdll, DWORD reason, LPVOID reserved ) { int rc; static int processes; switch( reason ) { case DLL_THREAD_ATTACH: #ifndef __SW_BR if( !__NTAddThread( NULL ) ) { return( FALSE ); } #endif rc = LibMain( hdll, reason, reserved ); break; case DLL_PROCESS_ATTACH: ++processes; if( processes > 1 ) { if( __disallow_single_dgroup( hdll ) ) { rc = FALSE; break; } } #ifdef __SW_BR __Is_DLL = 1; __InitRtns( INIT_PRIORITY_EXIT - 1 ); #else // The following initializers are called: (in the CLIB run-time DLL): // nothing is called __InitRtns( INIT_PRIORITY_THREAD ); // allocate some thread data storage and initialize run-time variables { thread_data *tdata = __AllocInitThreadData( NULL ); if( !tdata || !__NTInit( TRUE, tdata, hdll ) ) { rc = FALSE; break; } } // set up TLSIndex thingee if( !__NTThreadInit() ) { // safe to call multiple times rc = FALSE; break; } // The following initializers are called: (in the CLIB run-time DLL): // __chk8087 // __verify_pentium_fdiv_bug // __Init_Argv // __imthread_fn (which calls _NTThreadInit and __InitMultipleThread) __InitRtns( INIT_PRIORITY_EXIT - 1 ); // sets up semaphores and starts linked list of thread data storage __InitMultipleThread(); // now safe to call multiple times #endif if( _pRawDllMain != NULL ) { if( !_pRawDllMain( hdll, reason, reserved ) ) { __FiniRtns( 0, FINI_PRIORITY_EXIT - 1 ); rc = FALSE; break; } } // The following initializers are called: (in the CLIB run-time DLL): // profilog_init // __InitWinLinesSem // dbgdata@do_it // __setenvp // __mbInitOnStartup // __sig_init // (??) in STK // __InitFiles // __clock_init __InitRtns( 255 ); #ifdef __SW_BR { static char fn[_MAX_PATH]; __lib_GetModuleFileNameA( hdll, fn, sizeof( fn ) ); _LpDllName = fn; } { static wchar_t wfn[_MAX_PATH]; __lib_GetModuleFileNameW( hdll, wfn, sizeof( wfn ) ); _LpwDllName = wfn; } #endif __CommonInit(); __sig_init_rtn(); rc = LibMain( hdll, reason, reserved ); if( !rc ) { __FiniRtns( 0, 255 ); } break; case DLL_THREAD_DETACH: rc = LibMain( hdll, reason, reserved ); #ifndef __SW_BR __NTRemoveThread( TRUE ); #endif break; case DLL_PROCESS_DETACH: rc = LibMain( hdll, reason, reserved ); __FiniRtns( FINI_PRIORITY_EXIT, 255 ); if( _pRawDllMain != NULL ) { _pRawDllMain( hdll, reason, reserved ); } #ifndef __SW_BR __NTFini(); // must be done before following finalizers get called #endif __FiniRtns( 0, FINI_PRIORITY_EXIT - 1 ); #ifndef __SW_BR __NTRemoveThread( TRUE ); __FreeInitThreadData( __FirstThreadData ); __FirstThreadData = NULL; #endif --processes; } return( rc ); }
/***************************************************************************** // __exit should ensure that __deinit_environment is // called at termination. *****************************************************************************/ extern void __exit( unsigned rc ) { __FiniRtns( 0, InitFiniLevel ); _exit( rc ); }