mshtml: COM cleanup for the IHTMLDOMNode iface.
[wine] / dlls / msvcr90 / tests / msvcr90.c
1 /*
2  * Copyright 2010 Detlef Riekenberg
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 <stdarg.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22
23 #include <windef.h>
24 #include <winbase.h>
25 #include <errno.h>
26 #include "wine/test.h"
27
28 #define DEFINE_EXPECT(func) \
29     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
30
31 #define SET_EXPECT(func) \
32     expect_ ## func = TRUE
33
34 #define CHECK_EXPECT2(func) \
35     do { \
36         ok(expect_ ##func, "unexpected call " #func "\n"); \
37         called_ ## func = TRUE; \
38     }while(0)
39
40 #define CHECK_EXPECT(func) \
41     do { \
42         CHECK_EXPECT2(func); \
43         expect_ ## func = FALSE; \
44     }while(0)
45
46 #define CHECK_CALLED(func) \
47     do { \
48         ok(called_ ## func, "expected " #func "\n"); \
49         expect_ ## func = called_ ## func = FALSE; \
50     }while(0)
51
52 DEFINE_EXPECT(invalid_parameter_handler);
53
54 static _invalid_parameter_handler (__cdecl *p_set_invalid_parameter_handler)(_invalid_parameter_handler);
55 typedef int (__cdecl *_INITTERM_E_FN)(void);
56 static int (__cdecl *p_initterm_e)(_INITTERM_E_FN *table, _INITTERM_E_FN *end);
57 static void* (__cdecl *p_encode_pointer)(void *);
58 static void* (__cdecl *p_decode_pointer)(void *);
59 static void* (__cdecl *p_encoded_null)(void);
60 static int *p_sys_nerr;
61 static int* (__cdecl *p__sys_nerr)(void);
62 static char **p_sys_errlist;
63 static char** (__cdecl *p__sys_errlist)(void);
64 static __int64 (__cdecl *p_strtoi64)(const char *, char **, int);
65 static unsigned __int64 (__cdecl *p_strtoui64)(const char *, char **, int);
66 static errno_t (__cdecl *p_itoa_s)(int,char*,size_t,int);
67 static int (__cdecl *p_wcsncat_s)(wchar_t *dst, size_t elem, const wchar_t *src, size_t count);
68 static void (__cdecl *p_qsort_s)(void *, size_t, size_t, int (__cdecl *)(void *, const void *, const void *), void *);
69 static int (__cdecl *p_controlfp_s)(unsigned int *, unsigned int, unsigned int);
70
71 static void* (WINAPI *pEncodePointer)(void *);
72
73 static int cb_called[4];
74 static int g_qsort_s_context_counter;
75
76 /* ########## */
77
78 static void __cdecl test_invalid_parameter_handler(const wchar_t *expression,
79         const wchar_t *function, const wchar_t *file,
80         unsigned line, uintptr_t arg)
81 {
82     CHECK_EXPECT(invalid_parameter_handler);
83     ok(expression == NULL, "expression is not NULL\n");
84     ok(function == NULL, "function is not NULL\n");
85     ok(file == NULL, "file is not NULL\n");
86     ok(line == 0, "line = %u\n", line);
87     ok(arg == 0, "arg = %lx\n", (UINT_PTR)arg);
88 }
89
90 static int __cdecl initterm_cb0(void)
91 {
92     cb_called[0]++;
93     return 0;
94 }
95
96 static int __cdecl initterm_cb1(void)
97 {
98     cb_called[1]++;
99     return 1;
100 }
101
102 static int __cdecl initterm_cb2(void)
103 {
104     cb_called[2]++;
105     return 2;
106 }
107
108
109 static void test__initterm_e(void)
110 {
111     _INITTERM_E_FN table[4];
112     int res;
113
114     if (!p_initterm_e) {
115         skip("_initterm_e not found\n");
116         return;
117     }
118
119     memset(table, 0, sizeof(table));
120
121     memset(cb_called, 0, sizeof(cb_called));
122     errno = 0xdeadbeef;
123     res = p_initterm_e(table, table);
124     ok( !res && !cb_called[0] && !cb_called[1] && !cb_called[2],
125         "got %d with 0x%x {%d, %d, %d}\n",
126         res, errno, cb_called[0], cb_called[1], cb_called[2]);
127
128     memset(cb_called, 0, sizeof(cb_called));
129     errno = 0xdeadbeef;
130     res = p_initterm_e(table, NULL);
131     ok( !res && !cb_called[0] && !cb_called[1] && !cb_called[2],
132         "got %d with 0x%x {%d, %d, %d}\n",
133         res, errno, cb_called[0], cb_called[1], cb_called[2]);
134
135     if (0) {
136         /* this crash on Windows */
137         errno = 0xdeadbeef;
138         res = p_initterm_e(NULL, table);
139         trace("got %d with 0x%x\n", res, errno);
140     }
141
142     table[0] = initterm_cb0;
143     memset(cb_called, 0, sizeof(cb_called));
144     errno = 0xdeadbeef;
145     res = p_initterm_e(table, &table[1]);
146     ok( !res && (cb_called[0] == 1) && !cb_called[1] && !cb_called[2],
147         "got %d with 0x%x {%d, %d, %d}\n",
148         res, errno, cb_called[0], cb_called[1], cb_called[2]);
149
150
151     /* init-function returning failure */
152     table[1] = initterm_cb1;
153     memset(cb_called, 0, sizeof(cb_called));
154     errno = 0xdeadbeef;
155     res = p_initterm_e(table, &table[3]);
156     ok( (res == 1) && (cb_called[0] == 1) && (cb_called[1] == 1) && !cb_called[2],
157         "got %d with 0x%x {%d, %d, %d}\n",
158         res, errno, cb_called[0], cb_called[1], cb_called[2]);
159
160     /* init-function not called, when end < start */
161     memset(cb_called, 0, sizeof(cb_called));
162     errno = 0xdeadbeef;
163     res = p_initterm_e(&table[3], table);
164     ok( !res && !cb_called[0] && !cb_called[1] && !cb_called[2],
165         "got %d with 0x%x {%d, %d, %d}\n",
166         res, errno, cb_called[0], cb_called[1], cb_called[2]);
167
168     /* initialization stop after first non-zero result */
169     table[2] = initterm_cb0;
170     memset(cb_called, 0, sizeof(cb_called));
171     errno = 0xdeadbeef;
172     res = p_initterm_e(table, &table[3]);
173     ok( (res == 1) && (cb_called[0] == 1) && (cb_called[1] == 1) && !cb_called[2],
174         "got %d with 0x%x {%d, %d, %d}\n",
175         res, errno, cb_called[0], cb_called[1], cb_called[2]);
176
177     /* NULL pointer in the array are skipped */
178     table[1] = NULL;
179     table[2] = initterm_cb2;
180     memset(cb_called, 0, sizeof(cb_called));
181     errno = 0xdeadbeef;
182     res = p_initterm_e(table, &table[3]);
183     ok( (res == 2) && (cb_called[0] == 1) && !cb_called[1] && (cb_called[2] == 1),
184         "got %d with 0x%x {%d, %d, %d}\n",
185         res, errno, cb_called[0], cb_called[1], cb_called[2]);
186
187 }
188
189 /* Beware that _encode_pointer is a NOP before XP
190    (the parameter is returned unchanged) */
191 static void test__encode_pointer(void)
192 {
193     void *ptr, *res;
194
195     if(!p_encode_pointer || !p_decode_pointer || !p_encoded_null) {
196         win_skip("_encode_pointer, _decode_pointer or _encoded_null not found\n");
197         return;
198     }
199
200     ptr = (void*)0xdeadbeef;
201     res = p_encode_pointer(ptr);
202     res = p_decode_pointer(res);
203     ok(res == ptr, "Pointers are different after encoding and decoding\n");
204
205     ok(p_encoded_null() == p_encode_pointer(NULL), "Error encoding null\n");
206
207     ptr = p_encode_pointer(p_encode_pointer);
208     ok(p_decode_pointer(ptr) == p_encode_pointer, "Error decoding pointer\n");
209
210     /* Not present before XP */
211     if (!pEncodePointer) {
212         win_skip("EncodePointer not found\n");
213         return;
214     }
215
216     res = pEncodePointer(p_encode_pointer);
217     ok(ptr == res, "_encode_pointer produced different result than EncodePointer\n");
218
219 }
220
221 static void test_error_messages(void)
222 {
223     int *size, size_copy;
224
225     if(!p_sys_nerr || !p__sys_nerr || !p_sys_errlist || !p__sys_errlist) {
226         win_skip("Skipping test_error_messages tests\n");
227         return;
228     }
229
230     size = p__sys_nerr();
231     size_copy = *size;
232     ok(*p_sys_nerr == *size, "_sys_nerr = %u, size = %u\n", *p_sys_nerr, *size);
233
234     *size = 20;
235     ok(*p_sys_nerr == *size, "_sys_nerr = %u, size = %u\n", *p_sys_nerr, *size);
236
237     *size = size_copy;
238
239     ok(*p_sys_errlist == *(p__sys_errlist()), "p_sys_errlist != p__sys_errlist()\n");
240 }
241
242 static void test__strtoi64(void)
243 {
244     __int64 res;
245     unsigned __int64 ures;
246
247     if(!p_strtoi64 || !p_strtoui64) {
248         win_skip("_strtoi64 or _strtoui64 not found\n");
249         return;
250     }
251
252     if(!p_set_invalid_parameter_handler) {
253         win_skip("_set_invalid_parameter_handler not found\n");
254         return;
255     }
256
257     errno = 0xdeadbeef;
258     SET_EXPECT(invalid_parameter_handler);
259     res = p_strtoi64(NULL, NULL, 10);
260     ok(res == 0, "res != 0\n");
261     CHECK_CALLED(invalid_parameter_handler);
262
263     SET_EXPECT(invalid_parameter_handler);
264     res = p_strtoi64("123", NULL, 1);
265     ok(res == 0, "res != 0\n");
266     CHECK_CALLED(invalid_parameter_handler);
267
268     SET_EXPECT(invalid_parameter_handler);
269     res = p_strtoi64("123", NULL, 37);
270     ok(res == 0, "res != 0\n");
271     CHECK_CALLED(invalid_parameter_handler);
272
273     SET_EXPECT(invalid_parameter_handler);
274     ures = p_strtoui64(NULL, NULL, 10);
275     ok(ures == 0, "res = %d\n", (int)ures);
276     CHECK_CALLED(invalid_parameter_handler);
277
278     SET_EXPECT(invalid_parameter_handler);
279     ures = p_strtoui64("123", NULL, 1);
280     ok(ures == 0, "res = %d\n", (int)ures);
281     CHECK_CALLED(invalid_parameter_handler);
282
283     SET_EXPECT(invalid_parameter_handler);
284     ures = p_strtoui64("123", NULL, 37);
285     ok(ures == 0, "res = %d\n", (int)ures);
286     CHECK_CALLED(invalid_parameter_handler);
287     ok(errno == 0xdeadbeef, "errno = %x\n", errno);
288 }
289
290 static void test__itoa_s(void)
291 {
292     errno_t ret;
293     char buffer[33];
294
295     if (!p_itoa_s)
296     {
297         win_skip("Skipping _itoa_s tests\n");
298         return;
299     }
300
301     if(!p_set_invalid_parameter_handler) {
302         win_skip("_set_invalid_parameter_handler not found\n");
303         return;
304     }
305
306     /* _itoa_s (on msvcr90) doesn't set errno (in case of errors) while msvcrt does
307      * as we always set errno in our msvcrt implementation, don't test here that errno
308      * isn't changed
309      */
310     SET_EXPECT(invalid_parameter_handler);
311     ret = p_itoa_s(0, NULL, 0, 0);
312     ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
313     CHECK_CALLED(invalid_parameter_handler);
314
315     memset(buffer, 'X', sizeof(buffer));
316     SET_EXPECT(invalid_parameter_handler);
317     ret = p_itoa_s(0, buffer, 0, 0);
318     ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
319     ok(buffer[0] == 'X', "Expected the output buffer to be untouched\n");
320     CHECK_CALLED(invalid_parameter_handler);
321
322     memset(buffer, 'X', sizeof(buffer));
323     SET_EXPECT(invalid_parameter_handler);
324     ret = p_itoa_s(0, buffer, sizeof(buffer), 0);
325     ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
326     ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
327     CHECK_CALLED(invalid_parameter_handler);
328
329     memset(buffer, 'X', sizeof(buffer));
330     SET_EXPECT(invalid_parameter_handler);
331     ret = p_itoa_s(0, buffer, sizeof(buffer), 64);
332     ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
333     ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
334     CHECK_CALLED(invalid_parameter_handler);
335
336     memset(buffer, 'X', sizeof(buffer));
337     SET_EXPECT(invalid_parameter_handler);
338     ret = p_itoa_s(12345678, buffer, 4, 10);
339     ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
340     ok(!memcmp(buffer, "\000765", 4),
341        "Expected the output buffer to be null terminated with truncated output\n");
342     CHECK_CALLED(invalid_parameter_handler);
343
344     memset(buffer, 'X', sizeof(buffer));
345     SET_EXPECT(invalid_parameter_handler);
346     ret = p_itoa_s(12345678, buffer, 8, 10);
347     ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
348     ok(!memcmp(buffer, "\0007654321", 8),
349        "Expected the output buffer to be null terminated with truncated output\n");
350     CHECK_CALLED(invalid_parameter_handler);
351
352     memset(buffer, 'X', sizeof(buffer));
353     SET_EXPECT(invalid_parameter_handler);
354     ret = p_itoa_s(-12345678, buffer, 9, 10);
355     ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
356     ok(!memcmp(buffer, "\00087654321", 9),
357        "Expected the output buffer to be null terminated with truncated output\n");
358     CHECK_CALLED(invalid_parameter_handler);
359
360     ret = p_itoa_s(12345678, buffer, 9, 10);
361     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
362     ok(!strcmp(buffer, "12345678"),
363        "Expected output buffer string to be \"12345678\", got \"%s\"\n",
364        buffer);
365
366     ret = p_itoa_s(43690, buffer, sizeof(buffer), 2);
367     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
368     ok(!strcmp(buffer, "1010101010101010"),
369        "Expected output buffer string to be \"1010101010101010\", got \"%s\"\n",
370        buffer);
371
372     ret = p_itoa_s(1092009, buffer, sizeof(buffer), 36);
373     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
374     ok(!strcmp(buffer, "nell"),
375        "Expected output buffer string to be \"nell\", got \"%s\"\n",
376        buffer);
377
378     ret = p_itoa_s(5704, buffer, sizeof(buffer), 18);
379     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
380     ok(!strcmp(buffer, "hag"),
381        "Expected output buffer string to be \"hag\", got \"%s\"\n",
382        buffer);
383
384     ret = p_itoa_s(-12345678, buffer, sizeof(buffer), 10);
385     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
386     ok(!strcmp(buffer, "-12345678"),
387        "Expected output buffer string to be \"-12345678\", got \"%s\"\n",
388        buffer);
389 }
390
391 static void test_wcsncat_s(void)
392 {
393     static wchar_t abcW[] = {'a','b','c',0};
394     int ret;
395     wchar_t dst[4];
396     wchar_t src[4];
397
398     if (!p_wcsncat_s)
399     {
400         win_skip("skipping wcsncat_s tests\n");
401         return;
402     }
403
404     if(!p_set_invalid_parameter_handler) {
405         win_skip("_set_invalid_parameter_handler not found\n");
406         return;
407     }
408
409     memcpy(src, abcW, sizeof(abcW));
410     dst[0] = 0;
411     SET_EXPECT(invalid_parameter_handler);
412     ret = p_wcsncat_s(NULL, 4, src, 4);
413     ok(ret == EINVAL, "err = %d\n", ret);
414     CHECK_CALLED(invalid_parameter_handler);
415
416     SET_EXPECT(invalid_parameter_handler);
417     ret = p_wcsncat_s(dst, 0, src, 4);
418     ok(ret == EINVAL, "err = %d\n", ret);
419     CHECK_CALLED(invalid_parameter_handler);
420
421     SET_EXPECT(invalid_parameter_handler);
422     ret = p_wcsncat_s(dst, 0, src, _TRUNCATE);
423     ok(ret == EINVAL, "err = %d\n", ret);
424     CHECK_CALLED(invalid_parameter_handler);
425
426     ret = p_wcsncat_s(dst, 4, NULL, 0);
427     ok(ret == 0, "err = %d\n", ret);
428
429     dst[0] = 0;
430     SET_EXPECT(invalid_parameter_handler);
431     ret = p_wcsncat_s(dst, 2, src, 4);
432     ok(ret == ERANGE, "err = %d\n", ret);
433     CHECK_CALLED(invalid_parameter_handler);
434
435     dst[0] = 0;
436     ret = p_wcsncat_s(dst, 2, src, _TRUNCATE);
437     ok(ret == STRUNCATE, "err = %d\n", ret);
438     ok(dst[0] == 'a' && dst[1] == 0, "dst is %s\n", wine_dbgstr_w(dst));
439
440     memcpy(dst, abcW, sizeof(abcW));
441     dst[3] = 'd';
442     SET_EXPECT(invalid_parameter_handler);
443     ret = p_wcsncat_s(dst, 4, src, 4);
444     ok(ret == EINVAL, "err = %d\n", ret);
445     CHECK_CALLED(invalid_parameter_handler);
446 }
447
448 /* Based on dlls/ntdll/tests/string.c */
449 static __cdecl int intcomparefunc(void *context, const void *a, const void*b)
450 {
451     ok (a != b, "must never get the same pointer\n");
452     ++*(int *) context;
453     return (*(int*)a) - (*(int*)b);
454 }
455
456 static __cdecl int charcomparefunc(void *context, const void *a, const void*b)
457 {
458     ok (a != b, "must never get the same pointer\n");
459     ++*(int *) context;
460     return (*(char*)a) - (*(char*)b);
461 }
462
463 static __cdecl int strcomparefunc(void *context, const void *a, const void*b)
464 {
465     ok (a != b, "must never get the same pointer\n");
466     ++*(int *) context;
467     return lstrcmpA(*(char**)a,*(char**)b);
468 }
469
470 static void test_qsort_s(void)
471 {
472     int arr[5] = { 23, 42, 8, 4, 16 };
473     int arr2[5] = { 23, 42, 8, 4, 16 };
474     char carr[5] = { 42, 23, 4, 8, 16 };
475     const char *strarr[7] = {
476     "Hello",
477     "Wine",
478     "World",
479     "!",
480     "Hopefully",
481     "Sorted",
482     "."
483     };
484
485     if(!p_qsort_s) {
486         win_skip("qsort_s not found\n");
487         return;
488     }
489
490     SET_EXPECT(invalid_parameter_handler);
491     p_qsort_s(NULL, 0, 0, NULL, NULL);
492     CHECK_CALLED(invalid_parameter_handler);
493
494     SET_EXPECT(invalid_parameter_handler);
495     p_qsort_s(NULL, 0, 0, intcomparefunc, NULL);
496     CHECK_CALLED(invalid_parameter_handler);
497
498     SET_EXPECT(invalid_parameter_handler);
499     p_qsort_s(NULL, 0, sizeof(int), NULL, NULL);
500     CHECK_CALLED(invalid_parameter_handler);
501
502     SET_EXPECT(invalid_parameter_handler);
503     p_qsort_s(NULL, 1, sizeof(int), intcomparefunc, NULL);
504     CHECK_CALLED(invalid_parameter_handler);
505
506     g_qsort_s_context_counter = 0;
507     p_qsort_s(NULL, 0, sizeof(int), intcomparefunc, NULL);
508     ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
509
510     /* overflow without side effects, other overflow values crash */
511     g_qsort_s_context_counter = 0;
512     p_qsort_s((void*)arr2, (((size_t)1) << (8*sizeof(size_t) - 1)) + 1, sizeof(int), intcomparefunc, &g_qsort_s_context_counter);
513     ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
514     ok(arr2[0] == 23, "should remain unsorted, arr2[0] is %d\n", arr2[0]);
515     ok(arr2[1] == 42, "should remain unsorted, arr2[1] is %d\n", arr2[1]);
516     ok(arr2[2] == 8,  "should remain unsorted, arr2[2] is %d\n", arr2[2]);
517     ok(arr2[3] == 4,  "should remain unsorted, arr2[3] is %d\n", arr2[3]);
518
519     g_qsort_s_context_counter = 0;
520     p_qsort_s((void*)arr, 0, sizeof(int), intcomparefunc, &g_qsort_s_context_counter);
521     ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
522     ok(arr[0] == 23, "badly sorted, nmemb=0, arr[0] is %d\n", arr[0]);
523     ok(arr[1] == 42, "badly sorted, nmemb=0, arr[1] is %d\n", arr[1]);
524     ok(arr[2] == 8,  "badly sorted, nmemb=0, arr[2] is %d\n", arr[2]);
525     ok(arr[3] == 4,  "badly sorted, nmemb=0, arr[3] is %d\n", arr[3]);
526     ok(arr[4] == 16, "badly sorted, nmemb=0, arr[4] is %d\n", arr[4]);
527
528     g_qsort_s_context_counter = 0;
529     p_qsort_s((void*)arr, 1, sizeof(int), intcomparefunc, &g_qsort_s_context_counter);
530     ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
531     ok(arr[0] == 23, "badly sorted, nmemb=1, arr[0] is %d\n", arr[0]);
532     ok(arr[1] == 42, "badly sorted, nmemb=1, arr[1] is %d\n", arr[1]);
533     ok(arr[2] == 8,  "badly sorted, nmemb=1, arr[2] is %d\n", arr[2]);
534     ok(arr[3] == 4,  "badly sorted, nmemb=1, arr[3] is %d\n", arr[3]);
535     ok(arr[4] == 16, "badly sorted, nmemb=1, arr[4] is %d\n", arr[4]);
536
537     SET_EXPECT(invalid_parameter_handler);
538     g_qsort_s_context_counter = 0;
539     p_qsort_s((void*)arr, 5, 0, intcomparefunc, &g_qsort_s_context_counter);
540     ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
541     ok(arr[0] == 23, "badly sorted, size=0, arr[0] is %d\n", arr[0]);
542     ok(arr[1] == 42, "badly sorted, size=0, arr[1] is %d\n", arr[1]);
543     ok(arr[2] == 8,  "badly sorted, size=0, arr[2] is %d\n", arr[2]);
544     ok(arr[3] == 4,  "badly sorted, size=0, arr[3] is %d\n", arr[3]);
545     ok(arr[4] == 16, "badly sorted, size=0, arr[4] is %d\n", arr[4]);
546     CHECK_CALLED(invalid_parameter_handler);
547
548     g_qsort_s_context_counter = 0;
549     p_qsort_s((void*)arr, 5, sizeof(int), intcomparefunc, &g_qsort_s_context_counter);
550     ok(g_qsort_s_context_counter > 0, "callback wasn't called\n");
551     ok(arr[0] == 4,  "badly sorted, arr[0] is %d\n", arr[0]);
552     ok(arr[1] == 8,  "badly sorted, arr[1] is %d\n", arr[1]);
553     ok(arr[2] == 16, "badly sorted, arr[2] is %d\n", arr[2]);
554     ok(arr[3] == 23, "badly sorted, arr[3] is %d\n", arr[3]);
555     ok(arr[4] == 42, "badly sorted, arr[4] is %d\n", arr[4]);
556
557     g_qsort_s_context_counter = 0;
558     p_qsort_s((void*)carr, 5, sizeof(char), charcomparefunc, &g_qsort_s_context_counter);
559     ok(g_qsort_s_context_counter > 0, "callback wasn't called\n");
560     ok(carr[0] == 4,  "badly sorted, carr[0] is %d\n", carr[0]);
561     ok(carr[1] == 8,  "badly sorted, carr[1] is %d\n", carr[1]);
562     ok(carr[2] == 16, "badly sorted, carr[2] is %d\n", carr[2]);
563     ok(carr[3] == 23, "badly sorted, carr[3] is %d\n", carr[3]);
564     ok(carr[4] == 42, "badly sorted, carr[4] is %d\n", carr[4]);
565
566     g_qsort_s_context_counter = 0;
567     p_qsort_s((void*)strarr, 7, sizeof(char*), strcomparefunc, &g_qsort_s_context_counter);
568     ok(g_qsort_s_context_counter > 0, "callback wasn't called\n");
569     ok(!strcmp(strarr[0],"!"),  "badly sorted, strarr[0] is %s\n", strarr[0]);
570     ok(!strcmp(strarr[1],"."),  "badly sorted, strarr[1] is %s\n", strarr[1]);
571     ok(!strcmp(strarr[2],"Hello"),  "badly sorted, strarr[2] is %s\n", strarr[2]);
572     ok(!strcmp(strarr[3],"Hopefully"),  "badly sorted, strarr[3] is %s\n", strarr[3]);
573     ok(!strcmp(strarr[4],"Sorted"),  "badly sorted, strarr[4] is %s\n", strarr[4]);
574     ok(!strcmp(strarr[5],"Wine"),  "badly sorted, strarr[5] is %s\n", strarr[5]);
575     ok(!strcmp(strarr[6],"World"),  "badly sorted, strarr[6] is %s\n", strarr[6]);
576 }
577
578 static void test_controlfp_s(void)
579 {
580     unsigned int cur;
581     int ret;
582
583     if (!p_controlfp_s)
584     {
585         win_skip("_controlfp_s not found\n");
586         return;
587     }
588
589     SET_EXPECT(invalid_parameter_handler);
590     ret = p_controlfp_s( NULL, ~0, ~0 );
591     ok( ret == EINVAL, "wrong result %d\n", ret );
592     CHECK_CALLED(invalid_parameter_handler);
593
594     cur = 0xdeadbeef;
595     SET_EXPECT(invalid_parameter_handler);
596     ret = p_controlfp_s( &cur, ~0, ~0 );
597     ok( ret == EINVAL, "wrong result %d\n", ret );
598     ok( cur != 0xdeadbeef, "value not set\n" );
599     CHECK_CALLED(invalid_parameter_handler);
600
601     cur = 0xdeadbeef;
602     ret = p_controlfp_s( &cur, 0, 0 );
603     ok( !ret, "wrong result %d\n", ret );
604     ok( cur != 0xdeadbeef, "value not set\n" );
605
606     SET_EXPECT(invalid_parameter_handler);
607     cur = 0xdeadbeef;
608     ret = p_controlfp_s( &cur, 0x80000000, 0x80000000 );
609     ok( ret == EINVAL, "wrong result %d\n", ret );
610     ok( cur != 0xdeadbeef, "value not set\n" );
611     CHECK_CALLED(invalid_parameter_handler);
612
613     cur = 0xdeadbeef;
614     /* mask is only checked when setting invalid bits */
615     ret = p_controlfp_s( &cur, 0, 0x80000000 );
616     ok( !ret, "wrong result %d\n", ret );
617     ok( cur != 0xdeadbeef, "value not set\n" );
618 }
619
620 START_TEST(msvcr90)
621 {
622     HMODULE hcrt;
623     HMODULE hkernel32;
624
625     SetLastError(0xdeadbeef);
626     hcrt = LoadLibraryA("msvcr90.dll");
627     if (!hcrt) {
628         win_skip("msvcr90.dll not installed (got %d)\n", GetLastError());
629         return;
630     }
631
632     p_set_invalid_parameter_handler = (void *) GetProcAddress(hcrt, "_set_invalid_parameter_handler");
633     if(p_set_invalid_parameter_handler)
634         ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
635                 "Invalid parameter handler was already set\n");
636
637     p_initterm_e = (void *) GetProcAddress(hcrt, "_initterm_e");
638     p_encode_pointer = (void *) GetProcAddress(hcrt, "_encode_pointer");
639     p_decode_pointer = (void *) GetProcAddress(hcrt, "_decode_pointer");
640     p_encoded_null = (void *) GetProcAddress(hcrt, "_encoded_null");
641     p_sys_nerr = (void *) GetProcAddress(hcrt, "_sys_nerr");
642     p__sys_nerr = (void *) GetProcAddress(hcrt, "__sys_nerr");
643     p_sys_errlist = (void *) GetProcAddress(hcrt, "_sys_errlist");
644     p__sys_errlist = (void *) GetProcAddress(hcrt, "__sys_errlist");
645     p_strtoi64 = (void *) GetProcAddress(hcrt, "_strtoi64");
646     p_strtoui64 = (void *) GetProcAddress(hcrt, "_strtoui64");
647     p_itoa_s = (void *)GetProcAddress(hcrt, "_itoa_s");
648     p_wcsncat_s = (void *)GetProcAddress( hcrt,"wcsncat_s" );
649     p_qsort_s = (void *) GetProcAddress(hcrt, "qsort_s");
650     p_controlfp_s = (void *) GetProcAddress(hcrt, "_controlfp_s");
651
652     hkernel32 = GetModuleHandleA("kernel32.dll");
653     pEncodePointer = (void *) GetProcAddress(hkernel32, "EncodePointer");
654
655     test__initterm_e();
656     test__encode_pointer();
657     test_error_messages();
658     test__strtoi64();
659     test__itoa_s();
660     test_wcsncat_s();
661     test_qsort_s();
662     test_controlfp_s();
663 }