Serge Ivanov
[wine/multimedia.git] / dlls / ntdll / rtlstr.c
blob10499ec54ef6c9493119f5da6c9ce755f6f4430c
1 /*
2 * Rtl string functions
4 * Copyright 1996-1998 Marcus Meissner
5 */
7 #include "config.h"
9 #include <stdlib.h>
10 #include <string.h>
11 #include <ctype.h>
12 #ifdef HAVE_WCTYPE_H
13 # include <wctype.h>
14 #endif
15 #include "wine/winestring.h"
16 #include "crtdll.h"
17 #include "heap.h"
18 #include "winnls.h"
19 #include "debugtools.h"
20 #include "ntdll_misc.h"
21 #include "ntddk.h"
23 DEFAULT_DEBUG_CHANNEL(ntdll)
25 /* STRING FUNCTIONS */
27 /**************************************************************************
28 * RtlInitString
30 VOID WINAPI RtlInitString(PSTRING target,LPCSTR source)
32 TRACE("%p %p(%s)\n", target, source, debugstr_a(source));
34 target->Buffer = (LPSTR)source;
35 if (source)
37 target->Length = lstrlenA(source);
38 target->MaximumLength = target->Length+1;
40 else
42 target->Length = target->MaximumLength = 0;
48 /* ANSI FUNCTIONS */
50 /**************************************************************************
51 * RtlInitAnsiString
53 VOID WINAPI RtlInitAnsiString(
54 PANSI_STRING target,
55 LPCSTR source)
57 TRACE("%p %p(%s)\n", target, source, debugstr_a(source));
59 target->Buffer = (LPSTR)source;
60 if (source)
62 target->Length = lstrlenA(source);
63 target->MaximumLength = target->Length+1;
65 else
67 target->Length = target->MaximumLength = 0;
71 /**************************************************************************
72 * RtlFreeAnsiString
74 VOID WINAPI RtlFreeAnsiString(
75 PANSI_STRING AnsiString)
77 TRACE("%p\n", AnsiString);
78 dump_AnsiString(AnsiString, TRUE);
80 if( AnsiString->Buffer )
81 HeapFree( GetProcessHeap(),0,AnsiString->Buffer );
86 /* UNICODE FUNCTIONS */
88 /**************************************************************************
89 * RtlInitUnicodeString [NTDLL.403]
91 VOID WINAPI RtlInitUnicodeString(
92 PUNICODE_STRING target,
93 LPCWSTR source)
95 TRACE("%p %p(%s)\n", target, source, debugstr_w(source));
97 target->Buffer = (LPWSTR)source;
98 if (source)
100 target->Length = lstrlenW(source)*2;
101 target->MaximumLength = target->Length + 2;
103 else
105 target->Length = target->MaximumLength = 0;
109 /**************************************************************************
110 * RtlFreeUnicodeString [NTDLL.377]
112 VOID WINAPI RtlFreeUnicodeString(
113 PUNICODE_STRING UnicodeString)
115 TRACE("%p\n", UnicodeString);
116 dump_UnicodeString(UnicodeString, TRUE);
118 if (UnicodeString->Buffer)
119 HeapFree(GetProcessHeap(),0,UnicodeString->Buffer);
123 COMPARE FUNCTIONS
126 /**************************************************************************
127 * RtlEqualUnicodeString
129 BOOLEAN WINAPI RtlEqualUnicodeString(
130 IN PUNICODE_STRING s1,
131 IN PUNICODE_STRING s2,
132 IN BOOLEAN CaseInsensitive)
134 BOOLEAN ret;
135 TRACE("(%p,%p,%x)\n",s1,s2,CaseInsensitive);
136 dump_UnicodeString(s1, TRUE);
137 dump_UnicodeString(s2, TRUE);
139 if(!s1 || !s2 || !s1->Buffer || !s2->Buffer) return FALSE;
140 if (s1->Length != s2->Length) return FALSE;
142 if (CaseInsensitive)
143 ret = !CRTDLL__wcsnicmp(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
144 else
145 ret = !CRTDLL_wcsncmp(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
146 return ret;
149 /******************************************************************************
150 * RtlCompareUnicodeString
152 LONG WINAPI RtlCompareUnicodeString(
153 PUNICODE_STRING s1,
154 PUNICODE_STRING s2,
155 BOOLEAN CaseInsensitive)
157 LONG ret;
159 TRACE("(%p,%p,%x)\n",s1,s2,CaseInsensitive);
160 dump_UnicodeString(s1, TRUE);
161 dump_UnicodeString(s2, TRUE);
163 if(!s1 || !s2 || !s1->Buffer || !s2->Buffer) return FALSE;
165 if (s1->Length != s2->Length) return (s1->Length - s2->Length);
167 if (CaseInsensitive)
168 ret = CRTDLL__wcsnicmp(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
169 else
170 ret = CRTDLL_wcsncmp(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
171 return ret;
175 COPY BETWEEN ANSI_STRING or UNICODE_STRING
176 there is no parameter checking, it just crashes
179 /**************************************************************************
180 * RtlAnsiStringToUnicodeString
182 * NOTES:
183 * writes terminating 0
185 NTSTATUS
186 WINAPI RtlAnsiStringToUnicodeString(
187 PUNICODE_STRING uni,
188 PANSI_STRING ansi,
189 BOOLEAN doalloc)
191 int len = ansi->Length * sizeof(WCHAR);
193 TRACE("%p %p %u\n",uni, ansi, doalloc);
194 dump_AnsiString(ansi, TRUE);
195 dump_UnicodeString(uni, FALSE);
197 if (len>0xfffe) return STATUS_INVALID_PARAMETER_2;
198 uni->Length = len;
199 if (doalloc)
201 uni->MaximumLength = len + sizeof(WCHAR);
202 uni->Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,uni->MaximumLength);
203 if (!uni->Buffer) return STATUS_NO_MEMORY;
205 else if (len+sizeof(WCHAR) > uni->MaximumLength)
207 return STATUS_BUFFER_OVERFLOW;
209 lstrcpynAtoW(uni->Buffer,ansi->Buffer,ansi->Length+1);
210 return STATUS_SUCCESS;
213 /**************************************************************************
214 * RtlUpcaseUnicodeString
216 * NOTES:
217 * destination string is never 0-terminated because dest can be equal to src
218 * and src might be not 0-terminated
219 * dest.Length only set when success
221 DWORD WINAPI RtlUpcaseUnicodeString(
222 PUNICODE_STRING dest,
223 PUNICODE_STRING src,
224 BOOLEAN doalloc)
226 int i, len = src->Length;
228 TRACE("(%p,%p,%x)\n",dest, src, doalloc);
229 dump_UnicodeString(dest, FALSE);
230 dump_UnicodeString(src, TRUE);
232 if (doalloc)
234 dest->Buffer = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
235 if (!dest->Buffer) return STATUS_NO_MEMORY;
236 dest->MaximumLength = len;
238 else if (len > dest->MaximumLength)
240 return STATUS_BUFFER_OVERFLOW;
243 for (i=0; i < len/sizeof(WCHAR); i++)
245 dest->Buffer[i] = towupper(src->Buffer[i]);
247 dest->Length = len;
248 return STATUS_SUCCESS;
251 /**************************************************************************
252 * RtlOemStringToUnicodeString
254 * NOTES
255 * writes terminating 0
256 * buffer must be bigger than (ansi->Length+1)*2
257 * if astr.Length > 0x7ffe it returns STATUS_INVALID_PARAMETER_2
259 * FIXME
260 * OEM to unicode
262 NTSTATUS
263 WINAPI RtlOemStringToUnicodeString(
264 PUNICODE_STRING uni,
265 PSTRING ansi,
266 BOOLEAN doalloc)
268 int len = ansi->Length * sizeof(WCHAR);
270 if (len > 0xfffe) return STATUS_INVALID_PARAMETER_2;
272 uni->Length = len;
273 if (doalloc)
275 uni->Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, len + sizeof(WCHAR));
276 if (!uni->Buffer) return STATUS_NO_MEMORY;
277 uni->MaximumLength = len + sizeof(WCHAR);
279 else if (len+1 > uni->MaximumLength )
281 return STATUS_BUFFER_OVERFLOW;
283 lstrcpynAtoW(uni->Buffer,ansi->Buffer,ansi->Length+1);
284 return STATUS_SUCCESS;
287 /**************************************************************************
288 * RtlUnicodeStringToOemString
290 * NOTES
291 * allocates uni->Length+1
292 * writes terminating 0
294 NTSTATUS
295 WINAPI RtlUnicodeStringToOemString(
296 PANSI_STRING oem,
297 PUNICODE_STRING uni,
298 BOOLEAN doalloc)
300 int len = uni->Length/sizeof(WCHAR);
302 TRACE("%p %s %i\n", oem, debugstr_us(uni), doalloc);
304 oem->Length = len;
305 if (doalloc)
307 oem->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len+1);
308 if (! oem->Buffer) return STATUS_NO_MEMORY;
309 oem->MaximumLength = len + 1;
311 else if (oem->MaximumLength <= len)
313 return STATUS_BUFFER_OVERFLOW;
315 lstrcpynWtoA(oem->Buffer, uni->Buffer, len+1);
316 return STATUS_SUCCESS;
319 /**************************************************************************
320 * RtlUpcaseUnicodeStringToOemString
322 * NOTES
323 * writes terminating 0
325 NTSTATUS
326 WINAPI RtlUpcaseUnicodeStringToOemString(
327 PANSI_STRING oem,
328 PUNICODE_STRING uni,
329 BOOLEAN doalloc)
331 int i, len = uni->Length/sizeof(WCHAR);
333 TRACE("%p %s %i\n", oem, debugstr_us(uni), doalloc);
335 oem->Length = len;
336 if (doalloc)
338 oem->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len+1);
339 if (! oem->Buffer) return STATUS_NO_MEMORY;
340 oem->MaximumLength = len + 1;
342 else if (oem->MaximumLength <= len)
344 return STATUS_BUFFER_OVERFLOW;
347 for (i=0; i < len; i++)
349 oem->Buffer[i] = towupper((char)(uni->Buffer[i]));
351 oem->Buffer[i] = 0;
352 return STATUS_SUCCESS;
355 /**************************************************************************
356 * RtlUnicodeStringToAnsiString
358 * NOTES
359 * writes terminating 0
360 * copys a part if the buffer is to small
362 NTSTATUS
363 WINAPI RtlUnicodeStringToAnsiString(
364 PANSI_STRING ansi,
365 PUNICODE_STRING uni,
366 BOOLEAN doalloc)
368 int len = uni->Length/sizeof(WCHAR);
369 NTSTATUS ret = STATUS_SUCCESS;
371 TRACE("%p %s %i\n", ansi, debugstr_us(uni), doalloc);
373 ansi->Length = len;
374 if (doalloc)
376 ansi->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len+1);
377 if (! ansi->Buffer) return STATUS_NO_MEMORY;
378 ansi->MaximumLength = len + 1;
380 else if (ansi->MaximumLength <= len)
382 ansi->Length = ansi->MaximumLength - 1;
383 ret = STATUS_BUFFER_OVERFLOW;
385 lstrcpynWtoA(ansi->Buffer, uni->Buffer, ansi->Length+1);
386 return ret;
390 COPY BETWEEN ANSI/UNICODE_STRING AND MULTIBYTE STRINGS
392 /**************************************************************************
393 * RtlMultiByteToUnicodeN
395 * NOTES
396 * dest can be equal to src
397 * if unistr is to small a part is copyed
399 * FIXME
400 * multibyte support
402 NTSTATUS
403 WINAPI RtlMultiByteToUnicodeN(
404 LPWSTR unistr,
405 DWORD unilen,
406 LPDWORD reslen,
407 LPSTR oemstr,
408 DWORD oemlen)
410 UINT len;
411 int i;
413 TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
415 len = (unilen/sizeof(WCHAR) < oemlen) ? unilen/sizeof(WCHAR) : oemlen;
417 for (i = len-1; i>=0; i--)
418 unistr[i] = (WCHAR)oemstr[i];
420 if (reslen) *reslen = len * 2;
421 return 0;
424 /**************************************************************************
425 * RtlOemToUnicodeN
427 NTSTATUS
428 WINAPI RtlOemToUnicodeN(
429 LPWSTR unistr,
430 DWORD unilen,
431 LPDWORD reslen,
432 LPSTR oemstr,
433 DWORD oemlen)
435 UINT len;
436 int i;
438 TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
440 len = (unilen/sizeof(WCHAR) < oemlen) ? unilen/sizeof(WCHAR) : oemlen;
442 for (i = len-1; i>=0; i--)
443 unistr[i] = (WCHAR)oemstr[i];
445 if (reslen) *reslen = len * 2;
446 return 0;
450 /**************************************************************************
451 * RtlUnicodeToOemN
453 NTSTATUS
454 WINAPI RtlUnicodeToOemN(
455 LPSTR oemstr,
456 DWORD oemlen,
457 LPDWORD reslen,
458 LPWSTR unistr,
459 DWORD unilen)
461 UINT len;
462 int i;
464 TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
466 len = (oemlen < unilen/sizeof(WCHAR)) ? unilen/sizeof(WCHAR) : oemlen;
468 for (i = len-1; i>=0; i--)
469 oemstr[i] = (CHAR)unistr[i];
471 if (reslen) *reslen = len * 2;
472 return 0;
475 /**************************************************************************
476 * RtlUpcaseUnicodeToOemN
478 NTSTATUS
479 WINAPI RtlUpcaseUnicodeToOemN(
480 LPSTR oemstr,
481 DWORD oemlen,
482 LPDWORD reslen,
483 LPWSTR unistr,
484 DWORD unilen)
486 UINT len;
487 int i;
489 TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
491 len = (oemlen < unilen/sizeof(WCHAR)) ? unilen/sizeof(WCHAR) : oemlen;
493 for (i = len-1; i>=0; i--)
494 oemstr[i] = toupper((CHAR)unistr[i]);
496 if (reslen) *reslen = len * 2;
497 return 0;
500 /**************************************************************************
501 * RtlUnicodeToMultiByteN
503 NTSTATUS WINAPI RtlUnicodeToMultiByteN(
504 PCHAR MbString,
505 ULONG MbSize,
506 PULONG ResultSize,
507 PWCHAR UnicodeString,
508 ULONG UnicodeSize)
510 int Size = 0, i;
512 TRACE("(%p,%lu,%p,%p(%s),%lu)\n",
513 MbString, MbSize, ResultSize, UnicodeString, debugstr_w(UnicodeString), UnicodeSize);
515 Size = (UnicodeSize > (MbSize*sizeof(WCHAR))) ? MbSize: UnicodeSize/sizeof(WCHAR);
517 if (ResultSize != NULL) *ResultSize = Size;
519 for(i = 0; i < Size; i++)
521 *(MbString++) = *(UnicodeString++);
523 return STATUS_SUCCESS;
527 STRING SIZE
529 Rtlx* supports multibyte
532 /**************************************************************************
533 * RtlxOemStringToUnicodeSize
535 UINT WINAPI RtlxOemStringToUnicodeSize(PSTRING str)
537 return str->Length*2+2;
540 /**************************************************************************
541 * RtlxAnsiStringToUnicodeSize
543 UINT WINAPI RtlxAnsiStringToUnicodeSize(PANSI_STRING str)
545 return str->Length*2+2;
548 /**************************************************************************
549 * RtlxUnicodeStringToOemSize
552 UINT WINAPI RtlxUnicodeStringToOemSize(PUNICODE_STRING str)
554 return str->Length+1;
558 MISC
561 /**************************************************************************
562 * RtlIsTextUnicode
564 * Apply various feeble heuristics to guess whether
565 * the text buffer contains Unicode.
566 * FIXME: should implement more tests.
568 DWORD WINAPI RtlIsTextUnicode(
569 LPVOID buf,
570 DWORD len,
571 DWORD *pf)
573 LPWSTR s = buf;
574 DWORD flags = -1, out_flags = 0;
576 if (!len)
577 goto out;
578 if (pf)
579 flags = *pf;
581 * Apply various tests to the text string. According to the
582 * docs, each test "passed" sets the corresponding flag in
583 * the output flags. But some of the tests are mutually
584 * exclusive, so I don't see how you could pass all tests ...
587 /* Check for an odd length ... pass if even. */
588 if (!(len & 1))
589 out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
591 /* Check for the special unicode marker byte. */
592 if (*s == 0xFEFF)
593 out_flags |= IS_TEXT_UNICODE_SIGNATURE;
596 * Check whether the string passed all of the tests.
598 flags &= ITU_IMPLEMENTED_TESTS;
599 if ((out_flags & flags) != flags)
600 len = 0;
601 out:
602 if (pf)
603 *pf = out_flags;
604 return len;
607 /**************************************************************************
608 * RtlPrefixUnicodeString
610 NTSTATUS WINAPI RtlPrefixUnicodeString(
611 PUNICODE_STRING a,
612 PUNICODE_STRING b,
613 DWORD x)
615 TRACE("(%s,%s,%lx)\n",debugstr_us(a),debugstr_us(b),x);
616 return STATUS_SUCCESS;