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