extern "C" size_t __cdecl _wcstombs_l_helper( char* s, const wchar_t* pwcs, size_t n, _locale_t plocinfo ) { size_t count = 0; int i, retval; char buffer[MB_LEN_MAX]; BOOL defused = 0; if (s && n == 0) /* dest string exists, but 0 bytes converted */ { return 0; } /* validation section */ _VALIDATE_RETURN(pwcs != NULL, EINVAL, (size_t) - 1); _VALIDATE_RETURN(n <= INT_MAX, EINVAL, (size_t) - 1); /* if destination string exists, fill it in */ _LocaleUpdate _loc_update(plocinfo); if (s) { if (_loc_update.GetLocaleT()->locinfo->lc_handle[LC_CTYPE] == _CLOCALEHANDLE) { /* C locale: easy and fast */ /* Actually, there are such wchar_t characters which are > 255, * but they can be transformed to a valid single byte char * (i.e. a char in the C locale case). Like, for example, * alternative digits in unicode like Arabic-Indic U+0660..U+0669. * The problem is that WideCharToMultiByte() does not translate those * wchar_t unless we pass the correct codepage (1256, Arabic). * See bug VSW:192653. */ while (count < n) { if (*pwcs > 255) { /* validate high byte */ errno = EILSEQ; return (size_t) - 1; /* error */ } s[count] = (char) * pwcs; if (*pwcs++ == L'\0') { return count; } count++; } return count; } else { if (1 == _loc_update.GetLocaleT()->locinfo->mb_cur_max) { /* If SBCS, one wchar_t maps to one char */ /* WideCharToMultiByte will compare past NULL - reset n */ if (n > 0) { n = wcsncnt(pwcs, n); } if (((count = WideCharToMultiByte(_loc_update.GetLocaleT()->locinfo->lc_codepage, 0, pwcs, (int)n, s, (int)n, NULL, &defused)) != 0) && (!defused)) { if (*(s + count - 1) == '\0') { count--; /* don't count NUL */ } return count; } errno = EILSEQ; return (size_t) - 1; } else { /* If MBCS, wchar_t to char mapping unknown */ /* Assume that usually the buffer is large enough */ if (((count = WideCharToMultiByte(_loc_update.GetLocaleT()->locinfo->lc_codepage, 0, pwcs, -1, s, (int)n, NULL, &defused)) != 0) && (!defused)) { return count - 1; /* don't count NUL */ } if (defused || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { errno = EILSEQ; return (size_t) - 1; } /* buffer not large enough, must do char by char */ while (count < n) { if (((retval = WideCharToMultiByte(_loc_update.GetLocaleT()->locinfo->lc_codepage, 0, pwcs, 1, buffer, _loc_update.GetLocaleT()->locinfo->mb_cur_max, NULL, &defused)) == 0) || defused) { errno = EILSEQ; return (size_t) - 1; } /* enforce this for prefast */ if (retval < 0 || retval > _countof(buffer)) { errno = EILSEQ; return (size_t) - 1; } if (count + retval > n) { return count; } for (i = 0; i < retval; i++, count++) /* store character */ if ((s[count] = buffer[i]) == '\0') { return count; } pwcs++; } return count; } } } else { /* s == NULL, get size only, pwcs must be NUL-terminated */ if (_loc_update.GetLocaleT()->locinfo->lc_handle[LC_CTYPE] == _CLOCALEHANDLE) { return wcslen(pwcs); } else { if (((count = WideCharToMultiByte(_loc_update.GetLocaleT()->locinfo->lc_codepage, 0, pwcs, -1, NULL, 0, NULL, &defused)) == 0) || (defused)) { errno = EILSEQ; return (size_t) - 1; } return count - 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; } }
int __cdecl __crtLCMapStringW( 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 (0 != LCMapStringA(0, LCMAP_LOWERCASE, "\0", 1, NULL, 0)) f_use = USE_A; else return 0; } /* * 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) { int retval; int inbuff_size; int outbuff_size; unsigned char *inbuffer; unsigned char *outbuffer; /* * 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 == code_page) code_page = __lc_codepage; /* find out how big a buffer we need (includes NULL if any) */ if ( 0 == (inbuff_size = WideCharToMultiByte( code_page, WC_COMPOSITECHECK | WC_SEPCHARS, lpSrcStr, cchSrc, NULL, 0, NULL, NULL )) ) return 0; /* allocate enough space for chars */ __try { inbuffer = (unsigned char *)_alloca( inbuff_size * sizeof(char) ); } __except(EXCEPTION_EXECUTE_HANDLER) { inbuffer = NULL; } if ( inbuffer == NULL ) return 0; /* do the conversion */ if ( 0 == WideCharToMultiByte( code_page, WC_COMPOSITECHECK | WC_SEPCHARS, lpSrcStr, cchSrc, inbuffer, inbuff_size, NULL, NULL ) ) return 0; /* get size required for string mapping */ if ( 0 == (outbuff_size = LCMapStringA( Locale, dwMapFlags, inbuffer, inbuff_size, NULL, 0 )) ) return 0; /* allocate enough space for chars and NULL */ __try { outbuffer = (unsigned char *)_alloca( outbuff_size * sizeof(char) ); } __except(EXCEPTION_EXECUTE_HANDLER) { outbuffer = NULL; } if ( outbuffer == NULL ) return 0; /* do string mapping */ if ( 0 == LCMapStringA( Locale, dwMapFlags, inbuffer, inbuff_size, outbuffer, outbuff_size ) ) return 0; if (dwMapFlags & LCMAP_SORTKEY) { /* outbuff_size > cchDest is allowed */ retval = outbuff_size; if (0 != cchDest) /* SORTKEY returns BYTES, just copy */ strncpy( (char *)lpDestStr, (char *)outbuffer, cchDest < outbuff_size ? cchDest : outbuff_size ); } else { if (0 == cchDest) { /* get size required */ if ( 0 == (retval = MultiByteToWideChar( code_page, MB_PRECOMPOSED, outbuffer, outbuff_size, NULL, 0 )) ) return 0; } else { /* convert mapping */ if ( 0 == (retval = MultiByteToWideChar( code_page, MB_PRECOMPOSED, outbuffer, outbuff_size, lpDestStr, cchDest )) ) return 0; } } return retval; }
int __cdecl __crtCompareStringW( LCID Locale, DWORD dwCmpFlags, LPCWSTR lpString1, int cchCount1, LPCWSTR lpString2, int cchCount2, 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 != CompareStringW(0, 0, L"\0", 1, L"\0", 1)) f_use = USE_W; else if (0 != CompareStringA(0, 0, "\0", 1, "\0", 1)) f_use = USE_A; else return 0; } /* * CompareString will compare past NULL. Must find NULL if in string * before cchCountn wide characters. */ if (cchCount1 > 0) cchCount1= wcsncnt(lpString1, cchCount1); if (cchCount2 > 0) cchCount2= wcsncnt(lpString2, cchCount2); if (!cchCount1 || !cchCount2) return (cchCount1 - cchCount2 == 0) ? 2 : (cchCount1 - cchCount2 < 0) ? 1 : 3; /* Use "W" version */ if (USE_W == f_use) { return CompareStringW( Locale, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2 ); } /* Use "A" version */ if (USE_A == f_use) { int buff_size1; int buff_size2; unsigned char *buffer1; unsigned char *buffer2; /* * Use __lc_codepage for conversion if code_page not specified */ if (0 == code_page) code_page = __lc_codepage; /* * Convert strings and return the requested information. */ /* find out how big a buffer we need (includes NULL if any) */ if ( 0 == (buff_size1 = WideCharToMultiByte( code_page, WC_COMPOSITECHECK | WC_SEPCHARS, lpString1, cchCount1, NULL, 0, NULL, NULL )) ) return 0; /* allocate enough space for chars */ __try { buffer1 = (unsigned char *)_alloca( buff_size1 * sizeof(char) ); } __except( EXCEPTION_EXECUTE_HANDLER ) { buffer1 = NULL; } if ( buffer1 == NULL ) return 0; /* do the conversion */ if ( 0 == WideCharToMultiByte( code_page, WC_COMPOSITECHECK | WC_SEPCHARS, lpString1, cchCount1, buffer1, buff_size1, NULL, NULL ) ) return 0; /* find out how big a buffer we need (includes NULL if any) */ if ( 0 == (buff_size2 = WideCharToMultiByte( code_page, WC_COMPOSITECHECK | WC_SEPCHARS, lpString2, cchCount2, NULL, 0, NULL, NULL )) ) return 0; /* allocate enough space for chars */ __try { buffer2 = (unsigned char *)_alloca( buff_size2 * sizeof(char) ); } __except( EXCEPTION_EXECUTE_HANDLER ) { buffer2 = NULL; } if ( buffer2 == NULL ) return 0; /* do the conversion */ if ( 0 == WideCharToMultiByte( code_page, WC_COMPOSITECHECK | WC_SEPCHARS, lpString2, cchCount2, buffer2, buff_size2, NULL, NULL ) ) return 0; return CompareStringA( Locale, dwCmpFlags, buffer1, buff_size1, buffer2, buff_size2 ); }
size_t __cdecl _wcstombs_lk #else size_t __cdecl wcstombs #endif ( char * s, const wchar_t * pwcs, size_t n ) { size_t count = 0; #ifdef _WIN32 int i, retval; char buffer[MB_LEN_MAX]; BOOL defused = 0; #endif if (s && n == 0) /* dest string exists, but 0 bytes converted */ return (size_t) 0; _ASSERTE(pwcs != NULL); #ifdef _WIN32 #if !defined( _NTSUBSET_ ) && !defined(_POSIX_) /* if destination string exists, fill it in */ if (s) { if (__lc_handle[LC_CTYPE] == _CLOCALEHANDLE) { /* C locale: easy and fast */ while(count < n) { if (*pwcs > 255) /* validate high byte */ { errno = EILSEQ; return (size_t)-1; /* error */ } s[count] = (char) *pwcs; if (*pwcs++ == L'\0') return count; count++; } return count; } else { if (1 == MB_CUR_MAX) { /* If SBCS, one wchar_t maps to one char */ /* WideCharToMultiByte will compare past NULL - reset n */ if (n > 0) n = wcsncnt(pwcs, n); if (((count=WideCharToMultiByte(__lc_codepage, WC_COMPOSITECHECK | WC_SEPCHARS, pwcs, n, s, n, NULL, &defused)) != 0) && (!defused)) { if (*(s+count-1) == '\0') count--; /* don't count NUL */ return count; } errno = EILSEQ; return (size_t)-1; } else { /* If MBCS, wchar_t to char mapping unknown */ /* Assume that usually the buffer is large enough */ if (((count=WideCharToMultiByte(__lc_codepage, WC_COMPOSITECHECK | WC_SEPCHARS, pwcs, -1, s, n, NULL, &defused)) != 0) && (!defused)) { return count - 1; /* don't count NUL */ } if (defused || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { errno = EILSEQ; return (size_t)-1; } /* buffer not large enough, must do char by char */ while (count < n) { if (((retval = WideCharToMultiByte (__lc_codepage, 0, pwcs, 1, buffer, MB_CUR_MAX, NULL, &defused)) == 0) || defused) { errno = EILSEQ; return (size_t)-1; } if (count + retval > n) return count; for (i = 0; i < retval; i++, count++) /* store character */ if((s[count] = buffer[i])=='\0') return count; pwcs++; } return count; } } } else { /* s == NULL, get size only, pwcs must be NUL-terminated */ if (__lc_handle[LC_CTYPE] == _CLOCALEHANDLE) return wcslen(pwcs); else { if (((count=WideCharToMultiByte(__lc_codepage, WC_COMPOSITECHECK | WC_SEPCHARS, pwcs, -1, NULL, 0, NULL, &defused)) == 0) || (defused)) { errno = EILSEQ; return (size_t)-1; } return count - 1; } } #else /* _NTSUBSET_/_POSIX_ */ /* if destination string exists, fill it in */ if (s) { NTSTATUS Status; Status = RtlUnicodeToMultiByteN(s, n, (PULONG)&count, (wchar_t *)pwcs, (wcslen(pwcs)+1)*sizeof(WCHAR)); if (NT_SUCCESS(Status)) { return count - 1; /* don't count NUL */ } else { errno = EILSEQ; count = (size_t)-1; } } else { /* s == NULL, get size only, pwcs must be NUL-terminated */ NTSTATUS Status; Status = RtlUnicodeToMultiByteSize((PULONG)&count, (wchar_t *)pwcs, (wcslen(pwcs)+1)*sizeof(WCHAR)); if (NT_SUCCESS(Status)) { return count - 1; /* don't count NUL */ } else { errno = EILSEQ; count = (size_t)-1; } } #endif /* _NTSUBSET_/_POSIX_ */ #else /* _WIN32 */ /* if destination string exists, fill it in */ if (s) { /* C locale: easy and fast */ while(count < n) { if (*pwcs > 255) /* validate high byte */ { errno = EILSEQ; return (size_t)-1; /* error */ } s[count] = (char) *pwcs; if (*pwcs++ == L'\0') return count; count++; } return count; } else { /* s == NULL, get size only, pwcs must be NUL-terminated */ const wchar_t *eos = pwcs; while( *eos++ ) ; return( (size_t)(eos - pwcs - 1) ); } #endif /* _WIN32 */ }