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