ReactOS  0.4.12-dev-432-g3463b2d
string.c
Go to the documentation of this file.
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_tolower)(int);
92 static size_t (__cdecl *p_mbrlen)(const char*, size_t, mbstate_t*);
93 static size_t (__cdecl *p_mbrtowc)(wchar_t*, const char*, size_t, mbstate_t*);
94 static int (__cdecl *p__atodbl_l)(_CRT_DOUBLE*,char*,_locale_t);
95 static double (__cdecl *p__atof_l)(const char*,_locale_t);
96 static double (__cdecl *p__strtod_l)(const char *,char**,_locale_t);
97 static int (__cdecl *p__strnset_s)(char*,size_t,int,size_t);
98 static int (__cdecl *p__wcsset_s)(wchar_t*,size_t,wchar_t);
99 static size_t (__cdecl *p__mbsnlen)(const unsigned char*, size_t);
100 static int (__cdecl *p__mbccpy_s)(unsigned char*, size_t, int*, const unsigned char*);
101 static int (__cdecl *p__memicmp)(const char*, const char*, size_t);
102 static int (__cdecl *p__memicmp_l)(const char*, const char*, size_t, _locale_t);
103 
104 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y)
105 #define SET(x,y) SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y)
106 
108 
109 static void test_swab( void ) {
110  char original[] = "BADCFEHGJILKNMPORQTSVUXWZY@#";
111  char expected1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ@#";
112  char expected2[] = "ABCDEFGHIJKLMNOPQRSTUVWX$";
113  char expected3[] = "$";
114 
115  char from[30];
116  char to[30];
117 
118  int testsize;
119 
120  /* Test 1 - normal even case */
121  memset(to,'$', sizeof(to));
122  memset(from,'@', sizeof(from));
123  testsize = 26;
124  memcpy(from, original, testsize);
125  _swab( from, to, testsize );
126  ok(memcmp(to,expected1,testsize) == 0, "Testing even size %d returned '%*.*s'\n", testsize, testsize, testsize, to);
127 
128  /* Test 2 - uneven case */
129  memset(to,'$', sizeof(to));
130  memset(from,'@', sizeof(from));
131  testsize = 25;
132  memcpy(from, original, testsize);
133  _swab( from, to, testsize );
134  ok(memcmp(to,expected2,testsize) == 0, "Testing odd size %d returned '%*.*s'\n", testsize, testsize, testsize, to);
135 
136  /* Test 3 - from = to */
137  memset(to,'$', sizeof(to));
138  memset(from,'@', sizeof(from));
139  testsize = 26;
140  memcpy(to, original, testsize);
141  _swab( to, to, testsize );
142  ok(memcmp(to,expected1,testsize) == 0, "Testing overlapped size %d returned '%*.*s'\n", testsize, testsize, testsize, to);
143 
144  /* Test 4 - 1 bytes */
145  memset(to,'$', sizeof(to));
146  memset(from,'@', sizeof(from));
147  testsize = 1;
148  memcpy(from, original, testsize);
149  _swab( from, to, testsize );
150  ok(memcmp(to,expected3,testsize) == 0, "Testing small size %d returned '%*.*s'\n", testsize, testsize, testsize, to);
151 }
152 
153 #if 0 /* use this to generate more tests */
154 
155 static void test_codepage(int cp)
156 {
157  int i;
158  int prev;
159  int count = 1;
160 
161  ok(_setmbcp(cp) == 0, "Couldn't set mbcp\n");
162 
163  prev = p_mbctype[0];
164  printf("static int result_cp_%d_mbctype[] = { ", cp);
165  for (i = 1; i < 257; i++)
166  {
167  if (p_mbctype[i] != prev)
168  {
169  printf("0x%x,%d, ", prev, count);
170  prev = p_mbctype[i];
171  count = 1;
172  }
173  else
174  count++;
175  }
176  printf("0x%x,%d };\n", prev, count);
177 }
178 
179 #else
180 
181 /* RLE-encoded mbctype tables for given codepages */
182 static int result_cp_932_mbctype[] = { 0x0,65, 0x8,1, 0x18,26, 0x8,6, 0x28,26, 0x8,4,
183  0x0,1, 0x8,1, 0xc,31, 0x8,1, 0xa,5, 0x9,58, 0xc,29, 0,3 };
184 static int result_cp_936_mbctype[] = { 0x0,65, 0x8,1, 0x18,26, 0x8,6, 0x28,26, 0x8,6,
185  0xc,126, 0,1 };
186 static int result_cp_949_mbctype[] = { 0x0,66, 0x18,26, 0x8,6, 0x28,26, 0x8,6, 0xc,126,
187  0,1 };
188 static int result_cp_950_mbctype[] = { 0x0,65, 0x8,1, 0x18,26, 0x8,6, 0x28,26, 0x8,4,
189  0x0,2, 0x4,32, 0xc,94, 0,1 };
190 
191 static void test_cp_table(int cp, int *result)
192 {
193  int i;
194  int count = 0;
195  int curr = 0;
196  _setmbcp(cp);
197  for (i = 0; i < 256; i++)
198  {
199  if (count == 0)
200  {
201  curr = result[0];
202  count = result[1];
203  result += 2;
204  }
205  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);
206  count--;
207  }
208 }
209 
210 #define test_codepage(num) test_cp_table(num, result_cp_##num##_mbctype);
211 
212 #endif
213 
214 static void test_mbcp(void)
215 {
216  int mb_orig_max = *p__mb_cur_max;
217  int curr_mbcp = _getmbcp();
218  unsigned char *mbstring = (unsigned char *)"\xb0\xb1\xb2 \xb3\xb4 \xb5"; /* incorrect string */
219  unsigned char *mbstring2 = (unsigned char *)"\xb0\xb1\xb2\xb3Q\xb4\xb5"; /* correct string */
220  unsigned char *mbsonlylead = (unsigned char *)"\xb0\0\xb1\xb2 \xb3";
221  unsigned char buf[16];
222  int step;
223  CPINFO cp_info;
224 
225  /* _mbtype tests */
226 
227  /* An SBCS codepage test. The ctype of characters on e.g. CP1252 or CP1250 differs slightly
228  * between versions of Windows. Also Windows 9x seems to ignore the codepage and always uses
229  * CP1252 (or the ACP?) so we test only a few ASCII characters */
230  _setmbcp(1252);
231  expect_eq(p_mbctype[10], 0, char, "%x");
232  expect_eq(p_mbctype[50], 0, char, "%x");
233  expect_eq(p_mbctype[66], _SBUP, char, "%x");
234  expect_eq(p_mbctype[100], _SBLOW, char, "%x");
235  expect_eq(p_mbctype[128], 0, char, "%x");
236  _setmbcp(1250);
237  expect_eq(p_mbctype[10], 0, char, "%x");
238  expect_eq(p_mbctype[50], 0, char, "%x");
239  expect_eq(p_mbctype[66], _SBUP, char, "%x");
240  expect_eq(p_mbctype[100], _SBLOW, char, "%x");
241  expect_eq(p_mbctype[128], 0, char, "%x");
242 
243  /* double byte code pages */
244  test_codepage(932);
245  test_codepage(936);
246  test_codepage(949);
247  test_codepage(950);
248 
249  _setmbcp(936);
250  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);
251  ok(_ismbblead('\354'), "\354 should be a lead byte\n");
252  ok(_ismbblead(' ') == FALSE, "' ' should not be a lead byte\n");
253  ok(_ismbblead(0x1234b0), "0x1234b0 should not be a lead byte\n");
254  ok(_ismbblead(0x123420) == FALSE, "0x123420 should not be a lead byte\n");
255  ok(_ismbbtrail('\xb0'), "\xa0 should be a trail byte\n");
256  ok(_ismbbtrail(' ') == FALSE, "' ' should not be a trail byte\n");
257 
258  /* _ismbslead */
259  expect_eq(_ismbslead(mbstring, &mbstring[0]), -1, int, "%d");
260  expect_eq(_ismbslead(mbstring, &mbstring[1]), FALSE, int, "%d");
261  expect_eq(_ismbslead(mbstring, &mbstring[2]), -1, int, "%d");
262  expect_eq(_ismbslead(mbstring, &mbstring[3]), FALSE, int, "%d");
263  expect_eq(_ismbslead(mbstring, &mbstring[4]), -1, int, "%d");
264  expect_eq(_ismbslead(mbstring, &mbstring[5]), FALSE, int, "%d");
265  expect_eq(_ismbslead(mbstring, &mbstring[6]), FALSE, int, "%d");
266  expect_eq(_ismbslead(mbstring, &mbstring[7]), -1, int, "%d");
267  expect_eq(_ismbslead(mbstring, &mbstring[8]), FALSE, int, "%d");
268 
269  expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[0]), -1, int, "%d");
270  expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[1]), FALSE, int, "%d");
271  expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[2]), FALSE, int, "%d");
272  expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[5]), FALSE, int, "%d");
273 
274  /* _ismbstrail */
275  expect_eq(_ismbstrail(mbstring, &mbstring[0]), FALSE, int, "%d");
276  expect_eq(_ismbstrail(mbstring, &mbstring[1]), -1, int, "%d");
277  expect_eq(_ismbstrail(mbstring, &mbstring[2]), FALSE, int, "%d");
278  expect_eq(_ismbstrail(mbstring, &mbstring[3]), -1, int, "%d");
279  expect_eq(_ismbstrail(mbstring, &mbstring[4]), FALSE, int, "%d");
280  expect_eq(_ismbstrail(mbstring, &mbstring[5]), -1, int, "%d");
281  expect_eq(_ismbstrail(mbstring, &mbstring[6]), FALSE, int, "%d");
282  expect_eq(_ismbstrail(mbstring, &mbstring[7]), FALSE, int, "%d");
283  expect_eq(_ismbstrail(mbstring, &mbstring[8]), -1, int, "%d");
284 
285  expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[0]), FALSE, int, "%d");
286  expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[1]), -1, int, "%d");
287  expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[2]), FALSE, int, "%d");
288  expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[3]), FALSE, int, "%d");
289  expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[4]), FALSE, int, "%d");
290  expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[5]), FALSE, int, "%d");
291 
292  /* _mbsbtype */
293  expect_eq(_mbsbtype(mbstring, 0), _MBC_LEAD, int, "%d");
294  expect_eq(_mbsbtype(mbstring, 1), _MBC_TRAIL, int, "%d");
295  expect_eq(_mbsbtype(mbstring, 2), _MBC_LEAD, int, "%d");
296  expect_eq(_mbsbtype(mbstring, 3), _MBC_ILLEGAL, int, "%d");
297  expect_eq(_mbsbtype(mbstring, 4), _MBC_LEAD, int, "%d");
298  expect_eq(_mbsbtype(mbstring, 5), _MBC_TRAIL, int, "%d");
299  expect_eq(_mbsbtype(mbstring, 6), _MBC_SINGLE, int, "%d");
300  expect_eq(_mbsbtype(mbstring, 7), _MBC_LEAD, int, "%d");
301  expect_eq(_mbsbtype(mbstring, 8), _MBC_ILLEGAL, int, "%d");
302 
303  expect_eq(_mbsbtype(mbsonlylead, 0), _MBC_LEAD, int, "%d");
304  expect_eq(_mbsbtype(mbsonlylead, 1), _MBC_ILLEGAL, int, "%d");
305  expect_eq(_mbsbtype(mbsonlylead, 2), _MBC_ILLEGAL, int, "%d");
306  expect_eq(_mbsbtype(mbsonlylead, 3), _MBC_ILLEGAL, int, "%d");
307  expect_eq(_mbsbtype(mbsonlylead, 4), _MBC_ILLEGAL, int, "%d");
308  expect_eq(_mbsbtype(mbsonlylead, 5), _MBC_ILLEGAL, int, "%d");
309 
310  /* _mbsnextc */
311  expect_eq(_mbsnextc(mbstring), 0xb0b1, int, "%x");
312  expect_eq(_mbsnextc(&mbstring[2]), 0xb220, int, "%x"); /* lead + invalid tail */
313  expect_eq(_mbsnextc(&mbstring[3]), 0x20, int, "%x"); /* single char */
314 
315  /* _mbclen/_mbslen */
316  expect_eq(_mbclen(mbstring), 2, int, "%d");
317  expect_eq(_mbclen(&mbstring[2]), 2, int, "%d");
318  expect_eq(_mbclen(&mbstring[3]), 1, int, "%d");
319  expect_eq(_mbslen(mbstring2), 4, int, "%d");
320  expect_eq(_mbslen(mbsonlylead), 0, int, "%d"); /* lead + NUL not counted as character */
321  expect_eq(_mbslen(mbstring), 4, int, "%d"); /* lead + invalid trail counted */
322 
323  if(!p__mbsnlen) {
324  win_skip("_mbsnlen tests\n");
325  }else {
326  expect_eq(p__mbsnlen(mbstring, 8), 8, int, "%d");
327  expect_eq(p__mbsnlen(mbstring, 9), 4, int, "%d");
328  expect_eq(p__mbsnlen(mbstring, 10), 4, int, "%d");
329  expect_eq(p__mbsnlen(mbsonlylead, 0), 0, int, "%d");
330  expect_eq(p__mbsnlen(mbsonlylead, 1), 1, int, "%d");
331  expect_eq(p__mbsnlen(mbsonlylead, 2), 0, int, "%d");
332  expect_eq(p__mbsnlen(mbstring2, 7), 7, int, "%d");
333  expect_eq(p__mbsnlen(mbstring2, 8), 4, int, "%d");
334  expect_eq(p__mbsnlen(mbstring2, 9), 4, int, "%d");
335  }
336 
337  /* mbrlen */
338  if(!setlocale(LC_ALL, ".936") || !p_mbrlen) {
339  win_skip("mbrlen tests\n");
340  }else {
341  mbstate_t state = 0;
342  expect_eq(p_mbrlen((const char*)mbstring, 2, NULL), 2, int, "%d");
343  expect_eq(p_mbrlen((const char*)&mbstring[2], 2, NULL), 2, int, "%d");
344  expect_eq(p_mbrlen((const char*)&mbstring[3], 2, NULL), 1, int, "%d");
345  expect_eq(p_mbrlen((const char*)mbstring, 1, NULL), -2, int, "%d");
346  expect_eq(p_mbrlen((const char*)mbstring, 1, &state), -2, int, "%d");
347  ok(state == mbstring[0], "incorrect state value (%x)\n", state);
348  expect_eq(p_mbrlen((const char*)&mbstring[1], 1, &state), 2, int, "%d");
349  }
350 
351  /* mbrtowc */
352  if(!setlocale(LC_ALL, ".936") || !p_mbrtowc) {
353  win_skip("mbrtowc tests\n");
354  }else {
355  mbstate_t state = 0;
356  wchar_t dst;
357  expect_eq(p_mbrtowc(&dst, (const char*)mbstring, 2, NULL), 2, int, "%d");
358  ok(dst == 0x6c28, "dst = %x, expected 0x6c28\n", dst);
359  expect_eq(p_mbrtowc(&dst, (const char*)mbstring+2, 2, NULL), 2, int, "%d");
360  ok(dst == 0x3f, "dst = %x, expected 0x3f\n", dst);
361  expect_eq(p_mbrtowc(&dst, (const char*)mbstring+3, 2, NULL), 1, int, "%d");
362  ok(dst == 0x20, "dst = %x, expected 0x20\n", dst);
363  expect_eq(p_mbrtowc(&dst, (const char*)mbstring, 1, NULL), -2, int, "%d");
364  ok(dst == 0, "dst = %x, expected 0\n", dst);
365  expect_eq(p_mbrtowc(&dst, (const char*)mbstring, 1, &state), -2, int, "%d");
366  ok(dst == 0, "dst = %x, expected 0\n", dst);
367  ok(state == mbstring[0], "incorrect state value (%x)\n", state);
368  expect_eq(p_mbrtowc(&dst, (const char*)mbstring+1, 1, &state), 2, int, "%d");
369  ok(dst == 0x6c28, "dst = %x, expected 0x6c28\n", dst);
370  ok(state == 0, "incorrect state value (%x)\n", state);
371  }
372  setlocale(LC_ALL, "C");
373 
374  /* _mbccpy/_mbsncpy */
375  memset(buf, 0xff, sizeof(buf));
376  _mbccpy(buf, mbstring);
377  expect_bin(buf, "\xb0\xb1\xff", 3);
378 
379  if(!p__mbccpy_s) {
380  win_skip("_mbccpy_s tests\n");
381  }else {
382  int err, copied;
383 
384  memset(buf, 0xff, sizeof(buf));
385  copied = -1;
386  err = p__mbccpy_s(buf, 0, &copied, mbstring);
387  ok(err == EINVAL, "_mbccpy_s returned %d\n", err);
388  ok(!copied, "copied = %d\n", copied);
389  ok(buf[0] == 0xff, "buf[0] = %x\n", buf[0]);
390 
391  memset(buf, 0xff, sizeof(buf));
392  copied = -1;
393  err = p__mbccpy_s(buf, 1, &copied, mbstring);
394  ok(err == ERANGE, "_mbccpy_s returned %d\n", err);
395  ok(!copied, "copied = %d\n", copied);
396  ok(!buf[0], "buf[0] = %x\n", buf[0]);
397 
398  memset(buf, 0xff, sizeof(buf));
399  copied = -1;
400  err = p__mbccpy_s(buf, 2, &copied, mbstring);
401  ok(!err, "_mbccpy_s returned %d\n", err);
402  ok(copied == 2, "copied = %d\n", copied);
403  expect_bin(buf, "\xb0\xb1\xff", 3);
404 
405  memset(buf, 0xff, sizeof(buf));
406  copied = -1;
407  err = p__mbccpy_s(buf, 2, &copied, (unsigned char *)"\xb0");
408  ok(err == EILSEQ, "_mbccpy_s returned %d\n", err);
409  ok(copied == 1, "copied = %d\n", copied);
410  expect_bin(buf, "\x00\xff", 2);
411  }
412 
413  memset(buf, 0xff, sizeof(buf));
414  _mbsncpy(buf, mbstring, 1);
415  expect_bin(buf, "\xb0\xb1\xff", 3);
416  memset(buf, 0xff, sizeof(buf));
417  _mbsncpy(buf, mbstring, 2);
418  expect_bin(buf, "\xb0\xb1\xb2 \xff", 5);
419  memset(buf, 0xff, sizeof(buf));
420  _mbsncpy(buf, mbstring, 3);
421  expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4\xff", 7);
422  memset(buf, 0xff, sizeof(buf));
423  _mbsncpy(buf, mbstring, 4);
424  expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4 \xff", 8);
425  memset(buf, 0xff, sizeof(buf));
426  _mbsncpy(buf, mbstring, 5);
427  expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4 \0\0\xff", 10);
428  memset(buf, 0xff, sizeof(buf));
429  _mbsncpy(buf, mbsonlylead, 6);
430  expect_bin(buf, "\0\0\0\0\0\0\0\xff", 8);
431 
432  memset(buf, 0xff, sizeof(buf));
433  _mbsnbcpy(buf, mbstring2, 2);
434  expect_bin(buf, "\xb0\xb1\xff", 3);
435  _mbsnbcpy(buf, mbstring2, 3);
436  expect_bin(buf, "\xb0\xb1\0\xff", 4);
437  _mbsnbcpy(buf, mbstring2, 4);
438  expect_bin(buf, "\xb0\xb1\xb2\xb3\xff", 5);
439  memset(buf, 0xff, sizeof(buf));
440  _mbsnbcpy(buf, mbsonlylead, 5);
441  expect_bin(buf, "\0\0\0\0\0\xff", 6);
442 
443  /* _mbsinc/mbsdec */
444  step = _mbsinc(mbstring) - mbstring;
445  ok(step == 2, "_mbsinc adds %d (exp. 2)\n", step);
446  step = _mbsinc(&mbstring[2]) - &mbstring[2]; /* lead + invalid tail */
447  ok(step == 2, "_mbsinc adds %d (exp. 2)\n", step);
448 
449  step = _mbsninc(mbsonlylead, 1) - mbsonlylead;
450  ok(step == 0, "_mbsninc adds %d (exp. 0)\n", step);
451  step = _mbsninc(mbsonlylead, 2) - mbsonlylead; /* lead + NUL byte + lead + char */
452  ok(step == 0, "_mbsninc adds %d (exp. 0)\n", step);
453  step = _mbsninc(mbstring2, 0) - mbstring2;
454  ok(step == 0, "_mbsninc adds %d (exp. 2)\n", step);
455  step = _mbsninc(mbstring2, 1) - mbstring2;
456  ok(step == 2, "_mbsninc adds %d (exp. 2)\n", step);
457  step = _mbsninc(mbstring2, 2) - mbstring2;
458  ok(step == 4, "_mbsninc adds %d (exp. 4)\n", step);
459  step = _mbsninc(mbstring2, 3) - mbstring2;
460  ok(step == 5, "_mbsninc adds %d (exp. 5)\n", step);
461  step = _mbsninc(mbstring2, 4) - mbstring2;
462  ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step);
463  step = _mbsninc(mbstring2, 5) - mbstring2;
464  ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step);
465  step = _mbsninc(mbstring2, 17) - mbstring2;
466  ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step);
467 
468  /* functions that depend on locale codepage, not mbcp.
469  * we hope the current locale to be SBCS because setlocale(LC_ALL, ".1252") seems not to work yet
470  * (as of Wine 0.9.43)
471  */
472  GetCPInfo(GetACP(), &cp_info);
473  if (cp_info.MaxCharSize == 1)
474  {
475  expect_eq(mblen((char *)mbstring, 3), 1, int, "%x");
476  expect_eq(_mbstrlen((char *)mbstring2), 7, int, "%d");
477  }
478  else
479  skip("Current locale has double-byte charset - could lead to false positives\n");
480 
481  _setmbcp(1361);
482  expect_eq(_ismbblead(0x80), 0, int, "%d");
483  todo_wine {
484  expect_eq(_ismbblead(0x81), 1, int, "%d");
485  expect_eq(_ismbblead(0x83), 1, int, "%d");
486  }
487  expect_eq(_ismbblead(0x84), 1, int, "%d");
488  expect_eq(_ismbblead(0xd3), 1, int, "%d");
489  expect_eq(_ismbblead(0xd7), 0, int, "%d");
490  expect_eq(_ismbblead(0xd8), 1, int, "%d");
491  expect_eq(_ismbblead(0xd9), 1, int, "%d");
492 
493  expect_eq(_ismbbtrail(0x30), 0, int, "%d");
494  expect_eq(_ismbbtrail(0x31), 1, int, "%d");
495  expect_eq(_ismbbtrail(0x7e), 1, int, "%d");
496  expect_eq(_ismbbtrail(0x7f), 0, int, "%d");
497  expect_eq(_ismbbtrail(0x80), 0, int, "%d");
498  expect_eq(_ismbbtrail(0x81), 1, int, "%d");
499  expect_eq(_ismbbtrail(0xfe), 1, int, "%d");
500  expect_eq(_ismbbtrail(0xff), 0, int, "%d");
501 
502  _setmbcp(curr_mbcp);
503 }
504 
505 static void test_mbsspn( void)
506 {
507  unsigned char str1[]="cabernet";
508  unsigned char str2[]="shiraz";
509  unsigned char set[]="abc";
510  unsigned char empty[]="";
511  int ret;
512  ret=_mbsspn( str1, set);
513  ok( ret==3, "_mbsspn returns %d should be 3\n", ret);
514  ret=_mbsspn( str2, set);
515  ok( ret==0, "_mbsspn returns %d should be 0\n", ret);
516  ret=_mbsspn( str1, empty);
517  ok( ret==0, "_mbsspn returns %d should be 0\n", ret);
518 }
519 
520 static void test_mbsspnp( void)
521 {
522  unsigned char str1[]="cabernet";
523  unsigned char str2[]="shiraz";
524  unsigned char set[]="abc";
525  unsigned char empty[]="";
526  unsigned char full[]="abcenrt";
527  unsigned char* ret;
528  ret=_mbsspnp( str1, set);
529  ok( ret[0]=='e', "_mbsspnp returns %c should be e\n", ret[0]);
530  ret=_mbsspnp( str2, set);
531  ok( ret[0]=='s', "_mbsspnp returns %c should be s\n", ret[0]);
532  ret=_mbsspnp( str1, empty);
533  ok( ret[0]=='c', "_mbsspnp returns %c should be c\n", ret[0]);
534  ret=_mbsspnp( str1, full);
535  ok( ret==NULL, "_mbsspnp returns %p should be NULL\n", ret);
536 }
537 
538 static void test_strdup(void)
539 {
540  char *str;
541  str = _strdup( 0 );
542  ok( str == 0, "strdup returns %s should be 0\n", str);
543  free( str );
544 }
545 
546 static void test_strcpy_s(void)
547 {
548  char dest[8];
549  const char small[] = "small";
550  const char big[] = "atoolongstringforthislittledestination";
551  int ret;
552 
553  if(!pstrcpy_s)
554  {
555  win_skip("strcpy_s not found\n");
556  return;
557  }
558 
559  memset(dest, 'X', sizeof(dest));
560  ret = pstrcpy_s(dest, sizeof(dest), small);
561  ok(ret == 0, "Copying a string into a big enough destination returned %d, expected 0\n", ret);
562  ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == 'l' &&
563  dest[4] == 'l' && dest[5] == '\0'&& dest[6] == 'X' && dest[7] == 'X',
564  "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
565  dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
566 
567  memset(dest, 'X', sizeof(dest));
568  ret = pstrcpy_s(dest, 0, big);
569  ok(ret == EINVAL, "Copying into a destination of size 0 returned %d, expected EINVAL\n", ret);
570  ok(dest[0] == 'X' && dest[1] == 'X' && dest[2] == 'X' && dest[3] == 'X' &&
571  dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
572  "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
573  dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
574  ret = pstrcpy_s(dest, 0, NULL);
575  ok(ret == EINVAL, "Copying into a destination of size 0 returned %d, expected EINVAL\n", ret);
576  ok(dest[0] == 'X' && dest[1] == 'X' && dest[2] == 'X' && dest[3] == 'X' &&
577  dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
578  "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
579  dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
580 
581  memset(dest, 'X', sizeof(dest));
582  ret = pstrcpy_s(dest, sizeof(dest), big);
583  ok(ret == ERANGE, "Copying a big string in a small location returned %d, expected ERANGE\n", ret);
584  ok(dest[0] == '\0'&& dest[1] == 't' && dest[2] == 'o' && dest[3] == 'o' &&
585  dest[4] == 'l' && dest[5] == 'o' && dest[6] == 'n' && dest[7] == 'g',
586  "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
587  dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
588 
589  memset(dest, 'X', sizeof(dest));
590  ret = pstrcpy_s(dest, sizeof(dest), NULL);
591  ok(ret == EINVAL, "Copying from a NULL source string returned %d, expected EINVAL\n", ret);
592  ok(dest[0] == '\0'&& dest[1] == 'X' && dest[2] == 'X' && dest[3] == 'X' &&
593  dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
594  "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
595  dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
596 
597  ret = pstrcpy_s(NULL, sizeof(dest), small);
598  ok(ret == EINVAL, "Copying a big string a NULL dest returned %d, expected EINVAL\n", ret);
599 
600  /* strcpy overlapping buffers test */
601  memset(dest, 'X', sizeof(dest));
602  memcpy(dest+1, small, sizeof(small));
603  p_strcpy(dest, dest+1);
604  ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == 'l' &&
605  dest[4] == 'l' && dest[5] == '\0' && dest[6] == '\0' && dest[7] == 'X',
606  "Unexpected return data from strcpy: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
607  dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
608 }
609 
610 #define NUMELMS(array) (sizeof(array)/sizeof((array)[0]))
611 
612 #define okchars(dst, b0, b1, b2, b3, b4, b5, b6, b7) \
613  ok(dst[0] == b0 && dst[1] == b1 && dst[2] == b2 && dst[3] == b3 && \
614  dst[4] == b4 && dst[5] == b5 && dst[6] == b6 && dst[7] == b7, \
615  "Bad result: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",\
616  dst[0], dst[1], dst[2], dst[3], dst[4], dst[5], dst[6], dst[7])
617 
618 static void test_memcpy_s(void)
619 {
620  static char dest[8];
621  static const char tiny[] = {'T',0,'I','N','Y',0};
622  static const char big[] = {'a','t','o','o','l','o','n','g','s','t','r','i','n','g',0};
623  int ret;
624  if (!p_memcpy_s) {
625  win_skip("memcpy_s not found\n");
626  return;
627  }
628 
629  /* Normal */
630  memset(dest, 'X', sizeof(dest));
631  ret = p_memcpy_s(dest, NUMELMS(dest), tiny, NUMELMS(tiny));
632  ok(ret == 0, "Copying a buffer into a big enough destination returned %d, expected 0\n", ret);
633  okchars(dest, tiny[0], tiny[1], tiny[2], tiny[3], tiny[4], tiny[5], 'X', 'X');
634 
635  /* Vary source size */
636  errno = 0xdeadbeef;
637  memset(dest, 'X', sizeof(dest));
638  ret = p_memcpy_s(dest, NUMELMS(dest), big, NUMELMS(big));
639  ok(ret == ERANGE, "Copying a big buffer to a small destination returned %d, expected ERANGE\n", ret);
640  ok(errno == ERANGE, "errno is %d, expected ERANGE\n", errno);
641  okchars(dest, 0, 0, 0, 0, 0, 0, 0, 0);
642 
643  /* Replace source with NULL */
644  errno = 0xdeadbeef;
645  memset(dest, 'X', sizeof(dest));
646  ret = p_memcpy_s(dest, NUMELMS(dest), NULL, NUMELMS(tiny));
647  ok(ret == EINVAL, "Copying a NULL source buffer returned %d, expected EINVAL\n", ret);
648  ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
649  okchars(dest, 0, 0, 0, 0, 0, 0, 0, 0);
650 
651  /* Vary dest size */
652  errno = 0xdeadbeef;
653  memset(dest, 'X', sizeof(dest));
654  ret = p_memcpy_s(dest, 0, tiny, NUMELMS(tiny));
655  ok(ret == ERANGE, "Copying into a destination of size 0 returned %d, expected ERANGE\n", ret);
656  ok(errno == ERANGE, "errno is %d, expected ERANGE\n", errno);
657  okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
658 
659  /* Replace dest with NULL */
660  errno = 0xdeadbeef;
661  ret = p_memcpy_s(NULL, NUMELMS(dest), tiny, NUMELMS(tiny));
662  ok(ret == EINVAL, "Copying a tiny buffer to a big NULL destination returned %d, expected EINVAL\n", ret);
663  ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
664 
665  /* Combinations */
666  errno = 0xdeadbeef;
667  memset(dest, 'X', sizeof(dest));
668  ret = p_memcpy_s(dest, 0, NULL, NUMELMS(tiny));
669  ok(ret == EINVAL, "Copying a NULL buffer into a destination of size 0 returned %d, expected EINVAL\n", ret);
670  ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
671  okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
672 }
673 
674 static void test_memmove_s(void)
675 {
676  static char dest[8];
677  static const char tiny[] = {'T',0,'I','N','Y',0};
678  static const char big[] = {'a','t','o','o','l','o','n','g','s','t','r','i','n','g',0};
679  int ret;
680  if (!p_memmove_s) {
681  win_skip("memmove_s not found\n");
682  return;
683  }
684 
685  /* Normal */
686  memset(dest, 'X', sizeof(dest));
687  ret = p_memmove_s(dest, NUMELMS(dest), tiny, NUMELMS(tiny));
688  ok(ret == 0, "Moving a buffer into a big enough destination returned %d, expected 0\n", ret);
689  okchars(dest, tiny[0], tiny[1], tiny[2], tiny[3], tiny[4], tiny[5], 'X', 'X');
690 
691  /* Overlapping */
692  memcpy(dest, big, sizeof(dest));
693  ret = p_memmove_s(dest+1, NUMELMS(dest)-1, dest, NUMELMS(dest)-1);
694  ok(ret == 0, "Moving a buffer up one char returned %d, expected 0\n", ret);
695  okchars(dest, big[0], big[0], big[1], big[2], big[3], big[4], big[5], big[6]);
696 
697  /* Vary source size */
698  errno = 0xdeadbeef;
699  memset(dest, 'X', sizeof(dest));
700  ret = p_memmove_s(dest, NUMELMS(dest), big, NUMELMS(big));
701  ok(ret == ERANGE, "Moving a big buffer to a small destination returned %d, expected ERANGE\n", ret);
702  ok(errno == ERANGE, "errno is %d, expected ERANGE\n", errno);
703  okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
704 
705  /* Replace source with NULL */
706  errno = 0xdeadbeef;
707  memset(dest, 'X', sizeof(dest));
708  ret = p_memmove_s(dest, NUMELMS(dest), NULL, NUMELMS(tiny));
709  ok(ret == EINVAL, "Moving a NULL source buffer returned %d, expected EINVAL\n", ret);
710  ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
711  okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
712 
713  /* Vary dest size */
714  errno = 0xdeadbeef;
715  memset(dest, 'X', sizeof(dest));
716  ret = p_memmove_s(dest, 0, tiny, NUMELMS(tiny));
717  ok(ret == ERANGE, "Moving into a destination of size 0 returned %d, expected ERANGE\n", ret);
718  ok(errno == ERANGE, "errno is %d, expected ERANGE\n", errno);
719  okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
720 
721  /* Replace dest with NULL */
722  errno = 0xdeadbeef;
723  ret = p_memmove_s(NULL, NUMELMS(dest), tiny, NUMELMS(tiny));
724  ok(ret == EINVAL, "Moving a tiny buffer to a big NULL destination returned %d, expected EINVAL\n", ret);
725  ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
726 
727  /* Combinations */
728  errno = 0xdeadbeef;
729  memset(dest, 'X', sizeof(dest));
730  ret = p_memmove_s(dest, 0, NULL, NUMELMS(tiny));
731  ok(ret == EINVAL, "Moving a NULL buffer into a destination of size 0 returned %d, expected EINVAL\n", ret);
732  ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
733  okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
734 }
735 
736 static void test_strcat_s(void)
737 {
738  char dest[8];
739  const char *small = "sma";
740  int ret;
741 
742  if(!pstrcat_s)
743  {
744  win_skip("strcat_s not found\n");
745  return;
746  }
747 
748  memset(dest, 'X', sizeof(dest));
749  dest[0] = '\0';
750  ret = pstrcat_s(dest, sizeof(dest), small);
751  ok(ret == 0, "strcat_s: Copying a string into a big enough destination returned %d, expected 0\n", ret);
752  ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == '\0'&&
753  dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
754  "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
755  dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
756  ret = pstrcat_s(dest, sizeof(dest), small);
757  ok(ret == 0, "strcat_s: Attaching a string to a big enough destination returned %d, expected 0\n", ret);
758  ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == 's' &&
759  dest[4] == 'm' && dest[5] == 'a' && dest[6] == '\0'&& dest[7] == 'X',
760  "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
761  dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
762 
763  ret = pstrcat_s(dest, sizeof(dest), small);
764  ok(ret == ERANGE, "strcat_s: Attaching a string to a filled up destination returned %d, expected ERANGE\n", ret);
765  ok(dest[0] == '\0'&& dest[1] == 'm' && dest[2] == 'a' && dest[3] == 's' &&
766  dest[4] == 'm' && dest[5] == 'a' && dest[6] == 's' && dest[7] == 'm',
767  "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
768  dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
769 
770  memset(dest, 'X', sizeof(dest));
771  dest[0] = 'a';
772  dest[1] = '\0';
773 
774  ret = pstrcat_s(dest, 0, small);
775  ok(ret == EINVAL, "strcat_s: Source len = 0 returned %d, expected EINVAL\n", ret);
776  ok(dest[0] == 'a' && dest[1] == '\0'&& dest[2] == 'X' && dest[3] == 'X' &&
777  dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
778  "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
779  dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
780 
781  ret = pstrcat_s(dest, 0, NULL);
782  ok(ret == EINVAL, "strcat_s: len = 0 and src = NULL returned %d, expected EINVAL\n", ret);
783  ok(dest[0] == 'a' && dest[1] == '\0'&& dest[2] == 'X' && dest[3] == 'X' &&
784  dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
785  "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
786  dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
787 
788  ret = pstrcat_s(dest, sizeof(dest), NULL);
789  ok(ret == EINVAL, "strcat_s: Sourcing from NULL returned %d, expected EINVAL\n", ret);
790  ok(dest[0] == '\0'&& dest[1] == '\0'&& dest[2] == 'X' && dest[3] == 'X' &&
791  dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
792  "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
793  dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
794 
795  ret = pstrcat_s(NULL, sizeof(dest), small);
796  ok(ret == EINVAL, "strcat_s: Writing to a NULL string returned %d, expected EINVAL\n", ret);
797 }
798 
799 static void test__mbscat_s(void)
800 {
801  unsigned char dst[8], src[4];
802  int err;
803  int prev_cp = _getmbcp();
804 
805  if(!p_mbscat_s)
806  {
807  win_skip("_mbscat_s not found\n");
808  return;
809  }
810 
811 
812  src[0] = dst[0] = 0;
813  err = p_mbscat_s(NULL, sizeof(dst), src);
814  ok(err == EINVAL, "_mbscat_s returned %d\n", err);
815 
816  err = p_mbscat_s(dst, sizeof(dst), NULL);
817  ok(err == EINVAL, "_mbscat_s returned %d\n", err);
818 
819  dst[0] = 'a';
820  err = p_mbscat_s(dst, 1, src);
821  ok(err == EINVAL, "_mbscat_s returned %d\n", err);
822 
823  memset(dst, 'a', sizeof(dst));
824  dst[6] = 0;
825  src[0] = 'b';
826  src[1] = 0;
827 
828  err = p_mbscat_s(dst, sizeof(dst), src);
829  ok(err == 0, "_mbscat_s returned %d\n", err);
830  ok(!memcmp(dst, "aaaaaab", 8), "dst = %s\n", dst);
831 
832  err = p_mbscat_s(dst, sizeof(dst), src);
833  ok(err == ERANGE, "_mbscat_s returned %d\n", err);
834  ok(!dst[0], "dst[0] = %c\n", dst[0]);
835  ok(dst[1] == 'a', "dst[1] = %c\n", dst[1]);
836 
837  _setmbcp(932);
838  /* test invalid str in dst */
839  dst[0] = 0x81;
840  dst[1] = 0x81;
841  dst[2] = 0x52;
842  dst[3] = 0;
843  src[0] = 'a';
844  src[1] = 0;
845  err = p_mbscat_s(dst, sizeof(dst), src);
846  ok(err == 0, "_mbscat_s returned %d\n", err);
847 
848  /* test invalid str in src */
849  dst[0] = 0;
850  src[0] = 0x81;
851  src[1] = 0x81;
852  src[2] = 0x52;
853  src[3] = 0;
854  err = p_mbscat_s(dst, sizeof(dst), src);
855  ok(err == 0, "_mbscat_s returned %d\n", err);
856 
857  /* test dst with leading byte on the end of buffer */
858  dst[0] = 'a';
859  dst[1] = 0x81;
860  dst[2] = 0;
861  src[0] = 'R';
862  src[1] = 0;
863  err = p_mbscat_s(dst, sizeof(dst), src);
864  ok(err == EILSEQ, "_mbscat_s returned %d\n", err);
865  ok(!memcmp(dst, "aR", 3), "dst = %s\n", dst);
866 
867  /* test src with leading byte on the end of buffer */
868  dst[0] = 'a';
869  dst[1] = 0;
870  src[0] = 'b';
871  src[1] = 0x81;
872  src[2] = 0;
873  err = p_mbscat_s(dst, sizeof(dst), src);
874  ok(err == EILSEQ, "_mbscat_s returned %d\n", err);
875  ok(!memcmp(dst, "ab", 3), "dst = %s\n", dst);
876  _setmbcp(prev_cp);
877 }
878 
879 static void test__mbsnbcpy_s(void)
880 {
881  unsigned char dest[8];
882  const unsigned char big[] = "atoolongstringforthislittledestination";
883  const unsigned char small[] = "small";
884  int ret;
885 
886  if(!p_mbsnbcpy_s)
887  {
888  win_skip("_mbsnbcpy_s not found\n");
889  return;
890  }
891 
892  memset(dest, 'X', sizeof(dest));
893  ret = p_mbsnbcpy_s(dest, sizeof(dest), small, sizeof(small));
894  ok(ret == 0, "_mbsnbcpy_s: Copying a string into a big enough destination returned %d, expected 0\n", ret);
895  ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == 'l' &&
896  dest[4] == 'l' && dest[5] == '\0'&& dest[6] == 'X' && dest[7] == 'X',
897  "Unexpected return data from _mbsnbcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
898  dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
899 
900  /* WTF? */
901  memset(dest, 'X', sizeof(dest));
902  ret = p_mbsnbcpy_s(dest, sizeof(dest) - 2, big, sizeof(small));
903  ok(ret == ERANGE, "_mbsnbcpy_s: Copying a too long string returned %d, expected ERANGE\n", ret);
904  ok(dest[0] == '\0'&& dest[1] == 't' && dest[2] == 'o' && dest[3] == 'o' &&
905  dest[4] == 'l' && dest[5] == 'o' && dest[6] == 'X' && dest[7] == 'X',
906  "Unexpected return data from _mbsnbcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
907  dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
908 
909  memset(dest, 'X', sizeof(dest));
910  ret = p_mbsnbcpy_s(dest, sizeof(dest) - 2, big, 4);
911  ok(ret == 0, "_mbsnbcpy_s: Copying a too long string with a count cap returned %d, expected 0\n", ret);
912  ok(dest[0] == 'a' && dest[1] == 't' && dest[2] == 'o' && dest[3] == 'o' &&
913  dest[4] == '\0'&& dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
914  "Unexpected return data from _mbsnbcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
915  dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
916 
917  memset(dest, 'X', sizeof(dest));
918  ret = p_mbsnbcpy_s(dest, sizeof(dest) - 2, small, sizeof(small) + 10);
919  ok(ret == 0, "_mbsnbcpy_s: Copying more data than the source string len returned %d, expected 0\n", ret);
920  ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == 'l' &&
921  dest[4] == 'l' && dest[5] == '\0'&& dest[6] == 'X' && dest[7] == 'X',
922  "Unexpected return data from _mbsnbcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
923  dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
924 }
925 
926 static void test__mbscpy_s(void)
927 {
928  const unsigned char src[] = "source string";
929  unsigned char dest[16];
930  int ret;
931 
932  if(!p__mbscpy_s)
933  {
934  win_skip("_mbscpy_s not found\n");
935  return;
936  }
937 
938  ret = p__mbscpy_s(NULL, 0, src);
939  ok(ret == EINVAL, "got %d\n", ret);
940  ret = p__mbscpy_s(NULL, sizeof(dest), src);
941  ok(ret == EINVAL, "got %d\n", ret);
942  ret = p__mbscpy_s(dest, 0, src);
943  ok(ret == EINVAL, "got %d\n", ret);
944  dest[0] = 'x';
945  ret = p__mbscpy_s(dest, sizeof(dest), NULL);
946  ok(ret == EINVAL, "got %d\n", ret);
947  ok(!dest[0], "dest buffer was not modified on invalid argument\n");
948 
949  memset(dest, 'X', sizeof(dest));
950  ret = p__mbscpy_s(dest, sizeof(dest), src);
951  ok(!ret, "got %d\n", ret);
952  ok(!memcmp(dest, src, sizeof(src)), "dest = %s\n", dest);
953  ok(dest[sizeof(src)] == 'X', "unused part of buffer was modified\n");
954 
955  memset(dest, 'X', sizeof(dest));
956  ret = p__mbscpy_s(dest, 4, src);
957  ok(ret == ERANGE, "got %d\n", ret);
958  ok(!dest[0], "incorrect dest buffer (%d)\n", dest[0]);
959  ok(dest[1] == src[1], "incorrect dest buffer (%d)\n", dest[1]);
960 }
961 
962 static void test_wcscpy_s(void)
963 {
964  static const WCHAR szLongText[] = { 'T','h','i','s','A','L','o','n','g','s','t','r','i','n','g',0 };
965  static WCHAR szDest[18];
966  static WCHAR szDestShort[8];
967  int ret;
968 
969  if(!p_wcscpy_s)
970  {
971  win_skip("wcscpy_s not found\n");
972  return;
973  }
974 
975  /* Test NULL Dest */
976  errno = EBADF;
977  ret = p_wcscpy_s(NULL, 18, szLongText);
978  ok(ret == EINVAL, "p_wcscpy_s expect EINVAL got %d\n", ret);
979  ok(errno == EINVAL, "expected errno EINVAL got %d\n", errno);
980 
981  /* Test NULL Source */
982  errno = EBADF;
983  szDest[0] = 'A';
984  ret = p_wcscpy_s(szDest, 18, NULL);
985  ok(ret == EINVAL, "expected EINVAL got %d\n", ret);
986  ok(errno == EINVAL, "expected errno EINVAL got %d\n", errno);
987  ok(szDest[0] == 0, "szDest[0] not 0, got %c\n", szDest[0]);
988 
989  /* Test invalid size */
990  errno = EBADF;
991  szDest[0] = 'A';
992  ret = p_wcscpy_s(szDest, 0, szLongText);
993  /* Later versions changed the return value for this case to EINVAL,
994  * and don't modify the result if the dest size is 0.
995  */
996  ok(ret == ERANGE || ret == EINVAL, "expected ERANGE/EINVAL got %d\n", ret);
997  ok(errno == ERANGE || errno == EINVAL, "expected errno ERANGE/EINVAL got %d\n", errno);
998  ok(szDest[0] == 0 || ret == EINVAL, "szDest[0] not 0\n");
999 
1000  /* Copy same buffer size */
1001  ret = p_wcscpy_s(szDest, 18, szLongText);
1002  ok(ret == 0, "expected 0 got %d\n", ret);
1003  ok(lstrcmpW(szDest, szLongText) == 0, "szDest != szLongText\n");
1004 
1005  /* Copy smaller buffer size */
1006  errno = EBADF;
1007  szDest[0] = 'A';
1008  ret = p_wcscpy_s(szDestShort, 8, szLongText);
1009  ok(ret == ERANGE || ret == EINVAL, "expected ERANGE/EINVAL got %d\n", ret);
1010  ok(errno == ERANGE || errno == EINVAL, "expected errno ERANGE/EINVAL got %d\n", errno);
1011  ok(szDestShort[0] == 0, "szDestShort[0] not 0\n");
1012 
1013  if(!p_wcsncpy_s)
1014  {
1015  win_skip("wcsncpy_s not found\n");
1016  return;
1017  }
1018 
1019  ret = p_wcsncpy_s(NULL, 18, szLongText, sizeof(szLongText)/sizeof(WCHAR));
1020  ok(ret == EINVAL, "p_wcsncpy_s expect EINVAL got %d\n", ret);
1021 
1022  szDest[0] = 'A';
1023  ret = p_wcsncpy_s(szDest, 18, NULL, 1);
1024  ok(ret == EINVAL, "expected EINVAL got %d\n", ret);
1025  ok(szDest[0] == 0, "szDest[0] not 0\n");
1026 
1027  szDest[0] = 'A';
1028  ret = p_wcsncpy_s(szDest, 18, NULL, 0);
1029  ok(ret == 0, "expected ERROR_SUCCESS got %d\n", ret);
1030  ok(szDest[0] == 0, "szDest[0] not 0\n");
1031 
1032  szDest[0] = 'A';
1033  ret = p_wcsncpy_s(szDest, 0, szLongText, sizeof(szLongText)/sizeof(WCHAR));
1034  ok(ret == ERANGE || ret == EINVAL, "expected ERANGE/EINVAL got %d\n", ret);
1035  ok(szDest[0] == 0 || ret == EINVAL, "szDest[0] not 0\n");
1036 
1037  ret = p_wcsncpy_s(szDest, 18, szLongText, sizeof(szLongText)/sizeof(WCHAR));
1038  ok(ret == 0, "expected 0 got %d\n", ret);
1039  ok(lstrcmpW(szDest, szLongText) == 0, "szDest != szLongText\n");
1040 
1041  szDest[0] = 'A';
1042  ret = p_wcsncpy_s(szDestShort, 8, szLongText, sizeof(szLongText)/sizeof(WCHAR));
1043  ok(ret == ERANGE || ret == EINVAL, "expected ERANGE/EINVAL got %d\n", ret);
1044  ok(szDestShort[0] == 0, "szDestShort[0] not 0\n");
1045 
1046  szDest[0] = 'A';
1047  ret = p_wcsncpy_s(szDest, 5, szLongText, -1);
1048  ok(ret == STRUNCATE, "expected STRUNCATE got %d\n", ret);
1049  ok(szDest[4] == 0, "szDest[4] not 0\n");
1050  ok(!memcmp(szDest, szLongText, 4*sizeof(WCHAR)), "szDest = %s\n", wine_dbgstr_w(szDest));
1051 
1052  ret = p_wcsncpy_s(NULL, 0, (void*)0xdeadbeef, 0);
1053  ok(ret == 0, "ret = %d\n", ret);
1054 
1055  szDestShort[0] = '1';
1056  szDestShort[1] = 0;
1057  ret = p_wcsncpy_s(szDestShort+1, 4, szDestShort, -1);
1058  ok(ret == STRUNCATE, "expected ERROR_SUCCESS got %d\n", ret);
1059  ok(szDestShort[0]=='1' && szDestShort[1]=='1' && szDestShort[2]=='1' && szDestShort[3]=='1',
1060  "szDestShort = %s\n", wine_dbgstr_w(szDestShort));
1061 }
1062 
1063 static void test__wcsupr_s(void)
1064 {
1065  static const WCHAR mixedString[] = {'M', 'i', 'X', 'e', 'D', 'l', 'o', 'w',
1066  'e', 'r', 'U', 'P', 'P', 'E', 'R', 0};
1067  static const WCHAR expectedString[] = {'M', 'I', 'X', 'E', 'D', 'L', 'O',
1068  'W', 'E', 'R', 'U', 'P', 'P', 'E',
1069  'R', 0};
1070  WCHAR testBuffer[2*sizeof(mixedString)/sizeof(WCHAR)];
1071  int ret;
1072 
1073  if (!p_wcsupr_s)
1074  {
1075  win_skip("_wcsupr_s not found\n");
1076  return;
1077  }
1078 
1079  /* Test NULL input string and invalid size. */
1080  errno = EBADF;
1081  ret = p_wcsupr_s(NULL, 0);
1082  ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
1083  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1084 
1085  /* Test NULL input string and valid size. */
1086  errno = EBADF;
1087  ret = p_wcsupr_s(NULL, sizeof(testBuffer)/sizeof(WCHAR));
1088  ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
1089  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1090 
1091  /* Test empty string with zero size. */
1092  errno = EBADF;
1093  testBuffer[0] = '\0';
1094  ret = p_wcsupr_s(testBuffer, 0);
1095  ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
1096  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1097  ok(testBuffer[0] == '\0', "Expected the buffer to be unchanged\n");
1098 
1099  /* Test empty string with size of one. */
1100  testBuffer[0] = '\0';
1101  ret = p_wcsupr_s(testBuffer, 1);
1102  ok(ret == 0, "Expected _wcsupr_s to succeed, got %d\n", ret);
1103  ok(testBuffer[0] == '\0', "Expected the buffer to be unchanged\n");
1104 
1105  /* Test one-byte buffer with zero size. */
1106  errno = EBADF;
1107  testBuffer[0] = 'x';
1108  ret = p_wcsupr_s(testBuffer, 0);
1109  ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
1110  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1111  ok(testBuffer[0] == '\0', "Expected the first buffer character to be null\n");
1112 
1113  /* Test one-byte buffer with size of one. */
1114  errno = EBADF;
1115  testBuffer[0] = 'x';
1116  ret = p_wcsupr_s(testBuffer, 1);
1117  ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
1118  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1119  ok(testBuffer[0] == '\0', "Expected the first buffer character to be null\n");
1120 
1121  /* Test invalid size. */
1122  wcscpy(testBuffer, mixedString);
1123  errno = EBADF;
1124  ret = p_wcsupr_s(testBuffer, 0);
1125  ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
1126  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1127  ok(testBuffer[0] == '\0', "Expected the first buffer character to be null\n");
1128 
1129  /* Test normal string uppercasing. */
1130  wcscpy(testBuffer, mixedString);
1131  ret = p_wcsupr_s(testBuffer, sizeof(mixedString)/sizeof(WCHAR));
1132  ok(ret == 0, "Expected _wcsupr_s to succeed, got %d\n", ret);
1133  ok(!wcscmp(testBuffer, expectedString), "Expected the string to be fully upper-case\n");
1134 
1135  /* Test uppercasing with a shorter buffer size count. */
1136  wcscpy(testBuffer, mixedString);
1137  errno = EBADF;
1138  ret = p_wcsupr_s(testBuffer, sizeof(mixedString)/sizeof(WCHAR) - 1);
1139  ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
1140  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
1141  ok(testBuffer[0] == '\0', "Expected the first buffer character to be null\n");
1142 
1143  /* Test uppercasing with a longer buffer size count. */
1144  wcscpy(testBuffer, mixedString);
1145  ret = p_wcsupr_s(testBuffer, sizeof(testBuffer)/sizeof(WCHAR));
1146  ok(ret == 0, "Expected _wcsupr_s to succeed, got %d\n", ret);
1147  ok(!wcscmp(testBuffer, expectedString), "Expected the string to be fully upper-case\n");
1148 }
1149 
1150 static void test__wcslwr_s(void)
1151 {
1152  static const WCHAR mixedString[] = {'M', 'i', 'X', 'e', 'D', 'l', 'o', 'w',
1153  'e', 'r', 'U', 'P', 'P', 'E', 'R', 0};
1154  static const WCHAR expectedString[] = {'m', 'i', 'x', 'e', 'd', 'l', 'o',
1155  'w', 'e', 'r', 'u', 'p', 'p', 'e',
1156  'r', 0};
1157  WCHAR buffer[2*sizeof(mixedString)/sizeof(WCHAR)];
1158  int ret;
1159 
1160  if (!p_wcslwr_s)
1161  {
1162  win_skip("_wcslwr_s not found\n");
1163  return;
1164  }
1165 
1166  /* Test NULL input string and invalid size. */
1167  errno = EBADF;
1168  ret = p_wcslwr_s(NULL, 0);
1169  ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
1170  ok(errno == EINVAL, "expected errno EINVAL, got %d\n", errno);
1171 
1172  /* Test NULL input string and valid size. */
1173  errno = EBADF;
1174  ret = p_wcslwr_s(NULL, sizeof(buffer)/sizeof(buffer[0]));
1175  ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
1176  ok(errno == EINVAL, "expected errno EINVAL, got %d\n", errno);
1177 
1178  /* Test empty string with zero size. */
1179  errno = EBADF;
1180  buffer[0] = 'a';
1181  ret = p_wcslwr_s(buffer, 0);
1182  ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
1183  ok(errno == EINVAL, "expected errno EINVAL, got %d\n", errno);
1184  ok(buffer[0] == 0, "expected empty string\n");
1185 
1186  /* Test empty string with size of one. */
1187  buffer[0] = 0;
1188  ret = p_wcslwr_s(buffer, 1);
1189  ok(ret == 0, "got %d\n", ret);
1190  ok(buffer[0] == 0, "expected buffer to be unchanged\n");
1191 
1192  /* Test one-byte buffer with zero size. */
1193  errno = EBADF;
1194  buffer[0] = 'x';
1195  ret = p_wcslwr_s(buffer, 0);
1196  ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
1197  ok(errno == EINVAL, "expected errno to be EINVAL, got %d\n", errno);
1198  ok(buffer[0] == '\0', "expected empty string\n");
1199 
1200  /* Test one-byte buffer with size of one. */
1201  errno = EBADF;
1202  buffer[0] = 'x';
1203  ret = p_wcslwr_s(buffer, 1);
1204  ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
1205  ok(errno == EINVAL, "expected errno to be EINVAL, got %d\n", errno);
1206  ok(buffer[0] == '\0', "expected empty string\n");
1207 
1208  /* Test invalid size. */
1209  wcscpy(buffer, mixedString);
1210  errno = EBADF;
1211  ret = p_wcslwr_s(buffer, 0);
1212  ok(ret == EINVAL, "Expected EINVAL, got %d\n", ret);
1213  ok(errno == EINVAL, "expected errno to be EINVAL, got %d\n", errno);
1214  ok(buffer[0] == '\0', "expected empty string\n");
1215 
1216  /* Test normal string uppercasing. */
1217  wcscpy(buffer, mixedString);
1218  ret = p_wcslwr_s(buffer, sizeof(mixedString)/sizeof(WCHAR));
1219  ok(ret == 0, "expected 0, got %d\n", ret);
1220  ok(!wcscmp(buffer, expectedString), "expected lowercase\n");
1221 
1222  /* Test uppercasing with a shorter buffer size count. */
1223  wcscpy(buffer, mixedString);
1224  errno = EBADF;
1225  ret = p_wcslwr_s(buffer, sizeof(mixedString)/sizeof(WCHAR) - 1);
1226  ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
1227  ok(errno == EINVAL, "expected errno to be EINVAL, got %d\n", errno);
1228  ok(buffer[0] == '\0', "expected empty string\n");
1229 
1230  /* Test uppercasing with a longer buffer size count. */
1231  wcscpy(buffer, mixedString);
1232  ret = p_wcslwr_s(buffer, sizeof(buffer)/sizeof(WCHAR));
1233  ok(ret == 0, "expected 0, got %d\n", ret);
1234  ok(!wcscmp(buffer, expectedString), "expected lowercase\n");
1235 }
1236 
1237 static void test_mbcjisjms(void)
1238 {
1239  /* List of value-pairs to test. The test assumes the last pair to be {0, ..} */
1240  unsigned int jisjms[][2] = { {0x2020, 0}, {0x2021, 0}, {0x2120, 0}, {0x2121, 0x8140},
1241  {0x7f7f, 0}, {0x7f7e, 0}, {0x7e7f, 0}, {0x7e7e, 0xeffc},
1242  {0x255f, 0x837e}, {0x2560, 0x8380}, {0x2561, 0x8381},
1243  {0x2121FFFF, 0}, {0x2223, 0x81a1}, {0x237e, 0x829e}, {0, 0}};
1244  int cp[] = { 932, 936, 939, 950, 1361, _MB_CP_SBCS };
1245  unsigned int i, j;
1246  int prev_cp = _getmbcp();
1247 
1248  for (i = 0; i < sizeof(cp)/sizeof(cp[0]); i++)
1249  {
1250  _setmbcp(cp[i]);
1251  for (j = 0; jisjms[j][0] != 0; j++)
1252  {
1253  unsigned int ret, exp;
1254  ret = _mbcjistojms(jisjms[j][0]);
1255  exp = (cp[i] == 932) ? jisjms[j][1] : jisjms[j][0];
1256  ok(ret == exp, "Expected 0x%x, got 0x%x (0x%x, codepage=%d)\n",
1257  exp, ret, jisjms[j][0], cp[i]);
1258  }
1259  }
1260  _setmbcp(prev_cp);
1261 }
1262 
1263 static void test_mbcjmsjis(void)
1264 {
1265  /* List of value-pairs to test. The test assumes the last pair to be {0, ..} */
1266  unsigned int jmsjis[][2] = { {0x80fc, 0}, {0x813f, 0}, {0x8140, 0x2121},
1267  {0x817e, 0x215f}, {0x817f, 0}, {0x8180, 0x2160},
1268  {0x819e, 0x217e}, {0x819f, 0x2221}, {0x81fc, 0x227e},
1269  {0x81fd, 0}, {0x9ffc, 0x5e7e}, {0x9ffd, 0},
1270  {0xa040, 0}, {0xdffc, 0}, {0xe040, 0x5f21},
1271  {0xeffc, 0x7e7e}, {0xf040, 0}, {0x21, 0}, {0, 0}};
1272  int cp[] = { 932, 936, 939, 950, 1361, _MB_CP_SBCS };
1273  unsigned int i, j;
1274  int prev_cp = _getmbcp();
1275 
1276  for (i = 0; i < sizeof(cp)/sizeof(cp[0]); i++)
1277  {
1278  _setmbcp(cp[i]);
1279  for (j = 0; jmsjis[j][0] != 0; j++)
1280  {
1281  unsigned int ret, exp;
1282  ret = _mbcjmstojis(jmsjis[j][0]);
1283  exp = (cp[i] == 932) ? jmsjis[j][1] : jmsjis[j][0];
1284  ok(ret == exp, "Expected 0x%x, got 0x%x (0x%x, codepage=%d)\n",
1285  exp, ret, jmsjis[j][0], cp[i]);
1286  }
1287  }
1288  _setmbcp(prev_cp);
1289 }
1290 
1291 static void test_mbctohira(void)
1292 {
1293  static const unsigned int mbchira_932[][2] = {
1294  {0x8152, 0x8152}, {0x8153, 0x8153}, {0x8154, 0x8154}, {0x8155, 0x8155},
1295  {0x82a0, 0x82a0}, {0x833f, 0x833f}, {0x8340, 0x829f}, {0x837e, 0x82dd},
1296  {0x837f, 0x837f}, {0x8380, 0x82de}, {0x8393, 0x82f1}, {0x8394, 0x8394},
1297  {0x8396, 0x8396}, {0x8397, 0x8397},
1298  {0xa5, 0xa5}, {0xb0, 0xb0}, {0xdd, 0xdd} };
1299  unsigned int i;
1300  unsigned int prev_cp = _getmbcp();
1301 
1303  for (i = 0; i < sizeof(mbchira_932)/sizeof(mbchira_932[0]); i++)
1304  {
1305  int ret, exp = mbchira_932[i][0];
1306  ret = _mbctohira(mbchira_932[i][0]);
1307  ok(ret == exp, "Expected 0x%x, got 0x%x\n", exp, ret);
1308  }
1309 
1310  _setmbcp(932);
1311  for (i = 0; i < sizeof(mbchira_932)/sizeof(mbchira_932[0]); i++)
1312  {
1313  unsigned int ret, exp;
1314  ret = _mbctohira(mbchira_932[i][0]);
1315  exp = mbchira_932[i][1];
1316  ok(ret == exp, "Expected 0x%x, got 0x%x\n", exp, ret);
1317  }
1318  _setmbcp(prev_cp);
1319 }
1320 
1321 static void test_mbctokata(void)
1322 {
1323  static const unsigned int mbckata_932[][2] = {
1324  {0x8152, 0x8152}, {0x8153, 0x8153}, {0x8154, 0x8154}, {0x8155, 0x8155},
1325  {0x833f, 0x833f}, {0x829f, 0x8340}, {0x82dd, 0x837e}, {0x837f, 0x837f},
1326  {0x82de, 0x8380}, {0x8394, 0x8394}, {0x8397, 0x8397},
1327  {0xa5, 0xa5}, {0xb0, 0xb0}, {0xdd, 0xdd} };
1328  unsigned int i;
1329  unsigned int prev_cp = _getmbcp();
1330 
1332  for (i = 0; i < sizeof(mbckata_932)/sizeof(mbckata_932[0]); i++)
1333  {
1334  int ret, exp = mbckata_932[i][0];
1335  ret = _mbctokata(mbckata_932[i][0]);
1336  ok(ret == exp, "Expected 0x%x, got 0x%x\n", exp, ret);
1337  }
1338 
1339  _setmbcp(932);
1340  for (i = 0; i < sizeof(mbckata_932)/sizeof(mbckata_932[0]); i++)
1341  {
1342  unsigned int ret, exp;
1343  ret = _mbctokata(mbckata_932[i][0]);
1344  exp = mbckata_932[i][1];
1345  ok(ret == exp, "Expected 0x%x, got 0x%x\n", exp, ret);
1346  }
1347  _setmbcp(prev_cp);
1348 }
1349 
1350 static void test_mbbtombc(void)
1351 {
1352  static const unsigned int mbbmbc[][2] = {
1353  {0x1f, 0x1f}, {0x20, 0x8140}, {0x39, 0x8258}, {0x40, 0x8197},
1354  {0x41, 0x8260}, {0x5e, 0x814f}, {0x7e, 0x8150}, {0x7f, 0x7f},
1355  {0x80, 0x80}, {0x81, 0x81}, {0xa0, 0xa0}, {0xa7, 0x8340},
1356  {0xb0, 0x815b}, {0xd1, 0x8380}, {0xff, 0xff}, {0,0}};
1357  int cp[] = { 932, 936, 939, 950, 1361, _MB_CP_SBCS };
1358  int i, j;
1359  int prev_cp = _getmbcp();
1360 
1361  for (i = 0; i < sizeof(cp)/sizeof(cp[0]); i++)
1362  {
1363  _setmbcp(cp[i]);
1364  for (j = 0; mbbmbc[j][0] != 0; j++)
1365  {
1366  unsigned int exp, ret;
1367  ret = _mbbtombc(mbbmbc[j][0]);
1368  exp = (cp[i] == 932) ? mbbmbc[j][1] : mbbmbc[j][0];
1369  ok(ret == exp, "Expected 0x%x, got 0x%x (0x%x, codepage %d)\n",
1370  exp, ret, mbbmbc[j][0], cp[i]);
1371  }
1372  }
1373  _setmbcp(prev_cp);
1374 }
1375 
1376 static void test_mbctombb(void)
1377 {
1378  static const unsigned int mbcmbb_932[][2] = {
1379  {0x829e, 0x829e}, {0x829f, 0xa7}, {0x82f1, 0xdd}, {0x82f2, 0x82f2},
1380  {0x833f, 0x833f}, {0x8340, 0xa7}, {0x837e, 0xd0}, {0x837f, 0x837f},
1381  {0x8380, 0xd1}, {0x8396, 0xb9}, {0x8397, 0x8397}, {0x813f, 0x813f},
1382  {0x8140, 0x20}, {0x814c, 0x814c}, {0x814f, 0x5e}, {0x8197, 0x40},
1383  {0x8198, 0x8198}, {0x8258, 0x39}, {0x8259, 0x8259}, {0x825f, 0x825f},
1384  {0x8260, 0x41}, {0x82f1, 0xdd}, {0x82f2, 0x82f2}, {0,0}};
1385  unsigned int exp, ret, i;
1386  unsigned int prev_cp = _getmbcp();
1387 
1388  _setmbcp(932);
1389  for (i = 0; mbcmbb_932[i][0] != 0; i++)
1390  {
1391  ret = _mbctombb(mbcmbb_932[i][0]);
1392  exp = mbcmbb_932[i][1];
1393  ok(ret == exp, "Expected 0x%x, got 0x%x\n", exp, ret);
1394  }
1395  _setmbcp(prev_cp);
1396 }
1397 
1398 static void test_ismbckata(void) {
1399  struct katakana_pair {
1400  UINT c;
1401  BOOL exp;
1402  };
1403  static const struct katakana_pair tests[] = {
1404  {0x8152, FALSE}, {0x8153, FALSE}, {0x8154, FALSE}, {0x8155, FALSE},
1405  {0x82a0, FALSE}, {0x833f, FALSE}, {0x8340, TRUE }, {0x837e, TRUE },
1406  {0x837f, FALSE}, {0x8380, TRUE }, {0x8396, TRUE }, {0x8397, FALSE},
1407  {0xa5, FALSE}, {0xb0, FALSE}, {0xdd, FALSE}
1408  };
1409  unsigned int prev_cp = _getmbcp();
1410  int ret;
1411  unsigned int i;
1412 
1414  for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
1415  ret = _ismbckata(tests[i].c);
1416  ok(!ret, "expected 0, got %d for %04x\n", ret, tests[i].c);
1417  }
1418 
1419  _setmbcp(932);
1420  for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
1421  ret = _ismbckata(tests[i].c);
1422  ok(!!ret == tests[i].exp, "expected %d, got %d for %04x\n",
1423  tests[i].exp, !!ret, tests[i].c);
1424  }
1425 
1426  _setmbcp(prev_cp);
1427 }
1428 
1429 static void test_ismbclegal(void) {
1430  unsigned int prev_cp = _getmbcp();
1431  int ret, exp, err;
1432  unsigned int i;
1433 
1434  _setmbcp(932); /* Japanese */
1435  err = 0;
1436  for(i = 0; i < 0x10000; i++) {
1437  ret = _ismbclegal(i);
1438  exp = ((HIBYTE(i) >= 0x81 && HIBYTE(i) <= 0x9F) ||
1439  (HIBYTE(i) >= 0xE0 && HIBYTE(i) <= 0xFC)) &&
1440  ((LOBYTE(i) >= 0x40 && LOBYTE(i) <= 0x7E) ||
1441  (LOBYTE(i) >= 0x80 && LOBYTE(i) <= 0xFC));
1442  if(ret != exp) {
1443  err = 1;
1444  break;
1445  }
1446  }
1447  ok(!err, "_ismbclegal (932) : Expected 0x%x, got 0x%x (0x%x)\n", exp, ret, i);
1448  _setmbcp(936); /* Chinese (GBK) */
1449  err = 0;
1450  for(i = 0; i < 0x10000; i++) {
1451  ret = _ismbclegal(i);
1452  exp = HIBYTE(i) >= 0x81 && HIBYTE(i) <= 0xFE &&
1453  LOBYTE(i) >= 0x40 && LOBYTE(i) <= 0xFE;
1454  if(ret != exp) {
1455  err = 1;
1456  break;
1457  }
1458  }
1459  ok(!err, "_ismbclegal (936) : Expected 0x%x, got 0x%x (0x%x)\n", exp, ret, i);
1460  _setmbcp(949); /* Korean */
1461  err = 0;
1462  for(i = 0; i < 0x10000; i++) {
1463  ret = _ismbclegal(i);
1464  exp = HIBYTE(i) >= 0x81 && HIBYTE(i) <= 0xFE &&
1465  LOBYTE(i) >= 0x41 && LOBYTE(i) <= 0xFE;
1466  if(ret != exp) {
1467  err = 1;
1468  break;
1469  }
1470  }
1471  ok(!err, "_ismbclegal (949) : Expected 0x%x, got 0x%x (0x%x)\n", exp, ret, i);
1472  _setmbcp(950); /* Chinese (Big5) */
1473  err = 0;
1474  for(i = 0; i < 0x10000; i++) {
1475  ret = _ismbclegal(i);
1476  exp = HIBYTE(i) >= 0x81 && HIBYTE(i) <= 0xFE &&
1477  ((LOBYTE(i) >= 0x40 && LOBYTE(i) <= 0x7E) ||
1478  (LOBYTE(i) >= 0xA1 && LOBYTE(i) <= 0xFE));
1479  if(ret != exp) {
1480  err = 1;
1481  break;
1482  }
1483  }
1484  ok(!err, "_ismbclegal (950) : Expected 0x%x, got 0x%x (0x%x)\n", exp, ret, i);
1485  _setmbcp(1361); /* Korean (Johab) */
1486  err = 0;
1487  for(i = 0; i < 0x10000; i++) {
1488  ret = _ismbclegal(i);
1489  exp = ((HIBYTE(i) >= 0x81 && HIBYTE(i) <= 0xD3) ||
1490  (HIBYTE(i) >= 0xD8 && HIBYTE(i) <= 0xF9)) &&
1491  ((LOBYTE(i) >= 0x31 && LOBYTE(i) <= 0x7E) ||
1492  (LOBYTE(i) >= 0x81 && LOBYTE(i) <= 0xFE)) &&
1493  HIBYTE(i) != 0xDF;
1494  if(ret != exp) {
1495  err = 1;
1496  break;
1497  }
1498  }
1499  todo_wine ok(!err, "_ismbclegal (1361) : Expected 0x%x, got 0x%x (0x%x)\n", exp, ret, i);
1500 
1501  _setmbcp(prev_cp);
1502 }
1503 
1504 static const struct {
1505  const char* string;
1506  const char* delimiter;
1507  int exp_offsetret1; /* returned offset from string after first call to strtok()
1508  -1 means NULL */
1509  int exp_offsetret2; /* returned offset from string after second call to strtok()
1510  -1 means NULL */
1511  int exp_offsetret3; /* returned offset from string after third call to strtok()
1512  -1 means NULL */
1513 } testcases_strtok[] = {
1514  { "red cabernet", " ", 0, 4, -1 },
1515  { "sparkling white riesling", " ", 0, 10, 16 },
1516  { " pale cream sherry", "e ", 1, 6, 9 },
1517  /* end mark */
1518  { 0}
1519 };
1520 
1521 static void test_strtok(void)
1522 {
1523  int i;
1524  char *strret;
1525  char teststr[100];
1526  for( i = 0; testcases_strtok[i].string; i++){
1527  strcpy( teststr, testcases_strtok[i].string);
1528  strret = strtok( teststr, testcases_strtok[i].delimiter);
1529  ok( (int)(strret - teststr) == testcases_strtok[i].exp_offsetret1 ||
1530  (!strret && testcases_strtok[i].exp_offsetret1 == -1),
1531  "string (%p) \'%s\' return %p\n",
1532  teststr, testcases_strtok[i].string, strret);
1533  if( !strret) continue;
1534  strret = strtok( NULL, testcases_strtok[i].delimiter);
1535  ok( (int)(strret - teststr) == testcases_strtok[i].exp_offsetret2 ||
1536  (!strret && testcases_strtok[i].exp_offsetret2 == -1),
1537  "second call string (%p) \'%s\' return %p\n",
1538  teststr, testcases_strtok[i].string, strret);
1539  if( !strret) continue;
1540  strret = strtok( NULL, testcases_strtok[i].delimiter);
1541  ok( (int)(strret - teststr) == testcases_strtok[i].exp_offsetret3 ||
1542  (!strret && testcases_strtok[i].exp_offsetret3 == -1),
1543  "third call string (%p) \'%s\' return %p\n",
1544  teststr, testcases_strtok[i].string, strret);
1545  }
1546 }
1547 
1548 static void test_strtol(void)
1549 {
1550  static char neg[] = "-0x";
1551 
1552  char* e;
1553  LONG l;
1554  ULONG ul;
1555 
1556  /* errno is only set in case of error, so reset errno to EBADF to check for errno modification */
1557  /* errno is modified on W2K8+ */
1558  errno = EBADF;
1559  l = strtol("-1234", &e, 0);
1560  ok(l==-1234, "wrong value %d\n", l);
1561  ok(errno == EBADF || broken(errno == 0), "wrong errno %d\n", errno);
1562  errno = EBADF;
1563  ul = strtoul("1234", &e, 0);
1564  ok(ul==1234, "wrong value %u\n", ul);
1565  ok(errno == EBADF || broken(errno == 0), "wrong errno %d\n", errno);
1566 
1567  errno = EBADF;
1568  l = strtol("2147483647L", &e, 0);
1569  ok(l==2147483647, "wrong value %d\n", l);
1570  ok(errno == EBADF || broken(errno == 0), "wrong errno %d\n", errno);
1571  errno = EBADF;
1572  l = strtol("-2147483648L", &e, 0);
1573  ok(l==-2147483647L - 1, "wrong value %d\n", l);
1574  ok(errno == EBADF || broken(errno == 0), "wrong errno %d\n", errno);
1575  errno = EBADF;
1576  ul = strtoul("4294967295UL", &e, 0);
1577  ok(ul==4294967295ul, "wrong value %u\n", ul);
1578  ok(errno == EBADF || broken(errno == 0), "wrong errno %d\n", errno);
1579 
1580  errno = 0;
1581  l = strtol("9223372036854775807L", &e, 0);
1582  ok(l==2147483647, "wrong value %d\n", l);
1583  ok(errno == ERANGE, "wrong errno %d\n", errno);
1584  errno = 0;
1585  ul = strtoul("9223372036854775807L", &e, 0);
1586  ok(ul==4294967295ul, "wrong value %u\n", ul);
1587  ok(errno == ERANGE, "wrong errno %d\n", errno);
1588 
1589  errno = 0;
1590  ul = strtoul("-2", NULL, 0);
1591  ok(ul == -2, "wrong value %u\n", ul);
1592  ok(errno == 0, "wrong errno %d\n", errno);
1593 
1594  errno = 0;
1595  ul = strtoul("-4294967294", NULL, 0);
1596  ok(ul == 2, "wrong value %u\n", ul);
1597  ok(errno == 0, "wrong errno %d\n", errno);
1598 
1599  errno = 0;
1600  ul = strtoul("-4294967295", NULL, 0);
1601  ok(ul==1, "wrong value %u\n", ul);
1602  ok(errno == 0, "wrong errno %d\n", errno);
1603 
1604  errno = 0;
1605  ul = strtoul("-4294967296", NULL, 0);
1606  ok(ul == 1, "wrong value %u\n", ul);
1607  ok(errno == ERANGE, "wrong errno %d\n", errno);
1608 
1609  errno = 0;
1610  l = strtol(neg, &e, 0);
1611  ok(l == 0, "wrong value %d\n", l);
1612  ok(errno == 0, "wrong errno %d\n", errno);
1613  ok(e == neg, "e = %p, neg = %p\n", e, neg);
1614 }
1615 
1616 static void test_strnlen(void)
1617 {
1618  static const char str[] = "string";
1619  size_t res;
1620 
1621  if(!p_strnlen) {
1622  win_skip("strnlen not found\n");
1623  return;
1624  }
1625 
1626  res = p_strnlen(str, 20);
1627  ok(res == 6, "Returned length = %d\n", (int)res);
1628 
1629  res = p_strnlen(str, 3);
1630  ok(res == 3, "Returned length = %d\n", (int)res);
1631 
1632  res = p_strnlen(NULL, 0);
1633  ok(res == 0, "Returned length = %d\n", (int)res);
1634 }
1635 
1636 static void test__strtoi64(void)
1637 {
1638  static const char no1[] = "31923";
1639  static const char no2[] = "-213312";
1640  static const char no3[] = "12aa";
1641  static const char no4[] = "abc12";
1642  static const char overflow[] = "99999999999999999999";
1643  static const char neg_overflow[] = "-99999999999999999999";
1644  static const char hex[] = "0x123";
1645  static const char oct[] = "000123";
1646  static const char blanks[] = " 12 212.31";
1647 
1648  __int64 res;
1649  unsigned __int64 ures;
1650  char *endpos;
1651 
1652  if(!p_strtoi64 || !p_strtoui64) {
1653  win_skip("_strtoi64 or _strtoui64 not found\n");
1654  return;
1655  }
1656 
1657  errno = 0xdeadbeef;
1658  res = p_strtoi64(no1, NULL, 10);
1659  ok(res == 31923, "res != 31923\n");
1660  res = p_strtoi64(no2, NULL, 10);
1661  ok(res == -213312, "res != -213312\n");
1662  res = p_strtoi64(no3, NULL, 10);
1663  ok(res == 12, "res != 12\n");
1664  res = p_strtoi64(no4, &endpos, 10);
1665  ok(res == 0, "res != 0\n");
1666  ok(endpos == no4, "Scanning was not stopped on first character\n");
1667  res = p_strtoi64(hex, &endpos, 10);
1668  ok(res == 0, "res != 0\n");
1669  ok(endpos == hex+1, "Incorrect endpos (%p-%p)\n", hex, endpos);
1670  res = p_strtoi64(oct, &endpos, 10);
1671  ok(res == 123, "res != 123\n");
1672  ok(endpos == oct+strlen(oct), "Incorrect endpos (%p-%p)\n", oct, endpos);
1673  res = p_strtoi64(blanks, &endpos, 10);
1674  ok(res == 12, "res != 12\n");
1675  ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos);
1676  ok(errno == 0xdeadbeef, "errno = %x\n", errno);
1677 
1678  errno = 0xdeadbeef;
1679  res = p_strtoi64(overflow, &endpos, 10);
1680  ok(res == _I64_MAX, "res != _I64_MAX\n");
1681  ok(endpos == overflow+strlen(overflow), "Incorrect endpos (%p-%p)\n", overflow, endpos);
1682  ok(errno == ERANGE, "errno = %x\n", errno);
1683 
1684  errno = 0xdeadbeef;
1685  res = p_strtoi64(neg_overflow, &endpos, 10);
1686  ok(res == _I64_MIN, "res != _I64_MIN\n");
1687  ok(endpos == neg_overflow+strlen(neg_overflow), "Incorrect endpos (%p-%p)\n", neg_overflow, endpos);
1688  ok(errno == ERANGE, "errno = %x\n", errno);
1689 
1690  errno = 0xdeadbeef;
1691  res = p_strtoi64(no1, &endpos, 16);
1692  ok(res == 203043, "res != 203043\n");
1693  ok(endpos == no1+strlen(no1), "Incorrect endpos (%p-%p)\n", no1, endpos);
1694  res = p_strtoi64(no2, &endpos, 16);
1695  ok(res == -2175762, "res != -2175762\n");
1696  ok(endpos == no2+strlen(no2), "Incorrect endpos (%p-%p)\n", no2, endpos);
1697  res = p_strtoi64(no3, &endpos, 16);
1698  ok(res == 4778, "res != 4778\n");
1699  ok(endpos == no3+strlen(no3), "Incorrect endpos (%p-%p)\n", no3, endpos);
1700  res = p_strtoi64(no4, &endpos, 16);
1701  ok(res == 703506, "res != 703506\n");
1702  ok(endpos == no4+strlen(no4), "Incorrect endpos (%p-%p)\n", no4, endpos);
1703  res = p_strtoi64(hex, &endpos, 16);
1704  ok(res == 291, "res != 291\n");
1705  ok(endpos == hex+strlen(hex), "Incorrect endpos (%p-%p)\n", hex, endpos);
1706  res = p_strtoi64(oct, &endpos, 16);
1707  ok(res == 291, "res != 291\n");
1708  ok(endpos == oct+strlen(oct), "Incorrect endpos (%p-%p)\n", oct, endpos);
1709  res = p_strtoi64(blanks, &endpos, 16);
1710  ok(res == 18, "res != 18\n");
1711  ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos);
1712  ok(errno == 0xdeadbeef, "errno = %x\n", errno);
1713 
1714  errno = 0xdeadbeef;
1715  res = p_strtoi64(hex, &endpos, 36);
1716  ok(res == 1541019, "res != 1541019\n");
1717  ok(endpos == hex+strlen(hex), "Incorrect endpos (%p-%p)\n", hex, endpos);
1718  ok(errno == 0xdeadbeef, "errno = %x\n", errno);
1719 
1720  errno = 0xdeadbeef;
1721  res = p_strtoi64(no1, &endpos, 0);
1722  ok(res == 31923, "res != 31923\n");
1723  ok(endpos == no1+strlen(no1), "Incorrect endpos (%p-%p)\n", no1, endpos);
1724  res = p_strtoi64(no2, &endpos, 0);
1725  ok(res == -213312, "res != -213312\n");
1726  ok(endpos == no2+strlen(no2), "Incorrect endpos (%p-%p)\n", no2, endpos);
1727  res = p_strtoi64(no3, &endpos, 10);
1728  ok(res == 12, "res != 12\n");
1729  ok(endpos == no3+2, "Incorrect endpos (%p-%p)\n", no3, endpos);
1730  res = p_strtoi64(no4, &endpos, 10);
1731  ok(res == 0, "res != 0\n");
1732  ok(endpos == no4, "Incorrect endpos (%p-%p)\n", no4, endpos);
1733  res = p_strtoi64(hex, &endpos, 10);
1734  ok(res == 0, "res != 0\n");
1735  ok(endpos == hex+1, "Incorrect endpos (%p-%p)\n", hex, endpos);
1736  res = p_strtoi64(oct, &endpos, 10);
1737  ok(res == 123, "res != 123\n");
1738  ok(endpos == oct+strlen(oct), "Incorrect endpos (%p-%p)\n", oct, endpos);
1739  res = p_strtoi64(blanks, &endpos, 10);
1740  ok(res == 12, "res != 12\n");
1741  ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos);
1742  ok(errno == 0xdeadbeef, "errno = %x\n", errno);
1743 
1744  errno = 0xdeadbeef;
1745  ures = p_strtoui64(no1, &endpos, 0);
1746  ok(ures == 31923, "ures != 31923\n");
1747  ok(endpos == no1+strlen(no1), "Incorrect endpos (%p-%p)\n", no1, endpos);
1748  ures = p_strtoui64(no2, &endpos, 0);
1749  ok(ures == -213312, "ures != -213312\n");
1750  ok(endpos == no2+strlen(no2), "Incorrect endpos (%p-%p)\n", no2, endpos);
1751  ures = p_strtoui64(no3, &endpos, 10);
1752  ok(ures == 12, "ures != 12\n");
1753  ok(endpos == no3+2, "Incorrect endpos (%p-%p)\n", no3, endpos);
1754  ures = p_strtoui64(no4, &endpos, 10);
1755  ok(ures == 0, "ures != 0\n");
1756  ok(endpos == no4, "Incorrect endpos (%p-%p)\n", no4, endpos);
1757  ures = p_strtoui64(hex, &endpos, 10);
1758  ok(ures == 0, "ures != 0\n");
1759  ok(endpos == hex+1, "Incorrect endpos (%p-%p)\n", hex, endpos);
1760  ures = p_strtoui64(oct, &endpos, 10);
1761  ok(ures == 123, "ures != 123\n");
1762  ok(endpos == oct+strlen(oct), "Incorrect endpos (%p-%p)\n", oct, endpos);
1763  ures = p_strtoui64(blanks, &endpos, 10);
1764  ok(ures == 12, "ures != 12\n");
1765  ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos);
1766  ok(errno == 0xdeadbeef, "errno = %x\n", errno);
1767 
1768  errno = 0xdeadbeef;
1769  ures = p_strtoui64(overflow, &endpos, 10);
1770  ok(ures == _UI64_MAX, "ures != _UI64_MAX\n");
1771  ok(endpos == overflow+strlen(overflow), "Incorrect endpos (%p-%p)\n", overflow, endpos);
1772  ok(errno == ERANGE, "errno = %x\n", errno);
1773 
1774  errno = 0xdeadbeef;
1775  ures = p_strtoui64(neg_overflow, &endpos, 10);
1776  ok(ures == 1, "ures != 1\n");
1777  ok(endpos == neg_overflow+strlen(neg_overflow), "Incorrect endpos (%p-%p)\n", neg_overflow, endpos);
1778  ok(errno == ERANGE, "errno = %x\n", errno);
1779 }
1780 
1781 static inline BOOL almost_equal(double d1, double d2) {
1782  if(d1-d2>-1e-30 && d1-d2<1e-30)
1783  return TRUE;
1784  return FALSE;
1785 }
1786 
1787 static void test__strtod(void)
1788 {
1789  const char double1[] = "12.1";
1790  const char double2[] = "-13.721";
1791  const char double3[] = "INF";
1792  const char double4[] = ".21e12";
1793  const char double5[] = "214353e-3";
1794  const char double6[] = "NAN";
1795  const char overflow[] = "1d9999999999999999999";
1796  const char white_chars[] = " d10";
1797 
1798  char *end;
1799  double d;
1800 
1801  d = strtod(double1, &end);
1802  ok(almost_equal(d, 12.1), "d = %lf\n", d);
1803  ok(end == double1+4, "incorrect end (%d)\n", (int)(end-double1));
1804 
1805  d = strtod(double2, &end);
1806  ok(almost_equal(d, -13.721), "d = %lf\n", d);
1807  ok(end == double2+7, "incorrect end (%d)\n", (int)(end-double2));
1808 
1809  d = strtod(double3, &end);
1810  ok(almost_equal(d, 0), "d = %lf\n", d);
1811  ok(end == double3, "incorrect end (%d)\n", (int)(end-double3));
1812 
1813  d = strtod(double4, &end);
1814  ok(almost_equal(d, 210000000000.0), "d = %lf\n", d);
1815  ok(end == double4+6, "incorrect end (%d)\n", (int)(end-double4));
1816 
1817  d = strtod(double5, &end);
1818  ok(almost_equal(d, 214.353), "d = %lf\n", d);
1819  ok(end == double5+9, "incorrect end (%d)\n", (int)(end-double5));
1820 
1821  d = strtod(double6, &end);
1822  ok(almost_equal(d, 0), "d = %lf\n", d);
1823  ok(end == double6, "incorrect end (%d)\n", (int)(end-double6));
1824 
1825  d = strtod("12.1d2", NULL);
1826  ok(almost_equal(d, 12.1e2), "d = %lf\n", d);
1827 
1828  d = strtod(white_chars, &end);
1829  ok(almost_equal(d, 0), "d = %lf\n", d);
1830  ok(end == white_chars, "incorrect end (%d)\n", (int)(end-white_chars));
1831 
1832  if (!p__strtod_l)
1833  win_skip("_strtod_l not found\n");
1834  else
1835  {
1836  errno = EBADF;
1837  d = strtod(NULL, NULL);
1838  ok(almost_equal(d, 0.0), "d = %lf\n", d);
1839  ok(errno == EINVAL, "errno = %x\n", errno);
1840 
1841  errno = EBADF;
1842  end = (char *)0xdeadbeef;
1843  d = strtod(NULL, &end);
1844  ok(almost_equal(d, 0.0), "d = %lf\n", d);
1845  ok(errno == EINVAL, "errno = %x\n", errno);
1846  ok(!end, "incorrect end ptr %p\n", end);
1847 
1848  errno = EBADF;
1849  d = p__strtod_l(NULL, NULL, NULL);
1850  ok(almost_equal(d, 0.0), "d = %lf\n", d);
1851  ok(errno == EINVAL, "errno = %x\n", errno);
1852  }
1853 
1854  /* Set locale with non '.' decimal point (',') */
1855  if(!setlocale(LC_ALL, "Polish")) {
1856  win_skip("system with limited locales\n");
1857  return;
1858  }
1859 
1860  d = strtod("12.1", NULL);
1861  ok(almost_equal(d, 12.0), "d = %lf\n", d);
1862 
1863  d = strtod("12,1", NULL);
1864  ok(almost_equal(d, 12.1), "d = %lf\n", d);
1865 
1866  setlocale(LC_ALL, "C");
1867 
1868  /* Precision tests */
1869  d = strtod("0.1", NULL);
1870  ok(almost_equal(d, 0.1), "d = %lf\n", d);
1871  d = strtod("-0.1", NULL);
1872  ok(almost_equal(d, -0.1), "d = %lf\n", d);
1873  d = strtod("0.1281832188491894198128921", NULL);
1874  ok(almost_equal(d, 0.1281832188491894198128921), "d = %lf\n", d);
1875  d = strtod("0.82181281288121", NULL);
1876  ok(almost_equal(d, 0.82181281288121), "d = %lf\n", d);
1877  d = strtod("21921922352523587651128218821", NULL);
1878  ok(almost_equal(d, 21921922352523587651128218821.0), "d = %lf\n", d);
1879  d = strtod("0.1d238", NULL);
1880  ok(almost_equal(d, 0.1e238L), "d = %lf\n", d);
1881  d = strtod("0.1D-4736", NULL);
1882  ok(almost_equal(d, 0.1e-4736L), "d = %lf\n", d);
1883 
1884  errno = 0xdeadbeef;
1885  strtod(overflow, &end);
1886  ok(errno == ERANGE, "errno = %x\n", errno);
1887  ok(end == overflow+21, "incorrect end (%d)\n", (int)(end-overflow));
1888 
1889  errno = 0xdeadbeef;
1890  strtod("-1d309", NULL);
1891  ok(errno == ERANGE, "errno = %x\n", errno);
1892 }
1893 
1894 static void test_mbstowcs(void)
1895 {
1896  static const wchar_t wSimple[] = { 't','e','x','t',0 };
1897  static const wchar_t wHiragana[] = { 0x3042,0x3043,0 };
1898  static const wchar_t wEmpty[] = { 0 };
1899  static const char mSimple[] = "text";
1900  static const char mHiragana[] = { 0x82,0xa0,0x82,0xa1,0 };
1901  static const char mEmpty[] = { 0 };
1902 
1903  const wchar_t *pwstr;
1904  wchar_t wOut[6];
1905  char mOut[6];
1906  size_t ret;
1907  int err;
1908  const char *pmbstr;
1909  mbstate_t state;
1910 
1911  wOut[4] = '!'; wOut[5] = '\0';
1912  mOut[4] = '!'; mOut[5] = '\0';
1913 
1914  if(pmbstowcs_s) {
1915  /* crashes on some systems */
1916  errno = 0xdeadbeef;
1917  ret = mbstowcs(wOut, NULL, 4);
1918  ok(ret == -1, "mbstowcs did not return -1\n");
1919  ok(errno == EINVAL, "errno = %d\n", errno);
1920  }
1921 
1922  ret = mbstowcs(NULL, mSimple, 0);
1923  ok(ret == 4, "mbstowcs did not return 4\n");
1924 
1925  ret = mbstowcs(wOut, mSimple, 4);
1926  ok(ret == 4, "mbstowcs did not return 4\n");
1927  ok(!memcmp(wOut, wSimple, 4*sizeof(wchar_t)), "wOut = %s\n", wine_dbgstr_w(wOut));
1928  ok(wOut[4] == '!', "wOut[4] != \'!\'\n");
1929 
1930  ret = mbstowcs(NULL, mEmpty, 1);
1931  ok(ret == 0, "mbstowcs did not return 0, got %d\n", (int)ret);
1932 
1933  ret = mbstowcs(wOut, mEmpty, 1);
1934  ok(ret == 0, "mbstowcs did not return 0, got %d\n", (int)ret);
1935  ok(!memcmp(wOut, wEmpty, sizeof(wEmpty)), "wOut = %s\n", wine_dbgstr_w(wOut));
1936 
1937  ret = wcstombs(NULL, wSimple, 0);
1938  ok(ret == 4, "wcstombs did not return 4\n");
1939 
1940  ret = wcstombs(mOut, wSimple, 6);
1941  ok(ret == 4, "wcstombs did not return 4\n");
1942  ok(!memcmp(mOut, mSimple, 5*sizeof(char)), "mOut = %s\n", mOut);
1943 
1944  ret = wcstombs(mOut, wSimple, 2);
1945  ok(ret == 2, "wcstombs did not return 2\n");
1946  ok(!memcmp(mOut, mSimple, 5*sizeof(char)), "mOut = %s\n", mOut);
1947 
1948  ret = wcstombs(NULL, wEmpty, 1);
1949  ok(ret == 0, "wcstombs did not return 0, got %d\n", (int)ret);
1950 
1951  ret = wcstombs(mOut, wEmpty, 1);
1952  ok(ret == 0, "wcstombs did not return 0, got %d\n", (int)ret);
1953  ok(!memcmp(mOut, mEmpty, sizeof(mEmpty)), "mOut = %s\n", mOut);
1954 
1955  if(!setlocale(LC_ALL, "Japanese_Japan.932")) {
1956  win_skip("Japanese_Japan.932 locale not available\n");
1957  return;
1958  }
1959 
1960  ret = mbstowcs(wOut, mHiragana, 6);
1961  ok(ret == 2, "mbstowcs did not return 2\n");
1962  ok(!memcmp(wOut, wHiragana, sizeof(wHiragana)), "wOut = %s\n", wine_dbgstr_w(wOut));
1963 
1964  ret = mbstowcs(wOut, mEmpty, 6);
1965  ok(ret == 0, "mbstowcs did not return 0, got %d\n", (int)ret);
1966  ok(!memcmp(wOut, wEmpty, sizeof(wEmpty)), "wOut = %s\n", wine_dbgstr_w(wOut));
1967 
1968  ret = wcstombs(mOut, wHiragana, 6);
1969  ok(ret == 4, "wcstombs did not return 4\n");
1970  ok(!memcmp(mOut, mHiragana, sizeof(mHiragana)), "mOut = %s\n", mOut);
1971 
1972  ret = wcstombs(mOut, wEmpty, 6);
1973  ok(ret == 0, "wcstombs did not return 0, got %d\n", (int)ret);
1974  ok(!memcmp(mOut, mEmpty, sizeof(mEmpty)), "mOut = %s\n", mOut);
1975 
1976  if(!pmbstowcs_s || !pwcstombs_s) {
1977  setlocale(LC_ALL, "C");
1978  win_skip("mbstowcs_s or wcstombs_s not available\n");
1979  return;
1980  }
1981 
1982  err = pmbstowcs_s(&ret, wOut, 6, mSimple, _TRUNCATE);
1983  ok(err == 0, "err = %d\n", err);
1984  ok(ret == 5, "mbstowcs_s did not return 5\n");
1985  ok(!memcmp(wOut, wSimple, sizeof(wSimple)), "wOut = %s\n", wine_dbgstr_w(wOut));
1986 
1987  err = pmbstowcs_s(&ret, wOut, 6, mHiragana, _TRUNCATE);
1988  ok(err == 0, "err = %d\n", err);
1989  ok(ret == 3, "mbstowcs_s did not return 3\n");
1990  ok(!memcmp(wOut, wHiragana, sizeof(wHiragana)), "wOut = %s\n", wine_dbgstr_w(wOut));
1991 
1992  err = pmbstowcs_s(&ret, wOut, 6, mEmpty, _TRUNCATE);
1993  ok(err == 0, "err = %d\n", err);
1994  ok(ret == 1, "mbstowcs_s did not return 1, got %d\n", (int)ret);
1995  ok(!memcmp(wOut, wEmpty, sizeof(wEmpty)), "wOut = %s\n", wine_dbgstr_w(wOut));
1996 
1997  err = pmbstowcs_s(&ret, NULL, 0, mHiragana, 1);
1998  ok(err == 0, "err = %d\n", err);
1999  ok(ret == 3, "mbstowcs_s did not return 3\n");
2000 
2001  err = pwcstombs_s(&ret, mOut, 6, wSimple, _TRUNCATE);
2002  ok(err == 0, "err = %d\n", err);
2003  ok(ret == 5, "wcstombs_s did not return 5\n");
2004  ok(!memcmp(mOut, mSimple, sizeof(mSimple)), "mOut = %s\n", mOut);
2005 
2006  err = pwcstombs_s(&ret, mOut, 6, wHiragana, _TRUNCATE);
2007  ok(err == 0, "err = %d\n", err);
2008  ok(ret == 5, "wcstombs_s did not return 5\n");
2009  ok(!memcmp(mOut, mHiragana, sizeof(mHiragana)), "mOut = %s\n", mOut);
2010 
2011  err = pwcstombs_s(&ret, mOut, 6, wEmpty, _TRUNCATE);
2012  ok(err == 0, "err = %d\n", err);
2013  ok(ret == 1, "wcstombs_s did not return 1, got %d\n", (int)ret);
2014  ok(!memcmp(mOut, mEmpty, sizeof(mEmpty)), "mOut = %s\n", mOut);
2015 
2016  err = pwcstombs_s(&ret, NULL, 0, wHiragana, 1);
2017  ok(err == 0, "err = %d\n", err);
2018  ok(ret == 5, "wcstombs_s did not return 5\n");
2019 
2020  if(!pwcsrtombs) {
2021  setlocale(LC_ALL, "C");
2022  win_skip("wcsrtombs not available\n");
2023  return;
2024  }
2025 
2026  pwstr = wSimple;
2027  err = -3;
2028  ret = pwcsrtombs(mOut, &pwstr, 4, &err);
2029  ok(ret == 4, "wcsrtombs did not return 4\n");
2030  ok(err == 0, "err = %d\n", err);
2031  ok(pwstr == wSimple+4, "pwstr = %p (wszSimple = %p)\n", pwstr, wSimple);
2032  ok(!memcmp(mOut, mSimple, ret), "mOut = %s\n", mOut);
2033 
2034  pwstr = wSimple;
2035  ret = pwcsrtombs(mOut, &pwstr, 5, NULL);
2036  ok(ret == 4, "wcsrtombs did not return 4\n");
2037  ok(pwstr == NULL, "pwstr != NULL\n");
2038  ok(!memcmp(mOut, mSimple, sizeof(mSimple)), "mOut = %s\n", mOut);
2039 
2040  if(!p_mbsrtowcs) {
2041  setlocale(LC_ALL, "C");
2042  win_skip("mbsrtowcs not available\n");
2043  return;
2044  }
2045 
2046  pmbstr = mHiragana;
2047  ret = p_mbsrtowcs(NULL, &pmbstr, 6, NULL);
2048  ok(ret == 2, "mbsrtowcs did not return 2\n");
2049  ok(pmbstr == mHiragana, "pmbstr = %p, expected %p\n", pmbstr, mHiragana);
2050 
2051  pmbstr = mHiragana;
2052  ret = p_mbsrtowcs(wOut, &pmbstr, 6, NULL);
2053  ok(ret == 2, "mbsrtowcs did not return 2\n");
2054  ok(!memcmp(wOut, wHiragana, sizeof(wHiragana)), "wOut = %s\n", wine_dbgstr_w(wOut));
2055  ok(!pmbstr, "pmbstr != NULL\n");
2056 
2057  state = mHiragana[0];
2058  pmbstr = mHiragana+1;
2059  ret = p_mbsrtowcs(wOut, &pmbstr, 6, &state);
2060  ok(ret == 2, "mbsrtowcs did not return 2\n");
2061  ok(wOut[0] == 0x3042, "wOut[0] = %x\n", wOut[0]);
2062  ok(wOut[1] == 0xff61, "wOut[1] = %x\n", wOut[1]);
2063  ok(wOut[2] == 0, "wOut[2] = %x\n", wOut[2]);
2064  ok(!pmbstr, "pmbstr != NULL\n");
2065 
2066  errno = EBADF;
2067  ret = p_mbsrtowcs(wOut, NULL, 6, &state);
2068  ok(ret == -1, "mbsrtowcs did not return -1\n");
2069  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2070 
2071  if(!p_mbsrtowcs_s) {
2072  setlocale(LC_ALL, "C");
2073  win_skip("mbsrtowcs_s not available\n");
2074  return;
2075  }
2076 
2077  pmbstr = mHiragana;
2078  err = p_mbsrtowcs_s(&ret, NULL, 0, NULL, 6, NULL);
2079  ok(ret == -1, "mbsrtowcs_s did not return -1\n");
2080  ok(err == EINVAL, "err = %d\n", err);
2081  err = p_mbsrtowcs_s(&ret, NULL, 1, &pmbstr, 6, NULL);
2082  ok(ret == -1, "mbsrtowcs_s did not return -1\n");
2083  ok(err == EINVAL, "err = %d\n", err);
2084  err = p_mbsrtowcs_s(&ret, wOut, 0, &pmbstr, 6, NULL);
2085  ok(ret == -1, "mbsrtowcs_s did not return -1\n");
2086  ok(err == EINVAL, "err = %d\n", err);
2087 
2088  pmbstr = mHiragana;
2089  errno = 0;
2090  err = p_mbsrtowcs_s(&ret, NULL, 0, &pmbstr, 6, NULL);
2091  ok(ret == 3, "mbsrtowcs_s did not return 3\n");
2092  ok(err == 0, "err = %d\n", err);
2093  ok(pmbstr == mHiragana, "pmbstr = %p, expected %p\n", pmbstr, mHiragana);
2094  ok(errno == 0, "errno = %d\n", errno);
2095 
2096  pmbstr = mHiragana;
2097  err = p_mbsrtowcs_s(&ret, wOut, 1, &pmbstr, 6, NULL);
2098  ok(ret == 2, "mbsrtowcs_s did not return 2\n");
2099  ok(err == 0, "err = %d\n", err);
2100  ok(!wOut[0], "wOut[0] = '%c'\n", wOut[0]);
2101  ok(pmbstr == mHiragana+2, "pmbstr = %p, expected %p\n", pmbstr, mHiragana+2);
2102  ok(errno == 0, "errno = %d\n", errno);
2103 
2104  pmbstr = mHiragana;
2105  err = p_mbsrtowcs_s(&ret, wOut, 2, &pmbstr, 6, NULL);
2106  ok(ret == 3, "mbsrtowcs_s did not return 3\n");
2107  ok(err == 0, "err = %d\n", err);
2108  ok(!wOut[0], "wOut[0] = '%c'\n", wOut[0]);
2109  ok(pmbstr == mHiragana+4, "pmbstr = %p, expected %p\n", pmbstr, mHiragana+4);
2110  ok(errno == 0, "errno = %d\n", errno);
2111 
2112  pmbstr = mHiragana;
2113  err = p_mbsrtowcs_s(&ret, wOut, 3, &pmbstr, 6, NULL);
2114  ok(ret == 3, "mbsrtowcs_s did not return 3\n");
2115  ok(err == 0, "err = %d\n", err);
2116  ok(!pmbstr, "pmbstr != NULL\n");
2117  ok(errno == 0, "errno = %d\n", errno);
2118 
2119  setlocale(LC_ALL, "C");
2120 }
2121 
2122 static void test_gcvt(void)
2123 {
2124  char buf[1024], *res;
2125  errno_t err;
2126 
2127  if(!p_gcvt_s) {
2128  win_skip("Skipping _gcvt tests\n");
2129  return;
2130  }
2131 
2132  errno = 0;
2133  res = _gcvt(1.2, -1, buf);
2134  ok(res == NULL, "res != NULL\n");
2135  ok(errno == ERANGE, "errno = %d\n", errno);
2136 
2137  errno = 0;
2138  res = _gcvt(1.2, 5, NULL);
2139  ok(res == NULL, "res != NULL\n");
2140  ok(errno == EINVAL, "errno = %d\n", errno);
2141 
2142  res = gcvt(1.2, 5, buf);
2143  ok(res == buf, "res != buf\n");
2144  ok(!strcmp(buf, "1.2"), "buf = %s\n", buf);
2145 
2146  buf[0] = 'x';
2147  err = p_gcvt_s(buf, 5, 1.2, 10);
2148  ok(err == ERANGE, "err = %d\n", err);
2149  ok(buf[0] == '\0', "buf[0] = %c\n", buf[0]);
2150 
2151  buf[0] = 'x';
2152  err = p_gcvt_s(buf, 4, 123456, 2);
2153  ok(err == ERANGE, "err = %d\n", err);
2154  ok(buf[0] == '\0', "buf[0] = %c\n", buf[0]);
2155 }
2156 
2157 static void test__itoa_s(void)
2158 {
2159  errno_t ret;
2160  char buffer[33];
2161 
2162  if (!p_itoa_s)
2163  {
2164  win_skip("Skipping _itoa_s tests\n");
2165  return;
2166  }
2167 
2168  errno = EBADF;
2169  ret = p_itoa_s(0, NULL, 0, 0);
2170  ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
2171  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2172 
2173  memset(buffer, 'X', sizeof(buffer));
2174  errno = EBADF;
2175  ret = p_itoa_s(0, buffer, 0, 0);
2176  ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
2177  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2178  ok(buffer[0] == 'X', "Expected the output buffer to be untouched\n");
2179 
2180  memset(buffer, 'X', sizeof(buffer));
2181  errno = EBADF;
2182  ret = p_itoa_s(0, buffer, sizeof(buffer), 0);
2183  ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
2184  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2185  ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
2186 
2187  memset(buffer, 'X', sizeof(buffer));
2188  errno = EBADF;
2189  ret = p_itoa_s(0, buffer, sizeof(buffer), 64);
2190  ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
2191  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2192  ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
2193 
2194  memset(buffer, 'X', sizeof(buffer));
2195  errno = EBADF;
2196  ret = p_itoa_s(12345678, buffer, 4, 10);
2197  ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
2198  ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
2199  ok(!memcmp(buffer, "\000765", 4),
2200  "Expected the output buffer to be null terminated with truncated output\n");
2201 
2202  memset(buffer, 'X', sizeof(buffer));
2203  errno = EBADF;
2204  ret = p_itoa_s(12345678, buffer, 8, 10);
2205  ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
2206  ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
2207  ok(!memcmp(buffer, "\0007654321", 8),
2208  "Expected the output buffer to be null terminated with truncated output\n");
2209 
2210  memset(buffer, 'X', sizeof(buffer));
2211  errno = EBADF;
2212  ret = p_itoa_s(-12345678, buffer, 9, 10);
2213  ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
2214  ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
2215  ok(!memcmp(buffer, "\00087654321", 9),
2216  "Expected the output buffer to be null terminated with truncated output\n");
2217 
2218  ret = p_itoa_s(12345678, buffer, 9, 10);
2219  ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
2220  ok(!strcmp(buffer, "12345678"),
2221  "Expected output buffer string to be \"12345678\", got \"%s\"\n",
2222  buffer);
2223 
2224  ret = p_itoa_s(43690, buffer, sizeof(buffer), 2);
2225  ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
2226  ok(!strcmp(buffer, "1010101010101010"),
2227  "Expected output buffer string to be \"1010101010101010\", got \"%s\"\n",
2228  buffer);
2229 
2230  ret = p_itoa_s(1092009, buffer, sizeof(buffer), 36);
2231  ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
2232  ok(!strcmp(buffer, "nell"),
2233  "Expected output buffer string to be \"nell\", got \"%s\"\n",
2234  buffer);
2235 
2236  ret = p_itoa_s(5704, buffer, sizeof(buffer), 18);
2237  ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
2238  ok(!strcmp(buffer, "hag"),
2239  "Expected output buffer string to be \"hag\", got \"%s\"\n",
2240  buffer);
2241 
2242  ret = p_itoa_s(-12345678, buffer, sizeof(buffer), 10);
2243  ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
2244  ok(!strcmp(buffer, "-12345678"),
2245  "Expected output buffer string to be \"-12345678\", got \"%s\"\n",
2246  buffer);
2247 
2248  itoa(100, buffer, 100);
2249  ok(!strcmp(buffer, "10"),
2250  "Expected output buffer string to be \"10\", got \"%s\"\n", buffer);
2251 }
2252 
2253 static void test__strlwr_s(void)
2254 {
2255  errno_t ret;
2256  char buffer[20];
2257 
2258  if (!p_strlwr_s)
2259  {
2260  win_skip("Skipping _strlwr_s tests\n");
2261  return;
2262  }
2263 
2264  errno = EBADF;
2265  ret = p_strlwr_s(NULL, 0);
2266  ok(ret == EINVAL, "Expected _strlwr_s to return EINVAL, got %d\n", ret);
2267  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2268 
2269  errno = EBADF;
2270  ret = p_strlwr_s(NULL, sizeof(buffer));
2271  ok(ret == EINVAL, "Expected _strlwr_s to return EINVAL, got %d\n", ret);
2272  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2273 
2274  errno = EBADF;
2275  ret = p_strlwr_s(buffer, 0);
2276  ok(ret == EINVAL, "Expected _strlwr_s to return EINVAL, got %d\n", ret);
2277  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2278 
2279  strcpy(buffer, "GoRrIsTeR");
2280  errno = EBADF;
2281  ret = p_strlwr_s(buffer, 5);
2282  ok(ret == EINVAL, "Expected _strlwr_s to return EINVAL, got %d\n", ret);
2283  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2284  ok(!memcmp(buffer, "\0oRrIsTeR", sizeof("\0oRrIsTeR")),
2285  "Expected the output buffer to be \"\\0oRrIsTeR\"\n");
2286 
2287  strcpy(buffer, "GoRrIsTeR");
2288  errno = EBADF;
2289  ret = p_strlwr_s(buffer, sizeof("GoRrIsTeR") - 1);
2290  ok(ret == EINVAL, "Expected _strlwr_s to return EINVAL, got %d\n", ret);
2291  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2292  ok(!memcmp(buffer, "\0oRrIsTeR", sizeof("\0oRrIsTeR")),
2293  "Expected the output buffer to be \"\\0oRrIsTeR\"\n");
2294 
2295  strcpy(buffer, "GoRrIsTeR");
2296  ret = p_strlwr_s(buffer, sizeof("GoRrIsTeR"));
2297  ok(ret == 0, "Expected _strlwr_s to return 0, got %d\n", ret);
2298  ok(!strcmp(buffer, "gorrister"),
2299  "Expected the output buffer to be \"gorrister\", got \"%s\"\n",
2300  buffer);
2301 
2302  memcpy(buffer, "GoRrIsTeR\0ELLEN", sizeof("GoRrIsTeR\0ELLEN"));
2303  ret = p_strlwr_s(buffer, sizeof(buffer));
2304  ok(ret == 0, "Expected _strlwr_s to return 0, got %d\n", ret);
2305  ok(!memcmp(buffer, "gorrister\0ELLEN", sizeof("gorrister\0ELLEN")),
2306  "Expected the output buffer to be \"gorrister\\0ELLEN\", got \"%s\"\n",
2307  buffer);
2308 }
2309 
2310 static void test_wcsncat_s(void)
2311 {
2312  static wchar_t abcW[] = {'a','b','c',0};
2313  int ret;
2314  wchar_t dst[4];
2315  wchar_t src[4];
2316 
2317  if (!p_wcsncat_s)
2318  {
2319  win_skip("skipping wcsncat_s tests\n");
2320  return;
2321  }
2322 
2323  memcpy(src, abcW, sizeof(abcW));
2324  dst[0] = 0;
2325  ret = p_wcsncat_s(NULL, 4, src, 4);
2326  ok(ret == EINVAL, "err = %d\n", ret);
2327  ret = p_wcsncat_s(dst, 0, src, 4);
2328  ok(ret == EINVAL, "err = %d\n", ret);
2329  ret = p_wcsncat_s(dst, 0, src, _TRUNCATE);
2330  ok(ret == EINVAL, "err = %d\n", ret);
2331  ret = p_wcsncat_s(dst, 4, NULL, 0);
2332  ok(ret == 0, "err = %d\n", ret);
2333 
2334  dst[0] = 0;
2335  ret = p_wcsncat_s(dst, 2, src, 4);
2336  ok(ret == ERANGE, "err = %d\n", ret);
2337 
2338  dst[0] = 0;
2339  ret = p_wcsncat_s(dst, 2, src, _TRUNCATE);
2340  ok(ret == STRUNCATE, "err = %d\n", ret);
2341  ok(dst[0] == 'a' && dst[1] == 0, "dst is %s\n", wine_dbgstr_w(dst));
2342 
2343  memcpy(dst, abcW, sizeof(abcW));
2344  dst[3] = 'd';
2345  ret = p_wcsncat_s(dst, 4, src, 4);
2346  ok(ret == EINVAL, "err = %d\n", ret);
2347 }
2348 
2349 static void test__mbsnbcat_s(void)
2350 {
2351  unsigned char dest[16];
2352  const unsigned char first[] = "dinosaur";
2353  const unsigned char second[] = "duck";
2354  int ret;
2355 
2356  if (!p_mbsnbcat_s)
2357  {
2358  win_skip("Skipping _mbsnbcat_s tests\n");
2359  return;
2360  }
2361 
2362  /* Test invalid arguments. */
2363  ret = p_mbsnbcat_s(NULL, 0, NULL, 0);
2364  ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
2365 
2366  errno = EBADF;
2367  ret = p_mbsnbcat_s(NULL, 10, NULL, 0);
2368  ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
2369  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2370 
2371  errno = EBADF;
2372  ret = p_mbsnbcat_s(NULL, 0, NULL, 10);
2373  ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
2374  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2375 
2376  memset(dest, 'X', sizeof(dest));
2377  errno = EBADF;
2378  ret = p_mbsnbcat_s(dest, 0, NULL, 0);
2379  ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
2380  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2381  ok(dest[0] == 'X', "Expected the output buffer to be untouched\n");
2382 
2383  memset(dest, 'X', sizeof(dest));
2384  errno = EBADF;
2385  ret = p_mbsnbcat_s(dest, 0, second, 0);
2386  ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
2387  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2388  ok(dest[0] == 'X', "Expected the output buffer to be untouched\n");
2389 
2390  memset(dest, 'X', sizeof(dest));
2391  errno = EBADF;
2392  ret = p_mbsnbcat_s(dest, sizeof(dest), NULL, 0);
2393  ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
2394  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2395  ok(dest[0] == '\0', "Expected the output buffer to be null terminated\n");
2396 
2397  memset(dest, 'X', sizeof(dest));
2398  errno = EBADF;
2399  ret = p_mbsnbcat_s(dest, sizeof(dest), NULL, 10);
2400  ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
2401  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2402  ok(dest[0] == '\0', "Expected the output buffer to be null terminated\n");
2403 
2404  memset(dest, 'X', sizeof(dest));
2405  dest[0] = '\0';
2406  ret = p_mbsnbcat_s(dest, sizeof(dest), second, sizeof(second));
2407  ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
2408  ok(!memcmp(dest, second, sizeof(second)),
2409  "Expected the output buffer string to be \"duck\"\n");
2410 
2411  /* Test source truncation behavior. */
2412  memset(dest, 'X', sizeof(dest));
2413  memcpy(dest, first, sizeof(first));
2414  ret = p_mbsnbcat_s(dest, sizeof(dest), second, 0);
2415  ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
2416  ok(!memcmp(dest, first, sizeof(first)),
2417  "Expected the output buffer string to be \"dinosaur\"\n");
2418 
2419  memset(dest, 'X', sizeof(dest));
2420  memcpy(dest, first, sizeof(first));
2421  ret = p_mbsnbcat_s(dest, sizeof(dest), second, sizeof(second));
2422  ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
2423  ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
2424  "Expected the output buffer string to be \"dinosaurduck\"\n");
2425 
2426  memset(dest, 'X', sizeof(dest));
2427  memcpy(dest, first, sizeof(first));
2428  ret = p_mbsnbcat_s(dest, sizeof(dest), second, sizeof(second) + 1);
2429  ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
2430  ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
2431  "Expected the output buffer string to be \"dinosaurduck\"\n");
2432 
2433  memset(dest, 'X', sizeof(dest));
2434  memcpy(dest, first, sizeof(first));
2435  ret = p_mbsnbcat_s(dest, sizeof(dest), second, sizeof(second) - 1);
2436  ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
2437  ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
2438  "Expected the output buffer string to be \"dinosaurduck\"\n");
2439 
2440  memset(dest, 'X', sizeof(dest));
2441  memcpy(dest, first, sizeof(first));
2442  ret = p_mbsnbcat_s(dest, sizeof(dest), second, sizeof(second) - 2);
2443  ok(ret == 0, "Expected _mbsnbcat_s to return 0, got %d\n", ret);
2444  ok(!memcmp(dest, "dinosaurduc", sizeof("dinosaurduc")),
2445  "Expected the output buffer string to be \"dinosaurduc\"\n");
2446 
2447  /* Test destination truncation behavior. */
2448  memset(dest, 'X', sizeof(dest));
2449  memcpy(dest, first, sizeof(first));
2450  errno = EBADF;
2451  ret = p_mbsnbcat_s(dest, sizeof(first) - 1, second, sizeof(second));
2452  ok(ret == EINVAL, "Expected _mbsnbcat_s to return EINVAL, got %d\n", ret);
2453  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2454  ok(!memcmp(dest, "\0inosaur", sizeof("\0inosaur") - 1),
2455  "Expected the output buffer string to be \"\\0inosaur\" without ending null terminator\n");
2456 
2457  memset(dest, 'X', sizeof(dest));
2458  memcpy(dest, first, sizeof(first));
2459  errno = EBADF;
2460  ret = p_mbsnbcat_s(dest, sizeof(first), second, sizeof(second));
2461  ok(ret == ERANGE, "Expected _mbsnbcat_s to return ERANGE, got %d\n", ret);
2462  ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
2463  ok(!memcmp(dest, "\0inosaurd", sizeof("\0inosaurd") - 1),
2464  "Expected the output buffer string to be \"\\0inosaurd\" without ending null terminator\n");
2465 
2466  memset(dest, 'X', sizeof(dest));
2467  memcpy(dest, first, sizeof(first));
2468  errno = EBADF;
2469  ret = p_mbsnbcat_s(dest, sizeof(first) + 1, second, sizeof(second));
2470  ok(ret == ERANGE, "Expected _mbsnbcat_s to return ERANGE, got %d\n", ret);
2471  ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
2472  ok(!memcmp(dest, "\0inosaurdu", sizeof("\0inosaurdu") - 1),
2473  "Expected the output buffer string to be \"\\0inosaurdu\" without ending null terminator\n");
2474 }
2475 
2476 static void test__mbsupr_s(void)
2477 {
2478  errno_t ret;
2479  unsigned char buffer[20];
2480 
2481  if (!p_mbsupr_s)
2482  {
2483  win_skip("Skipping _mbsupr_s tests\n");
2484  return;
2485  }
2486 
2487  errno = EBADF;
2488  ret = p_mbsupr_s(NULL, 0);
2489  ok(ret == 0, "Expected _mbsupr_s to return 0, got %d\n", ret);
2490 
2491  errno = EBADF;
2492  ret = p_mbsupr_s(NULL, sizeof(buffer));
2493  ok(ret == EINVAL, "Expected _mbsupr_s to return EINVAL, got %d\n", ret);
2494  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2495 
2496  errno = EBADF;
2497  ret = p_mbsupr_s(buffer, 0);
2498  ok(ret == EINVAL, "Expected _mbsupr_s to return EINVAL, got %d\n", ret);
2499  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2500 
2501  memcpy(buffer, "abcdefgh", sizeof("abcdefgh"));
2502  errno = EBADF;
2503  ret = p_mbsupr_s(buffer, sizeof("abcdefgh"));
2504  ok(ret == 0, "Expected _mbsupr_s to return 0, got %d\n", ret);
2505  ok(!memcmp(buffer, "ABCDEFGH", sizeof("ABCDEFGH")),
2506  "Expected the output buffer to be \"ABCDEFGH\", got \"%s\"\n",
2507  buffer);
2508 
2509  memcpy(buffer, "abcdefgh", sizeof("abcdefgh"));
2510  errno = EBADF;
2511  ret = p_mbsupr_s(buffer, sizeof(buffer));
2512  ok(ret == 0, "Expected _mbsupr_s to return 0, got %d\n", ret);
2513  ok(!memcmp(buffer, "ABCDEFGH", sizeof("ABCDEFGH")),
2514  "Expected the output buffer to be \"ABCDEFGH\", got \"%s\"\n",
2515  buffer);
2516 
2517  memcpy(buffer, "abcdefgh", sizeof("abcdefgh"));
2518  errno = EBADF;
2519  ret = p_mbsupr_s(buffer, 4);
2520  ok(ret == EINVAL, "Expected _mbsupr_s to return EINVAL, got %d\n", ret);
2521  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2522 
2523  memcpy(buffer, "abcdefgh\0ijklmnop", sizeof("abcdefgh\0ijklmnop"));
2524  errno = EBADF;
2525  ret = p_mbsupr_s(buffer, sizeof(buffer));
2526  ok(ret == 0, "Expected _mbsupr_s to return 0, got %d\n", ret);
2527  ok(!memcmp(buffer, "ABCDEFGH\0ijklmnop", sizeof("ABCDEFGH\0ijklmnop")),
2528  "Expected the output buffer to be \"ABCDEFGH\\0ijklmnop\", got \"%s\"\n",
2529  buffer);
2530 
2531 }
2532 
2533 static void test__mbslwr_s(void)
2534 {
2535  errno_t ret;
2536  unsigned char buffer[20];
2537 
2538  if (!p_mbslwr_s)
2539  {
2540  win_skip("Skipping _mbslwr_s tests\n");
2541  return;
2542  }
2543 
2544  errno = EBADF;
2545  ret = p_mbslwr_s(NULL, 0);
2546  ok(ret == 0, "Expected _mbslwr_s to return 0, got %d\n", ret);
2547 
2548  errno = EBADF;
2549  ret = p_mbslwr_s(NULL, sizeof(buffer));
2550  ok(ret == EINVAL, "Expected _mbslwr_s to return EINVAL, got %d\n", ret);
2551  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2552 
2553  errno = EBADF;
2554  ret = p_mbslwr_s(buffer, 0);
2555  ok(ret == EINVAL, "Expected _mbslwr_s to return EINVAL, got %d\n", ret);
2556  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2557 
2558  memcpy(buffer, "ABCDEFGH", sizeof("ABCDEFGH"));
2559  errno = EBADF;
2560  ret = p_mbslwr_s(buffer, sizeof("ABCDEFGH"));
2561  ok(ret == 0, "Expected _mbslwr_s to return 0, got %d\n", ret);
2562  ok(!memcmp(buffer, "abcdefgh", sizeof("abcdefgh")),
2563  "Expected the output buffer to be \"abcdefgh\", got \"%s\"\n",
2564  buffer);
2565 
2566  memcpy(buffer, "ABCDEFGH", sizeof("ABCDEFGH"));
2567  errno = EBADF;
2568  ret = p_mbslwr_s(buffer, sizeof(buffer));
2569  ok(ret == 0, "Expected _mbslwr_s to return 0, got %d\n", ret);
2570  ok(!memcmp(buffer, "abcdefgh", sizeof("abcdefgh")),
2571  "Expected the output buffer to be \"abcdefgh\", got \"%s\"\n",
2572  buffer);
2573 
2574  memcpy(buffer, "ABCDEFGH", sizeof("ABCDEFGH"));
2575  errno = EBADF;
2576  ret = p_mbslwr_s(buffer, 4);
2577  ok(ret == EINVAL, "Expected _mbslwr_s to return EINVAL, got %d\n", ret);
2578  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2579 
2580  memcpy(buffer, "ABCDEFGH\0IJKLMNOP", sizeof("ABCDEFGH\0IJKLMNOP"));
2581  errno = EBADF;
2582  ret = p_mbslwr_s(buffer, sizeof(buffer));
2583  ok(ret == 0, "Expected _mbslwr_s to return 0, got %d\n", ret);
2584  ok(!memcmp(buffer, "abcdefgh\0IJKLMNOP", sizeof("abcdefgh\0IJKLMNOP")),
2585  "Expected the output buffer to be \"abcdefgh\\0IJKLMNOP\", got \"%s\"\n",
2586  buffer);
2587 }
2588 
2589 static void test__mbstok(void)
2590 {
2591  const unsigned char delim[] = "t";
2592 
2593  char str[] = "!.!test";
2594  unsigned char *ret;
2595 
2596  strtok(str, "!");
2597 
2598  ret = _mbstok(NULL, delim);
2599  /* most versions of msvcrt use the same buffer for strtok and _mbstok */
2600  ok(!ret || broken((char*)ret==str+4),
2601  "_mbstok(NULL, \"t\") = %p, expected NULL (%p)\n", ret, str);
2602 
2603  ret = _mbstok(NULL, delim);
2604  ok(!ret, "_mbstok(NULL, \"t\") = %p, expected NULL\n", ret);
2605 }
2606 
2607 static void test__ultoa_s(void)
2608 {
2609  errno_t ret;
2610  char buffer[33];
2611 
2612  if (!p_ultoa_s)
2613  {
2614  win_skip("Skipping _ultoa_s tests\n");
2615  return;
2616  }
2617 
2618  errno = EBADF;
2619  ret = p_ultoa_s(0, NULL, 0, 0);
2620  ok(ret == EINVAL, "Expected _ultoa_s to return EINVAL, got %d\n", ret);
2621  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2622 
2623  memset(buffer, 'X', sizeof(buffer));
2624  errno = EBADF;
2625  ret = p_ultoa_s(0, buffer, 0, 0);
2626  ok(ret == EINVAL, "Expected _ultoa_s to return EINVAL, got %d\n", ret);
2627  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2628  ok(buffer[0] == 'X', "Expected the output buffer to be untouched\n");
2629 
2630  memset(buffer, 'X', sizeof(buffer));
2631  errno = EBADF;
2632  ret = p_ultoa_s(0, buffer, sizeof(buffer), 0);
2633  ok(ret == EINVAL, "Expected _ultoa_s to return EINVAL, got %d\n", ret);
2634  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2635  ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
2636 
2637  memset(buffer, 'X', sizeof(buffer));
2638  errno = EBADF;
2639  ret = p_ultoa_s(0, buffer, sizeof(buffer), 64);
2640  ok(ret == EINVAL, "Expected _ultoa_s to return EINVAL, got %d\n", ret);
2641  ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
2642  ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
2643 
2644  memset(buffer, 'X', sizeof(buffer));
2645  errno = EBADF;
2646  ret = p_ultoa_s(12345678, buffer, 4, 10);
2647  ok(ret == ERANGE, "Expected _ultoa_s to return ERANGE, got %d\n", ret);
2648  ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
2649  ok(!memcmp(buffer, "\000765", 4),
2650  "Expected the output buffer to be null terminated with truncated output\n");
2651 
2652  memset(buffer, 'X', sizeof(buffer));
2653  errno = EBADF;
2654  ret = p_ultoa_s(12345678, buffer, 8, 10);
2655  ok(ret == ERANGE, "Expected _ultoa_s to return ERANGE, got %d\n", ret);
2656  ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
2657  ok(!memcmp(buffer, "\0007654321", 8),
2658  "Expected the output buffer to be null terminated with truncated output\n");
2659 
2660  ret = p_ultoa_s(12345678, buffer, 9, 10);
2661  ok(ret == 0, "Expected _ultoa_s to return 0, got %d\n", ret);
2662  ok(!strcmp(buffer, "12345678"),
2663  "Expected output buffer string to be \"12345678\", got \"%s\"\n",
2664  buffer);
2665 
2666  ret = p_ultoa_s(43690, buffer, sizeof(buffer), 2);
2667  ok(ret == 0, "Expected _ultoa_s to return 0, got %d\n", ret);
2668  ok(!strcmp(buffer, "1010101010101010"),
2669  "Expected output buffer string to be \"1010101010101010\", got \"%s\"\n",
2670  buffer);
2671 
2672  ret = p_ultoa_s(1092009, buffer, sizeof(buffer), 36);
2673  ok(ret == 0, "Expected _ultoa_s to return 0, got %d\n", ret);
2674  ok(!strcmp(buffer, "nell"),
2675  "Expected output buffer string to be \"nell\", got \"%s\"\n",
2676  buffer);
2677 
2678  ret = p_ultoa_s(5704, buffer, sizeof(buffer), 18);
2679  ok(ret == 0, "Expected _ultoa_s to return 0, got %d\n", ret);
2680  ok(!strcmp(buffer, "hag"),
2681  "Expected output buffer string to be \"hag\", got \"%s\"\n",
2682  buffer);
2683 }
2684 
2685 static void test_wctob(void)
2686 {
2687  int ret;
2688 
2689  if(!p_wctob || !setlocale(LC_ALL, "chinese-traditional")) {
2690  win_skip("Skipping wctob tests\n");
2691  return;
2692  }
2693 
2694  ret = p_wctob(0x8141);
2695  ok(ret == EOF, "ret = %x\n", ret);
2696 
2697  ret = p_wctob(0x81);
2698  ok(ret == EOF, "ret = %x\n", ret);
2699 
2700  ret = p_wctob(0xe0);
2701  ok(ret == 0x61, "ret = %x\n", ret);
2702 
2703  _setmbcp(1250);
2704  ret = p_wctob(0x81);
2705  ok(ret == EOF, "ret = %x\n", ret);
2706 
2707  setlocale(LC_ALL, "C");
2708  ret = p_wctob(0x8141);
2709  ok(ret == EOF, "ret = %x\n", ret);
2710 
2711  ret = p_wctob(0x81);
2712  ok(ret == (int)(char)0x81, "ret = %x\n", ret);
2713 
2714  ret = p_wctob(0x9f);
2715  ok(ret == (int)(char)0x9f, "ret = %x\n", ret);
2716 
2717  ret = p_wctob(0xe0);
2718  ok(ret == (int)(char)0xe0, "ret = %x\n", ret);
2719 }
2720 static void test_wctomb(void)
2721 {
2722  mbstate_t state;
2723  unsigned char dst[10];
2724  size_t ret;
2725 
2726  if(!p_wcrtomb || !setlocale(LC_ALL, "Japanese_Japan.932")) {
2727  win_skip("wcrtomb tests\n");
2728  return;
2729  }
2730 
2731  ret = p_wcrtomb(NULL, 0x3042, NULL);
2732  ok(ret == 2, "wcrtomb did not return 2\n");
2733 
2734  state = 1;
2735  dst[2] = 'a';
2736  ret = p_wcrtomb((char*)dst, 0x3042, &state);
2737  ok(ret == 2, "wcrtomb did not return 2\n");
2738  ok(state == 0, "state != 0\n");
2739  ok(dst[0] == 0x82, "dst[0] = %x, expected 0x82\n", dst[0]);
2740  ok(dst[1] == 0xa0, "dst[1] = %x, expected 0xa0\n", dst[1]);
2741  ok(dst[2] == 'a', "dst[2] != 'a'\n");
2742 
2743  ret = p_wcrtomb((char*)dst, 0x3043, NULL);
2744  ok(ret == 2, "wcrtomb did not return 2\n");
2745  ok(dst[0] == 0x82, "dst[0] = %x, expected 0x82\n", dst[0]);
2746  ok(dst[1] == 0xa1, "dst[1] = %x, expected 0xa1\n", dst[1]);
2747 
2748  ret = p_wcrtomb((char*)dst, 0x20, NULL);
2749  ok(ret == 1, "wcrtomb did not return 1\n");
2750  ok(dst[0] == 0x20, "dst[0] = %x, expected 0x20\n", dst[0]);
2751 
2752  ret = p_wcrtomb((char*)dst, 0xffff, NULL);
2753  ok(ret == -1, "wcrtomb did not return -1\n");
2754  ok(dst[0] == 0x3f, "dst[0] = %x, expected 0x3f\n", dst[0]);
2755 
2756  setlocale(LC_ALL, "C");
2757 }
2758 
2759 static void test_tolower(void)
2760 {
2761  WCHAR chw, lower;
2762  char ch, lch;
2763  int ret, len;
2764 
2765  /* test C locale when locale was never changed */
2766  ret = p_tolower(0x41);
2767  ok(ret == 0x61, "ret = %x\n", ret);
2768 
2769  ret = p_tolower(0xF4);
2770  ok(ret == 0xF4, "ret = %x\n", ret);
2771 
2772  errno = 0xdeadbeef;
2773  ret = p_tolower((char)0xF4);
2774  todo_wine ok(ret == (char)0xF4, "ret = %x\n", ret);
2775  todo_wine ok(errno == 0xdeadbeef, "errno = %d\n", errno);
2776 
2777  errno = 0xdeadbeef;
2778  ret = p_tolower((char)0xD0);
2779  todo_wine ok(ret == (char)0xD0, "ret = %x\n", ret);
2780  todo_wine ok(errno == 0xdeadbeef, "errno = %d\n", errno);
2781 
2782  /* test C locale after setting locale */
2783  if(!setlocale(LC_ALL, "us")) {
2784  win_skip("skipping tolower tests that depends on locale\n");
2785  return;
2786  }
2787  setlocale(LC_ALL, "C");
2788 
2789  ch = 0xF4;
2790  errno = 0xdeadbeef;
2791  ret = p_tolower(ch);
2792  if(!MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, &ch, 1, &chw, 1) ||
2793  LCMapStringW(CP_ACP, LCMAP_LOWERCASE, &chw, 1, &lower, 1) != 1 ||
2794  (len = WideCharToMultiByte(CP_ACP, 0, &lower, 1, &lch, 1, NULL, NULL)) != 1)
2795  len = 0;
2796  if(len)
2797  ok(ret==(unsigned char)lch || broken(ret==ch)/*WinXP-*/, "ret = %x\n", ret);
2798  else
2799  ok(ret == ch, "ret = %x\n", ret);
2800  if(!len || ret==(unsigned char)lch)
2801  ok(errno == EILSEQ, "errno = %d\n", errno);
2802 
2803  ch = 0xD0;
2804  errno = 0xdeadbeef;
2805  ret = p_tolower(ch);
2806  if(!MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, &ch, 1, &chw, 1) ||
2807  LCMapStringW(CP_ACP, LCMAP_LOWERCASE, &chw, 1, &lower, 1) != 1 ||
2808  (len = WideCharToMultiByte(CP_ACP, 0, &lower, 1, &lch, 1, NULL, NULL)) != 1)
2809  len = 0;
2810  if(len)
2811  ok(ret==(unsigned char)lch || broken(ret==ch)/*WinXP-*/, "ret = %x\n", ret);
2812  else
2813  ok(ret == ch, "ret = %x\n", ret);
2814  if(!len || ret==(unsigned char)lch)
2815  ok(errno == EILSEQ, "errno = %d\n", errno);
2816 
2817  ret = p_tolower(0xD0);
2818  ok(ret == 0xD0, "ret = %x\n", ret);
2819 
2820  ok(setlocale(LC_ALL, "us") != NULL, "setlocale failed\n");
2821 
2822  ret = p_tolower((char)0xD0);
2823  ok(ret == 0xF0, "ret = %x\n", ret);
2824 
2825  ret = p_tolower(0xD0);
2826  ok(ret == 0xF0, "ret = %x\n", ret);
2827 
2828  setlocale(LC_ALL, "C");
2829 }
2830 
2831 static void test__atodbl(void)
2832 {
2833  _CRT_DOUBLE d;
2834  char num[32];
2835  int ret;
2836 
2837  if(!p__atodbl_l) {
2838  /* Old versions of msvcrt use different values for _OVERFLOW and _UNDERFLOW
2839  * Because of this lets skip _atodbl tests when _atodbl_l is not available */
2840  win_skip("_atodbl_l is not available\n");
2841  return;
2842  }
2843 
2844  num[0] = 0;
2845  ret = p__atodbl_l(&d, num, NULL);
2846  ok(ret == 0, "_atodbl_l(&d, \"\", NULL) returned %d, expected 0\n", ret);
2847  ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
2848  ret = _atodbl(&d, num);
2849  ok(ret == 0, "_atodbl(&d, \"\") returned %d, expected 0\n", ret);
2850  ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
2851 
2852  strcpy(num, "t");
2853  ret = p__atodbl_l(&d, num, NULL);
2854  ok(ret == 0, "_atodbl_l(&d, \"t\", NULL) returned %d, expected 0\n", ret);
2855  ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
2856  ret = _atodbl(&d, num);
2857  ok(ret == 0, "_atodbl(&d, \"t\") returned %d, expected 0\n", ret);
2858  ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
2859 
2860  strcpy(num, "0");
2861  ret = p__atodbl_l(&d, num, NULL);
2862  ok(ret == 0, "_atodbl_l(&d, \"0\", NULL) returned %d, expected 0\n", ret);
2863  ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
2864  ret = _atodbl(&d, num);
2865  ok(ret == 0, "_atodbl(&d, \"0\") returned %d, expected 0\n", ret);
2866  ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
2867 
2868  strcpy(num, "123");
2869  ret = p__atodbl_l(&d, num, NULL);
2870  ok(ret == 0, "_atodbl_l(&d, \"123\", NULL) returned %d, expected 0\n", ret);
2871  ok(d.x == 123, "d.x = %lf, expected 123\n", d.x);
2872  ret = _atodbl(&d, num);
2873  ok(ret == 0, "_atodbl(&d, \"123\") returned %d, expected 0\n", ret);
2874  ok(d.x == 123, "d.x = %lf, expected 123\n", d.x);
2875 
2876  strcpy(num, "1e-309");
2877  ret = p__atodbl_l(&d, num, NULL);
2878  ok(ret == _UNDERFLOW, "_atodbl_l(&d, \"1e-309\", NULL) returned %d, expected _UNDERFLOW\n", ret);
2879  ok(d.x!=0 && almost_equal(d.x, 0), "d.x = %le, expected 0\n", d.x);
2880  ret = _atodbl(&d, num);
2881  ok(ret == _UNDERFLOW, "_atodbl(&d, \"1e-309\") returned %d, expected _UNDERFLOW\n", ret);
2882  ok(d.x!=0 && almost_equal(d.x, 0), "d.x = %le, expected 0\n", d.x);
2883 
2884  strcpy(num, "1e309");
2885  ret = p__atodbl_l(&d, num, NULL);
2886  ok(ret == _OVERFLOW, "_atodbl_l(&d, \"1e309\", NULL) returned %d, expected _OVERFLOW\n", ret);
2887  ret = _atodbl(&d, num);
2888  ok(ret == _OVERFLOW, "_atodbl(&d, \"1e309\") returned %d, expected _OVERFLOW\n", ret);
2889 }
2890 
2891 static void test__stricmp(void)
2892 {
2893  int ret;
2894 
2895  ret = _stricmp("test", "test");
2896  ok(ret == 0, "_stricmp returned %d\n", ret);
2897  ret = _stricmp("a", "z");
2898  ok(ret < 0, "_stricmp returned %d\n", ret);
2899  ret = _stricmp("z", "a");
2900  ok(ret > 0, "_stricmp returned %d\n", ret);
2901  ret = _stricmp("\xa5", "\xb9");
2902  ok(ret < 0, "_stricmp returned %d\n", ret);
2903 
2904  if(!setlocale(LC_ALL, "polish")) {
2905  win_skip("stricmp tests\n");
2906  return;
2907  }
2908 
2909  ret = _stricmp("test", "test");
2910  ok(ret == 0, "_stricmp returned %d\n", ret);
2911  ret = _stricmp("a", "z");
2912  ok(ret < 0, "_stricmp returned %d\n", ret);
2913  ret = _stricmp("z", "a");
2914  ok(ret > 0, "_stricmp returned %d\n", ret);
2915  ret = _stricmp("\xa5", "\xb9");
2916  ok(ret == 0, "_stricmp returned %d\n", ret);
2917  ret = _stricmp("a", "\xb9");
2918  ok(ret < 0, "_stricmp returned %d\n", ret);
2919 
2920  setlocale(LC_ALL, "C");
2921 }
2922 
2923 static void test__wcstoi64(void)
2924 {
2925  static const WCHAR digit[] = { '9', 0 };
2926  static const WCHAR space[] = { ' ', 0 };
2927  static const WCHAR stock[] = { 0x3231, 0 }; /* PARENTHESIZED IDEOGRAPH STOCK */
2928  static const WCHAR cjk_1[] = { 0x4e00, 0 }; /* CJK Ideograph, First */
2929  static const WCHAR tamil[] = { 0x0bef, 0 }; /* TAMIL DIGIT NINE */
2930  static const WCHAR thai[] = { 0x0e59, 0 }; /* THAI DIGIT NINE */
2931  static const WCHAR fullwidth[] = { 0xff19, 0 }; /* FULLWIDTH DIGIT NINE */
2932  static const WCHAR superscript1[] = { 0xb9, 0 }; /* SUPERSCRIPT ONE */
2933  static const WCHAR minus_0x91[] = { '-', 0x0e50, 'x', 0xff19, '1', 0 };
2934  static const WCHAR plus_071[] = { '+', 0x0e50, 0xff17, '1', 0 };
2935  static const WCHAR hex[] = { 0xff19, 'f', 0x0e59, 0xff46, 0 };
2936  static const WCHAR zeros[] = {
2937  0x660, 0x6f0, 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xc66, 0xce6,
2938  0xd66, 0xe50, 0xed0, 0xf20, 0x1040, 0x17e0, 0x1810, 0xff10
2939  };
2940  int i;
2941 
2942  __int64 res;
2943  unsigned __int64 ures;
2944  WCHAR *endpos;
2945 
2946  if (!p_wcstoi64 || !p_wcstoui64) {
2947  win_skip("_wcstoi64 or _wcstoui64 not found\n");
2948  return;
2949  }
2950 
2951  res = p_wcstoi64(digit, NULL, 10);
2952  ok(res == 9, "res != 9\n");
2953  res = p_wcstoi64(space, &endpos, 0);
2954  ok(endpos == space, "endpos != space\n");
2955  res = p_wcstoi64(stock, &endpos, 10);
2956  ok(res == 0, "res != 0\n");
2957  ok(endpos == stock, "Incorrect endpos (%p-%p)\n", stock, endpos);
2958  res = p_wcstoi64(cjk_1, NULL, 0);
2959  ok(res == 0, "res != 0\n");
2960  res = p_wcstoi64(tamil, &endpos, 10);
2961  ok(res == 0, "res != 0\n");
2962  ok(endpos == tamil, "Incorrect endpos (%p-%p)\n", tamil, endpos);
2963  res = p_wcstoi64(thai, NULL, 10);
2964  ok(res == 9, "res != 9\n");
2965  res = p_wcstoi64(fullwidth, NULL, 10);
2966  ok(res == 9, "res != 9\n");
2967  res = p_wcstoi64(superscript1, NULL, 10);
2968  ok(res == 0, "res != 0\n");
2969  res = p_wcstoi64(hex, NULL, 16);
2970  ok(res == 0x9f9, "res != 0x9f9\n");
2971  res = p_wcstoi64(minus_0x91, NULL, 0);
2972  ok(res == -0x91, "res != -0x91\n");
2973  res = p_wcstoi64(plus_071, NULL, 0);
2974  ok(res == 071, "res != 071\n");
2975 
2976  ures = p_wcstoui64(digit, NULL, 10);
2977  ok(ures == 9, "ures != 9\n");
2978  ures = p_wcstoui64(space, &endpos, 0);
2979  ok(endpos == space, "endpos != space\n");
2980  ures = p_wcstoui64(stock, &endpos, 10);
2981  ok(ures == 0, "ures != 0\n");
2982  ok(endpos == stock, "Incorrect endpos (%p-%p)\n", stock, endpos);
2983  ures = p_wcstoui64(tamil, &endpos, 10);
2984  ok(ures == 0, "ures != 0\n");
2985  ok(endpos == tamil, "Incorrect endpos (%p-%p)\n", tamil, endpos);
2986  ures = p_wcstoui64(thai, NULL, 10);
2987  ok(ures == 9, "ures != 9\n");
2988  ures = p_wcstoui64(fullwidth, NULL, 10);
2989  ok(ures == 9, "ures != 9\n");
2990  ures = p_wcstoui64(superscript1, NULL, 10);
2991  ok(ures == 0, "ures != 0\n");
2992  ures = p_wcstoui64(hex, NULL, 16);
2993  ok(ures == 0x9f9, "ures != 0x9f9\n");
2994  ures = p_wcstoui64(plus_071, NULL, 0);
2995  ok(ures == 071, "ures != 071\n");
2996 
2997  /* Test various unicode digits */
2998  for (i = 0; i < sizeof(zeros) / sizeof(zeros[0]); ++i) {
2999  WCHAR tmp[] = {zeros[i] + 4, zeros[i], zeros[i] + 5, 0};
3000  res = p_wcstoi64(tmp, NULL, 0);
3001  ok(res == 405, "with zero = U+%04X: got %d, expected 405\n", zeros[i], (int)res);
3002  tmp[1] = zeros[i] + 10;
3003  res = p_wcstoi64(tmp, NULL, 16);
3004  ok(res == 4, "with zero = U+%04X: got %d, expected 4\n", zeros[i], (int)res);
3005  }
3006 
3007  return;
3008 }
3009 
3010 static void test_atoi(void)
3011 {
3012  int r;
3013 
3014  r = atoi("0");
3015  ok(r == 0, "atoi(0) = %d\n", r);
3016 
3017  r = atoi("-1");
3018  ok(r == -1, "atoi(-1) = %d\n", r);
3019 
3020  r = atoi("1");
3021  ok(r == 1, "atoi(1) = %d\n", r);
3022 
3023  r = atoi("4294967296");
3024  ok(r == 0, "atoi(4294967296) = %d\n", r);
3025 }
3026 
3027 static void test_atof(void)
3028 {
3029  double d;
3030 
3031  d = atof("0.0");
3032  ok(almost_equal(d, 0.0), "d = %lf\n", d);
3033 
3034  d = atof("1.0");
3035  ok(almost_equal(d, 1.0), "d = %lf\n", d);
3036 
3037  d = atof("-1.0");
3038  ok(almost_equal(d, -1.0), "d = %lf\n", d);
3039 
3040  if (!p__atof_l)
3041  {
3042  win_skip("_atof_l not found\n");
3043  return;
3044  }
3045 
3046  errno = EBADF;
3047  d = atof(NULL);
3048  ok(almost_equal(d, 0.0), "d = %lf\n", d);
3049  ok(errno == EINVAL, "errno = %x\n", errno);
3050 
3051  errno = EBADF;
3052  d = p__atof_l(NULL, NULL);
3053  ok(almost_equal(d, 0.0), "d = %lf\n", d);
3054  ok(errno == EINVAL, "errno = %x\n", errno);
3055 }
3056 
3057 static void test_strncpy(void)
3058 {
3059 #define TEST_STRNCPY_LEN 10
3060  char *ret;
3061  char dst[TEST_STRNCPY_LEN + 1];
3062  char not_null_terminated[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
3063 
3064  /* strlen(src) > TEST_STRNCPY_LEN */
3065  ret = strncpy(dst, "01234567890123456789", TEST_STRNCPY_LEN);
3066  ok(ret == dst, "ret != dst\n");
3067  ok(!strncmp(dst, "0123456789", TEST_STRNCPY_LEN), "dst != 0123456789\n");
3068 
3069  /* without null-terminated */
3070  ret = strncpy(dst, not_null_terminated, TEST_STRNCPY_LEN);
3071  ok(ret == dst, "ret != dst\n");
3072  ok(!strncmp(dst, "0123456789", TEST_STRNCPY_LEN), "dst != 0123456789\n");
3073 
3074  /* strlen(src) < TEST_STRNCPY_LEN */
3075  strcpy(dst, "0123456789");
3076  ret = strncpy(dst, "012345", TEST_STRNCPY_LEN);
3077  ok(ret == dst, "ret != dst\n");
3078  ok(!strcmp(dst, "012345"), "dst != 012345\n");
3079  ok(dst[TEST_STRNCPY_LEN - 1] == '\0', "dst[TEST_STRNCPY_LEN - 1] != 0\n");
3080