Removed obsolete INT_Int31Handler.
[wine/multimedia.git] / dlls / ntdll / rtlstr.c
blob2bab2bc8f4a0294915dbd931bf6f8487008742e8
1 /*
2 * Rtl string functions
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
22 #include "config.h"
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
29 #include "winternl.h"
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 );
45 return ansi_table;
48 inline static const union cptable *get_oem_table(void)
50 if (!oem_table) oem_table = cp_get_table( 437 );
51 return oem_table;
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 )
62 ansi_table = ansi;
63 oem_table = 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 )
114 if (src)
116 unsigned int len = min( src->Length, dst->MaximumLength );
117 memcpy( dst->Buffer, src->Buffer, len );
118 dst->Length = 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);
148 return TRUE;
152 /**************************************************************************
153 * RtlCreateUnicodeStringFromAsciiz (NTDLL.@)
155 BOOLEAN WINAPI RtlCreateUnicodeStringFromAsciiz( PUNICODE_STRING target, LPCSTR src )
157 STRING ansi;
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 )
177 if (src)
179 unsigned int len = min( src->Length, dst->MaximumLength );
180 memcpy( dst->Buffer, src->Buffer, len );
181 dst->Length = 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 )
194 if (str->Buffer)
196 memset( str->Buffer, 0, str->MaximumLength );
197 str->Length = 0;
202 COMPARISON FUNCTIONS
205 /******************************************************************************
206 * RtlCompareString (NTDLL.@)
208 LONG WINAPI RtlCompareString( const STRING *s1, const STRING *s2, BOOLEAN CaseInsensitive )
210 unsigned int len;
211 LONG ret = 0;
212 LPCSTR p1, p2;
214 len = min(s1->Length, s2->Length);
215 p1 = s1->Buffer;
216 p2 = s2->Buffer;
218 if (CaseInsensitive)
220 while (!ret && len--) ret = toupper(*p1++) - toupper(*p2++);
222 else
224 while (!ret && len--) ret = *p1++ - *p2++;
226 if (!ret) ret = s1->Length - s2->Length;
227 return ret;
231 /******************************************************************************
232 * RtlCompareUnicodeString (NTDLL.@)
234 LONG WINAPI RtlCompareUnicodeString( const UNICODE_STRING *s1, const UNICODE_STRING *s2,
235 BOOLEAN CaseInsensitive )
237 unsigned int len;
238 LONG ret = 0;
239 LPCWSTR p1, p2;
241 len = min(s1->Length, s2->Length) / sizeof(WCHAR);
242 p1 = s1->Buffer;
243 p2 = s2->Buffer;
245 if (CaseInsensitive)
247 while (!ret && len--) ret = toupperW(*p1++) - toupperW(*p2++);
249 else
251 while (!ret && len--) ret = *p1++ - *p2++;
253 if (!ret) ret = s1->Length - s2->Length;
254 return ret;
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 )
286 unsigned int i;
288 if (s1->Length > s2->Length) return FALSE;
289 if (ignore_case)
291 for (i = 0; i < s1->Length; i++)
292 if (toupper(s1->Buffer[i]) != toupper(s2->Buffer[i])) return FALSE;
294 else
296 for (i = 0; i < s1->Length; i++)
297 if (s1->Buffer[i] != s2->Buffer[i]) return FALSE;
299 return TRUE;
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 )
312 unsigned int i;
314 if (s1->Length > s2->Length) return FALSE;
315 if (ignore_case)
317 for (i = 0; i < s1->Length / sizeof(WCHAR); i++)
318 if (toupper(s1->Buffer[i]) != toupper(s2->Buffer[i])) return FALSE;
320 else
322 for (i = 0; i < s1->Length / sizeof(WCHAR); i++)
323 if (s1->Buffer[i] != s2->Buffer[i]) return FALSE;
325 return TRUE;
330 COPY BETWEEN ANSI_STRING or UNICODE_STRING
331 there is no parameter checking, it just crashes
335 /**************************************************************************
336 * RtlAnsiStringToUnicodeString (NTDLL.@)
338 * NOTES:
339 * writes terminating 0
341 NTSTATUS WINAPI RtlAnsiStringToUnicodeString( PUNICODE_STRING uni,
342 PCANSI_STRING ansi,
343 BOOLEAN doalloc )
345 DWORD total = RtlAnsiStringToUnicodeSize( ansi );
347 if (total > 0xffff) return STATUS_INVALID_PARAMETER_2;
348 uni->Length = total - sizeof(WCHAR);
349 if (doalloc)
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.@)
365 * NOTES
366 * writes terminating 0
367 * if resulting length > 0xffff it returns STATUS_INVALID_PARAMETER_2
369 NTSTATUS WINAPI RtlOemStringToUnicodeString( UNICODE_STRING *uni,
370 const STRING *oem,
371 BOOLEAN doalloc )
373 DWORD total = RtlOemStringToUnicodeSize( oem );
375 if (total > 0xffff) return STATUS_INVALID_PARAMETER_2;
376 uni->Length = total - sizeof(WCHAR);
377 if (doalloc)
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.@)
393 * NOTES
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,
399 BOOLEAN doalloc )
401 NTSTATUS ret = STATUS_SUCCESS;
402 DWORD len = RtlUnicodeStringToAnsiSize( uni );
404 ansi->Length = len - 1;
405 if (doalloc)
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;
419 return ret;
423 /**************************************************************************
424 * RtlUnicodeStringToOemString (NTDLL.@)
426 * NOTES
427 * allocates uni->Length+1
428 * writes terminating 0
430 NTSTATUS WINAPI RtlUnicodeStringToOemString( STRING *oem,
431 const UNICODE_STRING *uni,
432 BOOLEAN doalloc )
434 NTSTATUS ret = STATUS_SUCCESS;
435 DWORD len = RtlUnicodeStringToOemSize( uni );
437 oem->Length = len - 1;
438 if (doalloc)
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;
452 return ret;
456 /**************************************************************************
457 * RtlMultiByteToUnicodeN (NTDLL.@)
459 * NOTES
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) );
467 if (reslen)
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) );
480 if (reslen)
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 );
494 if (reslen)
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 );
508 if (reslen)
509 *reslen = (ret >= 0) ? ret : dstlen; /* overflow -> we filled up to dstlen */
510 return STATUS_SUCCESS;
515 CASE CONVERSIONS
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]);
526 dst->Length = len;
530 /**************************************************************************
531 * RtlUpcaseUnicodeString (NTDLL.@)
533 * NOTES:
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,
540 BOOLEAN doalloc )
542 DWORD i, len = src->Length;
544 if (doalloc)
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]);
552 dest->Length = len;
553 return STATUS_SUCCESS;
557 /**************************************************************************
558 * RtlUpcaseUnicodeStringToAnsiString (NTDLL.@)
560 * NOTES
561 * writes terminating 0
563 NTSTATUS WINAPI RtlUpcaseUnicodeStringToAnsiString( STRING *dst,
564 const UNICODE_STRING *src,
565 BOOLEAN doalloc )
567 NTSTATUS ret;
568 UNICODE_STRING upcase;
570 if (!(ret = RtlUpcaseUnicodeString( &upcase, src, TRUE )))
572 ret = RtlUnicodeStringToAnsiString( dst, &upcase, doalloc );
573 RtlFreeUnicodeString( &upcase );
575 return ret;
579 /**************************************************************************
580 * RtlUpcaseUnicodeStringToOemString (NTDLL.@)
582 * NOTES
583 * writes terminating 0
585 NTSTATUS WINAPI RtlUpcaseUnicodeStringToOemString( STRING *dst,
586 const UNICODE_STRING *src,
587 BOOLEAN doalloc )
589 NTSTATUS ret;
590 UNICODE_STRING upcase;
592 if (!(ret = RtlUpcaseUnicodeString( &upcase, src, TRUE )))
594 ret = RtlUnicodeStringToOemString( dst, &upcase, doalloc );
595 RtlFreeUnicodeString( &upcase );
597 return ret;
601 /**************************************************************************
602 * RtlUpcaseUnicodeToMultiByteN (NTDLL.@)
604 NTSTATUS WINAPI RtlUpcaseUnicodeToMultiByteN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
605 LPCWSTR src, DWORD srclen )
607 NTSTATUS ret;
608 LPWSTR upcase;
609 DWORD i;
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 );
615 return ret;
619 /**************************************************************************
620 * RtlUpcaseUnicodeToOemN (NTDLL.@)
622 NTSTATUS WINAPI RtlUpcaseUnicodeToOemN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
623 LPCWSTR src, DWORD srclen )
625 NTSTATUS ret;
626 LPWSTR upcase;
627 DWORD i;
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 );
633 return ret;
638 STRING SIZE
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 )
664 DWORD ret;
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( PULONG size, LPCWSTR str, ULONG 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 )
705 DWORD ret;
706 RtlUnicodeToMultiByteSize( &ret, str->Buffer, str->Length );
707 return ret + 1;
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 );
733 dst->Length = len;
734 return STATUS_SUCCESS;
738 /**************************************************************************
739 * RtlAppendAsciizToString (NTDLL.@)
741 NTSTATUS WINAPI RtlAppendAsciizToString( STRING *dst, LPCSTR src )
743 if (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 );
749 dst->Length = total;
751 return STATUS_SUCCESS;
755 /**************************************************************************
756 * RtlAppendUnicodeToString (NTDLL.@)
758 NTSTATUS WINAPI RtlAppendUnicodeToString( UNICODE_STRING *dst, LPCWSTR src )
760 if (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 );
766 dst->Length = total;
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 );
782 dst->Length = len;
783 /* append terminating NULL if enough space */
784 if (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0;
785 return STATUS_SUCCESS;
790 MISC
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(
801 LPVOID buf,
802 DWORD len,
803 DWORD *pf)
805 LPWSTR s = buf;
806 DWORD flags = -1, out_flags = 0;
808 if (!len)
809 goto out;
810 if (pf)
811 flags = *pf;
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. */
820 if (!(len & 1))
821 out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
823 /* Check for the special unicode marker byte. */
824 if (*s == 0xFEFF)
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)
832 len = 0;
833 out:
834 if (pf)
835 *pf = out_flags;
836 return len;
839 /**************************************************************************
840 * RtlUnicodeStringToInteger (NTDLL.@)
842 * Convert a text buffer into its integer form
844 NTSTATUS WINAPI RtlUnicodeStringToInteger(
845 const UNICODE_STRING *str,
846 int base,
847 int * pdest)
849 LPWSTR lpwstr = str->Buffer;
850 WCHAR wchCurrent = 0;
851 int CharsParsed = 0;
852 int RunningTotal = 0;
853 char bMinus = 0;
855 /* no checking done on UNICODE_STRING and int* in native DLL either */
856 TRACE("(%p, %d, %p)", str, base, pdest);
858 switch (base)
860 case 0:
861 base = 10;
862 break;
863 case 2:
864 case 8:
865 case 10:
866 case 16:
867 break;
868 default:
869 return STATUS_INVALID_PARAMETER;
872 if ((str->Length) >= 4 && (base == 10) && (*lpwstr == '0') && (*(lpwstr+1) == 'x'))
874 lpwstr+=2;
875 base = 16;
878 *pdest = 0;
879 for (; (CharsParsed*sizeof(WCHAR) < str->Length) && (*lpwstr <= ' '); lpwstr++)
880 CharsParsed++;
882 if (*lpwstr == '+')
883 lpwstr++;
884 else if (*lpwstr == '-')
886 bMinus = 1;
887 lpwstr++;
890 for (; (CharsParsed*sizeof(WCHAR) < str->Length) && (*lpwstr != '\0'); lpwstr++)
892 CharsParsed++;
893 wchCurrent = *lpwstr;
894 if (wchCurrent >= 'A')
895 wchCurrent = '0' + 10 + wchCurrent - 'A';
896 if ((wchCurrent - '0') >= base || wchCurrent < '0')
898 *pdest = bMinus ? -RunningTotal: RunningTotal;
899 return STATUS_SUCCESS;
902 * increase significance of previous digits each time
903 * we find another valid one and add on this valid one
905 RunningTotal = wchCurrent - '0' + RunningTotal * base;
908 *pdest = bMinus ? -RunningTotal : RunningTotal;
909 return STATUS_SUCCESS;