4 * Copyright (C) 1996-1998 Marcus Meissner
5 * Copyright (C) 2000 Alexandre Julliard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "wine/unicode.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(ntdll
);
35 UINT NlsAnsiCodePage
= 1252;
36 BYTE NlsMbCodePageTag
= 0;
37 BYTE NlsMbOemCodePageTag
= 0;
39 static const union cptable
*ansi_table
;
40 static const union cptable
*oem_table
;
42 inline static const union cptable
*get_ansi_table(void)
44 if (!ansi_table
) ansi_table
= cp_get_table( 1252 );
48 inline static const union cptable
*get_oem_table(void)
50 if (!oem_table
) oem_table
= cp_get_table( 437 );
55 /**************************************************************************
56 * __wine_init_codepages (NTDLL.@)
58 * Set the code page once kernel32 is loaded. Should be done differently.
60 void __wine_init_codepages( const union cptable
*ansi
, const union cptable
*oem
)
64 NlsAnsiCodePage
= ansi
->info
.codepage
;
68 /**************************************************************************
69 * RtlInitAnsiString (NTDLL.@)
71 void WINAPI
RtlInitAnsiString( PSTRING target
, LPCSTR source
)
73 if ((target
->Buffer
= (LPSTR
)source
))
75 target
->Length
= strlen(source
);
76 target
->MaximumLength
= target
->Length
+ 1;
78 else target
->Length
= target
->MaximumLength
= 0;
82 /**************************************************************************
83 * RtlInitString (NTDLL.@)
85 void WINAPI
RtlInitString( PSTRING target
, LPCSTR source
)
87 RtlInitAnsiString( target
, source
);
91 /**************************************************************************
92 * RtlFreeAnsiString (NTDLL.@)
94 void WINAPI
RtlFreeAnsiString( PSTRING str
)
96 if (str
->Buffer
) RtlFreeHeap( GetProcessHeap(), 0, str
->Buffer
);
100 /**************************************************************************
101 * RtlFreeOemString (NTDLL.@)
103 void WINAPI
RtlFreeOemString( PSTRING str
)
105 RtlFreeAnsiString( str
);
109 /**************************************************************************
110 * RtlCopyString (NTDLL.@)
112 void WINAPI
RtlCopyString( STRING
*dst
, const STRING
*src
)
116 unsigned int len
= min( src
->Length
, dst
->MaximumLength
);
117 memcpy( dst
->Buffer
, src
->Buffer
, len
);
120 else dst
->Length
= 0;
124 /**************************************************************************
125 * RtlInitUnicodeString (NTDLL.@)
127 void WINAPI
RtlInitUnicodeString( PUNICODE_STRING target
, LPCWSTR source
)
129 if ((target
->Buffer
= (LPWSTR
)source
))
131 target
->Length
= strlenW(source
) * sizeof(WCHAR
);
132 target
->MaximumLength
= target
->Length
+ sizeof(WCHAR
);
134 else target
->Length
= target
->MaximumLength
= 0;
138 /**************************************************************************
139 * RtlCreateUnicodeString (NTDLL.@)
141 BOOLEAN WINAPI
RtlCreateUnicodeString( PUNICODE_STRING target
, LPCWSTR src
)
143 int len
= (strlenW(src
) + 1) * sizeof(WCHAR
);
144 if (!(target
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0, len
))) return FALSE
;
145 memcpy( target
->Buffer
, src
, len
);
146 target
->MaximumLength
= len
;
147 target
->Length
= len
- sizeof(WCHAR
);
152 /**************************************************************************
153 * RtlCreateUnicodeStringFromAsciiz (NTDLL.@)
155 BOOLEAN WINAPI
RtlCreateUnicodeStringFromAsciiz( PUNICODE_STRING target
, LPCSTR src
)
158 RtlInitAnsiString( &ansi
, src
);
159 return !RtlAnsiStringToUnicodeString( target
, &ansi
, TRUE
);
163 /**************************************************************************
164 * RtlFreeUnicodeString (NTDLL.@)
166 void WINAPI
RtlFreeUnicodeString( PUNICODE_STRING str
)
168 if (str
->Buffer
) RtlFreeHeap( GetProcessHeap(), 0, str
->Buffer
);
172 /**************************************************************************
173 * RtlCopyUnicodeString (NTDLL.@)
175 void WINAPI
RtlCopyUnicodeString( UNICODE_STRING
*dst
, const UNICODE_STRING
*src
)
179 unsigned int len
= min( src
->Length
, dst
->MaximumLength
);
180 memcpy( dst
->Buffer
, src
->Buffer
, len
);
182 /* append terminating NULL if enough space */
183 if (len
< dst
->MaximumLength
) dst
->Buffer
[len
/ sizeof(WCHAR
)] = 0;
185 else dst
->Length
= 0;
189 /**************************************************************************
190 * RtlEraseUnicodeString (NTDLL.@)
192 void WINAPI
RtlEraseUnicodeString( UNICODE_STRING
*str
)
196 memset( str
->Buffer
, 0, str
->MaximumLength
);
205 /******************************************************************************
206 * RtlCompareString (NTDLL.@)
208 LONG WINAPI
RtlCompareString( const STRING
*s1
, const STRING
*s2
, BOOLEAN CaseInsensitive
)
214 len
= min(s1
->Length
, s2
->Length
);
220 while (!ret
&& len
--) ret
= toupper(*p1
++) - toupper(*p2
++);
224 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
226 if (!ret
) ret
= s1
->Length
- s2
->Length
;
231 /******************************************************************************
232 * RtlCompareUnicodeString (NTDLL.@)
234 LONG WINAPI
RtlCompareUnicodeString( const UNICODE_STRING
*s1
, const UNICODE_STRING
*s2
,
235 BOOLEAN CaseInsensitive
)
241 len
= min(s1
->Length
, s2
->Length
) / sizeof(WCHAR
);
247 while (!ret
&& len
--) ret
= toupperW(*p1
++) - toupperW(*p2
++);
251 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
253 if (!ret
) ret
= s1
->Length
- s2
->Length
;
258 /**************************************************************************
259 * RtlEqualString (NTDLL.@)
261 BOOLEAN WINAPI
RtlEqualString( const STRING
*s1
, const STRING
*s2
, BOOLEAN CaseInsensitive
)
263 if (s1
->Length
!= s2
->Length
) return FALSE
;
264 return !RtlCompareString( s1
, s2
, CaseInsensitive
);
268 /**************************************************************************
269 * RtlEqualUnicodeString (NTDLL.@)
271 BOOLEAN WINAPI
RtlEqualUnicodeString( const UNICODE_STRING
*s1
, const UNICODE_STRING
*s2
,
272 BOOLEAN CaseInsensitive
)
274 if (s1
->Length
!= s2
->Length
) return FALSE
;
275 return !RtlCompareUnicodeString( s1
, s2
, CaseInsensitive
);
279 /**************************************************************************
280 * RtlPrefixString (NTDLL.@)
282 * Test if s1 is a prefix in s2
284 BOOLEAN WINAPI
RtlPrefixString( const STRING
*s1
, const STRING
*s2
, BOOLEAN ignore_case
)
288 if (s1
->Length
> s2
->Length
) return FALSE
;
291 for (i
= 0; i
< s1
->Length
; i
++)
292 if (toupper(s1
->Buffer
[i
]) != toupper(s2
->Buffer
[i
])) return FALSE
;
296 for (i
= 0; i
< s1
->Length
; i
++)
297 if (s1
->Buffer
[i
] != s2
->Buffer
[i
]) return FALSE
;
303 /**************************************************************************
304 * RtlPrefixUnicodeString (NTDLL.@)
306 * Test if s1 is a prefix in s2
308 BOOLEAN WINAPI
RtlPrefixUnicodeString( const UNICODE_STRING
*s1
,
309 const UNICODE_STRING
*s2
,
310 BOOLEAN ignore_case
)
314 if (s1
->Length
> s2
->Length
) return FALSE
;
317 for (i
= 0; i
< s1
->Length
/ sizeof(WCHAR
); i
++)
318 if (toupper(s1
->Buffer
[i
]) != toupper(s2
->Buffer
[i
])) return FALSE
;
322 for (i
= 0; i
< s1
->Length
/ sizeof(WCHAR
); i
++)
323 if (s1
->Buffer
[i
] != s2
->Buffer
[i
]) return FALSE
;
330 COPY BETWEEN ANSI_STRING or UNICODE_STRING
331 there is no parameter checking, it just crashes
335 /**************************************************************************
336 * RtlAnsiStringToUnicodeString (NTDLL.@)
339 * writes terminating 0
341 NTSTATUS WINAPI
RtlAnsiStringToUnicodeString( UNICODE_STRING
*uni
,
345 DWORD total
= RtlAnsiStringToUnicodeSize( ansi
);
347 if (total
> 0xffff) return STATUS_INVALID_PARAMETER_2
;
348 uni
->Length
= total
- sizeof(WCHAR
);
351 uni
->MaximumLength
= total
;
352 if (!(uni
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0, total
))) return STATUS_NO_MEMORY
;
354 else if (total
> uni
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
356 RtlMultiByteToUnicodeN( uni
->Buffer
, uni
->Length
, NULL
, ansi
->Buffer
, ansi
->Length
);
357 uni
->Buffer
[uni
->Length
/ sizeof(WCHAR
)] = 0;
358 return STATUS_SUCCESS
;
362 /**************************************************************************
363 * RtlOemStringToUnicodeString (NTDLL.@)
366 * writes terminating 0
367 * if resulting length > 0xffff it returns STATUS_INVALID_PARAMETER_2
369 NTSTATUS WINAPI
RtlOemStringToUnicodeString( UNICODE_STRING
*uni
,
373 DWORD total
= RtlOemStringToUnicodeSize( oem
);
375 if (total
> 0xffff) return STATUS_INVALID_PARAMETER_2
;
376 uni
->Length
= total
- sizeof(WCHAR
);
379 uni
->MaximumLength
= total
;
380 if (!(uni
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0, total
))) return STATUS_NO_MEMORY
;
382 else if (total
> uni
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
384 RtlOemToUnicodeN( uni
->Buffer
, uni
->Length
, NULL
, oem
->Buffer
, oem
->Length
);
385 uni
->Buffer
[uni
->Length
/ sizeof(WCHAR
)] = 0;
386 return STATUS_SUCCESS
;
390 /**************************************************************************
391 * RtlUnicodeStringToAnsiString (NTDLL.@)
394 * writes terminating 0
395 * copies a part if the buffer is too small
397 NTSTATUS WINAPI
RtlUnicodeStringToAnsiString( STRING
*ansi
,
398 const UNICODE_STRING
*uni
,
401 NTSTATUS ret
= STATUS_SUCCESS
;
402 DWORD len
= RtlUnicodeStringToAnsiSize( uni
);
404 ansi
->Length
= len
- 1;
407 ansi
->MaximumLength
= len
;
408 if (!(ansi
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0, len
))) return STATUS_NO_MEMORY
;
410 else if (ansi
->MaximumLength
< len
)
412 if (!ansi
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
413 ansi
->Length
= ansi
->MaximumLength
- 1;
414 ret
= STATUS_BUFFER_OVERFLOW
;
417 RtlUnicodeToMultiByteN( ansi
->Buffer
, ansi
->Length
, NULL
, uni
->Buffer
, uni
->Length
);
418 ansi
->Buffer
[ansi
->Length
] = 0;
423 /**************************************************************************
424 * RtlUnicodeStringToOemString (NTDLL.@)
427 * allocates uni->Length+1
428 * writes terminating 0
430 NTSTATUS WINAPI
RtlUnicodeStringToOemString( STRING
*oem
,
431 const UNICODE_STRING
*uni
,
434 NTSTATUS ret
= STATUS_SUCCESS
;
435 DWORD len
= RtlUnicodeStringToOemSize( uni
);
437 oem
->Length
= len
- 1;
440 oem
->MaximumLength
= len
;
441 if (!(oem
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0, len
))) return STATUS_NO_MEMORY
;
443 else if (oem
->MaximumLength
< len
)
445 if (!oem
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
446 oem
->Length
= oem
->MaximumLength
- 1;
447 ret
= STATUS_BUFFER_OVERFLOW
;
450 RtlUnicodeToOemN( oem
->Buffer
, oem
->Length
, NULL
, uni
->Buffer
, uni
->Length
);
451 oem
->Buffer
[oem
->Length
] = 0;
456 /**************************************************************************
457 * RtlMultiByteToUnicodeN (NTDLL.@)
460 * if unistr is too small a part is copied
462 NTSTATUS WINAPI
RtlMultiByteToUnicodeN( LPWSTR dst
, DWORD dstlen
, LPDWORD reslen
,
463 LPCSTR src
, DWORD srclen
)
466 int ret
= cp_mbstowcs( get_ansi_table(), 0, src
, srclen
, dst
, dstlen
/sizeof(WCHAR
) );
468 *reslen
= (ret
>= 0) ? ret
*sizeof(WCHAR
) : dstlen
; /* overflow -> we filled up to dstlen */
469 return STATUS_SUCCESS
;
473 /**************************************************************************
474 * RtlOemToUnicodeN (NTDLL.@)
476 NTSTATUS WINAPI
RtlOemToUnicodeN( LPWSTR dst
, DWORD dstlen
, LPDWORD reslen
,
477 LPCSTR src
, DWORD srclen
)
479 int ret
= cp_mbstowcs( get_oem_table(), 0, src
, srclen
, dst
, dstlen
/sizeof(WCHAR
) );
481 *reslen
= (ret
>= 0) ? ret
*sizeof(WCHAR
) : dstlen
; /* overflow -> we filled up to dstlen */
482 return STATUS_SUCCESS
;
486 /**************************************************************************
487 * RtlUnicodeToMultiByteN (NTDLL.@)
489 NTSTATUS WINAPI
RtlUnicodeToMultiByteN( LPSTR dst
, DWORD dstlen
, LPDWORD reslen
,
490 LPCWSTR src
, DWORD srclen
)
492 int ret
= cp_wcstombs( get_ansi_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
;
500 /**************************************************************************
501 * RtlUnicodeToOemN (NTDLL.@)
503 NTSTATUS WINAPI
RtlUnicodeToOemN( LPSTR dst
, DWORD dstlen
, LPDWORD reslen
,
504 LPCWSTR src
, DWORD srclen
)
506 int ret
= cp_wcstombs( get_oem_table(), 0, src
, srclen
/ sizeof(WCHAR
),
507 dst
, dstlen
, NULL
, NULL
);
509 *reslen
= (ret
>= 0) ? ret
: dstlen
; /* overflow -> we filled up to dstlen */
510 return STATUS_SUCCESS
;
518 /**************************************************************************
519 * RtlUpperString (NTDLL.@)
521 void WINAPI
RtlUpperString( STRING
*dst
, const STRING
*src
)
523 unsigned int i
, len
= min(src
->Length
, dst
->MaximumLength
);
525 for (i
= 0; i
< len
; i
++) dst
->Buffer
[i
] = toupper(src
->Buffer
[i
]);
530 /**************************************************************************
531 * RtlUpcaseUnicodeString (NTDLL.@)
534 * destination string is never 0-terminated because dest can be equal to src
535 * and src might be not 0-terminated
536 * dest.Length only set when success
538 NTSTATUS WINAPI
RtlUpcaseUnicodeString( UNICODE_STRING
*dest
,
539 const UNICODE_STRING
*src
,
542 DWORD i
, len
= src
->Length
;
546 dest
->MaximumLength
= len
;
547 if (!(dest
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0, len
))) return STATUS_NO_MEMORY
;
549 else if (len
> dest
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
551 for (i
= 0; i
< len
/sizeof(WCHAR
); i
++) dest
->Buffer
[i
] = toupperW(src
->Buffer
[i
]);
553 return STATUS_SUCCESS
;
557 /**************************************************************************
558 * RtlUpcaseUnicodeStringToAnsiString (NTDLL.@)
561 * writes terminating 0
563 NTSTATUS WINAPI
RtlUpcaseUnicodeStringToAnsiString( STRING
*dst
,
564 const UNICODE_STRING
*src
,
568 UNICODE_STRING upcase
;
570 if (!(ret
= RtlUpcaseUnicodeString( &upcase
, src
, TRUE
)))
572 ret
= RtlUnicodeStringToAnsiString( dst
, &upcase
, doalloc
);
573 RtlFreeUnicodeString( &upcase
);
579 /**************************************************************************
580 * RtlUpcaseUnicodeStringToOemString (NTDLL.@)
583 * writes terminating 0
585 NTSTATUS WINAPI
RtlUpcaseUnicodeStringToOemString( STRING
*dst
,
586 const UNICODE_STRING
*src
,
590 UNICODE_STRING upcase
;
592 if (!(ret
= RtlUpcaseUnicodeString( &upcase
, src
, TRUE
)))
594 ret
= RtlUnicodeStringToOemString( dst
, &upcase
, doalloc
);
595 RtlFreeUnicodeString( &upcase
);
601 /**************************************************************************
602 * RtlUpcaseUnicodeToMultiByteN (NTDLL.@)
604 NTSTATUS WINAPI
RtlUpcaseUnicodeToMultiByteN( LPSTR dst
, DWORD dstlen
, LPDWORD reslen
,
605 LPCWSTR src
, DWORD srclen
)
611 if (!(upcase
= RtlAllocateHeap( GetProcessHeap(), 0, srclen
))) return STATUS_NO_MEMORY
;
612 for (i
= 0; i
< srclen
/sizeof(WCHAR
); i
++) upcase
[i
] = toupperW(src
[i
]);
613 ret
= RtlUnicodeToMultiByteN( dst
, dstlen
, reslen
, upcase
, srclen
);
614 RtlFreeHeap( GetProcessHeap(), 0, upcase
);
619 /**************************************************************************
620 * RtlUpcaseUnicodeToOemN (NTDLL.@)
622 NTSTATUS WINAPI
RtlUpcaseUnicodeToOemN( LPSTR dst
, DWORD dstlen
, LPDWORD reslen
,
623 LPCWSTR src
, DWORD srclen
)
629 if (!(upcase
= RtlAllocateHeap( GetProcessHeap(), 0, srclen
))) return STATUS_NO_MEMORY
;
630 for (i
= 0; i
< srclen
/sizeof(WCHAR
); i
++) upcase
[i
] = toupperW(src
[i
]);
631 ret
= RtlUnicodeToOemN( dst
, dstlen
, reslen
, upcase
, srclen
);
632 RtlFreeHeap( GetProcessHeap(), 0, upcase
);
641 /**************************************************************************
642 * RtlOemStringToUnicodeSize (NTDLL.@)
643 * RtlxOemStringToUnicodeSize (NTDLL.@)
645 * Return the size in bytes necessary for the Unicode conversion of 'str',
646 * including the terminating NULL.
648 UINT WINAPI
RtlOemStringToUnicodeSize( const STRING
*str
)
650 int ret
= cp_mbstowcs( get_oem_table(), 0, str
->Buffer
, str
->Length
, NULL
, 0 );
651 return (ret
+ 1) * sizeof(WCHAR
);
655 /**************************************************************************
656 * RtlAnsiStringToUnicodeSize (NTDLL.@)
657 * RtlxAnsiStringToUnicodeSize (NTDLL.@)
659 * Return the size in bytes necessary for the Unicode conversion of 'str',
660 * including the terminating NULL.
662 DWORD WINAPI
RtlAnsiStringToUnicodeSize( const STRING
*str
)
665 RtlMultiByteToUnicodeSize( &ret
, str
->Buffer
, str
->Length
);
666 return ret
+ sizeof(WCHAR
);
670 /**************************************************************************
671 * RtlMultiByteToUnicodeSize (NTDLL.@)
673 * Compute the size in bytes necessary for the Unicode conversion of 'str',
674 * without the terminating NULL.
676 NTSTATUS WINAPI
RtlMultiByteToUnicodeSize( DWORD
*size
, LPCSTR str
, UINT len
)
678 *size
= cp_mbstowcs( get_ansi_table(), 0, str
, len
, NULL
, 0 ) * sizeof(WCHAR
);
679 return STATUS_SUCCESS
;
683 /**************************************************************************
684 * RtlUnicodeToMultiByteSize (NTDLL.@)
686 * Compute the size necessary for the multibyte conversion of 'str',
687 * without the terminating NULL.
689 NTSTATUS WINAPI
RtlUnicodeToMultiByteSize( DWORD
*size
, LPCWSTR str
, UINT len
)
691 *size
= cp_wcstombs( get_ansi_table(), 0, str
, len
/ sizeof(WCHAR
), NULL
, 0, NULL
, NULL
);
692 return STATUS_SUCCESS
;
696 /**************************************************************************
697 * RtlUnicodeStringToAnsiSize (NTDLL.@)
698 * RtlxUnicodeStringToAnsiSize (NTDLL.@)
700 * Return the size in bytes necessary for the Ansi conversion of 'str',
701 * including the terminating NULL.
703 DWORD WINAPI
RtlUnicodeStringToAnsiSize( const UNICODE_STRING
*str
)
706 RtlUnicodeToMultiByteSize( &ret
, str
->Buffer
, str
->Length
);
711 /**************************************************************************
712 * RtlUnicodeStringToOemSize (NTDLL.@)
713 * RtlxUnicodeStringToOemSize (NTDLL.@)
715 * Return the size in bytes necessary for the OEM conversion of 'str',
716 * including the terminating NULL.
718 DWORD WINAPI
RtlUnicodeStringToOemSize( const UNICODE_STRING
*str
)
720 return cp_wcstombs( get_oem_table(), 0, str
->Buffer
, str
->Length
/ sizeof(WCHAR
),
721 NULL
, 0, NULL
, NULL
) + 1;
725 /**************************************************************************
726 * RtlAppendStringToString (NTDLL.@)
728 NTSTATUS WINAPI
RtlAppendStringToString( STRING
*dst
, const STRING
*src
)
730 unsigned int len
= src
->Length
+ dst
->Length
;
731 if (len
> dst
->MaximumLength
) return STATUS_BUFFER_TOO_SMALL
;
732 memcpy( dst
->Buffer
+ dst
->Length
, src
->Buffer
, src
->Length
);
734 return STATUS_SUCCESS
;
738 /**************************************************************************
739 * RtlAppendAsciizToString (NTDLL.@)
741 NTSTATUS WINAPI
RtlAppendAsciizToString( STRING
*dst
, LPCSTR src
)
745 unsigned int srclen
= strlen(src
);
746 unsigned int total
= srclen
+ dst
->Length
;
747 if (total
> dst
->MaximumLength
) return STATUS_BUFFER_TOO_SMALL
;
748 memcpy( dst
->Buffer
+ dst
->Length
, src
, srclen
);
751 return STATUS_SUCCESS
;
755 /**************************************************************************
756 * RtlAppendUnicodeToString (NTDLL.@)
758 NTSTATUS WINAPI
RtlAppendUnicodeToString( UNICODE_STRING
*dst
, LPCWSTR src
)
762 unsigned int srclen
= strlenW(src
) * sizeof(WCHAR
);
763 unsigned int total
= srclen
+ dst
->Length
;
764 if (total
> dst
->MaximumLength
) return STATUS_BUFFER_TOO_SMALL
;
765 memcpy( dst
->Buffer
+ dst
->Length
/sizeof(WCHAR
), src
, srclen
);
767 /* append terminating NULL if enough space */
768 if (total
< dst
->MaximumLength
) dst
->Buffer
[total
/ sizeof(WCHAR
)] = 0;
770 return STATUS_SUCCESS
;
774 /**************************************************************************
775 * RtlAppendUnicodeStringToString (NTDLL.@)
777 NTSTATUS WINAPI
RtlAppendUnicodeStringToString( UNICODE_STRING
*dst
, const UNICODE_STRING
*src
)
779 unsigned int len
= src
->Length
+ dst
->Length
;
780 if (len
> dst
->MaximumLength
) return STATUS_BUFFER_TOO_SMALL
;
781 memcpy( dst
->Buffer
+ dst
->Length
/sizeof(WCHAR
), src
->Buffer
, src
->Length
);
783 /* append terminating NULL if enough space */
784 if (len
< dst
->MaximumLength
) dst
->Buffer
[len
/ sizeof(WCHAR
)] = 0;
785 return STATUS_SUCCESS
;
793 /**************************************************************************
794 * RtlIsTextUnicode (NTDLL.@)
796 * Apply various feeble heuristics to guess whether
797 * the text buffer contains Unicode.
798 * FIXME: should implement more tests.
800 DWORD WINAPI
RtlIsTextUnicode(
806 DWORD flags
= -1, out_flags
= 0;
813 * Apply various tests to the text string. According to the
814 * docs, each test "passed" sets the corresponding flag in
815 * the output flags. But some of the tests are mutually
816 * exclusive, so I don't see how you could pass all tests ...
819 /* Check for an odd length ... pass if even. */
821 out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
823 /* Check for the special unicode marker byte. */
825 out_flags
|= IS_TEXT_UNICODE_SIGNATURE
;
828 * Check whether the string passed all of the tests.
830 flags
&= ITU_IMPLEMENTED_TESTS
;
831 if ((out_flags
& flags
) != flags
)