xref: /reactos/boot/rtl/nlsboot.c (revision 24cb57fd)
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 
17 BOOLEAN NlsMbCodePageTag = FALSE;
18 
19 BOOLEAN NlsMbOemCodePageTag = FALSE;
20 PUSHORT NlsOemToUnicodeTable = NULL;
21 PCHAR NlsUnicodeToOemTable = NULL;
22 PUSHORT NlsUnicodeToMbOemTable = NULL;
23 PUSHORT NlsOemLeadByteInfo = NULL;
24 
25 USHORT NlsOemDefaultChar = '\0';
26 USHORT NlsUnicodeDefaultChar = 0;
27 
28 /* FUNCTIONS *****************************************************************/
29 
30 WCHAR
31 NTAPI
RtlpDowncaseUnicodeChar(_In_ WCHAR Source)32 RtlpDowncaseUnicodeChar(
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 
51 WCHAR
52 NTAPI
RtlDowncaseUnicodeChar(_In_ WCHAR Source)53 RtlDowncaseUnicodeChar(
54     _In_ WCHAR Source)
55 {
56     return RtlpDowncaseUnicodeChar(Source);
57 }
58 
59 _Use_decl_annotations_
60 NTSTATUS
61 NTAPI
RtlMultiByteToUnicodeN(_Out_ PWCH UnicodeString,_In_ ULONG UnicodeSize,_Out_opt_ PULONG ResultSize,_In_ PCCH MbString,_In_ ULONG MbSize)62 RtlMultiByteToUnicodeN(
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_
91 NTSTATUS
92 NTAPI
RtlMultiByteToUnicodeSize(_Out_ PULONG UnicodeSize,_In_ PCCH MbString,_In_ ULONG MbSize)93 RtlMultiByteToUnicodeSize(
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_
105 NTSTATUS
106 NTAPI
RtlUnicodeToMultiByteN(_Out_ PCHAR MbString,_In_ ULONG MbSize,_Out_opt_ PULONG ResultSize,_In_ PCWCH UnicodeString,_In_ ULONG UnicodeSize)107 RtlUnicodeToMultiByteN(
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_
143 NTSTATUS
144 NTAPI
RtlUnicodeToMultiByteSize(_Out_ PULONG MbSize,_In_ PCWCH UnicodeString,_In_ ULONG UnicodeSize)145 RtlUnicodeToMultiByteSize(
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 
158 WCHAR
159 NTAPI
RtlpUpcaseUnicodeChar(_In_ WCHAR Source)160 RtlpUpcaseUnicodeChar(
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 
174 WCHAR
175 NTAPI
RtlUpcaseUnicodeChar(_In_ WCHAR Source)176 RtlUpcaseUnicodeChar(
177     _In_ WCHAR Source)
178 {
179     return RtlpUpcaseUnicodeChar(Source);
180 }
181 
182 _Use_decl_annotations_
183 NTSTATUS
184 NTAPI
RtlUpcaseUnicodeToMultiByteN(_Out_ PCHAR MbString,_In_ ULONG MbSize,_Out_opt_ PULONG ResultSize,_In_ PCWCH UnicodeString,_In_ ULONG UnicodeSize)185 RtlUpcaseUnicodeToMultiByteN(
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 
227 CHAR
228 NTAPI
RtlUpperChar(_In_ CHAR Source)229 RtlUpperChar(
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_
261 NTSTATUS
262 NTAPI
RtlUnicodeToOemN(_Out_ PCHAR OemString,_In_ ULONG OemSize,_Out_opt_ PULONG ResultSize,_In_ PCWCH UnicodeString,_In_ ULONG UnicodeSize)263 RtlUnicodeToOemN(
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_
280 NTSTATUS
281 NTAPI
RtlOemToUnicodeN(_Out_ PWCHAR UnicodeString,_In_ ULONG UnicodeSize,_Out_opt_ PULONG ResultSize,_In_ PCCH OemString,_In_ ULONG OemSize)282 RtlOemToUnicodeN(
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_
299 NTSTATUS
300 NTAPI
RtlUpcaseUnicodeToOemN(_Out_ PCHAR OemString,_In_ ULONG OemSize,_Out_opt_ PULONG ResultSize,_In_ PCWCH UnicodeString,_In_ ULONG UnicodeSize)301 RtlUpcaseUnicodeToOemN(
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 */
318