Reactos
1/*
2 * PROJECT: FreeLoader
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: "Poor-man" boot-time National Language Support (NLS) functions.
5 * COPYRIGHT: Copyright 2022 Hermès Bélusca-Maïto
6 *
7 * NOTE: This code is used at boot-time when no NLS tables are loaded.
8 * Adapted from lib/rtl/nls.c
9 */
10
11/* INCLUDES ******************************************************************/
12
13#include <rtl.h>
14
15/* GLOBALS *******************************************************************/
16
17BOOLEAN NlsMbCodePageTag = FALSE;
18
19BOOLEAN NlsMbOemCodePageTag = FALSE;
20PUSHORT NlsOemToUnicodeTable = NULL;
21PCHAR NlsUnicodeToOemTable = NULL;
22PUSHORT NlsUnicodeToMbOemTable = NULL;
23PUSHORT NlsOemLeadByteInfo = NULL;
24
25USHORT NlsOemDefaultChar = '\0';
26USHORT NlsUnicodeDefaultChar = 0;
27
28/* FUNCTIONS *****************************************************************/
29
30WCHAR
31NTAPI
32RtlpDowncaseUnicodeChar(
33 _In_ WCHAR Source)
34{
35 USHORT Offset = 0;
36
37 if (Source < L'A')
38 return Source;
39
40 if (Source <= L'Z')
41 return Source + (L'a' - L'A');
42
43#if 0
44 if (Source < 0x80)
45 return Source;
46#endif
47
48 return Source + (SHORT)Offset;
49}
50
51WCHAR
52NTAPI
53RtlDowncaseUnicodeChar(
54 _In_ WCHAR Source)
55{
56 return RtlpDowncaseUnicodeChar(Source);
57}
58
59_Use_decl_annotations_
60NTSTATUS
61NTAPI
62RtlMultiByteToUnicodeN(
63 _Out_ PWCH UnicodeString,
64 _In_ ULONG UnicodeSize,
65 _Out_opt_ PULONG ResultSize,
66 _In_ PCCH MbString,
67 _In_ ULONG MbSize)
68{
69 ULONG Size = 0;
70 ULONG i;
71
72 /* single-byte code page */
73 if (MbSize > (UnicodeSize / sizeof(WCHAR)))
74 Size = UnicodeSize / sizeof(WCHAR);
75 else
76 Size = MbSize;
77
78 if (ResultSize)
79 *ResultSize = Size * sizeof(WCHAR);
80
81 for (i = 0; i < Size; i++)
82 {
83 /* Trivially zero-extend */
84 UnicodeString[i] = (WCHAR)MbString[i];
85 }
86
87 return STATUS_SUCCESS;
88}
89
90_Use_decl_annotations_
91NTSTATUS
92NTAPI
93RtlMultiByteToUnicodeSize(
94 _Out_ PULONG UnicodeSize,
95 _In_ PCCH MbString,
96 _In_ ULONG MbSize)
97{
98 /* single-byte code page */
99 *UnicodeSize = MbSize * sizeof(WCHAR);
100
101 return STATUS_SUCCESS;
102}
103
104_Use_decl_annotations_
105NTSTATUS
106NTAPI
107RtlUnicodeToMultiByteN(
108 _Out_ PCHAR MbString,
109 _In_ ULONG MbSize,
110 _Out_opt_ PULONG ResultSize,
111 _In_ PCWCH UnicodeString,
112 _In_ ULONG UnicodeSize)
113{
114 ULONG Size = 0;
115 ULONG i;
116
117 /* single-byte code page */
118 Size = (UnicodeSize > (MbSize * sizeof(WCHAR)))
119 ? MbSize : (UnicodeSize / sizeof(WCHAR));
120
121 if (ResultSize)
122 *ResultSize = Size;
123
124 for (i = 0; i < Size; i++)
125 {
126 /* Check for characters that cannot be trivially demoted to ANSI */
127 if (*((PCHAR)UnicodeString + 1) == 0)
128 {
129 *MbString++ = (CHAR)*UnicodeString++;
130 }
131 else
132 {
133 /* Invalid character, use default */
134 *MbString++ = NlsOemDefaultChar;
135 UnicodeString++;
136 }
137 }
138
139 return STATUS_SUCCESS;
140}
141
142_Use_decl_annotations_
143NTSTATUS
144NTAPI
145RtlUnicodeToMultiByteSize(
146 _Out_ PULONG MbSize,
147 _In_ PCWCH UnicodeString,
148 _In_ ULONG UnicodeSize)
149{
150 ULONG UnicodeLength = UnicodeSize / sizeof(WCHAR);
151
152 /* single-byte code page */
153 *MbSize = UnicodeLength;
154
155 return STATUS_SUCCESS;
156}
157
158WCHAR
159NTAPI
160RtlpUpcaseUnicodeChar(
161 _In_ WCHAR Source)
162{
163 USHORT Offset = 0;
164
165 if (Source < 'a')
166 return Source;
167
168 if (Source <= 'z')
169 return (Source - ('a' - 'A'));
170
171 return Source + (SHORT)Offset;
172}
173
174WCHAR
175NTAPI
176RtlUpcaseUnicodeChar(
177 _In_ WCHAR Source)
178{
179 return RtlpUpcaseUnicodeChar(Source);
180}
181
182_Use_decl_annotations_
183NTSTATUS
184NTAPI
185RtlUpcaseUnicodeToMultiByteN(
186 _Out_ PCHAR MbString,
187 _In_ ULONG MbSize,
188 _Out_opt_ PULONG ResultSize,
189 _In_ PCWCH UnicodeString,
190 _In_ ULONG UnicodeSize)
191{
192 WCHAR UpcaseChar;
193 ULONG Size = 0;
194 ULONG i;
195
196 /* single-byte code page */
197 if (UnicodeSize > (MbSize * sizeof(WCHAR)))
198 Size = MbSize;
199 else
200 Size = UnicodeSize / sizeof(WCHAR);
201
202 if (ResultSize)
203 *ResultSize = Size;
204
205 for (i = 0; i < Size; i++)
206 {
207 UpcaseChar = RtlpUpcaseUnicodeChar(*UnicodeString);
208
209 /* Check for characters that cannot be trivially demoted to ANSI */
210 if (*((PCHAR)&UpcaseChar + 1) == 0)
211 {
212 *MbString = (CHAR)UpcaseChar;
213 }
214 else
215 {
216 /* Invalid character, use default */
217 *MbString = NlsOemDefaultChar;
218 }
219
220 MbString++;
221 UnicodeString++;
222 }
223
224 return STATUS_SUCCESS;
225}
226
227CHAR
228NTAPI
229RtlUpperChar(
230 _In_ CHAR Source)
231{
232 /* Check for simple ANSI case */
233 if (Source <= 'z')
234 {
235 /* Check for simple downcase a-z case */
236 if (Source >= 'a')
237 {
238 /* Just XOR with the difference */
239 return Source ^ ('a' - 'A');
240 }
241 else
242 {
243 /* Otherwise return the same char, it's already upcase */
244 return Source;
245 }
246 }
247 else
248 {
249 /* single-byte code page */
250 return (CHAR)RtlpUpcaseUnicodeChar((WCHAR)Source);
251 }
252}
253
254
255/**
256 * Stubbed OEM helpers that should not be used in the OS boot loader,
257 * but are necessary for linking with the rest of the RTL unicode.c.
258 **/
259
260_Use_decl_annotations_
261NTSTATUS
262NTAPI
263RtlUnicodeToOemN(
264 _Out_ PCHAR OemString,
265 _In_ ULONG OemSize,
266 _Out_opt_ PULONG ResultSize,
267 _In_ PCWCH UnicodeString,
268 _In_ ULONG UnicodeSize)
269{
270 if (OemSize)
271 *OemString = ANSI_NULL;
272
273 if (ResultSize)
274 *ResultSize = 0;
275
276 return STATUS_NOT_IMPLEMENTED;
277}
278
279_Use_decl_annotations_
280NTSTATUS
281NTAPI
282RtlOemToUnicodeN(
283 _Out_ PWCHAR UnicodeString,
284 _In_ ULONG UnicodeSize,
285 _Out_opt_ PULONG ResultSize,
286 _In_ PCCH OemString,
287 _In_ ULONG OemSize)
288{
289 if (UnicodeString)
290 *UnicodeString = UNICODE_NULL;
291
292 if (ResultSize)
293 *ResultSize = 0;
294
295 return STATUS_NOT_IMPLEMENTED;
296}
297
298_Use_decl_annotations_
299NTSTATUS
300NTAPI
301RtlUpcaseUnicodeToOemN(
302 _Out_ PCHAR OemString,
303 _In_ ULONG OemSize,
304 _Out_opt_ PULONG ResultSize,
305 _In_ PCWCH UnicodeString,
306 _In_ ULONG UnicodeSize)
307{
308 if (OemSize)
309 *OemString = ANSI_NULL;
310
311 if (ResultSize)
312 *ResultSize = 0;
313
314 return STATUS_NOT_IMPLEMENTED;
315}
316
317/* EOF */