4 * Copyright (C) 1996-1998 Marcus Meissner
5 * Copyright (C) 2000 Alexandre Julliard
13 #include "wine/unicode.h"
16 #include "debugtools.h"
17 #include "ntdll_misc.h"
20 DEFAULT_DEBUG_CHANNEL(ntdll);
22 /* STRING CREATION FUNCTIONS */
24 /**************************************************************************
25 * RtlInitAnsiString (NTDLL.@)
27 void WINAPI RtlInitAnsiString( PSTRING target, LPCSTR source)
29 if ((target->Buffer = (LPSTR)source))
31 target->Length = strlen(source);
32 target->MaximumLength = target->Length + 1;
34 else target->Length = target->MaximumLength = 0;
38 /**************************************************************************
39 * RtlInitString (NTDLL.@)
41 void WINAPI RtlInitString( PSTRING target, LPCSTR source )
43 return RtlInitAnsiString( target, source );
47 /**************************************************************************
48 * RtlFreeAnsiString (NTDLL.@)
50 void WINAPI RtlFreeAnsiString( PSTRING str )
52 if (str->Buffer) HeapFree( GetProcessHeap(), 0, str->Buffer );
56 /**************************************************************************
57 * RtlFreeOemString (NTDLL.@)
59 void WINAPI RtlFreeOemString( PSTRING str )
61 RtlFreeAnsiString( str );
65 /**************************************************************************
66 * RtlCopyString (NTDLL.@)
68 void WINAPI RtlCopyString( STRING *dst, const STRING *src )
72 unsigned int len = min( src->Length, dst->MaximumLength );
73 memcpy( dst->Buffer, src->Buffer, len );
80 /**************************************************************************
81 * RtlInitUnicodeString (NTDLL.@)
83 void WINAPI RtlInitUnicodeString( PUNICODE_STRING target, LPCWSTR source )
85 if ((target->Buffer = (LPWSTR)source))
87 target->Length = strlenW(source) * sizeof(WCHAR);
88 target->MaximumLength = target->Length + sizeof(WCHAR);
90 else target->Length = target->MaximumLength = 0;
94 /**************************************************************************
95 * RtlCreateUnicodeString (NTDLL.@)
97 BOOLEAN WINAPI RtlCreateUnicodeString( PUNICODE_STRING target, LPCWSTR src )
99 int len = (strlenW(src) + 1) * sizeof(WCHAR);
100 if (!(target->Buffer = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE;
101 memcpy( target->Buffer, src, len );
102 target->MaximumLength = len;
103 target->Length = len - 2;
108 /**************************************************************************
109 * RtlCreateUnicodeStringFromAsciiz (NTDLL.@)
111 BOOLEAN WINAPI RtlCreateUnicodeStringFromAsciiz( PUNICODE_STRING target, LPCSTR src )
114 RtlInitAnsiString( &ansi, src );
115 return !RtlAnsiStringToUnicodeString( target, &ansi, TRUE );
119 /**************************************************************************
120 * RtlFreeUnicodeString (NTDLL.@)
122 void WINAPI RtlFreeUnicodeString( PUNICODE_STRING str )
124 if (str->Buffer) HeapFree( GetProcessHeap(), 0, str->Buffer );
128 /**************************************************************************
129 * RtlCopyUnicodeString (NTDLL.@)
131 void WINAPI RtlCopyUnicodeString( UNICODE_STRING *dst, const UNICODE_STRING *src )
135 unsigned int len = min( src->Length, dst->MaximumLength );
136 memcpy( dst->Buffer, src->Buffer, len );
138 /* append terminating NULL if enough space */
139 if (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0;
141 else dst->Length = 0;
145 /**************************************************************************
146 * RtlEraseUnicodeString (NTDLL.@)
148 void WINAPI RtlEraseUnicodeString( UNICODE_STRING *str )
152 memset( str->Buffer, 0, str->MaximumLength );
161 /******************************************************************************
162 * RtlCompareString (NTDLL.@)
164 LONG WINAPI RtlCompareString( const STRING *s1, const STRING *s2, BOOLEAN CaseInsensitive )
170 len = min(s1->Length, s2->Length);
176 while (!ret && len--) ret = toupper(*p1++) - toupper(*p2++);
180 while (!ret && len--) ret = *p1++ - *p2++;
182 if (!ret) ret = s1->Length - s2->Length;
187 /******************************************************************************
188 * RtlCompareUnicodeString (NTDLL.@)
190 LONG WINAPI RtlCompareUnicodeString( const UNICODE_STRING *s1, const UNICODE_STRING *s2,
191 BOOLEAN CaseInsensitive )
197 len = min(s1->Length, s2->Length) / sizeof(WCHAR);
203 while (!ret && len--) ret = toupperW(*p1++) - toupperW(*p2++);
207 while (!ret && len--) ret = *p1++ - *p2++;
209 if (!ret) ret = s1->Length - s2->Length;
214 /**************************************************************************
215 * RtlEqualString (NTDLL.@)
217 BOOLEAN WINAPI RtlEqualString( const STRING *s1, const STRING *s2, BOOLEAN CaseInsensitive )
219 if (s1->Length != s2->Length) return FALSE;
220 return !RtlCompareString( s1, s2, CaseInsensitive );
224 /**************************************************************************
225 * RtlEqualUnicodeString (NTDLL.@)
227 BOOLEAN WINAPI RtlEqualUnicodeString( const UNICODE_STRING *s1, const UNICODE_STRING *s2,
228 BOOLEAN CaseInsensitive )
230 if (s1->Length != s2->Length) return FALSE;
231 return !RtlCompareUnicodeString( s1, s2, CaseInsensitive );
235 /**************************************************************************
236 * RtlPrefixString (NTDLL.@)
238 * Test if s1 is a prefix in s2
240 BOOLEAN WINAPI RtlPrefixString( const STRING *s1, const STRING *s2, BOOLEAN ignore_case )
244 if (s1->Length > s2->Length) return FALSE;
247 for (i = 0; i < s1->Length; i++)
248 if (toupper(s1->Buffer[i]) != toupper(s2->Buffer[i])) return FALSE;
252 for (i = 0; i < s1->Length; i++)
253 if (s1->Buffer[i] != s2->Buffer[i]) return FALSE;
259 /**************************************************************************
260 * RtlPrefixUnicodeString (NTDLL.@)
262 * Test if s1 is a prefix in s2
264 BOOLEAN WINAPI RtlPrefixUnicodeString( const UNICODE_STRING *s1,
265 const UNICODE_STRING *s2,
266 BOOLEAN ignore_case )
270 if (s1->Length > s2->Length) return FALSE;
273 for (i = 0; i < s1->Length / sizeof(WCHAR); i++)
274 if (toupper(s1->Buffer[i]) != toupper(s2->Buffer[i])) return FALSE;
278 for (i = 0; i < s1->Length / sizeof(WCHAR); i++)
279 if (s1->Buffer[i] != s2->Buffer[i]) return FALSE;
286 COPY BETWEEN ANSI_STRING or UNICODE_STRING
287 there is no parameter checking, it just crashes
291 /**************************************************************************
292 * RtlAnsiStringToUnicodeString (NTDLL.@)
295 * writes terminating 0
297 NTSTATUS WINAPI RtlAnsiStringToUnicodeString( UNICODE_STRING *uni,
301 DWORD len = MultiByteToWideChar( CP_ACP, 0, ansi->Buffer, ansi->Length, NULL, 0 );
302 DWORD total = (len + 1) * sizeof(WCHAR);
304 if (total > 0xffff) return STATUS_INVALID_PARAMETER_2;
305 uni->Length = len * sizeof(WCHAR);
308 uni->MaximumLength = total;
309 if (!(uni->Buffer = HeapAlloc( GetProcessHeap(), 0, total ))) return STATUS_NO_MEMORY;
311 else if (total > uni->MaximumLength) return STATUS_BUFFER_OVERFLOW;
313 MultiByteToWideChar( CP_ACP, 0, ansi->Buffer, ansi->Length, uni->Buffer, len );
314 uni->Buffer[len] = 0;
315 return STATUS_SUCCESS;
319 /**************************************************************************
320 * RtlOemStringToUnicodeString (NTDLL.@)
323 * writes terminating 0
324 * if resulting length > 0xffff it returns STATUS_INVALID_PARAMETER_2
326 NTSTATUS WINAPI RtlOemStringToUnicodeString( UNICODE_STRING *uni,
330 DWORD len = MultiByteToWideChar( CP_OEMCP, 0, oem->Buffer, oem->Length, NULL, 0 );
331 DWORD total = (len + 1) * sizeof(WCHAR);
333 if (total > 0xffff) return STATUS_INVALID_PARAMETER_2;
334 uni->Length = len * sizeof(WCHAR);
337 uni->MaximumLength = total;
338 if (!(uni->Buffer = HeapAlloc( GetProcessHeap(), 0, total ))) return STATUS_NO_MEMORY;
340 else if (total > uni->MaximumLength) return STATUS_BUFFER_OVERFLOW;
342 MultiByteToWideChar( CP_OEMCP, 0, oem->Buffer, oem->Length, uni->Buffer, len );
343 uni->Buffer[len] = 0;
344 return STATUS_SUCCESS;
348 /**************************************************************************
349 * RtlUnicodeStringToAnsiString (NTDLL.@)
352 * writes terminating 0
353 * copies a part if the buffer is too small
355 NTSTATUS WINAPI RtlUnicodeStringToAnsiString( STRING *ansi,
356 const UNICODE_STRING *uni,
359 NTSTATUS ret = STATUS_SUCCESS;
360 DWORD len = RtlUnicodeStringToAnsiSize( uni );
365 ansi->MaximumLength = len + 1;
366 if (!(ansi->Buffer = HeapAlloc( GetProcessHeap(), 0, len + 1 ))) return STATUS_NO_MEMORY;
368 else if (ansi->MaximumLength <= len)
370 if (!ansi->MaximumLength) return STATUS_BUFFER_OVERFLOW;
371 ansi->Length = ansi->MaximumLength - 1;
372 ret = STATUS_BUFFER_OVERFLOW;
375 WideCharToMultiByte( CP_ACP, 0, uni->Buffer, uni->Length / sizeof(WCHAR),
376 ansi->Buffer, ansi->Length, NULL, NULL );
377 ansi->Buffer[ansi->Length] = 0;
382 /**************************************************************************
383 * RtlUnicodeStringToOemString (NTDLL.@)
386 * allocates uni->Length+1
387 * writes terminating 0
389 NTSTATUS WINAPI RtlUnicodeStringToOemString( STRING *oem,
390 const UNICODE_STRING *uni,
393 NTSTATUS ret = STATUS_SUCCESS;
394 DWORD len = RtlUnicodeStringToOemSize( uni );
399 oem->MaximumLength = len + 1;
400 if (!(oem->Buffer = HeapAlloc( GetProcessHeap(), 0, len + 1 ))) return STATUS_NO_MEMORY;
402 else if (oem->MaximumLength <= len)
404 if (!oem->MaximumLength) return STATUS_BUFFER_OVERFLOW;
405 oem->Length = oem->MaximumLength - 1;
406 ret = STATUS_BUFFER_OVERFLOW;
409 WideCharToMultiByte( CP_OEMCP, 0, uni->Buffer, uni->Length / sizeof(WCHAR),
410 oem->Buffer, oem->Length, NULL, NULL );
411 oem->Buffer[oem->Length] = 0;
416 /**************************************************************************
417 * RtlMultiByteToUnicodeN (NTDLL.@)
420 * if unistr is too small a part is copied
422 NTSTATUS WINAPI RtlMultiByteToUnicodeN( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
423 LPCSTR src, DWORD srclen )
425 DWORD res = MultiByteToWideChar( CP_ACP, 0, src, srclen, dst, dstlen/sizeof(WCHAR) );
427 *reslen = res ? res * sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
428 return STATUS_SUCCESS;
432 /**************************************************************************
433 * RtlOemToUnicodeN (NTDLL.@)
435 NTSTATUS WINAPI RtlOemToUnicodeN( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
436 LPCSTR src, DWORD srclen )
438 DWORD res = MultiByteToWideChar( CP_OEMCP, 0, src, srclen, dst, dstlen/sizeof(WCHAR) );
440 *reslen = res ? res * sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
441 return STATUS_SUCCESS;
445 /**************************************************************************
446 * RtlUnicodeToMultiByteN (NTDLL.@)
448 NTSTATUS WINAPI RtlUnicodeToMultiByteN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
449 LPCWSTR src, DWORD srclen )
451 DWORD res = WideCharToMultiByte( CP_ACP, 0, src, srclen/sizeof(WCHAR),
452 dst, dstlen, NULL, NULL );
454 *reslen = res ? res * sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
455 return STATUS_SUCCESS;
459 /**************************************************************************
460 * RtlUnicodeToOemN (NTDLL.@)
462 NTSTATUS WINAPI RtlUnicodeToOemN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
463 LPCWSTR src, DWORD srclen )
465 DWORD res = WideCharToMultiByte( CP_OEMCP, 0, src, srclen/sizeof(WCHAR),
466 dst, dstlen, NULL, NULL );
468 *reslen = res ? res * sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
469 return STATUS_SUCCESS;
477 /**************************************************************************
478 * RtlUpperString (NTDLL.@)
480 void WINAPI RtlUpperString( STRING *dst, const STRING *src )
482 unsigned int i, len = min(src->Length, dst->MaximumLength);
484 for (i = 0; i < len; i++) dst->Buffer[i] = toupper(src->Buffer[i]);
489 /**************************************************************************
490 * RtlUpcaseUnicodeString (NTDLL.@)
493 * destination string is never 0-terminated because dest can be equal to src
494 * and src might be not 0-terminated
495 * dest.Length only set when success
497 NTSTATUS WINAPI RtlUpcaseUnicodeString( UNICODE_STRING *dest,
498 const UNICODE_STRING *src,
501 DWORD i, len = src->Length;
505 dest->MaximumLength = len;
506 if (!(dest->Buffer = HeapAlloc( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY;
508 else if (len > dest->MaximumLength) return STATUS_BUFFER_OVERFLOW;
510 for (i = 0; i < len/sizeof(WCHAR); i++) dest->Buffer[i] = toupperW(src->Buffer[i]);
512 return STATUS_SUCCESS;
516 /**************************************************************************
517 * RtlUpcaseUnicodeStringToAnsiString (NTDLL.@)
520 * writes terminating 0
522 NTSTATUS WINAPI RtlUpcaseUnicodeStringToAnsiString( STRING *dst,
523 const UNICODE_STRING *src,
527 UNICODE_STRING upcase;
529 if (!(ret = RtlUpcaseUnicodeString( &upcase, src, TRUE )))
531 ret = RtlUnicodeStringToAnsiString( dst, &upcase, doalloc );
532 RtlFreeUnicodeString( &upcase );
538 /**************************************************************************
539 * RtlUpcaseUnicodeStringToOemString (NTDLL.@)
542 * writes terminating 0
544 NTSTATUS WINAPI RtlUpcaseUnicodeStringToOemString( STRING *dst,
545 const UNICODE_STRING *src,
549 UNICODE_STRING upcase;
551 if (!(ret = RtlUpcaseUnicodeString( &upcase, src, TRUE )))
553 ret = RtlUnicodeStringToOemString( dst, &upcase, doalloc );
554 RtlFreeUnicodeString( &upcase );
560 /**************************************************************************
561 * RtlUpcaseUnicodeToMultiByteN (NTDLL.@)
563 NTSTATUS WINAPI RtlUpcaseUnicodeToMultiByteN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
564 LPCWSTR src, DWORD srclen )
570 if (!(upcase = HeapAlloc( GetProcessHeap(), 0, srclen ))) return STATUS_NO_MEMORY;
571 for (i = 0; i < srclen/sizeof(WCHAR); i++) upcase[i] = toupperW(src[i]);
572 ret = RtlUnicodeToMultiByteN( dst, dstlen, reslen, upcase, srclen );
573 HeapFree( GetProcessHeap(), 0, upcase );
578 /**************************************************************************
579 * RtlUpcaseUnicodeToOemN (NTDLL.@)
581 NTSTATUS WINAPI RtlUpcaseUnicodeToOemN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
582 LPCWSTR src, DWORD srclen )
588 if (!(upcase = HeapAlloc( GetProcessHeap(), 0, srclen ))) return STATUS_NO_MEMORY;
589 for (i = 0; i < srclen/sizeof(WCHAR); i++) upcase[i] = toupperW(src[i]);
590 ret = RtlUnicodeToOemN( dst, dstlen, reslen, upcase, srclen );
591 HeapFree( GetProcessHeap(), 0, upcase );
600 /**************************************************************************
601 * RtlOemStringToUnicodeSize (NTDLL.@)
603 * Return the size in bytes necessary for the Unicode conversion of 'str',
604 * including the terminating NULL.
606 UINT WINAPI RtlOemStringToUnicodeSize(PSTRING str)
608 DWORD ret = MultiByteToWideChar( CP_OEMCP, 0, str->Buffer, str->Length, NULL, 0 );
609 return (ret + 1) * sizeof(WCHAR);
613 /**************************************************************************
614 * RtlAnsiStringToUnicodeSize (NTDLL.@)
616 * Return the size in bytes necessary for the Unicode conversion of 'str',
617 * including the terminating NULL.
619 DWORD WINAPI RtlAnsiStringToUnicodeSize(PSTRING str)
621 DWORD ret = MultiByteToWideChar( CP_ACP, 0, str->Buffer, str->Length, NULL, 0 );
622 return (ret + 1) * sizeof(WCHAR);
626 /**************************************************************************
627 * RtlMultiByteToUnicodeSize (NTDLL.@)
629 * Compute the size in bytes necessary for the Unicode conversion of 'str',
630 * without the terminating NULL.
632 NTSTATUS WINAPI RtlMultiByteToUnicodeSize( DWORD *size, LPCSTR str, UINT len )
634 *size = MultiByteToWideChar( CP_ACP, 0, str, len, NULL, 0 ) * sizeof(WCHAR);
639 /**************************************************************************
640 * RtlUnicodeToMultiByteSize (NTDLL.@)
642 * Compute the size necessary for the multibyte conversion of 'str',
643 * without the terminating NULL.
645 NTSTATUS WINAPI RtlUnicodeToMultiByteSize( DWORD *size, LPCWSTR str, UINT len )
647 *size = WideCharToMultiByte( CP_ACP, 0, str, len / sizeof(WCHAR), NULL, 0, NULL, NULL );
652 /**************************************************************************
653 * RtlUnicodeStringToAnsiSize (NTDLL.@)
655 * Return the size in bytes necessary for the Ansi conversion of 'str',
656 * including the terminating NULL.
658 DWORD WINAPI RtlUnicodeStringToAnsiSize( const UNICODE_STRING *str )
660 return WideCharToMultiByte( CP_ACP, 0, str->Buffer, str->Length / sizeof(WCHAR),
661 NULL, 0, NULL, NULL ) + 1;
665 /**************************************************************************
666 * RtlUnicodeStringToOemSize (NTDLL.@)
668 * Return the size in bytes necessary for the OEM conversion of 'str',
669 * including the terminating NULL.
671 DWORD WINAPI RtlUnicodeStringToOemSize( const UNICODE_STRING *str )
673 return WideCharToMultiByte( CP_OEMCP, 0, str->Buffer, str->Length / sizeof(WCHAR),
674 NULL, 0, NULL, NULL ) + 1;
678 /**************************************************************************
679 * RtlAppendStringToString (NTDLL.@)
681 NTSTATUS WINAPI RtlAppendStringToString( STRING *dst, const STRING *src )
683 unsigned int len = src->Length + dst->Length;
684 if (len > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
685 memcpy( dst->Buffer + dst->Length, src->Buffer, src->Length );
687 return STATUS_SUCCESS;
691 /**************************************************************************
692 * RtlAppendAsciizToString (NTDLL.@)
694 NTSTATUS WINAPI RtlAppendAsciizToString( STRING *dst, LPCSTR src )
698 unsigned int srclen = strlen(src);
699 unsigned int total = srclen + dst->Length;
700 if (total > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
701 memcpy( dst->Buffer + dst->Length, src, srclen );
704 return STATUS_SUCCESS;
708 /**************************************************************************
709 * RtlAppendUnicodeToString (NTDLL.@)
711 NTSTATUS WINAPI RtlAppendUnicodeToString( UNICODE_STRING *dst, LPCWSTR src )
715 unsigned int srclen = strlenW(src) * sizeof(WCHAR);
716 unsigned int total = srclen + dst->Length;
717 if (total > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
718 memcpy( dst->Buffer + dst->Length/sizeof(WCHAR), src, srclen );
720 /* append terminating NULL if enough space */
721 if (total < dst->MaximumLength) dst->Buffer[total / sizeof(WCHAR)] = 0;
723 return STATUS_SUCCESS;
727 /**************************************************************************
728 * RtlAppendUnicodeStringToString (NTDLL.@)
730 NTSTATUS WINAPI RtlAppendUnicodeStringToString( UNICODE_STRING *dst, const UNICODE_STRING *src )
732 unsigned int len = src->Length + dst->Length;
733 if (len > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
734 memcpy( dst->Buffer + dst->Length/sizeof(WCHAR), src->Buffer, src->Length );
736 /* append terminating NULL if enough space */
737 if (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0;
738 return STATUS_SUCCESS;
746 /**************************************************************************
749 * Apply various feeble heuristics to guess whether
750 * the text buffer contains Unicode.
751 * FIXME: should implement more tests.
753 DWORD WINAPI RtlIsTextUnicode(
759 DWORD flags = -1, out_flags = 0;
766 * Apply various tests to the text string. According to the
767 * docs, each test "passed" sets the corresponding flag in
768 * the output flags. But some of the tests are mutually
769 * exclusive, so I don't see how you could pass all tests ...
772 /* Check for an odd length ... pass if even. */
774 out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
776 /* Check for the special unicode marker byte. */
778 out_flags |= IS_TEXT_UNICODE_SIGNATURE;
781 * Check whether the string passed all of the tests.
783 flags &= ITU_IMPLEMENTED_TESTS;
784 if ((out_flags & flags) != flags)