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