ReactOS  0.4.14-dev-342-gdc047f9
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 
43 static BOOL (WINAPI *pChrCmpIA)(CHAR, CHAR);
44 static BOOL (WINAPI *pChrCmpIW)(WCHAR, WCHAR);
45 static BOOL (WINAPI *pIntlStrEqWorkerA)(BOOL,LPCSTR,LPCSTR,int);
46 static BOOL (WINAPI *pIntlStrEqWorkerW)(BOOL,LPCWSTR,LPCWSTR,int);
47 static DWORD (WINAPI *pSHAnsiToAnsi)(LPCSTR,LPSTR,int);
48 static DWORD (WINAPI *pSHUnicodeToUnicode)(LPCWSTR,LPWSTR,int);
49 static LPSTR (WINAPI *pStrCatBuffA)(LPSTR,LPCSTR,INT);
50 static LPWSTR (WINAPI *pStrCatBuffW)(LPWSTR,LPCWSTR,INT);
51 static DWORD (WINAPI *pStrCatChainW)(LPWSTR,DWORD,DWORD,LPCWSTR);
52 static LPSTR (WINAPI *pStrCpyNXA)(LPSTR,LPCSTR,int);
53 static LPWSTR (WINAPI *pStrCpyNXW)(LPWSTR,LPCWSTR,int);
54 static LPSTR (WINAPI *pStrFormatByteSize64A)(LONGLONG,LPSTR,UINT);
55 static LPSTR (WINAPI *pStrFormatKBSizeA)(LONGLONG,LPSTR,UINT);
56 static LPWSTR (WINAPI *pStrFormatKBSizeW)(LONGLONG,LPWSTR,UINT);
57 static BOOL (WINAPI *pStrIsIntlEqualA)(BOOL,LPCSTR,LPCSTR,int);
58 static BOOL (WINAPI *pStrIsIntlEqualW)(BOOL,LPCWSTR,LPCWSTR,int);
59 static LPWSTR (WINAPI *pStrPBrkW)(LPCWSTR,LPCWSTR);
60 static LPSTR (WINAPI *pStrRChrA)(LPCSTR,LPCSTR,WORD);
61 static HRESULT (WINAPI *pStrRetToBSTR)(STRRET*,LPCITEMIDLIST,BSTR*);
62 static HRESULT (WINAPI *pStrRetToBufA)(STRRET*,LPCITEMIDLIST,LPSTR,UINT);
63 static HRESULT (WINAPI *pStrRetToBufW)(STRRET*,LPCITEMIDLIST,LPWSTR,UINT);
64 static LPWSTR (WINAPI *pStrStrNW)(LPCWSTR,LPCWSTR,UINT);
65 static LPWSTR (WINAPI *pStrStrNIW)(LPCWSTR,LPCWSTR,UINT);
66 static INT (WINAPIV *pwnsprintfA)(LPSTR,INT,LPCSTR, ...);
67 static INT (WINAPIV *pwnsprintfW)(LPWSTR,INT,LPCWSTR, ...);
68 static LPWSTR (WINAPI *pStrChrNW)(LPCWSTR,WCHAR,UINT);
69 static BOOL (WINAPI *pStrToInt64ExA)(LPCSTR,DWORD,LONGLONG*);
70 static BOOL (WINAPI *pStrToInt64ExW)(LPCWSTR,DWORD,LONGLONG*);
71 
72 static 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 */
79 typedef struct tagStrToIntResult
80 {
81  const char* string;
86 
87 static const StrToIntResult StrToInt_results[] = {
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 {
147  int digits;
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  */
209 static BOOL is_lang_english(void)
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 
238 static 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 
264 static 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 
289 static 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 
316 static 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 
343 static 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 
374 static 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 
406 static 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 
435 static 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 
457 static 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 
471 static 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 
487 static 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 
519 static 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 
554 static 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 
592 static 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 
633 static 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 
659 static void test_StrFormatByteSize64A(void)
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 
682 static 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 
705 static 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 
730 static void test_StrFromTimeIntervalA(void)
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 
745 static 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 
776 static 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 
807 static 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 
815 static 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 
855 static 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 
874 static 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 
900 static 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 
934 static 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 
958 static 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 
985 static 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;
991  HRESULT hres;
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 
1017 if (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 
1123 static 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 
1170 static 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 
1212  ret = StrStrW(emptyW, emptyW);
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 
1224 static 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 
1272 static 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 
1316  ret = StrStrIW(emptyW, emptyW);
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 
1328 static 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 
1410 static 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 
1504 static 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 
1623 START_TEST(string)
1624 {
1625  HMODULE hShlwapi;
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();
1671  test_StrToIntA();
1672  test_StrToIntW();
1673  test_StrToIntExA();
1674  test_StrToIntExW();
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();
1696  test_StrCpyNXA();
1697  test_StrCpyNXW();
1698  test_StrRStrI();
1702  test_StrStrA();
1703  test_StrStrW();
1704  test_StrStrIA();
1705  test_StrStrIW();
1706  test_StrStrNW();
1707  test_StrStrNIW();
1709 
1710  CoUninitialize();
1711 }
signed char * PCHAR
Definition: retypes.h:7
static const StrFormatSizeResult StrFormatSize_results[]
Definition: string.c:124
static void test_StrFromTimeIntervalA(void)
Definition: string.c:730
static INT
Definition: string.c:39
static short search(int val, const short *table, int size)
Definition: msg711.c:255
#define TRUE
Definition: types.h:120
const char * string
Definition: string.c:1565
static void test_StrCpyNXA(void)
Definition: string.c:855
BOOL WINAPI StrToIntExA(LPCSTR lpszStr, DWORD dwFlags, LPINT lpiRet)
Definition: string.c:886
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
INT WINAPI StrCmpNW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen)
Definition: string.c:504
INT WINAPI StrFromTimeIntervalA(LPSTR lpszStr, UINT cchMax, DWORD dwMS, int iDigits)
Definition: string.c:2117
#define WideCharToMultiByte
Definition: compat.h:101
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
static void test_StrFormatKBSizeA(void)
Definition: string.c:705
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define expect_eq(expr, val, type, fmt)
Definition: string.c:33
static CHAR
Definition: string.c:43
static void(__cdecl *p_qsort)(void *
char * wine_dbgstr_w(const wchar_t *wstr)
Definition: atltest.h:87
#define CP_ACP
Definition: compat.h:99
INT WINAPI GetLocaleInfoA(LCID lcid, LCTYPE lctype, LPSTR buffer, INT len)
Definition: lang.c:1018
#define LOCALE_USER_DEFAULT
GLuint GLuint GLsizei count
Definition: gl.h:1545
static void test_StrCmpA(void)
Definition: string.c:745
const char * string
Definition: string.c:81
LPSTR WINAPI StrChrIA(LPCSTR lpszStr, WORD ch)
Definition: string.c:614
char CHAR
Definition: xmlstorage.h:175
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
static LPSTR
Definition: string.c:39
#define U(x)
Definition: wordpad.c:44
LPWSTR WINAPI StrCpyNW(LPWSTR dst, LPCWSTR src, int count)
Definition: string.c:536
static void test_StrToIntExA(void)
Definition: string.c:487
static HINSTANCE hkernel32
Definition: process.c:66
static LONGLONG *static LONGLONG *static int strcmpW(const WCHAR *str1, const WCHAR *str2)
Definition: string.c:72
static WORD
Definition: string.c:60
WORD LANGID
Definition: typedefs.h:79
OLECHAR * BSTR
Definition: compat.h:1942
uint16_t * PWCHAR
Definition: typedefs.h:54
char * LPSTR
Definition: xmlstorage.h:182
static void test_StrCatChainW(void)
Definition: string.c:1504
struct tagStrFormatSizeResult StrFormatSizeResult
#define E_FAIL
Definition: ddrawi.h:102
static void test_StrRChrA(void)
Definition: string.c:343
LPWSTR WINAPI StrDupW(LPCWSTR lpszStr)
Definition: string.c:1089
int32_t INT
Definition: typedefs.h:56
static void test_StrCpyW(void)
Definition: string.c:406
static void test_StrFormatKBSizeW(void)
Definition: string.c:682
static void test_StrChrIW(void)
Definition: string.c:316
static HMODULE hShlwapi
Definition: clsid.c:38
static void test_StrChrA(void)
Definition: string.c:238
static void test_StrXXX_overflows(void)
Definition: string.c:985
static void test_StrRetToBSTR(void)
Definition: string.c:815
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
static void test_SHAnsiToAnsi(void)
Definition: string.c:934
#define LOCALE_STHOUSAND
Definition: winnls.h:43
LONGLONG str_to_int64_ex
Definition: string.c:83
static void test_StrToIntW(void)
Definition: string.c:471
unsigned int BOOL
Definition: ntddk_ex.h:94
LPSTR WINAPI StrChrA(LPCSTR lpszStr, WORD ch)
Definition: string.c:270
LPWSTR WINAPI StrStrIW(LPCWSTR lpszStr, LPCWSTR lpszSearch)
Definition: string.c:384
static void test_StrChrNW(void)
Definition: string.c:435
static void test_StrRChrW(void)
Definition: string.c:374
Definition: polytest.cpp:35
#define expect_eq2(expr, val1, val2, type, fmt)
Definition: string.c:38
static WCHAR * CoDupStrW(const char *src)
Definition: string.c:807
static void test_StrCmpW(void)
Definition: string.c:776
LPSTR WINAPI StrRChrA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch)
Definition: string.c:525
static WCHAR
Definition: string.c:57
smooth NULL
Definition: ftsmooth.c:416
LPSTR WINAPI StrStrA(LPCSTR lpszStr, LPCSTR lpszSearch)
Definition: string.c:582
#define check_strrstri(type, str, pos, needle, exp)
Definition: string.c:895
static void test_StrStrNIW(void)
Definition: string.c:1410
#define LOCALE_SDECIMAL
Definition: winnls.h:42
static BOOL(WINAPI *pChrCmpIA)(CHAR
const char * LPCSTR
Definition: xmlstorage.h:183
static void test_StrFormatByteSize64A(void)
Definition: string.c:659
static void test_StrStrIW(void)
Definition: string.c:1272
int64_t LONGLONG
Definition: typedefs.h:66
static void test_StrChrIA(void)
Definition: string.c:289
#define StrCpyNA
Definition: shlwapi.h:1514
static BOOL is_lang_english(void)
Definition: string.c:209
HRESULT hres
Definition: protocol.c:465
__wchar_t WCHAR
Definition: xmlstorage.h:180
LONG HRESULT
Definition: typedefs.h:77
static DWORD
Definition: string.c:35
#define MAX_PATH
Definition: compat.h:26
#define WINAPI
Definition: msvc.h:8
const char * time_interval
Definition: string.c:148
static void test_StrDupA(void)
Definition: string.c:633
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
static void test_StrToInt64ExW(void)
Definition: string.c:592
static HRESULT(WINAPI *pStrRetToBSTR)(STRRET *
INT WINAPI StrCmpNIA(LPCSTR lpszStr, LPCSTR lpszComp, INT iLen)
Definition: string.c:300
INT WINAPI StrCmpNA(LPCSTR lpszStr, LPCSTR lpszComp, INT iLen)
Definition: string.c:493
LPSTR WINAPI StrStrIA(LPCSTR lpszStr, LPCSTR lpszSearch)
Definition: string.c:355
LPSTR WINAPI lstrcpyA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:100
BOOL WINAPI StrToIntExW(LPCWSTR lpszStr, DWORD dwFlags, LPINT lpiRet)
Definition: string.c:970
#define LANG_ENGLISH
Definition: nls.h:52
static void test_SHUnicodeToUnicode(void)
Definition: string.c:958
LPSTR WINAPI StrDupA(LPCSTR lpszStr)
Definition: string.c:1064
int ret
LPWSTR WINAPI StrChrIW(LPCWSTR lpszStr, WCHAR ch)
Definition: string.c:635
Definition: ttei1.cpp:12
static void test_StrCpyNXW(void)
Definition: string.c:874
static LPCITEMIDLIST
Definition: string.c:61
static UINT
Definition: string.c:54
static void test_StrChrW(void)
Definition: string.c:264
static LPCSTR
Definition: string.c:33
#define STIF_SUPPORT_HEX
Definition: shlwapi.h:1452
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:821
LPWSTR WINAPI StrCpyW(LPWSTR lpszStr, LPCWSTR lpszSrc)
Definition: string.c:514
GLenum src
Definition: glext.h:6340
const char * byte_size_64
Definition: string.c:117
const char * kb_size2
Definition: string.c:120
#define E_NOT_SUFFICIENT_BUFFER
Definition: winerror.h:2345
static void test_StrRStrI(void)
Definition: string.c:900
#define WINAPIV
Definition: sdbpapi.h:64
#define broken(x)
Definition: _sntprintf.h:21
LPWSTR WINAPI StrStrW(LPCWSTR lpszStr, LPCWSTR lpszSearch)
Definition: string.c:594
static BOOL is_locale_english(void)
Definition: string.c:232
START_TEST(string)
Definition: string.c:3859
int WINAPI StrCmpW(LPCWSTR lpszStr, LPCWSTR lpszComp)
Definition: string.c:434
static const StrToIntResult StrToInt_results[]
Definition: string.c:87
#define S_OK
Definition: intsafe.h:59
static void test_StrToIntA(void)
Definition: string.c:457
static const WCHAR emptyW[]
Definition: navigate.c:40
const char * kb_size
Definition: string.c:118
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
#define ARRAY_SIZE(a)
Definition: main.h:24
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
#define ok(value,...)
Definition: atltest.h:57
static char int
Definition: string.c:71
#define expect(expected, got)
Definition: combo.c:36
static LPCWSTR
Definition: string.c:46
LPWSTR WINAPI StrChrW(LPCWSTR lpszStr, WCHAR ch)
Definition: string.c:468
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:274
static size_t const unsigned char size_t count
Definition: string.c:63
unsigned int UINT
Definition: ndis.h:50
LONGLONG str_to_int64_hex
Definition: string.c:84
static void test_StrToIntExW(void)
Definition: string.c:519
INT WINAPI StrToIntW(LPCWSTR lpString)
Definition: string.c:411
#define MultiByteToWideChar
Definition: compat.h:100
#define skip(...)
Definition: atltest.h:64
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:1964
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
static void test_StrStrNW(void)
Definition: string.c:1328
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:41
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define GetProcAddress(x, y)
Definition: compat.h:418
LANGID WINAPI GetUserDefaultLangID(void)
Definition: lang.c:734
static char * dest
Definition: rtl.c:135
INT WINAPI StrToIntA(LPCSTR lpszStr)
Definition: string.c:374
static void test_StrToInt64ExA(void)
Definition: string.c:554
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
static const StrFromTimeIntervalResult StrFromTimeInterval_results[]
Definition: string.c:152
LPWSTR WINAPI StrRChrW(LPCWSTR str, LPCWSTR end, WORD ch)
Definition: string.c:556
UINT uType
Definition: shtypes.idl:93
GLuint64EXT * result
Definition: glext.h:11304
#define memset(x, y, z)
Definition: compat.h:39
struct tagStrToIntResult StrToIntResult
#define win_skip
Definition: test.h:141
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:404
static void test_StrStrIA(void)
Definition: string.c:1224
struct tagStrFromTimeIntervalResult StrFromTimeIntervalResult
static LONGLONG(WINAPIV *p_atoi64)(const char *)
Definition: dsound.c:943
static void test_StrStrA(void)
Definition: string.c:1123
static LPWSTR
Definition: string.c:48
#define PRIMARYLANGID(l)
Definition: nls.h:16
static void test_StrStrW(void)
Definition: string.c:1170
INT WINAPI StrCmpNIW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen)
Definition: string.c:311