4 * Copyright 1996-1998 Marcus Meissner
12 #include "wine/winestring.h"
16 #include "debugtools.h"
17 #include "ntdll_misc.h"
22 DEFAULT_DEBUG_CHANNEL(ntdll)
24 /* STRING FUNCTIONS */
26 /**************************************************************************
29 WCHAR CDECL NTDLL_towupper(WCHAR code)
31 const WCHAR * ptr = uprtable[HIBYTE(code)];
32 return ptr ? ptr[LOBYTE(code)] : code;
35 /**************************************************************************
38 WCHAR CDECL NTDLL_towlower(WCHAR code)
40 const WCHAR * ptr = lwrtable[HIBYTE(code)];
41 return ptr ? ptr[LOBYTE(code)] : code;
44 /**************************************************************************
47 VOID WINAPI RtlInitString(PSTRING target,LPCSTR source)
49 TRACE("%p %p(%s)\n", target, source, debugstr_a(source));
51 target->Buffer = (LPSTR)source;
54 target->Length = lstrlenA(source);
55 target->MaximumLength = target->Length+1;
59 target->Length = target->MaximumLength = 0;
67 /**************************************************************************
70 VOID WINAPI RtlInitAnsiString(
74 TRACE("%p %p(%s)\n", target, source, debugstr_a(source));
76 target->Buffer = (LPSTR)source;
79 target->Length = lstrlenA(source);
80 target->MaximumLength = target->Length+1;
84 target->Length = target->MaximumLength = 0;
88 /**************************************************************************
91 VOID WINAPI RtlFreeAnsiString(
92 PANSI_STRING AnsiString)
94 TRACE("%p\n", AnsiString);
95 dump_AnsiString(AnsiString, TRUE);
97 if( AnsiString->Buffer )
98 HeapFree( GetProcessHeap(),0,AnsiString->Buffer );
103 /* UNICODE FUNCTIONS */
105 /**************************************************************************
106 * RtlInitUnicodeString [NTDLL.403]
108 VOID WINAPI RtlInitUnicodeString(
109 PUNICODE_STRING target,
112 TRACE("%p %p(%s)\n", target, source, debugstr_w(source));
114 target->Buffer = (LPWSTR)source;
117 target->Length = lstrlenW(source)*2;
118 target->MaximumLength = target->Length + 2;
122 target->Length = target->MaximumLength = 0;
126 /**************************************************************************
127 * RtlFreeUnicodeString [NTDLL.377]
129 VOID WINAPI RtlFreeUnicodeString(
130 PUNICODE_STRING UnicodeString)
132 TRACE("%p\n", UnicodeString);
133 dump_UnicodeString(UnicodeString, TRUE);
135 if (UnicodeString->Buffer)
136 HeapFree(GetProcessHeap(),0,UnicodeString->Buffer);
143 /**************************************************************************
144 * RtlEqualUnicodeString
146 BOOLEAN WINAPI RtlEqualUnicodeString(
147 IN PUNICODE_STRING s1,
148 IN PUNICODE_STRING s2,
149 IN BOOLEAN CaseInsensitive)
152 TRACE("(%p,%p,%x)\n",s1,s2,CaseInsensitive);
153 dump_UnicodeString(s1, TRUE);
154 dump_UnicodeString(s2, TRUE);
156 if(!s1 || !s2 || !s1->Buffer || !s2->Buffer) return FALSE;
157 if (s1->Length != s2->Length) return FALSE;
160 ret = !CRTDLL__wcsnicmp(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
162 ret = !CRTDLL_wcsncmp(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
166 /******************************************************************************
167 * RtlCompareUnicodeString
169 LONG WINAPI RtlCompareUnicodeString(
172 BOOLEAN CaseInsensitive)
176 TRACE("(%p,%p,%x)\n",s1,s2,CaseInsensitive);
177 dump_UnicodeString(s1, TRUE);
178 dump_UnicodeString(s2, TRUE);
180 if(!s1 || !s2 || !s1->Buffer || !s2->Buffer) return FALSE;
182 if (s1->Length != s2->Length) return (s1->Length - s2->Length);
185 ret = CRTDLL__wcsnicmp(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
187 ret = CRTDLL_wcsncmp(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
192 COPY BETWEEN ANSI_STRING or UNICODE_STRING
193 there is no parameter checking, it just crashes
196 /**************************************************************************
197 * RtlAnsiStringToUnicodeString
200 * writes terminating 0
203 WINAPI RtlAnsiStringToUnicodeString(
208 int len = ansi->Length * sizeof(WCHAR);
210 TRACE("%p %p %u\n",uni, ansi, doalloc);
211 dump_AnsiString(ansi, TRUE);
212 dump_UnicodeString(uni, FALSE);
214 if (len>0xfffe) return STATUS_INVALID_PARAMETER_2;
218 uni->MaximumLength = len + sizeof(WCHAR);
219 uni->Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,uni->MaximumLength);
220 if (!uni->Buffer) return STATUS_NO_MEMORY;
222 else if (len+sizeof(WCHAR) > uni->MaximumLength)
224 return STATUS_BUFFER_OVERFLOW;
226 lstrcpynAtoW(uni->Buffer,ansi->Buffer,ansi->Length+1);
227 return STATUS_SUCCESS;
230 /**************************************************************************
231 * RtlUpcaseUnicodeString
234 * destination string is never 0-terminated because dest can be equal to src
235 * and src might be not 0-terminated
236 * dest.Length only set when success
238 DWORD WINAPI RtlUpcaseUnicodeString(
239 PUNICODE_STRING dest,
243 int i, len = src->Length;
245 TRACE("(%p,%p,%x)\n",dest, src, doalloc);
246 dump_UnicodeString(dest, FALSE);
247 dump_UnicodeString(src, TRUE);
251 dest->Buffer = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
252 if (!dest->Buffer) return STATUS_NO_MEMORY;
253 dest->MaximumLength = len;
255 else if (len > dest->MaximumLength)
257 return STATUS_BUFFER_OVERFLOW;
260 for (i=0; i < len/sizeof(WCHAR); i++)
262 dest->Buffer[i] = NTDLL_towupper(src->Buffer[i]);
265 return STATUS_SUCCESS;
268 /**************************************************************************
269 * RtlOemStringToUnicodeString
272 * writes terminating 0
273 * buffer must be bigger than (ansi->Length+1)*2
274 * if astr.Length > 0x7ffe it returns STATUS_INVALID_PARAMETER_2
280 WINAPI RtlOemStringToUnicodeString(
285 int len = ansi->Length * sizeof(WCHAR);
287 if (len > 0xfffe) return STATUS_INVALID_PARAMETER_2;
292 uni->Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, len + sizeof(WCHAR));
293 if (!uni->Buffer) return STATUS_NO_MEMORY;
294 uni->MaximumLength = len + sizeof(WCHAR);
296 else if (len+1 > uni->MaximumLength )
298 return STATUS_BUFFER_OVERFLOW;
300 lstrcpynAtoW(uni->Buffer,ansi->Buffer,ansi->Length+1);
301 return STATUS_SUCCESS;
304 /**************************************************************************
305 * RtlUnicodeStringToOemString
308 * allocates uni->Length+1
309 * writes terminating 0
312 WINAPI RtlUnicodeStringToOemString(
317 int len = uni->Length/sizeof(WCHAR);
319 TRACE("%p %s %i\n", oem, debugstr_us(uni), doalloc);
324 oem->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len+1);
325 if (! oem->Buffer) return STATUS_NO_MEMORY;
326 oem->MaximumLength = len + 1;
328 else if (oem->MaximumLength <= len)
330 return STATUS_BUFFER_OVERFLOW;
332 lstrcpynWtoA(oem->Buffer, uni->Buffer, len+1);
333 return STATUS_SUCCESS;
336 /**************************************************************************
337 * RtlUpcaseUnicodeStringToOemString
340 * writes terminating 0
343 WINAPI RtlUpcaseUnicodeStringToOemString(
348 int i, len = uni->Length/sizeof(WCHAR);
350 TRACE("%p %s %i\n", oem, debugstr_us(uni), doalloc);
355 oem->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len+1);
356 if (! oem->Buffer) return STATUS_NO_MEMORY;
357 oem->MaximumLength = len + 1;
359 else if (oem->MaximumLength <= len)
361 return STATUS_BUFFER_OVERFLOW;
364 for (i=0; i < len; i++)
366 oem->Buffer[i] = NTDLL_towupper((char)(uni->Buffer[i]));
369 return STATUS_SUCCESS;
372 /**************************************************************************
373 * RtlUnicodeStringToAnsiString
376 * writes terminating 0
377 * copys a part if the buffer is to small
380 WINAPI RtlUnicodeStringToAnsiString(
385 int len = uni->Length/sizeof(WCHAR);
386 NTSTATUS ret = STATUS_SUCCESS;
388 TRACE("%p %s %i\n", ansi, debugstr_us(uni), doalloc);
393 ansi->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len+1);
394 if (! ansi->Buffer) return STATUS_NO_MEMORY;
395 ansi->MaximumLength = len + 1;
397 else if (ansi->MaximumLength <= len)
399 ansi->Length = ansi->MaximumLength - 1;
400 ret = STATUS_BUFFER_OVERFLOW;
402 lstrcpynWtoA(ansi->Buffer, uni->Buffer, ansi->Length+1);
407 COPY BETWEEN ANSI/UNICODE_STRING AND MULTIBYTE STRINGS
409 /**************************************************************************
410 * RtlMultiByteToUnicodeN
413 * dest can be equal to src
414 * if unistr is to small a part is copyed
420 WINAPI RtlMultiByteToUnicodeN(
430 TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
432 len = (unilen/sizeof(WCHAR) < oemlen) ? unilen/sizeof(WCHAR) : oemlen;
434 for (i = len-1; i>=0; i--)
435 unistr[i] = (WCHAR)oemstr[i];
437 if (reslen) *reslen = len * 2;
441 /**************************************************************************
445 WINAPI RtlOemToUnicodeN(
455 TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
457 len = (unilen/sizeof(WCHAR) < oemlen) ? unilen/sizeof(WCHAR) : oemlen;
459 for (i = len-1; i>=0; i--)
460 unistr[i] = (WCHAR)oemstr[i];
462 if (reslen) *reslen = len * 2;
467 /**************************************************************************
471 WINAPI RtlUnicodeToOemN(
481 TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
483 len = (oemlen < unilen/sizeof(WCHAR)) ? unilen/sizeof(WCHAR) : oemlen;
485 for (i = len-1; i>=0; i--)
486 oemstr[i] = (CHAR)unistr[i];
488 if (reslen) *reslen = len * 2;
492 /**************************************************************************
493 * RtlUpcaseUnicodeToOemN
496 WINAPI RtlUpcaseUnicodeToOemN(
506 TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
508 len = (oemlen < unilen/sizeof(WCHAR)) ? unilen/sizeof(WCHAR) : oemlen;
510 for (i = len-1; i>=0; i--)
511 oemstr[i] = toupper((CHAR)unistr[i]);
513 if (reslen) *reslen = len * 2;
517 /**************************************************************************
518 * RtlUnicodeToMultiByteN
520 NTSTATUS WINAPI RtlUnicodeToMultiByteN(
524 PWCHAR UnicodeString,
529 TRACE("(%p,%lu,%p,%p(%s),%lu)\n",
530 MbString, MbSize, ResultSize, UnicodeString, debugstr_w(UnicodeString), UnicodeSize);
532 Size = (UnicodeSize > (MbSize*sizeof(WCHAR))) ? MbSize: UnicodeSize/sizeof(WCHAR);
534 if (ResultSize != NULL) *ResultSize = Size;
536 for(i = 0; i < Size; i++)
538 *(MbString++) = *(UnicodeString++);
540 return STATUS_SUCCESS;
546 Rtlx* supports multibyte
549 /**************************************************************************
550 * RtlxOemStringToUnicodeSize
552 UINT WINAPI RtlxOemStringToUnicodeSize(PSTRING str)
554 return str->Length*2+2;
557 /**************************************************************************
558 * RtlxAnsiStringToUnicodeSize
560 UINT WINAPI RtlxAnsiStringToUnicodeSize(PANSI_STRING str)
562 return str->Length*2+2;
565 /**************************************************************************
566 * RtlxUnicodeStringToOemSize
569 UINT WINAPI RtlxUnicodeStringToOemSize(PUNICODE_STRING str)
571 return str->Length+1;
578 /**************************************************************************
581 * Apply various feeble heuristics to guess whether
582 * the text buffer contains Unicode.
583 * FIXME: should implement more tests.
585 DWORD WINAPI RtlIsTextUnicode(
591 DWORD flags = -1, out_flags = 0;
598 * Apply various tests to the text string. According to the
599 * docs, each test "passed" sets the corresponding flag in
600 * the output flags. But some of the tests are mutually
601 * exclusive, so I don't see how you could pass all tests ...
604 /* Check for an odd length ... pass if even. */
606 out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
608 /* Check for the special unicode marker byte. */
610 out_flags |= IS_TEXT_UNICODE_SIGNATURE;
613 * Check whether the string passed all of the tests.
615 flags &= ITU_IMPLEMENTED_TESTS;
616 if ((out_flags & flags) != flags)
624 /**************************************************************************
625 * RtlPrefixUnicodeString
627 NTSTATUS WINAPI RtlPrefixUnicodeString(
632 TRACE("(%s,%s,%lx)\n",debugstr_us(a),debugstr_us(b),x);
633 return STATUS_SUCCESS;