msvcrt: Forward _realloc_crt to realloc.
[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 #include <math.h>
23 #include <fcntl.h>
24 #include <share.h>
25 #include <sys/stat.h>
26
27 #include <windef.h>
28 #include <winbase.h>
29 #include <errno.h>
30 #include "wine/test.h"
31
32 #define DEFINE_EXPECT(func) \
33     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
34
35 #define SET_EXPECT(func) \
36     expect_ ## func = TRUE
37
38 #define CHECK_EXPECT2(func) \
39     do { \
40         ok(expect_ ##func, "unexpected call " #func "\n"); \
41         called_ ## func = TRUE; \
42     }while(0)
43
44 #define CHECK_EXPECT(func) \
45     do { \
46         CHECK_EXPECT2(func); \
47         expect_ ## func = FALSE; \
48     }while(0)
49
50 #define CHECK_CALLED(func) \
51     do { \
52         ok(called_ ## func, "expected " #func "\n"); \
53         expect_ ## func = called_ ## func = FALSE; \
54     }while(0)
55
56 DEFINE_EXPECT(invalid_parameter_handler);
57
58 static _invalid_parameter_handler (__cdecl *p_set_invalid_parameter_handler)(_invalid_parameter_handler);
59 typedef int (__cdecl *_INITTERM_E_FN)(void);
60 static int (__cdecl *p_initterm_e)(_INITTERM_E_FN *table, _INITTERM_E_FN *end);
61 static void* (__cdecl *p_encode_pointer)(void *);
62 static void* (__cdecl *p_decode_pointer)(void *);
63 static void* (__cdecl *p_encoded_null)(void);
64 static int *p_sys_nerr;
65 static int* (__cdecl *p__sys_nerr)(void);
66 static char **p_sys_errlist;
67 static char** (__cdecl *p__sys_errlist)(void);
68 static __int64 (__cdecl *p_strtoi64)(const char *, char **, int);
69 static unsigned __int64 (__cdecl *p_strtoui64)(const char *, char **, int);
70 static errno_t (__cdecl *p_itoa_s)(int,char*,size_t,int);
71 static int (__cdecl *p_wcsncat_s)(wchar_t *dst, size_t elem, const wchar_t *src, size_t count);
72 static void (__cdecl *p_qsort_s)(void *, size_t, size_t, int (__cdecl *)(void *, const void *, const void *), void *);
73 static int (__cdecl *p_controlfp_s)(unsigned int *, unsigned int, unsigned int);
74 static int (__cdecl *p_atoflt)(_CRT_FLOAT *, char *);
75 static unsigned int (__cdecl *p_set_abort_behavior)(unsigned int, unsigned int);
76 static int (__cdecl *p_sopen_s)(int*, const char*, int, int, int);
77 static int (__cdecl *p_wsopen_s)(int*, const wchar_t*, int, int, int);
78 static void* (__cdecl *p_realloc_crt)(void*, size_t);
79 static void* (__cdecl *p_malloc)(size_t);
80 static void (__cdecl *p_free)(void*);
81
82 static void* (WINAPI *pEncodePointer)(void *);
83
84 static int cb_called[4];
85 static int g_qsort_s_context_counter;
86
87 static inline int almost_equal_f(float f1, float f2)
88 {
89     return f1-f2 > -1e-30 && f1-f2 < 1e-30;
90 }
91
92 /* ########## */
93
94 static void __cdecl test_invalid_parameter_handler(const wchar_t *expression,
95         const wchar_t *function, const wchar_t *file,
96         unsigned line, uintptr_t arg)
97 {
98     CHECK_EXPECT(invalid_parameter_handler);
99     ok(expression == NULL, "expression is not NULL\n");
100     ok(function == NULL, "function is not NULL\n");
101     ok(file == NULL, "file is not NULL\n");
102     ok(line == 0, "line = %u\n", line);
103     ok(arg == 0, "arg = %lx\n", (UINT_PTR)arg);
104 }
105
106 static int __cdecl initterm_cb0(void)
107 {
108     cb_called[0]++;
109     return 0;
110 }
111
112 static int __cdecl initterm_cb1(void)
113 {
114     cb_called[1]++;
115     return 1;
116 }
117
118 static int __cdecl initterm_cb2(void)
119 {
120     cb_called[2]++;
121     return 2;
122 }
123
124
125 static void test__initterm_e(void)
126 {
127     _INITTERM_E_FN table[4];
128     int res;
129
130     if (!p_initterm_e) {
131         skip("_initterm_e not found\n");
132         return;
133     }
134
135     memset(table, 0, sizeof(table));
136
137     memset(cb_called, 0, sizeof(cb_called));
138     errno = 0xdeadbeef;
139     res = p_initterm_e(table, table);
140     ok( !res && !cb_called[0] && !cb_called[1] && !cb_called[2],
141         "got %d with 0x%x {%d, %d, %d}\n",
142         res, errno, cb_called[0], cb_called[1], cb_called[2]);
143
144     memset(cb_called, 0, sizeof(cb_called));
145     errno = 0xdeadbeef;
146     res = p_initterm_e(table, NULL);
147     ok( !res && !cb_called[0] && !cb_called[1] && !cb_called[2],
148         "got %d with 0x%x {%d, %d, %d}\n",
149         res, errno, cb_called[0], cb_called[1], cb_called[2]);
150
151     if (0) {
152         /* this crash on Windows */
153         errno = 0xdeadbeef;
154         res = p_initterm_e(NULL, table);
155         trace("got %d with 0x%x\n", res, errno);
156     }
157
158     table[0] = initterm_cb0;
159     memset(cb_called, 0, sizeof(cb_called));
160     errno = 0xdeadbeef;
161     res = p_initterm_e(table, &table[1]);
162     ok( !res && (cb_called[0] == 1) && !cb_called[1] && !cb_called[2],
163         "got %d with 0x%x {%d, %d, %d}\n",
164         res, errno, cb_called[0], cb_called[1], cb_called[2]);
165
166
167     /* init-function returning failure */
168     table[1] = initterm_cb1;
169     memset(cb_called, 0, sizeof(cb_called));
170     errno = 0xdeadbeef;
171     res = p_initterm_e(table, &table[3]);
172     ok( (res == 1) && (cb_called[0] == 1) && (cb_called[1] == 1) && !cb_called[2],
173         "got %d with 0x%x {%d, %d, %d}\n",
174         res, errno, cb_called[0], cb_called[1], cb_called[2]);
175
176     /* init-function not called, when end < start */
177     memset(cb_called, 0, sizeof(cb_called));
178     errno = 0xdeadbeef;
179     res = p_initterm_e(&table[3], table);
180     ok( !res && !cb_called[0] && !cb_called[1] && !cb_called[2],
181         "got %d with 0x%x {%d, %d, %d}\n",
182         res, errno, cb_called[0], cb_called[1], cb_called[2]);
183
184     /* initialization stop after first non-zero result */
185     table[2] = initterm_cb0;
186     memset(cb_called, 0, sizeof(cb_called));
187     errno = 0xdeadbeef;
188     res = p_initterm_e(table, &table[3]);
189     ok( (res == 1) && (cb_called[0] == 1) && (cb_called[1] == 1) && !cb_called[2],
190         "got %d with 0x%x {%d, %d, %d}\n",
191         res, errno, cb_called[0], cb_called[1], cb_called[2]);
192
193     /* NULL pointer in the array are skipped */
194     table[1] = NULL;
195     table[2] = initterm_cb2;
196     memset(cb_called, 0, sizeof(cb_called));
197     errno = 0xdeadbeef;
198     res = p_initterm_e(table, &table[3]);
199     ok( (res == 2) && (cb_called[0] == 1) && !cb_called[1] && (cb_called[2] == 1),
200         "got %d with 0x%x {%d, %d, %d}\n",
201         res, errno, cb_called[0], cb_called[1], cb_called[2]);
202
203 }
204
205 /* Beware that _encode_pointer is a NOP before XP
206    (the parameter is returned unchanged) */
207 static void test__encode_pointer(void)
208 {
209     void *ptr, *res;
210
211     if(!p_encode_pointer || !p_decode_pointer || !p_encoded_null) {
212         win_skip("_encode_pointer, _decode_pointer or _encoded_null not found\n");
213         return;
214     }
215
216     ptr = (void*)0xdeadbeef;
217     res = p_encode_pointer(ptr);
218     res = p_decode_pointer(res);
219     ok(res == ptr, "Pointers are different after encoding and decoding\n");
220
221     ok(p_encoded_null() == p_encode_pointer(NULL), "Error encoding null\n");
222
223     ptr = p_encode_pointer(p_encode_pointer);
224     ok(p_decode_pointer(ptr) == p_encode_pointer, "Error decoding pointer\n");
225
226     /* Not present before XP */
227     if (!pEncodePointer) {
228         win_skip("EncodePointer not found\n");
229         return;
230     }
231
232     res = pEncodePointer(p_encode_pointer);
233     ok(ptr == res, "_encode_pointer produced different result than EncodePointer\n");
234
235 }
236
237 static void test_error_messages(void)
238 {
239     int *size, size_copy;
240
241     if(!p_sys_nerr || !p__sys_nerr || !p_sys_errlist || !p__sys_errlist) {
242         win_skip("Skipping test_error_messages tests\n");
243         return;
244     }
245
246     size = p__sys_nerr();
247     size_copy = *size;
248     ok(*p_sys_nerr == *size, "_sys_nerr = %u, size = %u\n", *p_sys_nerr, *size);
249
250     *size = 20;
251     ok(*p_sys_nerr == *size, "_sys_nerr = %u, size = %u\n", *p_sys_nerr, *size);
252
253     *size = size_copy;
254
255     ok(*p_sys_errlist == *(p__sys_errlist()), "p_sys_errlist != p__sys_errlist()\n");
256 }
257
258 static void test__strtoi64(void)
259 {
260     __int64 res;
261     unsigned __int64 ures;
262
263     if(!p_strtoi64 || !p_strtoui64) {
264         win_skip("_strtoi64 or _strtoui64 not found\n");
265         return;
266     }
267
268     if(!p_set_invalid_parameter_handler) {
269         win_skip("_set_invalid_parameter_handler not found\n");
270         return;
271     }
272
273     errno = 0xdeadbeef;
274     SET_EXPECT(invalid_parameter_handler);
275     res = p_strtoi64(NULL, NULL, 10);
276     ok(res == 0, "res != 0\n");
277     CHECK_CALLED(invalid_parameter_handler);
278
279     SET_EXPECT(invalid_parameter_handler);
280     res = p_strtoi64("123", NULL, 1);
281     ok(res == 0, "res != 0\n");
282     CHECK_CALLED(invalid_parameter_handler);
283
284     SET_EXPECT(invalid_parameter_handler);
285     res = p_strtoi64("123", NULL, 37);
286     ok(res == 0, "res != 0\n");
287     CHECK_CALLED(invalid_parameter_handler);
288
289     SET_EXPECT(invalid_parameter_handler);
290     ures = p_strtoui64(NULL, NULL, 10);
291     ok(ures == 0, "res = %d\n", (int)ures);
292     CHECK_CALLED(invalid_parameter_handler);
293
294     SET_EXPECT(invalid_parameter_handler);
295     ures = p_strtoui64("123", NULL, 1);
296     ok(ures == 0, "res = %d\n", (int)ures);
297     CHECK_CALLED(invalid_parameter_handler);
298
299     SET_EXPECT(invalid_parameter_handler);
300     ures = p_strtoui64("123", NULL, 37);
301     ok(ures == 0, "res = %d\n", (int)ures);
302     CHECK_CALLED(invalid_parameter_handler);
303     ok(errno == 0xdeadbeef, "errno = %x\n", errno);
304 }
305
306 static void test__itoa_s(void)
307 {
308     errno_t ret;
309     char buffer[33];
310
311     if (!p_itoa_s)
312     {
313         win_skip("Skipping _itoa_s tests\n");
314         return;
315     }
316
317     if(!p_set_invalid_parameter_handler) {
318         win_skip("_set_invalid_parameter_handler not found\n");
319         return;
320     }
321
322     /* _itoa_s (on msvcr90) doesn't set errno (in case of errors) while msvcrt does
323      * as we always set errno in our msvcrt implementation, don't test here that errno
324      * isn't changed
325      */
326     SET_EXPECT(invalid_parameter_handler);
327     ret = p_itoa_s(0, NULL, 0, 0);
328     ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
329     CHECK_CALLED(invalid_parameter_handler);
330
331     memset(buffer, 'X', sizeof(buffer));
332     SET_EXPECT(invalid_parameter_handler);
333     ret = p_itoa_s(0, buffer, 0, 0);
334     ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
335     ok(buffer[0] == 'X', "Expected the output buffer to be untouched\n");
336     CHECK_CALLED(invalid_parameter_handler);
337
338     memset(buffer, 'X', sizeof(buffer));
339     SET_EXPECT(invalid_parameter_handler);
340     ret = p_itoa_s(0, buffer, sizeof(buffer), 0);
341     ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
342     ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
343     CHECK_CALLED(invalid_parameter_handler);
344
345     memset(buffer, 'X', sizeof(buffer));
346     SET_EXPECT(invalid_parameter_handler);
347     ret = p_itoa_s(0, buffer, sizeof(buffer), 64);
348     ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
349     ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\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, 4, 10);
355     ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
356     ok(!memcmp(buffer, "\000765", 4),
357        "Expected the output buffer to be null terminated with truncated output\n");
358     CHECK_CALLED(invalid_parameter_handler);
359
360     memset(buffer, 'X', sizeof(buffer));
361     SET_EXPECT(invalid_parameter_handler);
362     ret = p_itoa_s(12345678, buffer, 8, 10);
363     ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
364     ok(!memcmp(buffer, "\0007654321", 8),
365        "Expected the output buffer to be null terminated with truncated output\n");
366     CHECK_CALLED(invalid_parameter_handler);
367
368     memset(buffer, 'X', sizeof(buffer));
369     SET_EXPECT(invalid_parameter_handler);
370     ret = p_itoa_s(-12345678, buffer, 9, 10);
371     ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
372     ok(!memcmp(buffer, "\00087654321", 9),
373        "Expected the output buffer to be null terminated with truncated output\n");
374     CHECK_CALLED(invalid_parameter_handler);
375
376     ret = p_itoa_s(12345678, buffer, 9, 10);
377     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
378     ok(!strcmp(buffer, "12345678"),
379        "Expected output buffer string to be \"12345678\", got \"%s\"\n",
380        buffer);
381
382     ret = p_itoa_s(43690, buffer, sizeof(buffer), 2);
383     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
384     ok(!strcmp(buffer, "1010101010101010"),
385        "Expected output buffer string to be \"1010101010101010\", got \"%s\"\n",
386        buffer);
387
388     ret = p_itoa_s(1092009, buffer, sizeof(buffer), 36);
389     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
390     ok(!strcmp(buffer, "nell"),
391        "Expected output buffer string to be \"nell\", got \"%s\"\n",
392        buffer);
393
394     ret = p_itoa_s(5704, buffer, sizeof(buffer), 18);
395     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
396     ok(!strcmp(buffer, "hag"),
397        "Expected output buffer string to be \"hag\", got \"%s\"\n",
398        buffer);
399
400     ret = p_itoa_s(-12345678, buffer, sizeof(buffer), 10);
401     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
402     ok(!strcmp(buffer, "-12345678"),
403        "Expected output buffer string to be \"-12345678\", got \"%s\"\n",
404        buffer);
405 }
406
407 static void test_wcsncat_s(void)
408 {
409     static wchar_t abcW[] = {'a','b','c',0};
410     int ret;
411     wchar_t dst[4];
412     wchar_t src[4];
413
414     if (!p_wcsncat_s)
415     {
416         win_skip("skipping wcsncat_s tests\n");
417         return;
418     }
419
420     if(!p_set_invalid_parameter_handler) {
421         win_skip("_set_invalid_parameter_handler not found\n");
422         return;
423     }
424
425     memcpy(src, abcW, sizeof(abcW));
426     dst[0] = 0;
427     SET_EXPECT(invalid_parameter_handler);
428     ret = p_wcsncat_s(NULL, 4, src, 4);
429     ok(ret == EINVAL, "err = %d\n", ret);
430     CHECK_CALLED(invalid_parameter_handler);
431
432     SET_EXPECT(invalid_parameter_handler);
433     ret = p_wcsncat_s(dst, 0, src, 4);
434     ok(ret == EINVAL, "err = %d\n", ret);
435     CHECK_CALLED(invalid_parameter_handler);
436
437     SET_EXPECT(invalid_parameter_handler);
438     ret = p_wcsncat_s(dst, 0, src, _TRUNCATE);
439     ok(ret == EINVAL, "err = %d\n", ret);
440     CHECK_CALLED(invalid_parameter_handler);
441
442     ret = p_wcsncat_s(dst, 4, NULL, 0);
443     ok(ret == 0, "err = %d\n", ret);
444
445     dst[0] = 0;
446     SET_EXPECT(invalid_parameter_handler);
447     ret = p_wcsncat_s(dst, 2, src, 4);
448     ok(ret == ERANGE, "err = %d\n", ret);
449     CHECK_CALLED(invalid_parameter_handler);
450
451     dst[0] = 0;
452     ret = p_wcsncat_s(dst, 2, src, _TRUNCATE);
453     ok(ret == STRUNCATE, "err = %d\n", ret);
454     ok(dst[0] == 'a' && dst[1] == 0, "dst is %s\n", wine_dbgstr_w(dst));
455
456     memcpy(dst, abcW, sizeof(abcW));
457     dst[3] = 'd';
458     SET_EXPECT(invalid_parameter_handler);
459     ret = p_wcsncat_s(dst, 4, src, 4);
460     ok(ret == EINVAL, "err = %d\n", ret);
461     CHECK_CALLED(invalid_parameter_handler);
462 }
463
464 /* Based on dlls/ntdll/tests/string.c */
465 static __cdecl int intcomparefunc(void *context, const void *a, const void*b)
466 {
467     ok (a != b, "must never get the same pointer\n");
468     ++*(int *) context;
469     return (*(int*)a) - (*(int*)b);
470 }
471
472 static __cdecl int charcomparefunc(void *context, const void *a, const void*b)
473 {
474     ok (a != b, "must never get the same pointer\n");
475     ++*(int *) context;
476     return (*(char*)a) - (*(char*)b);
477 }
478
479 static __cdecl int strcomparefunc(void *context, const void *a, const void*b)
480 {
481     ok (a != b, "must never get the same pointer\n");
482     ++*(int *) context;
483     return lstrcmpA(*(char**)a,*(char**)b);
484 }
485
486 static void test_qsort_s(void)
487 {
488     int arr[5] = { 23, 42, 8, 4, 16 };
489     int arr2[5] = { 23, 42, 8, 4, 16 };
490     char carr[5] = { 42, 23, 4, 8, 16 };
491     const char *strarr[7] = {
492     "Hello",
493     "Wine",
494     "World",
495     "!",
496     "Hopefully",
497     "Sorted",
498     "."
499     };
500
501     if(!p_qsort_s) {
502         win_skip("qsort_s not found\n");
503         return;
504     }
505
506     SET_EXPECT(invalid_parameter_handler);
507     p_qsort_s(NULL, 0, 0, NULL, NULL);
508     CHECK_CALLED(invalid_parameter_handler);
509
510     SET_EXPECT(invalid_parameter_handler);
511     p_qsort_s(NULL, 0, 0, intcomparefunc, NULL);
512     CHECK_CALLED(invalid_parameter_handler);
513
514     SET_EXPECT(invalid_parameter_handler);
515     p_qsort_s(NULL, 0, sizeof(int), NULL, NULL);
516     CHECK_CALLED(invalid_parameter_handler);
517
518     SET_EXPECT(invalid_parameter_handler);
519     p_qsort_s(NULL, 1, sizeof(int), intcomparefunc, NULL);
520     CHECK_CALLED(invalid_parameter_handler);
521
522     g_qsort_s_context_counter = 0;
523     p_qsort_s(NULL, 0, sizeof(int), intcomparefunc, NULL);
524     ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
525
526     /* overflow without side effects, other overflow values crash */
527     g_qsort_s_context_counter = 0;
528     p_qsort_s((void*)arr2, (((size_t)1) << (8*sizeof(size_t) - 1)) + 1, sizeof(int), intcomparefunc, &g_qsort_s_context_counter);
529     ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
530     ok(arr2[0] == 23, "should remain unsorted, arr2[0] is %d\n", arr2[0]);
531     ok(arr2[1] == 42, "should remain unsorted, arr2[1] is %d\n", arr2[1]);
532     ok(arr2[2] == 8,  "should remain unsorted, arr2[2] is %d\n", arr2[2]);
533     ok(arr2[3] == 4,  "should remain unsorted, arr2[3] is %d\n", arr2[3]);
534
535     g_qsort_s_context_counter = 0;
536     p_qsort_s((void*)arr, 0, sizeof(int), intcomparefunc, &g_qsort_s_context_counter);
537     ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
538     ok(arr[0] == 23, "badly sorted, nmemb=0, arr[0] is %d\n", arr[0]);
539     ok(arr[1] == 42, "badly sorted, nmemb=0, arr[1] is %d\n", arr[1]);
540     ok(arr[2] == 8,  "badly sorted, nmemb=0, arr[2] is %d\n", arr[2]);
541     ok(arr[3] == 4,  "badly sorted, nmemb=0, arr[3] is %d\n", arr[3]);
542     ok(arr[4] == 16, "badly sorted, nmemb=0, arr[4] is %d\n", arr[4]);
543
544     g_qsort_s_context_counter = 0;
545     p_qsort_s((void*)arr, 1, sizeof(int), intcomparefunc, &g_qsort_s_context_counter);
546     ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
547     ok(arr[0] == 23, "badly sorted, nmemb=1, arr[0] is %d\n", arr[0]);
548     ok(arr[1] == 42, "badly sorted, nmemb=1, arr[1] is %d\n", arr[1]);
549     ok(arr[2] == 8,  "badly sorted, nmemb=1, arr[2] is %d\n", arr[2]);
550     ok(arr[3] == 4,  "badly sorted, nmemb=1, arr[3] is %d\n", arr[3]);
551     ok(arr[4] == 16, "badly sorted, nmemb=1, arr[4] is %d\n", arr[4]);
552
553     SET_EXPECT(invalid_parameter_handler);
554     g_qsort_s_context_counter = 0;
555     p_qsort_s((void*)arr, 5, 0, intcomparefunc, &g_qsort_s_context_counter);
556     ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
557     ok(arr[0] == 23, "badly sorted, size=0, arr[0] is %d\n", arr[0]);
558     ok(arr[1] == 42, "badly sorted, size=0, arr[1] is %d\n", arr[1]);
559     ok(arr[2] == 8,  "badly sorted, size=0, arr[2] is %d\n", arr[2]);
560     ok(arr[3] == 4,  "badly sorted, size=0, arr[3] is %d\n", arr[3]);
561     ok(arr[4] == 16, "badly sorted, size=0, arr[4] is %d\n", arr[4]);
562     CHECK_CALLED(invalid_parameter_handler);
563
564     g_qsort_s_context_counter = 0;
565     p_qsort_s((void*)arr, 5, sizeof(int), intcomparefunc, &g_qsort_s_context_counter);
566     ok(g_qsort_s_context_counter > 0, "callback wasn't called\n");
567     ok(arr[0] == 4,  "badly sorted, arr[0] is %d\n", arr[0]);
568     ok(arr[1] == 8,  "badly sorted, arr[1] is %d\n", arr[1]);
569     ok(arr[2] == 16, "badly sorted, arr[2] is %d\n", arr[2]);
570     ok(arr[3] == 23, "badly sorted, arr[3] is %d\n", arr[3]);
571     ok(arr[4] == 42, "badly sorted, arr[4] is %d\n", arr[4]);
572
573     g_qsort_s_context_counter = 0;
574     p_qsort_s((void*)carr, 5, sizeof(char), charcomparefunc, &g_qsort_s_context_counter);
575     ok(g_qsort_s_context_counter > 0, "callback wasn't called\n");
576     ok(carr[0] == 4,  "badly sorted, carr[0] is %d\n", carr[0]);
577     ok(carr[1] == 8,  "badly sorted, carr[1] is %d\n", carr[1]);
578     ok(carr[2] == 16, "badly sorted, carr[2] is %d\n", carr[2]);
579     ok(carr[3] == 23, "badly sorted, carr[3] is %d\n", carr[3]);
580     ok(carr[4] == 42, "badly sorted, carr[4] is %d\n", carr[4]);
581
582     g_qsort_s_context_counter = 0;
583     p_qsort_s((void*)strarr, 7, sizeof(char*), strcomparefunc, &g_qsort_s_context_counter);
584     ok(g_qsort_s_context_counter > 0, "callback wasn't called\n");
585     ok(!strcmp(strarr[0],"!"),  "badly sorted, strarr[0] is %s\n", strarr[0]);
586     ok(!strcmp(strarr[1],"."),  "badly sorted, strarr[1] is %s\n", strarr[1]);
587     ok(!strcmp(strarr[2],"Hello"),  "badly sorted, strarr[2] is %s\n", strarr[2]);
588     ok(!strcmp(strarr[3],"Hopefully"),  "badly sorted, strarr[3] is %s\n", strarr[3]);
589     ok(!strcmp(strarr[4],"Sorted"),  "badly sorted, strarr[4] is %s\n", strarr[4]);
590     ok(!strcmp(strarr[5],"Wine"),  "badly sorted, strarr[5] is %s\n", strarr[5]);
591     ok(!strcmp(strarr[6],"World"),  "badly sorted, strarr[6] is %s\n", strarr[6]);
592 }
593
594 static void test_controlfp_s(void)
595 {
596     unsigned int cur;
597     int ret;
598
599     if (!p_controlfp_s)
600     {
601         win_skip("_controlfp_s not found\n");
602         return;
603     }
604
605     SET_EXPECT(invalid_parameter_handler);
606     ret = p_controlfp_s( NULL, ~0, ~0 );
607     ok( ret == EINVAL, "wrong result %d\n", ret );
608     CHECK_CALLED(invalid_parameter_handler);
609
610     cur = 0xdeadbeef;
611     SET_EXPECT(invalid_parameter_handler);
612     ret = p_controlfp_s( &cur, ~0, ~0 );
613     ok( ret == EINVAL, "wrong result %d\n", ret );
614     ok( cur != 0xdeadbeef, "value not set\n" );
615     CHECK_CALLED(invalid_parameter_handler);
616
617     cur = 0xdeadbeef;
618     ret = p_controlfp_s( &cur, 0, 0 );
619     ok( !ret, "wrong result %d\n", ret );
620     ok( cur != 0xdeadbeef, "value not set\n" );
621
622     SET_EXPECT(invalid_parameter_handler);
623     cur = 0xdeadbeef;
624     ret = p_controlfp_s( &cur, 0x80000000, 0x80000000 );
625     ok( ret == EINVAL, "wrong result %d\n", ret );
626     ok( cur != 0xdeadbeef, "value not set\n" );
627     CHECK_CALLED(invalid_parameter_handler);
628
629     cur = 0xdeadbeef;
630     /* mask is only checked when setting invalid bits */
631     ret = p_controlfp_s( &cur, 0, 0x80000000 );
632     ok( !ret, "wrong result %d\n", ret );
633     ok( cur != 0xdeadbeef, "value not set\n" );
634 }
635
636 typedef struct
637 {
638     const char *str;
639     float flt;
640     int ret;
641 } _atoflt_test;
642
643 static const _atoflt_test _atoflt_testdata[] = {
644     { "12.1", 12.1, 0 },
645     { "-13.721", -13.721, 0 },
646     { "INF", 0.0, 0 },
647     { ".21e12", 0.21e12, 0 },
648     { "214353e-3", 214.353, 0 },
649     { "1d9999999999999999999", 0.0, _OVERFLOW },
650     { "  d10", 0.0, 0 },
651     /* more significant digits */
652     { "1.23456789", 1.23456789, 0 },
653     { "1.23456789e1", 12.3456789, 0 },
654     { "1e39", 0.0, _OVERFLOW },
655     { "1e-39", 0.0, _UNDERFLOW },
656     { NULL }
657 };
658
659 static void test__atoflt(void)
660 {
661     _CRT_FLOAT flt;
662     int ret, i = 0;
663
664     if (!p_atoflt)
665     {
666         win_skip("_atoflt not found\n");
667         return;
668     }
669
670 if (0)
671 {
672     /* crashes on native */
673     ret = p_atoflt(NULL, NULL);
674     ret = p_atoflt(NULL, (char*)_atoflt_testdata[0].str);
675     ret = p_atoflt(&flt, NULL);
676 }
677
678     while (_atoflt_testdata[i].str)
679     {
680         ret = p_atoflt(&flt, (char*)_atoflt_testdata[i].str);
681         ok(ret == _atoflt_testdata[i].ret, "got ret %d, expected ret %d, for %s\n", ret,
682             _atoflt_testdata[i].ret, _atoflt_testdata[i].str);
683
684         if (ret == 0)
685           ok(almost_equal_f(flt.f, _atoflt_testdata[i].flt), "got %f, expected %f, for %s\n", flt.f,
686               _atoflt_testdata[i].flt, _atoflt_testdata[i].str);
687
688         i++;
689     }
690 }
691
692 static void test__set_abort_behavior(void)
693 {
694     unsigned int res;
695
696     if (!p_set_abort_behavior)
697     {
698         win_skip("_set_abort_behavior not found\n");
699         return;
700     }
701
702     /* default is _WRITE_ABORT_MSG | _CALL_REPORTFAULT */
703     res = p_set_abort_behavior(0, 0);
704     ok (res == (_WRITE_ABORT_MSG | _CALL_REPORTFAULT),
705         "got 0x%x (expected 0x%x)\n", res, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
706
707     /* no internal mask */
708     p_set_abort_behavior(0xffffffff, 0xffffffff);
709     res = p_set_abort_behavior(0, 0);
710     ok (res == 0xffffffff, "got 0x%x (expected 0x%x)\n", res, 0xffffffff);
711
712     /* set to default value */
713     p_set_abort_behavior(_WRITE_ABORT_MSG | _CALL_REPORTFAULT, 0xffffffff);
714 }
715
716 static void test__sopen_s(void)
717 {
718     int ret, fd;
719
720     if(!p_sopen_s)
721     {
722         win_skip("_sopen_s not found\n");
723         return;
724     }
725
726     SET_EXPECT(invalid_parameter_handler);
727     ret = p_sopen_s(NULL, "test", _O_RDONLY, _SH_DENYNO, _S_IREAD);
728     ok(ret == EINVAL, "got %d, expected EINVAL\n", ret);
729     CHECK_CALLED(invalid_parameter_handler);
730
731     fd = 0xdead;
732     ret = p_sopen_s(&fd, "test", _O_RDONLY, _SH_DENYNO, _S_IREAD);
733     ok(ret == ENOENT, "got %d, expected ENOENT\n", ret);
734     ok(fd == -1, "got %d\n", fd);
735 }
736
737 static void test__wsopen_s(void)
738 {
739     wchar_t testW[] = {'t','e','s','t',0};
740     int ret, fd;
741
742     if(!p_wsopen_s)
743     {
744         win_skip("_wsopen_s not found\n");
745         return;
746     }
747
748     SET_EXPECT(invalid_parameter_handler);
749     ret = p_wsopen_s(NULL, testW, _O_RDONLY, _SH_DENYNO, _S_IREAD);
750     ok(ret == EINVAL, "got %d, expected EINVAL\n", ret);
751     CHECK_CALLED(invalid_parameter_handler);
752
753     fd = 0xdead;
754     ret = p_wsopen_s(&fd, testW, _O_RDONLY, _SH_DENYNO, _S_IREAD);
755     ok(ret == ENOENT, "got %d, expected ENOENT\n", ret);
756     ok(fd == -1, "got %d\n", fd);
757 }
758
759 static void test__realloc_crt(void)
760 {
761     void *mem;
762
763     if(!p_realloc_crt)
764     {
765         win_skip("_realloc_crt not found\n");
766         return;
767     }
768
769 if (0)
770 {
771     /* crashes on some systems starting Vista */
772     mem = p_realloc_crt(NULL, 10);
773 }
774
775     mem = p_malloc(10);
776     ok(mem != NULL, "memory not allocated\n");
777
778     mem = p_realloc_crt(mem, 20);
779     ok(mem != NULL, "memory not reallocated\n");
780
781     mem = p_realloc_crt(mem, 0);
782     ok(mem == NULL, "memory not freed\n");
783
784     mem = p_realloc_crt(NULL, 0);
785     ok(mem != NULL, "memory not (re)allocated for size 0\n");
786     p_free(mem);
787 }
788
789 START_TEST(msvcr90)
790 {
791     HMODULE hcrt;
792     HMODULE hkernel32;
793
794     SetLastError(0xdeadbeef);
795     hcrt = LoadLibraryA("msvcr90.dll");
796     if (!hcrt) {
797         win_skip("msvcr90.dll not installed (got %d)\n", GetLastError());
798         return;
799     }
800
801     p_set_invalid_parameter_handler = (void *) GetProcAddress(hcrt, "_set_invalid_parameter_handler");
802     if(p_set_invalid_parameter_handler)
803         ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
804                 "Invalid parameter handler was already set\n");
805
806     p_initterm_e = (void *) GetProcAddress(hcrt, "_initterm_e");
807     p_encode_pointer = (void *) GetProcAddress(hcrt, "_encode_pointer");
808     p_decode_pointer = (void *) GetProcAddress(hcrt, "_decode_pointer");
809     p_encoded_null = (void *) GetProcAddress(hcrt, "_encoded_null");
810     p_sys_nerr = (void *) GetProcAddress(hcrt, "_sys_nerr");
811     p__sys_nerr = (void *) GetProcAddress(hcrt, "__sys_nerr");
812     p_sys_errlist = (void *) GetProcAddress(hcrt, "_sys_errlist");
813     p__sys_errlist = (void *) GetProcAddress(hcrt, "__sys_errlist");
814     p_strtoi64 = (void *) GetProcAddress(hcrt, "_strtoi64");
815     p_strtoui64 = (void *) GetProcAddress(hcrt, "_strtoui64");
816     p_itoa_s = (void *)GetProcAddress(hcrt, "_itoa_s");
817     p_wcsncat_s = (void *)GetProcAddress( hcrt,"wcsncat_s" );
818     p_qsort_s = (void *) GetProcAddress(hcrt, "qsort_s");
819     p_controlfp_s = (void *) GetProcAddress(hcrt, "_controlfp_s");
820     p_atoflt = (void* )GetProcAddress(hcrt, "_atoflt");
821     p_set_abort_behavior = (void *) GetProcAddress(hcrt, "_set_abort_behavior");
822     p_sopen_s = (void*) GetProcAddress(hcrt, "_sopen_s");
823     p_wsopen_s = (void*) GetProcAddress(hcrt, "_wsopen_s");
824     p_realloc_crt = (void*) GetProcAddress(hcrt, "_realloc_crt");
825     p_malloc = (void*) GetProcAddress(hcrt, "malloc");
826     p_free = (void*)GetProcAddress(hcrt, "free");
827
828     hkernel32 = GetModuleHandleA("kernel32.dll");
829     pEncodePointer = (void *) GetProcAddress(hkernel32, "EncodePointer");
830
831     test__initterm_e();
832     test__encode_pointer();
833     test_error_messages();
834     test__strtoi64();
835     test__itoa_s();
836     test_wcsncat_s();
837     test_qsort_s();
838     test_controlfp_s();
839     test__atoflt();
840     test__set_abort_behavior();
841     test__sopen_s();
842     test__wsopen_s();
843     test__realloc_crt();
844 }