2 * Copyright 2010 Detlef Riekenberg
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.
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.
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
32 #include "wine/test.h"
34 #define DEFINE_EXPECT(func) \
35 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
37 #define SET_EXPECT(func) \
38 expect_ ## func = TRUE
40 #define CHECK_EXPECT2(func) \
42 ok(expect_ ##func, "unexpected call " #func "\n"); \
43 called_ ## func = TRUE; \
46 #define CHECK_EXPECT(func) \
48 CHECK_EXPECT2(func); \
49 expect_ ## func = FALSE; \
52 #define CHECK_CALLED(func) \
54 ok(called_ ## func, "expected " #func "\n"); \
55 expect_ ## func = called_ ## func = FALSE; \
58 DEFINE_EXPECT(invalid_parameter_handler);
60 static _invalid_parameter_handler (__cdecl *p_set_invalid_parameter_handler)(_invalid_parameter_handler);
61 typedef int (__cdecl *_INITTERM_E_FN)(void);
62 static int (__cdecl *p_initterm_e)(_INITTERM_E_FN *table, _INITTERM_E_FN *end);
63 static void* (__cdecl *p_encode_pointer)(void *);
64 static void* (__cdecl *p_decode_pointer)(void *);
65 static void* (__cdecl *p_encoded_null)(void);
66 static int *p_sys_nerr;
67 static int* (__cdecl *p__sys_nerr)(void);
68 static char **p_sys_errlist;
69 static char** (__cdecl *p__sys_errlist)(void);
70 static __int64 (__cdecl *p_strtoi64)(const char *, char **, int);
71 static unsigned __int64 (__cdecl *p_strtoui64)(const char *, char **, int);
72 static errno_t (__cdecl *p_itoa_s)(int,char*,size_t,int);
73 static int (__cdecl *p_wcsncat_s)(wchar_t *dst, size_t elem, const wchar_t *src, size_t count);
74 static void (__cdecl *p_qsort_s)(void *, size_t, size_t, int (__cdecl *)(void *, const void *, const void *), void *);
75 static int (__cdecl *p_controlfp_s)(unsigned int *, unsigned int, unsigned int);
76 static int (__cdecl *p_atoflt)(_CRT_FLOAT *, char *);
77 static unsigned int (__cdecl *p_set_abort_behavior)(unsigned int, unsigned int);
78 static int (__cdecl *p_sopen_s)(int*, const char*, int, int, int);
79 static int (__cdecl *p_wsopen_s)(int*, const wchar_t*, int, int, int);
80 static void* (__cdecl *p_realloc_crt)(void*, size_t);
81 static void* (__cdecl *p_malloc)(size_t);
82 static void (__cdecl *p_free)(void*);
83 static void* (__cdecl *p_getptd)(void);
84 static int* (__cdecl *p_errno)(void);
85 static __msvcrt_ulong* (__cdecl *p_doserrno)(void);
86 static void (__cdecl *p_srand)(unsigned int);
87 static char* (__cdecl *p_strtok)(char*, const char*);
88 static wchar_t* (__cdecl *p_wcstok)(wchar_t*, const wchar_t*);
89 static char* (__cdecl *p_strerror)(int);
90 static wchar_t* (__cdecl *p_wcserror)(int);
91 static char* (__cdecl *p_tmpnam)(char*);
92 static wchar_t* (__cdecl *p_wtmpnam)(wchar_t*);
93 static char* (__cdecl *p_asctime)(struct tm*);
94 static wchar_t* (__cdecl *p_wasctime)(struct tm*);
95 static struct tm* (__cdecl *p_localtime64)(__time64_t*);
96 static char* (__cdecl *p_ecvt)(double, int, int*, int*);
97 static int* (__cdecl *p_fpecode)(void);
98 static int (__cdecl *p_configthreadlocale)(int);
99 static void* (__cdecl *p_get_terminate)(void);
100 static void* (__cdecl *p_get_unexpected)(void);
101 static int (__cdecl *p__vswprintf_l)(wchar_t*, const wchar_t*, _locale_t, __ms_va_list);
102 static int (__cdecl *p_vswprintf_l)(wchar_t*, const wchar_t*, _locale_t, __ms_va_list);
103 static FILE* (__cdecl *p_fopen)(const char*, const char*);
104 static int (__cdecl *p_fclose)(FILE*);
105 static int (__cdecl *p_unlink)(const char*);
106 static void (__cdecl *p_lock_file)(FILE*);
107 static void (__cdecl *p_unlock_file)(FILE*);
108 static int (__cdecl *p_fileno)(FILE*);
109 static int (__cdecl *p_feof)(FILE*);
110 static int (__cdecl *p_ferror)(FILE*);
111 static int (__cdecl *p_flsbuf)(int, FILE*);
112 static unsigned long (__cdecl *p_byteswap_ulong)(unsigned long);
116 typedef struct __type_info
124 struct __type_info_node
127 struct __type_info_node* next;
130 static char* (WINAPI *p_type_info_name_internal_method)(type_info*, struct __type_info_node *);
131 static void (WINAPI *ptype_info_dtor)(type_info*);
133 static void* (WINAPI *pEncodePointer)(void *);
135 static int cb_called[4];
136 static int g_qsort_s_context_counter;
138 static inline int almost_equal_f(float f1, float f2)
140 return f1-f2 > -1e-30 && f1-f2 < 1e-30;
145 /* thiscall emulation */
146 /* Emulate a __thiscall */
149 static inline void* do_call_func1(void *func, void *_this)
151 volatile void* retval = 0;
160 return (void*)retval;
163 static inline void* do_call_func2(void *func, void *_this, const void* arg)
165 volatile void* retval = 0;
175 return (void*)retval;
178 static void* do_call_func1(void *func, void *_this)
181 __asm__ __volatile__ ("call *%2"
182 : "=a" (ret), "=c" (dummy)
183 : "g" (func), "1" (_this)
188 static void* do_call_func2(void *func, void *_this, const void* arg)
191 __asm__ __volatile__ ("pushl %3\n\tcall *%2"
192 : "=a" (ret), "=c" (dummy)
193 : "r" (func), "r" (arg), "1" (_this)
199 #define call_func1(func,_this) do_call_func1(func,_this)
200 #define call_func2(func,_this,a) do_call_func2(func,_this,(const void*)a)
204 #define call_func1(func,_this) func(_this)
205 #define call_func2(func,_this,a) func(_this,a)
207 #endif /* __i386__ */
209 static void __cdecl test_invalid_parameter_handler(const wchar_t *expression,
210 const wchar_t *function, const wchar_t *file,
211 unsigned line, uintptr_t arg)
213 CHECK_EXPECT(invalid_parameter_handler);
214 ok(expression == NULL, "expression is not NULL\n");
215 ok(function == NULL, "function is not NULL\n");
216 ok(file == NULL, "file is not NULL\n");
217 ok(line == 0, "line = %u\n", line);
218 ok(arg == 0, "arg = %lx\n", (UINT_PTR)arg);
221 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(hcrt,y)
222 #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
223 static BOOL init(void)
228 SetLastError(0xdeadbeef);
229 hcrt = LoadLibraryA("msvcr90.dll");
231 win_skip("msvcr90.dll not installed (got %d)\n", GetLastError());
235 SET(p_set_invalid_parameter_handler, "_set_invalid_parameter_handler");
236 if(p_set_invalid_parameter_handler)
237 ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
238 "Invalid parameter handler was already set\n");
240 SET(p_initterm_e, "_initterm_e");
241 SET(p_encode_pointer, "_encode_pointer");
242 SET(p_decode_pointer, "_decode_pointer");
243 SET(p_encoded_null, "_encoded_null");
244 SET(p_sys_nerr, "_sys_nerr");
245 SET(p__sys_nerr, "__sys_nerr");
246 SET(p_sys_errlist, "_sys_errlist");
247 SET(p__sys_errlist, "__sys_errlist");
248 SET(p_strtoi64, "_strtoi64");
249 SET(p_strtoui64, "_strtoui64");
250 SET(p_itoa_s, "_itoa_s");
251 SET(p_wcsncat_s,"wcsncat_s" );
252 SET(p_qsort_s, "qsort_s");
253 SET(p_controlfp_s, "_controlfp_s");
254 SET(p_atoflt, "_atoflt");
255 SET(p_set_abort_behavior, "_set_abort_behavior");
256 SET(p_sopen_s, "_sopen_s");
257 SET(p_wsopen_s, "_wsopen_s");
258 SET(p_realloc_crt, "_realloc_crt");
259 SET(p_malloc, "malloc");
261 SET(p_getptd, "_getptd");
262 SET(p_errno, "_errno");
263 SET(p_doserrno, "__doserrno");
264 SET(p_srand, "srand");
265 SET(p_strtok, "strtok");
266 SET(p_wcstok, "wcstok");
267 SET(p_strerror, "strerror");
268 SET(p_wcserror, "_wcserror");
269 SET(p_tmpnam, "tmpnam");
270 SET(p_wtmpnam, "_wtmpnam");
271 SET(p_asctime, "asctime");
272 SET(p_wasctime, "_wasctime");
273 SET(p_localtime64, "_localtime64");
274 SET(p_ecvt, "_ecvt");
275 SET(p_fpecode, "__fpecode");
276 SET(p_configthreadlocale, "_configthreadlocale");
277 SET(p_get_terminate, "_get_terminate");
278 SET(p_get_unexpected, "_get_unexpected");
279 SET(p__vswprintf_l, "__vswprintf_l");
280 SET(p_vswprintf_l, "_vswprintf_l");
281 SET(p_fopen, "fopen");
282 SET(p_fclose, "fclose");
283 SET(p_unlink, "_unlink");
284 SET(p_lock_file, "_lock_file");
285 SET(p_unlock_file, "_unlock_file");
286 SET(p_fileno, "_fileno");
288 SET(p_ferror, "ferror");
289 SET(p_flsbuf, "_flsbuf");
290 SET(p_byteswap_ulong, "_byteswap_ulong");
291 if (sizeof(void *) == 8)
293 SET(p_type_info_name_internal_method, "?_name_internal_method@type_info@@QEBAPEBDPEAU__type_info_node@@@Z");
294 SET(ptype_info_dtor, "??1type_info@@UEAA@XZ");
298 SET(p_type_info_name_internal_method, "?_name_internal_method@type_info@@QBEPBDPAU__type_info_node@@@Z");
299 SET(ptype_info_dtor, "??1type_info@@UAE@XZ");
302 hkernel32 = GetModuleHandleA("kernel32.dll");
303 pEncodePointer = (void *) GetProcAddress(hkernel32, "EncodePointer");
307 static int __cdecl initterm_cb0(void)
313 static int __cdecl initterm_cb1(void)
319 static int __cdecl initterm_cb2(void)
326 static void test__initterm_e(void)
328 _INITTERM_E_FN table[4];
331 memset(table, 0, sizeof(table));
333 memset(cb_called, 0, sizeof(cb_called));
335 res = p_initterm_e(table, table);
336 ok( !res && !cb_called[0] && !cb_called[1] && !cb_called[2],
337 "got %d with 0x%x {%d, %d, %d}\n",
338 res, errno, cb_called[0], cb_called[1], cb_called[2]);
340 memset(cb_called, 0, sizeof(cb_called));
342 res = p_initterm_e(table, NULL);
343 ok( !res && !cb_called[0] && !cb_called[1] && !cb_called[2],
344 "got %d with 0x%x {%d, %d, %d}\n",
345 res, errno, cb_called[0], cb_called[1], cb_called[2]);
348 /* this crash on Windows */
350 res = p_initterm_e(NULL, table);
351 trace("got %d with 0x%x\n", res, errno);
354 table[0] = initterm_cb0;
355 memset(cb_called, 0, sizeof(cb_called));
357 res = p_initterm_e(table, &table[1]);
358 ok( !res && (cb_called[0] == 1) && !cb_called[1] && !cb_called[2],
359 "got %d with 0x%x {%d, %d, %d}\n",
360 res, errno, cb_called[0], cb_called[1], cb_called[2]);
363 /* init-function returning failure */
364 table[1] = initterm_cb1;
365 memset(cb_called, 0, sizeof(cb_called));
367 res = p_initterm_e(table, &table[3]);
368 ok( (res == 1) && (cb_called[0] == 1) && (cb_called[1] == 1) && !cb_called[2],
369 "got %d with 0x%x {%d, %d, %d}\n",
370 res, errno, cb_called[0], cb_called[1], cb_called[2]);
372 /* init-function not called, when end < start */
373 memset(cb_called, 0, sizeof(cb_called));
375 res = p_initterm_e(&table[3], table);
376 ok( !res && !cb_called[0] && !cb_called[1] && !cb_called[2],
377 "got %d with 0x%x {%d, %d, %d}\n",
378 res, errno, cb_called[0], cb_called[1], cb_called[2]);
380 /* initialization stop after first non-zero result */
381 table[2] = initterm_cb0;
382 memset(cb_called, 0, sizeof(cb_called));
384 res = p_initterm_e(table, &table[3]);
385 ok( (res == 1) && (cb_called[0] == 1) && (cb_called[1] == 1) && !cb_called[2],
386 "got %d with 0x%x {%d, %d, %d}\n",
387 res, errno, cb_called[0], cb_called[1], cb_called[2]);
389 /* NULL pointer in the array are skipped */
391 table[2] = initterm_cb2;
392 memset(cb_called, 0, sizeof(cb_called));
394 res = p_initterm_e(table, &table[3]);
395 ok( (res == 2) && (cb_called[0] == 1) && !cb_called[1] && (cb_called[2] == 1),
396 "got %d with 0x%x {%d, %d, %d}\n",
397 res, errno, cb_called[0], cb_called[1], cb_called[2]);
401 /* Beware that _encode_pointer is a NOP before XP
402 (the parameter is returned unchanged) */
403 static void test__encode_pointer(void)
407 ptr = (void*)0xdeadbeef;
408 res = p_encode_pointer(ptr);
409 res = p_decode_pointer(res);
410 ok(res == ptr, "Pointers are different after encoding and decoding\n");
412 ok(p_encoded_null() == p_encode_pointer(NULL), "Error encoding null\n");
414 ptr = p_encode_pointer(p_encode_pointer);
415 ok(p_decode_pointer(ptr) == p_encode_pointer, "Error decoding pointer\n");
417 /* Not present before XP */
418 if (!pEncodePointer) {
419 win_skip("EncodePointer not found\n");
423 res = pEncodePointer(p_encode_pointer);
424 ok(ptr == res, "_encode_pointer produced different result than EncodePointer\n");
428 static void test_error_messages(void)
430 int *size, size_copy;
432 size = p__sys_nerr();
434 ok(*p_sys_nerr == *size, "_sys_nerr = %u, size = %u\n", *p_sys_nerr, *size);
437 ok(*p_sys_nerr == *size, "_sys_nerr = %u, size = %u\n", *p_sys_nerr, *size);
441 ok(*p_sys_errlist == *(p__sys_errlist()), "p_sys_errlist != p__sys_errlist()\n");
444 static void test__strtoi64(void)
447 unsigned __int64 ures;
450 SET_EXPECT(invalid_parameter_handler);
451 res = p_strtoi64(NULL, NULL, 10);
452 ok(res == 0, "res != 0\n");
453 CHECK_CALLED(invalid_parameter_handler);
455 SET_EXPECT(invalid_parameter_handler);
456 res = p_strtoi64("123", NULL, 1);
457 ok(res == 0, "res != 0\n");
458 CHECK_CALLED(invalid_parameter_handler);
460 SET_EXPECT(invalid_parameter_handler);
461 res = p_strtoi64("123", NULL, 37);
462 ok(res == 0, "res != 0\n");
463 CHECK_CALLED(invalid_parameter_handler);
465 SET_EXPECT(invalid_parameter_handler);
466 ures = p_strtoui64(NULL, NULL, 10);
467 ok(ures == 0, "res = %d\n", (int)ures);
468 CHECK_CALLED(invalid_parameter_handler);
470 SET_EXPECT(invalid_parameter_handler);
471 ures = p_strtoui64("123", NULL, 1);
472 ok(ures == 0, "res = %d\n", (int)ures);
473 CHECK_CALLED(invalid_parameter_handler);
475 SET_EXPECT(invalid_parameter_handler);
476 ures = p_strtoui64("123", NULL, 37);
477 ok(ures == 0, "res = %d\n", (int)ures);
478 CHECK_CALLED(invalid_parameter_handler);
479 ok(errno == 0xdeadbeef, "errno = %x\n", errno);
482 static void test__itoa_s(void)
487 /* _itoa_s (on msvcr90) doesn't set errno (in case of errors) while msvcrt does
488 * as we always set errno in our msvcrt implementation, don't test here that errno
491 SET_EXPECT(invalid_parameter_handler);
492 ret = p_itoa_s(0, NULL, 0, 0);
493 ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
494 CHECK_CALLED(invalid_parameter_handler);
496 memset(buffer, 'X', sizeof(buffer));
497 SET_EXPECT(invalid_parameter_handler);
498 ret = p_itoa_s(0, buffer, 0, 0);
499 ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
500 ok(buffer[0] == 'X', "Expected the output buffer to be untouched\n");
501 CHECK_CALLED(invalid_parameter_handler);
503 memset(buffer, 'X', sizeof(buffer));
504 SET_EXPECT(invalid_parameter_handler);
505 ret = p_itoa_s(0, buffer, sizeof(buffer), 0);
506 ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
507 ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
508 CHECK_CALLED(invalid_parameter_handler);
510 memset(buffer, 'X', sizeof(buffer));
511 SET_EXPECT(invalid_parameter_handler);
512 ret = p_itoa_s(0, buffer, sizeof(buffer), 64);
513 ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
514 ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
515 CHECK_CALLED(invalid_parameter_handler);
517 memset(buffer, 'X', sizeof(buffer));
518 SET_EXPECT(invalid_parameter_handler);
519 ret = p_itoa_s(12345678, buffer, 4, 10);
520 ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
521 ok(!memcmp(buffer, "\000765", 4),
522 "Expected the output buffer to be null terminated with truncated output\n");
523 CHECK_CALLED(invalid_parameter_handler);
525 memset(buffer, 'X', sizeof(buffer));
526 SET_EXPECT(invalid_parameter_handler);
527 ret = p_itoa_s(12345678, buffer, 8, 10);
528 ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
529 ok(!memcmp(buffer, "\0007654321", 8),
530 "Expected the output buffer to be null terminated with truncated output\n");
531 CHECK_CALLED(invalid_parameter_handler);
533 memset(buffer, 'X', sizeof(buffer));
534 SET_EXPECT(invalid_parameter_handler);
535 ret = p_itoa_s(-12345678, buffer, 9, 10);
536 ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
537 ok(!memcmp(buffer, "\00087654321", 9),
538 "Expected the output buffer to be null terminated with truncated output\n");
539 CHECK_CALLED(invalid_parameter_handler);
541 ret = p_itoa_s(12345678, buffer, 9, 10);
542 ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
543 ok(!strcmp(buffer, "12345678"),
544 "Expected output buffer string to be \"12345678\", got \"%s\"\n",
547 ret = p_itoa_s(43690, buffer, sizeof(buffer), 2);
548 ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
549 ok(!strcmp(buffer, "1010101010101010"),
550 "Expected output buffer string to be \"1010101010101010\", got \"%s\"\n",
553 ret = p_itoa_s(1092009, buffer, sizeof(buffer), 36);
554 ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
555 ok(!strcmp(buffer, "nell"),
556 "Expected output buffer string to be \"nell\", got \"%s\"\n",
559 ret = p_itoa_s(5704, buffer, sizeof(buffer), 18);
560 ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
561 ok(!strcmp(buffer, "hag"),
562 "Expected output buffer string to be \"hag\", got \"%s\"\n",
565 ret = p_itoa_s(-12345678, buffer, sizeof(buffer), 10);
566 ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
567 ok(!strcmp(buffer, "-12345678"),
568 "Expected output buffer string to be \"-12345678\", got \"%s\"\n",
572 static void test_wcsncat_s(void)
574 static wchar_t abcW[] = {'a','b','c',0};
579 memcpy(src, abcW, sizeof(abcW));
581 SET_EXPECT(invalid_parameter_handler);
582 ret = p_wcsncat_s(NULL, 4, src, 4);
583 ok(ret == EINVAL, "err = %d\n", ret);
584 CHECK_CALLED(invalid_parameter_handler);
586 SET_EXPECT(invalid_parameter_handler);
587 ret = p_wcsncat_s(dst, 0, src, 4);
588 ok(ret == EINVAL, "err = %d\n", ret);
589 CHECK_CALLED(invalid_parameter_handler);
591 SET_EXPECT(invalid_parameter_handler);
592 ret = p_wcsncat_s(dst, 0, src, _TRUNCATE);
593 ok(ret == EINVAL, "err = %d\n", ret);
594 CHECK_CALLED(invalid_parameter_handler);
596 ret = p_wcsncat_s(dst, 4, NULL, 0);
597 ok(ret == 0, "err = %d\n", ret);
600 SET_EXPECT(invalid_parameter_handler);
601 ret = p_wcsncat_s(dst, 2, src, 4);
602 ok(ret == ERANGE, "err = %d\n", ret);
603 CHECK_CALLED(invalid_parameter_handler);
606 ret = p_wcsncat_s(dst, 2, src, _TRUNCATE);
607 ok(ret == STRUNCATE, "err = %d\n", ret);
608 ok(dst[0] == 'a' && dst[1] == 0, "dst is %s\n", wine_dbgstr_w(dst));
610 memcpy(dst, abcW, sizeof(abcW));
612 SET_EXPECT(invalid_parameter_handler);
613 ret = p_wcsncat_s(dst, 4, src, 4);
614 ok(ret == EINVAL, "err = %d\n", ret);
615 CHECK_CALLED(invalid_parameter_handler);
618 /* Based on dlls/ntdll/tests/string.c */
619 static __cdecl int intcomparefunc(void *context, const void *a, const void *b)
621 const int *p = a, *q = b;
623 ok (a != b, "must never get the same pointer\n");
629 static __cdecl int charcomparefunc(void *context, const void *a, const void *b)
631 const char *p = a, *q = b;
633 ok (a != b, "must never get the same pointer\n");
639 static __cdecl int strcomparefunc(void *context, const void *a, const void *b)
641 const char * const *p = a;
642 const char * const *q = b;
644 ok (a != b, "must never get the same pointer\n");
647 return lstrcmpA(*p, *q);
650 static void test_qsort_s(void)
652 int arr[5] = { 23, 42, 8, 4, 16 };
653 int arr2[5] = { 23, 42, 8, 4, 16 };
654 char carr[5] = { 42, 23, 4, 8, 16 };
655 const char *strarr[7] = {
665 SET_EXPECT(invalid_parameter_handler);
666 p_qsort_s(NULL, 0, 0, NULL, NULL);
667 CHECK_CALLED(invalid_parameter_handler);
669 SET_EXPECT(invalid_parameter_handler);
670 p_qsort_s(NULL, 0, 0, intcomparefunc, NULL);
671 CHECK_CALLED(invalid_parameter_handler);
673 SET_EXPECT(invalid_parameter_handler);
674 p_qsort_s(NULL, 0, sizeof(int), NULL, NULL);
675 CHECK_CALLED(invalid_parameter_handler);
677 SET_EXPECT(invalid_parameter_handler);
678 p_qsort_s(NULL, 1, sizeof(int), intcomparefunc, NULL);
679 CHECK_CALLED(invalid_parameter_handler);
681 g_qsort_s_context_counter = 0;
682 p_qsort_s(NULL, 0, sizeof(int), intcomparefunc, NULL);
683 ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
685 /* overflow without side effects, other overflow values crash */
686 g_qsort_s_context_counter = 0;
687 p_qsort_s((void*)arr2, (((size_t)1) << (8*sizeof(size_t) - 1)) + 1, sizeof(int), intcomparefunc, &g_qsort_s_context_counter);
688 ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
689 ok(arr2[0] == 23, "should remain unsorted, arr2[0] is %d\n", arr2[0]);
690 ok(arr2[1] == 42, "should remain unsorted, arr2[1] is %d\n", arr2[1]);
691 ok(arr2[2] == 8, "should remain unsorted, arr2[2] is %d\n", arr2[2]);
692 ok(arr2[3] == 4, "should remain unsorted, arr2[3] is %d\n", arr2[3]);
694 g_qsort_s_context_counter = 0;
695 p_qsort_s((void*)arr, 0, sizeof(int), intcomparefunc, &g_qsort_s_context_counter);
696 ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
697 ok(arr[0] == 23, "badly sorted, nmemb=0, arr[0] is %d\n", arr[0]);
698 ok(arr[1] == 42, "badly sorted, nmemb=0, arr[1] is %d\n", arr[1]);
699 ok(arr[2] == 8, "badly sorted, nmemb=0, arr[2] is %d\n", arr[2]);
700 ok(arr[3] == 4, "badly sorted, nmemb=0, arr[3] is %d\n", arr[3]);
701 ok(arr[4] == 16, "badly sorted, nmemb=0, arr[4] is %d\n", arr[4]);
703 g_qsort_s_context_counter = 0;
704 p_qsort_s((void*)arr, 1, sizeof(int), intcomparefunc, &g_qsort_s_context_counter);
705 ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
706 ok(arr[0] == 23, "badly sorted, nmemb=1, arr[0] is %d\n", arr[0]);
707 ok(arr[1] == 42, "badly sorted, nmemb=1, arr[1] is %d\n", arr[1]);
708 ok(arr[2] == 8, "badly sorted, nmemb=1, arr[2] is %d\n", arr[2]);
709 ok(arr[3] == 4, "badly sorted, nmemb=1, arr[3] is %d\n", arr[3]);
710 ok(arr[4] == 16, "badly sorted, nmemb=1, arr[4] is %d\n", arr[4]);
712 SET_EXPECT(invalid_parameter_handler);
713 g_qsort_s_context_counter = 0;
714 p_qsort_s((void*)arr, 5, 0, intcomparefunc, &g_qsort_s_context_counter);
715 ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
716 ok(arr[0] == 23, "badly sorted, size=0, arr[0] is %d\n", arr[0]);
717 ok(arr[1] == 42, "badly sorted, size=0, arr[1] is %d\n", arr[1]);
718 ok(arr[2] == 8, "badly sorted, size=0, arr[2] is %d\n", arr[2]);
719 ok(arr[3] == 4, "badly sorted, size=0, arr[3] is %d\n", arr[3]);
720 ok(arr[4] == 16, "badly sorted, size=0, arr[4] is %d\n", arr[4]);
721 CHECK_CALLED(invalid_parameter_handler);
723 g_qsort_s_context_counter = 0;
724 p_qsort_s((void*)arr, 5, sizeof(int), intcomparefunc, &g_qsort_s_context_counter);
725 ok(g_qsort_s_context_counter > 0, "callback wasn't called\n");
726 ok(arr[0] == 4, "badly sorted, arr[0] is %d\n", arr[0]);
727 ok(arr[1] == 8, "badly sorted, arr[1] is %d\n", arr[1]);
728 ok(arr[2] == 16, "badly sorted, arr[2] is %d\n", arr[2]);
729 ok(arr[3] == 23, "badly sorted, arr[3] is %d\n", arr[3]);
730 ok(arr[4] == 42, "badly sorted, arr[4] is %d\n", arr[4]);
732 g_qsort_s_context_counter = 0;
733 p_qsort_s((void*)carr, 5, sizeof(char), charcomparefunc, &g_qsort_s_context_counter);
734 ok(g_qsort_s_context_counter > 0, "callback wasn't called\n");
735 ok(carr[0] == 4, "badly sorted, carr[0] is %d\n", carr[0]);
736 ok(carr[1] == 8, "badly sorted, carr[1] is %d\n", carr[1]);
737 ok(carr[2] == 16, "badly sorted, carr[2] is %d\n", carr[2]);
738 ok(carr[3] == 23, "badly sorted, carr[3] is %d\n", carr[3]);
739 ok(carr[4] == 42, "badly sorted, carr[4] is %d\n", carr[4]);
741 g_qsort_s_context_counter = 0;
742 p_qsort_s((void*)strarr, 7, sizeof(char*), strcomparefunc, &g_qsort_s_context_counter);
743 ok(g_qsort_s_context_counter > 0, "callback wasn't called\n");
744 ok(!strcmp(strarr[0],"!"), "badly sorted, strarr[0] is %s\n", strarr[0]);
745 ok(!strcmp(strarr[1],"."), "badly sorted, strarr[1] is %s\n", strarr[1]);
746 ok(!strcmp(strarr[2],"Hello"), "badly sorted, strarr[2] is %s\n", strarr[2]);
747 ok(!strcmp(strarr[3],"Hopefully"), "badly sorted, strarr[3] is %s\n", strarr[3]);
748 ok(!strcmp(strarr[4],"Sorted"), "badly sorted, strarr[4] is %s\n", strarr[4]);
749 ok(!strcmp(strarr[5],"Wine"), "badly sorted, strarr[5] is %s\n", strarr[5]);
750 ok(!strcmp(strarr[6],"World"), "badly sorted, strarr[6] is %s\n", strarr[6]);
753 static void test_controlfp_s(void)
758 SET_EXPECT(invalid_parameter_handler);
759 ret = p_controlfp_s( NULL, ~0, ~0 );
760 ok( ret == EINVAL, "wrong result %d\n", ret );
761 CHECK_CALLED(invalid_parameter_handler);
764 SET_EXPECT(invalid_parameter_handler);
765 ret = p_controlfp_s( &cur, ~0, ~0 );
766 ok( ret == EINVAL, "wrong result %d\n", ret );
767 ok( cur != 0xdeadbeef, "value not set\n" );
768 CHECK_CALLED(invalid_parameter_handler);
771 ret = p_controlfp_s( &cur, 0, 0 );
772 ok( !ret, "wrong result %d\n", ret );
773 ok( cur != 0xdeadbeef, "value not set\n" );
775 SET_EXPECT(invalid_parameter_handler);
777 ret = p_controlfp_s( &cur, 0x80000000, 0x80000000 );
778 ok( ret == EINVAL, "wrong result %d\n", ret );
779 ok( cur != 0xdeadbeef, "value not set\n" );
780 CHECK_CALLED(invalid_parameter_handler);
783 /* mask is only checked when setting invalid bits */
784 ret = p_controlfp_s( &cur, 0, 0x80000000 );
785 ok( !ret, "wrong result %d\n", ret );
786 ok( cur != 0xdeadbeef, "value not set\n" );
796 static const _atoflt_test _atoflt_testdata[] = {
798 { "-13.721", -13.721, 0 },
800 { ".21e12", 0.21e12, 0 },
801 { "214353e-3", 214.353, 0 },
802 { "1d9999999999999999999", 0.0, _OVERFLOW },
804 /* more significant digits */
805 { "1.23456789", 1.23456789, 0 },
806 { "1.23456789e1", 12.3456789, 0 },
807 { "1e39", 0.0, _OVERFLOW },
808 { "1e-39", 0.0, _UNDERFLOW },
812 static void test__atoflt(void)
819 /* crashes on native */
820 p_atoflt(NULL, NULL);
821 p_atoflt(NULL, (char*)_atoflt_testdata[0].str);
822 p_atoflt(&flt, NULL);
825 while (_atoflt_testdata[i].str)
827 ret = p_atoflt(&flt, (char*)_atoflt_testdata[i].str);
828 ok(ret == _atoflt_testdata[i].ret, "got ret %d, expected ret %d, for %s\n", ret,
829 _atoflt_testdata[i].ret, _atoflt_testdata[i].str);
832 ok(almost_equal_f(flt.f, _atoflt_testdata[i].flt), "got %f, expected %f, for %s\n", flt.f,
833 _atoflt_testdata[i].flt, _atoflt_testdata[i].str);
839 static void test__set_abort_behavior(void)
843 /* default is _WRITE_ABORT_MSG | _CALL_REPORTFAULT */
844 res = p_set_abort_behavior(0, 0);
845 ok (res == (_WRITE_ABORT_MSG | _CALL_REPORTFAULT),
846 "got 0x%x (expected 0x%x)\n", res, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
848 /* no internal mask */
849 p_set_abort_behavior(0xffffffff, 0xffffffff);
850 res = p_set_abort_behavior(0, 0);
851 ok (res == 0xffffffff, "got 0x%x (expected 0x%x)\n", res, 0xffffffff);
853 /* set to default value */
854 p_set_abort_behavior(_WRITE_ABORT_MSG | _CALL_REPORTFAULT, 0xffffffff);
857 static void test__sopen_s(void)
861 SET_EXPECT(invalid_parameter_handler);
862 ret = p_sopen_s(NULL, "test", _O_RDONLY, _SH_DENYNO, _S_IREAD);
863 ok(ret == EINVAL, "got %d, expected EINVAL\n", ret);
864 CHECK_CALLED(invalid_parameter_handler);
867 ret = p_sopen_s(&fd, "test", _O_RDONLY, _SH_DENYNO, _S_IREAD);
868 ok(ret == ENOENT, "got %d, expected ENOENT\n", ret);
869 ok(fd == -1, "got %d\n", fd);
872 static void test__wsopen_s(void)
874 wchar_t testW[] = {'t','e','s','t',0};
877 SET_EXPECT(invalid_parameter_handler);
878 ret = p_wsopen_s(NULL, testW, _O_RDONLY, _SH_DENYNO, _S_IREAD);
879 ok(ret == EINVAL, "got %d, expected EINVAL\n", ret);
880 CHECK_CALLED(invalid_parameter_handler);
883 ret = p_wsopen_s(&fd, testW, _O_RDONLY, _SH_DENYNO, _S_IREAD);
884 ok(ret == ENOENT, "got %d, expected ENOENT\n", ret);
885 ok(fd == -1, "got %d\n", fd);
888 static void test__realloc_crt(void)
894 /* crashes on some systems starting Vista */
895 p_realloc_crt(NULL, 10);
899 ok(mem != NULL, "memory not allocated\n");
901 mem = p_realloc_crt(mem, 20);
902 ok(mem != NULL, "memory not reallocated\n");
904 mem = p_realloc_crt(mem, 0);
905 ok(mem == NULL, "memory not freed\n");
907 mem = p_realloc_crt(NULL, 0);
908 ok(mem != NULL, "memory not (re)allocated for size 0\n");
912 static void test_typeinfo(void)
914 static type_info t1 = { NULL, NULL,{'.','?','A','V','t','e','s','t','1','@','@',0,0,0,0,0 } };
915 struct __type_info_node node;
922 name = call_func2(p_type_info_name_internal_method, &t1, &node);
923 ok(name != NULL, "got %p\n", name);
924 ok(name && t1.name && !strcmp(name, t1.name), "bad name '%s' for t1\n", name);
926 ok(t1.name && !strcmp(t1.name, "class test1"), "demangled to '%s' for t1\n", t1.name);
927 call_func1(ptype_info_dtor, &t1);
930 /* Keep in sync with msvcrt/msvcrt.h */
931 struct __thread_data {
935 __msvcrt_ulong thread_doserrno;
937 unsigned int random_seed;
939 wchar_t *wcstok_next;
940 unsigned char *mbstok_next;
941 char *strerror_buffer;
942 wchar_t *wcserror_buffer;
944 wchar_t *wtmpnam_buffer;
946 char *asctime_buffer;
947 wchar_t *wasctime_buffer;
948 struct tm *time_buffer;
953 pthreadmbcinfo mbcinfo;
954 pthreadlocinfo locinfo;
957 void* terminate_handler;
958 void* unexpected_handler;
962 EXCEPTION_RECORD *exc_record;
965 static void test_getptd(void)
967 struct __thread_data *ptd = p_getptd();
968 DWORD tid = GetCurrentThreadId();
969 wchar_t testW[] = {'t','e','s','t',0}, tW[] = {'t',0}, *wp;
970 char test[] = "test", *p;
974 void *mbcinfo, *locinfo;
976 ok(ptd->tid == tid, "ptd->tid = %x, expected %x\n", ptd->tid, tid);
977 ok(ptd->handle == INVALID_HANDLE_VALUE, "ptd->handle = %p\n", ptd->handle);
978 ok(p_errno() == &ptd->thread_errno, "ptd->thread_errno is different then _errno()\n");
979 ok(p_doserrno() == &ptd->thread_doserrno, "ptd->thread_doserrno is different then __doserrno()\n");
981 ok(ptd->random_seed == 1234, "ptd->random_seed = %d\n", ptd->random_seed);
982 p = p_strtok(test, "t");
983 ok(ptd->strtok_next == p+3, "ptd->strtok_next is incorrect\n");
984 wp = p_wcstok(testW, tW);
985 ok(ptd->wcstok_next == wp+3, "ptd->wcstok_next is incorrect\n");
986 ok(p_strerror(0) == ptd->strerror_buffer, "ptd->strerror_buffer is incorrect\n");
987 ok(p_wcserror(0) == ptd->wcserror_buffer, "ptd->wcserror_buffer is incorrect\n");
988 ok(p_tmpnam(NULL) == ptd->tmpnam_buffer, "ptd->tmpnam_buffer is incorrect\n");
989 ok(p_wtmpnam(NULL) == ptd->wtmpnam_buffer, "ptd->wtmpnam_buffer is incorrect\n");
990 memset(&time, 0, sizeof(time));
992 ok(p_asctime(&time) == ptd->asctime_buffer, "ptd->asctime_buffer is incorrect\n");
993 ok(p_wasctime(&time) == ptd->wasctime_buffer, "ptd->wasctime_buffer is incorrect\n");
994 ok(p_localtime64(&secs) == ptd->time_buffer, "ptd->time_buffer is incorrect\n");
995 ok(p_ecvt(3.12, 1, &dec, &sign) == ptd->efcvt_buffer, "ptd->efcvt_buffer is incorrect\n");
996 ok(p_fpecode() == &ptd->fpecode, "ptd->fpecode is incorrect\n");
997 mbcinfo = ptd->mbcinfo;
998 locinfo = ptd->locinfo;
999 todo_wine ok(ptd->have_locale == 1, "ptd->have_locale = %x\n", ptd->have_locale);
1000 p_configthreadlocale(1);
1001 todo_wine ok(mbcinfo == ptd->mbcinfo, "ptd->mbcinfo != mbcinfo\n");
1002 todo_wine ok(locinfo == ptd->locinfo, "ptd->locinfo != locinfo\n");
1003 todo_wine ok(ptd->have_locale == 3, "ptd->have_locale = %x\n", ptd->have_locale);
1004 ok(p_get_terminate() == ptd->terminate_handler, "ptd->terminate_handler != _get_terminate()\n");
1005 ok(p_get_unexpected() == ptd->unexpected_handler, "ptd->unexpected_handler != _get_unexpected()\n");
1008 static int __cdecl __vswprintf_l_wrapper(wchar_t *buf,
1009 const wchar_t *format, _locale_t locale, ...)
1012 __ms_va_list valist;
1013 __ms_va_start(valist, locale);
1014 ret = p__vswprintf_l(buf, format, locale, valist);
1015 __ms_va_end(valist);
1019 static int __cdecl _vswprintf_l_wrapper(wchar_t *buf,
1020 const wchar_t *format, _locale_t locale, ...)
1023 __ms_va_list valist;
1024 __ms_va_start(valist, locale);
1025 ret = p_vswprintf_l(buf, format, locale, valist);
1026 __ms_va_end(valist);
1030 static void test__vswprintf_l(void)
1032 static const wchar_t format[] = {'t','e','s','t',0};
1037 ret = __vswprintf_l_wrapper(buf, format, NULL);
1038 ok(ret == 4, "ret = %d\n", ret);
1039 ok(!memcmp(buf, format, sizeof(format)), "buf = %s, expected %s\n",
1040 wine_dbgstr_w(buf), wine_dbgstr_w(format));
1042 ret = _vswprintf_l_wrapper(buf, format, NULL);
1043 ok(ret == 4, "ret = %d\n", ret);
1044 ok(!memcmp(buf, format, sizeof(format)), "buf = %s, expected %s\n",
1045 wine_dbgstr_w(buf), wine_dbgstr_w(format));
1048 struct block_file_arg
1055 static DWORD WINAPI block_file(void *arg)
1057 struct block_file_arg *files = arg;
1059 p_lock_file(files->read);
1060 p_lock_file(files->write);
1061 SetEvent(files->blocked);
1062 WaitForSingleObject(files->blocked, INFINITE);
1063 p_unlock_file(files->read);
1064 p_unlock_file(files->write);
1068 static void test_nonblocking_file_access(void)
1071 struct block_file_arg arg;
1072 FILE *filer, *filew;
1075 if(!p_lock_file || !p_unlock_file) {
1076 win_skip("_lock_file not available\n");
1080 filew = p_fopen("test_file", "w");
1081 ok(filew != NULL, "unable to create test file\n");
1084 filer = p_fopen("test_file", "r");
1085 ok(filer != NULL, "unable to open test file\n");
1088 p_unlink("test_file");
1094 arg.blocked = CreateEvent(NULL, FALSE, FALSE, NULL);
1095 ok(arg.blocked != NULL, "CreateEvent failed\n");
1099 p_unlink("test_file");
1102 thread = CreateThread(NULL, 0, block_file, (void*)&arg, 0, NULL);
1103 ok(thread != NULL, "CreateThread failed\n");
1105 CloseHandle(arg.blocked);
1108 p_unlink("test_file");
1111 WaitForSingleObject(arg.blocked, INFINITE);
1113 ret = p_fileno(filer);
1114 ok(ret, "_fileno(filer) returned %d\n", ret);
1115 ret = p_fileno(filew);
1116 ok(ret, "_fileno(filew) returned %d\n", ret);
1118 ret = p_feof(filer);
1119 ok(ret==0, "feof(filer) returned %d\n", ret);
1120 ret = p_feof(filew);
1121 ok(ret==0, "feof(filew) returned %d\n", ret);
1123 ret = p_ferror(filer);
1124 ok(ret==0, "ferror(filer) returned %d\n", ret);
1125 ret = p_ferror(filew);
1126 ok(ret==0, "ferror(filew) returned %d\n", ret);
1128 ret = p_flsbuf('a', filer);
1129 ok(ret==-1, "_flsbuf(filer) returned %d\n", ret);
1130 ret = p_flsbuf('a', filew);
1131 ok(ret=='a', "_flsbuf(filew) returned %d\n", ret);
1133 SetEvent(arg.blocked);
1134 WaitForSingleObject(thread, INFINITE);
1135 CloseHandle(arg.blocked);
1136 CloseHandle(thread);
1139 p_unlink("test_file");
1142 static void test_byteswap(void)
1146 ret = p_byteswap_ulong(0x12345678);
1147 ok(ret == 0x78563412, "ret = %lx\n", ret);
1149 ret = p_byteswap_ulong(0);
1150 ok(ret == 0, "ret = %lx\n", ret);
1159 test__encode_pointer();
1160 test_error_messages();
1167 test__set_abort_behavior();
1170 test__realloc_crt();
1173 test__vswprintf_l();
1174 test_nonblocking_file_access();