/*** *errno_t _strerror_s(buffer, sizeInTChars, 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: * TCHAR * buffer - Destination buffer. * size_t sizeInTChars - Size of the destination buffer. * TCHAR * message - user's message to prefix system error message * *Exit: * The error code. * *Exceptions: * Input parameters are validated. Refer to the validation section of the function. * *******************************************************************************/ #define _MIN_MSG_LENGTH 5 #ifdef _UNICODE errno_t __cdecl __wcserror_s( #else /* _UNICODE */ errno_t __cdecl _strerror_s( #endif /* _UNICODE */ TCHAR* buffer, size_t sizeInTChars, const _TCHAR *message ) { errno_t e = 0; /* validation section */ _VALIDATE_RETURN_ERRCODE(buffer != NULL, EINVAL); _VALIDATE_RETURN_ERRCODE(sizeInTChars > 0, EINVAL); buffer[0] = '\0'; if (message && *message && _tcslen(message) < (sizeInTChars - 2 - _MIN_MSG_LENGTH)) { _ERRCHECK(_tcscpy_s(buffer, sizeInTChars, message)); _ERRCHECK(_tcscat_s(buffer, sizeInTChars, _T(": "))); } /* append the error message at the end of the buffer */ return _tcserror_s(buffer + _tcslen(buffer), sizeInTChars - _tcslen(buffer), errno); }
/*** *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); }
static Character* __cdecl common_tempnam( Character const* const alternative, Character const* const prefix, int const block_use, char const* const file_name, int const line_number ) throw() { // These are referenced only in the Debug CRT build UNREFERENCED_PARAMETER(block_use); UNREFERENCED_PARAMETER(file_name); UNREFERENCED_PARAMETER(line_number); typedef __acrt_stdio_char_traits<Character> stdio_traits; Character const* directory = nullptr; __crt_unique_heap_ptr<Character const> const directory_cleanup(get_directory(alternative, &directory)); unsigned const prefix_length = prefix != nullptr ? static_cast<unsigned>(stdio_traits::tcslen(prefix)) : 0; // The 12 allows for a backslash, a ten character temporary string, and a // null terminator. unsigned const buffer_size = static_cast<unsigned>(stdio_traits::tcslen(directory)) + prefix_length + 12; __crt_unique_heap_ptr<Character, __crt_public_free_policy> result( static_cast<Character*>(_calloc_dbg( buffer_size, sizeof(Character), block_use, file_name, line_number))); if (!result) return nullptr; *result.get() = 0; _ERRCHECK(stdio_traits::tcscat_s(result.get(), buffer_size, directory)); if (__crt_stdio_path_requires_backslash(directory)) { static Character const backslash[] = { '\\', '\0' }; _ERRCHECK(stdio_traits::tcscat_s(result.get(), buffer_size, backslash)); } if (prefix != nullptr) { _ERRCHECK(stdio_traits::tcscat_s(result.get(), buffer_size, prefix)); } Character* const ptr = result.get() + stdio_traits::tcslen(result.get()); size_t const ptr_size = buffer_size - (ptr - result.get()); if (!compute_name(result.get(), ptr, ptr_size, prefix_length)) return nullptr; return result.detach(); }
static bool __cdecl initialize_tmpfile_buffer_nolock(buffer_id const buffer_id) throw() { typedef __acrt_stdio_char_traits<Character> stdio_traits; Character* const buffer = get_tmpfile_buffer_nolock<Character>(buffer_id); size_t const buffer_count = L_tmpnam; if (!buffer) { return false; } // The temporary path must be short enough so that we can append a file name // of the form [buffer id][process id].[unique id], which is at most 21 // characters in length (plus we must leave room for the null terminator). // 1 Buffer Id ("s", "t", or "u") // 7 Base-36 Process Id (maximum: "1z141z3") // 13 Base-36 Unique File Id (maximum: "3w5e11264sgsf") DWORD const max_supported_temp_path_length = buffer_count - 22; // Generate the path prefix; make sure it ends with a slash or backslash: // CRT_REFACTOR TODO We need to use the WinRT temp path logic here. DWORD const temp_path_length = stdio_traits::get_temp_path(static_cast<DWORD>(buffer_count), buffer); if (temp_path_length == 0 || temp_path_length > max_supported_temp_path_length) { buffer[0] = '\0'; return false; } Character* tail = buffer + temp_path_length; auto tail_count = [&]() { return buffer_count - (tail - buffer); }; // Append the buffer identifier part of the file name: switch (buffer_id) { case buffer_id::tmpnam: *tail++ = sizeof(Character) == 1 ? 's' : 'v'; break; case buffer_id::tmpfile: *tail++ = sizeof(Character) == 1 ? 't' : 'w'; break; case buffer_id::tmpnam_s: *tail++ = sizeof(Character) == 1 ? 'u' : 'x'; break; } // Append the process identifier part of the file name: _ERRCHECK(stdio_traits::ulltot_s(GetCurrentProcessId(), tail, tail_count(), 36)); tail += stdio_traits::tcslen(tail); // Append the dot part of the file name and the initial unique id: *tail++ = '.'; *tail++ = '0'; *tail++ = '\0'; return true; }
wchar_t * __cdecl _wcsdup ( const wchar_t * string ) #endif /* _DEBUG */ { wchar_t *memory; size_t size = 0; if (!string) return(NULL); size = wcslen(string) + 1; #ifdef _DEBUG if (memory = (wchar_t *) _calloc_dbg(size, sizeof(wchar_t), nBlockUse, szFileName, nLine)) #else /* _DEBUG */ if (memory = (wchar_t *) calloc(size, sizeof(wchar_t))) #endif /* _DEBUG */ { _ERRCHECK(wcscpy_s(memory, size, string)); return memory; } return(NULL); }
/*** *errno_t strerror_s(buffer, sizeInTChars, errnum) - Map error number to error message string. * *Purpose: * The strerror_s runtime takes an error number for input and * copies the corresponding error message string in the destination * buffer. If the buffer is too small, the message is truncated. * *Entry: * TCHAR * buffer - Destination buffer. * size_t sizeInTChars - Size of the destination buffer. * int errnum - Integer error number (corresponding to an errno value). * *Exit: * The error code. * *Exceptions: * Input parameters are validated. Refer to the validation section of the function. * *******************************************************************************/ #ifdef _UNICODE errno_t __cdecl _wcserror_s( #else /* _UNICODE */ errno_t __cdecl strerror_s( #endif /* _UNICODE */ TCHAR* buffer, size_t sizeInTChars, int errnum ) { errno_t e = 0; /* validation section */ _VALIDATE_RETURN_ERRCODE(buffer != NULL, EINVAL); _VALIDATE_RETURN_ERRCODE(sizeInTChars > 0, EINVAL); /* we use mbstowcs_s or strncpy_s because we want to truncate the error string * if the destination is not big enough */ #ifdef _UNICODE e = _ERRCHECK_EINVAL_ERANGE(mbstowcs_s(NULL, buffer, sizeInTChars, _get_sys_err_msg(errnum), _TRUNCATE)); /* ignore the truncate information */ if (e == STRUNCATE) { e = 0; } #else /* _UNICODE */ _ERRCHECK(strncpy_s(buffer, sizeInTChars, _get_sys_err_msg(errnum), sizeInTChars - 1)); #endif /* _UNICODE */ return e; }
char * __cdecl _strdup ( const char * string ) #endif /* _DEBUG */ { char *memory; size_t size = 0; if (!string) return(NULL); size = strlen(string) + 1; #ifdef _DEBUG if (memory = _malloc_dbg(size, nBlockUse, szFileName, nLine)) #else /* _DEBUG */ if (memory = malloc(size)) #endif /* _DEBUG */ { _ERRCHECK(strcpy_s(memory, size, string)); return memory; } return(NULL); }
static bool __cdecl compute_name( Character const* const path_buffer, Character* const suffix_pointer, size_t const suffix_count, size_t const prefix_length ) throw() { typedef __acrt_stdio_char_traits<Character> stdio_traits; // Re-initialize _tempoff if necessary. If we don't re-init _tempoff, we // can get into an infinate loop (e.g., (a) _tempoff is a big number on // entry, (b) prefix is a long string (e.g., 8 chars) and all tempfiles // with that prefix exist, (c) _tempoff will never equal first and we'll // loop forever). // [NOTE: To avoid a conflict that causes the same bug as that discussed // above, _tempnam() uses _tempoff; tmpnam() uses _tmpoff] bool return_value = false; __acrt_lock(__acrt_tempnam_lock); __try { if (_old_pfxlen < prefix_length) _tempoff = 1; _old_pfxlen = static_cast<unsigned int>(prefix_length); unsigned const first = _tempoff; errno_t const saved_errno = errno; do { ++_tempoff; if (_tempoff - first > _TMP_MAX_S) { errno = saved_errno; __leave; } // The maximum length string returned by the conversion is ten // characters, assuming a 32-bit unsigned integer, so there is // sufficient room in the result buffer for it. _ERRCHECK(stdio_traits::ultot_s(_tempoff, suffix_pointer, suffix_count, 10)); errno = 0; } while (stdio_traits::taccess_s(path_buffer, 0) == 0 || errno == EACCES); errno = saved_errno; return_value = true; } __finally { __acrt_unlock(__acrt_tempnam_lock); } return return_value; }
_CRTIMP errno_t __cdecl _ftime64_s ( struct __timeb64 *tp ) { FT nt_time; __time64_t t; TIME_ZONE_INFORMATION tzinfo; DWORD tzstate; long timezone = 0; _VALIDATE_RETURN_ERRCODE( ( tp != NULL ), EINVAL ) __tzset(); _ERRCHECK(_get_timezone(&timezone)); tp->timezone = (short)(timezone / 60); GetSystemTimeAsFileTime( &(nt_time.ft_struct) ); /* * Obtain the current DST status. Note the status is cached and only * updated once per minute, if necessary. */ if ( (t = (__time64_t)(nt_time.ft_scalar / 600000000i64)) != elapsed_minutes_cache ) { if ( (tzstate = GetTimeZoneInformation( &tzinfo )) != 0xFFFFFFFF ) { /* * Must be very careful in determining whether or not DST is * really in effect. */ if ( (tzstate == TIME_ZONE_ID_DAYLIGHT) && (tzinfo.DaylightDate.wMonth != 0) && (tzinfo.DaylightBias != 0) ) dstflag_cache = DAYLIGHT_TIME; else /* * When in doubt, assume standard time */ dstflag_cache = STANDARD_TIME; } else dstflag_cache = UNKNOWN_TIME; elapsed_minutes_cache = t; } tp->dstflag = (short)dstflag_cache; tp->millitm = (unsigned short)((nt_time.ft_scalar / 10000i64) % 1000i64); tp->time = (__time64_t)((nt_time.ft_scalar - EPOCH_BIAS) / 10000000i64); return 0; }
intptr_t __cdecl _tfindfirst64i32( const _TSCHAR * szWild, struct _tfinddata64i32_t * pfd ) #endif /* _USE_INT64 */ { WIN32_FIND_DATA wfd; HANDLE hFile; DWORD err; _VALIDATE_RETURN( (pfd != NULL), EINVAL, -1); /* We assert to make sure the underlying Win32 struct WIN32_FIND_DATA's cFileName member doesn't have an array size greater than ours */ _VALIDATE_RETURN( (sizeof(pfd->name) <= sizeof(wfd.cFileName)), ENOMEM, -1); _VALIDATE_RETURN( (szWild != NULL), EINVAL, -1); if ((hFile = FindFirstFile(szWild, &wfd)) == INVALID_HANDLE_VALUE) { err = GetLastError(); switch (err) { case ERROR_NO_MORE_FILES: case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: errno = ENOENT; break; case ERROR_NOT_ENOUGH_MEMORY: errno = ENOMEM; break; default: errno = EINVAL; break; } return (-1); } pfd->attrib = (wfd.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) ? 0 : wfd.dwFileAttributes; pfd->time_create = __time64_t_from_ft(&wfd.ftCreationTime); pfd->time_access = __time64_t_from_ft(&wfd.ftLastAccessTime); pfd->time_write = __time64_t_from_ft(&wfd.ftLastWriteTime); #if _USE_INT64 pfd->size = ((__int64)(wfd.nFileSizeHigh)) * (0x100000000i64) + (__int64)(wfd.nFileSizeLow); #else /* _USE_INT64 */ pfd->size = wfd.nFileSizeLow; #endif /* _USE_INT64 */ _ERRCHECK(_tcscpy_s(pfd->name, _countof(pfd->name), wfd.cFileName)); return ((intptr_t)hFile); }
/*** *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; }
int __cdecl _tfindnext64i32(intptr_t hFile, struct _tfinddata64i32_t * pfd) #endif /* _USE_INT64 */ { WIN32_FIND_DATA wfd; DWORD err; _VALIDATE_RETURN( ((HANDLE)hFile != INVALID_HANDLE_VALUE), EINVAL, -1); _VALIDATE_RETURN( (pfd != NULL), EINVAL, -1); _VALIDATE_RETURN( (sizeof(pfd->name) <= sizeof(wfd.cFileName)), ENOMEM, -1); if (!FindNextFile((HANDLE)hFile, &wfd)) { err = GetLastError(); switch (err) { case ERROR_NO_MORE_FILES: case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: errno = ENOENT; break; case ERROR_NOT_ENOUGH_MEMORY: errno = ENOMEM; break; default: errno = EINVAL; break; } return (-1); } pfd->attrib = (wfd.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) ? 0 : wfd.dwFileAttributes; pfd->time_create = __time64_t_from_ft(&wfd.ftCreationTime); pfd->time_access = __time64_t_from_ft(&wfd.ftLastAccessTime); pfd->time_write = __time64_t_from_ft(&wfd.ftLastWriteTime); #if _USE_INT64 pfd->size = ((__int64)(wfd.nFileSizeHigh)) * (0x100000000i64) + (__int64)(wfd.nFileSizeLow); #else /* _USE_INT64 */ pfd->size = wfd.nFileSizeLow; #endif /* _USE_INT64 */ _ERRCHECK(_tcscpy_s(pfd->name, _countof(pfd->name), wfd.cFileName)); return (0); }
__RELIABILITY_CONTRACT const char * type_info::_Name_base(const type_info *_This,__type_info_node* __ptype_info_node) { void *pTmpUndName; size_t len; if (_This->_m_data == NULL) { if ((pTmpUndName = __unDNameHelper(NULL, (_This->_m_d_name)+1, 0, 0)) == NULL) return NULL; /* * Pad all the trailing spaces with null. Note that len-- > 0 is used * at left side which depends on operator associativity. Also note * that len will be used later so don't trash. */ for (len=strlen((char *)pTmpUndName); len-- > 0 && ((char *)pTmpUndName)[len] == ' ';) { ((char *)pTmpUndName)[len] = '\0'; } bool _MustReleaseLock = false; __PREPARE_CONSTRAINED_REGION __TRY __BEGIN_CONSTRAINED_REGION System::Threading::Thread::BeginThreadAffinity(); _mlock(_TYPEINFO_LOCK); _MustReleaseLock = true; __END_CONSTRAINED_REGION /* * We need to check if this->_m_data is still NULL, this will * prevent the memory leak. */ if (_This->_m_data == NULL) { /* * allocate a node which will store the pointer to the memory * allocated for this->_m_data. We need to store all this in * linklist so that we can free them as process exit. Note * that __clean_type_info_names is freeing this memory. */ __type_info_node *pNode = (__type_info_node *)_malloc_base(sizeof(__type_info_node)); if (pNode != NULL) { /* * We should be doing only if we are sucessful in allocating * node pointer. Note that we need to add 2 to len, this * is because len = strlen(pTmpUndName)-1. */ if ((((type_info *)_This)->_m_data = _malloc_base(len+2)) != NULL) { _ERRCHECK(strcpy_s ((char *)((type_info *)_This)->_m_data, len+2, (char *)pTmpUndName)); pNode->memPtr = _This->_m_data; /* * Add this to global linklist. Note that we always * add this as second element in linklist. */ pNode->next = __ptype_info_node->next; __ptype_info_node->next = pNode; } else { /* * Free node pointer as there is no allocation for * this->_m_data, this means that we don't really * need this in the link list. */ _free_base(pNode); } } } /* * Free the temporary undecorated name. */ _free_base (pTmpUndName); __FINALLY if (_MustReleaseLock) { _munlock(_TYPEINFO_LOCK); System::Threading::Thread::EndThreadAffinity(); } __END_TRY_FINALLY } return (char *) _This->_m_data; }
int __set_loosefpmath(void) { _ERRCHECK(_controlfp_s(NULL, _DN_FLUSH, _MCW_DN)); return 0; }
static __time64_t __cdecl _make__time64_t ( struct tm *tb, int ultflag ) { __time64_t tmptm1, tmptm2, tmptm3; struct tm tbtemp; long dstbias = 0; long timezone = 0; _VALIDATE_RETURN( ( tb != NULL ), EINVAL, ( ( __time64_t )( -1 ) ) ) /* * First, make sure tm_year is reasonably close to being in range. */ if ( ((tmptm1 = tb->tm_year) < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR64 + 1) ) goto err_mktime; /* * Adjust month value so it is in the range 0 - 11. This is because * we don't know how many days are in months 12, 13, 14, etc. */ if ( (tb->tm_mon < 0) || (tb->tm_mon > 11) ) { tmptm1 += (tb->tm_mon / 12); if ( (tb->tm_mon %= 12) < 0 ) { tb->tm_mon += 12; tmptm1--; } /* * Make sure year count is still in range. */ if ( (tmptm1 < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR64 + 1) ) goto err_mktime; } /***** HERE: tmptm1 holds number of elapsed years *****/ /* * Calculate days elapsed minus one, in the given year, to the given * month. Check for leap year and adjust if necessary. */ tmptm2 = _days[tb->tm_mon]; if ( _IS_LEAP_YEAR(tmptm1) && (tb->tm_mon > 1) ) tmptm2++; /* * Calculate elapsed days since base date (midnight, 1/1/70, UTC) * * * 365 days for each elapsed year since 1970, plus one more day for * each elapsed leap year. no danger of overflow because of the range * check (above) on tmptm1. */ tmptm3 = (tmptm1 - _BASE_YEAR) * 365 + _ELAPSED_LEAP_YEARS(tmptm1); /* * elapsed days to current month (still no possible overflow) */ tmptm3 += tmptm2; /* * elapsed days to current date. */ tmptm1 = tmptm3 + (tmptm2 = (__time64_t)(tb->tm_mday)); /***** HERE: tmptm1 holds number of elapsed days *****/ /* * Calculate elapsed hours since base date */ tmptm2 = tmptm1 * 24; tmptm1 = tmptm2 + (tmptm3 = (__time64_t)tb->tm_hour); /***** HERE: tmptm1 holds number of elapsed hours *****/ /* * Calculate elapsed minutes since base date */ tmptm2 = tmptm1 * 60; tmptm1 = tmptm2 + (tmptm3 = (__time64_t)tb->tm_min); /***** HERE: tmptm1 holds number of elapsed minutes *****/ /* * Calculate elapsed seconds since base date */ tmptm2 = tmptm1 * 60; tmptm1 = tmptm2 + (tmptm3 = (__time64_t)tb->tm_sec); /***** HERE: tmptm1 holds number of elapsed seconds *****/ if ( ultflag ) { /* * Adjust for timezone. No need to check for overflow since * localtime() will check its arg value */ __tzset(); _ERRCHECK(_get_dstbias(&dstbias)); _ERRCHECK(_get_timezone(&timezone)); tmptm1 += timezone; /* * Convert this second count back into a time block structure. * If localtime returns NULL, return an error. */ if ( _localtime64_s(&tbtemp, &tmptm1) != 0 ) goto err_mktime; /* * Now must compensate for DST. The ANSI rules are to use the * passed-in tm_isdst flag if it is non-negative. Otherwise, * compute if DST applies. Recall that tbtemp has the time without * DST compensation, but has set tm_isdst correctly. */ if ( (tb->tm_isdst > 0) || ((tb->tm_isdst < 0) && (tbtemp.tm_isdst > 0)) ) { tmptm1 += dstbias; if ( _localtime64_s(&tbtemp, &tmptm1) != 0 ) goto err_mktime; } } else { if ( _gmtime64_s(&tbtemp, &tmptm1) != 0) goto err_mktime; } /***** HERE: tmptm1 holds number of elapsed seconds, adjusted *****/ /***** for local time if requested *****/ *tb = tbtemp; return tmptm1; err_mktime: /* * All errors come to here */ errno = EINVAL; return (__time64_t)(-1); }
static int __cdecl __crtLCMapStringW_stat( _locale_t plocinfo, LCID Locale, DWORD dwMapFlags, LPCWSTR lpSrcStr, int cchSrc, LPWSTR lpDestStr, int cchDest, int code_page ) { 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 (0 != LCMapStringW(0, LCMAP_LOWERCASE, L"\0", 1, NULL, 0)) { f_use = USE_W; } else if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { f_use = USE_A; } } /* * LCMapString will map past NULL. Must find NULL if in string * before cchSrc wide characters. */ if (cchSrc > 0) { cchSrc = wcsncnt(lpSrcStr, cchSrc); } /* Use "W" version */ if (USE_W == f_use) { return LCMapStringW(Locale, dwMapFlags, lpSrcStr, cchSrc, lpDestStr, cchDest); } /* Use "A" version */ if (USE_A == f_use || f_use == 0) { int retval = 0; int inbuff_size; int outbuff_size; unsigned char* inbuffer = NULL; unsigned char* outbuffer = NULL; int AnsiCP = 0; /* * 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 multibyte characters * (enforced by WC_SEPCHARS) in the buffer or the resulting mapped * string will be worthless to the user. * */ /* * Use __lc_codepage for conversion if code_page not specified */ if (0 == Locale) { Locale = plocinfo->locinfo->lc_handle[LC_CTYPE]; } if (0 == code_page) { code_page = plocinfo->locinfo->lc_codepage; } /* * Always use Ansi codepage with Ansi WinAPI because they use * Ansi codepage */ if (code_page != (AnsiCP = __ansicp(Locale))) { if (AnsiCP != -1) { code_page = AnsiCP; } } /* find out how big a buffer we need (includes NULL if any) */ if (0 == (inbuff_size = WideCharToMultiByte(code_page, 0, lpSrcStr, cchSrc, NULL, 0, NULL, NULL))) { return 0; } /* allocate enough space for chars */ inbuffer = (unsigned char*)_calloca(inbuff_size, sizeof(char)); if (inbuffer == NULL) { return 0; } /* do the conversion */ if (0 == WideCharToMultiByte(code_page, 0, lpSrcStr, cchSrc, (char*)inbuffer, inbuff_size, NULL, NULL)) { goto error_cleanup; } /* get size required for string mapping */ if (0 == (outbuff_size = LCMapStringA(Locale, dwMapFlags, (const char*)inbuffer, inbuff_size, NULL, 0))) { goto error_cleanup; } /* allocate enough space for chars and NULL */ outbuffer = (unsigned char*)_calloca(outbuff_size, sizeof(char)); if (outbuffer == NULL) { goto error_cleanup; } /* do string mapping */ if (0 == LCMapStringA(Locale, dwMapFlags, (const char*)inbuffer, inbuff_size, (char*)outbuffer, outbuff_size)) { goto error_cleanup; } if (dwMapFlags & LCMAP_SORTKEY) { /* outbuff_size > cchDest is allowed */ retval = outbuff_size; if (0 != cchDest) /* SORTKEY returns BYTES, just copy */ _ERRCHECK(strncpy_s((char*)lpDestStr, cchDest, (char*)outbuffer, cchDest <= outbuff_size ? cchDest - 1 : outbuff_size)); } else { if (0 == cchDest) { /* get size required */ if (0 == (retval = MultiByteToWideChar(code_page, MB_PRECOMPOSED, (const char*)outbuffer, outbuff_size, NULL, 0))) { goto error_cleanup; } } else { /* convert mapping */ if (0 == (retval = MultiByteToWideChar(code_page, MB_PRECOMPOSED, (const char*)outbuffer, outbuff_size, lpDestStr, cchDest))) { goto error_cleanup; } } } error_cleanup: if (outbuffer != NULL) { _freea(outbuffer); } _freea(inbuffer); return retval; } else { /* f_use is neither USE_A nor USE_W */ return 0; } }
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); }
static errno_t __cdecl common_localtime_s( tm* const ptm, TimeType const* const ptime ) throw() { typedef __crt_time_time_t_traits<TimeType> time_traits; _VALIDATE_RETURN_ERRCODE(ptm != nullptr, EINVAL); memset(ptm, 0xff, sizeof(tm)); _VALIDATE_RETURN_ERRCODE(ptime != nullptr, EINVAL); // Check for illegal time_t value: _VALIDATE_RETURN_ERRCODE_NOEXC(*ptime >= 0, EINVAL); _VALIDATE_RETURN_ERRCODE_NOEXC(*ptime <= time_traits::max_time_t, EINVAL); __tzset(); int daylight = 0; long dstbias = 0; long timezone = 0; _ERRCHECK(_get_daylight(&daylight)); _ERRCHECK(_get_dstbias (&dstbias )); _ERRCHECK(_get_timezone(&timezone)); if (*ptime > 3 * _DAY_SEC && *ptime < time_traits::max_time_t - 3 * _DAY_SEC) { // The date does not fall within the first three or last three representable // days; therefore, there is no possibility of overflowing or underflowing // the time_t representation as we compensate for time zone and daylight // savings time. TimeType ltime = *ptime - timezone; errno_t status0 = time_traits::gmtime_s(ptm, <ime); if (status0 != 0) return status0; // Check and adjust for daylight savings time: if (daylight && _isindst(ptm)) { ltime -= dstbias; errno_t const status1 = time_traits::gmtime_s(ptm, <ime); if (status1 != 0) return status1; ptm->tm_isdst = 1; } } else { // The date falls within the first three or last three representable days; // therefore, it is possible that the time_t representation would overflow // or underflow while compensating for time zone and daylight savings time. // Therefore, we make the time zone and daylight savings time adjustments // directly in the tm structure. errno_t const status0 = time_traits::gmtime_s(ptm, ptime); if (status0 != 0) return status0; TimeType ltime = static_cast<TimeType>(ptm->tm_sec); // First, adjust for the time zone: if (daylight && _isindst(ptm)) { ltime -= (timezone + dstbias); ptm->tm_isdst = 1; } else { ltime -= timezone; } ptm->tm_sec = static_cast<int>(ltime % 60); if (ptm->tm_sec < 0) { ptm->tm_sec += 60; ltime -= 60; } ltime = static_cast<TimeType>(ptm->tm_min) + ltime / 60; ptm->tm_min = static_cast<int>(ltime % 60); if (ptm->tm_min < 0) { ptm->tm_min += 60; ltime -= 60; } ltime = static_cast<TimeType>(ptm->tm_hour) + ltime / 60; ptm->tm_hour = static_cast<int>(ltime % 24); if (ptm->tm_hour < 0) { ptm->tm_hour += 24; ltime -=24; } ltime /= 24; if (ltime > 0) { // There is no possibility of overflowing the tm_day and tm_yday // members because the date can be no later than January 19. ptm->tm_wday = (ptm->tm_wday + static_cast<int>(ltime)) % 7; ptm->tm_mday += static_cast<int>(ltime); ptm->tm_yday += static_cast<int>(ltime); } else if (ltime < 0) { // It is possible to underflow the tm_mday and tm_yday fields. If // this happens, then the adjusted date must lie in December 1969: ptm->tm_wday = (ptm->tm_wday + 7 + static_cast<int>(ltime)) % 7; ptm->tm_mday += static_cast<int>(ltime); if (ptm->tm_mday <= 0) { ptm->tm_mday += 31; // Per assumption #4 above, the time zone can cause the date to // underflow the epoch by more than a day. ptm->tm_yday = ptm->tm_yday + static_cast<int>(ltime) + 365; ptm->tm_mon = 11; ptm->tm_year--; } else { ptm->tm_yday += static_cast<int>(ltime); } } } 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; }
int __cdecl _resetstkoflw(void) { LPBYTE pStack, pStackBase, pMaxGuard, pMinGuard; #if defined (_M_IA64) LPBYTE pBspBase; DWORD BspRegionSize; #endif /* defined (_M_IA64) */ MEMORY_BASIC_INFORMATION mbi; SYSTEM_INFO si; DWORD PageSize; DWORD RegionSize; DWORD flNewProtect; DWORD flOldProtect; BOOL (*SetThreadStackGuaranteePointer)( ULONG * StackSizeInBytes ); unsigned int osplatform = 0; // Use _alloca() to get the current stack pointer #pragma warning(push) #pragma warning(disable:6255) // prefast(6255): This alloca is safe and we do not want a __try here pStack = (LPBYTE)_alloca(1); #pragma warning(pop) // Find the base of the stack. if (VirtualQuery(pStack, &mbi, sizeof mbi) == 0) { return 0; } pStackBase = (LPBYTE)mbi.AllocationBase; GetSystemInfo(&si); PageSize = si.dwPageSize; RegionSize = 0; // Enable the new guard page. _ERRCHECK(_get_osplatform(&osplatform)); if (osplatform == VER_PLATFORM_WIN32_NT) { // // Note: if the GuaranteedStackBytes TEB field is 0 // (on older OS versions or if SetThreadStackGuarantee is // not being used) we will use the default value of // RegionSize (2 pages for ia64, 1 page for other platforms). // ULONG StackSizeInBytes; HMODULE ModuleHandle; // // Don't call SetThreadStackGuarantee directly as older kernel32.dll // versions do not have this export. // ModuleHandle = GetModuleHandle("kernel32.dll"); if (ModuleHandle != NULL) { SetThreadStackGuaranteePointer = (PVOID) GetProcAddress(ModuleHandle, "SetThreadStackGuarantee"); if (SetThreadStackGuaranteePointer != NULL) { StackSizeInBytes = 0; // Indicate just querying if (SetThreadStackGuaranteePointer(&StackSizeInBytes) == TRUE && StackSizeInBytes > 0) { RegionSize = StackSizeInBytes; } } } } flNewProtect = (osplatform == VER_PLATFORM_WIN32_WINDOWS) ? PAGE_NOACCESS : PAGE_READWRITE | PAGE_GUARD; RegionSize = (RegionSize + PageSize - 1) & ~(PageSize - 1); // // If there is a stack guarantee (RegionSize nonzero), then increase // our guard page size by 1 so that even a subsequent fault that occurs // midway (instead of at the beginning) through the first guard page // will have the extra page to preserve the guarantee. // if (RegionSize != 0) { RegionSize += PageSize; } #if defined (_M_IA64) // // Reset the backstore stack pages. // // // Calculate the top of the BSP stack, by getting the size of the normal // stack and adding it to the StackBase. // pBspBase = (LPBYTE)(((ULONG_PTR)(((PNT_TIB)NtCurrentTeb())->StackBase) - (ULONG_PTR) mbi.AllocationBase) + (ULONG_PTR)(((PNT_TIB)NtCurrentTeb())->StackBase)); // // Get the current BSP and round up since the BSP grows up. // pMinGuard = (LPBYTE)((__getReg(__REG_IA64_RsBSP) + PageSize) & ~(ULONG_PTR)(PageSize - 1)); // // The highest BSP address is the top of the BSP stack less one page for // the guard. // pMaxGuard = pBspBase - PageSize; BspRegionSize = RegionSize; if (BspRegionSize < MIN_BSP_REQ_WINNT * PageSize) { BspRegionSize = MIN_BSP_REQ_WINNT * PageSize; } if (((ULONG_PTR)pMaxGuard < BspRegionSize) || (pMaxGuard - BspRegionSize) < pMinGuard) { // // The current BSP is already in the highest guard region. // return 0; } if (VirtualAlloc(pMinGuard, BspRegionSize, MEM_COMMIT, PAGE_READWRITE) == NULL || VirtualProtect(pMinGuard, BspRegionSize, flNewProtect, &flOldProtect) == 0) { return 0; } #endif /* defined (_M_IA64) */ if (RegionSize < MIN_STACK_REQ_WINNT * PageSize) { RegionSize = MIN_STACK_REQ_WINNT * PageSize; } // // Find the page(s) just below where the stack pointer currently points. // This is the highest potential guard page. // pMaxGuard = (LPBYTE)(((DWORD_PTR)pStack & ~(DWORD_PTR)(PageSize - 1)) - RegionSize); // // If the potential guard page is too close to the start of the stack // region, abandon the reset effort for lack of space. Win9x has a // larger reserved stack requirement. // pMinGuard = pStackBase + ( (osplatform == VER_PLATFORM_WIN32_WINDOWS) ? MIN_STACK_REQ_WIN9X : PageSize); if (pMaxGuard < pMinGuard) { return 0; } // Set the new guard page just below the current stack page. if (VirtualAlloc(pMaxGuard, RegionSize, MEM_COMMIT, PAGE_READWRITE) == NULL || VirtualProtect(pMaxGuard, RegionSize, flNewProtect, &flOldProtect) == 0) { return 0; } return 1; }
// prefast (6262): This func uses lots of stack because we want to tolerate very large reports, and we can't use malloc here. int __cdecl _VCrtDbgReportA( int nRptType, void * returnAddress, char const* szFile, int nLine, char const* szModule, char const* szFormat, va_list arglist ) { int retval=0; int handled=FALSE; char szLineMessage[DBGRPT_MAX_MSG]{0}; char szOutMessage [DBGRPT_MAX_MSG]{0}; wchar_t szOutMessage2[DBGRPT_MAX_MSG]{0}; char szUserMessage[DBGRPT_MAX_MSG]{0}; if (nRptType < 0 || nRptType >= _CRT_ERRCNT) return -1; /* * handle the (hopefully rare) case of * * 1) ASSERT while already dealing with an ASSERT * or * 2) two threads asserting at the same time */ __try { if (_CRT_ASSERT == nRptType && _InterlockedIncrement(&_crtAssertBusy) > 0) { /* use only 'safe' functions -- must not assert in here! */ _ERRCHECK(_itoa_s(nLine, szLineMessage, DBGRPT_MAX_MSG, 10)); OutputDebugStringA("Second Chance Assertion Failed: File "); OutputDebugStringA(szFile ? szFile : "<file unknown>"); OutputDebugStringA(", Line "); OutputDebugStringA(szLineMessage); OutputDebugStringA("\n"); _CrtDbgBreak(); retval=-1; __leave; } // Leave space for ASSERTINTRO1 and "\r\n" if (szFormat) { int szlen = 0; _ERRCHECK_SPRINTF(szlen = _vsnprintf_s(szUserMessage, DBGRPT_MAX_MSG, DBGRPT_MAX_MSG - 2- max(sizeof(ASSERTINTRO1),sizeof(ASSERTINTRO2)), szFormat, arglist)); if (szlen < 0) { _ERRCHECK(strcpy_s(szUserMessage, DBGRPT_MAX_MSG, DBGRPT_TOOLONGMSG)); } } if (_CRT_ASSERT == nRptType) { _ERRCHECK(strcpy_s(szLineMessage, DBGRPT_MAX_MSG, szFormat ? ASSERTINTRO1 : ASSERTINTRO2)); } _ERRCHECK(strcat_s(szLineMessage, DBGRPT_MAX_MSG, szUserMessage)); if (_CRT_ASSERT == nRptType) { if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_FILE) { _ERRCHECK(strcat_s(szLineMessage, DBGRPT_MAX_MSG, "\r")); } _ERRCHECK(strcat_s(szLineMessage, DBGRPT_MAX_MSG, "\n")); } if (szFile) { int szlen = 0; _ERRCHECK_SPRINTF(szlen = _snprintf_s(szOutMessage, DBGRPT_MAX_MSG, DBGRPT_MAX_MSG - 1, "%s(%d) : %s", szFile, nLine, szLineMessage)); if (szlen < 0) { _ERRCHECK(strcpy_s(szOutMessage, DBGRPT_MAX_MSG, DBGRPT_TOOLONGMSG)); } } else { _ERRCHECK(strcpy_s(szOutMessage, DBGRPT_MAX_MSG, szLineMessage)); } { size_t ret = 0; errno_t e = 0; _ERRCHECK_EINVAL_ERANGE(e = mbstowcs_s(&ret, szOutMessage2, DBGRPT_MAX_MSG, szOutMessage, _TRUNCATE)); if(e != 0) { _ERRCHECK(wcscpy_s(szOutMessage2, DBGRPT_MAX_MSG, _CRT_WIDE(DBGRPT_INVALIDMSG))); } } /* User hook may handle report. We have to check the ANSI Hook2 List & then the UNICODE Hook2 List. Then we have check any ANSI individual Hook set through SetReportHook */ if (_pReportHookList || _pReportHookListW) { __crt_report_hook_node<char> *pnode=nullptr; __crt_report_hook_node<wchar_t> *pnodeW=nullptr; __acrt_lock(__acrt_debug_lock); __try { for (pnode = _pReportHookList; pnode; pnode = pnode->next) { int hook_retval=0; if (pnode->hook(nRptType, szOutMessage, &hook_retval)) { handled=TRUE; retval=hook_retval; __leave; } } for (pnodeW = _pReportHookListW; pnodeW; pnodeW = pnodeW->next) { int hook_retval=0; if (pnodeW->hook(nRptType, szOutMessage2, &hook_retval)) { handled=TRUE; retval=hook_retval; __leave; } } } __finally { __acrt_unlock(__acrt_debug_lock); } } if (handled) __leave; if (_pfnReportHook) { int hook_retval=0; if (_pfnReportHook(nRptType, szOutMessage, &hook_retval)) { retval = hook_retval; __leave; } } if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_FILE) { if (_CrtDbgFile[nRptType] != _CRTDBG_INVALID_HFILE) { DWORD bytes_written = 0; WriteFile(_CrtDbgFile[nRptType], szOutMessage, static_cast<DWORD>(strlen(szOutMessage)), &bytes_written, nullptr); } } if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_DEBUG) { OutputDebugStringA(szOutMessage); } if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_WNDW) { szLineMessage[0] = 0; if (nLine) { _ERRCHECK(_itoa_s(nLine, szLineMessage, DBGRPT_MAX_MSG, 10)); } retval = __acrt_MessageWindowA(nRptType, returnAddress, szFile, (nLine ? szLineMessage : nullptr), szModule, szUserMessage); } }