Convert MRULists to Unicode.
[wine/testsucceed.git] / dlls / ntdll / rtlstr.c
blob13164b9845196803300d341fc4924c7bcda080d3
1 /*
2 * Rtl string functions
4 * Copyright (C) 1996-1998 Marcus Meissner
5 * Copyright (C) 2000 Alexandre Julliard
6 */
8 #include "config.h"
10 #include <assert.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ctype.h>
15 #include "ntddk.h"
16 #include "wine/unicode.h"
17 #include "debugtools.h"
19 DEFAULT_DEBUG_CHANNEL(ntdll);
21 UINT NlsAnsiCodePage = 1252;
22 BYTE NlsMbCodePageTag = 0;
23 BYTE NlsMbOemCodePageTag = 0;
25 static const union cptable *ansi_table;
26 static const union cptable *oem_table;
28 inline static const union cptable *get_ansi_table(void)
30 if (!ansi_table) ansi_table = cp_get_table( 1252 );
31 return ansi_table;
34 inline static const union cptable *get_oem_table(void)
36 if (!oem_table) oem_table = cp_get_table( 437 );
37 return oem_table;
41 /**************************************************************************
42 * __wine_init_codepages (NTDLL.@)
44 * Set the code page once kernel32 is loaded. Should be done differently.
46 void __wine_init_codepages( const union cptable *ansi, const union cptable *oem )
48 ansi_table = ansi;
49 oem_table = oem;
50 NlsAnsiCodePage = ansi->info.codepage;
54 /**************************************************************************
55 * RtlInitAnsiString (NTDLL.@)
57 void WINAPI RtlInitAnsiString( PSTRING target, LPCSTR source)
59 if ((target->Buffer = (LPSTR)source))
61 target->Length = strlen(source);
62 target->MaximumLength = target->Length + 1;
64 else target->Length = target->MaximumLength = 0;
68 /**************************************************************************
69 * RtlInitString (NTDLL.@)
71 void WINAPI RtlInitString( PSTRING target, LPCSTR source )
73 return RtlInitAnsiString( target, source );
77 /**************************************************************************
78 * RtlFreeAnsiString (NTDLL.@)
80 void WINAPI RtlFreeAnsiString( PSTRING str )
82 if (str->Buffer) RtlFreeHeap( GetProcessHeap(), 0, str->Buffer );
86 /**************************************************************************
87 * RtlFreeOemString (NTDLL.@)
89 void WINAPI RtlFreeOemString( PSTRING str )
91 RtlFreeAnsiString( str );
95 /**************************************************************************
96 * RtlCopyString (NTDLL.@)
98 void WINAPI RtlCopyString( STRING *dst, const STRING *src )
100 if (src)
102 unsigned int len = min( src->Length, dst->MaximumLength );
103 memcpy( dst->Buffer, src->Buffer, len );
104 dst->Length = len;
106 else dst->Length = 0;
110 /**************************************************************************
111 * RtlInitUnicodeString (NTDLL.@)
113 void WINAPI RtlInitUnicodeString( PUNICODE_STRING target, LPCWSTR source )
115 if ((target->Buffer = (LPWSTR)source))
117 target->Length = strlenW(source) * sizeof(WCHAR);
118 target->MaximumLength = target->Length + sizeof(WCHAR);
120 else target->Length = target->MaximumLength = 0;
124 /**************************************************************************
125 * RtlCreateUnicodeString (NTDLL.@)
127 BOOLEAN WINAPI RtlCreateUnicodeString( PUNICODE_STRING target, LPCWSTR src )
129 int len = (strlenW(src) + 1) * sizeof(WCHAR);
130 if (!(target->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return FALSE;
131 memcpy( target->Buffer, src, len );
132 target->MaximumLength = len;
133 target->Length = len - 2;
134 return TRUE;
138 /**************************************************************************
139 * RtlCreateUnicodeStringFromAsciiz (NTDLL.@)
141 BOOLEAN WINAPI RtlCreateUnicodeStringFromAsciiz( PUNICODE_STRING target, LPCSTR src )
143 STRING ansi;
144 RtlInitAnsiString( &ansi, src );
145 return !RtlAnsiStringToUnicodeString( target, &ansi, TRUE );
149 /**************************************************************************
150 * RtlFreeUnicodeString (NTDLL.@)
152 void WINAPI RtlFreeUnicodeString( PUNICODE_STRING str )
154 if (str->Buffer) RtlFreeHeap( GetProcessHeap(), 0, str->Buffer );
158 /**************************************************************************
159 * RtlCopyUnicodeString (NTDLL.@)
161 void WINAPI RtlCopyUnicodeString( UNICODE_STRING *dst, const UNICODE_STRING *src )
163 if (src)
165 unsigned int len = min( src->Length, dst->MaximumLength );
166 memcpy( dst->Buffer, src->Buffer, len );
167 dst->Length = len;
168 /* append terminating NULL if enough space */
169 if (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0;
171 else dst->Length = 0;
175 /**************************************************************************
176 * RtlEraseUnicodeString (NTDLL.@)
178 void WINAPI RtlEraseUnicodeString( UNICODE_STRING *str )
180 if (str->Buffer)
182 memset( str->Buffer, 0, str->MaximumLength );
183 str->Length = 0;
188 COMPARISON FUNCTIONS
191 /******************************************************************************
192 * RtlCompareString (NTDLL.@)
194 LONG WINAPI RtlCompareString( const STRING *s1, const STRING *s2, BOOLEAN CaseInsensitive )
196 unsigned int len;
197 LONG ret = 0;
198 LPCSTR p1, p2;
200 len = min(s1->Length, s2->Length);
201 p1 = s1->Buffer;
202 p2 = s2->Buffer;
204 if (CaseInsensitive)
206 while (!ret && len--) ret = toupper(*p1++) - toupper(*p2++);
208 else
210 while (!ret && len--) ret = *p1++ - *p2++;
212 if (!ret) ret = s1->Length - s2->Length;
213 return ret;
217 /******************************************************************************
218 * RtlCompareUnicodeString (NTDLL.@)
220 LONG WINAPI RtlCompareUnicodeString( const UNICODE_STRING *s1, const UNICODE_STRING *s2,
221 BOOLEAN CaseInsensitive )
223 unsigned int len;
224 LONG ret = 0;
225 LPCWSTR p1, p2;
227 len = min(s1->Length, s2->Length) / sizeof(WCHAR);
228 p1 = s1->Buffer;
229 p2 = s2->Buffer;
231 if (CaseInsensitive)
233 while (!ret && len--) ret = toupperW(*p1++) - toupperW(*p2++);
235 else
237 while (!ret && len--) ret = *p1++ - *p2++;
239 if (!ret) ret = s1->Length - s2->Length;
240 return ret;
244 /**************************************************************************
245 * RtlEqualString (NTDLL.@)
247 BOOLEAN WINAPI RtlEqualString( const STRING *s1, const STRING *s2, BOOLEAN CaseInsensitive )
249 if (s1->Length != s2->Length) return FALSE;
250 return !RtlCompareString( s1, s2, CaseInsensitive );
254 /**************************************************************************
255 * RtlEqualUnicodeString (NTDLL.@)
257 BOOLEAN WINAPI RtlEqualUnicodeString( const UNICODE_STRING *s1, const UNICODE_STRING *s2,
258 BOOLEAN CaseInsensitive )
260 if (s1->Length != s2->Length) return FALSE;
261 return !RtlCompareUnicodeString( s1, s2, CaseInsensitive );
265 /**************************************************************************
266 * RtlPrefixString (NTDLL.@)
268 * Test if s1 is a prefix in s2
270 BOOLEAN WINAPI RtlPrefixString( const STRING *s1, const STRING *s2, BOOLEAN ignore_case )
272 unsigned int i;
274 if (s1->Length > s2->Length) return FALSE;
275 if (ignore_case)
277 for (i = 0; i < s1->Length; i++)
278 if (toupper(s1->Buffer[i]) != toupper(s2->Buffer[i])) return FALSE;
280 else
282 for (i = 0; i < s1->Length; i++)
283 if (s1->Buffer[i] != s2->Buffer[i]) return FALSE;
285 return TRUE;
289 /**************************************************************************
290 * RtlPrefixUnicodeString (NTDLL.@)
292 * Test if s1 is a prefix in s2
294 BOOLEAN WINAPI RtlPrefixUnicodeString( const UNICODE_STRING *s1,
295 const UNICODE_STRING *s2,
296 BOOLEAN ignore_case )
298 unsigned int i;
300 if (s1->Length > s2->Length) return FALSE;
301 if (ignore_case)
303 for (i = 0; i < s1->Length / sizeof(WCHAR); i++)
304 if (toupper(s1->Buffer[i]) != toupper(s2->Buffer[i])) return FALSE;
306 else
308 for (i = 0; i < s1->Length / sizeof(WCHAR); i++)
309 if (s1->Buffer[i] != s2->Buffer[i]) return FALSE;
311 return TRUE;
316 COPY BETWEEN ANSI_STRING or UNICODE_STRING
317 there is no parameter checking, it just crashes
321 /**************************************************************************
322 * RtlAnsiStringToUnicodeString (NTDLL.@)
324 * NOTES:
325 * writes terminating 0
327 NTSTATUS WINAPI RtlAnsiStringToUnicodeString( UNICODE_STRING *uni,
328 const STRING *ansi,
329 BOOLEAN doalloc )
331 DWORD total = RtlAnsiStringToUnicodeSize( ansi );
333 if (total > 0xffff) return STATUS_INVALID_PARAMETER_2;
334 uni->Length = total - sizeof(WCHAR);
335 if (doalloc)
337 uni->MaximumLength = total;
338 if (!(uni->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, total ))) return STATUS_NO_MEMORY;
340 else if (total > uni->MaximumLength) return STATUS_BUFFER_OVERFLOW;
342 RtlMultiByteToUnicodeN( uni->Buffer, uni->Length, NULL, ansi->Buffer, ansi->Length );
343 uni->Buffer[uni->Length / sizeof(WCHAR)] = 0;
344 return STATUS_SUCCESS;
348 /**************************************************************************
349 * RtlOemStringToUnicodeString (NTDLL.@)
351 * NOTES
352 * writes terminating 0
353 * if resulting length > 0xffff it returns STATUS_INVALID_PARAMETER_2
355 NTSTATUS WINAPI RtlOemStringToUnicodeString( UNICODE_STRING *uni,
356 const STRING *oem,
357 BOOLEAN doalloc )
359 DWORD total = RtlOemStringToUnicodeSize( oem );
361 if (total > 0xffff) return STATUS_INVALID_PARAMETER_2;
362 uni->Length = total - sizeof(WCHAR);
363 if (doalloc)
365 uni->MaximumLength = total;
366 if (!(uni->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, total ))) return STATUS_NO_MEMORY;
368 else if (total > uni->MaximumLength) return STATUS_BUFFER_OVERFLOW;
370 RtlOemToUnicodeN( uni->Buffer, uni->Length, NULL, oem->Buffer, oem->Length );
371 uni->Buffer[uni->Length / sizeof(WCHAR)] = 0;
372 return STATUS_SUCCESS;
376 /**************************************************************************
377 * RtlUnicodeStringToAnsiString (NTDLL.@)
379 * NOTES
380 * writes terminating 0
381 * copies a part if the buffer is too small
383 NTSTATUS WINAPI RtlUnicodeStringToAnsiString( STRING *ansi,
384 const UNICODE_STRING *uni,
385 BOOLEAN doalloc )
387 NTSTATUS ret = STATUS_SUCCESS;
388 DWORD len = RtlUnicodeStringToAnsiSize( uni );
390 ansi->Length = len;
391 if (doalloc)
393 ansi->MaximumLength = len + 1;
394 if (!(ansi->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len + 1 ))) return STATUS_NO_MEMORY;
396 else if (ansi->MaximumLength <= len)
398 if (!ansi->MaximumLength) return STATUS_BUFFER_OVERFLOW;
399 ansi->Length = ansi->MaximumLength - 1;
400 ret = STATUS_BUFFER_OVERFLOW;
403 RtlUnicodeToMultiByteN( ansi->Buffer, ansi->Length, NULL, uni->Buffer, uni->Length );
404 ansi->Buffer[ansi->Length] = 0;
405 return ret;
409 /**************************************************************************
410 * RtlUnicodeStringToOemString (NTDLL.@)
412 * NOTES
413 * allocates uni->Length+1
414 * writes terminating 0
416 NTSTATUS WINAPI RtlUnicodeStringToOemString( STRING *oem,
417 const UNICODE_STRING *uni,
418 BOOLEAN doalloc )
420 NTSTATUS ret = STATUS_SUCCESS;
421 DWORD len = RtlUnicodeStringToOemSize( uni );
423 oem->Length = len;
424 if (doalloc)
426 oem->MaximumLength = len + 1;
427 if (!(oem->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len + 1 ))) return STATUS_NO_MEMORY;
429 else if (oem->MaximumLength <= len)
431 if (!oem->MaximumLength) return STATUS_BUFFER_OVERFLOW;
432 oem->Length = oem->MaximumLength - 1;
433 ret = STATUS_BUFFER_OVERFLOW;
436 RtlUnicodeToOemN( oem->Buffer, oem->Length, NULL, uni->Buffer, uni->Length );
437 oem->Buffer[oem->Length] = 0;
438 return ret;
442 /**************************************************************************
443 * RtlMultiByteToUnicodeN (NTDLL.@)
445 * NOTES
446 * if unistr is too small a part is copied
448 NTSTATUS WINAPI RtlMultiByteToUnicodeN( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
449 LPCSTR src, DWORD srclen )
452 int ret = cp_mbstowcs( get_ansi_table(), 0, src, srclen, dst, dstlen/sizeof(WCHAR) );
453 if (reslen)
454 *reslen = (ret >= 0) ? ret*sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
455 return STATUS_SUCCESS;
459 /**************************************************************************
460 * RtlOemToUnicodeN (NTDLL.@)
462 NTSTATUS WINAPI RtlOemToUnicodeN( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
463 LPCSTR src, DWORD srclen )
465 int ret = cp_mbstowcs( get_oem_table(), 0, src, srclen, dst, dstlen/sizeof(WCHAR) );
466 if (reslen)
467 *reslen = (ret >= 0) ? ret*sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
468 return STATUS_SUCCESS;
472 /**************************************************************************
473 * RtlUnicodeToMultiByteN (NTDLL.@)
475 NTSTATUS WINAPI RtlUnicodeToMultiByteN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
476 LPCWSTR src, DWORD srclen )
478 int ret = cp_wcstombs( get_ansi_table(), 0, src, srclen / sizeof(WCHAR),
479 dst, dstlen, NULL, NULL );
480 if (reslen)
481 *reslen = (ret >= 0) ? ret : dstlen; /* overflow -> we filled up to dstlen */
482 return STATUS_SUCCESS;
486 /**************************************************************************
487 * RtlUnicodeToOemN (NTDLL.@)
489 NTSTATUS WINAPI RtlUnicodeToOemN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
490 LPCWSTR src, DWORD srclen )
492 int ret = cp_wcstombs( get_oem_table(), 0, src, srclen / sizeof(WCHAR),
493 dst, dstlen, NULL, NULL );
494 if (reslen)
495 *reslen = (ret >= 0) ? ret : dstlen; /* overflow -> we filled up to dstlen */
496 return STATUS_SUCCESS;
501 CASE CONVERSIONS
504 /**************************************************************************
505 * RtlUpperString (NTDLL.@)
507 void WINAPI RtlUpperString( STRING *dst, const STRING *src )
509 unsigned int i, len = min(src->Length, dst->MaximumLength);
511 for (i = 0; i < len; i++) dst->Buffer[i] = toupper(src->Buffer[i]);
512 dst->Length = len;
516 /**************************************************************************
517 * RtlUpcaseUnicodeString (NTDLL.@)
519 * NOTES:
520 * destination string is never 0-terminated because dest can be equal to src
521 * and src might be not 0-terminated
522 * dest.Length only set when success
524 NTSTATUS WINAPI RtlUpcaseUnicodeString( UNICODE_STRING *dest,
525 const UNICODE_STRING *src,
526 BOOLEAN doalloc )
528 DWORD i, len = src->Length;
530 if (doalloc)
532 dest->MaximumLength = len;
533 if (!(dest->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY;
535 else if (len > dest->MaximumLength) return STATUS_BUFFER_OVERFLOW;
537 for (i = 0; i < len/sizeof(WCHAR); i++) dest->Buffer[i] = toupperW(src->Buffer[i]);
538 dest->Length = len;
539 return STATUS_SUCCESS;
543 /**************************************************************************
544 * RtlUpcaseUnicodeStringToAnsiString (NTDLL.@)
546 * NOTES
547 * writes terminating 0
549 NTSTATUS WINAPI RtlUpcaseUnicodeStringToAnsiString( STRING *dst,
550 const UNICODE_STRING *src,
551 BOOLEAN doalloc )
553 NTSTATUS ret;
554 UNICODE_STRING upcase;
556 if (!(ret = RtlUpcaseUnicodeString( &upcase, src, TRUE )))
558 ret = RtlUnicodeStringToAnsiString( dst, &upcase, doalloc );
559 RtlFreeUnicodeString( &upcase );
561 return ret;
565 /**************************************************************************
566 * RtlUpcaseUnicodeStringToOemString (NTDLL.@)
568 * NOTES
569 * writes terminating 0
571 NTSTATUS WINAPI RtlUpcaseUnicodeStringToOemString( STRING *dst,
572 const UNICODE_STRING *src,
573 BOOLEAN doalloc )
575 NTSTATUS ret;
576 UNICODE_STRING upcase;
578 if (!(ret = RtlUpcaseUnicodeString( &upcase, src, TRUE )))
580 ret = RtlUnicodeStringToOemString( dst, &upcase, doalloc );
581 RtlFreeUnicodeString( &upcase );
583 return ret;
587 /**************************************************************************
588 * RtlUpcaseUnicodeToMultiByteN (NTDLL.@)
590 NTSTATUS WINAPI RtlUpcaseUnicodeToMultiByteN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
591 LPCWSTR src, DWORD srclen )
593 NTSTATUS ret;
594 LPWSTR upcase;
595 DWORD i;
597 if (!(upcase = RtlAllocateHeap( GetProcessHeap(), 0, srclen ))) return STATUS_NO_MEMORY;
598 for (i = 0; i < srclen/sizeof(WCHAR); i++) upcase[i] = toupperW(src[i]);
599 ret = RtlUnicodeToMultiByteN( dst, dstlen, reslen, upcase, srclen );
600 RtlFreeHeap( GetProcessHeap(), 0, upcase );
601 return ret;
605 /**************************************************************************
606 * RtlUpcaseUnicodeToOemN (NTDLL.@)
608 NTSTATUS WINAPI RtlUpcaseUnicodeToOemN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
609 LPCWSTR src, DWORD srclen )
611 NTSTATUS ret;
612 LPWSTR upcase;
613 DWORD i;
615 if (!(upcase = RtlAllocateHeap( GetProcessHeap(), 0, srclen ))) return STATUS_NO_MEMORY;
616 for (i = 0; i < srclen/sizeof(WCHAR); i++) upcase[i] = toupperW(src[i]);
617 ret = RtlUnicodeToOemN( dst, dstlen, reslen, upcase, srclen );
618 RtlFreeHeap( GetProcessHeap(), 0, upcase );
619 return ret;
624 STRING SIZE
627 /**************************************************************************
628 * RtlOemStringToUnicodeSize (NTDLL.@)
629 * RtlxOemStringToUnicodeSize (NTDLL.@)
631 * Return the size in bytes necessary for the Unicode conversion of 'str',
632 * including the terminating NULL.
634 UINT WINAPI RtlOemStringToUnicodeSize( const STRING *str )
636 int ret = cp_mbstowcs( get_oem_table(), 0, str->Buffer, str->Length, NULL, 0 );
637 return (ret + 1) * sizeof(WCHAR);
641 /**************************************************************************
642 * RtlAnsiStringToUnicodeSize (NTDLL.@)
643 * RtlxAnsiStringToUnicodeSize (NTDLL.@)
645 * Return the size in bytes necessary for the Unicode conversion of 'str',
646 * including the terminating NULL.
648 DWORD WINAPI RtlAnsiStringToUnicodeSize( const STRING *str )
650 DWORD ret;
651 RtlMultiByteToUnicodeSize( &ret, str->Buffer, str->Length );
652 return ret + sizeof(WCHAR);
656 /**************************************************************************
657 * RtlMultiByteToUnicodeSize (NTDLL.@)
659 * Compute the size in bytes necessary for the Unicode conversion of 'str',
660 * without the terminating NULL.
662 NTSTATUS WINAPI RtlMultiByteToUnicodeSize( DWORD *size, LPCSTR str, UINT len )
664 *size = cp_mbstowcs( get_ansi_table(), 0, str, len, NULL, 0 ) * sizeof(WCHAR);
665 return STATUS_SUCCESS;
669 /**************************************************************************
670 * RtlUnicodeToMultiByteSize (NTDLL.@)
672 * Compute the size necessary for the multibyte conversion of 'str',
673 * without the terminating NULL.
675 NTSTATUS WINAPI RtlUnicodeToMultiByteSize( DWORD *size, LPCWSTR str, UINT len )
677 *size = cp_wcstombs( get_ansi_table(), 0, str, len / sizeof(WCHAR), NULL, 0, NULL, NULL );
678 return STATUS_SUCCESS;
682 /**************************************************************************
683 * RtlUnicodeStringToAnsiSize (NTDLL.@)
684 * RtlxUnicodeStringToAnsiSize (NTDLL.@)
686 * Return the size in bytes necessary for the Ansi conversion of 'str',
687 * including the terminating NULL.
689 DWORD WINAPI RtlUnicodeStringToAnsiSize( const UNICODE_STRING *str )
691 DWORD ret;
692 RtlUnicodeToMultiByteSize( &ret, str->Buffer, str->Length );
693 return ret + 1;
697 /**************************************************************************
698 * RtlUnicodeStringToOemSize (NTDLL.@)
699 * RtlxUnicodeStringToOemSize (NTDLL.@)
701 * Return the size in bytes necessary for the OEM conversion of 'str',
702 * including the terminating NULL.
704 DWORD WINAPI RtlUnicodeStringToOemSize( const UNICODE_STRING *str )
706 return cp_wcstombs( get_oem_table(), 0, str->Buffer, str->Length / sizeof(WCHAR),
707 NULL, 0, NULL, NULL ) + 1;
711 /**************************************************************************
712 * RtlAppendStringToString (NTDLL.@)
714 NTSTATUS WINAPI RtlAppendStringToString( STRING *dst, const STRING *src )
716 unsigned int len = src->Length + dst->Length;
717 if (len > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
718 memcpy( dst->Buffer + dst->Length, src->Buffer, src->Length );
719 dst->Length = len;
720 return STATUS_SUCCESS;
724 /**************************************************************************
725 * RtlAppendAsciizToString (NTDLL.@)
727 NTSTATUS WINAPI RtlAppendAsciizToString( STRING *dst, LPCSTR src )
729 if (src)
731 unsigned int srclen = strlen(src);
732 unsigned int total = srclen + dst->Length;
733 if (total > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
734 memcpy( dst->Buffer + dst->Length, src, srclen );
735 dst->Length = total;
737 return STATUS_SUCCESS;
741 /**************************************************************************
742 * RtlAppendUnicodeToString (NTDLL.@)
744 NTSTATUS WINAPI RtlAppendUnicodeToString( UNICODE_STRING *dst, LPCWSTR src )
746 if (src)
748 unsigned int srclen = strlenW(src) * sizeof(WCHAR);
749 unsigned int total = srclen + dst->Length;
750 if (total > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
751 memcpy( dst->Buffer + dst->Length/sizeof(WCHAR), src, srclen );
752 dst->Length = total;
753 /* append terminating NULL if enough space */
754 if (total < dst->MaximumLength) dst->Buffer[total / sizeof(WCHAR)] = 0;
756 return STATUS_SUCCESS;
760 /**************************************************************************
761 * RtlAppendUnicodeStringToString (NTDLL.@)
763 NTSTATUS WINAPI RtlAppendUnicodeStringToString( UNICODE_STRING *dst, const UNICODE_STRING *src )
765 unsigned int len = src->Length + dst->Length;
766 if (len > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
767 memcpy( dst->Buffer + dst->Length/sizeof(WCHAR), src->Buffer, src->Length );
768 dst->Length = len;
769 /* append terminating NULL if enough space */
770 if (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0;
771 return STATUS_SUCCESS;
776 MISC
779 /**************************************************************************
780 * RtlIsTextUnicode (NTDLL.@)
782 * Apply various feeble heuristics to guess whether
783 * the text buffer contains Unicode.
784 * FIXME: should implement more tests.
786 DWORD WINAPI RtlIsTextUnicode(
787 LPVOID buf,
788 DWORD len,
789 DWORD *pf)
791 LPWSTR s = buf;
792 DWORD flags = -1, out_flags = 0;
794 if (!len)
795 goto out;
796 if (pf)
797 flags = *pf;
799 * Apply various tests to the text string. According to the
800 * docs, each test "passed" sets the corresponding flag in
801 * the output flags. But some of the tests are mutually
802 * exclusive, so I don't see how you could pass all tests ...
805 /* Check for an odd length ... pass if even. */
806 if (!(len & 1))
807 out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
809 /* Check for the special unicode marker byte. */
810 if (*s == 0xFEFF)
811 out_flags |= IS_TEXT_UNICODE_SIGNATURE;
814 * Check whether the string passed all of the tests.
816 flags &= ITU_IMPLEMENTED_TESTS;
817 if ((out_flags & flags) != flags)
818 len = 0;
819 out:
820 if (pf)
821 *pf = out_flags;
822 return len;