4 * Copyright 1996-1998 Marcus Meissner
12 #include "wine/winestring.h"
13 #include "wine/unicode.h"
17 #include "debugtools.h"
18 #include "ntdll_misc.h"
21 DEFAULT_DEBUG_CHANNEL(ntdll);
23 /* STRING FUNCTIONS */
25 /**************************************************************************
28 WCHAR CDECL NTDLL_towupper(WCHAR code)
30 return toupperW(code);
33 /**************************************************************************
36 WCHAR CDECL NTDLL_towlower(WCHAR code)
38 return tolowerW(code);
41 /**************************************************************************
44 VOID WINAPI RtlInitString(PSTRING target,LPCSTR source)
46 TRACE("%p %p(%s)\n", target, source, debugstr_a(source));
48 target->Buffer = (LPSTR)source;
51 target->Length = lstrlenA(source);
52 target->MaximumLength = target->Length+1;
56 target->Length = target->MaximumLength = 0;
64 /**************************************************************************
67 VOID WINAPI RtlInitAnsiString(
71 TRACE("%p %p(%s)\n", target, source, debugstr_a(source));
73 target->Buffer = (LPSTR)source;
76 target->Length = lstrlenA(source);
77 target->MaximumLength = target->Length+1;
81 target->Length = target->MaximumLength = 0;
85 /**************************************************************************
88 VOID WINAPI RtlFreeAnsiString(
89 PANSI_STRING AnsiString)
91 TRACE("%p\n", AnsiString);
92 dump_AnsiString(AnsiString, TRUE);
94 if( AnsiString->Buffer )
95 HeapFree( GetProcessHeap(),0,AnsiString->Buffer );
100 /* UNICODE FUNCTIONS */
102 /**************************************************************************
103 * RtlInitUnicodeString [NTDLL.403]
105 VOID WINAPI RtlInitUnicodeString(
106 PUNICODE_STRING target,
109 TRACE("%p %p(%s)\n", target, source, debugstr_w(source));
111 target->Buffer = (LPWSTR)source;
114 target->Length = lstrlenW(source)*2;
115 target->MaximumLength = target->Length + 2;
119 target->Length = target->MaximumLength = 0;
123 /**************************************************************************
124 * RtlFreeUnicodeString [NTDLL.377]
126 VOID WINAPI RtlFreeUnicodeString(
127 PUNICODE_STRING UnicodeString)
129 TRACE("%p\n", UnicodeString);
130 dump_UnicodeString(UnicodeString, TRUE);
132 if (UnicodeString->Buffer)
133 HeapFree(GetProcessHeap(),0,UnicodeString->Buffer);
140 /**************************************************************************
141 * RtlEqualUnicodeString
143 BOOLEAN WINAPI RtlEqualUnicodeString(
144 IN PUNICODE_STRING s1,
145 IN PUNICODE_STRING s2,
146 IN BOOLEAN CaseInsensitive)
149 TRACE("(%p,%p,%x)\n",s1,s2,CaseInsensitive);
150 dump_UnicodeString(s1, TRUE);
151 dump_UnicodeString(s2, TRUE);
153 if(!s1 || !s2 || !s1->Buffer || !s2->Buffer) return FALSE;
154 if (s1->Length != s2->Length) return FALSE;
157 ret = !CRTDLL__wcsnicmp(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
159 ret = !CRTDLL_wcsncmp(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
163 /******************************************************************************
164 * RtlCompareUnicodeString
166 LONG WINAPI RtlCompareUnicodeString(
169 BOOLEAN CaseInsensitive)
173 TRACE("(%p,%p,%x)\n",s1,s2,CaseInsensitive);
174 dump_UnicodeString(s1, TRUE);
175 dump_UnicodeString(s2, TRUE);
177 if(!s1 || !s2 || !s1->Buffer || !s2->Buffer) return FALSE;
179 if (s1->Length != s2->Length) return (s1->Length - s2->Length);
182 ret = CRTDLL__wcsnicmp(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
184 ret = CRTDLL_wcsncmp(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
189 COPY BETWEEN ANSI_STRING or UNICODE_STRING
190 there is no parameter checking, it just crashes
193 /**************************************************************************
194 * RtlAnsiStringToUnicodeString
197 * writes terminating 0
200 WINAPI RtlAnsiStringToUnicodeString(
205 int len = ansi->Length * sizeof(WCHAR);
207 TRACE("%p %p %u\n",uni, ansi, doalloc);
208 dump_AnsiString(ansi, TRUE);
209 dump_UnicodeString(uni, FALSE);
211 if (len>0xfffe) return STATUS_INVALID_PARAMETER_2;
215 uni->MaximumLength = len + sizeof(WCHAR);
216 uni->Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,uni->MaximumLength);
217 if (!uni->Buffer) return STATUS_NO_MEMORY;
219 else if (len+sizeof(WCHAR) > uni->MaximumLength)
221 return STATUS_BUFFER_OVERFLOW;
223 lstrcpynAtoW(uni->Buffer,ansi->Buffer,ansi->Length+1);
224 return STATUS_SUCCESS;
227 /**************************************************************************
228 * RtlUpcaseUnicodeString
231 * destination string is never 0-terminated because dest can be equal to src
232 * and src might be not 0-terminated
233 * dest.Length only set when success
235 DWORD WINAPI RtlUpcaseUnicodeString(
236 PUNICODE_STRING dest,
240 int i, len = src->Length;
242 TRACE("(%p,%p,%x)\n",dest, src, doalloc);
243 dump_UnicodeString(dest, FALSE);
244 dump_UnicodeString(src, TRUE);
248 dest->Buffer = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
249 if (!dest->Buffer) return STATUS_NO_MEMORY;
250 dest->MaximumLength = len;
252 else if (len > dest->MaximumLength)
254 return STATUS_BUFFER_OVERFLOW;
257 for (i=0; i < len/sizeof(WCHAR); i++)
259 dest->Buffer[i] = toupperW(src->Buffer[i]);
262 return STATUS_SUCCESS;
265 /**************************************************************************
266 * RtlOemStringToUnicodeString
269 * writes terminating 0
270 * buffer must be bigger than (ansi->Length+1)*2
271 * if astr.Length > 0x7ffe it returns STATUS_INVALID_PARAMETER_2
277 WINAPI RtlOemStringToUnicodeString(
282 int len = ansi->Length * sizeof(WCHAR);
284 if (len > 0xfffe) return STATUS_INVALID_PARAMETER_2;
289 uni->Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, len + sizeof(WCHAR));
290 if (!uni->Buffer) return STATUS_NO_MEMORY;
291 uni->MaximumLength = len + sizeof(WCHAR);
293 else if (len+1 > uni->MaximumLength )
295 return STATUS_BUFFER_OVERFLOW;
297 lstrcpynAtoW(uni->Buffer,ansi->Buffer,ansi->Length+1);
298 return STATUS_SUCCESS;
301 /**************************************************************************
302 * RtlUnicodeStringToOemString
305 * allocates uni->Length+1
306 * writes terminating 0
309 WINAPI RtlUnicodeStringToOemString(
314 int len = uni->Length/sizeof(WCHAR);
316 TRACE("%p %s %i\n", oem, debugstr_us(uni), doalloc);
321 oem->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len+1);
322 if (! oem->Buffer) return STATUS_NO_MEMORY;
323 oem->MaximumLength = len + 1;
325 else if (oem->MaximumLength <= len)
327 return STATUS_BUFFER_OVERFLOW;
329 lstrcpynWtoA(oem->Buffer, uni->Buffer, len+1);
330 return STATUS_SUCCESS;
333 /**************************************************************************
334 * RtlUpcaseUnicodeStringToOemString
337 * writes terminating 0
340 WINAPI RtlUpcaseUnicodeStringToOemString(
345 int i, len = uni->Length/sizeof(WCHAR);
347 TRACE("%p %s %i\n", oem, debugstr_us(uni), doalloc);
352 oem->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len+1);
353 if (! oem->Buffer) return STATUS_NO_MEMORY;
354 oem->MaximumLength = len + 1;
356 else if (oem->MaximumLength <= len)
358 return STATUS_BUFFER_OVERFLOW;
361 for (i=0; i < len; i++)
363 oem->Buffer[i] = toupperW((char)(uni->Buffer[i]));
366 return STATUS_SUCCESS;
369 /**************************************************************************
370 * RtlUnicodeStringToAnsiString
373 * writes terminating 0
374 * copys a part if the buffer is to small
377 WINAPI RtlUnicodeStringToAnsiString(
382 int len = uni->Length/sizeof(WCHAR);
383 NTSTATUS ret = STATUS_SUCCESS;
385 TRACE("%p %s %i\n", ansi, debugstr_us(uni), doalloc);
390 ansi->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len+1);
391 if (! ansi->Buffer) return STATUS_NO_MEMORY;
392 ansi->MaximumLength = len + 1;
394 else if (ansi->MaximumLength <= len)
396 ansi->Length = ansi->MaximumLength - 1;
397 ret = STATUS_BUFFER_OVERFLOW;
399 lstrcpynWtoA(ansi->Buffer, uni->Buffer, ansi->Length+1);
404 COPY BETWEEN ANSI/UNICODE_STRING AND MULTIBYTE STRINGS
406 /**************************************************************************
407 * RtlMultiByteToUnicodeN
410 * dest can be equal to src
411 * if unistr is to small a part is copyed
417 WINAPI RtlMultiByteToUnicodeN(
427 TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
429 len = (unilen/sizeof(WCHAR) < oemlen) ? unilen/sizeof(WCHAR) : oemlen;
431 for (i = len-1; i>=0; i--)
432 unistr[i] = (WCHAR)oemstr[i];
434 if (reslen) *reslen = len * 2;
438 /**************************************************************************
442 WINAPI RtlOemToUnicodeN(
452 TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
454 len = (unilen/sizeof(WCHAR) < oemlen) ? unilen/sizeof(WCHAR) : oemlen;
456 for (i = len-1; i>=0; i--)
457 unistr[i] = (WCHAR)oemstr[i];
459 if (reslen) *reslen = len * 2;
464 /**************************************************************************
468 WINAPI RtlUnicodeToOemN(
478 TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
480 len = (oemlen < unilen/sizeof(WCHAR)) ? unilen/sizeof(WCHAR) : oemlen;
482 for (i = len-1; i>=0; i--)
483 oemstr[i] = (CHAR)unistr[i];
485 if (reslen) *reslen = len * 2;
489 /**************************************************************************
490 * RtlUpcaseUnicodeToOemN
493 WINAPI RtlUpcaseUnicodeToOemN(
503 TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
505 len = (oemlen < unilen/sizeof(WCHAR)) ? unilen/sizeof(WCHAR) : oemlen;
507 for (i = len-1; i>=0; i--)
508 oemstr[i] = toupper((CHAR)unistr[i]);
510 if (reslen) *reslen = len * 2;
514 /**************************************************************************
515 * RtlUnicodeToMultiByteN
517 NTSTATUS WINAPI RtlUnicodeToMultiByteN(
521 PWCHAR UnicodeString,
526 TRACE("(%p,%lu,%p,%p(%s),%lu)\n",
527 MbString, MbSize, ResultSize, UnicodeString, debugstr_w(UnicodeString), UnicodeSize);
529 Size = (UnicodeSize > (MbSize*sizeof(WCHAR))) ? MbSize: UnicodeSize/sizeof(WCHAR);
531 if (ResultSize != NULL) *ResultSize = Size;
533 for(i = 0; i < Size; i++)
535 *(MbString++) = *(UnicodeString++);
537 return STATUS_SUCCESS;
543 Rtlx* supports multibyte
546 /**************************************************************************
547 * RtlxOemStringToUnicodeSize
549 UINT WINAPI RtlxOemStringToUnicodeSize(PSTRING str)
551 return str->Length*2+2;
554 /**************************************************************************
555 * RtlxAnsiStringToUnicodeSize
557 UINT WINAPI RtlxAnsiStringToUnicodeSize(PANSI_STRING str)
559 return str->Length*2+2;
562 /**************************************************************************
563 * RtlxUnicodeStringToOemSize
566 UINT WINAPI RtlxUnicodeStringToOemSize(PUNICODE_STRING str)
568 return str->Length+1;
575 /**************************************************************************
578 * Apply various feeble heuristics to guess whether
579 * the text buffer contains Unicode.
580 * FIXME: should implement more tests.
582 DWORD WINAPI RtlIsTextUnicode(
588 DWORD flags = -1, out_flags = 0;
595 * Apply various tests to the text string. According to the
596 * docs, each test "passed" sets the corresponding flag in
597 * the output flags. But some of the tests are mutually
598 * exclusive, so I don't see how you could pass all tests ...
601 /* Check for an odd length ... pass if even. */
603 out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
605 /* Check for the special unicode marker byte. */
607 out_flags |= IS_TEXT_UNICODE_SIGNATURE;
610 * Check whether the string passed all of the tests.
612 flags &= ITU_IMPLEMENTED_TESTS;
613 if ((out_flags & flags) != flags)
621 /**************************************************************************
622 * RtlPrefixUnicodeString
624 NTSTATUS WINAPI RtlPrefixUnicodeString(
629 TRACE("(%s,%s,%lx)\n",debugstr_us(a),debugstr_us(b),x);
630 return STATUS_SUCCESS;