1 /*
2  * Unit test suite for string functions.
3  *
4  * Copyright 2004 Uwe Bonnes
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 <string.h>
23 #include <mbstring.h>
24 #include <wchar.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <mbctype.h>
28 #include <locale.h>
29 #include <errno.h>
30 #include <limits.h>
31 #include <math.h>
32 
33 /* make it use a definition from string.h */
34 #undef strncpy
35 #include "winbase.h"
36 #include "winnls.h"
37 
38 static char *buf_to_string(const unsigned char *bin, int len, int nr)
39 {
40     static char buf[2][1024];
41     char *w = buf[nr];
42     int i;
43 
44     for (i = 0; i < len; i++)
45     {
46         sprintf(w, "%02x ", (unsigned char)bin[i]);
47         w += strlen(w);
48     }
49     return buf[nr];
50 }
51 
52 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
53 #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)); }
54 
55 static void* (__cdecl *pmemcpy)(void *, const void *, size_t n);
56 static int (__cdecl *p_memcpy_s)(void *, size_t, const void *, size_t);
57 static int (__cdecl *p_memmove_s)(void *, size_t, const void *, size_t);
58 static int* (__cdecl *pmemcmp)(void *, const void *, size_t n);
59 static int (__cdecl *p_strcpy)(char *dst, const char *src);
60 static int (__cdecl *pstrcpy_s)(char *dst, size_t len, const char *src);
61 static int (__cdecl *pstrcat_s)(char *dst, size_t len, const char *src);
62 static int (__cdecl *p_mbscat_s)(unsigned char *dst, size_t size, const unsigned char *src);
63 static int (__cdecl *p_mbsnbcat_s)(unsigned char *dst, size_t size, const unsigned char *src, size_t count);
64 static int (__cdecl *p_mbsnbcpy_s)(unsigned char * dst, size_t size, const unsigned char * src, size_t count);
65 static int (__cdecl *p__mbscpy_s)(unsigned char*, size_t, const unsigned char*);
66 static int (__cdecl *p_wcscpy_s)(wchar_t *wcDest, size_t size, const wchar_t *wcSrc);
67 static int (__cdecl *p_wcsncpy_s)(wchar_t *wcDest, size_t size, const wchar_t *wcSrc, size_t count);
68 static int (__cdecl *p_wcsncat_s)(wchar_t *dst, size_t elem, const wchar_t *src, size_t count);
69 static int (__cdecl *p_wcsupr_s)(wchar_t *str, size_t size);
70 static size_t (__cdecl *p_strnlen)(const char *, size_t);
71 static __int64 (__cdecl *p_strtoi64)(const char *, char **, int);
72 static unsigned __int64 (__cdecl *p_strtoui64)(const char *, char **, int);
73 static __int64 (__cdecl *p_wcstoi64)(const wchar_t *, wchar_t **, int);
74 static unsigned __int64 (__cdecl *p_wcstoui64)(const wchar_t *, wchar_t **, int);
75 static int (__cdecl *pwcstombs_s)(size_t*,char*,size_t,const wchar_t*,size_t);
76 static int (__cdecl *pmbstowcs_s)(size_t*,wchar_t*,size_t,const char*,size_t);
77 static size_t (__cdecl *p_mbsrtowcs)(wchar_t*, const char**, size_t, mbstate_t*);
78 static int (__cdecl *p_mbsrtowcs_s)(size_t*,wchar_t*,size_t,const char**,size_t,mbstate_t*);
79 static size_t (__cdecl *pwcsrtombs)(char*, const wchar_t**, size_t, int*);
80 static errno_t (__cdecl *p_gcvt_s)(char*,size_t,double,int);
81 static errno_t (__cdecl *p_itoa_s)(int,char*,size_t,int);
82 static errno_t (__cdecl *p_strlwr_s)(char*,size_t);
83 static errno_t (__cdecl *p_ultoa_s)(__msvcrt_ulong,char*,size_t,int);
84 static int *p__mb_cur_max;
85 static unsigned char *p_mbctype;
86 static int (__cdecl *p_wcslwr_s)(wchar_t*,size_t);
87 static errno_t (__cdecl *p_mbsupr_s)(unsigned char *str, size_t numberOfElements);
88 static errno_t (__cdecl *p_mbslwr_s)(unsigned char *str, size_t numberOfElements);
89 static int (__cdecl *p_wctob)(wint_t);
90 static size_t (__cdecl *p_wcrtomb)(char*, wchar_t, mbstate_t*);
91 static int (__cdecl *p_wcrtomb_s)(size_t*, char*, size_t, wchar_t, mbstate_t*);
92 static int (__cdecl *p_tolower)(int);
93 static int (__cdecl *p_towlower)(wint_t);
94 static int (__cdecl *p__towlower_l)(wint_t, _locale_t);
95 static int (__cdecl *p_towupper)(wint_t);
96 static int (__cdecl *p__towupper_l)(wint_t, _locale_t);
97 static _locale_t(__cdecl *p__create_locale)(int, const char*);
98 static void(__cdecl *p__free_locale)(_locale_t);
99 static size_t (__cdecl *p_mbrlen)(const char*, size_t, mbstate_t*);
100 static size_t (__cdecl *p_mbrtowc)(wchar_t*, const char*, size_t, mbstate_t*);
101 static int (__cdecl *p__atodbl_l)(_CRT_DOUBLE*,char*,_locale_t);
102 static double (__cdecl *p__atof_l)(const char*,_locale_t);
103 static double (__cdecl *p__strtod_l)(const char *,char**,_locale_t);
104 static int (__cdecl *p__strnset_s)(char*,size_t,int,size_t);
105 static int (__cdecl *p__wcsnset_s)(wchar_t*,size_t,wchar_t,size_t);
106 static int (__cdecl *p__wcsset_s)(wchar_t*,size_t,wchar_t);
107 static size_t (__cdecl *p__mbsnlen)(const unsigned char*, size_t);
108 static int (__cdecl *p__mbccpy_s)(unsigned char*, size_t, int*, const unsigned char*);
109 static int (__cdecl *p__memicmp)(const char*, const char*, size_t);
110 static int (__cdecl *p__memicmp_l)(const char*, const char*, size_t, _locale_t);
111 static size_t (__cdecl *p___strncnt)(const char*, size_t);
112 
113 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y)
114 #define SET(x,y) SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y)
115 
116 static HMODULE hMsvcrt;
117 
118 static void test_swab( void ) {
119     char original[]  = "BADCFEHGJILKNMPORQTSVUXWZY@#";
120     char expected1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ@#";
121     char expected2[] = "ABCDEFGHIJKLMNOPQRSTUVWX$";
122     char expected3[] = "$";
123 
124     char from[30];
125     char to[30];
126 
127     int testsize;
128 
129     /* Test 1 - normal even case */
130     memset(to,'$', sizeof(to));
131     memset(from,'@', sizeof(from));
132     testsize = 26;
133     memcpy(from, original, testsize);
134     _swab( from, to, testsize );
135     ok(memcmp(to,expected1,testsize) == 0, "Testing even size %d returned '%*.*s'\n", testsize, testsize, testsize, to);
136 
137     /* Test 2 - uneven case  */
138     memset(to,'$', sizeof(to));
139     memset(from,'@', sizeof(from));
140     testsize = 25;
141     memcpy(from, original, testsize);
142     _swab( from, to, testsize );
143     ok(memcmp(to,expected2,testsize) == 0, "Testing odd size %d returned '%*.*s'\n", testsize, testsize, testsize, to);
144 
145     /* Test 3 - from = to */
146     memset(to,'$', sizeof(to));
147     memset(from,'@', sizeof(from));
148     testsize = 26;
149     memcpy(to, original, testsize);
150     _swab( to, to, testsize );
151     ok(memcmp(to,expected1,testsize) == 0, "Testing overlapped size %d returned '%*.*s'\n", testsize, testsize, testsize, to);
152 
153     /* Test 4 - 1 bytes */
154     memset(to,'$', sizeof(to));
155     memset(from,'@', sizeof(from));
156     testsize = 1;
157     memcpy(from, original, testsize);
158     _swab( from, to, testsize );
159     ok(memcmp(to,expected3,testsize) == 0, "Testing small size %d returned '%*.*s'\n", testsize, testsize, testsize, to);
160 }
161 
162 #if 0      /* use this to generate more tests */
163 
164 static void test_codepage(int cp)
165 {
166     int i;
167     int prev;
168     int count = 1;
169 
170     ok(_setmbcp(cp) == 0, "Couldn't set mbcp\n");
171 
172     prev = p_mbctype[0];
173     printf("static int result_cp_%d_mbctype[] = { ", cp);
174     for (i = 1; i < 257; i++)
175     {
176         if (p_mbctype[i] != prev)
177         {
178             printf("0x%x,%d, ", prev, count);
179             prev = p_mbctype[i];
180             count = 1;
181         }
182         else
183             count++;
184     }
185     printf("0x%x,%d };\n", prev, count);
186 }
187 
188 #else
189 
190 /* RLE-encoded mbctype tables for given codepages */
191 static int result_cp_932_mbctype[] = { 0x0,65, 0x8,1, 0x18,26, 0x8,6, 0x28,26, 0x8,4,
192   0x0,1, 0x8,1, 0xc,31, 0x8,1, 0xa,5, 0x9,58, 0xc,29, 0,3 };
193 static int result_cp_936_mbctype[] = { 0x0,65, 0x8,1, 0x18,26, 0x8,6, 0x28,26, 0x8,6,
194   0xc,126, 0,1 };
195 static int result_cp_949_mbctype[] = { 0x0,66, 0x18,26, 0x8,6, 0x28,26, 0x8,6, 0xc,126,
196   0,1 };
197 static int result_cp_950_mbctype[] = { 0x0,65, 0x8,1, 0x18,26, 0x8,6, 0x28,26, 0x8,4,
198   0x0,2, 0x4,32, 0xc,94, 0,1 };
199 
200 static void test_cp_table(int cp, int *result)
201 {
202     int i;
203     int count = 0;
204     int curr = 0;
205     _setmbcp(cp);
206     for (i = 0; i < 256; i++)
207     {
208         if (count == 0)
209         {
210             curr = result[0];
211             count = result[1];
212             result += 2;
213         }
214         ok(p_mbctype[i] == curr, "CP%d: Mismatch in ctype for character %d - %d instead of %d\n", cp, i-1, p_mbctype[i], curr);
215         count--;
216     }
217 }
218 
219 #define test_codepage(num) test_cp_table(num, result_cp_##num##_mbctype);
220 
221 #endif
222 
223 static void test_mbcp(void)
224 {
225     int mb_orig_max = *p__mb_cur_max;
226     int curr_mbcp = _getmbcp();
227     unsigned char *mbstring = (unsigned char *)"\xb0\xb1\xb2 \xb3\xb4 \xb5"; /* incorrect string */
228     unsigned char *mbstring2 = (unsigned char *)"\xb0\xb1\xb2\xb3Q\xb4\xb5"; /* correct string */
229     unsigned char *mbsonlylead = (unsigned char *)"\xb0\0\xb1\xb2 \xb3";
230     unsigned char buf[16];
231     int step;
232     CPINFO cp_info;
233 
234     /* _mbtype tests */
235 
236     /* An SBCS codepage test. The ctype of characters on e.g. CP1252 or CP1250 differs slightly
237      * between versions of Windows. Also Windows 9x seems to ignore the codepage and always uses
238      * CP1252 (or the ACP?) so we test only a few ASCII characters */
239     _setmbcp(1252);
240     expect_eq(p_mbctype[10], 0, char, "%x");
241     expect_eq(p_mbctype[50], 0, char, "%x");
242     expect_eq(p_mbctype[66], _SBUP, char, "%x");
243     expect_eq(p_mbctype[100], _SBLOW, char, "%x");
244     expect_eq(p_mbctype[128], 0, char, "%x");
245     _setmbcp(1250);
246     expect_eq(p_mbctype[10], 0, char, "%x");
247     expect_eq(p_mbctype[50], 0, char, "%x");
248     expect_eq(p_mbctype[66], _SBUP, char, "%x");
249     expect_eq(p_mbctype[100], _SBLOW, char, "%x");
250     expect_eq(p_mbctype[128], 0, char, "%x");
251 
252     /* double byte code pages */
253     test_codepage(932);
254     test_codepage(936);
255     test_codepage(949);
256     test_codepage(950);
257 
258     _setmbcp(936);
259     ok(*p__mb_cur_max == mb_orig_max, "__mb_cur_max shouldn't be updated (is %d != %d)\n", *p__mb_cur_max, mb_orig_max);
260     ok(_ismbblead('\354'), "\354 should be a lead byte\n");
261     ok(_ismbblead(' ') == FALSE, "' ' should not be a lead byte\n");
262     ok(_ismbblead(0x1234b0), "0x1234b0 should not be a lead byte\n");
263     ok(_ismbblead(0x123420) == FALSE, "0x123420 should not be a lead byte\n");
264     ok(_ismbbtrail('\xb0'), "\xa0 should be a trail byte\n");
265     ok(_ismbbtrail(' ') == FALSE, "' ' should not be a trail byte\n");
266 
267     /* _ismbslead */
268     expect_eq(_ismbslead(mbstring, &mbstring[0]), -1, int, "%d");
269     expect_eq(_ismbslead(mbstring, &mbstring[1]), FALSE, int, "%d");
270     expect_eq(_ismbslead(mbstring, &mbstring[2]), -1, int, "%d");
271     expect_eq(_ismbslead(mbstring, &mbstring[3]), FALSE, int, "%d");
272     expect_eq(_ismbslead(mbstring, &mbstring[4]), -1, int, "%d");
273     expect_eq(_ismbslead(mbstring, &mbstring[5]), FALSE, int, "%d");
274     expect_eq(_ismbslead(mbstring, &mbstring[6]), FALSE, int, "%d");
275     expect_eq(_ismbslead(mbstring, &mbstring[7]), -1, int, "%d");
276     expect_eq(_ismbslead(mbstring, &mbstring[8]), FALSE, int, "%d");
277 
278     expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[0]), -1, int, "%d");
279     expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[1]), FALSE, int, "%d");
280     expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[2]), FALSE, int, "%d");
281     expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[5]), FALSE, int, "%d");
282 
283     /* _ismbstrail */
284     expect_eq(_ismbstrail(mbstring, &mbstring[0]), FALSE, int, "%d");
285     expect_eq(_ismbstrail(mbstring, &mbstring[1]), -1, int, "%d");
286     expect_eq(_ismbstrail(mbstring, &mbstring[2]), FALSE, int, "%d");
287     expect_eq(_ismbstrail(mbstring, &mbstring[3]), -1, int, "%d");
288     expect_eq(_ismbstrail(mbstring, &mbstring[4]), FALSE, int, "%d");
289     expect_eq(_ismbstrail(mbstring, &mbstring[5]), -1, int, "%d");
290     expect_eq(_ismbstrail(mbstring, &mbstring[6]), FALSE, int, "%d");
291     expect_eq(_ismbstrail(mbstring, &mbstring[7]), FALSE, int, "%d");
292     expect_eq(_ismbstrail(mbstring, &mbstring[8]), -1, int, "%d");
293 
294     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[0]), FALSE, int, "%d");
295     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[1]), -1, int, "%d");
296     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[2]), FALSE, int, "%d");
297     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[3]), FALSE, int, "%d");
298     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[4]), FALSE, int, "%d");
299     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[5]), FALSE, int, "%d");
300 
301     /* _mbsbtype */
302     expect_eq(_mbsbtype(mbstring, 0), _MBC_LEAD, int, "%d");
303     expect_eq(_mbsbtype(mbstring, 1), _MBC_TRAIL, int, "%d");
304     expect_eq(_mbsbtype(mbstring, 2), _MBC_LEAD, int, "%d");
305     expect_eq(_mbsbtype(mbstring, 3), _MBC_ILLEGAL, int, "%d");
306     expect_eq(_mbsbtype(mbstring, 4), _MBC_LEAD, int, "%d");
307     expect_eq(_mbsbtype(mbstring, 5), _MBC_TRAIL, int, "%d");
308     expect_eq(_mbsbtype(mbstring, 6), _MBC_SINGLE, int, "%d");
309     expect_eq(_mbsbtype(mbstring, 7), _MBC_LEAD, int, "%d");
310     expect_eq(_mbsbtype(mbstring, 8), _MBC_ILLEGAL, int, "%d");
311 
312     expect_eq(_mbsbtype(mbsonlylead, 0), _MBC_LEAD, int, "%d");
313     expect_eq(_mbsbtype(mbsonlylead, 1), _MBC_ILLEGAL, int, "%d");
314     expect_eq(_mbsbtype(mbsonlylead, 2), _MBC_ILLEGAL, int, "%d");
315     expect_eq(_mbsbtype(mbsonlylead, 3), _MBC_ILLEGAL, int, "%d");
316     expect_eq(_mbsbtype(mbsonlylead, 4), _MBC_ILLEGAL, int, "%d");
317     expect_eq(_mbsbtype(mbsonlylead, 5), _MBC_ILLEGAL, int, "%d");
318 
319     /* _mbsnextc */
320     expect_eq(_mbsnextc(mbstring), 0xb0b1, int, "%x");
321     expect_eq(_mbsnextc(&mbstring[2]), 0xb220, int, "%x");  /* lead + invalid tail */
322     expect_eq(_mbsnextc(&mbstring[3]), 0x20, int, "%x");    /* single char */
323 
324     /* _mbclen/_mbslen */
325     expect_eq(_mbclen(mbstring), 2, int, "%d");
326     expect_eq(_mbclen(&mbstring[2]), 2, int, "%d");
327     expect_eq(_mbclen(&mbstring[3]), 1, int, "%d");
328     expect_eq(_mbslen(mbstring2), 4, int, "%d");
329     expect_eq(_mbslen(mbsonlylead), 0, int, "%d");          /* lead + NUL not counted as character */
330     expect_eq(_mbslen(mbstring), 4, int, "%d");             /* lead + invalid trail counted */
331 
332     if(!p__mbsnlen) {
333         win_skip("_mbsnlen tests\n");
334     }else {
335         expect_eq(p__mbsnlen(mbstring, 8), 8, int, "%d");
336         expect_eq(p__mbsnlen(mbstring, 9), 4, int, "%d");
337         expect_eq(p__mbsnlen(mbstring, 10), 4, int, "%d");
338         expect_eq(p__mbsnlen(mbsonlylead, 0), 0, int, "%d");
339         expect_eq(p__mbsnlen(mbsonlylead, 1), 1, int, "%d");
340         expect_eq(p__mbsnlen(mbsonlylead, 2), 0, int, "%d");
341         expect_eq(p__mbsnlen(mbstring2, 7), 7, int, "%d");
342         expect_eq(p__mbsnlen(mbstring2, 8), 4, int, "%d");
343         expect_eq(p__mbsnlen(mbstring2, 9), 4, int, "%d");
344     }
345 
346     /* mbrlen */
347     if(!setlocale(LC_ALL, ".936") || !p_mbrlen) {
348         win_skip("mbrlen tests\n");
349     }else {
350         mbstate_t state = 0;
351         expect_eq(p_mbrlen((const char*)mbstring, 2, NULL), 2, int, "%d");
352         expect_eq(p_mbrlen((const char*)&mbstring[2], 2, NULL), 2, int, "%d");
353         expect_eq(p_mbrlen((const char*)&mbstring[3], 2, NULL), 1, int, "%d");
354         expect_eq(p_mbrlen((const char*)mbstring, 1, NULL), -2, int, "%d");
355         expect_eq(p_mbrlen((const char*)mbstring, 1, &state), -2, int, "%d");
356         ok(state == mbstring[0], "incorrect state value (%x)\n", state);
357         expect_eq(p_mbrlen((const char*)&mbstring[1], 1, &state), 2, int, "%d");
358     }
359 
360     /* mbrtowc */
361     if(!setlocale(LC_ALL, ".936") || !p_mbrtowc) {
362         win_skip("mbrtowc tests\n");
363     }else {
364         mbstate_t state = 0;
365         wchar_t dst;
366         expect_eq(p_mbrtowc(&dst, (const char*)mbstring, 2, NULL), 2, int, "%d");
367         ok(dst == 0x6c28, "dst = %x, expected 0x6c28\n", dst);
368         expect_eq(p_mbrtowc(&dst, (const char*)mbstring+2, 2, NULL), 2, int, "%d");
369         ok(dst == 0x3f, "dst = %x, expected 0x3f\n", dst);
370         expect_eq(p_mbrtowc(&dst, (const char*)mbstring+3, 2, NULL), 1, int, "%d");
371         ok(dst == 0x20, "dst = %x, expected 0x20\n", dst);
372         expect_eq(p_mbrtowc(&dst, (const char*)mbstring, 1, NULL), -2, int, "%d");
373         ok(dst == 0, "dst = %x, expected 0\n", dst);
374         expect_eq(p_mbrtowc(&dst, (const char*)mbstring, 1, &state), -2, int, "%d");
375         ok(dst == 0, "dst = %x, expected 0\n", dst);
376         ok(state == mbstring[0], "incorrect state value (%x)\n", state);
377         expect_eq(p_mbrtowc(&dst, (const char*)mbstring+1, 1, &state), 2, int, "%d");
378         ok(dst == 0x6c28, "dst = %x, expected 0x6c28\n", dst);
379         ok(state == 0, "incorrect state value (%x)\n", state);
380     }
381     setlocale(LC_ALL, "C");
382 
383     /* _mbccpy/_mbsncpy */
384     memset(buf, 0xff, sizeof(buf));
385     _mbccpy(buf, mbstring);
386     expect_bin(buf, "\xb0\xb1\xff", 3);
387 
388     if(!p__mbccpy_s) {
389         win_skip("_mbccpy_s tests\n");
390     }else {
391         int err, copied;
392 
393         memset(buf, 0xff, sizeof(buf));
394         copied = -1;
395         err = p__mbccpy_s(buf, 0, &copied, mbstring);
396         ok(err == EINVAL, "_mbccpy_s returned %d\n", err);
397         ok(!copied, "copied = %d\n", copied);
398         ok(buf[0] == 0xff, "buf[0] = %x\n", buf[0]);
399 
400         memset(buf, 0xff, sizeof(buf));
401         copied = -1;
402         err = p__mbccpy_s(buf, 1, &copied, mbstring);
403         ok(err == ERANGE, "_mbccpy_s returned %d\n", err);
404         ok(!copied, "copied = %d\n", copied);
405         ok(!buf[0], "buf[0] = %x\n", buf[0]);
406 
407         memset(buf, 0xff, sizeof(buf));
408         copied = -1;
409         err = p__mbccpy_s(buf, 2, &copied, mbstring);
410         ok(!err, "_mbccpy_s returned %d\n", err);
411         ok(copied == 2, "copied = %d\n", copied);
412         expect_bin(buf, "\xb0\xb1\xff", 3);
413 
414         memset(buf, 0xff, sizeof(buf));
415         copied = -1;
416         err = p__mbccpy_s(buf, 2, &copied, (unsigned char *)"\xb0");
417         ok(err == EILSEQ, "_mbccpy_s returned %d\n", err);
418         ok(copied == 1, "copied = %d\n", copied);
419         expect_bin(buf, "\x00\xff", 2);
420     }
421 
422     memset(buf, 0xff, sizeof(buf));
423     _mbsncpy(buf, mbstring, 1);
424     expect_bin(buf, "\xb0\xb1\xff", 3);
425     memset(buf, 0xff, sizeof(buf));
426     _mbsncpy(buf, mbstring, 2);
427     expect_bin(buf, "\xb0\xb1\xb2 \xff", 5);
428     memset(buf, 0xff, sizeof(buf));
429     _mbsncpy(buf, mbstring, 3);
430     expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4\xff", 7);
431     memset(buf, 0xff, sizeof(buf));
432     _mbsncpy(buf, mbstring, 4);
433     expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4 \xff", 8);
434     memset(buf, 0xff, sizeof(buf));
435     _mbsncpy(buf, mbstring, 5);
436     expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4 \0\0\xff", 10);
437     memset(buf, 0xff, sizeof(buf));
438     _mbsncpy(buf, mbsonlylead, 6);
439     expect_bin(buf, "\0\0\0\0\0\0\0\xff", 8);
440 
441     memset(buf, 0xff, sizeof(buf));
442     _mbsnbcpy(buf, mbstring2, 2);
443     expect_bin(buf, "\xb0\xb1\xff", 3);
444     _mbsnbcpy(buf, mbstring2, 3);
445     expect_bin(buf, "\xb0\xb1\0\xff", 4);
446     _mbsnbcpy(buf, mbstring2, 4);
447     expect_bin(buf, "\xb0\xb1\xb2\xb3\xff", 5);
448     memset(buf, 0xff, sizeof(buf));
449     _mbsnbcpy(buf, mbsonlylead, 5);
450     expect_bin(buf, "\0\0\0\0\0\xff", 6);
451 
452     /* _mbsinc/mbsdec */
453     step = _mbsinc(mbstring) - mbstring;
454     ok(step == 2, "_mbsinc adds %d (exp. 2)\n", step);
455     step = _mbsinc(&mbstring[2]) - &mbstring[2];  /* lead + invalid tail */
456     ok(step == 2, "_mbsinc adds %d (exp. 2)\n", step);
457 
458     step = _mbsninc(mbsonlylead, 1) - mbsonlylead;
459     ok(step == 0, "_mbsninc adds %d (exp. 0)\n", step);
460     step = _mbsninc(mbsonlylead, 2) - mbsonlylead;  /* lead + NUL byte + lead + char */
461     ok(step == 0, "_mbsninc adds %d (exp. 0)\n", step);
462     step = _mbsninc(mbstring2, 0) - mbstring2;
463     ok(step == 0, "_mbsninc adds %d (exp. 2)\n", step);
464     step = _mbsninc(mbstring2, 1) - mbstring2;
465     ok(step == 2, "_mbsninc adds %d (exp. 2)\n", step);
466     step = _mbsninc(mbstring2, 2) - mbstring2;
467     ok(step == 4, "_mbsninc adds %d (exp. 4)\n", step);
468     step = _mbsninc(mbstring2, 3) - mbstring2;
469     ok(step == 5, "_mbsninc adds %d (exp. 5)\n", step);
470     step = _mbsninc(mbstring2, 4) - mbstring2;
471     ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step);
472     step = _mbsninc(mbstring2, 5) - mbstring2;
473     ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step);
474     step = _mbsninc(mbstring2, 17) - mbstring2;
475     ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step);
476 
477     /* functions that depend on locale codepage, not mbcp.
478      * we hope the current locale to be SBCS because setlocale(LC_ALL, ".1252") seems not to work yet
479      * (as of Wine 0.9.43)
480      */
481     GetCPInfo(GetACP(), &cp_info);
482     if (cp_info.MaxCharSize == 1)
483     {
484         expect_eq(mblen((char *)mbstring, 3), 1, int, "%x");
485         expect_eq(_mbstrlen((char *)mbstring2), 7, int, "%d");
486     }
487     else
488         skip("Current locale has double-byte charset - could lead to false positives\n");
489 
490     _setmbcp(1361);
491     expect_eq(_ismbblead(0x80), 0, int, "%d");
492     todo_wine {
493       expect_eq(_ismbblead(0x81), 1, int, "%d");
494       expect_eq(_ismbblead(0x83), 1, int, "%d");
495     }
496     expect_eq(_ismbblead(0x84), 1, int, "%d");
497     expect_eq(_ismbblead(0xd3), 1, int, "%d");
498     expect_eq(_ismbblead(0xd7), 0, int, "%d");
499     expect_eq(_ismbblead(0xd8), 1, int, "%d");
500     expect_eq(_ismbblead(0xd9), 1, int, "%d");
501 
502     expect_eq(_ismbbtrail(0x30), 0, int, "%d");
503     expect_eq(_ismbbtrail(0x31), 1, int, "%d");
504     expect_eq(_ismbbtrail(0x7e), 1, int, "%d");
505     expect_eq(_ismbbtrail(0x7f), 0, int, "%d");
506     expect_eq(_ismbbtrail(0x80), 0, int, "%d");
507     expect_eq(_ismbbtrail(0x81), 1, int, "%d");
508     expect_eq(_ismbbtrail(0xfe), 1, int, "%d");
509     expect_eq(_ismbbtrail(0xff), 0, int, "%d");
510 
511     _setmbcp(curr_mbcp);
512 }
513 
514 static void test_mbsspn( void)
515 {
516     unsigned char str1[]="cabernet";
517     unsigned char str2[]="shiraz";
518     unsigned char set[]="abc";
519     unsigned char empty[]="";
520     unsigned char mbstr[]=" 2019\x94\x4e" "6\x8c\x8e" "29\x93\xfa";
521     unsigned char mbset1[]="0123456789 \x94\x4e";
522     unsigned char mbset2[]=" \x94\x4e\x8c\x8e";
523     unsigned char mbset3[]="\x8e";
524     int ret, cp = _getmbcp();
525 
526     ret=_mbsspn( str1, set);
527     ok( ret==3, "_mbsspn returns %d should be 3\n", ret);
528     ret=_mbsspn( str2, set);
529     ok( ret==0, "_mbsspn returns %d should be 0\n", ret);
530     ret=_mbsspn( str1, empty);
531     ok( ret==0, "_mbsspn returns %d should be 0\n", ret);
532 
533     _setmbcp( 932);
534     ret=_mbsspn( mbstr, mbset1);
535     ok( ret==8, "_mbsspn returns %d should be 8\n", ret);
536     ret=_mbsspn( mbstr, mbset2);
537     ok( ret==1, "_mbsspn returns %d should be 1\n", ret);
538     ret=_mbsspn( mbstr+8, mbset1);
539     ok( ret==0, "_mbsspn returns %d should be 0\n", ret);
540     ret=_mbsspn( mbstr+8, mbset2);
541     ok( ret==2, "_mbsspn returns %d should be 2\n", ret);
542     ret=_mbsspn( mbstr, mbset3);
543     ok( ret==14, "_mbsspn returns %d should be 14\n", ret);
544 
545     _setmbcp( cp);
546 }
547 
548 static void test_mbsspnp( void)
549 {
550     unsigned char str1[]="cabernet";
551     unsigned char str2[]="shiraz";
552     unsigned char set[]="abc";
553     unsigned char empty[]="";
554     unsigned char full[]="abcenrt";
555     unsigned char mbstr[]=" 2019\x94\x4e" "6\x8c\x8e" "29\x93\xfa";
556     unsigned char mbset1[]="0123456789 \x94\x4e";
557     unsigned char mbset2[]=" \x94\x4e\x8c\x8e";
558     unsigned char* ret;
559     int cp = _getmbcp();
560 
561     ret=_mbsspnp( str1, set);
562     ok( ret[0]=='e', "_mbsspnp returns %c should be e\n", ret[0]);
563     ret=_mbsspnp( str2, set);
564     ok( ret[0]=='s', "_mbsspnp returns %c should be s\n", ret[0]);
565     ret=_mbsspnp( str1, empty);
566     ok( ret[0]=='c', "_mbsspnp returns %c should be c\n", ret[0]);
567     ret=_mbsspnp( str1, full);
568     ok( ret==NULL, "_mbsspnp returns %p should be NULL\n", ret);
569 
570     _setmbcp( 932);
571     ret=_mbsspnp( mbstr, mbset1);
572     ok( ret==mbstr+8, "_mbsspnp returns %p should be %p\n", ret, mbstr+8);
573     ret=_mbsspnp( mbstr, mbset2);
574     ok( ret==mbstr+1, "_mbsspnp returns %p should be %p\n", ret, mbstr+1);
575     ret=_mbsspnp( mbstr+8, mbset1);
576     ok( ret==mbstr+8, "_mbsspnp returns %p should be %p\n", ret, mbstr+8);
577     ret=_mbsspnp( mbstr+8, mbset2);
578     ok( ret==mbstr+10, "_mbsspnp returns %p should be %p\n", ret, mbstr+10);
579 
580     _setmbcp( cp);
581 }
582 
583 static void test_strdup(void)
584 {
585    char *str;
586    str = _strdup( 0 );
587    ok( str == 0, "strdup returns %s should be 0\n", str);
588    free( str );
589 }
590 
591 static void test_strcpy_s(void)
592 {
593     char dest[8];
594     const char small[] = "small";
595     const char big[] = "atoolongstringforthislittledestination";
596     int ret;
597 
598     if(!pstrcpy_s)
599     {
600         win_skip("strcpy_s not found\n");
601         return;
602     }
603 
604     memset(dest, 'X', sizeof(dest));
605     ret = pstrcpy_s(dest, sizeof(dest), small);
606     ok(ret == 0, "Copying a string into a big enough destination returned %d, expected 0\n", ret);
607     ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == 'l' &&
608        dest[4] == 'l' && dest[5] == '\0'&& dest[6] == 'X' && dest[7] == 'X',
609        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
610        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
611 
612     memset(dest, 'X', sizeof(dest));
613     ret = pstrcpy_s(dest, 0, big);
614     ok(ret == EINVAL, "Copying into a destination of size 0 returned %d, expected EINVAL\n", ret);
615     ok(dest[0] == 'X' && dest[1] == 'X' && dest[2] == 'X' && dest[3] == 'X' &&
616        dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
617        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
618        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
619     ret = pstrcpy_s(dest, 0, NULL);
620     ok(ret == EINVAL, "Copying into a destination of size 0 returned %d, expected EINVAL\n", ret);
621     ok(dest[0] == 'X' && dest[1] == 'X' && dest[2] == 'X' && dest[3] == 'X' &&
622        dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
623        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
624        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
625 
626     memset(dest, 'X', sizeof(dest));
627     ret = pstrcpy_s(dest, sizeof(dest), big);
628     ok(ret == ERANGE, "Copying a big string in a small location returned %d, expected ERANGE\n", ret);
629     ok(dest[0] == '\0'&& dest[1] == 't' && dest[2] == 'o' && dest[3] == 'o' &&
630        dest[4] == 'l' && dest[5] == 'o' && dest[6] == 'n' && dest[7] == 'g',
631        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
632        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
633 
634     memset(dest, 'X', sizeof(dest));
635     ret = pstrcpy_s(dest, sizeof(dest), NULL);
636     ok(ret == EINVAL, "Copying from a NULL source string returned %d, expected EINVAL\n", ret);
637     ok(dest[0] == '\0'&& dest[1] == 'X' && dest[2] == 'X' && dest[3] == 'X' &&
638        dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
639        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
640        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
641 
642     ret = pstrcpy_s(NULL, sizeof(dest), small);
643     ok(ret == EINVAL, "Copying a big string a NULL dest returned %d, expected EINVAL\n", ret);
644 
645     /* strcpy overlapping buffers test */
646     memset(dest, 'X', sizeof(dest));
647     memcpy(dest+1, small, sizeof(small));
648     p_strcpy(dest, dest+1);
649     ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == 'l' &&
650             dest[4] == 'l' && dest[5] == '\0' && dest[6] == '\0' && dest[7] == 'X',
651             "Unexpected return data from strcpy: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
652             dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
653 }
654 
655 #define okchars(dst, b0, b1, b2, b3, b4, b5, b6, b7) \
656     ok(dst[0] == b0 && dst[1] == b1 && dst[2] == b2 && dst[3] == b3 && \
657        dst[4] == b4 && dst[5] == b5 && dst[6] == b6 && dst[7] == b7, \
658        "Bad result: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",\
659        dst[0], dst[1], dst[2], dst[3], dst[4], dst[5], dst[6], dst[7])
660 
661 static void test_memcpy_s(void)
662 {
663     static char dest[8], buf[32];
664     static const char tiny[] = {'T',0,'I','N','Y',0};
665     static const char big[] = {'a','t','o','o','l','o','n','g','s','t','r','i','n','g',0};
666     int ret;
667     if (!p_memcpy_s) {
668         win_skip("memcpy_s not found\n");
669         return;
670     }
671 
672     /* Normal */
673     memset(dest, 'X', sizeof(dest));
674     ret = p_memcpy_s(dest, ARRAY_SIZE(dest), tiny, ARRAY_SIZE(tiny));
675     ok(ret == 0, "Copying a buffer into a big enough destination returned %d, expected 0\n", ret);
676     okchars(dest, tiny[0], tiny[1], tiny[2], tiny[3], tiny[4], tiny[5], 'X', 'X');
677 
678     /* Vary source size */
679     errno = 0xdeadbeef;
680     memset(dest, 'X', sizeof(dest));
681     ret = p_memcpy_s(dest, ARRAY_SIZE(dest), big, ARRAY_SIZE(big));
682     ok(ret == ERANGE, "Copying a big buffer to a small destination returned %d, expected ERANGE\n", ret);
683     ok(errno == ERANGE, "errno is %d, expected ERANGE\n", errno);
684     okchars(dest, 0, 0, 0, 0, 0, 0, 0, 0);
685 
686     /* Replace source with NULL */
687     errno = 0xdeadbeef;
688     memset(dest, 'X', sizeof(dest));
689     ret = p_memcpy_s(dest, ARRAY_SIZE(dest), NULL, ARRAY_SIZE(tiny));
690     ok(ret == EINVAL, "Copying a NULL source buffer returned %d, expected EINVAL\n", ret);
691     ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
692     okchars(dest, 0, 0, 0, 0, 0, 0, 0, 0);
693 
694     /* Vary dest size */
695     errno = 0xdeadbeef;
696     memset(dest, 'X', sizeof(dest));
697     ret = p_memcpy_s(dest, 0, tiny, ARRAY_SIZE(tiny));
698     ok(ret == ERANGE, "Copying into a destination of size 0 returned %d, expected ERANGE\n", ret);
699     ok(errno == ERANGE, "errno is %d, expected ERANGE\n", errno);
700     okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
701 
702     /* Replace dest with NULL */
703     errno = 0xdeadbeef;
704     ret = p_memcpy_s(NULL, ARRAY_SIZE(dest), tiny, ARRAY_SIZE(tiny));
705     ok(ret == EINVAL, "Copying a tiny buffer to a big NULL destination returned %d, expected EINVAL\n", ret);
706     ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
707 
708     /* Combinations */
709     errno = 0xdeadbeef;
710     memset(dest, 'X', sizeof(dest));
711     ret = p_memcpy_s(dest, 0, NULL, ARRAY_SIZE(tiny));
712     ok(ret == EINVAL, "Copying a NULL buffer into a destination of size 0 returned %d, expected EINVAL\n", ret);
713     ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
714     okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
715 
716     ret = p_memcpy_s(buf, ARRAY_SIZE(buf), big, ARRAY_SIZE(big));
717     ok(!ret, "memcpy_s returned %d\n", ret);
718     ok(!memcmp(buf, big, sizeof(big)), "unexpected buf\n");
719 
720     ret = p_memcpy_s(buf + 1, ARRAY_SIZE(buf) - 1, buf, ARRAY_SIZE(big));
721     ok(!ret, "memcpy_s returned %d\n", ret);
722     ok(!memcmp(buf + 1, big, sizeof(big)), "unexpected buf\n");
723 
724     ret = p_memcpy_s(buf, ARRAY_SIZE(buf), buf + 1, ARRAY_SIZE(big));
725     ok(!ret, "memcpy_s returned %d\n", ret);
726     ok(!memcmp(buf, big, sizeof(big)), "unexpected buf\n");
727 }
728 
729 static void test_memmove_s(void)
730 {
731     static char dest[8];
732     static const char tiny[] = {'T',0,'I','N','Y',0};
733     static const char big[] = {'a','t','o','o','l','o','n','g','s','t','r','i','n','g',0};
734     int ret;
735     if (!p_memmove_s) {
736         win_skip("memmove_s not found\n");
737         return;
738     }
739 
740     /* Normal */
741     memset(dest, 'X', sizeof(dest));
742     ret = p_memmove_s(dest, ARRAY_SIZE(dest), tiny, ARRAY_SIZE(tiny));
743     ok(ret == 0, "Moving a buffer into a big enough destination returned %d, expected 0\n", ret);
744     okchars(dest, tiny[0], tiny[1], tiny[2], tiny[3], tiny[4], tiny[5], 'X', 'X');
745 
746     /* Overlapping */
747     memcpy(dest, big, sizeof(dest));
748     ret = p_memmove_s(dest+1, ARRAY_SIZE(dest)-1, dest, ARRAY_SIZE(dest)-1);
749     ok(ret == 0, "Moving a buffer up one char returned %d, expected 0\n", ret);
750     okchars(dest, big[0], big[0], big[1], big[2], big[3], big[4], big[5], big[6]);
751 
752     /* Vary source size */
753     errno = 0xdeadbeef;
754     memset(dest, 'X', sizeof(dest));
755     ret = p_memmove_s(dest, ARRAY_SIZE(dest), big, ARRAY_SIZE(big));
756     ok(ret == ERANGE, "Moving a big buffer to a small destination returned %d, expected ERANGE\n", ret);
757     ok(errno == ERANGE, "errno is %d, expected ERANGE\n", errno);
758     okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
759 
760     /* Replace source with NULL */
761     errno = 0xdeadbeef;
762     memset(dest, 'X', sizeof(dest));
763     ret = p_memmove_s(dest, ARRAY_SIZE(dest), NULL, ARRAY_SIZE(tiny));
764     ok(ret == EINVAL, "Moving a NULL source buffer returned %d, expected EINVAL\n", ret);
765     ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
766     okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
767 
768     /* Vary dest size */
769     errno = 0xdeadbeef;
770     memset(dest, 'X', sizeof(dest));
771     ret = p_memmove_s(dest, 0, tiny, ARRAY_SIZE(tiny));
772     ok(ret == ERANGE, "Moving into a destination of size 0 returned %d, expected ERANGE\n", ret);
773     ok(errno == ERANGE, "errno is %d, expected ERANGE\n", errno);
774     okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
775 
776     /* Replace dest with NULL */
777     errno = 0xdeadbeef;
778     ret = p_memmove_s(NULL, ARRAY_SIZE(dest), tiny, ARRAY_SIZE(tiny));
779     ok(ret == EINVAL, "Moving a tiny buffer to a big NULL destination returned %d, expected EINVAL\n", ret);
780     ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
781 
782     /* Combinations */
783     errno = 0xdeadbeef;
784     memset(dest, 'X', sizeof(dest));
785     ret = p_memmove_s(dest, 0, NULL, ARRAY_SIZE(tiny));
786     ok(ret == EINVAL, "Moving a NULL buffer into a destination of size 0 returned %d, expected EINVAL\n", ret);
787     ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
788     okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
789 }
790 
791 static void test_strcat_s(void)
792 {
793     char dest[8];
794     const char *small = "sma";
795     int ret;
796 
797     if(!pstrcat_s)
798     {
799         win_skip("strcat_s not found\n");
800         return;
801     }
802 
803     memset(dest, 'X', sizeof(dest));
804     dest[0] = '\0';
805     ret = pstrcat_s(dest, sizeof(dest), small);
806     ok(ret == 0, "strcat_s: Copying a string into a big enough destination returned %d, expected 0\n", ret);
807     ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == '\0'&&
808        dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
809        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
810        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
811     ret = pstrcat_s(dest, sizeof(dest), small);
812     ok(ret == 0, "strcat_s: Attaching a string to a big enough destination returned %d, expected 0\n", ret);
813     ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == 's' &&
814        dest[4] == 'm' && dest[5] == 'a' && dest[6] == '\0'&& dest[7] == 'X',
815        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
816        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
817 
818     ret = pstrcat_s(dest, sizeof(dest), small);
819     ok(ret == ERANGE, "strcat_s: Attaching a string to a filled up destination returned %d, expected ERANGE\n", ret);
820     ok(dest[0] == '\0'&& dest[1] == 'm' && dest[2] == 'a' && dest[3] == 's' &&
821        dest[4] == 'm' && dest[5] == 'a' && dest[6] == 's' && dest[7] == 'm',
822        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
823        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
824 
825     memset(dest, 'X', sizeof(dest));
826     dest[0] = 'a';
827     dest[1] = '\0';
828 
829     ret = pstrcat_s(dest, 0, small);
830     ok(ret == EINVAL, "strcat_s: Source len = 0 returned %d, expected EINVAL\n", ret);
831     ok(dest[0] == 'a' && dest[1] == '\0'&& dest[2] == 'X' && dest[3] == 'X' &&
832        dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
833        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
834        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
835 
836     ret = pstrcat_s(dest, 0, NULL);
837     ok(ret == EINVAL, "strcat_s: len = 0 and src = NULL returned %d, expected EINVAL\n", ret);
838     ok(dest[0] == 'a' && dest[1] == '\0'&& dest[2] == 'X' && dest[3] == 'X' &&
839        dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
840        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
841        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
842 
843     ret = pstrcat_s(dest, sizeof(dest), NULL);
844     ok(ret == EINVAL, "strcat_s:  Sourcing from NULL returned %d, expected EINVAL\n", ret);
845     ok(dest[0] == '\0'&& dest[1] == '\0'&& dest[2] == 'X' && dest[3] == 'X' &&
846        dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
847        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
848        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
849 
850     ret = pstrcat_s(NULL, sizeof(dest), small);
851     ok(ret == EINVAL, "strcat_s: Writing to a NULL string returned %d, expected EINVAL\n", ret);
852 }
853 
854 static void test__mbscat_s(void)
855 {
856     unsigned char dst[8], src[4];
857     int err;
858     int prev_cp = _getmbcp();
859 
860     if(!p_mbscat_s)
861     {
862         win_skip("_mbscat_s not found\n");
863         return;
864     }
865 
866 
867     src[0] = dst[0] = 0;
868     err = p_mbscat_s(NULL, sizeof(dst), src);
869     ok(err == EINVAL, "_mbscat_s returned %d\n", err);
870 
871     err = p_mbscat_s(dst, sizeof(dst), NULL);
872     ok(err == EINVAL, "_mbscat_s returned %d\n", err);
873 
874     dst[0] = 'a';
875     err = p_mbscat_s(dst, 1, src);
876     ok(err == EINVAL, "_mbscat_s returned %d\n", err);
877 
878     memset(dst, 'a', sizeof(dst));
879     dst[6] = 0;
880     src[0] = 'b';
881     src[1] = 0;
882 
883     err = p_mbscat_s(dst, sizeof(dst), src);
884     ok(err == 0, "_mbscat_s returned %d\n", err);
885     ok(!memcmp(dst, "aaaaaab", 8), "dst = %s\n", dst);
886 
887     err = p_mbscat_s(dst, sizeof(dst), src);
888     ok(err == ERANGE, "_mbscat_s returned %d\n", err);
889     ok(!dst[0], "dst[0] = %c\n", dst[0]);
890     ok(dst[1] == 'a', "dst[1] = %c\n", dst[1]);
891 
892     _setmbcp(932);
893     /* test invalid str in dst */
894     dst[0] = 0x81;
895     dst[1] = 0x81;
896     dst[2] = 0x52;
897     dst[3] = 0;
898     src[0] = 'a';
899     src[1] = 0;
900     err = p_mbscat_s(dst, sizeof(dst), src);
901     ok(err == 0, "_mbscat_s returned %d\n", err);
902 
903     /* test invalid str in src */
904     dst[0] = 0;
905     src[0] = 0x81;
906     src[1] = 0x81;
907     src[2] = 0x52;
908     src[3] = 0;
909     err = p_mbscat_s(dst, sizeof(dst), src);
910     ok(err == 0, "_mbscat_s returned %d\n", err);
911 
912     /* test dst with leading byte on the end of buffer */
913     dst[0] = 'a';
914     dst[1] = 0x81;
915     dst[2] = 0;
916     src[0] = 'R';
917     src[1] = 0;
918     err = p_mbscat_s(dst, sizeof(dst), src);
919     ok(err == EILSEQ, "_mbscat_s returned %d\n", err);
920     ok(!memcmp(dst, "aR", 3), "dst = %s\n", dst);
921 
922     /* test src with leading byte on the end of buffer */
923     dst[0] = 'a';
924     dst[1] = 0;
925     src[0] = 'b';
926     src[1] = 0x81;
927     src[2] = 0;
928     err = p_mbscat_s(dst, sizeof(dst), src);
929     ok(err == EILSEQ, "_mbscat_s returned %d\n", err);
930     ok(!memcmp(dst, "ab", 3), "dst = %s\n", dst);
931     _setmbcp(prev_cp);
932 }
933 
934 static void test__mbsnbcpy_s(void)
935 {
936     unsigned char dest[8];
937     const unsigned char big[] = "atoolongstringforthislittledestination";
938     const unsigned char small[] = "small";
939     int ret;
940 
941     if(!p_mbsnbcpy_s)
942     {
943         win_skip("_mbsnbcpy_s not found\n");
944         return;
945     }
946 
947     memset(dest, 'X', sizeof(dest));
948     ret = p_mbsnbcpy_s(dest, sizeof(dest), small, sizeof(small));
949     ok(ret == 0, "_mbsnbcpy_s: Copying a string into a big enough destination returned %d, expected 0\n", ret);
950     ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == 'l' &&
951        dest[4] == 'l' && dest[5] == '\0'&& dest[6] == 'X' && dest[7] == 'X',
952        "Unexpected return data from _mbsnbcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
953        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
954 
955     /* WTF? */
956     memset(dest, 'X', sizeof(dest));
957     ret = p_mbsnbcpy_s(dest, sizeof(dest) - 2, big, sizeof(small));
958     ok(ret == ERANGE, "_mbsnbcpy_s: Copying a too long string returned %d, expected ERANGE\n", ret);
959     ok(dest[0] == '\0'&& dest[1] == 't' && dest[2] == 'o' && dest[3] == 'o' &&
960        dest[4] == 'l' && dest[5] == 'o' && dest[6] == 'X' && dest[7] == 'X',
961        "Unexpected return data from _mbsnbcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
962        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
963 
964     memset(dest, 'X', sizeof(dest));
965     ret = p_mbsnbcpy_s(dest, sizeof(dest) - 2, big, 4);
966     ok(ret == 0, "_mbsnbcpy_s: Copying a too long string with a count cap returned %d, expected 0\n", ret);
967     ok(dest[0] == 'a' && dest[1] == 't' && dest[2] == 'o' && dest[3] == 'o' &&
968        dest[4] == '\0'&& dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
969        "Unexpected return data from _mbsnbcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
970        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
971 
972     memset(dest, 'X', sizeof(dest));
973     ret = p_mbsnbcpy_s(dest, sizeof(dest) - 2, small, sizeof(small) + 10);
974     ok(ret == 0, "_mbsnbcpy_s: Copying more data than the source string len returned %d, expected 0\n", ret);
975     ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == 'l' &&
976        dest[4] == 'l' && dest[5] == '\0'&& dest[6] == 'X' && dest[7] == 'X',
977        "Unexpected return data from _mbsnbcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
978        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
979 }
980 
981 static void test__mbscpy_s(void)
982 {
983     const unsigned char src[] = "source string";
984     unsigned char dest[16];
985     int ret;
986 
987     if(!p__mbscpy_s)
988     {
989         win_skip("_mbscpy_s not found\n");
990         return;
991     }
992 
993     ret = p__mbscpy_s(NULL, 0, src);
994     ok(ret == EINVAL, "got %d\n", ret);
995     ret = p__mbscpy_s(NULL, sizeof(dest), src);
996     ok(ret == EINVAL, "got %d\n", ret);
997     ret = p__mbscpy_s(dest, 0, src);
998     ok(ret == EINVAL, "got %d\n", ret);
999     dest[0] = 'x';
1000     ret = p__mbscpy_s(dest, sizeof(dest), NULL);
1001     ok(ret == EINVAL, "got %d\n", ret);
1002     ok(!dest[0], "dest buffer was not modified on invalid argument\n");
1003 
1004     memset(dest, 'X', sizeof(dest));
1005     ret = p__mbscpy_s(dest, sizeof(dest), src);
1006     ok(!ret, "got %d\n", ret);
1007     ok(!memcmp(dest, src, sizeof(src)), "dest = %s\n", dest);
1008     ok(dest[sizeof(src)] == 'X', "unused part of buffer was modified\n");
1009 
1010     memset(dest, 'X', sizeof(dest));
1011     ret = p__mbscpy_s(dest, 4, src);
1012     ok(ret == ERANGE, "got %d\n", ret);
1013     ok(!dest[0], "incorrect dest buffer (%d)\n", dest[0]);
1014     ok(dest[1] == src[1], "incorrect dest buffer (%d)\n", dest[1]);
1015 }
1016 
1017 static void test_wcscpy_s(void)
1018 {
1019     static const WCHAR szLongText[] = { 'T','h','i','s','A','L','o','n','g','s','t','r','i','n','g',0 };
1020     static WCHAR szDest[18];
1021     static WCHAR szDestShort[8];
1022     int ret;
1023 
1024     if(!p_wcscpy_s)
1025     {
1026         win_skip("wcscpy_s not found\n");
1027         return;
1028     }
1029 
1030     /* Test NULL Dest */
1031     errno = EBADF;
1032     ret = p_wcscpy_s(NULL, 18, szLongText);
1033     ok(ret == EINVAL, "p_wcscpy_s expect EINVAL got %d\n", ret);
1034     ok(errno == EINVAL, "expected errno EINVAL got %d\n", errno);
1035 
1036     /* Test NULL Source */
1037     errno = EBADF;
1038     szDest[0] = 'A';
1039     ret = p_wcscpy_s(szDest, 18, NULL);
1040     ok(ret == EINVAL, "expected EINVAL got %d\n", ret);
1041     ok(errno == EINVAL, "expected errno EINVAL got %d\n", errno);
1042     ok(szDest[0] == 0, "szDest[0] not 0, got %c\n", szDest[0]);
1043 
1044     /* Test invalid size */
1045     errno = EBADF;
1046     szDest[0] = 'A';
1047     ret = p_wcscpy_s(szDest, 0, szLongText);
1048     /* Later versions changed the return value for this case to EINVAL,
1049      * and don't modify the result if the dest size is 0.
1050      */
1051     ok(ret == ERANGE || ret == EINVAL, "expected ERANGE/EINVAL got %d\n", ret);
1052     ok(errno == ERANGE || errno == EINVAL, "expected errno ERANGE/EINVAL got %d\n", errno);
1053     ok(szDest[0] == 0 || ret == EINVAL, "szDest[0] not 0\n");
1054 
1055     /* Copy same buffer size */
1056     ret = p_wcscpy_s(szDest, 18, szLongText);
1057     ok(ret == 0, "expected 0 got %d\n", ret);
1058     ok(lstrcmpW(szDest, szLongText) == 0, "szDest != szLongText\n");
1059 
1060     /* dest == source */
1061     ret = p_wcscpy_s(szDest, 18, szDest);
1062     ok(ret == 0, "expected 0 got %d\n", ret);
1063     ok(lstrcmpW(szDest, szLongText) == 0, "szDest != szLongText\n");
1064 
1065     /* Copy smaller buffer size */
1066     errno = EBADF;
1067     szDest[0] = 'A';
1068     ret = p_wcscpy_s(szDestShort, 8, szLongText);
1069     ok(ret == ERANGE || ret == EINVAL, "expected ERANGE/EINVAL got %d\n", ret);
1070     ok(errno == ERANGE || errno == EINVAL, "expected errno ERANGE/EINVAL got %d\n", errno);
1071     ok(szDestShort[0] == 0, "szDestShort[0] not 0\n");
1072 
1073     if(!p_wcsncpy_s)
1074     {
1075         win_skip("wcsncpy_s not found\n");
1076         return;
1077     }
1078 
1079     ret = p_wcsncpy_s(NULL, 18, szLongText, ARRAY_SIZE(szLongText));
1080     ok(ret == EINVAL, "p_wcsncpy_s expect EINVAL got %d\n", ret);
1081 
1082     szDest[0] = 'A';
1083     ret = p_wcsncpy_s(szDest, 18, NULL, 1);
1084     ok(ret == EINVAL, "expected EINVAL got %d\n", ret);
1085     ok(szDest[0] == 0, "szDest[0] not 0\n");
1086 
1087     szDest[0] = 'A';
1088     ret = p_wcsncpy_s(szDest, 18, NULL, 0);
1089     ok(ret == 0, "expected ERROR_SUCCESS got %d\n", ret);
1090     ok(szDest[0] == 0, "szDest[0] not 0\n");
1091 
1092     szDest[0] = 'A';
1093     ret = p_wcsncpy_s(szDest, 0, szLongText, ARRAY_SIZE(szLongText));
1094     ok(ret == ERANGE || ret == EINVAL, "expected ERANGE/EINVAL got %d\n", ret);
1095     ok(szDest[0] == 0 || ret == EINVAL, "szDest[0] not 0\n");
1096 
1097     ret = p_wcsncpy_s(szDest, 18, szLongText, ARRAY_SIZE(szLongText));
1098     ok(ret == 0, "expected 0 got %d\n", ret);
1099     ok(lstrcmpW(szDest, szLongText) == 0, "szDest != szLongText\n");
1100 
1101     szDest[0] = 'A';
1102     ret = p_wcsncpy_s(szDestShort, 8, szLongText, ARRAY_SIZE(szLongText));
1103     ok(ret == ERANGE || ret == EINVAL, "expected ERANGE/EINVAL got %d\n", ret);
1104     ok(szDestShort[0] == 0, "szDestShort[0] not 0\n");
1105 
1106     szDest[0] = 'A';
1107     ret = p_wcsncpy_s(szDest, 5, szLongText, -1);
1108     ok(ret == STRUNCATE, "expected STRUNCATE got %d\n", ret);
1109     ok(szDest[4] == 0, "szDest[4] not 0\n");
1110     ok(!memcmp(szDest, szLongText, 4*sizeof(WCHAR)), "szDest = %s\n", wine_dbgstr_w(szDest));
1111 
1112     ret = p_wcsncpy_s(NULL, 0, (void*)0xdeadbeef, 0);
1113     ok(ret == 0, "ret = %d\n", ret);
1114 
1115     szDestShort[0] = '1';
1116     szDestShort[1] = 0;
1117     ret = p_wcsncpy_s(szDestShort+1, 4, szDestShort, -1);
1118     ok(ret == STRUNCATE, "expected ERROR_SUCCESS got %d\n", ret);
1119     ok(szDestShort[0]=='1' && szDestShort[1]=='1' && szDestShort[2]=='1' && szDestShort[3]=='1',
1120             "szDestShort = %s\n", wine_dbgstr_w(szDestShort));
1121 }
1122 
1123 static void test__wcsupr_s(void)
1124 {
1125     static const WCHAR mixedString[] = {'M', 'i', 'X', 'e', 'D', 'l', 'o', 'w',
1126                                         'e', 'r', 'U', 'P', 'P', 'E', 'R', 0};
1127     static const WCHAR expectedString[] = {'M', 'I', 'X', 'E', 'D', 'L', 'O',
1128                                            'W', 'E', 'R', 'U', 'P', 'P', 'E',
1129                                            'R', 0};
1130     WCHAR testBuffer[2*ARRAY_SIZE(mixedString)];
1131     int ret;
1132 
1133     if (!p_wcsupr_s)
1134     {
1135         win_skip("_wcsupr_s not found\n");
1136         return;
1137     }
1138 
1139     /* Test NULL input string and invalid size. */
1140     errno = EBADF;
1141     ret = p_wcsupr_s(NULL, 0);
1142     ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
1143     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1144 
1145     /* Test NULL input string and valid size. */
1146     errno = EBADF;
1147     ret = p_wcsupr_s(NULL, ARRAY_SIZE(testBuffer));
1148     ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
1149     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1150 
1151     /* Test empty string with zero size. */
1152     errno = EBADF;
1153     testBuffer[0] = '\0';
1154     ret = p_wcsupr_s(testBuffer, 0);
1155     ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
1156     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1157     ok(testBuffer[0] == '\0', "Expected the buffer to be unchanged\n");
1158 
1159     /* Test empty string with size of one. */
1160     testBuffer[0] = '\0';
1161     ret = p_wcsupr_s(testBuffer, 1);
1162     ok(ret == 0, "Expected _wcsupr_s to succeed, got %d\n", ret);
1163     ok(testBuffer[0] == '\0', "Expected the buffer to be unchanged\n");
1164 
1165     /* Test one-byte buffer with zero size. */
1166     errno = EBADF;
1167     testBuffer[0] = 'x';
1168     ret = p_wcsupr_s(testBuffer, 0);
1169     ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
1170     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1171     ok(testBuffer[0] == '\0', "Expected the first buffer character to be null\n");
1172 
1173     /* Test one-byte buffer with size of one. */
1174     errno = EBADF;
1175     testBuffer[0] = 'x';
1176     ret = p_wcsupr_s(testBuffer, 1);
1177     ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
1178     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1179     ok(testBuffer[0] == '\0', "Expected the first buffer character to be null\n");
1180 
1181     /* Test invalid size. */
1182     wcscpy(testBuffer, mixedString);
1183     errno = EBADF;
1184     ret = p_wcsupr_s(testBuffer, 0);
1185     ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
1186     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1187     ok(testBuffer[0] == '\0', "Expected the first buffer character to be null\n");
1188 
1189     /* Test normal string uppercasing. */
1190     wcscpy(testBuffer, mixedString);
1191     ret = p_wcsupr_s(testBuffer, ARRAY_SIZE(mixedString));
1192     ok(ret == 0, "Expected _wcsupr_s to succeed, got %d\n", ret);
1193     ok(!wcscmp(testBuffer, expectedString), "Expected the string to be fully upper-case\n");
1194 
1195     /* Test uppercasing with a shorter buffer size count. */
1196     wcscpy(testBuffer, mixedString);
1197     errno = EBADF;
1198     ret = p_wcsupr_s(testBuffer, ARRAY_SIZE(mixedString) - 1);
1199     ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
1200     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1201     ok(testBuffer[0] == '\0', "Expected the first buffer character to be null\n");
1202 
1203     /* Test uppercasing with a longer buffer size count. */
1204     wcscpy(testBuffer, mixedString);
1205     ret = p_wcsupr_s(testBuffer, ARRAY_SIZE(testBuffer));
1206     ok(ret == 0, "Expected _wcsupr_s to succeed, got %d\n", ret);
1207     ok(!wcscmp(testBuffer, expectedString), "Expected the string to be fully upper-case\n");
1208 }
1209 
1210 static void test__wcslwr_s(void)
1211 {
1212     static const WCHAR mixedString[] = {'M', 'i', 'X', 'e', 'D', 'l', 'o', 'w',
1213                                         'e', 'r', 'U', 'P', 'P', 'E', 'R', 0};
1214     static const WCHAR expectedString[] = {'m', 'i', 'x', 'e', 'd', 'l', 'o',
1215                                            'w', 'e', 'r', 'u', 'p', 'p', 'e',
1216                                            'r', 0};
1217     WCHAR buffer[2*ARRAY_SIZE(mixedString)];
1218     int ret;
1219 
1220     if (!p_wcslwr_s)
1221     {
1222         win_skip("_wcslwr_s not found\n");
1223         return;
1224     }
1225 
1226     /* Test NULL input string and invalid size. */
1227     errno = EBADF;
1228     ret = p_wcslwr_s(NULL, 0);
1229     ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
1230     ok(errno == EINVAL, "expected errno EINVAL, got %d\n", errno);
1231 
1232     /* Test NULL input string and valid size. */
1233     errno = EBADF;
1234     ret = p_wcslwr_s(NULL, ARRAY_SIZE(buffer));
1235     ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
1236     ok(errno == EINVAL, "expected errno EINVAL, got %d\n", errno);
1237 
1238     /* Test empty string with zero size. */
1239     errno = EBADF;
1240     buffer[0] = 'a';
1241     ret = p_wcslwr_s(buffer, 0);
1242     ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
1243     ok(errno == EINVAL, "expected errno EINVAL, got %d\n", errno);
1244     ok(buffer[0] == 0, "expected empty string\n");
1245 
1246     /* Test empty string with size of one. */
1247     buffer[0] = 0;
1248     ret = p_wcslwr_s(buffer, 1);
1249     ok(ret == 0, "got %d\n", ret);
1250     ok(buffer[0] == 0, "expected buffer to be unchanged\n");
1251 
1252     /* Test one-byte buffer with zero size. */
1253     errno = EBADF;
1254     buffer[0] = 'x';
1255     ret = p_wcslwr_s(buffer, 0);
1256     ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
1257     ok(errno == EINVAL, "expected errno to be EINVAL, got %d\n", errno);
1258     ok(buffer[0] == '\0', "expected empty string\n");
1259 
1260     /* Test one-byte buffer with size of one. */
1261     errno = EBADF;
1262     buffer[0] = 'x';
1263     ret = p_wcslwr_s(buffer, 1);
1264     ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
1265     ok(errno == EINVAL, "expected errno to be EINVAL, got %d\n", errno);
1266     ok(buffer[0] == '\0', "expected empty string\n");
1267 
1268     /* Test invalid size. */
1269     wcscpy(buffer, mixedString);
1270     errno = EBADF;
1271     ret = p_wcslwr_s(buffer, 0);
1272     ok(ret == EINVAL, "Expected EINVAL, got %d\n", ret);
1273     ok(errno == EINVAL, "expected errno to be EINVAL, got %d\n", errno);
1274     ok(buffer[0] == '\0', "expected empty string\n");
1275 
1276     /* Test normal string uppercasing. */
1277     wcscpy(buffer, mixedString);
1278     ret = p_wcslwr_s(buffer, ARRAY_SIZE(mixedString));
1279     ok(ret == 0, "expected 0, got %d\n", ret);
1280     ok(!wcscmp(buffer, expectedString), "expected lowercase\n");
1281 
1282     /* Test uppercasing with a shorter buffer size count. */
1283     wcscpy(buffer, mixedString);
1284     errno = EBADF;
1285     ret = p_wcslwr_s(buffer, ARRAY_SIZE(mixedString) - 1);
1286     ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
1287     ok(errno == EINVAL, "expected errno to be EINVAL, got %d\n", errno);
1288     ok(buffer[0] == '\0', "expected empty string\n");
1289 
1290     /* Test uppercasing with a longer buffer size count. */
1291     wcscpy(buffer, mixedString);
1292     ret = p_wcslwr_s(buffer, ARRAY_SIZE(buffer));
1293     ok(ret == 0, "expected 0, got %d\n", ret);
1294     ok(!wcscmp(buffer, expectedString), "expected lowercase\n");
1295 }
1296 
1297 static void test_mbcjisjms(void)
1298 {
1299     /* List of value-pairs to test. The test assumes the last pair to be {0, ..} */
1300     unsigned int jisjms[][2] = { {0x2020, 0}, {0x2021, 0}, {0x2120, 0}, {0x2121, 0x8140},
1301                                  {0x7f7f, 0}, {0x7f7e, 0}, {0x7e7f, 0}, {0x7e7e, 0xeffc},
1302                                  {0x255f, 0x837e}, {0x2560, 0x8380}, {0x2561, 0x8381},
1303                                  {0x2121FFFF, 0}, {0x2223, 0x81a1}, {0x237e, 0x829e}, {0, 0}};
1304     int cp[] = { 932, 936, 939, 950, 1361, _MB_CP_SBCS };
1305     unsigned int i, j;
1306     int prev_cp = _getmbcp();
1307 
1308     for (i = 0; i < ARRAY_SIZE(cp); i++)
1309     {
1310         _setmbcp(cp[i]);
1311         for (j = 0; jisjms[j][0] != 0; j++)
1312         {
1313             unsigned int ret, exp;
1314             ret = _mbcjistojms(jisjms[j][0]);
1315             exp = (cp[i] == 932) ? jisjms[j][1] : jisjms[j][0];
1316             ok(ret == exp, "Expected 0x%x, got 0x%x (0x%x, codepage=%d)\n",
1317                exp, ret, jisjms[j][0], cp[i]);
1318         }
1319     }
1320     _setmbcp(prev_cp);
1321 }
1322 
1323 static void test_mbcjmsjis(void)
1324 {
1325     /* List of value-pairs to test. The test assumes the last pair to be {0, ..} */
1326     unsigned int jmsjis[][2] = { {0x80fc, 0}, {0x813f, 0}, {0x8140, 0x2121},
1327                                  {0x817e, 0x215f}, {0x817f, 0}, {0x8180, 0x2160},
1328                                  {0x819e, 0x217e}, {0x819f, 0x2221}, {0x81fc, 0x227e},
1329                                  {0x81fd, 0}, {0x9ffc, 0x5e7e}, {0x9ffd, 0},
1330                                  {0xa040, 0}, {0xdffc, 0}, {0xe040, 0x5f21},
1331                                  {0xeffc, 0x7e7e}, {0xf040, 0}, {0x21, 0}, {0, 0}};
1332     int cp[] = { 932, 936, 939, 950, 1361, _MB_CP_SBCS };
1333     unsigned int i, j;
1334     int prev_cp = _getmbcp();
1335 
1336     for (i = 0; i < ARRAY_SIZE(cp); i++)
1337     {
1338         _setmbcp(cp[i]);
1339         for (j = 0; jmsjis[j][0] != 0; j++)
1340         {
1341             unsigned int ret, exp;
1342             ret = _mbcjmstojis(jmsjis[j][0]);
1343             exp = (cp[i] == 932) ? jmsjis[j][1] : jmsjis[j][0];
1344             ok(ret == exp, "Expected 0x%x, got 0x%x (0x%x, codepage=%d)\n",
1345                exp, ret, jmsjis[j][0], cp[i]);
1346         }
1347     }
1348     _setmbcp(prev_cp);
1349 }
1350 
1351 static void test_mbctohira(void)
1352 {
1353     static const unsigned int mbchira_932[][2] = {
1354         {0x8152, 0x8152}, {0x8153, 0x8153}, {0x8154, 0x8154}, {0x8155, 0x8155},
1355         {0x82a0, 0x82a0}, {0x833f, 0x833f}, {0x8340, 0x829f}, {0x837e, 0x82dd},
1356         {0x837f, 0x837f}, {0x8380, 0x82de}, {0x8393, 0x82f1}, {0x8394, 0x8394},
1357         {0x8396, 0x8396}, {0x8397, 0x8397},
1358         {0xa5, 0xa5}, {0xb0, 0xb0}, {0xdd, 0xdd} };
1359     unsigned int i;
1360     unsigned int prev_cp = _getmbcp();
1361 
1362     _setmbcp(_MB_CP_SBCS);
1363     for (i = 0; i < ARRAY_SIZE(mbchira_932); i++)
1364     {
1365         int ret, exp = mbchira_932[i][0];
1366         ret = _mbctohira(mbchira_932[i][0]);
1367         ok(ret == exp, "Expected 0x%x, got 0x%x\n", exp, ret);
1368     }
1369 
1370     _setmbcp(932);
1371     for (i = 0; i < ARRAY_SIZE(mbchira_932); i++)
1372     {
1373         unsigned int ret, exp;
1374         ret = _mbctohira(mbchira_932[i][0]);
1375         exp = mbchira_932[i][1];
1376         ok(ret == exp, "Expected 0x%x, got 0x%x\n", exp, ret);
1377     }
1378     _setmbcp(prev_cp);
1379 }
1380 
1381 static void test_mbctokata(void)
1382 {
1383     static const unsigned int mbckata_932[][2] = {
1384         {0x8152, 0x8152}, {0x8153, 0x8153}, {0x8154, 0x8154}, {0x8155, 0x8155},
1385         {0x833f, 0x833f}, {0x829f, 0x8340}, {0x82dd, 0x837e}, {0x837f, 0x837f},
1386         {0x82de, 0x8380}, {0x8394, 0x8394}, {0x8397, 0x8397},
1387         {0xa5, 0xa5}, {0xb0, 0xb0}, {0xdd, 0xdd} };
1388     unsigned int i;
1389     unsigned int prev_cp = _getmbcp();
1390 
1391     _setmbcp(_MB_CP_SBCS);
1392     for (i = 0; i < ARRAY_SIZE(mbckata_932); i++)
1393     {
1394         int ret, exp = mbckata_932[i][0];
1395         ret = _mbctokata(mbckata_932[i][0]);
1396         ok(ret == exp, "Expected 0x%x, got 0x%x\n", exp, ret);
1397     }
1398 
1399     _setmbcp(932);
1400     for (i = 0; i < ARRAY_SIZE(mbckata_932); i++)
1401     {
1402         unsigned int ret, exp;
1403         ret = _mbctokata(mbckata_932[i][0]);
1404         exp = mbckata_932[i][1];
1405         ok(ret == exp, "Expected 0x%x, got 0x%x\n", exp, ret);
1406     }
1407     _setmbcp(prev_cp);
1408 }
1409 
1410 static void test_mbbtombc(void)
1411 {
1412     static const unsigned int mbbmbc[][2] = {
1413         {0x1f, 0x1f}, {0x20, 0x8140}, {0x39, 0x8258}, {0x40, 0x8197},
1414         {0x41, 0x8260}, {0x5e, 0x814f}, {0x7e, 0x8150}, {0x7f, 0x7f},
1415         {0x80, 0x80}, {0x81, 0x81}, {0xa0, 0xa0}, {0xa7, 0x8340},
1416         {0xb0, 0x815b}, {0xd1, 0x8380}, {0xff, 0xff}, {0,0}};
1417     int cp[] = { 932, 936, 939, 950, 1361, _MB_CP_SBCS };
1418     int i, j;
1419     int prev_cp = _getmbcp();
1420 
1421     for (i = 0; i < ARRAY_SIZE(cp); i++)
1422     {
1423         _setmbcp(cp[i]);
1424         for (j = 0; mbbmbc[j][0] != 0; j++)
1425         {
1426             unsigned int exp, ret;
1427             ret = _mbbtombc(mbbmbc[j][0]);
1428             exp = (cp[i] == 932) ? mbbmbc[j][1] : mbbmbc[j][0];
1429             ok(ret == exp, "Expected 0x%x, got 0x%x (0x%x, codepage %d)\n",
1430                exp, ret, mbbmbc[j][0], cp[i]);
1431         }
1432     }
1433     _setmbcp(prev_cp);
1434 }
1435 
1436 static void test_mbctombb(void)
1437 {
1438     static const unsigned int mbcmbb_932[][2] = {
1439         {0x829e, 0x829e}, {0x829f, 0xa7}, {0x82f1, 0xdd}, {0x82f2, 0x82f2},
1440         {0x833f, 0x833f}, {0x8340, 0xa7}, {0x837e, 0xd0}, {0x837f, 0x837f},
1441         {0x8380, 0xd1}, {0x8396, 0xb9}, {0x8397, 0x8397}, {0x813f, 0x813f},
1442         {0x8140, 0x20}, {0x814c, 0x814c}, {0x814f, 0x5e}, {0x8197, 0x40},
1443         {0x8198, 0x8198}, {0x8258, 0x39}, {0x8259, 0x8259}, {0x825f, 0x825f},
1444         {0x8260, 0x41}, {0x82f1, 0xdd}, {0x82f2, 0x82f2}, {0,0}};
1445     unsigned int exp, ret, i;
1446     unsigned int prev_cp = _getmbcp();
1447 
1448     _setmbcp(932);
1449     for (i = 0; mbcmbb_932[i][0] != 0; i++)
1450     {
1451         ret = _mbctombb(mbcmbb_932[i][0]);
1452         exp = mbcmbb_932[i][1];
1453         ok(ret == exp, "Expected 0x%x, got 0x%x\n", exp, ret);
1454     }
1455     _setmbcp(prev_cp);
1456 }
1457 
1458 static void test_ismbckata(void) {
1459     struct katakana_pair {
1460         UINT c;
1461         BOOL exp;
1462     };
1463     static const struct katakana_pair tests[] = {
1464         {0x8152, FALSE}, {0x8153, FALSE}, {0x8154, FALSE}, {0x8155, FALSE},
1465         {0x82a0, FALSE}, {0x833f, FALSE}, {0x8340, TRUE }, {0x837e, TRUE },
1466         {0x837f, FALSE}, {0x8380, TRUE }, {0x8396, TRUE }, {0x8397, FALSE},
1467         {0xa5, FALSE}, {0xb0, FALSE}, {0xdd, FALSE}
1468     };
1469     unsigned int prev_cp = _getmbcp();
1470     int ret;
1471     unsigned int i;
1472 
1473     _setmbcp(_MB_CP_SBCS);
1474     for (i = 0; i < ARRAY_SIZE(tests); i++) {
1475         ret = _ismbckata(tests[i].c);
1476         ok(!ret, "expected 0, got %d for %04x\n", ret, tests[i].c);
1477     }
1478 
1479     _setmbcp(932);
1480     for (i = 0; i < ARRAY_SIZE(tests); i++) {
1481         ret = _ismbckata(tests[i].c);
1482         ok(!!ret == tests[i].exp, "expected %d, got %d for %04x\n",
1483            tests[i].exp, !!ret, tests[i].c);
1484     }
1485 
1486     _setmbcp(prev_cp);
1487 }
1488 
1489 static void test_ismbclegal(void) {
1490     unsigned int prev_cp = _getmbcp();
1491     int ret, exp, err;
1492     unsigned int i;
1493 
1494     _setmbcp(932); /* Japanese */
1495     err = 0;
1496     for(i = 0; i < 0x10000; i++) {
1497         ret = _ismbclegal(i);
1498         exp = ((HIBYTE(i) >= 0x81 && HIBYTE(i) <= 0x9F) ||
1499                (HIBYTE(i) >= 0xE0 && HIBYTE(i) <= 0xFC)) &&
1500               ((LOBYTE(i) >= 0x40 && LOBYTE(i) <= 0x7E) ||
1501                (LOBYTE(i) >= 0x80 && LOBYTE(i) <= 0xFC));
1502         if(ret != exp) {
1503             err = 1;
1504             break;
1505         }
1506     }
1507     ok(!err, "_ismbclegal (932) : Expected 0x%x, got 0x%x (0x%x)\n", exp, ret, i);
1508     _setmbcp(936); /* Chinese (GBK) */
1509     err = 0;
1510     for(i = 0; i < 0x10000; i++) {
1511         ret = _ismbclegal(i);
1512         exp = HIBYTE(i) >= 0x81 && HIBYTE(i) <= 0xFE &&
1513               LOBYTE(i) >= 0x40 && LOBYTE(i) <= 0xFE;
1514         if(ret != exp) {
1515             err = 1;
1516             break;
1517         }
1518     }
1519     ok(!err, "_ismbclegal (936) : Expected 0x%x, got 0x%x (0x%x)\n", exp, ret, i);
1520     _setmbcp(949); /* Korean */
1521     err = 0;
1522     for(i = 0; i < 0x10000; i++) {
1523         ret = _ismbclegal(i);
1524         exp = HIBYTE(i) >= 0x81 && HIBYTE(i) <= 0xFE &&
1525               LOBYTE(i) >= 0x41 && LOBYTE(i) <= 0xFE;
1526         if(ret != exp) {
1527             err = 1;
1528             break;
1529         }
1530     }
1531     ok(!err, "_ismbclegal (949) : Expected 0x%x, got 0x%x (0x%x)\n", exp, ret, i);
1532     _setmbcp(950); /* Chinese (Big5) */
1533     err = 0;
1534     for(i = 0; i < 0x10000; i++) {
1535         ret = _ismbclegal(i);
1536         exp = HIBYTE(i) >= 0x81 && HIBYTE(i) <= 0xFE &&
1537             ((LOBYTE(i) >= 0x40 && LOBYTE(i) <= 0x7E) ||
1538              (LOBYTE(i) >= 0xA1 && LOBYTE(i) <= 0xFE));
1539         if(ret != exp) {
1540             err = 1;
1541             break;
1542         }
1543     }
1544     ok(!err, "_ismbclegal (950) : Expected 0x%x, got 0x%x (0x%x)\n", exp, ret, i);
1545     _setmbcp(1361); /* Korean (Johab) */
1546     err = 0;
1547     for(i = 0; i < 0x10000; i++) {
1548         ret = _ismbclegal(i);
1549         exp = ((HIBYTE(i) >= 0x81 && HIBYTE(i) <= 0xD3) ||
1550                (HIBYTE(i) >= 0xD8 && HIBYTE(i) <= 0xF9)) &&
1551               ((LOBYTE(i) >= 0x31 && LOBYTE(i) <= 0x7E) ||
1552                (LOBYTE(i) >= 0x81 && LOBYTE(i) <= 0xFE)) &&
1553                 HIBYTE(i) != 0xDF;
1554         if(ret != exp) {
1555             err = 1;
1556             break;
1557         }
1558     }
1559     todo_wine ok(!err, "_ismbclegal (1361) : Expected 0x%x, got 0x%x (0x%x)\n", exp, ret, i);
1560 
1561     _setmbcp(prev_cp);
1562 }
1563 
1564 static const struct {
1565     const char* string;
1566     const char* delimiter;
1567     int exp_offsetret1; /* returned offset from string after first call to strtok()
1568                            -1 means NULL  */
1569     int exp_offsetret2; /* returned offset from string after second call to strtok()
1570                            -1 means NULL  */
1571     int exp_offsetret3; /* returned offset from string after third call to strtok()
1572                            -1 means NULL  */
1573 } testcases_strtok[] = {
1574     { "red cabernet", " ", 0, 4, -1 },
1575     { "sparkling white riesling", " ", 0, 10, 16 },
1576     { " pale cream sherry", "e ", 1, 6, 9 },
1577     /* end mark */
1578     { 0}
1579 };
1580 
1581 static void test_strtok(void)
1582 {
1583     int i;
1584     char *strret;
1585     char teststr[100];
1586     for( i = 0; testcases_strtok[i].string; i++){
1587         strcpy( teststr, testcases_strtok[i].string);
1588         strret = strtok( teststr, testcases_strtok[i].delimiter);
1589         ok( (int)(strret - teststr) ==  testcases_strtok[i].exp_offsetret1 ||
1590                 (!strret && testcases_strtok[i].exp_offsetret1 == -1),
1591                 "string (%p) \'%s\' return %p\n",
1592                 teststr, testcases_strtok[i].string, strret);
1593         if( !strret) continue;
1594         strret = strtok( NULL, testcases_strtok[i].delimiter);
1595         ok( (int)(strret - teststr) ==  testcases_strtok[i].exp_offsetret2 ||
1596                 (!strret && testcases_strtok[i].exp_offsetret2 == -1),
1597                 "second call string (%p) \'%s\' return %p\n",
1598                 teststr, testcases_strtok[i].string, strret);
1599         if( !strret) continue;
1600         strret = strtok( NULL, testcases_strtok[i].delimiter);
1601         ok( (int)(strret - teststr) ==  testcases_strtok[i].exp_offsetret3 ||
1602                 (!strret && testcases_strtok[i].exp_offsetret3 == -1),
1603                 "third call string (%p) \'%s\' return %p\n",
1604                 teststr, testcases_strtok[i].string, strret);
1605     }
1606 }
1607 
1608 static void test_strtol(void)
1609 {
1610     static char neg[] = "-0x";
1611 
1612     char* e;
1613     LONG l;
1614     ULONG ul;
1615 
1616     /* errno is only set in case of error, so reset errno to EBADF to check for errno modification */
1617     /* errno is modified on W2K8+ */
1618     errno = EBADF;
1619     l = strtol("-1234", &e, 0);
1620     ok(l==-1234, "wrong value %d\n", l);
1621     ok(errno == EBADF || broken(errno == 0), "wrong errno %d\n", errno);
1622     errno = EBADF;
1623     ul = strtoul("1234", &e, 0);
1624     ok(ul==1234, "wrong value %u\n", ul);
1625     ok(errno == EBADF || broken(errno == 0), "wrong errno %d\n", errno);
1626 
1627     errno = EBADF;
1628     l = strtol("2147483647L", &e, 0);
1629     ok(l==2147483647, "wrong value %d\n", l);
1630     ok(errno == EBADF || broken(errno == 0), "wrong errno %d\n", errno);
1631     errno = EBADF;
1632     l = strtol("-2147483648L", &e, 0);
1633     ok(l==-2147483647L - 1, "wrong value %d\n", l);
1634     ok(errno == EBADF || broken(errno == 0), "wrong errno %d\n", errno);
1635     errno = EBADF;
1636     ul = strtoul("4294967295UL", &e, 0);
1637     ok(ul==4294967295ul, "wrong value %u\n", ul);
1638     ok(errno == EBADF || broken(errno == 0), "wrong errno %d\n", errno);
1639 
1640     errno = 0;
1641     l = strtol("9223372036854775807L", &e, 0);
1642     ok(l==2147483647, "wrong value %d\n", l);
1643     ok(errno == ERANGE, "wrong errno %d\n", errno);
1644     errno = 0;
1645     ul = strtoul("9223372036854775807L", &e, 0);
1646     ok(ul==4294967295ul, "wrong value %u\n", ul);
1647     ok(errno == ERANGE, "wrong errno %d\n", errno);
1648 
1649     errno = 0;
1650     ul = strtoul("-2", NULL, 0);
1651     ok(ul == -2, "wrong value %u\n", ul);
1652     ok(errno == 0, "wrong errno %d\n", errno);
1653 
1654     errno = 0;
1655     ul = strtoul("-4294967294", NULL, 0);
1656     ok(ul == 2, "wrong value %u\n", ul);
1657     ok(errno == 0, "wrong errno %d\n", errno);
1658 
1659     errno = 0;
1660     ul = strtoul("-4294967295", NULL, 0);
1661     ok(ul==1, "wrong value %u\n", ul);
1662     ok(errno == 0, "wrong errno %d\n", errno);
1663 
1664     errno = 0;
1665     ul = strtoul("-4294967296", NULL, 0);
1666     ok(ul == 1, "wrong value %u\n", ul);
1667     ok(errno == ERANGE, "wrong errno %d\n", errno);
1668 
1669     errno = 0;
1670     l = strtol(neg, &e, 0);
1671     ok(l == 0, "wrong value %d\n", l);
1672     ok(errno == 0, "wrong errno %d\n", errno);
1673     ok(e == neg, "e = %p, neg = %p\n", e, neg);
1674 }
1675 
1676 static void test_strnlen(void)
1677 {
1678     static const char str[] = "string";
1679     size_t res;
1680 
1681     if(!p_strnlen) {
1682         win_skip("strnlen not found\n");
1683         return;
1684     }
1685 
1686     res = p_strnlen(str, 20);
1687     ok(res == 6, "Returned length = %d\n", (int)res);
1688 
1689     res = p_strnlen(str, 3);
1690     ok(res == 3, "Returned length = %d\n", (int)res);
1691 
1692     res = p_strnlen(NULL, 0);
1693     ok(res == 0, "Returned length = %d\n", (int)res);
1694 }
1695 
1696 static void test__strtoi64(void)
1697 {
1698     static const char no1[] = "31923";
1699     static const char no2[] = "-213312";
1700     static const char no3[] = "12aa";
1701     static const char no4[] = "abc12";
1702     static const char overflow[] = "99999999999999999999";
1703     static const char neg_overflow[] = "-99999999999999999999";
1704     static const char hex[] = "0x123";
1705     static const char oct[] = "000123";
1706     static const char blanks[] = "        12 212.31";
1707 
1708     __int64 res;
1709     unsigned __int64 ures;
1710     char *endpos;
1711 
1712     if(!p_strtoi64 || !p_strtoui64) {
1713         win_skip("_strtoi64 or _strtoui64 not found\n");
1714         return;
1715     }
1716 
1717     errno = 0xdeadbeef;
1718     res = p_strtoi64(no1, NULL, 10);
1719     ok(res == 31923, "res != 31923\n");
1720     res = p_strtoi64(no2, NULL, 10);
1721     ok(res == -213312, "res != -213312\n");
1722     res = p_strtoi64(no3, NULL, 10);
1723     ok(res == 12, "res != 12\n");
1724     res = p_strtoi64(no4, &endpos, 10);
1725     ok(res == 0, "res != 0\n");
1726     ok(endpos == no4, "Scanning was not stopped on first character\n");
1727     res = p_strtoi64(hex, &endpos, 10);
1728     ok(res == 0, "res != 0\n");
1729     ok(endpos == hex+1, "Incorrect endpos (%p-%p)\n", hex, endpos);
1730     res = p_strtoi64(oct, &endpos, 10);
1731     ok(res == 123, "res != 123\n");
1732     ok(endpos == oct+strlen(oct), "Incorrect endpos (%p-%p)\n", oct, endpos);
1733     res = p_strtoi64(blanks, &endpos, 10);
1734     ok(res == 12, "res != 12\n");
1735     ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos);
1736     ok(errno == 0xdeadbeef, "errno = %x\n", errno);
1737 
1738     errno = 0xdeadbeef;
1739     res = p_strtoi64(overflow, &endpos, 10);
1740     ok(res == _I64_MAX, "res != _I64_MAX\n");
1741     ok(endpos == overflow+strlen(overflow), "Incorrect endpos (%p-%p)\n", overflow, endpos);
1742     ok(errno == ERANGE, "errno = %x\n", errno);
1743 
1744     errno = 0xdeadbeef;
1745     res = p_strtoi64(neg_overflow, &endpos, 10);
1746     ok(res == _I64_MIN, "res != _I64_MIN\n");
1747     ok(endpos == neg_overflow+strlen(neg_overflow), "Incorrect endpos (%p-%p)\n", neg_overflow, endpos);
1748     ok(errno == ERANGE, "errno = %x\n", errno);
1749 
1750     errno = 0xdeadbeef;
1751     res = p_strtoi64(no1, &endpos, 16);
1752     ok(res == 203043, "res != 203043\n");
1753     ok(endpos == no1+strlen(no1), "Incorrect endpos (%p-%p)\n", no1, endpos);
1754     res = p_strtoi64(no2, &endpos, 16);
1755     ok(res == -2175762, "res != -2175762\n");
1756     ok(endpos == no2+strlen(no2), "Incorrect endpos (%p-%p)\n", no2, endpos);
1757     res = p_strtoi64(no3, &endpos, 16);
1758     ok(res == 4778, "res != 4778\n");
1759     ok(endpos == no3+strlen(no3), "Incorrect endpos (%p-%p)\n", no3, endpos);
1760     res = p_strtoi64(no4, &endpos, 16);
1761     ok(res == 703506, "res != 703506\n");
1762     ok(endpos == no4+strlen(no4), "Incorrect endpos (%p-%p)\n", no4, endpos);
1763     res = p_strtoi64(hex, &endpos, 16);
1764     ok(res == 291, "res != 291\n");
1765     ok(endpos == hex+strlen(hex), "Incorrect endpos (%p-%p)\n", hex, endpos);
1766     res = p_strtoi64(oct, &endpos, 16);
1767     ok(res == 291, "res != 291\n");
1768     ok(endpos == oct+strlen(oct), "Incorrect endpos (%p-%p)\n", oct, endpos);
1769     res = p_strtoi64(blanks, &endpos, 16);
1770     ok(res == 18, "res != 18\n");
1771     ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos);
1772     ok(errno == 0xdeadbeef, "errno = %x\n", errno);
1773 
1774     errno = 0xdeadbeef;
1775     res = p_strtoi64(hex, &endpos, 36);
1776     ok(res == 1541019, "res != 1541019\n");
1777     ok(endpos == hex+strlen(hex), "Incorrect endpos (%p-%p)\n", hex, endpos);
1778     ok(errno == 0xdeadbeef, "errno = %x\n", errno);
1779 
1780     errno = 0xdeadbeef;
1781     res = p_strtoi64(no1, &endpos, 0);
1782     ok(res == 31923, "res != 31923\n");
1783     ok(endpos == no1+strlen(no1), "Incorrect endpos (%p-%p)\n", no1, endpos);
1784     res = p_strtoi64(no2, &endpos, 0);
1785     ok(res == -213312, "res != -213312\n");
1786     ok(endpos == no2+strlen(no2), "Incorrect endpos (%p-%p)\n", no2, endpos);
1787     res = p_strtoi64(no3, &endpos, 10);
1788     ok(res == 12, "res != 12\n");
1789     ok(endpos == no3+2, "Incorrect endpos (%p-%p)\n", no3, endpos);
1790     res = p_strtoi64(no4, &endpos, 10);
1791     ok(res == 0, "res != 0\n");
1792     ok(endpos == no4, "Incorrect endpos (%p-%p)\n", no4, endpos);
1793     res = p_strtoi64(hex, &endpos, 10);
1794     ok(res == 0, "res != 0\n");
1795     ok(endpos == hex+1, "Incorrect endpos (%p-%p)\n", hex, endpos);
1796     res = p_strtoi64(oct, &endpos, 10);
1797     ok(res == 123, "res != 123\n");
1798     ok(endpos == oct+strlen(oct), "Incorrect endpos (%p-%p)\n", oct, endpos);
1799     res = p_strtoi64(blanks, &endpos, 10);
1800     ok(res == 12, "res != 12\n");
1801     ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos);
1802     ok(errno == 0xdeadbeef, "errno = %x\n", errno);
1803 
1804     errno = 0xdeadbeef;
1805     ures = p_strtoui64(no1, &endpos, 0);
1806     ok(ures == 31923, "ures != 31923\n");
1807     ok(endpos == no1+strlen(no1), "Incorrect endpos (%p-%p)\n", no1, endpos);
1808     ures = p_strtoui64(no2, &endpos, 0);
1809     ok(ures == -213312, "ures != -213312\n");
1810     ok(endpos == no2+strlen(no2), "Incorrect endpos (%p-%p)\n", no2, endpos);
1811     ures = p_strtoui64(no3, &endpos, 10);
1812     ok(ures == 12, "ures != 12\n");
1813     ok(endpos == no3+2, "Incorrect endpos (%p-%p)\n", no3, endpos);
1814     ures = p_strtoui64(no4, &endpos, 10);
1815     ok(ures == 0, "ures != 0\n");
1816     ok(endpos == no4, "Incorrect endpos (%p-%p)\n", no4, endpos);
1817     ures = p_strtoui64(hex, &endpos, 10);
1818     ok(ures == 0, "ures != 0\n");
1819     ok(endpos == hex+1, "Incorrect endpos (%p-%p)\n", hex, endpos);
1820     ures = p_strtoui64(oct, &endpos, 10);
1821     ok(ures == 123, "ures != 123\n");
1822     ok(endpos == oct+strlen(oct), "Incorrect endpos (%p-%p)\n", oct, endpos);
1823     ures = p_strtoui64(blanks, &endpos, 10);
1824     ok(ures == 12, "ures != 12\n");
1825     ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos);
1826     ok(errno == 0xdeadbeef, "errno = %x\n", errno);
1827 
1828     errno = 0xdeadbeef;
1829     ures = p_strtoui64(overflow, &endpos, 10);
1830     ok(ures == _UI64_MAX, "ures != _UI64_MAX\n");
1831     ok(endpos == overflow+strlen(overflow), "Incorrect endpos (%p-%p)\n", overflow, endpos);
1832     ok(errno == ERANGE, "errno = %x\n", errno);
1833 
1834     errno = 0xdeadbeef;
1835     ures = p_strtoui64(neg_overflow, &endpos, 10);
1836     ok(ures == 1, "ures != 1\n");
1837     ok(endpos == neg_overflow+strlen(neg_overflow), "Incorrect endpos (%p-%p)\n", neg_overflow, endpos);
1838     ok(errno == ERANGE, "errno = %x\n", errno);
1839 }
1840 
1841 static inline BOOL almost_equal(double d1, double d2) {
1842     if(d1-d2>-1e-30 && d1-d2<1e-30)
1843         return TRUE;
1844     return FALSE;
1845 }
1846 
1847 static void test__strtod(void)
1848 {
1849     const char double1[] = "12.1";
1850     const char double2[] = "-13.721";
1851     const char double3[] = "INF";
1852     const char double4[] = ".21e12";
1853     const char double5[] = "214353e-3";
1854     const char double6[] = "NAN";
1855     const char overflow[] = "1d9999999999999999999";
1856     const char white_chars[] = "  d10";
1857 
1858     char *end;
1859     double d;
1860 
1861     d = strtod(double1, &end);
1862     ok(almost_equal(d, 12.1), "d = %lf\n", d);
1863     ok(end == double1+4, "incorrect end (%d)\n", (int)(end-double1));
1864 
1865     d = strtod(double2, &end);
1866     ok(almost_equal(d, -13.721), "d = %lf\n", d);
1867     ok(end == double2+7, "incorrect end (%d)\n", (int)(end-double2));
1868 
1869     d = strtod(double3, &end);
1870     ok(almost_equal(d, 0), "d = %lf\n", d);
1871     ok(end == double3, "incorrect end (%d)\n", (int)(end-double3));
1872 
1873     d = strtod(double4, &end);
1874     ok(almost_equal(d, 210000000000.0), "d = %lf\n", d);
1875     ok(end == double4+6, "incorrect end (%d)\n", (int)(end-double4));
1876 
1877     d = strtod(double5, &end);
1878     ok(almost_equal(d, 214.353), "d = %lf\n", d);
1879     ok(end == double5+9, "incorrect end (%d)\n", (int)(end-double5));
1880 
1881     d = strtod(double6, &end);
1882     ok(almost_equal(d, 0), "d = %lf\n", d);
1883     ok(end == double6, "incorrect end (%d)\n", (int)(end-double6));
1884 
1885     d = strtod("12.1d2", NULL);
1886     ok(almost_equal(d, 12.1e2), "d = %lf\n", d);
1887 
1888     d = strtod(white_chars, &end);
1889     ok(almost_equal(d, 0), "d = %lf\n", d);
1890     ok(end == white_chars, "incorrect end (%d)\n", (int)(end-white_chars));
1891 
1892     if (!p__strtod_l)
1893         win_skip("_strtod_l not found\n");
1894     else
1895     {
1896         errno = EBADF;
1897         d = strtod(NULL, NULL);
1898         ok(almost_equal(d, 0.0), "d = %lf\n", d);
1899         ok(errno == EINVAL, "errno = %x\n", errno);
1900 
1901         errno = EBADF;
1902         end = (char *)0xdeadbeef;
1903         d = strtod(NULL, &end);
1904         ok(almost_equal(d, 0.0), "d = %lf\n", d);
1905         ok(errno == EINVAL, "errno = %x\n", errno);
1906         ok(!end, "incorrect end ptr %p\n", end);
1907 
1908         errno = EBADF;
1909         d = p__strtod_l(NULL, NULL, NULL);
1910         ok(almost_equal(d, 0.0), "d = %lf\n", d);
1911         ok(errno == EINVAL, "errno = %x\n", errno);
1912     }
1913 
1914     /* Set locale with non '.' decimal point (',') */
1915     if(!setlocale(LC_ALL, "Polish")) {
1916         win_skip("system with limited locales\n");
1917         return;
1918     }
1919 
1920     d = strtod("12.1", NULL);
1921     ok(almost_equal(d, 12.0), "d = %lf\n", d);
1922 
1923     d = strtod("12,1", NULL);
1924     ok(almost_equal(d, 12.1), "d = %lf\n", d);
1925 
1926     setlocale(LC_ALL, "C");
1927 
1928     /* Precision tests */
1929     d = strtod("0.1", NULL);
1930     ok(almost_equal(d, 0.1), "d = %lf\n", d);
1931     d = strtod("-0.1", NULL);
1932     ok(almost_equal(d, -0.1), "d = %lf\n", d);
1933     d = strtod("0.1281832188491894198128921", NULL);
1934     ok(almost_equal(d, 0.1281832188491894198128921), "d = %lf\n", d);
1935     d = strtod("0.82181281288121", NULL);
1936     ok(almost_equal(d, 0.82181281288121), "d = %lf\n", d);
1937     d = strtod("21921922352523587651128218821", NULL);
1938     ok(almost_equal(d, 21921922352523587651128218821.0), "d = %lf\n", d);
1939     d = strtod("0.1d238", NULL);
1940     ok(almost_equal(d, 0.1e238L), "d = %lf\n", d);
1941     d = strtod("0.1D-4736", NULL);
1942     ok(almost_equal(d, 0.1e-4736L), "d = %lf\n", d);
1943 
1944     errno = 0xdeadbeef;
1945     strtod(overflow, &end);
1946     ok(errno == ERANGE, "errno = %x\n", errno);
1947     ok(end == overflow+21, "incorrect end (%d)\n", (int)(end-overflow));
1948 
1949     errno = 0xdeadbeef;
1950     strtod("-1d309", NULL);
1951     ok(errno == ERANGE, "errno = %x\n", errno);
1952 }
1953 
1954 static void test_mbstowcs(void)
1955 {
1956     static const wchar_t wSimple[] = { 't','e','x','t',0 };
1957     static const wchar_t wHiragana[] = { 0x3042,0x3043,0 };
1958     static const wchar_t wEmpty[] = { 0 };
1959     static const char mSimple[] = "text";
1960     static const char mHiragana[] = { 0x82,0xa0,0x82,0xa1,0 };
1961     static const char mEmpty[] = { 0 };
1962 
1963     const wchar_t *pwstr;
1964     wchar_t wOut[6];
1965     char mOut[6];
1966     size_t ret;
1967     int err;
1968     const char *pmbstr;
1969     mbstate_t state;
1970 
1971     wOut[4] = '!'; wOut[5] = '\0';
1972     mOut[4] = '!'; mOut[5] = '\0';
1973 
1974     if(pmbstowcs_s) {
1975         /* crashes on some systems */
1976         errno = 0xdeadbeef;
1977         ret = mbstowcs(wOut, NULL, 4);
1978         ok(ret == -1, "mbstowcs did not return -1\n");
1979         ok(errno == EINVAL, "errno = %d\n", errno);
1980     }
1981 
1982     ret = mbstowcs(NULL, mSimple, 0);
1983     ok(ret == 4, "mbstowcs did not return 4\n");
1984 
1985     ret = mbstowcs(wOut, mSimple, 4);
1986     ok(ret == 4, "mbstowcs did not return 4\n");
1987     ok(!memcmp(wOut, wSimple, 4*sizeof(wchar_t)), "wOut = %s\n", wine_dbgstr_w(wOut));
1988     ok(wOut[4] == '!', "wOut[4] != \'!\'\n");
1989 
1990     ret = mbstowcs(NULL, mEmpty, 1);
1991     ok(ret == 0, "mbstowcs did not return 0, got %d\n", (int)ret);
1992 
1993     ret = mbstowcs(wOut, mEmpty, 1);
1994     ok(ret == 0, "mbstowcs did not return 0, got %d\n", (int)ret);
1995     ok(!memcmp(wOut, wEmpty, sizeof(wEmpty)), "wOut = %s\n", wine_dbgstr_w(wOut));
1996 
1997     ret = wcstombs(NULL, wSimple, 0);
1998     ok(ret == 4, "wcstombs did not return 4\n");
1999 
2000     ret = wcstombs(mOut, wSimple, 6);
2001     ok(ret == 4, "wcstombs did not return 4\n");
2002     ok(!memcmp(mOut, mSimple, 5*sizeof(char)), "mOut = %s\n", mOut);
2003 
2004     ret = wcstombs(mOut, wSimple, 2);
2005     ok(ret == 2, "wcstombs did not return 2\n");
2006     ok(!memcmp(mOut, mSimple, 5*sizeof(char)), "mOut = %s\n", mOut);
2007 
2008     ret = wcstombs(NULL, wEmpty, 1);
2009     ok(ret == 0, "wcstombs did not return 0, got %d\n", (int)ret);
2010 
2011     ret = wcstombs(mOut, wEmpty, 1);
2012     ok(ret == 0, "wcstombs did not return 0, got %d\n", (int)ret);
2013     ok(!memcmp(mOut, mEmpty, sizeof(mEmpty)), "mOut = %s\n", mOut);
2014 
2015     if(!setlocale(LC_ALL, "Japanese_Japan.932")) {
2016         win_skip("Japanese_Japan.932 locale not available\n");
2017         return;
2018     }
2019 
2020     ret = mbstowcs(wOut, mHiragana, 6);
2021     ok(ret == 2, "mbstowcs did not return 2\n");
2022     ok(!memcmp(wOut, wHiragana, sizeof(wHiragana)), "wOut = %s\n", wine_dbgstr_w(wOut));
2023 
2024     ret = mbstowcs(wOut, mEmpty, 6);
2025     ok(ret == 0, "mbstowcs did not return 0, got %d\n", (int)ret);
2026     ok(!memcmp(wOut, wEmpty, sizeof(wEmpty)), "wOut = %s\n", wine_dbgstr_w(wOut));
2027 
2028     ret = wcstombs(mOut, wHiragana, 6);
2029     ok(ret == 4, "wcstombs did not return 4\n");
2030     ok(!memcmp(mOut, mHiragana, sizeof(mHiragana)), "mOut = %s\n", mOut);
2031 
2032     ret = wcstombs(mOut, wEmpty, 6);
2033     ok(ret == 0, "wcstombs did not return 0, got %d\n", (int)ret);
2034     ok(!memcmp(mOut, mEmpty, sizeof(mEmpty)), "mOut = %s\n", mOut);
2035 
2036     if(!pmbstowcs_s || !pwcstombs_s) {
2037         setlocale(LC_ALL, "C");
2038         win_skip("mbstowcs_s or wcstombs_s not available\n");
2039         return;
2040     }
2041 
2042     err = pmbstowcs_s(&ret, wOut, 6, mSimple, _TRUNCATE);
2043     ok(err == 0, "err = %d\n", err);
2044     ok(ret == 5, "mbstowcs_s did not return 5\n");
2045     ok(!memcmp(wOut, wSimple, sizeof(wSimple)), "wOut = %s\n", wine_dbgstr_w(wOut));
2046 
2047     err = pmbstowcs_s(&ret, wOut, 6, mHiragana, _TRUNCATE);
2048     ok(err == 0, "err = %d\n", err);
2049     ok(ret == 3, "mbstowcs_s did not return 3\n");
2050     ok(!memcmp(wOut, wHiragana, sizeof(wHiragana)), "wOut = %s\n", wine_dbgstr_w(wOut));
2051 
2052     err = pmbstowcs_s(&ret, wOut, 6, mEmpty, _TRUNCATE);
2053     ok(err == 0, "err = %d\n", err);
2054     ok(ret == 1, "mbstowcs_s did not return 1, got %d\n", (int)ret);
2055     ok(!memcmp(wOut, wEmpty, sizeof(wEmpty)), "wOut = %s\n", wine_dbgstr_w(wOut));
2056 
2057     err = pmbstowcs_s(&ret, NULL, 0, mHiragana, 1);
2058     ok(err == 0, "err = %d\n", err);
2059     ok(ret == 3, "mbstowcs_s did not return 3\n");
2060 
2061     err = pwcstombs_s(&ret, mOut, 6, wSimple, _TRUNCATE);
2062     ok(err == 0, "err = %d\n", err);
2063     ok(ret == 5, "wcstombs_s did not return 5\n");
2064     ok(!memcmp(mOut, mSimple, sizeof(mSimple)), "mOut = %s\n", mOut);
2065 
2066     err = pwcstombs_s(&ret, mOut, 6, wHiragana, _TRUNCATE);
2067     ok(err == 0, "err = %d\n", err);
2068     ok(ret == 5, "wcstombs_s did not return 5\n");
2069     ok(!memcmp(mOut, mHiragana, sizeof(mHiragana)), "mOut = %s\n", mOut);
2070 
2071     err = pwcstombs_s(&ret, mOut, 6, wEmpty, _TRUNCATE);
2072     ok(err == 0, "err = %d\n", err);
2073     ok(ret == 1, "wcstombs_s did not return 1, got %d\n", (int)ret);
2074     ok(!memcmp(mOut, mEmpty, sizeof(mEmpty)), "mOut = %s\n", mOut);
2075 
2076     err = pwcstombs_s(&ret, NULL, 0, wHiragana, 1);
2077     ok(err == 0, "err = %d\n", err);
2078     ok(ret == 5, "wcstombs_s did not return 5\n");
2079 
2080     if(!pwcsrtombs) {
2081         setlocale(LC_ALL, "C");
2082         win_skip("wcsrtombs not available\n");
2083         return;
2084     }
2085 
2086     pwstr = wSimple;
2087     err = -3;
2088     ret = pwcsrtombs(mOut, &pwstr, 4, &err);
2089     ok(ret == 4, "wcsrtombs did not return 4\n");
2090     ok(err == 0, "err = %d\n", err);
2091     ok(pwstr == wSimple+4, "pwstr = %p (wszSimple = %p)\n", pwstr, wSimple);
2092     ok(!memcmp(mOut, mSimple, ret), "mOut = %s\n", mOut);
2093 
2094     pwstr = wSimple;
2095     ret = pwcsrtombs(mOut, &pwstr, 5, NULL);
2096     ok(ret == 4, "wcsrtombs did not return 4\n");
2097     ok(pwstr == NULL, "pwstr != NULL\n");
2098     ok(!memcmp(mOut, mSimple, sizeof(mSimple)), "mOut = %s\n", mOut);
2099 
2100     if(!p_mbsrtowcs) {
2101         setlocale(LC_ALL, "C");
2102         win_skip("mbsrtowcs not available\n");
2103         return;
2104     }
2105 
2106     pmbstr = mHiragana;
2107     ret = p_mbsrtowcs(NULL, &pmbstr, 6, NULL);
2108     ok(ret == 2, "mbsrtowcs did not return 2\n");
2109     ok(pmbstr == mHiragana, "pmbstr = %p, expected %p\n", pmbstr, mHiragana);
2110 
2111     pmbstr = mHiragana;
2112     ret = p_mbsrtowcs(wOut, &pmbstr, 6, NULL);
2113     ok(ret == 2, "mbsrtowcs did not return 2\n");
2114     ok(!memcmp(wOut, wHiragana, sizeof(wHiragana)), "wOut = %s\n", wine_dbgstr_w(wOut));
2115     ok(!pmbstr, "pmbstr != NULL\n");
2116 
2117     state = mHiragana[0];
2118     pmbstr = mHiragana+1;
2119     ret = p_mbsrtowcs(wOut, &pmbstr, 6, &state);
2120     ok(ret == 2, "mbsrtowcs did not return 2\n");
2121     ok(wOut[0] == 0x3042, "wOut[0] = %x\n", wOut[0]);
2122     ok(wOut[1] == 0xff61, "wOut[1] = %x\n", wOut[1]);
2123     ok(wOut[2] == 0, "wOut[2] = %x\n", wOut[2]);
2124     ok(!pmbstr, "pmbstr != NULL\n");
2125 
2126     errno = EBADF;
2127     ret = p_mbsrtowcs(wOut, NULL, 6, &state);
2128     ok(ret == -1, "mbsrtowcs did not return -1\n");
2129     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2130 
2131     if(!p_mbsrtowcs_s) {
2132         setlocale(LC_ALL, "C");
2133         win_skip("mbsrtowcs_s not available\n");
2134         return;
2135     }
2136 
2137     pmbstr = mHiragana;
2138     err = p_mbsrtowcs_s(&ret, NULL, 0, NULL, 6, NULL);
2139     ok(ret == -1, "mbsrtowcs_s did not return -1\n");
2140     ok(err == EINVAL, "err = %d\n", err);
2141     err = p_mbsrtowcs_s(&ret, NULL, 1, &pmbstr, 6, NULL);
2142     ok(ret == -1, "mbsrtowcs_s did not return -1\n");
2143     ok(err == EINVAL, "err = %d\n", err);
2144     err = p_mbsrtowcs_s(&ret, wOut, 0, &pmbstr, 6, NULL);
2145     ok(ret == -1, "mbsrtowcs_s did not return -1\n");
2146     ok(err == EINVAL, "err = %d\n", err);
2147 
2148     pmbstr = mHiragana;
2149     errno = 0;
2150     err = p_mbsrtowcs_s(&ret, NULL, 0, &pmbstr, 6, NULL);
2151     ok(ret == 3, "mbsrtowcs_s did not return 3\n");
2152     ok(err == 0, "err = %d\n", err);
2153     ok(pmbstr == mHiragana, "pmbstr = %p, expected %p\n", pmbstr, mHiragana);
2154     ok(errno == 0, "errno = %d\n", errno);
2155 
2156     pmbstr = mHiragana;
2157     err = p_mbsrtowcs_s(&ret, wOut, 1, &pmbstr, 6, NULL);
2158     ok(ret == 2, "mbsrtowcs_s did not return 2\n");
2159     ok(err == 0, "err = %d\n", err);
2160     ok(!wOut[0], "wOut[0] = '%c'\n", wOut[0]);
2161     ok(pmbstr == mHiragana+2, "pmbstr = %p, expected %p\n", pmbstr, mHiragana+2);
2162     ok(errno == 0, "errno = %d\n", errno);
2163 
2164     pmbstr = mHiragana;
2165     err = p_mbsrtowcs_s(&ret, wOut, 2, &pmbstr, 6, NULL);
2166     ok(ret == 3, "mbsrtowcs_s did not return 3\n");
2167     ok(err == 0, "err = %d\n", err);
2168     ok(!wOut[0], "wOut[0] = '%c'\n", wOut[0]);
2169     ok(pmbstr == mHiragana+4, "pmbstr = %p, expected %p\n", pmbstr, mHiragana+4);
2170     ok(errno == 0, "errno = %d\n", errno);
2171 
2172     pmbstr = mHiragana;
2173     err = p_mbsrtowcs_s(&ret, wOut, 3, &pmbstr, 6, NULL);
2174     ok(ret == 3, "mbsrtowcs_s did not return 3\n");
2175     ok(err == 0, "err = %d\n", err);
2176     ok(!pmbstr, "pmbstr != NULL\n");
2177     ok(errno == 0, "errno = %d\n", errno);
2178 
2179     setlocale(LC_ALL, "C");
2180 }
2181 
2182 static void test_gcvt(void)
2183 {
2184     char buf[1024], *res;
2185     errno_t err;
2186 
2187     if(!p_gcvt_s) {
2188         win_skip("Skipping _gcvt tests\n");
2189         return;
2190     }
2191 
2192     errno = 0;
2193     res = _gcvt(1.2, -1, buf);
2194     ok(res == NULL, "res != NULL\n");
2195     ok(errno == ERANGE, "errno = %d\n", errno);
2196 
2197     errno = 0;
2198     res = _gcvt(1.2, 5, NULL);
2199     ok(res == NULL, "res != NULL\n");
2200     ok(errno == EINVAL, "errno = %d\n", errno);
2201 
2202     res = gcvt(1.2, 5, buf);
2203     ok(res == buf, "res != buf\n");
2204     ok(!strcmp(buf, "1.2"), "buf = %s\n", buf);
2205 
2206     buf[0] = 'x';
2207     err = p_gcvt_s(buf, 5, 1.2, 10);
2208     ok(err == ERANGE, "err = %d\n", err);
2209     ok(buf[0] == '\0', "buf[0] = %c\n", buf[0]);
2210 
2211     buf[0] = 'x';
2212     err = p_gcvt_s(buf, 4, 123456, 2);
2213     ok(err == ERANGE, "err = %d\n", err);
2214     ok(buf[0] == '\0', "buf[0] = %c\n", buf[0]);
2215 }
2216 
2217 static void test__itoa_s(void)
2218 {
2219     errno_t ret;
2220     char buffer[33];
2221 
2222     if (!p_itoa_s)
2223     {
2224         win_skip("Skipping _itoa_s tests\n");
2225         return;
2226     }
2227 
2228     errno = EBADF;
2229     ret = p_itoa_s(0, NULL, 0, 0);
2230     ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
2231     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2232 
2233     memset(buffer, 'X', sizeof(buffer));
2234     errno = EBADF;
2235     ret = p_itoa_s(0, buffer, 0, 0);
2236     ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
2237     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2238     ok(buffer[0] == 'X', "Expected the output buffer to be untouched\n");
2239 
2240     memset(buffer, 'X', sizeof(buffer));
2241     errno = EBADF;
2242     ret = p_itoa_s(0, buffer, sizeof(buffer), 0);
2243     ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
2244     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2245     ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
2246 
2247     memset(buffer, 'X', sizeof(buffer));
2248     errno = EBADF;
2249     ret = p_itoa_s(0, buffer, sizeof(buffer), 64);
2250     ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
2251     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2252     ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
2253 
2254     memset(buffer, 'X', sizeof(buffer));
2255     errno = EBADF;
2256     ret = p_itoa_s(12345678, buffer, 4, 10);
2257     ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
2258     ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
2259     ok(!memcmp(buffer, "\000765", 4),
2260        "Expected the output buffer to be null terminated with truncated output\n");
2261 
2262     memset(buffer, 'X', sizeof(buffer));
2263     errno = EBADF;
2264     ret = p_itoa_s(12345678, buffer, 8, 10);
2265     ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
2266     ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
2267     ok(!memcmp(buffer, "\0007654321", 8),
2268        "Expected the output buffer to be null terminated with truncated output\n");
2269 
2270     memset(buffer, 'X', sizeof(buffer));
2271     errno = EBADF;
2272     ret = p_itoa_s(-12345678, buffer, 9, 10);
2273     ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
2274     ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
2275     ok(!memcmp(buffer, "\00087654321", 9),
2276        "Expected the output buffer to be null terminated with truncated output\n");
2277 
2278     ret = p_itoa_s(12345678, buffer, 9, 10);
2279     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
2280     ok(!strcmp(buffer, "12345678"),
2281        "Expected output buffer string to be \"12345678\", got \"%s\"\n",
2282        buffer);
2283 
2284     ret = p_itoa_s(43690, buffer, sizeof(buffer), 2);
2285     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
2286     ok(!strcmp(buffer, "1010101010101010"),
2287        "Expected output buffer string to be \"1010101010101010\", got \"%s\"\n",
2288        buffer);
2289 
2290     ret = p_itoa_s(1092009, buffer, sizeof(buffer), 36);
2291     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
2292     ok(!strcmp(buffer, "nell"),
2293        "Expected output buffer string to be \"nell\", got \"%s\"\n",
2294        buffer);
2295 
2296     ret = p_itoa_s(5704, buffer, sizeof(buffer), 18);
2297     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
2298     ok(!strcmp(buffer, "hag"),
2299        "Expected output buffer string to be \"hag\", got \"%s\"\n",
2300        buffer);
2301 
2302     ret = p_itoa_s(-12345678, buffer, sizeof(buffer), 10);
2303     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
2304     ok(!strcmp(buffer, "-12345678"),
2305        "Expected output buffer string to be \"-12345678\", got \"%s\"\n",
2306        buffer);
2307 
2308     itoa(100, buffer, 100);
2309     ok(!strcmp(buffer, "10"),
2310             "Expected output buffer string to be \"10\", got \"%s\"\n", buffer);
2311 }
2312 
2313 static void test__strlwr_s(void)
2314 {
2315     errno_t ret;
2316     char buffer[20];
2317 
2318     if (!p_strlwr_s)
2319     {
2320         win_skip("Skipping _strlwr_s tests\n");
2321         return;
2322     }
2323 
2324     errno = EBADF;
2325     ret = p_strlwr_s(NULL, 0);
2326     ok(ret == EINVAL, "Expected _strlwr_s to return EINVAL, got %d\n", ret);
2327     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2328 
2329     errno = EBADF;
2330     ret = p_strlwr_s(NULL, sizeof(buffer));
2331     ok(ret == EINVAL, "Expected _strlwr_s to return EINVAL, got %d\n", ret);
2332     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2333 
2334     errno = EBADF;
2335     ret = p_strlwr_s(buffer, 0);
2336     ok(ret == EINVAL, "Expected _strlwr_s to return EINVAL, got %d\n", ret);
2337     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2338 
2339     strcpy(buffer, "GoRrIsTeR");
2340     errno = EBADF;
2341     ret = p_strlwr_s(buffer, 5);
2342     ok(ret == EINVAL, "Expected _strlwr_s to return EINVAL, got %d\n", ret);
2343     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2344     ok(!memcmp(buffer, "\0oRrIsTeR", sizeof("\0oRrIsTeR")),
2345        "Expected the output buffer to be \"\\0oRrIsTeR\"\n");
2346 
2347     strcpy(buffer, "GoRrIsTeR");
2348     errno = EBADF;
2349     ret = p_strlwr_s(buffer, sizeof("GoRrIsTeR") - 1);
2350     ok(ret == EINVAL, "Expected _strlwr_s to return EINVAL, got %d\n", ret);
2351     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2352     ok(!memcmp(buffer, "\0oRrIsTeR", sizeof("\0oRrIsTeR")),
2353        "Expected the output buffer to be \"\\0oRrIsTeR\"\n");
2354 
2355     strcpy(buffer, "GoRrIsTeR");
2356     ret = p_strlwr_s(buffer, sizeof("GoRrIsTeR"));
2357     ok(ret == 0, "Expected _strlwr_s to return 0, got %d\n", ret);
2358     ok(!strcmp(buffer, "gorrister"),
2359        "Expected the output buffer to be \"gorrister\", got \"%s\"\n",
2360        buffer);
2361 
2362     memcpy(buffer, "GoRrIsTeR\0ELLEN", sizeof("GoRrIsTeR\0ELLEN"));
2363     ret = p_strlwr_s(buffer, sizeof(buffer));
2364     ok(ret == 0, "Expected _strlwr_s to return 0, got %d\n", ret);
2365     ok(!memcmp(buffer, "gorrister\0ELLEN", sizeof("gorrister\0ELLEN")),
2366        "Expected the output buffer to be \"gorrister\\0ELLEN\", got \"%s\"\n",
2367        buffer);
2368 }
2369 
2370 static void test_wcsncat_s(void)
2371 {
2372     static wchar_t abcW[] = {'a','b','c',0};
2373     int ret;
2374     wchar_t dst[4];
2375     wchar_t src[4];
2376 
2377     if (!p_wcsncat_s)
2378     {
2379         win_skip("skipping wcsncat_s tests\n");
2380         return;
2381     }
2382 
2383     memcpy(src, abcW, sizeof(abcW));
2384     dst[0] = 0;
2385     ret = p_wcsncat_s(NULL, 4, src, 4);
2386     ok(ret == EINVAL, "err = %d\n", ret);
2387     ret = p_wcsncat_s(dst, 0, src, 4);
2388     ok(ret == EINVAL, "err = %d\n", ret);
2389     ret = p_wcsncat_s(dst, 0, src, _TRUNCATE);
2390     ok(ret == EINVAL, "err = %d\n", ret);
2391     ret = p_wcsncat_s(dst, 4, NULL, 0);
2392     ok(ret == 0, "err = %d\n", ret);
2393 
2394     dst[0] = 0;
2395     ret = p_wcsncat_s(dst, 2, src, 4);
2396     ok(ret == ERANGE, "err = %d\n", ret);
2397 
2398     dst[0] = 0;
2399     ret = p_wcsncat_s(dst, 2, src, _TRUNCATE);
2400     ok(ret == STRUNCATE, "err = %d\n", ret);
2401     ok(dst[0] == 'a' && dst[1] == 0, "dst is %s\n", wine_dbgstr_w(dst));
2402 
2403     memcpy(dst, abcW, sizeof(abcW));
2404     dst[3] = 'd';
2405     ret = p_wcsncat_s(dst, 4, src, 4);
2406     ok(ret == EINVAL, "err = %d\n", ret);
2407 }
2408 
2409 static void test__mbsnbcat_s(void)
2410 {
2411     unsigned char dest[16];
2412     const unsigned char first[] = "dinosaur";
2413     const unsigned char second[] = "duck";
2414     int ret;
2415 
2416     if (!p_mbsnbcat_s)
2417     {
2418         win_skip("Skipping _mbsnbcat_s tests\n");
2419         return;
2420     }
2421 
2422     /* Test invalid arguments. */
2423     ret = p_mbsnbcat_s(NULL, 0, NULL, 0);
2424     ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
2425 
2426     errno = EBADF;
2427     ret = p_mbsnbcat_s(NULL, 10, NULL, 0);
2428     ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
2429     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2430 
2431     errno = EBADF;
2432     ret = p_mbsnbcat_s(NULL, 0, NULL, 10);
2433     ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
2434     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2435 
2436     memset(dest, 'X', sizeof(dest));
2437     errno = EBADF;
2438     ret = p_mbsnbcat_s(dest, 0, NULL, 0);
2439     ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
2440     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2441     ok(dest[0] == 'X', "Expected the output buffer to be untouched\n");
2442 
2443     memset(dest, 'X', sizeof(dest));
2444     errno = EBADF;
2445     ret = p_mbsnbcat_s(dest, 0, second, 0);
2446     ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
2447     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2448     ok(dest[0] == 'X', "Expected the output buffer to be untouched\n");
2449 
2450     memset(dest, 'X', sizeof(dest));
2451     errno = EBADF;
2452     ret = p_mbsnbcat_s(dest, sizeof(dest), NULL, 0);
2453     ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
2454     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2455     ok(dest[0] == '\0', "Expected the output buffer to be null terminated\n");
2456 
2457     memset(dest, 'X', sizeof(dest));
2458     errno = EBADF;
2459     ret = p_mbsnbcat_s(dest, sizeof(dest), NULL, 10);
2460     ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
2461     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2462     ok(dest[0] == '\0', "Expected the output buffer to be null terminated\n");
2463 
2464     memset(dest, 'X', sizeof(dest));
2465     dest[0] = '\0';
2466     ret = p_mbsnbcat_s(dest, sizeof(dest), second, sizeof(second));
2467     ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
2468     ok(!memcmp(dest, second, sizeof(second)),
2469        "Expected the output buffer string to be \"duck\"\n");
2470 
2471     /* Test source truncation behavior. */
2472     memset(dest, 'X', sizeof(dest));
2473     memcpy(dest, first, sizeof(first));
2474     ret = p_mbsnbcat_s(dest, sizeof(dest), second, 0);
2475     ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
2476     ok(!memcmp(dest, first, sizeof(first)),
2477        "Expected the output buffer string to be \"dinosaur\"\n");
2478 
2479     memset(dest, 'X', sizeof(dest));
2480     memcpy(dest, first, sizeof(first));
2481     ret = p_mbsnbcat_s(dest, sizeof(dest), second, sizeof(second));
2482     ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
2483     ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
2484        "Expected the output buffer string to be \"dinosaurduck\"\n");
2485 
2486     memset(dest, 'X', sizeof(dest));
2487     memcpy(dest, first, sizeof(first));
2488     ret = p_mbsnbcat_s(dest, sizeof(dest), second, sizeof(second) + 1);
2489     ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
2490     ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
2491        "Expected the output buffer string to be \"dinosaurduck\"\n");
2492 
2493     memset(dest, 'X', sizeof(dest));
2494     memcpy(dest, first, sizeof(first));
2495     ret = p_mbsnbcat_s(dest, sizeof(dest), second, sizeof(second) - 1);
2496     ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
2497     ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
2498        "Expected the output buffer string to be \"dinosaurduck\"\n");
2499 
2500     memset(dest, 'X', sizeof(dest));
2501     memcpy(dest, first, sizeof(first));
2502     ret = p_mbsnbcat_s(dest, sizeof(dest), second, sizeof(second) - 2);
2503     ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
2504     ok(!memcmp(dest, "dinosaurduc", sizeof("dinosaurduc")),
2505        "Expected the output buffer string to be \"dinosaurduc\"\n");
2506 
2507     /* Test destination truncation behavior. */
2508     memset(dest, 'X', sizeof(dest));
2509     memcpy(dest, first, sizeof(first));
2510     errno = EBADF;
2511     ret = p_mbsnbcat_s(dest, sizeof(first) - 1, second, sizeof(second));
2512     ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
2513     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2514     ok(!memcmp(dest, "\0inosaur", sizeof("\0inosaur") - 1),
2515        "Expected the output buffer string to be \"\\0inosaur\" without ending null terminator\n");
2516 
2517     memset(dest, 'X', sizeof(dest));
2518     memcpy(dest, first, sizeof(first));
2519     errno = EBADF;
2520     ret = p_mbsnbcat_s(dest, sizeof(first), second, sizeof(second));
2521     ok(ret == ERANGE, "Expected _mbsnbcat_s to return ERANGE, got %d\n", ret);
2522     ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
2523     ok(!memcmp(dest, "\0inosaurd", sizeof("\0inosaurd") - 1),
2524        "Expected the output buffer string to be \"\\0inosaurd\" without ending null terminator\n");
2525 
2526     memset(dest, 'X', sizeof(dest));
2527     memcpy(dest, first, sizeof(first));
2528     errno = EBADF;
2529     ret = p_mbsnbcat_s(dest, sizeof(first) + 1, second, sizeof(second));
2530     ok(ret == ERANGE, "Expected _mbsnbcat_s to return ERANGE, got %d\n", ret);
2531     ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
2532     ok(!memcmp(dest, "\0inosaurdu", sizeof("\0inosaurdu") - 1),
2533        "Expected the output buffer string to be \"\\0inosaurdu\" without ending null terminator\n");
2534 }
2535 
2536 static void test__mbsupr_s(void)
2537 {
2538     errno_t ret;
2539     unsigned char buffer[20];
2540 
2541     if (!p_mbsupr_s)
2542     {
2543         win_skip("Skipping _mbsupr_s tests\n");
2544         return;
2545     }
2546 
2547     errno = EBADF;
2548     ret = p_mbsupr_s(NULL, 0);
2549     ok(ret == 0, "Expected _mbsupr_s to return 0, got %d\n", ret);
2550 
2551     errno = EBADF;
2552     ret = p_mbsupr_s(NULL, sizeof(buffer));
2553     ok(ret == EINVAL, "Expected _mbsupr_s to return EINVAL, got %d\n", ret);
2554     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2555 
2556     errno = EBADF;
2557     ret = p_mbsupr_s(buffer, 0);
2558     ok(ret == EINVAL, "Expected _mbsupr_s to return EINVAL, got %d\n", ret);
2559     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2560 
2561     memcpy(buffer, "abcdefgh", sizeof("abcdefgh"));
2562     errno = EBADF;
2563     ret = p_mbsupr_s(buffer, sizeof("abcdefgh"));
2564     ok(ret == 0, "Expected _mbsupr_s to return 0, got %d\n", ret);
2565     ok(!memcmp(buffer, "ABCDEFGH", sizeof("ABCDEFGH")),
2566        "Expected the output buffer to be \"ABCDEFGH\", got \"%s\"\n",
2567        buffer);
2568 
2569     memcpy(buffer, "abcdefgh", sizeof("abcdefgh"));
2570     errno = EBADF;
2571     ret = p_mbsupr_s(buffer, sizeof(buffer));
2572     ok(ret == 0, "Expected _mbsupr_s to return 0, got %d\n", ret);
2573     ok(!memcmp(buffer, "ABCDEFGH", sizeof("ABCDEFGH")),
2574        "Expected the output buffer to be \"ABCDEFGH\", got \"%s\"\n",
2575        buffer);
2576 
2577     memcpy(buffer, "abcdefgh", sizeof("abcdefgh"));
2578     errno = EBADF;
2579     ret = p_mbsupr_s(buffer, 4);
2580     ok(ret == EINVAL, "Expected _mbsupr_s to return EINVAL, got %d\n", ret);
2581     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2582 
2583     memcpy(buffer, "abcdefgh\0ijklmnop", sizeof("abcdefgh\0ijklmnop"));
2584     errno = EBADF;
2585     ret = p_mbsupr_s(buffer, sizeof(buffer));
2586     ok(ret == 0, "Expected _mbsupr_s to return 0, got %d\n", ret);
2587     ok(!memcmp(buffer, "ABCDEFGH\0ijklmnop", sizeof("ABCDEFGH\0ijklmnop")),
2588        "Expected the output buffer to be \"ABCDEFGH\\0ijklmnop\", got \"%s\"\n",
2589        buffer);
2590 
2591 }
2592 
2593 static void test__mbslwr_s(void)
2594 {
2595     errno_t ret;
2596     unsigned char buffer[20];
2597 
2598     if (!p_mbslwr_s)
2599     {
2600         win_skip("Skipping _mbslwr_s tests\n");
2601         return;
2602     }
2603 
2604     errno = EBADF;
2605     ret = p_mbslwr_s(NULL, 0);
2606     ok(ret == 0, "Expected _mbslwr_s to return 0, got %d\n", ret);
2607 
2608     errno = EBADF;
2609     ret = p_mbslwr_s(NULL, sizeof(buffer));
2610     ok(ret == EINVAL, "Expected _mbslwr_s to return EINVAL, got %d\n", ret);
2611     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2612 
2613     errno = EBADF;
2614     ret = p_mbslwr_s(buffer, 0);
2615     ok(ret == EINVAL, "Expected _mbslwr_s to return EINVAL, got %d\n", ret);
2616     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2617 
2618     memcpy(buffer, "ABCDEFGH", sizeof("ABCDEFGH"));
2619     errno = EBADF;
2620     ret = p_mbslwr_s(buffer, sizeof("ABCDEFGH"));
2621     ok(ret == 0, "Expected _mbslwr_s to return 0, got %d\n", ret);
2622     ok(!memcmp(buffer, "abcdefgh", sizeof("abcdefgh")),
2623        "Expected the output buffer to be \"abcdefgh\", got \"%s\"\n",
2624        buffer);
2625 
2626     memcpy(buffer, "ABCDEFGH", sizeof("ABCDEFGH"));
2627     errno = EBADF;
2628     ret = p_mbslwr_s(buffer, sizeof(buffer));
2629     ok(ret == 0, "Expected _mbslwr_s to return 0, got %d\n", ret);
2630     ok(!memcmp(buffer, "abcdefgh", sizeof("abcdefgh")),
2631        "Expected the output buffer to be \"abcdefgh\", got \"%s\"\n",
2632        buffer);
2633 
2634     memcpy(buffer, "ABCDEFGH", sizeof("ABCDEFGH"));
2635     errno = EBADF;
2636     ret = p_mbslwr_s(buffer, 4);
2637     ok(ret == EINVAL, "Expected _mbslwr_s to return EINVAL, got %d\n", ret);
2638     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2639 
2640     memcpy(buffer, "ABCDEFGH\0IJKLMNOP", sizeof("ABCDEFGH\0IJKLMNOP"));
2641     errno = EBADF;
2642     ret = p_mbslwr_s(buffer, sizeof(buffer));
2643     ok(ret == 0, "Expected _mbslwr_s to return 0, got %d\n", ret);
2644     ok(!memcmp(buffer, "abcdefgh\0IJKLMNOP", sizeof("abcdefgh\0IJKLMNOP")),
2645        "Expected the output buffer to be \"abcdefgh\\0IJKLMNOP\", got \"%s\"\n",
2646        buffer);
2647 }
2648 
2649 static void test__mbstok(void)
2650 {
2651     const unsigned char delim[] = "t";
2652 
2653     char str[] = "!.!test";
2654     unsigned char *ret;
2655 
2656     strtok(str, "!");
2657 
2658     ret = _mbstok(NULL, delim);
2659     /* most versions of msvcrt use the same buffer for strtok and _mbstok */
2660     ok(!ret || broken((char*)ret==str+4),
2661             "_mbstok(NULL, \"t\") = %p, expected NULL (%p)\n", ret, str);
2662 
2663     ret = _mbstok(NULL, delim);
2664     ok(!ret, "_mbstok(NULL, \"t\") = %p, expected NULL\n", ret);
2665 }
2666 
2667 static void test__ultoa_s(void)
2668 {
2669     errno_t ret;
2670     char buffer[33];
2671 
2672     if (!p_ultoa_s)
2673     {
2674         win_skip("Skipping _ultoa_s tests\n");
2675         return;
2676     }
2677 
2678     errno = EBADF;
2679     ret = p_ultoa_s(0, NULL, 0, 0);
2680     ok(ret == EINVAL, "Expected _ultoa_s to return EINVAL, got %d\n", ret);
2681     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2682 
2683     memset(buffer, 'X', sizeof(buffer));
2684     errno = EBADF;
2685     ret = p_ultoa_s(0, buffer, 0, 0);
2686     ok(ret == EINVAL, "Expected _ultoa_s to return EINVAL, got %d\n", ret);
2687     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2688     ok(buffer[0] == 'X', "Expected the output buffer to be untouched\n");
2689 
2690     memset(buffer, 'X', sizeof(buffer));
2691     errno = EBADF;
2692     ret = p_ultoa_s(0, buffer, sizeof(buffer), 0);
2693     ok(ret == EINVAL, "Expected _ultoa_s to return EINVAL, got %d\n", ret);
2694     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2695     ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
2696 
2697     memset(buffer, 'X', sizeof(buffer));
2698     errno = EBADF;
2699     ret = p_ultoa_s(0, buffer, sizeof(buffer), 64);
2700     ok(ret == EINVAL, "Expected _ultoa_s to return EINVAL, got %d\n", ret);
2701     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2702     ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
2703 
2704     memset(buffer, 'X', sizeof(buffer));
2705     errno = EBADF;
2706     ret = p_ultoa_s(12345678, buffer, 4, 10);
2707     ok(ret == ERANGE, "Expected _ultoa_s to return ERANGE, got %d\n", ret);
2708     ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
2709     ok(!memcmp(buffer, "\000765", 4),
2710        "Expected the output buffer to be null terminated with truncated output\n");
2711 
2712     memset(buffer, 'X', sizeof(buffer));
2713     errno = EBADF;
2714     ret = p_ultoa_s(12345678, buffer, 8, 10);
2715     ok(ret == ERANGE, "Expected _ultoa_s to return ERANGE, got %d\n", ret);
2716     ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
2717     ok(!memcmp(buffer, "\0007654321", 8),
2718        "Expected the output buffer to be null terminated with truncated output\n");
2719 
2720     ret = p_ultoa_s(12345678, buffer, 9, 10);
2721     ok(ret == 0, "Expected _ultoa_s to return 0, got %d\n", ret);
2722     ok(!strcmp(buffer, "12345678"),
2723        "Expected output buffer string to be \"12345678\", got \"%s\"\n",
2724        buffer);
2725 
2726     ret = p_ultoa_s(43690, buffer, sizeof(buffer), 2);
2727     ok(ret == 0, "Expected _ultoa_s to return 0, got %d\n", ret);
2728     ok(!strcmp(buffer, "1010101010101010"),
2729        "Expected output buffer string to be \"1010101010101010\", got \"%s\"\n",
2730        buffer);
2731 
2732     ret = p_ultoa_s(1092009, buffer, sizeof(buffer), 36);
2733     ok(ret == 0, "Expected _ultoa_s to return 0, got %d\n", ret);
2734     ok(!strcmp(buffer, "nell"),
2735        "Expected output buffer string to be \"nell\", got \"%s\"\n",
2736        buffer);
2737 
2738     ret = p_ultoa_s(5704, buffer, sizeof(buffer), 18);
2739     ok(ret == 0, "Expected _ultoa_s to return 0, got %d\n", ret);
2740     ok(!strcmp(buffer, "hag"),
2741        "Expected output buffer string to be \"hag\", got \"%s\"\n",
2742        buffer);
2743 }
2744 
2745 static void test_wctob(void)
2746 {
2747     int ret, cp = _getmbcp();
2748 
2749     if(!p_wctob || !setlocale(LC_ALL, "chinese-traditional")) {
2750         win_skip("Skipping wctob tests\n");
2751         return;
2752     }
2753 
2754     ret = p_wctob(0x8141);
2755     ok(ret == EOF, "ret = %x\n", ret);
2756 
2757     ret = p_wctob(0x81);
2758     ok(ret == EOF, "ret = %x\n", ret);
2759 
2760     ret = p_wctob(0xe0);
2761     ok(ret == 0x61, "ret = %x\n", ret);
2762 
2763     _setmbcp(1250);
2764     ret = p_wctob(0x81);
2765     ok(ret == EOF, "ret = %x\n", ret);
2766 
2767     setlocale(LC_ALL, "C");
2768     ret = p_wctob(0x8141);
2769     ok(ret == EOF, "ret = %x\n", ret);
2770 
2771     ret = p_wctob(0x81);
2772     ok(ret == (int)(char)0x81, "ret = %x\n", ret);
2773 
2774     ret = p_wctob(0x9f);
2775     ok(ret == (int)(char)0x9f, "ret = %x\n", ret);
2776 
2777     ret = p_wctob(0xe0);
2778     ok(ret == (int)(char)0xe0, "ret = %x\n", ret);
2779 
2780     _setmbcp(cp);
2781 }
2782 
2783 static void test_wctomb(void)
2784 {
2785     mbstate_t state;
2786     unsigned char dst[10];
2787     size_t ret;
2788     int err;
2789 
2790     if(!p_wcrtomb || !setlocale(LC_ALL, "Japanese_Japan.932")) {
2791         win_skip("wcrtomb tests\n");
2792         return;
2793     }
2794 
2795     ret = p_wcrtomb(NULL, 0x3042, NULL);
2796     ok(ret == 2, "wcrtomb did not return 2\n");
2797 
2798     state = 1;
2799     dst[2] = 'a';
2800     ret = p_wcrtomb((char*)dst, 0x3042, &state);
2801     ok(ret == 2, "wcrtomb did not return 2\n");
2802     ok(state == 0, "state != 0\n");
2803     ok(dst[0] == 0x82, "dst[0] = %x, expected 0x82\n", dst[0]);
2804     ok(dst[1] == 0xa0, "dst[1] = %x, expected 0xa0\n", dst[1]);
2805     ok(dst[2] == 'a', "dst[2] != 'a'\n");
2806 
2807     ret = p_wcrtomb((char*)dst, 0x3043, NULL);
2808     ok(ret == 2, "wcrtomb did not return 2\n");
2809     ok(dst[0] == 0x82, "dst[0] = %x, expected 0x82\n", dst[0]);
2810     ok(dst[1] == 0xa1, "dst[1] = %x, expected 0xa1\n", dst[1]);
2811 
2812     ret = p_wcrtomb((char*)dst, 0x20, NULL);
2813     ok(ret == 1, "wcrtomb did not return 1\n");
2814     ok(dst[0] == 0x20, "dst[0] = %x, expected 0x20\n", dst[0]);
2815 
2816     ret = p_wcrtomb((char*)dst, 0xffff, NULL);
2817     ok(ret == -1, "wcrtomb did not return -1\n");
2818     ok(dst[0] == 0x3f, "dst[0] = %x, expected 0x3f\n", dst[0]);
2819 
2820     if(!p_wcrtomb_s) {
2821         win_skip("wcrtomb_s tests\n");
2822         setlocale(LC_ALL, "C");
2823         return;
2824     }
2825 
2826     state = 1;
2827     dst[2] = 'a';
2828     err = p_wcrtomb_s(&ret, (char*)dst, sizeof(dst), 0x3042, &state);
2829     ok(!err, "err = %d\n", err);
2830     ok(ret == 2, "ret != 2\n");
2831     ok(!state, "state != 0\n");
2832     ok(dst[0] == 0x82, "dst[0] = %x, expected 0x82\n", dst[0]);
2833     ok(dst[1] == 0xa0, "dst[1] = %x, expected 0xa0\n", dst[1]);
2834     ok(dst[2] == 'a', "dst[2] != 'a'\n");
2835 
2836     err = p_wcrtomb_s(&ret, (char*)dst, sizeof(dst), 0x3042, NULL);
2837     ok(!err, "err = %d\n", err);
2838     ok(ret == 2, "ret != 2\n");
2839     ok(!state, "state != 0\n");
2840     ok(dst[0] == 0x82, "dst[0] = %x, expected 0x82\n", dst[0]);
2841     ok(dst[1] == 0xa0, "dst[1] = %x, expected 0xa0\n", dst[1]);
2842 
2843     err = p_wcrtomb_s(&ret, (char*)dst, sizeof(dst), 0x20, NULL);
2844     ok(!err, "err = %d\n", err);
2845     ok(ret == 1, "ret != 1\n");
2846     ok(dst[0] == 0x20, "dst[0] = %x, expected 0x20\n", dst[0]);
2847 
2848     err = p_wcrtomb_s(&ret, NULL, 0, 0x20, NULL);
2849     ok(!err, "err = %d\n", err);
2850     ok(ret == 1, "ret != 1\n");
2851 
2852     err = p_wcrtomb_s(&ret, (char*)dst, sizeof(dst), 0xffff, NULL);
2853     ok(err == EILSEQ, "err = %d\n", err);
2854     ok(ret == -1, "wcrtomb did not return -1\n");
2855     ok(dst[0] == 0x3f, "dst[0] = %x, expected 0x3f\n", dst[0]);
2856 
2857     setlocale(LC_ALL, "C");
2858 }
2859 
2860 static void test_tolower(void)
2861 {
2862     WCHAR chw, lower;
2863     char ch, lch;
2864     int ret, len;
2865 
2866     /* test C locale when locale was never changed */
2867     ret = p_tolower(0x41);
2868     ok(ret == 0x61, "ret = %x\n", ret);
2869 
2870     ret = p_tolower(0xF4);
2871     ok(ret == 0xF4, "ret = %x\n", ret);
2872 
2873     errno = 0xdeadbeef;
2874     ret = p_tolower((char)0xF4);
2875     ok(ret == (char)0xF4, "ret = %x\n", ret);
2876     ok(errno == 0xdeadbeef, "errno = %d\n", errno);
2877 
2878     errno = 0xdeadbeef;
2879     ret = p_tolower((char)0xD0);
2880     ok(ret == (char)0xD0, "ret = %x\n", ret);
2881     ok(errno == 0xdeadbeef, "errno = %d\n", errno);
2882 
2883     setlocale(LC_ALL, "C");
2884     errno = 0xdeadbeef;
2885     ret = p_tolower((char)0xF4);
2886     ok(ret == (char)0xF4, "ret = %x\n", ret);
2887     ok(errno == 0xdeadbeef, "errno = %d\n", errno);
2888 
2889     /* test C locale after setting locale */
2890     if(!setlocale(LC_ALL, "us")) {
2891         win_skip("skipping tolower tests that depends on locale\n");
2892         return;
2893     }
2894     setlocale(LC_ALL, "C");
2895 
2896     ch = 0xF4;
2897     errno = 0xdeadbeef;
2898     ret = p_tolower(ch);
2899     if(!MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, &ch, 1, &chw, 1) ||
2900             LCMapStringW(CP_ACP, LCMAP_LOWERCASE, &chw, 1, &lower, 1) != 1 ||
2901             (len = WideCharToMultiByte(CP_ACP, 0, &lower, 1, &lch, 1, NULL, NULL)) != 1)
2902         len = 0;
2903     if(len)
2904         ok(ret==(unsigned char)lch || broken(ret==ch)/*WinXP-*/, "ret = %x\n", ret);
2905     else
2906         ok(ret == ch, "ret = %x\n", ret);
2907     if(!len || ret==(unsigned char)lch)
2908         ok(errno == EILSEQ, "errno = %d\n", errno);
2909 
2910     ch = 0xD0;
2911     errno = 0xdeadbeef;
2912     ret = p_tolower(ch);
2913     if(!MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, &ch, 1, &chw, 1) ||
2914             LCMapStringW(CP_ACP, LCMAP_LOWERCASE, &chw, 1, &lower, 1) != 1 ||
2915             (len = WideCharToMultiByte(CP_ACP, 0, &lower, 1, &lch, 1, NULL, NULL)) != 1)
2916         len = 0;
2917     if(len)
2918         ok(ret==(unsigned char)lch || broken(ret==ch)/*WinXP-*/, "ret = %x\n", ret);
2919     else
2920         ok(ret == ch, "ret = %x\n", ret);
2921     if(!len || ret==(unsigned char)lch)
2922         ok(errno == EILSEQ, "errno = %d\n", errno);
2923 
2924     ret = p_tolower(0xD0);
2925     ok(ret == 0xD0, "ret = %x\n", ret);
2926 
2927     ok(setlocale(LC_ALL, "us") != NULL, "setlocale failed\n");
2928 
2929     ret = p_tolower((char)0xD0);
2930     ok(ret == 0xF0, "ret = %x\n", ret);
2931 
2932     ret = p_tolower(0xD0);
2933     ok(ret == 0xF0, "ret = %x\n", ret);
2934 
2935     setlocale(LC_ALL, "C");
2936 }
2937 
2938 static void test__atodbl(void)
2939 {
2940     _CRT_DOUBLE d;
2941     char num[32];
2942     int ret;
2943 
2944     if(!p__atodbl_l) {
2945         /* Old versions of msvcrt use different values for _OVERFLOW and _UNDERFLOW
2946          * Because of this lets skip _atodbl tests when _atodbl_l is not available */
2947         win_skip("_atodbl_l is not available\n");
2948         return;
2949     }
2950 
2951     num[0] = 0;
2952     ret = p__atodbl_l(&d, num, NULL);
2953     ok(ret == 0, "_atodbl_l(&d, \"\", NULL) returned %d, expected 0\n", ret);
2954     ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
2955     ret = _atodbl(&d, num);
2956     ok(ret == 0, "_atodbl(&d, \"\") returned %d, expected 0\n", ret);
2957     ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
2958 
2959     strcpy(num, "t");
2960     ret = p__atodbl_l(&d, num, NULL);
2961     ok(ret == 0, "_atodbl_l(&d, \"t\", NULL) returned %d, expected 0\n", ret);
2962     ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
2963     ret = _atodbl(&d, num);
2964     ok(ret == 0, "_atodbl(&d, \"t\") returned %d, expected 0\n", ret);
2965     ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
2966 
2967     strcpy(num, "0");
2968     ret = p__atodbl_l(&d, num, NULL);
2969     ok(ret == 0, "_atodbl_l(&d, \"0\", NULL) returned %d, expected 0\n", ret);
2970     ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
2971     ret = _atodbl(&d, num);
2972     ok(ret == 0, "_atodbl(&d, \"0\") returned %d, expected 0\n", ret);
2973     ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
2974 
2975     strcpy(num, "123");
2976     ret = p__atodbl_l(&d, num, NULL);
2977     ok(ret == 0, "_atodbl_l(&d, \"123\", NULL) returned %d, expected 0\n", ret);
2978     ok(d.x == 123, "d.x = %lf, expected 123\n", d.x);
2979     ret = _atodbl(&d, num);
2980     ok(ret == 0, "_atodbl(&d, \"123\") returned %d, expected 0\n", ret);
2981     ok(d.x == 123, "d.x = %lf, expected 123\n", d.x);
2982 
2983     strcpy(num, "1e-309");
2984     ret = p__atodbl_l(&d, num, NULL);
2985     ok(ret == _UNDERFLOW, "_atodbl_l(&d, \"1e-309\", NULL) returned %d, expected _UNDERFLOW\n", ret);
2986     ok(d.x!=0 && almost_equal(d.x, 0), "d.x = %le, expected 0\n", d.x);
2987     ret = _atodbl(&d, num);
2988     ok(ret == _UNDERFLOW, "_atodbl(&d, \"1e-309\") returned %d, expected _UNDERFLOW\n", ret);
2989     ok(d.x!=0 && almost_equal(d.x, 0), "d.x = %le, expected 0\n", d.x);
2990 
2991     strcpy(num, "1e309");
2992     ret = p__atodbl_l(&d, num, NULL);
2993     ok(ret == _OVERFLOW, "_atodbl_l(&d, \"1e309\", NULL) returned %d, expected _OVERFLOW\n", ret);
2994     ret = _atodbl(&d, num);
2995     ok(ret == _OVERFLOW, "_atodbl(&d, \"1e309\") returned %d, expected _OVERFLOW\n", ret);
2996 }
2997 
2998 static void test__stricmp(void)
2999 {
3000     int ret;
3001 
3002     ret = _stricmp("test", "test");
3003     ok(ret == 0, "_stricmp returned %d\n", ret);
3004     ret = _stricmp("a", "z");
3005     ok(ret < 0, "_stricmp returned %d\n", ret);
3006     ret = _stricmp("z", "a");
3007     ok(ret > 0, "_stricmp returned %d\n", ret);
3008     ret = _stricmp("\xa5", "\xb9");
3009     ok(ret < 0, "_stricmp returned %d\n", ret);
3010 
3011     if(!setlocale(LC_ALL, "polish")) {
3012         win_skip("stricmp tests\n");
3013         return;
3014     }
3015 
3016     ret = _stricmp("test", "test");
3017     ok(ret == 0, "_stricmp returned %d\n", ret);
3018     ret = _stricmp("a", "z");
3019     ok(ret < 0, "_stricmp returned %d\n", ret);
3020     ret = _stricmp("z", "a");
3021     ok(ret > 0, "_stricmp returned %d\n", ret);
3022     ret = _stricmp("\xa5", "\xb9");
3023     ok(ret == 0, "_stricmp returned %d\n", ret);
3024     ret = _stricmp("a", "\xb9");
3025     ok(ret < 0, "_stricmp returned %d\n", ret);
3026 
3027     setlocale(LC_ALL, "C");
3028 }
3029 
3030 static void test__wcstoi64(void)
3031 {
3032     static const WCHAR digit[] = { '9', 0 };
3033     static const WCHAR space[] = { ' ', 0 };
3034     static const WCHAR stock[] = { 0x3231, 0 }; /* PARENTHESIZED IDEOGRAPH STOCK */
3035     static const WCHAR cjk_1[] = { 0x4e00, 0 }; /* CJK Ideograph, First */
3036     static const WCHAR tamil[] = { 0x0bef, 0 }; /* TAMIL DIGIT NINE */
3037     static const WCHAR thai[]  = { 0x0e59, 0 }; /* THAI DIGIT NINE */
3038     static const WCHAR fullwidth[] = { 0xff19, 0 }; /* FULLWIDTH DIGIT NINE */
3039     static const WCHAR superscript1[] = { 0xb9, 0 }; /* SUPERSCRIPT ONE */
3040     static const WCHAR minus_0x91[]  = { '-', 0x0e50, 'x', 0xff19, '1', 0 };
3041     static const WCHAR plus_071[]  = { '+', 0x0e50, 0xff17, '1', 0 };
3042     static const WCHAR hex[] = { 0xff19, 'f', 0x0e59, 0xff46, 0 };
3043     static const WCHAR zeros[] = {
3044         0x660, 0x6f0, 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xc66, 0xce6,
3045         0xd66, 0xe50, 0xed0, 0xf20, 0x1040, 0x17e0, 0x1810, 0xff10
3046     };
3047     int i;
3048 
3049     __int64 res;
3050     unsigned __int64 ures;
3051     WCHAR *endpos;
3052 
3053     if (!p_wcstoi64 || !p_wcstoui64) {
3054         win_skip("_wcstoi64 or _wcstoui64 not found\n");
3055         return;
3056     }
3057 
3058     res = p_wcstoi64(digit, NULL, 10);
3059     ok(res == 9, "res != 9\n");
3060     res = p_wcstoi64(space, &endpos, 0);
3061     ok(endpos == space, "endpos != space\n");
3062     res = p_wcstoi64(stock, &endpos, 10);
3063     ok(res == 0, "res != 0\n");
3064     ok(endpos == stock, "Incorrect endpos (%p-%p)\n", stock, endpos);
3065     res = p_wcstoi64(cjk_1, NULL, 0);
3066     ok(res == 0, "res != 0\n");
3067     res = p_wcstoi64(tamil, &endpos, 10);
3068     ok(res == 0, "res != 0\n");
3069     ok(endpos == tamil, "Incorrect endpos (%p-%p)\n", tamil, endpos);
3070     res = p_wcstoi64(thai, NULL, 10);
3071     ok(res == 9, "res != 9\n");
3072     res = p_wcstoi64(fullwidth, NULL, 10);
3073     ok(res == 9, "res != 9\n");
3074     res = p_wcstoi64(superscript1, NULL, 10);
3075     ok(res == 0, "res != 0\n");
3076     res = p_wcstoi64(hex, NULL, 16);
3077     ok(res == 0x9f9, "res != 0x9f9\n");
3078     res = p_wcstoi64(minus_0x91, NULL, 0);
3079     ok(res == -0x91, "res != -0x91\n");
3080     res = p_wcstoi64(plus_071, NULL, 0);
3081     ok(res == 071, "res != 071\n");
3082 
3083     ures = p_wcstoui64(digit, NULL, 10);
3084     ok(ures == 9, "ures != 9\n");
3085     ures = p_wcstoui64(space, &endpos, 0);
3086     ok(endpos == space, "endpos != space\n");
3087     ures = p_wcstoui64(stock, &endpos, 10);
3088     ok(ures == 0, "ures != 0\n");
3089     ok(endpos == stock, "Incorrect endpos (%p-%p)\n", stock, endpos);
3090     ures = p_wcstoui64(tamil, &endpos, 10);
3091     ok(ures == 0, "ures != 0\n");
3092     ok(endpos == tamil, "Incorrect endpos (%p-%p)\n", tamil, endpos);
3093     ures = p_wcstoui64(thai, NULL, 10);
3094     ok(ures == 9, "ures != 9\n");
3095     ures = p_wcstoui64(fullwidth, NULL, 10);
3096     ok(ures == 9, "ures != 9\n");
3097     ures = p_wcstoui64(superscript1, NULL, 10);
3098     ok(ures == 0, "ures != 0\n");
3099     ures = p_wcstoui64(hex, NULL, 16);
3100     ok(ures == 0x9f9, "ures != 0x9f9\n");
3101     ures = p_wcstoui64(plus_071, NULL, 0);
3102     ok(ures == 071, "ures != 071\n");
3103 
3104     /* Test various unicode digits */
3105     for (i = 0; i < ARRAY_SIZE(zeros); ++i) {
3106         WCHAR tmp[] = {zeros[i] + 4, zeros[i], zeros[i] + 5, 0};
3107         res = p_wcstoi64(tmp, NULL, 0);
3108         ok(res == 405, "with zero = U+%04X: got %d, expected 405\n", zeros[i], (int)res);
3109         tmp[1] = zeros[i] + 10;
3110         res = p_wcstoi64(tmp, NULL, 16);
3111         ok(res == 4, "with zero = U+%04X: got %d, expected 4\n", zeros[i], (int)res);
3112     }
3113 
3114     return;
3115 }
3116 
3117 static void test_atoi(void)
3118 {
3119     int r;
3120 
3121     r = atoi("0");
3122     ok(r == 0, "atoi(0) = %d\n", r);
3123 
3124     r = atoi("-1");
3125     ok(r == -1, "atoi(-1) = %d\n", r);
3126 
3127     r = atoi("1");
3128     ok(r == 1, "atoi(1) = %d\n", r);
3129 
3130     r = atoi("4294967296");
3131     ok(r == 0, "atoi(4294967296) = %d\n", r);
3132 }
3133 
3134 static void test_atol(void)
3135 {
3136     int r;
3137 
3138     r = atol("0");
3139     ok(r == 0, "atol(0) = %d\n", r);
3140 
3141     r = atol("-1");
3142     ok(r == -1, "atol(-1) = %d\n", r);
3143 
3144     r = atol("1");
3145     ok(r == 1, "atol(1) = %d\n", r);
3146 
3147     r = atol("4294967296");
3148     ok(r == 0, "atol(4294967296) = %d\n", r);
3149 }
3150 
3151 static void test_atof(void)
3152 {
3153     double d;
3154 
3155     d = atof("0.0");
3156     ok(almost_equal(d, 0.0), "d = %lf\n", d);
3157 
3158     d = atof("1.0");
3159     ok(almost_equal(d, 1.0), "d = %lf\n", d);
3160 
3161     d = atof("-1.0");
3162     ok(almost_equal(d, -1.0), "d = %lf\n", d);
3163 
3164     if (!p__atof_l)
3165     {
3166         win_skip("_atof_l not found\n");
3167         return;
3168     }
3169 
3170     errno = EBADF;
3171     d = atof(NULL);
3172     ok(almost_equal(d, 0.0), "d = %lf\n", d);
3173     ok(errno == EINVAL, "errno = %x\n", errno);
3174 
3175     errno = EBADF;
3176     d = p__atof_l(NULL, NULL);
3177     ok(almost_equal(d, 0.0), "d = %lf\n", d);
3178     ok(errno == EINVAL, "errno = %x\n", errno);
3179 }
3180 
3181 static void test_strncpy(void)
3182 {
3183 #define TEST_STRNCPY_LEN 10
3184     /* use function pointer to bypass gcc builtin */
3185     char *(__cdecl *p_strncpy)(char*,const char*,size_t);
3186     char *ret;
3187     char dst[TEST_STRNCPY_LEN + 1];
3188     char not_null_terminated[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
3189 
3190     p_strncpy = (void *)GetProcAddress( GetModuleHandleA("msvcrt.dll"), "strncpy");
3191 
3192     /* strlen(src) > TEST_STRNCPY_LEN */
3193     ret = p_strncpy(dst, "01234567890123456789", TEST_STRNCPY_LEN);
3194     ok(ret == dst, "ret != dst\n");
3195     ok(!strncmp(dst, "0123456789", TEST_STRNCPY_LEN), "dst != 0123456789\n");
3196 
3197     /* without null-terminated */
3198     ret = p_strncpy(dst, not_null_terminated, TEST_STRNCPY_LEN);
3199     ok(ret == dst, "ret != dst\n");
3200     ok(!strncmp(dst, "0123456789", TEST_STRNCPY_LEN), "dst != 0123456789\n");
3201 
3202     /* strlen(src) < TEST_STRNCPY_LEN */
3203     strcpy(dst, "0123456789");
3204     ret = p_strncpy(dst, "012345", TEST_STRNCPY_LEN);
3205     ok(ret == dst, "ret != dst\n");
3206     ok(!strcmp(dst, "012345"), "dst != 012345\n");
3207     ok(dst[TEST_STRNCPY_LEN - 1] == '\0', "dst[TEST_STRNCPY_LEN - 1] != 0\n");
3208 
3209     /* strlen(src) == TEST_STRNCPY_LEN */
3210     ret = p_strncpy(dst, "0123456789", TEST_STRNCPY_LEN);
3211     ok(ret == dst, "ret != dst\n");
3212     ok(!strncmp(dst, "0123456789", TEST_STRNCPY_LEN), "dst != 0123456789\n");
3213 }
3214 
3215 static void test_strxfrm(void)
3216 {
3217     char dest[256];
3218     size_t ret;
3219 
3220     /* crashes on old version of msvcrt */
3221     if(p__atodbl_l) {
3222         errno = 0xdeadbeef;
3223         ret = strxfrm(NULL, "src", 1);
3224         ok(ret == INT_MAX, "ret = %d\n", (int)ret);
3225         ok(errno == EINVAL, "errno = %d\n", errno);
3226 
3227         errno = 0xdeadbeef;
3228         ret = strxfrm(dest, NULL, 100);
3229         ok(ret == INT_MAX, "ret = %d\n", (int)ret);
3230         ok(errno == EINVAL, "errno = %d\n", errno);
3231     }
3232 
3233     ret = strxfrm(NULL, "src", 0);
3234     ok(ret == 3, "ret = %d\n", (int)ret);
3235     dest[0] = 'a';
3236     ret = strxfrm(dest, "src", 0);
3237     ok(ret == 3, "ret = %d\n", (int)ret);
3238     ok(dest[0] == 'a', "dest[0] = %d\n", dest[0]);
3239 
3240     dest[3] = 'a';
3241     ret = strxfrm(dest, "src", 5);
3242     ok(ret == 3, "ret = %d\n", (int)ret);
3243     ok(!strcmp(dest, "src"), "dest = %s\n", dest);
3244 
3245     errno = 0xdeadbeef;
3246     dest[1] = 'a';
3247     ret = strxfrm(dest, "src", 1);
3248     ok(ret == 3, "ret = %d\n", (int)ret);
3249     ok(dest[0] == 's', "dest[0] = %d\n", dest[0]);
3250     ok(dest[1] == 'a', "dest[1] = %d\n", dest[1]);
3251     ok(errno == 0xdeadbeef, "errno = %d\n", errno);
3252 
3253     ret = strxfrm(dest, "", 5);
3254     ok(ret == 0, "ret = %d\n", (int)ret);
3255     ok(!dest[0], "dest[0] = %d\n", dest[0]);
3256 
3257     if(!setlocale(LC_ALL, "polish")) {
3258         win_skip("stxfrm tests\n");
3259         return;
3260     }
3261 
3262     ret = strxfrm(NULL, "src", 0);
3263     ok(ret < sizeof(dest)-1, "ret = %d\n", (int)ret);
3264     dest[0] = 'a';
3265     ret = strxfrm(dest, "src", 0);
3266     ok(ret < sizeof(dest)-1, "ret = %d\n", (int)ret);
3267     ok(dest[0] == 'a', "dest[0] = %d\n", dest[0]);
3268 
3269     ret = strxfrm(dest, "src", ret+1);
3270     ok(ret < sizeof(dest)-1, "ret = %d\n", (int)ret);
3271     ok(dest[0], "dest[0] = 0\n");
3272 
3273     errno = 0xdeadbeef;
3274     dest[0] = 'a';
3275     ret = strxfrm(dest, "src", 5);
3276     ok(ret>5 && ret<sizeof(dest)-1, "ret = %d\n", (int)ret);
3277     ok(!dest[0] || broken(!p__atodbl_l && dest[0]=='a'), "dest[0] = %d\n", dest[0]);
3278 
3279     setlocale(LC_ALL, "C");
3280 }
3281 
3282 static void test__strnset_s(void)
3283 {
3284     char buf[5] = {0};
3285     int r;
3286 
3287     if(!p__strnset_s) {
3288         win_skip("_strnset_s not available\n");
3289         return;
3290     }
3291 
3292     r = p__strnset_s(NULL, 0, 'a', 0);
3293     ok(r == 0, "r = %d\n", r);
3294 
3295     buf[0] = buf[1] = buf[2] = 'b';
3296     r = p__strnset_s(buf, sizeof(buf), 'a', 2);
3297     ok(r == 0, "r = %d\n", r);
3298     ok(!strcmp(buf, "aab"), "buf = %s\n", buf);
3299 
3300     r = p__strnset_s(buf, 0, 'a', 0);
3301     ok(r == EINVAL, "r = %d\n", r);
3302 
3303     r = p__strnset_s(NULL, 0, 'a', 1);
3304     ok(r == EINVAL, "r = %d\n", r);
3305 
3306     buf[3] = 'b';
3307     r = p__strnset_s(buf, sizeof(buf)-1, 'c', 2);
3308     ok(r == EINVAL, "r = %d\n", r);
3309     ok(!buf[0] && buf[1]=='c' && buf[2]=='b', "buf = %s\n", buf);
3310 }
3311 
3312 static void test__wcsnset_s(void)
3313 {
3314     wchar_t text[] = { 't','e','x','t',0 };
3315     int r;
3316 
3317     if(!p__wcsnset_s) {
3318         win_skip("_wcsnset_s not available\n");
3319         return;
3320     }
3321 
3322     r = p__wcsnset_s(NULL, 0, 'a', 0);
3323     ok(r == 0, "r = %d\n", r);
3324 
3325     r = p__wcsnset_s(text, 0, 'a', 1);
3326     ok(r == EINVAL, "r = %d\n", r);
3327     ok(text[0] == 't', "text[0] = %d\n", text[0]);
3328 
3329     r = p__wcsnset_s(NULL, 2, 'a', 1);
3330     ok(r == EINVAL, "r = %d\n", r);
3331 
3332     r = p__wcsnset_s(text, 2, 'a', 3);
3333     ok(r == EINVAL, "r = %d\n", r);
3334     ok(text[0] == 0, "text[0] = %d\n", text[0]);
3335     ok(text[1] == 'e', "text[1] = %d\n", text[1]);
3336 
3337     text[0] = 't';
3338     r = p__wcsnset_s(text, 5, 'a', 1);
3339     ok(r == 0, "r = %d\n", r);
3340     ok(text[0] == 'a', "text[0] = %d\n", text[0]);
3341     ok(text[1] == 'e', "text[1] = %d\n", text[1]);
3342 
3343     text[1] = 0;
3344     r = p__wcsnset_s(text, 5, 'b', 3);
3345     ok(r == 0, "r = %d\n", r);
3346     ok(text[0] == 'b', "text[0] = %d\n", text[0]);
3347     ok(text[1] == 0, "text[1] = %d\n", text[1]);
3348     ok(text[2] == 'x', "text[2] = %d\n", text[2]);
3349 }
3350 
3351 static void test__wcsset_s(void)
3352 {
3353     wchar_t str[10];
3354     int r;
3355 
3356     if(!p__wcsset_s) {
3357         win_skip("_wcsset_s not available\n");
3358         return;
3359     }
3360 
3361     r = p__wcsset_s(NULL, 0, 'a');
3362     ok(r == EINVAL, "r = %d\n", r);
3363 
3364     str[0] = 'a';
3365     r = p__wcsset_s(str, 0, 'a');
3366     ok(r == EINVAL, "r = %d\n", r);
3367     ok(str[0] == 'a', "str[0] = %d\n", str[0]);
3368 
3369     str[0] = 'a';
3370     str[1] = 'b';
3371     r = p__wcsset_s(str, 2, 'c');
3372     ok(r == EINVAL, "r = %d\n", r);
3373     ok(!str[0], "str[0] = %d\n", str[0]);
3374     ok(str[1] == 'b', "str[1] = %d\n", str[1]);
3375 
3376     str[0] = 'a';
3377     str[1] = 0;
3378     str[2] = 'b';
3379     r = p__wcsset_s(str, 3, 'c');
3380     ok(r == 0, "r = %d\n", r);
3381     ok(str[0] == 'c', "str[0] = %d\n", str[0]);
3382     ok(str[1] == 0, "str[1] = %d\n", str[1]);
3383     ok(str[2] == 'b', "str[2] = %d\n", str[2]);
3384 }
3385 
3386 static void test__mbscmp(void)
3387 {
3388     static const unsigned char a[] = {'a',0}, b[] = {'b',0};
3389     int ret;
3390 
3391     if (!p_mbrlen)
3392     {
3393         win_skip("_mbscmp tests\n");
3394         return;
3395     }
3396 
3397     ret = _mbscmp(NULL, NULL);
3398     ok(ret == INT_MAX, "got %d\n", ret);
3399 
3400     ret = _mbscmp(a, NULL);
3401     ok(ret == INT_MAX, "got %d\n", ret);
3402 
3403     ret = _mbscmp(NULL, a);
3404     ok(ret == INT_MAX, "got %d\n", ret);
3405 
3406     ret = _mbscmp(a, a);
3407     ok(!ret, "got %d\n", ret);
3408 
3409     ret = _mbscmp(a, b);
3410     ok(ret == -1, "got %d\n", ret);
3411 
3412     ret = _mbscmp(b, a);
3413     ok(ret == 1, "got %d\n", ret);
3414 }
3415 
3416 static void test__ismbclx(void)
3417 {
3418     int ret, cp = _getmbcp();
3419 
3420     ret = _ismbcl0(0);
3421     ok(!ret, "got %d\n", ret);
3422 
3423     ret = _ismbcl1(0);
3424     ok(!ret, "got %d\n", ret);
3425 
3426     ret = _ismbcl2(0);
3427     ok(!ret, "got %d\n", ret);
3428 
3429     _setmbcp(1252);
3430 
3431     ret = _ismbcl0(0x8140);
3432     ok(!ret, "got %d\n", ret);
3433 
3434     ret = _ismbcl1(0x889f);
3435     ok(!ret, "got %d\n", ret);
3436 
3437     ret = _ismbcl2(0x989f);
3438     ok(!ret, "got %d\n", ret);
3439 
3440     _setmbcp(932);
3441 
3442     ret = _ismbcl0(0);
3443     ok(!ret, "got %d\n", ret);
3444 
3445     ret = _ismbcl0(0x8140);
3446     ok(ret, "got %d\n", ret);
3447 
3448     ret = _ismbcl0(0x817f);
3449     ok(!ret, "got %d\n", ret);
3450 
3451     ret = _ismbcl1(0);
3452     ok(!ret, "got %d\n", ret);
3453 
3454     ret = _ismbcl1(0x889f);
3455     ok(ret, "got %d\n", ret);
3456 
3457     ret = _ismbcl1(0x88fd);
3458     ok(!ret, "got %d\n", ret);
3459 
3460     ret = _ismbcl2(0);
3461     ok(!ret, "got %d\n", ret);
3462 
3463     ret = _ismbcl2(0x989f);
3464     ok(ret, "got %d\n", ret);
3465 
3466     ret = _ismbcl2(0x993f);
3467     ok(!ret, "got %d\n", ret);
3468 
3469     _setmbcp(cp);
3470 }
3471 
3472 static void test__memicmp(void)
3473 {
3474     static const char *s1 = "abc";
3475     static const char *s2 = "aBd";
3476     int ret;
3477 
3478     ret = p__memicmp(NULL, NULL, 0);
3479     ok(!ret, "got %d\n", ret);
3480 
3481     ret = p__memicmp(s1, s2, 2);
3482     ok(!ret, "got %d\n", ret);
3483 
3484     ret = p__memicmp(s1, s2, 3);
3485     ok(ret == -1, "got %d\n", ret);
3486 
3487     if (!p__memicmp_l)
3488         return;
3489 
3490     /* Following calls crash on WinXP/W2k3. */
3491     errno = 0xdeadbeef;
3492     ret = p__memicmp(NULL, NULL, 1);
3493     ok(ret == _NLSCMPERROR, "got %d\n", ret);
3494     ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
3495 
3496     errno = 0xdeadbeef;
3497     ret = p__memicmp(s1, NULL, 1);
3498     ok(ret == _NLSCMPERROR, "got %d\n", ret);
3499     ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
3500 
3501     errno = 0xdeadbeef;
3502     ret = p__memicmp(NULL, s2, 1);
3503     ok(ret == _NLSCMPERROR, "got %d\n", ret);
3504     ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
3505 }
3506 
3507 static void test__memicmp_l(void)
3508 {
3509     static const char *s1 = "abc";
3510     static const char *s2 = "aBd";
3511     int ret;
3512 
3513     if (!p__memicmp_l)
3514     {
3515         win_skip("_memicmp_l not found.\n");
3516         return;
3517     }
3518 
3519     errno = 0xdeadbeef;
3520     ret = p__memicmp_l(NULL, NULL, 0, NULL);
3521     ok(!ret, "got %d\n", ret);
3522     ok(errno == 0xdeadbeef, "errno is %d, expected 0xdeadbeef\n", errno);
3523 
3524     errno = 0xdeadbeef;
3525     ret = p__memicmp_l(NULL, NULL, 1, NULL);
3526     ok(ret == _NLSCMPERROR, "got %d\n", ret);
3527     ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
3528 
3529     errno = 0xdeadbeef;
3530     ret = p__memicmp_l(s1, NULL, 1, NULL);
3531     ok(ret == _NLSCMPERROR, "got %d\n", ret);
3532     ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
3533 
3534     errno = 0xdeadbeef;
3535     ret = p__memicmp_l(NULL, s2, 1, NULL);
3536     ok(ret == _NLSCMPERROR, "got %d\n", ret);
3537     ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
3538 
3539     errno = 0xdeadbeef;
3540     ret = p__memicmp_l(s1, s2, 2, NULL);
3541     ok(!ret, "got %d\n", ret);
3542     ok(errno == 0xdeadbeef, "errno is %d, expected 0xdeadbeef\n", errno);
3543 
3544     errno = 0xdeadbeef;
3545     ret = p__memicmp_l(s1, s2, 3, NULL);
3546     ok(ret == -1, "got %d\n", ret);
3547     ok(errno == 0xdeadbeef, "errno is %d, expected 0xdeadbeef\n", errno);
3548 }
3549 
3550 static void test__strupr(void)
3551 {
3552     const char str[] = "123";
3553     char str2[4];
3554     char *mem, *p;
3555     DWORD prot;
3556 
3557     mem = VirtualAlloc(NULL, sizeof(str), MEM_COMMIT, PAGE_READWRITE);
3558     ok(mem != NULL, "VirtualAlloc failed\n");
3559     memcpy(mem, str, sizeof(str));
3560     ok(VirtualProtect(mem, sizeof(str), PAGE_READONLY, &prot), "VirtualProtect failed\n");
3561 
3562     strcpy(str2, "aBc");
3563     p = _strupr(str2);
3564     ok(p == str2, "_strupr returned %p\n", p);
3565     ok(!strcmp(str2, "ABC"), "str2 = %s\n", str2);
3566 
3567     p = _strupr(mem);
3568     ok(p == mem, "_strupr returned %p\n", p);
3569     ok(!strcmp(mem, "123"), "mem = %s\n", mem);
3570 
3571     if(!setlocale(LC_ALL, "english")) {
3572         VirtualFree(mem, sizeof(str), MEM_RELEASE);
3573         win_skip("English locale _strupr tests\n");
3574         return;
3575     }
3576 
3577     strcpy(str2, "aBc");
3578     p = _strupr(str2);
3579     ok(p == str2, "_strupr returned %p\n", p);
3580     ok(!strcmp(str2, "ABC"), "str2 = %s\n", str2);
3581 
3582     if (0) /* crashes on Windows */
3583     {
3584         p = _strupr(mem);
3585         ok(p == mem, "_strupr returned %p\n", p);
3586         ok(!strcmp(mem, "123"), "mem = %s\n", mem);
3587     }
3588 
3589     setlocale(LC_ALL, "C");
3590     VirtualFree(mem, sizeof(str), MEM_RELEASE);
3591 }
3592 
3593 static void test__tcsncoll(void)
3594 {
3595     struct test {
3596         const char *locale;
3597         const char *str1;
3598         const char *str2;
3599         size_t count;
3600         int exp;
3601     };
3602     static const struct test tests[] = {
3603         { "English", "ABCD", "ABCD",  4,  0 },
3604         { "English", "ABCD", "ABCD", 10,  0 },
3605 
3606         { "English", "ABC",  "ABCD",  3,  0 },
3607         { "English", "ABC",  "ABCD",  4, -1 },
3608         { "English", "ABC",  "ABCD", 10, -1 },
3609 
3610         { "English", "ABCD",  "ABC",  3,  0 },
3611         { "English", "ABCD",  "ABC",  4,  1 },
3612         { "English", "ABCD",  "ABC", 10,  1 },
3613 
3614         { "English", "ABCe", "ABCf",  3,  0 },
3615         { "English", "abcd", "ABCD", 10, -1 },
3616 
3617         { "C",       "ABCD", "ABCD",  4,  0 },
3618         { "C",       "ABCD", "ABCD", 10,  0 },
3619 
3620         { "C",       "ABC",  "ABCD",  3,  0 },
3621         { "C",       "ABC",  "ABCD", 10, -1 },
3622 
3623         { "C",       "ABCD",  "ABC",  3,  0 },
3624         { "C",       "ABCD",  "ABC", 10,  1 },
3625 
3626         { "C",       "ABCe", "ABCf",  3,  0 },
3627         { "C",       "abcd", "ABCD", 10,  1 },
3628     };
3629     WCHAR str1W[16];
3630     WCHAR str2W[16];
3631     char str1[16];
3632     char str2[16];
3633     size_t len;
3634     int i, ret;
3635 
3636     for (i = 0; i < ARRAY_SIZE(tests); i++)
3637     {
3638         if (!setlocale(LC_ALL, tests[i].locale))
3639         {
3640             win_skip("%s locale _tcsncoll tests\n", tests[i].locale);
3641             for (; i+1 < ARRAY_SIZE(tests); i++)
3642                 if (strcmp(tests[i].locale, tests[i+1].locale)) break;
3643             continue;
3644         }
3645 
3646         memset(str1, 0xee, sizeof(str1));
3647         strcpy(str1, tests[i].str1);
3648 
3649         memset(str2, 0xff, sizeof(str2));
3650         strcpy(str2, tests[i].str2);
3651 
3652         ret = _strncoll(str1, str2, tests[i].count);
3653         if (!tests[i].exp)
3654             ok(!ret, "expected 0, got %d for %s, %s, %d\n", ret, str1, str2, (int)tests[i].count);
3655         else if (tests[i].exp < 0)
3656             ok(ret < 0, "expected < 0, got %d for %s, %s, %d\n", ret, str1, str2, (int)tests[i].count);
3657         else
3658             ok(ret > 0, "expected > 0, got %d for %s, %s, %d\n", ret, str1, str2, (int)tests[i].count);
3659 
3660         memset(str1W, 0xee, sizeof(str1W));
3661         len = mbstowcs(str1W, str1, ARRAY_SIZE(str1W));
3662         str1W[len] = 0;
3663 
3664         memset(str2W, 0xff, sizeof(str2W));
3665         len = mbstowcs(str2W, str2, ARRAY_SIZE(str2W));
3666         str2W[len] = 0;
3667 
3668         ret = _wcsncoll(str1W, str2W, tests[i].count);
3669         if (!tests[i].exp)
3670             ok(!ret, "expected 0, got %d for %s, %s, %d\n", ret, str1, str2, (int)tests[i].count);
3671         else if (tests[i].exp < 0)
3672             ok(ret < 0, "expected < 0, got %d for %s, %s, %d\n", ret, str1, str2, (int)tests[i].count);
3673         else
3674             ok(ret > 0, "expected > 0, got %d for %s, %s, %d\n", ret, str1, str2, (int)tests[i].count);
3675     }
3676 }
3677 
3678 static void test__tcsnicoll(void)
3679 {
3680     struct test {
3681         const char *locale;
3682         const char *str1;
3683         const char *str2;
3684         size_t count;
3685         int exp;
3686     };
3687     static const struct test tests[] = {
3688         { "English", "abcd", "ABCD",  4,  0 },
3689         { "English", "abcd", "ABCD", 10,  0 },
3690 
3691         { "English", "abc",  "ABCD",  3,  0 },
3692         { "English", "abc",  "ABCD",  4, -1 },
3693         { "English", "abc",  "ABCD", 10, -1 },
3694 
3695         { "English", "abcd",  "ABC",  3,  0 },
3696         { "English", "abcd",  "ABC",  4,  1 },
3697         { "English", "abcd",  "ABC", 10,  1 },
3698 
3699         { "English", "abcE", "ABCF",  3,  0 },
3700 
3701         { "C",       "abcd", "ABCD",  4,  0 },
3702         { "C",       "abcd", "ABCD", 10,  0 },
3703 
3704         { "C",       "abc",  "ABCD",  3,  0 },
3705         { "C",       "abc",  "ABCD", 10, -1 },
3706 
3707         { "C",       "abcd",  "ABC",  3,  0 },
3708         { "C",       "abcd",  "ABC", 10,  1 },
3709 
3710         { "C",       "abce", "ABCf",  3,  0 },
3711     };
3712     WCHAR str1W[16];
3713     WCHAR str2W[16];
3714     char str1[16];
3715     char str2[16];
3716     size_t len;
3717     int i, ret;
3718 
3719     for (i = 0; i < ARRAY_SIZE(tests); i++)
3720     {
3721         if (!setlocale(LC_ALL, tests[i].locale))
3722         {
3723             win_skip("%s locale _tcsnicoll tests\n", tests[i].locale);
3724             for (; i+1 < ARRAY_SIZE(tests); i++)
3725                 if (strcmp(tests[i].locale, tests[i+1].locale)) break;
3726             continue;
3727         }
3728 
3729         memset(str1, 0xee, sizeof(str1));
3730         strcpy(str1, tests[i].str1);
3731 
3732         memset(str2, 0xff, sizeof(str2));
3733         strcpy(str2, tests[i].str2);
3734 
3735         ret = _strnicoll(str1, str2, tests[i].count);
3736         if (!tests[i].exp)
3737             ok(!ret, "expected 0, got %d for %s, %s, %d\n", ret, str1, str2, (int)tests[i].count);
3738         else if (tests[i].exp < 0)
3739             ok(ret < 0, "expected < 0, got %d for %s, %s, %d\n", ret, str1, str2, (int)tests[i].count);
3740         else
3741             ok(ret > 0, "expected > 0, got %d for %s, %s, %d\n", ret, str1, str2, (int)tests[i].count);
3742 
3743         memset(str1W, 0xee, sizeof(str1W));
3744         len = mbstowcs(str1W, str1, ARRAY_SIZE(str1W));
3745         str1W[len] = 0;
3746 
3747         memset(str2W, 0xff, sizeof(str2W));
3748         len = mbstowcs(str2W, str2, ARRAY_SIZE(str2W));
3749         str2W[len] = 0;
3750 
3751         ret = _wcsnicoll(str1W, str2W, tests[i].count);
3752         if (!tests[i].exp)
3753             ok(!ret, "expected 0, got %d for %s, %s, %d\n", ret, str1, str2, (int)tests[i].count);
3754         else if (tests[i].exp < 0)
3755             ok(ret < 0, "expected < 0, got %d for %s, %s, %d\n", ret, str1, str2, (int)tests[i].count);
3756         else
3757             ok(ret > 0, "expected > 0, got %d for %s, %s, %d\n", ret, str1, str2, (int)tests[i].count);
3758     }
3759 }
3760 
3761 static void test___strncnt(void)
3762 {
3763     static const struct
3764     {
3765         const char *str;
3766         size_t size;
3767         size_t ret;
3768     }
3769     strncnt_tests[] =
3770     {
3771         { NULL, 0, 0 },
3772         { "a", 0, 0 },
3773         { "a", 1, 1 },
3774         { "a", 10, 1 },
3775         { "abc", 1, 1 },
3776     };
3777     unsigned int i;
3778     size_t ret;
3779 
3780     if (!p___strncnt)
3781     {
3782         win_skip("__strncnt() is not available.\n");
3783         return;
3784     }
3785 
3786     if (0) /* crashes */
3787         ret = p___strncnt(NULL, 1);
3788 
3789     for (i = 0; i < ARRAY_SIZE(strncnt_tests); ++i)
3790     {
3791         ret = p___strncnt(strncnt_tests[i].str, strncnt_tests[i].size);
3792         ok(ret == strncnt_tests[i].ret, "%u: unexpected return value %u.\n", i, (int)ret);
3793     }
3794 }
3795 
3796 static void test_C_locale(void)
3797 {
3798     int i, j;
3799     wint_t ret, exp;
3800     _locale_t locale;
3801     static const char *locales[] = { NULL, "C" };
3802 
3803     /* C locale only converts case for [a-zA-Z] */
3804     setlocale(LC_ALL, "C");
3805     for (i = 0; i <= 0xffff; i++)
3806     {
3807         ret = p_towlower(i);
3808         if (i >= 'A' && i <= 'Z')
3809         {
3810             exp = i + 'a' - 'A';
3811             ok(ret == exp, "expected %x, got %x for C locale\n", exp, ret);
3812         }
3813         else
3814             ok(ret == i, "expected self %x, got %x for C locale\n", i, ret);
3815 
3816         ret = p_towupper(i);
3817         if (i >= 'a' && i <= 'z')
3818         {
3819             exp = i + 'A' - 'a';
3820             ok(ret == exp, "expected %x, got %x for C locale\n", exp, ret);
3821         }
3822         else
3823             ok(ret == i, "expected self %x, got %x for C locale\n", i, ret);
3824     }
3825 
3826     if (!p__towlower_l || !p__towupper_l || !p__create_locale)
3827     {
3828         win_skip("_towlower_l/_towupper_l/_create_locale not available\n");
3829         return;
3830     }
3831 
3832     for (i = 0; i < ARRAY_SIZE(locales); i++) {
3833         locale = locales[i] ? p__create_locale(LC_ALL, locales[i]) : NULL;
3834 
3835         for (j = 0; j <= 0xffff; j++) {
3836             ret = p__towlower_l(j, locale);
3837             if (j >= 'A' && j <= 'Z')
3838             {
3839                 exp = j + 'a' - 'A';
3840                 ok(ret == exp, "expected %x, got %x for C locale\n", exp, ret);
3841             }
3842             else
3843                 ok(ret == j, "expected self %x, got %x for C locale\n", j, ret);
3844 
3845             ret = p__towupper_l(j, locale);
3846             if (j >= 'a' && j <= 'z')
3847             {
3848                 exp = j + 'A' - 'a';
3849                 ok(ret == exp, "expected %x, got %x for C locale\n", exp, ret);
3850             }
3851             else
3852                 ok(ret == j, "expected self %x, got %x for C locale\n", j, ret);
3853         }
3854 
3855         p__free_locale(locale);
3856     }
3857 }
3858 
3859 START_TEST(string)
3860 {
3861     char mem[100];
3862     static const char xilstring[]="c:/xilinx";
3863     int nLen;
3864 
3865     hMsvcrt = GetModuleHandleA("msvcrt.dll");
3866     if (!hMsvcrt)
3867         hMsvcrt = GetModuleHandleA("msvcrtd.dll");
3868     ok(hMsvcrt != 0, "GetModuleHandleA failed\n");
3869     SET(pmemcpy,"memcpy");
3870     p_memcpy_s = (void*)GetProcAddress( hMsvcrt, "memcpy_s" );
3871     p_memmove_s = (void*)GetProcAddress( hMsvcrt, "memmove_s" );
3872     SET(pmemcmp,"memcmp");
3873     SET(p_mbctype,"_mbctype");
3874     SET(p__mb_cur_max,"__mb_cur_max");
3875     SET(p_strcpy, "strcpy");
3876     pstrcpy_s = (void *)GetProcAddress( hMsvcrt,"strcpy_s" );
3877     pstrcat_s = (void *)GetProcAddress( hMsvcrt,"strcat_s" );
3878     p_mbscat_s = (void*)GetProcAddress( hMsvcrt, "_mbscat_s" );
3879     p_mbsnbcat_s = (void *)GetProcAddress( hMsvcrt,"_mbsnbcat_s" );
3880     p_mbsnbcpy_s = (void *)GetProcAddress( hMsvcrt,"_mbsnbcpy_s" );
3881     p__mbscpy_s = (void *)GetProcAddress( hMsvcrt,"_mbscpy_s" );
3882     p_wcscpy_s = (void *)GetProcAddress( hMsvcrt,"wcscpy_s" );
3883     p_wcsncpy_s = (void *)GetProcAddress( hMsvcrt,"wcsncpy_s" );
3884     p_wcsncat_s = (void *)GetProcAddress( hMsvcrt,"wcsncat_s" );
3885     p_wcsupr_s = (void *)GetProcAddress( hMsvcrt,"_wcsupr_s" );
3886     p_strnlen = (void *)GetProcAddress( hMsvcrt,"strnlen" );
3887     p_strtoi64 = (void *)GetProcAddress(hMsvcrt, "_strtoi64");
3888     p_strtoui64 = (void *)GetProcAddress(hMsvcrt, "_strtoui64");
3889     p_wcstoi64 = (void *)GetProcAddress(hMsvcrt, "_wcstoi64");
3890     p_wcstoui64 = (void *)GetProcAddress(hMsvcrt, "_wcstoui64");
3891     pmbstowcs_s = (void *)GetProcAddress(hMsvcrt, "mbstowcs_s");
3892     pwcstombs_s = (void *)GetProcAddress(hMsvcrt, "wcstombs_s");
3893     pwcsrtombs = (void *)GetProcAddress(hMsvcrt, "wcsrtombs");
3894     p_gcvt_s = (void *)GetProcAddress(hMsvcrt, "_gcvt_s");
3895     p_itoa_s = (void *)GetProcAddress(hMsvcrt, "_itoa_s");
3896     p_strlwr_s = (void *)GetProcAddress(hMsvcrt, "_strlwr_s");
3897     p_ultoa_s = (void *)GetProcAddress(hMsvcrt, "_ultoa_s");
3898     p_wcslwr_s = (void*)GetProcAddress(hMsvcrt, "_wcslwr_s");
3899     p_mbsupr_s = (void*)GetProcAddress(hMsvcrt, "_mbsupr_s");
3900     p_mbslwr_s = (void*)GetProcAddress(hMsvcrt, "_mbslwr_s");
3901     p_wctob = (void*)GetProcAddress(hMsvcrt, "wctob");
3902     p_wcrtomb = (void*)GetProcAddress(hMsvcrt, "wcrtomb");
3903     p_wcrtomb_s = (void*)GetProcAddress(hMsvcrt, "wcrtomb_s");
3904     p_tolower = (void*)GetProcAddress(hMsvcrt, "tolower");
3905     p_towlower = (void*)GetProcAddress(hMsvcrt, "towlower");
3906     p__towlower_l = (void*)GetProcAddress(hMsvcrt, "_towlower_l");
3907     p_towupper = (void*)GetProcAddress(hMsvcrt, "towupper");
3908     p__towupper_l = (void*)GetProcAddress(hMsvcrt, "_towupper_l");
3909     p__create_locale = (void*)GetProcAddress(hMsvcrt, "_create_locale");
3910     p__free_locale = (void*)GetProcAddress(hMsvcrt, "_free_locale");
3911     p_mbrlen = (void*)GetProcAddress(hMsvcrt, "mbrlen");
3912     p_mbrtowc = (void*)GetProcAddress(hMsvcrt, "mbrtowc");
3913     p_mbsrtowcs = (void*)GetProcAddress(hMsvcrt, "mbsrtowcs");
3914     p_mbsrtowcs_s = (void*)GetProcAddress(hMsvcrt, "mbsrtowcs_s");
3915     p__atodbl_l = (void*)GetProcAddress(hMsvcrt, "_atodbl_l");
3916     p__atof_l = (void*)GetProcAddress(hMsvcrt, "_atof_l");
3917     p__strtod_l = (void*)GetProcAddress(hMsvcrt, "_strtod_l");
3918     p__strnset_s = (void*)GetProcAddress(hMsvcrt, "_strnset_s");
3919     p__wcsnset_s = (void*)GetProcAddress(hMsvcrt, "_wcsnset_s");
3920     p__wcsset_s = (void*)GetProcAddress(hMsvcrt, "_wcsset_s");
3921     p__mbsnlen = (void*)GetProcAddress(hMsvcrt, "_mbsnlen");
3922     p__mbccpy_s = (void*)GetProcAddress(hMsvcrt, "_mbccpy_s");
3923     p__memicmp = (void*)GetProcAddress(hMsvcrt, "_memicmp");
3924     p__memicmp_l = (void*)GetProcAddress(hMsvcrt, "_memicmp_l");
3925     p___strncnt = (void*)GetProcAddress(hMsvcrt, "__strncnt");
3926 
3927     /* MSVCRT memcpy behaves like memmove for overlapping moves,
3928        MFC42 CString::Insert seems to rely on that behaviour */
3929     strcpy(mem,xilstring);
3930     nLen=strlen(xilstring);
3931     pmemcpy(mem+5, mem,nLen+1);
3932     ok(pmemcmp(mem+5,xilstring, nLen) == 0,
3933        "Got result %s\n",mem+5);
3934 
3935     /* run tolower tests first */
3936     test_tolower();
3937     test_swab();
3938     test_mbcp();
3939     test_mbsspn();
3940     test_mbsspnp();
3941     test_strdup();
3942     test_strcpy_s();
3943     test_memcpy_s();
3944     test_memmove_s();
3945     test_strcat_s();
3946     test__mbscat_s();
3947     test__mbsnbcpy_s();
3948     test__mbscpy_s();
3949     test_mbcjisjms();
3950     test_mbcjmsjis();
3951     test_mbctohira();
3952     test_mbctokata();
3953     test_mbbtombc();
3954     test_mbctombb();
3955     test_ismbckata();
3956     test_ismbclegal();
3957     test_strtok();
3958     test__mbstok();
3959     test_wcscpy_s();
3960     test__wcsupr_s();
3961     test_strtol();
3962     test_strnlen();
3963     test__strtoi64();
3964     test__strtod();
3965     test_mbstowcs();
3966     test_gcvt();
3967     test__itoa_s();
3968     test__strlwr_s();
3969     test_wcsncat_s();
3970     test__mbsnbcat_s();
3971     test__ultoa_s();
3972     test__wcslwr_s();
3973     test__mbsupr_s();
3974     test__mbslwr_s();
3975     test_wctob();
3976     test_wctomb();
3977     test__atodbl();
3978     test__stricmp();
3979     test__wcstoi64();
3980     test_atoi();
3981     test_atol();
3982     test_atof();
3983     test_strncpy();
3984     test_strxfrm();
3985     test__strnset_s();
3986     test__wcsnset_s();
3987     test__wcsset_s();
3988     test__mbscmp();
3989     test__ismbclx();
3990     test__memicmp();
3991     test__memicmp_l();
3992     test__strupr();
3993     test__tcsncoll();
3994     test__tcsnicoll();
3995     test___strncnt();
3996     test_C_locale();
3997 }
3998