Added spec entry for _itoa.
[wine] / dlls / ntdll / rtlstr.c
1 /*
2  *      Rtl string functions
3  *
4  *      Copyright 1996-1998 Marcus Meissner
5  */
6
7 #include "config.h"
8
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
21 #include "ntddk.h"
22
23 DEFAULT_DEBUG_CHANNEL(ntdll)
24 /*
25  *      STRING FUNCTIONS
26  */
27
28 /**************************************************************************
29  *                 RtlAnsiStringToUnicodeString         [NTDLL.269]
30  */
31 DWORD /* NTSTATUS */ 
32 WINAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING uni,PANSI_STRING ansi,BOOLEAN doalloc)
33 {
34         DWORD   unilen = (ansi->Length+1)*sizeof(WCHAR);
35
36         if (unilen>0xFFFF)
37                 return STATUS_INVALID_PARAMETER_2;
38         uni->Length = unilen;
39         if (doalloc) {
40                 uni->MaximumLength = unilen;
41                 uni->Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,unilen);
42                 if (!uni->Buffer)
43                         return STATUS_NO_MEMORY;
44         }
45         if (unilen>uni->MaximumLength)
46                 return STATUS_BUFFER_OVERFLOW;
47         lstrcpynAtoW(uni->Buffer,ansi->Buffer,unilen/2);
48         return STATUS_SUCCESS;
49 }
50
51 /**************************************************************************
52  *                 RtlOemStringToUnicodeString          [NTDLL.447]
53  */
54 DWORD /* NTSTATUS */ 
55 WINAPI RtlOemStringToUnicodeString(PUNICODE_STRING uni,PSTRING ansi,BOOLEAN doalloc)
56 {
57         DWORD   unilen = (ansi->Length+1)*sizeof(WCHAR);
58
59         if (unilen>0xFFFF)
60                 return STATUS_INVALID_PARAMETER_2;
61         uni->Length = unilen;
62         if (doalloc) {
63                 uni->MaximumLength = unilen;
64                 uni->Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,unilen);
65                 if (!uni->Buffer)
66                         return STATUS_NO_MEMORY;
67         }
68         if (unilen>uni->MaximumLength)
69                 return STATUS_BUFFER_OVERFLOW;
70         lstrcpynAtoW(uni->Buffer,ansi->Buffer,unilen/2);
71         return STATUS_SUCCESS;
72 }
73 /**************************************************************************
74  *                 RtlMultiByteToUnicodeN               [NTDLL.436]
75  * FIXME: multibyte support
76  */
77 DWORD /* NTSTATUS */ 
78 WINAPI RtlMultiByteToUnicodeN(LPWSTR unistr,DWORD unilen,LPDWORD reslen,LPSTR oemstr,DWORD oemlen)
79 {
80         DWORD   len;
81         LPWSTR  x;
82
83         len = oemlen;
84         if (unilen/2 < len)
85                 len = unilen/2;
86         x=(LPWSTR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR));
87         lstrcpynAtoW(x,oemstr,len+1);
88         memcpy(unistr,x,len*2);
89         if (reslen) *reslen = len*2;
90         return 0;
91 }
92
93 /**************************************************************************
94  *                 RtlOemToUnicodeN                     [NTDLL.448]
95  */
96 DWORD /* NTSTATUS */ 
97 WINAPI RtlOemToUnicodeN(LPWSTR unistr,DWORD unilen,LPDWORD reslen,LPSTR oemstr,DWORD oemlen)
98 {
99         DWORD   len;
100         LPWSTR  x;
101
102         len = oemlen;
103         if (unilen/2 < len)
104                 len = unilen/2;
105         x=(LPWSTR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR));
106         lstrcpynAtoW(x,oemstr,len+1);
107         memcpy(unistr,x,len*2);
108         if (reslen) *reslen = len*2;
109         return 0;
110 }
111
112 /**************************************************************************
113  *                 RtlInitAnsiString                    [NTDLL.399]
114  */
115 VOID WINAPI RtlInitAnsiString(PANSI_STRING target,LPCSTR source)
116 {
117         target->Length = target->MaximumLength = 0;
118         target->Buffer = (LPSTR)source;
119         if (!source)
120                 return;
121         target->MaximumLength = lstrlenA(target->Buffer);
122         target->Length = target->MaximumLength+1;
123 }
124 /**************************************************************************
125  *                 RtlInitString                        [NTDLL.402]
126  */
127 VOID WINAPI RtlInitString(PSTRING target,LPCSTR source)
128 {
129         target->Length = target->MaximumLength = 0;
130         target->Buffer = (LPSTR)source;
131         if (!source)
132                 return;
133         target->MaximumLength = lstrlenA(target->Buffer);
134         target->Length = target->MaximumLength+1;
135 }
136
137 /**************************************************************************
138  *                 RtlInitUnicodeString                 [NTDLL.403]
139  */
140 VOID WINAPI RtlInitUnicodeString(PUNICODE_STRING target,LPCWSTR source)
141 {
142         TRACE("%p %p(%s)\n", target, source, debugstr_w(source));
143         
144         target->Length = target->MaximumLength = 0;
145         target->Buffer = (LPWSTR)source;
146         if (!source)
147                 return;
148         target->MaximumLength = lstrlenW(target->Buffer)*2;
149         target->Length = target->MaximumLength+2;
150 }
151
152 /**************************************************************************
153  *                 RtlFreeUnicodeString                 [NTDLL.377]
154  */
155 VOID WINAPI RtlFreeUnicodeString(PUNICODE_STRING str)
156 {
157         if (str->Buffer)
158                 HeapFree(GetProcessHeap(),0,str->Buffer);
159 }
160
161 /**************************************************************************
162  * RtlFreeAnsiString [NTDLL.373]
163  */
164 VOID WINAPI RtlFreeAnsiString(PANSI_STRING AnsiString)
165 {
166     if( AnsiString->Buffer )
167         HeapFree( GetProcessHeap(),0,AnsiString->Buffer );
168 }
169
170
171 /**************************************************************************
172  *                 RtlUnicodeToOemN                     [NTDLL.515]
173  */
174 DWORD /* NTSTATUS */ 
175 WINAPI RtlUnicodeToOemN(LPSTR oemstr,DWORD oemlen,LPDWORD reslen,LPWSTR unistr,DWORD unilen)
176 {
177         DWORD   len;
178         LPSTR   x;
179
180         len = oemlen;
181         if (unilen/2 < len)
182                 len = unilen/2;
183         x=(LPSTR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,len+1);
184         lstrcpynWtoA(x,unistr,len+1);
185         memcpy(oemstr,x,len);
186         if (reslen) *reslen = len;
187         return 0;
188 }
189
190 /**************************************************************************
191  *                 RtlUnicodeStringToOemString          [NTDLL.511]
192  */
193 DWORD /* NTSTATUS */ 
194 WINAPI RtlUnicodeStringToOemString(PANSI_STRING oem,PUNICODE_STRING uni,BOOLEAN alloc)
195 {
196         if (alloc) {
197                 oem->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,uni->Length/2)+1;
198                 oem->MaximumLength = uni->Length/2+1;
199         }
200         oem->Length = uni->Length/2;
201         lstrcpynWtoA(oem->Buffer,uni->Buffer,uni->Length/2+1);
202         return 0;
203 }
204
205 /**************************************************************************
206  *                 RtlUnicodeStringToAnsiString         [NTDLL.507]
207  */
208 DWORD /* NTSTATUS */ 
209 WINAPI RtlUnicodeStringToAnsiString(PANSI_STRING oem,PUNICODE_STRING uni,BOOLEAN alloc)
210 {
211         if (alloc) {
212                 oem->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,uni->Length/2)+1;
213                 oem->MaximumLength = uni->Length/2+1;
214         }
215         oem->Length = uni->Length/2;
216         lstrcpynWtoA(oem->Buffer,uni->Buffer,uni->Length/2+1);
217         return 0;
218 }
219
220 /**************************************************************************
221  *                 RtlEqualUnicodeString                [NTDLL]
222  */
223 DWORD WINAPI RtlEqualUnicodeString(PUNICODE_STRING s1,PUNICODE_STRING s2,DWORD x) {
224         FIXME("(%s,%s,%ld),stub!\n",debugstr_w(s1->Buffer),debugstr_w(s2->Buffer),x);
225         return 0;
226         if (s1->Length != s2->Length)
227                 return 1;
228         return !CRTDLL_wcsncmp(s1->Buffer,s2->Buffer,s1->Length/2);
229 }
230
231 /**************************************************************************
232  *                 RtlUpcaseUnicodeString               [NTDLL.520]
233  */
234 DWORD WINAPI RtlUpcaseUnicodeString(PUNICODE_STRING dest,PUNICODE_STRING src,BOOLEAN doalloc)
235 {
236         LPWSTR  s,t;
237         DWORD   i,len;
238
239         len = src->Length;
240         if (doalloc) {
241                 dest->MaximumLength = len; 
242                 dest->Buffer = (LPWSTR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,len);
243                 if (!dest->Buffer)
244                         return STATUS_NO_MEMORY;
245
246         }
247         if (dest->MaximumLength < len)
248                 return STATUS_BUFFER_OVERFLOW;
249         s=dest->Buffer;t=src->Buffer;
250         /* len is in bytes */
251         for (i=0;i<len/2;i++)
252                 s[i] = towupper(t[i]);
253         return STATUS_SUCCESS;
254 }
255
256 /**************************************************************************
257  *                 RtlxOemStringToUnicodeSize           [NTDLL.549]
258  */
259 UINT WINAPI RtlxOemStringToUnicodeSize(PSTRING str)
260 {
261         return str->Length*2+2;
262 }
263
264 /**************************************************************************
265  *                 RtlxAnsiStringToUnicodeSize          [NTDLL.548]
266  */
267 UINT WINAPI RtlxAnsiStringToUnicodeSize(PANSI_STRING str)
268 {
269         return str->Length*2+2;
270 }
271
272 /**************************************************************************
273  *                 RtlIsTextUnicode                     [NTDLL.417]
274  *
275  *      Apply various feeble heuristics to guess whether
276  *      the text buffer contains Unicode.
277  *      FIXME: should implement more tests.
278  */
279 DWORD WINAPI RtlIsTextUnicode(LPVOID buf, DWORD len, DWORD *pf)
280 {
281         LPWSTR s = buf;
282         DWORD flags = -1, out_flags = 0;
283
284         if (!len)
285                 goto out;
286         if (pf)
287                 flags = *pf;
288         /*
289          * Apply various tests to the text string. According to the
290          * docs, each test "passed" sets the corresponding flag in
291          * the output flags. But some of the tests are mutually
292          * exclusive, so I don't see how you could pass all tests ...
293          */
294
295         /* Check for an odd length ... pass if even. */
296         if (!(len & 1))
297                 out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
298
299         /* Check for the special unicode marker byte. */
300         if (*s == 0xFEFF)
301                 out_flags |= IS_TEXT_UNICODE_SIGNATURE;
302
303         /*
304          * Check whether the string passed all of the tests.
305          */
306         flags &= ITU_IMPLEMENTED_TESTS;
307         if ((out_flags & flags) != flags)
308                 len = 0;
309 out:
310         if (pf)
311                 *pf = out_flags;
312         return len;
313 }
314
315
316 /******************************************************************************
317  *      RtlCompareUnicodeString [NTDLL] 
318  */
319 NTSTATUS WINAPI RtlCompareUnicodeString(
320         PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive) 
321 {
322         FIXME("(%s,%s,0x%08x),stub!\n",debugstr_w(String1->Buffer),debugstr_w(String1->Buffer),CaseInSensitive);
323         return 0;
324 }
325
326