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