Added a few more large integer functions.
[wine] / dlls / ntdll / rtlstr.c
1 /*
2  * Rtl string functions
3  *
4  * Copyright (C) 1996-1998 Marcus Meissner
5  * Copyright (C) 2000      Alexandre Julliard
6  */
7
8 #include "config.h"
9
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include "wine/winestring.h"
14 #include "wine/unicode.h"
15 #include "heap.h"
16 #include "winnls.h"
17 #include "debugtools.h"
18 #include "ntdll_misc.h"
19 #include "ntddk.h"
20
21 DEFAULT_DEBUG_CHANNEL(ntdll);
22
23 /* STRING CREATION FUNCTIONS */
24
25 /**************************************************************************
26  *      RtlInitAnsiString   (NTDLL.@)
27  */
28 void WINAPI RtlInitAnsiString( PSTRING target, LPCSTR source)
29 {
30     if ((target->Buffer = (LPSTR)source))
31     {
32         target->Length = strlen(source);
33         target->MaximumLength = target->Length + 1;
34     }
35     else target->Length = target->MaximumLength = 0;
36 }
37
38
39 /**************************************************************************
40  *      RtlInitString   (NTDLL.@)
41  */
42 void WINAPI RtlInitString( PSTRING target, LPCSTR source )
43 {
44     return RtlInitAnsiString( target, source );
45 }
46
47
48 /**************************************************************************
49  *      RtlFreeAnsiString   (NTDLL.@)
50  */
51 void WINAPI RtlFreeAnsiString( PSTRING str )
52 {
53     if (str->Buffer) HeapFree( GetProcessHeap(), 0, str->Buffer );
54 }
55
56
57 /**************************************************************************
58  *      RtlFreeOemString   (NTDLL.@)
59  */
60 void WINAPI RtlFreeOemString( PSTRING str )
61 {
62     RtlFreeAnsiString( str );
63 }
64
65
66 /**************************************************************************
67  *      RtlCopyString   (NTDLL.@)
68  */
69 void WINAPI RtlCopyString( STRING *dst, const STRING *src )
70 {
71     if (src)
72     {
73         unsigned int len = min( src->Length, dst->MaximumLength );
74         memcpy( dst->Buffer, src->Buffer, len );
75         dst->Length = len;
76     }
77     else dst->Length = 0;
78 }
79
80
81 /**************************************************************************
82  *      RtlInitUnicodeString   (NTDLL.@)
83  */
84 void WINAPI RtlInitUnicodeString( PUNICODE_STRING target, LPCWSTR source )
85 {
86     if ((target->Buffer = (LPWSTR)source))
87     {
88         target->Length = strlenW(source) * sizeof(WCHAR);
89         target->MaximumLength = target->Length + sizeof(WCHAR);
90     }
91     else target->Length = target->MaximumLength = 0;
92 }
93
94
95 /**************************************************************************
96  *      RtlCreateUnicodeString   (NTDLL.@)
97  */
98 BOOLEAN WINAPI RtlCreateUnicodeString( PUNICODE_STRING target, LPCWSTR src )
99 {
100     int len = (strlenW(src) + 1) * sizeof(WCHAR);
101     if (!(target->Buffer = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE;
102     memcpy( target->Buffer, src, len );
103     target->MaximumLength = len;
104     target->Length = len - 2;
105     return TRUE;
106 }
107
108
109 /**************************************************************************
110  *      RtlCreateUnicodeStringFromAsciiz   (NTDLL.@)
111  */
112 BOOLEAN WINAPI RtlCreateUnicodeStringFromAsciiz( PUNICODE_STRING target, LPCSTR src )
113 {
114     STRING ansi;
115     RtlInitAnsiString( &ansi, src );
116     return !RtlAnsiStringToUnicodeString( target, &ansi, TRUE );
117 }
118
119
120 /**************************************************************************
121  *      RtlFreeUnicodeString   (NTDLL.@)
122  */
123 void WINAPI RtlFreeUnicodeString( PUNICODE_STRING str )
124 {
125     if (str->Buffer) HeapFree( GetProcessHeap(), 0, str->Buffer );
126 }
127
128
129 /**************************************************************************
130  *      RtlCopyUnicodeString   (NTDLL.@)
131  */
132 void WINAPI RtlCopyUnicodeString( UNICODE_STRING *dst, const UNICODE_STRING *src )
133 {
134     if (src)
135     {
136         unsigned int len = min( src->Length, dst->MaximumLength );
137         memcpy( dst->Buffer, src->Buffer, len );
138         dst->Length = len;
139         /* append terminating NULL if enough space */
140         if (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0;
141     }
142     else dst->Length = 0;
143 }
144
145
146 /**************************************************************************
147  *      RtlEraseUnicodeString   (NTDLL.@)
148  */
149 void WINAPI RtlEraseUnicodeString( UNICODE_STRING *str )
150 {
151     if (str->Buffer)
152     {
153         memset( str->Buffer, 0, str->MaximumLength );
154         str->Length = 0;
155     }
156 }
157
158 /*
159     COMPARISON FUNCTIONS
160 */
161
162 /******************************************************************************
163  *      RtlCompareString   (NTDLL.@)
164  */
165 LONG WINAPI RtlCompareString( const STRING *s1, const STRING *s2, BOOLEAN CaseInsensitive )
166 {
167     unsigned int len;
168     LONG ret = 0;
169     LPCSTR p1, p2;
170
171     len = min(s1->Length, s2->Length);
172     p1 = s1->Buffer;
173     p2 = s2->Buffer;
174
175     if (CaseInsensitive)
176     {
177         while (!ret && len--) ret = toupper(*p1++) - toupper(*p2++);
178     }
179     else
180     {
181         while (!ret && len--) ret = *p1++ - *p2++;
182     }
183     if (!ret) ret = s1->Length - s2->Length;
184     return ret;
185 }
186
187
188 /******************************************************************************
189  *      RtlCompareUnicodeString   (NTDLL.@)
190  */
191 LONG WINAPI RtlCompareUnicodeString( const UNICODE_STRING *s1, const UNICODE_STRING *s2,
192                                      BOOLEAN CaseInsensitive )
193 {
194     unsigned int len;
195     LONG ret = 0;
196     LPCWSTR p1, p2;
197
198     len = min(s1->Length, s2->Length) / sizeof(WCHAR);
199     p1 = s1->Buffer;
200     p2 = s2->Buffer;
201
202     if (CaseInsensitive)
203     {
204         while (!ret && len--) ret = toupperW(*p1++) - toupperW(*p2++);
205     }
206     else
207     {
208         while (!ret && len--) ret = *p1++ - *p2++;
209     }
210     if (!ret) ret = s1->Length - s2->Length;
211     return ret;
212 }
213
214
215 /**************************************************************************
216  *      RtlEqualString   (NTDLL.@)
217  */
218 BOOLEAN WINAPI RtlEqualString( const STRING *s1, const STRING *s2, BOOLEAN CaseInsensitive )
219 {
220     if (s1->Length != s2->Length) return FALSE;
221     return !RtlCompareString( s1, s2, CaseInsensitive );
222 }
223
224
225 /**************************************************************************
226  *      RtlEqualUnicodeString   (NTDLL.@)
227  */
228 BOOLEAN WINAPI RtlEqualUnicodeString( const UNICODE_STRING *s1, const UNICODE_STRING *s2,
229                                       BOOLEAN CaseInsensitive )
230 {
231     if (s1->Length != s2->Length) return FALSE;
232     return !RtlCompareUnicodeString( s1, s2, CaseInsensitive );
233 }
234
235
236 /**************************************************************************
237  *      RtlPrefixString   (NTDLL.@)
238  *
239  * Test if s1 is a prefix in s2
240  */
241 BOOLEAN WINAPI RtlPrefixString( const STRING *s1, const STRING *s2, BOOLEAN ignore_case )
242 {
243     unsigned int i;
244
245     if (s1->Length > s2->Length) return FALSE;
246     if (ignore_case)
247     {
248         for (i = 0; i < s1->Length; i++)
249             if (toupper(s1->Buffer[i]) != toupper(s2->Buffer[i])) return FALSE;
250     }
251     else
252     {
253         for (i = 0; i < s1->Length; i++)
254             if (s1->Buffer[i] != s2->Buffer[i]) return FALSE;
255     }
256     return TRUE;
257 }
258
259
260 /**************************************************************************
261  *      RtlPrefixUnicodeString   (NTDLL.@)
262  *
263  * Test if s1 is a prefix in s2
264  */
265 BOOLEAN WINAPI RtlPrefixUnicodeString( const UNICODE_STRING *s1,
266                                        const UNICODE_STRING *s2,
267                                        BOOLEAN ignore_case )
268 {
269     unsigned int i;
270
271     if (s1->Length > s2->Length) return FALSE;
272     if (ignore_case)
273     {
274         for (i = 0; i < s1->Length / sizeof(WCHAR); i++)
275             if (toupper(s1->Buffer[i]) != toupper(s2->Buffer[i])) return FALSE;
276     }
277     else
278     {
279         for (i = 0; i < s1->Length / sizeof(WCHAR); i++)
280             if (s1->Buffer[i] != s2->Buffer[i]) return FALSE;
281     }
282     return TRUE;
283 }
284
285
286 /*
287         COPY BETWEEN ANSI_STRING or UNICODE_STRING
288         there is no parameter checking, it just crashes
289 */
290
291
292 /**************************************************************************
293  *      RtlAnsiStringToUnicodeString   (NTDLL.@)
294  *
295  * NOTES:
296  *  writes terminating 0
297  */
298 NTSTATUS WINAPI RtlAnsiStringToUnicodeString( UNICODE_STRING *uni,
299                                               const STRING *ansi,
300                                               BOOLEAN doalloc )
301 {
302     DWORD len = MultiByteToWideChar( CP_ACP, 0, ansi->Buffer, ansi->Length, NULL, 0 );
303     DWORD total = (len + 1) * sizeof(WCHAR);
304
305     if (total > 0xffff) return STATUS_INVALID_PARAMETER_2;
306     uni->Length = len * sizeof(WCHAR);
307     if (doalloc)
308     {
309         uni->MaximumLength = total;
310         if (!(uni->Buffer = HeapAlloc( GetProcessHeap(), 0, total ))) return STATUS_NO_MEMORY;
311     }
312     else if (total > uni->MaximumLength) return STATUS_BUFFER_OVERFLOW;
313
314     MultiByteToWideChar( CP_ACP, 0, ansi->Buffer, ansi->Length, uni->Buffer, len );
315     uni->Buffer[len] = 0;
316     return STATUS_SUCCESS;
317 }
318
319
320 /**************************************************************************
321  *      RtlOemStringToUnicodeString   (NTDLL.@)
322  *
323  * NOTES
324  *  writes terminating 0
325  *  if resulting length > 0xffff it returns STATUS_INVALID_PARAMETER_2
326  */
327 NTSTATUS WINAPI RtlOemStringToUnicodeString( UNICODE_STRING *uni,
328                                              const STRING *oem,
329                                              BOOLEAN doalloc )
330 {
331     DWORD len = MultiByteToWideChar( CP_OEMCP, 0, oem->Buffer, oem->Length, NULL, 0 );
332     DWORD total = (len + 1) * sizeof(WCHAR);
333
334     if (total > 0xffff) return STATUS_INVALID_PARAMETER_2;
335     uni->Length = len * sizeof(WCHAR);
336     if (doalloc)
337     {
338         uni->MaximumLength = total;
339         if (!(uni->Buffer = HeapAlloc( GetProcessHeap(), 0, total ))) return STATUS_NO_MEMORY;
340     }
341     else if (total > uni->MaximumLength) return STATUS_BUFFER_OVERFLOW;
342
343     MultiByteToWideChar( CP_OEMCP, 0, oem->Buffer, oem->Length, uni->Buffer, len );
344     uni->Buffer[len] = 0;
345     return STATUS_SUCCESS;
346 }
347
348
349 /**************************************************************************
350  *      RtlUnicodeStringToAnsiString   (NTDLL.@)
351  *
352  * NOTES
353  *  writes terminating 0
354  *  copies a part if the buffer is too small
355  */
356 NTSTATUS WINAPI RtlUnicodeStringToAnsiString( STRING *ansi,
357                                               const UNICODE_STRING *uni,
358                                               BOOLEAN doalloc )
359 {
360     NTSTATUS ret = STATUS_SUCCESS;
361     DWORD len = RtlUnicodeStringToAnsiSize( uni );
362
363     ansi->Length = len;
364     if (doalloc)
365     {
366         ansi->MaximumLength = len + 1;
367         if (!(ansi->Buffer = HeapAlloc( GetProcessHeap(), 0, len + 1 ))) return STATUS_NO_MEMORY;
368     }
369     else if (ansi->MaximumLength <= len)
370     {
371         if (!ansi->MaximumLength) return STATUS_BUFFER_OVERFLOW;
372         ansi->Length = ansi->MaximumLength - 1;
373         ret = STATUS_BUFFER_OVERFLOW;
374     }
375
376     WideCharToMultiByte( CP_ACP, 0, uni->Buffer, uni->Length / sizeof(WCHAR),
377                          ansi->Buffer, ansi->Length, NULL, NULL );
378     ansi->Buffer[ansi->Length] = 0;
379     return ret;
380 }
381
382
383 /**************************************************************************
384  *      RtlUnicodeStringToOemString   (NTDLL.@)
385  *
386  * NOTES
387  *   allocates uni->Length+1
388  *   writes terminating 0
389  */
390 NTSTATUS WINAPI RtlUnicodeStringToOemString( STRING *oem,
391                                              const UNICODE_STRING *uni,
392                                              BOOLEAN doalloc )
393 {
394     NTSTATUS ret = STATUS_SUCCESS;
395     DWORD len = RtlUnicodeStringToOemSize( uni );
396
397     oem->Length = len;
398     if (doalloc)
399     {
400         oem->MaximumLength = len + 1;
401         if (!(oem->Buffer = HeapAlloc( GetProcessHeap(), 0, len + 1 ))) return STATUS_NO_MEMORY;
402     }
403     else if (oem->MaximumLength <= len)
404     {
405         if (!oem->MaximumLength) return STATUS_BUFFER_OVERFLOW;
406         oem->Length = oem->MaximumLength - 1;
407         ret = STATUS_BUFFER_OVERFLOW;
408     }
409
410     WideCharToMultiByte( CP_OEMCP, 0, uni->Buffer, uni->Length / sizeof(WCHAR),
411                          oem->Buffer, oem->Length, NULL, NULL );
412     oem->Buffer[oem->Length] = 0;
413     return ret;
414 }
415
416
417 /**************************************************************************
418  *      RtlMultiByteToUnicodeN   (NTDLL.@)
419  *
420  * NOTES
421  *  if unistr is too small a part is copied
422  */
423 NTSTATUS WINAPI RtlMultiByteToUnicodeN( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
424                                         LPCSTR src, DWORD srclen )
425 {
426     DWORD res = MultiByteToWideChar( CP_ACP, 0, src, srclen, dst, dstlen/sizeof(WCHAR) );
427     if (reslen)
428         *reslen = res ? res * sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
429     return STATUS_SUCCESS;
430 }
431
432
433 /**************************************************************************
434  *      RtlOemToUnicodeN   (NTDLL.@)
435  */
436 NTSTATUS WINAPI RtlOemToUnicodeN( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
437                                   LPCSTR src, DWORD srclen )
438 {
439     DWORD res = MultiByteToWideChar( CP_OEMCP, 0, src, srclen, dst, dstlen/sizeof(WCHAR) );
440     if (reslen)
441         *reslen = res ? res * sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
442     return STATUS_SUCCESS;
443 }
444
445
446 /**************************************************************************
447  *      RtlUnicodeToMultiByteN   (NTDLL.@)
448  */
449 NTSTATUS WINAPI RtlUnicodeToMultiByteN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
450                                         LPCWSTR src, DWORD srclen )
451 {
452     DWORD res = WideCharToMultiByte( CP_ACP, 0, src, srclen/sizeof(WCHAR),
453                                      dst, dstlen, NULL, NULL );
454     if (reslen)
455         *reslen = res ? res * sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
456     return STATUS_SUCCESS;
457 }
458
459
460 /**************************************************************************
461  *      RtlUnicodeToOemN   (NTDLL.@)
462  */
463 NTSTATUS WINAPI RtlUnicodeToOemN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
464                                   LPCWSTR src, DWORD srclen )
465 {
466     DWORD res = WideCharToMultiByte( CP_OEMCP, 0, src, srclen/sizeof(WCHAR),
467                                      dst, dstlen, NULL, NULL );
468     if (reslen)
469         *reslen = res ? res * sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
470     return STATUS_SUCCESS;
471 }
472
473
474 /*
475      CASE CONVERSIONS
476 */
477
478 /**************************************************************************
479  *      RtlUpperString   (NTDLL.@)
480  */
481 void WINAPI RtlUpperString( STRING *dst, const STRING *src )
482 {
483     unsigned int i, len = min(src->Length, dst->MaximumLength);
484
485     for (i = 0; i < len; i++) dst->Buffer[i] = toupper(src->Buffer[i]);
486     dst->Length = len;
487 }
488
489
490 /**************************************************************************
491  *      RtlUpcaseUnicodeString   (NTDLL.@)
492  *
493  * NOTES:
494  *  destination string is never 0-terminated because dest can be equal to src
495  *  and src might be not 0-terminated
496  *  dest.Length only set when success
497  */
498 NTSTATUS WINAPI RtlUpcaseUnicodeString( UNICODE_STRING *dest,
499                                         const UNICODE_STRING *src,
500                                         BOOLEAN doalloc )
501 {
502     DWORD i, len = src->Length;
503
504     if (doalloc)
505     {
506         dest->MaximumLength = len;
507         if (!(dest->Buffer = HeapAlloc( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY;
508     }
509     else if (len > dest->MaximumLength) return STATUS_BUFFER_OVERFLOW;
510
511     for (i = 0; i < len/sizeof(WCHAR); i++) dest->Buffer[i] = toupperW(src->Buffer[i]);
512     dest->Length = len;
513     return STATUS_SUCCESS;
514 }
515
516
517 /**************************************************************************
518  *      RtlUpcaseUnicodeStringToAnsiString   (NTDLL.@)
519  *
520  * NOTES
521  *  writes terminating 0
522  */
523 NTSTATUS WINAPI RtlUpcaseUnicodeStringToAnsiString( STRING *dst,
524                                                     const UNICODE_STRING *src,
525                                                     BOOLEAN doalloc )
526 {
527     NTSTATUS ret;
528     UNICODE_STRING upcase;
529
530     if (!(ret = RtlUpcaseUnicodeString( &upcase, src, TRUE )))
531     {
532         ret = RtlUnicodeStringToAnsiString( dst, &upcase, doalloc );
533         RtlFreeUnicodeString( &upcase );
534     }
535     return ret;
536 }
537
538
539 /**************************************************************************
540  *      RtlUpcaseUnicodeStringToOemString   (NTDLL.@)
541  *
542  * NOTES
543  *  writes terminating 0
544  */
545 NTSTATUS WINAPI RtlUpcaseUnicodeStringToOemString( STRING *dst,
546                                                    const UNICODE_STRING *src,
547                                                    BOOLEAN doalloc )
548 {
549     NTSTATUS ret;
550     UNICODE_STRING upcase;
551
552     if (!(ret = RtlUpcaseUnicodeString( &upcase, src, TRUE )))
553     {
554         ret = RtlUnicodeStringToOemString( dst, &upcase, doalloc );
555         RtlFreeUnicodeString( &upcase );
556     }
557     return ret;
558 }
559
560
561 /**************************************************************************
562  *      RtlUpcaseUnicodeToMultiByteN   (NTDLL.@)
563  */
564 NTSTATUS WINAPI RtlUpcaseUnicodeToMultiByteN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
565                                               LPCWSTR src, DWORD srclen )
566 {
567     NTSTATUS ret;
568     LPWSTR upcase;
569     DWORD i;
570
571     if (!(upcase = HeapAlloc( GetProcessHeap(), 0, srclen ))) return STATUS_NO_MEMORY;
572     for (i = 0; i < srclen/sizeof(WCHAR); i++) upcase[i] = toupperW(src[i]);
573     ret = RtlUnicodeToMultiByteN( dst, dstlen, reslen, upcase, srclen );
574     HeapFree( GetProcessHeap(), 0, upcase );
575     return ret;
576 }
577
578
579 /**************************************************************************
580  *      RtlUpcaseUnicodeToOemN   (NTDLL.@)
581  */
582 NTSTATUS WINAPI RtlUpcaseUnicodeToOemN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
583                                         LPCWSTR src, DWORD srclen )
584 {
585     NTSTATUS ret;
586     LPWSTR upcase;
587     DWORD i;
588
589     if (!(upcase = HeapAlloc( GetProcessHeap(), 0, srclen ))) return STATUS_NO_MEMORY;
590     for (i = 0; i < srclen/sizeof(WCHAR); i++) upcase[i] = toupperW(src[i]);
591     ret = RtlUnicodeToOemN( dst, dstlen, reslen, upcase, srclen );
592     HeapFree( GetProcessHeap(), 0, upcase );
593     return ret;
594 }
595
596
597 /*
598         STRING SIZE
599 */
600
601 /**************************************************************************
602  *      RtlOemStringToUnicodeSize   (NTDLL.@)
603  *
604  * Return the size in bytes necessary for the Unicode conversion of 'str',
605  * including the terminating NULL.
606  */
607 UINT WINAPI RtlOemStringToUnicodeSize(PSTRING str)
608 {
609     DWORD ret = MultiByteToWideChar( CP_OEMCP, 0, str->Buffer, str->Length, NULL, 0 );
610     return (ret + 1) * sizeof(WCHAR);
611 }
612
613
614 /**************************************************************************
615  *      RtlAnsiStringToUnicodeSize   (NTDLL.@)
616  *
617  * Return the size in bytes necessary for the Unicode conversion of 'str',
618  * including the terminating NULL.
619  */
620 DWORD WINAPI RtlAnsiStringToUnicodeSize(PSTRING str)
621 {
622     DWORD ret = MultiByteToWideChar( CP_ACP, 0, str->Buffer, str->Length, NULL, 0 );
623     return (ret + 1) * sizeof(WCHAR);
624 }
625
626
627 /**************************************************************************
628  *      RtlMultiByteToUnicodeSize   (NTDLL.@)
629  *
630  * Compute the size in bytes necessary for the Unicode conversion of 'str',
631  * without the terminating NULL.
632  */
633 NTSTATUS WINAPI RtlMultiByteToUnicodeSize( DWORD *size, LPCSTR str, UINT len )
634 {
635     *size = MultiByteToWideChar( CP_ACP, 0, str, len, NULL, 0 ) * sizeof(WCHAR);
636     return 0;
637 }
638
639
640 /**************************************************************************
641  *      RtlUnicodeToMultiByteSize   (NTDLL.@)
642  *
643  * Compute the size necessary for the multibyte conversion of 'str',
644  * without the terminating NULL.
645  */
646 NTSTATUS WINAPI RtlUnicodeToMultiByteSize( DWORD *size, LPCWSTR str, UINT len )
647 {
648     *size = WideCharToMultiByte( CP_ACP, 0, str, len / sizeof(WCHAR), NULL, 0, NULL, NULL );
649     return 0;
650 }
651
652
653 /**************************************************************************
654  *      RtlUnicodeStringToAnsiSize   (NTDLL.@)
655  *
656  * Return the size in bytes necessary for the Ansi conversion of 'str',
657  * including the terminating NULL.
658  */
659 DWORD WINAPI RtlUnicodeStringToAnsiSize( const UNICODE_STRING *str )
660 {
661     return WideCharToMultiByte( CP_ACP, 0, str->Buffer, str->Length / sizeof(WCHAR),
662                                 NULL, 0, NULL, NULL ) + 1;
663 }
664
665
666 /**************************************************************************
667  *      RtlUnicodeStringToOemSize   (NTDLL.@)
668  *
669  * Return the size in bytes necessary for the OEM conversion of 'str',
670  * including the terminating NULL.
671  */
672 DWORD WINAPI RtlUnicodeStringToOemSize( const UNICODE_STRING *str )
673 {
674     return WideCharToMultiByte( CP_OEMCP, 0, str->Buffer, str->Length / sizeof(WCHAR),
675                                 NULL, 0, NULL, NULL ) + 1;
676 }
677
678
679 /**************************************************************************
680  *      RtlAppendStringToString   (NTDLL.@)
681  */
682 NTSTATUS WINAPI RtlAppendStringToString( STRING *dst, const STRING *src )
683 {
684     unsigned int len = src->Length + dst->Length;
685     if (len > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
686     memcpy( dst->Buffer + dst->Length, src->Buffer, src->Length );
687     dst->Length = len;
688     return STATUS_SUCCESS;
689 }
690
691
692 /**************************************************************************
693  *      RtlAppendAsciizToString   (NTDLL.@)
694  */
695 NTSTATUS WINAPI RtlAppendAsciizToString( STRING *dst, LPCSTR src )
696 {
697     if (src)
698     {
699         unsigned int srclen = strlen(src);
700         unsigned int total  = srclen + dst->Length;
701         if (total > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
702         memcpy( dst->Buffer + dst->Length, src, srclen );
703         dst->Length = total;
704     }
705     return STATUS_SUCCESS;
706 }
707
708
709 /**************************************************************************
710  *      RtlAppendUnicodeToString   (NTDLL.@)
711  */
712 NTSTATUS WINAPI RtlAppendUnicodeToString( UNICODE_STRING *dst, LPCWSTR src )
713 {
714     if (src)
715     {
716         unsigned int srclen = strlenW(src) * sizeof(WCHAR);
717         unsigned int total  = srclen + dst->Length;
718         if (total > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
719         memcpy( dst->Buffer + dst->Length/sizeof(WCHAR), src, srclen );
720         dst->Length = total;
721         /* append terminating NULL if enough space */
722         if (total < dst->MaximumLength) dst->Buffer[total / sizeof(WCHAR)] = 0;
723     }
724     return STATUS_SUCCESS;
725 }
726
727
728 /**************************************************************************
729  *      RtlAppendUnicodeStringToString   (NTDLL.@)
730  */
731 NTSTATUS WINAPI RtlAppendUnicodeStringToString( UNICODE_STRING *dst, const UNICODE_STRING *src )
732 {
733     unsigned int len = src->Length + dst->Length;
734     if (len > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
735     memcpy( dst->Buffer + dst->Length/sizeof(WCHAR), src->Buffer, src->Length );
736     dst->Length = len;
737     /* append terminating NULL if enough space */
738     if (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0;
739     return STATUS_SUCCESS;
740 }
741
742
743 /*
744         MISC
745 */
746
747 /**************************************************************************
748  *      RtlIsTextUnicode
749  *
750  *      Apply various feeble heuristics to guess whether
751  *      the text buffer contains Unicode.
752  *      FIXME: should implement more tests.
753  */
754 DWORD WINAPI RtlIsTextUnicode(
755         LPVOID buf,
756         DWORD len,
757         DWORD *pf)
758 {
759         LPWSTR s = buf;
760         DWORD flags = -1, out_flags = 0;
761
762         if (!len)
763                 goto out;
764         if (pf)
765                 flags = *pf;
766         /*
767          * Apply various tests to the text string. According to the
768          * docs, each test "passed" sets the corresponding flag in
769          * the output flags. But some of the tests are mutually
770          * exclusive, so I don't see how you could pass all tests ...
771          */
772
773         /* Check for an odd length ... pass if even. */
774         if (!(len & 1))
775                 out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
776
777         /* Check for the special unicode marker byte. */
778         if (*s == 0xFEFF)
779                 out_flags |= IS_TEXT_UNICODE_SIGNATURE;
780
781         /*
782          * Check whether the string passed all of the tests.
783          */
784         flags &= ITU_IMPLEMENTED_TESTS;
785         if ((out_flags & flags) != flags)
786                 len = 0;
787 out:
788         if (pf)
789                 *pf = out_flags;
790         return len;
791 }