crypt32: Add additional path for Solaris 11 Express.
[wine] / dlls / msvcrt / tests / string.c
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 "winbase.h"
23 #include "winnls.h"
24 #include <string.h>
25 #include <mbstring.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <mbctype.h>
29 #include <locale.h>
30 #include <errno.h>
31 #include <limits.h>
32
33 static char *buf_to_string(const unsigned char *bin, int len, int nr)
34 {
35     static char buf[2][1024];
36     char *w = buf[nr];
37     int i;
38
39     for (i = 0; i < len; i++)
40     {
41         sprintf(w, "%02x ", (unsigned char)bin[i]);
42         w += strlen(w);
43     }
44     return buf[nr];
45 }
46
47 static void __cdecl test_invalid_parameter_handler(const wchar_t *expression,
48         const wchar_t *function, const wchar_t *file,
49         unsigned line, uintptr_t arg)
50 {
51     /* we just ignore handler calls */
52 }
53
54 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
55 #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)); }
56
57 static void* (__cdecl *pmemcpy)(void *, const void *, size_t n);
58 static int* (__cdecl *pmemcmp)(void *, const void *, size_t n);
59 static int (__cdecl *pstrcpy_s)(char *dst, size_t len, const char *src);
60 static int (__cdecl *pstrcat_s)(char *dst, size_t len, const char *src);
61 static int (__cdecl *p_mbsnbcat_s)(unsigned char *dst, size_t size, const unsigned char *src, size_t count);
62 static int (__cdecl *p_mbsnbcpy_s)(unsigned char * dst, size_t size, const unsigned char * src, size_t count);
63 static int (__cdecl *p_wcscpy_s)(wchar_t *wcDest, size_t size, const wchar_t *wcSrc);
64 static int (__cdecl *p_wcsncat_s)(wchar_t *dst, size_t elem, const wchar_t *src, size_t count);
65 static int (__cdecl *p_wcsupr_s)(wchar_t *str, size_t size);
66 static size_t (__cdecl *p_strnlen)(const char *, size_t);
67 static __int64 (__cdecl *p_strtoi64)(const char *, char **, int);
68 static unsigned __int64 (__cdecl *p_strtoui64)(const char *, char **, int);
69 static int (__cdecl *pwcstombs_s)(size_t*,char*,size_t,const wchar_t*,size_t);
70 static int (__cdecl *pmbstowcs_s)(size_t*,wchar_t*,size_t,const char*,size_t);
71 static size_t (__cdecl *pwcsrtombs)(char*, const wchar_t**, size_t, int*);
72 static errno_t (__cdecl *p_gcvt_s)(char*,size_t,double,int);
73 static errno_t (__cdecl *p_itoa_s)(int,char*,size_t,int);
74 static errno_t (__cdecl *p_strlwr_s)(char*,size_t);
75 static errno_t (__cdecl *p_ultoa_s)(__msvcrt_ulong,char*,size_t,int);
76 static int *p__mb_cur_max;
77 static unsigned char *p_mbctype;
78 static _invalid_parameter_handler (__cdecl *p_set_invalid_parameter_handler)(_invalid_parameter_handler);
79 static int (__cdecl *p_wcslwr_s)(wchar_t*,size_t);
80 static errno_t (__cdecl *p_mbsupr_s)(unsigned char *str, size_t numberOfElements);
81 static errno_t (__cdecl *p_mbslwr_s)(unsigned char *str, size_t numberOfElements);
82 static int (__cdecl *p_wctob)(wint_t);
83 static int (__cdecl *p_tolower)(int);
84
85 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y)
86 #define SET(x,y) SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y)
87
88 static HMODULE hMsvcrt;
89
90 static void test_swab( void ) {
91     char original[]  = "BADCFEHGJILKNMPORQTSVUXWZY@#";
92     char expected1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ@#";
93     char expected2[] = "ABCDEFGHIJKLMNOPQRSTUVWX$";
94     char expected3[] = "$";
95     
96     char from[30];
97     char to[30];
98     
99     int testsize;
100     
101     /* Test 1 - normal even case */                               
102     memset(to,'$', sizeof(to));
103     memset(from,'@', sizeof(from));
104     testsize = 26;
105     memcpy(from, original, testsize);
106     _swab( from, to, testsize );
107     ok(memcmp(to,expected1,testsize) == 0, "Testing even size %d returned '%*.*s'\n", testsize, testsize, testsize, to);
108
109     /* Test 2 - uneven case  */                               
110     memset(to,'$', sizeof(to));
111     memset(from,'@', sizeof(from));
112     testsize = 25;
113     memcpy(from, original, testsize);
114     _swab( from, to, testsize );
115     ok(memcmp(to,expected2,testsize) == 0, "Testing odd size %d returned '%*.*s'\n", testsize, testsize, testsize, to);
116
117     /* Test 3 - from = to */                               
118     memset(to,'$', sizeof(to));
119     memset(from,'@', sizeof(from));
120     testsize = 26;
121     memcpy(to, original, testsize);
122     _swab( to, to, testsize );
123     ok(memcmp(to,expected1,testsize) == 0, "Testing overlapped size %d returned '%*.*s'\n", testsize, testsize, testsize, to);
124
125     /* Test 4 - 1 bytes */                               
126     memset(to,'$', sizeof(to));
127     memset(from,'@', sizeof(from));
128     testsize = 1;
129     memcpy(from, original, testsize);
130     _swab( from, to, testsize );
131     ok(memcmp(to,expected3,testsize) == 0, "Testing small size %d returned '%*.*s'\n", testsize, testsize, testsize, to);
132 }
133
134 #if 0      /* use this to generate more tests */
135
136 static void test_codepage(int cp)
137 {
138     int i;
139     int prev;
140     int count = 1;
141
142     ok(_setmbcp(cp) == 0, "Couldn't set mbcp\n");
143
144     prev = p_mbctype[0];
145     printf("static int result_cp_%d_mbctype[] = { ", cp);
146     for (i = 1; i < 257; i++)
147     {
148         if (p_mbctype[i] != prev)
149         {
150             printf("0x%x,%d, ", prev, count);
151             prev = p_mbctype[i];
152             count = 1;
153         }
154         else
155             count++;
156     }
157     printf("0x%x,%d };\n", prev, count);
158 }
159
160 #else
161
162 /* RLE-encoded mbctype tables for given codepages */
163 static int result_cp_932_mbctype[] = { 0x0,65, 0x8,1, 0x18,26, 0x8,6, 0x28,26, 0x8,4,
164   0x0,1, 0x8,1, 0xc,31, 0x8,1, 0xa,5, 0x9,58, 0xc,29, 0,3 };
165 static int result_cp_936_mbctype[] = { 0x0,65, 0x8,1, 0x18,26, 0x8,6, 0x28,26, 0x8,6,
166   0xc,126, 0,1 };
167 static int result_cp_949_mbctype[] = { 0x0,66, 0x18,26, 0x8,6, 0x28,26, 0x8,6, 0xc,126,
168   0,1 };
169 static int result_cp_950_mbctype[] = { 0x0,65, 0x8,1, 0x18,26, 0x8,6, 0x28,26, 0x8,4,
170   0x0,2, 0x4,32, 0xc,94, 0,1 };
171
172 static void test_cp_table(int cp, int *result)
173 {
174     int i;
175     int count = 0;
176     int curr = 0;
177     _setmbcp(cp);
178     for (i = 0; i < 256; i++)
179     {
180         if (count == 0)
181         {
182             curr = result[0];
183             count = result[1];
184             result += 2;
185         }
186         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);
187         count--;
188     }
189 }
190
191 #define test_codepage(num) test_cp_table(num, result_cp_##num##_mbctype);
192
193 #endif
194
195 static void test_mbcp(void)
196 {
197     int mb_orig_max = *p__mb_cur_max;
198     int curr_mbcp = _getmbcp();
199     unsigned char *mbstring = (unsigned char *)"\xb0\xb1\xb2 \xb3\xb4 \xb5"; /* incorrect string */
200     unsigned char *mbstring2 = (unsigned char *)"\xb0\xb1\xb2\xb3Q\xb4\xb5"; /* correct string */
201     unsigned char *mbsonlylead = (unsigned char *)"\xb0\0\xb1\xb2 \xb3";
202     unsigned char buf[16];
203     int step;
204     CPINFO cp_info;
205
206     /* _mbtype tests */
207
208     /* An SBCS codepage test. The ctype of characters on e.g. CP1252 or CP1250 differs slightly
209      * between versions of Windows. Also Windows 9x seems to ignore the codepage and always uses
210      * CP1252 (or the ACP?) so we test only a few ASCII characters */
211     _setmbcp(1252);
212     expect_eq(p_mbctype[10], 0, char, "%x");
213     expect_eq(p_mbctype[50], 0, char, "%x");
214     expect_eq(p_mbctype[66], _SBUP, char, "%x");
215     expect_eq(p_mbctype[100], _SBLOW, char, "%x");
216     expect_eq(p_mbctype[128], 0, char, "%x");
217     _setmbcp(1250);
218     expect_eq(p_mbctype[10], 0, char, "%x");
219     expect_eq(p_mbctype[50], 0, char, "%x");
220     expect_eq(p_mbctype[66], _SBUP, char, "%x");
221     expect_eq(p_mbctype[100], _SBLOW, char, "%x");
222     expect_eq(p_mbctype[128], 0, char, "%x");
223
224     /* double byte code pages */
225     test_codepage(932);
226     test_codepage(936);
227     test_codepage(949);
228     test_codepage(950);
229
230     _setmbcp(936);
231     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);
232     ok(_ismbblead('\354'), "\354 should be a lead byte\n");
233     ok(_ismbblead(' ') == FALSE, "' ' should not be a lead byte\n");
234     ok(_ismbblead(0x1234b0), "0x1234b0 should not be a lead byte\n");
235     ok(_ismbblead(0x123420) == FALSE, "0x123420 should not be a lead byte\n");
236     ok(_ismbbtrail('\xb0'), "\xa0 should be a trail byte\n");
237     ok(_ismbbtrail(' ') == FALSE, "' ' should not be a trail byte\n");
238
239     /* _ismbslead */
240     expect_eq(_ismbslead(mbstring, &mbstring[0]), -1, int, "%d");
241     expect_eq(_ismbslead(mbstring, &mbstring[1]), FALSE, int, "%d");
242     expect_eq(_ismbslead(mbstring, &mbstring[2]), -1, int, "%d");
243     expect_eq(_ismbslead(mbstring, &mbstring[3]), FALSE, int, "%d");
244     expect_eq(_ismbslead(mbstring, &mbstring[4]), -1, int, "%d");
245     expect_eq(_ismbslead(mbstring, &mbstring[5]), FALSE, int, "%d");
246     expect_eq(_ismbslead(mbstring, &mbstring[6]), FALSE, int, "%d");
247     expect_eq(_ismbslead(mbstring, &mbstring[7]), -1, int, "%d");
248     expect_eq(_ismbslead(mbstring, &mbstring[8]), FALSE, int, "%d");
249
250     expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[0]), -1, int, "%d");
251     expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[1]), FALSE, int, "%d");
252     expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[2]), FALSE, int, "%d");
253     expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[5]), FALSE, int, "%d");
254
255     /* _ismbstrail */
256     expect_eq(_ismbstrail(mbstring, &mbstring[0]), FALSE, int, "%d");
257     expect_eq(_ismbstrail(mbstring, &mbstring[1]), -1, int, "%d");
258     expect_eq(_ismbstrail(mbstring, &mbstring[2]), FALSE, int, "%d");
259     expect_eq(_ismbstrail(mbstring, &mbstring[3]), -1, int, "%d");
260     expect_eq(_ismbstrail(mbstring, &mbstring[4]), FALSE, int, "%d");
261     expect_eq(_ismbstrail(mbstring, &mbstring[5]), -1, int, "%d");
262     expect_eq(_ismbstrail(mbstring, &mbstring[6]), FALSE, int, "%d");
263     expect_eq(_ismbstrail(mbstring, &mbstring[7]), FALSE, int, "%d");
264     expect_eq(_ismbstrail(mbstring, &mbstring[8]), -1, int, "%d");
265
266     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[0]), FALSE, int, "%d");
267     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[1]), -1, int, "%d");
268     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[2]), FALSE, int, "%d");
269     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[3]), FALSE, int, "%d");
270     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[4]), FALSE, int, "%d");
271     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[5]), FALSE, int, "%d");
272
273     /* _mbsbtype */
274     expect_eq(_mbsbtype(mbstring, 0), _MBC_LEAD, int, "%d");
275     expect_eq(_mbsbtype(mbstring, 1), _MBC_TRAIL, int, "%d");
276     expect_eq(_mbsbtype(mbstring, 2), _MBC_LEAD, int, "%d");
277     expect_eq(_mbsbtype(mbstring, 3), _MBC_ILLEGAL, int, "%d");
278     expect_eq(_mbsbtype(mbstring, 4), _MBC_LEAD, int, "%d");
279     expect_eq(_mbsbtype(mbstring, 5), _MBC_TRAIL, int, "%d");
280     expect_eq(_mbsbtype(mbstring, 6), _MBC_SINGLE, int, "%d");
281     expect_eq(_mbsbtype(mbstring, 7), _MBC_LEAD, int, "%d");
282     expect_eq(_mbsbtype(mbstring, 8), _MBC_ILLEGAL, int, "%d");
283
284     expect_eq(_mbsbtype(mbsonlylead, 0), _MBC_LEAD, int, "%d");
285     expect_eq(_mbsbtype(mbsonlylead, 1), _MBC_ILLEGAL, int, "%d");
286     expect_eq(_mbsbtype(mbsonlylead, 2), _MBC_ILLEGAL, int, "%d");
287     expect_eq(_mbsbtype(mbsonlylead, 3), _MBC_ILLEGAL, int, "%d");
288     expect_eq(_mbsbtype(mbsonlylead, 4), _MBC_ILLEGAL, int, "%d");
289     expect_eq(_mbsbtype(mbsonlylead, 5), _MBC_ILLEGAL, int, "%d");
290
291     /* _mbsnextc */
292     expect_eq(_mbsnextc(mbstring), 0xb0b1, int, "%x");
293     expect_eq(_mbsnextc(&mbstring[2]), 0xb220, int, "%x");  /* lead + invalid tail */
294     expect_eq(_mbsnextc(&mbstring[3]), 0x20, int, "%x");    /* single char */
295
296     /* _mbclen/_mbslen */
297     expect_eq(_mbclen(mbstring), 2, int, "%d");
298     expect_eq(_mbclen(&mbstring[2]), 2, int, "%d");
299     expect_eq(_mbclen(&mbstring[3]), 1, int, "%d");
300     expect_eq(_mbslen(mbstring2), 4, int, "%d");
301     expect_eq(_mbslen(mbsonlylead), 0, int, "%d");          /* lead + NUL not counted as character */
302     expect_eq(_mbslen(mbstring), 4, int, "%d");             /* lead + invalid trail counted */
303
304     /* _mbccpy/_mbsncpy */
305     memset(buf, 0xff, sizeof(buf));
306     _mbccpy(buf, mbstring);
307     expect_bin(buf, "\xb0\xb1\xff", 3);
308
309     memset(buf, 0xff, sizeof(buf));
310     _mbsncpy(buf, mbstring, 1);
311     expect_bin(buf, "\xb0\xb1\xff", 3);
312     memset(buf, 0xff, sizeof(buf));
313     _mbsncpy(buf, mbstring, 2);
314     expect_bin(buf, "\xb0\xb1\xb2 \xff", 5);
315     memset(buf, 0xff, sizeof(buf));
316     _mbsncpy(buf, mbstring, 3);
317     expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4\xff", 7);
318     memset(buf, 0xff, sizeof(buf));
319     _mbsncpy(buf, mbstring, 4);
320     expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4 \xff", 8);
321     memset(buf, 0xff, sizeof(buf));
322     _mbsncpy(buf, mbstring, 5);
323     expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4 \0\0\xff", 10);
324     memset(buf, 0xff, sizeof(buf));
325     _mbsncpy(buf, mbsonlylead, 6);
326     expect_bin(buf, "\0\0\0\0\0\0\0\xff", 8);
327
328     memset(buf, 0xff, sizeof(buf));
329     _mbsnbcpy(buf, mbstring2, 2);
330     expect_bin(buf, "\xb0\xb1\xff", 3);
331     _mbsnbcpy(buf, mbstring2, 3);
332     expect_bin(buf, "\xb0\xb1\0\xff", 4);
333     _mbsnbcpy(buf, mbstring2, 4);
334     expect_bin(buf, "\xb0\xb1\xb2\xb3\xff", 5);
335     memset(buf, 0xff, sizeof(buf));
336     _mbsnbcpy(buf, mbsonlylead, 5);
337     expect_bin(buf, "\0\0\0\0\0\xff", 6);
338
339     /* _mbsinc/mbsdec */
340     step = _mbsinc(mbstring) - mbstring;
341     ok(step == 2, "_mbsinc adds %d (exp. 2)\n", step);
342     step = _mbsinc(&mbstring[2]) - &mbstring[2];  /* lead + invalid tail */
343     ok(step == 2, "_mbsinc adds %d (exp. 2)\n", step);
344
345     step = _mbsninc(mbsonlylead, 1) - mbsonlylead;
346     ok(step == 0, "_mbsninc adds %d (exp. 0)\n", step);
347     step = _mbsninc(mbsonlylead, 2) - mbsonlylead;  /* lead + NUL byte + lead + char */
348     ok(step == 0, "_mbsninc adds %d (exp. 0)\n", step);
349     step = _mbsninc(mbstring2, 0) - mbstring2;
350     ok(step == 0, "_mbsninc adds %d (exp. 2)\n", step);
351     step = _mbsninc(mbstring2, 1) - mbstring2;
352     ok(step == 2, "_mbsninc adds %d (exp. 2)\n", step);
353     step = _mbsninc(mbstring2, 2) - mbstring2;
354     ok(step == 4, "_mbsninc adds %d (exp. 4)\n", step);
355     step = _mbsninc(mbstring2, 3) - mbstring2;
356     ok(step == 5, "_mbsninc adds %d (exp. 5)\n", step);
357     step = _mbsninc(mbstring2, 4) - mbstring2;
358     ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step);
359     step = _mbsninc(mbstring2, 5) - mbstring2;
360     ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step);
361     step = _mbsninc(mbstring2, 17) - mbstring2;
362     ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step);
363
364     /* functions that depend on locale codepage, not mbcp.
365      * we hope the current locale to be SBCS because setlocale(LC_ALL, ".1252") seems not to work yet
366      * (as of Wine 0.9.43)
367      */
368     GetCPInfo(GetACP(), &cp_info);
369     if (cp_info.MaxCharSize == 1)
370     {
371         expect_eq(mblen((char *)mbstring, 3), 1, int, "%x");
372         expect_eq(_mbstrlen((char *)mbstring2), 7, int, "%d");
373     }
374     else
375         skip("Current locale has double-byte charset - could lead to false positives\n");
376
377     _setmbcp(1361);
378     expect_eq(_ismbblead(0x80), 0, int, "%d");
379     todo_wine {
380       expect_eq(_ismbblead(0x81), 1, int, "%d");
381       expect_eq(_ismbblead(0x83), 1, int, "%d");
382     }
383     expect_eq(_ismbblead(0x84), 1, int, "%d");
384     expect_eq(_ismbblead(0xd3), 1, int, "%d");
385     expect_eq(_ismbblead(0xd7), 0, int, "%d");
386     todo_wine {
387       expect_eq(_ismbblead(0xd8), 1, int, "%d");
388     }
389     expect_eq(_ismbblead(0xd9), 1, int, "%d");
390
391     expect_eq(_ismbbtrail(0x30), 0, int, "%d");
392     expect_eq(_ismbbtrail(0x31), 1, int, "%d");
393     expect_eq(_ismbbtrail(0x7e), 1, int, "%d");
394     expect_eq(_ismbbtrail(0x7f), 0, int, "%d");
395     expect_eq(_ismbbtrail(0x80), 0, int, "%d");
396     expect_eq(_ismbbtrail(0x81), 1, int, "%d");
397     expect_eq(_ismbbtrail(0xfe), 1, int, "%d");
398     expect_eq(_ismbbtrail(0xff), 0, int, "%d");
399
400     _setmbcp(curr_mbcp);
401 }
402
403 static void test_mbsspn( void)
404 {
405     unsigned char str1[]="cabernet";
406     unsigned char str2[]="shiraz";
407     unsigned char set[]="abc";
408     unsigned char empty[]="";
409     int ret;
410     ret=_mbsspn( str1, set);
411     ok( ret==3, "_mbsspn returns %d should be 3\n", ret);
412     ret=_mbsspn( str2, set);
413     ok( ret==0, "_mbsspn returns %d should be 0\n", ret);
414     ret=_mbsspn( str1, empty);
415     ok( ret==0, "_mbsspn returns %d should be 0\n", ret);
416 }
417
418 static void test_mbsspnp( void)
419 {
420     unsigned char str1[]="cabernet";
421     unsigned char str2[]="shiraz";
422     unsigned char set[]="abc";
423     unsigned char empty[]="";
424     unsigned char full[]="abcenrt";
425     unsigned char* ret;
426     ret=_mbsspnp( str1, set);
427     ok( ret[0]=='e', "_mbsspnp returns %c should be e\n", ret[0]);
428     ret=_mbsspnp( str2, set);
429     ok( ret[0]=='s', "_mbsspnp returns %c should be s\n", ret[0]);
430     ret=_mbsspnp( str1, empty);
431     ok( ret[0]=='c', "_mbsspnp returns %c should be c\n", ret[0]);
432     ret=_mbsspnp( str1, full);
433     ok( ret==NULL, "_mbsspnp returns %p should be NULL\n", ret);
434 }
435
436 static void test_strdup(void)
437 {
438    char *str;
439    str = _strdup( 0 );
440    ok( str == 0, "strdup returns %s should be 0\n", str);
441    free( str );
442 }
443
444 static void test_strcpy_s(void)
445 {
446     char dest[8];
447     const char *small = "small";
448     const char *big = "atoolongstringforthislittledestination";
449     int ret;
450
451     if(!pstrcpy_s)
452     {
453         skip("strcpy_s not found\n");
454         return;
455     }
456
457     memset(dest, 'X', sizeof(dest));
458     ret = pstrcpy_s(dest, sizeof(dest), small);
459     ok(ret == 0, "Copying a string into a big enough destination returned %d, expected 0\n", ret);
460     ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == 'l' &&
461        dest[4] == 'l' && dest[5] == '\0'&& dest[6] == 'X' && dest[7] == 'X',
462        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
463        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
464
465     memset(dest, 'X', sizeof(dest));
466     ret = pstrcpy_s(dest, 0, big);
467     ok(ret == EINVAL, "Copying into a destination of size 0 returned %d, expected EINVAL\n", ret);
468     ok(dest[0] == 'X' && dest[1] == 'X' && dest[2] == 'X' && dest[3] == 'X' &&
469        dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
470        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
471        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
472     ret = pstrcpy_s(dest, 0, NULL);
473     ok(ret == EINVAL, "Copying into a destination of size 0 returned %d, expected EINVAL\n", ret);
474     ok(dest[0] == 'X' && dest[1] == 'X' && dest[2] == 'X' && dest[3] == 'X' &&
475        dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
476        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
477        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
478
479     memset(dest, 'X', sizeof(dest));
480     ret = pstrcpy_s(dest, sizeof(dest), big);
481     ok(ret == ERANGE, "Copying a big string in a small location returned %d, expected ERANGE\n", ret);
482     ok(dest[0] == '\0'&& dest[1] == 't' && dest[2] == 'o' && dest[3] == 'o' &&
483        dest[4] == 'l' && dest[5] == 'o' && dest[6] == 'n' && dest[7] == 'g',
484        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
485        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
486
487     memset(dest, 'X', sizeof(dest));
488     ret = pstrcpy_s(dest, sizeof(dest), NULL);
489     ok(ret == EINVAL, "Copying from a NULL source string returned %d, expected EINVAL\n", ret);
490     ok(dest[0] == '\0'&& dest[1] == 'X' && dest[2] == 'X' && dest[3] == 'X' &&
491        dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
492        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
493        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
494
495     ret = pstrcpy_s(NULL, sizeof(dest), small);
496     ok(ret == EINVAL, "Copying a big string a NULL dest returned %d, expected EINVAL\n", ret);
497 }
498
499 static void test_strcat_s(void)
500 {
501     char dest[8];
502     const char *small = "sma";
503     int ret;
504
505     if(!pstrcat_s)
506     {
507         skip("strcat_s not found\n");
508         return;
509     }
510
511     memset(dest, 'X', sizeof(dest));
512     dest[0] = '\0';
513     ret = pstrcat_s(dest, sizeof(dest), small);
514     ok(ret == 0, "strcat_s: Copying a string into a big enough destination returned %d, expected 0\n", ret);
515     ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == '\0'&&
516        dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
517        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
518        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
519     ret = pstrcat_s(dest, sizeof(dest), small);
520     ok(ret == 0, "strcat_s: Attaching a string to a big enough destination returned %d, expected 0\n", ret);
521     ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == 's' &&
522        dest[4] == 'm' && dest[5] == 'a' && dest[6] == '\0'&& dest[7] == 'X',
523        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
524        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
525
526     ret = pstrcat_s(dest, sizeof(dest), small);
527     ok(ret == ERANGE, "strcat_s: Attaching a string to a filled up destination returned %d, expected ERANGE\n", ret);
528     ok(dest[0] == '\0'&& dest[1] == 'm' && dest[2] == 'a' && dest[3] == 's' &&
529        dest[4] == 'm' && dest[5] == 'a' && dest[6] == 's' && dest[7] == 'm',
530        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
531        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
532
533     memset(dest, 'X', sizeof(dest));
534     dest[0] = 'a';
535     dest[1] = '\0';
536
537     ret = pstrcat_s(dest, 0, small);
538     ok(ret == EINVAL, "strcat_s: Source len = 0 returned %d, expected EINVAL\n", ret);
539     ok(dest[0] == 'a' && dest[1] == '\0'&& dest[2] == 'X' && dest[3] == 'X' &&
540        dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
541        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
542        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
543
544     ret = pstrcat_s(dest, 0, NULL);
545     ok(ret == EINVAL, "strcat_s: len = 0 and src = NULL returned %d, expected EINVAL\n", ret);
546     ok(dest[0] == 'a' && dest[1] == '\0'&& dest[2] == 'X' && dest[3] == 'X' &&
547        dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
548        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
549        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
550
551     ret = pstrcat_s(dest, sizeof(dest), NULL);
552     ok(ret == EINVAL, "strcat_s:  Sourcing from NULL returned %d, expected EINVAL\n", ret);
553     ok(dest[0] == '\0'&& dest[1] == '\0'&& dest[2] == 'X' && dest[3] == 'X' &&
554        dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
555        "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
556        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
557
558     ret = pstrcat_s(NULL, sizeof(dest), small);
559     ok(ret == EINVAL, "strcat_s: Writing to a NULL string returned %d, expected EINVAL\n", ret);
560 }
561
562 static void test__mbsnbcpy_s(void)
563 {
564     unsigned char dest[8];
565     const unsigned char big[] = "atoolongstringforthislittledestination";
566     const unsigned char small[] = "small";
567     int ret;
568
569     if(!p_mbsnbcpy_s)
570     {
571         skip("_mbsnbcpy_s not found\n");
572         return;
573     }
574
575     memset(dest, 'X', sizeof(dest));
576     ret = p_mbsnbcpy_s(dest, sizeof(dest), small, sizeof(small));
577     ok(ret == 0, "_mbsnbcpy_s: Copying a string into a big enough destination returned %d, expected 0\n", ret);
578     ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == 'l' &&
579        dest[4] == 'l' && dest[5] == '\0'&& dest[6] == 'X' && dest[7] == 'X',
580        "Unexpected return data from _mbsnbcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
581        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
582
583     /* WTF? */
584     memset(dest, 'X', sizeof(dest));
585     ret = p_mbsnbcpy_s(dest, sizeof(dest) - 2, big, sizeof(small));
586     ok(ret == ERANGE, "_mbsnbcpy_s: Copying a too long string returned %d, expected ERANGE\n", ret);
587     ok(dest[0] == '\0'&& dest[1] == 't' && dest[2] == 'o' && dest[3] == 'o' &&
588        dest[4] == 'l' && dest[5] == 'o' && dest[6] == 'X' && dest[7] == 'X',
589        "Unexpected return data from _mbsnbcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
590        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
591
592     memset(dest, 'X', sizeof(dest));
593     ret = p_mbsnbcpy_s(dest, sizeof(dest) - 2, big, 4);
594     ok(ret == 0, "_mbsnbcpy_s: Copying a too long string with a count cap returned %d, expected 0\n", ret);
595     ok(dest[0] == 'a' && dest[1] == 't' && dest[2] == 'o' && dest[3] == 'o' &&
596        dest[4] == '\0'&& dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
597        "Unexpected return data from _mbsnbcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
598        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
599
600     memset(dest, 'X', sizeof(dest));
601     ret = p_mbsnbcpy_s(dest, sizeof(dest) - 2, small, sizeof(small) + 10);
602     ok(ret == 0, "_mbsnbcpy_s: Copying more data than the source string len returned %d, expected 0\n", ret);
603     ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == 'l' &&
604        dest[4] == 'l' && dest[5] == '\0'&& dest[6] == 'X' && dest[7] == 'X',
605        "Unexpected return data from _mbsnbcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
606        dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
607 }
608
609 static void test_wcscpy_s(void)
610 {
611     static const WCHAR szLongText[] = { 'T','h','i','s','A','L','o','n','g','s','t','r','i','n','g',0 };
612     static WCHAR szDest[18];
613     static WCHAR szDestShort[8];
614     int ret;
615
616     if(!p_wcscpy_s)
617     {
618         skip("wcscpy_s not found\n");
619         return;
620     }
621
622     /* Test NULL Dest */
623     ret = p_wcscpy_s(NULL, 18, szLongText);
624     ok(ret == EINVAL, "p_wcscpy_s expect EINVAL got %d\n", ret);
625
626     /* Test NULL Source */
627     szDest[0] = 'A';
628     ret = p_wcscpy_s(szDest, 18, NULL);
629     ok(ret == EINVAL, "expected EINVAL got %d\n", ret);
630     ok(szDest[0] == 0, "szDest[0] not 0\n");
631
632     /* Test invalid size */
633     szDest[0] = 'A';
634     ret = p_wcscpy_s(szDest, 0, szLongText);
635     /* Later versions changed the return value for this case to EINVAL,
636      * and don't modify the result if the dest size is 0.
637      */
638     ok(ret == ERANGE || ret == EINVAL, "expected ERANGE/EINVAL got %d\n", ret);
639     ok(szDest[0] == 0 || ret == EINVAL, "szDest[0] not 0\n");
640
641     /* Copy same buffer size */
642     ret = p_wcscpy_s(szDest, 18, szLongText);
643     ok(ret == 0, "expected 0 got %d\n", ret);
644     ok(lstrcmpW(szDest, szLongText) == 0, "szDest != szLongText\n");
645
646     /* Copy smaller buffer size */
647     szDest[0] = 'A';
648     ret = p_wcscpy_s(szDestShort, 8, szLongText);
649     ok(ret == ERANGE || ret == EINVAL, "expected ERANGE/EINVAL got %d\n", ret);
650     ok(szDestShort[0] == 0, "szDestShort[0] not 0\n");
651 }
652
653 static void test__wcsupr_s(void)
654 {
655     static const WCHAR mixedString[] = {'M', 'i', 'X', 'e', 'D', 'l', 'o', 'w',
656                                         'e', 'r', 'U', 'P', 'P', 'E', 'R', 0};
657     static const WCHAR expectedString[] = {'M', 'I', 'X', 'E', 'D', 'L', 'O',
658                                            'W', 'E', 'R', 'U', 'P', 'P', 'E',
659                                            'R', 0};
660     WCHAR testBuffer[2*sizeof(mixedString)/sizeof(WCHAR)];
661     int ret;
662
663     if (!p_wcsupr_s)
664     {
665         win_skip("_wcsupr_s not found\n");
666         return;
667     }
668
669     /* Test NULL input string and invalid size. */
670     errno = EBADF;
671     ret = p_wcsupr_s(NULL, 0);
672     ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
673     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
674
675     /* Test NULL input string and valid size. */
676     errno = EBADF;
677     ret = p_wcsupr_s(NULL, sizeof(testBuffer)/sizeof(WCHAR));
678     ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
679     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
680
681     /* Test empty string with zero size. */
682     errno = EBADF;
683     testBuffer[0] = '\0';
684     ret = p_wcsupr_s(testBuffer, 0);
685     ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
686     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
687     ok(testBuffer[0] == '\0', "Expected the buffer to be unchanged\n");
688
689     /* Test empty string with size of one. */
690     testBuffer[0] = '\0';
691     ret = p_wcsupr_s(testBuffer, 1);
692     ok(ret == 0, "Expected _wcsupr_s to succeed, got %d\n", ret);
693     ok(testBuffer[0] == '\0', "Expected the buffer to be unchanged\n");
694
695     /* Test one-byte buffer with zero size. */
696     errno = EBADF;
697     testBuffer[0] = 'x';
698     ret = p_wcsupr_s(testBuffer, 0);
699     ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
700     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
701     ok(testBuffer[0] == '\0', "Expected the first buffer character to be null\n");
702
703     /* Test one-byte buffer with size of one. */
704     errno = EBADF;
705     testBuffer[0] = 'x';
706     ret = p_wcsupr_s(testBuffer, 1);
707     ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
708     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
709     ok(testBuffer[0] == '\0', "Expected the first buffer character to be null\n");
710
711     /* Test invalid size. */
712     wcscpy(testBuffer, mixedString);
713     errno = EBADF;
714     ret = p_wcsupr_s(testBuffer, 0);
715     ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
716     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
717     ok(testBuffer[0] == '\0', "Expected the first buffer character to be null\n");
718
719     /* Test normal string uppercasing. */
720     wcscpy(testBuffer, mixedString);
721     ret = p_wcsupr_s(testBuffer, sizeof(mixedString)/sizeof(WCHAR));
722     ok(ret == 0, "Expected _wcsupr_s to succeed, got %d\n", ret);
723     ok(!wcscmp(testBuffer, expectedString), "Expected the string to be fully upper-case\n");
724
725     /* Test uppercasing with a shorter buffer size count. */
726     wcscpy(testBuffer, mixedString);
727     errno = EBADF;
728     ret = p_wcsupr_s(testBuffer, sizeof(mixedString)/sizeof(WCHAR) - 1);
729     ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
730     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
731     ok(testBuffer[0] == '\0', "Expected the first buffer character to be null\n");
732
733     /* Test uppercasing with a longer buffer size count. */
734     wcscpy(testBuffer, mixedString);
735     ret = p_wcsupr_s(testBuffer, sizeof(testBuffer)/sizeof(WCHAR));
736     ok(ret == 0, "Expected _wcsupr_s to succeed, got %d\n", ret);
737     ok(!wcscmp(testBuffer, expectedString), "Expected the string to be fully upper-case\n");
738 }
739
740 static void test__wcslwr_s(void)
741 {
742     static const WCHAR mixedString[] = {'M', 'i', 'X', 'e', 'D', 'l', 'o', 'w',
743                                         'e', 'r', 'U', 'P', 'P', 'E', 'R', 0};
744     static const WCHAR expectedString[] = {'m', 'i', 'x', 'e', 'd', 'l', 'o',
745                                            'w', 'e', 'r', 'u', 'p', 'p', 'e',
746                                            'r', 0};
747     WCHAR buffer[2*sizeof(mixedString)/sizeof(WCHAR)];
748     int ret;
749
750     if (!p_wcslwr_s)
751     {
752         win_skip("_wcslwr_s not found\n");
753         return;
754     }
755
756     /* Test NULL input string and invalid size. */
757     errno = EBADF;
758     ret = p_wcslwr_s(NULL, 0);
759     ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
760     ok(errno == EINVAL, "expected errno EINVAL, got %d\n", errno);
761
762     /* Test NULL input string and valid size. */
763     errno = EBADF;
764     ret = p_wcslwr_s(NULL, sizeof(buffer)/sizeof(wchar_t));
765     ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
766     ok(errno == EINVAL, "expected errno EINVAL, got %d\n", errno);
767
768     /* Test empty string with zero size. */
769     errno = EBADF;
770     buffer[0] = 'a';
771     ret = p_wcslwr_s(buffer, 0);
772     ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
773     ok(errno == EINVAL, "expected errno EINVAL, got %d\n", errno);
774     ok(buffer[0] == 0, "expected empty string\n");
775
776     /* Test empty string with size of one. */
777     buffer[0] = 0;
778     ret = p_wcslwr_s(buffer, 1);
779     ok(ret == 0, "got %d\n", ret);
780     ok(buffer[0] == 0, "expected buffer to be unchanged\n");
781
782     /* Test one-byte buffer with zero size. */
783     errno = EBADF;
784     buffer[0] = 'x';
785     ret = p_wcslwr_s(buffer, 0);
786     ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
787     ok(errno == EINVAL, "expected errno to be EINVAL, got %d\n", errno);
788     ok(buffer[0] == '\0', "expected empty string\n");
789
790     /* Test one-byte buffer with size of one. */
791     errno = EBADF;
792     buffer[0] = 'x';
793     ret = p_wcslwr_s(buffer, 1);
794     ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
795     ok(errno == EINVAL, "expected errno to be EINVAL, got %d\n", errno);
796     ok(buffer[0] == '\0', "expected empty string\n");
797
798     /* Test invalid size. */
799     wcscpy(buffer, mixedString);
800     errno = EBADF;
801     ret = p_wcslwr_s(buffer, 0);
802     ok(ret == EINVAL, "Expected EINVAL, got %d\n", ret);
803     ok(errno == EINVAL, "expected errno to be EINVAL, got %d\n", errno);
804     ok(buffer[0] == '\0', "expected empty string\n");
805
806     /* Test normal string uppercasing. */
807     wcscpy(buffer, mixedString);
808     ret = p_wcslwr_s(buffer, sizeof(mixedString)/sizeof(WCHAR));
809     ok(ret == 0, "expected 0, got %d\n", ret);
810     ok(!wcscmp(buffer, expectedString), "expected lowercase\n");
811
812     /* Test uppercasing with a shorter buffer size count. */
813     wcscpy(buffer, mixedString);
814     errno = EBADF;
815     ret = p_wcslwr_s(buffer, sizeof(mixedString)/sizeof(WCHAR) - 1);
816     ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
817     ok(errno == EINVAL, "expected errno to be EINVAL, got %d\n", errno);
818     ok(buffer[0] == '\0', "expected empty string\n");
819
820     /* Test uppercasing with a longer buffer size count. */
821     wcscpy(buffer, mixedString);
822     ret = p_wcslwr_s(buffer, sizeof(buffer)/sizeof(WCHAR));
823     ok(ret == 0, "expected 0, got %d\n", ret);
824     ok(!wcscmp(buffer, expectedString), "expected lowercase\n");
825 }
826
827 static void test_mbcjisjms(void)
828 {
829     /* List of value-pairs to test. The test assumes the last pair to be {0, ..} */
830     unsigned int jisjms[][2] = { {0x2020, 0}, {0x2021, 0}, {0x2120, 0}, {0x2121, 0x8140},
831                                  {0x7f7f, 0}, {0x7f7e, 0}, {0x7e7f, 0}, {0x7e7e, 0xeffc},
832                                  {0x2121FFFF, 0}, {0x2223, 0x81a1}, {0x237e, 0x829e}, {0, 0}};
833     unsigned int ret, exp, i;
834
835     i = 0;
836     do
837     {
838         ret = _mbcjistojms(jisjms[i][0]);
839
840         if(_getmbcp() == 932)   /* Japanese codepage? */
841             exp = jisjms[i][1];
842         else
843             exp = jisjms[i][0]; /* If not, no conversion */
844
845         ok(ret == exp, "Expected 0x%x, got 0x%x\n", exp, ret);
846     } while(jisjms[i++][0] != 0);
847 }
848
849 static void test_mbctombb(void)
850 {
851     static const unsigned int mbcmbb_932[][2] = {
852         {0x829e, 0x829e}, {0x829f, 0xa7}, {0x82f1, 0xdd}, {0x82f2, 0x82f2},
853         {0x833f, 0x833f}, {0x8340, 0xa7}, {0x837e, 0xd0}, {0x837f, 0x837f},
854         {0x8380, 0xd1}, {0x8396, 0xb9}, {0x8397, 0x8397}, {0x813f, 0x813f},
855         {0x8140, 0x20}, {0x814c, 0x814c}, {0x814f, 0x5e}, {0x8197, 0x40},
856         {0x8198, 0x8198}, {0x8258, 0x39}, {0x8259, 0x8259}, {0x825f, 0x825f},
857         {0x8260, 0x41}, {0x82f1, 0xdd}, {0x82f2, 0x82f2}, {0,0}};
858     unsigned int exp, ret, i;
859     unsigned int prev_cp = _getmbcp();
860
861     _setmbcp(932);
862     for (i = 0; mbcmbb_932[i][0] != 0; i++)
863     {
864         ret = _mbctombb(mbcmbb_932[i][0]);
865         exp = mbcmbb_932[i][1];
866         ok(ret == exp, "Expected 0x%x, got 0x%x\n", exp, ret);
867     }
868     _setmbcp(prev_cp);
869 }
870
871 static void test_ismbclegal(void) {
872     unsigned int prev_cp = _getmbcp();
873     int ret, exp, err;
874     unsigned int i;
875
876     _setmbcp(932); /* Japanese */
877     err = 0;
878     for(i = 0; i < 0x10000; i++) {
879         ret = _ismbclegal(i);
880         exp = ((HIBYTE(i) >= 0x81 && HIBYTE(i) <= 0x9F) ||
881                (HIBYTE(i) >= 0xE0 && HIBYTE(i) <= 0xFC)) &&
882               ((LOBYTE(i) >= 0x40 && LOBYTE(i) <= 0x7E) ||
883                (LOBYTE(i) >= 0x80 && LOBYTE(i) <= 0xFC));
884         if(ret != exp) {
885             err = 1;
886             break;
887         }
888     }
889     ok(!err, "_ismbclegal (932) : Expected 0x%x, got 0x%x (0x%x)\n", exp, ret, i);
890     _setmbcp(936); /* Chinese (GBK) */
891     err = 0;
892     for(i = 0; i < 0x10000; i++) {
893         ret = _ismbclegal(i);
894         exp = HIBYTE(i) >= 0x81 && HIBYTE(i) <= 0xFE &&
895               LOBYTE(i) >= 0x40 && LOBYTE(i) <= 0xFE;
896         if(ret != exp) {
897             err = 1;
898             break;
899         }
900     }
901     ok(!err, "_ismbclegal (936) : Expected 0x%x, got 0x%x (0x%x)\n", exp, ret, i);
902     _setmbcp(949); /* Korean */
903     err = 0;
904     for(i = 0; i < 0x10000; i++) {
905         ret = _ismbclegal(i);
906         exp = HIBYTE(i) >= 0x81 && HIBYTE(i) <= 0xFE &&
907               LOBYTE(i) >= 0x41 && LOBYTE(i) <= 0xFE;
908         if(ret != exp) {
909             err = 1;
910             break;
911         }
912     }
913     ok(!err, "_ismbclegal (949) : Expected 0x%x, got 0x%x (0x%x)\n", exp, ret, i);
914     _setmbcp(950); /* Chinese (Big5) */
915     err = 0;
916     for(i = 0; i < 0x10000; i++) {
917         ret = _ismbclegal(i);
918         exp = HIBYTE(i) >= 0x81 && HIBYTE(i) <= 0xFE &&
919             ((LOBYTE(i) >= 0x40 && LOBYTE(i) <= 0x7E) ||
920              (LOBYTE(i) >= 0xA1 && LOBYTE(i) <= 0xFE));
921         if(ret != exp) {
922             err = 1;
923             break;
924         }
925     }
926     ok(!err, "_ismbclegal (950) : Expected 0x%x, got 0x%x (0x%x)\n", exp, ret, i);
927     _setmbcp(1361); /* Korean (Johab) */
928     err = 0;
929     for(i = 0; i < 0x10000; i++) {
930         ret = _ismbclegal(i);
931         exp = ((HIBYTE(i) >= 0x81 && HIBYTE(i) <= 0xD3) ||
932                (HIBYTE(i) >= 0xD8 && HIBYTE(i) <= 0xF9)) &&
933               ((LOBYTE(i) >= 0x31 && LOBYTE(i) <= 0x7E) ||
934                (LOBYTE(i) >= 0x81 && LOBYTE(i) <= 0xFE)) &&
935                 HIBYTE(i) != 0xDF;
936         if(ret != exp) {
937             err = 1;
938             break;
939         }
940     }
941     todo_wine ok(!err, "_ismbclegal (1361) : Expected 0x%x, got 0x%x (0x%x)\n", exp, ret, i);
942
943     _setmbcp(prev_cp);
944 }
945
946 static const struct {
947     const char* string;
948     const char* delimiter;
949     int exp_offsetret1; /* returned offset from string after first call to strtok()
950                            -1 means NULL  */
951     int exp_offsetret2; /* returned offset from string after second call to strtok()
952                            -1 means NULL  */
953     int exp_offsetret3; /* returned offset from string after third call to strtok()
954                            -1 means NULL  */
955 } testcases_strtok[] = {
956     { "red cabernet", " ", 0, 4, -1 },
957     { "sparkling white riesling", " ", 0, 10, 16 },
958     { " pale cream sherry", "e ", 1, 6, 9 },
959     /* end mark */
960     { 0}
961 };
962
963 static void test_strtok(void)
964 {
965     int i;
966     char *strret;
967     char teststr[100];
968     for( i = 0; testcases_strtok[i].string; i++){
969         strcpy( teststr, testcases_strtok[i].string);
970         strret = strtok( teststr, testcases_strtok[i].delimiter);
971         ok( (int)(strret - teststr) ==  testcases_strtok[i].exp_offsetret1 ||
972                 (!strret && testcases_strtok[i].exp_offsetret1 == -1),
973                 "string (%p) \'%s\' return %p\n",
974                 teststr, testcases_strtok[i].string, strret);
975         if( !strret) continue;
976         strret = strtok( NULL, testcases_strtok[i].delimiter);
977         ok( (int)(strret - teststr) ==  testcases_strtok[i].exp_offsetret2 ||
978                 (!strret && testcases_strtok[i].exp_offsetret2 == -1),
979                 "second call string (%p) \'%s\' return %p\n",
980                 teststr, testcases_strtok[i].string, strret);
981         if( !strret) continue;
982         strret = strtok( NULL, testcases_strtok[i].delimiter);
983         ok( (int)(strret - teststr) ==  testcases_strtok[i].exp_offsetret3 ||
984                 (!strret && testcases_strtok[i].exp_offsetret3 == -1),
985                 "third call string (%p) \'%s\' return %p\n",
986                 teststr, testcases_strtok[i].string, strret);
987     }
988 }
989
990 static void test_strtol(void)
991 {
992     char* e;
993     LONG l;
994     ULONG ul;
995
996     /* errno is only set in case of error, so reset errno to EBADF to check for errno modification */
997     /* errno is modified on W2K8+ */
998     errno = EBADF;
999     l = strtol("-1234", &e, 0);
1000     ok(l==-1234, "wrong value %d\n", l);
1001     ok(errno == EBADF || broken(errno == 0), "wrong errno %d\n", errno);
1002     errno = EBADF;
1003     ul = strtoul("1234", &e, 0);
1004     ok(ul==1234, "wrong value %u\n", ul);
1005     ok(errno == EBADF || broken(errno == 0), "wrong errno %d\n", errno);
1006
1007     errno = EBADF;
1008     l = strtol("2147483647L", &e, 0);
1009     ok(l==2147483647, "wrong value %d\n", l);
1010     ok(errno == EBADF || broken(errno == 0), "wrong errno %d\n", errno);
1011     errno = EBADF;
1012     l = strtol("-2147483648L", &e, 0);
1013     ok(l==-2147483647L - 1, "wrong value %d\n", l);
1014     ok(errno == EBADF || broken(errno == 0), "wrong errno %d\n", errno);
1015     errno = EBADF;
1016     ul = strtoul("4294967295UL", &e, 0);
1017     ok(ul==4294967295ul, "wrong value %u\n", ul);
1018     ok(errno == EBADF || broken(errno == 0), "wrong errno %d\n", errno);
1019
1020     errno = 0;
1021     l = strtol("9223372036854775807L", &e, 0);
1022     ok(l==2147483647, "wrong value %d\n", l);
1023     ok(errno == ERANGE, "wrong errno %d\n", errno);
1024     errno = 0;
1025     ul = strtoul("9223372036854775807L", &e, 0);
1026     ok(ul==4294967295ul, "wrong value %u\n", ul);
1027     ok(errno == ERANGE, "wrong errno %d\n", errno);
1028 }
1029
1030 static void test_strnlen(void)
1031 {
1032     static const char str[] = "string";
1033     size_t res;
1034
1035     if(!p_strnlen) {
1036         win_skip("strnlen not found\n");
1037         return;
1038     }
1039
1040     res = p_strnlen(str, 20);
1041     ok(res == 6, "Returned length = %d\n", (int)res);
1042
1043     res = p_strnlen(str, 3);
1044     ok(res == 3, "Returned length = %d\n", (int)res);
1045
1046     res = p_strnlen(NULL, 0);
1047     ok(res == 0, "Returned length = %d\n", (int)res);
1048 }
1049
1050 static void test__strtoi64(void)
1051 {
1052     static const char no1[] = "31923";
1053     static const char no2[] = "-213312";
1054     static const char no3[] = "12aa";
1055     static const char no4[] = "abc12";
1056     static const char overflow[] = "99999999999999999999";
1057     static const char neg_overflow[] = "-99999999999999999999";
1058     static const char hex[] = "0x123";
1059     static const char oct[] = "000123";
1060     static const char blanks[] = "        12 212.31";
1061
1062     __int64 res;
1063     unsigned __int64 ures;
1064     char *endpos;
1065
1066     if(!p_strtoi64 || !p_strtoui64) {
1067         win_skip("_strtoi64 or _strtoui64 not found\n");
1068         return;
1069     }
1070
1071     errno = 0xdeadbeef;
1072     res = p_strtoi64(no1, NULL, 10);
1073     ok(res == 31923, "res != 31923\n");
1074     res = p_strtoi64(no2, NULL, 10);
1075     ok(res == -213312, "res != -213312\n");
1076     res = p_strtoi64(no3, NULL, 10);
1077     ok(res == 12, "res != 12\n");
1078     res = p_strtoi64(no4, &endpos, 10);
1079     ok(res == 0, "res != 0\n");
1080     ok(endpos == no4, "Scanning was not stopped on first character\n");
1081     res = p_strtoi64(hex, &endpos, 10);
1082     ok(res == 0, "res != 0\n");
1083     ok(endpos == hex+1, "Incorrect endpos (%p-%p)\n", hex, endpos);
1084     res = p_strtoi64(oct, &endpos, 10);
1085     ok(res == 123, "res != 123\n");
1086     ok(endpos == oct+strlen(oct), "Incorrect endpos (%p-%p)\n", oct, endpos);
1087     res = p_strtoi64(blanks, &endpos, 10);
1088     ok(res == 12, "res != 12\n");
1089     ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos);
1090     ok(errno == 0xdeadbeef, "errno = %x\n", errno);
1091
1092     errno = 0xdeadbeef;
1093     res = p_strtoi64(overflow, &endpos, 10);
1094     ok(res == _I64_MAX, "res != _I64_MAX\n");
1095     ok(endpos == overflow+strlen(overflow), "Incorrect endpos (%p-%p)\n", overflow, endpos);
1096     ok(errno == ERANGE, "errno = %x\n", errno);
1097
1098     errno = 0xdeadbeef;
1099     res = p_strtoi64(neg_overflow, &endpos, 10);
1100     ok(res == _I64_MIN, "res != _I64_MIN\n");
1101     ok(endpos == neg_overflow+strlen(neg_overflow), "Incorrect endpos (%p-%p)\n", neg_overflow, endpos);
1102     ok(errno == ERANGE, "errno = %x\n", errno);
1103
1104     errno = 0xdeadbeef;
1105     res = p_strtoi64(no1, &endpos, 16);
1106     ok(res == 203043, "res != 203043\n");
1107     ok(endpos == no1+strlen(no1), "Incorrect endpos (%p-%p)\n", no1, endpos);
1108     res = p_strtoi64(no2, &endpos, 16);
1109     ok(res == -2175762, "res != -2175762\n");
1110     ok(endpos == no2+strlen(no2), "Incorrect endpos (%p-%p)\n", no2, endpos);
1111     res = p_strtoi64(no3, &endpos, 16);
1112     ok(res == 4778, "res != 4778\n");
1113     ok(endpos == no3+strlen(no3), "Incorrect endpos (%p-%p)\n", no3, endpos);
1114     res = p_strtoi64(no4, &endpos, 16);
1115     ok(res == 703506, "res != 703506\n");
1116     ok(endpos == no4+strlen(no4), "Incorrect endpos (%p-%p)\n", no4, endpos);
1117     res = p_strtoi64(hex, &endpos, 16);
1118     ok(res == 291, "res != 291\n");
1119     ok(endpos == hex+strlen(hex), "Incorrect endpos (%p-%p)\n", hex, endpos);
1120     res = p_strtoi64(oct, &endpos, 16);
1121     ok(res == 291, "res != 291\n");
1122     ok(endpos == oct+strlen(oct), "Incorrect endpos (%p-%p)\n", oct, endpos);
1123     res = p_strtoi64(blanks, &endpos, 16);
1124     ok(res == 18, "res != 18\n");
1125     ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos);
1126     ok(errno == 0xdeadbeef, "errno = %x\n", errno);
1127
1128     errno = 0xdeadbeef;
1129     res = p_strtoi64(hex, &endpos, 36);
1130     ok(res == 1541019, "res != 1541019\n");
1131     ok(endpos == hex+strlen(hex), "Incorrect endpos (%p-%p)\n", hex, endpos);
1132     ok(errno == 0xdeadbeef, "errno = %x\n", errno);
1133
1134     errno = 0xdeadbeef;
1135     res = p_strtoi64(no1, &endpos, 0);
1136     ok(res == 31923, "res != 31923\n");
1137     ok(endpos == no1+strlen(no1), "Incorrect endpos (%p-%p)\n", no1, endpos);
1138     res = p_strtoi64(no2, &endpos, 0);
1139     ok(res == -213312, "res != -213312\n");
1140     ok(endpos == no2+strlen(no2), "Incorrect endpos (%p-%p)\n", no2, endpos);
1141     res = p_strtoi64(no3, &endpos, 10);
1142     ok(res == 12, "res != 12\n");
1143     ok(endpos == no3+2, "Incorrect endpos (%p-%p)\n", no3, endpos);
1144     res = p_strtoi64(no4, &endpos, 10);
1145     ok(res == 0, "res != 0\n");
1146     ok(endpos == no4, "Incorrect endpos (%p-%p)\n", no4, endpos);
1147     res = p_strtoi64(hex, &endpos, 10);
1148     ok(res == 0, "res != 0\n");
1149     ok(endpos == hex+1, "Incorrect endpos (%p-%p)\n", hex, endpos);
1150     res = p_strtoi64(oct, &endpos, 10);
1151     ok(res == 123, "res != 123\n");
1152     ok(endpos == oct+strlen(oct), "Incorrect endpos (%p-%p)\n", oct, endpos);
1153     res = p_strtoi64(blanks, &endpos, 10);
1154     ok(res == 12, "res != 12\n");
1155     ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos);
1156     ok(errno == 0xdeadbeef, "errno = %x\n", errno);
1157
1158     errno = 0xdeadbeef;
1159     ures = p_strtoui64(no1, &endpos, 0);
1160     ok(ures == 31923, "ures != 31923\n");
1161     ok(endpos == no1+strlen(no1), "Incorrect endpos (%p-%p)\n", no1, endpos);
1162     ures = p_strtoui64(no2, &endpos, 0);
1163     ok(ures == -213312, "ures != -213312\n");
1164     ok(endpos == no2+strlen(no2), "Incorrect endpos (%p-%p)\n", no2, endpos);
1165     ures = p_strtoui64(no3, &endpos, 10);
1166     ok(ures == 12, "ures != 12\n");
1167     ok(endpos == no3+2, "Incorrect endpos (%p-%p)\n", no3, endpos);
1168     ures = p_strtoui64(no4, &endpos, 10);
1169     ok(ures == 0, "ures != 0\n");
1170     ok(endpos == no4, "Incorrect endpos (%p-%p)\n", no4, endpos);
1171     ures = p_strtoui64(hex, &endpos, 10);
1172     ok(ures == 0, "ures != 0\n");
1173     ok(endpos == hex+1, "Incorrect endpos (%p-%p)\n", hex, endpos);
1174     ures = p_strtoui64(oct, &endpos, 10);
1175     ok(ures == 123, "ures != 123\n");
1176     ok(endpos == oct+strlen(oct), "Incorrect endpos (%p-%p)\n", oct, endpos);
1177     ures = p_strtoui64(blanks, &endpos, 10);
1178     ok(ures == 12, "ures != 12\n");
1179     ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos);
1180     ok(errno == 0xdeadbeef, "errno = %x\n", errno);
1181
1182     errno = 0xdeadbeef;
1183     ures = p_strtoui64(overflow, &endpos, 10);
1184     ok(ures == _UI64_MAX, "ures != _UI64_MAX\n");
1185     ok(endpos == overflow+strlen(overflow), "Incorrect endpos (%p-%p)\n", overflow, endpos);
1186     ok(errno == ERANGE, "errno = %x\n", errno);
1187
1188     errno = 0xdeadbeef;
1189     ures = p_strtoui64(neg_overflow, &endpos, 10);
1190     ok(ures == 1, "ures != 1\n");
1191     ok(endpos == neg_overflow+strlen(neg_overflow), "Incorrect endpos (%p-%p)\n", neg_overflow, endpos);
1192     ok(errno == ERANGE, "errno = %x\n", errno);
1193 }
1194
1195 static inline BOOL almost_equal(double d1, double d2) {
1196     if(d1-d2>-1e-30 && d1-d2<1e-30)
1197         return TRUE;
1198     return FALSE;
1199 }
1200
1201 static void test__strtod(void)
1202 {
1203     const char double1[] = "12.1";
1204     const char double2[] = "-13.721";
1205     const char double3[] = "INF";
1206     const char double4[] = ".21e12";
1207     const char double5[] = "214353e-3";
1208     const char overflow[] = "1d9999999999999999999";
1209     const char white_chars[] = "  d10";
1210
1211     char *end;
1212     double d;
1213
1214     d = strtod(double1, &end);
1215     ok(almost_equal(d, 12.1), "d = %lf\n", d);
1216     ok(end == double1+4, "incorrect end (%d)\n", (int)(end-double1));
1217
1218     d = strtod(double2, &end);
1219     ok(almost_equal(d, -13.721), "d = %lf\n", d);
1220     ok(end == double2+7, "incorrect end (%d)\n", (int)(end-double2));
1221
1222     d = strtod(double3, &end);
1223     ok(almost_equal(d, 0), "d = %lf\n", d);
1224     ok(end == double3, "incorrect end (%d)\n", (int)(end-double3));
1225
1226     d = strtod(double4, &end);
1227     ok(almost_equal(d, 210000000000.0), "d = %lf\n", d);
1228     ok(end == double4+6, "incorrect end (%d)\n", (int)(end-double4));
1229
1230     d = strtod(double5, &end);
1231     ok(almost_equal(d, 214.353), "d = %lf\n", d);
1232     ok(end == double5+9, "incorrect end (%d)\n", (int)(end-double5));
1233
1234     d = strtod("12.1d2", NULL);
1235     ok(almost_equal(d, 12.1e2), "d = %lf\n", d);
1236
1237     d = strtod(white_chars, &end);
1238     ok(almost_equal(d, 0), "d = %lf\n", d);
1239     ok(end == white_chars, "incorrect end (%d)\n", (int)(end-white_chars));
1240
1241     /* Set locale with non '.' decimal point (',') */
1242     if(!setlocale(LC_ALL, "Polish")) {
1243         win_skip("system with limited locales\n");
1244         return;
1245     }
1246
1247     d = strtod("12.1", NULL);
1248     ok(almost_equal(d, 12.0), "d = %lf\n", d);
1249
1250     d = strtod("12,1", NULL);
1251     ok(almost_equal(d, 12.1), "d = %lf\n", d);
1252
1253     setlocale(LC_ALL, "C");
1254
1255     /* Precision tests */
1256     d = strtod("0.1", NULL);
1257     ok(almost_equal(d, 0.1), "d = %lf\n", d);
1258     d = strtod("-0.1", NULL);
1259     ok(almost_equal(d, -0.1), "d = %lf\n", d);
1260     d = strtod("0.1281832188491894198128921", NULL);
1261     ok(almost_equal(d, 0.1281832188491894198128921), "d = %lf\n", d);
1262     d = strtod("0.82181281288121", NULL);
1263     ok(almost_equal(d, 0.82181281288121), "d = %lf\n", d);
1264     d = strtod("21921922352523587651128218821", NULL);
1265     ok(almost_equal(d, 21921922352523587651128218821.0), "d = %lf\n", d);
1266     d = strtod("0.1d238", NULL);
1267     ok(almost_equal(d, 0.1e238L), "d = %lf\n", d);
1268     d = strtod("0.1D-4736", NULL);
1269     ok(almost_equal(d, 0.1e-4736L), "d = %lf\n", d);
1270
1271     errno = 0xdeadbeef;
1272     strtod(overflow, &end);
1273     ok(errno == ERANGE, "errno = %x\n", errno);
1274     ok(end == overflow+21, "incorrect end (%d)\n", (int)(end-overflow));
1275
1276     errno = 0xdeadbeef;
1277     strtod("-1d309", NULL);
1278     ok(errno == ERANGE, "errno = %x\n", errno);
1279 }
1280
1281 static void test_mbstowcs(void)
1282 {
1283     static const wchar_t wSimple[] = { 't','e','x','t',0 };
1284     static const wchar_t wHiragana[] = { 0x3042,0x3043,0 };
1285     static const char mSimple[] = "text";
1286     static const char mHiragana[] = { 0x82,0xa0,0x82,0xa1,0 };
1287
1288     const wchar_t *pwstr;
1289     wchar_t wOut[6];
1290     char mOut[6];
1291     size_t ret;
1292     int err;
1293
1294     wOut[4] = '!'; wOut[5] = '\0';
1295     mOut[4] = '!'; mOut[5] = '\0';
1296
1297     ret = mbstowcs(NULL, mSimple, 0);
1298     ok(ret == 4, "mbstowcs did not return 4\n");
1299
1300     ret = mbstowcs(wOut, mSimple, 4);
1301     ok(ret == 4, "mbstowcs did not return 4\n");
1302     ok(!memcmp(wOut, wSimple, 4*sizeof(wchar_t)), "wOut = %s\n", wine_dbgstr_w(wOut));
1303     ok(wOut[4] == '!', "wOut[4] != \'!\'\n");
1304
1305     ret = wcstombs(NULL, wSimple, 0);
1306     ok(ret == 4, "wcstombs did not return 4\n");
1307
1308     ret = wcstombs(mOut, wSimple, 6);
1309     ok(ret == 4, "wcstombs did not return 4\n");
1310     ok(!memcmp(mOut, mSimple, 5*sizeof(char)), "mOut = %s\n", mOut);
1311
1312     ret = wcstombs(mOut, wSimple, 2);
1313     ok(ret == 2, "wcstombs did not return 2\n");
1314     ok(!memcmp(mOut, mSimple, 5*sizeof(char)), "mOut = %s\n", mOut);
1315
1316     if(!setlocale(LC_ALL, "Japanese_Japan.932")) {
1317         win_skip("Japanese_Japan.932 locale not available\n");
1318         return;
1319     }
1320
1321     ret = mbstowcs(wOut, mHiragana, 6);
1322     ok(ret == 2, "mbstowcs did not return 2\n");
1323     ok(!memcmp(wOut, wHiragana, sizeof(wHiragana)), "wOut = %s\n", wine_dbgstr_w(wOut));
1324
1325     ret = wcstombs(mOut, wHiragana, 6);
1326     ok(ret == 4, "wcstombs did not return 4\n");
1327     ok(!memcmp(mOut, mHiragana, sizeof(mHiragana)), "mOut = %s\n", mOut);
1328
1329     if(!pmbstowcs_s || !pwcstombs_s) {
1330         setlocale(LC_ALL, "C");
1331         win_skip("mbstowcs_s or wcstombs_s not available\n");
1332         return;
1333     }
1334
1335     err = pmbstowcs_s(&ret, wOut, 6, mSimple, _TRUNCATE);
1336     ok(err == 0, "err = %d\n", err);
1337     ok(ret == 5, "mbstowcs_s did not return 5\n");
1338     ok(!memcmp(wOut, wSimple, sizeof(wSimple)), "wOut = %s\n", wine_dbgstr_w(wOut));
1339
1340     err = pmbstowcs_s(&ret, wOut, 6, mHiragana, _TRUNCATE);
1341     ok(err == 0, "err = %d\n", err);
1342     ok(ret == 3, "mbstowcs_s did not return 3\n");
1343     ok(!memcmp(wOut, wHiragana, sizeof(wHiragana)), "wOut = %s\n", wine_dbgstr_w(wOut));
1344
1345     err = pmbstowcs_s(&ret, NULL, 0, mHiragana, 1);
1346     ok(err == 0, "err = %d\n", err);
1347     ok(ret == 3, "mbstowcs_s did not return 3\n");
1348
1349     err = pwcstombs_s(&ret, mOut, 6, wSimple, _TRUNCATE);
1350     ok(err == 0, "err = %d\n", err);
1351     ok(ret == 5, "wcstombs_s did not return 5\n");
1352     ok(!memcmp(mOut, mSimple, sizeof(mSimple)), "mOut = %s\n", mOut);
1353
1354     err = pwcstombs_s(&ret, mOut, 6, wHiragana, _TRUNCATE);
1355     ok(err == 0, "err = %d\n", err);
1356     ok(ret == 5, "wcstombs_s did not return 5\n");
1357     ok(!memcmp(mOut, mHiragana, sizeof(mHiragana)), "mOut = %s\n", mOut);
1358
1359     err = pwcstombs_s(&ret, NULL, 0, wHiragana, 1);
1360     ok(err == 0, "err = %d\n", err);
1361     ok(ret == 5, "wcstombs_s did not return 5\n");
1362
1363     if(!pwcsrtombs) {
1364         setlocale(LC_ALL, "C");
1365         win_skip("wcsrtombs not available\n");
1366         return;
1367     }
1368
1369     pwstr = wSimple;
1370     err = -3;
1371     ret = pwcsrtombs(mOut, &pwstr, 4, &err);
1372     ok(ret == 4, "wcsrtombs did not return 4\n");
1373     ok(err == 0, "err = %d\n", err);
1374     ok(pwstr == wSimple+4, "pwstr = %p (wszSimple = %p)\n", pwstr, wSimple);
1375     ok(!memcmp(mOut, mSimple, ret), "mOut = %s\n", mOut);
1376
1377     pwstr = wSimple;
1378     ret = pwcsrtombs(mOut, &pwstr, 5, NULL);
1379     ok(ret == 4, "wcsrtombs did not return 4\n");
1380     ok(pwstr == NULL, "pwstr != NULL\n");
1381     ok(!memcmp(mOut, mSimple, sizeof(mSimple)), "mOut = %s\n", mOut);
1382
1383     setlocale(LC_ALL, "C");
1384 }
1385
1386 static void test_gcvt(void)
1387 {
1388     char buf[1024], *res;
1389     errno_t err;
1390
1391     if(!p_gcvt_s) {
1392         win_skip("Skipping _gcvt tests\n");
1393         return;
1394     }
1395
1396     errno = 0;
1397     res = _gcvt(1.2, -1, buf);
1398     ok(res == NULL, "res != NULL\n");
1399     ok(errno == ERANGE, "errno = %d\n", errno);
1400
1401     errno = 0;
1402     res = _gcvt(1.2, 5, NULL);
1403     ok(res == NULL, "res != NULL\n");
1404     ok(errno == EINVAL, "errno = %d\n", errno);
1405
1406     res = gcvt(1.2, 5, buf);
1407     ok(res == buf, "res != buf\n");
1408     ok(!strcmp(buf, "1.2"), "buf = %s\n", buf);
1409
1410     buf[0] = 'x';
1411     err = p_gcvt_s(buf, 5, 1.2, 10);
1412     ok(err == ERANGE, "err = %d\n", err);
1413     ok(buf[0] == '\0', "buf[0] = %c\n", buf[0]);
1414
1415     buf[0] = 'x';
1416     err = p_gcvt_s(buf, 4, 123456, 2);
1417     ok(err == ERANGE, "err = %d\n", err);
1418     ok(buf[0] == '\0', "buf[0] = %c\n", buf[0]);
1419 }
1420
1421 static void test__itoa_s(void)
1422 {
1423     errno_t ret;
1424     char buffer[33];
1425
1426     if (!p_itoa_s)
1427     {
1428         win_skip("Skipping _itoa_s tests\n");
1429         return;
1430     }
1431
1432     if (p_set_invalid_parameter_handler)
1433         ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
1434                 "Invalid parameter handler was already set\n");
1435
1436     errno = EBADF;
1437     ret = p_itoa_s(0, NULL, 0, 0);
1438     ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
1439     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1440
1441     memset(buffer, 'X', sizeof(buffer));
1442     errno = EBADF;
1443     ret = p_itoa_s(0, buffer, 0, 0);
1444     ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
1445     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1446     ok(buffer[0] == 'X', "Expected the output buffer to be untouched\n");
1447
1448     memset(buffer, 'X', sizeof(buffer));
1449     errno = EBADF;
1450     ret = p_itoa_s(0, buffer, sizeof(buffer), 0);
1451     ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
1452     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1453     ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
1454
1455     memset(buffer, 'X', sizeof(buffer));
1456     errno = EBADF;
1457     ret = p_itoa_s(0, buffer, sizeof(buffer), 64);
1458     ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
1459     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1460     ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
1461
1462     memset(buffer, 'X', sizeof(buffer));
1463     errno = EBADF;
1464     ret = p_itoa_s(12345678, buffer, 4, 10);
1465     ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
1466     ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
1467     ok(!memcmp(buffer, "\000765", 4),
1468        "Expected the output buffer to be null terminated with truncated output\n");
1469
1470     memset(buffer, 'X', sizeof(buffer));
1471     errno = EBADF;
1472     ret = p_itoa_s(12345678, buffer, 8, 10);
1473     ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
1474     ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
1475     ok(!memcmp(buffer, "\0007654321", 8),
1476        "Expected the output buffer to be null terminated with truncated output\n");
1477
1478     memset(buffer, 'X', sizeof(buffer));
1479     errno = EBADF;
1480     ret = p_itoa_s(-12345678, buffer, 9, 10);
1481     ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
1482     ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
1483     ok(!memcmp(buffer, "\00087654321", 9),
1484        "Expected the output buffer to be null terminated with truncated output\n");
1485
1486     ret = p_itoa_s(12345678, buffer, 9, 10);
1487     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
1488     ok(!strcmp(buffer, "12345678"),
1489        "Expected output buffer string to be \"12345678\", got \"%s\"\n",
1490        buffer);
1491
1492     ret = p_itoa_s(43690, buffer, sizeof(buffer), 2);
1493     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
1494     ok(!strcmp(buffer, "1010101010101010"),
1495        "Expected output buffer string to be \"1010101010101010\", got \"%s\"\n",
1496        buffer);
1497
1498     ret = p_itoa_s(1092009, buffer, sizeof(buffer), 36);
1499     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
1500     ok(!strcmp(buffer, "nell"),
1501        "Expected output buffer string to be \"nell\", got \"%s\"\n",
1502        buffer);
1503
1504     ret = p_itoa_s(5704, buffer, sizeof(buffer), 18);
1505     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
1506     ok(!strcmp(buffer, "hag"),
1507        "Expected output buffer string to be \"hag\", got \"%s\"\n",
1508        buffer);
1509
1510     ret = p_itoa_s(-12345678, buffer, sizeof(buffer), 10);
1511     ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
1512     ok(!strcmp(buffer, "-12345678"),
1513        "Expected output buffer string to be \"-12345678\", got \"%s\"\n",
1514        buffer);
1515     if (p_set_invalid_parameter_handler)
1516         ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler,
1517                 "Cannot reset invalid parameter handler\n");
1518 }
1519
1520 static void test__strlwr_s(void)
1521 {
1522     errno_t ret;
1523     char buffer[20];
1524
1525     if (!p_strlwr_s)
1526     {
1527         win_skip("Skipping _strlwr_s tests\n");
1528         return;
1529     }
1530
1531     errno = EBADF;
1532     ret = p_strlwr_s(NULL, 0);
1533     ok(ret == EINVAL, "Expected _strlwr_s to return EINVAL, got %d\n", ret);
1534     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1535
1536     errno = EBADF;
1537     ret = p_strlwr_s(NULL, sizeof(buffer));
1538     ok(ret == EINVAL, "Expected _strlwr_s to return EINVAL, got %d\n", ret);
1539     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1540
1541     errno = EBADF;
1542     ret = p_strlwr_s(buffer, 0);
1543     ok(ret == EINVAL, "Expected _strlwr_s to return EINVAL, got %d\n", ret);
1544     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1545
1546     strcpy(buffer, "GoRrIsTeR");
1547     errno = EBADF;
1548     ret = p_strlwr_s(buffer, 5);
1549     ok(ret == EINVAL, "Expected _strlwr_s to return EINVAL, got %d\n", ret);
1550     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1551     ok(!memcmp(buffer, "\0oRrIsTeR", sizeof("\0oRrIsTeR")),
1552        "Expected the output buffer to be \"gorrIsTeR\"\n");
1553
1554     strcpy(buffer, "GoRrIsTeR");
1555     errno = EBADF;
1556     ret = p_strlwr_s(buffer, sizeof("GoRrIsTeR") - 1);
1557     ok(ret == EINVAL, "Expected _strlwr_s to return EINVAL, got %d\n", ret);
1558     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1559     ok(!memcmp(buffer, "\0oRrIsTeR", sizeof("\0oRrIsTeR")),
1560        "Expected the output buffer to be \"gorrIsTeR\"\n");
1561
1562     strcpy(buffer, "GoRrIsTeR");
1563     ret = p_strlwr_s(buffer, sizeof("GoRrIsTeR"));
1564     ok(ret == 0, "Expected _strlwr_s to return 0, got %d\n", ret);
1565     ok(!strcmp(buffer, "gorrister"),
1566        "Expected the output buffer to be \"gorrister\", got \"%s\"\n",
1567        buffer);
1568
1569     memcpy(buffer, "GoRrIsTeR\0ELLEN", sizeof("GoRrIsTeR\0ELLEN"));
1570     ret = p_strlwr_s(buffer, sizeof(buffer));
1571     ok(ret == 0, "Expected _strlwr_s to return 0, got %d\n", ret);
1572     ok(!memcmp(buffer, "gorrister\0ELLEN", sizeof("gorrister\0ELLEN")),
1573        "Expected the output buffer to be \"gorrister\\0ELLEN\", got \"%s\"\n",
1574        buffer);
1575 }
1576
1577 static void test_wcsncat_s(void)
1578 {
1579     static wchar_t abcW[] = {'a','b','c',0};
1580     int ret;
1581     wchar_t dst[4];
1582     wchar_t src[4];
1583
1584     if (!p_wcsncat_s)
1585     {
1586         win_skip("skipping wcsncat_s tests\n");
1587         return;
1588     }
1589
1590     if (p_set_invalid_parameter_handler)
1591         ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
1592                 "Invalid parameter handler was already set\n");
1593
1594     memcpy(src, abcW, sizeof(abcW));
1595     dst[0] = 0;
1596     ret = p_wcsncat_s(NULL, 4, src, 4);
1597     ok(ret == EINVAL, "err = %d\n", ret);
1598     ret = p_wcsncat_s(dst, 0, src, 4);
1599     ok(ret == EINVAL, "err = %d\n", ret);
1600     ret = p_wcsncat_s(dst, 0, src, _TRUNCATE);
1601     ok(ret == EINVAL, "err = %d\n", ret);
1602     ret = p_wcsncat_s(dst, 4, NULL, 0);
1603     ok(ret == 0, "err = %d\n", ret);
1604
1605     dst[0] = 0;
1606     ret = p_wcsncat_s(dst, 2, src, 4);
1607     ok(ret == ERANGE, "err = %d\n", ret);
1608
1609     dst[0] = 0;
1610     ret = p_wcsncat_s(dst, 2, src, _TRUNCATE);
1611     ok(ret == STRUNCATE, "err = %d\n", ret);
1612     ok(dst[0] == 'a' && dst[1] == 0, "dst is %s\n", wine_dbgstr_w(dst));
1613
1614     memcpy(dst, abcW, sizeof(abcW));
1615     dst[3] = 'd';
1616     ret = p_wcsncat_s(dst, 4, src, 4);
1617     ok(ret == EINVAL, "err = %d\n", ret);
1618
1619     if (p_set_invalid_parameter_handler)
1620         ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler,
1621                 "Cannot reset invalid parameter handler\n");
1622 }
1623
1624 static void test__mbsnbcat_s(void)
1625 {
1626     unsigned char dest[16];
1627     const unsigned char first[] = "dinosaur";
1628     const unsigned char second[] = "duck";
1629     int ret;
1630
1631     if (!p_mbsnbcat_s)
1632     {
1633         win_skip("Skipping _mbsnbcat_s tests\n");
1634         return;
1635     }
1636
1637     /* Test invalid arguments. */
1638     ret = p_mbsnbcat_s(NULL, 0, NULL, 0);
1639     ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
1640
1641     errno = EBADF;
1642     ret = p_mbsnbcat_s(NULL, 10, NULL, 0);
1643     ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
1644     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1645
1646     errno = EBADF;
1647     ret = p_mbsnbcat_s(NULL, 0, NULL, 10);
1648     ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
1649     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1650
1651     memset(dest, 'X', sizeof(dest));
1652     errno = EBADF;
1653     ret = p_mbsnbcat_s(dest, 0, NULL, 0);
1654     ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
1655     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1656     ok(dest[0] == 'X', "Expected the output buffer to be untouched\n");
1657
1658     memset(dest, 'X', sizeof(dest));
1659     errno = EBADF;
1660     ret = p_mbsnbcat_s(dest, 0, second, 0);
1661     ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
1662     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1663     ok(dest[0] == 'X', "Expected the output buffer to be untouched\n");
1664
1665     memset(dest, 'X', sizeof(dest));
1666     errno = EBADF;
1667     ret = p_mbsnbcat_s(dest, sizeof(dest), NULL, 0);
1668     ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
1669     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1670     ok(dest[0] == '\0', "Expected the output buffer to be null terminated\n");
1671
1672     memset(dest, 'X', sizeof(dest));
1673     errno = EBADF;
1674     ret = p_mbsnbcat_s(dest, sizeof(dest), NULL, 10);
1675     ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
1676     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1677     ok(dest[0] == '\0', "Expected the output buffer to be null terminated\n");
1678
1679     memset(dest, 'X', sizeof(dest));
1680     dest[0] = '\0';
1681     ret = p_mbsnbcat_s(dest, sizeof(dest), second, sizeof(second));
1682     ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
1683     ok(!memcmp(dest, second, sizeof(second)),
1684        "Expected the output buffer string to be \"duck\"\n");
1685
1686     /* Test source truncation behavior. */
1687     memset(dest, 'X', sizeof(dest));
1688     memcpy(dest, first, sizeof(first));
1689     ret = p_mbsnbcat_s(dest, sizeof(dest), second, 0);
1690     ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
1691     ok(!memcmp(dest, first, sizeof(first)),
1692        "Expected the output buffer string to be \"dinosaur\"\n");
1693
1694     memset(dest, 'X', sizeof(dest));
1695     memcpy(dest, first, sizeof(first));
1696     ret = p_mbsnbcat_s(dest, sizeof(dest), second, sizeof(second));
1697     ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
1698     ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
1699        "Expected the output buffer string to be \"dinosaurduck\"\n");
1700
1701     memset(dest, 'X', sizeof(dest));
1702     memcpy(dest, first, sizeof(first));
1703     ret = p_mbsnbcat_s(dest, sizeof(dest), second, sizeof(second) + 1);
1704     ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
1705     ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
1706        "Expected the output buffer string to be \"dinosaurduck\"\n");
1707
1708     memset(dest, 'X', sizeof(dest));
1709     memcpy(dest, first, sizeof(first));
1710     ret = p_mbsnbcat_s(dest, sizeof(dest), second, sizeof(second) - 1);
1711     ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
1712     ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
1713        "Expected the output buffer string to be \"dinosaurduck\"\n");
1714
1715     memset(dest, 'X', sizeof(dest));
1716     memcpy(dest, first, sizeof(first));
1717     ret = p_mbsnbcat_s(dest, sizeof(dest), second, sizeof(second) - 2);
1718     ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
1719     ok(!memcmp(dest, "dinosaurduc", sizeof("dinosaurduc")),
1720        "Expected the output buffer string to be \"dinosaurduc\"\n");
1721
1722     /* Test destination truncation behavior. */
1723     memset(dest, 'X', sizeof(dest));
1724     memcpy(dest, first, sizeof(first));
1725     errno = EBADF;
1726     ret = p_mbsnbcat_s(dest, sizeof(first) - 1, second, sizeof(second));
1727     ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
1728     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1729     ok(!memcmp(dest, "\0inosaur", sizeof("\0inosaur") - 1),
1730        "Expected the output buffer string to be \"\\0inosaur\" without ending null terminator\n");
1731
1732     memset(dest, 'X', sizeof(dest));
1733     memcpy(dest, first, sizeof(first));
1734     errno = EBADF;
1735     ret = p_mbsnbcat_s(dest, sizeof(first), second, sizeof(second));
1736     ok(ret == ERANGE, "Expected _mbsnbcat_s to return ERANGE, got %d\n", ret);
1737     ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
1738     ok(!memcmp(dest, "\0inosaurd", sizeof("\0inosaurd") - 1),
1739        "Expected the output buffer string to be \"\\0inosaurd\" without ending null terminator\n");
1740
1741     memset(dest, 'X', sizeof(dest));
1742     memcpy(dest, first, sizeof(first));
1743     errno = EBADF;
1744     ret = p_mbsnbcat_s(dest, sizeof(first) + 1, second, sizeof(second));
1745     ok(ret == ERANGE, "Expected _mbsnbcat_s to return ERANGE, got %d\n", ret);
1746     ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
1747     ok(!memcmp(dest, "\0inosaurdu", sizeof("\0inosaurdu") - 1),
1748        "Expected the output buffer string to be \"\\0inosaurdu\" without ending null terminator\n");
1749 }
1750
1751 static void test__mbsupr_s(void)
1752 {
1753     errno_t ret;
1754     unsigned char buffer[20];
1755
1756     if (!p_mbsupr_s)
1757     {
1758         win_skip("Skipping _mbsupr_s tests\n");
1759         return;
1760     }
1761
1762     errno = EBADF;
1763     ret = p_mbsupr_s(NULL, 0);
1764     ok(ret == 0, "Expected _mbsupr_s to return 0, got %d\n", ret);
1765
1766     errno = EBADF;
1767     ret = p_mbsupr_s(NULL, sizeof(buffer));
1768     ok(ret == EINVAL, "Expected _mbsupr_s to return EINVAL, got %d\n", ret);
1769     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1770
1771     errno = EBADF;
1772     ret = p_mbsupr_s(buffer, 0);
1773     ok(ret == EINVAL, "Expected _mbsupr_s to return EINVAL, got %d\n", ret);
1774     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1775
1776     memcpy(buffer, "abcdefgh", sizeof("abcdefgh"));
1777     errno = EBADF;
1778     ret = p_mbsupr_s(buffer, sizeof("abcdefgh"));
1779     ok(ret == 0, "Expected _mbsupr_s to return 0, got %d\n", ret);
1780     ok(!memcmp(buffer, "ABCDEFGH", sizeof("ABCDEFGH")),
1781        "Expected the output buffer to be \"ABCDEFGH\", got \"%s\"\n",
1782        buffer);
1783
1784     memcpy(buffer, "abcdefgh", sizeof("abcdefgh"));
1785     errno = EBADF;
1786     ret = p_mbsupr_s(buffer, sizeof(buffer));
1787     ok(ret == 0, "Expected _mbsupr_s to return 0, got %d\n", ret);
1788     ok(!memcmp(buffer, "ABCDEFGH", sizeof("ABCDEFGH")),
1789        "Expected the output buffer to be \"ABCDEFGH\", got \"%s\"\n",
1790        buffer);
1791
1792     memcpy(buffer, "abcdefgh", sizeof("abcdefgh"));
1793     errno = EBADF;
1794     ret = p_mbsupr_s(buffer, 4);
1795     ok(ret == EINVAL, "Expected _mbsupr_s to return EINVAL, got %d\n", ret);
1796     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1797
1798     memcpy(buffer, "abcdefgh\0ijklmnop", sizeof("abcdefgh\0ijklmnop"));
1799     errno = EBADF;
1800     ret = p_mbsupr_s(buffer, sizeof(buffer));
1801     ok(ret == 0, "Expected _mbsupr_s to return 0, got %d\n", ret);
1802     ok(!memcmp(buffer, "ABCDEFGH\0ijklmnop", sizeof("ABCDEFGH\0ijklmnop")),
1803        "Expected the output buffer to be \"ABCDEFGH\\0ijklmnop\", got \"%s\"\n",
1804        buffer);
1805
1806 }
1807
1808 static void test__mbslwr_s(void)
1809 {
1810     errno_t ret;
1811     unsigned char buffer[20];
1812
1813     if (!p_mbslwr_s)
1814     {
1815         win_skip("Skipping _mbslwr_s tests\n");
1816         return;
1817     }
1818
1819     errno = EBADF;
1820     ret = p_mbslwr_s(NULL, 0);
1821     ok(ret == 0, "Expected _mbslwr_s to return 0, got %d\n", ret);
1822
1823     errno = EBADF;
1824     ret = p_mbslwr_s(NULL, sizeof(buffer));
1825     ok(ret == EINVAL, "Expected _mbslwr_s to return EINVAL, got %d\n", ret);
1826     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1827
1828     errno = EBADF;
1829     ret = p_mbslwr_s(buffer, 0);
1830     ok(ret == EINVAL, "Expected _mbslwr_s to return EINVAL, got %d\n", ret);
1831     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1832
1833     memcpy(buffer, "ABCDEFGH", sizeof("ABCDEFGH"));
1834     errno = EBADF;
1835     ret = p_mbslwr_s(buffer, sizeof("ABCDEFGH"));
1836     ok(ret == 0, "Expected _mbslwr_s to return 0, got %d\n", ret);
1837     ok(!memcmp(buffer, "abcdefgh", sizeof("abcdefgh")),
1838        "Expected the output buffer to be \"abcdefgh\", got \"%s\"\n",
1839        buffer);
1840
1841     memcpy(buffer, "ABCDEFGH", sizeof("ABCDEFGH"));
1842     errno = EBADF;
1843     ret = p_mbslwr_s(buffer, sizeof(buffer));
1844     ok(ret == 0, "Expected _mbslwr_s to return 0, got %d\n", ret);
1845     ok(!memcmp(buffer, "abcdefgh", sizeof("abcdefgh")),
1846        "Expected the output buffer to be \"abcdefgh\", got \"%s\"\n",
1847        buffer);
1848
1849     memcpy(buffer, "ABCDEFGH", sizeof("ABCDEFGH"));
1850     errno = EBADF;
1851     ret = p_mbslwr_s(buffer, 4);
1852     ok(ret == EINVAL, "Expected _mbslwr_s to return EINVAL, got %d\n", ret);
1853     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1854
1855     memcpy(buffer, "ABCDEFGH\0IJKLMNOP", sizeof("ABCDEFGH\0IJKLMNOP"));
1856     errno = EBADF;
1857     ret = p_mbslwr_s(buffer, sizeof(buffer));
1858     ok(ret == 0, "Expected _mbslwr_s to return 0, got %d\n", ret);
1859     ok(!memcmp(buffer, "abcdefgh\0IJKLMNOP", sizeof("abcdefgh\0IJKLMNOP")),
1860        "Expected the output buffer to be \"abcdefgh\\0IJKLMNOP\", got \"%s\"\n",
1861        buffer);
1862 }
1863
1864 static void test__ultoa_s(void)
1865 {
1866     errno_t ret;
1867     char buffer[33];
1868
1869     if (!p_ultoa_s)
1870     {
1871         win_skip("Skipping _ultoa_s tests\n");
1872         return;
1873     }
1874
1875     errno = EBADF;
1876     ret = p_ultoa_s(0, NULL, 0, 0);
1877     ok(ret == EINVAL, "Expected _ultoa_s to return EINVAL, got %d\n", ret);
1878     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1879
1880     memset(buffer, 'X', sizeof(buffer));
1881     errno = EBADF;
1882     ret = p_ultoa_s(0, buffer, 0, 0);
1883     ok(ret == EINVAL, "Expected _ultoa_s to return EINVAL, got %d\n", ret);
1884     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1885     ok(buffer[0] == 'X', "Expected the output buffer to be untouched\n");
1886
1887     memset(buffer, 'X', sizeof(buffer));
1888     errno = EBADF;
1889     ret = p_ultoa_s(0, buffer, sizeof(buffer), 0);
1890     ok(ret == EINVAL, "Expected _ultoa_s to return EINVAL, got %d\n", ret);
1891     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1892     ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
1893
1894     memset(buffer, 'X', sizeof(buffer));
1895     errno = EBADF;
1896     ret = p_ultoa_s(0, buffer, sizeof(buffer), 64);
1897     ok(ret == EINVAL, "Expected _ultoa_s to return EINVAL, got %d\n", ret);
1898     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1899     ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
1900
1901     memset(buffer, 'X', sizeof(buffer));
1902     errno = EBADF;
1903     ret = p_ultoa_s(12345678, buffer, 4, 10);
1904     ok(ret == ERANGE, "Expected _ultoa_s to return ERANGE, got %d\n", ret);
1905     ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
1906     ok(!memcmp(buffer, "\000765", 4),
1907        "Expected the output buffer to be null terminated with truncated output\n");
1908
1909     memset(buffer, 'X', sizeof(buffer));
1910     errno = EBADF;
1911     ret = p_ultoa_s(12345678, buffer, 8, 10);
1912     ok(ret == ERANGE, "Expected _ultoa_s to return ERANGE, got %d\n", ret);
1913     ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
1914     ok(!memcmp(buffer, "\0007654321", 8),
1915        "Expected the output buffer to be null terminated with truncated output\n");
1916
1917     ret = p_ultoa_s(12345678, buffer, 9, 10);
1918     ok(ret == 0, "Expected _ultoa_s to return 0, got %d\n", ret);
1919     ok(!strcmp(buffer, "12345678"),
1920        "Expected output buffer string to be \"12345678\", got \"%s\"\n",
1921        buffer);
1922
1923     ret = p_ultoa_s(43690, buffer, sizeof(buffer), 2);
1924     ok(ret == 0, "Expected _ultoa_s to return 0, got %d\n", ret);
1925     ok(!strcmp(buffer, "1010101010101010"),
1926        "Expected output buffer string to be \"1010101010101010\", got \"%s\"\n",
1927        buffer);
1928
1929     ret = p_ultoa_s(1092009, buffer, sizeof(buffer), 36);
1930     ok(ret == 0, "Expected _ultoa_s to return 0, got %d\n", ret);
1931     ok(!strcmp(buffer, "nell"),
1932        "Expected output buffer string to be \"nell\", got \"%s\"\n",
1933        buffer);
1934
1935     ret = p_ultoa_s(5704, buffer, sizeof(buffer), 18);
1936     ok(ret == 0, "Expected _ultoa_s to return 0, got %d\n", ret);
1937     ok(!strcmp(buffer, "hag"),
1938        "Expected output buffer string to be \"hag\", got \"%s\"\n",
1939        buffer);
1940 }
1941
1942 static void test_wctob(void)
1943 {
1944     int ret;
1945
1946     if(!p_wctob || !setlocale(LC_ALL, "chinese-traditional")) {
1947         win_skip("Skipping wctob tests\n");
1948         return;
1949     }
1950
1951     ret = p_wctob(0x8141);
1952     ok(ret == EOF, "ret = %x\n", ret);
1953
1954     ret = p_wctob(0x81);
1955     ok(ret == EOF, "ret = %x\n", ret);
1956
1957     ret = p_wctob(0xe0);
1958     ok(ret == 0x61, "ret = %x\n", ret);
1959
1960     _setmbcp(1250);
1961     ret = p_wctob(0x81);
1962     /* wctob should not be affected by _setmbcp */
1963     todo_wine ok(ret == EOF, "ret = %x\n", ret);
1964
1965     setlocale(LC_ALL, "C");
1966     ret = p_wctob(0x8141);
1967     ok(ret == EOF, "ret = %x\n", ret);
1968
1969     ret = p_wctob(0x81);
1970     ok(ret == (int)(char)0x81, "ret = %x\n", ret);
1971
1972     ret = p_wctob(0xe0);
1973     ok(ret == (int)(char)0xe0, "ret = %x\n", ret);
1974 }
1975
1976 static void test_tolower(void)
1977 {
1978     int ret;
1979
1980     ret = p_tolower(0x41);
1981     ok(ret == 0x61, "ret = %x\n", ret);
1982
1983     ret = p_tolower(0xF4);
1984     ok(ret == 0xF4, "ret = %x\n", ret);
1985
1986     ret = p_tolower((char)0xF4);
1987     ok(ret==0xF4/*Vista+*/ || ret==(char)0xF4, "ret = %x\n", ret);
1988
1989     /* is it using different locale (CP_ACP) for negative values?? */
1990     /* current implementation matches msvcr90 behaviour */
1991     ret = p_tolower((char)0xD0);
1992     todo_wine ok(ret==0xF0/*Vista+*/ || ret==(char)0xD0, "ret = %x\n", ret);
1993
1994     ret = p_tolower(0xD0);
1995     ok(ret == 0xD0, "ret = %x\n", ret);
1996
1997     if(!setlocale(LC_ALL, "us")) {
1998         win_skip("skipping tolower tests that depends on locale\n");
1999         return;
2000     }
2001
2002     ret = p_tolower((char)0xD0);
2003     ok(ret == 0xF0, "ret = %x\n", ret);
2004
2005     ret = p_tolower(0xD0);
2006     ok(ret == 0xF0, "ret = %x\n", ret);
2007
2008     setlocale(LC_ALL, "C");
2009 }
2010
2011 START_TEST(string)
2012 {
2013     char mem[100];
2014     static const char xilstring[]="c:/xilinx";
2015     int nLen;
2016
2017     hMsvcrt = GetModuleHandleA("msvcrt.dll");
2018     if (!hMsvcrt)
2019         hMsvcrt = GetModuleHandleA("msvcrtd.dll");
2020     ok(hMsvcrt != 0, "GetModuleHandleA failed\n");
2021     SET(pmemcpy,"memcpy");
2022     SET(pmemcmp,"memcmp");
2023     SET(p_mbctype,"_mbctype");
2024     SET(p__mb_cur_max,"__mb_cur_max");
2025     pstrcpy_s = (void *)GetProcAddress( hMsvcrt,"strcpy_s" );
2026     pstrcat_s = (void *)GetProcAddress( hMsvcrt,"strcat_s" );
2027     p_mbsnbcat_s = (void *)GetProcAddress( hMsvcrt,"_mbsnbcat_s" );
2028     p_mbsnbcpy_s = (void *)GetProcAddress( hMsvcrt,"_mbsnbcpy_s" );
2029     p_wcscpy_s = (void *)GetProcAddress( hMsvcrt,"wcscpy_s" );
2030     p_wcsncat_s = (void *)GetProcAddress( hMsvcrt,"wcsncat_s" );
2031     p_wcsupr_s = (void *)GetProcAddress( hMsvcrt,"_wcsupr_s" );
2032     p_strnlen = (void *)GetProcAddress( hMsvcrt,"strnlen" );
2033     p_strtoi64 = (void *)GetProcAddress(hMsvcrt, "_strtoi64");
2034     p_strtoui64 = (void *)GetProcAddress(hMsvcrt, "_strtoui64");
2035     pmbstowcs_s = (void *)GetProcAddress(hMsvcrt, "mbstowcs_s");
2036     pwcstombs_s = (void *)GetProcAddress(hMsvcrt, "wcstombs_s");
2037     pwcsrtombs = (void *)GetProcAddress(hMsvcrt, "wcsrtombs");
2038     p_gcvt_s = (void *)GetProcAddress(hMsvcrt, "_gcvt_s");
2039     p_itoa_s = (void *)GetProcAddress(hMsvcrt, "_itoa_s");
2040     p_strlwr_s = (void *)GetProcAddress(hMsvcrt, "_strlwr_s");
2041     p_ultoa_s = (void *)GetProcAddress(hMsvcrt, "_ultoa_s");
2042     p_set_invalid_parameter_handler = (void *) GetProcAddress(hMsvcrt, "_set_invalid_parameter_handler");
2043     p_wcslwr_s = (void*)GetProcAddress(hMsvcrt, "_wcslwr_s");
2044     p_mbsupr_s = (void*)GetProcAddress(hMsvcrt, "_mbsupr_s");
2045     p_mbslwr_s = (void*)GetProcAddress(hMsvcrt, "_mbslwr_s");
2046     p_wctob = (void*)GetProcAddress(hMsvcrt, "wctob");
2047     p_tolower = (void*)GetProcAddress(hMsvcrt, "tolower");
2048
2049     /* MSVCRT memcpy behaves like memmove for overlapping moves,
2050        MFC42 CString::Insert seems to rely on that behaviour */
2051     strcpy(mem,xilstring);
2052     nLen=strlen(xilstring);
2053     pmemcpy(mem+5, mem,nLen+1);
2054     ok(pmemcmp(mem+5,xilstring, nLen) == 0,
2055        "Got result %s\n",mem+5);
2056
2057     /* Test _swab function */
2058     test_swab();
2059
2060     /* Test ismbblead*/
2061     test_mbcp();
2062    /* test _mbsspn */
2063     test_mbsspn();
2064     test_mbsspnp();
2065    /* test _strdup */
2066     test_strdup();
2067     test_strcpy_s();
2068     test_strcat_s();
2069     test__mbsnbcpy_s();
2070     test_mbcjisjms();
2071     test_mbctombb();
2072     test_ismbclegal();
2073     test_strtok();
2074     test_wcscpy_s();
2075     test__wcsupr_s();
2076     test_strtol();
2077     test_strnlen();
2078     test__strtoi64();
2079     test__strtod();
2080     test_mbstowcs();
2081     test_gcvt();
2082     test__itoa_s();
2083     test__strlwr_s();
2084     test_wcsncat_s();
2085     test__mbsnbcat_s();
2086     test__ultoa_s();
2087     test__wcslwr_s();
2088     test__mbsupr_s();
2089     test__mbslwr_s();
2090     test_wctob();
2091     test_tolower();
2092 }