4 * Copyright 1996-1998 Marcus Meissner
12 #include "wine/winestring.h"
13 #include "wine/unicode.h"
16 #include "debugtools.h"
17 #include "ntdll_misc.h"
20 DEFAULT_DEBUG_CHANNEL(ntdll
);
22 /* STRING FUNCTIONS */
24 /**************************************************************************
27 VOID WINAPI
RtlInitString(PSTRING target
,LPCSTR source
)
29 TRACE("%p %p(%s)\n", target
, source
, debugstr_a(source
));
31 target
->Buffer
= (LPSTR
)source
;
34 target
->Length
= lstrlenA(source
);
35 target
->MaximumLength
= target
->Length
+1;
39 target
->Length
= target
->MaximumLength
= 0;
47 /**************************************************************************
50 VOID WINAPI
RtlInitAnsiString(
54 TRACE("%p %p(%s)\n", target
, source
, debugstr_a(source
));
56 target
->Buffer
= (LPSTR
)source
;
59 target
->Length
= lstrlenA(source
);
60 target
->MaximumLength
= target
->Length
+1;
64 target
->Length
= target
->MaximumLength
= 0;
68 /**************************************************************************
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
,
92 TRACE("%p %p(%s)\n", target
, source
, debugstr_w(source
));
94 target
->Buffer
= (LPWSTR
)source
;
97 target
->Length
= lstrlenW(source
)*2;
98 target
->MaximumLength
= target
->Length
+ 2;
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
);
123 /**************************************************************************
124 * RtlEqualUnicodeString
126 BOOLEAN WINAPI
RtlEqualUnicodeString(
127 IN PUNICODE_STRING s1
,
128 IN PUNICODE_STRING s2
,
129 IN BOOLEAN CaseInsensitive
)
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
;
140 ret
= !strncmpiW(s1
->Buffer
,s2
->Buffer
,s1
->Length
/sizeof(WCHAR
));
142 ret
= !strncmpW(s1
->Buffer
,s2
->Buffer
,s1
->Length
/sizeof(WCHAR
));
146 /******************************************************************************
147 * RtlCompareUnicodeString
149 LONG WINAPI
RtlCompareUnicodeString(
152 BOOLEAN CaseInsensitive
)
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
);
165 ret
= strncmpiW(s1
->Buffer
,s2
->Buffer
,s1
->Length
/sizeof(WCHAR
));
167 ret
= strncmpW(s1
->Buffer
,s2
->Buffer
,s1
->Length
/sizeof(WCHAR
));
172 COPY BETWEEN ANSI_STRING or UNICODE_STRING
173 there is no parameter checking, it just crashes
176 /**************************************************************************
177 * RtlAnsiStringToUnicodeString
180 * writes terminating 0
183 WINAPI
RtlAnsiStringToUnicodeString(
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
;
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
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
,
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
);
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
]);
245 return STATUS_SUCCESS
;
248 /**************************************************************************
249 * RtlOemStringToUnicodeString
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
260 WINAPI
RtlOemStringToUnicodeString(
265 int len
= ansi
->Length
* sizeof(WCHAR
);
267 if (len
> 0xfffe) return STATUS_INVALID_PARAMETER_2
;
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
288 * allocates uni->Length+1
289 * writes terminating 0
292 WINAPI
RtlUnicodeStringToOemString(
297 int len
= uni
->Length
/sizeof(WCHAR
);
299 TRACE("%p %s %i\n", oem
, debugstr_us(uni
), 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
320 * writes terminating 0
323 WINAPI
RtlUpcaseUnicodeStringToOemString(
328 int i
, len
= uni
->Length
/sizeof(WCHAR
);
330 TRACE("%p %s %i\n", oem
, debugstr_us(uni
), 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
]));
349 return STATUS_SUCCESS
;
352 /**************************************************************************
353 * RtlUnicodeStringToAnsiString
356 * writes terminating 0
357 * copys a part if the buffer is to small
360 WINAPI
RtlUnicodeStringToAnsiString(
365 int len
= uni
->Length
/sizeof(WCHAR
);
366 NTSTATUS ret
= STATUS_SUCCESS
;
368 TRACE("%p %s %i\n", ansi
, debugstr_us(uni
), 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);
387 COPY BETWEEN ANSI/UNICODE_STRING AND MULTIBYTE STRINGS
389 /**************************************************************************
390 * RtlMultiByteToUnicodeN
393 * dest can be equal to src
394 * if unistr is to small a part is copyed
400 WINAPI
RtlMultiByteToUnicodeN(
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;
421 /**************************************************************************
425 WINAPI
RtlOemToUnicodeN(
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;
447 /**************************************************************************
451 WINAPI
RtlUnicodeToOemN(
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;
472 /**************************************************************************
473 * RtlUpcaseUnicodeToOemN
476 WINAPI
RtlUpcaseUnicodeToOemN(
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;
497 /**************************************************************************
498 * RtlUnicodeToMultiByteN
500 NTSTATUS WINAPI
RtlUnicodeToMultiByteN(
504 PWCHAR UnicodeString
,
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
;
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;
558 /**************************************************************************
561 * Apply various feeble heuristics to guess whether
562 * the text buffer contains Unicode.
563 * FIXME: should implement more tests.
565 DWORD WINAPI
RtlIsTextUnicode(
571 DWORD flags
= -1, out_flags
= 0;
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. */
586 out_flags
|= IS_TEXT_UNICODE_ODD_LENGTH
;
588 /* Check for the special unicode marker byte. */
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
)
604 /**************************************************************************
605 * RtlPrefixUnicodeString
607 NTSTATUS WINAPI
RtlPrefixUnicodeString(
612 TRACE("(%s,%s,%lx)\n",debugstr_us(a
),debugstr_us(b
),x
);
613 return STATUS_SUCCESS
;