Moved shared crtdll/ntdll functions into ntdll.
[wine.git] / dlls / ntdll / rtlstr.c
blob73d456cbbd6d2e7677ed9482505abf0357d44de0
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 #include "wine/winestring.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"
20 DEFAULT_DEBUG_CHANNEL(ntdll);
22 /* STRING FUNCTIONS */
24 /**************************************************************************
25 * RtlInitString
27 VOID WINAPI RtlInitString(PSTRING target,LPCSTR source)
29 TRACE("%p %p(%s)\n", target, source, debugstr_a(source));
31 target->Buffer = (LPSTR)source;
32 if (source)
34 target->Length = lstrlenA(source);
35 target->MaximumLength = target->Length+1;
37 else
39 target->Length = target->MaximumLength = 0;
45 /* ANSI FUNCTIONS */
47 /**************************************************************************
48 * RtlInitAnsiString
50 VOID WINAPI RtlInitAnsiString(
51 PANSI_STRING target,
52 LPCSTR source)
54 TRACE("%p %p(%s)\n", target, source, debugstr_a(source));
56 target->Buffer = (LPSTR)source;
57 if (source)
59 target->Length = lstrlenA(source);
60 target->MaximumLength = target->Length+1;
62 else
64 target->Length = target->MaximumLength = 0;
68 /**************************************************************************
69 * RtlFreeAnsiString
71 VOID WINAPI RtlFreeAnsiString(
72 PANSI_STRING AnsiString)
74 TRACE("%p\n", AnsiString);
75 dump_AnsiString(AnsiString, TRUE);
77 if( AnsiString->Buffer )
78 HeapFree( GetProcessHeap(),0,AnsiString->Buffer );
83 /* UNICODE FUNCTIONS */
85 /**************************************************************************
86 * RtlInitUnicodeString [NTDLL.403]
88 VOID WINAPI RtlInitUnicodeString(
89 PUNICODE_STRING target,
90 LPCWSTR source)
92 TRACE("%p %p(%s)\n", target, source, debugstr_w(source));
94 target->Buffer = (LPWSTR)source;
95 if (source)
97 target->Length = lstrlenW(source)*2;
98 target->MaximumLength = target->Length + 2;
100 else
102 target->Length = target->MaximumLength = 0;
106 /**************************************************************************
107 * RtlFreeUnicodeString [NTDLL.377]
109 VOID WINAPI RtlFreeUnicodeString(
110 PUNICODE_STRING UnicodeString)
112 TRACE("%p\n", UnicodeString);
113 dump_UnicodeString(UnicodeString, TRUE);
115 if (UnicodeString->Buffer)
116 HeapFree(GetProcessHeap(),0,UnicodeString->Buffer);
120 COMPARE FUNCTIONS
123 /**************************************************************************
124 * RtlEqualUnicodeString
126 BOOLEAN WINAPI RtlEqualUnicodeString(
127 IN PUNICODE_STRING s1,
128 IN PUNICODE_STRING s2,
129 IN BOOLEAN CaseInsensitive)
131 BOOLEAN ret;
132 TRACE("(%p,%p,%x)\n",s1,s2,CaseInsensitive);
133 dump_UnicodeString(s1, TRUE);
134 dump_UnicodeString(s2, TRUE);
136 if(!s1 || !s2 || !s1->Buffer || !s2->Buffer) return FALSE;
137 if (s1->Length != s2->Length) return FALSE;
139 if (CaseInsensitive)
140 ret = !strncmpiW(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
141 else
142 ret = !strncmpW(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
143 return ret;
146 /******************************************************************************
147 * RtlCompareUnicodeString
149 LONG WINAPI RtlCompareUnicodeString(
150 PUNICODE_STRING s1,
151 PUNICODE_STRING s2,
152 BOOLEAN CaseInsensitive)
154 LONG ret;
156 TRACE("(%p,%p,%x)\n",s1,s2,CaseInsensitive);
157 dump_UnicodeString(s1, TRUE);
158 dump_UnicodeString(s2, TRUE);
160 if(!s1 || !s2 || !s1->Buffer || !s2->Buffer) return FALSE;
162 if (s1->Length != s2->Length) return (s1->Length - s2->Length);
164 if (CaseInsensitive)
165 ret = strncmpiW(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
166 else
167 ret = strncmpW(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
168 return ret;
172 COPY BETWEEN ANSI_STRING or UNICODE_STRING
173 there is no parameter checking, it just crashes
176 /**************************************************************************
177 * RtlAnsiStringToUnicodeString
179 * NOTES:
180 * writes terminating 0
182 NTSTATUS
183 WINAPI RtlAnsiStringToUnicodeString(
184 PUNICODE_STRING uni,
185 PANSI_STRING ansi,
186 BOOLEAN doalloc)
188 int len = ansi->Length * sizeof(WCHAR);
190 TRACE("%p %p %u\n",uni, ansi, doalloc);
191 dump_AnsiString(ansi, TRUE);
192 dump_UnicodeString(uni, FALSE);
194 if (len>0xfffe) return STATUS_INVALID_PARAMETER_2;
195 uni->Length = len;
196 if (doalloc)
198 uni->MaximumLength = len + sizeof(WCHAR);
199 uni->Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,uni->MaximumLength);
200 if (!uni->Buffer) return STATUS_NO_MEMORY;
202 else if (len+sizeof(WCHAR) > uni->MaximumLength)
204 return STATUS_BUFFER_OVERFLOW;
206 lstrcpynAtoW(uni->Buffer,ansi->Buffer,ansi->Length+1);
207 return STATUS_SUCCESS;
210 /**************************************************************************
211 * RtlUpcaseUnicodeString
213 * NOTES:
214 * destination string is never 0-terminated because dest can be equal to src
215 * and src might be not 0-terminated
216 * dest.Length only set when success
218 DWORD WINAPI RtlUpcaseUnicodeString(
219 PUNICODE_STRING dest,
220 PUNICODE_STRING src,
221 BOOLEAN doalloc)
223 int i, len = src->Length;
225 TRACE("(%p,%p,%x)\n",dest, src, doalloc);
226 dump_UnicodeString(dest, FALSE);
227 dump_UnicodeString(src, TRUE);
229 if (doalloc)
231 dest->Buffer = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
232 if (!dest->Buffer) return STATUS_NO_MEMORY;
233 dest->MaximumLength = len;
235 else if (len > dest->MaximumLength)
237 return STATUS_BUFFER_OVERFLOW;
240 for (i=0; i < len/sizeof(WCHAR); i++)
242 dest->Buffer[i] = toupperW(src->Buffer[i]);
244 dest->Length = len;
245 return STATUS_SUCCESS;
248 /**************************************************************************
249 * RtlOemStringToUnicodeString
251 * NOTES
252 * writes terminating 0
253 * buffer must be bigger than (ansi->Length+1)*2
254 * if astr.Length > 0x7ffe it returns STATUS_INVALID_PARAMETER_2
256 * FIXME
257 * OEM to unicode
259 NTSTATUS
260 WINAPI RtlOemStringToUnicodeString(
261 PUNICODE_STRING uni,
262 PSTRING ansi,
263 BOOLEAN doalloc)
265 int len = ansi->Length * sizeof(WCHAR);
267 if (len > 0xfffe) return STATUS_INVALID_PARAMETER_2;
269 uni->Length = len;
270 if (doalloc)
272 uni->Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, len + sizeof(WCHAR));
273 if (!uni->Buffer) return STATUS_NO_MEMORY;
274 uni->MaximumLength = len + sizeof(WCHAR);
276 else if (len+1 > uni->MaximumLength )
278 return STATUS_BUFFER_OVERFLOW;
280 lstrcpynAtoW(uni->Buffer,ansi->Buffer,ansi->Length+1);
281 return STATUS_SUCCESS;
284 /**************************************************************************
285 * RtlUnicodeStringToOemString
287 * NOTES
288 * allocates uni->Length+1
289 * writes terminating 0
291 NTSTATUS
292 WINAPI RtlUnicodeStringToOemString(
293 PANSI_STRING oem,
294 PUNICODE_STRING uni,
295 BOOLEAN doalloc)
297 int len = uni->Length/sizeof(WCHAR);
299 TRACE("%p %s %i\n", oem, debugstr_us(uni), doalloc);
301 oem->Length = len;
302 if (doalloc)
304 oem->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len+1);
305 if (! oem->Buffer) return STATUS_NO_MEMORY;
306 oem->MaximumLength = len + 1;
308 else if (oem->MaximumLength <= len)
310 return STATUS_BUFFER_OVERFLOW;
312 lstrcpynWtoA(oem->Buffer, uni->Buffer, len+1);
313 return STATUS_SUCCESS;
316 /**************************************************************************
317 * RtlUpcaseUnicodeStringToOemString
319 * NOTES
320 * writes terminating 0
322 NTSTATUS
323 WINAPI RtlUpcaseUnicodeStringToOemString(
324 PANSI_STRING oem,
325 PUNICODE_STRING uni,
326 BOOLEAN doalloc)
328 int i, len = uni->Length/sizeof(WCHAR);
330 TRACE("%p %s %i\n", oem, debugstr_us(uni), doalloc);
332 oem->Length = len;
333 if (doalloc)
335 oem->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len+1);
336 if (! oem->Buffer) return STATUS_NO_MEMORY;
337 oem->MaximumLength = len + 1;
339 else if (oem->MaximumLength <= len)
341 return STATUS_BUFFER_OVERFLOW;
344 for (i=0; i < len; i++)
346 oem->Buffer[i] = toupperW((char)(uni->Buffer[i]));
348 oem->Buffer[i] = 0;
349 return STATUS_SUCCESS;
352 /**************************************************************************
353 * RtlUnicodeStringToAnsiString
355 * NOTES
356 * writes terminating 0
357 * copys a part if the buffer is to small
359 NTSTATUS
360 WINAPI RtlUnicodeStringToAnsiString(
361 PANSI_STRING ansi,
362 PUNICODE_STRING uni,
363 BOOLEAN doalloc)
365 int len = uni->Length/sizeof(WCHAR);
366 NTSTATUS ret = STATUS_SUCCESS;
368 TRACE("%p %s %i\n", ansi, debugstr_us(uni), doalloc);
370 ansi->Length = len;
371 if (doalloc)
373 ansi->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len+1);
374 if (! ansi->Buffer) return STATUS_NO_MEMORY;
375 ansi->MaximumLength = len + 1;
377 else if (ansi->MaximumLength <= len)
379 ansi->Length = ansi->MaximumLength - 1;
380 ret = STATUS_BUFFER_OVERFLOW;
382 lstrcpynWtoA(ansi->Buffer, uni->Buffer, ansi->Length+1);
383 return ret;
387 COPY BETWEEN ANSI/UNICODE_STRING AND MULTIBYTE STRINGS
389 /**************************************************************************
390 * RtlMultiByteToUnicodeN
392 * NOTES
393 * dest can be equal to src
394 * if unistr is to small a part is copyed
396 * FIXME
397 * multibyte support
399 NTSTATUS
400 WINAPI RtlMultiByteToUnicodeN(
401 LPWSTR unistr,
402 DWORD unilen,
403 LPDWORD reslen,
404 LPSTR oemstr,
405 DWORD oemlen)
407 UINT len;
408 int i;
410 TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
412 len = (unilen/sizeof(WCHAR) < oemlen) ? unilen/sizeof(WCHAR) : oemlen;
414 for (i = len-1; i>=0; i--)
415 unistr[i] = (WCHAR)oemstr[i];
417 if (reslen) *reslen = len * 2;
418 return 0;
421 /**************************************************************************
422 * RtlOemToUnicodeN
424 NTSTATUS
425 WINAPI RtlOemToUnicodeN(
426 LPWSTR unistr,
427 DWORD unilen,
428 LPDWORD reslen,
429 LPSTR oemstr,
430 DWORD oemlen)
432 UINT len;
433 int i;
435 TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
437 len = (unilen/sizeof(WCHAR) < oemlen) ? unilen/sizeof(WCHAR) : oemlen;
439 for (i = len-1; i>=0; i--)
440 unistr[i] = (WCHAR)oemstr[i];
442 if (reslen) *reslen = len * 2;
443 return 0;
447 /**************************************************************************
448 * RtlUnicodeToOemN
450 NTSTATUS
451 WINAPI RtlUnicodeToOemN(
452 LPSTR oemstr,
453 DWORD oemlen,
454 LPDWORD reslen,
455 LPWSTR unistr,
456 DWORD unilen)
458 UINT len;
459 int i;
461 TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
463 len = (oemlen < unilen/sizeof(WCHAR)) ? unilen/sizeof(WCHAR) : oemlen;
465 for (i = len-1; i>=0; i--)
466 oemstr[i] = (CHAR)unistr[i];
468 if (reslen) *reslen = len * 2;
469 return 0;
472 /**************************************************************************
473 * RtlUpcaseUnicodeToOemN
475 NTSTATUS
476 WINAPI RtlUpcaseUnicodeToOemN(
477 LPSTR oemstr,
478 DWORD oemlen,
479 LPDWORD reslen,
480 LPWSTR unistr,
481 DWORD unilen)
483 UINT len;
484 int i;
486 TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
488 len = (oemlen < unilen/sizeof(WCHAR)) ? unilen/sizeof(WCHAR) : oemlen;
490 for (i = len-1; i>=0; i--)
491 oemstr[i] = toupper((CHAR)unistr[i]);
493 if (reslen) *reslen = len * 2;
494 return 0;
497 /**************************************************************************
498 * RtlUnicodeToMultiByteN
500 NTSTATUS WINAPI RtlUnicodeToMultiByteN(
501 PCHAR MbString,
502 ULONG MbSize,
503 PULONG ResultSize,
504 PWCHAR UnicodeString,
505 ULONG UnicodeSize)
507 int Size = 0, i;
509 TRACE("(%p,%lu,%p,%p(%s),%lu)\n",
510 MbString, MbSize, ResultSize, UnicodeString, debugstr_w(UnicodeString), UnicodeSize);
512 Size = (UnicodeSize > (MbSize*sizeof(WCHAR))) ? MbSize: UnicodeSize/sizeof(WCHAR);
514 if (ResultSize != NULL) *ResultSize = Size;
516 for(i = 0; i < Size; i++)
518 *(MbString++) = *(UnicodeString++);
520 return STATUS_SUCCESS;
524 STRING SIZE
526 Rtlx* supports multibyte
529 /**************************************************************************
530 * RtlxOemStringToUnicodeSize
532 UINT WINAPI RtlxOemStringToUnicodeSize(PSTRING str)
534 return str->Length*2+2;
537 /**************************************************************************
538 * RtlxAnsiStringToUnicodeSize
540 UINT WINAPI RtlxAnsiStringToUnicodeSize(PANSI_STRING str)
542 return str->Length*2+2;
545 /**************************************************************************
546 * RtlxUnicodeStringToOemSize
549 UINT WINAPI RtlxUnicodeStringToOemSize(PUNICODE_STRING str)
551 return str->Length+1;
555 MISC
558 /**************************************************************************
559 * RtlIsTextUnicode
561 * Apply various feeble heuristics to guess whether
562 * the text buffer contains Unicode.
563 * FIXME: should implement more tests.
565 DWORD WINAPI RtlIsTextUnicode(
566 LPVOID buf,
567 DWORD len,
568 DWORD *pf)
570 LPWSTR s = buf;
571 DWORD flags = -1, out_flags = 0;
573 if (!len)
574 goto out;
575 if (pf)
576 flags = *pf;
578 * Apply various tests to the text string. According to the
579 * docs, each test "passed" sets the corresponding flag in
580 * the output flags. But some of the tests are mutually
581 * exclusive, so I don't see how you could pass all tests ...
584 /* Check for an odd length ... pass if even. */
585 if (!(len & 1))
586 out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
588 /* Check for the special unicode marker byte. */
589 if (*s == 0xFEFF)
590 out_flags |= IS_TEXT_UNICODE_SIGNATURE;
593 * Check whether the string passed all of the tests.
595 flags &= ITU_IMPLEMENTED_TESTS;
596 if ((out_flags & flags) != flags)
597 len = 0;
598 out:
599 if (pf)
600 *pf = out_flags;
601 return len;
604 /**************************************************************************
605 * RtlPrefixUnicodeString
607 NTSTATUS WINAPI RtlPrefixUnicodeString(
608 PUNICODE_STRING a,
609 PUNICODE_STRING b,
610 DWORD x)
612 TRACE("(%s,%s,%lx)\n",debugstr_us(a),debugstr_us(b),x);
613 return STATUS_SUCCESS;