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; 82 int str_to_int; 83 LONGLONG str_to_int64_ex; 84 LONGLONG str_to_int64_hex; 85 } StrToIntResult; 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 */ 114 typedef struct tagStrFormatSizeResult 115 { 116 LONGLONG value; 117 const char* byte_size_64; 118 const char* kb_size; 119 int kb_size_broken; 120 const char* kb_size2; 121 } StrFormatSizeResult; 122 123 124 static const StrFormatSizeResult StrFormatSize_results[] = { 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 */ 144 typedef struct tagStrFromTimeIntervalResult 145 { 146 DWORD ms; 147 int digits; 148 const char* time_interval; 149 } StrFromTimeIntervalResult; 150 151 152 static const StrFromTimeIntervalResult StrFromTimeInterval_results[] = { 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 226 return PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH; 227 } 228 229 /* Returns true if the dates, numbers, etc. are formatted using English 230 * conventions. 231 */ 232 static BOOL is_locale_english(void) 233 { 234 /* Surprisingly GetThreadLocale() is irrelevant here */ 235 return PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH; 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]; 410 const StrFormatSizeResult* result = StrFormatSize_results; 411 LPWSTR lpRes; 412 413 while(result->value) 414 { 415 MultiByteToWideChar(CP_ACP,0,result->byte_size_64,-1,szSrc,sizeof(szSrc)/sizeof(WCHAR)); 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 { 459 const StrToIntResult *result = StrToInt_results; 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]; 474 const StrToIntResult *result = StrToInt_results; 475 int return_val; 476 477 while (result->string) 478 { 479 MultiByteToWideChar(CP_ACP,0,result->string,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR)); 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 { 489 const StrToIntResult *result = StrToInt_results; 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 505 result = StrToInt_results; 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]; 522 const StrToIntResult *result = StrToInt_results; 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,sizeof(szBuff)/sizeof(WCHAR)); 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 539 result = StrToInt_results; 540 while (result->string) 541 { 542 return_val = -1; 543 MultiByteToWideChar(CP_ACP,0,result->string,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR)); 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 { 556 const StrToIntResult *result = StrToInt_results; 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 578 result = StrToInt_results; 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]; 595 const StrToIntResult *result = StrToInt_results; 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,sizeof(szBuff)/sizeof(WCHAR)); 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 618 result = StrToInt_results; 619 while (result->string) 620 { 621 return_val = -1; 622 MultiByteToWideChar(CP_ACP,0,result->string,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR)); 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; 636 const StrFormatSizeResult* result = StrFormatSize_results; 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]; 662 const StrFormatSizeResult* result = StrFormatSize_results; 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]; 686 const StrFormatSizeResult* result = StrFormatSize_results; 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,sizeof(szBuff)/sizeof(WCHAR),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]; 708 const StrFormatSizeResult* result = StrFormatSize_results; 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]; 733 const StrFromTimeIntervalResult* result = StrFromTimeInterval_results; 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, sizeof(dest)/sizeof(dest[0])); 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, sizeof(dest)/sizeof(dest[0])); 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, sizeof(dest)/sizeof(dest[0])); 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, sizeof(dest)/sizeof(dest[0])); 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); 1066 if (hres == E_NOT_SUFFICIENT_BUFFER) 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 < sizeof(StrStrA_cases)/sizeof(StrStrA_cases[0]); 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 < sizeof(StrStrW_cases)/sizeof(StrStrW_cases[0]); 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 < sizeof(StrStrIA_cases)/sizeof(StrStrIA_cases[0]); 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 < sizeof(StrStrIW_cases)/sizeof(StrStrIW_cases[0]); 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, sizeof(deadbeefW)/sizeof(WCHAR), NULL}, 1347 {deadW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW}, 1348 {dead_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), NULL}, 1349 {adbeW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 2}, 1350 {adbe_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), NULL}, 1351 {beefW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 4}, 1352 {beef_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), 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 < sizeof(StrStrNW_cases)/sizeof(StrStrNW_cases[0]); 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, sizeof(deadbeefW)/sizeof(WCHAR), NULL}, 1430 {deadW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW}, 1431 {dead_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW}, 1432 {adbeW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 2}, 1433 {adbe_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 2}, 1434 {beefW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 4}, 1435 {beef_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 4}, 1436 {cafeW, sizeof(deadbeefW)/sizeof(WCHAR), 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 < sizeof(StrStrNIW_cases)/sizeof(StrStrNIW_cases[0]); 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 1630 GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, thousandDelim, 8); 1631 GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, decimalDelim, 8); 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(); 1675 test_StrToInt64ExA(); 1676 test_StrToInt64ExW(); 1677 test_StrDupA(); 1678 1679 /* language-dependent test */ 1680 if (is_lang_english() && is_locale_english()) 1681 { 1682 test_StrFormatByteSize64A(); 1683 test_StrFormatKBSizeA(); 1684 test_StrFormatKBSizeW(); 1685 } 1686 else 1687 skip("An English UI and locale is required for the StrFormat*Size tests\n"); 1688 if (is_lang_english()) 1689 test_StrFromTimeIntervalA(); 1690 else 1691 skip("An English UI is required for the StrFromTimeInterval tests\n"); 1692 1693 test_StrCmpA(); 1694 test_StrCmpW(); 1695 test_StrRetToBSTR(); 1696 test_StrCpyNXA(); 1697 test_StrCpyNXW(); 1698 test_StrRStrI(); 1699 test_SHAnsiToAnsi(); 1700 test_SHUnicodeToUnicode(); 1701 test_StrXXX_overflows(); 1702 test_StrStrA(); 1703 test_StrStrW(); 1704 test_StrStrIA(); 1705 test_StrStrIW(); 1706 test_StrStrNW(); 1707 test_StrStrNIW(); 1708 test_StrCatChainW(); 1709 1710 CoUninitialize(); 1711 } 1712