4 * Copyright 1996-1998 Marcus Meissner
15 #include "wine/winestring.h"
19 #include "debugtools.h"
20 #include "ntdll_misc.h"
23 DEFAULT_DEBUG_CHANNEL(ntdll
)
25 /* STRING FUNCTIONS */
27 /**************************************************************************
30 VOID WINAPI
RtlInitString(PSTRING target
,LPCSTR source
)
32 TRACE("%p %p(%s)\n", target
, source
, debugstr_a(source
));
34 target
->Buffer
= (LPSTR
)source
;
37 target
->Length
= lstrlenA(source
);
38 target
->MaximumLength
= target
->Length
+1;
42 target
->Length
= target
->MaximumLength
= 0;
50 /**************************************************************************
53 VOID WINAPI
RtlInitAnsiString(
57 TRACE("%p %p(%s)\n", target
, source
, debugstr_a(source
));
59 target
->Buffer
= (LPSTR
)source
;
62 target
->Length
= lstrlenA(source
);
63 target
->MaximumLength
= target
->Length
+1;
67 target
->Length
= target
->MaximumLength
= 0;
71 /**************************************************************************
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
,
95 TRACE("%p %p(%s)\n", target
, source
, debugstr_w(source
));
97 target
->Buffer
= (LPWSTR
)source
;
100 target
->Length
= lstrlenW(source
)*2;
101 target
->MaximumLength
= target
->Length
+ 2;
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
);
126 /**************************************************************************
127 * RtlEqualUnicodeString
129 BOOLEAN WINAPI
RtlEqualUnicodeString(
130 IN PUNICODE_STRING s1
,
131 IN PUNICODE_STRING s2
,
132 IN BOOLEAN CaseInsensitive
)
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
;
143 ret
= !CRTDLL__wcsnicmp(s1
->Buffer
,s2
->Buffer
,s1
->Length
/sizeof(WCHAR
));
145 ret
= !CRTDLL_wcsncmp(s1
->Buffer
,s2
->Buffer
,s1
->Length
/sizeof(WCHAR
));
149 /******************************************************************************
150 * RtlCompareUnicodeString
152 LONG WINAPI
RtlCompareUnicodeString(
155 BOOLEAN CaseInsensitive
)
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
);
168 ret
= CRTDLL__wcsnicmp(s1
->Buffer
,s2
->Buffer
,s1
->Length
/sizeof(WCHAR
));
170 ret
= CRTDLL_wcsncmp(s1
->Buffer
,s2
->Buffer
,s1
->Length
/sizeof(WCHAR
));
175 COPY BETWEEN ANSI_STRING or UNICODE_STRING
176 there is no parameter checking, it just crashes
179 /**************************************************************************
180 * RtlAnsiStringToUnicodeString
183 * writes terminating 0
186 WINAPI
RtlAnsiStringToUnicodeString(
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
;
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
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
,
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
);
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
]);
248 return STATUS_SUCCESS
;
251 /**************************************************************************
252 * RtlOemStringToUnicodeString
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
263 WINAPI
RtlOemStringToUnicodeString(
268 int len
= ansi
->Length
* sizeof(WCHAR
);
270 if (len
> 0xfffe) return STATUS_INVALID_PARAMETER_2
;
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
291 * allocates uni->Length+1
292 * writes terminating 0
295 WINAPI
RtlUnicodeStringToOemString(
300 int len
= uni
->Length
/sizeof(WCHAR
);
302 TRACE("%p %s %i\n", oem
, debugstr_us(uni
), 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
323 * writes terminating 0
326 WINAPI
RtlUpcaseUnicodeStringToOemString(
331 int i
, len
= uni
->Length
/sizeof(WCHAR
);
333 TRACE("%p %s %i\n", oem
, debugstr_us(uni
), 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
]));
352 return STATUS_SUCCESS
;
355 /**************************************************************************
356 * RtlUnicodeStringToAnsiString
359 * writes terminating 0
360 * copys a part if the buffer is to small
363 WINAPI
RtlUnicodeStringToAnsiString(
368 int len
= uni
->Length
/sizeof(WCHAR
);
369 NTSTATUS ret
= STATUS_SUCCESS
;
371 TRACE("%p %s %i\n", ansi
, debugstr_us(uni
), 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);
390 COPY BETWEEN ANSI/UNICODE_STRING AND MULTIBYTE STRINGS
392 /**************************************************************************
393 * RtlMultiByteToUnicodeN
396 * dest can be equal to src
397 * if unistr is to small a part is copyed
403 WINAPI
RtlMultiByteToUnicodeN(
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;
424 /**************************************************************************
428 WINAPI
RtlOemToUnicodeN(
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;
450 /**************************************************************************
454 WINAPI
RtlUnicodeToOemN(
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;
475 /**************************************************************************
476 * RtlUpcaseUnicodeToOemN
479 WINAPI
RtlUpcaseUnicodeToOemN(
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;
500 /**************************************************************************
501 * RtlUnicodeToMultiByteN
503 NTSTATUS WINAPI
RtlUnicodeToMultiByteN(
507 PWCHAR UnicodeString
,
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
;
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;
561 /**************************************************************************
564 * Apply various feeble heuristics to guess whether
565 * the text buffer contains Unicode.
566 * FIXME: should implement more tests.
568 DWORD WINAPI
RtlIsTextUnicode(
574 DWORD flags
= -1, out_flags
= 0;
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. */
589 out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
591 /* Check for the special unicode marker byte. */
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
)
607 /**************************************************************************
608 * RtlPrefixUnicodeString
610 NTSTATUS WINAPI
RtlPrefixUnicodeString(
615 TRACE("(%s,%s,%lx)\n",debugstr_us(a
),debugstr_us(b
),x
);
616 return STATUS_SUCCESS
;