📄 wsetloca.c
字号:
/***
*wsetlocal.c - Contains the setlocale function (wchar_t version)
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Contains the _wsetlocale() function.
*
*******************************************************************************/
#include <wchar.h>
#include <stdlib.h>
#include <setlocal.h>
#include <locale.h>
#include <dbgint.h>
#include <mtdll.h>
#include <internal.h>
#include <malloc.h>
#define MAXSIZE ((MAX_LC_LEN+1) * (LC_MAX-LC_MIN+1) + CATNAMES_LEN)
wchar_t * __cdecl _wsetlocale (
int _category,
const wchar_t *_wlocale
)
{
size_t size = 0;
char *inlocale = NULL;
char *outlocale;
pthreadlocinfo ptloci;
int *refcount = NULL;
wchar_t *outwlocale = NULL;
_locale_tstruct locale;
_ptiddata ptd;
/* convert WCS string into ASCII string */
if (_wlocale)
{
_ERRCHECK_EINVAL_ERANGE(wcstombs_s(&size, NULL, 0, _wlocale, INT_MAX));
if (size==0 || (inlocale = (char *)_calloc_crt(size, sizeof(char))) == NULL)
return NULL;
if (_ERRCHECK_EINVAL_ERANGE(wcstombs_s(NULL, inlocale, size, _wlocale, _TRUNCATE)) != 0)
{
_free_crt (inlocale);
return NULL;
}
}
/* set the locale and get ASCII return string */
outlocale = setlocale(_category, inlocale);
_free_crt (inlocale);
if (NULL == outlocale)
return NULL;
// We now have a locale string, but the global locale can be changed by
// another thread. If we allow this thread's locale to be updated before we're done
// with this string, it might be freed from under us.
// Call versions of the MB-to-wide-char conversions that do not update the current thread's
// locale.
ptd = _getptd();
locale.locinfo = ptd->ptlocinfo;
locale.mbcinfo = ptd->ptmbcinfo;
/* get space for WCS return value, first call only */
size = 0;
if (_ERRCHECK_EINVAL_ERANGE(_mbstowcs_s_l(&size, NULL, 0, outlocale, 0, &locale)) != 0)
return NULL;
/* ensure that (size * num) does not overflow */
if(((_HEAP_MAXREQ-sizeof(int)) / sizeof(wchar_t)) < size)
{
return NULL;
}
refcount = (int *)_malloc_crt(size * sizeof(wchar_t) + sizeof(int));
if (!refcount)
return NULL;
outwlocale = (wchar_t *)&refcount[1];
/* convert return value to WCS */
if ( _ERRCHECK_EINVAL_ERANGE(_mbstowcs_s_l(NULL, outwlocale, size, outlocale, _TRUNCATE, &locale)) != 0)
{
_free_crt(refcount);
return NULL;
}
ptloci = locale.locinfo;
_mlock(_SETLOCALE_LOCK);
__try {
_ASSERTE(((ptloci->lc_category[_category].wlocale != NULL) && (ptloci->lc_category[_category].wrefcount != NULL)) ||
((ptloci->lc_category[_category].wlocale == NULL) && (ptloci->lc_category[_category].wrefcount == NULL)));
if (ptloci->lc_category[_category].wrefcount != NULL &&
InterlockedDecrement(ptloci->lc_category[_category].wrefcount) == 0) {
_free_crt(ptloci->lc_category[_category].wrefcount);
}
if (!(ptd->_ownlocale & _PER_THREAD_LOCALE_BIT) &&
!(__globallocalestatus & _GLOBAL_LOCALE_BIT)) {
if (ptloci->lc_category[_category].wrefcount != NULL &&
InterlockedDecrement(ptloci->lc_category[_category].wrefcount) == 0) {
_free_crt(ptloci->lc_category[_category].wrefcount);
}
}
/*
* Note that we are using a risky trick here. We are adding this
* wlocale to an existing threadlocinfo struct, and thus starting
* the wlocale's wrefcount with the same value as the whole struct.
* That means all code which modifies both threadlocinfo::refcount
* and threadlocinfo::lc_category[]::wrefcount in structs that are
* potentially shared across threads must make those modifications
* under _SETLOCALE_LOCK. Otherwise, there's a race condition
* for some other thread modifying threadlocinfo::refcount after
* we load it but before we store it to wrefcount.
*/
*refcount = ptloci->refcount;
ptloci->lc_category[_category].wrefcount = refcount;
ptloci->lc_category[_category].wlocale = outwlocale;
}
__finally {
_munlock(_SETLOCALE_LOCK);
}
return outwlocale;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -