[MSVCRT_WINETEST]
authorAmine Khaldi <amine.khaldi@reactos.org>
Mon, 13 Oct 2014 10:53:02 +0000 (10:53 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Mon, 13 Oct 2014 10:53:02 +0000 (10:53 +0000)
* Sync with Wine 1.7.27.
CORE-8540

svn path=/trunk/; revision=64712

rostests/winetests/msvcrt/file.c
rostests/winetests/msvcrt/heap.c
rostests/winetests/msvcrt/misc.c
rostests/winetests/msvcrt/string.c
rostests/winetests/msvcrt/time.c

index f6a1624..c253f88 100644 (file)
@@ -144,6 +144,9 @@ static void test_fileops( void )
         fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
         file = fdopen (fd, "rb");
         setvbuf(file,NULL,bufmodes[bufmode],2048);
+        if(bufmodes[bufmode] == _IOFBF)
+            ok(file->_bufsiz == 2048, "file->_bufsiz = %d\n", file->_bufsiz);
+        ok(file->_base != NULL, "file->_base = NULL\n");
         ok(strlen(outbuffer) == (sizeof(outbuffer)-1),"strlen/sizeof error for bufmode=%x\n", bufmodes[bufmode]);
         ok(fgets(buffer,sizeof(buffer),file) !=0,"fgets failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
         ok(fgets(buffer,sizeof(buffer),file) ==0,"fgets didn't signal EOF for bufmode=%x\n", bufmodes[bufmode]);
@@ -629,6 +632,7 @@ static void test_flsbuf( void )
   ok(tempfh->_cnt == 0, "_cnt on freshly opened file was %d\n", tempfh->_cnt);
   setbuf(tempfh, NULL);
   ok(tempfh->_cnt == 0, "_cnt on unbuffered file was %d\n", tempfh->_cnt);
+  ok(tempfh->_bufsiz == 2, "_bufsiz = %d\n", tempfh->_bufsiz);
   /* Inlined putchar sets _cnt to -1.  Native seems to ignore the value... */
   tempfh->_cnt = 1234;
   ret = _flsbuf('Q',tempfh);
@@ -1624,7 +1628,7 @@ static void test_fopen_s( void )
     const char name[] = "empty1";
     char buff[16];
     unsigned char *ubuff = (unsigned char*)buff;
-    FILE *file;
+    FILE *file, *file2;
     int ret;
     int len;
 
@@ -1715,6 +1719,22 @@ static void test_fopen_s( void )
             ubuff[0], ubuff[1], ubuff[2]);
     fclose(file);
 
+    /* test initial FILE values */
+    memset(file, 0xfe, sizeof(*file));
+    file->_flag = 0;
+    ret = p_fopen_s(&file2, name, "r");
+    ok(!ret, "fopen_s failed with %d\n", ret);
+    ok(file == file2, "file != file2 %p %p\n", file, file2);
+    ok(!file->_ptr, "file->_ptr != NULL\n");
+    ok(!file->_cnt, "file->_cnt != 0\n");
+    ok(!file->_base, "file->_base != NULL\n");
+    ok(file->_flag == 1, "file->_flag = %x\n", file->_flag);
+    ok(file->_file, "file->_file == 0\n");
+    ok(file->_charbuf == 0xfefefefe, "file->_charbuf = %x\n", file->_charbuf);
+    ok(file->_bufsiz == 0xfefefefe, "file->_bufsiz = %x\n", file->_bufsiz);
+    ok(!file->_tmpfname, "file->_tmpfname != NULL\n");
+    fclose(file2);
+
     ok(_unlink(name) == 0, "Couldn't unlink file named '%s'\n", name);
 }
 
@@ -2219,6 +2239,65 @@ static void test__open_osfhandle(void)
     CloseHandle(tmp);
 }
 
+static void test_write_flush_size(FILE *file, int bufsize)
+{
+    char *inbuffer;
+    char *outbuffer;
+    int size, fd;
+
+    fd = fileno(file);
+    inbuffer = calloc(bufsize + 1, 1);
+    outbuffer = calloc(bufsize + 1, 1);
+    _snprintf(outbuffer, bufsize + 1, "0,1,2,3,4,5,6,7,8,9");
+
+    for (size = bufsize + 1; size >= bufsize - 1; size--) {
+        rewind(file);
+        ok(file->_cnt == 0, "_cnt should be 0 after rewind, but is %d\n", file->_cnt);
+        fwrite(outbuffer, 1, size, file);
+        /* lseek() below intentionally redirects the write in fflush() to detect
+         * if fwrite() has already flushed the whole buffer or not.
+         */
+        lseek(fd, 1, SEEK_SET);
+        fflush(file);
+        ok(file->_cnt == 0, "_cnt should be 0 after fflush, but is %d\n", file->_cnt);
+        fseek(file, 0, SEEK_SET);
+        ok(fread(inbuffer, 1, bufsize, file) == bufsize, "read failed\n");
+        if (size == bufsize)
+            ok(memcmp(outbuffer, inbuffer, bufsize) == 0, "missing flush by %d byte write\n", size);
+        else
+            ok(memcmp(outbuffer, inbuffer, bufsize) != 0, "unexpected flush by %d byte write\n", size);
+    }
+    rewind(file);
+    fwrite(outbuffer, 1, bufsize / 2, file);
+    fwrite(outbuffer + bufsize / 2, 1, bufsize / 2, file);
+    lseek(fd, 1, SEEK_SET);
+    fflush(file);
+    fseek(file, 0, SEEK_SET);
+    ok(fread(inbuffer, 1, bufsize, file) == bufsize, "read failed\n");
+    ok(memcmp(outbuffer, inbuffer, bufsize) != 0, "unexpected flush by %d/2 byte double write\n", bufsize);
+    free(inbuffer);
+    free(outbuffer);
+}
+
+static void test_write_flush(void)
+{
+    char iobuf[1024];
+    char *tempf;
+    FILE *file;
+
+    tempf = _tempnam(".","wne");
+    file = fopen(tempf, "wb+");
+    ok(file != NULL, "unable to create test file\n");
+    iobuf[0] = 0;
+    ok(file->_bufsiz == 4096, "incorrect default buffer size: %d\n", file->_bufsiz);
+    test_write_flush_size(file, file->_bufsiz);
+    setvbuf(file, iobuf, _IOFBF, sizeof(iobuf));
+    test_write_flush_size(file, sizeof(iobuf));
+    fclose(file);
+    unlink(tempf);
+    free(tempf);
+}
+
 START_TEST(file)
 {
     int arg_c;
@@ -2284,6 +2363,7 @@ START_TEST(file)
     test_stdin();
     test_mktemp();
     test__open_osfhandle();
+    test_write_flush();
 
     /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
      * file contains lines in the correct order
index 309e194..2aaf48d 100644 (file)
@@ -413,6 +413,49 @@ static void test_aligned(void)
     test_aligned_offset_realloc(256, 128, 64, 112);
 }
 
+static void test_sbheap(void)
+{
+    void *mem;
+    int threshold;
+
+    if(sizeof(void*) == 8) {
+        ok(!_set_sbh_threshold(0), "_set_sbh_threshold succeeded\n");
+        ok(!_set_sbh_threshold(1000), "_set_sbh_threshold succeeded\n");
+        return;
+    }
+
+    mem = malloc(1);
+    ok(mem != NULL, "malloc failed\n");
+
+    ok(_set_sbh_threshold(1), "_set_sbh_threshold failed\n");
+    threshold = _get_sbh_threshold();
+    ok(threshold == 16, "threshold = %d\n", threshold);
+
+    ok(_set_sbh_threshold(8), "_set_sbh_threshold failed\n");
+    threshold = _get_sbh_threshold();
+    ok(threshold == 16, "threshold = %d\n", threshold);
+
+    ok(_set_sbh_threshold(1000), "_set_sbh_threshold failed\n");
+    threshold = _get_sbh_threshold();
+    ok(threshold == 1008, "threshold = %d\n", threshold);
+
+    free(mem);
+
+    mem = malloc(1);
+    ok(mem != NULL, "malloc failed\n");
+    ok(!((UINT_PTR)mem & 0xf), "incorrect alignement (%p)\n", mem);
+
+    mem = realloc(mem, 10);
+    ok(mem != NULL, "realloc failed\n");
+    ok(!((UINT_PTR)mem & 0xf), "incorrect alignement (%p)\n", mem);
+
+    ok(_set_sbh_threshold(0), "_set_sbh_threshold failed\n");
+    threshold = _get_sbh_threshold();
+    ok(threshold == 0, "threshold = %d\n", threshold);
+
+    free(mem);
+}
+
 START_TEST(heap)
 {
     void *mem;
@@ -436,4 +479,5 @@ START_TEST(heap)
     free(mem);
 
     test_aligned();
+    test_sbheap();
 }
index 26225f3..a4c5c8c 100644 (file)
@@ -30,6 +30,10 @@ static int (__cdecl *p_get_doserrno)(int *);
 static int (__cdecl *p_get_errno)(int *);
 static int (__cdecl *p_set_doserrno)(int);
 static int (__cdecl *p_set_errno)(int);
+static void (__cdecl *p__invalid_parameter)(const wchar_t*,
+        const wchar_t*, const wchar_t*, unsigned int, uintptr_t);
+static void (__cdecl *p_qsort_s)(void*, MSVCRT_size_t, MSVCRT_size_t,
+        int (__cdecl*)(void*, const void*, const void*), void*);
 
 static void init(void)
 {
@@ -42,6 +46,8 @@ static void init(void)
     p_get_errno = (void *)GetProcAddress(hmod, "_get_errno");
     p_set_doserrno = (void *)GetProcAddress(hmod, "_set_doserrno");
     p_set_errno = (void *)GetProcAddress(hmod, "_set_errno");
+    p__invalid_parameter = (void *)GetProcAddress(hmod, "_invalid_parameter");
+    p_qsort_s = (void *)GetProcAddress(hmod, "qsort_s");
 }
 
 static void test_rand_s(void)
@@ -324,7 +330,7 @@ static void test__popen(const char *name)
     char buf[1024];
     int ret;
 
-    sprintf(buf, "%s misc popen", name);
+    sprintf(buf, "\"%s\" misc popen", name);
     pipe = _popen(buf, "r");
     ok(pipe != NULL, "_popen failed with error: %d\n", errno);
 
@@ -341,6 +347,136 @@ static void test__popen(const char *name)
         ok(errno == EBADF, "errno = %d\n", errno);
 }
 
+static void test__invalid_parameter(void)
+{
+    if(!p__invalid_parameter) {
+        win_skip("_invalid_parameter not available\n");
+        return;
+    }
+
+    p__invalid_parameter(NULL, NULL, NULL, 0, 0);
+}
+
+struct qsort_test
+{
+    int pos;
+    int *base;
+
+    struct {
+        int l;
+        int r;
+    } cmp[64];
+};
+
+static int __cdecl qsort_comp(void *ctx, const void *l, const void *r)
+{
+    struct qsort_test *qt = ctx;
+
+    if(qt) {
+        ok(qt->pos < 64, "qt->pos = %d\n", qt->pos);
+        ok(qt->cmp[qt->pos].l == (int*)l-qt->base,
+           "%d) l on %ld position\n", qt->pos, (long)((int*)l - qt->base));
+        ok(qt->cmp[qt->pos].r == (int*)r-qt->base,
+           "%d) r on %ld position\n", qt->pos, (long)((int*)r - qt->base));
+        qt->pos++;
+    }
+
+    return *(int*)l%1000 - *(int*)r%1000;
+}
+
+static void test_qsort_s(void)
+{
+    static const int nonstable_test[] = {9000, 8001, 7002, 6003, 1003, 5004, 4005, 3006, 2007};
+    int tab[100], i;
+
+    struct qsort_test small_sort = {
+        0, tab, {
+            {1, 0}, {2, 1}, {3, 2}, {4, 3}, {5, 4}, {6, 5}, {7, 6},
+            {1, 0}, {2, 1}, {3, 2}, {4, 3}, {5, 4}, {6, 5},
+            {1, 0}, {2, 1}, {3, 2}, {4, 3}, {5, 4},
+            {1, 0}, {2, 1}, {3, 2}, {4, 3},
+            {1, 0}, {2, 1}, {3, 2},
+            {1, 0}, {2, 1},
+            {1, 0}
+        }
+    }, small_sort2 = {
+        0, tab, {
+            {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}, {7, 0},
+            {1, 0}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1},
+            {1, 0}, {2, 1}, {3, 2}, {4, 2}, {5, 2},
+            {1, 0}, {2, 1}, {3, 2}, {4, 3},
+            {1, 0}, {2, 1}, {3, 2},
+            {1, 0}, {2, 1},
+            {1, 0}
+        }
+    }, quick_sort = {
+        0, tab, {
+            {0, 4}, {0, 8}, {4, 8},
+            {1, 4}, {2, 4}, {3, 4}, {5, 4}, {6, 4}, {7, 4}, {7, 4}, {6, 4},
+            {6, 4},
+            {8, 7},
+            {1, 0}, {2, 1}, {3, 2}, {4, 3}, {5, 4}, {6, 4},
+            {1, 0}, {2, 1}, {3, 2}, {4, 3}, {5, 3},
+            {1, 0}, {2, 1}, {3, 2}, {4, 2},
+            {1, 0}, {2, 1}, {3, 2},
+            {1, 0}, {2, 1},
+            {1, 0}
+        }
+    };
+
+    if(!p_qsort_s) {
+        win_skip("qsort_s not available\n");
+        return;
+    }
+
+    for(i=0; i<8; i++) tab[i] = i;
+    p_qsort_s(tab, 8, sizeof(int), qsort_comp, &small_sort);
+    ok(small_sort.pos == 28, "small_sort.pos = %d\n", small_sort.pos);
+    for(i=0; i<8; i++)
+        ok(tab[i] == i, "tab[%d] = %d\n", i, tab[i]);
+
+    for(i=0; i<8; i++) tab[i] = 7-i;
+    p_qsort_s(tab, 8, sizeof(int), qsort_comp, &small_sort2);
+    ok(small_sort2.pos == 28, "small_sort2.pos = %d\n", small_sort2.pos);
+    for(i=0; i<8; i++)
+        ok(tab[i] == i, "tab[%d] = %d\n", i, tab[i]);
+
+    for(i=0; i<9; i++) tab[i] = i;
+    tab[5] = 1;
+    tab[6] = 2;
+    p_qsort_s(tab, 9, sizeof(int), qsort_comp, &quick_sort);
+    ok(quick_sort.pos == 34, "quick_sort.pos = %d\n", quick_sort.pos);
+
+    /* show that qsort is not stable */
+    for(i=0; i<9; i++) tab[i] = 8-i + 1000*(i+1);
+    tab[0] = 1003;
+    p_qsort_s(tab, 9, sizeof(int), qsort_comp, NULL);
+    for(i=0; i<9; i++)
+        ok(tab[i] == nonstable_test[i], "tab[%d] = %d, expected %d\n", i, tab[i], nonstable_test[i]);
+
+    /* check if random data is sorted */
+    srand(0);
+    for(i=0; i<100; i++) tab[i] = rand()%1000;
+    p_qsort_s(tab, 100, sizeof(int), qsort_comp, NULL);
+    for(i=1; i<100; i++)
+        ok(tab[i-1] <= tab[i], "data sorted incorrectly on position %d: %d <= %d\n", i, tab[i-1], tab[i]);
+
+    /* test if random permutation is sorted correctly */
+    for(i=0; i<100; i++) tab[i] = i;
+    for(i=0; i<100; i++) {
+        int b = rand()%100;
+        int e = rand()%100;
+
+        if(b == e) continue;
+        tab[b] ^= tab[e];
+        tab[e] ^= tab[b];
+        tab[b] ^= tab[e];
+    }
+    p_qsort_s(tab, 100, sizeof(int), qsort_comp, NULL);
+    for(i=0; i<100; i++)
+        ok(tab[i] == i, "data sorted incorrectly on position %d: %d\n", i, tab[i]);
+}
+
 START_TEST(misc)
 {
     int arg_c;
@@ -366,4 +502,6 @@ START_TEST(misc)
     test__set_doserrno();
     test__set_errno();
     test__popen(arg_v[0]);
+    test__invalid_parameter();
+    test_qsort_s();
 }
index 7d820e1..1788035 100644 (file)
@@ -49,13 +49,6 @@ static char *buf_to_string(const unsigned char *bin, int len, int nr)
     return buf[nr];
 }
 
-static void __cdecl test_invalid_parameter_handler(const wchar_t *expression,
-        const wchar_t *function, const wchar_t *file,
-        unsigned line, uintptr_t arg)
-{
-    /* we just ignore handler calls */
-}
-
 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
 #define expect_bin(buf, value, len) { ok(memcmp((buf), value, len) == 0, "Binary buffer mismatch - expected %s, got %s\n", buf_to_string((unsigned char *)value, len, 1), buf_to_string((buf), len, 0)); }
 
@@ -67,6 +60,7 @@ static int (__cdecl *pstrcpy_s)(char *dst, size_t len, const char *src);
 static int (__cdecl *pstrcat_s)(char *dst, size_t len, const char *src);
 static int (__cdecl *p_mbsnbcat_s)(unsigned char *dst, size_t size, const unsigned char *src, size_t count);
 static int (__cdecl *p_mbsnbcpy_s)(unsigned char * dst, size_t size, const unsigned char * src, size_t count);
+static int (__cdecl *p__mbscpy_s)(unsigned char*, size_t, const unsigned char*);
 static int (__cdecl *p_wcscpy_s)(wchar_t *wcDest, size_t size, const wchar_t *wcSrc);
 static int (__cdecl *p_wcsncpy_s)(wchar_t *wcDest, size_t size, const wchar_t *wcSrc, size_t count);
 static int (__cdecl *p_wcsncat_s)(wchar_t *dst, size_t elem, const wchar_t *src, size_t count);
@@ -86,7 +80,6 @@ static errno_t (__cdecl *p_strlwr_s)(char*,size_t);
 static errno_t (__cdecl *p_ultoa_s)(__msvcrt_ulong,char*,size_t,int);
 static int *p__mb_cur_max;
 static unsigned char *p_mbctype;
-static _invalid_parameter_handler (__cdecl *p_set_invalid_parameter_handler)(_invalid_parameter_handler);
 static int (__cdecl *p_wcslwr_s)(wchar_t*,size_t);
 static errno_t (__cdecl *p_mbsupr_s)(unsigned char *str, size_t numberOfElements);
 static errno_t (__cdecl *p_mbslwr_s)(unsigned char *str, size_t numberOfElements);
@@ -96,6 +89,7 @@ static int (__cdecl *p_tolower)(int);
 static size_t (__cdecl *p_mbrlen)(const char*, size_t, mbstate_t*);
 static size_t (__cdecl *p_mbrtowc)(wchar_t*, const char*, size_t, mbstate_t*);
 static int (__cdecl *p__atodbl_l)(_CRT_DOUBLE*,char*,_locale_t);
+static int (__cdecl *p__strnset_s)(char*,size_t,int,size_t);
 
 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y)
 #define SET(x,y) SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y)
@@ -500,7 +494,7 @@ static void test_strcpy_s(void)
 
     if(!pstrcpy_s)
     {
-        skip("strcpy_s not found\n");
+        win_skip("strcpy_s not found\n");
         return;
     }
 
@@ -561,14 +555,10 @@ static void test_memcpy_s(void)
     static const char big[] = {'a','t','o','o','l','o','n','g','s','t','r','i','n','g',0};
     int ret;
     if (!p_memcpy_s) {
-        skip("memcpy_s not found\n");
+        win_skip("memcpy_s not found\n");
         return;
     }
 
-    if (p_set_invalid_parameter_handler)
-        ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
-            "Invalid parameter handler was already set\n");
-
     /* Normal */
     memset(dest, 'X', sizeof(dest));
     ret = p_memcpy_s(dest, NUMELMS(dest), tiny, NUMELMS(tiny));
@@ -612,10 +602,6 @@ static void test_memcpy_s(void)
     ok(ret == EINVAL, "Copying a NULL buffer into a destination of size 0 returned %d, expected EINVAL\n", ret);
     ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
     okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
-
-    if (p_set_invalid_parameter_handler)
-        ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler,
-            "Cannot reset invalid parameter handler\n");
 }
 
 static void test_memmove_s(void)
@@ -625,14 +611,10 @@ static void test_memmove_s(void)
     static const char big[] = {'a','t','o','o','l','o','n','g','s','t','r','i','n','g',0};
     int ret;
     if (!p_memmove_s) {
-        skip("memmove_s not found\n");
+        win_skip("memmove_s not found\n");
         return;
     }
 
-    if (p_set_invalid_parameter_handler)
-        ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
-            "Invalid parameter handler was already set\n");
-
     /* Normal */
     memset(dest, 'X', sizeof(dest));
     ret = p_memmove_s(dest, NUMELMS(dest), tiny, NUMELMS(tiny));
@@ -682,10 +664,6 @@ static void test_memmove_s(void)
     ok(ret == EINVAL, "Moving a NULL buffer into a destination of size 0 returned %d, expected EINVAL\n", ret);
     ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
     okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
-
-    if (p_set_invalid_parameter_handler)
-        ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler,
-            "Cannot reset invalid parameter handler\n");
 }
 
 static void test_strcat_s(void)
@@ -696,7 +674,7 @@ static void test_strcat_s(void)
 
     if(!pstrcat_s)
     {
-        skip("strcat_s not found\n");
+        win_skip("strcat_s not found\n");
         return;
     }
 
@@ -760,7 +738,7 @@ static void test__mbsnbcpy_s(void)
 
     if(!p_mbsnbcpy_s)
     {
-        skip("_mbsnbcpy_s not found\n");
+        win_skip("_mbsnbcpy_s not found\n");
         return;
     }
 
@@ -798,6 +776,42 @@ static void test__mbsnbcpy_s(void)
        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
 }
 
+static void test__mbscpy_s(void)
+{
+    const unsigned char src[] = "source string";
+    unsigned char dest[16];
+    int ret;
+
+    if(!p__mbscpy_s)
+    {
+        win_skip("_mbscpy_s not found\n");
+        return;
+    }
+
+    ret = p__mbscpy_s(NULL, 0, src);
+    ok(ret == EINVAL, "got %d\n", ret);
+    ret = p__mbscpy_s(NULL, sizeof(dest), src);
+    ok(ret == EINVAL, "got %d\n", ret);
+    ret = p__mbscpy_s(dest, 0, src);
+    ok(ret == EINVAL, "got %d\n", ret);
+    dest[0] = 'x';
+    ret = p__mbscpy_s(dest, sizeof(dest), NULL);
+    ok(ret == EINVAL, "got %d\n", ret);
+    ok(!dest[0], "dest buffer was not modified on invalid argument\n");
+
+    memset(dest, 'X', sizeof(dest));
+    ret = p__mbscpy_s(dest, sizeof(dest), src);
+    ok(!ret, "got %d\n", ret);
+    ok(!memcmp(dest, src, sizeof(src)), "dest = %s\n", dest);
+    ok(dest[sizeof(src)] == 'X', "unused part of buffer was modified\n");
+
+    memset(dest, 'X', sizeof(dest));
+    ret = p__mbscpy_s(dest, 4, src);
+    ok(ret == ERANGE, "got %d\n", ret);
+    ok(!dest[0], "incorrect dest buffer (%d)\n", dest[0]);
+    ok(dest[1] == src[1], "incorrect dest buffer (%d)\n", dest[1]);
+}
+
 static void test_wcscpy_s(void)
 {
     static const WCHAR szLongText[] = { 'T','h','i','s','A','L','o','n','g','s','t','r','i','n','g',0 };
@@ -811,10 +825,6 @@ static void test_wcscpy_s(void)
         return;
     }
 
-    if (p_set_invalid_parameter_handler)
-        ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
-            "Invalid parameter handler was already set\n");
-
     /* Test NULL Dest */
     errno = EBADF;
     ret = p_wcscpy_s(NULL, 18, szLongText);
@@ -856,10 +866,6 @@ static void test_wcscpy_s(void)
     if(!p_wcsncpy_s)
     {
         win_skip("wcsncpy_s not found\n");
-
-        if (p_set_invalid_parameter_handler)
-            ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler,
-                    "Cannot reset invalid parameter handler\n");
         return;
     }
 
@@ -905,10 +911,6 @@ static void test_wcscpy_s(void)
     ok(ret == STRUNCATE, "expected ERROR_SUCCESS got %d\n", ret);
     ok(szDestShort[0]=='1' && szDestShort[1]=='1' && szDestShort[2]=='1' && szDestShort[3]=='1',
             "szDestShort = %s\n", wine_dbgstr_w(szDestShort));
-
-    if (p_set_invalid_parameter_handler)
-        ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler,
-                "Cannot reset invalid parameter handler\n");
 }
 
 static void test__wcsupr_s(void)
@@ -1750,16 +1752,10 @@ static void test_mbstowcs(void)
     ok(wOut[2] == 0, "wOut[2] = %x\n", wOut[2]);
     ok(!pmbstr, "pmbstr != NULL\n");
 
-    if (p_set_invalid_parameter_handler)
-        ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
-                "Invalid parameter handler was already set\n");
     errno = EBADF;
     ret = p_mbsrtowcs(wOut, NULL, 6, &state);
     ok(ret == -1, "mbsrtowcs did not return -1\n");
     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
-    if (p_set_invalid_parameter_handler)
-        ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler,
-                "Cannot reset invalid parameter handler\n");
 
     setlocale(LC_ALL, "C");
 }
@@ -1810,10 +1806,6 @@ static void test__itoa_s(void)
         return;
     }
 
-    if (p_set_invalid_parameter_handler)
-        ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
-                "Invalid parameter handler was already set\n");
-
     errno = EBADF;
     ret = p_itoa_s(0, NULL, 0, 0);
     ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
@@ -1897,10 +1889,6 @@ static void test__itoa_s(void)
     itoa(100, buffer, 100);
     ok(!strcmp(buffer, "10"),
             "Expected output buffer string to be \"10\", got \"%s\"\n", buffer);
-
-    if (p_set_invalid_parameter_handler)
-        ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler,
-                "Cannot reset invalid parameter handler\n");
 }
 
 static void test__strlwr_s(void)
@@ -1973,10 +1961,6 @@ static void test_wcsncat_s(void)
         return;
     }
 
-    if (p_set_invalid_parameter_handler)
-        ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
-                "Invalid parameter handler was already set\n");
-
     memcpy(src, abcW, sizeof(abcW));
     dst[0] = 0;
     ret = p_wcsncat_s(NULL, 4, src, 4);
@@ -2001,10 +1985,6 @@ static void test_wcsncat_s(void)
     dst[3] = 'd';
     ret = p_wcsncat_s(dst, 4, src, 4);
     ok(ret == EINVAL, "err = %d\n", ret);
-
-    if (p_set_invalid_parameter_handler)
-        ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler,
-                "Cannot reset invalid parameter handler\n");
 }
 
 static void test__mbsnbcat_s(void)
@@ -2568,6 +2548,8 @@ static void test__stricmp(void)
     ok(ret > 0, "_stricmp returned %d\n", ret);
     ret = _stricmp("\xa5", "\xb9");
     ok(ret == 0, "_stricmp returned %d\n", ret);
+    ret = _stricmp("a", "\xb9");
+    ok(ret < 0, "_stricmp returned %d\n", ret);
 
     setlocale(LC_ALL, "C");
 }
@@ -2670,6 +2652,103 @@ static void test_strncpy(void)
     ok(!strncmp(dst, "0123456789", TEST_STRNCPY_LEN), "dst != 0123456789\n");
 }
 
+static void test_strxfrm(void)
+{
+    char dest[256];
+    size_t ret;
+
+    /* crashes on old version of msvcrt */
+    if(p__atodbl_l) {
+        errno = 0xdeadbeef;
+        ret = strxfrm(NULL, "src", 1);
+        ok(ret == INT_MAX, "ret = %d\n", (int)ret);
+        ok(errno == EINVAL, "errno = %d\n", errno);
+
+        errno = 0xdeadbeef;
+        ret = strxfrm(dest, NULL, 100);
+        ok(ret == INT_MAX, "ret = %d\n", (int)ret);
+        ok(errno == EINVAL, "errno = %d\n", errno);
+    }
+
+    ret = strxfrm(NULL, "src", 0);
+    ok(ret == 3, "ret = %d\n", (int)ret);
+    dest[0] = 'a';
+    ret = strxfrm(dest, "src", 0);
+    ok(ret == 3, "ret = %d\n", (int)ret);
+    ok(dest[0] == 'a', "dest[0] = %d\n", dest[0]);
+
+    dest[3] = 'a';
+    ret = strxfrm(dest, "src", 5);
+    ok(ret == 3, "ret = %d\n", (int)ret);
+    ok(!strcmp(dest, "src"), "dest = %s\n", dest);
+
+    errno = 0xdeadbeef;
+    dest[1] = 'a';
+    ret = strxfrm(dest, "src", 1);
+    ok(ret == 3, "ret = %d\n", (int)ret);
+    ok(dest[0] == 's', "dest[0] = %d\n", dest[0]);
+    ok(dest[1] == 'a', "dest[1] = %d\n", dest[1]);
+    ok(errno == 0xdeadbeef, "errno = %d\n", errno);
+
+    ret = strxfrm(dest, "", 5);
+    ok(ret == 0, "ret = %d\n", (int)ret);
+    ok(!dest[0], "dest[0] = %d\n", dest[0]);
+
+    if(!setlocale(LC_ALL, "polish")) {
+        win_skip("stxfrm tests\n");
+        return;
+    }
+
+    ret = strxfrm(NULL, "src", 0);
+    ok(ret < sizeof(dest)-1, "ret = %d\n", (int)ret);
+    dest[0] = 'a';
+    ret = strxfrm(dest, "src", 0);
+    ok(ret < sizeof(dest)-1, "ret = %d\n", (int)ret);
+    ok(dest[0] == 'a', "dest[0] = %d\n", dest[0]);
+
+    ret = strxfrm(dest, "src", ret+1);
+    ok(ret < sizeof(dest)-1, "ret = %d\n", (int)ret);
+    ok(dest[0], "dest[0] = 0\n");
+
+    errno = 0xdeadbeef;
+    dest[0] = 'a';
+    ret = strxfrm(dest, "src", 5);
+    ok(ret>5 && ret<sizeof(dest)-1, "ret = %d\n", (int)ret);
+    ok(!dest[0] || broken(!p__atodbl_l && dest[0]=='a'), "dest[0] = %d\n", dest[0]);
+
+    setlocale(LC_ALL, "C");
+}
+
+static void test__strnset_s(void)
+{
+    char buf[5] = {0};
+    int r;
+
+    if(!p__strnset_s) {
+        win_skip("_strnset_s not available\n");
+        return;
+    }
+
+    r = p__strnset_s(NULL, 0, 'a', 0);
+    ok(r == 0, "r = %d\n", r);
+
+    buf[0] = buf[1] = buf[2] = 'b';
+    r = p__strnset_s(buf, sizeof(buf), 'a', 2);
+    ok(r == 0, "r = %d\n", r);
+    ok(!strcmp(buf, "aab"), "buf = %s\n", buf);
+
+    r = p__strnset_s(buf, 0, 'a', 0);
+    ok(r == EINVAL, "r = %d\n", r);
+
+    r = p__strnset_s(NULL, 0, 'a', 1);
+    ok(r == EINVAL, "r = %d\n", r);
+
+    buf[3] = 'b';
+    r = p__strnset_s(buf, sizeof(buf)-1, 'c', 2);
+    ok(r == EINVAL, "r = %d\n", r);
+    ok(!buf[0] && buf[1]=='c' && buf[2]=='b', "buf = %s\n", buf);
+}
+
 START_TEST(string)
 {
     char mem[100];
@@ -2690,6 +2769,7 @@ START_TEST(string)
     pstrcat_s = (void *)GetProcAddress( hMsvcrt,"strcat_s" );
     p_mbsnbcat_s = (void *)GetProcAddress( hMsvcrt,"_mbsnbcat_s" );
     p_mbsnbcpy_s = (void *)GetProcAddress( hMsvcrt,"_mbsnbcpy_s" );
+    p__mbscpy_s = (void *)GetProcAddress( hMsvcrt,"_mbscpy_s" );
     p_wcscpy_s = (void *)GetProcAddress( hMsvcrt,"wcscpy_s" );
     p_wcsncpy_s = (void *)GetProcAddress( hMsvcrt,"wcsncpy_s" );
     p_wcsncat_s = (void *)GetProcAddress( hMsvcrt,"wcsncat_s" );
@@ -2706,7 +2786,6 @@ START_TEST(string)
     p_itoa_s = (void *)GetProcAddress(hMsvcrt, "_itoa_s");
     p_strlwr_s = (void *)GetProcAddress(hMsvcrt, "_strlwr_s");
     p_ultoa_s = (void *)GetProcAddress(hMsvcrt, "_ultoa_s");
-    p_set_invalid_parameter_handler = (void *) GetProcAddress(hMsvcrt, "_set_invalid_parameter_handler");
     p_wcslwr_s = (void*)GetProcAddress(hMsvcrt, "_wcslwr_s");
     p_mbsupr_s = (void*)GetProcAddress(hMsvcrt, "_mbsupr_s");
     p_mbslwr_s = (void*)GetProcAddress(hMsvcrt, "_mbslwr_s");
@@ -2717,6 +2796,7 @@ START_TEST(string)
     p_mbrtowc = (void*)GetProcAddress(hMsvcrt, "mbrtowc");
     p_mbsrtowcs = (void*)GetProcAddress(hMsvcrt, "mbsrtowcs");
     p__atodbl_l = (void*)GetProcAddress(hMsvcrt, "_atodbl_l");
+    p__strnset_s = (void*)GetProcAddress(hMsvcrt, "_strnset_s");
 
     /* MSVCRT memcpy behaves like memmove for overlapping moves,
        MFC42 CString::Insert seems to rely on that behaviour */
@@ -2738,6 +2818,7 @@ START_TEST(string)
     test_memmove_s();
     test_strcat_s();
     test__mbsnbcpy_s();
+    test__mbscpy_s();
     test_mbcjisjms();
     test_mbcjmsjis();
     test_mbbtombc();
@@ -2768,4 +2849,6 @@ START_TEST(string)
     test__wcstoi64();
     test_atoi();
     test_strncpy();
+    test_strxfrm();
+    test__strnset_s();
 }
index 71e58ba..995ece2 100644 (file)
@@ -47,6 +47,7 @@ static errno_t    (__cdecl *p_localtime64_s)(struct tm*, __time64_t*);
 static int*       (__cdecl *p__daylight)(void);
 static int*       (__cdecl *p___p__daylight)(void);
 static long*      (__cdecl *p___p__dstbias)(void);
+static long*      (__cdecl *p__dstbias)(void);
 static long*      (__cdecl *p___p__timezone)(void);
 static size_t     (__cdecl *p_strftime)(char *, size_t, const char *, const struct tm *);
 static size_t     (__cdecl *p_wcsftime)(wchar_t *, size_t, const wchar_t *, const struct tm *);
@@ -67,6 +68,7 @@ static void init(void)
     p__daylight = (void*)GetProcAddress(hmod, "__daylight");
     p___p__daylight = (void*)GetProcAddress(hmod, "__p__daylight");
     p___p__dstbias = (void*)GetProcAddress(hmod, "__p__dstbias");
+    p__dstbias = (void*)GetProcAddress(hmod, "__dstbias");
     p___p__timezone = (void*)GetProcAddress(hmod, "__p__timezone");
     p_strftime = (void*)GetProcAddress(hmod, "strftime");
     p_wcsftime = (void*)GetProcAddress(hmod, "wcsftime");
@@ -821,6 +823,15 @@ static void test__tzset(void)
         return;
     }
 
+    if (p__dstbias) {
+        ret = *p__dstbias();
+        ok(ret == -3600, "*__dstbias() = %d\n", ret);
+        ret = *p___p__dstbias();
+        ok(ret == -3600, "*__p__dstbias() = %d\n", ret);
+    }
+    else
+        win_skip("__dstbias() is not available.\n");
+
     _snprintf(TZ_env,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
 
     ret = *p___p__daylight();