1 /* 2 * Unit tests for miscellaneous msvcrt functions 3 * 4 * Copyright 2010 Andrew Nguyen 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "wine/test.h" 22 #include <errno.h> 23 #include <stdio.h> 24 #include <math.h> 25 #include "msvcrt.h" 26 #include <process.h> 27 28 static inline float __port_infinity(void) 29 { 30 static const unsigned __inf_bytes = 0x7f800000; 31 return *(const float *)&__inf_bytes; 32 } 33 #ifdef __REACTOS__ 34 #undef INFINITY 35 #endif 36 #define INFINITY __port_infinity() 37 38 static inline float __port_nan(void) 39 { 40 static const unsigned __nan_bytes = 0x7fc00000; 41 return *(const float *)&__nan_bytes; 42 } 43 #ifdef __REACTOS__ 44 #undef NAN 45 #endif 46 #define NAN __port_nan() 47 48 static inline BOOL almost_equal(double d1, double d2) { 49 if(d1-d2>-1e-30 && d1-d2<1e-30) 50 return TRUE; 51 return FALSE; 52 } 53 54 static int (__cdecl *prand_s)(unsigned int *); 55 static int (__cdecl *pI10_OUTPUT)(long double, int, int, void*); 56 static int (__cdecl *pstrerror_s)(char *, MSVCRT_size_t, int); 57 static int (__cdecl *p_get_doserrno)(int *); 58 static int (__cdecl *p_get_errno)(int *); 59 static int (__cdecl *p_set_doserrno)(int); 60 static int (__cdecl *p_set_errno)(int); 61 static void (__cdecl *p__invalid_parameter)(const wchar_t*, 62 const wchar_t*, const wchar_t*, unsigned int, uintptr_t); 63 static void (__cdecl *p_qsort_s)(void*, MSVCRT_size_t, MSVCRT_size_t, 64 int (__cdecl*)(void*, const void*, const void*), void*); 65 static double (__cdecl *p_atan)(double); 66 static double (__cdecl *p_exp)(double); 67 static double (__cdecl *p_tanh)(double); 68 static void *(__cdecl *p_lfind_s)(const void*, const void*, unsigned int*, 69 size_t, int (__cdecl *)(void*, const void*, const void*), void*); 70 71 static void init(void) 72 { 73 HMODULE hmod = GetModuleHandleA("msvcrt.dll"); 74 75 prand_s = (void *)GetProcAddress(hmod, "rand_s"); 76 pI10_OUTPUT = (void*)GetProcAddress(hmod, "$I10_OUTPUT"); 77 pstrerror_s = (void *)GetProcAddress(hmod, "strerror_s"); 78 p_get_doserrno = (void *)GetProcAddress(hmod, "_get_doserrno"); 79 p_get_errno = (void *)GetProcAddress(hmod, "_get_errno"); 80 p_set_doserrno = (void *)GetProcAddress(hmod, "_set_doserrno"); 81 p_set_errno = (void *)GetProcAddress(hmod, "_set_errno"); 82 p__invalid_parameter = (void *)GetProcAddress(hmod, "_invalid_parameter"); 83 p_qsort_s = (void *)GetProcAddress(hmod, "qsort_s"); 84 p_atan = (void *)GetProcAddress(hmod, "atan"); 85 p_exp = (void *)GetProcAddress(hmod, "exp"); 86 p_tanh = (void *)GetProcAddress(hmod, "tanh"); 87 p_lfind_s = (void *)GetProcAddress(hmod, "_lfind_s"); 88 } 89 90 static void test_rand_s(void) 91 { 92 int ret; 93 unsigned int rand; 94 95 if (!prand_s) 96 { 97 win_skip("rand_s is not available\n"); 98 return; 99 } 100 101 errno = EBADF; 102 ret = prand_s(NULL); 103 ok(ret == EINVAL, "Expected rand_s to return EINVAL, got %d\n", ret); 104 ok(errno == EINVAL, "Expected errno to return EINVAL, got %d\n", errno); 105 106 ret = prand_s(&rand); 107 ok(ret == 0, "Expected rand_s to return 0, got %d\n", ret); 108 } 109 110 typedef struct _I10_OUTPUT_data { 111 short pos; 112 char sign; 113 BYTE len; 114 char str[100]; 115 } I10_OUTPUT_data; 116 117 typedef struct _I10_OUTPUT_test { 118 long double d; 119 int size; 120 int flags; 121 122 I10_OUTPUT_data out; 123 int ret; 124 const char *remain; 125 } I10_OUTPUT_test; 126 127 static const I10_OUTPUT_test I10_OUTPUT_tests[] = { 128 /* arg3 = 0 */ 129 { 0.0, 10, 0, {0, ' ', 1, "0"}, 1, "" }, 130 { 1.0, 10, 0, {1, ' ', 1, "1"}, 1, "000000009" }, 131 { -1.0, 10, 0, {1, '-', 1, "1"}, 1, "000000009" }, 132 { 1.23, 10, 0, {1, ' ', 3, "123"}, 1, "0000009" }, 133 { 1e13, 10, 0, {14, ' ', 1, "1"}, 1, "000000009" }, 134 { 1e30, 30, 0, {31, ' ', 21, "100000000000000001988"}, 1, "" }, 135 { 1e-13, 10, 0, {-12, ' ', 1, "1"}, 1, "000000000" }, 136 { 0.25, 10, 0, {0, ' ', 2, "25"}, 1, "00000000" }, 137 { 1.0000001, 10, 0, {1, ' ', 8, "10000001"}, 1, "00" }, 138 /* arg3 = 1 */ 139 { 0.0, 10, 1, {0, ' ', 1, "0"}, 1, "" }, 140 { 1.0, 10, 1, {1, ' ', 1, "1"}, 1, "0000000009" }, 141 { -1.0, 10, 1, {1, '-', 1, "1"}, 1, "0000000009" }, 142 { 1.23, 10, 1, {1, ' ', 3, "123"}, 1, "00000009" }, 143 { 1e13, 10, 1, {14, ' ', 1, "1"}, 1, "00000000000000000009" }, 144 { 1e30, 30, 1, {31, ' ', 21, "100000000000000001988"}, 1, "" }, 145 { 1e-13, 10, 1, {0, ' ', 1, "0"}, 1, "" }, 146 { 1e-7, 10, 1, {-6, ' ', 1, "1"}, 1, "09" }, 147 { 0.25, 10, 1, {0, ' ', 2, "25"}, 1, "00000000" }, 148 { 1.0000001, 10, 1, {1, ' ', 8, "10000001"}, 1, "000" }, 149 /* too small buffer */ 150 { 0.0, 0, 0, {0, ' ', 1, "0"}, 1, "" }, 151 { 0.0, 0, 1, {0, ' ', 1, "0"}, 1, "" }, 152 { 123.0, 2, 0, {3, ' ', 2, "12"}, 1, "" }, 153 { 123.0, 0, 0, {0, ' ', 1, "0"}, 1, "" }, 154 { 123.0, 2, 1, {3, ' ', 3, "123"}, 1, "09" }, 155 { 0.99, 1, 0, {1, ' ', 1, "1"}, 1, "" }, 156 { 1264567.0, 2, 0, {7, ' ', 2, "13"}, 1, "" }, 157 { 1264567.0, 2, 1, {7, ' ', 7, "1264567"}, 1, "00" }, 158 { 1234567891.0, 2, 1, {10, ' ', 10, "1234567891"}, 1, "09" } 159 }; 160 161 static void test_I10_OUTPUT(void) 162 { 163 I10_OUTPUT_data out; 164 int i, j = sizeof(long double), ret; 165 166 if(!pI10_OUTPUT) { 167 win_skip("I10_OUTPUT not available\n"); 168 return; 169 } 170 if (j != 12) 171 trace("sizeof(long double) = %d on this machine\n", j); 172 173 for(i=0; i<ARRAY_SIZE(I10_OUTPUT_tests); i++) { 174 memset(out.str, '#', sizeof(out.str)); 175 176 if (sizeof(long double) == 12) 177 ret = pI10_OUTPUT(I10_OUTPUT_tests[i].d, I10_OUTPUT_tests[i].size, I10_OUTPUT_tests[i].flags, &out); 178 else { 179 /* MS' "long double" is an 80 bit FP that takes 12 bytes*/ 180 typedef struct { ULONG x80[3]; } uld; /* same calling convention */ 181 union { long double ld; uld ld12; } fp80; 182 int (__cdecl *pI10_OUTPUT12)(uld, int, int, void*) = (void*)pI10_OUTPUT; 183 fp80.ld = I10_OUTPUT_tests[i].d; 184 ret = pI10_OUTPUT12(fp80.ld12, I10_OUTPUT_tests[i].size, I10_OUTPUT_tests[i].flags, &out); 185 } 186 ok(ret == I10_OUTPUT_tests[i].ret, "%d: ret = %d\n", i, ret); 187 ok(out.pos == I10_OUTPUT_tests[i].out.pos, "%d: out.pos = %hd\n", i, out.pos); 188 ok(out.sign == I10_OUTPUT_tests[i].out.sign, "%d: out.size = %c\n", i, out.sign); 189 ok(out.len == I10_OUTPUT_tests[i].out.len, "%d: out.len = %d\n", i, (int)out.len); 190 ok(!strcmp(out.str, I10_OUTPUT_tests[i].out.str), "%d: out.str = %s\n", i, out.str); 191 192 j = strlen(I10_OUTPUT_tests[i].remain); 193 todo_wine_if(j && I10_OUTPUT_tests[i].remain[j-1]=='9') 194 ok(!strncmp(out.str+out.len+1, I10_OUTPUT_tests[i].remain, j), 195 "%d: &out.str[%d] = %.25s...\n", i, out.len+1, out.str+out.len+1); 196 197 for(j=out.len+strlen(I10_OUTPUT_tests[i].remain)+1; j<sizeof(out.str); j++) 198 if(out.str[j] != '#') 199 ok(0, "%d: out.str[%d] = %c (expected \'#\')\n", i, j, out.str[j]); 200 } 201 } 202 203 static void test_strerror_s(void) 204 { 205 int ret; 206 char buf[256]; 207 208 if (!pstrerror_s) 209 { 210 win_skip("strerror_s is not available\n"); 211 return; 212 } 213 214 errno = EBADF; 215 ret = pstrerror_s(NULL, 0, 0); 216 ok(ret == EINVAL, "Expected strerror_s to return EINVAL, got %d\n", ret); 217 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno); 218 219 errno = EBADF; 220 ret = pstrerror_s(NULL, sizeof(buf), 0); 221 ok(ret == EINVAL, "Expected strerror_s to return EINVAL, got %d\n", ret); 222 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno); 223 224 memset(buf, 'X', sizeof(buf)); 225 errno = EBADF; 226 ret = pstrerror_s(buf, 0, 0); 227 ok(ret == EINVAL, "Expected strerror_s to return EINVAL, got %d\n", ret); 228 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno); 229 ok(buf[0] == 'X', "Expected output buffer to be untouched\n"); 230 231 memset(buf, 'X', sizeof(buf)); 232 ret = pstrerror_s(buf, 1, 0); 233 ok(ret == 0, "Expected strerror_s to return 0, got %d\n", ret); 234 ok(strlen(buf) == 0, "Expected output buffer to be null terminated\n"); 235 236 memset(buf, 'X', sizeof(buf)); 237 ret = pstrerror_s(buf, 2, 0); 238 ok(ret == 0, "Expected strerror_s to return 0, got %d\n", ret); 239 ok(strlen(buf) == 1, "Expected output buffer to be truncated\n"); 240 241 memset(buf, 'X', sizeof(buf)); 242 ret = pstrerror_s(buf, sizeof(buf), 0); 243 ok(ret == 0, "Expected strerror_s to return 0, got %d\n", ret); 244 245 memset(buf, 'X', sizeof(buf)); 246 ret = pstrerror_s(buf, sizeof(buf), -1); 247 ok(ret == 0, "Expected strerror_s to return 0, got %d\n", ret); 248 } 249 250 static void test__get_doserrno(void) 251 { 252 int ret, out; 253 254 if (!p_get_doserrno) 255 { 256 win_skip("_get_doserrno is not available\n"); 257 return; 258 } 259 260 _doserrno = ERROR_INVALID_CMM; 261 errno = EBADF; 262 ret = p_get_doserrno(NULL); 263 ok(ret == EINVAL, "Expected _get_doserrno to return EINVAL, got %d\n", ret); 264 ok(_doserrno == ERROR_INVALID_CMM, "Expected _doserrno to be ERROR_INVALID_CMM, got %d\n", _doserrno); 265 ok(errno == EBADF, "Expected errno to be EBADF, got %d\n", errno); 266 267 _doserrno = ERROR_INVALID_CMM; 268 errno = EBADF; 269 out = 0xdeadbeef; 270 ret = p_get_doserrno(&out); 271 ok(ret == 0, "Expected _get_doserrno to return 0, got %d\n", ret); 272 ok(out == ERROR_INVALID_CMM, "Expected output variable to be ERROR_INVALID_CMM, got %d\n", out); 273 } 274 275 static void test__get_errno(void) 276 { 277 int ret, out; 278 279 if (!p_get_errno) 280 { 281 win_skip("_get_errno is not available\n"); 282 return; 283 } 284 285 errno = EBADF; 286 ret = p_get_errno(NULL); 287 ok(ret == EINVAL, "Expected _get_errno to return EINVAL, got %d\n", ret); 288 ok(errno == EBADF, "Expected errno to be EBADF, got %d\n", errno); 289 290 errno = EBADF; 291 out = 0xdeadbeef; 292 ret = p_get_errno(&out); 293 ok(ret == 0, "Expected _get_errno to return 0, got %d\n", ret); 294 ok(out == EBADF, "Expected output variable to be EBADF, got %d\n", out); 295 } 296 297 static void test__set_doserrno(void) 298 { 299 int ret; 300 301 if (!p_set_doserrno) 302 { 303 win_skip("_set_doserrno is not available\n"); 304 return; 305 } 306 307 _doserrno = ERROR_INVALID_CMM; 308 ret = p_set_doserrno(ERROR_FILE_NOT_FOUND); 309 ok(ret == 0, "Expected _set_doserrno to return 0, got %d\n", ret); 310 ok(_doserrno == ERROR_FILE_NOT_FOUND, 311 "Expected _doserrno to be ERROR_FILE_NOT_FOUND, got %d\n", _doserrno); 312 313 _doserrno = ERROR_INVALID_CMM; 314 ret = p_set_doserrno(-1); 315 ok(ret == 0, "Expected _set_doserrno to return 0, got %d\n", ret); 316 ok(_doserrno == -1, 317 "Expected _doserrno to be -1, got %d\n", _doserrno); 318 319 _doserrno = ERROR_INVALID_CMM; 320 ret = p_set_doserrno(0xdeadbeef); 321 ok(ret == 0, "Expected _set_doserrno to return 0, got %d\n", ret); 322 ok(_doserrno == 0xdeadbeef, 323 "Expected _doserrno to be 0xdeadbeef, got %d\n", _doserrno); 324 } 325 326 static void test__set_errno(void) 327 { 328 int ret; 329 330 if (!p_set_errno) 331 { 332 win_skip("_set_errno is not available\n"); 333 return; 334 } 335 336 errno = EBADF; 337 ret = p_set_errno(EINVAL); 338 ok(ret == 0, "Expected _set_errno to return 0, got %d\n", ret); 339 ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno); 340 341 errno = EBADF; 342 ret = p_set_errno(-1); 343 ok(ret == 0, "Expected _set_errno to return 0, got %d\n", ret); 344 ok(errno == -1, "Expected errno to be -1, got %d\n", errno); 345 346 errno = EBADF; 347 ret = p_set_errno(0xdeadbeef); 348 ok(ret == 0, "Expected _set_errno to return 0, got %d\n", ret); 349 ok(errno == 0xdeadbeef, "Expected errno to be 0xdeadbeef, got %d\n", errno); 350 } 351 352 static void test__popen_child(void) 353 { 354 /* don't execute any tests here */ 355 /* ExitProcess is used to set return code of _pclose */ 356 printf("child output\n"); 357 ExitProcess(0x37); 358 } 359 360 static void test__popen(const char *name) 361 { 362 FILE *pipe; 363 char buf[1024]; 364 int ret; 365 366 sprintf(buf, "\"%s\" misc popen", name); 367 pipe = _popen(buf, "r"); 368 ok(pipe != NULL, "_popen failed with error: %d\n", errno); 369 370 fgets(buf, sizeof(buf), pipe); 371 ok(!strcmp(buf, "child output\n"), "buf = %s\n", buf); 372 373 ret = _pclose(pipe); 374 ok(ret == 0x37, "_pclose returned %x, expected 0x37\n", ret); 375 376 errno = 0xdeadbeef; 377 ret = _pclose((FILE*)0xdeadbeef); 378 ok(ret == -1, "_pclose returned %x, expected -1\n", ret); 379 if(p_set_errno) 380 ok(errno == EBADF, "errno = %d\n", errno); 381 } 382 383 static void test__invalid_parameter(void) 384 { 385 if(!p__invalid_parameter) { 386 win_skip("_invalid_parameter not available\n"); 387 return; 388 } 389 390 p__invalid_parameter(NULL, NULL, NULL, 0, 0); 391 } 392 393 struct qsort_test 394 { 395 int pos; 396 int *base; 397 398 struct { 399 int l; 400 int r; 401 } cmp[64]; 402 }; 403 404 static int __cdecl qsort_comp(void *ctx, const void *l, const void *r) 405 { 406 struct qsort_test *qt = ctx; 407 408 if(qt) { 409 ok(qt->pos < 64, "qt->pos = %d\n", qt->pos); 410 ok(qt->cmp[qt->pos].l == (int*)l-qt->base, 411 "%d) l on %ld position\n", qt->pos, (long)((int*)l - qt->base)); 412 ok(qt->cmp[qt->pos].r == (int*)r-qt->base, 413 "%d) r on %ld position\n", qt->pos, (long)((int*)r - qt->base)); 414 qt->pos++; 415 } 416 417 return *(int*)l%1000 - *(int*)r%1000; 418 } 419 420 static void test_qsort_s(void) 421 { 422 static const int nonstable_test[] = {9000, 8001, 7002, 6003, 1003, 5004, 4005, 3006, 2007}; 423 int tab[100], i; 424 425 struct qsort_test small_sort = { 426 0, tab, { 427 {1, 0}, {2, 1}, {3, 2}, {4, 3}, {5, 4}, {6, 5}, {7, 6}, 428 {1, 0}, {2, 1}, {3, 2}, {4, 3}, {5, 4}, {6, 5}, 429 {1, 0}, {2, 1}, {3, 2}, {4, 3}, {5, 4}, 430 {1, 0}, {2, 1}, {3, 2}, {4, 3}, 431 {1, 0}, {2, 1}, {3, 2}, 432 {1, 0}, {2, 1}, 433 {1, 0} 434 } 435 }, small_sort2 = { 436 0, tab, { 437 {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}, {7, 0}, 438 {1, 0}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, 439 {1, 0}, {2, 1}, {3, 2}, {4, 2}, {5, 2}, 440 {1, 0}, {2, 1}, {3, 2}, {4, 3}, 441 {1, 0}, {2, 1}, {3, 2}, 442 {1, 0}, {2, 1}, 443 {1, 0} 444 } 445 }, quick_sort = { 446 0, tab, { 447 {0, 4}, {0, 8}, {4, 8}, 448 {1, 4}, {2, 4}, {3, 4}, {5, 4}, {6, 4}, {7, 4}, {7, 4}, {6, 4}, 449 {6, 4}, 450 {8, 7}, 451 {1, 0}, {2, 1}, {3, 2}, {4, 3}, {5, 4}, {6, 4}, 452 {1, 0}, {2, 1}, {3, 2}, {4, 3}, {5, 3}, 453 {1, 0}, {2, 1}, {3, 2}, {4, 2}, 454 {1, 0}, {2, 1}, {3, 2}, 455 {1, 0}, {2, 1}, 456 {1, 0} 457 } 458 }; 459 460 if(!p_qsort_s) { 461 win_skip("qsort_s not available\n"); 462 return; 463 } 464 465 for(i=0; i<8; i++) tab[i] = i; 466 p_qsort_s(tab, 8, sizeof(int), qsort_comp, &small_sort); 467 ok(small_sort.pos == 28, "small_sort.pos = %d\n", small_sort.pos); 468 for(i=0; i<8; i++) 469 ok(tab[i] == i, "tab[%d] = %d\n", i, tab[i]); 470 471 for(i=0; i<8; i++) tab[i] = 7-i; 472 p_qsort_s(tab, 8, sizeof(int), qsort_comp, &small_sort2); 473 ok(small_sort2.pos == 28, "small_sort2.pos = %d\n", small_sort2.pos); 474 for(i=0; i<8; i++) 475 ok(tab[i] == i, "tab[%d] = %d\n", i, tab[i]); 476 477 for(i=0; i<9; i++) tab[i] = i; 478 tab[5] = 1; 479 tab[6] = 2; 480 p_qsort_s(tab, 9, sizeof(int), qsort_comp, &quick_sort); 481 ok(quick_sort.pos == 34, "quick_sort.pos = %d\n", quick_sort.pos); 482 483 /* show that qsort is not stable */ 484 for(i=0; i<9; i++) tab[i] = 8-i + 1000*(i+1); 485 tab[0] = 1003; 486 p_qsort_s(tab, 9, sizeof(int), qsort_comp, NULL); 487 for(i=0; i<9; i++) 488 ok(tab[i] == nonstable_test[i], "tab[%d] = %d, expected %d\n", i, tab[i], nonstable_test[i]); 489 490 /* check if random data is sorted */ 491 srand(0); 492 for(i=0; i<100; i++) tab[i] = rand()%1000; 493 p_qsort_s(tab, 100, sizeof(int), qsort_comp, NULL); 494 for(i=1; i<100; i++) 495 ok(tab[i-1] <= tab[i], "data sorted incorrectly on position %d: %d <= %d\n", i, tab[i-1], tab[i]); 496 497 /* test if random permutation is sorted correctly */ 498 for(i=0; i<100; i++) tab[i] = i; 499 for(i=0; i<100; i++) { 500 int b = rand()%100; 501 int e = rand()%100; 502 503 if(b == e) continue; 504 tab[b] ^= tab[e]; 505 tab[e] ^= tab[b]; 506 tab[b] ^= tab[e]; 507 } 508 p_qsort_s(tab, 100, sizeof(int), qsort_comp, NULL); 509 for(i=0; i<100; i++) 510 ok(tab[i] == i, "data sorted incorrectly on position %d: %d\n", i, tab[i]); 511 } 512 513 static void test_math_functions(void) 514 { 515 double ret; 516 517 errno = 0xdeadbeef; 518 p_atan(NAN); 519 ok(errno == EDOM, "errno = %d\n", errno); 520 521 errno = 0xdeadbeef; 522 ret = p_atan(INFINITY); 523 ok(almost_equal(ret, 1.57079632679489661923), "ret = %lf\n", ret); 524 ok(errno == 0xdeadbeef, "errno = %d\n", errno); 525 526 errno = 0xdeadbeef; 527 ret = p_atan(-INFINITY); 528 ok(almost_equal(ret, -1.57079632679489661923), "ret = %lf\n", ret); 529 ok(errno == 0xdeadbeef, "errno = %d\n", errno); 530 531 errno = 0xdeadbeef; 532 p_tanh(NAN); 533 ok(errno == EDOM, "errno = %d\n", errno); 534 535 errno = 0xdeadbeef; 536 ret = p_tanh(INFINITY); 537 ok(almost_equal(ret, 1.0), "ret = %lf\n", ret); 538 ok(errno == 0xdeadbeef, "errno = %d\n", errno); 539 540 errno = 0xdeadbeef; 541 p_exp(NAN); 542 ok(errno == EDOM, "errno = %d\n", errno); 543 544 errno = 0xdeadbeef; 545 p_exp(INFINITY); 546 ok(errno == 0xdeadbeef, "errno = %d\n", errno); 547 } 548 549 static void __cdecl test_thread_func(void *end_thread_type) 550 { 551 if (end_thread_type == (void*)1) 552 _endthread(); 553 else if (end_thread_type == (void*)2) 554 ExitThread(0); 555 else if (end_thread_type == (void*)3) 556 _endthreadex(0); 557 } 558 559 static unsigned __stdcall test_thread_func_ex(void *arg) 560 { 561 _endthread(); 562 return 0; 563 } 564 565 static void test_thread_handle_close(void) 566 { 567 HANDLE hThread; 568 DWORD ret; 569 570 /* _beginthread: handle is not closed on ExitThread and _endthreadex */ 571 hThread = (HANDLE)_beginthread(test_thread_func, 0, NULL); 572 ok(hThread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno); 573 WaitForSingleObject(hThread, INFINITE); 574 ret = CloseHandle(hThread); 575 ok(!ret, "ret = %d\n", ret); 576 577 hThread = (HANDLE)_beginthread(test_thread_func, 0, (void*)1); 578 ok(hThread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno); 579 WaitForSingleObject(hThread, INFINITE); 580 ret = CloseHandle(hThread); 581 ok(!ret, "ret = %d\n", ret); 582 583 hThread = (HANDLE)_beginthread(test_thread_func, 0, (void*)2); 584 ok(hThread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno); 585 Sleep(150); 586 ret = WaitForSingleObject(hThread, INFINITE); 587 ok(ret == WAIT_OBJECT_0, "ret = %d\n", ret); 588 ret = CloseHandle(hThread); 589 ok(ret, "ret = %d\n", ret); 590 591 hThread = (HANDLE)_beginthread(test_thread_func, 0, (void*)3); 592 ok(hThread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno); 593 Sleep(150); 594 ret = WaitForSingleObject(hThread, INFINITE); 595 ok(ret == WAIT_OBJECT_0, "ret = %d\n", ret); 596 ret = CloseHandle(hThread); 597 ok(ret, "ret = %d\n", ret); 598 599 /* _beginthreadex: handle is not closed on _endthread */ 600 hThread = (HANDLE)_beginthreadex(NULL,0, test_thread_func_ex, NULL, 0, NULL); 601 ok(hThread != NULL, "_beginthreadex failed (%d)\n", errno); 602 Sleep(150); 603 ret = WaitForSingleObject(hThread, INFINITE); 604 ok(ret == WAIT_OBJECT_0, "ret = %d\n", ret); 605 ret = CloseHandle(hThread); 606 ok(ret, "ret = %d\n", ret); 607 } 608 609 static int __cdecl _lfind_s_comp(void *ctx, const void *l, const void *r) 610 { 611 *(int *)ctx = 0xdeadc0de; 612 return *(int *)l - *(int *)r; 613 } 614 615 static void test__lfind_s(void) 616 { 617 static const int tests[] = {9000, 8001, 7002, 6003, 1003, 5004, 4005, 3006, 2007}; 618 unsigned int num; 619 void *found; 620 int ctx; 621 int key; 622 623 if (!p_lfind_s) 624 { 625 win_skip("_lfind_s is not available\n"); 626 return; 627 } 628 629 key = 1234; 630 num = ARRAY_SIZE(tests); 631 632 errno = 0xdeadbeef; 633 found = p_lfind_s(NULL, tests, &num, sizeof(int), _lfind_s_comp, NULL); 634 ok(errno == EINVAL, "errno = %d\n", errno); 635 ok(!found, "Expected NULL, got %p\n", found); 636 637 errno = 0xdeadbeef; 638 found = p_lfind_s(&key, NULL, &num, sizeof(int), _lfind_s_comp, NULL); 639 ok(errno == EINVAL, "errno = %d\n", errno); 640 ok(!found, "Expected NULL, got %p\n", found); 641 642 errno = 0xdeadbeef; 643 found = p_lfind_s(&key, tests, &num, 0, _lfind_s_comp, NULL); 644 ok(errno == EINVAL, "errno = %d\n", errno); 645 ok(!found, "Expected NULL, got %p\n", found); 646 647 errno = 0xdeadbeef; 648 found = p_lfind_s(&key, tests, &num, sizeof(int), NULL, NULL); 649 ok(errno == EINVAL, "errno = %d\n", errno); 650 ok(!found, "Expected NULL, got %p\n", found); 651 652 ctx = -1; 653 key = 9000; 654 errno = 0xdeadbeef; 655 found = p_lfind_s(&key, tests, &num, sizeof(int), _lfind_s_comp, &ctx); 656 ok(errno == 0xdeadbeef, "errno = %d\n", errno); 657 ok(found == tests, "Expected %p, got %p\n", tests, found); 658 ok(ctx == 0xdeadc0de, "Expected 0xdeadc0de, got %x\n", ctx); 659 660 ctx = -1; 661 key = 2007; 662 errno = 0xdeadbeef; 663 found = p_lfind_s(&key, tests, &num, sizeof(int), _lfind_s_comp, &ctx); 664 ok(errno == 0xdeadbeef, "errno = %d\n", errno); 665 ok(found == tests+8, "Expected %p, got %p\n", tests+8, found); 666 ok(ctx == 0xdeadc0de, "Expected 0xdeadc0de, got %x\n", ctx); 667 668 ctx = -1; 669 key = 1234; 670 errno = 0xdeadbeef; 671 found = p_lfind_s(&key, tests, &num, sizeof(int), _lfind_s_comp, &ctx); 672 ok(errno == 0xdeadbeef, "errno = %d\n", errno); 673 ok(!found, "Expected NULL, got %p\n", found); 674 ok(ctx == 0xdeadc0de, "Expected 0xdeadc0de, got %x\n", ctx); 675 } 676 677 START_TEST(misc) 678 { 679 int arg_c; 680 char** arg_v; 681 682 init(); 683 684 arg_c = winetest_get_mainargs(&arg_v); 685 if(arg_c >= 3) { 686 if(!strcmp(arg_v[2], "popen")) 687 test__popen_child(); 688 else 689 ok(0, "invalid argument '%s'\n", arg_v[2]); 690 691 return; 692 } 693 694 test_rand_s(); 695 test_I10_OUTPUT(); 696 test_strerror_s(); 697 test__get_doserrno(); 698 test__get_errno(); 699 test__set_doserrno(); 700 test__set_errno(); 701 test__popen(arg_v[0]); 702 test__invalid_parameter(); 703 test_qsort_s(); 704 test_math_functions(); 705 test_thread_handle_close(); 706 test__lfind_s(); 707 } 708