4 * Copyright (C) 1996-1998 Marcus Meissner
5 * Copyright (C) 2000 Alexandre Julliard
13 #include "wine/unicode.h"
15 #include "debugtools.h"
16 #include "ntdll_misc.h"
19 DEFAULT_DEBUG_CHANNEL(ntdll);
21 /* STRING CREATION FUNCTIONS */
23 /**************************************************************************
24 * RtlInitAnsiString (NTDLL.@)
26 void WINAPI RtlInitAnsiString( PSTRING target, LPCSTR source)
28 if ((target->Buffer = (LPSTR)source))
30 target->Length = strlen(source);
31 target->MaximumLength = target->Length + 1;
33 else target->Length = target->MaximumLength = 0;
37 /**************************************************************************
38 * RtlInitString (NTDLL.@)
40 void WINAPI RtlInitString( PSTRING target, LPCSTR source )
42 return RtlInitAnsiString( target, source );
46 /**************************************************************************
47 * RtlFreeAnsiString (NTDLL.@)
49 void WINAPI RtlFreeAnsiString( PSTRING str )
51 if (str->Buffer) HeapFree( GetProcessHeap(), 0, str->Buffer );
55 /**************************************************************************
56 * RtlFreeOemString (NTDLL.@)
58 void WINAPI RtlFreeOemString( PSTRING str )
60 RtlFreeAnsiString( str );
64 /**************************************************************************
65 * RtlCopyString (NTDLL.@)
67 void WINAPI RtlCopyString( STRING *dst, const STRING *src )
71 unsigned int len = min( src->Length, dst->MaximumLength );
72 memcpy( dst->Buffer, src->Buffer, len );
79 /**************************************************************************
80 * RtlInitUnicodeString (NTDLL.@)
82 void WINAPI RtlInitUnicodeString( PUNICODE_STRING target, LPCWSTR source )
84 if ((target->Buffer = (LPWSTR)source))
86 target->Length = strlenW(source) * sizeof(WCHAR);
87 target->MaximumLength = target->Length + sizeof(WCHAR);
89 else target->Length = target->MaximumLength = 0;
93 /**************************************************************************
94 * RtlCreateUnicodeString (NTDLL.@)
96 BOOLEAN WINAPI RtlCreateUnicodeString( PUNICODE_STRING target, LPCWSTR src )
98 int len = (strlenW(src) + 1) * sizeof(WCHAR);
99 if (!(target->Buffer = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE;
100 memcpy( target->Buffer, src, len );
101 target->MaximumLength = len;
102 target->Length = len - 2;
107 /**************************************************************************
108 * RtlCreateUnicodeStringFromAsciiz (NTDLL.@)
110 BOOLEAN WINAPI RtlCreateUnicodeStringFromAsciiz( PUNICODE_STRING target, LPCSTR src )
113 RtlInitAnsiString( &ansi, src );
114 return !RtlAnsiStringToUnicodeString( target, &ansi, TRUE );
118 /**************************************************************************
119 * RtlFreeUnicodeString (NTDLL.@)
121 void WINAPI RtlFreeUnicodeString( PUNICODE_STRING str )
123 if (str->Buffer) HeapFree( GetProcessHeap(), 0, str->Buffer );
127 /**************************************************************************
128 * RtlCopyUnicodeString (NTDLL.@)
130 void WINAPI RtlCopyUnicodeString( UNICODE_STRING *dst, const UNICODE_STRING *src )
134 unsigned int len = min( src->Length, dst->MaximumLength );
135 memcpy( dst->Buffer, src->Buffer, len );
137 /* append terminating NULL if enough space */
138 if (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0;
140 else dst->Length = 0;
144 /**************************************************************************
145 * RtlEraseUnicodeString (NTDLL.@)
147 void WINAPI RtlEraseUnicodeString( UNICODE_STRING *str )
151 memset( str->Buffer, 0, str->MaximumLength );
160 /******************************************************************************
161 * RtlCompareString (NTDLL.@)
163 LONG WINAPI RtlCompareString( const STRING *s1, const STRING *s2, BOOLEAN CaseInsensitive )
169 len = min(s1->Length, s2->Length);
175 while (!ret && len--) ret = toupper(*p1++) - toupper(*p2++);
179 while (!ret && len--) ret = *p1++ - *p2++;
181 if (!ret) ret = s1->Length - s2->Length;
186 /******************************************************************************
187 * RtlCompareUnicodeString (NTDLL.@)
189 LONG WINAPI RtlCompareUnicodeString( const UNICODE_STRING *s1, const UNICODE_STRING *s2,
190 BOOLEAN CaseInsensitive )
196 len = min(s1->Length, s2->Length) / sizeof(WCHAR);
202 while (!ret && len--) ret = toupperW(*p1++) - toupperW(*p2++);
206 while (!ret && len--) ret = *p1++ - *p2++;
208 if (!ret) ret = s1->Length - s2->Length;
213 /**************************************************************************
214 * RtlEqualString (NTDLL.@)
216 BOOLEAN WINAPI RtlEqualString( const STRING *s1, const STRING *s2, BOOLEAN CaseInsensitive )
218 if (s1->Length != s2->Length) return FALSE;
219 return !RtlCompareString( s1, s2, CaseInsensitive );
223 /**************************************************************************
224 * RtlEqualUnicodeString (NTDLL.@)
226 BOOLEAN WINAPI RtlEqualUnicodeString( const UNICODE_STRING *s1, const UNICODE_STRING *s2,
227 BOOLEAN CaseInsensitive )
229 if (s1->Length != s2->Length) return FALSE;
230 return !RtlCompareUnicodeString( s1, s2, CaseInsensitive );
234 /**************************************************************************
235 * RtlPrefixString (NTDLL.@)
237 * Test if s1 is a prefix in s2
239 BOOLEAN WINAPI RtlPrefixString( const STRING *s1, const STRING *s2, BOOLEAN ignore_case )
243 if (s1->Length > s2->Length) return FALSE;
246 for (i = 0; i < s1->Length; i++)
247 if (toupper(s1->Buffer[i]) != toupper(s2->Buffer[i])) return FALSE;
251 for (i = 0; i < s1->Length; i++)
252 if (s1->Buffer[i] != s2->Buffer[i]) return FALSE;
258 /**************************************************************************
259 * RtlPrefixUnicodeString (NTDLL.@)
261 * Test if s1 is a prefix in s2
263 BOOLEAN WINAPI RtlPrefixUnicodeString( const UNICODE_STRING *s1,
264 const UNICODE_STRING *s2,
265 BOOLEAN ignore_case )
269 if (s1->Length > s2->Length) return FALSE;
272 for (i = 0; i < s1->Length / sizeof(WCHAR); i++)
273 if (toupper(s1->Buffer[i]) != toupper(s2->Buffer[i])) return FALSE;
277 for (i = 0; i < s1->Length / sizeof(WCHAR); i++)
278 if (s1->Buffer[i] != s2->Buffer[i]) return FALSE;
285 COPY BETWEEN ANSI_STRING or UNICODE_STRING
286 there is no parameter checking, it just crashes
290 /**************************************************************************
291 * RtlAnsiStringToUnicodeString (NTDLL.@)
294 * writes terminating 0
296 NTSTATUS WINAPI RtlAnsiStringToUnicodeString( UNICODE_STRING *uni,
300 DWORD len = MultiByteToWideChar( CP_ACP, 0, ansi->Buffer, ansi->Length, NULL, 0 );
301 DWORD total = (len + 1) * sizeof(WCHAR);
303 if (total > 0xffff) return STATUS_INVALID_PARAMETER_2;
304 uni->Length = len * sizeof(WCHAR);
307 uni->MaximumLength = total;
308 if (!(uni->Buffer = HeapAlloc( GetProcessHeap(), 0, total ))) return STATUS_NO_MEMORY;
310 else if (total > uni->MaximumLength) return STATUS_BUFFER_OVERFLOW;
312 MultiByteToWideChar( CP_ACP, 0, ansi->Buffer, ansi->Length, uni->Buffer, len );
313 uni->Buffer[len] = 0;
314 return STATUS_SUCCESS;
318 /**************************************************************************
319 * RtlOemStringToUnicodeString (NTDLL.@)
322 * writes terminating 0
323 * if resulting length > 0xffff it returns STATUS_INVALID_PARAMETER_2
325 NTSTATUS WINAPI RtlOemStringToUnicodeString( UNICODE_STRING *uni,
329 DWORD len = MultiByteToWideChar( CP_OEMCP, 0, oem->Buffer, oem->Length, NULL, 0 );
330 DWORD total = (len + 1) * sizeof(WCHAR);
332 if (total > 0xffff) return STATUS_INVALID_PARAMETER_2;
333 uni->Length = len * sizeof(WCHAR);
336 uni->MaximumLength = total;
337 if (!(uni->Buffer = HeapAlloc( GetProcessHeap(), 0, total ))) return STATUS_NO_MEMORY;
339 else if (total > uni->MaximumLength) return STATUS_BUFFER_OVERFLOW;
341 MultiByteToWideChar( CP_OEMCP, 0, oem->Buffer, oem->Length, uni->Buffer, len );
342 uni->Buffer[len] = 0;
343 return STATUS_SUCCESS;
347 /**************************************************************************
348 * RtlUnicodeStringToAnsiString (NTDLL.@)
351 * writes terminating 0
352 * copies a part if the buffer is too small
354 NTSTATUS WINAPI RtlUnicodeStringToAnsiString( STRING *ansi,
355 const UNICODE_STRING *uni,
358 NTSTATUS ret = STATUS_SUCCESS;
359 DWORD len = RtlUnicodeStringToAnsiSize( uni );
364 ansi->MaximumLength = len + 1;
365 if (!(ansi->Buffer = HeapAlloc( GetProcessHeap(), 0, len + 1 ))) return STATUS_NO_MEMORY;
367 else if (ansi->MaximumLength <= len)
369 if (!ansi->MaximumLength) return STATUS_BUFFER_OVERFLOW;
370 ansi->Length = ansi->MaximumLength - 1;
371 ret = STATUS_BUFFER_OVERFLOW;
374 WideCharToMultiByte( CP_ACP, 0, uni->Buffer, uni->Length / sizeof(WCHAR),
375 ansi->Buffer, ansi->Length, NULL, NULL );
376 ansi->Buffer[ansi->Length] = 0;
381 /**************************************************************************
382 * RtlUnicodeStringToOemString (NTDLL.@)
385 * allocates uni->Length+1
386 * writes terminating 0
388 NTSTATUS WINAPI RtlUnicodeStringToOemString( STRING *oem,
389 const UNICODE_STRING *uni,
392 NTSTATUS ret = STATUS_SUCCESS;
393 DWORD len = RtlUnicodeStringToOemSize( uni );
398 oem->MaximumLength = len + 1;
399 if (!(oem->Buffer = HeapAlloc( GetProcessHeap(), 0, len + 1 ))) return STATUS_NO_MEMORY;
401 else if (oem->MaximumLength <= len)
403 if (!oem->MaximumLength) return STATUS_BUFFER_OVERFLOW;
404 oem->Length = oem->MaximumLength - 1;
405 ret = STATUS_BUFFER_OVERFLOW;
408 WideCharToMultiByte( CP_OEMCP, 0, uni->Buffer, uni->Length / sizeof(WCHAR),
409 oem->Buffer, oem->Length, NULL, NULL );
410 oem->Buffer[oem->Length] = 0;
415 /**************************************************************************
416 * RtlMultiByteToUnicodeN (NTDLL.@)
419 * if unistr is too small a part is copied
421 NTSTATUS WINAPI RtlMultiByteToUnicodeN( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
422 LPCSTR src, DWORD srclen )
424 DWORD res = MultiByteToWideChar( CP_ACP, 0, src, srclen, dst, dstlen/sizeof(WCHAR) );
426 *reslen = res ? res * sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
427 return STATUS_SUCCESS;
431 /**************************************************************************
432 * RtlOemToUnicodeN (NTDLL.@)
434 NTSTATUS WINAPI RtlOemToUnicodeN( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
435 LPCSTR src, DWORD srclen )
437 DWORD res = MultiByteToWideChar( CP_OEMCP, 0, src, srclen, dst, dstlen/sizeof(WCHAR) );
439 *reslen = res ? res * sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
440 return STATUS_SUCCESS;
444 /**************************************************************************
445 * RtlUnicodeToMultiByteN (NTDLL.@)
447 NTSTATUS WINAPI RtlUnicodeToMultiByteN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
448 LPCWSTR src, DWORD srclen )
450 DWORD res = WideCharToMultiByte( CP_ACP, 0, src, srclen/sizeof(WCHAR),
451 dst, dstlen, NULL, NULL );
453 *reslen = res ? res * sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
454 return STATUS_SUCCESS;
458 /**************************************************************************
459 * RtlUnicodeToOemN (NTDLL.@)
461 NTSTATUS WINAPI RtlUnicodeToOemN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
462 LPCWSTR src, DWORD srclen )
464 DWORD res = WideCharToMultiByte( CP_OEMCP, 0, src, srclen/sizeof(WCHAR),
465 dst, dstlen, NULL, NULL );
467 *reslen = res ? res * sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
468 return STATUS_SUCCESS;
476 /**************************************************************************
477 * RtlUpperString (NTDLL.@)
479 void WINAPI RtlUpperString( STRING *dst, const STRING *src )
481 unsigned int i, len = min(src->Length, dst->MaximumLength);
483 for (i = 0; i < len; i++) dst->Buffer[i] = toupper(src->Buffer[i]);
488 /**************************************************************************
489 * RtlUpcaseUnicodeString (NTDLL.@)
492 * destination string is never 0-terminated because dest can be equal to src
493 * and src might be not 0-terminated
494 * dest.Length only set when success
496 NTSTATUS WINAPI RtlUpcaseUnicodeString( UNICODE_STRING *dest,
497 const UNICODE_STRING *src,
500 DWORD i, len = src->Length;
504 dest->MaximumLength = len;
505 if (!(dest->Buffer = HeapAlloc( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY;
507 else if (len > dest->MaximumLength) return STATUS_BUFFER_OVERFLOW;
509 for (i = 0; i < len/sizeof(WCHAR); i++) dest->Buffer[i] = toupperW(src->Buffer[i]);
511 return STATUS_SUCCESS;
515 /**************************************************************************
516 * RtlUpcaseUnicodeStringToAnsiString (NTDLL.@)
519 * writes terminating 0
521 NTSTATUS WINAPI RtlUpcaseUnicodeStringToAnsiString( STRING *dst,
522 const UNICODE_STRING *src,
526 UNICODE_STRING upcase;
528 if (!(ret = RtlUpcaseUnicodeString( &upcase, src, TRUE )))
530 ret = RtlUnicodeStringToAnsiString( dst, &upcase, doalloc );
531 RtlFreeUnicodeString( &upcase );
537 /**************************************************************************
538 * RtlUpcaseUnicodeStringToOemString (NTDLL.@)
541 * writes terminating 0
543 NTSTATUS WINAPI RtlUpcaseUnicodeStringToOemString( STRING *dst,
544 const UNICODE_STRING *src,
548 UNICODE_STRING upcase;
550 if (!(ret = RtlUpcaseUnicodeString( &upcase, src, TRUE )))
552 ret = RtlUnicodeStringToOemString( dst, &upcase, doalloc );
553 RtlFreeUnicodeString( &upcase );
559 /**************************************************************************
560 * RtlUpcaseUnicodeToMultiByteN (NTDLL.@)
562 NTSTATUS WINAPI RtlUpcaseUnicodeToMultiByteN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
563 LPCWSTR src, DWORD srclen )
569 if (!(upcase = HeapAlloc( GetProcessHeap(), 0, srclen ))) return STATUS_NO_MEMORY;
570 for (i = 0; i < srclen/sizeof(WCHAR); i++) upcase[i] = toupperW(src[i]);
571 ret = RtlUnicodeToMultiByteN( dst, dstlen, reslen, upcase, srclen );
572 HeapFree( GetProcessHeap(), 0, upcase );
577 /**************************************************************************
578 * RtlUpcaseUnicodeToOemN (NTDLL.@)
580 NTSTATUS WINAPI RtlUpcaseUnicodeToOemN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
581 LPCWSTR src, DWORD srclen )
587 if (!(upcase = HeapAlloc( GetProcessHeap(), 0, srclen ))) return STATUS_NO_MEMORY;
588 for (i = 0; i < srclen/sizeof(WCHAR); i++) upcase[i] = toupperW(src[i]);
589 ret = RtlUnicodeToOemN( dst, dstlen, reslen, upcase, srclen );
590 HeapFree( GetProcessHeap(), 0, upcase );
599 /**************************************************************************
600 * RtlOemStringToUnicodeSize (NTDLL.@)
601 * RtlxOemStringToUnicodeSize (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.@)
615 * RtlxAnsiStringToUnicodeSize (NTDLL.@)
617 * Return the size in bytes necessary for the Unicode conversion of 'str',
618 * including the terminating NULL.
620 DWORD WINAPI RtlAnsiStringToUnicodeSize(PSTRING str)
622 DWORD ret = MultiByteToWideChar( CP_ACP, 0, str->Buffer, str->Length, NULL, 0 );
623 return (ret + 1) * sizeof(WCHAR);
627 /**************************************************************************
628 * RtlMultiByteToUnicodeSize (NTDLL.@)
630 * Compute the size in bytes necessary for the Unicode conversion of 'str',
631 * without the terminating NULL.
633 NTSTATUS WINAPI RtlMultiByteToUnicodeSize( DWORD *size, LPCSTR str, UINT len )
635 *size = MultiByteToWideChar( CP_ACP, 0, str, len, NULL, 0 ) * sizeof(WCHAR);
640 /**************************************************************************
641 * RtlUnicodeToMultiByteSize (NTDLL.@)
643 * Compute the size necessary for the multibyte conversion of 'str',
644 * without the terminating NULL.
646 NTSTATUS WINAPI RtlUnicodeToMultiByteSize( DWORD *size, LPCWSTR str, UINT len )
648 *size = WideCharToMultiByte( CP_ACP, 0, str, len / sizeof(WCHAR), NULL, 0, NULL, NULL );
653 /**************************************************************************
654 * RtlUnicodeStringToAnsiSize (NTDLL.@)
655 * RtlxUnicodeStringToAnsiSize (NTDLL.@)
657 * Return the size in bytes necessary for the Ansi conversion of 'str',
658 * including the terminating NULL.
660 DWORD WINAPI RtlUnicodeStringToAnsiSize( const UNICODE_STRING *str )
662 return WideCharToMultiByte( CP_ACP, 0, str->Buffer, str->Length / sizeof(WCHAR),
663 NULL, 0, NULL, NULL ) + 1;
667 /**************************************************************************
668 * RtlUnicodeStringToOemSize (NTDLL.@)
669 * RtlxUnicodeStringToOemSize (NTDLL.@)
671 * Return the size in bytes necessary for the OEM conversion of 'str',
672 * including the terminating NULL.
674 DWORD WINAPI RtlUnicodeStringToOemSize( const UNICODE_STRING *str )
676 return WideCharToMultiByte( CP_OEMCP, 0, str->Buffer, str->Length / sizeof(WCHAR),
677 NULL, 0, NULL, NULL ) + 1;
681 /**************************************************************************
682 * RtlAppendStringToString (NTDLL.@)
684 NTSTATUS WINAPI RtlAppendStringToString( STRING *dst, const STRING *src )
686 unsigned int len = src->Length + dst->Length;
687 if (len > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
688 memcpy( dst->Buffer + dst->Length, src->Buffer, src->Length );
690 return STATUS_SUCCESS;
694 /**************************************************************************
695 * RtlAppendAsciizToString (NTDLL.@)
697 NTSTATUS WINAPI RtlAppendAsciizToString( STRING *dst, LPCSTR src )
701 unsigned int srclen = strlen(src);
702 unsigned int total = srclen + dst->Length;
703 if (total > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
704 memcpy( dst->Buffer + dst->Length, src, srclen );
707 return STATUS_SUCCESS;
711 /**************************************************************************
712 * RtlAppendUnicodeToString (NTDLL.@)
714 NTSTATUS WINAPI RtlAppendUnicodeToString( UNICODE_STRING *dst, LPCWSTR src )
718 unsigned int srclen = strlenW(src) * sizeof(WCHAR);
719 unsigned int total = srclen + dst->Length;
720 if (total > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
721 memcpy( dst->Buffer + dst->Length/sizeof(WCHAR), src, srclen );
723 /* append terminating NULL if enough space */
724 if (total < dst->MaximumLength) dst->Buffer[total / sizeof(WCHAR)] = 0;
726 return STATUS_SUCCESS;
730 /**************************************************************************
731 * RtlAppendUnicodeStringToString (NTDLL.@)
733 NTSTATUS WINAPI RtlAppendUnicodeStringToString( UNICODE_STRING *dst, const UNICODE_STRING *src )
735 unsigned int len = src->Length + dst->Length;
736 if (len > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
737 memcpy( dst->Buffer + dst->Length/sizeof(WCHAR), src->Buffer, src->Length );
739 /* append terminating NULL if enough space */
740 if (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0;
741 return STATUS_SUCCESS;
749 /**************************************************************************
750 * RtlIsTextUnicode (NTDLL.@)
752 * Apply various feeble heuristics to guess whether
753 * the text buffer contains Unicode.
754 * FIXME: should implement more tests.
756 DWORD WINAPI RtlIsTextUnicode(
762 DWORD flags = -1, out_flags = 0;
769 * Apply various tests to the text string. According to the
770 * docs, each test "passed" sets the corresponding flag in
771 * the output flags. But some of the tests are mutually
772 * exclusive, so I don't see how you could pass all tests ...
775 /* Check for an odd length ... pass if even. */
777 out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
779 /* Check for the special unicode marker byte. */
781 out_flags |= IS_TEXT_UNICODE_SIGNATURE;
784 * Check whether the string passed all of the tests.
786 flags &= ITU_IMPLEMENTED_TESTS;
787 if ((out_flags & flags) != flags)