_CRTIMP2 int __cdecl _Strcoll ( const char *_string1, const char *_end1, const char *_string2, const char *_end2, const _Collvec *ploc ) { #ifdef _WIN32 int ret; LCID handle; #ifdef _MT int local_lock_flag; #endif #endif size_t n1 = _end1 - _string1; size_t n2 = _end2 - _string2; _lock_locale( local_lock_flag ) #ifdef _WIN32 if (ploc == 0) handle = __lc_handle[LC_COLLATE]; else handle = ploc->_Hand; if (handle == _CLOCALEHANDLE) { int ans; _unlock_locale( local_lock_flag ) ans = memcmp(_string1, _string2, n1 < n2 ? n1 : n2); return ans != 0 || n1 == n2 ? ans : n1 < n2 ? -1 : +1; } if ( 0 == (ret = __crtCompareStringA( handle, 0, _string1, n1, _string2, n2, __lc_collate_cp )) ) goto error_cleanup; _unlock_locale( local_lock_flag ) return (ret - 2); error_cleanup: _unlock_locale( local_lock_flag ) errno = EINVAL; return _NLSCMPERROR; #else /* defined (_WIN32) */ int ans = memcmp(_string1, _string2, n1 < n2 ? n1 : n2); return ans != 0 || n1 == n2 ? ans : n1 < n2 ? -1 : +1; #endif /* defined (_WIN32) */ }
void _cleanLocale() { _lock_locale(); _cleanCategories(__locale); if (__locale != &CLOCALE) { if (__locale->setLocaleReturnW) { free(__locale->setLocaleReturnW); __locale->setLocaleReturnW = NULL; } if (__locale->setLocaleReturn) { free(__locale->setLocaleReturn); __locale->setLocaleReturn = NULL; } free(__locale); } _unlock_locale(); #ifdef __MT__ DeleteCriticalSection(__localeLock); #endif // __MT__ free(__localeLock); }
LPWSTR _setLocale32W(SHORT Category, LPCWSTR LocaleName) { LPSTR localename; size_t len; _lock_locale(); if (LocaleName) { localename = (LPSTR) malloc(4096); wcstombs(localename, LocaleName, 4096); _setLocale32A(Category, localename); if (__locale != &CLOCALE) { len = strlen(__locale->setLocaleReturn)*2; __locale->setLocaleReturnW = realloc(__locale->setLocaleReturnW, len * sizeof(wchar_t));// leak mbstowcs(__locale->setLocaleReturnW, __locale->setLocaleReturn, len); } free(localename); } else _setLocale32A(Category, 0); _unlock_locale(); return __locale->setLocaleReturnW; }
int __cdecl _Wcscoll ( const wchar_t *_string1, const wchar_t *_end1, const wchar_t *_string2, const wchar_t *_end2, const _Collvec *ploc ) { size_t n1 = _end1 - _string1; size_t n2 = _end2 - _string2; int ret; LCID handle; #ifdef _MT int local_lock_flag; _lock_locale( local_lock_flag ) #endif if (ploc == 0) handle = __lc_handle[LC_COLLATE]; else handle = ploc->_Hand; if (handle == _CLOCALEHANDLE) { int ans; _unlock_locale( local_lock_flag ) ans = _Wmemcmp(_string1, _string2, n1 < n2 ? n1 : n2); return ans != 0 || n1 == n2 ? ans : n1 < n2 ? -1 : +1; } if (0 == (ret = __crtCompareStringW(handle, 0, _string1, n1, _string2, n2, __lc_collate_cp))) { _unlock_locale( local_lock_flag ) errno = EINVAL; return _NLSCMPERROR; } _unlock_locale( local_lock_flag ) return (ret - 2); }
size_t __cdecl wcstombs ( char * s, const wchar_t * pwcs, size_t n ) { int retval; int local_lock_flag; _lock_locale( local_lock_flag ) retval = _wcstombs_lk(s, pwcs, n); _unlock_locale( local_lock_flag ); return retval; }
LPSTR _setLocaleFromString(LPWIN32LOCALE _locale, LPCSTR LocaleName) { char* p = (LPSTR) LocaleName; char token[256]; char locale[256]; int tokenp; SHORT Category = 0; _lock_locale(); memset(token, 0, sizeof(token)); tokenp = 0; while (*p) { if (*p == '=') { if (strcmp(token, "LC_CTYPE") == 0) Category |= LC_CTYPE; if (strcmp(token, "LC_TIME") == 0) Category |= LC_TIME; if (strcmp(token, "LC_NUMERIC") == 0) Category |= LC_NUMERIC; if (strcmp(token, "LC_MONETARY") == 0) Category |= LC_MONETARY; if (strcmp(token, "LC_COLLATE") == 0) Category |= LC_COLLATE; memset(token, 0, sizeof(token)); tokenp = 0; } else if (*p == '\n') { strcpy(locale, token); memset(token, 0, sizeof(token)); tokenp = 0; } else token[tokenp++] = *p; p++; } _locale->handle = _getLocale(_locale, locale); if (!IsValidLocale(_locale->handle, LCID_INSTALLED) && !_locale->isCLocale) { SetLastError(ERROR_LOCALE_NOTINSTALLED); _unlock_locale(); return NULL; } /* SetThreadLocale will only work for NT but it's better to do it in case the application uses OLE2 or some other functionnality requiring a Locale. */ SetThreadLocale(__locale->handle); _cleanCategories(__locale); if (_setNewCategories(__locale, Category) == 0) { SetLastError(ERROR_CATEGORY_INVALID); _unlock_locale(); return NULL; } _unlock_locale(); return __locale->setLocaleReturn; }
LPSTR _setLocale32A(SHORT Category, LPCSTR localeName) { char codepage[7]; BOOL restoreC = FALSE; char* LocaleName = NULL; LCID Handle = 0; char* p; CPINFO cpinfo; if (localeName) LocaleName = strdup(localeName); _lock_locale(); if (__locale == NULL || __locale == &CLOCALE) { if (__locale == &CLOCALE) restoreC = TRUE; if ((__locale = (LPWIN32LOCALE) calloc(1, sizeof(WIN32LOCALE))) == NULL) { SetLastError(ERROR_OUTOFMEMORY); free(LocaleName); _unlock_locale(); return NULL; } } if (__locale->setLocaleReturn != NULL) { free(__locale->setLocaleReturn); __locale->setLocaleReturn = NULL; } if (LocaleName == NULL || LocaleName[0] == 0x0) { if (LocaleName == NULL) { if (restoreC) { _cleanCategories(__locale); free(__locale); __locale = &CLOCALE; } else { if ((Category & LC_MONETARY) == LC_MONETARY) _addCategoryName(__locale, "LC_MONETARY"); if ((Category & LC_NUMERIC) == LC_NUMERIC) _addCategoryName(__locale, "LC_NUMERIC"); if ((Category & LC_TIME) == LC_TIME) _addCategoryName(__locale, "LC_TIME"); if ((Category & LC_COLLATE) == LC_COLLATE) _addCategoryName(__locale, "LC_COLLATE"); if ((Category & LC_CTYPE) == LC_CTYPE) _addCategoryName(__locale, "LC_CTYPE"); free(LocaleName); _llocaleconv(); _unlock_locale(); return __locale->setLocaleReturn; } } else { Handle = GetUserDefaultLCID(); GetLocaleInfoA(Handle, LOCALE_IDEFAULTCODEPAGE, codepage, 7); __locale->codepage = atol(codepage); __locale->isCLocale = FALSE; } } else { if (strstr(localeName, "en_US")) { strcpy(LocaleName, "ENU"); if ((p = strchr(localeName, '.')) != NULL) strcpy(&LocaleName[3], p); } else if (strstr(localeName, "en_GB")) { strcpy(LocaleName, "ENG"); if ((p = strchr(localeName, '.')) != NULL) strcpy(&LocaleName[3], p); } else if (strstr(localeName, "fr_FR")) { strcpy(LocaleName, "FRA"); if ((p = strchr(localeName, '.')) != NULL) strcpy(&LocaleName[3], p); } else if (strstr(localeName, "de_DE")) { strcpy(LocaleName, "DEU"); if ((p = strchr(localeName, '.')) != NULL) strcpy(&LocaleName[3], p); } if (strcmp(localeName, "C") == 0) { _cleanCategories(__locale); free(__locale); __locale = &CLOCALE; } else if (LocaleName[0] == 'L' && LocaleName[1] == 'C' && LocaleName[2] == '_') { free(LocaleName); _unlock_locale(); return _setLocaleFromString(__locale, localeName); } else { __locale->isCLocale = FALSE; if ((Handle = _getLocale(__locale, (LPSTR)LocaleName)) == 0) { if (restoreC) { free(__locale); __locale = &CLOCALE; } _unlock_locale(); free(LocaleName); return NULL; } } } __locale->handle = Handle; free(LocaleName); if (!IsValidLocale(__locale->handle, LCID_INSTALLED) && !__locale->isCLocale) { SetLastError(ERROR_LOCALE_NOTINSTALLED); if (restoreC) { _cleanCategories(__locale); free(__locale); __locale = &CLOCALE; } _unlock_locale(); return NULL; } /* SetThreadLocale will only work under NT but it's best to do it in case the application uses OLE2 or some other functionnality requiring a Locale. */ SetThreadLocale(__locale->handle); if (!__locale->isCLocale) { _cleanCategories(__locale); if (_setNewCategories(__locale, Category) == 0) { SetLastError(ERROR_CATEGORY_INVALID); if (restoreC) { _cleanCategories(__locale); free(__locale); __locale = &CLOCALE; } _unlock_locale(); return NULL; } if (_setmbcp(__locale->codepage) != 0 || !GetCPInfo(__locale->codepage, &cpinfo)) { _unlock_locale(); SetLastError(ERROR_MBCS_CODEPAGE_INVALID); return NULL; } __mb_cur_max = cpinfo.MaxCharSize; _llocaleconv(); _unlock_locale(); return __locale->setLocaleReturn; } else { __mb_cur_max = 1; _llocaleconv(); _unlock_locale(); return __locale->setLocaleReturn; } }
struct lconv * _RTLENTRY _EXPFUNC _llocaleconv( void ) { /* lock locale convention global structure */ _lock_locale(); memset(&_localeconvention, 0, sizeof(_localeconvention)); if (__locale->numeric) { _localeconvention.decimal_point = (char *) __locale->numeric->Decimal; _localeconvention.thousands_sep = (char *) __locale->numeric->ThousandSeparator; _localeconvention.grouping = (char *) __locale->numeric->Grouping; _localeconvention.positive_sign = (char *) __locale->numeric->PositiveSign; _localeconvention.negative_sign = (char *) __locale->numeric->NegativeSign; } if (__locale->monetary) { _localeconvention.int_curr_symbol = (char *) __locale->monetary->IntlSymbol; _localeconvention.currency_symbol = (char *) __locale->monetary->Symbol; _localeconvention.mon_decimal_point = (char *) __locale->monetary->Decimal; _localeconvention.mon_thousands_sep = (char *) __locale->monetary->ThousandSeparator; _localeconvention.mon_grouping = (char *) __locale->monetary->Grouping; _localeconvention.int_frac_digits = __locale->monetary->IntlDigits; _localeconvention.frac_digits = __locale->monetary->Digits; _localeconvention.p_cs_precedes = __locale->monetary->PosSymbolPrec; _localeconvention.p_sep_by_space = __locale->monetary->PosSymbolSpace; _localeconvention.n_cs_precedes = __locale->monetary->NegSymbolPrec; _localeconvention.n_sep_by_space = __locale->monetary->NegSymbolSpace; _localeconvention.p_sign_posn = __locale->monetary->PositiveFormat; _localeconvention.n_sign_posn = __locale->monetary->NegativeFormat; } /* unlock before leaving */ _unlock_locale(); return( &_localeconvention ); }