ReactOS 0.4.16-dev-937-g7afcd2a
setlocale.cpp File Reference
#include <corecrt_internal.h>
#include <locale.h>
#include <stdlib.h>
Include dependency graph for setlocale.cpp:

Go to the source code of this file.

Functions

static wchar_t *__cdecl call_wsetlocale (int const category, char const *const narrow_locale)
 
char *__cdecl setlocale (int _category, char const *_locale)
 

Function Documentation

◆ call_wsetlocale()

static wchar_t *__cdecl call_wsetlocale ( int const  category,
char const *const  narrow_locale 
)
static

Definition at line 15 of file setlocale.cpp.

16{
17 if (narrow_locale == nullptr)
18 return _wsetlocale(category, nullptr);
19
20 size_t size;
21 _ERRCHECK_EINVAL_ERANGE(mbstowcs_s(&size, nullptr, 0, narrow_locale, INT_MAX));
22
23 __crt_unique_heap_ptr<wchar_t> wide_locale(_calloc_crt_t(wchar_t, size));
24 if (wide_locale.get() == nullptr)
25 return nullptr;
26
27 if (_ERRCHECK_EINVAL_ERANGE(mbstowcs_s(nullptr, wide_locale.get(), size, narrow_locale, _TRUNCATE)) != 0)
28 return nullptr;
29
30 return _wsetlocale(category, wide_locale.get());
31}
#define _ERRCHECK_EINVAL_ERANGE(e)
GLsizeiptr size
Definition: glext.h:5919
_Check_return_opt_ _CRTIMP wchar_t *__cdecl _wsetlocale(_In_ int _Category, _In_opt_z_ const wchar_t *_Locale)
#define INT_MAX
Definition: intsafe.h:150
errno_t mbstowcs_s(size_t *cchConverted, wchar_t *widechar, size_t charoutct, const char *multibyte, size_t count)
Definition: mbstowcs.cpp:316
#define _TRUNCATE
Definition: corecrt.h:278

Referenced by setlocale().

◆ setlocale()

char *__cdecl setlocale ( int  _category,
char const _locale 
)

Definition at line 33 of file setlocale.cpp.

34{
35 // Deadlock Avoidance: See the comment in _wsetlocale on usage of this function.
37
38 return __acrt_lock_and_call(__acrt_locale_lock, [&]() -> char*
39 {
40 // Convert ASCII string into a wide character string:
41 wchar_t* const outwlocale = call_wsetlocale(_category, _locale);
42 if (outwlocale == nullptr)
43 {
44 return nullptr;
45 }
46
47 __acrt_ptd* const ptd = __acrt_getptd();
48
50 locale.locinfo = ptd->_locale_info;
51 locale.mbcinfo = ptd->_multibyte_info;
52
53 // We now have a locale string, but the global locale can be changed by
54 // another thread. If we allow this thread's locale to be updated before
55 // we're done with this string, it might be freed from under us. We call
56 // the versions of the wide-to-multibyte conversions that do not update the
57 // current thread's locale.
58 size_t size = 0;
59 if (_ERRCHECK_EINVAL_ERANGE(_wcstombs_s_l(&size, nullptr, 0, outwlocale, 0, &locale)) != 0)
60 {
61 return nullptr;
62 }
63
64 long* const refcount = static_cast<long*>(_malloc_crt(size + sizeof(long)));
65 if (refcount == nullptr)
66 {
67 return nullptr;
68 }
69
70 char* outlocale = reinterpret_cast<char*>(&refcount[1]);
71
72 /* convert return value to ASCII */
73 if (_ERRCHECK_EINVAL_ERANGE(_wcstombs_s_l(nullptr, outlocale, size, outwlocale, _TRUNCATE, &locale)) != 0)
74 {
75 _free_crt(refcount);
76 return nullptr;
77 }
78
79 __crt_locale_data* ptloci = locale.locinfo;
80
81 _ASSERTE((ptloci->lc_category[_category].locale != nullptr && ptloci->lc_category[_category].refcount != nullptr) ||
82 (ptloci->lc_category[_category].locale == nullptr && ptloci->lc_category[_category].refcount == nullptr));
83
84 if (ptloci->lc_category[_category].refcount != nullptr &&
85 _InterlockedDecrement(ptloci->lc_category[_category].refcount) == 0)
86 {
87 _free_crt(ptloci->lc_category[_category].refcount);
88 ptloci->lc_category[_category].refcount = nullptr;
89 }
90
91 if (__acrt_should_sync_with_global_locale(ptd))
92 {
93 if (ptloci->lc_category[_category].refcount != nullptr &&
94 _InterlockedDecrement(ptloci->lc_category[_category].refcount) == 0)
95 {
96 _free_crt(ptloci->lc_category[_category].refcount);
97 ptloci->lc_category[_category].refcount = nullptr;
98 }
99 }
100
101 /*
102 * Note that we are using a risky trick here. We are adding this
103 * locale to an existing __crt_locale_data struct, and thus starting
104 * the locale's refcount with the same value as the whole struct.
105 * That means all code which modifies both __crt_locale_data::refcount
106 * and __crt_locale_data::lc_category[]::refcount in structs that are
107 * potentially shared across threads must make those modifications
108 * under the locale lock. Otherwise, there's a race condition
109 * for some other thread modifying __crt_locale_data::refcount after
110 * we load it but before we store it to refcount.
111 */
112 *refcount = ptloci->refcount;
113 ptloci->lc_category[_category].refcount = refcount;
114 ptloci->lc_category[_category].locale = outlocale;
115
116 return outlocale;
117 });
118}
Definition: _locale.h:75
__acrt_ptd *__cdecl __acrt_getptd(void)
@ __acrt_locale_lock
void __cdecl __acrt_eagerly_load_locale_apis(void)
#define _ASSERTE(expr)
Definition: crtdbg.h:114
_In_ size_t const _In_ int _In_ bool const _In_ unsigned const _In_ __acrt_rounding_mode const _Inout_ __crt_cached_ptd_host & ptd
Definition: cvt.cpp:355
_wcstombs_s_l
Definition: stdlib.h:1039
#define _free_crt
#define _malloc_crt
long __cdecl _InterlockedDecrement(_Interlocked_operand_ long volatile *_Addend)
static wchar_t *__cdecl call_wsetlocale(int const category, char const *const narrow_locale)
Definition: setlocale.cpp:15
__crt_locale_refcount lc_category[6]