hlink/tests: Don't check results in disabled tests (LLVM/Clang).
[wine] / dlls / msvcp90 / tests / string.c
1 /*
2  * Copyright 2010 Piotr Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include <stdio.h>
20
21 #include <windef.h>
22 #include <winbase.h>
23 #include "wine/test.h"
24
25 /* basic_string<char, char_traits<char>, allocator<char>> */
26 #define BUF_SIZE_CHAR 16
27 typedef struct _basic_string_char
28 {
29     void *allocator;
30     union {
31         char buf[BUF_SIZE_CHAR];
32         char *ptr;
33     } data;
34     size_t size;
35     size_t res;
36 } basic_string_char;
37
38 /* basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t>> */
39 #define BUF_SIZE_WCHAR 8
40 typedef struct _basic_string_wchar
41 {
42     void *allocator;
43     union {
44         wchar_t buf[BUF_SIZE_WCHAR];
45         wchar_t *ptr;
46     } data;
47     size_t size;
48     size_t res;
49 } basic_string_wchar;
50
51 static void* (__cdecl *p_set_invalid_parameter_handler)(void*);
52
53 #ifdef __i386__
54 static basic_string_char* (WINAPI *p_basic_string_char_ctor)(void);
55 static basic_string_char* (WINAPI *p_basic_string_char_copy_ctor)(basic_string_char*);
56 static basic_string_char* (WINAPI *p_basic_string_char_ctor_cstr)(const char*);
57 static void (WINAPI *p_basic_string_char_dtor)(void);
58 static basic_string_char* (WINAPI *p_basic_string_char_erase)(size_t, size_t);
59 static basic_string_char* (WINAPI *p_basic_string_char_assign_cstr_len)(const char*, size_t);
60 static const char* (WINAPI *p_basic_string_char_cstr)(void);
61 static const char* (WINAPI *p_basic_string_char_data)(void);
62 static size_t (WINAPI *p_basic_string_char_size)(void);
63 static size_t (WINAPI *p_basic_string_char_capacity)(void);
64 static void (WINAPI *p_basic_string_char_swap)(basic_string_char*);
65 static basic_string_char* (WINAPI *p_basic_string_char_append)(basic_string_char*);
66 static basic_string_char* (WINAPI *p_basic_string_char_append_substr)(basic_string_char*, size_t, size_t);
67 static int (WINAPI *p_basic_string_char_compare_substr_substr)(size_t, size_t, basic_string_char*, size_t, size_t);
68 static int (WINAPI *p_basic_string_char_compare_substr_cstr_len)(size_t, size_t, const char*, size_t);
69
70 static basic_string_wchar* (WINAPI *p_basic_string_wchar_ctor)(void);
71 static basic_string_wchar* (WINAPI *p_basic_string_wchar_copy_ctor)(basic_string_wchar*);
72 static basic_string_wchar* (WINAPI *p_basic_string_wchar_ctor_cstr)(const wchar_t*);
73 static void (WINAPI *p_basic_string_wchar_dtor)(void);
74 static basic_string_wchar* (WINAPI *p_basic_string_wchar_erase)(size_t, size_t);
75 static basic_string_wchar* (WINAPI *p_basic_string_wchar_assign_cstr_len)(const wchar_t*, size_t);
76 static const wchar_t* (WINAPI *p_basic_string_wchar_cstr)(void);
77 static const wchar_t* (WINAPI *p_basic_string_wchar_data)(void);
78 static size_t (WINAPI *p_basic_string_wchar_size)(void);
79 static size_t (WINAPI *p_basic_string_wchar_capacity)(void);
80 static void (WINAPI *p_basic_string_wchar_swap)(basic_string_wchar*);
81 #else
82 static basic_string_char* (__cdecl *p_basic_string_char_ctor)(basic_string_char*);
83 static basic_string_char* (__cdecl *p_basic_string_char_copy_ctor)(basic_string_char*, basic_string_char*);
84 static basic_string_char* (__cdecl *p_basic_string_char_ctor_cstr)(basic_string_char*, const char*);
85 static void (__cdecl *p_basic_string_char_dtor)(basic_string_char*);
86 static basic_string_char* (__cdecl *p_basic_string_char_erase)(basic_string_char*, size_t, size_t);
87 static basic_string_char* (__cdecl *p_basic_string_char_assign_cstr_len)(basic_string_char*, const char*, size_t);
88 static const char* (__cdecl *p_basic_string_char_cstr)(basic_string_char*);
89 static const char* (__cdecl *p_basic_string_char_data)(basic_string_char*);
90 static size_t (__cdecl *p_basic_string_char_size)(basic_string_char*);
91 static size_t (__cdecl *p_basic_string_char_capacity)(basic_string_char*);
92 static void (__cdecl *p_basic_string_char_swap)(basic_string_char*, basic_string_char*);
93 static basic_string_char* (WINAPI *p_basic_string_char_append)(basic_string_char*, basic_string_char*);
94 static basic_string_char* (WINAPI *p_basic_string_char_append_substr)(basic_string_char*, basic_string_char*, size_t, size_t);
95 static int (WINAPI *p_basic_string_char_compare_substr_substr)(basic_string_char*, size_t, size_t, basic_string_char*, size_t, size_t);
96 static int (WINAPI *p_basic_string_char_compare_substr_cstr_len)(basic_string_char*, size_t, size_t, const char*, size_t);
97
98 static basic_string_wchar* (__cdecl *p_basic_string_wchar_ctor)(basic_string_wchar*);
99 static basic_string_wchar* (__cdecl *p_basic_string_wchar_copy_ctor)(basic_string_wchar*, basic_string_wchar*);
100 static basic_string_wchar* (__cdecl *p_basic_string_wchar_ctor_cstr)(basic_string_wchar*, const wchar_t*);
101 static void (__cdecl *p_basic_string_wchar_dtor)(basic_string_wchar*);
102 static basic_string_wchar* (__cdecl *p_basic_string_wchar_erase)(basic_string_wchar*, size_t, size_t);
103 static basic_string_wchar* (__cdecl *p_basic_string_wchar_assign_cstr_len)(basic_string_wchar*, const wchar_t*, size_t);
104 static const wchar_t* (__cdecl *p_basic_string_wchar_cstr)(basic_string_wchar*);
105 static const wchar_t* (__cdecl *p_basic_string_wchar_data)(basic_string_wchar*);
106 static size_t (__cdecl *p_basic_string_wchar_size)(basic_string_wchar*);
107 static size_t (__cdecl *p_basic_string_wchar_capacity)(basic_string_wchar*);
108 static void (__cdecl *p_basic_string_wchar_swap)(basic_string_wchar*, basic_string_wchar*);
109 #endif
110
111 static int invalid_parameter = 0;
112 static void __cdecl test_invalid_parameter_handler(const wchar_t *expression,
113         const wchar_t *function, const wchar_t *file,
114         unsigned line, uintptr_t arg)
115 {
116     ok(expression == NULL, "expression is not NULL\n");
117     ok(function == NULL, "function is not NULL\n");
118     ok(file == NULL, "file is not NULL\n");
119     ok(line == 0, "line = %u\n", line);
120     ok(arg == 0, "arg = %lx\n", (UINT_PTR)arg);
121     invalid_parameter++;
122 }
123
124 /* Emulate a __thiscall */
125 #ifdef __i386__
126 #ifdef _MSC_VER
127 static inline void* do_call_func1(void *func, void *_this)
128 {
129     volatile void* retval = 0;
130     __asm
131     {
132         push ecx
133         mov ecx, _this
134         call func
135         mov retval, eax
136         pop ecx
137     }
138     return (void*)retval;
139 }
140
141 static inline void* do_call_func2(void *func, void *_this, const void *arg)
142 {
143     volatile void* retval = 0;
144     __asm
145     {
146         push ecx
147         push arg
148         mov ecx, _this
149         call func
150         mov retval, eax
151         pop ecx
152     }
153     return (void*)retval;
154 }
155
156 static inline void* do_call_func3(void *func, void *_this,
157         const void *arg1, const void *arg2)
158 {
159     volatile void* retval = 0;
160     __asm
161     {
162         push ecx
163         push arg1
164         push arg2
165         mov ecx, _this
166         call func
167         mov retval, eax
168         pop ecx
169     }
170     return (void*)retval;
171 }
172
173 static inline void* do_call_func4(void *func, void *_this,
174         const void *arg1, const void *arg2, const void *arg3)
175 {
176     volatile void* retval = 0;
177     __asm
178     {
179         push ecx
180         push arg1
181         push arg2
182         push arg3
183         mov ecx, _this
184         call func
185         mov retval, eax
186         pop ecx
187     }
188     return (void*)retval;
189 }
190
191 static inline void* do_call_func5(void *func, void *_this,
192         const void *arg1, const void *arg2, const void *arg3, const void *arg4)
193 {
194     volatile void* retval = 0;
195     __asm
196     {
197         push ecx
198         push arg1
199         push arg2
200         push arg3
201         push arg4
202         mov ecx, _this
203         call func
204         mov retval, eax
205         pop ecx
206     }
207     return (void*)retval;
208 }
209
210 static inline void* do_call_func6(void *func, void *_this,
211         const void *arg1, const void *arg2, const void *arg3,
212         const void *arg4, const void *arg5)
213 {
214     volatile void* retval = 0;
215     __asm
216     {
217         push ecx
218         push arg1
219         push arg2
220         push arg3
221         push arg4
222         push arg5
223         mov ecx, _this
224         call func
225         mov retval, eax
226         pop ecx
227     }
228     return (void*)retval;
229 }
230 #else
231 static void* do_call_func1(void *func, void *_this)
232 {
233     void *ret, *dummy;
234     __asm__ __volatile__ (
235             "call *%2"
236             : "=a" (ret), "=c" (dummy)
237             : "g" (func), "1" (_this)
238             : "edx", "memory"
239             );
240     return ret;
241 }
242
243 static void* do_call_func2(void *func, void *_this, const void *arg)
244 {
245     void *ret, *dummy;
246     __asm__ __volatile__ (
247             "pushl %3\n\tcall *%2"
248             : "=a" (ret), "=c" (dummy)
249             : "r" (func), "r" (arg), "1" (_this)
250             : "edx", "memory"
251             );
252     return ret;
253 }
254
255 static void* do_call_func3(void *func, void *_this,
256         const void *arg1, const void *arg2)
257 {
258     void *ret, *dummy;
259     __asm__ __volatile__ (
260             "pushl %4\n\tpushl %3\n\tcall *%2"
261             : "=a" (ret), "=c" (dummy)
262             : "r" (func), "r" (arg1), "r" (arg2), "1" (_this)
263             : "edx", "memory"
264             );
265     return ret;
266 }
267
268 static void* do_call_func4(void *func, void *_this,
269         const void *arg1, const void *arg2, const void *arg3)
270 {
271     void *ret, *dummy;
272     __asm__ __volatile__ (
273             "pushl %5\n\tpushl %4\n\tpushl %3\n\tcall *%2"
274             : "=a" (ret), "=c" (dummy)
275             : "r" (func), "r" (arg1), "r" (arg2), "m" (arg3), "1" (_this)
276             : "edx", "memory"
277             );
278     return ret;
279 }
280
281 static void* do_call_func5(void *func, void *_this,
282         const void *arg1, const void *arg2, const void *arg3, const void *arg4)
283 {
284     void *ret, *dummy;
285     __asm__ __volatile__ (
286             "pushl %6\n\tpushl %5\n\tpushl %4\n\tpushl %3\n\tcall *%2"
287             : "=a" (ret), "=c" (dummy)
288             : "r" (func), "r" (arg1), "r" (arg2), "m" (arg3), "m" (arg4), "1" (_this)
289             : "edx", "memory"
290             );
291     return ret;
292 }
293
294 static void* do_call_func6(void *func, void *_this,
295         const void *arg1, const void *arg2, const void *arg3,
296         const void *arg4, const void *arg5)
297 {
298     void *ret, *dummy;
299     __asm__ __volatile__ (
300             "pushl %7\n\tpushl %6\n\tpushl %5\n\tpushl %4\n\tpushl %3\n\tcall *%2"
301             : "=a" (ret), "=c" (dummy)
302             : "r" (func), "r" (arg1), "r" (arg2), "m" (arg3), "m" (arg4), "m" (arg5), "1" (_this)
303             : "edx", "memory"
304             );
305     return ret;
306 }
307 #endif
308
309 #define call_func1(func,_this)   do_call_func1(func,_this)
310 #define call_func2(func,_this,a) do_call_func2(func,_this,(const void*)a)
311 #define call_func3(func,_this,a,b) do_call_func3(func,_this,(const void*)a,(const void*)b)
312 #define call_func4(func,_this,a,b,c) do_call_func4(func,_this,(const void*)a,\
313         (const void*)b,(const void*)c)
314 #define call_func5(func,_this,a,b,c,d) do_call_func5(func,_this,(const void*)a,\
315         (const void*)b,(const void*)c,(const void*)d)
316 #define call_func6(func,_this,a,b,c,d,e) do_call_func6(func,_this,(const void*)a,\
317         (const void*)b,(const void*)c,(const void*)d,(const void*)e)
318
319 #else
320
321 #define call_func1(func,_this) func(_this)
322 #define call_func2(func,_this,a) func(_this,a)
323 #define call_func3(func,_this,a,b) func(_this,a,b)
324 #define call_func4(func,_this,a,b,c) func(_this,a,b,c)
325 #define call_func5(func,_this,a,b,c,d) func(_this,a,b,c,d)
326 #define call_func6(func,_this,a,b,c,d,e) func(_this,a,b,c,d,e)
327
328 #endif /* __i386__ */
329
330 static BOOL init(void)
331 {
332     HMODULE msvcr = LoadLibraryA("msvcr90.dll");
333     HMODULE msvcp = LoadLibraryA("msvcp90.dll");
334     if(!msvcr || !msvcp) {
335         win_skip("msvcp90.dll or msvcrt90.dll not installed\n");
336         return FALSE;
337     }
338
339     p_set_invalid_parameter_handler = (void*)GetProcAddress(msvcr, "_set_invalid_parameter_handler");
340     if(!p_set_invalid_parameter_handler) {
341         win_skip("Error setting tests environment\n");
342         return FALSE;
343     }
344
345     p_set_invalid_parameter_handler(test_invalid_parameter_handler);
346
347     if(sizeof(void*) == 8) { /* 64-bit initialization */
348         p_basic_string_char_ctor = (void*)GetProcAddress(msvcp,
349                 "??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@XZ");
350         p_basic_string_char_copy_ctor = (void*)GetProcAddress(msvcp,
351                 "??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@AEBV01@@Z");
352         p_basic_string_char_ctor_cstr = (void*)GetProcAddress(msvcp,
353                 "??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@PEBD@Z");
354         p_basic_string_char_dtor = (void*)GetProcAddress(msvcp,
355                 "??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@XZ");
356         p_basic_string_char_erase = (void*)GetProcAddress(msvcp,
357                 "?erase@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAAEAV12@_K0@Z");
358         p_basic_string_char_assign_cstr_len = (void*)GetProcAddress(msvcp,
359                 "?assign@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAAEAV12@PEBD_K@Z");
360         p_basic_string_char_cstr = (void*)GetProcAddress(msvcp,
361                 "?c_str@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEBAPEBDXZ");
362         p_basic_string_char_data = (void*)GetProcAddress(msvcp,
363                 "?data@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEBAPEBDXZ");
364         p_basic_string_char_size = (void*)GetProcAddress(msvcp,
365                 "?size@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEBA_KXZ");
366         p_basic_string_char_capacity = (void*)GetProcAddress(msvcp,
367                 "?capacity@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEBA_KXZ");
368         p_basic_string_char_swap = (void*)GetProcAddress(msvcp,
369                 "?swap@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAXAEAV12@@Z");
370         p_basic_string_char_append = (void*)GetProcAddress(msvcp,
371                 "?append@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAAEAV12@AEBV12@@Z");
372         p_basic_string_char_append_substr = (void*)GetProcAddress(msvcp,
373                 "?append@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAAEAV12@AEBV12@_K1@Z");
374         p_basic_string_char_compare_substr_substr = (void*)GetProcAddress(msvcp,
375                 "?compare@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEBAH_K0AEBV12@00@Z");
376         p_basic_string_char_compare_substr_cstr_len = (void*)GetProcAddress(msvcp,
377                 "?compare@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEBAH_K0PEBD0@Z");
378
379         p_basic_string_wchar_ctor = (void*)GetProcAddress(msvcp,
380                 "??0?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QEAA@XZ");
381         p_basic_string_wchar_copy_ctor = (void*)GetProcAddress(msvcp,
382                 "??0?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QEAA@AEBV01@@Z");
383         p_basic_string_wchar_ctor_cstr = (void*)GetProcAddress(msvcp,
384                 "??0?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QEAA@PEB_W@Z");
385         p_basic_string_wchar_dtor = (void*)GetProcAddress(msvcp,
386                 "??1?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QEAA@XZ");
387         p_basic_string_wchar_erase = (void*)GetProcAddress(msvcp,
388                 "?erase@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QEAAAEAV12@_K0@Z");
389         p_basic_string_wchar_assign_cstr_len = (void*)GetProcAddress(msvcp,
390                 "?assign@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QEAAAEAV12@PEB_W_K@Z");
391         p_basic_string_wchar_cstr = (void*)GetProcAddress(msvcp,
392                 "?c_str@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QEBAPEB_WXZ");
393         p_basic_string_wchar_data = (void*)GetProcAddress(msvcp,
394                 "?data@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QEBAPEB_WXZ");
395         p_basic_string_wchar_size = (void*)GetProcAddress(msvcp,
396                 "?size@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QEBA_KXZ");
397         p_basic_string_wchar_capacity = (void*)GetProcAddress(msvcp,
398                 "?capacity@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QEBA_KXZ");
399         p_basic_string_wchar_swap = (void*)GetProcAddress(msvcp,
400                 "?swap@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QEAAXAEAV12@@Z");
401     } else {
402         p_basic_string_char_ctor = (void*)GetProcAddress(msvcp,
403                 "??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ");
404         p_basic_string_char_copy_ctor = (void*)GetProcAddress(msvcp,
405                 "??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@ABV01@@Z");
406         p_basic_string_char_ctor_cstr = (void*)GetProcAddress(msvcp,
407                 "??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z");
408         p_basic_string_char_dtor = (void*)GetProcAddress(msvcp,
409                 "??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ");
410         p_basic_string_char_erase = (void*)GetProcAddress(msvcp,
411                 "?erase@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@II@Z");
412         p_basic_string_char_assign_cstr_len = (void*)GetProcAddress(msvcp,
413                 "?assign@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@PBDI@Z");
414         p_basic_string_char_cstr = (void*)GetProcAddress(msvcp,
415                 "?c_str@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEPBDXZ");
416         p_basic_string_char_data = (void*)GetProcAddress(msvcp,
417                 "?data@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEPBDXZ");
418         p_basic_string_char_size = (void*)GetProcAddress(msvcp,
419                 "?size@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEIXZ");
420         p_basic_string_char_capacity = (void*)GetProcAddress(msvcp,
421                 "?capacity@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEIXZ");
422         p_basic_string_char_swap = (void*)GetProcAddress(msvcp,
423                 "?swap@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEXAAV12@@Z");
424         p_basic_string_char_append = (void*)GetProcAddress(msvcp,
425                 "?append@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@ABV12@@Z");
426         p_basic_string_char_append_substr = (void*)GetProcAddress(msvcp,
427                 "?append@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@ABV12@II@Z");
428         p_basic_string_char_compare_substr_substr = (void*)GetProcAddress(msvcp,
429                 "?compare@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEHIIABV12@II@Z");
430         p_basic_string_char_compare_substr_cstr_len = (void*)GetProcAddress(msvcp,
431                 "?compare@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEHIIPBDI@Z");
432
433         p_basic_string_wchar_ctor = (void*)GetProcAddress(msvcp,
434                 "??0?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAE@XZ");
435         p_basic_string_wchar_copy_ctor = (void*)GetProcAddress(msvcp,
436                 "??0?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAE@ABV01@@Z");
437         p_basic_string_wchar_ctor_cstr = (void*)GetProcAddress(msvcp,
438                 "??0?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAE@PB_W@Z");
439         p_basic_string_wchar_dtor = (void*)GetProcAddress(msvcp,
440                 "??1?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAE@XZ");
441         p_basic_string_wchar_erase = (void*)GetProcAddress(msvcp,
442                 "?erase@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAEAAV12@II@Z");
443         p_basic_string_wchar_assign_cstr_len = (void*)GetProcAddress(msvcp,
444                 "?assign@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAEAAV12@PB_WI@Z");
445         p_basic_string_wchar_cstr = (void*)GetProcAddress(msvcp,
446                 "?c_str@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QBEPB_WXZ");
447         p_basic_string_wchar_data = (void*)GetProcAddress(msvcp,
448                 "?data@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QBEPB_WXZ");
449         p_basic_string_wchar_size = (void*)GetProcAddress(msvcp,
450                 "?size@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QBEIXZ");
451         p_basic_string_wchar_capacity = (void*)GetProcAddress(msvcp,
452                 "?capacity@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QBEIXZ");
453         p_basic_string_wchar_swap = (void*)GetProcAddress(msvcp,
454                 "?swap@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAEXAAV12@@Z");
455     }
456
457     return TRUE;
458 }
459
460 static void test_basic_string_char(void) {
461     basic_string_char str1, str2, *pstr;
462     const char *str;
463     size_t size, capacity;
464
465     if(!p_basic_string_char_ctor || !p_basic_string_char_copy_ctor
466             || !p_basic_string_char_ctor_cstr || !p_basic_string_char_dtor
467             || !p_basic_string_char_erase || !p_basic_string_char_assign_cstr_len
468             || !p_basic_string_char_cstr || !p_basic_string_char_data
469             || !p_basic_string_char_size || !p_basic_string_char_capacity) {
470         win_skip("basic_string<char> unavailable\n");
471         return;
472     }
473
474     call_func1(p_basic_string_char_ctor, &str1);
475     str = NULL;
476     str = call_func1(p_basic_string_char_cstr, &str1);
477     ok(str != NULL, "str = NULL\n");
478     ok(*str == '\0', "*str = %c\n", *str);
479     str = call_func1(p_basic_string_char_data, &str1);
480     ok(str != NULL, "str = NULL\n");
481     ok(*str == '\0', "*str = %c\n", *str);
482     call_func1(p_basic_string_char_dtor, &str1);
483
484     pstr = call_func2(p_basic_string_char_ctor_cstr, &str1, "test");
485     ok(pstr == &str1, "pstr != &str1\n");
486     str = call_func1(p_basic_string_char_cstr, &str1);
487     ok(!memcmp(str, "test", 5), "str = %s\n", str);
488     str = call_func1(p_basic_string_char_data, &str1);
489     ok(!memcmp(str, "test", 5), "str = %s\n", str);
490     size = (size_t)call_func1(p_basic_string_char_size, &str1);
491     ok(size == 4, "size = %lu\n", (unsigned long)size);
492     capacity = (size_t)call_func1(p_basic_string_char_capacity, &str1);
493     ok(capacity >= size, "capacity = %lu < size = %lu\n", (unsigned long)capacity, (unsigned long)size);
494
495     pstr = call_func2(p_basic_string_char_copy_ctor, &str2, &str1);
496     ok(pstr == &str2, "pstr != &str2\n");
497     str = call_func1(p_basic_string_char_cstr, &str2);
498     ok(!memcmp(str, "test", 5), "str = %s\n", str);
499     str = call_func1(p_basic_string_char_data, &str2);
500     ok(!memcmp(str, "test", 5), "str = %s\n", str);
501
502     call_func3(p_basic_string_char_erase, &str2, 1, 2);
503     str = call_func1(p_basic_string_char_cstr, &str2);
504     ok(!memcmp(str, "tt", 3), "str = %s\n", str);
505     str = call_func1(p_basic_string_char_data, &str2);
506     ok(!memcmp(str, "tt", 3), "str = %s\n", str);
507     size = (size_t)call_func1(p_basic_string_char_size, &str1);
508     ok(size == 4, "size = %lu\n", (unsigned long)size);
509     capacity = (size_t)call_func1(p_basic_string_char_capacity, &str1);
510     ok(capacity >= size, "capacity = %lu < size = %lu\n", (unsigned long)capacity, (unsigned long)size);
511
512     call_func3(p_basic_string_char_erase, &str2, 1, 100);
513     str = call_func1(p_basic_string_char_cstr, &str2);
514     ok(!memcmp(str, "t", 2), "str = %s\n", str);
515     str = call_func1(p_basic_string_char_data, &str2);
516     ok(!memcmp(str, "t", 2), "str = %s\n", str);
517     size = (size_t)call_func1(p_basic_string_char_size, &str1);
518     ok(size == 4, "size = %lu\n", (unsigned long)size);
519     capacity = (size_t)call_func1(p_basic_string_char_capacity, &str1);
520     ok(capacity >= size, "capacity = %lu < size = %lu\n", (unsigned long)capacity, (unsigned long)size);
521
522     call_func3(p_basic_string_char_assign_cstr_len, &str2, "test", 4);
523     str = call_func1(p_basic_string_char_cstr, &str2);
524     ok(!memcmp(str, "test", 5), "str = %s\n", str);
525     str = call_func1(p_basic_string_char_data, &str2);
526     ok(!memcmp(str, "test", 5), "str = %s\n", str);
527
528     call_func3(p_basic_string_char_assign_cstr_len, &str2, (str+1), 2);
529     str = call_func1(p_basic_string_char_cstr, &str2);
530     ok(!memcmp(str, "es", 3), "str = %s\n", str);
531     str = call_func1(p_basic_string_char_data, &str2);
532     ok(!memcmp(str, "es", 3), "str = %s\n", str);
533
534     call_func1(p_basic_string_char_dtor, &str1);
535     call_func1(p_basic_string_char_dtor, &str2);
536 }
537
538 static void test_basic_string_char_swap(void) {
539     basic_string_char str1, str2;
540     char atmp1[32], atmp2[32];
541
542     if(!p_basic_string_char_ctor_cstr || !p_basic_string_char_dtor ||
543             !p_basic_string_char_swap || !p_basic_string_char_cstr) {
544         win_skip("basic_string<char> unavailable\n");
545         return;
546     }
547
548     /* Swap self, local */
549     strcpy(atmp1, "qwerty");
550     call_func2(p_basic_string_char_ctor_cstr, &str1, atmp1);
551     call_func2(p_basic_string_char_swap, &str1, &str1);
552     ok(strcmp(atmp1, (const char *) call_func1(p_basic_string_char_cstr, &str1)) == 0, "Invalid value of str1\n");
553     call_func2(p_basic_string_char_swap, &str1, &str1);
554     ok(strcmp(atmp1, (const char *) call_func1(p_basic_string_char_cstr, &str1)) == 0, "Invalid value of str1\n");
555     call_func1(p_basic_string_char_dtor, &str1);
556
557     /* str1 allocated, str2 local */
558     strcpy(atmp1, "qwerty12345678901234567890");
559     strcpy(atmp2, "asd");
560     call_func2(p_basic_string_char_ctor_cstr, &str1, atmp1);
561     call_func2(p_basic_string_char_ctor_cstr, &str2, atmp2);
562     call_func2(p_basic_string_char_swap, &str1, &str2);
563     ok(strcmp(atmp2, (const char *) call_func1(p_basic_string_char_cstr, &str1)) == 0, "Invalid value of str1\n");
564     ok(strcmp(atmp1, (const char *) call_func1(p_basic_string_char_cstr, &str2)) == 0, "Invalid value of str2\n");
565     call_func2(p_basic_string_char_swap, &str1, &str2);
566     ok(strcmp(atmp1, (const char *) call_func1(p_basic_string_char_cstr, &str1)) == 0, "Invalid value of str1\n");
567     ok(strcmp(atmp2, (const char *) call_func1(p_basic_string_char_cstr, &str2)) == 0, "Invalid value of str2\n");
568     call_func1(p_basic_string_char_dtor, &str1);
569     call_func1(p_basic_string_char_dtor, &str2);
570 }
571
572 static void test_basic_string_char_append(void) {
573     basic_string_char str1, str2;
574     const char *str;
575
576     if(!p_basic_string_char_ctor_cstr || !p_basic_string_char_dtor
577             || !p_basic_string_char_append || !p_basic_string_char_append_substr
578             || !p_basic_string_char_cstr) {
579         win_skip("basic_string<char> unavailable\n");
580         return;
581     }
582
583     call_func2(p_basic_string_char_ctor_cstr, &str1, "");
584     call_func2(p_basic_string_char_ctor_cstr, &str2, "append");
585
586     call_func2(p_basic_string_char_append, &str1, &str2);
587     str = call_func1(p_basic_string_char_cstr, &str1);
588     ok(!memcmp(str, "append", 7), "str = %s\n", str);
589
590     call_func4(p_basic_string_char_append_substr, &str1, &str2, 3, 1);
591     str = call_func1(p_basic_string_char_cstr, &str1);
592     ok(!memcmp(str, "appende", 8), "str = %s\n", str);
593
594     call_func4(p_basic_string_char_append_substr, &str1, &str2, 5, 100);
595     str = call_func1(p_basic_string_char_cstr, &str1);
596     ok(!memcmp(str, "appended", 9), "str = %s\n", str);
597
598     call_func4(p_basic_string_char_append_substr, &str1, &str2, 6, 100);
599     str = call_func1(p_basic_string_char_cstr, &str1);
600     ok(!memcmp(str, "appended", 9), "str = %s\n", str);
601
602     call_func1(p_basic_string_char_dtor, &str1);
603     call_func1(p_basic_string_char_dtor, &str2);
604 }
605
606 static void test_basic_string_char_compare(void) {
607     basic_string_char str1, str2;
608     int ret;
609
610     if(!p_basic_string_char_ctor_cstr || !p_basic_string_char_dtor
611             || !p_basic_string_char_compare_substr_substr
612             || !p_basic_string_char_compare_substr_cstr_len) {
613         win_skip("basic_string<char> unavailable\n");
614         return;
615     }
616
617     call_func2(p_basic_string_char_ctor_cstr, &str1, "str1str");
618     call_func2(p_basic_string_char_ctor_cstr, &str2, "str9str");
619
620     ret = (int)call_func6(p_basic_string_char_compare_substr_substr,
621             &str1, 0, 3, &str2, 0, 3);
622     ok(ret == 0, "ret = %d\n", ret);
623     ret = (int)call_func6(p_basic_string_char_compare_substr_substr,
624             &str1, 4, 3, &str2, 4, 10);
625     ok(ret == 0, "ret = %d\n", ret);
626     ret = (int)call_func6(p_basic_string_char_compare_substr_substr,
627             &str1, 1, 3, &str2, 1, 4);
628     ok(ret == -1, "ret = %d\n", ret);
629
630     ret = (int)call_func5(p_basic_string_char_compare_substr_cstr_len,
631             &str1, 0, 1000, "str1str", 7);
632     ok(ret == 0, "ret = %d\n", ret);
633     ret = (int)call_func5(p_basic_string_char_compare_substr_cstr_len,
634             &str1, 1, 2, "tr", 2);
635     ok(ret == 0, "ret = %d\n", ret);
636     ret = (int)call_func5(p_basic_string_char_compare_substr_cstr_len,
637             &str1, 1, 0, "aaa", 0);
638     ok(ret == 0, "ret = %d\n", ret);
639     ret = (int)call_func5(p_basic_string_char_compare_substr_cstr_len,
640             &str1, 1, 0, "aaa", 1);
641     ok(ret == -1, "ret = %d\n", ret);
642
643     call_func1(p_basic_string_char_dtor, &str1);
644     call_func1(p_basic_string_char_dtor, &str2);
645 }
646
647 static void test_basic_string_wchar(void) {
648     static const wchar_t test[] = { 't','e','s','t',0 };
649
650     basic_string_wchar str1, str2, *pstr;
651     const wchar_t *str;
652     size_t size, capacity;
653
654     if(!p_basic_string_wchar_ctor || !p_basic_string_wchar_copy_ctor
655             || !p_basic_string_wchar_ctor_cstr || !p_basic_string_wchar_dtor
656             || !p_basic_string_wchar_erase || !p_basic_string_wchar_assign_cstr_len
657             || !p_basic_string_wchar_cstr || !p_basic_string_wchar_data
658             || !p_basic_string_wchar_size || !p_basic_string_wchar_capacity) {
659         win_skip("basic_string<wchar_t> unavailable\n");
660         return;
661     }
662
663     call_func1(p_basic_string_wchar_ctor, &str1);
664     str = NULL;
665     str = call_func1(p_basic_string_wchar_cstr, &str1);
666     ok(str != NULL, "str = NULL\n");
667     ok(*str == '\0', "*str = %c\n", *str);
668     str = call_func1(p_basic_string_wchar_data, &str1);
669     ok(str != NULL, "str = NULL\n");
670     ok(*str == '\0', "*str = %c\n", *str);
671     call_func1(p_basic_string_wchar_dtor, &str1);
672
673     pstr = call_func2(p_basic_string_wchar_ctor_cstr, &str1, test);
674     ok(pstr == &str1, "pstr != &str1\n");
675     str = call_func1(p_basic_string_wchar_cstr, &str1);
676     ok(!memcmp(str, test, 5*sizeof(wchar_t)), "str = %s\n", wine_dbgstr_w(str));
677     str = call_func1(p_basic_string_wchar_data, &str1);
678     ok(!memcmp(str, test, 5*sizeof(wchar_t)), "str = %s\n", wine_dbgstr_w(str));
679     size = (size_t)call_func1(p_basic_string_wchar_size, &str1);
680     ok(size == 4, "size = %lu\n", (unsigned long)size);
681     capacity = (size_t)call_func1(p_basic_string_wchar_capacity, &str1);
682     ok(capacity >= size, "capacity = %lu < size = %lu\n", (unsigned long)capacity, (unsigned long)size);
683
684     memset(&str2, 0, sizeof(basic_string_wchar));
685     pstr = call_func2(p_basic_string_wchar_copy_ctor, &str2, &str1);
686     ok(pstr == &str2, "pstr != &str2\n");
687     str = call_func1(p_basic_string_wchar_cstr, &str2);
688     ok(!memcmp(str, test, 5*sizeof(wchar_t)), "str = %s\n", wine_dbgstr_w(str));
689     str = call_func1(p_basic_string_wchar_data, &str2);
690     ok(!memcmp(str, test, 5*sizeof(wchar_t)), "str = %s\n", wine_dbgstr_w(str));
691
692     call_func3(p_basic_string_wchar_erase, &str2, 1, 2);
693     str = call_func1(p_basic_string_wchar_cstr, &str2);
694     ok(str[0]=='t' && str[1]=='t' && str[2]=='\0', "str = %s\n", wine_dbgstr_w(str));
695     str = call_func1(p_basic_string_wchar_data, &str2);
696     ok(str[0]=='t' && str[1]=='t' && str[2]=='\0', "str = %s\n", wine_dbgstr_w(str));
697     size = (size_t)call_func1(p_basic_string_wchar_size, &str1);
698     ok(size == 4, "size = %lu\n", (unsigned long)size);
699     capacity = (size_t)call_func1(p_basic_string_wchar_capacity, &str1);
700     ok(capacity >= size, "capacity = %lu < size = %lu\n", (unsigned long)capacity, (unsigned long)size);
701
702     call_func3(p_basic_string_wchar_erase, &str2, 1, 100);
703     str = call_func1(p_basic_string_wchar_cstr, &str2);
704     ok(str[0]=='t' && str[1]=='\0', "str = %s\n", wine_dbgstr_w(str));
705     str = call_func1(p_basic_string_wchar_data, &str2);
706     ok(str[0]=='t' && str[1]=='\0', "str = %s\n", wine_dbgstr_w(str));
707     size = (size_t)call_func1(p_basic_string_wchar_size, &str1);
708     ok(size == 4, "size = %lu\n", (unsigned long)size);
709     capacity = (size_t)call_func1(p_basic_string_wchar_capacity, &str1);
710     ok(capacity >= size, "capacity = %lu < size = %lu\n", (unsigned long)capacity, (unsigned long)size);
711
712     call_func3(p_basic_string_wchar_assign_cstr_len, &str2, test, 4);
713     str = call_func1(p_basic_string_wchar_cstr, &str2);
714     ok(!memcmp(str, test, 5*sizeof(wchar_t)), "str = %s\n", wine_dbgstr_w(str));
715     str = call_func1(p_basic_string_wchar_data, &str2);
716     ok(!memcmp(str, test, 5*sizeof(wchar_t)), "str = %s\n", wine_dbgstr_w(str));
717
718     call_func3(p_basic_string_wchar_assign_cstr_len, &str2, (str+1), 2);
719     str = call_func1(p_basic_string_wchar_cstr, &str2);
720     ok(str[0]=='e' && str[1]=='s' && str[2]=='\0', "str = %s\n", wine_dbgstr_w(str));
721     str = call_func1(p_basic_string_wchar_data, &str2);
722     ok(str[0]=='e' && str[1]=='s' && str[2]=='\0', "str = %s\n", wine_dbgstr_w(str));
723
724     call_func1(p_basic_string_wchar_dtor, &str1);
725     call_func1(p_basic_string_wchar_dtor, &str2);
726 }
727
728 static void test_basic_string_wchar_swap(void) {
729     basic_string_wchar str1, str2;
730     wchar_t wtmp1[32], wtmp2[32];
731
732     if(!p_basic_string_wchar_ctor_cstr || !p_basic_string_wchar_dtor ||
733             !p_basic_string_wchar_swap || !p_basic_string_wchar_cstr) {
734         win_skip("basic_string<wchar_t> unavailable\n");
735         return;
736     }
737
738     /* Swap self, local */
739     mbstowcs(wtmp1, "qwerty", 32);
740     call_func2(p_basic_string_wchar_ctor_cstr, &str1, wtmp1);
741     call_func2(p_basic_string_wchar_swap, &str1, &str1);
742     ok(wcscmp(wtmp1, (const wchar_t *) call_func1(p_basic_string_wchar_cstr, &str1)) == 0, "Invalid value of str1\n");
743     call_func2(p_basic_string_wchar_swap, &str1, &str1);
744     ok(wcscmp(wtmp1, (const wchar_t *) call_func1(p_basic_string_wchar_cstr, &str1)) == 0, "Invalid value of str1\n");
745     call_func1(p_basic_string_wchar_dtor, &str1);
746
747     /* str1 allocated, str2 local */
748     mbstowcs(wtmp1, "qwerty12345678901234567890", 32);
749     mbstowcs(wtmp2, "asd", 32);
750     call_func2(p_basic_string_wchar_ctor_cstr, &str1, wtmp1);
751     call_func2(p_basic_string_wchar_ctor_cstr, &str2, wtmp2);
752     call_func2(p_basic_string_wchar_swap, &str1, &str2);
753     ok(wcscmp(wtmp2, (const wchar_t *) call_func1(p_basic_string_wchar_cstr, &str1)) == 0, "Invalid value of str1\n");
754     ok(wcscmp(wtmp1, (const wchar_t *) call_func1(p_basic_string_wchar_cstr, &str2)) == 0, "Invalid value of str2\n");
755     call_func2(p_basic_string_wchar_swap, &str1, &str2);
756     ok(wcscmp(wtmp1, (const wchar_t *) call_func1(p_basic_string_wchar_cstr, &str1)) == 0, "Invalid value of str1\n");
757     ok(wcscmp(wtmp2, (const wchar_t *) call_func1(p_basic_string_wchar_cstr, &str2)) == 0, "Invalid value of str2\n");
758     call_func1(p_basic_string_wchar_dtor, &str1);
759     call_func1(p_basic_string_wchar_dtor, &str2);
760 }
761
762 START_TEST(string)
763 {
764     if(!init())
765         return;
766
767     test_basic_string_char();
768     test_basic_string_char_swap();
769     test_basic_string_char_append();
770     test_basic_string_char_compare();
771     test_basic_string_wchar();
772     test_basic_string_wchar_swap();
773
774     ok(!invalid_parameter, "invalid_parameter_handler was invoked too many times\n");
775 }