_TSCHAR * __cdecl _tasctime ( const struct tm *tb ) { _TSCHAR *p = buf; errno_t e = 0; _TSCHAR *retval; /* holds retval pointer */ _ptiddata ptd = _getptd_noexit(); /* Use per thread buffer area (malloc space, if necessary) */ if (ptd) { #ifdef _UNICODE if ( (ptd->_wasctimebuf != NULL) || ((ptd->_wasctimebuf = (wchar_t *)_calloc_crt(_ASCBUFSIZE, sizeof(wchar_t))) != NULL) ) p = ptd->_wasctimebuf; #else /* _UNICODE */ if ( (ptd->_asctimebuf != NULL) || ((ptd->_asctimebuf = (char *)_calloc_crt(_ASCBUFSIZE, sizeof(char))) != NULL) ) p = ptd->_asctimebuf; #endif /* _UNICODE */ } retval = p; /* save return value for later */ e = _tasctime_s( p, _ASCBUFSIZE, tb ); if ( e != 0 ) { return NULL; } return (retval); }
int __cdecl __initstdio(void) { int i; #ifndef CRTDLL /* * If the user has not supplied a definition of _nstream, set it * to _NSTREAM_. If the user has supplied a value that is too small * set _nstream to the minimum acceptable value (_IOB_ENTRIES). */ if (_nstream == 0) { _nstream = _NSTREAM_; } else if (_nstream < _IOB_ENTRIES) { _nstream = _IOB_ENTRIES; } #endif /* CRTDLL */ /* * Allocate the __piob array. Try for _nstream entries first. If this * fails then reset _nstream to _IOB_ENTRIES and try again. If it * still fails, bail out with an RTE. */ if ((__piob = (void**)_calloc_crt(_nstream, sizeof(void*))) == NULL) { _nstream = _IOB_ENTRIES; if ((__piob = (void**)_calloc_crt(_nstream, sizeof(void*))) == NULL) { return _RT_STDIOINIT; } } /* * Initialize the first _IOB_ENTRIES to point to the corresponding * entries in _iob[]. */ for (i = 0 ; i < _IOB_ENTRIES ; i++) { __piob[i] = (void*)&_iob[i]; } for (i = 0 ; i < 3 ; i++) { if ((_osfhnd(i) == (intptr_t)INVALID_HANDLE_VALUE) || (_osfhnd(i) == _NO_CONSOLE_FILENO) || (_osfhnd(i) == 0)) { /* * For stdin, stdout & stderr, we use _NO_CONSOLE_FILENO (a value * different from _INVALID_HANDLE_VALUE to distinguish between * a failure in opening a file & a program run without a console. */ _iob[i]._file = _NO_CONSOLE_FILENO; } } return 0; }
int __cdecl __init_time ( pthreadlocinfo ploci ) { /* Temporary date/time strings */ struct __lc_time_data *lc_time; if ( ploci->lc_handle[LC_TIME] != _CLOCALEHANDLE ) { /* Allocate structure filled with NULL pointers */ if ( (lc_time = (struct __lc_time_data *) _calloc_crt(1, sizeof(struct __lc_time_data))) == NULL ) return 1; if (_get_lc_time(lc_time, ploci)) { __free_lc_time (lc_time); _free_crt (lc_time); return 1; } lc_time->refcount = 1; } else { lc_time = &__lc_time_c; /* point to new one */ } if (ploci->lc_time_curr != &__lc_time_c && InterlockedDecrement(&(ploci->lc_time_curr->refcount)) == 0) { _ASSERTE(ploci->lc_time_curr->refcount > 0); } ploci->lc_time_curr = lc_time; /* point to new one */ return 0; }
/*** *char *strerror(errnum) - Map error number to error message string. * *Purpose: * The strerror runtime takes an error number for input and * returns the corresponding error message string. This routine * conforms to the ANSI standard interface. * *Entry: * int errnum - Integer error number (corresponding to an errno value). * *Exit: * char * - Strerror returns a pointer to the error message string. * This string is internal to the strerror routine (i.e., not supplied * by the user). * *Exceptions: * None. * *******************************************************************************/ #ifdef _UNICODE wchar_t * cdecl _wcserror( #else /* _UNICODE */ char * __cdecl strerror ( #endif /* _UNICODE */ int errnum ) { _TCHAR *errmsg; _ptiddata ptd = _getptd_noexit(); if (!ptd) return _T("Visual C++ CRT: Not enough memory to complete call to strerror."); if ( (ptd->_terrmsg == NULL) && ((ptd->_terrmsg = _calloc_crt(_ERRMSGLEN_, sizeof(_TCHAR))) == NULL) ) return _T("Visual C++ CRT: Not enough memory to complete call to strerror."); else errmsg = ptd->_terrmsg; #ifdef _UNICODE _ERRCHECK(mbstowcs_s(NULL, errmsg, _ERRMSGLEN_, _get_sys_err_msg(errnum), _ERRMSGLEN_ - 1)); #else /* _UNICODE */ _ERRCHECK(strcpy_s(errmsg, _ERRMSGLEN_, _get_sys_err_msg(errnum))); #endif /* _UNICODE */ return(errmsg); }
void __cdecl __initstdio(void) { int i; #ifndef CRTDLL /* * If the user has not supplied a definition of _nstream, set it * to _NSTREAM_. If the user has supplied a value that is too small * set _nstream to the minimum acceptable value (_IOB_ENTRIES). */ if ( _nstream == 0 ) _nstream = _NSTREAM_; else if ( _nstream < _IOB_ENTRIES ) _nstream = _IOB_ENTRIES; #endif /* CRTDLL */ /* * Allocate the __piob array. Try for _nstream entries first. If this * fails then reset _nstream to _IOB_ENTRIES and try again. If it * still fails, bail out with an RTE. */ if ( (__piob = (void **)_calloc_crt( _nstream, sizeof(void *) )) == NULL ) { _nstream = _IOB_ENTRIES; if ( (__piob = (void **)_calloc_crt( _nstream, sizeof(void *) )) == NULL ) _amsg_exit( _RT_STDIOINIT ); } /* * Initialize the first _IOB_ENTRIES to point to the corresponding * entries in _iob[]. */ for ( i = 0 ; i < _IOB_ENTRIES ; i++ ) __piob[i] = (void *)&_iob[i]; for ( i = 0 ; i < 3 ; i++ ) { if ( (_osfhnd(i) == (long)INVALID_HANDLE_VALUE) || (_osfhnd(i) == 0L) ) { _iob[i]._file = -1; } } }
int _Mtx_init(_Mtx_t *mtx, int type) { /* initialize mutex */ _Mtx_t mutex; *mtx = 0; if ((mutex = (_Mtx_t)_calloc_crt(1, sizeof (struct _Mtx_internal_imp_t))) == 0) return (_Thrd_nomem); /* report alloc failed */ _Mtx_init_in_situ(mutex, type); *mtx = mutex; return (_Thrd_success); }
int __cdecl __init_monetary ( void ) { struct lconv *lc; if (__lc_handle[LC_MONETARY] != _CLOCALEHANDLE) { /* Allocate structure filled with NULL pointers */ if ((lc = (struct lconv *) _calloc_crt (1, sizeof(struct lconv))) == NULL) return 1; if (_get_lc_lconv (lc)) { _free_lc_lconv (lc); _free_crt (lc); return 1; } /* Copy numeric locale fields */ lc->decimal_point = __lconv->decimal_point; lc->thousands_sep = __lconv->thousands_sep; lc->grouping = __lconv->grouping; __lconv = lc; /* point to new one */ _free_lc_lconv (__lconv_intl); /* free the old one */ _free_crt (__lconv_intl); __lconv_intl = lc; return 0; } else { /* * Copy numeric locale fields (not necessarily C locale) * to static structure. Note that __lconv_c numeric locale * fields may contain non-C locale information, but * monetary locale fields always contain C locale info. */ __lconv_c.decimal_point = __lconv->decimal_point; __lconv_c.thousands_sep = __lconv->thousands_sep; __lconv_c.grouping = __lconv->grouping; __lconv = &__lconv_c; /* point to new one */ _free_lc_lconv (__lconv_intl); /* free the old one */ _free_crt (__lconv_intl); __lconv_intl = NULL; return 0; } }
_ptiddata __cdecl _getptd_noexit ( void ) { _ptiddata ptd; DWORD TL_LastError; TL_LastError = GetLastError(); /* * Initialize FlsGetValue function pointer in TLS */ __set_flsgetvalue(); if ( (ptd = FLS_GETVALUE(__flsindex)) == NULL ) { /* * no per-thread data structure for this thread. try to create * one. */ if ((ptd = _calloc_crt(1, sizeof(struct _tiddata))) != NULL) { if (FLS_SETVALUE(__flsindex, (LPVOID)ptd) ) { /* * Initialize of per-thread data */ _initptd(ptd,NULL); ptd->_tid = GetCurrentThreadId(); ptd->_thandle = (uintptr_t)(-1); } else { /* * Return NULL to indicate failure */ _free_crt(ptd); ptd = NULL; } } } SetLastError(TL_LastError); return(ptd); }
void __cdecl _wperror ( const wchar_t *wmessage ) { int fh = 2; size_t size = 0; char *amessage; const char *sysmessage; /* convert WCS string into ASCII string */ if ( wmessage && *wmessage ) { _ERRCHECK_EINVAL_ERANGE(wcstombs_s( &size, NULL, 0, wmessage, INT_MAX)); if ( size==0 || (amessage = (char *)_calloc_crt(size, sizeof(char))) == NULL ) return; if ( _ERRCHECK_EINVAL_ERANGE(wcstombs_s(NULL, amessage, size, wmessage, _TRUNCATE)) != 0) { _free_crt(amessage); return; } } else amessage = NULL; _lock_fh( fh ); /* acquire file handle lock */ __try { if ( amessage ) { _write_nolock(fh,(char *)amessage,(unsigned)strlen(amessage)); _write_nolock(fh,": ",2); } _free_crt(amessage); /* note: freeing NULL is legal and benign */ sysmessage = _get_sys_err_msg( errno ); _write_nolock(fh, sysmessage,(unsigned)strlen(sysmessage)); _write_nolock(fh,"\n",1); } __finally { _unlock_fh( fh ); /* release file handle lock */ } }
int __cdecl __wtomb_environ ( void ) { char *envp=NULL; wchar_t **wenvp = _wenviron; /* * For every environment variable in the multibyte environment, * convert it and add it to the wide environment. */ while (*wenvp) { int size; /* find out how much space is needed */ if ((size = WideCharToMultiByte(CP_ACP, 0, *wenvp, -1, NULL, 0, NULL, NULL)) == 0) return -1; /* allocate space for variable */ if ((envp = (char *) _calloc_crt(size, sizeof(char))) == NULL) return -1; /* convert it */ if (WideCharToMultiByte(CP_ACP, 0, *wenvp, -1, envp, size, NULL, NULL) == 0) { _free_crt(envp); return -1; } /* set it - this is not primary call, so set primary == 0 */ if(__crtsetenv(&envp, 0)<0) { if(envp) { _free_crt(envp); envp=NULL; } } wenvp++; } return 0; }
/*** *int _capture_argv(arglist, static_argv, max_static_entries) - set up argv array * for exec?? functions * *Purpose: * Set up the argv array for the exec?? functions by captures the * arguments from the passed va_list into the static_argv array. If the * size of the static_argv array as specified by the max_static_entries * parameter is not large enough, then allocates a dynamic array to hold * the arguments. Return the address of the final argv array. If NULL * then not enough memory to hold argument array. If different from * static_argv parameter then call must free the return argv array when * done with it. * * The scan of the arglist is terminated when a NULL argument is * reached. The terminating NULL parameter is stored in the resulting * argv array. * *Entry: * va_list *arglist - pointer to variable length argument list. * _TSCHAR *firstarg - first argument to store in array * _TSCHAR **static_argv - pointer to static argv to use. * size_t max_static_entries - maximum number of entries that can be * placed in static_argv array. * *Exit: * returns NULL if no memory. * Otherwise returns pointer to argv array. * (sometimes calls malloc) * *Exceptions: * *******************************************************************************/ #ifdef WPRFLAG _TSCHAR ** __cdecl _wcapture_argv( #else /* WPRFLAG */ _TSCHAR ** __cdecl _capture_argv( #endif /* WPRFLAG */ va_list *arglist, const _TSCHAR *firstarg, _TSCHAR **static_argv, size_t max_static_entries ) { _TSCHAR ** argv; _TSCHAR * nextarg; size_t i; size_t max_entries; nextarg = (_TSCHAR *)firstarg; argv = static_argv; max_entries = max_static_entries; i = 0; for (;;) { if (i >= max_entries) { /* The math here looks slightly odd. We really want (max_entries*2)*sizeof(_TSCHAR), but that can overflow We take advantage of calloc's ability to catch overflow and the fact that sizeof(_TSCHAR)*2 cannot overflow */ if (argv == static_argv) { argv = _calloc_crt(max_entries, sizeof(_TSCHAR *)*2); } else { argv = _recalloc_crt(argv, max_entries, sizeof(_TSCHAR *)*2); } if (argv == NULL) break; max_entries += max_entries; } argv[ i++ ] = nextarg; if (nextarg == NULL) break; nextarg = va_arg(*arglist, _TSCHAR *); } return argv; }
/*** *char *_strerror(message) - get system error message * *Purpose: * builds an error message consisting of the users error message * (the message parameter), followed by ": ", followed by the system * error message (index through errno), followed by a newline. If * message is NULL or a null string, returns a pointer to just * the system error message. * *Entry: * char *message - user's message to prefix system error message * *Exit: * returns pointer to static memory containing error message. * returns NULL if malloc() fails in multi-thread versions. * *Exceptions: * *******************************************************************************/ #ifdef _UNICODE wchar_t * __cdecl __wcserror( #else /* _UNICODE */ char * __cdecl _strerror ( #endif /* _UNICODE */ const _TCHAR *message ) { const char *sysErrorMsg = NULL; _TCHAR *bldmsg; _ptiddata ptd = _getptd_noexit(); if (!ptd) return NULL; /* Use per thread buffer area (malloc space, if necessary) */ /* [NOTE: This buffer is shared between _strerror and streror.] */ if ( (ptd->_terrmsg == NULL) && ((ptd->_terrmsg = _calloc_crt(_ERRMSGLEN_, sizeof(_TCHAR))) == NULL) ) return(NULL); bldmsg = ptd->_terrmsg; /* Build the error message */ bldmsg[0] = '\0'; if (message && *message) { // should leave space for ": \n\0" _ERRCHECK(_tcsncat_s( bldmsg, _ERRMSGLEN_, message, _ERRMSGLEN_-4 )); _ERRCHECK(_tcscat_s( bldmsg, _ERRMSGLEN_, _T(": "))); } // We should have extra space for "\n\0" sysErrorMsg = _get_sys_err_msg(errno); #ifdef _UNICODE _ERRCHECK(mbstowcs_s(NULL, bldmsg + wcslen(bldmsg), _ERRMSGLEN_ - wcslen(bldmsg), sysErrorMsg, _ERRMSGLEN_ - wcslen(bldmsg) - 2)); #else /* _UNICODE */ _ERRCHECK(strncat_s(bldmsg, _ERRMSGLEN_, sysErrorMsg, _ERRMSGLEN_ - strlen(bldmsg) - 2)); #endif /* _UNICODE */ _ERRCHECK(_tcscat_s( bldmsg, _ERRMSGLEN_, _T("\n"))); return bldmsg; }
static int __cdecl extend_ioinfo_arrays( int fh ) { ioinfo *pio; int i; /* * Walk __pioinfo[], allocating an array of ioinfo structs for each * empty entry, until there is an ioinfo struct corresponding to fh. */ for ( i = 0 ; fh >= _nhandle ; i++ ) { if ( __pioinfo[i] == NULL ) { if ( (pio = _calloc_crt( IOINFO_ARRAY_ELTS, sizeof(ioinfo) )) != NULL ) { __pioinfo[i] = pio; _nhandle += IOINFO_ARRAY_ELTS; for ( ; pio < __pioinfo[i] + IOINFO_ARRAY_ELTS ; pio++ ) { pio->osfile = 0; pio->osfhnd = (intptr_t)INVALID_HANDLE_VALUE; pio->pipech = 10; pio->lockinitflag = 0; } } else { /* * Couldn't allocate another array, return failure. */ return -1; } } } return 0; }
LPVOID __cdecl __crtGetEnvironmentStringsW( VOID ) { static int f_use = 0; void* penv = NULL; char* pch; wchar_t* pwch; wchar_t* wbuffer; int total_size = 0; int str_size; /* * Look for unstubbed 'preferred' flavor. Otherwise use available flavor. * Must actually call the function to ensure it's not a stub. */ if (0 == f_use) { if (NULL != (penv = GetEnvironmentStringsW())) { f_use = USE_W; } else if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { f_use = USE_A; } } /* Use "W" version */ if (USE_W == f_use) { if (NULL == penv) if (NULL == (penv = GetEnvironmentStringsW())) { return NULL; } /* find out how big a buffer is needed */ pwch = penv; while (*pwch != L'\0') { if (*++pwch == L'\0') { pwch++; } } total_size = (int)((char*)pwch - (char*)penv) + (int)sizeof(wchar_t); /* allocate the buffer */ if (NULL == (wbuffer = _malloc_crt(total_size))) { FreeEnvironmentStringsW(penv); return NULL; } /* copy environment strings to buffer */ memcpy(wbuffer, penv, total_size); FreeEnvironmentStringsW(penv); return (LPVOID)wbuffer; } /* Use "A" version */ if (USE_A == f_use || f_use == 0) { /* * Convert strings and return the requested information. */ if (NULL == penv) if (NULL == (penv = GetEnvironmentStringsA())) { return NULL; } pch = penv; /* find out how big a buffer we need */ while (*pch != '\0') { if (0 == (str_size = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pch, -1, NULL, 0))) { return 0; } total_size += str_size; pch += strlen(pch) + 1; } /* room for final NULL */ total_size++; /* allocate enough space for chars */ if (NULL == (wbuffer = (wchar_t*) _calloc_crt(total_size, sizeof(wchar_t)))) { FreeEnvironmentStringsA(penv); return NULL; } /* do the conversion */ pch = penv; pwch = wbuffer; while (*pch != '\0') { if (0 == MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pch, -1, pwch, total_size - (int)(pwch - wbuffer))) { _free_crt(wbuffer); FreeEnvironmentStringsA(penv); return NULL; } pch += strlen(pch) + 1; pwch += wcslen(pwch) + 1; } *pwch = L'\0'; FreeEnvironmentStringsA(penv); return (LPVOID)wbuffer; } else { /* f_use is neither USE_A nor USE_W */ return NULL; } }
LPWSTR __cdecl __crtGetCommandLineW( VOID ) { static int f_use = 0; /* * Look for unstubbed 'preferred' flavor. Otherwise use available flavor. * Must actually call the function to ensure it's not a stub. */ if (0 == f_use) { if (NULL != GetCommandLineW()) { f_use = USE_W; } else if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { f_use = USE_A; } else { return 0; } } /* Use "W" version */ if (USE_W == f_use) { return GetCommandLineW(); } /* Use "A" version */ if (USE_A == f_use || f_use == 0) { int buff_size; wchar_t* wbuffer; LPSTR lpenv; /* * Convert strings and return the requested information. */ lpenv = GetCommandLineA(); /* find out how big a buffer we need */ if (0 == (buff_size = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpenv, -1, NULL, 0))) { return 0; } /* allocate enough space for chars */ if (NULL == (wbuffer = (wchar_t*) _calloc_crt(buff_size, sizeof(wchar_t)))) { return 0; } if (0 != MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpenv, -1, wbuffer, buff_size)) { return (LPWSTR)wbuffer; } else { _free_crt(wbuffer); return 0; } } else { /* f_use is neither USE_A nor USE_W */ return 0; } }
unsigned long __cdecl _beginthread ( void (__cdecl * initialcode) (void *), unsigned stacksize, void * argument ) { _ptiddata ptd; /* pointer to per-thread data */ unsigned long thdl; /* thread handle */ unsigned long errcode = 0L; /* Return from GetLastError() */ /* * Allocate and initialize a per-thread data structure for the to- * be-created thread. */ if ( (ptd = _calloc_crt(1, sizeof(struct _tiddata))) == NULL ) goto error_return; /* * Initialize the per-thread data */ _initptd(ptd); ptd->_initaddr = (void *) initialcode; ptd->_initarg = argument; /* * Create the new thread. Bring it up in a suspended state so that * the _thandle and _tid fields are filled in before execution * starts. */ if ( (ptd->_thandle = thdl = (unsigned long) CreateThread( NULL, stacksize, _threadstart, (LPVOID)ptd, CREATE_SUSPENDED, (LPDWORD)&(ptd->_tid) )) == 0L ) { errcode = GetLastError(); goto error_return; } /* * Start the new thread executing */ if ( ResumeThread( (HANDLE)thdl ) == (DWORD)(-1L) ) { errcode = GetLastError(); goto error_return; } /* * Good return */ return(thdl); /* * Error return */ error_return: /* * Either ptd is NULL, or it points to the no-longer-necessary block * calloc-ed for the _tiddata struct which should now be freed up. */ _free_crt(ptd); /* * Map the error, if necessary. */ if ( errcode != 0L ) _dosmaperr(errcode); return((unsigned long)-1L); }
_MCRTIMP uintptr_t __cdecl _beginthread ( void (__CLRCALL_OR_CDECL * initialcode) (void *), unsigned stacksize, void * argument ) { _ptiddata ptd; /* pointer to per-thread data */ uintptr_t thdl; /* thread handle */ unsigned long err = 0L; /* Return from GetLastError() */ /* validation section */ _VALIDATE_RETURN(initialcode != NULL, EINVAL, -1); /* Initialize FlsGetValue function pointer */ __set_flsgetvalue(); /* * Allocate and initialize a per-thread data structure for the to- * be-created thread. */ if ( (ptd = (_ptiddata)_calloc_crt(1, sizeof(struct _tiddata))) == NULL ) { goto error_return; } /* * Initialize the per-thread data */ _initptd(ptd, _getptd()->ptlocinfo); ptd->_initaddr = (void *) initialcode; ptd->_initarg = argument; #if defined (_M_CEE) || defined (MRTDLL) if(!_getdomain(&(ptd->__initDomain))) { goto error_return; } #endif /* defined (_M_CEE) || defined (MRTDLL) */ /* * Create the new thread. Bring it up in a suspended state so that * the _thandle and _tid fields are filled in before execution * starts. */ if ( (ptd->_thandle = thdl = (uintptr_t) CreateThread( NULL, stacksize, _threadstart, (LPVOID)ptd, CREATE_SUSPENDED, (LPDWORD)&(ptd->_tid) )) == (uintptr_t)0 ) { err = GetLastError(); goto error_return; } /* * Start the new thread executing */ if ( ResumeThread( (HANDLE)thdl ) == (DWORD)(-1) ) { err = GetLastError(); goto error_return; } /* * Good return */ return(thdl); /* * Error return */ error_return: /* * Either ptd is NULL, or it points to the no-longer-necessary block * calloc-ed for the _tiddata struct which should now be freed up. */ _free_crt(ptd); /* * Map the error, if necessary. */ if ( err != 0L ) _dosmaperr(err); return( (uintptr_t)(-1) ); }
/**** *_mtinit() - Init multi-thread data bases * *Purpose: * (1) Call _mtinitlocks to create/open all lock semaphores. * (2) Allocate a TLS index to hold pointers to per-thread data * structure. * * NOTES: * (1) Only to be called ONCE at startup * (2) Must be called BEFORE any mthread requests are made * *Entry: * <NONE> *Exit: * returns FALSE on failure * *Uses: * <any registers may be modified at init time> * *Exceptions: * *******************************************************************************/ int __cdecl _mtinit ( void ) { _ptiddata ptd; #ifndef _M_AMD64 /* * Initialize fiber local storage function pointers. */ HINSTANCE hKernel32 = GetModuleHandle(_KERNEL32); if (hKernel32 == NULL) { _mtterm(); return FALSE; /* fail to load DLL */ } gpFlsAlloc = (PFLS_ALLOC_FUNCTION)GetProcAddress(hKernel32, "FlsAlloc"); gpFlsGetValue = (PFLS_GETVALUE_FUNCTION)GetProcAddress(hKernel32, "FlsGetValue"); gpFlsSetValue = (PFLS_SETVALUE_FUNCTION)GetProcAddress(hKernel32, "FlsSetValue"); gpFlsFree = (PFLS_FREE_FUNCTION)GetProcAddress(hKernel32, "FlsFree"); if (!gpFlsAlloc || !gpFlsGetValue || !gpFlsSetValue || !gpFlsFree) { gpFlsAlloc = (PFLS_ALLOC_FUNCTION)__crtTlsAlloc; gpFlsGetValue = (PFLS_GETVALUE_FUNCTION)TlsGetValue; gpFlsSetValue = (PFLS_SETVALUE_FUNCTION)TlsSetValue; gpFlsFree = (PFLS_FREE_FUNCTION)TlsFree; } /* * Allocate and initialize a TLS index to store FlsGetValue pointer * so that the FLS_* macros can work transparently */ if ( (__getvalueindex = TlsAlloc()) == 0xffffffff || !TlsSetValue(__getvalueindex, (LPVOID)gpFlsGetValue) ) { return FALSE; } #endif /* _M_AMD64 */ _init_pointers(); /* initialize global function pointers */ #ifndef _M_AMD64 /* * Encode the fiber local storage function pointers */ gpFlsAlloc = (PFLS_ALLOC_FUNCTION) _encode_pointer(gpFlsAlloc); gpFlsGetValue = (PFLS_GETVALUE_FUNCTION) _encode_pointer(gpFlsGetValue); gpFlsSetValue = (PFLS_SETVALUE_FUNCTION) _encode_pointer(gpFlsSetValue); gpFlsFree = (PFLS_FREE_FUNCTION) _encode_pointer(gpFlsFree); #endif /* _M_AMD64 */ /* * Initialize the mthread lock data base */ if ( !_mtinitlocks() ) { _mtterm(); return FALSE; /* fail to load DLL */ } /* * Allocate a TLS index to maintain pointers to per-thread data */ if ( (__flsindex = FLS_ALLOC(&_freefls)) == 0xffffffff ) { _mtterm(); return FALSE; /* fail to load DLL */ } /* * Create a per-thread data structure for this (i.e., the startup) * thread. */ if ( ((ptd = _calloc_crt(1, sizeof(struct _tiddata))) == NULL) || !FLS_SETVALUE(__flsindex, (LPVOID)ptd) ) { _mtterm(); return FALSE; /* fail to load DLL */ } /* * Initialize the per-thread data */ _initptd(ptd,NULL); ptd->_tid = GetCurrentThreadId(); ptd->_thandle = (uintptr_t)(-1); return TRUE; }
BOOL __cdecl __crtGetStringTypeW( DWORD dwInfoType, LPCWSTR lpSrcStr, int cchSrc, LPWORD lpCharType, int code_page, int lcid ) { static int f_use = 0; /* * Look for unstubbed 'preferred' flavor. Otherwise use available flavor. * Must actually call the function to ensure it's not a stub. */ if (0 == f_use) { unsigned short dummy; if (0 != GetStringTypeW(CT_CTYPE1, L"\0", 1, &dummy)) f_use = USE_W; else if (0 != GetStringTypeA(0, CT_CTYPE1, "\0", 1, &dummy)) f_use = USE_A; else return FALSE; } /* Use "W" version */ if (USE_W == f_use) { return GetStringTypeW(dwInfoType, lpSrcStr, cchSrc, lpCharType); } /* Use "A" version */ if (USE_A == f_use) { int retval; int buff_size; BOOL retbool = FALSE; unsigned char *buffer = NULL; WORD * pwCharInfo = NULL; /* * Convert string and return the requested information. Note that * we are converting to a multibyte string so there is not a * one-to-one correspondence between number of wide chars in the * input string and the number of *bytes* in the buffer. However, * there had *better be* a one-to-one correspondence between the * number of wide characters and the number of WORDs in the * return buffer. */ /* * Use __lc_codepage for conversion if code_page not specified */ if (0 == code_page) code_page = __lc_codepage; /* find out how big a buffer we need */ if (0 == (buff_size = WideCharToMultiByte(code_page, WC_COMPOSITECHECK | WC_SEPCHARS, lpSrcStr, cchSrc, NULL, 0, NULL, NULL))) return FALSE; /* allocate enough space for chars */ if (NULL == (buffer = (unsigned char *)_calloc_crt(sizeof(char), buff_size))) return FALSE; /* do the conversion */ if (0 == (retval = WideCharToMultiByte(code_page, WC_COMPOSITECHECK | WC_SEPCHARS, lpSrcStr, cchSrc, buffer, buff_size, NULL, NULL))) goto done; /* allocate enough space for result (+1 for sanity check) */ if (NULL == (pwCharInfo = (WORD *) _malloc_crt(sizeof(WORD) * (buff_size+1)))) goto done; /* do we use default lcid */ if (0 == lcid) lcid = __lc_handle[LC_CTYPE]; /* set to known value */ pwCharInfo[cchSrc-1] = pwCharInfo[cchSrc] = 0xFFFF; /* obtain result */ retbool = GetStringTypeA(lcid, dwInfoType, buffer, buff_size, pwCharInfo); /* * GetStringTypeA does not reveal how many WORDs have been * modifed - to be safe we use another buffer and then * verify that EXACTLY cchSrc WORDs were modified. Note that * not all multibyte LCID/codepage combos are guaranteed to work. */ if (pwCharInfo[cchSrc-1] == 0xFFFF || pwCharInfo[cchSrc] != 0xFFFF) { retbool = FALSE; goto done; } memmove(lpCharType, pwCharInfo, cchSrc * sizeof(WORD)); done: _free_crt(buffer); _free_crt(pwCharInfo); return retbool; } }
BOOL __cdecl __crtGetStringTypeA( DWORD dwInfoType, LPCSTR lpSrcStr, int cchSrc, LPWORD lpCharType, int code_page, int lcid ) { static int f_use = 0; /* * Look for unstubbed 'preferred' flavor. Otherwise use available flavor. * Must actually call the function to ensure it's not a stub. */ if (0 == f_use) { unsigned short dummy; if (0 != GetStringTypeA(0, CT_CTYPE1, "\0", 1, &dummy)) f_use = USE_A; else if (0 != GetStringTypeW(CT_CTYPE1, L"\0", 1, &dummy)) f_use = USE_W; else return FALSE; } /* Use "A" version */ if (USE_A == f_use) { if (0 == lcid) lcid = __lc_handle[LC_CTYPE]; return GetStringTypeA(lcid, dwInfoType, lpSrcStr, cchSrc, lpCharType); } /* Use "W" version */ if (USE_W == f_use) { int retval; int buff_size; BOOL retbool = FALSE; wchar_t *wbuffer = NULL; /* * Convert string and return the requested information. Note that * we are converting to a wide character string so there is not a * one-to-one correspondence between number of multibyte chars in the * input string and the number of wide chars in the buffer. However, * there had *better be* a one-to-one correspondence between the * number of multibyte characters and the number of WORDs in the * return buffer. */ /* * Use __lc_codepage for conversion if code_page not specified */ if (0 == code_page) code_page = __lc_codepage; /* find out how big a buffer we need */ if (0 == (buff_size = MultiByteToWideChar(code_page, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, lpSrcStr, cchSrc, NULL, 0))) goto done; /* allocate enough space for wide chars */ if (NULL == (wbuffer = (wchar_t *)_calloc_crt(sizeof(wchar_t), buff_size))) goto done; /* do the conversion */ if (0 == (retval = MultiByteToWideChar(code_page, MB_PRECOMPOSED, lpSrcStr, cchSrc, wbuffer, buff_size))) goto done; /* obtain result */ retbool = GetStringTypeW(dwInfoType, wbuffer, retval, lpCharType); done: _free_crt(wbuffer); return retbool; } }
int __cdecl _tchdir ( const _TSCHAR *path ) { _TSCHAR env_var[4]; _TSCHAR abspath[MAX_PATH+1]; _TSCHAR *apath=abspath; int memfree=0; int r; int retval = -1; _VALIDATE_CLEAR_OSSERR_RETURN((path != NULL), EINVAL, -1); if ( SetCurrentDirectory((LPTSTR)path) ) { /* * If the new current directory path is NOT a UNC path, we must * update the OS environment variable specifying the current * directory for what is now current drive. To do this, get the * full current directory, build the environment variable string * and call SetEnvironmentVariable(). We need to do this because * SetCurrentDirectory does not (i.e., does not update the * current-directory-on-drive environment variables) and other * functions (fullpath, spawn, etc) need them to be set. * * If associated with a 'drive', the current directory should * have the form of the example below: * * D:\nt\private\mytests * * so that the environment variable should be of the form: * * =D:=D:\nt\private\mytests * */ r = GetCurrentDirectory(MAX_PATH+1,(LPTSTR)apath); if (r > MAX_PATH) { if ((apath = (_TSCHAR *)_calloc_crt(r+1, sizeof(_TSCHAR))) == NULL) { r = 0; } else { memfree = 1; } if (r) r = GetCurrentDirectory(r+1,(LPTSTR)apath); } if (r) { /* * check if it is a UNC name, just return if is */ if ( ((apath[0] == _T('\\')) || (apath[0] == _T('/'))) && (apath[0] == apath[1]) ) retval = 0; else { env_var[0] = _T('='); env_var[1] = (_TSCHAR) _totupper((_TUCHAR)apath[0]); env_var[2] = _T(':'); env_var[3] = _T('\0'); if ( SetEnvironmentVariable(env_var, apath) ) retval = 0; } } } if( 0 != retval ) { /* error occured -- map error code */ _dosmaperr( GetLastError() ); } if (memfree) _free_crt(apath); return retval; }
FILE * __cdecl _tpopen ( const _TSCHAR *cmdstring, const _TSCHAR *type ) { int phdls[2]; /* I/O handles for pipe */ int ph_open[2]; /* flags, set if correspond phdls is open */ int i1; /* index into phdls[] */ int i2; /* index into phdls[] */ int tm = 0; /* flag indicating text or binary mode */ int stdhdl; /* either STDIN or STDOUT */ HANDLE newhnd; /* ...in calls to DuplicateHandle API */ FILE *pstream = NULL; /* stream to be associated with pipe */ HANDLE prochnd; /* handle for current process */ _TSCHAR *cmdexe; /* pathname for the command processor */ _TSCHAR *envbuf = NULL; /* buffer for the env variable */ intptr_t childhnd; /* handle for child process (cmd.exe) */ IDpair *locidpair; /* pointer to IDpair table entry */ _TSCHAR *buf = NULL, *pfin, *env; _TSCHAR *CommandLine; size_t CommandLineSize = 0; _TSCHAR _type[3] = {0, 0, 0}; /* Info for spawning the child. */ STARTUPINFO StartupInfo; /* Info for spawning a child */ BOOL childstatus = 0; PROCESS_INFORMATION ProcessInfo; /* child process information */ errno_t save_errno; int fh_lock_held = 0; int popen_lock_held = 0; /* first check for errors in the arguments */ _VALIDATE_RETURN((cmdstring != NULL), EINVAL,NULL); _VALIDATE_RETURN((type != NULL), EINVAL,NULL); while (*type == _T(' ')) { type++; } _VALIDATE_RETURN(((*type == _T('w')) || (*type == _T('r'))), EINVAL,NULL); _type[0] = *type; ++type; while (*type == _T(' ')) { ++type; } _VALIDATE_RETURN(((*type == 0) || (*type == _T('t')) || (*type == _T('b'))), EINVAL, NULL); _type[1] = *type; /* do the _pipe(). note that neither of the resulting handles will * be inheritable. */ if ( _type[1] == _T('t') ) tm = _O_TEXT; else if ( _type[1] == _T('b') ) tm = _O_BINARY; tm |= _O_NOINHERIT; if ( _pipe( phdls, PSIZE, tm ) == -1 ) goto error1; /* test _type[0] and set stdhdl, i1 and i2 accordingly. */ if ( _type[0] == _T('w') ) { stdhdl = STDIN; i1 = 0; i2 = 1; } else { stdhdl = STDOUT; i1 = 1; i2 = 0; } /* ASSERT LOCK FOR IDPAIRS HERE!!!! */ if ( !_mtinitlocknum( _POPEN_LOCK )) { _close( phdls[0] ); _close( phdls[1] ); return NULL; } _mlock( _POPEN_LOCK ); __try { /* set flags to indicate pipe handles are open. note, these are only * used for error recovery. */ ph_open[ 0 ] = ph_open[ 1 ] = 1; /* get the process handle, it will be needed in some API calls */ prochnd = GetCurrentProcess(); if ( !DuplicateHandle( prochnd, (HANDLE)_osfhnd( phdls[i1] ), prochnd, &newhnd, 0L, TRUE, /* inheritable */ DUPLICATE_SAME_ACCESS ) ) { goto error2; } (void)_close( phdls[i1] ); ph_open[ i1 ] = 0; /* associate a stream with phdls[i2]. note that if there are no * errors, pstream is the return value to the caller. */ if ( (pstream = _tfdopen( phdls[i2], _type )) == NULL ) goto error2; /* next, set locidpair to a free entry in the idpairs table. */ if ( (locidpair = idtab( NULL )) == NULL ) goto error3; /* Find what to use. command.com or cmd.exe */ if ( (_ERRCHECK_EINVAL(_tdupenv_s_crt(&envbuf, NULL, _T("COMSPEC"))) != 0) || (envbuf == NULL) ) { unsigned int osver = 0; _get_osver(&osver); cmdexe = ( osver & 0x8000 ) ? _T("command.com") : _T("cmd.exe"); } else { cmdexe = envbuf; } /* * Initialise the variable for passing to CreateProcess */ memset(&StartupInfo, 0, sizeof(StartupInfo)); StartupInfo.cb = sizeof(StartupInfo); /* Used by os for duplicating the Handles. */ StartupInfo.dwFlags = STARTF_USESTDHANDLES; StartupInfo.hStdInput = stdhdl == STDIN ? (HANDLE) newhnd : (HANDLE) _osfhnd(0); StartupInfo.hStdOutput = stdhdl == STDOUT ? (HANDLE) newhnd : (HANDLE) _osfhnd(1); StartupInfo.hStdError = (HANDLE) _osfhnd(2); CommandLineSize = _tcslen(cmdexe) + _tcslen(_T(" /c ")) + (_tcslen(cmdstring)) +1; if ((CommandLine = _calloc_crt( CommandLineSize, sizeof(_TSCHAR))) == NULL) goto error3; _ERRCHECK(_tcscpy_s(CommandLine, CommandLineSize, cmdexe)); _ERRCHECK(_tcscat_s(CommandLine, CommandLineSize, _T(" /c "))); _ERRCHECK(_tcscat_s(CommandLine, CommandLineSize, cmdstring)); /* Check if cmdexe can be accessed. If yes CreateProcess else try * searching path. */ save_errno = errno; if (_taccess_s(cmdexe, 0) == 0) { childstatus = CreateProcess( (LPTSTR) cmdexe, (LPTSTR) CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &StartupInfo, &ProcessInfo ); } else { TCHAR* envPath = NULL; size_t envPathSize = 0; if ((buf = _calloc_crt(_MAX_PATH, sizeof(_TSCHAR))) == NULL) { _free_crt(buf); _free_crt(CommandLine); _free_crt(envbuf); cmdexe = NULL; errno = save_errno; goto error3; } if (_ERRCHECK_EINVAL(_tdupenv_s_crt(&envPath, NULL, _T("PATH"))) != 0) { _free_crt(envPath); _free_crt(buf); _free_crt(CommandLine); _free_crt(envbuf); cmdexe = NULL; errno = save_errno; goto error3; } env = envPath; #ifdef WPRFLAG while ( (env = _wgetpath(env, buf, _MAX_PATH -1)) && (*buf) ) { #else /* WPRFLAG */ while ( (env = _getpath(env, buf, _MAX_PATH -1)) && (*buf) ) { #endif /* WPRFLAG */ pfin = buf + _tcslen(buf) -1; #ifdef _MBCS if (*pfin == SLASHCHAR) { if (pfin != _mbsrchr(buf, SLASHCHAR)) _ERRCHECK(strcat_s(buf, _MAX_PATH, SLASH)); } else if (*pfin != XSLASHCHAR) _ERRCHECK(strcat_s(buf, _MAX_PATH, SLASH)); #else /* _MBCS */ if (*pfin != SLASHCHAR && *pfin != XSLASHCHAR) _ERRCHECK(_tcscat_s(buf, _MAX_PATH, SLASH)); #endif /* _MBCS */ /* check that the final path will be of legal size. if so, * build it. otherwise, return to the caller (return value * and errno rename set from initial call to _spawnve()). */ if ( (_tcslen(buf) + _tcslen(cmdexe)) < _MAX_PATH ) _ERRCHECK(_tcscat_s(buf, _MAX_PATH, cmdexe)); else break; /* Check if buf can be accessed. If yes CreateProcess else try * again. */ if (_taccess_s(buf, 0) == 0) { childstatus = CreateProcess( (LPTSTR) buf, CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &StartupInfo, &ProcessInfo ); break; } } _free_crt(envPath); _free_crt(buf); } _free_crt(CommandLine); _free_crt(envbuf); cmdexe = NULL; CloseHandle((HANDLE)newhnd); CloseHandle((HANDLE)ProcessInfo.hThread); errno = save_errno; /* check if the CreateProcess was sucessful. */ if ( childstatus) childhnd = (intptr_t)ProcessInfo.hProcess; else goto error4; locidpair->prochnd = childhnd; locidpair->stream = pstream; /* success, return the stream to the caller */ goto done; /** * error handling code. all detected errors end up here, entering * via a goto one of the labels. note that the logic is currently * a straight fall-thru scheme (e.g., if entered at error4, the * code for error4, error3,...,error1 is all executed). **********************************************************************/ error4: /* make sure locidpair is reusable */ locidpair->stream = NULL; error3: /* close pstream (also, clear ph_open[i2] since the stream * close will also close the pipe handle) */ (void)fclose( pstream ); ph_open[ i2 ] = 0; pstream = NULL; error2: /* close handles on pipe (if they are still open) */ if ( ph_open[i1] ) _close( phdls[i1] ); if ( ph_open[i2] ) _close( phdls[i2] ); done: ;} __finally { _munlock(_POPEN_LOCK); } error1: return pstream; } #ifndef _UNICODE /*** *int _pclose(pstream) - wait on a child command and close the stream on the * associated pipe * *Purpose: * Closes pstream then waits on the associated child command. The * argument, pstream, must be the return value from a previous call to * _popen. _pclose first looks up the process handle of child command * started by that _popen and does a cwait on it. Then, it closes pstream * and returns the exit status of the child command to the caller. * *Entry: * FILE *pstream - file stream returned by a previous call to _popen * *Exit: * If successful, _pclose returns the exit status of the child command. * The format of the return value is that same as for cwait, except that * the low order and high order bytes are swapped. * * If an error occurs, -1 is returned. * *Exceptions: * *******************************************************************************/ int __cdecl _pclose ( FILE *pstream ) { IDpair *locidpair; /* pointer to entry in idpairs table */ int termstat; /* termination status word */ int retval = -1; /* return value (to caller) */ errno_t save_errno; _VALIDATE_RETURN((pstream != NULL), EINVAL, -1); if (!_mtinitlocknum(_POPEN_LOCK)) return -1; _mlock(_POPEN_LOCK); __try { if ((locidpair = idtab(pstream)) == NULL) { /* invalid pstream, exit with retval == -1 */ errno = EBADF; goto done; } /* close pstream */ (void)fclose(pstream); /* wait on the child (copy of the command processor) and all of its * children. */ save_errno = errno; errno = 0; if ( (_cwait(&termstat, locidpair->prochnd, _WAIT_GRANDCHILD) != -1) || (errno == EINTR) ) retval = termstat; errno = save_errno; /* Mark the IDpairtable entry as free (note: prochnd was closed by the * preceding call to _cwait). */ locidpair->stream = NULL; locidpair->prochnd = 0; /* only return path! */ done: ; } __finally { _munlock(_POPEN_LOCK); } return(retval); }
int __cdecl __init_monetary ( pthreadlocinfo ploci ) { struct lconv *lc; int ret; LCID ctryid; int *lc_refcount; int *lconv_mon_refcount = NULL; _locale_tstruct locinfo; locinfo.locinfo = ploci; locinfo.mbcinfo = 0; if ( (ploci->lc_handle[LC_MONETARY] != _CLOCALEHANDLE) || (ploci->lc_handle[LC_NUMERIC] != _CLOCALEHANDLE) ) { /* * Allocate structure filled with NULL pointers */ if ( (lc = (struct lconv *) _calloc_crt(1, sizeof(struct lconv))) == NULL ) return 1; /* * Allocate a new reference counter for the lconv structure */ if ( (lc_refcount = _malloc_crt(sizeof(int))) == NULL ) { _free_crt(lc); return 1; } *lc_refcount = 0; if ( ploci->lc_handle[LC_MONETARY] != _CLOCALEHANDLE ) { /* * Allocate a new reference counter for the numeric info */ if ( (lconv_mon_refcount = _malloc_crt(sizeof(int))) == NULL ) { _free_crt(lc); _free_crt(lc_refcount); return 1; } *lconv_mon_refcount = 0; /* * Currency is country--not language--dependent. NT * work-around. */ ctryid = MAKELCID(ploci->lc_id[LC_MONETARY].wCountry, SORT_DEFAULT); ret = 0; ret |= __getlocaleinfo(&locinfo, LC_STR_TYPE, ctryid, LOCALE_SINTLSYMBOL, (void *)&lc->int_curr_symbol ); ret |= __getlocaleinfo(&locinfo, LC_STR_TYPE, ctryid, LOCALE_SCURRENCY, (void *)&lc->currency_symbol ); ret |= __getlocaleinfo(&locinfo, LC_STR_TYPE, ctryid, LOCALE_SMONDECIMALSEP, (void *)&lc->mon_decimal_point ); ret |= __getlocaleinfo(&locinfo, LC_STR_TYPE, ctryid, LOCALE_SMONTHOUSANDSEP, (void *)&lc->mon_thousands_sep ); ret |= __getlocaleinfo(&locinfo, LC_STR_TYPE, ctryid, LOCALE_SMONGROUPING, (void *)&lc->mon_grouping ); ret |= __getlocaleinfo(&locinfo, LC_STR_TYPE, ctryid, LOCALE_SPOSITIVESIGN, (void *)&lc->positive_sign); ret |= __getlocaleinfo(&locinfo, LC_STR_TYPE, ctryid, LOCALE_SNEGATIVESIGN, (void *)&lc->negative_sign); ret |= __getlocaleinfo(&locinfo, LC_INT_TYPE, ctryid, LOCALE_IINTLCURRDIGITS, (void *)&lc->int_frac_digits); ret |= __getlocaleinfo(&locinfo, LC_INT_TYPE, ctryid, LOCALE_ICURRDIGITS, (void *)&lc->frac_digits); ret |= __getlocaleinfo(&locinfo, LC_INT_TYPE, ctryid, LOCALE_IPOSSYMPRECEDES, (void *)&lc->p_cs_precedes); ret |= __getlocaleinfo(&locinfo, LC_INT_TYPE, ctryid, LOCALE_IPOSSEPBYSPACE, (void *)&lc->p_sep_by_space); ret |= __getlocaleinfo(&locinfo, LC_INT_TYPE, ctryid, LOCALE_INEGSYMPRECEDES, (void *)&lc->n_cs_precedes); ret |= __getlocaleinfo(&locinfo, LC_INT_TYPE, ctryid, LOCALE_INEGSEPBYSPACE, (void *)&lc->n_sep_by_space); ret |= __getlocaleinfo(&locinfo, LC_INT_TYPE, ctryid, LOCALE_IPOSSIGNPOSN, (void *)&lc->p_sign_posn); ret |= __getlocaleinfo(&locinfo, LC_INT_TYPE, ctryid, LOCALE_INEGSIGNPOSN, (void *)&lc->n_sign_posn); if ( ret != 0 ) { __free_lconv_mon(lc); _free_crt(lc); _free_crt(lc_refcount); _free_crt(lconv_mon_refcount); return 1; } fix_grouping(lc->mon_grouping); } else { /* * C locale for monetary category (the numeric category fields, * which are NOT of the C locale, get fixed up below). Note * that __lconv_c is copied, rather than directly assigning * the fields of lc because of the uncertainty of the values of * the int_frac_digits,..., n_sign_posn fields (SCHAR_MAX or * UCHAR_MAX, depending on whether or a compliand was built * with -J. */ *lc = __lconv_c; } /* * Copy the numeric locale fields from the old struct */ lc->decimal_point = ploci->lconv->decimal_point; lc->thousands_sep = ploci->lconv->thousands_sep; lc->grouping = ploci->lconv->grouping; *lc_refcount = 1; if (lconv_mon_refcount) *lconv_mon_refcount = 1; } else { /* * C locale for BOTH monetary and numeric categories. */ lconv_mon_refcount = NULL; lc_refcount = NULL; lc = &__lconv_c; /* point to new one */ } if ( (ploci->lconv_mon_refcount != NULL) && (InterlockedDecrement(ploci->lconv_mon_refcount) == 0)) { _ASSERTE(ploci->lconv_mon_refcount > 0); } if ( (ploci->lconv_intl_refcount != NULL) && (InterlockedDecrement(ploci->lconv_intl_refcount) == 0)) { _free_crt(ploci->lconv); _free_crt(ploci->lconv_intl_refcount); } ploci->lconv_mon_refcount = lconv_mon_refcount; ploci->lconv_intl_refcount = lc_refcount; ploci->lconv = lc; /* point to new one */ return 0; }
/*** *int _cenvarg(argv, envp, argblk, envblk, name) - set up cmd line/environ * *Purpose: * Set up the block forms of the environment and the command line. * If "envp" is null, "_environ" is used instead. * *Entry: * _TSCHAR **argv - argument vector * _TSCHAR **envp - environment vector * _TSCHAR **argblk - pointer to pointer set to malloc'ed space for args * _TSCHAR **envblk - pointer to pointer set to malloc'ed space for env * _TSCHAR *name - name of program being invoked * *Exit: * returns 0 if ok, -1 if fails * stores through argblk and envblk * (calls malloc) * *Exceptions: * *******************************************************************************/ #ifdef WPRFLAG int __cdecl _wcenvarg ( #else /* WPRFLAG */ int __cdecl _cenvarg ( #endif /* WPRFLAG */ const _TSCHAR * const *argv, const _TSCHAR * const *envp, _TSCHAR **argblk, _TSCHAR **envblk, const _TSCHAR *name ) { REG1 const _TSCHAR * const *vp; REG2 unsigned tmp; REG3 _TSCHAR *cptr; unsigned arg_len; unsigned env_len; int cfi_len; /* counts the number of file handles in CFI */ int retval = 0; /* * Null environment pointer "envp" means use global variable, * "_environ" */ int cwd_start; int cwd_end; /* length of "cwd" strings in environment */ _TSCHAR envpfx[] = _T("SystemRoot"); _TSCHAR *envbuf = NULL; int envsize = 0; int defined = 0; /* * Allocate space for command line string * tmp counts the number of bytes in the command line string * including spaces between arguments * An empty string is special -- 2 bytes */ for (vp = argv, tmp = 2; *vp; tmp += (unsigned int)_tcslen(*vp++) + 1) ; arg_len = tmp; /* * Allocate space for the command line plus 2 null bytes */ if ( (*argblk = _calloc_crt(tmp, sizeof(_TSCHAR))) == NULL) { *envblk = NULL; errno = ENOMEM; _doserrno = E_nomem; return(-1); } if (_ERRCHECK_EINVAL(_tdupenv_s_crt(&envbuf, NULL, envpfx)) != 0) { retval = -1; goto error; } envsize = (int)_tcslen(envpfx) + 2; if (envbuf != NULL) { envsize += (int)_tcslen(envbuf); } /* * Allocate space for environment strings * tmp counts the number of bytes in the environment strings * including nulls between strings * Also add "_C_FILE_INFO=" string */ if (envp) for (vp = envp, tmp = 2; *vp; tmp += (unsigned int)_tcslen(*vp++) + 1) ; /* * The _osfile and _osfhnd arrays are passed as binary data in * dospawn.c */ cfi_len = 0; /* no _C_FILE_INFO */ if (!envp) *envblk = NULL; else { /* * Now that we've decided to pass our own environment block, * compute the size of the "current directory" strings to * propagate to the new environment. */ #ifdef WPRFLAG /* * Make sure wide environment exists. */ if (!_wenvptr) { if ((_wenvptr = (wchar_t *)__crtGetEnvironmentStringsW()) == NULL) { retval = -1; goto error; } } #else /* WPRFLAG */ if (!_aenvptr) { if ((_aenvptr = (char *)__crtGetEnvironmentStringsA()) == NULL) { retval = -1; goto error; } } #endif /* WPRFLAG */ /* * search for the first one */ for (cwd_start = 0; _tenvptr[cwd_start] != _T('\0') && _tenvptr[cwd_start] != _T('='); cwd_start += (int)_tcslen(&_tenvptr[cwd_start]) + 1) { } /* find the total size of all contiguous ones */ cwd_end = cwd_start; while (_tenvptr[cwd_end+0] == _T('=') && _tenvptr[cwd_end+1] != _T('\0') && _tenvptr[cwd_end+2] == _T(':') && _tenvptr[cwd_end+3] == _T('=')) { cwd_end += 4 + (int)_tcslen(&_tenvptr[cwd_end+4]) + 1; } tmp += cwd_end - cwd_start; /* * Allocate space for the environment strings plus extra null byte */ env_len = tmp; /* * Check if SystemRoot is already defined in environment provided */ for (vp = envp; *vp; vp++) { if (_tcsncicmp(*vp, envpfx, _tcslen(envpfx)) == 0) { defined = 1; break; } } if (!defined) tmp += envsize; if( !(*envblk = _calloc_crt(tmp, sizeof(_TSCHAR))) ) { _free_crt(*argblk); *argblk = NULL; errno = ENOMEM; _doserrno = E_nomem; retval = -1; goto done; } } /* * Build the command line by concatenating the argument strings * with spaces between, and two null bytes at the end. * NOTE: The argv[0] argument is followed by a null. */ cptr = *argblk; vp = argv; if (!*vp) /* Empty argument list ? */ ++cptr; /* just two null bytes */ else { /* argv[0] must be followed by a null */ _ERRCHECK(_tcscpy_s(cptr, arg_len - (cptr - *argblk), *vp)); cptr += (int)_tcslen(*vp++) + 1; } while( *vp ) { _ERRCHECK(_tcscpy_s(cptr, arg_len - (cptr - *argblk), *vp)); cptr += (int)_tcslen(*vp++); *cptr++ = ' '; } *cptr = cptr[ -1 ] = _T('\0'); /* remove extra blank, add double null */ /* * Build the environment block by concatenating the environment * strings with nulls between and two null bytes at the end */ cptr = *envblk; if (envp != NULL) { /* * Copy the "cwd" strings to the new environment. */ memcpy(cptr, &_tenvptr[cwd_start], (cwd_end - cwd_start) * sizeof(_TSCHAR)); cptr += cwd_end - cwd_start; /* * Copy the environment strings from "envp". */ vp = envp; while( *vp ) { _ERRCHECK(_tcscpy_s(cptr, env_len - (cptr - *envblk), *vp)); cptr += 1 + (int)_tcslen(*vp++); } if (!defined) { /* * Copy SystemRoot to the new environment. */ _ERRCHECK(_tcscpy_s(cptr, envsize, envpfx)); _ERRCHECK(_tcscat_s(cptr, envsize, _T("="))); if (envbuf != NULL) { _ERRCHECK(_tcscat_s(cptr, envsize, envbuf)); } cptr += envsize; } } if (cptr != NULL) { if (cptr == *envblk) { /* * Empty environment block ... this requires two * nulls. */ *cptr++ = _T('\0'); } /* * Extra null terminates the segment */ *cptr = _T('\0'); } goto done; error: _free_crt(*argblk); *argblk = NULL; *envblk = NULL; done: #ifdef WPRFLAG if (_wenvptr) _free_crt(_wenvptr); _wenvptr = NULL; #else /* WPRFLAG */ if (_aenvptr) _free_crt(_aenvptr); _aenvptr = NULL; #endif /* WPRFLAG */ if (envbuf) _free_crt(envbuf); return retval; }
BOOL WINAPI _CRT_INIT( HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved ) { unsigned int osplatform = 0; unsigned int winver = 0; unsigned int winmajor = 0; unsigned int winminor = 0; unsigned int osver = 0; /* * Start-up code only gets executed when the process is initialized */ if (dwReason == DLL_PROCESS_ATTACH) { /* * Dynamically allocate the OSVERSIONINFOA buffer, so we avoid * triggering the /GS buffer overrun detection. That can't be * used here, since the guard cookie isn't available until we * initialize it from here! */ OSVERSIONINFOA* posvi = (OSVERSIONINFOA*)HeapAlloc(GetProcessHeap(), 0, sizeof(OSVERSIONINFOA)); if (!posvi) { return FALSE; } /* * Get the full Win32 version */ posvi->dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); if (!GetVersionExA(posvi)) { HeapFree(GetProcessHeap(), 0, posvi); return FALSE; } osplatform = posvi->dwPlatformId; winmajor = posvi->dwMajorVersion; winminor = posvi->dwMinorVersion; /* * The somewhat bizarre calculations of _osver and _winver are * required for backward compatibility (used to use GetVersion) */ osver = (posvi->dwBuildNumber) & 0x07fff; HeapFree(GetProcessHeap(), 0, posvi); if (osplatform != VER_PLATFORM_WIN32_NT) { osver |= 0x08000; } winver = (winmajor << 8) + winminor; _set_osplatform(osplatform); _set_winver(winver); _set_winmajor(winmajor); _set_winminor(winminor); _set_osver(osver); if (!_heap_init(1)) { /* initialize heap */ return FALSE; /* fail to load DLL */ } if (!_mtinit()) { /* initialize multi-thread */ _heap_term(); /* heap is now invalid! */ return FALSE; /* fail to load DLL */ } /* * Initialize the Runtime Checks stuff */ #ifdef _RTC _RTC_Initialize(); #endif /* _RTC */ _acmdln = (char*)GetCommandLineA(); _aenvptr = (char*)__crtGetEnvironmentStringsA(); if (_ioinit() < 0) { /* initialize lowio */ _mtterm(); /* free TLS index, call _mtdeletelocks() */ _heap_term(); /* heap is now invalid! */ return FALSE; /* fail to load DLL */ } if (_setargv() < 0 || /* get cmd line info */ _setenvp() < 0 || /* get environ info */ _cinit(FALSE) != 0) { /* do C data initialize, but don't init floating point */ _ioterm(); /* shut down lowio */ _mtterm(); /* free TLS index, call _mtdeletelocks() */ _heap_term(); /* heap is now invalid! */ return FALSE; /* fail to load DLL */ } /* Enable buffer count checking if linking against static lib */ _CrtSetCheckCount(TRUE); /* * 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 */ /* * 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. */ #ifndef _DEBUG if (lpreserved == NULL) { #endif /* _DEBUG */ /* * The process is NOT terminating so we must clean up... */ /* Shut down lowio */ _ioterm(); _mtterm(); /* This should be the last thing the C run-time does */ _heap_term(); /* heap is now invalid! */ #ifndef _DEBUG } #endif /* _DEBUG */ } else /* no prior process attach, just return */ { return FALSE; } } else if (dwReason == DLL_THREAD_ATTACH) { _ptiddata ptd; /* Initialize FlsGetValue function pointer */ __set_flsgetvalue(); if (((ptd = _calloc_crt(1, sizeof(struct _tiddata))) != NULL)) { if (FLS_SETVALUE(__flsindex, (LPVOID)ptd)) { /* * Initialize of per-thread data */ _initptd(ptd, NULL); ptd->_tid = GetCurrentThreadId(); ptd->_thandle = (uintptr_t)(-1); } else { _free_crt(ptd); return FALSE; } } else { return FALSE; } } else if (dwReason == DLL_THREAD_DETACH) { _freeptd(NULL); /* free up per-thread CRT data */ } return TRUE ; }
void * __fastcall _calloc_crt_fastcall(size_t count, size_t size) { return _calloc_crt(count, size); }