BOOL __cdecl __CRTDLL_INIT( HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved ) { BOOL term_all = FALSE; if ( dwReason == DLL_PROCESS_ATTACH ) { if ( !_heap_init() ) /* initialize heap */ /* * The heap cannot be initialized, return failure to the * loader. */ return FALSE; if(!_mtinit()) /* initialize multi-thread */ { /* * If the DLL load is going to fail, we must clean up * all resources that have already been allocated. */ _heap_term(); /* heap is now invalid! */ return FALSE; /* fail DLL load on failure */ } if (_ioinit() < 0) { _mtterm(); /* free TLS index, call _mtdeletelocks() */ _heap_term(); /* heap is now invalid! */ return FALSE; /* fail DLL load on failure */ } _wcmdln = GetCommandLineW(); #if !defined(_CRT_APP) || defined(_KERNELX) _aenvptr = (char *)__crtGetEnvironmentStringsA(); _acmdln = GetCommandLineA(); #else /* !defined(_CRT_APP) || defined(_KERNELX) */ // We cannot call GetCommandLineA in the App CRT: if (!__copy_to_char(_wcmdln, &_acmdln)) { _acmdln = NULL; } #endif /* !defined(_CRT_APP) || defined(_KERNELX) */ #if !defined(_CRT_APP) || defined(_KERNELX) #ifdef _MBCS /* * Initialize multibyte ctype table. Always done since it is * needed for processing the environment strings. */ __initmbctable(); #endif /* _MBCS */ if (_setenvp() < 0 || /* get environ info */ _cinit(FALSE) != 0) /* do C data initialize */ { term_all = TRUE; } #else /* !defined(_CRT_APP) || defined(_KERNELX) */ if (_cinit(FALSE) != 0) /* do C data initialize */ { term_all = TRUE; } #endif /* !defined(_CRT_APP) || defined(_KERNELX) */ if (term_all) { #if defined(_CRT_APP) && !defined(_KERNELX) _free_crt(_acmdln); _acmdln = NULL; #endif _ioterm(); /* shut down lowio */ _mtterm(); /* free TLS index, call _mtdeletelocks() */ _heap_term(); /* heap is now invalid! */ return FALSE; /* fail DLL load on failure */ } /* * Increment flag indicating process attach notification * has been received. */ proc_attached++; } else if ( dwReason == DLL_PROCESS_DETACH ) { /* * if a client process is detaching, make sure minimal * runtime termination is performed and clean up our * 'locks' (i.e., delete critical sections). */ if ( proc_attached > 0 ) { proc_attached--; __try { /* * Any basic clean-up done here may also need * to be done below if Process Attach is partly * processed and then a failure is encountered. */ if ( _C_Termination_Done == FALSE ) _cexit(); __crtdll_callstaticterminators(); /* Free all allocated CRT memory */ __freeCrtMemory(); #ifdef _DEBUG /* Dump all memory leaks */ if (_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & _CRTDBG_LEAK_CHECK_DF) { _CrtSetDumpClient(NULL); _CrtDumpMemoryLeaks(); } #endif /* _DEBUG */ /* * What remains is to clean up the system resources we have * used (handles, critical sections, memory,...,etc.). This * needs to be done if the whole process is NOT terminating. */ /* If dwReason is DLL_PROCESS_DETACH, lpreserved is NULL * if FreeLibrary has been called or the DLL load failed * and non-NULL if the process is terminating. */ if ( lpreserved == NULL ) { #if defined(_CRT_APP) && !defined(_KERNELX) _free_crt(_acmdln); _acmdln = NULL; #endif /* * The process is NOT terminating so we must clean up... */ _ioterm(); /* free TLS index, call _mtdeletelocks() */ _mtterm(); /* This should be the last thing the C run-time does */ _heap_term(); /* heap is now invalid! */ } } __finally { /* we shouldn't really have to care about this, because letting an exception escape from DllMain(DLL_PROCESS_DETACH) should result in process termination. Unfortunately, Windows up to Win7 as of now just silently swallows the exception. I have considered all kinds of tricks, but decided to leave it up to OS folks to fix this. For the time being just remove our FLS callback during phase 2 unwind that would otherwise be left pointing to unmapped address space. */ if ( lpreserved == NULL && __flsindex != FLS_OUT_OF_INDEXES ) _mtterm(); } } else /* no prior process attach, just return */ return FALSE;
/*** *_setargv, __setargv - set up "argc" and "argv" for C programs * *Purpose: * Read the command line and create the argv array for C * programs. * *Entry: * Arguments are retrieved from the program command line, * pointed to by _acmdln. * *Exit: * "argv" points to a null-terminated list of pointers to ASCIZ * strings, each of which is an argument from the command line. * "argc" is the number of arguments. The strings are copied from * the environment segment into space allocated on the heap/stack. * The list of pointers is also located on the heap or stack. * _pgmptr points to the program name. * *Exceptions: * Terminates with out of memory error if no memory to allocate. * *******************************************************************************/ #ifdef WILDCARD #ifdef WPRFLAG void __cdecl __wsetargv ( #else /* WPRFLAG */ void __cdecl __setargv ( #endif /* WPRFLAG */ #else /* WILDCARD */ #ifdef WPRFLAG void __cdecl _wsetargv ( #else /* WPRFLAG */ void __cdecl _setargv ( #endif /* WPRFLAG */ #endif /* WILDCARD */ void ) { _TSCHAR *p; _TSCHAR *cmdstart; /* start of command line to parse */ int numargs, numchars; static _TSCHAR _pgmname[ MAX_PATH ]; #if !defined (CRTDLL) && defined (_MBCS) /* If necessary, initialize the multibyte ctype table. */ if ( __mbctype_initialized == 0 ) __initmbctable(); #endif /* !defined (CRTDLL) && defined (_MBCS) */ /* Get the program name pointer from Win32 Base */ GetModuleFileName( NULL, _pgmname, sizeof( _pgmname ) / sizeof(_TSCHAR)); #ifdef WPRFLAG _wpgmptr = _pgmname; #else /* WPRFLAG */ _pgmptr = _pgmname; #endif /* WPRFLAG */ /* if there's no command line at all (won't happen from cmd.exe, but possibly another program), then we use _pgmptr as the command line to parse, so that argv[0] is initialized to the program name */ #ifdef WPRFLAG cmdstart = (*_wcmdln == NULCHAR) ? _wpgmptr : _wcmdln; #else /* WPRFLAG */ cmdstart = (*_acmdln == NULCHAR) ? _pgmptr : _acmdln; #endif /* WPRFLAG */ /* first find out how much space is needed to store args */ #ifdef WPRFLAG wparse_cmdline(cmdstart, NULL, NULL, &numargs, &numchars); #else /* WPRFLAG */ parse_cmdline(cmdstart, NULL, NULL, &numargs, &numchars); #endif /* WPRFLAG */ /* allocate space for argv[] vector and strings */ p = _malloc_crt(numargs * sizeof(_TSCHAR *) + numchars * sizeof(_TSCHAR)); if (p == NULL) _amsg_exit(_RT_SPACEARG); /* store args and argv ptrs in just allocated block */ #ifdef WPRFLAG wparse_cmdline(cmdstart, (wchar_t **)p, (wchar_t *)(((char *)p) + numargs * sizeof(wchar_t *)), &numargs, &numchars); #else /* WPRFLAG */ parse_cmdline(cmdstart, (char **)p, p + numargs * sizeof(char *), &numargs, &numchars); #endif /* WPRFLAG */ /* set argv and argc */ __argc = numargs - 1; #ifdef WPRFLAG __wargv = (wchar_t **)p; #else /* WPRFLAG */ __argv = (char **)p; #endif /* WPRFLAG */ #ifdef WILDCARD /* call _[w]cwild to expand wildcards in arg vector */ #ifdef WPRFLAG if (_wcwild()) #else /* WPRFLAG */ if (_cwild()) #endif /* WPRFLAG */ _amsg_exit(_RT_SPACEARG); /* out of space */ #endif /* WILDCARD */ }