source: trunk/src/NTDLL/rtlstr.c@ 9684

Last change on this file since 9684 was 9684, checked in by sandervl, 23 years ago

PF: Changes for building dll with GCC

File size: 26.1 KB
Line 
1/*
2 * Rtl string functions
3 *
4 * Copyright (C) 1996-1998 Marcus Meissner
5 * Copyright (C) 2000 Alexandre Julliard
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include "config.h"
23
24#include <assert.h>
25#include <stdlib.h>
26#include <string.h>
27#include <ctype.h>
28
29#include "ntddk.h"
30#include "wine/unicode.h"
31#include "wine/debug.h"
32
33WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
34
35#ifdef __WIN32OS2__
36#define RtlAllocateHeap HeapAlloc
37#define RtlFreeHeap HeapFree
38#ifdef __EMX__
39 #define min(a,b) (((a) < (b)) ? (a) : (b))
40 #define max(a,b) (((a) > (b)) ? (a) : (b))
41#endif
42#endif
43
44
45UINT NlsAnsiCodePage = 1252;
46BYTE NlsMbCodePageTag = 0;
47BYTE NlsMbOemCodePageTag = 0;
48
49static const union cptable *ansi_table;
50static const union cptable *oem_table;
51
52inline static const union cptable *get_ansi_table(void)
53{
54 if (!ansi_table) ansi_table = cp_get_table( 1252 );
55 return ansi_table;
56}
57
58inline static const union cptable *get_oem_table(void)
59{
60 if (!oem_table) oem_table = cp_get_table( 437 );
61 return oem_table;
62}
63
64
65/**************************************************************************
66 * __wine_init_codepages (NTDLL.@)
67 *
68 * Set the code page once kernel32 is loaded. Should be done differently.
69 */
70void __wine_init_codepages( const union cptable *ansi, const union cptable *oem )
71{
72 ansi_table = ansi;
73 oem_table = oem;
74 NlsAnsiCodePage = ansi->info.codepage;
75}
76
77
78/**************************************************************************
79 * RtlInitAnsiString (NTDLL.@)
80 */
81void WINAPI RtlInitAnsiString( PSTRING target, LPCSTR source)
82{
83 if ((target->Buffer = (LPSTR)source))
84 {
85 target->Length = strlen(source);
86 target->MaximumLength = target->Length + 1;
87 }
88 else target->Length = target->MaximumLength = 0;
89}
90
91
92/**************************************************************************
93 * RtlInitString (NTDLL.@)
94 */
95void WINAPI RtlInitString( PSTRING target, LPCSTR source )
96{
97 return RtlInitAnsiString( target, source );
98}
99
100
101/**************************************************************************
102 * RtlFreeAnsiString (NTDLL.@)
103 */
104void WINAPI RtlFreeAnsiString( PSTRING str )
105{
106 if (str->Buffer) RtlFreeHeap( GetProcessHeap(), 0, str->Buffer );
107}
108
109
110/**************************************************************************
111 * RtlFreeOemString (NTDLL.@)
112 */
113void WINAPI RtlFreeOemString( PSTRING str )
114{
115 RtlFreeAnsiString( str );
116}
117
118
119/**************************************************************************
120 * RtlCopyString (NTDLL.@)
121 */
122void WINAPI RtlCopyString( STRING *dst, const STRING *src )
123{
124 if (src)
125 {
126 unsigned int len = min( src->Length, dst->MaximumLength );
127 memcpy( dst->Buffer, src->Buffer, len );
128 dst->Length = len;
129 }
130 else dst->Length = 0;
131}
132
133
134/**************************************************************************
135 * RtlInitUnicodeString (NTDLL.@)
136 */
137void WINAPI RtlInitUnicodeString( PUNICODE_STRING target, LPCWSTR source )
138{
139 if ((target->Buffer = (LPWSTR)source))
140 {
141 target->Length = strlenW(source) * sizeof(WCHAR);
142 target->MaximumLength = target->Length + sizeof(WCHAR);
143 }
144 else target->Length = target->MaximumLength = 0;
145}
146
147
148/**************************************************************************
149 * RtlCreateUnicodeString (NTDLL.@)
150 */
151BOOLEAN WINAPI RtlCreateUnicodeString( PUNICODE_STRING target, LPCWSTR src )
152{
153 int len = (strlenW(src) + 1) * sizeof(WCHAR);
154 if (!(target->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return FALSE;
155 memcpy( target->Buffer, src, len );
156 target->MaximumLength = len;
157 target->Length = len - 2;
158 return TRUE;
159}
160
161
162/**************************************************************************
163 * RtlCreateUnicodeStringFromAsciiz (NTDLL.@)
164 */
165BOOLEAN WINAPI RtlCreateUnicodeStringFromAsciiz( PUNICODE_STRING target, LPCSTR src )
166{
167 STRING ansi;
168 RtlInitAnsiString( &ansi, src );
169 return !RtlAnsiStringToUnicodeString( target, &ansi, TRUE );
170}
171
172
173/**************************************************************************
174 * RtlFreeUnicodeString (NTDLL.@)
175 */
176void WINAPI RtlFreeUnicodeString( PUNICODE_STRING str )
177{
178 if (str->Buffer) RtlFreeHeap( GetProcessHeap(), 0, str->Buffer );
179}
180
181
182/**************************************************************************
183 * RtlCopyUnicodeString (NTDLL.@)
184 */
185void WINAPI RtlCopyUnicodeString( UNICODE_STRING *dst, const UNICODE_STRING *src )
186{
187 if (src)
188 {
189 unsigned int len = min( src->Length, dst->MaximumLength );
190 memcpy( dst->Buffer, src->Buffer, len );
191 dst->Length = len;
192 /* append terminating NULL if enough space */
193 if (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0;
194 }
195 else dst->Length = 0;
196}
197
198
199/**************************************************************************
200 * RtlEraseUnicodeString (NTDLL.@)
201 */
202void WINAPI RtlEraseUnicodeString( UNICODE_STRING *str )
203{
204 if (str->Buffer)
205 {
206 memset( str->Buffer, 0, str->MaximumLength );
207 str->Length = 0;
208 }
209}
210
211/*
212 COMPARISON FUNCTIONS
213*/
214
215/******************************************************************************
216 * RtlCompareString (NTDLL.@)
217 */
218LONG WINAPI RtlCompareString( const STRING *s1, const STRING *s2, BOOLEAN CaseInsensitive )
219{
220 unsigned int len;
221 LONG ret = 0;
222 LPCSTR p1, p2;
223
224 len = min(s1->Length, s2->Length);
225 p1 = s1->Buffer;
226 p2 = s2->Buffer;
227
228 if (CaseInsensitive)
229 {
230 while (!ret && len--) ret = toupper(*p1++) - toupper(*p2++);
231 }
232 else
233 {
234 while (!ret && len--) ret = *p1++ - *p2++;
235 }
236 if (!ret) ret = s1->Length - s2->Length;
237 return ret;
238}
239
240
241/******************************************************************************
242 * RtlCompareUnicodeString (NTDLL.@)
243 */
244LONG WINAPI RtlCompareUnicodeString( const UNICODE_STRING *s1, const UNICODE_STRING *s2,
245 BOOLEAN CaseInsensitive )
246{
247 unsigned int len;
248 LONG ret = 0;
249 LPCWSTR p1, p2;
250
251 len = min(s1->Length, s2->Length) / sizeof(WCHAR);
252 p1 = s1->Buffer;
253 p2 = s2->Buffer;
254
255 if (CaseInsensitive)
256 {
257 while (!ret && len--) ret = toupperW(*p1++) - toupperW(*p2++);
258 }
259 else
260 {
261 while (!ret && len--) ret = *p1++ - *p2++;
262 }
263 if (!ret) ret = s1->Length - s2->Length;
264 return ret;
265}
266
267
268/**************************************************************************
269 * RtlEqualString (NTDLL.@)
270 */
271BOOLEAN WINAPI RtlEqualString( const STRING *s1, const STRING *s2, BOOLEAN CaseInsensitive )
272{
273 if (s1->Length != s2->Length) return FALSE;
274 return !RtlCompareString( s1, s2, CaseInsensitive );
275}
276
277
278/**************************************************************************
279 * RtlEqualUnicodeString (NTDLL.@)
280 */
281BOOLEAN WINAPI RtlEqualUnicodeString( const UNICODE_STRING *s1, const UNICODE_STRING *s2,
282 BOOLEAN CaseInsensitive )
283{
284 if (s1->Length != s2->Length) return FALSE;
285 return !RtlCompareUnicodeString( s1, s2, CaseInsensitive );
286}
287
288
289/**************************************************************************
290 * RtlPrefixString (NTDLL.@)
291 *
292 * Test if s1 is a prefix in s2
293 */
294BOOLEAN WINAPI RtlPrefixString( const STRING *s1, const STRING *s2, BOOLEAN ignore_case )
295{
296 unsigned int i;
297
298 if (s1->Length > s2->Length) return FALSE;
299 if (ignore_case)
300 {
301 for (i = 0; i < s1->Length; i++)
302 if (toupper(s1->Buffer[i]) != toupper(s2->Buffer[i])) return FALSE;
303 }
304 else
305 {
306 for (i = 0; i < s1->Length; i++)
307 if (s1->Buffer[i] != s2->Buffer[i]) return FALSE;
308 }
309 return TRUE;
310}
311
312
313/**************************************************************************
314 * RtlPrefixUnicodeString (NTDLL.@)
315 *
316 * Test if s1 is a prefix in s2
317 */
318BOOLEAN WINAPI RtlPrefixUnicodeString( const UNICODE_STRING *s1,
319 const UNICODE_STRING *s2,
320 BOOLEAN ignore_case )
321{
322 unsigned int i;
323
324 if (s1->Length > s2->Length) return FALSE;
325 if (ignore_case)
326 {
327 for (i = 0; i < s1->Length / sizeof(WCHAR); i++)
328 if (toupper(s1->Buffer[i]) != toupper(s2->Buffer[i])) return FALSE;
329 }
330 else
331 {
332 for (i = 0; i < s1->Length / sizeof(WCHAR); i++)
333 if (s1->Buffer[i] != s2->Buffer[i]) return FALSE;
334 }
335 return TRUE;
336}
337
338
339/*
340 COPY BETWEEN ANSI_STRING or UNICODE_STRING
341 there is no parameter checking, it just crashes
342*/
343
344
345/**************************************************************************
346 * RtlAnsiStringToUnicodeString (NTDLL.@)
347 *
348 * NOTES:
349 * writes terminating 0
350 */
351NTSTATUS WINAPI RtlAnsiStringToUnicodeString( UNICODE_STRING *uni,
352 const STRING *ansi,
353 BOOLEAN doalloc )
354{
355 DWORD total = RtlAnsiStringToUnicodeSize( ansi );
356
357 if (total > 0xffff) return STATUS_INVALID_PARAMETER_2;
358 uni->Length = total - sizeof(WCHAR);
359 if (doalloc)
360 {
361 uni->MaximumLength = total;
362 if (!(uni->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, total ))) return STATUS_NO_MEMORY;
363 }
364 else if (total > uni->MaximumLength) return STATUS_BUFFER_OVERFLOW;
365
366 RtlMultiByteToUnicodeN( uni->Buffer, uni->Length, NULL, ansi->Buffer, ansi->Length );
367 uni->Buffer[uni->Length / sizeof(WCHAR)] = 0;
368 return STATUS_SUCCESS;
369}
370
371
372/**************************************************************************
373 * RtlOemStringToUnicodeString (NTDLL.@)
374 *
375 * NOTES
376 * writes terminating 0
377 * if resulting length > 0xffff it returns STATUS_INVALID_PARAMETER_2
378 */
379NTSTATUS WINAPI RtlOemStringToUnicodeString( UNICODE_STRING *uni,
380 const STRING *oem,
381 BOOLEAN doalloc )
382{
383 DWORD total = RtlOemStringToUnicodeSize( oem );
384
385 if (total > 0xffff) return STATUS_INVALID_PARAMETER_2;
386 uni->Length = total - sizeof(WCHAR);
387 if (doalloc)
388 {
389 uni->MaximumLength = total;
390 if (!(uni->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, total ))) return STATUS_NO_MEMORY;
391 }
392 else if (total > uni->MaximumLength) return STATUS_BUFFER_OVERFLOW;
393
394 RtlOemToUnicodeN( uni->Buffer, uni->Length, NULL, oem->Buffer, oem->Length );
395 uni->Buffer[uni->Length / sizeof(WCHAR)] = 0;
396 return STATUS_SUCCESS;
397}
398
399
400/**************************************************************************
401 * RtlUnicodeStringToAnsiString (NTDLL.@)
402 *
403 * NOTES
404 * writes terminating 0
405 * copies a part if the buffer is too small
406 */
407NTSTATUS WINAPI RtlUnicodeStringToAnsiString( STRING *ansi,
408 const UNICODE_STRING *uni,
409 BOOLEAN doalloc )
410{
411 NTSTATUS ret = STATUS_SUCCESS;
412 DWORD len = RtlUnicodeStringToAnsiSize( uni );
413
414 ansi->Length = len - 1;
415 if (doalloc)
416 {
417 ansi->MaximumLength = len;
418 if (!(ansi->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY;
419 }
420 else if (ansi->MaximumLength < len)
421 {
422 if (!ansi->MaximumLength) return STATUS_BUFFER_OVERFLOW;
423 ansi->Length = ansi->MaximumLength - 1;
424 ret = STATUS_BUFFER_OVERFLOW;
425 }
426
427 RtlUnicodeToMultiByteN( ansi->Buffer, ansi->Length, NULL, uni->Buffer, uni->Length );
428 ansi->Buffer[ansi->Length] = 0;
429 return ret;
430}
431
432
433/**************************************************************************
434 * RtlUnicodeStringToOemString (NTDLL.@)
435 *
436 * NOTES
437 * allocates uni->Length+1
438 * writes terminating 0
439 */
440NTSTATUS WINAPI RtlUnicodeStringToOemString( STRING *oem,
441 const UNICODE_STRING *uni,
442 BOOLEAN doalloc )
443{
444 NTSTATUS ret = STATUS_SUCCESS;
445 DWORD len = RtlUnicodeStringToOemSize( uni );
446
447 oem->Length = len - 1;
448 if (doalloc)
449 {
450 oem->MaximumLength = len;
451 if (!(oem->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY;
452 }
453 else if (oem->MaximumLength < len)
454 {
455 if (!oem->MaximumLength) return STATUS_BUFFER_OVERFLOW;
456 oem->Length = oem->MaximumLength - 1;
457 ret = STATUS_BUFFER_OVERFLOW;
458 }
459
460 RtlUnicodeToOemN( oem->Buffer, oem->Length, NULL, uni->Buffer, uni->Length );
461 oem->Buffer[oem->Length] = 0;
462 return ret;
463}
464
465
466/**************************************************************************
467 * RtlMultiByteToUnicodeN (NTDLL.@)
468 *
469 * NOTES
470 * if unistr is too small a part is copied
471 */
472NTSTATUS WINAPI RtlMultiByteToUnicodeN( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
473 LPCSTR src, DWORD srclen )
474{
475
476 int ret = cp_mbstowcs( get_ansi_table(), 0, src, srclen, dst, dstlen/sizeof(WCHAR) );
477 if (reslen)
478 *reslen = (ret >= 0) ? ret*sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
479 return STATUS_SUCCESS;
480}
481
482
483/**************************************************************************
484 * RtlOemToUnicodeN (NTDLL.@)
485 */
486NTSTATUS WINAPI RtlOemToUnicodeN( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
487 LPCSTR src, DWORD srclen )
488{
489 int ret = cp_mbstowcs( get_oem_table(), 0, src, srclen, dst, dstlen/sizeof(WCHAR) );
490 if (reslen)
491 *reslen = (ret >= 0) ? ret*sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
492 return STATUS_SUCCESS;
493}
494
495
496/**************************************************************************
497 * RtlUnicodeToMultiByteN (NTDLL.@)
498 */
499NTSTATUS WINAPI RtlUnicodeToMultiByteN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
500 LPCWSTR src, DWORD srclen )
501{
502 int ret = cp_wcstombs( get_ansi_table(), 0, src, srclen / sizeof(WCHAR),
503 dst, dstlen, NULL, NULL );
504 if (reslen)
505 *reslen = (ret >= 0) ? ret : dstlen; /* overflow -> we filled up to dstlen */
506 return STATUS_SUCCESS;
507}
508
509
510/**************************************************************************
511 * RtlUnicodeToOemN (NTDLL.@)
512 */
513NTSTATUS WINAPI RtlUnicodeToOemN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
514 LPCWSTR src, DWORD srclen )
515{
516 int ret = cp_wcstombs( get_oem_table(), 0, src, srclen / sizeof(WCHAR),
517 dst, dstlen, NULL, NULL );
518 if (reslen)
519 *reslen = (ret >= 0) ? ret : dstlen; /* overflow -> we filled up to dstlen */
520 return STATUS_SUCCESS;
521}
522
523
524/*
525 CASE CONVERSIONS
526*/
527
528/**************************************************************************
529 * RtlUpperString (NTDLL.@)
530 */
531void WINAPI RtlUpperString( STRING *dst, const STRING *src )
532{
533 unsigned int i, len = min(src->Length, dst->MaximumLength);
534
535 for (i = 0; i < len; i++) dst->Buffer[i] = toupper(src->Buffer[i]);
536 dst->Length = len;
537}
538
539
540/**************************************************************************
541 * RtlUpcaseUnicodeString (NTDLL.@)
542 *
543 * NOTES:
544 * destination string is never 0-terminated because dest can be equal to src
545 * and src might be not 0-terminated
546 * dest.Length only set when success
547 */
548NTSTATUS WINAPI RtlUpcaseUnicodeString( UNICODE_STRING *dest,
549 const UNICODE_STRING *src,
550 BOOLEAN doalloc )
551{
552 DWORD i, len = src->Length;
553
554 if (doalloc)
555 {
556 dest->MaximumLength = len;
557 if (!(dest->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY;
558 }
559 else if (len > dest->MaximumLength) return STATUS_BUFFER_OVERFLOW;
560
561 for (i = 0; i < len/sizeof(WCHAR); i++) dest->Buffer[i] = toupperW(src->Buffer[i]);
562 dest->Length = len;
563 return STATUS_SUCCESS;
564}
565
566
567/**************************************************************************
568 * RtlUpcaseUnicodeStringToAnsiString (NTDLL.@)
569 *
570 * NOTES
571 * writes terminating 0
572 */
573NTSTATUS WINAPI RtlUpcaseUnicodeStringToAnsiString( STRING *dst,
574 const UNICODE_STRING *src,
575 BOOLEAN doalloc )
576{
577 NTSTATUS ret;
578 UNICODE_STRING upcase;
579
580 if (!(ret = RtlUpcaseUnicodeString( &upcase, src, TRUE )))
581 {
582 ret = RtlUnicodeStringToAnsiString( dst, &upcase, doalloc );
583 RtlFreeUnicodeString( &upcase );
584 }
585 return ret;
586}
587
588
589/**************************************************************************
590 * RtlUpcaseUnicodeStringToOemString (NTDLL.@)
591 *
592 * NOTES
593 * writes terminating 0
594 */
595NTSTATUS WINAPI RtlUpcaseUnicodeStringToOemString( STRING *dst,
596 const UNICODE_STRING *src,
597 BOOLEAN doalloc )
598{
599 NTSTATUS ret;
600 UNICODE_STRING upcase;
601
602 if (!(ret = RtlUpcaseUnicodeString( &upcase, src, TRUE )))
603 {
604 ret = RtlUnicodeStringToOemString( dst, &upcase, doalloc );
605 RtlFreeUnicodeString( &upcase );
606 }
607 return ret;
608}
609
610
611/**************************************************************************
612 * RtlUpcaseUnicodeToMultiByteN (NTDLL.@)
613 */
614NTSTATUS WINAPI RtlUpcaseUnicodeToMultiByteN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
615 LPCWSTR src, DWORD srclen )
616{
617 NTSTATUS ret;
618 LPWSTR upcase;
619 DWORD i;
620
621 if (!(upcase = RtlAllocateHeap( GetProcessHeap(), 0, srclen ))) return STATUS_NO_MEMORY;
622 for (i = 0; i < srclen/sizeof(WCHAR); i++) upcase[i] = toupperW(src[i]);
623 ret = RtlUnicodeToMultiByteN( dst, dstlen, reslen, upcase, srclen );
624 RtlFreeHeap( GetProcessHeap(), 0, upcase );
625 return ret;
626}
627
628
629/**************************************************************************
630 * RtlUpcaseUnicodeToOemN (NTDLL.@)
631 */
632NTSTATUS WINAPI RtlUpcaseUnicodeToOemN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
633 LPCWSTR src, DWORD srclen )
634{
635 NTSTATUS ret;
636 LPWSTR upcase;
637 DWORD i;
638
639 if (!(upcase = RtlAllocateHeap( GetProcessHeap(), 0, srclen ))) return STATUS_NO_MEMORY;
640 for (i = 0; i < srclen/sizeof(WCHAR); i++) upcase[i] = toupperW(src[i]);
641 ret = RtlUnicodeToOemN( dst, dstlen, reslen, upcase, srclen );
642 RtlFreeHeap( GetProcessHeap(), 0, upcase );
643 return ret;
644}
645
646
647/*
648 STRING SIZE
649*/
650
651/**************************************************************************
652 * RtlOemStringToUnicodeSize (NTDLL.@)
653 * RtlxOemStringToUnicodeSize (NTDLL.@)
654 *
655 * Return the size in bytes necessary for the Unicode conversion of 'str',
656 * including the terminating NULL.
657 */
658UINT WINAPI RtlOemStringToUnicodeSize( const STRING *str )
659{
660 int ret = cp_mbstowcs( get_oem_table(), 0, str->Buffer, str->Length, NULL, 0 );
661 return (ret + 1) * sizeof(WCHAR);
662}
663
664
665/**************************************************************************
666 * RtlAnsiStringToUnicodeSize (NTDLL.@)
667 * RtlxAnsiStringToUnicodeSize (NTDLL.@)
668 *
669 * Return the size in bytes necessary for the Unicode conversion of 'str',
670 * including the terminating NULL.
671 */
672DWORD WINAPI RtlAnsiStringToUnicodeSize( const STRING *str )
673{
674 DWORD ret;
675 RtlMultiByteToUnicodeSize( &ret, str->Buffer, str->Length );
676 return ret + sizeof(WCHAR);
677}
678
679
680/**************************************************************************
681 * RtlMultiByteToUnicodeSize (NTDLL.@)
682 *
683 * Compute the size in bytes necessary for the Unicode conversion of 'str',
684 * without the terminating NULL.
685 */
686NTSTATUS WINAPI RtlMultiByteToUnicodeSize( DWORD *size, LPCSTR str, UINT len )
687{
688 *size = cp_mbstowcs( get_ansi_table(), 0, str, len, NULL, 0 ) * sizeof(WCHAR);
689 return STATUS_SUCCESS;
690}
691
692
693/**************************************************************************
694 * RtlUnicodeToMultiByteSize (NTDLL.@)
695 *
696 * Compute the size necessary for the multibyte conversion of 'str',
697 * without the terminating NULL.
698 */
699NTSTATUS WINAPI RtlUnicodeToMultiByteSize( DWORD *size, LPCWSTR str, UINT len )
700{
701 *size = cp_wcstombs( get_ansi_table(), 0, str, len / sizeof(WCHAR), NULL, 0, NULL, NULL );
702 return STATUS_SUCCESS;
703}
704
705
706/**************************************************************************
707 * RtlUnicodeStringToAnsiSize (NTDLL.@)
708 * RtlxUnicodeStringToAnsiSize (NTDLL.@)
709 *
710 * Return the size in bytes necessary for the Ansi conversion of 'str',
711 * including the terminating NULL.
712 */
713DWORD WINAPI RtlUnicodeStringToAnsiSize( const UNICODE_STRING *str )
714{
715 DWORD ret;
716 RtlUnicodeToMultiByteSize( &ret, str->Buffer, str->Length );
717 return ret + 1;
718}
719
720
721/**************************************************************************
722 * RtlUnicodeStringToOemSize (NTDLL.@)
723 * RtlxUnicodeStringToOemSize (NTDLL.@)
724 *
725 * Return the size in bytes necessary for the OEM conversion of 'str',
726 * including the terminating NULL.
727 */
728DWORD WINAPI RtlUnicodeStringToOemSize( const UNICODE_STRING *str )
729{
730 return cp_wcstombs( get_oem_table(), 0, str->Buffer, str->Length / sizeof(WCHAR),
731 NULL, 0, NULL, NULL ) + 1;
732}
733
734
735/**************************************************************************
736 * RtlAppendStringToString (NTDLL.@)
737 */
738NTSTATUS WINAPI RtlAppendStringToString( STRING *dst, const STRING *src )
739{
740 unsigned int len = src->Length + dst->Length;
741 if (len > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
742 memcpy( dst->Buffer + dst->Length, src->Buffer, src->Length );
743 dst->Length = len;
744 return STATUS_SUCCESS;
745}
746
747
748/**************************************************************************
749 * RtlAppendAsciizToString (NTDLL.@)
750 */
751NTSTATUS WINAPI RtlAppendAsciizToString( STRING *dst, LPCSTR src )
752{
753 if (src)
754 {
755 unsigned int srclen = strlen(src);
756 unsigned int total = srclen + dst->Length;
757 if (total > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
758 memcpy( dst->Buffer + dst->Length, src, srclen );
759 dst->Length = total;
760 }
761 return STATUS_SUCCESS;
762}
763
764
765/**************************************************************************
766 * RtlAppendUnicodeToString (NTDLL.@)
767 */
768NTSTATUS WINAPI RtlAppendUnicodeToString( UNICODE_STRING *dst, LPCWSTR src )
769{
770 if (src)
771 {
772 unsigned int srclen = strlenW(src) * sizeof(WCHAR);
773 unsigned int total = srclen + dst->Length;
774 if (total > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
775 memcpy( dst->Buffer + dst->Length/sizeof(WCHAR), src, srclen );
776 dst->Length = total;
777 /* append terminating NULL if enough space */
778 if (total < dst->MaximumLength) dst->Buffer[total / sizeof(WCHAR)] = 0;
779 }
780 return STATUS_SUCCESS;
781}
782
783
784/**************************************************************************
785 * RtlAppendUnicodeStringToString (NTDLL.@)
786 */
787NTSTATUS WINAPI RtlAppendUnicodeStringToString( UNICODE_STRING *dst, const UNICODE_STRING *src )
788{
789 unsigned int len = src->Length + dst->Length;
790 if (len > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
791 memcpy( dst->Buffer + dst->Length/sizeof(WCHAR), src->Buffer, src->Length );
792 dst->Length = len;
793 /* append terminating NULL if enough space */
794 if (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0;
795 return STATUS_SUCCESS;
796}
797
798
799/*
800 MISC
801*/
802
803/**************************************************************************
804 * RtlIsTextUnicode (NTDLL.@)
805 *
806 * Apply various feeble heuristics to guess whether
807 * the text buffer contains Unicode.
808 * FIXME: should implement more tests.
809 */
810DWORD WINAPI RtlIsTextUnicode(
811 LPVOID buf,
812 DWORD len,
813 DWORD *pf)
814{
815 LPWSTR s = buf;
816 DWORD flags = -1, out_flags = 0;
817
818 if (!len)
819 goto out;
820 if (pf)
821 flags = *pf;
822 /*
823 * Apply various tests to the text string. According to the
824 * docs, each test "passed" sets the corresponding flag in
825 * the output flags. But some of the tests are mutually
826 * exclusive, so I don't see how you could pass all tests ...
827 */
828
829 /* Check for an odd length ... pass if even. */
830 if (!(len & 1))
831 out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
832
833 /* Check for the special unicode marker byte. */
834 if (*s == 0xFEFF)
835 out_flags |= IS_TEXT_UNICODE_SIGNATURE;
836
837 /*
838 * Check whether the string passed all of the tests.
839 */
840 flags &= ITU_IMPLEMENTED_TESTS;
841 if ((out_flags & flags) != flags)
842 len = 0;
843out:
844 if (pf)
845 *pf = out_flags;
846 return len;
847}
848
849/**************************************************************************
850 * RtlUnicodeStringToInteger (NTDLL.@)
851 *
852 * Convert a text buffer into its integer form
853 */
854NTSTATUS WINAPI RtlUnicodeStringToInteger(
855 const UNICODE_STRING *str,
856 int base,
857 int * pdest)
858{
859 LPWSTR lpwstr = str->Buffer;
860 WCHAR wchCurrent = 0;
861 int CharsParsed = 0;
862 int RunningTotal = 0;
863 char bMinus = 0;
864
865 /* no checking done on UNICODE_STRING and int* in native DLL either */
866 TRACE("(%p, %d, %p)", str, base, pdest);
867
868 switch (base)
869 {
870 case 0:
871 base = 10;
872 break;
873 case 2:
874 case 8:
875 case 10:
876 case 16:
877 break;
878 default:
879 return STATUS_INVALID_PARAMETER;
880 }
881
882 if ((str->Length) >= 4 && (base == 10) && (*lpwstr == '0') && (*(lpwstr+1) == 'x'))
883 {
884 lpwstr+=2;
885 base = 16;
886 }
887
888 *pdest = 0;
889 for (; (CharsParsed*sizeof(WCHAR) < str->Length) && (*lpwstr <= ' '); lpwstr++)
890 CharsParsed++;
891
892 if (*lpwstr == '+')
893 lpwstr++;
894 else if (*lpwstr == '-')
895 {
896 bMinus = 1;
897 lpwstr++;
898 }
899
900 for (; (CharsParsed*sizeof(WCHAR) < str->Length) && (*lpwstr != '\0'); lpwstr++)
901 {
902 CharsParsed++;
903 wchCurrent = *lpwstr;
904 if (wchCurrent >= 'A')
905 wchCurrent = '0' + 10 + wchCurrent - 'A';
906 if ((wchCurrent - '0') >= base || wchCurrent < '0')
907 {
908 *pdest = bMinus ? -RunningTotal: RunningTotal;
909 return STATUS_SUCCESS;
910 }
911 /*
912 * increase significance of previous digits each time
913 * we find another valid one and add on this valid one
914 */
915 RunningTotal = wchCurrent - '0' + RunningTotal * base;
916 }
917
918 *pdest = bMinus ? -RunningTotal : RunningTotal;
919 return STATUS_SUCCESS;
920}
Note: See TracBrowser for help on using the repository browser.