ReactOS 0.4.15-dev-8235-gcd88a97
string.c
Go to the documentation of this file.
1/* Unit test suite for SHLWAPI string functions
2 *
3 * Copyright 2003 Jon Griffiths
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20#include <stdio.h>
21
22#include "wine/test.h"
23#include "winbase.h"
24#include "winerror.h"
25#include "winnls.h"
26#define NO_SHLWAPI_REG
27#define NO_SHLWAPI_PATH
28#define NO_SHLWAPI_GDI
29#define NO_SHLWAPI_STREAM
30#include "shlwapi.h"
31#include "shtypes.h"
32
33#define expect_eq(expr, val, type, fmt) do { \
34 type ret = expr; \
35 ok(ret == val, "Unexpected value of '" #expr "': " #fmt " instead of " #val "\n", ret); \
36} while (0);
37
38#define expect_eq2(expr, val1, val2, type, fmt) do { \
39 type ret = expr; \
40 ok(ret == val1 || ret == val2, "Unexpected value of '" #expr "': " #fmt " instead of " #val1 " or " #val2 "\n", ret); \
41} while (0);
42
43static BOOL (WINAPI *pChrCmpIA)(CHAR, CHAR);
44static BOOL (WINAPI *pChrCmpIW)(WCHAR, WCHAR);
45static BOOL (WINAPI *pIntlStrEqWorkerA)(BOOL,LPCSTR,LPCSTR,int);
46static BOOL (WINAPI *pIntlStrEqWorkerW)(BOOL,LPCWSTR,LPCWSTR,int);
47static DWORD (WINAPI *pSHAnsiToAnsi)(LPCSTR,LPSTR,int);
48static DWORD (WINAPI *pSHUnicodeToUnicode)(LPCWSTR,LPWSTR,int);
49static LPSTR (WINAPI *pStrCatBuffA)(LPSTR,LPCSTR,INT);
50static LPWSTR (WINAPI *pStrCatBuffW)(LPWSTR,LPCWSTR,INT);
51static DWORD (WINAPI *pStrCatChainW)(LPWSTR,DWORD,DWORD,LPCWSTR);
52static LPSTR (WINAPI *pStrCpyNXA)(LPSTR,LPCSTR,int);
53static LPWSTR (WINAPI *pStrCpyNXW)(LPWSTR,LPCWSTR,int);
54static LPSTR (WINAPI *pStrFormatByteSize64A)(LONGLONG,LPSTR,UINT);
55static LPSTR (WINAPI *pStrFormatKBSizeA)(LONGLONG,LPSTR,UINT);
56static LPWSTR (WINAPI *pStrFormatKBSizeW)(LONGLONG,LPWSTR,UINT);
57static BOOL (WINAPI *pStrIsIntlEqualA)(BOOL,LPCSTR,LPCSTR,int);
58static BOOL (WINAPI *pStrIsIntlEqualW)(BOOL,LPCWSTR,LPCWSTR,int);
59static LPWSTR (WINAPI *pStrPBrkW)(LPCWSTR,LPCWSTR);
60static LPSTR (WINAPI *pStrRChrA)(LPCSTR,LPCSTR,WORD);
61static HRESULT (WINAPI *pStrRetToBSTR)(STRRET*,LPCITEMIDLIST,BSTR*);
62static HRESULT (WINAPI *pStrRetToBufA)(STRRET*,LPCITEMIDLIST,LPSTR,UINT);
63static HRESULT (WINAPI *pStrRetToBufW)(STRRET*,LPCITEMIDLIST,LPWSTR,UINT);
64static LPWSTR (WINAPI *pStrStrNW)(LPCWSTR,LPCWSTR,UINT);
65static LPWSTR (WINAPI *pStrStrNIW)(LPCWSTR,LPCWSTR,UINT);
66static INT (WINAPIV *pwnsprintfA)(LPSTR,INT,LPCSTR, ...);
67static INT (WINAPIV *pwnsprintfW)(LPWSTR,INT,LPCWSTR, ...);
68static LPWSTR (WINAPI *pStrChrNW)(LPCWSTR,WCHAR,UINT);
69static BOOL (WINAPI *pStrToInt64ExA)(LPCSTR,DWORD,LONGLONG*);
70static BOOL (WINAPI *pStrToInt64ExW)(LPCWSTR,DWORD,LONGLONG*);
71
72static int strcmpW(const WCHAR *str1, const WCHAR *str2)
73{
74 while (*str1 && (*str1 == *str2)) { str1++; str2++; }
75 return *str1 - *str2;
76}
77
78/* StrToInt/StrToIntEx results */
79typedef struct tagStrToIntResult
80{
81 const char* string;
86
88 { "1099", 1099, 1099, 1099 },
89 { "4294967319", 23, ((LONGLONG)1 << 32) | 23, ((LONGLONG)1 << 32) | 23 },
90 { "+88987", 0, 88987, 88987 },
91 { "012", 12, 12, 12 },
92 { "-55", -55, -55, -55 },
93 { "-0", 0, 0, 0 },
94 { "0x44ff", 0, 0, 0x44ff },
95 { "0x2bdc546291f4b1", 0, 0, ((LONGLONG)0x2bdc54 << 32) | 0x6291f4b1 },
96 { "+0x44f4", 0, 0, 0x44f4 },
97 { "-0x44fd", 0, 0, 0x44fd },
98 { "+ 88987", 0, 0, 0 },
99 { "- 55", 0, 0, 0 },
100 { "- 0", 0, 0, 0 },
101 { "+ 0x44f4", 0, 0, 0 },
102 { "--0x44fd", 0, 0, 0 },
103 { " 1999", 0, 1999, 1999 },
104 { " +88987", 0, 88987, 88987 },
105 { " 012", 0, 12, 12 },
106 { " -55", 0, -55, -55 },
107 { " 0x44ff", 0, 0, 0x44ff },
108 { " +0x44f4", 0, 0, 0x44f4 },
109 { " -0x44fd", 0, 0, 0x44fd },
110 { NULL, 0, 0, 0 }
111};
112
113/* pStrFormatByteSize64/StrFormatKBSize results */
115{
117 const char* byte_size_64;
118 const char* kb_size;
120 const char* kb_size2;
122
123
125 { -1023, "-1023 bytes", "0 KB"},
126 { -24, "-24 bytes", "0 KB"},
127 { 309, "309 bytes", "1 KB"},
128 { 10191, "9.95 KB", "10 KB"},
129 { 100353, "98.0 KB", "99 KB"},
130 { 1022286, "998 KB", "999 KB"},
131 { 1046862, "0.99 MB", "1,023 KB", 1, "1023 KB"},
132 { 1048574619, "999 MB", "1,023,999 KB", 1, "1023999 KB"},
133 { 1073741775, "0.99 GB", "1,048,576 KB", 1, "1048576 KB"},
134 { ((LONGLONG)0x000000f9 << 32) | 0xfffff94e, "999 GB", "1,048,575,999 KB", 1, "1048575999 KB"},
135 { ((LONGLONG)0x000000ff << 32) | 0xfffffa9b, "0.99 TB", "1,073,741,823 KB", 1, "1073741823 KB"},
136 { ((LONGLONG)0x0003e7ff << 32) | 0xfffffa9b, "999 TB", "1,073,741,823,999 KB", 1, "4294967295 KB"},
137 { ((LONGLONG)0x0003ffff << 32) | 0xfffffbe8, "0.99 PB", "1,099,511,627,775 KB", 1, "4294967295 KB"},
138 { ((LONGLONG)0x0f9fffff << 32) | 0xfffffd35, "999 PB", "1,099,511,627,776,000 KB", 1, "0 KB"},
139 { ((LONGLONG)0x0fffffff << 32) | 0xfffffa9b, "0.99 EB", "1,125,899,906,842,623 KB", 1, "4294967295 KB"},
140 { 0, NULL, NULL }
141};
142
143/* StrFromTimeIntervalA/StrFromTimeIntervalW results */
145{
148 const char* time_interval;
150
151
153 { 1, 1, " 0 sec" },
154 { 1, 2, " 0 sec" },
155 { 1, 3, " 0 sec" },
156 { 1, 4, " 0 sec" },
157 { 1, 5, " 0 sec" },
158 { 1, 6, " 0 sec" },
159 { 1, 7, " 0 sec" },
160
161 { 1000000, 1, " 10 min" },
162 { 1000000, 2, " 16 min" },
163 { 1000000, 3, " 16 min 40 sec" },
164 { 1000000, 4, " 16 min 40 sec" },
165 { 1000000, 5, " 16 min 40 sec" },
166 { 1000000, 6, " 16 min 40 sec" },
167 { 1000000, 7, " 16 min 40 sec" },
168
169 { 1999999, 1, " 30 min" },
170 { 1999999, 2, " 33 min" },
171 { 1999999, 3, " 33 min 20 sec" },
172 { 1999999, 4, " 33 min 20 sec" },
173 { 1999999, 5, " 33 min 20 sec" },
174 { 1999999, 6, " 33 min 20 sec" },
175 { 1999999, 7, " 33 min 20 sec" },
176
177 { 3999997, 1, " 1 hr" },
178 { 3999997, 2, " 1 hr 6 min" },
179 { 3999997, 3, " 1 hr 6 min 40 sec" },
180 { 3999997, 4, " 1 hr 6 min 40 sec" },
181 { 3999997, 5, " 1 hr 6 min 40 sec" },
182 { 3999997, 6, " 1 hr 6 min 40 sec" },
183 { 3999997, 7, " 1 hr 6 min 40 sec" },
184
185 { 149999851, 7, " 41 hr 40 min 0 sec" },
186 { 150999850, 1, " 40 hr" },
187 { 150999850, 2, " 41 hr" },
188 { 150999850, 3, " 41 hr 50 min" },
189 { 150999850, 4, " 41 hr 56 min" },
190 { 150999850, 5, " 41 hr 56 min 40 sec" },
191 { 150999850, 6, " 41 hr 56 min 40 sec" },
192 { 150999850, 7, " 41 hr 56 min 40 sec" },
193
194 { 493999507, 1, " 100 hr" },
195 { 493999507, 2, " 130 hr" },
196 { 493999507, 3, " 137 hr" },
197 { 493999507, 4, " 137 hr 10 min" },
198 { 493999507, 5, " 137 hr 13 min" },
199 { 493999507, 6, " 137 hr 13 min 20 sec" },
200 { 493999507, 7, " 137 hr 13 min 20 sec" },
201
202 { 0, 0, NULL }
203};
204
205
206/* Returns true if the user interface is in English. Note that this does not
207 * presume of the formatting of dates, numbers, etc.
208 */
210{
211 static HMODULE hkernel32 = NULL;
212 static LANGID (WINAPI *pGetThreadUILanguage)(void) = NULL;
213 static LANGID (WINAPI *pGetUserDefaultUILanguage)(void) = NULL;
214
215 if (!hkernel32)
216 {
217 hkernel32 = GetModuleHandleA("kernel32.dll");
218 pGetThreadUILanguage = (void*)GetProcAddress(hkernel32, "GetThreadUILanguage");
219 pGetUserDefaultUILanguage = (void*)GetProcAddress(hkernel32, "GetUserDefaultUILanguage");
220 }
221 if (pGetThreadUILanguage)
222 return PRIMARYLANGID(pGetThreadUILanguage()) == LANG_ENGLISH;
223 if (pGetUserDefaultUILanguage)
224 return PRIMARYLANGID(pGetUserDefaultUILanguage()) == LANG_ENGLISH;
225
227}
228
229/* Returns true if the dates, numbers, etc. are formatted using English
230 * conventions.
231 */
233{
234 /* Surprisingly GetThreadLocale() is irrelevant here */
236}
237
238static void test_StrChrA(void)
239{
240 char string[129];
241 WORD count;
242
243 /* this test crashes on win2k SP4 */
244 /*ok(!StrChrA(NULL,'\0'), "found a character in a NULL string!\n");*/
245
246 for (count = 32; count < 128; count++)
247 string[count] = (char)count;
248 string[128] = '\0';
249
250 for (count = 32; count < 128; count++)
251 {
252 LPSTR result = StrChrA(string+32, count);
253 INT pos = result - string;
254 ok(pos == count, "found char '%c' in wrong place: got %d, expected %d\n", count, pos, count);
255 }
256
257 for (count = 32; count < 128; count++)
258 {
259 LPSTR result = StrChrA(string+count+1, count);
260 ok(!result, "found char '%c' not in the string\n", count);
261 }
262}
263
264static void test_StrChrW(void)
265{
266 WCHAR string[16385];
267 WORD count;
268
269 /* this test crashes on win2k SP4 */
270 /*ok(!StrChrW(NULL,'\0'), "found a character in a NULL string!\n");*/
271
272 for (count = 32; count < 16384; count++)
273 string[count] = count;
274 string[16384] = '\0';
275
276 for (count = 32; count < 16384; count++)
277 {
278 LPWSTR result = StrChrW(string+32, count);
279 ok((result - string) == count, "found char %d in wrong place\n", count);
280 }
281
282 for (count = 32; count < 16384; count++)
283 {
284 LPWSTR result = StrChrW(string+count+1, count);
285 ok(!result, "found char not in the string\n");
286 }
287}
288
289static void test_StrChrIA(void)
290{
291 char string[129];
292 WORD count;
293
294 /* this test crashes on win2k SP4 */
295 /*ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!\n");*/
296
297 for (count = 32; count < 128; count++)
298 string[count] = (char)count;
299 string[128] = '\0';
300
301 for (count = 'A'; count <= 'X'; count++)
302 {
303 LPSTR result = StrChrIA(string+32, count);
304
305 ok(result - string == count, "found char '%c' in wrong place\n", count);
306 ok(StrChrIA(result, count)!=NULL, "didn't find lowercase '%c'\n", count);
307 }
308
309 for (count = 'a'; count < 'z'; count++)
310 {
311 LPSTR result = StrChrIA(string+count+1, count);
312 ok(!result, "found char not in the string\n");
313 }
314}
315
316static void test_StrChrIW(void)
317{
318 WCHAR string[129];
319 WORD count;
320
321 /* this test crashes on win2k SP4 */
322 /*ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!\n");*/
323
324 for (count = 32; count < 128; count++)
325 string[count] = count;
326 string[128] = '\0';
327
328 for (count = 'A'; count <= 'X'; count++)
329 {
330 LPWSTR result = StrChrIW(string+32, count);
331
332 ok(result - string == count, "found char '%c' in wrong place\n", count);
333 ok(StrChrIW(result, count)!=NULL, "didn't find lowercase '%c'\n", count);
334 }
335
336 for (count = 'a'; count < 'z'; count++)
337 {
338 LPWSTR result = StrChrIW(string+count+1, count);
339 ok(!result, "found char not in the string\n");
340 }
341}
342
343static void test_StrRChrA(void)
344{
345 char string[129];
346 WORD count;
347
348 /* this test crashes on win2k SP4 */
349 /*ok(!StrRChrA(NULL, NULL,'\0'), "found a character in a NULL string!\n");*/
350
351 for (count = 32; count < 128; count++)
352 string[count] = (char)count;
353 string[128] = '\0';
354
355 for (count = 32; count < 128; count++)
356 {
357 LPSTR result = StrRChrA(string+32, NULL, count);
358 ok(result - string == count, "found char %d in wrong place\n", count);
359 }
360
361 for (count = 32; count < 128; count++)
362 {
363 LPSTR result = StrRChrA(string+count+1, NULL, count);
364 ok(!result, "found char not in the string\n");
365 }
366
367 for (count = 32; count < 128; count++)
368 {
369 LPSTR result = StrRChrA(string+count+1, string + 127, count);
370 ok(!result, "found char not in the string\n");
371 }
372}
373
374static void test_StrRChrW(void)
375{
376 WCHAR string[129];
377 WORD count;
378
379 /* this test crashes on win2k SP4 */
380 /*ok(!StrRChrW(NULL, NULL,'\0'), "found a character in a NULL string!\n");*/
381
382 for (count = 32; count < 128; count++)
383 string[count] = count;
384 string[128] = '\0';
385
386 for (count = 32; count < 128; count++)
387 {
388 LPWSTR result = StrRChrW(string+32, NULL, count);
389 INT pos = result - string;
390 ok(pos == count, "found char %d in wrong place: got %d, expected %d\n", count, pos, count);
391 }
392
393 for (count = 32; count < 128; count++)
394 {
395 LPWSTR result = StrRChrW(string+count+1, NULL, count);
396 ok(!result, "found char %d not in the string\n", count);
397 }
398
399 for (count = 32; count < 128; count++)
400 {
401 LPWSTR result = StrRChrW(string+count+1, string + 127, count);
402 ok(!result, "found char %d not in the string\n", count);
403 }
404}
405
406static void test_StrCpyW(void)
407{
408 WCHAR szSrc[256];
409 WCHAR szBuff[256];
411 LPWSTR lpRes;
412
413 while(result->value)
414 {
415 MultiByteToWideChar(CP_ACP, 0, result->byte_size_64, -1, szSrc, ARRAY_SIZE(szSrc));
416
417 lpRes = StrCpyW(szBuff, szSrc);
418 ok(!StrCmpW(szSrc, szBuff) && lpRes == szBuff, "Copied string %s wrong\n", result->byte_size_64);
419 result++;
420 }
421
422 /* this test crashes on win2k SP4 */
423 /*lpRes = StrCpyW(szBuff, NULL);*/
424 /*ok(lpRes == szBuff, "Wrong return value: got %p expected %p\n", lpRes, szBuff);*/
425
426 /* this test crashes on win2k SP4 */
427 /*lpRes = StrCpyW(NULL, szSrc);*/
428 /*ok(lpRes == NULL, "Wrong return value: got %p expected NULL\n", lpRes);*/
429
430 /* this test crashes on win2k SP4 */
431 /*lpRes = StrCpyW(NULL, NULL);*/
432 /*ok(lpRes == NULL, "Wrong return value: got %p expected NULL\n", lpRes);*/
433}
434
435static void test_StrChrNW(void)
436{
437 static const WCHAR string[] = {'T','e','s','t','i','n','g',' ','S','t','r','i','n','g',0};
438 LPWSTR p;
439
440 if (!pStrChrNW)
441 {
442 win_skip("StrChrNW not available\n");
443 return;
444 }
445
446 p = pStrChrNW(string,'t',10);
447 ok(*p=='t',"Found wrong 't'\n");
448 ok(*(p+1)=='i',"next should be 'i'\n");
449
450 p = pStrChrNW(string,'S',10);
451 ok(*p=='S',"Found wrong 'S'\n");
452
453 p = pStrChrNW(string,'r',10);
454 ok(p==NULL,"Should not have found 'r'\n");
455}
456
457static void test_StrToIntA(void)
458{
460 int return_val;
461
462 while (result->string)
463 {
464 return_val = StrToIntA(result->string);
465 ok(return_val == result->str_to_int, "converted '%s' wrong (%d)\n",
466 result->string, return_val);
467 result++;
468 }
469}
470
471static void test_StrToIntW(void)
472{
473 WCHAR szBuff[256];
475 int return_val;
476
477 while (result->string)
478 {
479 MultiByteToWideChar(CP_ACP, 0, result->string, -1, szBuff, ARRAY_SIZE(szBuff));
480 return_val = StrToIntW(szBuff);
481 ok(return_val == result->str_to_int, "converted '%s' wrong (%d)\n",
482 result->string, return_val);
483 result++;
484 }
485}
486
487static void test_StrToIntExA(void)
488{
490 int return_val;
491 BOOL bRet;
492
493 while (result->string)
494 {
495 return_val = -1;
496 bRet = StrToIntExA(result->string,0,&return_val);
497 ok(!bRet || return_val != -1, "No result returned from '%s'\n",
498 result->string);
499 if (bRet)
500 ok(return_val == (int)result->str_to_int64_ex, "converted '%s' wrong (%d)\n",
501 result->string, return_val);
502 result++;
503 }
504
506 while (result->string)
507 {
508 return_val = -1;
509 bRet = StrToIntExA(result->string,STIF_SUPPORT_HEX,&return_val);
510 ok(!bRet || return_val != -1, "No result returned from '%s'\n",
511 result->string);
512 if (bRet)
513 ok(return_val == (int)result->str_to_int64_hex, "converted '%s' wrong (%d)\n",
514 result->string, return_val);
515 result++;
516 }
517}
518
519static void test_StrToIntExW(void)
520{
521 WCHAR szBuff[256];
523 int return_val;
524 BOOL bRet;
525
526 while (result->string)
527 {
528 return_val = -1;
529 MultiByteToWideChar(CP_ACP, 0, result->string, -1, szBuff, ARRAY_SIZE(szBuff));
530 bRet = StrToIntExW(szBuff, 0, &return_val);
531 ok(!bRet || return_val != -1, "No result returned from '%s'\n",
532 result->string);
533 if (bRet)
534 ok(return_val == (int)result->str_to_int64_ex, "converted '%s' wrong (%d)\n",
535 result->string, return_val);
536 result++;
537 }
538
540 while (result->string)
541 {
542 return_val = -1;
543 MultiByteToWideChar(CP_ACP, 0, result->string, -1, szBuff, ARRAY_SIZE(szBuff));
544 bRet = StrToIntExW(szBuff, STIF_SUPPORT_HEX, &return_val);
545 ok(!bRet || return_val != -1, "No result returned from '%s'\n",
546 result->string);
547 if (bRet)
548 ok(return_val == (int)result->str_to_int64_hex, "converted '%s' wrong (%d)\n",
549 result->string, return_val);
550 result++;
551 }
552}
553
554static void test_StrToInt64ExA(void)
555{
557 LONGLONG return_val;
558 BOOL bRet;
559
560 if (!pStrToInt64ExA)
561 {
562 win_skip("StrToInt64ExA() is not available\n");
563 return;
564 }
565
566 while (result->string)
567 {
568 return_val = -1;
569 bRet = pStrToInt64ExA(result->string,0,&return_val);
570 ok(!bRet || return_val != -1, "No result returned from '%s'\n",
571 result->string);
572 if (bRet)
573 ok(return_val == result->str_to_int64_ex, "converted '%s' wrong (%s)\n",
574 result->string, wine_dbgstr_longlong(return_val));
575 result++;
576 }
577
579 while (result->string)
580 {
581 return_val = -1;
582 bRet = pStrToInt64ExA(result->string,STIF_SUPPORT_HEX,&return_val);
583 ok(!bRet || return_val != -1, "No result returned from '%s'\n",
584 result->string);
585 if (bRet)
586 ok(return_val == result->str_to_int64_hex, "converted '%s' wrong (%s)\n",
587 result->string, wine_dbgstr_longlong(return_val));
588 result++;
589 }
590}
591
592static void test_StrToInt64ExW(void)
593{
594 WCHAR szBuff[256];
596 LONGLONG return_val;
597 BOOL bRet;
598
599 if (!pStrToInt64ExW)
600 {
601 win_skip("StrToInt64ExW() is not available\n");
602 return;
603 }
604
605 while (result->string)
606 {
607 return_val = -1;
608 MultiByteToWideChar(CP_ACP, 0, result->string, -1, szBuff, ARRAY_SIZE(szBuff));
609 bRet = pStrToInt64ExW(szBuff, 0, &return_val);
610 ok(!bRet || return_val != -1, "No result returned from '%s'\n",
611 result->string);
612 if (bRet)
613 ok(return_val == result->str_to_int64_ex, "converted '%s' wrong (%s)\n",
614 result->string, wine_dbgstr_longlong(return_val));
615 result++;
616 }
617
619 while (result->string)
620 {
621 return_val = -1;
622 MultiByteToWideChar(CP_ACP, 0, result->string, -1, szBuff, ARRAY_SIZE(szBuff));
623 bRet = pStrToInt64ExW(szBuff, STIF_SUPPORT_HEX, &return_val);
624 ok(!bRet || return_val != -1, "No result returned from '%s'\n",
625 result->string);
626 if (bRet)
627 ok(return_val == result->str_to_int64_hex, "converted '%s' wrong (%s)\n",
628 result->string, wine_dbgstr_longlong(return_val));
629 result++;
630 }
631}
632
633static void test_StrDupA(void)
634{
635 LPSTR lpszStr;
637
638 while(result->value)
639 {
640 lpszStr = StrDupA(result->byte_size_64);
641
642 ok(lpszStr != NULL, "Dup failed\n");
643 if (lpszStr)
644 {
645 ok(!strcmp(result->byte_size_64, lpszStr), "Copied string wrong\n");
646 LocalFree(lpszStr);
647 }
648 result++;
649 }
650
651 /* Later versions of shlwapi return NULL for this, but earlier versions
652 * returned an empty string (as Wine does).
653 */
654 lpszStr = StrDupA(NULL);
655 ok(lpszStr == NULL || *lpszStr == '\0', "NULL string returned %p\n", lpszStr);
656 LocalFree(lpszStr);
657}
658
660{
661 char szBuff[256];
663
664 if (!pStrFormatByteSize64A)
665 {
666 win_skip("StrFormatByteSize64A() is not available\n");
667 return;
668 }
669
670 while(result->value)
671 {
672 pStrFormatByteSize64A(result->value, szBuff, 256);
673
674 ok(!strcmp(result->byte_size_64, szBuff),
675 "Formatted %s wrong: got %s, expected %s\n",
676 wine_dbgstr_longlong(result->value), szBuff, result->byte_size_64);
677
678 result++;
679 }
680}
681
682static void test_StrFormatKBSizeW(void)
683{
684 WCHAR szBuffW[256];
685 char szBuff[256];
687
688 if (!pStrFormatKBSizeW)
689 {
690 win_skip("StrFormatKBSizeW() is not available\n");
691 return;
692 }
693
694 while(result->value)
695 {
696 pStrFormatKBSizeW(result->value, szBuffW, 256);
697 WideCharToMultiByte(CP_ACP, 0, szBuffW, -1, szBuff, ARRAY_SIZE(szBuff), NULL, NULL);
698
699 ok(!strcmp(result->kb_size, szBuff), "Formatted %s wrong: got %s, expected %s\n",
700 wine_dbgstr_longlong(result->value), szBuff, result->kb_size);
701 result++;
702 }
703}
704
705static void test_StrFormatKBSizeA(void)
706{
707 char szBuff[256];
709
710 if (!pStrFormatKBSizeA)
711 {
712 win_skip("StrFormatKBSizeA() is not available\n");
713 return;
714 }
715
716 while(result->value)
717 {
718 pStrFormatKBSizeA(result->value, szBuff, 256);
719
720 /* shlwapi on Win98 SE does not appear to apply delimiters to the output
721 * and does not correctly handle extremely large values. */
722 ok(!strcmp(result->kb_size, szBuff) ||
723 (result->kb_size_broken && !strcmp(result->kb_size2, szBuff)),
724 "Formatted %s wrong: got %s, expected %s\n",
725 wine_dbgstr_longlong(result->value), szBuff, result->kb_size);
726 result++;
727 }
728}
729
731{
732 char szBuff[256];
734
735 while(result->ms)
736 {
737 StrFromTimeIntervalA(szBuff, 256, result->ms, result->digits);
738
739 ok(!strcmp(result->time_interval, szBuff), "Formatted %d %d wrong: %s\n",
740 result->ms, result->digits, szBuff);
741 result++;
742 }
743}
744
745static void test_StrCmpA(void)
746{
747 static const char str1[] = {'a','b','c','d','e','f'};
748 static const char str2[] = {'a','B','c','d','e','f'};
749 ok(0 != StrCmpNA(str1, str2, 6), "StrCmpNA is case-insensitive\n");
750 ok(0 == StrCmpNIA(str1, str2, 6), "StrCmpNIA is case-sensitive\n");
751 if (pChrCmpIA) {
752 ok(!pChrCmpIA('a', 'a'), "ChrCmpIA doesn't work at all!\n");
753 ok(!pChrCmpIA('b', 'B'), "ChrCmpIA is not case-insensitive\n");
754 ok(pChrCmpIA('a', 'z'), "ChrCmpIA believes that a == z!\n");
755 }
756 else
757 win_skip("ChrCmpIA() is not available\n");
758
759 if (pStrIsIntlEqualA)
760 {
761 ok(pStrIsIntlEqualA(FALSE, str1, str2, 5), "StrIsIntlEqualA(FALSE,...) isn't case-insensitive\n");
762 ok(!pStrIsIntlEqualA(TRUE, str1, str2, 5), "StrIsIntlEqualA(TRUE,...) isn't case-sensitive\n");
763 }
764 else
765 win_skip("StrIsIntlEqualA() is not available\n");
766
767 if (pIntlStrEqWorkerA)
768 {
769 ok(pIntlStrEqWorkerA(FALSE, str1, str2, 5), "IntlStrEqWorkerA(FALSE,...) isn't case-insensitive\n");
770 ok(!pIntlStrEqWorkerA(TRUE, str1, str2, 5), "pIntlStrEqWorkerA(TRUE,...) isn't case-sensitive\n");
771 }
772 else
773 win_skip("IntlStrEqWorkerA() is not available\n");
774}
775
776static void test_StrCmpW(void)
777{
778 static const WCHAR str1[] = {'a','b','c','d','e','f'};
779 static const WCHAR str2[] = {'a','B','c','d','e','f'};
780 ok(0 != StrCmpNW(str1, str2, 5), "StrCmpNW is case-insensitive\n");
781 ok(0 == StrCmpNIW(str1, str2, 5), "StrCmpNIW is case-sensitive\n");
782 if (pChrCmpIW) {
783 ok(!pChrCmpIW('a', 'a'), "ChrCmpIW doesn't work at all!\n");
784 ok(!pChrCmpIW('b', 'B'), "ChrCmpIW is not case-insensitive\n");
785 ok(pChrCmpIW('a', 'z'), "ChrCmpIW believes that a == z!\n");
786 }
787 else
788 win_skip("ChrCmpIW() is not available\n");
789
790 if (pStrIsIntlEqualW)
791 {
792 ok(pStrIsIntlEqualW(FALSE, str1, str2, 5), "StrIsIntlEqualW(FALSE,...) isn't case-insensitive\n");
793 ok(!pStrIsIntlEqualW(TRUE, str1, str2, 5), "StrIsIntlEqualW(TRUE,...) isn't case-sensitive\n");
794 }
795 else
796 win_skip("StrIsIntlEqualW() is not available\n");
797
798 if (pIntlStrEqWorkerW)
799 {
800 ok(pIntlStrEqWorkerW(FALSE, str1, str2, 5), "IntlStrEqWorkerW(FALSE,...) isn't case-insensitive\n");
801 ok(!pIntlStrEqWorkerW(TRUE, str1, str2, 5), "IntlStrEqWorkerW(TRUE,...) isn't case-sensitive\n");
802 }
803 else
804 win_skip("IntlStrEqWorkerW() is not available\n");
805}
806
807static WCHAR *CoDupStrW(const char* src)
808{
809 INT len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
810 WCHAR* szTemp = CoTaskMemAlloc(len * sizeof(WCHAR));
811 MultiByteToWideChar(CP_ACP, 0, src, -1, szTemp, len);
812 return szTemp;
813}
814
815static void test_StrRetToBSTR(void)
816{
817 static const WCHAR szTestW[] = { 'T','e','s','t','\0' };
818 ITEMIDLIST iidl[10];
819 BSTR bstr;
820 STRRET strret;
821 HRESULT ret;
822
823 if (!pStrRetToBSTR)
824 {
825 win_skip("StrRetToBSTR() is not available\n");
826 return;
827 }
828
829 strret.uType = STRRET_WSTR;
830 U(strret).pOleStr = CoDupStrW("Test");
831 bstr = 0;
832 ret = pStrRetToBSTR(&strret, NULL, &bstr);
833 ok(ret == S_OK && bstr && !strcmpW(bstr, szTestW),
834 "STRRET_WSTR: dup failed, ret=0x%08x, bstr %p\n", ret, bstr);
835 SysFreeString(bstr);
836
837 strret.uType = STRRET_CSTR;
838 lstrcpyA(U(strret).cStr, "Test");
839 ret = pStrRetToBSTR(&strret, NULL, &bstr);
840 ok(ret == S_OK && bstr && !strcmpW(bstr, szTestW),
841 "STRRET_CSTR: dup failed, ret=0x%08x, bstr %p\n", ret, bstr);
842 SysFreeString(bstr);
843
844 strret.uType = STRRET_OFFSET;
845 U(strret).uOffset = 1;
846 strcpy((char*)&iidl, " Test");
847 ret = pStrRetToBSTR(&strret, iidl, &bstr);
848 ok(ret == S_OK && bstr && !strcmpW(bstr, szTestW),
849 "STRRET_OFFSET: dup failed, ret=0x%08x, bstr %p\n", ret, bstr);
850 SysFreeString(bstr);
851
852 /* Native crashes if str is NULL */
853}
854
855static void test_StrCpyNXA(void)
856{
857 LPCSTR lpSrc = "hello";
858 LPSTR lpszRes;
859 char dest[8];
860
861 if (!pStrCpyNXA)
862 {
863 win_skip("StrCpyNXA() is not available\n");
864 return;
865 }
866
867 memset(dest, '\n', sizeof(dest));
868 lpszRes = pStrCpyNXA(dest, lpSrc, ARRAY_SIZE(dest));
869 ok(lpszRes == dest + 5 && !memcmp(dest, "hello\0\n\n", sizeof(dest)),
870 "StrCpyNXA: expected %p, \"hello\\0\\n\\n\", got %p, \"%d,%d,%d,%d,%d,%d,%d,%d\"\n",
871 dest + 5, lpszRes, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
872}
873
874static void test_StrCpyNXW(void)
875{
876 static const WCHAR lpInit[] = { '\n','\n','\n','\n','\n','\n','\n','\n' };
877 static const WCHAR lpSrc[] = { 'h','e','l','l','o','\0' };
878 static const WCHAR lpRes[] = { 'h','e','l','l','o','\0','\n','\n' };
879 LPWSTR lpszRes;
880 WCHAR dest[8];
881
882 if (!pStrCpyNXW)
883 {
884 win_skip("StrCpyNXW() is not available\n");
885 return;
886 }
887
888 memcpy(dest, lpInit, sizeof(lpInit));
889 lpszRes = pStrCpyNXW(dest, lpSrc, ARRAY_SIZE(dest));
890 ok(lpszRes == dest + 5 && !memcmp(dest, lpRes, sizeof(dest)),
891 "StrCpyNXW: expected %p, \"hello\\0\\n\\n\", got %p, \"%d,%d,%d,%d,%d,%d,%d,%d\"\n",
892 dest + 5, lpszRes, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
893}
894
895#define check_strrstri(type, str, pos, needle, exp) \
896 ret##type = StrRStrI##type(str, str+pos, needle); \
897 ok(ret##type == (exp), "Type " #type ", expected %p but got %p (string base %p)\n", \
898 (exp), ret##type, str);
899
900static void test_StrRStrI(void)
901{
902 static const CHAR szTest[] = "yAxxxxAy";
903 static const CHAR szTest2[] = "ABABABAB";
904 static const WCHAR wszTest[] = {'y','A','x','x','x','x','A','y',0};
905 static const WCHAR wszTest2[] = {'A','B','A','B','A','B','A','B',0};
906
907 static const WCHAR wszPattern1[] = {'A',0};
908 static const WCHAR wszPattern2[] = {'a','X',0};
909 static const WCHAR wszPattern3[] = {'A','y',0};
910 static const WCHAR wszPattern4[] = {'a','b',0};
911 LPWSTR retW;
912 LPSTR retA;
913
914 check_strrstri(A, szTest, 4, "A", szTest+1);
915 check_strrstri(A, szTest, 4, "aX", szTest+1);
916 check_strrstri(A, szTest, 4, "Ay", NULL);
917 check_strrstri(W, wszTest, 4, wszPattern1, wszTest+1);
918 check_strrstri(W, wszTest, 4, wszPattern2, wszTest+1);
919 check_strrstri(W, wszTest, 4, wszPattern3, NULL);
920
921 check_strrstri(A, szTest2, 4, "ab", szTest2+2);
922 check_strrstri(A, szTest2, 3, "ab", szTest2+2);
923 check_strrstri(A, szTest2, 2, "ab", szTest2);
924 check_strrstri(A, szTest2, 1, "ab", szTest2);
925 check_strrstri(A, szTest2, 0, "ab", NULL);
926 check_strrstri(W, wszTest2, 4, wszPattern4, wszTest2+2);
927 check_strrstri(W, wszTest2, 3, wszPattern4, wszTest2+2);
928 check_strrstri(W, wszTest2, 2, wszPattern4, wszTest2);
929 check_strrstri(W, wszTest2, 1, wszPattern4, wszTest2);
930 check_strrstri(W, wszTest2, 0, wszPattern4, NULL);
931
932}
933
934static void test_SHAnsiToAnsi(void)
935{
936 char dest[8];
937 DWORD dwRet;
938
939 if (!pSHAnsiToAnsi)
940 {
941 win_skip("SHAnsiToAnsi() is not available\n");
942 return;
943 }
944
945 if (pSHAnsiToAnsi == (void *)pStrPBrkW)
946 {
947 win_skip("Ordinal 345 corresponds to StrPBrkW, skipping SHAnsiToAnsi tests\n");
948 return;
949 }
950
951 memset(dest, '\n', sizeof(dest));
952 dwRet = pSHAnsiToAnsi("hello", dest, ARRAY_SIZE(dest));
953 ok(dwRet == 6 && !memcmp(dest, "hello\0\n\n", sizeof(dest)),
954 "SHAnsiToAnsi: expected 6, \"hello\\0\\n\\n\", got %d, \"%d,%d,%d,%d,%d,%d,%d,%d\"\n",
955 dwRet, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
956}
957
958static void test_SHUnicodeToUnicode(void)
959{
960 static const WCHAR lpInit[] = { '\n','\n','\n','\n','\n','\n','\n','\n' };
961 static const WCHAR lpSrc[] = { 'h','e','l','l','o','\0' };
962 static const WCHAR lpRes[] = { 'h','e','l','l','o','\0','\n','\n' };
963 WCHAR dest[8];
964 DWORD dwRet;
965
966 if (!pSHUnicodeToUnicode)
967 {
968 win_skip("SHUnicodeToUnicode() is not available\n");
969 return;
970 }
971
972 if (pSHUnicodeToUnicode == (void *)pStrRChrA)
973 {
974 win_skip("Ordinal 346 corresponds to StrRChrA, skipping SHUnicodeToUnicode tests\n");
975 return;
976 }
977
978 memcpy(dest, lpInit, sizeof(lpInit));
979 dwRet = pSHUnicodeToUnicode(lpSrc, dest, ARRAY_SIZE(dest));
980 ok(dwRet == 6 && !memcmp(dest, lpRes, sizeof(dest)),
981 "SHUnicodeToUnicode: expected 6, \"hello\\0\\n\\n\", got %d, \"%d,%d,%d,%d,%d,%d,%d,%d\"\n",
982 dwRet, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
983}
984
985static void test_StrXXX_overflows(void)
986{
987 CHAR str1[2*MAX_PATH+1], buf[2*MAX_PATH];
988 WCHAR wstr1[2*MAX_PATH+1], wbuf[2*MAX_PATH];
989 const WCHAR fmt[] = {'%','s',0};
990 STRRET strret;
992 int ret;
993 int i;
994
995 for (i=0; i<2*MAX_PATH; i++)
996 {
997 str1[i] = '0'+(i%10);
998 wstr1[i] = '0'+(i%10);
999 }
1000 str1[2*MAX_PATH] = 0;
1001 wstr1[2*MAX_PATH] = 0;
1002
1003 memset(buf, 0xbf, sizeof(buf));
1004 expect_eq(StrCpyNA(buf, str1, 10), buf, PCHAR, "%p");
1005 expect_eq(buf[9], 0, CHAR, "%x");
1006 expect_eq(buf[10], '\xbf', CHAR, "%x");
1007
1008 if (pStrCatBuffA)
1009 {
1010 expect_eq(pStrCatBuffA(buf, str1, 100), buf, PCHAR, "%p");
1011 expect_eq(buf[99], 0, CHAR, "%x");
1012 expect_eq(buf[100], '\xbf', CHAR, "%x");
1013 }
1014 else
1015 win_skip("StrCatBuffA() is not available\n");
1016
1017if (0)
1018{
1019 /* crashes on XP */
1020 StrCpyNW(wbuf, (LPCWSTR)0x1, 10);
1021 StrCpyNW((LPWSTR)0x1, wstr1, 10);
1022}
1023
1024 memset(wbuf, 0xbf, sizeof(wbuf));
1025 expect_eq(StrCpyNW(wbuf, (LPCWSTR)0x1, 1), wbuf, PWCHAR, "%p");
1026 expect_eq(wbuf[0], 0, WCHAR, "%x");
1027 expect_eq(wbuf[1], (WCHAR)0xbfbf, WCHAR, "%x");
1028
1029 memset(wbuf, 0xbf, sizeof(wbuf));
1030 expect_eq(StrCpyNW(wbuf, 0, 10), wbuf, PWCHAR, "%p");
1031 expect_eq(wbuf[0], 0, WCHAR, "%x");
1032 expect_eq(wbuf[1], (WCHAR)0xbfbf, WCHAR, "%x");
1033
1034 memset(wbuf, 0xbf, sizeof(wbuf));
1035 expect_eq(StrCpyNW(wbuf, 0, 0), wbuf, PWCHAR, "%p");
1036 expect_eq(wbuf[0], (WCHAR)0xbfbf, WCHAR, "%x");
1037 expect_eq(wbuf[1], (WCHAR)0xbfbf, WCHAR, "%x");
1038
1039 memset(wbuf, 0xbf, sizeof(wbuf));
1040 expect_eq(StrCpyNW(wbuf, wstr1, 0), wbuf, PWCHAR, "%p");
1041 expect_eq(wbuf[0], (WCHAR)0xbfbf, WCHAR, "%x");
1042 expect_eq(wbuf[1], (WCHAR)0xbfbf, WCHAR, "%x");
1043
1044 memset(wbuf, 0xbf, sizeof(wbuf));
1045 expect_eq(StrCpyNW(wbuf, wstr1, 10), wbuf, PWCHAR, "%p");
1046 expect_eq(wbuf[9], 0, WCHAR, "%x");
1047 expect_eq(wbuf[10], (WCHAR)0xbfbf, WCHAR, "%x");
1048
1049 if (pStrCatBuffW)
1050 {
1051 expect_eq(pStrCatBuffW(wbuf, wstr1, 100), wbuf, PWCHAR, "%p");
1052 expect_eq(wbuf[99], 0, WCHAR, "%x");
1053 expect_eq(wbuf[100], (WCHAR)0xbfbf, WCHAR, "%x");
1054 }
1055 else
1056 win_skip("StrCatBuffW() is not available\n");
1057
1058 if (pStrRetToBufW)
1059 {
1060 memset(wbuf, 0xbf, sizeof(wbuf));
1061 strret.uType = STRRET_WSTR;
1062 U(strret).pOleStr = StrDupW(wstr1);
1063 hres = pStrRetToBufW(&strret, NULL, wbuf, 10);
1064 ok(hres == E_NOT_SUFFICIENT_BUFFER || broken(hres == S_OK) /* winxp */,
1065 "StrRetToBufW returned %08x\n", hres);
1067 expect_eq(wbuf[0], 0, WCHAR, "%x");
1068 expect_eq(wbuf[9], 0, WCHAR, "%x");
1069 expect_eq(wbuf[10], (WCHAR)0xbfbf, WCHAR, "%x");
1070
1071 memset(wbuf, 0xbf, sizeof(wbuf));
1072 strret.uType = STRRET_CSTR;
1073 StrCpyNA(U(strret).cStr, str1, MAX_PATH);
1074 hres = pStrRetToBufW(&strret, NULL, wbuf, 10);
1075 ok(hres == S_OK, "StrRetToBufW returned %08x\n", hres);
1076 ok(!memcmp(wbuf, wstr1, 9*sizeof(WCHAR)) && !wbuf[9], "StrRetToBuf returned %s\n", wine_dbgstr_w(wbuf));
1077
1078 memset(wbuf, 0xbf, sizeof(wbuf));
1079 strret.uType = STRRET_WSTR;
1080 U(strret).pOleStr = NULL;
1081 hres = pStrRetToBufW(&strret, NULL, wbuf, 10);
1082 ok(hres == E_FAIL, "StrRetToBufW returned %08x\n", hres);
1083 ok(!wbuf[0], "StrRetToBuf returned %s\n", wine_dbgstr_w(wbuf));
1084 }
1085 else
1086 win_skip("StrRetToBufW() is not available\n");
1087
1088 if (pStrRetToBufA)
1089 {
1090 memset(buf, 0xbf, sizeof(buf));
1091 strret.uType = STRRET_CSTR;
1092 StrCpyNA(U(strret).cStr, str1, MAX_PATH);
1093 expect_eq2(pStrRetToBufA(&strret, NULL, buf, 10), S_OK, E_NOT_SUFFICIENT_BUFFER /* Vista */, HRESULT, "%x");
1094 expect_eq(buf[9], 0, CHAR, "%x");
1095 expect_eq(buf[10], (CHAR)0xbf, CHAR, "%x");
1096 }
1097 else
1098 win_skip("StrRetToBufA() is not available\n");
1099
1100 if (pwnsprintfA)
1101 {
1102 memset(buf, 0xbf, sizeof(buf));
1103 ret = pwnsprintfA(buf, 10, "%s", str1);
1104 ok(broken(ret == 9) || ret == -1 /* Vista */, "Unexpected wnsprintfA return %d, expected 9 or -1\n", ret);
1105 expect_eq(buf[9], 0, CHAR, "%x");
1106 expect_eq(buf[10], (CHAR)0xbf, CHAR, "%x");
1107 }
1108 else
1109 win_skip("wnsprintfA() is not available\n");
1110
1111 if (pwnsprintfW)
1112 {
1113 memset(wbuf, 0xbf, sizeof(wbuf));
1114 ret = pwnsprintfW(wbuf, 10, fmt, wstr1);
1115 ok(broken(ret == 9) || ret == -1 /* Vista */, "Unexpected wnsprintfW return %d, expected 9 or -1\n", ret);
1116 expect_eq(wbuf[9], 0, WCHAR, "%x");
1117 expect_eq(wbuf[10], (WCHAR)0xbfbf, WCHAR, "%x");
1118 }
1119 else
1120 win_skip("wnsprintfW() is not available\n");
1121}
1122
1123static void test_StrStrA(void)
1124{
1125 static const char *deadbeefA = "DeAdBeEf";
1126
1127 const struct
1128 {
1129 const char *search;
1130 const char *expect;
1131 } StrStrA_cases[] =
1132 {
1133 {"", NULL},
1134 {"DeAd", deadbeefA},
1135 {"dead", NULL},
1136 {"AdBe", deadbeefA + 2},
1137 {"adbe", NULL},
1138 {"BeEf", deadbeefA + 4},
1139 {"beef", NULL},
1140 };
1141
1142 LPSTR ret;
1143 int i;
1144
1145 /* Tests crash on Win2k */
1146 if (0)
1147 {
1148 ret = StrStrA(NULL, NULL);
1149 ok(!ret, "Expected StrStrA to return NULL, got %p\n", ret);
1150
1151 ret = StrStrA(NULL, "");
1152 ok(!ret, "Expected StrStrA to return NULL, got %p\n", ret);
1153
1154 ret = StrStrA("", NULL);
1155 ok(!ret, "Expected StrStrA to return NULL, got %p\n", ret);
1156 }
1157
1158 ret = StrStrA("", "");
1159 ok(!ret, "Expected StrStrA to return NULL, got %p\n", ret);
1160
1161 for (i = 0; i < ARRAY_SIZE(StrStrA_cases); i++)
1162 {
1163 ret = StrStrA(deadbeefA, StrStrA_cases[i].search);
1164 ok(ret == StrStrA_cases[i].expect,
1165 "[%d] Expected StrStrA to return %p, got %p\n",
1166 i, StrStrA_cases[i].expect, ret);
1167 }
1168}
1169
1170static void test_StrStrW(void)
1171{
1172 static const WCHAR emptyW[] = {0};
1173 static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0};
1174 static const WCHAR deadW[] = {'D','e','A','d',0};
1175 static const WCHAR dead_lowerW[] = {'d','e','a','d',0};
1176 static const WCHAR adbeW[] = {'A','d','B','e',0};
1177 static const WCHAR adbe_lowerW[] = {'a','d','b','e',0};
1178 static const WCHAR beefW[] = {'B','e','E','f',0};
1179 static const WCHAR beef_lowerW[] = {'b','e','e','f',0};
1180
1181 const struct
1182 {
1183 const WCHAR *search;
1184 const WCHAR *expect;
1185 } StrStrW_cases[] =
1186 {
1187 {emptyW, NULL},
1188 {deadW, deadbeefW},
1189 {dead_lowerW, NULL},
1190 {adbeW, deadbeefW + 2},
1191 {adbe_lowerW, NULL},
1192 {beefW, deadbeefW + 4},
1193 {beef_lowerW, NULL},
1194 };
1195
1196 LPWSTR ret;
1197 int i;
1198
1199 /* Tests crash on Win2k */
1200 if (0)
1201 {
1202 ret = StrStrW(NULL, NULL);
1203 ok(!ret, "Expected StrStrW to return NULL, got %p\n", ret);
1204
1205 ret = StrStrW(NULL, emptyW);
1206 ok(!ret, "Expected StrStrW to return NULL, got %p\n", ret);
1207
1208 ret = StrStrW(emptyW, NULL);
1209 ok(!ret, "Expected StrStrW to return NULL, got %p\n", ret);
1210 }
1211
1213 ok(!ret, "Expected StrStrW to return NULL, got %p\n", ret);
1214
1215 for (i = 0; i < ARRAY_SIZE(StrStrW_cases); i++)
1216 {
1217 ret = StrStrW(deadbeefW, StrStrW_cases[i].search);
1218 ok(ret == StrStrW_cases[i].expect,
1219 "[%d] Expected StrStrW to return %p, got %p\n",
1220 i, StrStrW_cases[i].expect, ret);
1221 }
1222}
1223
1224static void test_StrStrIA(void)
1225{
1226 static const char *deadbeefA = "DeAdBeEf";
1227
1228 const struct
1229 {
1230 const char *search;
1231 const char *expect;
1232 } StrStrIA_cases[] =
1233 {
1234 {"", NULL},
1235 {"DeAd", deadbeefA},
1236 {"dead", deadbeefA},
1237 {"AdBe", deadbeefA + 2},
1238 {"adbe", deadbeefA + 2},
1239 {"BeEf", deadbeefA + 4},
1240 {"beef", deadbeefA + 4},
1241 {"cafe", NULL},
1242 };
1243
1244 LPSTR ret;
1245 int i;
1246
1247 /* Tests crash on Win2k */
1248 if (0)
1249 {
1250 ret = StrStrIA(NULL, NULL);
1251 ok(!ret, "Expected StrStrIA to return NULL, got %p\n", ret);
1252
1253 ret = StrStrIA(NULL, "");
1254 ok(!ret, "Expected StrStrIA to return NULL, got %p\n", ret);
1255
1256 ret = StrStrIA("", NULL);
1257 ok(!ret, "Expected StrStrIA to return NULL, got %p\n", ret);
1258 }
1259
1260 ret = StrStrIA("", "");
1261 ok(!ret, "Expected StrStrIA to return NULL, got %p\n", ret);
1262
1263 for (i = 0; i < ARRAY_SIZE(StrStrIA_cases); i++)
1264 {
1265 ret = StrStrIA(deadbeefA, StrStrIA_cases[i].search);
1266 ok(ret == StrStrIA_cases[i].expect,
1267 "[%d] Expected StrStrIA to return %p, got %p\n",
1268 i, StrStrIA_cases[i].expect, ret);
1269 }
1270}
1271
1272static void test_StrStrIW(void)
1273{
1274 static const WCHAR emptyW[] = {0};
1275 static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0};
1276 static const WCHAR deadW[] = {'D','e','A','d',0};
1277 static const WCHAR dead_lowerW[] = {'d','e','a','d',0};
1278 static const WCHAR adbeW[] = {'A','d','B','e',0};
1279 static const WCHAR adbe_lowerW[] = {'a','d','b','e',0};
1280 static const WCHAR beefW[] = {'B','e','E','f',0};
1281 static const WCHAR beef_lowerW[] = {'b','e','e','f',0};
1282 static const WCHAR cafeW[] = {'c','a','f','e',0};
1283
1284 const struct
1285 {
1286 const WCHAR *search;
1287 const WCHAR *expect;
1288 } StrStrIW_cases[] =
1289 {
1290 {emptyW, NULL},
1291 {deadW, deadbeefW},
1292 {dead_lowerW, deadbeefW},
1293 {adbeW, deadbeefW + 2},
1294 {adbe_lowerW, deadbeefW + 2},
1295 {beefW, deadbeefW + 4},
1296 {beef_lowerW, deadbeefW + 4},
1297 {cafeW, NULL},
1298 };
1299
1300 LPWSTR ret;
1301 int i;
1302
1303 /* Tests crash on Win2k */
1304 if (0)
1305 {
1306 ret = StrStrIW(NULL, NULL);
1307 ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret);
1308
1309 ret = StrStrIW(NULL, emptyW);
1310 ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret);
1311
1312 ret = StrStrIW(emptyW, NULL);
1313 ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret);
1314 }
1315
1317 ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret);
1318
1319 for (i = 0; i < ARRAY_SIZE(StrStrIW_cases); i++)
1320 {
1321 ret = StrStrIW(deadbeefW, StrStrIW_cases[i].search);
1322 ok(ret == StrStrIW_cases[i].expect,
1323 "[%d] Expected StrStrIW to return %p, got %p\n",
1324 i, StrStrIW_cases[i].expect, ret);
1325 }
1326}
1327
1328static void test_StrStrNW(void)
1329{
1330 static const WCHAR emptyW[] = {0};
1331 static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0};
1332 static const WCHAR deadW[] = {'D','e','A','d',0};
1333 static const WCHAR dead_lowerW[] = {'d','e','a','d',0};
1334 static const WCHAR adbeW[] = {'A','d','B','e',0};
1335 static const WCHAR adbe_lowerW[] = {'a','d','b','e',0};
1336 static const WCHAR beefW[] = {'B','e','E','f',0};
1337 static const WCHAR beef_lowerW[] = {'b','e','e','f',0};
1338
1339 const struct
1340 {
1341 const WCHAR *search;
1342 const UINT count;
1343 const WCHAR *expect;
1344 } StrStrNW_cases[] =
1345 {
1346 {emptyW, ARRAY_SIZE(deadbeefW), NULL},
1347 {deadW, ARRAY_SIZE(deadbeefW), deadbeefW},
1348 {dead_lowerW, ARRAY_SIZE(deadbeefW), NULL},
1349 {adbeW, ARRAY_SIZE(deadbeefW), deadbeefW + 2},
1350 {adbe_lowerW, ARRAY_SIZE(deadbeefW), NULL},
1351 {beefW, ARRAY_SIZE(deadbeefW), deadbeefW + 4},
1352 {beef_lowerW, ARRAY_SIZE(deadbeefW), NULL},
1353 {beefW, 0, NULL},
1354 {beefW, 1, NULL},
1355 {beefW, 2, NULL},
1356 {beefW, 3, NULL},
1357 {beefW, 4, NULL},
1358 {beefW, 5, deadbeefW + 4},
1359 {beefW, 6, deadbeefW + 4},
1360 {beefW, 7, deadbeefW + 4},
1361 {beefW, 8, deadbeefW + 4},
1362 {beefW, 9, deadbeefW + 4},
1363 };
1364
1365 LPWSTR ret;
1366 UINT i;
1367
1368 if (!pStrStrNW)
1369 {
1370 win_skip("StrStrNW() is not available\n");
1371 return;
1372 }
1373
1374 ret = pStrStrNW(NULL, NULL, 0);
1375 ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
1376
1377 ret = pStrStrNW(NULL, NULL, 10);
1378 ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
1379
1380 ret = pStrStrNW(NULL, emptyW, 10);
1381 ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
1382
1383 ret = pStrStrNW(emptyW, NULL, 10);
1384 ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
1385
1386 ret = pStrStrNW(emptyW, emptyW, 10);
1387 ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
1388
1389 for (i = 0; i < ARRAY_SIZE(StrStrNW_cases); i++)
1390 {
1391 ret = pStrStrNW(deadbeefW, StrStrNW_cases[i].search, StrStrNW_cases[i].count);
1392 ok(ret == StrStrNW_cases[i].expect,
1393 "[%d] Expected StrStrNW to return %p, got %p\n",
1394 i, StrStrNW_cases[i].expect, ret);
1395 }
1396
1397 /* StrStrNW accepts counts larger than the search string length but rejects
1398 * counts larger than around 2G. The limit seems to change based on the
1399 * caller executable itself. */
1400 ret = pStrStrNW(deadbeefW, beefW, 100);
1401 ok(ret == deadbeefW + 4, "Expected StrStrNW to return deadbeefW + 4, got %p\n", ret);
1402
1403 if (0)
1404 {
1405 ret = pStrStrNW(deadbeefW, beefW, ~0U);
1406 ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
1407 }
1408}
1409
1410static void test_StrStrNIW(void)
1411{
1412 static const WCHAR emptyW[] = {0};
1413 static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0};
1414 static const WCHAR deadW[] = {'D','e','A','d',0};
1415 static const WCHAR dead_lowerW[] = {'d','e','a','d',0};
1416 static const WCHAR adbeW[] = {'A','d','B','e',0};
1417 static const WCHAR adbe_lowerW[] = {'a','d','b','e',0};
1418 static const WCHAR beefW[] = {'B','e','E','f',0};
1419 static const WCHAR beef_lowerW[] = {'b','e','e','f',0};
1420 static const WCHAR cafeW[] = {'c','a','f','e',0};
1421
1422 const struct
1423 {
1424 const WCHAR *search;
1425 const UINT count;
1426 const WCHAR *expect;
1427 } StrStrNIW_cases[] =
1428 {
1429 {emptyW, ARRAY_SIZE(deadbeefW), NULL},
1430 {deadW, ARRAY_SIZE(deadbeefW), deadbeefW},
1431 {dead_lowerW, ARRAY_SIZE(deadbeefW), deadbeefW},
1432 {adbeW, ARRAY_SIZE(deadbeefW), deadbeefW + 2},
1433 {adbe_lowerW, ARRAY_SIZE(deadbeefW), deadbeefW + 2},
1434 {beefW, ARRAY_SIZE(deadbeefW), deadbeefW + 4},
1435 {beef_lowerW, ARRAY_SIZE(deadbeefW), deadbeefW + 4},
1436 {cafeW, ARRAY_SIZE(deadbeefW), NULL},
1437 {beefW, 0, NULL},
1438 {beefW, 1, NULL},
1439 {beefW, 2, NULL},
1440 {beefW, 3, NULL},
1441 {beefW, 4, NULL},
1442 {beefW, 5, deadbeefW + 4},
1443 {beefW, 6, deadbeefW + 4},
1444 {beefW, 7, deadbeefW + 4},
1445 {beefW, 8, deadbeefW + 4},
1446 {beefW, 9, deadbeefW + 4},
1447 {beef_lowerW, 0, NULL},
1448 {beef_lowerW, 1, NULL},
1449 {beef_lowerW, 2, NULL},
1450 {beef_lowerW, 3, NULL},
1451 {beef_lowerW, 4, NULL},
1452 {beef_lowerW, 5, deadbeefW + 4},
1453 {beef_lowerW, 6, deadbeefW + 4},
1454 {beef_lowerW, 7, deadbeefW + 4},
1455 {beef_lowerW, 8, deadbeefW + 4},
1456 {beef_lowerW, 9, deadbeefW + 4},
1457 };
1458
1459 LPWSTR ret;
1460 UINT i;
1461
1462 if (!pStrStrNIW)
1463 {
1464 win_skip("StrStrNIW() is not available\n");
1465 return;
1466 }
1467
1468 ret = pStrStrNIW(NULL, NULL, 0);
1469 ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
1470
1471 ret = pStrStrNIW(NULL, NULL, 10);
1472 ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
1473
1474 ret = pStrStrNIW(NULL, emptyW, 10);
1475 ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
1476
1477 ret = pStrStrNIW(emptyW, NULL, 10);
1478 ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
1479
1480 ret = pStrStrNIW(emptyW, emptyW, 10);
1481 ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
1482
1483 for (i = 0; i < ARRAY_SIZE(StrStrNIW_cases); i++)
1484 {
1485 ret = pStrStrNIW(deadbeefW, StrStrNIW_cases[i].search, StrStrNIW_cases[i].count);
1486 ok(ret == StrStrNIW_cases[i].expect,
1487 "[%d] Expected StrStrNIW to return %p, got %p\n",
1488 i, StrStrNIW_cases[i].expect, ret);
1489 }
1490
1491 /* StrStrNIW accepts counts larger than the search string length but rejects
1492 * counts larger than around 2G. The limit seems to change based on the
1493 * caller executable itself. */
1494 ret = pStrStrNIW(deadbeefW, beefW, 100);
1495 ok(ret == deadbeefW + 4, "Expected StrStrNIW to return deadbeefW + 4, got %p\n", ret);
1496
1497 if (0)
1498 {
1499 ret = pStrStrNIW(deadbeefW, beefW, ~0U);
1500 ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
1501 }
1502}
1503
1504static void test_StrCatChainW(void)
1505{
1506 static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0};
1507 static const WCHAR deadW[] = {'D','e','A','d',0};
1508 static const WCHAR beefW[] = {'B','e','E','f',0};
1509
1510 WCHAR buf[32 + 1];
1511 DWORD ret;
1512
1513 if (!pStrCatChainW)
1514 {
1515 win_skip("StrCatChainW is not available\n");
1516 return;
1517 }
1518
1519 /* Test with NULL buffer */
1520 ret = pStrCatChainW(NULL, 0, 0, beefW);
1521 ok(ret == 0, "Expected StrCatChainW to return 0, got %u\n", ret);
1522
1523 /* Test with empty buffer */
1524 memset(buf, 0x11, sizeof(buf));
1525 ret = pStrCatChainW(buf, 0, 0, beefW);
1526 ok(ret == 0, "Expected StrCatChainW to return 0, got %u\n", ret);
1527 ok(buf[0] == 0x1111, "Expected buf[0] = 0x1111, got %x\n", buf[0]);
1528
1529 memcpy(buf, deadbeefW, sizeof(deadbeefW));
1530 ret = pStrCatChainW(buf, 0, -1, beefW);
1531 ok(ret == 8, "Expected StrCatChainW to return 8, got %u\n", ret);
1532 ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n");
1533
1534 /* Append data to existing string with offset = -1 */
1535 memset(buf, 0x11, sizeof(buf));
1536 ret = pStrCatChainW(buf, 32, 0, deadW);
1537 ok(ret == 4, "Expected StrCatChainW to return 4, got %u\n", ret);
1538 ok(!memcmp(buf, deadW, sizeof(deadW)), "Buffer contains wrong data\n");
1539
1540 ret = pStrCatChainW(buf, 32, -1, beefW);
1541 ok(ret == 8, "Expected StrCatChainW to return 8, got %u\n", ret);
1542 ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n");
1543
1544 /* Append data at a fixed offset */
1545 memset(buf, 0x11, sizeof(buf));
1546 ret = pStrCatChainW(buf, 32, 0, deadW);
1547 ok(ret == 4, "Expected StrCatChainW to return 4, got %u\n", ret);
1548 ok(!memcmp(buf, deadW, sizeof(deadW)), "Buffer contains wrong data\n");
1549
1550 ret = pStrCatChainW(buf, 32, 4, beefW);
1551 ok(ret == 8, "Expected StrCatChainW to return 8, got %u\n", ret);
1552 ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n");
1553
1554 /* Buffer exactly sufficient for string + terminating null */
1555 memset(buf, 0x11, sizeof(buf));
1556 ret = pStrCatChainW(buf, 5, 0, deadW);
1557 ok(ret == 4, "Expected StrCatChainW to return 4, got %u\n", ret);
1558 ok(!memcmp(buf, deadW, sizeof(deadW)), "Buffer contains wrong data\n");
1559
1560 /* Buffer too small, string will be truncated */
1561 memset(buf, 0x11, sizeof(buf));
1562 ret = pStrCatChainW(buf, 4, 0, deadW);
1563 if (ret == 4)
1564 {
1565 /* Windows 2000 and XP uses a slightly different implementation
1566 * for StrCatChainW, which doesn't ensure that strings are null-
1567 * terminated. Skip test if we detect such an implementation. */
1568 win_skip("Windows2000/XP behaviour detected for StrCatChainW, skipping tests\n");
1569 return;
1570 }
1571 ok(ret == 3, "Expected StrCatChainW to return 3, got %u\n", ret);
1572 ok(!memcmp(buf, deadW, 3 * sizeof(WCHAR)), "Buffer contains wrong data\n");
1573 ok(!buf[3], "String is not nullterminated\n");
1574 ok(buf[4] == 0x1111, "Expected buf[4] = 0x1111, got %x\n", buf[4]);
1575
1576 /* Overwrite part of an existing string */
1577 ret = pStrCatChainW(buf, 4, 1, beefW);
1578 ok(ret == 3, "Expected StrCatChainW to return 3, got %u\n", ret);
1579 ok(buf[0] == 'D', "Expected buf[0] = 'D', got %x\n", buf[0]);
1580 ok(buf[1] == 'B', "Expected buf[1] = 'B', got %x\n", buf[1]);
1581 ok(buf[2] == 'e', "Expected buf[2] = 'e', got %x\n", buf[2]);
1582 ok(!buf[3], "String is not nullterminated\n");
1583 ok(buf[4] == 0x1111, "Expected buf[4] = 0x1111, got %x\n", buf[4]);
1584
1585 /* Test appending to full buffer */
1586 memset(buf, 0x11, sizeof(buf));
1587 memcpy(buf, deadbeefW, sizeof(deadbeefW));
1588 memcpy(buf + 9, deadW, sizeof(deadW));
1589 ret = pStrCatChainW(buf, 9, 8, beefW);
1590 ok(ret == 8, "Expected StrCatChainW to return 8, got %u\n", ret);
1591 ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n");
1592 ok(!memcmp(buf + 9, deadW, sizeof(deadW)), "Buffer contains wrong data\n");
1593
1594 /* Offset points at the end of the buffer */
1595 ret = pStrCatChainW(buf, 9, 9, beefW);
1596 ok(ret == 8, "Expected StrCatChainW to return 8, got %u\n", ret);
1597 ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n");
1598 ok(!memcmp(buf + 9, deadW, sizeof(deadW)), "Buffer contains wrong data\n");
1599
1600 /* Offset points outside of the buffer */
1601 ret = pStrCatChainW(buf, 9, 10, beefW);
1602 ok(ret == 10, "Expected StrCatChainW to return 10, got %u\n", ret);
1603 ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n");
1604 ok(!memcmp(buf + 9, deadW, sizeof(deadW)), "Buffer contains wrong data\n");
1605
1606 /* The same but without nullterminated string */
1607 memcpy(buf, deadbeefW, sizeof(deadbeefW));
1608 ret = pStrCatChainW(buf, 5, -1, deadW);
1609 ok(ret == 8, "Expected StrCatChainW to return 8, got %u\n", ret);
1610 ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n");
1611
1612 ret = pStrCatChainW(buf, 5, 5, deadW);
1613 ok(ret == 4, "Expected StrCatChainW to return 4, got %u\n", ret);
1614 ok(!memcmp(buf, deadW, sizeof(deadW)), "Buffer contains wrong data\n");
1615 ok(buf[5] == 'e', "Expected buf[5] = 'e', got %x\n", buf[5]);
1616
1617 ret = pStrCatChainW(buf, 5, 6, deadW);
1618 ok(ret == 6, "Expected StrCatChainW to return 6, got %u\n", ret);
1619 ok(!memcmp(buf, deadW, sizeof(deadW)), "Buffer contains wrong data\n");
1620 ok(buf[5] == 'e', "Expected buf[5] = 'e', got %x\n", buf[5]);
1621}
1622
1624{
1626 CHAR thousandDelim[8];
1627 CHAR decimalDelim[8];
1628 CoInitialize(0);
1629
1632
1633 hShlwapi = GetModuleHandleA("shlwapi");
1634 pChrCmpIA = (void *)GetProcAddress(hShlwapi, "ChrCmpIA");
1635 pChrCmpIW = (void *)GetProcAddress(hShlwapi, "ChrCmpIW");
1636 pIntlStrEqWorkerA = (void *)GetProcAddress(hShlwapi, "IntlStrEqWorkerA");
1637 pIntlStrEqWorkerW = (void *)GetProcAddress(hShlwapi, "IntlStrEqWorkerW");
1638 pSHAnsiToAnsi = (void *)GetProcAddress(hShlwapi, (LPSTR)345);
1639 pSHUnicodeToUnicode = (void *)GetProcAddress(hShlwapi, (LPSTR)346);
1640 pStrCatBuffA = (void *)GetProcAddress(hShlwapi, "StrCatBuffA");
1641 pStrCatBuffW = (void *)GetProcAddress(hShlwapi, "StrCatBuffW");
1642 pStrCatChainW = (void *)GetProcAddress(hShlwapi, "StrCatChainW");
1643 pStrCpyNXA = (void *)GetProcAddress(hShlwapi, (LPSTR)399);
1644 pStrCpyNXW = (void *)GetProcAddress(hShlwapi, (LPSTR)400);
1645 pStrChrNW = (void *)GetProcAddress(hShlwapi, "StrChrNW");
1646 pStrFormatByteSize64A = (void *)GetProcAddress(hShlwapi, "StrFormatByteSize64A");
1647 pStrFormatKBSizeA = (void *)GetProcAddress(hShlwapi, "StrFormatKBSizeA");
1648 pStrFormatKBSizeW = (void *)GetProcAddress(hShlwapi, "StrFormatKBSizeW");
1649 pStrIsIntlEqualA = (void *)GetProcAddress(hShlwapi, "StrIsIntlEqualA");
1650 pStrIsIntlEqualW = (void *)GetProcAddress(hShlwapi, "StrIsIntlEqualW");
1651 pStrPBrkW = (void *)GetProcAddress(hShlwapi, "StrPBrkW");
1652 pStrRChrA = (void *)GetProcAddress(hShlwapi, "StrRChrA");
1653 pStrRetToBSTR = (void *)GetProcAddress(hShlwapi, "StrRetToBSTR");
1654 pStrRetToBufA = (void *)GetProcAddress(hShlwapi, "StrRetToBufA");
1655 pStrRetToBufW = (void *)GetProcAddress(hShlwapi, "StrRetToBufW");
1656 pStrStrNW = (void *)GetProcAddress(hShlwapi, "StrStrNW");
1657 pStrStrNIW = (void *)GetProcAddress(hShlwapi, "StrStrNIW");
1658 pwnsprintfA = (void *)GetProcAddress(hShlwapi, "wnsprintfA");
1659 pwnsprintfW = (void *)GetProcAddress(hShlwapi, "wnsprintfW");
1660 pStrToInt64ExA = (void *)GetProcAddress(hShlwapi, "StrToInt64ExA");
1661 pStrToInt64ExW = (void *)GetProcAddress(hShlwapi, "StrToInt64ExW");
1662
1663 test_StrChrA();
1664 test_StrChrW();
1665 test_StrChrIA();
1666 test_StrChrIW();
1667 test_StrRChrA();
1668 test_StrRChrW();
1669 test_StrCpyW();
1670 test_StrChrNW();
1677 test_StrDupA();
1678
1679 /* language-dependent test */
1681 {
1685 }
1686 else
1687 skip("An English UI and locale is required for the StrFormat*Size tests\n");
1688 if (is_lang_english())
1690 else
1691 skip("An English UI is required for the StrFromTimeInterval tests\n");
1692
1693 test_StrCmpA();
1694 test_StrCmpW();
1698 test_StrRStrI();
1702 test_StrStrA();
1703 test_StrStrW();
1704 test_StrStrIA();
1705 test_StrStrIW();
1706 test_StrStrNW();
1709
1711}
#define expect(EXPECTED, GOT)
Definition: SystemMenu.c:483
#define broken(x)
Definition: _sntprintf.h:21
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define ARRAY_SIZE(A)
Definition: main.h:33
#define U(x)
Definition: wordpad.c:45
Definition: ehthrow.cxx:93
static HMODULE hShlwapi
Definition: clsid.c:38
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
INT WINAPI StrToIntW(LPCWSTR lpString)
Definition: string.c:411
LPWSTR WINAPI StrChrIW(LPCWSTR lpszStr, WCHAR ch)
Definition: string.c:635
LPWSTR WINAPI StrChrW(LPCWSTR lpszStr, WCHAR ch)
Definition: string.c:468
LPWSTR WINAPI StrRChrW(LPCWSTR str, LPCWSTR end, WORD ch)
Definition: string.c:556
LPSTR WINAPI StrStrIA(LPCSTR lpszStr, LPCSTR lpszSearch)
Definition: string.c:355
INT WINAPI StrCmpNIA(LPCSTR lpszStr, LPCSTR lpszComp, INT iLen)
Definition: string.c:300
LPSTR WINAPI StrChrIA(LPCSTR lpszStr, WORD ch)
Definition: string.c:614
LPWSTR WINAPI StrStrW(LPCWSTR lpszStr, LPCWSTR lpszSearch)
Definition: string.c:594
LPSTR WINAPI StrRChrA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch)
Definition: string.c:525
INT WINAPI StrToIntA(LPCSTR lpszStr)
Definition: string.c:374
LPSTR WINAPI StrChrA(LPCSTR lpszStr, WORD ch)
Definition: string.c:270
INT WINAPI StrCmpNIW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen)
Definition: string.c:311
LPWSTR WINAPI StrStrIW(LPCWSTR lpszStr, LPCWSTR lpszSearch)
Definition: string.c:384
INT WINAPI StrCmpNW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen)
Definition: string.c:504
LPSTR WINAPI StrStrA(LPCSTR lpszStr, LPCSTR lpszSearch)
Definition: string.c:582
INT WINAPI StrCmpNA(LPCSTR lpszStr, LPCSTR lpszComp, INT iLen)
Definition: string.c:493
#define CP_ACP
Definition: compat.h:109
#define GetProcAddress(x, y)
Definition: compat.h:753
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
OLECHAR * BSTR
Definition: compat.h:2293
#define MAX_PATH
Definition: compat.h:34
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
INT WINAPI GetLocaleInfoA(LCID lcid, LCTYPE lctype, LPSTR buffer, INT len)
Definition: locale.c:1599
LANGID WINAPI GetUserDefaultLangID(void)
Definition: locale.c:1176
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:1964
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
LPSTR WINAPI StrDupA(LPCSTR lpszStr)
Definition: string.c:1064
INT WINAPI StrFromTimeIntervalA(LPSTR lpszStr, UINT cchMax, DWORD dwMS, int iDigits)
Definition: string.c:2125
LPWSTR WINAPI StrCpyNW(LPWSTR dst, LPCWSTR src, int count)
Definition: string.c:536
int WINAPI StrCmpW(LPCWSTR lpszStr, LPCWSTR lpszComp)
Definition: string.c:434
BOOL WINAPI StrToIntExW(LPCWSTR lpszStr, DWORD dwFlags, LPINT lpiRet)
Definition: string.c:970
LPWSTR WINAPI StrCpyW(LPWSTR lpszStr, LPCWSTR lpszSrc)
Definition: string.c:514
BOOL WINAPI StrToIntExA(LPCSTR lpszStr, DWORD dwFlags, LPINT lpiRet)
Definition: string.c:886
LPWSTR WINAPI StrDupW(LPCWSTR lpszStr)
Definition: string.c:1093
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLenum src
Definition: glext.h:6340
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
static const WCHAR emptyW[]
Definition: navigate.c:40
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
#define S_OK
Definition: intsafe.h:52
#define wine_dbgstr_w
Definition: kernel32.h:34
USHORT LANGID
Definition: mui.h:9
LPSTR WINAPI lstrcpyA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:100
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
char string[160]
Definition: util.h:11
HRESULT hres
Definition: protocol.c:465
static HINSTANCE hkernel32
Definition: process.c:66
static char int
Definition: string.c:71
#define expect_eq(expr, value, type, format)
Definition: string.c:52
static char * dest
Definition: rtl.c:135
static LPSTR
Definition: string.c:39
static INT
Definition: string.c:39
static LPCSTR
Definition: string.c:33
static const ITEMIDLIST *static WCHAR * CoDupStrW(const char *src)
Definition: string.c:37
static DWORD
Definition: string.c:35
static void test_StrFormatByteSize64A(void)
Definition: string.c:659
static void test_StrChrIW(void)
Definition: string.c:316
static void test_StrStrIW(void)
Definition: string.c:1272
static void test_StrChrW(void)
Definition: string.c:264
static void test_StrFormatKBSizeA(void)
Definition: string.c:705
static BOOL is_locale_english(void)
Definition: string.c:232
static void test_StrStrNW(void)
Definition: string.c:1328
static void test_StrDupA(void)
Definition: string.c:633
static const StrFormatSizeResult StrFormatSize_results[]
Definition: string.c:124
#define check_strrstri(type, str, pos, needle, exp)
Definition: string.c:895
static void test_StrCmpA(void)
Definition: string.c:745
static void test_StrStrIA(void)
Definition: string.c:1224
static void test_StrToInt64ExW(void)
Definition: string.c:592
static void test_StrFromTimeIntervalA(void)
Definition: string.c:730
static void test_SHUnicodeToUnicode(void)
Definition: string.c:958
static void test_StrToInt64ExA(void)
Definition: string.c:554
static void test_StrToIntA(void)
Definition: string.c:457
static const StrFromTimeIntervalResult StrFromTimeInterval_results[]
Definition: string.c:152
static void test_StrRChrA(void)
Definition: string.c:343
static void test_StrRetToBSTR(void)
Definition: string.c:815
static void test_StrToIntExW(void)
Definition: string.c:519
static BOOL is_lang_english(void)
Definition: string.c:209
static void test_StrChrA(void)
Definition: string.c:238
static void test_StrCatChainW(void)
Definition: string.c:1504
static void test_StrRStrI(void)
Definition: string.c:900
static void test_StrStrW(void)
Definition: string.c:1170
static void test_SHAnsiToAnsi(void)
Definition: string.c:934
static void test_StrToIntW(void)
Definition: string.c:471
static CHAR
Definition: string.c:43
#define expect_eq2(expr, val1, val2, type, fmt)
Definition: string.c:38
struct tagStrToIntResult StrToIntResult
static void test_StrChrIA(void)
Definition: string.c:289
static void test_StrCpyW(void)
Definition: string.c:406
struct tagStrFormatSizeResult StrFormatSizeResult
static WORD
Definition: string.c:60
static void test_StrFormatKBSizeW(void)
Definition: string.c:682
static void test_StrToIntExA(void)
Definition: string.c:487
static void test_StrCmpW(void)
Definition: string.c:776
static void test_StrChrNW(void)
Definition: string.c:435
static void test_StrStrNIW(void)
Definition: string.c:1410
static UINT
Definition: string.c:54
static void test_StrXXX_overflows(void)
Definition: string.c:985
static void test_StrStrA(void)
Definition: string.c:1123
static LPCITEMIDLIST
Definition: string.c:61
static const StrToIntResult StrToInt_results[]
Definition: string.c:87
struct tagStrFromTimeIntervalResult StrFromTimeIntervalResult
static void test_StrRChrW(void)
Definition: string.c:374
static void test_StrCpyNXW(void)
Definition: string.c:874
static void test_StrCpyNXA(void)
Definition: string.c:855
static short search(int val, const short *table, int size)
Definition: msg711.c:255
unsigned int UINT
Definition: ndis.h:50
#define BOOL
Definition: nt_native.h:43
#define LOCALE_USER_DEFAULT
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
#define strcmpW(s1, s2)
Definition: unicode.h:44
#define WINAPIV
Definition: sdbpapi.h:64
#define LANG_ENGLISH
Definition: nls.h:52
#define PRIMARYLANGID(l)
Definition: nls.h:16
#define win_skip
Definition: test.h:163
#define memset(x, y, z)
Definition: compat.h:39
#define STIF_SUPPORT_HEX
Definition: shlwapi.h:1452
#define StrCpyNA
Definition: shlwapi.h:1514
@ STRRET_CSTR
Definition: shtypes.idl:87
@ STRRET_OFFSET
Definition: shtypes.idl:86
@ STRRET_WSTR
Definition: shtypes.idl:85
Definition: polytest.cpp:36
UINT uType
Definition: shtypes.idl:93
Definition: dsound.c:943
const char * kb_size2
Definition: string.c:120
const char * kb_size
Definition: string.c:118
const char * byte_size_64
Definition: string.c:117
const char * time_interval
Definition: string.c:148
const char * string
Definition: string.c:81
LONGLONG str_to_int64_ex
Definition: string.c:83
LONGLONG str_to_int64_hex
Definition: string.c:84
int64_t LONGLONG
Definition: typedefs.h:68
int32_t INT
Definition: typedefs.h:58
uint16_t * PWCHAR
Definition: typedefs.h:56
char * PCHAR
Definition: typedefs.h:51
int ret
#define HRESULT
Definition: msvc.h:7
#define WINAPI
Definition: msvc.h:6
#define E_NOT_SUFFICIENT_BUFFER
Definition: winerror.h:2345
#define LOCALE_SDECIMAL
Definition: winnls.h:42
#define LOCALE_STHOUSAND
Definition: winnls.h:43
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
char CHAR
Definition: xmlstorage.h:175