Solve remaining problems with scroll bars in the edit control.
[wine.git] / dlls / ntdll / rtlstr.c
blobdc7c3142a92a90f5da6ae4a85e58246bdc91389c
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 <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include "wine/unicode.h"
14 #include "heap.h"
15 #include "winnls.h"
16 #include "debugtools.h"
17 #include "ntdll_misc.h"
18 #include "ntddk.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 )
70 if (src)
72 unsigned int len = min( src->Length, dst->MaximumLength );
73 memcpy( dst->Buffer, src->Buffer, len );
74 dst->Length = len;
76 else dst->Length = 0;
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;
104 return TRUE;
108 /**************************************************************************
109 * RtlCreateUnicodeStringFromAsciiz (NTDLL.@)
111 BOOLEAN WINAPI RtlCreateUnicodeStringFromAsciiz( PUNICODE_STRING target, LPCSTR src )
113 STRING ansi;
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 )
133 if (src)
135 unsigned int len = min( src->Length, dst->MaximumLength );
136 memcpy( dst->Buffer, src->Buffer, len );
137 dst->Length = 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 )
150 if (str->Buffer)
152 memset( str->Buffer, 0, str->MaximumLength );
153 str->Length = 0;
158 COMPARISON FUNCTIONS
161 /******************************************************************************
162 * RtlCompareString (NTDLL.@)
164 LONG WINAPI RtlCompareString( const STRING *s1, const STRING *s2, BOOLEAN CaseInsensitive )
166 unsigned int len;
167 LONG ret = 0;
168 LPCSTR p1, p2;
170 len = min(s1->Length, s2->Length);
171 p1 = s1->Buffer;
172 p2 = s2->Buffer;
174 if (CaseInsensitive)
176 while (!ret && len--) ret = toupper(*p1++) - toupper(*p2++);
178 else
180 while (!ret && len--) ret = *p1++ - *p2++;
182 if (!ret) ret = s1->Length - s2->Length;
183 return ret;
187 /******************************************************************************
188 * RtlCompareUnicodeString (NTDLL.@)
190 LONG WINAPI RtlCompareUnicodeString( const UNICODE_STRING *s1, const UNICODE_STRING *s2,
191 BOOLEAN CaseInsensitive )
193 unsigned int len;
194 LONG ret = 0;
195 LPCWSTR p1, p2;
197 len = min(s1->Length, s2->Length) / sizeof(WCHAR);
198 p1 = s1->Buffer;
199 p2 = s2->Buffer;
201 if (CaseInsensitive)
203 while (!ret && len--) ret = toupperW(*p1++) - toupperW(*p2++);
205 else
207 while (!ret && len--) ret = *p1++ - *p2++;
209 if (!ret) ret = s1->Length - s2->Length;
210 return ret;
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 )
242 unsigned int i;
244 if (s1->Length > s2->Length) return FALSE;
245 if (ignore_case)
247 for (i = 0; i < s1->Length; i++)
248 if (toupper(s1->Buffer[i]) != toupper(s2->Buffer[i])) return FALSE;
250 else
252 for (i = 0; i < s1->Length; i++)
253 if (s1->Buffer[i] != s2->Buffer[i]) return FALSE;
255 return TRUE;
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 )
268 unsigned int i;
270 if (s1->Length > s2->Length) return FALSE;
271 if (ignore_case)
273 for (i = 0; i < s1->Length / sizeof(WCHAR); i++)
274 if (toupper(s1->Buffer[i]) != toupper(s2->Buffer[i])) return FALSE;
276 else
278 for (i = 0; i < s1->Length / sizeof(WCHAR); i++)
279 if (s1->Buffer[i] != s2->Buffer[i]) return FALSE;
281 return TRUE;
286 COPY BETWEEN ANSI_STRING or UNICODE_STRING
287 there is no parameter checking, it just crashes
291 /**************************************************************************
292 * RtlAnsiStringToUnicodeString (NTDLL.@)
294 * NOTES:
295 * writes terminating 0
297 NTSTATUS WINAPI RtlAnsiStringToUnicodeString( UNICODE_STRING *uni,
298 const STRING *ansi,
299 BOOLEAN doalloc )
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);
306 if (doalloc)
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.@)
322 * NOTES
323 * writes terminating 0
324 * if resulting length > 0xffff it returns STATUS_INVALID_PARAMETER_2
326 NTSTATUS WINAPI RtlOemStringToUnicodeString( UNICODE_STRING *uni,
327 const STRING *oem,
328 BOOLEAN doalloc )
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);
335 if (doalloc)
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.@)
351 * NOTES
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,
357 BOOLEAN doalloc )
359 NTSTATUS ret = STATUS_SUCCESS;
360 DWORD len = RtlUnicodeStringToAnsiSize( uni );
362 ansi->Length = len;
363 if (doalloc)
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;
378 return ret;
382 /**************************************************************************
383 * RtlUnicodeStringToOemString (NTDLL.@)
385 * NOTES
386 * allocates uni->Length+1
387 * writes terminating 0
389 NTSTATUS WINAPI RtlUnicodeStringToOemString( STRING *oem,
390 const UNICODE_STRING *uni,
391 BOOLEAN doalloc )
393 NTSTATUS ret = STATUS_SUCCESS;
394 DWORD len = RtlUnicodeStringToOemSize( uni );
396 oem->Length = len;
397 if (doalloc)
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;
412 return ret;
416 /**************************************************************************
417 * RtlMultiByteToUnicodeN (NTDLL.@)
419 * NOTES
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) );
426 if (reslen)
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) );
439 if (reslen)
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 );
453 if (reslen)
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 );
467 if (reslen)
468 *reslen = res ? res * sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
469 return STATUS_SUCCESS;
474 CASE CONVERSIONS
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]);
485 dst->Length = len;
489 /**************************************************************************
490 * RtlUpcaseUnicodeString (NTDLL.@)
492 * NOTES:
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,
499 BOOLEAN doalloc )
501 DWORD i, len = src->Length;
503 if (doalloc)
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]);
511 dest->Length = len;
512 return STATUS_SUCCESS;
516 /**************************************************************************
517 * RtlUpcaseUnicodeStringToAnsiString (NTDLL.@)
519 * NOTES
520 * writes terminating 0
522 NTSTATUS WINAPI RtlUpcaseUnicodeStringToAnsiString( STRING *dst,
523 const UNICODE_STRING *src,
524 BOOLEAN doalloc )
526 NTSTATUS ret;
527 UNICODE_STRING upcase;
529 if (!(ret = RtlUpcaseUnicodeString( &upcase, src, TRUE )))
531 ret = RtlUnicodeStringToAnsiString( dst, &upcase, doalloc );
532 RtlFreeUnicodeString( &upcase );
534 return ret;
538 /**************************************************************************
539 * RtlUpcaseUnicodeStringToOemString (NTDLL.@)
541 * NOTES
542 * writes terminating 0
544 NTSTATUS WINAPI RtlUpcaseUnicodeStringToOemString( STRING *dst,
545 const UNICODE_STRING *src,
546 BOOLEAN doalloc )
548 NTSTATUS ret;
549 UNICODE_STRING upcase;
551 if (!(ret = RtlUpcaseUnicodeString( &upcase, src, TRUE )))
553 ret = RtlUnicodeStringToOemString( dst, &upcase, doalloc );
554 RtlFreeUnicodeString( &upcase );
556 return ret;
560 /**************************************************************************
561 * RtlUpcaseUnicodeToMultiByteN (NTDLL.@)
563 NTSTATUS WINAPI RtlUpcaseUnicodeToMultiByteN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
564 LPCWSTR src, DWORD srclen )
566 NTSTATUS ret;
567 LPWSTR upcase;
568 DWORD i;
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 );
574 return ret;
578 /**************************************************************************
579 * RtlUpcaseUnicodeToOemN (NTDLL.@)
581 NTSTATUS WINAPI RtlUpcaseUnicodeToOemN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
582 LPCWSTR src, DWORD srclen )
584 NTSTATUS ret;
585 LPWSTR upcase;
586 DWORD i;
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 );
592 return ret;
597 STRING SIZE
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);
635 return 0;
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 );
648 return 0;
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 );
686 dst->Length = len;
687 return STATUS_SUCCESS;
691 /**************************************************************************
692 * RtlAppendAsciizToString (NTDLL.@)
694 NTSTATUS WINAPI RtlAppendAsciizToString( STRING *dst, LPCSTR src )
696 if (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 );
702 dst->Length = total;
704 return STATUS_SUCCESS;
708 /**************************************************************************
709 * RtlAppendUnicodeToString (NTDLL.@)
711 NTSTATUS WINAPI RtlAppendUnicodeToString( UNICODE_STRING *dst, LPCWSTR src )
713 if (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 );
719 dst->Length = total;
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 );
735 dst->Length = len;
736 /* append terminating NULL if enough space */
737 if (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0;
738 return STATUS_SUCCESS;
743 MISC
746 /**************************************************************************
747 * RtlIsTextUnicode
749 * Apply various feeble heuristics to guess whether
750 * the text buffer contains Unicode.
751 * FIXME: should implement more tests.
753 DWORD WINAPI RtlIsTextUnicode(
754 LPVOID buf,
755 DWORD len,
756 DWORD *pf)
758 LPWSTR s = buf;
759 DWORD flags = -1, out_flags = 0;
761 if (!len)
762 goto out;
763 if (pf)
764 flags = *pf;
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. */
773 if (!(len & 1))
774 out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
776 /* Check for the special unicode marker byte. */
777 if (*s == 0xFEFF)
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)
785 len = 0;
786 out:
787 if (pf)
788 *pf = out_flags;
789 return len;