dbghelp: Use local declarations of r_debug and link_map structs.
[wine.git] / dlls / ntdll / rtlstr.c
blobfc11aa46547c95af7a039e447a4af1a2b1e6ec82
1 /*
2 * Rtl string functions
4 * Copyright (C) 1996-1998 Marcus Meissner
5 * Copyright (C) 2000 Alexandre Julliard
6 * Copyright (C) 2003 Thomas Mertes
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
25 #include <assert.h>
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
30 #include "ntstatus.h"
31 #define WIN32_NO_STATUS
32 #include "windef.h"
33 #include "winnt.h"
34 #include "winternl.h"
35 #include "wine/debug.h"
36 #include "ntdll_misc.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
40 #define GUID_STRING_LENGTH 38
43 /**************************************************************************
44 * RtlInitAnsiString (NTDLL.@)
46 * Initializes a buffered ansi string.
48 * RETURNS
49 * Nothing.
51 * NOTES
52 * Assigns source to target->Buffer. The length of source is assigned to
53 * target->Length and target->MaximumLength. If source is NULL the length
54 * of source is assumed to be 0.
56 void WINAPI RtlInitAnsiString(
57 PANSI_STRING target, /* [I/O] Buffered ansi string to be initialized */
58 PCSZ source) /* [I] '\0' terminated string used to initialize target */
60 if ((target->Buffer = (PCHAR) source))
62 target->Length = strlen(source);
63 target->MaximumLength = target->Length + 1;
65 else target->Length = target->MaximumLength = 0;
68 /**************************************************************************
69 * RtlInitAnsiStringEx (NTDLL.@)
71 * Initializes a buffered ansi string.
73 * RETURNS
74 * An appropriate NTSTATUS value.
76 * NOTES
77 * Assigns source to target->Buffer. The length of source is assigned to
78 * target->Length and target->MaximumLength. If source is NULL the length
79 * of source is assumed to be 0.
81 NTSTATUS WINAPI RtlInitAnsiStringEx(PANSI_STRING target, PCSZ source)
83 if (source)
85 unsigned int len = strlen(source);
86 if (len+1 > 0xffff)
87 return STATUS_NAME_TOO_LONG;
89 target->Buffer = (PCHAR) source;
90 target->Length = len;
91 target->MaximumLength = len + 1;
93 else
95 target->Buffer = NULL;
96 target->Length = 0;
97 target->MaximumLength = 0;
99 return STATUS_SUCCESS;
102 /**************************************************************************
103 * RtlInitString (NTDLL.@)
105 * Initializes a buffered string.
107 * RETURNS
108 * Nothing.
110 * NOTES
111 * Assigns source to target->Buffer. The length of source is assigned to
112 * target->Length and target->MaximumLength. If source is NULL the length
113 * of source is assumed to be 0.
115 void WINAPI RtlInitString(
116 PSTRING target, /* [I/O] Buffered string to be initialized */
117 PCSZ source) /* [I] '\0' terminated string used to initialize target */
119 RtlInitAnsiString( target, source );
123 /**************************************************************************
124 * RtlFreeAnsiString (NTDLL.@)
126 void WINAPI RtlFreeAnsiString( PSTRING str )
128 if (str->Buffer)
130 RtlFreeHeap( GetProcessHeap(), 0, str->Buffer );
131 RtlZeroMemory( str, sizeof(*str) );
136 /**************************************************************************
137 * RtlFreeOemString (NTDLL.@)
139 void WINAPI RtlFreeOemString( PSTRING str )
141 RtlFreeAnsiString( str );
145 /**************************************************************************
146 * RtlCopyString (NTDLL.@)
148 void WINAPI RtlCopyString( STRING *dst, const STRING *src )
150 if (src)
152 unsigned int len = min( src->Length, dst->MaximumLength );
153 memcpy( dst->Buffer, src->Buffer, len );
154 dst->Length = len;
156 else dst->Length = 0;
160 /**************************************************************************
161 * RtlInitUnicodeString (NTDLL.@)
163 * Initializes a buffered unicode string.
165 * RETURNS
166 * Nothing.
168 * NOTES
169 * Assigns source to target->Buffer. The length of source is assigned to
170 * target->Length and target->MaximumLength. If source is NULL the length
171 * of source is assumed to be 0.
173 void WINAPI RtlInitUnicodeString(
174 PUNICODE_STRING target, /* [I/O] Buffered unicode string to be initialized */
175 PCWSTR source) /* [I] '\0' terminated unicode string used to initialize target */
177 if ((target->Buffer = (PWSTR) source))
179 unsigned int length = wcslen(source) * sizeof(WCHAR);
180 if (length > 0xfffc)
181 length = 0xfffc;
182 target->Length = length;
183 target->MaximumLength = target->Length + sizeof(WCHAR);
185 else target->Length = target->MaximumLength = 0;
189 /**************************************************************************
190 * RtlInitUnicodeStringEx (NTDLL.@)
192 * Initializes a buffered unicode string.
194 * RETURNS
195 * Success: STATUS_SUCCESS. target is initialized.
196 * Failure: STATUS_NAME_TOO_LONG, if the source string is larger than 65532 bytes.
198 * NOTES
199 * Assigns source to target->Buffer. The length of source is assigned to
200 * target->Length and target->MaximumLength. If source is NULL the length
201 * of source is assumed to be 0.
203 NTSTATUS WINAPI RtlInitUnicodeStringEx(
204 PUNICODE_STRING target, /* [I/O] Buffered unicode string to be initialized */
205 PCWSTR source) /* [I] '\0' terminated unicode string used to initialize target */
207 if (source != NULL) {
208 unsigned int len = wcslen(source) * sizeof(WCHAR);
210 if (len > 0xFFFC) {
211 return STATUS_NAME_TOO_LONG;
212 } else {
213 target->Length = len;
214 target->MaximumLength = len + sizeof(WCHAR);
215 target->Buffer = (PWSTR) source;
216 } /* if */
217 } else {
218 target->Length = 0;
219 target->MaximumLength = 0;
220 target->Buffer = NULL;
221 } /* if */
222 return STATUS_SUCCESS;
226 /**************************************************************************
227 * RtlCreateUnicodeString (NTDLL.@)
229 * Creates a UNICODE_STRING from a null-terminated Unicode string.
231 * RETURNS
232 * Success: TRUE
233 * Failure: FALSE
235 BOOLEAN WINAPI RtlCreateUnicodeString( PUNICODE_STRING target, LPCWSTR src )
237 int len = (wcslen(src) + 1) * sizeof(WCHAR);
238 if (!(target->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return FALSE;
239 memcpy( target->Buffer, src, len );
240 target->MaximumLength = len;
241 target->Length = len - sizeof(WCHAR);
242 return TRUE;
246 /**************************************************************************
247 * RtlCreateUnicodeStringFromAsciiz (NTDLL.@)
249 * Creates a UNICODE_STRING from a null-terminated Ascii string.
251 * RETURNS
252 * Success: TRUE
253 * Failure: FALSE
255 BOOLEAN WINAPI RtlCreateUnicodeStringFromAsciiz( PUNICODE_STRING target, LPCSTR src )
257 STRING ansi;
258 RtlInitAnsiString( &ansi, src );
259 return !RtlAnsiStringToUnicodeString( target, &ansi, TRUE );
263 /**************************************************************************
264 * RtlFreeUnicodeString (NTDLL.@)
266 * Frees a UNICODE_STRING created with RtlCreateUnicodeString() or
267 * RtlCreateUnicodeStringFromAsciiz().
269 * RETURNS
270 * nothing
272 void WINAPI RtlFreeUnicodeString( PUNICODE_STRING str )
274 if (str->Buffer)
276 RtlFreeHeap( GetProcessHeap(), 0, str->Buffer );
277 RtlZeroMemory( str, sizeof(*str) );
282 /**************************************************************************
283 * RtlCopyUnicodeString (NTDLL.@)
285 * Copies from one UNICODE_STRING to another.
287 * RETURNS
288 * nothing
290 void WINAPI RtlCopyUnicodeString( UNICODE_STRING *dst, const UNICODE_STRING *src )
292 if (src)
294 unsigned int len = min( src->Length, dst->MaximumLength );
295 memcpy( dst->Buffer, src->Buffer, len );
296 dst->Length = len;
297 /* append terminating '\0' if enough space */
298 if (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0;
300 else dst->Length = 0;
304 /**************************************************************************
305 * RtlDuplicateUnicodeString (NTDLL.@)
307 * Duplicates a unicode string.
309 * RETURNS
310 * Success: STATUS_SUCCESS. destination contains the duplicated unicode string.
311 * Failure: STATUS_INVALID_PARAMETER, if one of the parameters is illegal.
312 * STATUS_NO_MEMORY, if the allocation fails.
314 * NOTES
315 * For add_nul there are several possible values:
316 * 0 = destination will not be '\0' terminated,
317 * 1 = destination will be '\0' terminated,
318 * 3 = like 1 but for an empty source string produce '\0' terminated empty
319 * Buffer instead of assigning NULL to the Buffer.
320 * Other add_nul values are invalid.
322 NTSTATUS WINAPI RtlDuplicateUnicodeString(
323 int add_nul, /* [I] flag */
324 const UNICODE_STRING *source, /* [I] Unicode string to be duplicated */
325 UNICODE_STRING *destination) /* [O] destination for the duplicated unicode string */
327 if (source == NULL || destination == NULL ||
328 source->Length > source->MaximumLength ||
329 (source->Length == 0 && source->MaximumLength > 0 && source->Buffer == NULL) ||
330 add_nul == 2 || add_nul >= 4 || add_nul < 0) {
331 return STATUS_INVALID_PARAMETER;
332 } else {
333 if (source->Length == 0 && add_nul != 3) {
334 destination->Length = 0;
335 destination->MaximumLength = 0;
336 destination->Buffer = NULL;
337 } else {
338 unsigned int destination_max_len = source->Length;
340 if (add_nul) {
341 destination_max_len += sizeof(WCHAR);
342 } /* if */
343 destination->Buffer = RtlAllocateHeap(GetProcessHeap(), 0, destination_max_len);
344 if (destination->Buffer == NULL) {
345 return STATUS_NO_MEMORY;
346 } else {
347 memcpy(destination->Buffer, source->Buffer, source->Length);
348 destination->Length = source->Length;
349 destination->MaximumLength = source->Length;
350 /* append terminating '\0' if enough space */
351 if (add_nul) {
352 destination->MaximumLength = destination_max_len;
353 destination->Buffer[destination->Length / sizeof(WCHAR)] = 0;
354 } /* if */
355 } /* if */
356 } /* if */
357 } /* if */
358 return STATUS_SUCCESS;
362 /**************************************************************************
363 * RtlEraseUnicodeString (NTDLL.@)
365 * Overwrites a UNICODE_STRING with zeros.
367 * RETURNS
368 * nothing
370 void WINAPI RtlEraseUnicodeString( UNICODE_STRING *str )
372 if (str->Buffer)
374 memset( str->Buffer, 0, str->MaximumLength );
375 str->Length = 0;
381 COMPARISON FUNCTIONS
385 /******************************************************************************
386 * RtlCompareString (NTDLL.@)
388 LONG WINAPI RtlCompareString( const STRING *s1, const STRING *s2, BOOLEAN CaseInsensitive )
390 unsigned int len;
391 LONG ret = 0;
392 LPCSTR p1, p2;
394 len = min(s1->Length, s2->Length);
395 p1 = s1->Buffer;
396 p2 = s2->Buffer;
398 if (CaseInsensitive)
400 while (!ret && len--) ret = RtlUpperChar(*p1++) - RtlUpperChar(*p2++);
402 else
404 while (!ret && len--) ret = *p1++ - *p2++;
406 if (!ret) ret = s1->Length - s2->Length;
407 return ret;
411 /******************************************************************************
412 * RtlCompareUnicodeString (NTDLL.@)
414 LONG WINAPI RtlCompareUnicodeString( const UNICODE_STRING *s1, const UNICODE_STRING *s2,
415 BOOLEAN CaseInsensitive )
417 return RtlCompareUnicodeStrings( s1->Buffer, s1->Length / sizeof(WCHAR),
418 s2->Buffer, s2->Length / sizeof(WCHAR), CaseInsensitive );
422 /**************************************************************************
423 * RtlEqualString (NTDLL.@)
425 * Determine if two strings are equal.
427 * PARAMS
428 * s1 [I] Source string
429 * s2 [I] String to compare to s1
430 * CaseInsensitive [I] TRUE = Case insensitive, FALSE = Case sensitive
432 * RETURNS
433 * Non-zero if s1 is equal to s2, 0 otherwise.
435 BOOLEAN WINAPI RtlEqualString( const STRING *s1, const STRING *s2, BOOLEAN CaseInsensitive )
437 if (s1->Length != s2->Length) return FALSE;
438 return !RtlCompareString( s1, s2, CaseInsensitive );
442 /**************************************************************************
443 * RtlEqualUnicodeString (NTDLL.@)
445 * Unicode version of RtlEqualString.
447 BOOLEAN WINAPI RtlEqualUnicodeString( const UNICODE_STRING *s1, const UNICODE_STRING *s2,
448 BOOLEAN CaseInsensitive )
450 if (s1->Length != s2->Length) return FALSE;
451 return !RtlCompareUnicodeString( s1, s2, CaseInsensitive );
455 /**************************************************************************
456 * RtlPrefixString (NTDLL.@)
458 * Determine if one string is a prefix of another.
460 * PARAMS
461 * s1 [I] Prefix to look for in s2
462 * s2 [I] String that may contain s1 as a prefix
463 * ignore_case [I] TRUE = Case insensitive, FALSE = Case sensitive
465 * RETURNS
466 * TRUE if s2 contains s1 as a prefix, FALSE otherwise.
468 BOOLEAN WINAPI RtlPrefixString( const STRING *s1, const STRING *s2, BOOLEAN ignore_case )
470 unsigned int i;
472 if (s1->Length > s2->Length) return FALSE;
473 if (ignore_case)
475 for (i = 0; i < s1->Length; i++)
476 if (RtlUpperChar(s1->Buffer[i]) != RtlUpperChar(s2->Buffer[i])) return FALSE;
478 else
480 for (i = 0; i < s1->Length; i++)
481 if (s1->Buffer[i] != s2->Buffer[i]) return FALSE;
483 return TRUE;
487 /**************************************************************************
488 * RtlEqualComputerName (NTDLL.@)
490 * Determine if two computer names are the same.
492 * PARAMS
493 * left [I] First computer name
494 * right [I] Second computer name
496 * RETURNS
497 * 0 if the names are equal, non-zero otherwise.
499 * NOTES
500 * The comparison is case insensitive.
502 NTSTATUS WINAPI RtlEqualComputerName(const UNICODE_STRING *left,
503 const UNICODE_STRING *right)
505 NTSTATUS ret;
506 STRING upLeft, upRight;
508 if (!(ret = RtlUpcaseUnicodeStringToOemString( &upLeft, left, TRUE )))
510 if (!(ret = RtlUpcaseUnicodeStringToOemString( &upRight, right, TRUE )))
512 ret = RtlEqualString( &upLeft, &upRight, FALSE );
513 RtlFreeOemString( &upRight );
515 RtlFreeOemString( &upLeft );
517 return ret;
521 /**************************************************************************
522 * RtlEqualDomainName (NTDLL.@)
524 * Determine if two domain names are the same.
526 * PARAMS
527 * left [I] First domain name
528 * right [I] Second domain name
530 * RETURNS
531 * 0 if the names are equal, non-zero otherwise.
533 * NOTES
534 * The comparison is case insensitive.
536 NTSTATUS WINAPI RtlEqualDomainName(const UNICODE_STRING *left,
537 const UNICODE_STRING *right)
539 return RtlEqualComputerName(left, right);
544 COPY BETWEEN ANSI_STRING or UNICODE_STRING
545 there is no parameter checking, it just crashes
549 /**************************************************************************
550 * RtlAnsiStringToUnicodeString (NTDLL.@)
552 * Converts an ansi string to a unicode string.
554 * RETURNS
555 * Success: STATUS_SUCCESS. uni contains the converted string
556 * Failure: STATUS_BUFFER_OVERFLOW, if doalloc is FALSE and ansi is too small.
557 * STATUS_NO_MEMORY, if doalloc is TRUE and the allocation fails.
558 * STATUS_INVALID_PARAMETER_2, if the unicode string would be larger than 65535.
560 * NOTES
561 * This function always writes a terminating '\0'.
563 NTSTATUS WINAPI RtlAnsiStringToUnicodeString(
564 PUNICODE_STRING uni, /* [I/O] Destination for the unicode string */
565 PCANSI_STRING ansi, /* [I] Ansi string to be converted */
566 BOOLEAN doalloc) /* [I] TRUE=Allocate new buffer for uni, FALSE=Use existing buffer */
568 DWORD total = RtlAnsiStringToUnicodeSize( ansi );
570 if (total > 0xffff) return STATUS_INVALID_PARAMETER_2;
571 uni->Length = total - sizeof(WCHAR);
572 if (doalloc)
574 uni->MaximumLength = total;
575 if (!(uni->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, total )))
576 return STATUS_NO_MEMORY;
578 else if (total > uni->MaximumLength) return STATUS_BUFFER_OVERFLOW;
580 RtlMultiByteToUnicodeN( uni->Buffer, uni->Length, NULL, ansi->Buffer, ansi->Length );
581 uni->Buffer[uni->Length / sizeof(WCHAR)] = 0;
582 return STATUS_SUCCESS;
586 /**************************************************************************
587 * RtlOemStringToUnicodeString (NTDLL.@)
589 * Converts an oem string to a unicode string.
591 * RETURNS
592 * Success: STATUS_SUCCESS. uni contains the converted string
593 * Failure: STATUS_BUFFER_OVERFLOW, if doalloc is FALSE and oem is too small.
594 * STATUS_NO_MEMORY, if doalloc is TRUE and the allocation fails.
595 * STATUS_INVALID_PARAMETER_2, if the unicode string would be larger than 65535.
597 * NOTES
598 * This function always writes a terminating '\0'.
600 NTSTATUS WINAPI RtlOemStringToUnicodeString(
601 UNICODE_STRING *uni, /* [I/O] Destination for the unicode string */
602 const STRING *oem, /* [I] Oem string to be converted */
603 BOOLEAN doalloc) /* [I] TRUE=Allocate new buffer for uni, FALSE=Use existing buffer */
605 DWORD total = RtlOemStringToUnicodeSize( oem );
607 if (total > 0xffff) return STATUS_INVALID_PARAMETER_2;
608 uni->Length = total - sizeof(WCHAR);
609 if (doalloc)
611 uni->MaximumLength = total;
612 if (!(uni->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, total )))
613 return STATUS_NO_MEMORY;
615 else if (total > uni->MaximumLength) return STATUS_BUFFER_OVERFLOW;
617 RtlOemToUnicodeN( uni->Buffer, uni->Length, NULL, oem->Buffer, oem->Length );
618 uni->Buffer[uni->Length / sizeof(WCHAR)] = 0;
619 return STATUS_SUCCESS;
623 /**************************************************************************
624 * RtlUnicodeStringToAnsiString (NTDLL.@)
626 * Converts a unicode string to an ansi string.
628 * RETURNS
629 * Success: STATUS_SUCCESS. ansi contains the converted string
630 * Failure: STATUS_BUFFER_OVERFLOW, if doalloc is FALSE and ansi is too small.
631 * STATUS_NO_MEMORY, if doalloc is TRUE and the allocation fails.
633 * NOTES
634 * This function always writes a terminating '\0'.
635 * It performs a partial copy if ansi is too small.
637 NTSTATUS WINAPI RtlUnicodeStringToAnsiString(
638 STRING *ansi, /* [I/O] Destination for the ansi string */
639 const UNICODE_STRING *uni, /* [I] Unicode string to be converted */
640 BOOLEAN doalloc) /* [I] TRUE=Allocate new buffer for ansi, FALSE=Use existing buffer */
642 NTSTATUS ret = STATUS_SUCCESS;
643 DWORD len = RtlUnicodeStringToAnsiSize( uni );
645 ansi->Length = len - 1;
646 if (doalloc)
648 ansi->MaximumLength = len;
649 if (!(ansi->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
650 return STATUS_NO_MEMORY;
652 else if (ansi->MaximumLength < len)
654 if (!ansi->MaximumLength) return STATUS_BUFFER_OVERFLOW;
655 ansi->Length = ansi->MaximumLength - 1;
656 ret = STATUS_BUFFER_OVERFLOW;
659 RtlUnicodeToMultiByteN( ansi->Buffer, ansi->Length, NULL, uni->Buffer, uni->Length );
660 ansi->Buffer[ansi->Length] = 0;
661 return ret;
665 /**************************************************************************
666 * RtlUnicodeStringToOemString (NTDLL.@)
668 * Converts a Rtl Unicode string to an OEM string.
670 * PARAMS
671 * oem [O] Destination for OEM string
672 * uni [I] Source Unicode string
673 * doalloc [I] TRUE=Allocate new buffer for oem,FALSE=Use existing buffer
675 * RETURNS
676 * Success: STATUS_SUCCESS. oem contains the converted string
677 * Failure: STATUS_BUFFER_OVERFLOW, if doalloc is FALSE and oem is too small.
678 * STATUS_NO_MEMORY, if doalloc is TRUE and allocation fails.
680 * NOTES
681 * If doalloc is TRUE, the length allocated is uni->Length + 1.
682 * This function always '\0' terminates the string returned.
684 NTSTATUS WINAPI RtlUnicodeStringToOemString( STRING *oem,
685 const UNICODE_STRING *uni,
686 BOOLEAN doalloc )
688 NTSTATUS ret = STATUS_SUCCESS;
689 DWORD len = RtlUnicodeStringToOemSize( uni );
691 oem->Length = len - 1;
692 if (doalloc)
694 oem->MaximumLength = len;
695 if (!(oem->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
696 return STATUS_NO_MEMORY;
698 else if (oem->MaximumLength < len)
700 if (!oem->MaximumLength) return STATUS_BUFFER_OVERFLOW;
701 oem->Length = oem->MaximumLength - 1;
702 ret = STATUS_BUFFER_OVERFLOW;
705 RtlUnicodeToOemN( oem->Buffer, oem->Length, NULL, uni->Buffer, uni->Length );
706 oem->Buffer[oem->Length] = 0;
707 return ret;
712 CASE CONVERSIONS
716 /**************************************************************************
717 * RtlUpperChar (NTDLL.@)
719 * Converts an Ascii character to uppercase.
721 * PARAMS
722 * ch [I] Character to convert
724 * RETURNS
725 * The uppercase character value.
727 * NOTES
728 * For the input characters from 'a' .. 'z' it returns 'A' .. 'Z'.
729 * All other input characters are returned unchanged. The locale and
730 * multibyte characters are not taken into account (as native DLL).
732 CHAR WINAPI RtlUpperChar( CHAR ch )
734 if (ch >= 'a' && ch <= 'z') {
735 return ch - 'a' + 'A';
736 } else {
737 return ch;
738 } /* if */
742 /**************************************************************************
743 * RtlUpperString (NTDLL.@)
745 * Converts an Ascii string to uppercase.
747 * PARAMS
748 * dst [O] Destination for converted string
749 * src [I] Source string to convert
751 * RETURNS
752 * Nothing.
754 * NOTES
755 * For the src characters from 'a' .. 'z' it assigns 'A' .. 'Z' to dst.
756 * All other src characters are copied unchanged to dst. The locale and
757 * multibyte characters are not taken into account (as native DLL).
758 * The number of character copied is the minimum of src->Length and
759 * the dst->MaximumLength.
761 void WINAPI RtlUpperString( STRING *dst, const STRING *src )
763 unsigned int i, len = min(src->Length, dst->MaximumLength);
765 for (i = 0; i < len; i++) dst->Buffer[i] = RtlUpperChar(src->Buffer[i]);
766 dst->Length = len;
770 /**************************************************************************
771 * RtlUpcaseUnicodeStringToAnsiString (NTDLL.@)
773 * Converts a Unicode string to the equivalent ANSI upper-case representation.
775 * RETURNS
776 * NTSTATUS code
778 * NOTES
779 * writes terminating 0
781 NTSTATUS WINAPI RtlUpcaseUnicodeStringToAnsiString( STRING *ansi,
782 const UNICODE_STRING *uni,
783 BOOLEAN doalloc )
785 NTSTATUS ret = STATUS_SUCCESS;
786 DWORD len = RtlUnicodeStringToAnsiSize( uni );
788 ansi->Length = len - 1;
789 if (doalloc)
791 ansi->MaximumLength = len;
792 if (!(ansi->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
793 return STATUS_NO_MEMORY;
795 else if (ansi->MaximumLength < len)
797 if (!ansi->MaximumLength) return STATUS_BUFFER_OVERFLOW;
798 ansi->Length = ansi->MaximumLength - 1;
799 ret = STATUS_BUFFER_OVERFLOW;
802 RtlUpcaseUnicodeToMultiByteN( ansi->Buffer, ansi->Length, NULL, uni->Buffer, uni->Length );
803 ansi->Buffer[ansi->Length] = 0;
804 return ret;
808 /**************************************************************************
809 * RtlUpcaseUnicodeStringToOemString (NTDLL.@)
811 * Converts a UNICODE_STRING to the equivalent OEM upper-case representation
812 * stored in STRING format.
814 * RETURNS
815 * NTSTATUS code
817 * NOTES
818 * writes terminating 0
820 NTSTATUS WINAPI RtlUpcaseUnicodeStringToOemString( STRING *oem,
821 const UNICODE_STRING *uni,
822 BOOLEAN doalloc )
824 NTSTATUS ret = STATUS_SUCCESS;
825 DWORD len = RtlUnicodeStringToAnsiSize( uni );
827 oem->Length = len - 1;
828 if (doalloc)
830 oem->MaximumLength = len;
831 if (!(oem->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
832 return STATUS_NO_MEMORY;
834 else if (oem->MaximumLength < len)
836 if (!oem->MaximumLength) return STATUS_BUFFER_OVERFLOW;
837 oem->Length = oem->MaximumLength - 1;
838 ret = STATUS_BUFFER_OVERFLOW;
841 RtlUpcaseUnicodeToOemN( oem->Buffer, oem->Length, NULL, uni->Buffer, uni->Length );
842 oem->Buffer[oem->Length] = 0;
843 return ret;
847 /**************************************************************************
848 * RtlUpcaseUnicodeStringToCountedOemString (NTDLL.@)
850 * Converts a UNICODE_STRING to the equivalent OEM upper-case representation
851 * stored in STRING format.
853 * RETURNS
854 * NTSTATUS code
856 * NOTES
857 * Same as RtlUpcaseUnicodeStringToOemString but doesn't write terminating null
859 NTSTATUS WINAPI RtlUpcaseUnicodeStringToCountedOemString( STRING *oem,
860 const UNICODE_STRING *uni,
861 BOOLEAN doalloc )
863 NTSTATUS ret = STATUS_SUCCESS;
864 DWORD len = RtlUnicodeStringToOemSize( uni ) - 1;
866 oem->Length = len;
867 if (doalloc)
869 oem->MaximumLength = len;
870 if (!(oem->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY;
872 else if (oem->MaximumLength < len)
874 ret = STATUS_BUFFER_OVERFLOW;
875 oem->Length = oem->MaximumLength;
876 if (!oem->MaximumLength) return ret;
878 RtlUpcaseUnicodeToOemN( oem->Buffer, oem->Length, NULL, uni->Buffer, uni->Length );
879 return ret;
884 STRING SIZE
888 /**************************************************************************
889 * RtlAnsiStringToUnicodeSize (NTDLL.@)
890 * RtlxAnsiStringToUnicodeSize (NTDLL.@)
892 * Calculate the size in bytes necessary for the Unicode conversion of str,
893 * including the terminating '\0'.
895 * PARAMS
896 * str [I] String to calculate the size of
898 * RETURNS
899 * The calculated size.
901 DWORD WINAPI RtlAnsiStringToUnicodeSize( const STRING *str )
903 DWORD ret;
904 RtlMultiByteToUnicodeSize( &ret, str->Buffer, str->Length );
905 return ret + sizeof(WCHAR);
909 /**************************************************************************
910 * RtlUnicodeStringToAnsiSize (NTDLL.@)
911 * RtlxUnicodeStringToAnsiSize (NTDLL.@)
913 * Calculate the size in bytes necessary for the Ansi conversion of str,
914 * including the terminating '\0'.
916 * PARAMS
917 * str [I] String to calculate the size of
919 * RETURNS
920 * The calculated size.
922 DWORD WINAPI RtlUnicodeStringToAnsiSize( const UNICODE_STRING *str )
924 DWORD ret;
925 RtlUnicodeToMultiByteSize( &ret, str->Buffer, str->Length );
926 return ret + 1;
930 /**************************************************************************
931 * RtlAppendAsciizToString (NTDLL.@)
933 * Concatenates a buffered character string and a '\0' terminated character
934 * string
936 * RETURNS
937 * Success: STATUS_SUCCESS. src is appended to dest.
938 * Failure: STATUS_BUFFER_TOO_SMALL, if the buffer of dest is too small
939 * to hold the concatenated string.
941 * NOTES
942 * if src is NULL dest is unchanged.
943 * dest is never '\0' terminated.
945 NTSTATUS WINAPI RtlAppendAsciizToString(
946 STRING *dest, /* [I/O] Buffered character string to which src is concatenated */
947 LPCSTR src) /* [I] '\0' terminated character string to be concatenated */
949 if (src != NULL) {
950 unsigned int src_len = strlen(src);
951 unsigned int dest_len = src_len + dest->Length;
953 if (dest_len > dest->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
954 memcpy(dest->Buffer + dest->Length, src, src_len);
955 dest->Length = dest_len;
956 } /* if */
957 return STATUS_SUCCESS;
961 /**************************************************************************
962 * RtlAppendStringToString (NTDLL.@)
964 * Concatenates two buffered character strings
966 * RETURNS
967 * Success: STATUS_SUCCESS. src is appended to dest.
968 * Failure: STATUS_BUFFER_TOO_SMALL, if the buffer of dest is too small
969 * to hold the concatenated string.
971 * NOTES
972 * if src->length is zero dest is unchanged.
973 * dest is never '\0' terminated.
975 NTSTATUS WINAPI RtlAppendStringToString(
976 STRING *dest, /* [I/O] Buffered character string to which src is concatenated */
977 const STRING *src) /* [I] Buffered character string to be concatenated */
979 if (src->Length != 0) {
980 unsigned int dest_len = src->Length + dest->Length;
982 if (dest_len > dest->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
983 memcpy(dest->Buffer + dest->Length, src->Buffer, src->Length);
984 dest->Length = dest_len;
985 } /* if */
986 return STATUS_SUCCESS;
990 /**************************************************************************
991 * RtlAppendUnicodeToString (NTDLL.@)
993 * Concatenates a buffered unicode string and a '\0' terminated unicode
994 * string
996 * RETURNS
997 * Success: STATUS_SUCCESS. src is appended to dest.
998 * Failure: STATUS_BUFFER_TOO_SMALL, if the buffer of dest is too small
999 * to hold the concatenated string.
1001 * NOTES
1002 * if src is NULL dest is unchanged.
1003 * dest is '\0' terminated when the MaximumLength allows it.
1004 * When dest fits exactly in MaximumLength characters the '\0' is omitted.
1006 * DIFFERENCES
1007 * Does not write in the src->Buffer beyond MaximumLength when
1008 * MaximumLength is odd as the native function does.
1010 NTSTATUS WINAPI RtlAppendUnicodeToString(
1011 UNICODE_STRING *dest, /* [I/O] Buffered unicode string to which src is concatenated */
1012 LPCWSTR src) /* [I] '\0' terminated unicode string to be concatenated */
1014 if (src != NULL) {
1015 unsigned int src_len = wcslen(src) * sizeof(WCHAR);
1016 unsigned int dest_len = src_len + dest->Length;
1018 if (dest_len > dest->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
1019 memcpy(dest->Buffer + dest->Length/sizeof(WCHAR), src, src_len);
1020 dest->Length = dest_len;
1021 /* append terminating '\0' if enough space */
1022 if (dest_len + sizeof(WCHAR) <= dest->MaximumLength) {
1023 dest->Buffer[dest_len / sizeof(WCHAR)] = 0;
1024 } /* if */
1025 } /* if */
1026 return STATUS_SUCCESS;
1030 /**************************************************************************
1031 * RtlAppendUnicodeStringToString (NTDLL.@)
1033 * Concatenates two buffered unicode strings
1035 * RETURNS
1036 * Success: STATUS_SUCCESS. src is appended to dest.
1037 * Failure: STATUS_BUFFER_TOO_SMALL, if the buffer of dest is too small
1038 * to hold the concatenated string.
1040 * NOTES
1041 * if src->length is zero dest is unchanged.
1042 * dest is '\0' terminated when the MaximumLength allows it.
1043 * When dest fits exactly in MaximumLength characters the '\0' is omitted.
1045 * DIFFERENCES
1046 * Does not write in the src->Buffer beyond MaximumLength when
1047 * MaximumLength is odd as the native function does.
1049 NTSTATUS WINAPI RtlAppendUnicodeStringToString(
1050 UNICODE_STRING *dest, /* [I/O] Buffered unicode string to which src is concatenated */
1051 const UNICODE_STRING *src) /* [I] Buffered unicode string to be concatenated */
1053 if (src->Length != 0) {
1054 unsigned int dest_len = src->Length + dest->Length;
1056 if (dest_len > dest->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
1057 memcpy(dest->Buffer + dest->Length/sizeof(WCHAR), src->Buffer, src->Length);
1058 dest->Length = dest_len;
1059 /* append terminating '\0' if enough space */
1060 if (dest_len + sizeof(WCHAR) <= dest->MaximumLength) {
1061 dest->Buffer[dest_len / sizeof(WCHAR)] = 0;
1062 } /* if */
1063 } /* if */
1064 return STATUS_SUCCESS;
1068 /**************************************************************************
1069 * RtlFindCharInUnicodeString (NTDLL.@)
1071 * Searches for one of several unicode characters in a unicode string.
1073 * RETURNS
1074 * Success: STATUS_SUCCESS. pos contains the position after the character found.
1075 * Failure: STATUS_NOT_FOUND, if none of the search_chars are in main_str.
1077 NTSTATUS WINAPI RtlFindCharInUnicodeString(
1078 int flags, /* [I] Flags */
1079 const UNICODE_STRING *main_str, /* [I] Unicode string in which one or more characters are searched */
1080 const UNICODE_STRING *search_chars, /* [I] Unicode string which contains the characters to search for */
1081 USHORT *pos) /* [O] Position of the first character found + 2 */
1083 unsigned int main_idx, search_idx;
1085 switch (flags) {
1086 case 0:
1087 for (main_idx = 0; main_idx < main_str->Length / sizeof(WCHAR); main_idx++) {
1088 for (search_idx = 0; search_idx < search_chars->Length / sizeof(WCHAR); search_idx++) {
1089 if (main_str->Buffer[main_idx] == search_chars->Buffer[search_idx]) {
1090 *pos = (main_idx + 1) * sizeof(WCHAR);
1091 return STATUS_SUCCESS;
1095 *pos = 0;
1096 return STATUS_NOT_FOUND;
1097 case 1:
1098 main_idx = main_str->Length / sizeof(WCHAR);
1099 while (main_idx-- > 0) {
1100 for (search_idx = 0; search_idx < search_chars->Length / sizeof(WCHAR); search_idx++) {
1101 if (main_str->Buffer[main_idx] == search_chars->Buffer[search_idx]) {
1102 *pos = main_idx * sizeof(WCHAR);
1103 return STATUS_SUCCESS;
1107 *pos = 0;
1108 return STATUS_NOT_FOUND;
1109 case 2:
1110 for (main_idx = 0; main_idx < main_str->Length / sizeof(WCHAR); main_idx++) {
1111 search_idx = 0;
1112 while (search_idx < search_chars->Length / sizeof(WCHAR) &&
1113 main_str->Buffer[main_idx] != search_chars->Buffer[search_idx]) {
1114 search_idx++;
1116 if (search_idx >= search_chars->Length / sizeof(WCHAR)) {
1117 *pos = (main_idx + 1) * sizeof(WCHAR);
1118 return STATUS_SUCCESS;
1121 *pos = 0;
1122 return STATUS_NOT_FOUND;
1123 case 3:
1124 main_idx = main_str->Length / sizeof(WCHAR);
1125 while (main_idx-- > 0) {
1126 search_idx = 0;
1127 while (search_idx < search_chars->Length / sizeof(WCHAR) &&
1128 main_str->Buffer[main_idx] != search_chars->Buffer[search_idx]) {
1129 search_idx++;
1131 if (search_idx >= search_chars->Length / sizeof(WCHAR)) {
1132 *pos = main_idx * sizeof(WCHAR);
1133 return STATUS_SUCCESS;
1136 *pos = 0;
1137 return STATUS_NOT_FOUND;
1138 } /* switch */
1139 return STATUS_NOT_FOUND;
1144 MISC
1147 /**************************************************************************
1148 * RtlIsTextUnicode (NTDLL.@)
1150 * Attempt to guess whether a text buffer is Unicode.
1152 * PARAMS
1153 * buf [I] Text buffer to test
1154 * len [I] Length of buf
1155 * pf [O] Destination for test results
1157 * RETURNS
1158 * TRUE if the buffer is likely Unicode, FALSE otherwise.
1160 * FIXME
1161 * Should implement more tests.
1163 BOOLEAN WINAPI RtlIsTextUnicode( LPCVOID buf, INT len, INT *pf )
1165 static const WCHAR std_control_chars[] = {'\r','\n','\t',' ',0x3000,0};
1166 static const WCHAR byterev_control_chars[] = {0x0d00,0x0a00,0x0900,0x2000,0};
1167 const WCHAR *s = buf;
1168 int i;
1169 unsigned int flags = ~0U, out_flags = 0;
1171 if (len < sizeof(WCHAR))
1173 /* FIXME: MSDN documents IS_TEXT_UNICODE_BUFFER_TOO_SMALL but there is no such thing... */
1174 if (pf) *pf = 0;
1175 return FALSE;
1177 if (pf)
1178 flags = *pf;
1180 * Apply various tests to the text string. According to the
1181 * docs, each test "passed" sets the corresponding flag in
1182 * the output flags. But some of the tests are mutually
1183 * exclusive, so I don't see how you could pass all tests ...
1186 /* Check for an odd length ... pass if even. */
1187 if (len & 1) out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
1189 if (((const char *)buf)[len - 1] == 0)
1190 len--; /* Windows seems to do something like that to avoid e.g. false IS_TEXT_UNICODE_NULL_BYTES */
1192 len /= sizeof(WCHAR);
1193 /* Windows only checks the first 256 characters */
1194 if (len > 256) len = 256;
1196 /* Check for the special byte order unicode marks. */
1197 if (*s == 0xFEFF) out_flags |= IS_TEXT_UNICODE_SIGNATURE;
1198 if (*s == 0xFFFE) out_flags |= IS_TEXT_UNICODE_REVERSE_SIGNATURE;
1200 /* apply some statistical analysis */
1201 if (flags & IS_TEXT_UNICODE_STATISTICS)
1203 int stats = 0;
1204 /* FIXME: checks only for ASCII characters in the unicode stream */
1205 for (i = 0; i < len; i++)
1207 if (s[i] <= 255) stats++;
1209 if (stats > len / 2)
1210 out_flags |= IS_TEXT_UNICODE_STATISTICS;
1213 /* Check for unicode NULL chars */
1214 if (flags & IS_TEXT_UNICODE_NULL_BYTES)
1216 for (i = 0; i < len; i++)
1218 if (!(s[i] & 0xff) || !(s[i] >> 8))
1220 out_flags |= IS_TEXT_UNICODE_NULL_BYTES;
1221 break;
1226 if (flags & IS_TEXT_UNICODE_CONTROLS)
1228 for (i = 0; i < len; i++)
1230 if (wcschr(std_control_chars, s[i]))
1232 out_flags |= IS_TEXT_UNICODE_CONTROLS;
1233 break;
1238 if (flags & IS_TEXT_UNICODE_REVERSE_CONTROLS)
1240 for (i = 0; i < len; i++)
1242 if (wcschr(byterev_control_chars, s[i]))
1244 out_flags |= IS_TEXT_UNICODE_REVERSE_CONTROLS;
1245 break;
1250 if (pf)
1252 out_flags &= *pf;
1253 *pf = out_flags;
1255 /* check for flags that indicate it's definitely not valid Unicode */
1256 if (out_flags & (IS_TEXT_UNICODE_REVERSE_MASK | IS_TEXT_UNICODE_NOT_UNICODE_MASK)) return FALSE;
1257 /* now check for invalid ASCII, and assume Unicode if so */
1258 if (out_flags & IS_TEXT_UNICODE_NOT_ASCII_MASK) return TRUE;
1259 /* now check for Unicode flags */
1260 if (out_flags & IS_TEXT_UNICODE_UNICODE_MASK) return TRUE;
1261 /* no flags set */
1262 return FALSE;
1266 /**************************************************************************
1267 * RtlCharToInteger (NTDLL.@)
1269 * Converts a character string into its integer equivalent.
1271 * RETURNS
1272 * Success: STATUS_SUCCESS. value contains the converted number
1273 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
1274 * STATUS_ACCESS_VIOLATION, if value is NULL.
1276 * NOTES
1277 * For base 0 it uses 10 as base and the string should be in the format
1278 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
1279 * For other bases the string should be in the format
1280 * "{whitespace} [+|-] {digits}".
1281 * No check is made for value overflow, only the lower 32 bits are assigned.
1282 * If str is NULL it crashes, as the native function does.
1284 * DIFFERENCES
1285 * This function does not read garbage behind '\0' as the native version does.
1287 NTSTATUS WINAPI RtlCharToInteger(
1288 PCSZ str, /* [I] '\0' terminated single-byte string containing a number */
1289 ULONG base, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
1290 ULONG *value) /* [O] Destination for the converted value */
1292 CHAR chCurrent;
1293 int digit;
1294 ULONG RunningTotal = 0;
1295 BOOL bMinus = FALSE;
1297 while (*str != '\0' && *str <= ' ') {
1298 str++;
1299 } /* while */
1301 if (*str == '+') {
1302 str++;
1303 } else if (*str == '-') {
1304 bMinus = TRUE;
1305 str++;
1306 } /* if */
1308 if (base == 0) {
1309 base = 10;
1310 if (str[0] == '0') {
1311 if (str[1] == 'b') {
1312 str += 2;
1313 base = 2;
1314 } else if (str[1] == 'o') {
1315 str += 2;
1316 base = 8;
1317 } else if (str[1] == 'x') {
1318 str += 2;
1319 base = 16;
1320 } /* if */
1321 } /* if */
1322 } else if (base != 2 && base != 8 && base != 10 && base != 16) {
1323 return STATUS_INVALID_PARAMETER;
1324 } /* if */
1326 if (value == NULL) {
1327 return STATUS_ACCESS_VIOLATION;
1328 } /* if */
1330 while (*str != '\0') {
1331 chCurrent = *str;
1332 if (chCurrent >= '0' && chCurrent <= '9') {
1333 digit = chCurrent - '0';
1334 } else if (chCurrent >= 'A' && chCurrent <= 'Z') {
1335 digit = chCurrent - 'A' + 10;
1336 } else if (chCurrent >= 'a' && chCurrent <= 'z') {
1337 digit = chCurrent - 'a' + 10;
1338 } else {
1339 digit = -1;
1340 } /* if */
1341 if (digit < 0 || digit >= base) {
1342 *value = bMinus ? -RunningTotal : RunningTotal;
1343 return STATUS_SUCCESS;
1344 } /* if */
1346 RunningTotal = RunningTotal * base + digit;
1347 str++;
1348 } /* while */
1350 *value = bMinus ? -RunningTotal : RunningTotal;
1351 return STATUS_SUCCESS;
1355 /**************************************************************************
1356 * RtlIntegerToChar (NTDLL.@)
1358 * Converts an unsigned integer to a character string.
1360 * RETURNS
1361 * Success: STATUS_SUCCESS. str contains the converted number
1362 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
1363 * STATUS_BUFFER_OVERFLOW, if str would be larger than length.
1364 * STATUS_ACCESS_VIOLATION, if str is NULL.
1366 * NOTES
1367 * Instead of base 0 it uses 10 as base.
1368 * Writes at most length characters to the string str.
1369 * Str is '\0' terminated when length allows it.
1370 * When str fits exactly in length characters the '\0' is omitted.
1372 NTSTATUS WINAPI RtlIntegerToChar(
1373 ULONG value, /* [I] Value to be converted */
1374 ULONG base, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
1375 ULONG length, /* [I] Length of the str buffer in bytes */
1376 PCHAR str) /* [O] Destination for the converted value */
1378 CHAR buffer[33];
1379 PCHAR pos;
1380 CHAR digit;
1381 ULONG len;
1383 if (base == 0) {
1384 base = 10;
1385 } else if (base != 2 && base != 8 && base != 10 && base != 16) {
1386 return STATUS_INVALID_PARAMETER;
1387 } /* if */
1389 pos = &buffer[32];
1390 *pos = '\0';
1392 do {
1393 pos--;
1394 digit = value % base;
1395 value = value / base;
1396 if (digit < 10) {
1397 *pos = '0' + digit;
1398 } else {
1399 *pos = 'A' + digit - 10;
1400 } /* if */
1401 } while (value != 0L);
1403 len = &buffer[32] - pos;
1404 if (len > length) {
1405 return STATUS_BUFFER_OVERFLOW;
1406 } else if (str == NULL) {
1407 return STATUS_ACCESS_VIOLATION;
1408 } else if (len == length) {
1409 memcpy(str, pos, len);
1410 } else {
1411 memcpy(str, pos, len + 1);
1412 } /* if */
1413 return STATUS_SUCCESS;
1417 /**************************************************************************
1418 * RtlUnicodeStringToInteger (NTDLL.@)
1420 * Converts a unicode string into its integer equivalent.
1422 * RETURNS
1423 * Success: STATUS_SUCCESS. value contains the converted number
1424 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
1425 * STATUS_ACCESS_VIOLATION, if value is NULL.
1427 * NOTES
1428 * For base 0 it uses 10 as base and the string should be in the format
1429 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
1430 * For other bases the string should be in the format
1431 * "{whitespace} [+|-] {digits}".
1432 * No check is made for value overflow, only the lower 32 bits are assigned.
1433 * If str is NULL it crashes, as the native function does.
1435 * DIFFERENCES
1436 * This function does not read garbage on string length 0 as the native
1437 * version does.
1439 NTSTATUS WINAPI RtlUnicodeStringToInteger(
1440 const UNICODE_STRING *str, /* [I] Unicode string to be converted */
1441 ULONG base, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
1442 ULONG *value) /* [O] Destination for the converted value */
1444 LPWSTR lpwstr = str->Buffer;
1445 USHORT CharsRemaining = str->Length / sizeof(WCHAR);
1446 WCHAR wchCurrent;
1447 int digit;
1448 ULONG RunningTotal = 0;
1449 BOOL bMinus = FALSE;
1451 while (CharsRemaining >= 1 && *lpwstr <= ' ') {
1452 lpwstr++;
1453 CharsRemaining--;
1454 } /* while */
1456 if (CharsRemaining >= 1) {
1457 if (*lpwstr == '+') {
1458 lpwstr++;
1459 CharsRemaining--;
1460 } else if (*lpwstr == '-') {
1461 bMinus = TRUE;
1462 lpwstr++;
1463 CharsRemaining--;
1464 } /* if */
1465 } /* if */
1467 if (base == 0) {
1468 base = 10;
1469 if (CharsRemaining >= 2 && lpwstr[0] == '0') {
1470 if (lpwstr[1] == 'b') {
1471 lpwstr += 2;
1472 CharsRemaining -= 2;
1473 base = 2;
1474 } else if (lpwstr[1] == 'o') {
1475 lpwstr += 2;
1476 CharsRemaining -= 2;
1477 base = 8;
1478 } else if (lpwstr[1] == 'x') {
1479 lpwstr += 2;
1480 CharsRemaining -= 2;
1481 base = 16;
1482 } /* if */
1483 } /* if */
1484 } else if (base != 2 && base != 8 && base != 10 && base != 16) {
1485 return STATUS_INVALID_PARAMETER;
1486 } /* if */
1488 if (value == NULL) {
1489 return STATUS_ACCESS_VIOLATION;
1490 } /* if */
1492 while (CharsRemaining >= 1) {
1493 wchCurrent = *lpwstr;
1494 if (wchCurrent >= '0' && wchCurrent <= '9') {
1495 digit = wchCurrent - '0';
1496 } else if (wchCurrent >= 'A' && wchCurrent <= 'Z') {
1497 digit = wchCurrent - 'A' + 10;
1498 } else if (wchCurrent >= 'a' && wchCurrent <= 'z') {
1499 digit = wchCurrent - 'a' + 10;
1500 } else {
1501 digit = -1;
1502 } /* if */
1503 if (digit < 0 || digit >= base) {
1504 *value = bMinus ? -RunningTotal : RunningTotal;
1505 return STATUS_SUCCESS;
1506 } /* if */
1508 RunningTotal = RunningTotal * base + digit;
1509 lpwstr++;
1510 CharsRemaining--;
1511 } /* while */
1513 *value = bMinus ? -RunningTotal : RunningTotal;
1514 return STATUS_SUCCESS;
1518 /**************************************************************************
1519 * RtlIntegerToUnicodeString (NTDLL.@)
1521 * Converts an unsigned integer to a '\0' terminated unicode string.
1523 * RETURNS
1524 * Success: STATUS_SUCCESS. str contains the converted number
1525 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
1526 * STATUS_BUFFER_OVERFLOW, if str is too small to hold the string
1527 * (with the '\0' termination). In this case str->Length
1528 * is set to the length, the string would have (which can
1529 * be larger than the MaximumLength).
1531 * NOTES
1532 * Instead of base 0 it uses 10 as base.
1533 * If str is NULL it crashes, as the native function does.
1535 * DIFFERENCES
1536 * Do not return STATUS_BUFFER_OVERFLOW when the string is long enough.
1537 * The native function does this when the string would be longer than 16
1538 * characters even when the string parameter is long enough.
1540 NTSTATUS WINAPI RtlIntegerToUnicodeString(
1541 ULONG value, /* [I] Value to be converted */
1542 ULONG base, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
1543 UNICODE_STRING *str) /* [O] Destination for the converted value */
1545 WCHAR buffer[33];
1546 PWCHAR pos;
1547 WCHAR digit;
1549 if (base == 0) {
1550 base = 10;
1551 } else if (base != 2 && base != 8 && base != 10 && base != 16) {
1552 return STATUS_INVALID_PARAMETER;
1553 } /* if */
1555 pos = &buffer[32];
1556 *pos = '\0';
1558 do {
1559 pos--;
1560 digit = value % base;
1561 value = value / base;
1562 if (digit < 10) {
1563 *pos = '0' + digit;
1564 } else {
1565 *pos = 'A' + digit - 10;
1566 } /* if */
1567 } while (value != 0L);
1569 str->Length = (&buffer[32] - pos) * sizeof(WCHAR);
1570 if (str->Length >= str->MaximumLength) {
1571 return STATUS_BUFFER_OVERFLOW;
1572 } else {
1573 memcpy(str->Buffer, pos, str->Length + sizeof(WCHAR));
1574 } /* if */
1575 return STATUS_SUCCESS;
1579 /*************************************************************************
1580 * RtlGUIDFromString (NTDLL.@)
1582 * Convert a string representation of a GUID into a GUID.
1584 * PARAMS
1585 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
1586 * guid [O] Destination for the converted GUID
1588 * RETURNS
1589 * Success: STATUS_SUCCESS. guid contains the converted value.
1590 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
1592 * SEE ALSO
1593 * See RtlStringFromGUID.
1595 NTSTATUS WINAPI RtlGUIDFromString(PUNICODE_STRING str, GUID* guid)
1597 int i = 0;
1598 const WCHAR *lpszCLSID = str->Buffer;
1599 BYTE* lpOut = (BYTE*)guid;
1601 TRACE("(%s,%p)\n", debugstr_us(str), guid);
1603 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
1604 * to memory: DWORD... WORD WORD BYTES............
1606 while (i <= 37)
1608 switch (i)
1610 case 0:
1611 if (*lpszCLSID != '{')
1612 return STATUS_INVALID_PARAMETER;
1613 break;
1615 case 9: case 14: case 19: case 24:
1616 if (*lpszCLSID != '-')
1617 return STATUS_INVALID_PARAMETER;
1618 break;
1620 case 37:
1621 if (*lpszCLSID != '}')
1622 return STATUS_INVALID_PARAMETER;
1623 break;
1625 default:
1627 WCHAR ch = *lpszCLSID, ch2 = lpszCLSID[1];
1628 unsigned char byte;
1630 /* Read two hex digits as a byte value */
1631 if (ch >= '0' && ch <= '9') ch = ch - '0';
1632 else if (ch >= 'a' && ch <= 'f') ch = ch - 'a' + 10;
1633 else if (ch >= 'A' && ch <= 'F') ch = ch - 'A' + 10;
1634 else return STATUS_INVALID_PARAMETER;
1636 if (ch2 >= '0' && ch2 <= '9') ch2 = ch2 - '0';
1637 else if (ch2 >= 'a' && ch2 <= 'f') ch2 = ch2 - 'a' + 10;
1638 else if (ch2 >= 'A' && ch2 <= 'F') ch2 = ch2 - 'A' + 10;
1639 else return STATUS_INVALID_PARAMETER;
1641 byte = ch << 4 | ch2;
1643 switch (i)
1645 #ifndef WORDS_BIGENDIAN
1646 /* For Big Endian machines, we store the data such that the
1647 * dword/word members can be read as DWORDS and WORDS correctly. */
1648 /* Dword */
1649 case 1: lpOut[3] = byte; break;
1650 case 3: lpOut[2] = byte; break;
1651 case 5: lpOut[1] = byte; break;
1652 case 7: lpOut[0] = byte; lpOut += 4; break;
1653 /* Word */
1654 case 10: case 15: lpOut[1] = byte; break;
1655 case 12: case 17: lpOut[0] = byte; lpOut += 2; break;
1656 #endif
1657 /* Byte */
1658 default: lpOut[0] = byte; lpOut++; break;
1660 lpszCLSID++; /* Skip 2nd character of byte */
1661 i++;
1664 lpszCLSID++;
1665 i++;
1668 return STATUS_SUCCESS;
1671 /*************************************************************************
1672 * RtlStringFromGUID (NTDLL.@)
1674 * Convert a GUID into a string representation of a GUID.
1676 * PARAMS
1677 * guid [I] GUID to convert
1678 * str [O] Destination for the converted string
1680 * RETURNS
1681 * Success: STATUS_SUCCESS. str contains the converted value.
1682 * Failure: STATUS_NO_MEMORY, if memory for str cannot be allocated.
1684 * SEE ALSO
1685 * See RtlGUIDFromString.
1687 NTSTATUS WINAPI RtlStringFromGUID(const GUID* guid, UNICODE_STRING *str)
1689 static const WCHAR szFormat[] = { '{','%','0','8','l','X','-',
1690 '%','0','4','X','-', '%','0','4','X','-','%','0','2','X','%','0','2','X',
1691 '-', '%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X',
1692 '%','0','2','X','%','0','2','X','}','\0' };
1694 TRACE("(%p,%p)\n", guid, str);
1696 str->Length = GUID_STRING_LENGTH * sizeof(WCHAR);
1697 str->MaximumLength = str->Length + sizeof(WCHAR);
1698 str->Buffer = RtlAllocateHeap(GetProcessHeap(), 0, str->MaximumLength);
1699 if (!str->Buffer)
1701 str->Length = str->MaximumLength = 0;
1702 return STATUS_NO_MEMORY;
1704 NTDLL_swprintf(str->Buffer, szFormat, guid->Data1, guid->Data2, guid->Data3,
1705 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
1706 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
1708 return STATUS_SUCCESS;