1 /* Unit test suite for Rtl string functions
2  *
3  * Copyright 2002 Robert Shearman
4  * Copyright 2003 Thomas Mertes
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * NOTES
21  * We use function pointers here as there is no import library for NTDLL on
22  * windows.
23  */
24 
25 #include "ntdll_test.h"
26 
27 #include <initguid.h>
28 
29 #define HASH_STRING_ALGORITHM_X65599   1
30 #define HASH_STRING_ALGORITHM_INVALID  0xffffffff
31 
32 /* Function ptrs for ntdll calls */
33 static HMODULE hntdll = 0;
34 static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING, PCANSI_STRING, BOOLEAN);
35 static NTSTATUS (WINAPI *pRtlAppendAsciizToString)(STRING *, LPCSTR);
36 static NTSTATUS (WINAPI *pRtlAppendStringToString)(STRING *, const STRING *);
37 static NTSTATUS (WINAPI *pRtlAppendUnicodeStringToString)(UNICODE_STRING *, const UNICODE_STRING *);
38 static NTSTATUS (WINAPI *pRtlAppendUnicodeToString)(UNICODE_STRING *, LPCWSTR);
39 static NTSTATUS (WINAPI *pRtlCharToInteger)(PCSZ, ULONG, int *);
40 static LONG     (WINAPI *pRtlCompareUnicodeString)(const UNICODE_STRING*, const UNICODE_STRING*, BOOLEAN);
41 static LONG     (WINAPI *pRtlCompareUnicodeStrings)(const WCHAR *,SIZE_T,const WCHAR *,SIZE_T,BOOLEAN);
42 static VOID     (WINAPI *pRtlCopyString)(STRING *, const STRING *);
43 static BOOLEAN  (WINAPI *pRtlCreateUnicodeString)(PUNICODE_STRING, LPCWSTR);
44 static BOOLEAN  (WINAPI *pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPCSTR);
45 static NTSTATUS (WINAPI *pRtlDowncaseUnicodeString)(UNICODE_STRING *, const UNICODE_STRING *, BOOLEAN);
46 static NTSTATUS (WINAPI *pRtlDuplicateUnicodeString)(int, UNICODE_STRING *, UNICODE_STRING *);
47 static BOOLEAN  (WINAPI *pRtlEqualUnicodeString)(const UNICODE_STRING *, const UNICODE_STRING *, BOOLEAN);
48 static NTSTATUS (WINAPI *pRtlFindCharInUnicodeString)(int, const UNICODE_STRING *, const UNICODE_STRING *, USHORT *);
49 static VOID     (WINAPI *pRtlFreeAnsiString)(PSTRING);
50 static VOID     (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
51 static VOID     (WINAPI *pRtlInitAnsiString)(PSTRING, LPCSTR);
52 static VOID     (WINAPI *pRtlInitString)(PSTRING, LPCSTR);
53 static VOID     (WINAPI *pRtlInitUnicodeString)(PUNICODE_STRING, LPCWSTR);
54 static NTSTATUS (WINAPI *pRtlInitUnicodeStringEx)(PUNICODE_STRING, LPCWSTR);
55 static NTSTATUS (WINAPI *pRtlIntegerToChar)(ULONG, ULONG, ULONG, PCHAR);
56 static NTSTATUS (WINAPI *pRtlIntegerToUnicodeString)(ULONG, ULONG, UNICODE_STRING *);
57 static NTSTATUS (WINAPI *pRtlMultiAppendUnicodeStringBuffer)(UNICODE_STRING *, LONG, UNICODE_STRING *);
58 static NTSTATUS (WINAPI *pRtlUnicodeStringToAnsiString)(STRING *, const UNICODE_STRING *, BOOLEAN);
59 static NTSTATUS (WINAPI *pRtlUnicodeStringToInteger)(const UNICODE_STRING *, int, int *);
60 static WCHAR    (WINAPI *pRtlUpcaseUnicodeChar)(WCHAR);
61 static NTSTATUS (WINAPI *pRtlUpcaseUnicodeString)(UNICODE_STRING *, const UNICODE_STRING *, BOOLEAN);
62 static CHAR     (WINAPI *pRtlUpperChar)(CHAR);
63 static NTSTATUS (WINAPI *pRtlUpperString)(STRING *, const STRING *);
64 static NTSTATUS (WINAPI *pRtlValidateUnicodeString)(LONG, UNICODE_STRING *);
65 static NTSTATUS (WINAPI *pRtlGUIDFromString)(const UNICODE_STRING*,GUID*);
66 static NTSTATUS (WINAPI *pRtlStringFromGUID)(const GUID*, UNICODE_STRING*);
67 static BOOLEAN (WINAPI *pRtlIsTextUnicode)(LPVOID, INT, INT *);
68 static NTSTATUS (WINAPI *pRtlHashUnicodeString)(PCUNICODE_STRING,BOOLEAN,ULONG,ULONG*);
69 static NTSTATUS (WINAPI *pRtlUnicodeToUTF8N)(CHAR *, ULONG, ULONG *, const WCHAR *, ULONG);
70 static NTSTATUS (WINAPI *pRtlUTF8ToUnicodeN)(WCHAR *, ULONG, ULONG *, const CHAR *, ULONG);
71 
72 /*static VOID (WINAPI *pRtlFreeOemString)(PSTRING);*/
73 /*static VOID (WINAPI *pRtlCopyUnicodeString)(UNICODE_STRING *, const UNICODE_STRING *);*/
74 /*static VOID (WINAPI *pRtlEraseUnicodeString)(UNICODE_STRING *);*/
75 /*static LONG (WINAPI *pRtlCompareString)(const STRING *,const STRING *,BOOLEAN);*/
76 /*static BOOLEAN (WINAPI *pRtlEqualString)(const STRING *,const STRING *,BOOLEAN);*/
77 /*static BOOLEAN (WINAPI *pRtlPrefixString)(const STRING *, const STRING *, BOOLEAN);*/
78 /*static BOOLEAN (WINAPI *pRtlPrefixUnicodeString)(const UNICODE_STRING *, const UNICODE_STRING *, BOOLEAN);*/
79 /*static NTSTATUS (WINAPI *pRtlOemStringToUnicodeString)(PUNICODE_STRING, const STRING *, BOOLEAN);*/
80 /*static NTSTATUS (WINAPI *pRtlUnicodeStringToOemString)(STRING *, const UNICODE_STRING *, BOOLEAN);*/
81 /*static NTSTATUS (WINAPI *pRtlMultiByteToUnicodeN)(LPWSTR, DWORD, LPDWORD, LPCSTR, DWORD);*/
82 /*static NTSTATUS (WINAPI *pRtlOemToUnicodeN)(LPWSTR, DWORD, LPDWORD, LPCSTR, DWORD);*/
83 /*static NTSTATUS (WINAPI *pRtlUpcaseUnicodeStringToAnsiString)(STRING *, const UNICODE_STRING *, BOOLEAN);*/
84 /*static NTSTATUS (WINAPI *pRtlUpcaseUnicodeStringToOemString)(STRING *, const UNICODE_STRING *, BOOLEAN);*/
85 /*static NTSTATUS (WINAPI *pRtlUpcaseUnicodeToMultiByteN)(LPSTR, DWORD, LPDWORD, LPCWSTR, DWORD);*/
86 /*static NTSTATUS (WINAPI *pRtlUpcaseUnicodeToOemN)(LPSTR, DWORD, LPDWORD, LPCWSTR, DWORD);*/
87 /*static UINT (WINAPI *pRtlOemToUnicodeSize)(const STRING *);*/
88 /*static DWORD (WINAPI *pRtlAnsiStringToUnicodeSize)(const STRING *);*/
89 
90 
91 static WCHAR* AtoW( const char* p )
92 {
93     WCHAR* buffer;
94     DWORD len = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
95     buffer = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR) );
96     MultiByteToWideChar( CP_ACP, 0, p, -1, buffer, len );
97     return buffer;
98 }
99 
100 
101 static void InitFunctionPtrs(void)
102 {
103     hntdll = LoadLibraryA("ntdll.dll");
104     ok(hntdll != 0, "LoadLibrary failed\n");
105     if (hntdll) {
106 	pRtlAnsiStringToUnicodeString = (void *)GetProcAddress(hntdll, "RtlAnsiStringToUnicodeString");
107 	pRtlAppendAsciizToString = (void *)GetProcAddress(hntdll, "RtlAppendAsciizToString");
108 	pRtlAppendStringToString = (void *)GetProcAddress(hntdll, "RtlAppendStringToString");
109 	pRtlAppendUnicodeStringToString = (void *)GetProcAddress(hntdll, "RtlAppendUnicodeStringToString");
110 	pRtlAppendUnicodeToString = (void *)GetProcAddress(hntdll, "RtlAppendUnicodeToString");
111 	pRtlCharToInteger = (void *)GetProcAddress(hntdll, "RtlCharToInteger");
112 	pRtlCompareUnicodeString = (void *)GetProcAddress(hntdll, "RtlCompareUnicodeString");
113 	pRtlCompareUnicodeStrings = (void *)GetProcAddress(hntdll, "RtlCompareUnicodeStrings");
114 	pRtlCopyString = (void *)GetProcAddress(hntdll, "RtlCopyString");
115 	pRtlCreateUnicodeString = (void *)GetProcAddress(hntdll, "RtlCreateUnicodeString");
116 	pRtlCreateUnicodeStringFromAsciiz = (void *)GetProcAddress(hntdll, "RtlCreateUnicodeStringFromAsciiz");
117 	pRtlDowncaseUnicodeString = (void *)GetProcAddress(hntdll, "RtlDowncaseUnicodeString");
118 	pRtlDuplicateUnicodeString = (void *)GetProcAddress(hntdll, "RtlDuplicateUnicodeString");
119 	pRtlEqualUnicodeString = (void *)GetProcAddress(hntdll, "RtlEqualUnicodeString");
120 	pRtlFindCharInUnicodeString = (void *)GetProcAddress(hntdll, "RtlFindCharInUnicodeString");
121 	pRtlFreeAnsiString = (void *)GetProcAddress(hntdll, "RtlFreeAnsiString");
122 	pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
123 	pRtlInitAnsiString = (void *)GetProcAddress(hntdll, "RtlInitAnsiString");
124 	pRtlInitString = (void *)GetProcAddress(hntdll, "RtlInitString");
125 	pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
126 	pRtlInitUnicodeStringEx = (void *)GetProcAddress(hntdll, "RtlInitUnicodeStringEx");
127 	pRtlIntegerToChar = (void *)GetProcAddress(hntdll, "RtlIntegerToChar");
128 	pRtlIntegerToUnicodeString = (void *)GetProcAddress(hntdll, "RtlIntegerToUnicodeString");
129 	pRtlMultiAppendUnicodeStringBuffer = (void *)GetProcAddress(hntdll, "RtlMultiAppendUnicodeStringBuffer");
130 	pRtlUnicodeStringToAnsiString = (void *)GetProcAddress(hntdll, "RtlUnicodeStringToAnsiString");
131 	pRtlUnicodeStringToInteger = (void *)GetProcAddress(hntdll, "RtlUnicodeStringToInteger");
132 	pRtlUpcaseUnicodeChar = (void *)GetProcAddress(hntdll, "RtlUpcaseUnicodeChar");
133 	pRtlUpcaseUnicodeString = (void *)GetProcAddress(hntdll, "RtlUpcaseUnicodeString");
134 	pRtlUpperChar = (void *)GetProcAddress(hntdll, "RtlUpperChar");
135 	pRtlUpperString = (void *)GetProcAddress(hntdll, "RtlUpperString");
136 	pRtlValidateUnicodeString = (void *)GetProcAddress(hntdll, "RtlValidateUnicodeString");
137 	pRtlGUIDFromString = (void *)GetProcAddress(hntdll, "RtlGUIDFromString");
138 	pRtlStringFromGUID = (void *)GetProcAddress(hntdll, "RtlStringFromGUID");
139 	pRtlIsTextUnicode = (void *)GetProcAddress(hntdll, "RtlIsTextUnicode");
140         pRtlHashUnicodeString = (void*)GetProcAddress(hntdll, "RtlHashUnicodeString");
141         pRtlUnicodeToUTF8N = (void*)GetProcAddress(hntdll, "RtlUnicodeToUTF8N");
142         pRtlUTF8ToUnicodeN = (void*)GetProcAddress(hntdll, "RtlUTF8ToUnicodeN");
143     }
144 }
145 
146 static void test_RtlInitString(void)
147 {
148     static const char teststring[] = "Some Wild String";
149     STRING str;
150 
151     str.Length = 0;
152     str.MaximumLength = 0;
153     str.Buffer = (void *)0xdeadbeef;
154     pRtlInitString(&str, teststring);
155     ok(str.Length == sizeof(teststring) - sizeof(char), "Length uninitialized\n");
156     ok(str.MaximumLength == sizeof(teststring), "MaximumLength uninitialized\n");
157     ok(str.Buffer == teststring, "Buffer not equal to teststring\n");
158     ok(strcmp(str.Buffer, "Some Wild String") == 0, "Buffer written to\n");
159     pRtlInitString(&str, NULL);
160     ok(str.Length == 0, "Length uninitialized\n");
161     ok(str.MaximumLength == 0, "MaximumLength uninitialized\n");
162     ok(str.Buffer == NULL, "Buffer not equal to NULL\n");
163 /*  pRtlInitString(NULL, teststring); */
164 }
165 
166 
167 static void test_RtlInitUnicodeString(void)
168 {
169 #define STRINGW {'S','o','m','e',' ','W','i','l','d',' ','S','t','r','i','n','g',0}
170     static const WCHAR teststring[] = STRINGW;
171     static const WCHAR originalstring[] = STRINGW;
172 #undef STRINGW
173     UNICODE_STRING uni;
174 
175     uni.Length = 0;
176     uni.MaximumLength = 0;
177     uni.Buffer = (void *)0xdeadbeef;
178     pRtlInitUnicodeString(&uni, teststring);
179     ok(uni.Length == sizeof(teststring) - sizeof(WCHAR), "Length uninitialized\n");
180     ok(uni.MaximumLength == sizeof(teststring), "MaximumLength uninitialized\n");
181     ok(uni.Buffer == teststring, "Buffer not equal to teststring\n");
182     ok(lstrcmpW(uni.Buffer, originalstring) == 0, "Buffer written to\n");
183     pRtlInitUnicodeString(&uni, NULL);
184     ok(uni.Length == 0, "Length uninitialized\n");
185     ok(uni.MaximumLength == 0, "MaximumLength uninitialized\n");
186     ok(uni.Buffer == NULL, "Buffer not equal to NULL\n");
187 /*  pRtlInitUnicodeString(NULL, teststring); */
188 }
189 
190 
191 #define TESTSTRING2_LEN 1000000
192 /* #define TESTSTRING2_LEN 32766 */
193 
194 
195 static void test_RtlInitUnicodeStringEx(void)
196 {
197     static const WCHAR teststring[] = {'S','o','m','e',' ','W','i','l','d',' ','S','t','r','i','n','g',0};
198     WCHAR *teststring2;
199     UNICODE_STRING uni;
200     NTSTATUS result;
201 
202     if (!pRtlInitUnicodeStringEx)
203     {
204         win_skip("RtlInitUnicodeStringEx is not available\n");
205         return;
206     }
207 
208     teststring2 = HeapAlloc(GetProcessHeap(), 0, (TESTSTRING2_LEN + 1) * sizeof(WCHAR));
209     memset(teststring2, 'X', TESTSTRING2_LEN * sizeof(WCHAR));
210     teststring2[TESTSTRING2_LEN] = '\0';
211 
212     uni.Length = 12345;
213     uni.MaximumLength = 12345;
214     uni.Buffer = (void *) 0xdeadbeef;
215     result = pRtlInitUnicodeStringEx(&uni, teststring);
216     ok(result == STATUS_SUCCESS,
217        "pRtlInitUnicodeStringEx(&uni, 0) returns %x, expected 0\n",
218        result);
219     ok(uni.Length == 32,
220        "pRtlInitUnicodeStringEx(&uni, 0) sets Length to %u, expected %u\n",
221        uni.Length, 32);
222     ok(uni.MaximumLength == 34,
223        "pRtlInitUnicodeStringEx(&uni, 0) sets MaximumLength to %u, expected %u\n",
224        uni.MaximumLength, 34);
225     ok(uni.Buffer == teststring,
226        "pRtlInitUnicodeStringEx(&uni, 0) sets Buffer to %p, expected %p\n",
227        uni.Buffer, teststring);
228 
229     uni.Length = 12345;
230     uni.MaximumLength = 12345;
231     uni.Buffer = (void *) 0xdeadbeef;
232     pRtlInitUnicodeString(&uni, teststring);
233     ok(uni.Length == 32,
234        "pRtlInitUnicodeString(&uni, 0) sets Length to %u, expected %u\n",
235        uni.Length, 32);
236     ok(uni.MaximumLength == 34,
237        "pRtlInitUnicodeString(&uni, 0) sets MaximumLength to %u, expected %u\n",
238        uni.MaximumLength, 34);
239     ok(uni.Buffer == teststring,
240        "pRtlInitUnicodeString(&uni, 0) sets Buffer to %p, expected %p\n",
241        uni.Buffer, teststring);
242 
243     uni.Length = 12345;
244     uni.MaximumLength = 12345;
245     uni.Buffer = (void *) 0xdeadbeef;
246     result = pRtlInitUnicodeStringEx(&uni, teststring2);
247     ok(result == STATUS_NAME_TOO_LONG,
248        "pRtlInitUnicodeStringEx(&uni, 0) returns %x, expected %x\n",
249        result, STATUS_NAME_TOO_LONG);
250     ok(uni.Length == 12345 ||
251        uni.Length == 0, /* win2k3 */
252        "pRtlInitUnicodeStringEx(&uni, 0) sets Length to %u, expected 12345 or 0\n",
253        uni.Length);
254     ok(uni.MaximumLength == 12345 ||
255        uni.MaximumLength == 0, /* win2k3 */
256        "pRtlInitUnicodeStringEx(&uni, 0) sets MaximumLength to %u, expected 12345 or 0\n",
257        uni.MaximumLength);
258     ok(uni.Buffer == (void *) 0xdeadbeef ||
259        uni.Buffer == teststring2, /* win2k3 */
260        "pRtlInitUnicodeStringEx(&uni, 0) sets Buffer to %p, expected %x or %p\n",
261        uni.Buffer, 0xdeadbeef, teststring2);
262 
263     uni.Length = 12345;
264     uni.MaximumLength = 12345;
265     uni.Buffer = (void *) 0xdeadbeef;
266     pRtlInitUnicodeString(&uni, teststring2);
267     ok(uni.Length == 33920 /* <= Win2000 */ || uni.Length == 65532 /* >= Win XP */,
268        "pRtlInitUnicodeString(&uni, 0) sets Length to %u, expected %u\n",
269        uni.Length, 65532);
270     ok(uni.MaximumLength == 33922 /* <= Win2000 */ || uni.MaximumLength == 65534 /* >= Win XP */,
271        "pRtlInitUnicodeString(&uni, 0) sets MaximumLength to %u, expected %u\n",
272        uni.MaximumLength, 65534);
273     ok(uni.Buffer == teststring2,
274        "pRtlInitUnicodeString(&uni, 0) sets Buffer to %p, expected %p\n",
275        uni.Buffer, teststring2);
276     ok(memcmp(uni.Buffer, teststring2, (TESTSTRING2_LEN + 1) * sizeof(WCHAR)) == 0,
277        "pRtlInitUnicodeString(&uni, 0) changes Buffer\n");
278 
279     uni.Length = 12345;
280     uni.MaximumLength = 12345;
281     uni.Buffer = (void *) 0xdeadbeef;
282     result = pRtlInitUnicodeStringEx(&uni, 0);
283     ok(result == STATUS_SUCCESS,
284        "pRtlInitUnicodeStringEx(&uni, 0) returns %x, expected 0\n",
285        result);
286     ok(uni.Length == 0,
287        "pRtlInitUnicodeStringEx(&uni, 0) sets Length to %u, expected %u\n",
288        uni.Length, 0);
289     ok(uni.MaximumLength == 0,
290        "pRtlInitUnicodeStringEx(&uni, 0) sets MaximumLength to %u, expected %u\n",
291        uni.MaximumLength, 0);
292     ok(uni.Buffer == NULL,
293        "pRtlInitUnicodeStringEx(&uni, 0) sets Buffer to %p, expected %p\n",
294        uni.Buffer, NULL);
295 
296     uni.Length = 12345;
297     uni.MaximumLength = 12345;
298     uni.Buffer = (void *) 0xdeadbeef;
299     pRtlInitUnicodeString(&uni, 0);
300     ok(uni.Length == 0,
301        "pRtlInitUnicodeString(&uni, 0) sets Length to %u, expected %u\n",
302        uni.Length, 0);
303     ok(uni.MaximumLength == 0,
304        "pRtlInitUnicodeString(&uni, 0) sets MaximumLength to %u, expected %u\n",
305        uni.MaximumLength, 0);
306     ok(uni.Buffer == NULL,
307        "pRtlInitUnicodeString(&uni, 0) sets Buffer to %p, expected %p\n",
308        uni.Buffer, NULL);
309 
310     HeapFree(GetProcessHeap(), 0, teststring2);
311 }
312 
313 
314 typedef struct {
315     int add_nul;
316     int source_Length;
317     int source_MaximumLength;
318     int source_buf_size;
319     const char *source_buf;
320     int dest_Length;
321     int dest_MaximumLength;
322     int dest_buf_size;
323     const char *dest_buf;
324     int res_Length;
325     int res_MaximumLength;
326     int res_buf_size;
327     const char *res_buf;
328     NTSTATUS result;
329 } dupl_ustr_t;
330 
331 static const dupl_ustr_t dupl_ustr[] = {
332     { 0, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 32, 32, 32, "This is a string",     STATUS_SUCCESS},
333     { 0, 32, 32, 32, "This is a string", 40, 42, 42, "--------------------", 32, 32, 32, "This is a string",     STATUS_SUCCESS},
334     { 0, 32, 30, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
335     { 0, 32, 34, 34, "This is a string", 40, 42, 42, NULL,                   32, 32, 32, "This is a string",     STATUS_SUCCESS},
336     { 0, 32, 32, 32, "This is a string", 40, 42, 42, NULL,                   32, 32, 32, "This is a string",     STATUS_SUCCESS},
337     { 0, 32, 30, 34, "This is a string", 40, 42, 42, NULL,                   40, 42,  0, NULL,                   STATUS_INVALID_PARAMETER},
338     { 1, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 32, 34, 34, "This is a string",     STATUS_SUCCESS},
339     { 1, 32, 32, 32, "This is a string", 40, 42, 42, "--------------------", 32, 34, 34, "This is a string",     STATUS_SUCCESS},
340     { 1, 32, 30, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
341     { 1, 32, 34, 34, "This is a string", 40, 42, 42, NULL,                   32, 34, 34, "This is a string",     STATUS_SUCCESS},
342     { 1, 32, 32, 32, "This is a string", 40, 42, 42, NULL,                   32, 34, 34, "This is a string",     STATUS_SUCCESS},
343     { 1, 32, 30, 34, "This is a string", 40, 42, 42, NULL,                   40, 42,  0, NULL,                   STATUS_INVALID_PARAMETER},
344     { 2, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
345     { 2, 32, 32, 32, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
346     { 2, 32, 30, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
347     { 2, 32, 34, 34, "This is a string", 40, 42, 42, NULL,                   40, 42,  0, NULL,                   STATUS_INVALID_PARAMETER},
348     { 2, 32, 32, 32, "This is a string", 40, 42, 42, NULL,                   40, 42,  0, NULL,                   STATUS_INVALID_PARAMETER},
349     { 2, 32, 30, 34, "This is a string", 40, 42, 42, NULL,                   40, 42,  0, NULL,                   STATUS_INVALID_PARAMETER},
350     { 3, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 32, 34, 34, "This is a string",     STATUS_SUCCESS},
351     { 3, 32, 32, 32, "This is a string", 40, 42, 42, "--------------------", 32, 34, 34, "This is a string",     STATUS_SUCCESS},
352     { 3, 32, 30, 32, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
353     { 3, 32, 34, 34, "This is a string", 40, 42, 42, NULL,                   32, 34, 34, "This is a string",     STATUS_SUCCESS},
354     { 3, 32, 32, 32, "This is a string", 40, 42, 42, NULL,                   32, 34, 34, "This is a string",     STATUS_SUCCESS},
355     { 3, 32, 30, 32, "This is a string", 40, 42, 42, NULL,                   40, 42,  0, NULL,                   STATUS_INVALID_PARAMETER},
356     { 4, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
357     { 5, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
358     { 6, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
359     { 7, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
360     { 8, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
361     { 9, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
362     {10, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
363     {11, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
364     {12, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
365     {13, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
366     {14, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
367     {15, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
368     {16, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
369     {-1, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
370     {-5, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
371     {-9, 32, 34, 34, "This is a string", 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
372     { 0,  0,  2,  2, "",                 40, 42, 42, "--------------------",  0,  0,  0, NULL,                   STATUS_SUCCESS},
373     { 0,  0,  0,  0, "",                 40, 42, 42, "--------------------",  0,  0,  0, NULL,                   STATUS_SUCCESS},
374     { 0,  0,  2,  2, "",                 40, 42, 42, NULL,                    0,  0,  0, NULL,                   STATUS_SUCCESS},
375     { 0,  0,  0,  0, "",                 40, 42, 42, NULL,                    0,  0,  0, NULL,                   STATUS_SUCCESS},
376     { 0,  0,  2,  2, NULL,               40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
377     { 0,  0,  0,  0, NULL,               40, 42, 42, "--------------------",  0,  0,  0, NULL,                   STATUS_SUCCESS},
378     { 0,  0,  2,  2, NULL,               40, 42, 42, NULL,                   40, 42,  0, NULL,                   STATUS_INVALID_PARAMETER},
379     { 0,  0,  0,  0, NULL,               40, 42, 42, NULL,                    0,  0,  0, NULL,                   STATUS_SUCCESS},
380     { 1,  0,  2,  2, "",                 40, 42, 42, "--------------------",  0,  0,  0, NULL,                   STATUS_SUCCESS},
381     { 1,  0,  0,  0, "",                 40, 42, 42, "--------------------",  0,  0,  0, NULL,                   STATUS_SUCCESS},
382     { 1,  0,  2,  2, "",                 40, 42, 42, NULL,                    0,  0,  0, NULL,                   STATUS_SUCCESS},
383     { 1,  0,  0,  0, "",                 40, 42, 42, NULL,                    0,  0,  0, NULL,                   STATUS_SUCCESS},
384     { 1,  0,  2,  2, NULL,               40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
385     { 1,  0,  0,  0, NULL,               40, 42, 42, "--------------------",  0,  0,  0, NULL,                   STATUS_SUCCESS},
386     { 1,  0,  2,  2, NULL,               40, 42, 42, NULL,                   40, 42,  0, NULL,                   STATUS_INVALID_PARAMETER},
387     { 1,  0,  0,  0, NULL,               40, 42, 42, NULL,                    0,  0,  0, NULL,                   STATUS_SUCCESS},
388     { 2,  0,  2,  2, "",                 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
389     { 2,  0,  0,  0, "",                 40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
390     { 2,  0,  2,  2, "",                 40, 42, 42, NULL,                   40, 42,  0, NULL,                   STATUS_INVALID_PARAMETER},
391     { 2,  0,  0,  0, "",                 40, 42, 42, NULL,                   40, 42,  0, NULL,                   STATUS_INVALID_PARAMETER},
392     { 2,  0,  2,  2, NULL,               40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
393     { 2,  0,  0,  0, NULL,               40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
394     { 2,  0,  2,  2, NULL,               40, 42, 42, NULL,                   40, 42,  0, NULL,                   STATUS_INVALID_PARAMETER},
395     { 2,  0,  0,  0, NULL,               40, 42, 42, NULL,                   40, 42,  0, NULL,                   STATUS_INVALID_PARAMETER},
396     { 3,  0,  2,  2, "",                 40, 42, 42, "--------------------",  0,  2,  2, "",                     STATUS_SUCCESS},
397     { 3,  0,  0,  0, "",                 40, 42, 42, "--------------------",  0,  2,  2, "",                     STATUS_SUCCESS},
398     { 3,  0,  2,  2, "",                 40, 42, 42, NULL,                    0,  2,  2, "",                     STATUS_SUCCESS},
399     { 3,  0,  0,  0, "",                 40, 42, 42, NULL,                    0,  2,  2, "",                     STATUS_SUCCESS},
400     { 3,  0,  2,  2, NULL,               40, 42, 42, "--------------------", 40, 42, 42, "--------------------", STATUS_INVALID_PARAMETER},
401     { 3,  0,  0,  0, NULL,               40, 42, 42, "--------------------",  0,  2,  2, "",                     STATUS_SUCCESS},
402     { 3,  0,  2,  2, NULL,               40, 42, 42, NULL,                   40, 42,  0, NULL,                   STATUS_INVALID_PARAMETER},
403     { 3,  0,  0,  0, NULL,               40, 42, 42, NULL,                    0,  2,  2, "",                     STATUS_SUCCESS},
404 };
405 #define NB_DUPL_USTR (sizeof(dupl_ustr)/sizeof(*dupl_ustr))
406 
407 
408 static void test_RtlDuplicateUnicodeString(void)
409 {
410     size_t pos;
411     WCHAR source_buf[257];
412     WCHAR dest_buf[257];
413     WCHAR res_buf[257];
414     UNICODE_STRING source_str;
415     UNICODE_STRING dest_str;
416     UNICODE_STRING res_str;
417     CHAR dest_ansi_buf[257];
418     STRING dest_ansi_str;
419     NTSTATUS result;
420     unsigned int test_num;
421 
422     if (!pRtlDuplicateUnicodeString)
423     {
424         win_skip("RtlDuplicateUnicodeString is not available\n");
425         return;
426     }
427 
428     for (test_num = 0; test_num < NB_DUPL_USTR; test_num++) {
429 	source_str.Length        = dupl_ustr[test_num].source_Length;
430 	source_str.MaximumLength = dupl_ustr[test_num].source_MaximumLength;
431 	if (dupl_ustr[test_num].source_buf != NULL) {
432 	    for (pos = 0; pos < dupl_ustr[test_num].source_buf_size/sizeof(WCHAR); pos++) {
433 		source_buf[pos] = dupl_ustr[test_num].source_buf[pos];
434 	    }
435 	    source_str.Buffer = source_buf;
436 	} else {
437 	    source_str.Buffer = NULL;
438 	}
439 	dest_str.Length        = dupl_ustr[test_num].dest_Length;
440 	dest_str.MaximumLength = dupl_ustr[test_num].dest_MaximumLength;
441 	if (dupl_ustr[test_num].dest_buf != NULL) {
442 	    for (pos = 0; pos < dupl_ustr[test_num].dest_buf_size/sizeof(WCHAR); pos++) {
443 		dest_buf[pos] = dupl_ustr[test_num].dest_buf[pos];
444 	    }
445 	    dest_str.Buffer = dest_buf;
446 	} else {
447 	    dest_str.Buffer = NULL;
448 	}
449 	res_str.Length        = dupl_ustr[test_num].res_Length;
450 	res_str.MaximumLength = dupl_ustr[test_num].res_MaximumLength;
451 	if (dupl_ustr[test_num].res_buf != NULL) {
452 	    for (pos = 0; pos < dupl_ustr[test_num].res_buf_size/sizeof(WCHAR); pos++) {
453 		res_buf[pos] = dupl_ustr[test_num].res_buf[pos];
454 	    }
455 	    res_str.Buffer = res_buf;
456 	} else {
457 	    res_str.Buffer = NULL;
458 	}
459 	result = pRtlDuplicateUnicodeString(dupl_ustr[test_num].add_nul, &source_str, &dest_str);
460         dest_ansi_str.Length = dest_str.Length / sizeof(WCHAR);
461         dest_ansi_str.MaximumLength = dest_ansi_str.Length + 1;
462         for (pos = 0; pos < dest_ansi_str.Length; pos++) {
463        	    dest_ansi_buf[pos] = (char)dest_buf[pos];
464         }
465         dest_ansi_buf[dest_ansi_str.Length] = '\0';
466         dest_ansi_str.Buffer = dest_ansi_buf;
467 	ok(result == dupl_ustr[test_num].result,
468            "(test %d): RtlDuplicateUnicodeString(%d, source, dest) has result %x, expected %x\n",
469 	   test_num, dupl_ustr[test_num].add_nul, result, dupl_ustr[test_num].result);
470 	ok(dest_str.Length == dupl_ustr[test_num].res_Length,
471 	   "(test %d): RtlDuplicateUnicodeString(%d, source, dest) destination has Length %d, expected %d\n",
472 	   test_num, dupl_ustr[test_num].add_nul, dest_str.Length, dupl_ustr[test_num].res_Length);
473 	ok(dest_str.MaximumLength == dupl_ustr[test_num].res_MaximumLength,
474 	   "(test %d): RtlDuplicateUnicodeString(%d, source, dest) destination has MaximumLength %d, expected %d\n",
475 	   test_num, dupl_ustr[test_num].add_nul, dest_str.MaximumLength, dupl_ustr[test_num].res_MaximumLength);
476         if (result == STATUS_INVALID_PARAMETER) {
477 	    ok((dest_str.Buffer == NULL && res_str.Buffer == NULL) ||
478                dest_str.Buffer == dest_buf,
479 	       "(test %d): RtlDuplicateUnicodeString(%d, source, dest) destination buffer changed %p expected %p\n",
480 	       test_num, dupl_ustr[test_num].add_nul, dest_str.Buffer, dest_buf);
481         } else {
482 	    ok(dest_str.Buffer != dest_buf,
483 	       "(test %d): RtlDuplicateUnicodeString(%d, source, dest) has destination buffer unchanged %p\n",
484 	       test_num, dupl_ustr[test_num].add_nul, dest_str.Buffer);
485         }
486         if (dest_str.Buffer != NULL && dupl_ustr[test_num].res_buf != NULL) {
487 	    ok(memcmp(dest_str.Buffer, res_str.Buffer, dupl_ustr[test_num].res_buf_size) == 0,
488 	       "(test %d): RtlDuplicateUnicodeString(%d, source, dest) has destination \"%s\" expected \"%s\"\n",
489 	       test_num, dupl_ustr[test_num].add_nul, dest_ansi_str.Buffer, dupl_ustr[test_num].res_buf);
490             if(result == STATUS_SUCCESS) pRtlFreeUnicodeString(&dest_str);
491         } else {
492 	    ok(dest_str.Buffer == NULL && dupl_ustr[test_num].res_buf == NULL,
493 	       "(test %d): RtlDuplicateUnicodeString(%d, source, dest) has destination %p expected %p\n",
494 	       test_num, dupl_ustr[test_num].add_nul, dest_str.Buffer, dupl_ustr[test_num].res_buf);
495         }
496     }
497 }
498 
499 
500 static void test_RtlCopyString(void)
501 {
502     static const char teststring[] = "Some Wild String";
503     char deststring[] = "                    ";
504     STRING str;
505     STRING deststr;
506 
507     pRtlInitString(&str, teststring);
508     pRtlInitString(&deststr, deststring);
509     pRtlCopyString(&deststr, &str);
510     ok(strncmp(str.Buffer, deststring, str.Length) == 0, "String not copied\n");
511 }
512 
513 
514 static void test_RtlUpperChar(void)
515 {
516     int ch;
517     int upper_ch;
518     int expected_upper_ch;
519     int byte_ch;
520 
521     for (ch = -1; ch <= 1024; ch++) {
522 	upper_ch = pRtlUpperChar(ch);
523 	byte_ch = ch & 0xff;
524 	if (byte_ch >= 'a' && byte_ch <= 'z') {
525 	    expected_upper_ch = (CHAR) (byte_ch - 'a' + 'A');
526 	} else {
527 	    expected_upper_ch = (CHAR) byte_ch;
528 	}
529 	ok(upper_ch == expected_upper_ch,
530 	   "RtlUpperChar('%c'[=0x%x]) has result '%c'[=0x%x], expected '%c'[=0x%x]\n",
531 	   ch, ch, upper_ch, upper_ch, expected_upper_ch, expected_upper_ch);
532     }
533 }
534 
535 
536 static void test_RtlUpperString(void)
537 {
538     int i;
539     CHAR ch;
540     CHAR upper_ch;
541     char ascii_buf[257];
542     char result_buf[257];
543     char upper_buf[257];
544     STRING ascii_str;
545     STRING result_str;
546     STRING upper_str;
547 
548     for (i = 0; i <= 255; i++) {
549 	ch = (CHAR) i;
550 	if (ch >= 'a' && ch <= 'z') {
551 	    upper_ch = ch - 'a' + 'A';
552 	} else {
553 	    upper_ch = ch;
554 	}
555 	ascii_buf[i] = ch;
556 	result_buf[i] = '\0';
557 	upper_buf[i] = upper_ch;
558     }
559     ascii_buf[i] = '\0';
560     result_buf[i] = '\0';
561     upper_buf[i] = '\0';
562     ascii_str.Length = 256;
563     ascii_str.MaximumLength = 256;
564     ascii_str.Buffer = ascii_buf;
565     result_str.Length = 256;
566     result_str.MaximumLength = 256;
567     result_str.Buffer = result_buf;
568     upper_str.Length = 256;
569     upper_str.MaximumLength = 256;
570     upper_str.Buffer = upper_buf;
571 
572     pRtlUpperString(&result_str, &ascii_str);
573     ok(memcmp(result_str.Buffer, upper_str.Buffer, 256) == 0,
574        "RtlUpperString does not work as expected\n");
575 }
576 
577 
578 static void test_RtlUpcaseUnicodeChar(void)
579 {
580     int i;
581     WCHAR ch;
582     WCHAR upper_ch;
583     WCHAR expected_upper_ch;
584 
585     for (i = 0; i <= 255; i++) {
586 	ch = (WCHAR) i;
587 	upper_ch = pRtlUpcaseUnicodeChar(ch);
588 	if (ch >= 'a' && ch <= 'z') {
589 	    expected_upper_ch = ch - 'a' + 'A';
590 	} else if (ch >= 0xe0 && ch <= 0xfe && ch != 0xf7) {
591 	    expected_upper_ch = ch - 0x20;
592 	} else if (ch == 0xff) {
593 	    expected_upper_ch = 0x178;
594 	} else {
595 	    expected_upper_ch = ch;
596 	}
597 	ok(upper_ch == expected_upper_ch,
598 	   "RtlUpcaseUnicodeChar('%c'[=0x%x]) has result '%c'[=0x%x], expected: '%c'[=0x%x]\n",
599 	   ch, ch, upper_ch, upper_ch, expected_upper_ch, expected_upper_ch);
600     }
601 }
602 
603 
604 static void test_RtlUpcaseUnicodeString(void)
605 {
606     int i;
607     WCHAR ch;
608     WCHAR upper_ch;
609     WCHAR ascii_buf[257];
610     WCHAR result_buf[257];
611     WCHAR upper_buf[257];
612     UNICODE_STRING ascii_str;
613     UNICODE_STRING result_str;
614     UNICODE_STRING upper_str;
615 
616     for (i = 0; i <= 255; i++) {
617 	ch = (WCHAR) i;
618 	if (ch >= 'a' && ch <= 'z') {
619 	    upper_ch = ch - 'a' + 'A';
620 	} else if (ch >= 0xe0 && ch <= 0xfe && ch != 0xf7) {
621 	    upper_ch = ch - 0x20;
622 	} else if (ch == 0xff) {
623 	    upper_ch = 0x178;
624 	} else {
625 	    upper_ch = ch;
626 	}
627 	ascii_buf[i] = ch;
628 	result_buf[i] = '\0';
629 	upper_buf[i] = upper_ch;
630     }
631     ascii_buf[i] = '\0';
632     result_buf[i] = '\0';
633     upper_buf[i] = '\0';
634     ascii_str.Length = 512;
635     ascii_str.MaximumLength = 512;
636     ascii_str.Buffer = ascii_buf;
637     result_str.Length = 512;
638     result_str.MaximumLength = 512;
639     result_str.Buffer = result_buf;
640     upper_str.Length = 512;
641     upper_str.MaximumLength = 512;
642     upper_str.Buffer = upper_buf;
643 
644     pRtlUpcaseUnicodeString(&result_str, &ascii_str, 0);
645     for (i = 0; i <= 255; i++) {
646 	ok(result_str.Buffer[i] == upper_str.Buffer[i],
647 	   "RtlUpcaseUnicodeString works wrong: '%c'[=0x%x] is converted to '%c'[=0x%x], expected: '%c'[=0x%x]\n",
648 	   ascii_str.Buffer[i], ascii_str.Buffer[i],
649 	   result_str.Buffer[i], result_str.Buffer[i],
650 	   upper_str.Buffer[i], upper_str.Buffer[i]);
651     }
652 }
653 
654 
655 static void test_RtlDowncaseUnicodeString(void)
656 {
657     int i;
658     WCHAR ch;
659     WCHAR lower_ch;
660     WCHAR source_buf[1025];
661     WCHAR result_buf[1025];
662     WCHAR lower_buf[1025];
663     UNICODE_STRING source_str;
664     UNICODE_STRING result_str;
665     UNICODE_STRING lower_str;
666 
667     for (i = 0; i < 1024; i++) {
668 	ch = (WCHAR) i;
669 	if (ch >= 'A' && ch <= 'Z') {
670 	    lower_ch = ch - 'A' + 'a';
671 	} else if (ch >= 0xc0 && ch <= 0xde && ch != 0xd7) {
672 	    lower_ch = ch + 0x20;
673 	} else if (ch >= 0x391 && ch <= 0x3ab && ch != 0x3a2) {
674 	    lower_ch = ch + 0x20;
675 	} else {
676 	    switch (ch) {
677 		case 0x178: lower_ch = 0xff; break;
678 		case 0x181: lower_ch = 0x253; break;
679 		case 0x186: lower_ch = 0x254; break;
680 		case 0x189: lower_ch = 0x256; break;
681 		case 0x18a: lower_ch = 0x257; break;
682 		case 0x18e: lower_ch = 0x1dd; break;
683 		case 0x18f: lower_ch = 0x259; break;
684 		case 0x190: lower_ch = 0x25b; break;
685 		case 0x193: lower_ch = 0x260; break;
686 		case 0x194: lower_ch = 0x263; break;
687 		case 0x196: lower_ch = 0x269; break;
688 		case 0x197: lower_ch = 0x268; break;
689 		case 0x19c: lower_ch = 0x26f; break;
690 		case 0x19d: lower_ch = 0x272; break;
691 		case 0x19f: lower_ch = 0x275; break;
692 		case 0x1a9: lower_ch = 0x283; break;
693 		case 0x1ae: lower_ch = 0x288; break;
694 		case 0x1b1: lower_ch = 0x28a; break;
695 		case 0x1b2: lower_ch = 0x28b; break;
696 		case 0x1b7: lower_ch = 0x292; break;
697 		case 0x1c4: lower_ch = 0x1c6; break;
698 		case 0x1c7: lower_ch = 0x1c9; break;
699 		case 0x1ca: lower_ch = 0x1cc; break;
700 		case 0x1f1: lower_ch = 0x1f3; break;
701 		case 0x386: lower_ch = 0x3ac; break;
702 		case 0x388: lower_ch = 0x3ad; break;
703 		case 0x389: lower_ch = 0x3ae; break;
704 		case 0x38a: lower_ch = 0x3af; break;
705 		case 0x38c: lower_ch = 0x3cc; break;
706 		case 0x38e: lower_ch = 0x3cd; break;
707 		case 0x38f: lower_ch = 0x3ce; break;
708 		default: lower_ch = ch; break;
709 	    } /* switch */
710 	}
711 	source_buf[i] = ch;
712 	result_buf[i] = '\0';
713 	lower_buf[i] = lower_ch;
714     }
715     source_buf[i] = '\0';
716     result_buf[i] = '\0';
717     lower_buf[i] = '\0';
718     source_str.Length = 2048;
719     source_str.MaximumLength = 2048;
720     source_str.Buffer = source_buf;
721     result_str.Length = 2048;
722     result_str.MaximumLength = 2048;
723     result_str.Buffer = result_buf;
724     lower_str.Length = 2048;
725     lower_str.MaximumLength = 2048;
726     lower_str.Buffer = lower_buf;
727 
728     pRtlDowncaseUnicodeString(&result_str, &source_str, 0);
729     for (i = 0; i <= 1024; i++) {
730 	ok(result_str.Buffer[i] == lower_str.Buffer[i] || result_str.Buffer[i] == source_str.Buffer[i] + 1,
731 	   "RtlDowncaseUnicodeString works wrong: '%c'[=0x%x] is converted to '%c'[=0x%x], expected: '%c'[=0x%x]\n",
732 	   source_str.Buffer[i], source_str.Buffer[i],
733 	   result_str.Buffer[i], result_str.Buffer[i],
734 	   lower_str.Buffer[i], lower_str.Buffer[i]);
735     }
736 }
737 
738 
739 typedef struct {
740     int ansi_Length;
741     int ansi_MaximumLength;
742     int ansi_buf_size;
743     const char *ansi_buf;
744     int uni_Length;
745     int uni_MaximumLength;
746     int uni_buf_size;
747     const char *uni_buf;
748     BOOLEAN doalloc;
749     int res_Length;
750     int res_MaximumLength;
751     int res_buf_size;
752     const char *res_buf;
753     NTSTATUS result;
754 } ustr2astr_t;
755 
756 static const ustr2astr_t ustr2astr[] = {
757     { 10, 12, 12, "------------",  0,  0,  0, "",       TRUE,  0, 1, 1, "",       STATUS_SUCCESS},
758     { 10, 12, 12, "------------", 12, 12, 12, "abcdef", TRUE,  6, 7, 7, "abcdef", STATUS_SUCCESS},
759     {  0,  2, 12, "------------", 12, 12, 12, "abcdef", TRUE,  6, 7, 7, "abcdef", STATUS_SUCCESS},
760     { 10, 12, 12, NULL,           12, 12, 12, "abcdef", TRUE,  6, 7, 7, "abcdef", STATUS_SUCCESS},
761     {  0,  0, 12, "------------", 12, 12, 12, "abcdef", FALSE, 6, 0, 0, "",       STATUS_BUFFER_OVERFLOW},
762     {  0,  1, 12, "------------", 12, 12, 12, "abcdef", FALSE, 0, 1, 1, "",       STATUS_BUFFER_OVERFLOW},
763     {  0,  2, 12, "------------", 12, 12, 12, "abcdef", FALSE, 1, 2, 2, "a",      STATUS_BUFFER_OVERFLOW},
764     {  0,  3, 12, "------------", 12, 12, 12, "abcdef", FALSE, 2, 3, 3, "ab",     STATUS_BUFFER_OVERFLOW},
765     {  0,  5, 12, "------------", 12, 12, 12, "abcdef", FALSE, 4, 5, 5, "abcd",   STATUS_BUFFER_OVERFLOW},
766     {  8,  5, 12, "------------", 12, 12, 12, "abcdef", FALSE, 4, 5, 5, "abcd",   STATUS_BUFFER_OVERFLOW},
767     {  8,  6, 12, "------------", 12, 12, 12, "abcdef", FALSE, 5, 6, 6, "abcde",  STATUS_BUFFER_OVERFLOW},
768     {  8,  7, 12, "------------", 12, 12, 12, "abcdef", FALSE, 6, 7, 7, "abcdef", STATUS_SUCCESS},
769     {  8,  7, 12, "------------",  0, 12, 12,  NULL,    FALSE, 0, 7, 0, "",       STATUS_SUCCESS},
770 #if 0
771     /* crashes on Japanese and Chinese XP */
772     {  0,  0, 12, NULL,           10, 10, 12,  NULL,    FALSE, 5, 0, 0, NULL,     STATUS_BUFFER_OVERFLOW},
773 #endif
774 };
775 #define NB_USTR2ASTR (sizeof(ustr2astr)/sizeof(*ustr2astr))
776 
777 
778 static void test_RtlUnicodeStringToAnsiString(void)
779 {
780     size_t pos;
781     CHAR ansi_buf[257];
782     WCHAR uni_buf[257];
783     STRING ansi_str;
784     UNICODE_STRING uni_str;
785     NTSTATUS result;
786     unsigned int test_num;
787 
788     for (test_num = 0; test_num < NB_USTR2ASTR; test_num++) {
789 	ansi_str.Length        = ustr2astr[test_num].ansi_Length;
790 	ansi_str.MaximumLength = ustr2astr[test_num].ansi_MaximumLength;
791 	if (ustr2astr[test_num].ansi_buf != NULL) {
792 	    memcpy(ansi_buf, ustr2astr[test_num].ansi_buf, ustr2astr[test_num].ansi_buf_size);
793 	    ansi_buf[ustr2astr[test_num].ansi_buf_size] = '\0';
794 	    ansi_str.Buffer = ansi_buf;
795 	} else {
796 	    ansi_str.Buffer = NULL;
797 	}
798 	uni_str.Length        = ustr2astr[test_num].uni_Length;
799 	uni_str.MaximumLength = ustr2astr[test_num].uni_MaximumLength;
800 	if (ustr2astr[test_num].uni_buf != NULL) {
801 	    for (pos = 0; pos < ustr2astr[test_num].uni_buf_size/sizeof(WCHAR); pos++) {
802 		uni_buf[pos] = ustr2astr[test_num].uni_buf[pos];
803 	    }
804 	    uni_str.Buffer = uni_buf;
805 	} else {
806 	    uni_str.Buffer = NULL;
807 	}
808 	result = pRtlUnicodeStringToAnsiString(&ansi_str, &uni_str, ustr2astr[test_num].doalloc);
809 	ok(result == ustr2astr[test_num].result,
810            "(test %d): RtlUnicodeStringToAnsiString(ansi, uni, %d) has result %x, expected %x\n",
811 	   test_num, ustr2astr[test_num].doalloc, result, ustr2astr[test_num].result);
812 	ok(ansi_str.Length == ustr2astr[test_num].res_Length,
813 	   "(test %d): RtlUnicodeStringToAnsiString(ansi, uni, %d) ansi has Length %d, expected %d\n",
814 	   test_num, ustr2astr[test_num].doalloc, ansi_str.Length, ustr2astr[test_num].res_Length);
815 	ok(ansi_str.MaximumLength == ustr2astr[test_num].res_MaximumLength,
816 	   "(test %d): RtlUnicodeStringToAnsiString(ansi, uni, %d) ansi has MaximumLength %d, expected %d\n",
817 	   test_num, ustr2astr[test_num].doalloc, ansi_str.MaximumLength, ustr2astr[test_num].res_MaximumLength);
818 	ok(memcmp(ansi_str.Buffer, ustr2astr[test_num].res_buf, ustr2astr[test_num].res_buf_size) == 0,
819 	   "(test %d): RtlUnicodeStringToAnsiString(ansi, uni, %d) has ansi \"%s\" expected \"%s\"\n",
820 	   test_num, ustr2astr[test_num].doalloc, ansi_str.Buffer, ustr2astr[test_num].res_buf);
821         if(result == STATUS_SUCCESS && ustr2astr[test_num].doalloc)
822             pRtlFreeAnsiString(&ansi_str);
823     }
824 }
825 
826 
827 typedef struct {
828     int dest_Length;
829     int dest_MaximumLength;
830     int dest_buf_size;
831     const char *dest_buf;
832     const char *src;
833     int res_Length;
834     int res_MaximumLength;
835     int res_buf_size;
836     const char *res_buf;
837     NTSTATUS result;
838 } app_asc2str_t;
839 
840 static const app_asc2str_t app_asc2str[] = {
841     { 5, 12, 15,  "TestS01234abcde", "tring", 10, 12, 15,  "TestStringabcde", STATUS_SUCCESS},
842     { 5, 11, 15,  "TestS01234abcde", "tring", 10, 11, 15,  "TestStringabcde", STATUS_SUCCESS},
843     { 5, 10, 15,  "TestS01234abcde", "tring", 10, 10, 15,  "TestStringabcde", STATUS_SUCCESS},
844     { 5,  9, 15,  "TestS01234abcde", "tring",  5,  9, 15,  "TestS01234abcde", STATUS_BUFFER_TOO_SMALL},
845     { 5,  0, 15,  "TestS01234abcde", "tring",  5,  0, 15,  "TestS01234abcde", STATUS_BUFFER_TOO_SMALL},
846     { 5, 14, 15,  "TestS01234abcde", "tring", 10, 14, 15,  "TestStringabcde", STATUS_SUCCESS},
847     { 5, 14, 15,  "TestS01234abcde",    NULL,  5, 14, 15,  "TestS01234abcde", STATUS_SUCCESS},
848     { 5, 14, 15,               NULL,    NULL,  5, 14, 15,               NULL, STATUS_SUCCESS},
849     { 5, 12, 15, "Tst\0S01234abcde", "tr\0i",  7, 12, 15, "Tst\0Str234abcde", STATUS_SUCCESS},
850 };
851 #define NB_APP_ASC2STR (sizeof(app_asc2str)/sizeof(*app_asc2str))
852 
853 
854 static void test_RtlAppendAsciizToString(void)
855 {
856     CHAR dest_buf[257];
857     STRING dest_str;
858     NTSTATUS result;
859     unsigned int test_num;
860 
861     for (test_num = 0; test_num < NB_APP_ASC2STR; test_num++) {
862 	dest_str.Length        = app_asc2str[test_num].dest_Length;
863 	dest_str.MaximumLength = app_asc2str[test_num].dest_MaximumLength;
864 	if (app_asc2str[test_num].dest_buf != NULL) {
865 	    memcpy(dest_buf, app_asc2str[test_num].dest_buf, app_asc2str[test_num].dest_buf_size);
866 	    dest_buf[app_asc2str[test_num].dest_buf_size] = '\0';
867 	    dest_str.Buffer = dest_buf;
868 	} else {
869 	    dest_str.Buffer = NULL;
870 	}
871 	result = pRtlAppendAsciizToString(&dest_str, app_asc2str[test_num].src);
872 	ok(result == app_asc2str[test_num].result,
873            "(test %d): RtlAppendAsciizToString(dest, src) has result %x, expected %x\n",
874 	   test_num, result, app_asc2str[test_num].result);
875 	ok(dest_str.Length == app_asc2str[test_num].res_Length,
876 	   "(test %d): RtlAppendAsciizToString(dest, src) dest has Length %d, expected %d\n",
877 	   test_num, dest_str.Length, app_asc2str[test_num].res_Length);
878 	ok(dest_str.MaximumLength == app_asc2str[test_num].res_MaximumLength,
879 	   "(test %d): RtlAppendAsciizToString(dest, src) dest has MaximumLength %d, expected %d\n",
880 	   test_num, dest_str.MaximumLength, app_asc2str[test_num].res_MaximumLength);
881 	if (dest_str.Buffer == dest_buf) {
882 	    ok(memcmp(dest_buf, app_asc2str[test_num].res_buf, app_asc2str[test_num].res_buf_size) == 0,
883 	       "(test %d): RtlAppendAsciizToString(dest, src) has dest \"%s\" expected \"%s\"\n",
884 	       test_num, dest_buf, app_asc2str[test_num].res_buf);
885 	} else {
886 	    ok(dest_str.Buffer == app_asc2str[test_num].res_buf,
887 	       "(test %d): RtlAppendAsciizToString(dest, src) dest has Buffer %p expected %p\n",
888 	       test_num, dest_str.Buffer, app_asc2str[test_num].res_buf);
889 	}
890     }
891 }
892 
893 
894 typedef struct {
895     int dest_Length;
896     int dest_MaximumLength;
897     int dest_buf_size;
898     const char *dest_buf;
899     int src_Length;
900     int src_MaximumLength;
901     int src_buf_size;
902     const char *src_buf;
903     int res_Length;
904     int res_MaximumLength;
905     int res_buf_size;
906     const char *res_buf;
907     NTSTATUS result;
908 } app_str2str_t;
909 
910 static const app_str2str_t app_str2str[] = {
911     { 5, 12, 15,  "TestS01234abcde", 5, 5, 7, "tringZY", 10, 12, 15,   "TestStringabcde", STATUS_SUCCESS},
912     { 5, 11, 15,  "TestS01234abcde", 5, 5, 7, "tringZY", 10, 11, 15,   "TestStringabcde", STATUS_SUCCESS},
913     { 5, 10, 15,  "TestS01234abcde", 5, 5, 7, "tringZY", 10, 10, 15,   "TestStringabcde", STATUS_SUCCESS},
914     { 5,  9, 15,  "TestS01234abcde", 5, 5, 7, "tringZY",  5,  9, 15,   "TestS01234abcde", STATUS_BUFFER_TOO_SMALL},
915     { 5,  0, 15,  "TestS01234abcde", 0, 0, 7, "tringZY",  5,  0, 15,   "TestS01234abcde", STATUS_SUCCESS},
916     { 5, 14, 15,  "TestS01234abcde", 0, 0, 7, "tringZY",  5, 14, 15,   "TestS01234abcde", STATUS_SUCCESS},
917     { 5, 14, 15,  "TestS01234abcde", 0, 0, 7,      NULL,  5, 14, 15,   "TestS01234abcde", STATUS_SUCCESS},
918     { 5, 14, 15,               NULL, 0, 0, 7,      NULL,  5, 14, 15,                NULL, STATUS_SUCCESS},
919     { 5, 12, 15, "Tst\0S01234abcde", 4, 4, 7, "tr\0iZY",  9, 12, 15, "Tst\0Str\0i4abcde", STATUS_SUCCESS},
920 };
921 #define NB_APP_STR2STR (sizeof(app_str2str)/sizeof(*app_str2str))
922 
923 
924 static void test_RtlAppendStringToString(void)
925 {
926     CHAR dest_buf[257];
927     CHAR src_buf[257];
928     STRING dest_str;
929     STRING src_str;
930     NTSTATUS result;
931     unsigned int test_num;
932 
933     for (test_num = 0; test_num < NB_APP_STR2STR; test_num++) {
934 	dest_str.Length        = app_str2str[test_num].dest_Length;
935 	dest_str.MaximumLength = app_str2str[test_num].dest_MaximumLength;
936 	if (app_str2str[test_num].dest_buf != NULL) {
937 	    memcpy(dest_buf, app_str2str[test_num].dest_buf, app_str2str[test_num].dest_buf_size);
938 	    dest_buf[app_str2str[test_num].dest_buf_size] = '\0';
939 	    dest_str.Buffer = dest_buf;
940 	} else {
941 	    dest_str.Buffer = NULL;
942 	}
943 	src_str.Length         = app_str2str[test_num].src_Length;
944 	src_str.MaximumLength  = app_str2str[test_num].src_MaximumLength;
945 	if (app_str2str[test_num].src_buf != NULL) {
946 	    memcpy(src_buf, app_str2str[test_num].src_buf, app_str2str[test_num].src_buf_size);
947 	    src_buf[app_str2str[test_num].src_buf_size] = '\0';
948 	    src_str.Buffer = src_buf;
949 	} else {
950 	    src_str.Buffer = NULL;
951 	}
952 	result = pRtlAppendStringToString(&dest_str, &src_str);
953 	ok(result == app_str2str[test_num].result,
954            "(test %d): RtlAppendStringToString(dest, src) has result %x, expected %x\n",
955 	   test_num, result, app_str2str[test_num].result);
956 	ok(dest_str.Length == app_str2str[test_num].res_Length,
957 	   "(test %d): RtlAppendStringToString(dest, src) dest has Length %d, expected %d\n",
958 	   test_num, dest_str.Length, app_str2str[test_num].res_Length);
959 	ok(dest_str.MaximumLength == app_str2str[test_num].res_MaximumLength,
960 	   "(test %d): RtlAppendStringToString(dest, src) dest has MaximumLength %d, expected %d\n",
961 	   test_num, dest_str.MaximumLength, app_str2str[test_num].res_MaximumLength);
962 	if (dest_str.Buffer == dest_buf) {
963 	    ok(memcmp(dest_buf, app_str2str[test_num].res_buf, app_str2str[test_num].res_buf_size) == 0,
964 	       "(test %d): RtlAppendStringToString(dest, src) has dest \"%s\" expected \"%s\"\n",
965 	       test_num, dest_buf, app_str2str[test_num].res_buf);
966 	} else {
967 	    ok(dest_str.Buffer == app_str2str[test_num].res_buf,
968 	       "(test %d): RtlAppendStringToString(dest, src) dest has Buffer %p expected %p\n",
969 	       test_num, dest_str.Buffer, app_str2str[test_num].res_buf);
970 	}
971     }
972 }
973 
974 
975 typedef struct {
976     int dest_Length;
977     int dest_MaximumLength;
978     int dest_buf_size;
979     const char *dest_buf;
980     const char *src;
981     int res_Length;
982     int res_MaximumLength;
983     int res_buf_size;
984     const char *res_buf;
985     NTSTATUS result;
986 } app_uni2str_t;
987 
988 static const app_uni2str_t app_uni2str[] = {
989     { 4, 12, 14,     "Fake0123abcdef",    "Ustr\0",  8, 12, 14,  "FakeUstr\0\0cdef", STATUS_SUCCESS},
990     { 4, 11, 14,     "Fake0123abcdef",    "Ustr\0",  8, 11, 14,  "FakeUstr\0\0cdef", STATUS_SUCCESS},
991     { 4, 10, 14,     "Fake0123abcdef",    "Ustr\0",  8, 10, 14,  "FakeUstr\0\0cdef", STATUS_SUCCESS},
992 /* In the following test the native function writes beyond MaximumLength
993  *  { 4,  9, 14,     "Fake0123abcdef",    "Ustr\0",  8,  9, 14,    "FakeUstrabcdef", STATUS_SUCCESS},
994  */
995     { 4,  8, 14,     "Fake0123abcdef",    "Ustr\0",  8,  8, 14,    "FakeUstrabcdef", STATUS_SUCCESS},
996     { 4,  7, 14,     "Fake0123abcdef",    "Ustr\0",  4,  7, 14,    "Fake0123abcdef", STATUS_BUFFER_TOO_SMALL},
997     { 4,  0, 14,     "Fake0123abcdef",    "Ustr\0",  4,  0, 14,    "Fake0123abcdef", STATUS_BUFFER_TOO_SMALL},
998     { 4, 14, 14,     "Fake0123abcdef",    "Ustr\0",  8, 14, 14,  "FakeUstr\0\0cdef", STATUS_SUCCESS},
999     { 4, 14, 14,     "Fake0123abcdef",        NULL,  4, 14, 14,    "Fake0123abcdef", STATUS_SUCCESS},
1000     { 4, 14, 14,                 NULL,        NULL,  4, 14, 14,                NULL, STATUS_SUCCESS},
1001     { 4, 14, 14,     "Fake0123abcdef", "U\0stri\0", 10, 14, 14, "FakeU\0stri\0\0ef", STATUS_SUCCESS},
1002     { 6, 14, 16, "Te\0\0stabcdefghij",  "St\0\0ri",  8, 14, 16, "Te\0\0stSt\0\0efghij", STATUS_SUCCESS},
1003 };
1004 #define NB_APP_UNI2STR (sizeof(app_uni2str)/sizeof(*app_uni2str))
1005 
1006 
1007 static void test_RtlAppendUnicodeToString(void)
1008 {
1009     WCHAR dest_buf[257];
1010     UNICODE_STRING dest_str;
1011     NTSTATUS result;
1012     unsigned int test_num;
1013 
1014     for (test_num = 0; test_num < NB_APP_UNI2STR; test_num++) {
1015 	dest_str.Length        = app_uni2str[test_num].dest_Length;
1016 	dest_str.MaximumLength = app_uni2str[test_num].dest_MaximumLength;
1017 	if (app_uni2str[test_num].dest_buf != NULL) {
1018 	    memcpy(dest_buf, app_uni2str[test_num].dest_buf, app_uni2str[test_num].dest_buf_size);
1019 	    dest_buf[app_uni2str[test_num].dest_buf_size/sizeof(WCHAR)] = '\0';
1020 	    dest_str.Buffer = dest_buf;
1021 	} else {
1022 	    dest_str.Buffer = NULL;
1023 	}
1024 	result = pRtlAppendUnicodeToString(&dest_str, (LPCWSTR) app_uni2str[test_num].src);
1025 	ok(result == app_uni2str[test_num].result,
1026            "(test %d): RtlAppendUnicodeToString(dest, src) has result %x, expected %x\n",
1027 	   test_num, result, app_uni2str[test_num].result);
1028 	ok(dest_str.Length == app_uni2str[test_num].res_Length,
1029 	   "(test %d): RtlAppendUnicodeToString(dest, src) dest has Length %d, expected %d\n",
1030 	   test_num, dest_str.Length, app_uni2str[test_num].res_Length);
1031 	ok(dest_str.MaximumLength == app_uni2str[test_num].res_MaximumLength,
1032 	   "(test %d): RtlAppendUnicodeToString(dest, src) dest has MaximumLength %d, expected %d\n",
1033 	   test_num, dest_str.MaximumLength, app_uni2str[test_num].res_MaximumLength);
1034 	if (dest_str.Buffer == dest_buf) {
1035 	    ok(memcmp(dest_buf, app_uni2str[test_num].res_buf, app_uni2str[test_num].res_buf_size) == 0,
1036 	       "(test %d): RtlAppendUnicodeToString(dest, src) has dest \"%s\" expected \"%s\"\n",
1037 	       test_num, (char *) dest_buf, app_uni2str[test_num].res_buf);
1038 	} else {
1039 	    ok(dest_str.Buffer == (WCHAR *) app_uni2str[test_num].res_buf,
1040 	       "(test %d): RtlAppendUnicodeToString(dest, src) dest has Buffer %p expected %p\n",
1041 	       test_num, dest_str.Buffer, app_uni2str[test_num].res_buf);
1042 	}
1043     }
1044 }
1045 
1046 
1047 typedef struct {
1048     int dest_Length;
1049     int dest_MaximumLength;
1050     int dest_buf_size;
1051     const char *dest_buf;
1052     int src_Length;
1053     int src_MaximumLength;
1054     int src_buf_size;
1055     const char *src_buf;
1056     int res_Length;
1057     int res_MaximumLength;
1058     int res_buf_size;
1059     const char *res_buf;
1060     NTSTATUS result;
1061 } app_ustr2str_t;
1062 
1063 static const app_ustr2str_t app_ustr2str[] = {
1064     { 4, 12, 14,     "Fake0123abcdef", 4, 6, 8,   "UstrZYXW",  8, 12, 14,   "FakeUstr\0\0cdef", STATUS_SUCCESS},
1065     { 4, 11, 14,     "Fake0123abcdef", 4, 6, 8,   "UstrZYXW",  8, 11, 14,   "FakeUstr\0\0cdef", STATUS_SUCCESS},
1066     { 4, 10, 14,     "Fake0123abcdef", 4, 6, 8,   "UstrZYXW",  8, 10, 14,   "FakeUstr\0\0cdef", STATUS_SUCCESS},
1067 /* In the following test the native function writes beyond MaximumLength
1068  *  { 4,  9, 14,     "Fake0123abcdef", 4, 6, 8,   "UstrZYXW",  8,  9, 14,     "FakeUstrabcdef", STATUS_SUCCESS},
1069  */
1070     { 4,  8, 14,     "Fake0123abcdef", 4, 6, 8,   "UstrZYXW",  8,  8, 14,     "FakeUstrabcdef", STATUS_SUCCESS},
1071     { 4,  7, 14,     "Fake0123abcdef", 4, 6, 8,   "UstrZYXW",  4,  7, 14,     "Fake0123abcdef", STATUS_BUFFER_TOO_SMALL},
1072     { 4,  0, 14,     "Fake0123abcdef", 0, 0, 8,   "UstrZYXW",  4,  0, 14,     "Fake0123abcdef", STATUS_SUCCESS},
1073     { 4, 14, 14,     "Fake0123abcdef", 0, 0, 8,   "UstrZYXW",  4, 14, 14,     "Fake0123abcdef", STATUS_SUCCESS},
1074     { 4, 14, 14,     "Fake0123abcdef", 0, 0, 8,         NULL,  4, 14, 14,     "Fake0123abcdef", STATUS_SUCCESS},
1075     { 4, 14, 14,                 NULL, 0, 0, 8,         NULL,  4, 14, 14,                 NULL, STATUS_SUCCESS},
1076     { 6, 14, 16, "Te\0\0stabcdefghij", 6, 8, 8, "St\0\0riZY", 12, 14, 16, "Te\0\0stSt\0\0ri\0\0ij", STATUS_SUCCESS},
1077 };
1078 #define NB_APP_USTR2STR (sizeof(app_ustr2str)/sizeof(*app_ustr2str))
1079 
1080 
1081 static void test_RtlAppendUnicodeStringToString(void)
1082 {
1083     WCHAR dest_buf[257];
1084     WCHAR src_buf[257];
1085     UNICODE_STRING dest_str;
1086     UNICODE_STRING src_str;
1087     NTSTATUS result;
1088     unsigned int test_num;
1089 
1090     for (test_num = 0; test_num < NB_APP_USTR2STR; test_num++) {
1091 	dest_str.Length        = app_ustr2str[test_num].dest_Length;
1092 	dest_str.MaximumLength = app_ustr2str[test_num].dest_MaximumLength;
1093 	if (app_ustr2str[test_num].dest_buf != NULL) {
1094 	    memcpy(dest_buf, app_ustr2str[test_num].dest_buf, app_ustr2str[test_num].dest_buf_size);
1095 	    dest_buf[app_ustr2str[test_num].dest_buf_size/sizeof(WCHAR)] = '\0';
1096 	    dest_str.Buffer = dest_buf;
1097 	} else {
1098 	    dest_str.Buffer = NULL;
1099 	}
1100 	src_str.Length         = app_ustr2str[test_num].src_Length;
1101 	src_str.MaximumLength  = app_ustr2str[test_num].src_MaximumLength;
1102 	if (app_ustr2str[test_num].src_buf != NULL) {
1103 	    memcpy(src_buf, app_ustr2str[test_num].src_buf, app_ustr2str[test_num].src_buf_size);
1104 	    src_buf[app_ustr2str[test_num].src_buf_size/sizeof(WCHAR)] = '\0';
1105 	    src_str.Buffer = src_buf;
1106 	} else {
1107 	    src_str.Buffer = NULL;
1108 	}
1109 	result = pRtlAppendUnicodeStringToString(&dest_str, &src_str);
1110 	ok(result == app_ustr2str[test_num].result,
1111            "(test %d): RtlAppendStringToString(dest, src) has result %x, expected %x\n",
1112 	   test_num, result, app_ustr2str[test_num].result);
1113 	ok(dest_str.Length == app_ustr2str[test_num].res_Length,
1114 	   "(test %d): RtlAppendStringToString(dest, src) dest has Length %d, expected %d\n",
1115 	   test_num, dest_str.Length, app_ustr2str[test_num].res_Length);
1116 	ok(dest_str.MaximumLength == app_ustr2str[test_num].res_MaximumLength,
1117 	   "(test %d): RtlAppendStringToString(dest, src) dest has MaximumLength %d, expected %d\n",
1118 	   test_num, dest_str.MaximumLength, app_ustr2str[test_num].res_MaximumLength);
1119 	if (dest_str.Buffer == dest_buf) {
1120 	    ok(memcmp(dest_buf, app_ustr2str[test_num].res_buf, app_ustr2str[test_num].res_buf_size) == 0,
1121 	       "(test %d): RtlAppendStringToString(dest, src) has dest \"%s\" expected \"%s\"\n",
1122 	       test_num, (char *) dest_buf, app_ustr2str[test_num].res_buf);
1123 	} else {
1124 	    ok(dest_str.Buffer == (WCHAR *) app_ustr2str[test_num].res_buf,
1125 	       "(test %d): RtlAppendStringToString(dest, src) dest has Buffer %p expected %p\n",
1126 	       test_num, dest_str.Buffer, app_ustr2str[test_num].res_buf);
1127 	}
1128     }
1129 }
1130 
1131 
1132 typedef struct {
1133     int flags;
1134     const char *main_str;
1135     const char *search_chars;
1136     USHORT pos;
1137     NTSTATUS result;
1138 } find_ch_in_ustr_t;
1139 
1140 static const find_ch_in_ustr_t find_ch_in_ustr[] = {
1141     { 0, "Some Wild String",           "S",       2, STATUS_SUCCESS},
1142     { 0, "This is a String",           "String",  6, STATUS_SUCCESS},
1143     { 1, "This is a String",           "String", 30, STATUS_SUCCESS},
1144     { 2, "This is a String",           "String",  2, STATUS_SUCCESS},
1145     { 3, "This is a String",           "String", 18, STATUS_SUCCESS},
1146     { 0, "This is a String",           "Wild",    6, STATUS_SUCCESS},
1147     { 1, "This is a String",           "Wild",   26, STATUS_SUCCESS},
1148     { 2, "This is a String",           "Wild",    2, STATUS_SUCCESS},
1149     { 3, "This is a String",           "Wild",   30, STATUS_SUCCESS},
1150     { 0, "abcdefghijklmnopqrstuvwxyz", "",        0, STATUS_NOT_FOUND},
1151     { 0, "abcdefghijklmnopqrstuvwxyz", "123",     0, STATUS_NOT_FOUND},
1152     { 0, "abcdefghijklmnopqrstuvwxyz", "a",       2, STATUS_SUCCESS},
1153     { 0, "abcdefghijklmnopqrstuvwxyz", "12a34",   2, STATUS_SUCCESS},
1154     { 0, "abcdefghijklmnopqrstuvwxyz", "12b34",   4, STATUS_SUCCESS},
1155     { 0, "abcdefghijklmnopqrstuvwxyz", "12y34",  50, STATUS_SUCCESS},
1156     { 0, "abcdefghijklmnopqrstuvwxyz", "12z34",  52, STATUS_SUCCESS},
1157     { 0, "abcdefghijklmnopqrstuvwxyz", "rvz",    36, STATUS_SUCCESS},
1158     { 0, "abcdefghijklmmlkjihgfedcba", "egik",   10, STATUS_SUCCESS},
1159     { 1, "abcdefghijklmnopqrstuvwxyz", "",        0, STATUS_NOT_FOUND},
1160     { 1, "abcdefghijklmnopqrstuvwxyz", "rvz",    50, STATUS_SUCCESS},
1161     { 1, "abcdefghijklmnopqrstuvwxyz", "ravy",   48, STATUS_SUCCESS},
1162     { 1, "abcdefghijklmnopqrstuvwxyz", "raxv",   46, STATUS_SUCCESS},
1163     { 2, "abcdefghijklmnopqrstuvwxyz", "",        2, STATUS_SUCCESS},
1164     { 2, "abcdefghijklmnopqrstuvwxyz", "rvz",     2, STATUS_SUCCESS},
1165     { 2, "abcdefghijklmnopqrstuvwxyz", "vaz",     4, STATUS_SUCCESS},
1166     { 2, "abcdefghijklmnopqrstuvwxyz", "ravbz",   6, STATUS_SUCCESS},
1167     { 3, "abcdefghijklmnopqrstuvwxyz", "",       50, STATUS_SUCCESS},
1168     { 3, "abcdefghijklmnopqrstuvwxyz", "123",    50, STATUS_SUCCESS},
1169     { 3, "abcdefghijklmnopqrstuvwxyz", "ahp",    50, STATUS_SUCCESS},
1170     { 3, "abcdefghijklmnopqrstuvwxyz", "rvz",    48, STATUS_SUCCESS},
1171     { 0, NULL,                         "abc",     0, STATUS_NOT_FOUND},
1172     { 1, NULL,                         "abc",     0, STATUS_NOT_FOUND},
1173     { 2, NULL,                         "abc",     0, STATUS_NOT_FOUND},
1174     { 3, NULL,                         "abc",     0, STATUS_NOT_FOUND},
1175     { 0, "abcdefghijklmnopqrstuvwxyz", NULL,      0, STATUS_NOT_FOUND},
1176     { 1, "abcdefghijklmnopqrstuvwxyz", NULL,      0, STATUS_NOT_FOUND},
1177     { 2, "abcdefghijklmnopqrstuvwxyz", NULL,      2, STATUS_SUCCESS},
1178     { 3, "abcdefghijklmnopqrstuvwxyz", NULL,     50, STATUS_SUCCESS},
1179     { 0, NULL,                         NULL,      0, STATUS_NOT_FOUND},
1180     { 1, NULL,                         NULL,      0, STATUS_NOT_FOUND},
1181     { 2, NULL,                         NULL,      0, STATUS_NOT_FOUND},
1182     { 3, NULL,                         NULL,      0, STATUS_NOT_FOUND},
1183     { 0, "abcdabcdabcdabcdabcdabcd",   "abcd",    2, STATUS_SUCCESS},
1184     { 1, "abcdabcdabcdabcdabcdabcd",   "abcd",   46, STATUS_SUCCESS},
1185     { 2, "abcdabcdabcdabcdabcdabcd",   "abcd",    0, STATUS_NOT_FOUND},
1186     { 3, "abcdabcdabcdabcdabcdabcd",   "abcd",    0, STATUS_NOT_FOUND},
1187 };
1188 #define NB_FIND_CH_IN_USTR (sizeof(find_ch_in_ustr)/sizeof(*find_ch_in_ustr))
1189 
1190 
1191 static void test_RtlFindCharInUnicodeString(void)
1192 {
1193     WCHAR main_str_buf[257];
1194     WCHAR search_chars_buf[257];
1195     UNICODE_STRING main_str;
1196     UNICODE_STRING search_chars;
1197     USHORT pos;
1198     NTSTATUS result;
1199     unsigned int idx;
1200     unsigned int test_num;
1201 
1202     if (!pRtlFindCharInUnicodeString)
1203     {
1204         win_skip("RtlFindCharInUnicodeString is not available\n");
1205         return;
1206     }
1207 
1208     for (test_num = 0; test_num < NB_FIND_CH_IN_USTR; test_num++) {
1209 	if (find_ch_in_ustr[test_num].main_str != NULL) {
1210 	    main_str.Length        = strlen(find_ch_in_ustr[test_num].main_str) * sizeof(WCHAR);
1211 	    main_str.MaximumLength = main_str.Length + sizeof(WCHAR);
1212 	    for (idx = 0; idx < main_str.Length / sizeof(WCHAR); idx++) {
1213 		main_str_buf[idx] = find_ch_in_ustr[test_num].main_str[idx];
1214 	    }
1215 	    main_str.Buffer = main_str_buf;
1216 	} else {
1217 	    main_str.Length        = 0;
1218 	    main_str.MaximumLength = 0;
1219 	    main_str.Buffer        = NULL;
1220 	}
1221 	if (find_ch_in_ustr[test_num].search_chars != NULL) {
1222 	    search_chars.Length        = strlen(find_ch_in_ustr[test_num].search_chars) * sizeof(WCHAR);
1223 	    search_chars.MaximumLength = search_chars.Length + sizeof(WCHAR);
1224 	    for (idx = 0; idx < search_chars.Length / sizeof(WCHAR); idx++) {
1225 		search_chars_buf[idx] = find_ch_in_ustr[test_num].search_chars[idx];
1226 	    }
1227 	    search_chars.Buffer = search_chars_buf;
1228 	} else {
1229 	    search_chars.Length        = 0;
1230 	    search_chars.MaximumLength = 0;
1231 	    search_chars.Buffer        = NULL;
1232 	}
1233 	pos = 12345;
1234         result = pRtlFindCharInUnicodeString(find_ch_in_ustr[test_num].flags, &main_str, &search_chars, &pos);
1235         ok(result == find_ch_in_ustr[test_num].result,
1236            "(test %d): RtlFindCharInUnicodeString(%d, %s, %s, [out]) has result %x, expected %x\n",
1237            test_num, find_ch_in_ustr[test_num].flags,
1238            find_ch_in_ustr[test_num].main_str, find_ch_in_ustr[test_num].search_chars,
1239            result, find_ch_in_ustr[test_num].result);
1240         ok(pos == find_ch_in_ustr[test_num].pos,
1241            "(test %d): RtlFindCharInUnicodeString(%d, %s, %s, [out]) assigns %d to pos, expected %d\n",
1242            test_num, find_ch_in_ustr[test_num].flags,
1243            find_ch_in_ustr[test_num].main_str, find_ch_in_ustr[test_num].search_chars,
1244            pos, find_ch_in_ustr[test_num].pos);
1245     }
1246 }
1247 
1248 
1249 typedef struct {
1250     int base;
1251     const char *str;
1252     int value;
1253     NTSTATUS result, alternative;
1254 } str2int_t;
1255 
1256 static const str2int_t str2int[] = {
1257     { 0, "1011101100",   1011101100, STATUS_SUCCESS},
1258     { 0, "1234567",         1234567, STATUS_SUCCESS},
1259     { 0, "-214",               -214, STATUS_SUCCESS},
1260     { 0, "+214",                214, STATUS_SUCCESS}, /* The + sign is allowed also */
1261     { 0, "--214",                 0, STATUS_SUCCESS}, /* Do not accept more than one sign */
1262     { 0, "-+214",                 0, STATUS_SUCCESS},
1263     { 0, "++214",                 0, STATUS_SUCCESS},
1264     { 0, "+-214",                 0, STATUS_SUCCESS},
1265     { 0, "\001\002\003\00411",   11, STATUS_SUCCESS}, /* whitespace char  1 to  4 */
1266     { 0, "\005\006\007\01012",   12, STATUS_SUCCESS}, /* whitespace char  5 to  8 */
1267     { 0, "\011\012\013\01413",   13, STATUS_SUCCESS}, /* whitespace char  9 to 12 */
1268     { 0, "\015\016\017\02014",   14, STATUS_SUCCESS}, /* whitespace char 13 to 16 */
1269     { 0, "\021\022\023\02415",   15, STATUS_SUCCESS}, /* whitespace char 17 to 20 */
1270     { 0, "\025\026\027\03016",   16, STATUS_SUCCESS}, /* whitespace char 21 to 24 */
1271     { 0, "\031\032\033\03417",   17, STATUS_SUCCESS}, /* whitespace char 25 to 28 */
1272     { 0, "\035\036\037\04018",   18, STATUS_SUCCESS}, /* whitespace char 29 to 32 */
1273     { 0, " \n \r \t214",        214, STATUS_SUCCESS},
1274     { 0, " \n \r \t+214",       214, STATUS_SUCCESS}, /* Signs can be used after whitespace */
1275     { 0, " \n \r \t-214",      -214, STATUS_SUCCESS},
1276     { 0, "+214 0",              214, STATUS_SUCCESS}, /* Space terminates the number */
1277     { 0, " 214.01",             214, STATUS_SUCCESS}, /* Decimal point not accepted */
1278     { 0, " 214,01",             214, STATUS_SUCCESS}, /* Decimal comma not accepted */
1279     { 0, "f81",                   0, STATUS_SUCCESS},
1280     { 0, "0x12345",         0x12345, STATUS_SUCCESS}, /* Hex */
1281     { 0, "00x12345",              0, STATUS_SUCCESS},
1282     { 0, "0xx12345",              0, STATUS_SUCCESS},
1283     { 0, "1x34",                  1, STATUS_SUCCESS},
1284     { 0, "-9999999999", -1410065407, STATUS_SUCCESS}, /* Big negative integer */
1285     { 0, "-2147483649",  2147483647, STATUS_SUCCESS}, /* Too small to fit in 32 Bits */
1286     { 0, "-2147483648", 0x80000000L, STATUS_SUCCESS}, /* Smallest negative integer */
1287     { 0, "-2147483647", -2147483647, STATUS_SUCCESS},
1288     { 0, "-1",                   -1, STATUS_SUCCESS},
1289     { 0, "0",                     0, STATUS_SUCCESS},
1290     { 0, "1",                     1, STATUS_SUCCESS},
1291     { 0, "2147483646",   2147483646, STATUS_SUCCESS},
1292     { 0, "2147483647",   2147483647, STATUS_SUCCESS}, /* Largest signed positive integer */
1293     { 0, "2147483648",  0x80000000L, STATUS_SUCCESS}, /* Positive int equal to smallest negative int */
1294     { 0, "2147483649",  -2147483647, STATUS_SUCCESS},
1295     { 0, "4294967294",           -2, STATUS_SUCCESS},
1296     { 0, "4294967295",           -1, STATUS_SUCCESS}, /* Largest unsigned integer */
1297     { 0, "4294967296",            0, STATUS_SUCCESS}, /* Too big to fit in 32 Bits */
1298     { 0, "9999999999",   1410065407, STATUS_SUCCESS}, /* Big positive integer */
1299     { 0, "056789",            56789, STATUS_SUCCESS}, /* Leading zero and still decimal */
1300     { 0, "b1011101100",           0, STATUS_SUCCESS}, /* Binary (b-notation) */
1301     { 0, "-b1011101100",          0, STATUS_SUCCESS}, /* Negative Binary (b-notation) */
1302     { 0, "b10123456789",          0, STATUS_SUCCESS}, /* Binary with nonbinary digits (2-9) */
1303     { 0, "0b1011101100",        748, STATUS_SUCCESS}, /* Binary (0b-notation) */
1304     { 0, "-0b1011101100",      -748, STATUS_SUCCESS}, /* Negative binary (0b-notation) */
1305     { 0, "0b10123456789",         5, STATUS_SUCCESS}, /* Binary with nonbinary digits (2-9) */
1306     { 0, "-0b10123456789",       -5, STATUS_SUCCESS}, /* Negative binary with nonbinary digits (2-9) */
1307     { 0, "0b1",                   1, STATUS_SUCCESS}, /* one digit binary */
1308     { 0, "0b2",                   0, STATUS_SUCCESS}, /* empty binary */
1309     { 0, "0b",                    0, STATUS_SUCCESS}, /* empty binary */
1310     { 0, "o1234567",              0, STATUS_SUCCESS}, /* Octal (o-notation) */
1311     { 0, "-o1234567",             0, STATUS_SUCCESS}, /* Negative Octal (o-notation) */
1312     { 0, "o56789",                0, STATUS_SUCCESS}, /* Octal with nonoctal digits (8 and 9) */
1313     { 0, "0o1234567",      01234567, STATUS_SUCCESS}, /* Octal (0o-notation) */
1314     { 0, "-0o1234567",    -01234567, STATUS_SUCCESS}, /* Negative octal (0o-notation) */
1315     { 0, "0o56789",            0567, STATUS_SUCCESS}, /* Octal with nonoctal digits (8 and 9) */
1316     { 0, "-0o56789",          -0567, STATUS_SUCCESS}, /* Negative octal with nonoctal digits (8 and 9) */
1317     { 0, "0o7",                   7, STATUS_SUCCESS}, /* one digit octal */
1318     { 0, "0o8",                   0, STATUS_SUCCESS}, /* empty octal */
1319     { 0, "0o",                    0, STATUS_SUCCESS}, /* empty octal */
1320     { 0, "0d1011101100",          0, STATUS_SUCCESS}, /* explicit decimal with 0d */
1321     { 0, "x89abcdef",             0, STATUS_SUCCESS}, /* Hex with lower case digits a-f (x-notation) */
1322     { 0, "xFEDCBA00",             0, STATUS_SUCCESS}, /* Hex with upper case digits A-F (x-notation) */
1323     { 0, "-xFEDCBA00",            0, STATUS_SUCCESS}, /* Negative Hexadecimal (x-notation) */
1324     { 0, "0x89abcdef",   0x89abcdef, STATUS_SUCCESS}, /* Hex with lower case digits a-f (0x-notation) */
1325     { 0, "0xFEDCBA00",   0xFEDCBA00, STATUS_SUCCESS}, /* Hex with upper case digits A-F (0x-notation) */
1326     { 0, "-0xFEDCBA00",    19088896, STATUS_SUCCESS}, /* Negative Hexadecimal (0x-notation) */
1327     { 0, "0xabcdefgh",     0xabcdef, STATUS_SUCCESS}, /* Hex with illegal lower case digits (g-z) */
1328     { 0, "0xABCDEFGH",     0xABCDEF, STATUS_SUCCESS}, /* Hex with illegal upper case digits (G-Z) */
1329     { 0, "0xF",                 0xf, STATUS_SUCCESS}, /* one digit hexadecimal */
1330     { 0, "0xG",                   0, STATUS_SUCCESS}, /* empty hexadecimal */
1331     { 0, "0x",                    0, STATUS_SUCCESS}, /* empty hexadecimal */
1332     { 0, "",                      0, STATUS_SUCCESS, STATUS_INVALID_PARAMETER}, /* empty string */
1333     { 2, "1011101100",          748, STATUS_SUCCESS},
1334     { 2, "-1011101100",        -748, STATUS_SUCCESS},
1335     { 2, "2",                     0, STATUS_SUCCESS},
1336     { 2, "0b1011101100",          0, STATUS_SUCCESS},
1337     { 2, "0o1011101100",          0, STATUS_SUCCESS},
1338     { 2, "0d1011101100",          0, STATUS_SUCCESS},
1339     { 2, "0x1011101100",          0, STATUS_SUCCESS},
1340     { 2, "",                      0, STATUS_SUCCESS, STATUS_INVALID_PARAMETER}, /* empty string */
1341     { 8, "1011101100",    136610368, STATUS_SUCCESS},
1342     { 8, "-1011101100",  -136610368, STATUS_SUCCESS},
1343     { 8, "8",                     0, STATUS_SUCCESS},
1344     { 8, "0b1011101100",          0, STATUS_SUCCESS},
1345     { 8, "0o1011101100",          0, STATUS_SUCCESS},
1346     { 8, "0d1011101100",          0, STATUS_SUCCESS},
1347     { 8, "0x1011101100",          0, STATUS_SUCCESS},
1348     { 8, "",                      0, STATUS_SUCCESS, STATUS_INVALID_PARAMETER}, /* empty string */
1349     {10, "1011101100",   1011101100, STATUS_SUCCESS},
1350     {10, "-1011101100", -1011101100, STATUS_SUCCESS},
1351     {10, "0b1011101100",          0, STATUS_SUCCESS},
1352     {10, "0o1011101100",          0, STATUS_SUCCESS},
1353     {10, "0d1011101100",          0, STATUS_SUCCESS},
1354     {10, "0x1011101100",          0, STATUS_SUCCESS},
1355     {10, "o12345",                0, STATUS_SUCCESS}, /* Octal although base is 10 */
1356     {10, "",                      0, STATUS_SUCCESS, STATUS_INVALID_PARAMETER}, /* empty string */
1357     {16, "1011101100",    286265600, STATUS_SUCCESS},
1358     {16, "-1011101100",  -286265600, STATUS_SUCCESS},
1359     {16, "G",                     0, STATUS_SUCCESS},
1360     {16, "g",                     0, STATUS_SUCCESS},
1361     {16, "0b1011101100",  286265600, STATUS_SUCCESS},
1362     {16, "0o1011101100",          0, STATUS_SUCCESS},
1363     {16, "0d1011101100",  286265600, STATUS_SUCCESS},
1364     {16, "0x1011101100",          0, STATUS_SUCCESS},
1365     {16, "",                      0, STATUS_SUCCESS, STATUS_INVALID_PARAMETER}, /* empty string */
1366     {20, "0",                     0, STATUS_INVALID_PARAMETER}, /* illegal base */
1367     {-8, "0",                     0, STATUS_INVALID_PARAMETER}, /* Negative base */
1368 /*    { 0, NULL,                    0, STATUS_SUCCESS}, */ /* NULL as string */
1369 };
1370 #define NB_STR2INT (sizeof(str2int)/sizeof(*str2int))
1371 
1372 
1373 static void test_RtlUnicodeStringToInteger(void)
1374 {
1375     unsigned int test_num;
1376     int value;
1377     NTSTATUS result;
1378     WCHAR *wstr;
1379     UNICODE_STRING uni;
1380 
1381     for (test_num = 0; test_num < NB_STR2INT; test_num++) {
1382 	wstr = AtoW(str2int[test_num].str);
1383 	value = 0xdeadbeef;
1384 	pRtlInitUnicodeString(&uni, wstr);
1385 	result = pRtlUnicodeStringToInteger(&uni, str2int[test_num].base, &value);
1386 	ok(result == str2int[test_num].result ||
1387            (str2int[test_num].alternative && result == str2int[test_num].alternative),
1388            "(test %d): RtlUnicodeStringToInteger(\"%s\", %d, [out]) has result %x, expected: %x (%x)\n",
1389 	   test_num, str2int[test_num].str, str2int[test_num].base, result,
1390            str2int[test_num].result, str2int[test_num].alternative);
1391         if (result == STATUS_SUCCESS)
1392             ok(value == str2int[test_num].value ||
1393                broken(str2int[test_num].str[0] == '\0' && str2int[test_num].base == 16), /* nt4 */
1394                "(test %d): RtlUnicodeStringToInteger(\"%s\", %d, [out]) assigns value %d, expected: %d\n",
1395                test_num, str2int[test_num].str, str2int[test_num].base, value, str2int[test_num].value);
1396         else
1397             ok(value == 0xdeadbeef || value == 0 /* vista */,
1398                "(test %d): RtlUnicodeStringToInteger(\"%s\", %d, [out]) assigns value %d, expected 0 or deadbeef\n",
1399                test_num, str2int[test_num].str, str2int[test_num].base, value);
1400 	HeapFree(GetProcessHeap(), 0, wstr);
1401     }
1402 
1403     wstr = AtoW(str2int[1].str);
1404     pRtlInitUnicodeString(&uni, wstr);
1405     result = pRtlUnicodeStringToInteger(&uni, str2int[1].base, NULL);
1406     ok(result == STATUS_ACCESS_VIOLATION,
1407        "call failed: RtlUnicodeStringToInteger(\"%s\", %d, NULL) has result %x\n",
1408        str2int[1].str, str2int[1].base, result);
1409     result = pRtlUnicodeStringToInteger(&uni, 20, NULL);
1410     ok(result == STATUS_INVALID_PARAMETER || result == STATUS_ACCESS_VIOLATION,
1411        "call failed: RtlUnicodeStringToInteger(\"%s\", 20, NULL) has result %x\n",
1412        str2int[1].str, result);
1413 
1414     uni.Length = 10; /* Make Length shorter (5 WCHARS instead of 7) */
1415     result = pRtlUnicodeStringToInteger(&uni, str2int[1].base, &value);
1416     ok(result == STATUS_SUCCESS,
1417        "call failed: RtlUnicodeStringToInteger(\"12345\", %d, [out]) has result %x\n",
1418        str2int[1].base, result);
1419     ok(value == 12345,
1420        "didn't return expected value (test a): expected: %d, got: %d\n",
1421        12345, value);
1422 
1423     uni.Length = 5; /* Use odd Length (2.5 WCHARS) */
1424     result = pRtlUnicodeStringToInteger(&uni, str2int[1].base, &value);
1425     ok(result == STATUS_SUCCESS || result == STATUS_INVALID_PARAMETER /* vista */,
1426        "call failed: RtlUnicodeStringToInteger(\"12\", %d, [out]) has result %x\n",
1427        str2int[1].base, result);
1428     if (result == STATUS_SUCCESS)
1429         ok(value == 12, "didn't return expected value (test b): expected: %d, got: %d\n", 12, value);
1430 
1431     uni.Length = 2;
1432     result = pRtlUnicodeStringToInteger(&uni, str2int[1].base, &value);
1433     ok(result == STATUS_SUCCESS,
1434        "call failed: RtlUnicodeStringToInteger(\"1\", %d, [out]) has result %x\n",
1435        str2int[1].base, result);
1436     ok(value == 1,
1437        "didn't return expected value (test c): expected: %d, got: %d\n",
1438        1, value);
1439     /* w2k: uni.Length = 0 returns value 11234567 instead of 0 */
1440     HeapFree(GetProcessHeap(), 0, wstr);
1441 }
1442 
1443 
1444 static void test_RtlCharToInteger(void)
1445 {
1446     unsigned int test_num;
1447     int value;
1448     NTSTATUS result;
1449 
1450     for (test_num = 0; test_num < NB_STR2INT; test_num++) {
1451 	/* w2k skips a leading '\0' and processes the string after */
1452 	if (str2int[test_num].str[0] != '\0') {
1453 	    value = 0xdeadbeef;
1454 	    result = pRtlCharToInteger(str2int[test_num].str, str2int[test_num].base, &value);
1455 	    ok(result == str2int[test_num].result ||
1456                (str2int[test_num].alternative && result == str2int[test_num].alternative),
1457                "(test %d): call failed: RtlCharToInteger(\"%s\", %d, [out]) has result %x, expected: %x (%x)\n",
1458 	       test_num, str2int[test_num].str, str2int[test_num].base, result,
1459                str2int[test_num].result, str2int[test_num].alternative);
1460             if (result == STATUS_SUCCESS)
1461                 ok(value == str2int[test_num].value,
1462                    "(test %d): call failed: RtlCharToInteger(\"%s\", %d, [out]) assigns value %d, expected: %d\n",
1463                    test_num, str2int[test_num].str, str2int[test_num].base, value, str2int[test_num].value);
1464             else
1465                 ok(value == 0 || value == 0xdeadbeef,
1466                    "(test %d): call failed: RtlCharToInteger(\"%s\", %d, [out]) assigns value %d, expected 0 or deadbeef\n",
1467                    test_num, str2int[test_num].str, str2int[test_num].base, value);
1468 	}
1469     }
1470 
1471     result = pRtlCharToInteger(str2int[1].str, str2int[1].base, NULL);
1472     ok(result == STATUS_ACCESS_VIOLATION,
1473        "call failed: RtlCharToInteger(\"%s\", %d, NULL) has result %x\n",
1474        str2int[1].str, str2int[1].base, result);
1475 
1476     result = pRtlCharToInteger(str2int[1].str, 20, NULL);
1477     ok(result == STATUS_INVALID_PARAMETER,
1478        "call failed: RtlCharToInteger(\"%s\", 20, NULL) has result %x\n",
1479        str2int[1].str, result);
1480 }
1481 
1482 
1483 #define STRI_BUFFER_LENGTH 35
1484 
1485 typedef struct {
1486     int base;
1487     ULONG value;
1488     USHORT Length;
1489     USHORT MaximumLength;
1490     const char *Buffer;
1491     NTSTATUS result;
1492 } int2str_t;
1493 
1494 static const int2str_t int2str[] = {
1495     {10,          123,  3, 11, "123\0-------------------------------", STATUS_SUCCESS},
1496 
1497     { 0,  0x80000000U, 10, 11, "2147483648\0------------------------", STATUS_SUCCESS}, /* min signed int */
1498     { 0,  -2147483647, 10, 11, "2147483649\0------------------------", STATUS_SUCCESS},
1499     { 0,           -2, 10, 11, "4294967294\0------------------------", STATUS_SUCCESS},
1500     { 0,           -1, 10, 11, "4294967295\0------------------------", STATUS_SUCCESS},
1501     { 0,            0,  1, 11, "0\0---------------------------------", STATUS_SUCCESS},
1502     { 0,            1,  1, 11, "1\0---------------------------------", STATUS_SUCCESS},
1503     { 0,           12,  2, 11, "12\0--------------------------------", STATUS_SUCCESS},
1504     { 0,          123,  3, 11, "123\0-------------------------------", STATUS_SUCCESS},
1505     { 0,         1234,  4, 11, "1234\0------------------------------", STATUS_SUCCESS},
1506     { 0,        12345,  5, 11, "12345\0-----------------------------", STATUS_SUCCESS},
1507     { 0,       123456,  6, 11, "123456\0----------------------------", STATUS_SUCCESS},
1508     { 0,      1234567,  7, 11, "1234567\0---------------------------", STATUS_SUCCESS},
1509     { 0,     12345678,  8, 11, "12345678\0--------------------------", STATUS_SUCCESS},
1510     { 0,    123456789,  9, 11, "123456789\0-------------------------", STATUS_SUCCESS},
1511     { 0,   2147483646, 10, 11, "2147483646\0------------------------", STATUS_SUCCESS},
1512     { 0,   2147483647, 10, 11, "2147483647\0------------------------", STATUS_SUCCESS}, /* max signed int */
1513     { 0,  2147483648U, 10, 11, "2147483648\0------------------------", STATUS_SUCCESS}, /* uint = -max int */
1514     { 0,  2147483649U, 10, 11, "2147483649\0------------------------", STATUS_SUCCESS},
1515     { 0,  4294967294U, 10, 11, "4294967294\0------------------------", STATUS_SUCCESS},
1516     { 0,  4294967295U, 10, 11, "4294967295\0------------------------", STATUS_SUCCESS}, /* max unsigned int */
1517 
1518     { 2,  0x80000000U, 32, 33, "10000000000000000000000000000000\0--", STATUS_SUCCESS}, /* min signed int */
1519     { 2,  -2147483647, 32, 33, "10000000000000000000000000000001\0--", STATUS_SUCCESS},
1520     { 2,           -2, 32, 33, "11111111111111111111111111111110\0--", STATUS_SUCCESS},
1521     { 2,           -1, 32, 33, "11111111111111111111111111111111\0--", STATUS_SUCCESS},
1522     { 2,            0,  1, 33, "0\0---------------------------------", STATUS_SUCCESS},
1523     { 2,            1,  1, 33, "1\0---------------------------------", STATUS_SUCCESS},
1524     { 2,           10,  4, 33, "1010\0------------------------------", STATUS_SUCCESS},
1525     { 2,          100,  7, 33, "1100100\0---------------------------", STATUS_SUCCESS},
1526     { 2,         1000, 10, 33, "1111101000\0------------------------", STATUS_SUCCESS},
1527     { 2,        10000, 14, 33, "10011100010000\0--------------------", STATUS_SUCCESS},
1528     { 2,        32767, 15, 33, "111111111111111\0-------------------", STATUS_SUCCESS},
1529 /*  { 2,        32768, 16, 33, "1000000000000000\0------------------", STATUS_SUCCESS}, broken on windows */
1530 /*  { 2,        65535, 16, 33, "1111111111111111\0------------------", STATUS_SUCCESS}, broken on windows */
1531     { 2,        65536, 17, 33, "10000000000000000\0-----------------", STATUS_SUCCESS},
1532     { 2,       100000, 17, 33, "11000011010100000\0-----------------", STATUS_SUCCESS},
1533     { 2,      1000000, 20, 33, "11110100001001000000\0--------------", STATUS_SUCCESS},
1534     { 2,     10000000, 24, 33, "100110001001011010000000\0----------", STATUS_SUCCESS},
1535     { 2,    100000000, 27, 33, "101111101011110000100000000\0-------", STATUS_SUCCESS},
1536     { 2,   1000000000, 30, 33, "111011100110101100101000000000\0----", STATUS_SUCCESS},
1537     { 2,   1073741823, 30, 33, "111111111111111111111111111111\0----", STATUS_SUCCESS},
1538     { 2,   2147483646, 31, 33, "1111111111111111111111111111110\0---", STATUS_SUCCESS},
1539     { 2,   2147483647, 31, 33, "1111111111111111111111111111111\0---", STATUS_SUCCESS}, /* max signed int */
1540     { 2,  2147483648U, 32, 33, "10000000000000000000000000000000\0--", STATUS_SUCCESS}, /* uint = -max int */
1541     { 2,  2147483649U, 32, 33, "10000000000000000000000000000001\0--", STATUS_SUCCESS},
1542     { 2,  4294967294U, 32, 33, "11111111111111111111111111111110\0--", STATUS_SUCCESS},
1543     { 2,  4294967295U, 32, 33, "11111111111111111111111111111111\0--", STATUS_SUCCESS}, /* max unsigned int */
1544 
1545     { 8,  0x80000000U, 11, 12, "20000000000\0-----------------------", STATUS_SUCCESS}, /* min signed int */
1546     { 8,  -2147483647, 11, 12, "20000000001\0-----------------------", STATUS_SUCCESS},
1547     { 8,           -2, 11, 12, "37777777776\0-----------------------", STATUS_SUCCESS},
1548     { 8,           -1, 11, 12, "37777777777\0-----------------------", STATUS_SUCCESS},
1549     { 8,            0,  1, 12, "0\0---------------------------------", STATUS_SUCCESS},
1550     { 8,            1,  1, 12, "1\0---------------------------------", STATUS_SUCCESS},
1551     { 8,   2147483646, 11, 12, "17777777776\0-----------------------", STATUS_SUCCESS},
1552     { 8,   2147483647, 11, 12, "17777777777\0-----------------------", STATUS_SUCCESS}, /* max signed int */
1553     { 8,  2147483648U, 11, 12, "20000000000\0-----------------------", STATUS_SUCCESS}, /* uint = -max int */
1554     { 8,  2147483649U, 11, 12, "20000000001\0-----------------------", STATUS_SUCCESS},
1555     { 8,  4294967294U, 11, 12, "37777777776\0-----------------------", STATUS_SUCCESS},
1556     { 8,  4294967295U, 11, 12, "37777777777\0-----------------------", STATUS_SUCCESS}, /* max unsigned int */
1557 
1558     {10,  0x80000000U, 10, 11, "2147483648\0------------------------", STATUS_SUCCESS}, /* min signed int */
1559     {10,  -2147483647, 10, 11, "2147483649\0------------------------", STATUS_SUCCESS},
1560     {10,           -2, 10, 11, "4294967294\0------------------------", STATUS_SUCCESS},
1561     {10,           -1, 10, 11, "4294967295\0------------------------", STATUS_SUCCESS},
1562     {10,            0,  1, 11, "0\0---------------------------------", STATUS_SUCCESS},
1563     {10,            1,  1, 11, "1\0---------------------------------", STATUS_SUCCESS},
1564     {10,   2147483646, 10, 11, "2147483646\0------------------------", STATUS_SUCCESS},
1565     {10,   2147483647, 10, 11, "2147483647\0------------------------", STATUS_SUCCESS}, /* max signed int */
1566     {10,  2147483648U, 10, 11, "2147483648\0------------------------", STATUS_SUCCESS}, /* uint = -max int */
1567     {10,  2147483649U, 10, 11, "2147483649\0------------------------", STATUS_SUCCESS},
1568     {10,  4294967294U, 10, 11, "4294967294\0------------------------", STATUS_SUCCESS},
1569     {10,  4294967295U, 10, 11, "4294967295\0------------------------", STATUS_SUCCESS}, /* max unsigned int */
1570 
1571     {16,  0x80000000U,  8,  9, "80000000\0--------------------------", STATUS_SUCCESS}, /* min signed int */
1572     {16,  -2147483647,  8,  9, "80000001\0--------------------------", STATUS_SUCCESS},
1573     {16,           -2,  8,  9, "FFFFFFFE\0--------------------------", STATUS_SUCCESS},
1574     {16,           -1,  8,  9, "FFFFFFFF\0--------------------------", STATUS_SUCCESS},
1575     {16,            0,  1,  9, "0\0---------------------------------", STATUS_SUCCESS},
1576     {16,            1,  1,  9, "1\0---------------------------------", STATUS_SUCCESS},
1577     {16,   2147483646,  8,  9, "7FFFFFFE\0--------------------------", STATUS_SUCCESS},
1578     {16,   2147483647,  8,  9, "7FFFFFFF\0--------------------------", STATUS_SUCCESS}, /* max signed int */
1579     {16,  2147483648U,  8,  9, "80000000\0--------------------------", STATUS_SUCCESS}, /* uint = -max int */
1580     {16,  2147483649U,  8,  9, "80000001\0--------------------------", STATUS_SUCCESS},
1581     {16,  4294967294U,  8,  9, "FFFFFFFE\0--------------------------", STATUS_SUCCESS},
1582     {16,  4294967295U,  8,  9, "FFFFFFFF\0--------------------------", STATUS_SUCCESS}, /* max unsigned int */
1583 
1584 /*  { 2,        32768, 16, 17, "1000000000000000\0------------------", STATUS_SUCCESS}, broken on windows */
1585 /*  { 2,        32768, 16, 16, "1000000000000000-------------------",  STATUS_SUCCESS}, broken on windows */
1586     { 2,        65536, 17, 18, "10000000000000000\0-----------------", STATUS_SUCCESS},
1587     { 2,        65536, 17, 17, "10000000000000000------------------",  STATUS_SUCCESS},
1588     { 2,       131072, 18, 19, "100000000000000000\0----------------", STATUS_SUCCESS},
1589     { 2,       131072, 18, 18, "100000000000000000-----------------",  STATUS_SUCCESS},
1590     {16,   0xffffffff,  8,  9, "FFFFFFFF\0--------------------------", STATUS_SUCCESS},
1591     {16,   0xffffffff,  8,  8, "FFFFFFFF---------------------------",  STATUS_SUCCESS}, /* No \0 term */
1592     {16,   0xffffffff,  8,  7, "-----------------------------------",  STATUS_BUFFER_OVERFLOW}, /* Too short */
1593     {16,          0xa,  1,  2, "A\0---------------------------------", STATUS_SUCCESS},
1594     {16,          0xa,  1,  1, "A----------------------------------",  STATUS_SUCCESS}, /* No \0 term */
1595     {16,            0,  1,  0, "-----------------------------------",  STATUS_BUFFER_OVERFLOW},
1596     {20,   0xdeadbeef,  0,  9, "-----------------------------------",  STATUS_INVALID_PARAMETER}, /* ill. base */
1597     {-8,     07654321,  0, 12, "-----------------------------------",  STATUS_INVALID_PARAMETER}, /* neg. base */
1598 };
1599 #define NB_INT2STR (sizeof(int2str)/sizeof(*int2str))
1600 
1601 
1602 static void one_RtlIntegerToUnicodeString_test(int test_num, const int2str_t *int2str)
1603 {
1604     int pos;
1605     WCHAR expected_str_Buffer[STRI_BUFFER_LENGTH + 1];
1606     UNICODE_STRING expected_unicode_string;
1607     STRING expected_ansi_str;
1608     WCHAR str_Buffer[STRI_BUFFER_LENGTH + 1];
1609     UNICODE_STRING unicode_string;
1610     STRING ansi_str;
1611     NTSTATUS result;
1612 
1613     for (pos = 0; pos < STRI_BUFFER_LENGTH; pos++) {
1614 	expected_str_Buffer[pos] = int2str->Buffer[pos];
1615     }
1616     expected_unicode_string.Length = int2str->Length * sizeof(WCHAR);
1617     expected_unicode_string.MaximumLength = int2str->MaximumLength * sizeof(WCHAR);
1618     expected_unicode_string.Buffer = expected_str_Buffer;
1619     pRtlUnicodeStringToAnsiString(&expected_ansi_str, &expected_unicode_string, 1);
1620 
1621     for (pos = 0; pos < STRI_BUFFER_LENGTH; pos++) {
1622 	str_Buffer[pos] = '-';
1623     }
1624     unicode_string.Length = 0;
1625     unicode_string.MaximumLength = int2str->MaximumLength * sizeof(WCHAR);
1626     unicode_string.Buffer = str_Buffer;
1627 
1628     result = pRtlIntegerToUnicodeString(int2str->value, int2str->base, &unicode_string);
1629     pRtlUnicodeStringToAnsiString(&ansi_str, &unicode_string, 1);
1630     if (result == STATUS_BUFFER_OVERFLOW) {
1631 	/* On BUFFER_OVERFLOW the string Buffer should be unchanged */
1632 	for (pos = 0; pos < STRI_BUFFER_LENGTH; pos++) {
1633 	    expected_str_Buffer[pos] = '-';
1634 	}
1635 	/* w2k: The native function has two reasons for BUFFER_OVERFLOW: */
1636 	/* If the value is too large to convert: The Length is unchanged */
1637 	/* If str is too small to hold the string: Set str->Length to the length */
1638 	/* the string would have (which can be larger than the MaximumLength). */
1639 	/* To allow all this in the tests we do the following: */
1640 	if (expected_unicode_string.Length > 32 && unicode_string.Length == 0) {
1641 	    /* The value is too large to convert only triggered when testing native */
1642 	    expected_unicode_string.Length = 0;
1643 	}
1644     } else {
1645 	ok(result == int2str->result,
1646            "(test %d): RtlIntegerToUnicodeString(%u, %d, [out]) has result %x, expected: %x\n",
1647 	   test_num, int2str->value, int2str->base, result, int2str->result);
1648 	if (result == STATUS_SUCCESS) {
1649 	    ok(unicode_string.Buffer[unicode_string.Length/sizeof(WCHAR)] == '\0',
1650                "(test %d): RtlIntegerToUnicodeString(%u, %d, [out]) string \"%s\" is not NULL terminated\n",
1651 	       test_num, int2str->value, int2str->base, ansi_str.Buffer);
1652 	}
1653     }
1654     ok(memcmp(unicode_string.Buffer, expected_unicode_string.Buffer, STRI_BUFFER_LENGTH * sizeof(WCHAR)) == 0,
1655        "(test %d): RtlIntegerToUnicodeString(%u, %d, [out]) assigns string \"%s\", expected: \"%s\"\n",
1656        test_num, int2str->value, int2str->base, ansi_str.Buffer, expected_ansi_str.Buffer);
1657     ok(unicode_string.Length == expected_unicode_string.Length,
1658        "(test %d): RtlIntegerToUnicodeString(%u, %d, [out]) string has Length %d, expected: %d\n",
1659        test_num, int2str->value, int2str->base, unicode_string.Length, expected_unicode_string.Length);
1660     ok(unicode_string.MaximumLength == expected_unicode_string.MaximumLength,
1661        "(test %d): RtlIntegerToUnicodeString(%u, %d, [out]) string has MaximumLength %d, expected: %d\n",
1662        test_num, int2str->value, int2str->base, unicode_string.MaximumLength, expected_unicode_string.MaximumLength);
1663     pRtlFreeAnsiString(&expected_ansi_str);
1664     pRtlFreeAnsiString(&ansi_str);
1665 }
1666 
1667 
1668 static void test_RtlIntegerToUnicodeString(void)
1669 {
1670     size_t test_num;
1671 
1672     for (test_num = 0; test_num < NB_INT2STR; test_num++)
1673         one_RtlIntegerToUnicodeString_test(test_num, &int2str[test_num]);
1674 }
1675 
1676 
1677 static void one_RtlIntegerToChar_test(int test_num, const int2str_t *int2str)
1678 {
1679     NTSTATUS result;
1680     char dest_str[STRI_BUFFER_LENGTH + 1];
1681 
1682     memset(dest_str, '-', STRI_BUFFER_LENGTH);
1683     dest_str[STRI_BUFFER_LENGTH] = '\0';
1684     result = pRtlIntegerToChar(int2str->value, int2str->base, int2str->MaximumLength, dest_str);
1685     ok(result == int2str->result,
1686        "(test %d): RtlIntegerToChar(%u, %d, %d, [out]) has result %x, expected: %x\n",
1687        test_num, int2str->value, int2str->base, int2str->MaximumLength, result, int2str->result);
1688     ok(memcmp(dest_str, int2str->Buffer, STRI_BUFFER_LENGTH) == 0,
1689        "(test %d): RtlIntegerToChar(%u, %d, %d, [out]) assigns string \"%s\", expected: \"%s\"\n",
1690        test_num, int2str->value, int2str->base, int2str->MaximumLength, dest_str, int2str->Buffer);
1691 }
1692 
1693 
1694 static void test_RtlIntegerToChar(void)
1695 {
1696     NTSTATUS result;
1697     size_t test_num;
1698 
1699     for (test_num = 0; test_num < NB_INT2STR; test_num++)
1700       one_RtlIntegerToChar_test(test_num, &int2str[test_num]);
1701 
1702     result = pRtlIntegerToChar(int2str[0].value, 20, int2str[0].MaximumLength, NULL);
1703     ok(result == STATUS_INVALID_PARAMETER,
1704        "(test a): RtlIntegerToChar(%u, %d, %d, NULL) has result %x, expected: %x\n",
1705        int2str[0].value, 20, int2str[0].MaximumLength, result, STATUS_INVALID_PARAMETER);
1706 
1707     result = pRtlIntegerToChar(int2str[0].value, 20, 0, NULL);
1708     ok(result == STATUS_INVALID_PARAMETER,
1709        "(test b): RtlIntegerToChar(%u, %d, %d, NULL) has result %x, expected: %x\n",
1710        int2str[0].value, 20, 0, result, STATUS_INVALID_PARAMETER);
1711 
1712     result = pRtlIntegerToChar(int2str[0].value, int2str[0].base, 0, NULL);
1713     ok(result == STATUS_BUFFER_OVERFLOW,
1714        "(test c): RtlIntegerToChar(%u, %d, %d, NULL) has result %x, expected: %x\n",
1715        int2str[0].value, int2str[0].base, 0, result, STATUS_BUFFER_OVERFLOW);
1716 
1717     result = pRtlIntegerToChar(int2str[0].value, int2str[0].base, int2str[0].MaximumLength, NULL);
1718     ok(result == STATUS_ACCESS_VIOLATION,
1719        "(test d): RtlIntegerToChar(%u, %d, %d, NULL) has result %x, expected: %x\n",
1720        int2str[0].value, int2str[0].base, int2str[0].MaximumLength, result, STATUS_ACCESS_VIOLATION);
1721 }
1722 
1723 static void test_RtlIsTextUnicode(void)
1724 {
1725     char ascii[] = "A simple string";
1726     char false_positive[] = {0x41, 0x0a, 0x0d, 0x1d};
1727     WCHAR false_negative = 0x0d0a;
1728     WCHAR unicode[] = {'A',' ','U','n','i','c','o','d','e',' ','s','t','r','i','n','g',0};
1729     WCHAR unicode_no_controls[] = {'A','U','n','i','c','o','d','e','s','t','r','i','n','g',0};
1730     /* String with both byte-reversed and standard Unicode control characters. */
1731     WCHAR mixed_controls[] = {'\t',0x9000,0x0d00,'\n',0};
1732     WCHAR *be_unicode;
1733     WCHAR *be_unicode_no_controls;
1734     BOOLEAN res;
1735     int flags;
1736     int i;
1737 
1738     if (!pRtlIsTextUnicode)
1739     {
1740         win_skip("RtlIsTextUnicode is not available\n");
1741         return;
1742     }
1743 
1744     ok(!pRtlIsTextUnicode(ascii, sizeof(ascii), NULL), "ASCII text detected as Unicode\n");
1745 
1746     res = pRtlIsTextUnicode(unicode, sizeof(unicode), NULL);
1747     ok(res ||
1748        broken(res == FALSE), /* NT4 */
1749        "Text should be Unicode\n");
1750 
1751     ok(!pRtlIsTextUnicode(unicode, sizeof(unicode) - 1, NULL), "Text should be Unicode\n");
1752 
1753     flags =  IS_TEXT_UNICODE_UNICODE_MASK;
1754     ok(pRtlIsTextUnicode(unicode, sizeof(unicode), &flags), "Text should not pass a Unicode\n");
1755     ok(flags == (IS_TEXT_UNICODE_STATISTICS | IS_TEXT_UNICODE_CONTROLS),
1756        "Expected flags 0x6, obtained %x\n", flags);
1757 
1758     flags =  IS_TEXT_UNICODE_REVERSE_MASK;
1759     ok(!pRtlIsTextUnicode(unicode, sizeof(unicode), &flags), "Text should not pass reverse Unicode tests\n");
1760     ok(flags == 0, "Expected flags 0, obtained %x\n", flags);
1761 
1762     flags = IS_TEXT_UNICODE_ODD_LENGTH;
1763     ok(!pRtlIsTextUnicode(unicode, sizeof(unicode) - 1, &flags), "Odd length test should have passed\n");
1764     ok(flags == IS_TEXT_UNICODE_ODD_LENGTH, "Expected flags 0x200, obtained %x\n", flags);
1765 
1766     be_unicode = HeapAlloc(GetProcessHeap(), 0, sizeof(unicode) + sizeof(WCHAR));
1767     be_unicode[0] = 0xfffe;
1768     for (i = 0; i < sizeof(unicode)/sizeof(unicode[0]); i++)
1769     {
1770         be_unicode[i + 1] = (unicode[i] >> 8) | ((unicode[i] & 0xff) << 8);
1771     }
1772     ok(!pRtlIsTextUnicode(be_unicode, sizeof(unicode) + 2, NULL), "Reverse endian should not be Unicode\n");
1773     ok(!pRtlIsTextUnicode(&be_unicode[1], sizeof(unicode), NULL), "Reverse endian should not be Unicode\n");
1774 
1775     flags = IS_TEXT_UNICODE_REVERSE_MASK;
1776     ok(!pRtlIsTextUnicode(&be_unicode[1], sizeof(unicode), &flags), "Reverse endian should be Unicode\n");
1777     todo_wine
1778     ok(flags == (IS_TEXT_UNICODE_REVERSE_ASCII16 | IS_TEXT_UNICODE_REVERSE_STATISTICS | IS_TEXT_UNICODE_REVERSE_CONTROLS),
1779        "Expected flags 0x70, obtained %x\n", flags);
1780 
1781     flags = IS_TEXT_UNICODE_REVERSE_MASK;
1782     ok(!pRtlIsTextUnicode(be_unicode, sizeof(unicode) + 2, &flags), "Reverse endian should be Unicode\n");
1783     ok(flags == (IS_TEXT_UNICODE_REVERSE_CONTROLS | IS_TEXT_UNICODE_REVERSE_SIGNATURE),
1784        "Expected flags 0xc0, obtained %x\n", flags);
1785 
1786     /* build byte reversed unicode string with no control chars */
1787     be_unicode_no_controls = HeapAlloc(GetProcessHeap(), 0, sizeof(unicode) + sizeof(WCHAR));
1788     ok(be_unicode_no_controls != NULL, "Expected HeapAlloc to succeed.\n");
1789     be_unicode_no_controls[0] = 0xfffe;
1790     for (i = 0; i < sizeof(unicode_no_controls)/sizeof(unicode_no_controls[0]); i++)
1791         be_unicode_no_controls[i + 1] = (unicode_no_controls[i] >> 8) | ((unicode_no_controls[i] & 0xff) << 8);
1792 
1793 
1794     /* The following tests verify that the tests for */
1795     /* IS_TEXT_UNICODE_CONTROLS and IS_TEXT_UNICODE_REVERSE_CONTROLS */
1796     /* are not mutually exclusive. Regardless of whether the strings */
1797     /* contain an indication of endianness, the tests are still */
1798     /* run if the flag is passed to (Rtl)IsTextUnicode. */
1799 
1800     /* Test IS_TEXT_UNICODE_CONTROLS flag */
1801     flags = IS_TEXT_UNICODE_CONTROLS;
1802     ok(!pRtlIsTextUnicode(unicode_no_controls, sizeof(unicode_no_controls), &flags), "Test should not pass on Unicode string lacking control characters.\n");
1803     ok(flags == 0, "Expected flags 0x0, obtained %x\n", flags);
1804 
1805     flags = IS_TEXT_UNICODE_CONTROLS;
1806     ok(!pRtlIsTextUnicode(be_unicode_no_controls, sizeof(unicode_no_controls), &flags), "Test should not pass on byte-reversed Unicode string lacking control characters.\n");
1807     ok(flags == 0, "Expected flags 0x0, obtained %x\n", flags);
1808 
1809     flags = IS_TEXT_UNICODE_CONTROLS;
1810     ok(pRtlIsTextUnicode(unicode, sizeof(unicode), &flags), "Test should pass on Unicode string lacking control characters.\n");
1811     ok(flags == IS_TEXT_UNICODE_CONTROLS, "Expected flags 0x04, obtained %x\n", flags);
1812 
1813     flags = IS_TEXT_UNICODE_CONTROLS;
1814     ok(!pRtlIsTextUnicode(be_unicode_no_controls, sizeof(unicode_no_controls) + 2, &flags),
1815             "Test should not pass with standard Unicode string.\n");
1816     ok(flags == 0, "Expected flags 0x0, obtained %x\n", flags);
1817 
1818     flags = IS_TEXT_UNICODE_CONTROLS;
1819     ok(pRtlIsTextUnicode(mixed_controls, sizeof(mixed_controls), &flags), "Test should pass on a string containing control characters.\n");
1820     ok(flags == IS_TEXT_UNICODE_CONTROLS, "Expected flags 0x04, obtained %x\n", flags);
1821 
1822     /* Test IS_TEXT_UNICODE_REVERSE_CONTROLS flag */
1823     flags = IS_TEXT_UNICODE_REVERSE_CONTROLS;
1824     ok(!pRtlIsTextUnicode(be_unicode_no_controls, sizeof(unicode_no_controls), &flags), "Test should not pass on Unicode string lacking control characters.\n");
1825     ok(flags == 0, "Expected flags 0x0, obtained %x\n", flags);
1826 
1827     flags = IS_TEXT_UNICODE_REVERSE_CONTROLS;
1828     ok(!pRtlIsTextUnicode(unicode_no_controls, sizeof(unicode_no_controls), &flags), "Test should not pass on Unicode string lacking control characters.\n");
1829     ok(flags == 0, "Expected flags 0x0, obtained %x\n", flags);
1830 
1831     flags = IS_TEXT_UNICODE_REVERSE_CONTROLS;
1832     ok(!pRtlIsTextUnicode(unicode, sizeof(unicode), &flags), "Test should not pass on Unicode string lacking control characters.\n");
1833     ok(flags == 0, "Expected flags 0x0, obtained %x\n", flags);
1834 
1835     flags = IS_TEXT_UNICODE_REVERSE_CONTROLS;
1836     ok(!pRtlIsTextUnicode(be_unicode, sizeof(unicode) + 2, &flags),
1837         "Test should pass with byte-reversed Unicode string containing control characters.\n");
1838     ok(flags == IS_TEXT_UNICODE_REVERSE_CONTROLS, "Expected flags 0x40, obtained %x\n", flags);
1839 
1840     flags = IS_TEXT_UNICODE_REVERSE_CONTROLS;
1841     ok(!pRtlIsTextUnicode(mixed_controls, sizeof(mixed_controls), &flags), "Test should pass on a string containing byte-reversed control characters.\n");
1842     ok(flags == IS_TEXT_UNICODE_REVERSE_CONTROLS, "Expected flags 0x40, obtained %x\n", flags);
1843 
1844     /* Test with flags for both byte-reverse and standard Unicode characters */
1845     flags = IS_TEXT_UNICODE_CONTROLS | IS_TEXT_UNICODE_REVERSE_CONTROLS;
1846     ok(!pRtlIsTextUnicode(mixed_controls, sizeof(mixed_controls), &flags), "Test should pass on string containing both byte-reversed and standard control characters.\n");
1847     ok(flags == (IS_TEXT_UNICODE_CONTROLS | IS_TEXT_UNICODE_REVERSE_CONTROLS), "Expected flags 0x44, obtained %x\n", flags);
1848 
1849     flags = IS_TEXT_UNICODE_STATISTICS;
1850     todo_wine ok(pRtlIsTextUnicode(false_positive, sizeof(false_positive), &flags), "Test should pass on false positive.\n");
1851 
1852     ok(!pRtlIsTextUnicode(&false_negative, sizeof(false_negative), NULL), "Test should fail on 0x0d0a (MALAYALAM LETTER UU).\n");
1853 
1854     HeapFree(GetProcessHeap(), 0, be_unicode);
1855     HeapFree(GetProcessHeap(), 0, be_unicode_no_controls);
1856 }
1857 
1858 static void test_RtlCompareUnicodeString(void)
1859 {
1860     WCHAR ch1, ch2;
1861     UNICODE_STRING str1, str2;
1862 
1863     str1.Buffer = &ch1;
1864     str1.Length = str1.MaximumLength = sizeof(WCHAR);
1865     str2.Buffer = &ch2;
1866     str2.Length = str2.MaximumLength = sizeof(WCHAR);
1867     for (ch1 = 0; ch1 < 512; ch1++)
1868     {
1869         for (ch2 = 0; ch2 < 1024; ch2++)
1870         {
1871             LONG res = pRtlCompareUnicodeString( &str1, &str2, FALSE );
1872             ok( res == (ch1 - ch2), "wrong result %d %04x %04x\n", res, ch1, ch2 );
1873             res = pRtlCompareUnicodeString( &str1, &str2, TRUE );
1874             ok( res == (pRtlUpcaseUnicodeChar(ch1) - pRtlUpcaseUnicodeChar(ch2)),
1875                 "wrong result %d %04x %04x\n", res, ch1, ch2 );
1876             if (pRtlCompareUnicodeStrings)
1877             {
1878                 res = pRtlCompareUnicodeStrings( &ch1, 1, &ch2, 1, FALSE );
1879                 ok( res == (ch1 - ch2), "wrong result %d %04x %04x\n", res, ch1, ch2 );
1880                 res = pRtlCompareUnicodeStrings( &ch1, 1, &ch2, 1, TRUE );
1881                 ok( res == (pRtlUpcaseUnicodeChar(ch1) - pRtlUpcaseUnicodeChar(ch2)),
1882                     "wrong result %d %04x %04x\n", res, ch1, ch2 );
1883             }
1884         }
1885     }
1886 }
1887 
1888 static const WCHAR szGuid[] = { '{','0','1','0','2','0','3','0','4','-',
1889   '0','5','0','6','-'  ,'0','7','0','8','-','0','9','0','A','-',
1890   '0','B','0','C','0','D','0','E','0','F','0','A','}','\0' };
1891 static const WCHAR szGuid2[] = { '{','0','1','0','2','0','3','0','4','-',
1892   '0','5','0','6','-'  ,'0','7','0','8','-','0','9','0','A','-',
1893   '0','B','0','C','0','D','0','E','0','F','0','A',']','\0' };
1894 DEFINE_GUID(IID_Endianness, 0x01020304, 0x0506, 0x0708, 0x09, 0x0A, 0x0B,
1895             0x0C, 0x0D, 0x0E, 0x0F, 0x0A);
1896 
1897 static void test_RtlGUIDFromString(void)
1898 {
1899   GUID guid;
1900   UNICODE_STRING str;
1901   NTSTATUS ret;
1902 
1903   if (!pRtlGUIDFromString)
1904   {
1905       win_skip("RtlGUIDFromString is not available\n");
1906       return;
1907   }
1908 
1909   str.Length = str.MaximumLength = sizeof(szGuid) - sizeof(WCHAR);
1910   str.Buffer = (LPWSTR)szGuid;
1911 
1912   ret = pRtlGUIDFromString(&str, &guid);
1913   ok(ret == 0, "expected ret=0, got 0x%0x\n", ret);
1914   ok(IsEqualGUID(&guid, &IID_Endianness), "Endianness broken\n");
1915 
1916   str.Length = str.MaximumLength = sizeof(szGuid2) - sizeof(WCHAR);
1917   str.Buffer = (LPWSTR)szGuid2;
1918 
1919   ret = pRtlGUIDFromString(&str, &guid);
1920   ok(ret, "expected ret!=0\n");
1921 }
1922 
1923 static void test_RtlStringFromGUID(void)
1924 {
1925   UNICODE_STRING str;
1926   NTSTATUS ret;
1927 
1928   if (!pRtlStringFromGUID)
1929   {
1930       win_skip("RtlStringFromGUID is not available\n");
1931       return;
1932   }
1933 
1934   str.Length = str.MaximumLength = 0;
1935   str.Buffer = NULL;
1936 
1937   ret = pRtlStringFromGUID(&IID_Endianness, &str);
1938   ok(ret == 0, "expected ret=0, got 0x%0x\n", ret);
1939   ok(str.Buffer && !lstrcmpiW(str.Buffer, szGuid), "Endianness broken\n");
1940   pRtlFreeUnicodeString(&str);
1941 }
1942 
1943 struct hash_unicodestring_test {
1944     WCHAR str[50];
1945     BOOLEAN case_insensitive;
1946     ULONG hash;
1947 };
1948 
1949 static const struct hash_unicodestring_test hash_test[] = {
1950     { {'T',0},                     FALSE, 0x00000054 },
1951     { {'T','e','s','t',0},         FALSE, 0x766bb952 },
1952     { {'T','e','S','t',0},         FALSE, 0x764bb172 },
1953     { {'t','e','s','t',0},         FALSE, 0x4745d132 },
1954     { {'t','e','s','t',0},         TRUE,  0x6689c132 },
1955     { {'T','E','S','T',0},         TRUE,  0x6689c132 },
1956     { {'T','E','S','T',0},         FALSE, 0x6689c132 },
1957     { {'a','b','c','d','e','f',0}, FALSE, 0x971318c3 },
1958     { { 0 } }
1959 };
1960 
1961 static void test_RtlHashUnicodeString(void)
1962 {
1963     static const WCHAR strW[] = {'T','e','s','t',0,'1',0};
1964     const struct hash_unicodestring_test *ptr;
1965     UNICODE_STRING str;
1966     NTSTATUS status;
1967     ULONG hash;
1968 
1969     if (!pRtlHashUnicodeString)
1970     {
1971         win_skip("RtlHashUnicodeString is not available\n");
1972         return;
1973     }
1974 
1975     status = pRtlHashUnicodeString(NULL, FALSE, HASH_STRING_ALGORITHM_X65599, &hash);
1976     ok(status == STATUS_INVALID_PARAMETER, "got status 0x%08x\n", status);
1977 
1978     RtlInitUnicodeString(&str, strW);
1979     status = pRtlHashUnicodeString(&str, FALSE, HASH_STRING_ALGORITHM_X65599, NULL);
1980     ok(status == STATUS_INVALID_PARAMETER, "got status 0x%08x\n", status);
1981 
1982     status = pRtlHashUnicodeString(&str, FALSE, HASH_STRING_ALGORITHM_INVALID, &hash);
1983     ok(status == STATUS_INVALID_PARAMETER, "got status 0x%08x\n", status);
1984 
1985     /* embedded null */
1986     str.Buffer = (PWSTR)strW;
1987     str.Length = sizeof(strW) - sizeof(WCHAR);
1988     str.MaximumLength = sizeof(strW);
1989     status = pRtlHashUnicodeString(&str, FALSE, HASH_STRING_ALGORITHM_X65599, &hash);
1990     ok(status == STATUS_SUCCESS, "got status 0x%08x\n", status);
1991     ok(hash == 0x32803083, "got 0x%08x\n", hash);
1992 
1993     ptr = hash_test;
1994     while (*ptr->str)
1995     {
1996         RtlInitUnicodeString(&str, ptr->str);
1997         hash = 0;
1998         status = pRtlHashUnicodeString(&str, ptr->case_insensitive, HASH_STRING_ALGORITHM_X65599, &hash);
1999         ok(status == STATUS_SUCCESS, "got status 0x%08x for %s\n", status, wine_dbgstr_w(ptr->str));
2000         ok(hash == ptr->hash, "got wrong hash 0x%08x, expected 0x%08x, for %s, mode %d\n", hash, ptr->hash,
2001             wine_dbgstr_w(ptr->str), ptr->case_insensitive);
2002 
2003         ptr++;
2004     }
2005 }
2006 
2007 struct unicode_to_utf8_test {
2008     WCHAR unicode[128];
2009     const char *expected;
2010     NTSTATUS status;
2011 };
2012 
2013 static const struct unicode_to_utf8_test unicode_to_utf8[] = {
2014     { { 0 }, "", STATUS_SUCCESS },
2015     { { '-',0 }, "-", STATUS_SUCCESS },
2016     { { 'h','e','l','l','o',0 }, "hello", STATUS_SUCCESS },
2017     { { '-',0x7f,'-',0x80,'-',0xff,'-',0x100,'-',0 }, "-\x7F-\xC2\x80-\xC3\xBF-\xC4\x80-", STATUS_SUCCESS },
2018     { { '-',0x7ff,'-',0x800,'-',0 }, "-\xDF\xBF-\xE0\xA0\x80-", STATUS_SUCCESS },
2019     { { '-',0xd7ff,'-',0xe000,'-',0 }, "-\xED\x9F\xBF-\xEE\x80\x80-", STATUS_SUCCESS },
2020                        /* 0x10000 */
2021     { { '-',0xffff,'-',0xd800,0xdc00,'-',0 }, "-\xEF\xBF\xBF-\xF0\x90\x80\x80-", STATUS_SUCCESS },
2022             /* 0x103ff */     /* 0x10400 */
2023     { { '-',0xd800,0xdfff,'-',0xd801,0xdc00,'-',0 }, "-\xF0\x90\x8F\xBF-\xF0\x90\x90\x80-", STATUS_SUCCESS },
2024             /* 0x10ffff */
2025     { { '-',0xdbff,0xdfff,'-',0 }, "-\xF4\x8F\xBF\xBF-", STATUS_SUCCESS },
2026     /* standalone lead surrogates become 0xFFFD */
2027     { { '-',0xd800,'-',0xdbff,'-',0 }, "-\xEF\xBF\xBD-\xEF\xBF\xBD-", STATUS_SOME_NOT_MAPPED },
2028     /* standalone trail surrogates become 0xFFFD */
2029     { { '-',0xdc00,'-',0xdfff,'-',0 }, "-\xEF\xBF\xBD-\xEF\xBF\xBD-", STATUS_SOME_NOT_MAPPED },
2030     /* reverse surrogate pair */
2031     { { '-',0xdfff,0xdbff,'-',0 }, "-\xEF\xBF\xBD\xEF\xBF\xBD-", STATUS_SOME_NOT_MAPPED },
2032     /* byte order marks */
2033     { { '-',0xfeff,'-',0xfffe,'-',0 }, "-\xEF\xBB\xBF-\xEF\xBF\xBE-", STATUS_SUCCESS },
2034     { { 0xfeff,'-',0 }, "\xEF\xBB\xBF-", STATUS_SUCCESS },
2035     { { 0xfffe,'-',0 }, "\xEF\xBF\xBE-", STATUS_SUCCESS },
2036     /* invalid code point */
2037     { { 0xffff,'-',0 }, "\xEF\xBF\xBF-", STATUS_SUCCESS },
2038     /* canonically equivalent representations -- no normalization should happen */
2039     { { '-',0x1e09,'-',0 }, "-\xE1\xB8\x89-", STATUS_SUCCESS },
2040     { { '-',0x0107,0x0327,'-',0 }, "-\xC4\x87\xCC\xA7-", STATUS_SUCCESS },
2041     { { '-',0x00e7,0x0301,'-',0 }, "-\xC3\xA7\xCC\x81-", STATUS_SUCCESS },
2042     { { '-',0x0063,0x0327,0x0301,'-',0 }, "-\x63\xCC\xA7\xCC\x81-", STATUS_SUCCESS },
2043     { { '-',0x0063,0x0301,0x0327,'-',0 }, "-\x63\xCC\x81\xCC\xA7-", STATUS_SUCCESS },
2044 };
2045 
2046 static void utf8_expect_(const unsigned char *out_string, ULONG buflen, ULONG out_bytes,
2047                          const WCHAR *in_string, ULONG in_bytes,
2048                          NTSTATUS expect_status, int line)
2049 {
2050     NTSTATUS status;
2051     ULONG bytes_out;
2052     char buffer[128];
2053     unsigned char *buf = (unsigned char *)buffer;
2054     unsigned int i;
2055 
2056     if (buflen == (ULONG)-1)
2057         buflen = sizeof(buffer);
2058     bytes_out = 0x55555555;
2059     memset(buffer, 0x55, sizeof(buffer));
2060     status = pRtlUnicodeToUTF8N(
2061         out_string ? buffer : NULL, buflen, &bytes_out,
2062         in_string, in_bytes);
2063     ok_(__FILE__, line)(status == expect_status, "status = 0x%x\n", status);
2064     ok_(__FILE__, line)(bytes_out == out_bytes, "bytes_out = %u\n", bytes_out);
2065     if (out_string)
2066     {
2067         for (i = 0; i < bytes_out; i++)
2068             ok_(__FILE__, line)(buf[i] == out_string[i],
2069                                 "buffer[%d] = 0x%x, expected 0x%x\n",
2070                                 i, buf[i], out_string[i]);
2071         for (; i < sizeof(buffer); i++)
2072             ok_(__FILE__, line)(buf[i] == 0x55,
2073                                 "buffer[%d] = 0x%x, expected 0x55\n",
2074                                 i, buf[i]);
2075     }
2076 }
2077 #define utf8_expect(out_string, buflen, out_bytes, in_string, in_bytes, expect_status) \
2078         utf8_expect_(out_string, buflen, out_bytes, in_string, in_bytes, expect_status, __LINE__)
2079 
2080 static void test_RtlUnicodeToUTF8N(void)
2081 {
2082     NTSTATUS status;
2083     ULONG bytes_out;
2084     ULONG bytes_out_array[2];
2085     void * const invalid_pointer = (void *)0x8;
2086     char buffer[128];
2087     const WCHAR empty_string[] = { 0 };
2088     const WCHAR test_string[] = { 'A',0,'a','b','c','d','e','f','g',0 };
2089     const WCHAR special_string[] = { 'X',0x80,0xd800,0 };
2090     const unsigned char special_expected[] = { 'X',0xc2,0x80,0xef,0xbf,0xbd,0 };
2091     unsigned int input_len;
2092     const unsigned int test_count = sizeof(unicode_to_utf8) / sizeof(unicode_to_utf8[0]);
2093     unsigned int i;
2094 
2095     if (!pRtlUnicodeToUTF8N)
2096     {
2097         skip("RtlUnicodeToUTF8N unavailable\n");
2098         return;
2099     }
2100 
2101     /* show that bytes_out is really ULONG */
2102     memset(bytes_out_array, 0x55, sizeof(bytes_out_array));
2103     status = pRtlUnicodeToUTF8N(NULL, 0, bytes_out_array, empty_string, 0);
2104     ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
2105     ok(bytes_out_array[0] == 0x00000000, "Got 0x%x\n", bytes_out_array[0]);
2106     ok(bytes_out_array[1] == 0x55555555, "Got 0x%x\n", bytes_out_array[1]);
2107 
2108     /* parameter checks */
2109     status = pRtlUnicodeToUTF8N(NULL, 0, NULL, NULL, 0);
2110     ok(status == STATUS_INVALID_PARAMETER_4, "status = 0x%x\n", status);
2111 
2112     status = pRtlUnicodeToUTF8N(NULL, 0, NULL, empty_string, 0);
2113     ok(status == STATUS_INVALID_PARAMETER, "status = 0x%x\n", status);
2114 
2115     bytes_out = 0x55555555;
2116     status = pRtlUnicodeToUTF8N(NULL, 0, &bytes_out, NULL, 0);
2117     ok(status == STATUS_INVALID_PARAMETER_4, "status = 0x%x\n", status);
2118     ok(bytes_out == 0x55555555, "bytes_out = 0x%x\n", bytes_out);
2119 
2120     bytes_out = 0x55555555;
2121     status = pRtlUnicodeToUTF8N(NULL, 0, &bytes_out, invalid_pointer, 0);
2122     ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
2123     ok(bytes_out == 0, "bytes_out = 0x%x\n", bytes_out);
2124 
2125     bytes_out = 0x55555555;
2126     status = pRtlUnicodeToUTF8N(NULL, 0, &bytes_out, empty_string, 0);
2127     ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
2128     ok(bytes_out == 0, "bytes_out = 0x%x\n", bytes_out);
2129 
2130     bytes_out = 0x55555555;
2131     status = pRtlUnicodeToUTF8N(NULL, 0, &bytes_out, test_string, 0);
2132     ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
2133     ok(bytes_out == 0, "bytes_out = 0x%x\n", bytes_out);
2134 
2135     bytes_out = 0x55555555;
2136     status = pRtlUnicodeToUTF8N(NULL, 0, &bytes_out, empty_string, 1);
2137     ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
2138     ok(bytes_out == 0, "bytes_out = 0x%x\n", bytes_out);
2139 
2140     bytes_out = 0x55555555;
2141     status = pRtlUnicodeToUTF8N(invalid_pointer, 0, &bytes_out, empty_string, 1);
2142     ok(status == STATUS_INVALID_PARAMETER_5, "status = 0x%x\n", status);
2143     ok(bytes_out == 0x55555555, "bytes_out = 0x%x\n", bytes_out);
2144 
2145     bytes_out = 0x55555555;
2146     status = pRtlUnicodeToUTF8N(invalid_pointer, 8, &bytes_out, empty_string, 1);
2147     ok(status == STATUS_INVALID_PARAMETER_5, "status = 0x%x\n", status);
2148     ok(bytes_out == 0x55555555, "bytes_out = 0x%x\n", bytes_out);
2149 
2150     /* length output with special chars */
2151 #define length_expect(in_chars, out_bytes, expect_status) \
2152         utf8_expect_(NULL, 0, out_bytes, \
2153                      special_string, in_chars * sizeof(WCHAR), \
2154                      expect_status, __LINE__)
2155 
2156     length_expect(0, 0, STATUS_SUCCESS);
2157     length_expect(1, 1, STATUS_SUCCESS);
2158     length_expect(2, 3, STATUS_SUCCESS);
2159     length_expect(3, 6, STATUS_SOME_NOT_MAPPED);
2160     length_expect(4, 7, STATUS_SOME_NOT_MAPPED);
2161 #undef length_expect
2162 
2163     /* output truncation */
2164 #define truncate_expect(buflen, out_bytes, expect_status) \
2165         utf8_expect_(special_expected, buflen, out_bytes, \
2166                      special_string, sizeof(special_string), \
2167                      expect_status, __LINE__)
2168 
2169     truncate_expect(0, 0, STATUS_BUFFER_TOO_SMALL);
2170     truncate_expect(1, 1, STATUS_BUFFER_TOO_SMALL);
2171     truncate_expect(2, 1, STATUS_BUFFER_TOO_SMALL);
2172     truncate_expect(3, 3, STATUS_BUFFER_TOO_SMALL);
2173     truncate_expect(4, 3, STATUS_BUFFER_TOO_SMALL);
2174     truncate_expect(5, 3, STATUS_BUFFER_TOO_SMALL);
2175     truncate_expect(6, 6, STATUS_BUFFER_TOO_SMALL);
2176     truncate_expect(7, 7, STATUS_SOME_NOT_MAPPED);
2177 #undef truncate_expect
2178 
2179     /* conversion behavior with varying input length */
2180     for (input_len = 0; input_len <= sizeof(test_string); input_len++) {
2181         /* no output buffer, just length */
2182         utf8_expect(NULL, 0, input_len / sizeof(WCHAR),
2183                     test_string, input_len, STATUS_SUCCESS);
2184 
2185         /* write output */
2186         bytes_out = 0x55555555;
2187         memset(buffer, 0x55, sizeof(buffer));
2188         status = pRtlUnicodeToUTF8N(
2189             buffer, sizeof(buffer), &bytes_out,
2190             test_string, input_len);
2191         if (input_len % sizeof(WCHAR) == 0) {
2192             ok(status == STATUS_SUCCESS,
2193                "(len %u): status = 0x%x\n", input_len, status);
2194             ok(bytes_out == input_len / sizeof(WCHAR),
2195                "(len %u): bytes_out = 0x%x\n", input_len, bytes_out);
2196             for (i = 0; i < bytes_out; i++) {
2197                 ok(buffer[i] == test_string[i],
2198                    "(len %u): buffer[%d] = 0x%x, expected 0x%x\n",
2199                    input_len, i, buffer[i], test_string[i]);
2200             }
2201             for (; i < sizeof(buffer); i++) {
2202                 ok(buffer[i] == 0x55,
2203                    "(len %u): buffer[%d] = 0x%x\n", input_len, i, buffer[i]);
2204             }
2205         } else {
2206             ok(status == STATUS_INVALID_PARAMETER_5,
2207                "(len %u): status = 0x%x\n", input_len, status);
2208             ok(bytes_out == 0x55555555,
2209                "(len %u): bytes_out = 0x%x\n", input_len, bytes_out);
2210             for (i = 0; i < sizeof(buffer); i++) {
2211                 ok(buffer[i] == 0x55,
2212                    "(len %u): buffer[%d] = 0x%x\n", input_len, i, buffer[i]);
2213             }
2214         }
2215     }
2216 
2217     /* test cases for special characters */
2218     for (i = 0; i < test_count; i++) {
2219         bytes_out = 0x55555555;
2220         memset(buffer, 0x55, sizeof(buffer));
2221         status = pRtlUnicodeToUTF8N(
2222             buffer, sizeof(buffer), &bytes_out,
2223             unicode_to_utf8[i].unicode, lstrlenW(unicode_to_utf8[i].unicode) * sizeof(WCHAR));
2224         ok(status == unicode_to_utf8[i].status,
2225            "(test %d): status is 0x%x, expected 0x%x\n",
2226            i, status, unicode_to_utf8[i].status);
2227         ok(bytes_out == strlen(unicode_to_utf8[i].expected),
2228            "(test %d): bytes_out is %u, expected %u\n",
2229            i, bytes_out, lstrlenA(unicode_to_utf8[i].expected));
2230         ok(!memcmp(buffer, unicode_to_utf8[i].expected, bytes_out),
2231            "(test %d): got \"%.*s\", expected \"%s\"\n",
2232            i, bytes_out, buffer, unicode_to_utf8[i].expected);
2233         ok(buffer[bytes_out] == 0x55,
2234            "(test %d): behind string: 0x%x\n", i, buffer[bytes_out]);
2235 
2236         /* same test but include the null terminator */
2237         bytes_out = 0x55555555;
2238         memset(buffer, 0x55, sizeof(buffer));
2239         status = pRtlUnicodeToUTF8N(
2240             buffer, sizeof(buffer), &bytes_out,
2241             unicode_to_utf8[i].unicode, (lstrlenW(unicode_to_utf8[i].unicode) + 1) * sizeof(WCHAR));
2242         ok(status == unicode_to_utf8[i].status,
2243            "(test %d): status is 0x%x, expected 0x%x\n",
2244            i, status, unicode_to_utf8[i].status);
2245         ok(bytes_out == strlen(unicode_to_utf8[i].expected) + 1,
2246            "(test %d): bytes_out is %u, expected %u\n",
2247            i, bytes_out, lstrlenA(unicode_to_utf8[i].expected) + 1);
2248         ok(!memcmp(buffer, unicode_to_utf8[i].expected, bytes_out),
2249            "(test %d): got \"%.*s\", expected \"%s\"\n",
2250            i, bytes_out, buffer, unicode_to_utf8[i].expected);
2251         ok(buffer[bytes_out] == 0x55,
2252            "(test %d): behind string: 0x%x\n", i, buffer[bytes_out]);
2253     }
2254 }
2255 
2256 struct utf8_to_unicode_test {
2257     const char *utf8;
2258     WCHAR expected[128];
2259     NTSTATUS status;
2260 };
2261 
2262 static const struct utf8_to_unicode_test utf8_to_unicode[] = {
2263     { "", { 0 }, STATUS_SUCCESS },
2264     { "-", { '-',0 }, STATUS_SUCCESS },
2265     { "hello", { 'h','e','l','l','o',0 }, STATUS_SUCCESS },
2266     /* first and last of each range */
2267     { "-\x7F-\xC2\x80-\xC3\xBF-\xC4\x80-", { '-',0x7f,'-',0x80,'-',0xff,'-',0x100,'-',0 }, STATUS_SUCCESS },
2268     { "-\xDF\xBF-\xE0\xA0\x80-", { '-',0x7ff,'-',0x800,'-',0 }, STATUS_SUCCESS },
2269     { "-\xED\x9F\xBF-\xEE\x80\x80-", { '-',0xd7ff,'-',0xe000,'-',0 }, STATUS_SUCCESS },
2270                      /*   0x10000  */
2271     { "-\xEF\xBF\xBF-\xF0\x90\x80\x80-", { '-',0xffff,'-',0xd800,0xdc00,'-',0 }, STATUS_SUCCESS },
2272         /*   0x103ff  */ /*   0x10400  */
2273     { "-\xF0\x90\x8F\xBF-\xF0\x90\x90\x80-", { '-',0xd800,0xdfff,'-',0xd801,0xdc00,'-',0 }, STATUS_SUCCESS },
2274         /*  0x10ffff  */
2275     { "-\xF4\x8F\xBF\xBF-", { '-',0xdbff,0xdfff,'-',0 }, STATUS_SUCCESS },
2276     /* standalone surrogate code points */
2277         /* 0xd800 */ /* 0xdbff */
2278     { "-\xED\xA0\x80-\xED\xAF\xBF-", { '-',0xfffd,0xfffd,'-',0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2279         /* 0xdc00 */ /* 0xdfff */
2280     { "-\xED\xB0\x80-\xED\xBF\xBF-", { '-',0xfffd,0xfffd,'-',0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2281     /* UTF-8 encoded surrogate pair */
2282         /* 0xdbff *//* 0xdfff */
2283     { "-\xED\xAF\xBF\xED\xBF\xBF-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2284     /* reverse surrogate pair */
2285         /* 0xdfff *//* 0xdbff */
2286     { "-\xED\xBF\xBF\xED\xAF\xBF-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2287     /* code points outside the UTF-16 range */
2288         /*  0x110000  */
2289     { "-\xF4\x90\x80\x80-", { '-',0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2290         /*  0x1fffff  */
2291     { "-\xF7\xBF\xBF\xBF-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2292         /*     0x200000   */
2293     { "-\xFA\x80\x80\x80\x80-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2294         /*    0x3ffffff   */
2295     { "-\xFB\xBF\xBF\xBF\xBF-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2296         /*      0x4000000     */
2297     { "-\xFC\x84\x80\x80\x80\x80-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2298         /*     0x7fffffff     */
2299     { "-\xFD\xBF\xBF\xBF\xBF\xBF-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2300     /* overlong encodings of each length for -, NUL, and the highest possible value */
2301     { "-\xC0\xAD-\xC0\x80-\xC1\xBF-", { '-',0xfffd,0xfffd,'-',0xfffd,0xfffd,'-',0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2302     { "-\xE0\x80\xAD-\xE0\x80\x80-\xE0\x9F\xBF-", { '-',0xfffd,0xfffd,'-',0xfffd,0xfffd,'-',0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2303     { "-\xF0\x80\x80\xAD-", { '-',0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2304     { "-\xF0\x80\x80\x80-", { '-',0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2305     { "-\xF0\x8F\xBF\xBF-", { '-',0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2306     { "-\xF8\x80\x80\x80\xAD-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2307     { "-\xF8\x80\x80\x80\x80-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2308     { "-\xF8\x87\xBF\xBF\xBF-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2309     { "-\xFC\x80\x80\x80\x80\xAD-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2310     { "-\xFC\x80\x80\x80\x80\x80-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2311     { "-\xFC\x83\xBF\xBF\xBF\xBF-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2312     /* invalid bytes */
2313     { "\xFE", { 0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
2314     { "\xFF", { 0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
2315     { "\xFE\xBF\xBF\xBF\xBF\xBF\xBF\xBF\xBF", { 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
2316     { "\xFF\xBF\xBF\xBF\xBF\xBF\xBF\xBF\xBF", { 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
2317     { "\xFF\x80\x80\x80\x80\x80\x80\x80\x80", { 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
2318     { "\xFF\x40\x80\x80\x80\x80\x80\x80\x80", { 0xfffd,0x40,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
2319     /* lone continuation bytes */
2320     { "\x80", { 0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
2321     { "\x80\x80", { 0xfffd,0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
2322     { "\xBF", { 0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
2323     { "\xBF\xBF", { 0xfffd,0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
2324     /* incomplete sequences */
2325     { "\xC2-", { 0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2326     { "\xE0\xA0-", { 0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2327     { "\xF0\x90\x80-", { 0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2328     { "\xF4\x8F\xBF-", { 0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2329     { "\xFA\x80\x80\x80-", { 0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2330     { "\xFC\x84\x80\x80\x80-", { 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2331     /* multibyte sequence followed by lone continuation byte */
2332     { "\xE0\xA0\x80\x80-", { 0x800,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
2333     /* byte order marks */
2334     { "-\xEF\xBB\xBF-\xEF\xBF\xBE-", { '-',0xfeff,'-',0xfffe,'-',0 }, STATUS_SUCCESS },
2335     { "\xEF\xBB\xBF-", { 0xfeff,'-',0 }, STATUS_SUCCESS },
2336     { "\xEF\xBF\xBE-", { 0xfffe,'-',0 }, STATUS_SUCCESS },
2337     /* invalid code point */
2338        /* 0xffff */
2339     { "\xEF\xBF\xBF-", { 0xffff,'-',0 }, STATUS_SUCCESS },
2340     /* canonically equivalent representations -- no normalization should happen */
2341     { "-\xE1\xB8\x89-", { '-',0x1e09,'-',0 }, STATUS_SUCCESS },
2342     { "-\xC4\x87\xCC\xA7-", { '-',0x0107,0x0327,'-',0 }, STATUS_SUCCESS },
2343     { "-\xC3\xA7\xCC\x81-", { '-',0x00e7,0x0301,'-',0 }, STATUS_SUCCESS },
2344     { "-\x63\xCC\xA7\xCC\x81-", { '-',0x0063,0x0327,0x0301,'-',0 }, STATUS_SUCCESS },
2345     { "-\x63\xCC\x81\xCC\xA7-", { '-',0x0063,0x0301,0x0327,'-',0 }, STATUS_SUCCESS },
2346 };
2347 
2348 static void unicode_expect_(const WCHAR *out_string, ULONG buflen, ULONG out_chars,
2349                             const char *in_string, ULONG in_chars,
2350                             NTSTATUS expect_status, int line)
2351 {
2352     NTSTATUS status;
2353     ULONG bytes_out;
2354     WCHAR buffer[128];
2355     unsigned int i;
2356 
2357     if (buflen == (ULONG)-1)
2358         buflen = sizeof(buffer);
2359     bytes_out = 0x55555555;
2360     memset(buffer, 0x55, sizeof(buffer));
2361     status = pRtlUTF8ToUnicodeN(
2362         out_string ? buffer : NULL, buflen, &bytes_out,
2363         in_string, in_chars);
2364     ok_(__FILE__, line)(status == expect_status, "status = 0x%x\n", status);
2365     ok_(__FILE__, line)(bytes_out == out_chars * sizeof(WCHAR),
2366                         "bytes_out = %u, expected %u\n", bytes_out, out_chars * (ULONG)sizeof(WCHAR));
2367     if (out_string)
2368     {
2369         for (i = 0; i < bytes_out / sizeof(WCHAR); i++)
2370             ok_(__FILE__, line)(buffer[i] == out_string[i],
2371                                 "buffer[%d] = 0x%x, expected 0x%x\n",
2372                                 i, buffer[i], out_string[i]);
2373         for (; i < sizeof(buffer) / sizeof(WCHAR); i++)
2374             ok_(__FILE__, line)(buffer[i] == 0x5555,
2375                                 "buffer[%d] = 0x%x, expected 0x5555\n",
2376                                 i, buffer[i]);
2377     }
2378 }
2379 #define unicode_expect(out_string, buflen, out_chars, in_string, in_chars, expect_status) \
2380         unicode_expect_(out_string, buflen, out_chars, in_string, in_chars, expect_status, __LINE__)
2381 
2382 static void test_RtlUTF8ToUnicodeN(void)
2383 {
2384     NTSTATUS status;
2385     ULONG bytes_out;
2386     ULONG bytes_out_array[2];
2387     void * const invalid_pointer = (void *)0x8;
2388     WCHAR buffer[128];
2389     const char empty_string[] = "";
2390     const char test_string[] = "A\0abcdefg";
2391     const WCHAR test_stringW[] = {'A',0,'a','b','c','d','e','f','g',0 };
2392     const char special_string[] = { 'X',0xc2,0x80,0xF0,0x90,0x80,0x80,0 };
2393     const WCHAR special_expected[] = { 'X',0x80,0xd800,0xdc00,0 };
2394     unsigned int input_len;
2395     const unsigned int test_count = sizeof(utf8_to_unicode) / sizeof(utf8_to_unicode[0]);
2396     unsigned int i;
2397 
2398     if (!pRtlUTF8ToUnicodeN)
2399     {
2400         skip("RtlUTF8ToUnicodeN unavailable\n");
2401         return;
2402     }
2403 
2404     /* show that bytes_out is really ULONG */
2405     memset(bytes_out_array, 0x55, sizeof(bytes_out_array));
2406     status = pRtlUTF8ToUnicodeN(NULL, 0, bytes_out_array, empty_string, 0);
2407     ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
2408     ok(bytes_out_array[0] == 0x00000000, "Got 0x%x\n", bytes_out_array[0]);
2409     ok(bytes_out_array[1] == 0x55555555, "Got 0x%x\n", bytes_out_array[1]);
2410 
2411     /* parameter checks */
2412     status = pRtlUTF8ToUnicodeN(NULL, 0, NULL, NULL, 0);
2413     ok(status == STATUS_INVALID_PARAMETER_4, "status = 0x%x\n", status);
2414 
2415     status = pRtlUTF8ToUnicodeN(NULL, 0, NULL, empty_string, 0);
2416     ok(status == STATUS_INVALID_PARAMETER, "status = 0x%x\n", status);
2417 
2418     bytes_out = 0x55555555;
2419     status = pRtlUTF8ToUnicodeN(NULL, 0, &bytes_out, NULL, 0);
2420     ok(status == STATUS_INVALID_PARAMETER_4, "status = 0x%x\n", status);
2421     ok(bytes_out == 0x55555555, "bytes_out = 0x%x\n", bytes_out);
2422 
2423     bytes_out = 0x55555555;
2424     status = pRtlUTF8ToUnicodeN(NULL, 0, &bytes_out, invalid_pointer, 0);
2425     ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
2426     ok(bytes_out == 0, "bytes_out = 0x%x\n", bytes_out);
2427 
2428     bytes_out = 0x55555555;
2429     status = pRtlUTF8ToUnicodeN(NULL, 0, &bytes_out, empty_string, 0);
2430     ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
2431     ok(bytes_out == 0, "bytes_out = 0x%x\n", bytes_out);
2432 
2433     bytes_out = 0x55555555;
2434     status = pRtlUTF8ToUnicodeN(NULL, 0, &bytes_out, test_string, 0);
2435     ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
2436     ok(bytes_out == 0, "bytes_out = 0x%x\n", bytes_out);
2437 
2438     bytes_out = 0x55555555;
2439     status = pRtlUTF8ToUnicodeN(NULL, 0, &bytes_out, empty_string, 1);
2440     ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
2441     ok(bytes_out == sizeof(WCHAR), "bytes_out = 0x%x\n", bytes_out);
2442 
2443     /* length output with special chars */
2444 #define length_expect(in_chars, out_chars, expect_status) \
2445         unicode_expect_(NULL, 0, out_chars, special_string, in_chars, \
2446                         expect_status, __LINE__)
2447 
2448     length_expect(0, 0, STATUS_SUCCESS);
2449     length_expect(1, 1, STATUS_SUCCESS);
2450     length_expect(2, 2, STATUS_SOME_NOT_MAPPED);
2451     length_expect(3, 2, STATUS_SUCCESS);
2452     length_expect(4, 3, STATUS_SOME_NOT_MAPPED);
2453     length_expect(5, 3, STATUS_SOME_NOT_MAPPED);
2454     length_expect(6, 3, STATUS_SOME_NOT_MAPPED);
2455     length_expect(7, 4, STATUS_SUCCESS);
2456     length_expect(8, 5, STATUS_SUCCESS);
2457 #undef length_expect
2458 
2459     /* output truncation */
2460 #define truncate_expect(buflen, out_chars, expect_status) \
2461         unicode_expect_(special_expected, buflen, out_chars, \
2462                         special_string, sizeof(special_string), \
2463                         expect_status, __LINE__)
2464 
2465     truncate_expect( 0, 0, STATUS_BUFFER_TOO_SMALL);
2466     truncate_expect( 1, 0, STATUS_BUFFER_TOO_SMALL);
2467     truncate_expect( 2, 1, STATUS_BUFFER_TOO_SMALL);
2468     truncate_expect( 3, 1, STATUS_BUFFER_TOO_SMALL);
2469     truncate_expect( 4, 2, STATUS_BUFFER_TOO_SMALL);
2470     truncate_expect( 5, 2, STATUS_BUFFER_TOO_SMALL);
2471     truncate_expect( 6, 3, STATUS_BUFFER_TOO_SMALL);
2472     truncate_expect( 7, 3, STATUS_BUFFER_TOO_SMALL);
2473     truncate_expect( 8, 4, STATUS_BUFFER_TOO_SMALL);
2474     truncate_expect( 9, 4, STATUS_BUFFER_TOO_SMALL);
2475     truncate_expect(10, 5, STATUS_SUCCESS);
2476 #undef truncate_expect
2477 
2478     /* conversion behavior with varying input length */
2479     for (input_len = 0; input_len <= sizeof(test_string); input_len++) {
2480         /* no output buffer, just length */
2481         unicode_expect(NULL, 0, input_len,
2482                        test_string, input_len, STATUS_SUCCESS);
2483 
2484         /* write output */
2485         unicode_expect(test_stringW, -1, input_len,
2486                        test_string, input_len, STATUS_SUCCESS);
2487     }
2488 
2489     /* test cases for special characters */
2490     for (i = 0; i < test_count; i++) {
2491         bytes_out = 0x55555555;
2492         memset(buffer, 0x55, sizeof(buffer));
2493         status = pRtlUTF8ToUnicodeN(
2494             buffer, sizeof(buffer), &bytes_out,
2495             utf8_to_unicode[i].utf8, strlen(utf8_to_unicode[i].utf8));
2496         ok(status == utf8_to_unicode[i].status,
2497            "(test %d): status is 0x%x, expected 0x%x\n",
2498            i, status, utf8_to_unicode[i].status);
2499         ok(bytes_out == lstrlenW(utf8_to_unicode[i].expected) * sizeof(WCHAR),
2500            "(test %d): bytes_out is %u, expected %u\n",
2501            i, bytes_out, lstrlenW(utf8_to_unicode[i].expected) * (ULONG)sizeof(WCHAR));
2502         ok(!memcmp(buffer, utf8_to_unicode[i].expected, bytes_out),
2503            "(test %d): got %s, expected %s\n",
2504            i, wine_dbgstr_wn(buffer, bytes_out / sizeof(WCHAR)), wine_dbgstr_w(utf8_to_unicode[i].expected));
2505         ok(buffer[bytes_out] == 0x5555,
2506            "(test %d): behind string: 0x%x\n", i, buffer[bytes_out]);
2507 
2508         /* same test but include the null terminator */
2509         bytes_out = 0x55555555;
2510         memset(buffer, 0x55, sizeof(buffer));
2511         status = pRtlUTF8ToUnicodeN(
2512             buffer, sizeof(buffer), &bytes_out,
2513             utf8_to_unicode[i].utf8, strlen(utf8_to_unicode[i].utf8) + 1);
2514         ok(status == utf8_to_unicode[i].status,
2515            "(test %d): status is 0x%x, expected 0x%x\n",
2516            i, status, utf8_to_unicode[i].status);
2517         ok(bytes_out == (lstrlenW(utf8_to_unicode[i].expected) + 1) * sizeof(WCHAR),
2518            "(test %d): bytes_out is %u, expected %u\n",
2519            i, bytes_out, (lstrlenW(utf8_to_unicode[i].expected) + 1) * (ULONG)sizeof(WCHAR));
2520         ok(!memcmp(buffer, utf8_to_unicode[i].expected, bytes_out),
2521            "(test %d): got %s, expected %s\n",
2522            i, wine_dbgstr_wn(buffer, bytes_out / sizeof(WCHAR)), wine_dbgstr_w(utf8_to_unicode[i].expected));
2523         ok(buffer[bytes_out] == 0x5555,
2524            "(test %d): behind string: 0x%x\n", i, buffer[bytes_out]);
2525     }
2526 }
2527 
2528 START_TEST(rtlstr)
2529 {
2530     InitFunctionPtrs();
2531     if (pRtlInitAnsiString) {
2532 	test_RtlInitString();
2533 	test_RtlInitUnicodeString();
2534 	test_RtlCopyString();
2535 	test_RtlUnicodeStringToInteger();
2536 	test_RtlCharToInteger();
2537 	test_RtlIntegerToUnicodeString();
2538 	test_RtlIntegerToChar();
2539 	test_RtlUpperChar();
2540 	test_RtlUpperString();
2541 	test_RtlUnicodeStringToAnsiString();
2542 	test_RtlAppendAsciizToString();
2543 	test_RtlAppendStringToString();
2544 	test_RtlAppendUnicodeToString();
2545 	test_RtlAppendUnicodeStringToString();
2546     }
2547 
2548     test_RtlInitUnicodeStringEx();
2549     test_RtlDuplicateUnicodeString();
2550     test_RtlFindCharInUnicodeString();
2551     test_RtlGUIDFromString();
2552     test_RtlStringFromGUID();
2553     test_RtlIsTextUnicode();
2554     test_RtlCompareUnicodeString();
2555     if(0)
2556     {
2557 	test_RtlUpcaseUnicodeChar();
2558 	test_RtlUpcaseUnicodeString();
2559 	test_RtlDowncaseUnicodeString();
2560     }
2561     test_RtlHashUnicodeString();
2562     test_RtlUnicodeToUTF8N();
2563     test_RtlUTF8ToUnicodeN();
2564 }
2565