4 * Copyright (C) 1996-1998 Marcus Meissner
5 * Copyright (C) 2000 Alexandre Julliard
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 );
34 inline static const union cptable
*get_oem_table(void)
36 if (!oem_table
) oem_table
= cp_get_table( 437 );
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
)
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
)
102 unsigned int len
= min( src
->Length
, dst
->MaximumLength
);
103 memcpy( dst
->Buffer
, src
->Buffer
, 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;
138 /**************************************************************************
139 * RtlCreateUnicodeStringFromAsciiz (NTDLL.@)
141 BOOLEAN WINAPI
RtlCreateUnicodeStringFromAsciiz( PUNICODE_STRING target
, LPCSTR src
)
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
)
165 unsigned int len
= min( src
->Length
, dst
->MaximumLength
);
166 memcpy( dst
->Buffer
, src
->Buffer
, 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
)
182 memset( str
->Buffer
, 0, str
->MaximumLength
);
191 /******************************************************************************
192 * RtlCompareString (NTDLL.@)
194 LONG WINAPI
RtlCompareString( const STRING
*s1
, const STRING
*s2
, BOOLEAN CaseInsensitive
)
200 len
= min(s1
->Length
, s2
->Length
);
206 while (!ret
&& len
--) ret
= toupper(*p1
++) - toupper(*p2
++);
210 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
212 if (!ret
) ret
= s1
->Length
- s2
->Length
;
217 /******************************************************************************
218 * RtlCompareUnicodeString (NTDLL.@)
220 LONG WINAPI
RtlCompareUnicodeString( const UNICODE_STRING
*s1
, const UNICODE_STRING
*s2
,
221 BOOLEAN CaseInsensitive
)
227 len
= min(s1
->Length
, s2
->Length
) / sizeof(WCHAR
);
233 while (!ret
&& len
--) ret
= toupperW(*p1
++) - toupperW(*p2
++);
237 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
239 if (!ret
) ret
= s1
->Length
- s2
->Length
;
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
)
274 if (s1
->Length
> s2
->Length
) return FALSE
;
277 for (i
= 0; i
< s1
->Length
; i
++)
278 if (toupper(s1
->Buffer
[i
]) != toupper(s2
->Buffer
[i
])) return FALSE
;
282 for (i
= 0; i
< s1
->Length
; i
++)
283 if (s1
->Buffer
[i
] != s2
->Buffer
[i
]) return FALSE
;
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
)
300 if (s1
->Length
> s2
->Length
) return FALSE
;
303 for (i
= 0; i
< s1
->Length
/ sizeof(WCHAR
); i
++)
304 if (toupper(s1
->Buffer
[i
]) != toupper(s2
->Buffer
[i
])) return FALSE
;
308 for (i
= 0; i
< s1
->Length
/ sizeof(WCHAR
); i
++)
309 if (s1
->Buffer
[i
] != s2
->Buffer
[i
]) return FALSE
;
316 COPY BETWEEN ANSI_STRING or UNICODE_STRING
317 there is no parameter checking, it just crashes
321 /**************************************************************************
322 * RtlAnsiStringToUnicodeString (NTDLL.@)
325 * writes terminating 0
327 NTSTATUS WINAPI
RtlAnsiStringToUnicodeString( UNICODE_STRING
*uni
,
331 DWORD total
= RtlAnsiStringToUnicodeSize( ansi
);
333 if (total
> 0xffff) return STATUS_INVALID_PARAMETER_2
;
334 uni
->Length
= total
- sizeof(WCHAR
);
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.@)
352 * writes terminating 0
353 * if resulting length > 0xffff it returns STATUS_INVALID_PARAMETER_2
355 NTSTATUS WINAPI
RtlOemStringToUnicodeString( UNICODE_STRING
*uni
,
359 DWORD total
= RtlOemStringToUnicodeSize( oem
);
361 if (total
> 0xffff) return STATUS_INVALID_PARAMETER_2
;
362 uni
->Length
= total
- sizeof(WCHAR
);
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.@)
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
,
387 NTSTATUS ret
= STATUS_SUCCESS
;
388 DWORD len
= RtlUnicodeStringToAnsiSize( uni
);
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;
409 /**************************************************************************
410 * RtlUnicodeStringToOemString (NTDLL.@)
413 * allocates uni->Length+1
414 * writes terminating 0
416 NTSTATUS WINAPI
RtlUnicodeStringToOemString( STRING
*oem
,
417 const UNICODE_STRING
*uni
,
420 NTSTATUS ret
= STATUS_SUCCESS
;
421 DWORD len
= RtlUnicodeStringToOemSize( uni
);
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;
442 /**************************************************************************
443 * RtlMultiByteToUnicodeN (NTDLL.@)
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
) );
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
) );
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
);
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
);
495 *reslen
= (ret
>= 0) ? ret
: dstlen
; /* overflow -> we filled up to dstlen */
496 return STATUS_SUCCESS
;
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
]);
516 /**************************************************************************
517 * RtlUpcaseUnicodeString (NTDLL.@)
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
,
528 DWORD i
, len
= src
->Length
;
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
]);
539 return STATUS_SUCCESS
;
543 /**************************************************************************
544 * RtlUpcaseUnicodeStringToAnsiString (NTDLL.@)
547 * writes terminating 0
549 NTSTATUS WINAPI
RtlUpcaseUnicodeStringToAnsiString( STRING
*dst
,
550 const UNICODE_STRING
*src
,
554 UNICODE_STRING upcase
;
556 if (!(ret
= RtlUpcaseUnicodeString( &upcase
, src
, TRUE
)))
558 ret
= RtlUnicodeStringToAnsiString( dst
, &upcase
, doalloc
);
559 RtlFreeUnicodeString( &upcase
);
565 /**************************************************************************
566 * RtlUpcaseUnicodeStringToOemString (NTDLL.@)
569 * writes terminating 0
571 NTSTATUS WINAPI
RtlUpcaseUnicodeStringToOemString( STRING
*dst
,
572 const UNICODE_STRING
*src
,
576 UNICODE_STRING upcase
;
578 if (!(ret
= RtlUpcaseUnicodeString( &upcase
, src
, TRUE
)))
580 ret
= RtlUnicodeStringToOemString( dst
, &upcase
, doalloc
);
581 RtlFreeUnicodeString( &upcase
);
587 /**************************************************************************
588 * RtlUpcaseUnicodeToMultiByteN (NTDLL.@)
590 NTSTATUS WINAPI
RtlUpcaseUnicodeToMultiByteN( LPSTR dst
, DWORD dstlen
, LPDWORD reslen
,
591 LPCWSTR src
, DWORD srclen
)
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
);
605 /**************************************************************************
606 * RtlUpcaseUnicodeToOemN (NTDLL.@)
608 NTSTATUS WINAPI
RtlUpcaseUnicodeToOemN( LPSTR dst
, DWORD dstlen
, LPDWORD reslen
,
609 LPCWSTR src
, DWORD srclen
)
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
);
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
)
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
)
692 RtlUnicodeToMultiByteSize( &ret
, str
->Buffer
, str
->Length
);
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
);
720 return STATUS_SUCCESS
;
724 /**************************************************************************
725 * RtlAppendAsciizToString (NTDLL.@)
727 NTSTATUS WINAPI
RtlAppendAsciizToString( STRING
*dst
, LPCSTR 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
);
737 return STATUS_SUCCESS
;
741 /**************************************************************************
742 * RtlAppendUnicodeToString (NTDLL.@)
744 NTSTATUS WINAPI
RtlAppendUnicodeToString( UNICODE_STRING
*dst
, LPCWSTR 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
);
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
);
769 /* append terminating NULL if enough space */
770 if (len
< dst
->MaximumLength
) dst
->Buffer
[len
/ sizeof(WCHAR
)] = 0;
771 return STATUS_SUCCESS
;
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(
792 DWORD flags
= -1, out_flags
= 0;
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. */
807 out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
809 /* Check for the special unicode marker byte. */
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
)