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
29 #define WIN32_NO_STATUS
33 #include "wine/debug.h"
34 #include "ntdll_misc.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ntdll
);
38 #define GUID_STRING_LENGTH 38
41 /**************************************************************************
42 * RtlInitAnsiString (NTDLL.@)
44 * Initializes a buffered ansi string.
50 * Assigns source to target->Buffer. The length of source is assigned to
51 * target->Length and target->MaximumLength. If source is NULL the length
52 * of source is assumed to be 0.
54 void WINAPI
RtlInitAnsiString(
55 PANSI_STRING target
, /* [I/O] Buffered ansi string to be initialized */
56 PCSZ source
) /* [I] '\0' terminated string used to initialize target */
58 if ((target
->Buffer
= (PCHAR
) source
))
60 target
->Length
= strlen(source
);
61 target
->MaximumLength
= target
->Length
+ 1;
63 else target
->Length
= target
->MaximumLength
= 0;
66 /**************************************************************************
67 * RtlInitAnsiStringEx (NTDLL.@)
69 * Initializes a buffered ansi string.
72 * An appropriate NTSTATUS value.
75 * Assigns source to target->Buffer. The length of source is assigned to
76 * target->Length and target->MaximumLength. If source is NULL the length
77 * of source is assumed to be 0.
79 NTSTATUS WINAPI
RtlInitAnsiStringEx(PANSI_STRING target
, PCSZ source
)
83 unsigned int len
= strlen(source
);
85 return STATUS_NAME_TOO_LONG
;
87 target
->Buffer
= (PCHAR
) source
;
89 target
->MaximumLength
= len
+ 1;
93 target
->Buffer
= NULL
;
95 target
->MaximumLength
= 0;
97 return STATUS_SUCCESS
;
100 /**************************************************************************
101 * RtlInitString (NTDLL.@)
103 * Initializes a buffered string.
109 * Assigns source to target->Buffer. The length of source is assigned to
110 * target->Length and target->MaximumLength. If source is NULL the length
111 * of source is assumed to be 0.
113 void WINAPI
RtlInitString(
114 PSTRING target
, /* [I/O] Buffered string to be initialized */
115 PCSZ source
) /* [I] '\0' terminated string used to initialize target */
117 RtlInitAnsiString( target
, source
);
121 /**************************************************************************
122 * RtlFreeAnsiString (NTDLL.@)
124 void WINAPI
RtlFreeAnsiString( PSTRING str
)
128 RtlFreeHeap( GetProcessHeap(), 0, str
->Buffer
);
129 RtlZeroMemory( str
, sizeof(*str
) );
134 /**************************************************************************
135 * RtlFreeOemString (NTDLL.@)
137 void WINAPI
RtlFreeOemString( PSTRING str
)
139 RtlFreeAnsiString( str
);
143 /**************************************************************************
144 * RtlCopyString (NTDLL.@)
146 void WINAPI
RtlCopyString( STRING
*dst
, const STRING
*src
)
150 unsigned int len
= min( src
->Length
, dst
->MaximumLength
);
151 memcpy( dst
->Buffer
, src
->Buffer
, len
);
154 else dst
->Length
= 0;
158 /**************************************************************************
159 * RtlInitUnicodeString (NTDLL.@)
161 * Initializes a buffered unicode string.
167 * Assigns source to target->Buffer. The length of source is assigned to
168 * target->Length and target->MaximumLength. If source is NULL the length
169 * of source is assumed to be 0.
171 void WINAPI
RtlInitUnicodeString(
172 PUNICODE_STRING target
, /* [I/O] Buffered unicode string to be initialized */
173 PCWSTR source
) /* [I] '\0' terminated unicode string used to initialize target */
175 if ((target
->Buffer
= (PWSTR
) source
))
177 unsigned int length
= wcslen(source
) * sizeof(WCHAR
);
180 target
->Length
= length
;
181 target
->MaximumLength
= target
->Length
+ sizeof(WCHAR
);
183 else target
->Length
= target
->MaximumLength
= 0;
187 /**************************************************************************
188 * RtlInitUnicodeStringEx (NTDLL.@)
190 * Initializes a buffered unicode string.
193 * Success: STATUS_SUCCESS. target is initialized.
194 * Failure: STATUS_NAME_TOO_LONG, if the source string is larger than 65532 bytes.
197 * Assigns source to target->Buffer. The length of source is assigned to
198 * target->Length and target->MaximumLength. If source is NULL the length
199 * of source is assumed to be 0.
201 NTSTATUS WINAPI
RtlInitUnicodeStringEx(
202 PUNICODE_STRING target
, /* [I/O] Buffered unicode string to be initialized */
203 PCWSTR source
) /* [I] '\0' terminated unicode string used to initialize target */
205 if (source
!= NULL
) {
206 unsigned int len
= wcslen(source
) * sizeof(WCHAR
);
209 return STATUS_NAME_TOO_LONG
;
211 target
->Length
= len
;
212 target
->MaximumLength
= len
+ sizeof(WCHAR
);
213 target
->Buffer
= (PWSTR
) source
;
217 target
->MaximumLength
= 0;
218 target
->Buffer
= NULL
;
220 return STATUS_SUCCESS
;
224 /**************************************************************************
225 * RtlCreateUnicodeString (NTDLL.@)
227 * Creates a UNICODE_STRING from a null-terminated Unicode string.
233 BOOLEAN WINAPI
RtlCreateUnicodeString( PUNICODE_STRING target
, LPCWSTR src
)
235 int len
= (wcslen(src
) + 1) * sizeof(WCHAR
);
236 if (!(target
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0, len
))) return FALSE
;
237 memcpy( target
->Buffer
, src
, len
);
238 target
->MaximumLength
= len
;
239 target
->Length
= len
- sizeof(WCHAR
);
244 /**************************************************************************
245 * RtlCreateUnicodeStringFromAsciiz (NTDLL.@)
247 * Creates a UNICODE_STRING from a null-terminated Ascii string.
253 BOOLEAN WINAPI
RtlCreateUnicodeStringFromAsciiz( PUNICODE_STRING target
, LPCSTR src
)
256 RtlInitAnsiString( &ansi
, src
);
257 return !RtlAnsiStringToUnicodeString( target
, &ansi
, TRUE
);
261 /**************************************************************************
262 * RtlFreeUnicodeString (NTDLL.@)
264 * Frees a UNICODE_STRING created with RtlCreateUnicodeString() or
265 * RtlCreateUnicodeStringFromAsciiz().
270 void WINAPI
RtlFreeUnicodeString( PUNICODE_STRING str
)
274 RtlFreeHeap( GetProcessHeap(), 0, str
->Buffer
);
275 RtlZeroMemory( str
, sizeof(*str
) );
280 /**************************************************************************
281 * RtlCopyUnicodeString (NTDLL.@)
283 * Copies from one UNICODE_STRING to another.
288 void WINAPI
RtlCopyUnicodeString( UNICODE_STRING
*dst
, const UNICODE_STRING
*src
)
292 unsigned int len
= min( src
->Length
, dst
->MaximumLength
);
293 memcpy( dst
->Buffer
, src
->Buffer
, len
);
295 /* append terminating '\0' if enough space */
296 if (len
< dst
->MaximumLength
) dst
->Buffer
[len
/ sizeof(WCHAR
)] = 0;
298 else dst
->Length
= 0;
302 /**************************************************************************
303 * RtlDuplicateUnicodeString (NTDLL.@)
305 * Duplicates a unicode string.
308 * Success: STATUS_SUCCESS. destination contains the duplicated unicode string.
309 * Failure: STATUS_INVALID_PARAMETER, if one of the parameters is illegal.
310 * STATUS_NO_MEMORY, if the allocation fails.
313 * For add_nul there are several possible values:
314 * 0 = destination will not be '\0' terminated,
315 * 1 = destination will be '\0' terminated,
316 * 3 = like 1 but for an empty source string produce '\0' terminated empty
317 * Buffer instead of assigning NULL to the Buffer.
318 * Other add_nul values are invalid.
320 NTSTATUS WINAPI
RtlDuplicateUnicodeString(
321 int add_nul
, /* [I] flag */
322 const UNICODE_STRING
*source
, /* [I] Unicode string to be duplicated */
323 UNICODE_STRING
*destination
) /* [O] destination for the duplicated unicode string */
325 if (source
== NULL
|| destination
== NULL
||
326 source
->Length
> source
->MaximumLength
||
327 (source
->Length
== 0 && source
->MaximumLength
> 0 && source
->Buffer
== NULL
) ||
328 add_nul
== 2 || add_nul
>= 4 || add_nul
< 0) {
329 return STATUS_INVALID_PARAMETER
;
331 if (source
->Length
== 0 && add_nul
!= 3) {
332 destination
->Length
= 0;
333 destination
->MaximumLength
= 0;
334 destination
->Buffer
= NULL
;
336 unsigned int destination_max_len
= source
->Length
;
339 destination_max_len
+= sizeof(WCHAR
);
341 destination
->Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, destination_max_len
);
342 if (destination
->Buffer
== NULL
) {
343 return STATUS_NO_MEMORY
;
345 memcpy(destination
->Buffer
, source
->Buffer
, source
->Length
);
346 destination
->Length
= source
->Length
;
347 destination
->MaximumLength
= source
->Length
;
348 /* append terminating '\0' if enough space */
350 destination
->MaximumLength
= destination_max_len
;
351 destination
->Buffer
[destination
->Length
/ sizeof(WCHAR
)] = 0;
356 return STATUS_SUCCESS
;
360 /**************************************************************************
361 * RtlEraseUnicodeString (NTDLL.@)
363 * Overwrites a UNICODE_STRING with zeros.
368 void WINAPI
RtlEraseUnicodeString( UNICODE_STRING
*str
)
372 memset( str
->Buffer
, 0, str
->MaximumLength
);
383 /******************************************************************************
384 * RtlCompareString (NTDLL.@)
386 LONG WINAPI
RtlCompareString( const STRING
*s1
, const STRING
*s2
, BOOLEAN CaseInsensitive
)
392 len
= min(s1
->Length
, s2
->Length
);
398 while (!ret
&& len
--) ret
= RtlUpperChar(*p1
++) - RtlUpperChar(*p2
++);
402 while (!ret
&& len
--) ret
= *p1
++ - *p2
++;
404 if (!ret
) ret
= s1
->Length
- s2
->Length
;
409 /******************************************************************************
410 * RtlCompareUnicodeString (NTDLL.@)
412 LONG WINAPI
RtlCompareUnicodeString( const UNICODE_STRING
*s1
, const UNICODE_STRING
*s2
,
413 BOOLEAN CaseInsensitive
)
415 return RtlCompareUnicodeStrings( s1
->Buffer
, s1
->Length
/ sizeof(WCHAR
),
416 s2
->Buffer
, s2
->Length
/ sizeof(WCHAR
), CaseInsensitive
);
420 /**************************************************************************
421 * RtlEqualString (NTDLL.@)
423 * Determine if two strings are equal.
426 * s1 [I] Source string
427 * s2 [I] String to compare to s1
428 * CaseInsensitive [I] TRUE = Case insensitive, FALSE = Case sensitive
431 * Non-zero if s1 is equal to s2, 0 otherwise.
433 BOOLEAN WINAPI
RtlEqualString( const STRING
*s1
, const STRING
*s2
, BOOLEAN CaseInsensitive
)
435 if (s1
->Length
!= s2
->Length
) return FALSE
;
436 return !RtlCompareString( s1
, s2
, CaseInsensitive
);
440 /**************************************************************************
441 * RtlEqualUnicodeString (NTDLL.@)
443 * Unicode version of RtlEqualString.
445 BOOLEAN WINAPI
RtlEqualUnicodeString( const UNICODE_STRING
*s1
, const UNICODE_STRING
*s2
,
446 BOOLEAN CaseInsensitive
)
448 if (s1
->Length
!= s2
->Length
) return FALSE
;
449 return !RtlCompareUnicodeString( s1
, s2
, CaseInsensitive
);
453 /**************************************************************************
454 * RtlPrefixString (NTDLL.@)
456 * Determine if one string is a prefix of another.
459 * s1 [I] Prefix to look for in s2
460 * s2 [I] String that may contain s1 as a prefix
461 * ignore_case [I] TRUE = Case insensitive, FALSE = Case sensitive
464 * TRUE if s2 contains s1 as a prefix, FALSE otherwise.
466 BOOLEAN WINAPI
RtlPrefixString( const STRING
*s1
, const STRING
*s2
, BOOLEAN ignore_case
)
470 if (s1
->Length
> s2
->Length
) return FALSE
;
473 for (i
= 0; i
< s1
->Length
; i
++)
474 if (RtlUpperChar(s1
->Buffer
[i
]) != RtlUpperChar(s2
->Buffer
[i
])) return FALSE
;
478 for (i
= 0; i
< s1
->Length
; i
++)
479 if (s1
->Buffer
[i
] != s2
->Buffer
[i
]) return FALSE
;
485 /**************************************************************************
486 * RtlEqualComputerName (NTDLL.@)
488 * Determine if two computer names are the same.
491 * left [I] First computer name
492 * right [I] Second computer name
495 * 0 if the names are equal, non-zero otherwise.
498 * The comparison is case insensitive.
500 NTSTATUS WINAPI
RtlEqualComputerName(const UNICODE_STRING
*left
,
501 const UNICODE_STRING
*right
)
504 STRING upLeft
, upRight
;
506 if (!(ret
= RtlUpcaseUnicodeStringToOemString( &upLeft
, left
, TRUE
)))
508 if (!(ret
= RtlUpcaseUnicodeStringToOemString( &upRight
, right
, TRUE
)))
510 ret
= RtlEqualString( &upLeft
, &upRight
, FALSE
);
511 RtlFreeOemString( &upRight
);
513 RtlFreeOemString( &upLeft
);
519 /**************************************************************************
520 * RtlEqualDomainName (NTDLL.@)
522 * Determine if two domain names are the same.
525 * left [I] First domain name
526 * right [I] Second domain name
529 * 0 if the names are equal, non-zero otherwise.
532 * The comparison is case insensitive.
534 NTSTATUS WINAPI
RtlEqualDomainName(const UNICODE_STRING
*left
,
535 const UNICODE_STRING
*right
)
537 return RtlEqualComputerName(left
, right
);
542 COPY BETWEEN ANSI_STRING or UNICODE_STRING
543 there is no parameter checking, it just crashes
547 /**************************************************************************
548 * RtlAnsiStringToUnicodeString (NTDLL.@)
550 * Converts an ansi string to a unicode string.
553 * Success: STATUS_SUCCESS. uni contains the converted string
554 * Failure: STATUS_BUFFER_OVERFLOW, if doalloc is FALSE and ansi is too small.
555 * STATUS_NO_MEMORY, if doalloc is TRUE and the allocation fails.
556 * STATUS_INVALID_PARAMETER_2, if the unicode string would be larger than 65535.
559 * This function always writes a terminating '\0'.
561 NTSTATUS WINAPI
RtlAnsiStringToUnicodeString(
562 PUNICODE_STRING uni
, /* [I/O] Destination for the unicode string */
563 PCANSI_STRING ansi
, /* [I] Ansi string to be converted */
564 BOOLEAN doalloc
) /* [I] TRUE=Allocate new buffer for uni, FALSE=Use existing buffer */
566 DWORD total
= RtlAnsiStringToUnicodeSize( ansi
);
568 if (total
> 0xffff) return STATUS_INVALID_PARAMETER_2
;
569 uni
->Length
= total
- sizeof(WCHAR
);
572 uni
->MaximumLength
= total
;
573 if (!(uni
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0, total
)))
574 return STATUS_NO_MEMORY
;
576 else if (total
> uni
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
578 RtlMultiByteToUnicodeN( uni
->Buffer
, uni
->Length
, NULL
, ansi
->Buffer
, ansi
->Length
);
579 uni
->Buffer
[uni
->Length
/ sizeof(WCHAR
)] = 0;
580 return STATUS_SUCCESS
;
584 /**************************************************************************
585 * RtlOemStringToUnicodeString (NTDLL.@)
587 * Converts an oem string to a unicode string.
590 * Success: STATUS_SUCCESS. uni contains the converted string
591 * Failure: STATUS_BUFFER_OVERFLOW, if doalloc is FALSE and oem is too small.
592 * STATUS_NO_MEMORY, if doalloc is TRUE and the allocation fails.
593 * STATUS_INVALID_PARAMETER_2, if the unicode string would be larger than 65535.
596 * This function always writes a terminating '\0'.
598 NTSTATUS WINAPI
RtlOemStringToUnicodeString(
599 UNICODE_STRING
*uni
, /* [I/O] Destination for the unicode string */
600 const STRING
*oem
, /* [I] Oem string to be converted */
601 BOOLEAN doalloc
) /* [I] TRUE=Allocate new buffer for uni, FALSE=Use existing buffer */
603 DWORD total
= RtlOemStringToUnicodeSize( oem
);
605 if (total
> 0xffff) return STATUS_INVALID_PARAMETER_2
;
606 uni
->Length
= total
- sizeof(WCHAR
);
609 uni
->MaximumLength
= total
;
610 if (!(uni
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0, total
)))
611 return STATUS_NO_MEMORY
;
613 else if (total
> uni
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
615 RtlOemToUnicodeN( uni
->Buffer
, uni
->Length
, NULL
, oem
->Buffer
, oem
->Length
);
616 uni
->Buffer
[uni
->Length
/ sizeof(WCHAR
)] = 0;
617 return STATUS_SUCCESS
;
621 /**************************************************************************
622 * RtlUnicodeStringToAnsiString (NTDLL.@)
624 * Converts a unicode string to an ansi string.
627 * Success: STATUS_SUCCESS. ansi contains the converted string
628 * Failure: STATUS_BUFFER_OVERFLOW, if doalloc is FALSE and ansi is too small.
629 * STATUS_NO_MEMORY, if doalloc is TRUE and the allocation fails.
632 * This function always writes a terminating '\0'.
633 * It performs a partial copy if ansi is too small.
635 NTSTATUS WINAPI
RtlUnicodeStringToAnsiString(
636 STRING
*ansi
, /* [I/O] Destination for the ansi string */
637 const UNICODE_STRING
*uni
, /* [I] Unicode string to be converted */
638 BOOLEAN doalloc
) /* [I] TRUE=Allocate new buffer for ansi, FALSE=Use existing buffer */
640 NTSTATUS ret
= STATUS_SUCCESS
;
641 DWORD len
= RtlUnicodeStringToAnsiSize( uni
);
643 ansi
->Length
= len
- 1;
646 ansi
->MaximumLength
= len
;
647 if (!(ansi
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0, len
)))
648 return STATUS_NO_MEMORY
;
650 else if (ansi
->MaximumLength
< len
)
652 if (!ansi
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
653 ansi
->Length
= ansi
->MaximumLength
- 1;
654 ret
= STATUS_BUFFER_OVERFLOW
;
657 RtlUnicodeToMultiByteN( ansi
->Buffer
, ansi
->Length
, NULL
, uni
->Buffer
, uni
->Length
);
658 ansi
->Buffer
[ansi
->Length
] = 0;
663 /**************************************************************************
664 * RtlUnicodeStringToOemString (NTDLL.@)
666 * Converts a Rtl Unicode string to an OEM string.
669 * oem [O] Destination for OEM string
670 * uni [I] Source Unicode string
671 * doalloc [I] TRUE=Allocate new buffer for oem,FALSE=Use existing buffer
674 * Success: STATUS_SUCCESS. oem contains the converted string
675 * Failure: STATUS_BUFFER_OVERFLOW, if doalloc is FALSE and oem is too small.
676 * STATUS_NO_MEMORY, if doalloc is TRUE and allocation fails.
679 * If doalloc is TRUE, the length allocated is uni->Length + 1.
680 * This function always '\0' terminates the string returned.
682 NTSTATUS WINAPI
RtlUnicodeStringToOemString( STRING
*oem
,
683 const UNICODE_STRING
*uni
,
686 NTSTATUS ret
= STATUS_SUCCESS
;
687 DWORD len
= RtlUnicodeStringToOemSize( uni
);
689 oem
->Length
= len
- 1;
692 oem
->MaximumLength
= len
;
693 if (!(oem
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0, len
)))
694 return STATUS_NO_MEMORY
;
696 else if (oem
->MaximumLength
< len
)
698 if (!oem
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
699 oem
->Length
= oem
->MaximumLength
- 1;
700 ret
= STATUS_BUFFER_OVERFLOW
;
703 RtlUnicodeToOemN( oem
->Buffer
, oem
->Length
, NULL
, uni
->Buffer
, uni
->Length
);
704 oem
->Buffer
[oem
->Length
] = 0;
714 /**************************************************************************
715 * RtlUpperChar (NTDLL.@)
717 * Converts an Ascii character to uppercase.
720 * ch [I] Character to convert
723 * The uppercase character value.
726 * For the input characters from 'a' .. 'z' it returns 'A' .. 'Z'.
727 * All other input characters are returned unchanged. The locale and
728 * multibyte characters are not taken into account (as native DLL).
730 CHAR WINAPI
RtlUpperChar( CHAR ch
)
732 if (ch
>= 'a' && ch
<= 'z') {
733 return ch
- 'a' + 'A';
740 /**************************************************************************
741 * RtlUpperString (NTDLL.@)
743 * Converts an Ascii string to uppercase.
746 * dst [O] Destination for converted string
747 * src [I] Source string to convert
753 * For the src characters from 'a' .. 'z' it assigns 'A' .. 'Z' to dst.
754 * All other src characters are copied unchanged to dst. The locale and
755 * multibyte characters are not taken into account (as native DLL).
756 * The number of character copied is the minimum of src->Length and
757 * the dst->MaximumLength.
759 void WINAPI
RtlUpperString( STRING
*dst
, const STRING
*src
)
761 unsigned int i
, len
= min(src
->Length
, dst
->MaximumLength
);
763 for (i
= 0; i
< len
; i
++) dst
->Buffer
[i
] = RtlUpperChar(src
->Buffer
[i
]);
768 /**************************************************************************
769 * RtlUpcaseUnicodeStringToAnsiString (NTDLL.@)
771 * Converts a Unicode string to the equivalent ANSI upper-case representation.
777 * writes terminating 0
779 NTSTATUS WINAPI
RtlUpcaseUnicodeStringToAnsiString( STRING
*ansi
,
780 const UNICODE_STRING
*uni
,
783 NTSTATUS ret
= STATUS_SUCCESS
;
784 DWORD len
= RtlUnicodeStringToAnsiSize( uni
);
786 ansi
->Length
= len
- 1;
789 ansi
->MaximumLength
= len
;
790 if (!(ansi
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0, len
)))
791 return STATUS_NO_MEMORY
;
793 else if (ansi
->MaximumLength
< len
)
795 if (!ansi
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
796 ansi
->Length
= ansi
->MaximumLength
- 1;
797 ret
= STATUS_BUFFER_OVERFLOW
;
800 RtlUpcaseUnicodeToMultiByteN( ansi
->Buffer
, ansi
->Length
, NULL
, uni
->Buffer
, uni
->Length
);
801 ansi
->Buffer
[ansi
->Length
] = 0;
806 /**************************************************************************
807 * RtlUpcaseUnicodeStringToOemString (NTDLL.@)
809 * Converts a UNICODE_STRING to the equivalent OEM upper-case representation
810 * stored in STRING format.
816 * writes terminating 0
818 NTSTATUS WINAPI
RtlUpcaseUnicodeStringToOemString( STRING
*oem
,
819 const UNICODE_STRING
*uni
,
822 NTSTATUS ret
= STATUS_SUCCESS
;
823 DWORD len
= RtlUnicodeStringToAnsiSize( uni
);
825 oem
->Length
= len
- 1;
828 oem
->MaximumLength
= len
;
829 if (!(oem
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0, len
)))
830 return STATUS_NO_MEMORY
;
832 else if (oem
->MaximumLength
< len
)
834 if (!oem
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
835 oem
->Length
= oem
->MaximumLength
- 1;
836 ret
= STATUS_BUFFER_OVERFLOW
;
839 RtlUpcaseUnicodeToOemN( oem
->Buffer
, oem
->Length
, NULL
, uni
->Buffer
, uni
->Length
);
840 oem
->Buffer
[oem
->Length
] = 0;
845 /**************************************************************************
846 * RtlUpcaseUnicodeStringToCountedOemString (NTDLL.@)
848 * Converts a UNICODE_STRING to the equivalent OEM upper-case representation
849 * stored in STRING format.
855 * Same as RtlUpcaseUnicodeStringToOemString but doesn't write terminating null
857 NTSTATUS WINAPI
RtlUpcaseUnicodeStringToCountedOemString( STRING
*oem
,
858 const UNICODE_STRING
*uni
,
861 NTSTATUS ret
= STATUS_SUCCESS
;
862 DWORD len
= RtlUnicodeStringToOemSize( uni
) - 1;
867 oem
->MaximumLength
= len
;
868 if (!(oem
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0, len
))) return STATUS_NO_MEMORY
;
870 else if (oem
->MaximumLength
< len
)
872 ret
= STATUS_BUFFER_OVERFLOW
;
873 oem
->Length
= oem
->MaximumLength
;
874 if (!oem
->MaximumLength
) return ret
;
876 RtlUpcaseUnicodeToOemN( oem
->Buffer
, oem
->Length
, NULL
, uni
->Buffer
, uni
->Length
);
886 /**************************************************************************
887 * RtlAnsiStringToUnicodeSize (NTDLL.@)
888 * RtlxAnsiStringToUnicodeSize (NTDLL.@)
890 * Calculate the size in bytes necessary for the Unicode conversion of str,
891 * including the terminating '\0'.
894 * str [I] String to calculate the size of
897 * The calculated size.
899 DWORD WINAPI
RtlAnsiStringToUnicodeSize( const STRING
*str
)
902 RtlMultiByteToUnicodeSize( &ret
, str
->Buffer
, str
->Length
);
903 return ret
+ sizeof(WCHAR
);
907 /**************************************************************************
908 * RtlUnicodeStringToAnsiSize (NTDLL.@)
909 * RtlxUnicodeStringToAnsiSize (NTDLL.@)
911 * Calculate the size in bytes necessary for the Ansi conversion of str,
912 * including the terminating '\0'.
915 * str [I] String to calculate the size of
918 * The calculated size.
920 DWORD WINAPI
RtlUnicodeStringToAnsiSize( const UNICODE_STRING
*str
)
923 RtlUnicodeToMultiByteSize( &ret
, str
->Buffer
, str
->Length
);
928 /**************************************************************************
929 * RtlAppendAsciizToString (NTDLL.@)
931 * Concatenates a buffered character string and a '\0' terminated character
935 * Success: STATUS_SUCCESS. src is appended to dest.
936 * Failure: STATUS_BUFFER_TOO_SMALL, if the buffer of dest is too small
937 * to hold the concatenated string.
940 * if src is NULL dest is unchanged.
941 * dest is never '\0' terminated.
943 NTSTATUS WINAPI
RtlAppendAsciizToString(
944 STRING
*dest
, /* [I/O] Buffered character string to which src is concatenated */
945 LPCSTR src
) /* [I] '\0' terminated character string to be concatenated */
948 unsigned int src_len
= strlen(src
);
949 unsigned int dest_len
= src_len
+ dest
->Length
;
951 if (dest_len
> dest
->MaximumLength
) return STATUS_BUFFER_TOO_SMALL
;
952 memcpy(dest
->Buffer
+ dest
->Length
, src
, src_len
);
953 dest
->Length
= dest_len
;
955 return STATUS_SUCCESS
;
959 /**************************************************************************
960 * RtlAppendStringToString (NTDLL.@)
962 * Concatenates two buffered character strings
965 * Success: STATUS_SUCCESS. src is appended to dest.
966 * Failure: STATUS_BUFFER_TOO_SMALL, if the buffer of dest is too small
967 * to hold the concatenated string.
970 * if src->length is zero dest is unchanged.
971 * dest is never '\0' terminated.
973 NTSTATUS WINAPI
RtlAppendStringToString(
974 STRING
*dest
, /* [I/O] Buffered character string to which src is concatenated */
975 const STRING
*src
) /* [I] Buffered character string to be concatenated */
977 if (src
->Length
!= 0) {
978 unsigned int dest_len
= src
->Length
+ dest
->Length
;
980 if (dest_len
> dest
->MaximumLength
) return STATUS_BUFFER_TOO_SMALL
;
981 memcpy(dest
->Buffer
+ dest
->Length
, src
->Buffer
, src
->Length
);
982 dest
->Length
= dest_len
;
984 return STATUS_SUCCESS
;
988 /**************************************************************************
989 * RtlAppendUnicodeToString (NTDLL.@)
991 * Concatenates a buffered unicode string and a '\0' terminated unicode
995 * Success: STATUS_SUCCESS. src is appended to dest.
996 * Failure: STATUS_BUFFER_TOO_SMALL, if the buffer of dest is too small
997 * to hold the concatenated string.
1000 * if src is NULL dest is unchanged.
1001 * dest is '\0' terminated when the MaximumLength allows it.
1002 * When dest fits exactly in MaximumLength characters the '\0' is omitted.
1005 * Does not write in the src->Buffer beyond MaximumLength when
1006 * MaximumLength is odd as the native function does.
1008 NTSTATUS WINAPI
RtlAppendUnicodeToString(
1009 UNICODE_STRING
*dest
, /* [I/O] Buffered unicode string to which src is concatenated */
1010 LPCWSTR src
) /* [I] '\0' terminated unicode string to be concatenated */
1013 unsigned int src_len
= wcslen(src
) * sizeof(WCHAR
);
1014 unsigned int dest_len
= src_len
+ dest
->Length
;
1016 if (dest_len
> dest
->MaximumLength
) return STATUS_BUFFER_TOO_SMALL
;
1017 memcpy(dest
->Buffer
+ dest
->Length
/sizeof(WCHAR
), src
, src_len
);
1018 dest
->Length
= dest_len
;
1019 /* append terminating '\0' if enough space */
1020 if (dest_len
+ sizeof(WCHAR
) <= dest
->MaximumLength
) {
1021 dest
->Buffer
[dest_len
/ sizeof(WCHAR
)] = 0;
1024 return STATUS_SUCCESS
;
1028 /**************************************************************************
1029 * RtlAppendUnicodeStringToString (NTDLL.@)
1031 * Concatenates two buffered unicode strings
1034 * Success: STATUS_SUCCESS. src is appended to dest.
1035 * Failure: STATUS_BUFFER_TOO_SMALL, if the buffer of dest is too small
1036 * to hold the concatenated string.
1039 * if src->length is zero dest is unchanged.
1040 * dest is '\0' terminated when the MaximumLength allows it.
1041 * When dest fits exactly in MaximumLength characters the '\0' is omitted.
1044 * Does not write in the src->Buffer beyond MaximumLength when
1045 * MaximumLength is odd as the native function does.
1047 NTSTATUS WINAPI
RtlAppendUnicodeStringToString(
1048 UNICODE_STRING
*dest
, /* [I/O] Buffered unicode string to which src is concatenated */
1049 const UNICODE_STRING
*src
) /* [I] Buffered unicode string to be concatenated */
1051 if (src
->Length
!= 0) {
1052 unsigned int dest_len
= src
->Length
+ dest
->Length
;
1054 if (dest_len
> dest
->MaximumLength
) return STATUS_BUFFER_TOO_SMALL
;
1055 memcpy(dest
->Buffer
+ dest
->Length
/sizeof(WCHAR
), src
->Buffer
, src
->Length
);
1056 dest
->Length
= dest_len
;
1057 /* append terminating '\0' if enough space */
1058 if (dest_len
+ sizeof(WCHAR
) <= dest
->MaximumLength
) {
1059 dest
->Buffer
[dest_len
/ sizeof(WCHAR
)] = 0;
1062 return STATUS_SUCCESS
;
1066 /**************************************************************************
1067 * RtlFindCharInUnicodeString (NTDLL.@)
1069 * Searches for one of several unicode characters in a unicode string.
1072 * Success: STATUS_SUCCESS. pos contains the position after the character found.
1073 * Failure: STATUS_NOT_FOUND, if none of the search_chars are in main_str.
1075 NTSTATUS WINAPI
RtlFindCharInUnicodeString(
1076 int flags
, /* [I] Flags */
1077 const UNICODE_STRING
*main_str
, /* [I] Unicode string in which one or more characters are searched */
1078 const UNICODE_STRING
*search_chars
, /* [I] Unicode string which contains the characters to search for */
1079 USHORT
*pos
) /* [O] Position of the first character found + 2 */
1081 unsigned int main_idx
, search_idx
;
1085 for (main_idx
= 0; main_idx
< main_str
->Length
/ sizeof(WCHAR
); main_idx
++) {
1086 for (search_idx
= 0; search_idx
< search_chars
->Length
/ sizeof(WCHAR
); search_idx
++) {
1087 if (main_str
->Buffer
[main_idx
] == search_chars
->Buffer
[search_idx
]) {
1088 *pos
= (main_idx
+ 1) * sizeof(WCHAR
);
1089 return STATUS_SUCCESS
;
1094 return STATUS_NOT_FOUND
;
1096 main_idx
= main_str
->Length
/ sizeof(WCHAR
);
1097 while (main_idx
-- > 0) {
1098 for (search_idx
= 0; search_idx
< search_chars
->Length
/ sizeof(WCHAR
); search_idx
++) {
1099 if (main_str
->Buffer
[main_idx
] == search_chars
->Buffer
[search_idx
]) {
1100 *pos
= main_idx
* sizeof(WCHAR
);
1101 return STATUS_SUCCESS
;
1106 return STATUS_NOT_FOUND
;
1108 for (main_idx
= 0; main_idx
< main_str
->Length
/ sizeof(WCHAR
); main_idx
++) {
1110 while (search_idx
< search_chars
->Length
/ sizeof(WCHAR
) &&
1111 main_str
->Buffer
[main_idx
] != search_chars
->Buffer
[search_idx
]) {
1114 if (search_idx
>= search_chars
->Length
/ sizeof(WCHAR
)) {
1115 *pos
= (main_idx
+ 1) * sizeof(WCHAR
);
1116 return STATUS_SUCCESS
;
1120 return STATUS_NOT_FOUND
;
1122 main_idx
= main_str
->Length
/ sizeof(WCHAR
);
1123 while (main_idx
-- > 0) {
1125 while (search_idx
< search_chars
->Length
/ sizeof(WCHAR
) &&
1126 main_str
->Buffer
[main_idx
] != search_chars
->Buffer
[search_idx
]) {
1129 if (search_idx
>= search_chars
->Length
/ sizeof(WCHAR
)) {
1130 *pos
= main_idx
* sizeof(WCHAR
);
1131 return STATUS_SUCCESS
;
1135 return STATUS_NOT_FOUND
;
1137 return STATUS_NOT_FOUND
;
1145 /**************************************************************************
1146 * RtlIsTextUnicode (NTDLL.@)
1148 * Attempt to guess whether a text buffer is Unicode.
1151 * buf [I] Text buffer to test
1152 * len [I] Length of buf
1153 * pf [O] Destination for test results
1156 * TRUE if the buffer is likely Unicode, FALSE otherwise.
1159 * Should implement more tests.
1161 BOOLEAN WINAPI
RtlIsTextUnicode( LPCVOID buf
, INT len
, INT
*pf
)
1163 const WCHAR
*s
= buf
;
1165 unsigned int flags
= ~0U, out_flags
= 0;
1167 if (len
< sizeof(WCHAR
))
1169 /* FIXME: MSDN documents IS_TEXT_UNICODE_BUFFER_TOO_SMALL but there is no such thing... */
1176 * Apply various tests to the text string. According to the
1177 * docs, each test "passed" sets the corresponding flag in
1178 * the output flags. But some of the tests are mutually
1179 * exclusive, so I don't see how you could pass all tests ...
1182 /* Check for an odd length ... pass if even. */
1183 if (len
& 1) out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
1185 if (((const char *)buf
)[len
- 1] == 0)
1186 len
--; /* Windows seems to do something like that to avoid e.g. false IS_TEXT_UNICODE_NULL_BYTES */
1188 len
/= sizeof(WCHAR
);
1189 /* Windows only checks the first 256 characters */
1190 if (len
> 256) len
= 256;
1192 /* Check for the special byte order unicode marks. */
1193 if (*s
== 0xFEFF) out_flags
|= IS_TEXT_UNICODE_SIGNATURE
;
1194 if (*s
== 0xFFFE) out_flags
|= IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
1196 /* apply some statistical analysis */
1197 if (flags
& IS_TEXT_UNICODE_STATISTICS
)
1200 /* FIXME: checks only for ASCII characters in the unicode stream */
1201 for (i
= 0; i
< len
; i
++)
1203 if (s
[i
] <= 255) stats
++;
1205 if (stats
> len
/ 2)
1206 out_flags
|= IS_TEXT_UNICODE_STATISTICS
;
1209 /* Check for unicode NULL chars */
1210 if (flags
& IS_TEXT_UNICODE_NULL_BYTES
)
1212 for (i
= 0; i
< len
; i
++)
1214 if (!(s
[i
] & 0xff) || !(s
[i
] >> 8))
1216 out_flags
|= IS_TEXT_UNICODE_NULL_BYTES
;
1222 if (flags
& IS_TEXT_UNICODE_CONTROLS
)
1224 for (i
= 0; i
< len
; i
++)
1226 if (wcschr(L
"\r\n\t \x3000", s
[i
]))
1228 out_flags
|= IS_TEXT_UNICODE_CONTROLS
;
1234 if (flags
& IS_TEXT_UNICODE_REVERSE_CONTROLS
)
1236 for (i
= 0; i
< len
; i
++)
1238 if (wcschr(L
"\x0d00\x0a00\x0900\x2000", s
[i
]))
1240 out_flags
|= IS_TEXT_UNICODE_REVERSE_CONTROLS
;
1251 /* check for flags that indicate it's definitely not valid Unicode */
1252 if (out_flags
& (IS_TEXT_UNICODE_REVERSE_MASK
| IS_TEXT_UNICODE_NOT_UNICODE_MASK
)) return FALSE
;
1253 /* now check for invalid ASCII, and assume Unicode if so */
1254 if (out_flags
& IS_TEXT_UNICODE_NOT_ASCII_MASK
) return TRUE
;
1255 /* now check for Unicode flags */
1256 if (out_flags
& IS_TEXT_UNICODE_UNICODE_MASK
) return TRUE
;
1262 /**************************************************************************
1263 * RtlCharToInteger (NTDLL.@)
1265 * Converts a character string into its integer equivalent.
1268 * Success: STATUS_SUCCESS. value contains the converted number
1269 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
1270 * STATUS_ACCESS_VIOLATION, if value is NULL.
1273 * For base 0 it uses 10 as base and the string should be in the format
1274 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
1275 * For other bases the string should be in the format
1276 * "{whitespace} [+|-] {digits}".
1277 * No check is made for value overflow, only the lower 32 bits are assigned.
1278 * If str is NULL it crashes, as the native function does.
1281 * This function does not read garbage behind '\0' as the native version does.
1283 NTSTATUS WINAPI
RtlCharToInteger(
1284 PCSZ str
, /* [I] '\0' terminated single-byte string containing a number */
1285 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
1286 ULONG
*value
) /* [O] Destination for the converted value */
1290 ULONG RunningTotal
= 0;
1291 BOOL bMinus
= FALSE
;
1293 while (*str
!= '\0' && *str
<= ' ') {
1299 } else if (*str
== '-') {
1306 if (str
[0] == '0') {
1307 if (str
[1] == 'b') {
1310 } else if (str
[1] == 'o') {
1313 } else if (str
[1] == 'x') {
1318 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
1319 return STATUS_INVALID_PARAMETER
;
1322 if (value
== NULL
) {
1323 return STATUS_ACCESS_VIOLATION
;
1326 while (*str
!= '\0') {
1328 if (chCurrent
>= '0' && chCurrent
<= '9') {
1329 digit
= chCurrent
- '0';
1330 } else if (chCurrent
>= 'A' && chCurrent
<= 'Z') {
1331 digit
= chCurrent
- 'A' + 10;
1332 } else if (chCurrent
>= 'a' && chCurrent
<= 'z') {
1333 digit
= chCurrent
- 'a' + 10;
1337 if (digit
< 0 || digit
>= base
) {
1338 *value
= bMinus
? -RunningTotal
: RunningTotal
;
1339 return STATUS_SUCCESS
;
1342 RunningTotal
= RunningTotal
* base
+ digit
;
1346 *value
= bMinus
? -RunningTotal
: RunningTotal
;
1347 return STATUS_SUCCESS
;
1351 /**************************************************************************
1352 * RtlIntegerToChar (NTDLL.@)
1354 * Converts an unsigned integer to a character string.
1357 * Success: STATUS_SUCCESS. str contains the converted number
1358 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
1359 * STATUS_BUFFER_OVERFLOW, if str would be larger than length.
1360 * STATUS_ACCESS_VIOLATION, if str is NULL.
1363 * Instead of base 0 it uses 10 as base.
1364 * Writes at most length characters to the string str.
1365 * Str is '\0' terminated when length allows it.
1366 * When str fits exactly in length characters the '\0' is omitted.
1368 NTSTATUS WINAPI
RtlIntegerToChar(
1369 ULONG value
, /* [I] Value to be converted */
1370 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
1371 ULONG length
, /* [I] Length of the str buffer in bytes */
1372 PCHAR str
) /* [O] Destination for the converted value */
1381 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
1382 return STATUS_INVALID_PARAMETER
;
1390 digit
= value
% base
;
1391 value
= value
/ base
;
1395 *pos
= 'A' + digit
- 10;
1397 } while (value
!= 0L);
1399 len
= &buffer
[32] - pos
;
1401 return STATUS_BUFFER_OVERFLOW
;
1402 } else if (str
== NULL
) {
1403 return STATUS_ACCESS_VIOLATION
;
1404 } else if (len
== length
) {
1405 memcpy(str
, pos
, len
);
1407 memcpy(str
, pos
, len
+ 1);
1409 return STATUS_SUCCESS
;
1413 /**************************************************************************
1414 * RtlUnicodeStringToInteger (NTDLL.@)
1416 * Converts a unicode string into its integer equivalent.
1419 * Success: STATUS_SUCCESS. value contains the converted number
1420 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
1421 * STATUS_ACCESS_VIOLATION, if value is NULL.
1424 * For base 0 it uses 10 as base and the string should be in the format
1425 * "{whitespace} [+|-] [0[x|o|b]] {digits}".
1426 * For other bases the string should be in the format
1427 * "{whitespace} [+|-] {digits}".
1428 * No check is made for value overflow, only the lower 32 bits are assigned.
1429 * If str is NULL it crashes, as the native function does.
1432 * This function does not read garbage on string length 0 as the native
1435 NTSTATUS WINAPI
RtlUnicodeStringToInteger(
1436 const UNICODE_STRING
*str
, /* [I] Unicode string to be converted */
1437 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
1438 ULONG
*value
) /* [O] Destination for the converted value */
1440 LPWSTR lpwstr
= str
->Buffer
;
1441 USHORT CharsRemaining
= str
->Length
/ sizeof(WCHAR
);
1444 ULONG RunningTotal
= 0;
1445 BOOL bMinus
= FALSE
;
1447 while (CharsRemaining
>= 1 && *lpwstr
<= ' ') {
1452 if (CharsRemaining
>= 1) {
1453 if (*lpwstr
== '+') {
1456 } else if (*lpwstr
== '-') {
1465 if (CharsRemaining
>= 2 && lpwstr
[0] == '0') {
1466 if (lpwstr
[1] == 'b') {
1468 CharsRemaining
-= 2;
1470 } else if (lpwstr
[1] == 'o') {
1472 CharsRemaining
-= 2;
1474 } else if (lpwstr
[1] == 'x') {
1476 CharsRemaining
-= 2;
1480 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
1481 return STATUS_INVALID_PARAMETER
;
1484 if (value
== NULL
) {
1485 return STATUS_ACCESS_VIOLATION
;
1488 while (CharsRemaining
>= 1) {
1489 wchCurrent
= *lpwstr
;
1490 if (wchCurrent
>= '0' && wchCurrent
<= '9') {
1491 digit
= wchCurrent
- '0';
1492 } else if (wchCurrent
>= 'A' && wchCurrent
<= 'Z') {
1493 digit
= wchCurrent
- 'A' + 10;
1494 } else if (wchCurrent
>= 'a' && wchCurrent
<= 'z') {
1495 digit
= wchCurrent
- 'a' + 10;
1499 if (digit
< 0 || digit
>= base
) {
1500 *value
= bMinus
? -RunningTotal
: RunningTotal
;
1501 return STATUS_SUCCESS
;
1504 RunningTotal
= RunningTotal
* base
+ digit
;
1509 *value
= bMinus
? -RunningTotal
: RunningTotal
;
1510 return STATUS_SUCCESS
;
1514 /**************************************************************************
1515 * RtlIntegerToUnicodeString (NTDLL.@)
1517 * Converts an unsigned integer to a '\0' terminated unicode string.
1520 * Success: STATUS_SUCCESS. str contains the converted number
1521 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
1522 * STATUS_BUFFER_OVERFLOW, if str is too small to hold the string
1523 * (with the '\0' termination). In this case str->Length
1524 * is set to the length, the string would have (which can
1525 * be larger than the MaximumLength).
1528 * Instead of base 0 it uses 10 as base.
1529 * If str is NULL it crashes, as the native function does.
1532 * Do not return STATUS_BUFFER_OVERFLOW when the string is long enough.
1533 * The native function does this when the string would be longer than 16
1534 * characters even when the string parameter is long enough.
1536 NTSTATUS WINAPI
RtlIntegerToUnicodeString(
1537 ULONG value
, /* [I] Value to be converted */
1538 ULONG base
, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
1539 UNICODE_STRING
*str
) /* [O] Destination for the converted value */
1547 } else if (base
!= 2 && base
!= 8 && base
!= 10 && base
!= 16) {
1548 return STATUS_INVALID_PARAMETER
;
1556 digit
= value
% base
;
1557 value
= value
/ base
;
1561 *pos
= 'A' + digit
- 10;
1563 } while (value
!= 0L);
1565 str
->Length
= (&buffer
[32] - pos
) * sizeof(WCHAR
);
1566 if (str
->Length
>= str
->MaximumLength
) {
1567 return STATUS_BUFFER_OVERFLOW
;
1569 memcpy(str
->Buffer
, pos
, str
->Length
+ sizeof(WCHAR
));
1571 return STATUS_SUCCESS
;
1575 /*************************************************************************
1576 * RtlGUIDFromString (NTDLL.@)
1578 * Convert a string representation of a GUID into a GUID.
1581 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
1582 * guid [O] Destination for the converted GUID
1585 * Success: STATUS_SUCCESS. guid contains the converted value.
1586 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format.
1589 * See RtlStringFromGUID.
1591 NTSTATUS WINAPI
RtlGUIDFromString(PUNICODE_STRING str
, GUID
* guid
)
1594 const WCHAR
*lpszCLSID
= str
->Buffer
;
1595 BYTE
* lpOut
= (BYTE
*)guid
;
1597 TRACE("(%s,%p)\n", debugstr_us(str
), guid
);
1599 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
1600 * to memory: DWORD... WORD WORD BYTES............
1607 if (*lpszCLSID
!= '{')
1608 return STATUS_INVALID_PARAMETER
;
1611 case 9: case 14: case 19: case 24:
1612 if (*lpszCLSID
!= '-')
1613 return STATUS_INVALID_PARAMETER
;
1617 if (*lpszCLSID
!= '}')
1618 return STATUS_INVALID_PARAMETER
;
1623 WCHAR ch
= *lpszCLSID
, ch2
= lpszCLSID
[1];
1626 /* Read two hex digits as a byte value */
1627 if (ch
>= '0' && ch
<= '9') ch
= ch
- '0';
1628 else if (ch
>= 'a' && ch
<= 'f') ch
= ch
- 'a' + 10;
1629 else if (ch
>= 'A' && ch
<= 'F') ch
= ch
- 'A' + 10;
1630 else return STATUS_INVALID_PARAMETER
;
1632 if (ch2
>= '0' && ch2
<= '9') ch2
= ch2
- '0';
1633 else if (ch2
>= 'a' && ch2
<= 'f') ch2
= ch2
- 'a' + 10;
1634 else if (ch2
>= 'A' && ch2
<= 'F') ch2
= ch2
- 'A' + 10;
1635 else return STATUS_INVALID_PARAMETER
;
1637 byte
= ch
<< 4 | ch2
;
1641 #ifndef WORDS_BIGENDIAN
1642 /* For Big Endian machines, we store the data such that the
1643 * dword/word members can be read as DWORDS and WORDS correctly. */
1645 case 1: lpOut
[3] = byte
; break;
1646 case 3: lpOut
[2] = byte
; break;
1647 case 5: lpOut
[1] = byte
; break;
1648 case 7: lpOut
[0] = byte
; lpOut
+= 4; break;
1650 case 10: case 15: lpOut
[1] = byte
; break;
1651 case 12: case 17: lpOut
[0] = byte
; lpOut
+= 2; break;
1654 default: lpOut
[0] = byte
; lpOut
++; break;
1656 lpszCLSID
++; /* Skip 2nd character of byte */
1664 return STATUS_SUCCESS
;
1667 /*************************************************************************
1668 * RtlStringFromGUID (NTDLL.@)
1670 * Convert a GUID into a string representation of a GUID.
1673 * guid [I] GUID to convert
1674 * str [O] Destination for the converted string
1677 * Success: STATUS_SUCCESS. str contains the converted value.
1678 * Failure: STATUS_NO_MEMORY, if memory for str cannot be allocated.
1681 * See RtlGUIDFromString.
1683 NTSTATUS WINAPI
RtlStringFromGUID(const GUID
* guid
, UNICODE_STRING
*str
)
1685 TRACE("(%p,%p)\n", guid
, str
);
1687 str
->Length
= GUID_STRING_LENGTH
* sizeof(WCHAR
);
1688 str
->MaximumLength
= str
->Length
+ sizeof(WCHAR
);
1689 str
->Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, str
->MaximumLength
);
1692 str
->Length
= str
->MaximumLength
= 0;
1693 return STATUS_NO_MEMORY
;
1695 swprintf(str
->Buffer
, str
->MaximumLength
/sizeof(WCHAR
),
1696 L
"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", guid
->Data1
, guid
->Data2
, guid
->Data3
,
1697 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
1698 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
1700 return STATUS_SUCCESS
;
1704 /***********************************************************************
1705 * Message formatting
1706 ***********************************************************************/
1708 struct format_message_args
1710 int last
; /* last used arg */
1711 ULONG_PTR
*array
; /* args array */
1712 va_list *list
; /* args va_list */
1713 UINT64 arglist
[102]; /* arguments fetched from va_list */
1716 static NTSTATUS
add_chars( WCHAR
**buffer
, WCHAR
*end
, const WCHAR
*str
, ULONG len
)
1718 if (len
> end
- *buffer
) return STATUS_BUFFER_OVERFLOW
;
1719 memcpy( *buffer
, str
, len
* sizeof(WCHAR
) );
1721 return STATUS_SUCCESS
;
1724 static UINT64
get_arg( int nr
, struct format_message_args
*args_data
, BOOL is64
)
1726 if (nr
== -1) nr
= args_data
->last
+ 1;
1727 while (nr
> args_data
->last
)
1728 args_data
->arglist
[args_data
->last
++] = is64
? va_arg( *args_data
->list
, UINT64
)
1729 : va_arg( *args_data
->list
, ULONG_PTR
);
1730 return args_data
->arglist
[nr
- 1];
1733 static NTSTATUS
add_format( WCHAR
**buffer
, WCHAR
*end
, const WCHAR
**src
, int insert
, BOOLEAN ansi
,
1734 struct format_message_args
*args_data
)
1736 const WCHAR
*format
= *src
;
1738 ULONG_PTR args
[5] = { 0 };
1741 int len
, stars
= 0, nb_args
= 0;
1746 if (*format
++ == '!')
1748 const WCHAR
*end
= wcschr( format
, '!' );
1750 if (!end
|| end
- format
> ARRAY_SIZE(fmt
) - 2) return STATUS_INVALID_PARAMETER
;
1753 while (wcschr( L
"0123456789 +-*#.", *format
))
1755 if (*format
== '*') stars
++;
1758 if (stars
> 2) return STATUS_INVALID_PARAMETER
;
1764 if (ansi
) *p
++ = *format
++ ^ ('s' - 'S');
1767 if (sizeof(void *) == sizeof(int) && format
[1] == '6' && format
[2] == '4') is_64
= TRUE
;
1770 while (format
!= end
) *p
++ = *format
++;
1772 else *p
++ = ansi
? 'S' : 's'; /* simple string */
1775 if (args_data
->list
)
1777 get_arg( insert
- 1, args_data
, is_64
); /* make sure previous args have been fetched */
1780 args
[nb_args
++] = get_arg( insert
, args_data
, FALSE
);
1783 /* replicate MS bug: drop an argument when using va_list with width/precision */
1784 if (insert
== -1) args_data
->last
--;
1785 val
= get_arg( insert
, args_data
, is_64
);
1786 args
[nb_args
++] = val
;
1787 args
[nb_args
] = val
>> 32;
1789 else if (args_data
->array
)
1791 args
[nb_args
++] = args_data
->array
[insert
- 1];
1792 if (args_data
->last
< insert
) args_data
->last
= insert
;
1793 /* replicate MS bug: first arg is considered 64-bit, even if it's actually width or precision */
1794 if (is_64
) nb_args
++;
1795 while (stars
--) args
[nb_args
++] = args_data
->array
[args_data
->last
++];
1797 else return STATUS_INVALID_PARAMETER
;
1799 len
= _snwprintf_s( *buffer
, end
- *buffer
, end
- *buffer
- 1, fmt
,
1800 args
[0], args
[1], args
[2], args
[3], args
[4] );
1801 if (len
== -1) return STATUS_BUFFER_OVERFLOW
;
1803 return STATUS_SUCCESS
;
1807 /**********************************************************************
1808 * RtlFormatMessage (NTDLL.@)
1810 NTSTATUS WINAPI
RtlFormatMessage( const WCHAR
*src
, ULONG width
, BOOLEAN ignore_inserts
,
1811 BOOLEAN ansi
, BOOLEAN is_array
, va_list *args
,
1812 WCHAR
*buffer
, ULONG size
, ULONG
*retsize
)
1814 return RtlFormatMessageEx( src
, width
, ignore_inserts
, ansi
, is_array
, args
, buffer
, size
, retsize
, 0 );
1818 /**********************************************************************
1819 * RtlFormatMessageEx (NTDLL.@)
1821 NTSTATUS WINAPI
RtlFormatMessageEx( const WCHAR
*src
, ULONG width
, BOOLEAN ignore_inserts
,
1822 BOOLEAN ansi
, BOOLEAN is_array
, va_list *args
,
1823 WCHAR
*buffer
, ULONG size
, ULONG
*retsize
, ULONG flags
)
1825 static const WCHAR spaceW
= ' ';
1826 static const WCHAR crW
= '\r';
1827 static const WCHAR tabW
= '\t';
1828 static const WCHAR crlfW
[] = {'\r','\n'};
1830 struct format_message_args args_data
;
1831 NTSTATUS status
= STATUS_SUCCESS
;
1833 WCHAR
*start
= buffer
; /* start of buffer */
1834 WCHAR
*end
= buffer
+ size
/ sizeof(WCHAR
); /* end of buffer */
1835 WCHAR
*line
= buffer
; /* start of last line */
1836 WCHAR
*space
= NULL
; /* last space */
1838 if (flags
) FIXME( "%s unknown flags %x\n", debugstr_w(src
), flags
);
1841 args_data
.array
= is_array
? (ULONG_PTR
*)args
: NULL
;
1842 args_data
.list
= is_array
? NULL
: args
;
1844 for ( ; *src
; src
++)
1849 if (src
[1] == '\n') src
++;
1854 status
= add_chars( &buffer
, end
, crlfW
, 2 );
1862 status
= add_chars( &buffer
, end
, &spaceW
, 1 );
1865 if (space
== buffer
- 1) space
= buffer
;
1866 status
= add_chars( &buffer
, end
, &tabW
, 1 );
1873 return STATUS_INVALID_PARAMETER
;
1877 status
= add_chars( &buffer
, end
, &tabW
, 1 );
1882 status
= add_chars( &buffer
, end
, crlfW
, 2 );
1887 status
= add_chars( &buffer
, end
, &crW
, 1 );
1892 while (src
[1]) src
++;
1894 case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
1895 if (!ignore_inserts
)
1897 int nr
= *src
++ - '0';
1899 if (*src
>= '0' && *src
<= '9') nr
= nr
* 10 + *src
++ - '0';
1900 status
= add_format( &buffer
, end
, &src
, nr
, ansi
, &args_data
);
1906 if (ignore_inserts
) status
= add_chars( &buffer
, end
, src
- 1, 2 );
1907 else status
= add_chars( &buffer
, end
, src
, 1 );
1912 status
= add_chars( &buffer
, end
, src
, 1 );
1916 if (status
) return status
;
1918 if (width
&& buffer
- line
>= width
)
1923 if (space
) /* split line at the last space */
1926 while (space
> line
&& (space
[-1] == ' ' || space
[-1] == '\t')) space
--;
1927 diff
-= next
- space
;
1929 else space
= next
= buffer
; /* split at the end of the buffer */
1931 if (diff
> 0 && end
- buffer
< diff
) return STATUS_BUFFER_OVERFLOW
;
1932 memmove( space
+ 2, next
, (buffer
- next
) * sizeof(WCHAR
) );
1934 memcpy( space
, crlfW
, sizeof(crlfW
) );
1940 if ((status
= add_chars( &buffer
, end
, L
"", 1 ))) return status
;
1942 *retsize
= (buffer
- start
) * sizeof(WCHAR
);
1943 return STATUS_SUCCESS
;