Reactos
at master 165 lines 5.3 kB view raw
1// 2// GetLocaleInfoA.cpp 3// 4// Copyright (c) Microsoft Corporation. All rights reserved. 5// 6// Defines the CRT-internal GetLocaleInfoA implementation. 7// 8#include <corecrt_internal.h> 9 10 11 12// Wraps a call to GetLocaleInfoEx and translates the result into a narrow string. 13_Success_(return > 0) 14static int __cdecl InternalGetLocaleInfoA( 15 _locale_t const locale, 16 PCWSTR const locale_name, 17 LCTYPE const locale_type, 18 _Out_writes_z_(result_size) char* const result, 19 int const result_size 20 ) 21{ 22 _LocaleUpdate locale_update(locale); 23 24 int const code_page = locale_update.GetLocaleT()->locinfo->_public._locale_lc_codepage; 25 26 int const buffer_size = __acrt_GetLocaleInfoEx(locale_name, locale_type, nullptr, 0); 27 if (buffer_size == 0) 28 return 0; 29 30 __crt_scoped_stack_ptr<wchar_t> const buffer(_malloca_crt_t(wchar_t, buffer_size)); 31 if (buffer.get() == nullptr) 32 return 0; 33 34 if (__acrt_GetLocaleInfoEx(locale_name, locale_type, buffer.get(), buffer_size) == 0) 35 return 0; 36 37 // Convert from wide to narrow strings: 38 return __acrt_WideCharToMultiByte( 39 code_page, 40 0, 41 buffer.get(), 42 -1, 43 result_size != 0 ? result : nullptr, 44 result_size, 45 nullptr, 46 nullptr); 47} 48 49 50 51// Gets locale information appropriate for use in the setlocale initialization 52// functions. In particular, wide locale strings can be converted to narrow 53// strings or numeric values depending on the value of the lc_type parameter. 54// 55// The void_result must be reinterpretable as a pointer to one of the following 56// types, depending on the value of LC_TYPE: 57// 58// * LC_STR_TYPE: char* 59// * LC_WSTR_TYPE: wchar_t* 60// * LC_INT_TYPE: unsigned char 61// 62// For the first two cases, where a pointer to a pointer is passed, if the 63// function succeeds, the caller is responsible for freeing the pointed-to 64// buffer. 65// 66// Returns 0 on success; -1 on failure. 67// 68// Future optimization: When converting a large number of wide strings to 69// multibyte, we do not need to query the size of the result. We can convert 70// them one after another into a large character buffer. 71int __cdecl __acrt_GetLocaleInfoA( 72 _locale_t const locale, 73 int const lc_type, 74 wchar_t const* const locale_name, 75 LCTYPE const locale_type, 76 void* const void_result 77 ) 78{ 79 *static_cast<void**>(void_result) = nullptr; 80 81 if (lc_type == LC_STR_TYPE) 82 { 83 char** const char_result = static_cast<char**>(void_result); 84 85 int const local_buffer_size = 128; 86 char local_buffer[local_buffer_size]; 87 88 int const local_length = InternalGetLocaleInfoA( 89 locale, locale_name, locale_type, local_buffer, local_buffer_size); 90 91 if (local_length != 0) 92 { 93 *char_result = _calloc_crt_t(char, local_length).detach(); 94 if (*char_result == nullptr) 95 return -1; 96 97 _ERRCHECK(strncpy_s(*char_result, local_length, local_buffer, local_length - 1)); 98 return 0; 99 } 100 101 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) 102 return -1; 103 104 // If the buffer size was too small, compute the required size and use a 105 // dynamically allocated buffer: 106 int const required_length = InternalGetLocaleInfoA( 107 locale, locale_name, locale_type, nullptr, 0); 108 109 if (required_length == 0) 110 return -1; 111 112 __crt_unique_heap_ptr<char> dynamic_buffer(_calloc_crt_t(char, required_length)); 113 if (dynamic_buffer.get() == nullptr) 114 return -1; 115 116 int const actual_length = InternalGetLocaleInfoA( 117 locale, locale_name, locale_type, dynamic_buffer.get(), required_length); 118 119 if (actual_length == 0) 120 return -1; 121 122 *char_result = dynamic_buffer.detach(); 123 return 0; 124 } 125 else if (lc_type == LC_WSTR_TYPE) 126 { 127 wchar_t** const wchar_result = static_cast<wchar_t**>(void_result); 128 129 int const required_length = __acrt_GetLocaleInfoEx(locale_name, locale_type, nullptr, 0); 130 if (required_length == 0) 131 return -1; 132 133 __crt_unique_heap_ptr<wchar_t> dynamic_buffer(_calloc_crt_t(wchar_t, required_length)); 134 if (dynamic_buffer.get() == nullptr) 135 return -1; 136 137 int const actual_length = __acrt_GetLocaleInfoEx( 138 locale_name, locale_type, dynamic_buffer.get(), required_length); 139 140 if (actual_length == 0) 141 return -1; 142 143 *wchar_result = dynamic_buffer.detach(); 144 return 0; 145 } 146 else if (lc_type == LC_INT_TYPE) 147 { 148 unsigned char* const uchar_result = static_cast<unsigned char*>(void_result); 149 150 DWORD value = 0; 151 int const actual_length = __acrt_GetLocaleInfoEx( 152 locale_name, 153 locale_type | LOCALE_RETURN_NUMBER, 154 reinterpret_cast<wchar_t*>(&value), 155 sizeof(value) / sizeof(wchar_t)); 156 157 if (actual_length == 0) 158 return -1; 159 160 *uchar_result = static_cast<unsigned char>(value); 161 return 0; 162 } 163 164 return -1; 165}