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