Reactos
at master 2023 lines 68 kB view raw
1/* Unit test suite for SHLWAPI string functions 2 * 3 * Copyright 2003 Jon Griffiths 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 */ 19 20#include <stdio.h> 21 22#include "wine/test.h" 23#include "winbase.h" 24#include "winerror.h" 25#include "winnls.h" 26#define NO_SHLWAPI_REG 27#define NO_SHLWAPI_PATH 28#define NO_SHLWAPI_GDI 29#define NO_SHLWAPI_STREAM 30#include "shlwapi.h" 31#include "shtypes.h" 32 33#define expect_eq(expr, val, type, fmt) do { \ 34 type ret = expr; \ 35 ok(ret == val, "Unexpected value of '" #expr "': " #fmt " instead of " #val "\n", ret); \ 36} while (0); 37 38#define expect_eq2(expr, val1, val2, type, fmt) do { \ 39 type ret = expr; \ 40 ok(ret == val1 || ret == val2, "Unexpected value of '" #expr "': " #fmt " instead of " #val1 " or " #val2 "\n", ret); \ 41} while (0); 42 43static BOOL (WINAPI *pChrCmpIA)(CHAR, CHAR); 44static BOOL (WINAPI *pChrCmpIW)(WCHAR, WCHAR); 45static BOOL (WINAPI *pIntlStrEqWorkerA)(BOOL,LPCSTR,LPCSTR,int); 46static BOOL (WINAPI *pIntlStrEqWorkerW)(BOOL,LPCWSTR,LPCWSTR,int); 47static DWORD (WINAPI *pSHAnsiToAnsi)(LPCSTR,LPSTR,int); 48static DWORD (WINAPI *pSHUnicodeToUnicode)(LPCWSTR,LPWSTR,int); 49static LPSTR (WINAPI *pStrCatBuffA)(LPSTR,LPCSTR,INT); 50static LPWSTR (WINAPI *pStrCatBuffW)(LPWSTR,LPCWSTR,INT); 51static DWORD (WINAPI *pStrCatChainW)(LPWSTR,DWORD,DWORD,LPCWSTR); 52static LPSTR (WINAPI *pStrCpyNXA)(LPSTR,LPCSTR,int); 53static LPWSTR (WINAPI *pStrCpyNXW)(LPWSTR,LPCWSTR,int); 54static LPSTR (WINAPI *pStrFormatByteSize64A)(LONGLONG,LPSTR,UINT); 55static HRESULT (WINAPI *pStrFormatByteSizeEx)(LONGLONG,SFBS_FLAGS,LPWSTR,UINT); 56static LPSTR (WINAPI *pStrFormatKBSizeA)(LONGLONG,LPSTR,UINT); 57static LPWSTR (WINAPI *pStrFormatKBSizeW)(LONGLONG,LPWSTR,UINT); 58static BOOL (WINAPI *pStrIsIntlEqualA)(BOOL,LPCSTR,LPCSTR,int); 59static BOOL (WINAPI *pStrIsIntlEqualW)(BOOL,LPCWSTR,LPCWSTR,int); 60static LPWSTR (WINAPI *pStrPBrkW)(LPCWSTR,LPCWSTR); 61static LPSTR (WINAPI *pStrRChrA)(LPCSTR,LPCSTR,WORD); 62static HRESULT (WINAPI *pStrRetToBSTR)(STRRET*,LPCITEMIDLIST,BSTR*); 63static HRESULT (WINAPI *pStrRetToBufA)(STRRET*,LPCITEMIDLIST,LPSTR,UINT); 64static HRESULT (WINAPI *pStrRetToBufW)(STRRET*,LPCITEMIDLIST,LPWSTR,UINT); 65static LPWSTR (WINAPI *pStrStrNW)(LPCWSTR,LPCWSTR,UINT); 66static LPWSTR (WINAPI *pStrStrNIW)(LPCWSTR,LPCWSTR,UINT); 67static INT (WINAPIV *pwnsprintfA)(LPSTR,INT,LPCSTR, ...); 68static INT (WINAPIV *pwnsprintfW)(LPWSTR,INT,LPCWSTR, ...); 69static LPWSTR (WINAPI *pStrChrNW)(LPCWSTR,WCHAR,UINT); 70static BOOL (WINAPI *pStrToInt64ExA)(LPCSTR,DWORD,LONGLONG*); 71static BOOL (WINAPI *pStrToInt64ExW)(LPCWSTR,DWORD,LONGLONG*); 72 73/* StrToInt/StrToIntEx results */ 74typedef struct tagStrToIntResult 75{ 76 const char* string; 77 int str_to_int; 78 LONGLONG str_to_int64_ex; 79 LONGLONG str_to_int64_hex; 80 BOOL failure; 81} StrToIntResult; 82 83static const StrToIntResult StrToInt_results[] = { 84 { "1099", 1099, 1099, 1099 }, 85 { "4294967319", 23, ((LONGLONG)1 << 32) | 23, ((LONGLONG)1 << 32) | 23 }, 86 { "+88987", 0, 88987, 88987 }, 87 { "012", 12, 12, 12 }, 88 { "-55", -55, -55, -55 }, 89 { "-0", 0, 0, 0 }, 90 { "0x44ff", 0, 0, 0x44ff }, 91 { "0x2bdc546291f4b1", 0, 0, ((LONGLONG)0x2bdc54 << 32) | 0x6291f4b1 }, 92 { "+0x44f4", 0, 0, 0x44f4 }, 93 { "-0x44fd", 0, 0, 0x44fd }, 94 { "+ 88987", 0, 0, 0, TRUE }, 95 96 { "- 55", 0, 0, 0, TRUE }, 97 { "- 0", 0, 0, 0, TRUE }, 98 { "+ 0x44f4", 0, 0, 0, TRUE }, 99 { "--0x44fd", 0, 0, 0, TRUE }, 100 { " 1999", 0, 1999, 1999 }, 101 { " +88987", 0, 88987, 88987 }, 102 { " 012", 0, 12, 12 }, 103 { " -55", 0, -55, -55 }, 104 { " 0x44ff", 0, 0, 0x44ff }, 105 { " +0x44f4", 0, 0, 0x44f4 }, 106 { " -0x44fd", 0, 0, 0x44fd }, 107 { "\t\n +3", 0, 3, 3 }, 108 { "\v+4", 0, 0, 0, TRUE }, 109 { "\f+5", 0, 0, 0, TRUE }, 110 { "\r+6", 0, 0, 0, TRUE }, 111 { NULL, 0, 0, 0 } 112}; 113 114/* pStrFormatByteSize64/StrFormatKBSize results */ 115typedef struct tagStrFormatSizeResult 116{ 117 LONGLONG value; 118 const char* byte_size_64; 119 const char* kb_size; 120 int kb_size_broken; 121 const char* kb_size2; 122} StrFormatSizeResult; 123 124 125static const StrFormatSizeResult StrFormatSize_results[] = { 126 { -1023, "-1023 bytes", "0 KB"}, 127 { -24, "-24 bytes", "0 KB"}, 128 { 309, "309 bytes", "1 KB"}, 129 { 10191, "9.95 KB", "10 KB"}, 130 { 100353, "98.0 KB", "99 KB"}, 131 { 1022286, "998 KB", "999 KB"}, 132 { 1046862, "0.99 MB", "1,023 KB", 1, "1023 KB"}, 133 { 1048574619, "999 MB", "1,023,999 KB", 1, "1023999 KB"}, 134 { 1073741775, "0.99 GB", "1,048,576 KB", 1, "1048576 KB"}, 135 { ((LONGLONG)0x000000f9 << 32) | 0xfffff94e, "999 GB", "1,048,575,999 KB", 1, "1048575999 KB"}, 136 { ((LONGLONG)0x000000ff << 32) | 0xfffffa9b, "0.99 TB", "1,073,741,823 KB", 1, "1073741823 KB"}, 137 { ((LONGLONG)0x0003e7ff << 32) | 0xfffffa9b, "999 TB", "1,073,741,823,999 KB", 1, "4294967295 KB"}, 138 { ((LONGLONG)0x0003ffff << 32) | 0xfffffbe8, "0.99 PB", "1,099,511,627,775 KB", 1, "4294967295 KB"}, 139 { ((LONGLONG)0x0f9fffff << 32) | 0xfffffd35, "999 PB", "1,099,511,627,776,000 KB", 1, "0 KB"}, 140 { ((LONGLONG)0x0fffffff << 32) | 0xfffffa9b, "0.99 EB", "1,125,899,906,842,623 KB", 1, "4294967295 KB"}, 141 { 0, NULL, NULL } 142}; 143 144/* StrFromTimeIntervalA/StrFromTimeIntervalW results */ 145typedef struct tagStrFromTimeIntervalResult 146{ 147 DWORD ms; 148 int digits; 149 const char* time_interval; 150} StrFromTimeIntervalResult; 151 152 153static const StrFromTimeIntervalResult StrFromTimeInterval_results[] = { 154 { 1, 1, " 0 sec" }, 155 { 1, 2, " 0 sec" }, 156 { 1, 3, " 0 sec" }, 157 { 1, 4, " 0 sec" }, 158 { 1, 5, " 0 sec" }, 159 { 1, 6, " 0 sec" }, 160 { 1, 7, " 0 sec" }, 161 162 { 1000000, 1, " 10 min" }, 163 { 1000000, 2, " 16 min" }, 164 { 1000000, 3, " 16 min 40 sec" }, 165 { 1000000, 4, " 16 min 40 sec" }, 166 { 1000000, 5, " 16 min 40 sec" }, 167 { 1000000, 6, " 16 min 40 sec" }, 168 { 1000000, 7, " 16 min 40 sec" }, 169 170 { 1999999, 1, " 30 min" }, 171 { 1999999, 2, " 33 min" }, 172 { 1999999, 3, " 33 min 20 sec" }, 173 { 1999999, 4, " 33 min 20 sec" }, 174 { 1999999, 5, " 33 min 20 sec" }, 175 { 1999999, 6, " 33 min 20 sec" }, 176 { 1999999, 7, " 33 min 20 sec" }, 177 178 { 3999997, 1, " 1 hr" }, 179 { 3999997, 2, " 1 hr 6 min" }, 180 { 3999997, 3, " 1 hr 6 min 40 sec" }, 181 { 3999997, 4, " 1 hr 6 min 40 sec" }, 182 { 3999997, 5, " 1 hr 6 min 40 sec" }, 183 { 3999997, 6, " 1 hr 6 min 40 sec" }, 184 { 3999997, 7, " 1 hr 6 min 40 sec" }, 185 186 { 149999851, 7, " 41 hr 40 min 0 sec" }, 187 { 150999850, 1, " 40 hr" }, 188 { 150999850, 2, " 41 hr" }, 189 { 150999850, 3, " 41 hr 50 min" }, 190 { 150999850, 4, " 41 hr 56 min" }, 191 { 150999850, 5, " 41 hr 56 min 40 sec" }, 192 { 150999850, 6, " 41 hr 56 min 40 sec" }, 193 { 150999850, 7, " 41 hr 56 min 40 sec" }, 194 195 { 493999507, 1, " 100 hr" }, 196 { 493999507, 2, " 130 hr" }, 197 { 493999507, 3, " 137 hr" }, 198 { 493999507, 4, " 137 hr 10 min" }, 199 { 493999507, 5, " 137 hr 13 min" }, 200 { 493999507, 6, " 137 hr 13 min 20 sec" }, 201 { 493999507, 7, " 137 hr 13 min 20 sec" }, 202 203 { 0, 0, NULL } 204}; 205 206 207/* Returns true if the user interface is in English. Note that this does not 208 * presume of the formatting of dates, numbers, etc. 209 */ 210static BOOL is_lang_english(void) 211{ 212 static HMODULE hkernel32 = NULL; 213 static LANGID (WINAPI *pGetThreadUILanguage)(void) = NULL; 214 static LANGID (WINAPI *pGetUserDefaultUILanguage)(void) = NULL; 215 216 if (!hkernel32) 217 { 218 hkernel32 = GetModuleHandleA("kernel32.dll"); 219 pGetThreadUILanguage = (void*)GetProcAddress(hkernel32, "GetThreadUILanguage"); 220 pGetUserDefaultUILanguage = (void*)GetProcAddress(hkernel32, "GetUserDefaultUILanguage"); 221 } 222 if (pGetThreadUILanguage) 223 return PRIMARYLANGID(pGetThreadUILanguage()) == LANG_ENGLISH; 224 if (pGetUserDefaultUILanguage) 225 return PRIMARYLANGID(pGetUserDefaultUILanguage()) == LANG_ENGLISH; 226 227 return PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH; 228} 229 230/* Returns true if the dates, numbers, etc. are formatted using English 231 * conventions. 232 */ 233static BOOL is_locale_english(void) 234{ 235 /* Surprisingly GetThreadLocale() is irrelevant here */ 236 return PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH; 237} 238 239static void test_StrChrA(void) 240{ 241 char string[129]; 242 WORD count; 243 244 /* this test crashes on win2k SP4 */ 245 /*ok(!StrChrA(NULL,'\0'), "found a character in a NULL string!\n");*/ 246 247 for (count = 32; count < 128; count++) 248 string[count] = (char)count; 249 string[128] = '\0'; 250 251 for (count = 32; count < 128; count++) 252 { 253 LPSTR result = StrChrA(string+32, count); 254 INT pos = result - string; 255 ok(pos == count, "found char '%c' in wrong place: got %d, expected %d\n", count, pos, count); 256 } 257 258 for (count = 32; count < 128; count++) 259 { 260 LPSTR result = StrChrA(string+count+1, count); 261 ok(!result, "found char '%c' not in the string\n", count); 262 } 263} 264 265static void test_StrChrW(void) 266{ 267 WCHAR string[16385]; 268 WORD count; 269 270 /* this test crashes on win2k SP4 */ 271 /*ok(!StrChrW(NULL,'\0'), "found a character in a NULL string!\n");*/ 272 273 for (count = 32; count < 16384; count++) 274 string[count] = count; 275 string[16384] = '\0'; 276 277 for (count = 32; count < 16384; count++) 278 { 279 LPWSTR result = StrChrW(string+32, count); 280 ok((result - string) == count, "found char %d in wrong place\n", count); 281 } 282 283 for (count = 32; count < 16384; count++) 284 { 285 LPWSTR result = StrChrW(string+count+1, count); 286 ok(!result, "found char not in the string\n"); 287 } 288} 289 290static void test_StrChrIA(void) 291{ 292 char string[129]; 293 WORD count; 294 295 /* this test crashes on win2k SP4 */ 296 /*ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!\n");*/ 297 298 for (count = 32; count < 128; count++) 299 string[count] = (char)count; 300 string[128] = '\0'; 301 302 for (count = 'A'; count <= 'X'; count++) 303 { 304 LPSTR result = StrChrIA(string+32, count); 305 306 ok(result - string == count, "found char '%c' in wrong place\n", count); 307 ok(StrChrIA(result, count)!=NULL, "didn't find lowercase '%c'\n", count); 308 } 309 310 for (count = 'a'; count < 'z'; count++) 311 { 312 LPSTR result = StrChrIA(string+count+1, count); 313 ok(!result, "found char not in the string\n"); 314 } 315} 316 317static void test_StrChrIW(void) 318{ 319 WCHAR string[129]; 320 WORD count; 321 322 /* this test crashes on win2k SP4 */ 323 /*ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!\n");*/ 324 325 for (count = 32; count < 128; count++) 326 string[count] = count; 327 string[128] = '\0'; 328 329 for (count = 'A'; count <= 'X'; count++) 330 { 331 LPWSTR result = StrChrIW(string+32, count); 332 333 ok(result - string == count, "found char '%c' in wrong place\n", count); 334 ok(StrChrIW(result, count)!=NULL, "didn't find lowercase '%c'\n", count); 335 } 336 337 for (count = 'a'; count < 'z'; count++) 338 { 339 LPWSTR result = StrChrIW(string+count+1, count); 340 ok(!result, "found char not in the string\n"); 341 } 342} 343 344static void test_StrRChrA(void) 345{ 346 char string[129]; 347 WORD count; 348 349 /* this test crashes on win2k SP4 */ 350 /*ok(!StrRChrA(NULL, NULL,'\0'), "found a character in a NULL string!\n");*/ 351 352 for (count = 32; count < 128; count++) 353 string[count] = (char)count; 354 string[128] = '\0'; 355 356 for (count = 32; count < 128; count++) 357 { 358 LPSTR result = StrRChrA(string+32, NULL, count); 359 ok(result - string == count, "found char %d in wrong place\n", count); 360 } 361 362 for (count = 32; count < 128; count++) 363 { 364 LPSTR result = StrRChrA(string+count+1, NULL, count); 365 ok(!result, "found char not in the string\n"); 366 } 367 368 for (count = 32; count < 128; count++) 369 { 370 LPSTR result = StrRChrA(string+count+1, string + 127, count); 371 ok(!result, "found char not in the string\n"); 372 } 373} 374 375static void test_StrRChrW(void) 376{ 377 WCHAR string[129]; 378 WORD count; 379 380 /* this test crashes on win2k SP4 */ 381 /*ok(!StrRChrW(NULL, NULL,'\0'), "found a character in a NULL string!\n");*/ 382 383 for (count = 32; count < 128; count++) 384 string[count] = count; 385 string[128] = '\0'; 386 387 for (count = 32; count < 128; count++) 388 { 389 LPWSTR result = StrRChrW(string+32, NULL, count); 390 INT pos = result - string; 391 ok(pos == count, "found char %d in wrong place: got %d, expected %d\n", count, pos, count); 392 } 393 394 for (count = 32; count < 128; count++) 395 { 396 LPWSTR result = StrRChrW(string+count+1, NULL, count); 397 ok(!result, "found char %d not in the string\n", count); 398 } 399 400 for (count = 32; count < 128; count++) 401 { 402 LPWSTR result = StrRChrW(string+count+1, string + 127, count); 403 ok(!result, "found char %d not in the string\n", count); 404 } 405} 406 407static void test_StrCpyW(void) 408{ 409 WCHAR szSrc[256]; 410 WCHAR szBuff[256]; 411 const StrFormatSizeResult* result = StrFormatSize_results; 412 LPWSTR lpRes; 413 414 while(result->value) 415 { 416 MultiByteToWideChar(CP_ACP, 0, result->byte_size_64, -1, szSrc, ARRAY_SIZE(szSrc)); 417 418 lpRes = StrCpyW(szBuff, szSrc); 419 ok(!StrCmpW(szSrc, szBuff) && lpRes == szBuff, "Copied string %s wrong\n", result->byte_size_64); 420 result++; 421 } 422 423 /* this test crashes on win2k SP4 */ 424 /*lpRes = StrCpyW(szBuff, NULL);*/ 425 /*ok(lpRes == szBuff, "Wrong return value: got %p expected %p\n", lpRes, szBuff);*/ 426 427 /* this test crashes on win2k SP4 */ 428 /*lpRes = StrCpyW(NULL, szSrc);*/ 429 /*ok(lpRes == NULL, "Wrong return value: got %p expected NULL\n", lpRes);*/ 430 431 /* this test crashes on win2k SP4 */ 432 /*lpRes = StrCpyW(NULL, NULL);*/ 433 /*ok(lpRes == NULL, "Wrong return value: got %p expected NULL\n", lpRes);*/ 434} 435 436static void test_StrChrNW(void) 437{ 438 static const WCHAR string[] = {'T','e','s','t','i','n','g',' ','S','t','r','i','n','g',0}; 439 LPWSTR p; 440 441 if (!pStrChrNW) 442 { 443 win_skip("StrChrNW not available\n"); 444 return; 445 } 446 447 p = pStrChrNW(string,'t',10); 448 ok(*p=='t',"Found wrong 't'\n"); 449 ok(*(p+1)=='i',"next should be 'i'\n"); 450 451 p = pStrChrNW(string,'S',10); 452 ok(*p=='S',"Found wrong 'S'\n"); 453 454 p = pStrChrNW(string,'r',10); 455 ok(p==NULL,"Should not have found 'r'\n"); 456} 457 458static void test_StrToIntA(void) 459{ 460 const StrToIntResult *result = StrToInt_results; 461 int return_val; 462 463 while (result->string) 464 { 465 return_val = StrToIntA(result->string); 466 ok(return_val == result->str_to_int, "converted '%s' wrong (%d)\n", 467 result->string, return_val); 468 result++; 469 } 470} 471 472static void test_StrToIntW(void) 473{ 474 WCHAR szBuff[256]; 475 const StrToIntResult *result = StrToInt_results; 476 int return_val; 477 478 while (result->string) 479 { 480 MultiByteToWideChar(CP_ACP, 0, result->string, -1, szBuff, ARRAY_SIZE(szBuff)); 481 return_val = StrToIntW(szBuff); 482 ok(return_val == result->str_to_int, "converted '%s' wrong (%d)\n", 483 result->string, return_val); 484 result++; 485 } 486} 487 488static void test_StrToIntExA(void) 489{ 490 const StrToIntResult *result = StrToInt_results; 491 int return_val; 492 BOOL bRet; 493 494 while (result->string) 495 { 496 return_val = -1; 497 bRet = StrToIntExA(result->string,0,&return_val); 498 if (result->failure) 499 ok(!bRet, "Got %d instead of failure for '%s'\n", return_val, result->string); 500 else 501 ok(bRet, "Failed for '%s'\n", result->string); 502 if (bRet) 503 ok(return_val == (int)result->str_to_int64_ex, "converted '%s' wrong (%d)\n", 504 result->string, return_val); 505 result++; 506 } 507 508 result = StrToInt_results; 509 while (result->string) 510 { 511 return_val = -1; 512 bRet = StrToIntExA(result->string,STIF_SUPPORT_HEX,&return_val); 513 if (result->failure) 514 ok(!bRet, "Got %d instead of failure for '%s'\n", return_val, result->string); 515 else 516 ok(bRet, "Failed for '%s'\n", 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 524static 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, ARRAY_SIZE(szBuff)); 535 bRet = StrToIntExW(szBuff, 0, &return_val); 536 if (result->failure) 537 ok(!bRet, "Got %d instead of failure for '%s'\n", return_val, result->string); 538 else 539 ok(bRet, "Failed for '%s'\n", result->string); 540 if (bRet) 541 ok(return_val == (int)result->str_to_int64_ex, "converted '%s' wrong (%d)\n", 542 result->string, return_val); 543 result++; 544 } 545 546 result = StrToInt_results; 547 while (result->string) 548 { 549 return_val = -1; 550 MultiByteToWideChar(CP_ACP, 0, result->string, -1, szBuff, ARRAY_SIZE(szBuff)); 551 bRet = StrToIntExW(szBuff, STIF_SUPPORT_HEX, &return_val); 552 if (result->failure) 553 ok(!bRet, "Got %d instead of failure for '%s'\n", return_val, result->string); 554 else 555 ok(bRet, "Failed for '%s'\n", result->string); 556 if (bRet) 557 ok(return_val == (int)result->str_to_int64_hex, "converted '%s' wrong (%d)\n", 558 result->string, return_val); 559 result++; 560 } 561 562 return_val = -1; 563 bRet = StrToIntExW(L"\x0661\x0662", 0, &return_val); 564 ok( !bRet, "Returned %d for Unicode digits\n", return_val ); 565 bRet = StrToIntExW(L"\x07c3\x07c4", 0, &return_val); 566 ok( !bRet, "Returned %d for Unicode digits\n", return_val ); 567 bRet = StrToIntExW(L"\xa0-2", 0, &return_val); 568 ok( !bRet, "Returned %d for Unicode space\n", return_val ); 569} 570 571static void test_StrToInt64ExA(void) 572{ 573 const StrToIntResult *result = StrToInt_results; 574 LONGLONG return_val; 575 BOOL bRet; 576 577 if (!pStrToInt64ExA) 578 { 579 win_skip("StrToInt64ExA() is not available\n"); 580 return; 581 } 582 583 while (result->string) 584 { 585 return_val = -1; 586 bRet = pStrToInt64ExA(result->string,0,&return_val); 587 if (result->failure) 588 ok(!bRet, "Got %s instead of failure for '%s'\n", 589 wine_dbgstr_longlong(return_val), result->string); 590 else 591 ok(bRet, "Failed for '%s'\n", result->string); 592 if (bRet) 593 ok(return_val == result->str_to_int64_ex, "converted '%s' wrong (%s)\n", 594 result->string, wine_dbgstr_longlong(return_val)); 595 result++; 596 } 597 598 result = StrToInt_results; 599 while (result->string) 600 { 601 return_val = -1; 602 bRet = pStrToInt64ExA(result->string,STIF_SUPPORT_HEX,&return_val); 603 if (result->failure) 604 ok(!bRet, "Got %s instead of failure for '%s'\n", 605 wine_dbgstr_longlong(return_val), result->string); 606 else 607 ok(bRet, "Failed for '%s'\n", result->string); 608 if (bRet) 609 ok(return_val == result->str_to_int64_hex, "converted '%s' wrong (%s)\n", 610 result->string, wine_dbgstr_longlong(return_val)); 611 result++; 612 } 613} 614 615static void test_StrToInt64ExW(void) 616{ 617 WCHAR szBuff[256]; 618 const StrToIntResult *result = StrToInt_results; 619 LONGLONG return_val; 620 BOOL bRet; 621 622 if (!pStrToInt64ExW) 623 { 624 win_skip("StrToInt64ExW() is not available\n"); 625 return; 626 } 627 628 while (result->string) 629 { 630 return_val = -1; 631 MultiByteToWideChar(CP_ACP, 0, result->string, -1, szBuff, ARRAY_SIZE(szBuff)); 632 bRet = pStrToInt64ExW(szBuff, 0, &return_val); 633 if (result->failure) 634 ok(!bRet, "Got %s instead of failure for '%s'\n", 635 wine_dbgstr_longlong(return_val), result->string); 636 else 637 ok(bRet, "Failed for '%s'\n", result->string); 638 if (bRet) 639 ok(return_val == result->str_to_int64_ex, "converted '%s' wrong (%s)\n", 640 result->string, wine_dbgstr_longlong(return_val)); 641 result++; 642 } 643 644 result = StrToInt_results; 645 while (result->string) 646 { 647 return_val = -1; 648 MultiByteToWideChar(CP_ACP, 0, result->string, -1, szBuff, ARRAY_SIZE(szBuff)); 649 bRet = pStrToInt64ExW(szBuff, STIF_SUPPORT_HEX, &return_val); 650 if (result->failure) 651 ok(!bRet, "Got %s instead of failure for '%s'\n", 652 wine_dbgstr_longlong(return_val), result->string); 653 else 654 ok(bRet, "Failed for '%s'\n", result->string); 655 if (bRet) 656 ok(return_val == result->str_to_int64_hex, "converted '%s' wrong (%s)\n", 657 result->string, wine_dbgstr_longlong(return_val)); 658 result++; 659 } 660 661 return_val = -1; 662 bRet = pStrToInt64ExW(L"\x0661\x0662", 0, &return_val); 663 ok( !bRet, "Returned %s for Unicode digits\n", wine_dbgstr_longlong(return_val) ); 664 bRet = pStrToInt64ExW(L"\x07c3\x07c4", 0, &return_val); 665 ok( !bRet, "Returned %s for Unicode digits\n", wine_dbgstr_longlong(return_val) ); 666 bRet = pStrToInt64ExW(L"\xa0-2", 0, &return_val); 667 ok( !bRet, "Returned %s for Unicode space\n", wine_dbgstr_longlong(return_val) ); 668} 669 670static void test_StrDupA(void) 671{ 672 LPSTR lpszStr; 673 const StrFormatSizeResult* result = StrFormatSize_results; 674 675 while(result->value) 676 { 677 lpszStr = StrDupA(result->byte_size_64); 678 679 ok(lpszStr != NULL, "Dup failed\n"); 680 if (lpszStr) 681 { 682 ok(!strcmp(result->byte_size_64, lpszStr), "Copied string wrong\n"); 683 LocalFree(lpszStr); 684 } 685 result++; 686 } 687 688 /* Later versions of shlwapi return NULL for this, but earlier versions 689 * returned an empty string (as Wine does). 690 */ 691 lpszStr = StrDupA(NULL); 692 ok(lpszStr == NULL || *lpszStr == '\0', "NULL string returned %p\n", lpszStr); 693 LocalFree(lpszStr); 694} 695 696static void test_StrFormatByteSize64A(void) 697{ 698 char szBuff[256]; 699 const StrFormatSizeResult* result = StrFormatSize_results; 700 701 if (!pStrFormatByteSize64A) 702 { 703 win_skip("StrFormatByteSize64A() is not available\n"); 704 return; 705 } 706 707 while(result->value) 708 { 709 pStrFormatByteSize64A(result->value, szBuff, 256); 710 711 ok(!strcmp(result->byte_size_64, szBuff), 712 "Formatted %s wrong: got %s, expected %s\n", 713 wine_dbgstr_longlong(result->value), szBuff, result->byte_size_64); 714 715 result++; 716 } 717} 718 719static void test_StrFormatByteSizeEx(void) 720{ 721 WCHAR szBuff[256]; 722 HRESULT hr; 723 LONGLONG test_value = 2147483647; 724 725 if (!pStrFormatByteSizeEx) 726 { 727 win_skip("StrFormatByteSizeEx is not available \n"); 728 return; 729 } 730 731 hr = pStrFormatByteSizeEx(0xdeadbeef, 732 SFBS_FLAGS_TRUNCATE_UNDISPLAYED_DECIMAL_DIGITS, szBuff, 0); 733 ok(hr == E_INVALIDARG, "Unexpected hr: %#lx expected: %#lx\n", hr, E_INVALIDARG); 734 735 hr = pStrFormatByteSizeEx(0xdeadbeef, 10, szBuff, 256); 736 ok(hr == E_INVALIDARG, "Unexpected hr: %#lx expected: %#lx\n", hr, E_INVALIDARG); 737 738 hr = pStrFormatByteSizeEx(test_value, SFBS_FLAGS_ROUND_TO_NEAREST_DISPLAYED_DIGIT, 739 szBuff, 256); 740 ok(hr == S_OK, "Invalid arguments \n"); 741 ok(!wcscmp(szBuff, L"2.00 GB"), "Formatted %s wrong: got %ls, expected 2.00 GB\n", 742 wine_dbgstr_longlong(test_value), szBuff); 743 744 hr = pStrFormatByteSizeEx(test_value, SFBS_FLAGS_TRUNCATE_UNDISPLAYED_DECIMAL_DIGITS, 745 szBuff, 256); 746 ok(hr == S_OK, "Invalid arguments \n"); 747 ok(!wcscmp(szBuff, L"1.99 GB"), "Formatted %s wrong: got %ls, expected 1.99 GB\n", 748 wine_dbgstr_longlong(test_value), szBuff); 749} 750 751static void test_StrFormatKBSizeW(void) 752{ 753 WCHAR szBuffW[256]; 754 char szBuff[256]; 755 const StrFormatSizeResult* result = StrFormatSize_results; 756 757 if (!pStrFormatKBSizeW) 758 { 759 win_skip("StrFormatKBSizeW() is not available\n"); 760 return; 761 } 762 763 while(result->value) 764 { 765 pStrFormatKBSizeW(result->value, szBuffW, 256); 766 WideCharToMultiByte(CP_ACP, 0, szBuffW, -1, szBuff, ARRAY_SIZE(szBuff), NULL, NULL); 767 768 ok(!strcmp(result->kb_size, szBuff), "Formatted %s wrong: got %s, expected %s\n", 769 wine_dbgstr_longlong(result->value), szBuff, result->kb_size); 770 result++; 771 } 772} 773 774static void test_StrFormatKBSizeA(void) 775{ 776 char szBuff[256]; 777 const StrFormatSizeResult* result = StrFormatSize_results; 778 779 if (!pStrFormatKBSizeA) 780 { 781 win_skip("StrFormatKBSizeA() is not available\n"); 782 return; 783 } 784 785 while(result->value) 786 { 787 pStrFormatKBSizeA(result->value, szBuff, 256); 788 789 /* shlwapi on Win98 SE does not appear to apply delimiters to the output 790 * and does not correctly handle extremely large values. */ 791 ok(!strcmp(result->kb_size, szBuff) || 792 (result->kb_size_broken && !strcmp(result->kb_size2, szBuff)), 793 "Formatted %s wrong: got %s, expected %s\n", 794 wine_dbgstr_longlong(result->value), szBuff, result->kb_size); 795 result++; 796 } 797} 798 799static void test_StrFromTimeIntervalA(void) 800{ 801 char szBuff[256]; 802 const StrFromTimeIntervalResult* result = StrFromTimeInterval_results; 803 804 while(result->ms) 805 { 806 StrFromTimeIntervalA(szBuff, 256, result->ms, result->digits); 807 808 ok(!strcmp(result->time_interval, szBuff), "Formatted %ld %d wrong: %s\n", 809 result->ms, result->digits, szBuff); 810 result++; 811 } 812} 813 814static void test_StrCmpA(void) 815{ 816 static const char str1[] = {'a','b','c','d','e','f'}; 817 static const char str2[] = {'a','B','c','d','e','f'}; 818 ok(0 != StrCmpNA(str1, str2, 6), "StrCmpNA is case-insensitive\n"); 819 ok(0 == StrCmpNIA(str1, str2, 6), "StrCmpNIA is case-sensitive\n"); 820 if (pChrCmpIA) { 821 ok(!pChrCmpIA('a', 'a'), "ChrCmpIA doesn't work at all!\n"); 822 ok(!pChrCmpIA('b', 'B'), "ChrCmpIA is not case-insensitive\n"); 823 ok(pChrCmpIA('a', 'z'), "ChrCmpIA believes that a == z!\n"); 824 } 825 else 826 win_skip("ChrCmpIA() is not available\n"); 827 828 if (pStrIsIntlEqualA) 829 { 830 ok(pStrIsIntlEqualA(FALSE, str1, str2, 5), "StrIsIntlEqualA(FALSE,...) isn't case-insensitive\n"); 831 ok(!pStrIsIntlEqualA(TRUE, str1, str2, 5), "StrIsIntlEqualA(TRUE,...) isn't case-sensitive\n"); 832 } 833 else 834 win_skip("StrIsIntlEqualA() is not available\n"); 835 836 if (pIntlStrEqWorkerA) 837 { 838 ok(pIntlStrEqWorkerA(FALSE, str1, str2, 5), "IntlStrEqWorkerA(FALSE,...) isn't case-insensitive\n"); 839 ok(!pIntlStrEqWorkerA(TRUE, str1, str2, 5), "pIntlStrEqWorkerA(TRUE,...) isn't case-sensitive\n"); 840 } 841 else 842 win_skip("IntlStrEqWorkerA() is not available\n"); 843} 844 845static void test_StrCmpW(void) 846{ 847 static const WCHAR str1[] = {'a','b','c','d','e','f'}; 848 static const WCHAR str2[] = {'a','B','c','d','e','f'}; 849 ok(0 != StrCmpNW(str1, str2, 5), "StrCmpNW is case-insensitive\n"); 850 ok(0 == StrCmpNIW(str1, str2, 5), "StrCmpNIW is case-sensitive\n"); 851 if (pChrCmpIW) { 852 ok(!pChrCmpIW('a', 'a'), "ChrCmpIW doesn't work at all!\n"); 853 ok(!pChrCmpIW('b', 'B'), "ChrCmpIW is not case-insensitive\n"); 854 ok(pChrCmpIW('a', 'z'), "ChrCmpIW believes that a == z!\n"); 855 } 856 else 857 win_skip("ChrCmpIW() is not available\n"); 858 859 if (pStrIsIntlEqualW) 860 { 861 ok(pStrIsIntlEqualW(FALSE, str1, str2, 5), "StrIsIntlEqualW(FALSE,...) isn't case-insensitive\n"); 862 ok(!pStrIsIntlEqualW(TRUE, str1, str2, 5), "StrIsIntlEqualW(TRUE,...) isn't case-sensitive\n"); 863 } 864 else 865 win_skip("StrIsIntlEqualW() is not available\n"); 866 867 if (pIntlStrEqWorkerW) 868 { 869 ok(pIntlStrEqWorkerW(FALSE, str1, str2, 5), "IntlStrEqWorkerW(FALSE,...) isn't case-insensitive\n"); 870 ok(!pIntlStrEqWorkerW(TRUE, str1, str2, 5), "IntlStrEqWorkerW(TRUE,...) isn't case-sensitive\n"); 871 } 872 else 873 win_skip("IntlStrEqWorkerW() is not available\n"); 874} 875 876static WCHAR *CoDupStrW(const char* src) 877{ 878 INT len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0); 879 WCHAR* szTemp = CoTaskMemAlloc(len * sizeof(WCHAR)); 880 MultiByteToWideChar(CP_ACP, 0, src, -1, szTemp, len); 881 return szTemp; 882} 883 884static void test_StrRetToBSTR(void) 885{ 886 static const WCHAR szTestW[] = { 'T','e','s','t','\0' }; 887 ITEMIDLIST iidl[10]; 888 BSTR bstr; 889 STRRET strret; 890 HRESULT ret; 891 892 if (!pStrRetToBSTR) 893 { 894 win_skip("StrRetToBSTR() is not available\n"); 895 return; 896 } 897 898 strret.uType = STRRET_WSTR; 899 strret.pOleStr = CoDupStrW("Test"); 900 bstr = 0; 901 ret = pStrRetToBSTR(&strret, NULL, &bstr); 902 ok(ret == S_OK && bstr && !wcscmp(bstr, szTestW), 903 "STRRET_WSTR: dup failed, ret=0x%08lx, bstr %p\n", ret, bstr); 904 SysFreeString(bstr); 905 906 strret.uType = STRRET_CSTR; 907 lstrcpyA(strret.cStr, "Test"); 908 ret = pStrRetToBSTR(&strret, NULL, &bstr); 909 ok(ret == S_OK && bstr && !wcscmp(bstr, szTestW), 910 "STRRET_CSTR: dup failed, ret=0x%08lx, bstr %p\n", ret, bstr); 911 SysFreeString(bstr); 912 913 strret.uType = STRRET_OFFSET; 914 strret.uOffset = 1; 915 strcpy((char*)&iidl, " Test"); 916 ret = pStrRetToBSTR(&strret, iidl, &bstr); 917 ok(ret == S_OK && bstr && !wcscmp(bstr, szTestW), 918 "STRRET_OFFSET: dup failed, ret=0x%08lx, bstr %p\n", ret, bstr); 919 SysFreeString(bstr); 920 921 /* Native crashes if str is NULL */ 922} 923 924static void test_StrCpyNXA(void) 925{ 926 LPCSTR lpSrc = "hello"; 927 LPSTR lpszRes; 928 char dest[8]; 929 930 if (!pStrCpyNXA) 931 { 932 win_skip("StrCpyNXA() is not available\n"); 933 return; 934 } 935 936 memset(dest, '\n', sizeof(dest)); 937 lpszRes = pStrCpyNXA(dest, lpSrc, ARRAY_SIZE(dest)); 938 ok(lpszRes == dest + 5 && !memcmp(dest, "hello\0\n\n", sizeof(dest)), 939 "StrCpyNXA: expected %p, \"hello\\0\\n\\n\", got %p, \"%d,%d,%d,%d,%d,%d,%d,%d\"\n", 940 dest + 5, lpszRes, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); 941} 942 943static void test_StrCpyNXW(void) 944{ 945 static const WCHAR lpInit[] = { '\n','\n','\n','\n','\n','\n','\n','\n' }; 946 static const WCHAR lpSrc[] = { 'h','e','l','l','o','\0' }; 947 static const WCHAR lpRes[] = { 'h','e','l','l','o','\0','\n','\n' }; 948 LPWSTR lpszRes; 949 WCHAR dest[8]; 950 951 if (!pStrCpyNXW) 952 { 953 win_skip("StrCpyNXW() is not available\n"); 954 return; 955 } 956 957 memcpy(dest, lpInit, sizeof(lpInit)); 958 lpszRes = pStrCpyNXW(dest, lpSrc, ARRAY_SIZE(dest)); 959 ok(lpszRes == dest + 5 && !memcmp(dest, lpRes, sizeof(dest)), 960 "StrCpyNXW: expected %p, \"hello\\0\\n\\n\", got %p, \"%d,%d,%d,%d,%d,%d,%d,%d\"\n", 961 dest + 5, lpszRes, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); 962} 963 964#define check_strrstri(type, str, pos, needle, exp) \ 965 ret##type = StrRStrI##type(str, str+pos, needle); \ 966 ok(ret##type == (exp), "Type " #type ", expected %p but got %p (string base %p)\n", \ 967 (exp), ret##type, str); 968 969static void test_StrRStrI(void) 970{ 971 static const CHAR szTest[] = "yAxxxxAy"; 972 static const CHAR szTest2[] = "ABABABAB"; 973 static const WCHAR wszTest[] = {'y','A','x','x','x','x','A','y',0}; 974 static const WCHAR wszTest2[] = {'A','B','A','B','A','B','A','B',0}; 975 976 static const WCHAR wszPattern1[] = {'A',0}; 977 static const WCHAR wszPattern2[] = {'a','X',0}; 978 static const WCHAR wszPattern3[] = {'A','y',0}; 979 static const WCHAR wszPattern4[] = {'a','b',0}; 980 LPWSTR retW; 981 LPSTR retA; 982 983 check_strrstri(A, szTest, 4, "A", szTest+1); 984 check_strrstri(A, szTest, 4, "aX", szTest+1); 985 check_strrstri(A, szTest, 4, "Ay", NULL); 986 check_strrstri(W, wszTest, 4, wszPattern1, wszTest+1); 987 check_strrstri(W, wszTest, 4, wszPattern2, wszTest+1); 988 check_strrstri(W, wszTest, 4, wszPattern3, NULL); 989 990 check_strrstri(A, szTest2, 4, "ab", szTest2+2); 991 check_strrstri(A, szTest2, 3, "ab", szTest2+2); 992 check_strrstri(A, szTest2, 2, "ab", szTest2); 993 check_strrstri(A, szTest2, 1, "ab", szTest2); 994 check_strrstri(A, szTest2, 0, "ab", NULL); 995 check_strrstri(W, wszTest2, 4, wszPattern4, wszTest2+2); 996 check_strrstri(W, wszTest2, 3, wszPattern4, wszTest2+2); 997 check_strrstri(W, wszTest2, 2, wszPattern4, wszTest2); 998 check_strrstri(W, wszTest2, 1, wszPattern4, wszTest2); 999 check_strrstri(W, wszTest2, 0, wszPattern4, NULL); 1000 1001} 1002 1003static void test_SHAnsiToAnsi(void) 1004{ 1005 char dest[8]; 1006 DWORD dwRet; 1007 1008 if (!pSHAnsiToAnsi) 1009 { 1010 win_skip("SHAnsiToAnsi() is not available\n"); 1011 return; 1012 } 1013 1014 if (pSHAnsiToAnsi == (void *)pStrPBrkW) 1015 { 1016 win_skip("Ordinal 345 corresponds to StrPBrkW, skipping SHAnsiToAnsi tests\n"); 1017 return; 1018 } 1019 1020 memset(dest, '\n', sizeof(dest)); 1021 dwRet = pSHAnsiToAnsi("hello", dest, ARRAY_SIZE(dest)); 1022 ok(dwRet == 6 && !memcmp(dest, "hello\0\n\n", sizeof(dest)), 1023 "SHAnsiToAnsi: expected 6, \"hello\\0\\n\\n\", got %ld, \"%d,%d,%d,%d,%d,%d,%d,%d\"\n", 1024 dwRet, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); 1025} 1026 1027static void test_SHUnicodeToUnicode(void) 1028{ 1029 static const WCHAR lpInit[] = { '\n','\n','\n','\n','\n','\n','\n','\n' }; 1030 static const WCHAR lpSrc[] = { 'h','e','l','l','o','\0' }; 1031 static const WCHAR lpRes[] = { 'h','e','l','l','o','\0','\n','\n' }; 1032 WCHAR dest[8]; 1033 DWORD dwRet; 1034 1035 if (!pSHUnicodeToUnicode) 1036 { 1037 win_skip("SHUnicodeToUnicode() is not available\n"); 1038 return; 1039 } 1040 1041 if (pSHUnicodeToUnicode == (void *)pStrRChrA) 1042 { 1043 win_skip("Ordinal 346 corresponds to StrRChrA, skipping SHUnicodeToUnicode tests\n"); 1044 return; 1045 } 1046 1047 memcpy(dest, lpInit, sizeof(lpInit)); 1048 dwRet = pSHUnicodeToUnicode(lpSrc, dest, ARRAY_SIZE(dest)); 1049 ok(dwRet == 6 && !memcmp(dest, lpRes, sizeof(dest)), 1050 "SHUnicodeToUnicode: expected 6, \"hello\\0\\n\\n\", got %ld, \"%d,%d,%d,%d,%d,%d,%d,%d\"\n", 1051 dwRet, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); 1052} 1053 1054static void test_StrXXX_overflows(void) 1055{ 1056 CHAR str1[2*MAX_PATH+1], buf[2*MAX_PATH]; 1057 WCHAR wstr1[2*MAX_PATH+1], wbuf[2*MAX_PATH]; 1058 const WCHAR fmt[] = {'%','s',0}; 1059 STRRET strret; 1060 HRESULT hres; 1061 int ret; 1062 int i; 1063 1064 for (i=0; i<2*MAX_PATH; i++) 1065 { 1066 str1[i] = '0'+(i%10); 1067 wstr1[i] = '0'+(i%10); 1068 } 1069 str1[2*MAX_PATH] = 0; 1070 wstr1[2*MAX_PATH] = 0; 1071 1072 memset(buf, 0xbf, sizeof(buf)); 1073 expect_eq(StrCpyNA(buf, str1, 10), buf, PCHAR, "%p"); 1074 expect_eq(buf[9], 0, CHAR, "%x"); 1075 expect_eq(buf[10], '\xbf', CHAR, "%x"); 1076 1077 if (pStrCatBuffA) 1078 { 1079 expect_eq(pStrCatBuffA(buf, str1, 100), buf, PCHAR, "%p"); 1080 expect_eq(buf[99], 0, CHAR, "%x"); 1081 expect_eq(buf[100], '\xbf', CHAR, "%x"); 1082 } 1083 else 1084 win_skip("StrCatBuffA() is not available\n"); 1085 1086if (0) 1087{ 1088 /* crashes on XP */ 1089 StrCpyNW(wbuf, (LPCWSTR)0x1, 10); 1090 StrCpyNW((LPWSTR)0x1, wstr1, 10); 1091} 1092 1093 memset(wbuf, 0xbf, sizeof(wbuf)); 1094 expect_eq(StrCpyNW(wbuf, (LPCWSTR)0x1, 1), wbuf, PWCHAR, "%p"); 1095 expect_eq(wbuf[0], 0, WCHAR, "%x"); 1096 expect_eq(wbuf[1], (WCHAR)0xbfbf, WCHAR, "%x"); 1097 1098 memset(wbuf, 0xbf, sizeof(wbuf)); 1099 expect_eq(StrCpyNW(wbuf, 0, 10), wbuf, PWCHAR, "%p"); 1100 expect_eq(wbuf[0], 0, WCHAR, "%x"); 1101 expect_eq(wbuf[1], (WCHAR)0xbfbf, WCHAR, "%x"); 1102 1103 memset(wbuf, 0xbf, sizeof(wbuf)); 1104 expect_eq(StrCpyNW(wbuf, 0, 0), wbuf, PWCHAR, "%p"); 1105 expect_eq(wbuf[0], (WCHAR)0xbfbf, WCHAR, "%x"); 1106 expect_eq(wbuf[1], (WCHAR)0xbfbf, WCHAR, "%x"); 1107 1108 memset(wbuf, 0xbf, sizeof(wbuf)); 1109 expect_eq(StrCpyNW(wbuf, wstr1, 0), wbuf, PWCHAR, "%p"); 1110 expect_eq(wbuf[0], (WCHAR)0xbfbf, WCHAR, "%x"); 1111 expect_eq(wbuf[1], (WCHAR)0xbfbf, WCHAR, "%x"); 1112 1113 memset(wbuf, 0xbf, sizeof(wbuf)); 1114 expect_eq(StrCpyNW(wbuf, wstr1, 10), wbuf, PWCHAR, "%p"); 1115 expect_eq(wbuf[9], 0, WCHAR, "%x"); 1116 expect_eq(wbuf[10], (WCHAR)0xbfbf, WCHAR, "%x"); 1117 1118 if (pStrCatBuffW) 1119 { 1120 expect_eq(pStrCatBuffW(wbuf, wstr1, 100), wbuf, PWCHAR, "%p"); 1121 expect_eq(wbuf[99], 0, WCHAR, "%x"); 1122 expect_eq(wbuf[100], (WCHAR)0xbfbf, WCHAR, "%x"); 1123 } 1124 else 1125 win_skip("StrCatBuffW() is not available\n"); 1126 1127 if (pStrRetToBufW) 1128 { 1129 memset(wbuf, 0xbf, sizeof(wbuf)); 1130 strret.uType = STRRET_WSTR; 1131 strret.pOleStr = StrDupW(wstr1); 1132 hres = pStrRetToBufW(&strret, NULL, wbuf, 10); 1133 ok(hres == E_NOT_SUFFICIENT_BUFFER || broken(hres == S_OK) /* winxp */, 1134 "StrRetToBufW returned %08lx\n", hres); 1135 if (hres == E_NOT_SUFFICIENT_BUFFER) 1136 expect_eq(wbuf[0], 0, WCHAR, "%x"); 1137 expect_eq(wbuf[9], 0, WCHAR, "%x"); 1138 expect_eq(wbuf[10], (WCHAR)0xbfbf, WCHAR, "%x"); 1139 1140 memset(wbuf, 0xbf, sizeof(wbuf)); 1141 strret.uType = STRRET_CSTR; 1142 StrCpyNA(strret.cStr, str1, MAX_PATH); 1143 hres = pStrRetToBufW(&strret, NULL, wbuf, 10); 1144 ok(hres == S_OK, "StrRetToBufW returned %08lx\n", hres); 1145 ok(!memcmp(wbuf, wstr1, 9*sizeof(WCHAR)) && !wbuf[9], "StrRetToBuf returned %s\n", wine_dbgstr_w(wbuf)); 1146 1147 memset(wbuf, 0xbf, sizeof(wbuf)); 1148 strret.uType = STRRET_WSTR; 1149 strret.pOleStr = NULL; 1150 hres = pStrRetToBufW(&strret, NULL, wbuf, 10); 1151 ok(hres == E_FAIL, "StrRetToBufW returned %08lx\n", hres); 1152 ok(!wbuf[0], "StrRetToBuf returned %s\n", wine_dbgstr_w(wbuf)); 1153 } 1154 else 1155 win_skip("StrRetToBufW() is not available\n"); 1156 1157 if (pStrRetToBufA) 1158 { 1159 memset(buf, 0xbf, sizeof(buf)); 1160 strret.uType = STRRET_CSTR; 1161 StrCpyNA(strret.cStr, str1, MAX_PATH); 1162 expect_eq2(pStrRetToBufA(&strret, NULL, buf, 10), S_OK, E_NOT_SUFFICIENT_BUFFER /* Vista */, HRESULT, "%lx"); 1163 expect_eq(buf[9], 0, CHAR, "%x"); 1164 expect_eq(buf[10], (CHAR)0xbf, CHAR, "%x"); 1165 } 1166 else 1167 win_skip("StrRetToBufA() is not available\n"); 1168 1169 if (pwnsprintfA) 1170 { 1171 memset(buf, 0xbf, sizeof(buf)); 1172 ret = pwnsprintfA(buf, 10, "%s", str1); 1173 ok(broken(ret == 9) || ret == -1 /* Vista */, "Unexpected wnsprintfA return %d, expected 9 or -1\n", ret); 1174 expect_eq(buf[9], 0, CHAR, "%x"); 1175 expect_eq(buf[10], (CHAR)0xbf, CHAR, "%x"); 1176 1177 memset(buf, 0xbf, sizeof(buf)); 1178 ret = pwnsprintfA(buf + 1, -1, "%s", str1); 1179#ifdef __REACTOS__ 1180 ok(ret == -1 || broken(ret == 0) /* WS03 */, "got %d.\n", ret); 1181#else 1182 ok(ret == -1, "got %d.\n", ret); 1183#endif 1184 expect_eq(buf[0], (CHAR)0xbf, CHAR, "%x"); 1185 if (!broken(1)) 1186 { 1187 /* This is 0xbf before Win8. */ 1188 expect_eq(buf[1], 0, CHAR, "%x"); 1189 } 1190 expect_eq(buf[2], (CHAR)0xbf, CHAR, "%x"); 1191 1192 memset(buf, 0xbf, sizeof(buf)); 1193 ret = pwnsprintfA(buf + 1, 0, "%s", str1); 1194#ifdef __REACTOS__ 1195 ok(ret == -1 || broken(ret == 0) /* WS03 */, "got %d.\n", ret); 1196#else 1197 ok(ret == -1, "got %d.\n", ret); 1198#endif 1199 expect_eq(buf[0], (CHAR)0xbf, CHAR, "%x"); 1200 expect_eq(buf[1], (CHAR)0xbf, CHAR, "%x"); 1201 1202 memset(buf, 0xbf, sizeof(buf)); 1203 ret = pwnsprintfA(buf, 1, ""); 1204 ok(!ret, "got %d.\n", ret); 1205 expect_eq(buf[0], 0, CHAR, "%x"); 1206 expect_eq(buf[1], (CHAR)0xbf, CHAR, "%x"); 1207 } 1208 else 1209 win_skip("wnsprintfA() is not available\n"); 1210 1211 if (pwnsprintfW) 1212 { 1213 memset(wbuf, 0xbf, sizeof(wbuf)); 1214 ret = pwnsprintfW(wbuf, 10, fmt, wstr1); 1215 ok(broken(ret == 9) || ret == -1 /* Vista */, "Unexpected wnsprintfW return %d, expected 9 or -1\n", ret); 1216 expect_eq(wbuf[9], 0, WCHAR, "%x"); 1217 expect_eq(wbuf[10], (WCHAR)0xbfbf, WCHAR, "%x"); 1218 1219 memset(wbuf, 0xbf, sizeof(wbuf)); 1220 ret = pwnsprintfW(wbuf + 1, -1, fmt, wstr1); 1221#ifdef __REACTOS__ 1222 ok(ret == -1 || broken(ret == 0) /* WS03 */, "got %d.\n", ret); 1223#else 1224 ok(ret == -1, "got %d.\n", ret); 1225#endif 1226 expect_eq(wbuf[0], (WCHAR)0xbfbf, WCHAR, "%x"); 1227 if (!broken(1)) 1228 { 1229 /* This is 0xbfbf before Win8. */ 1230 expect_eq(wbuf[1], 0, WCHAR, "%x"); 1231 } 1232 expect_eq(wbuf[2], (WCHAR)0xbfbf, WCHAR, "%x"); 1233 1234 memset(wbuf, 0xbf, sizeof(wbuf)); 1235 ret = pwnsprintfW(wbuf + 1, 0, fmt, wstr1); 1236#ifdef __REACTOS__ 1237 ok(ret == -1 || broken(ret == 0) /* WS03 */, "got %d.\n", ret); 1238#else 1239 ok(ret == -1, "got %d.\n", ret); 1240#endif 1241 expect_eq(wbuf[0], (WCHAR)0xbfbf, WCHAR, "%x"); 1242 expect_eq(wbuf[1], (WCHAR)0xbfbf, WCHAR, "%x"); 1243 1244 memset(wbuf, 0xbf, sizeof(wbuf)); 1245 ret = pwnsprintfW(wbuf, 1, L""); 1246 ok(!ret, "got %d.\n", ret); 1247 expect_eq(wbuf[0], 0, WCHAR, "%x"); 1248 expect_eq(wbuf[1], (WCHAR)0xbfbf, WCHAR, "%x"); 1249 } 1250 else 1251 win_skip("wnsprintfW() is not available\n"); 1252} 1253 1254static void test_StrStrA(void) 1255{ 1256 static const char *deadbeefA = "DeAdBeEf"; 1257 1258 const struct 1259 { 1260 const char *search; 1261 const char *expect; 1262 } StrStrA_cases[] = 1263 { 1264 {"", NULL}, 1265 {"DeAd", deadbeefA}, 1266 {"dead", NULL}, 1267 {"AdBe", deadbeefA + 2}, 1268 {"adbe", NULL}, 1269 {"BeEf", deadbeefA + 4}, 1270 {"beef", NULL}, 1271 }; 1272 1273 LPSTR ret; 1274 int i; 1275 1276 /* Tests crash on Win2k */ 1277 if (0) 1278 { 1279 ret = StrStrA(NULL, NULL); 1280 ok(!ret, "Expected StrStrA to return NULL, got %p\n", ret); 1281 1282 ret = StrStrA(NULL, ""); 1283 ok(!ret, "Expected StrStrA to return NULL, got %p\n", ret); 1284 1285 ret = StrStrA("", NULL); 1286 ok(!ret, "Expected StrStrA to return NULL, got %p\n", ret); 1287 } 1288 1289 ret = StrStrA("", ""); 1290 ok(!ret, "Expected StrStrA to return NULL, got %p\n", ret); 1291 1292 for (i = 0; i < ARRAY_SIZE(StrStrA_cases); i++) 1293 { 1294 ret = StrStrA(deadbeefA, StrStrA_cases[i].search); 1295 ok(ret == StrStrA_cases[i].expect, 1296 "[%d] Expected StrStrA to return %p, got %p\n", 1297 i, StrStrA_cases[i].expect, ret); 1298 } 1299} 1300 1301static void test_StrStrW(void) 1302{ 1303 static const WCHAR emptyW[] = {0}; 1304 static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0}; 1305 static const WCHAR deadW[] = {'D','e','A','d',0}; 1306 static const WCHAR dead_lowerW[] = {'d','e','a','d',0}; 1307 static const WCHAR adbeW[] = {'A','d','B','e',0}; 1308 static const WCHAR adbe_lowerW[] = {'a','d','b','e',0}; 1309 static const WCHAR beefW[] = {'B','e','E','f',0}; 1310 static const WCHAR beef_lowerW[] = {'b','e','e','f',0}; 1311 1312 const struct 1313 { 1314 const WCHAR *search; 1315 const WCHAR *expect; 1316 } StrStrW_cases[] = 1317 { 1318 {emptyW, NULL}, 1319 {deadW, deadbeefW}, 1320 {dead_lowerW, NULL}, 1321 {adbeW, deadbeefW + 2}, 1322 {adbe_lowerW, NULL}, 1323 {beefW, deadbeefW + 4}, 1324 {beef_lowerW, NULL}, 1325 }; 1326 1327 LPWSTR ret; 1328 int i; 1329 1330 /* Tests crash on Win2k */ 1331 if (0) 1332 { 1333 ret = StrStrW(NULL, NULL); 1334 ok(!ret, "Expected StrStrW to return NULL, got %p\n", ret); 1335 1336 ret = StrStrW(NULL, emptyW); 1337 ok(!ret, "Expected StrStrW to return NULL, got %p\n", ret); 1338 1339 ret = StrStrW(emptyW, NULL); 1340 ok(!ret, "Expected StrStrW to return NULL, got %p\n", ret); 1341 } 1342 1343 ret = StrStrW(emptyW, emptyW); 1344 ok(!ret, "Expected StrStrW to return NULL, got %p\n", ret); 1345 1346 for (i = 0; i < ARRAY_SIZE(StrStrW_cases); i++) 1347 { 1348 ret = StrStrW(deadbeefW, StrStrW_cases[i].search); 1349 ok(ret == StrStrW_cases[i].expect, 1350 "[%d] Expected StrStrW to return %p, got %p\n", 1351 i, StrStrW_cases[i].expect, ret); 1352 } 1353} 1354 1355static void test_StrStrIA(void) 1356{ 1357 static const char *deadbeefA = "DeAdBeEf"; 1358 1359 const struct 1360 { 1361 const char *search; 1362 const char *expect; 1363 } StrStrIA_cases[] = 1364 { 1365 {"", NULL}, 1366 {"DeAd", deadbeefA}, 1367 {"dead", deadbeefA}, 1368 {"AdBe", deadbeefA + 2}, 1369 {"adbe", deadbeefA + 2}, 1370 {"BeEf", deadbeefA + 4}, 1371 {"beef", deadbeefA + 4}, 1372 {"cafe", NULL}, 1373 }; 1374 1375 LPSTR ret; 1376 int i; 1377 1378 /* Tests crash on Win2k */ 1379 if (0) 1380 { 1381 ret = StrStrIA(NULL, NULL); 1382 ok(!ret, "Expected StrStrIA to return NULL, got %p\n", ret); 1383 1384 ret = StrStrIA(NULL, ""); 1385 ok(!ret, "Expected StrStrIA to return NULL, got %p\n", ret); 1386 1387 ret = StrStrIA("", NULL); 1388 ok(!ret, "Expected StrStrIA to return NULL, got %p\n", ret); 1389 } 1390 1391 ret = StrStrIA("", ""); 1392 ok(!ret, "Expected StrStrIA to return NULL, got %p\n", ret); 1393 1394 for (i = 0; i < ARRAY_SIZE(StrStrIA_cases); i++) 1395 { 1396 ret = StrStrIA(deadbeefA, StrStrIA_cases[i].search); 1397 ok(ret == StrStrIA_cases[i].expect, 1398 "[%d] Expected StrStrIA to return %p, got %p\n", 1399 i, StrStrIA_cases[i].expect, ret); 1400 } 1401} 1402 1403static void test_StrStrIW(void) 1404{ 1405 static const WCHAR emptyW[] = {0}; 1406 static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0}; 1407 static const WCHAR deadW[] = {'D','e','A','d',0}; 1408 static const WCHAR dead_lowerW[] = {'d','e','a','d',0}; 1409 static const WCHAR adbeW[] = {'A','d','B','e',0}; 1410 static const WCHAR adbe_lowerW[] = {'a','d','b','e',0}; 1411 static const WCHAR beefW[] = {'B','e','E','f',0}; 1412 static const WCHAR beef_lowerW[] = {'b','e','e','f',0}; 1413 static const WCHAR cafeW[] = {'c','a','f','e',0}; 1414 1415 const struct 1416 { 1417 const WCHAR *search; 1418 const WCHAR *expect; 1419 } StrStrIW_cases[] = 1420 { 1421 {emptyW, NULL}, 1422 {deadW, deadbeefW}, 1423 {dead_lowerW, deadbeefW}, 1424 {adbeW, deadbeefW + 2}, 1425 {adbe_lowerW, deadbeefW + 2}, 1426 {beefW, deadbeefW + 4}, 1427 {beef_lowerW, deadbeefW + 4}, 1428 {cafeW, NULL}, 1429 }; 1430 1431 LPWSTR ret; 1432 int i; 1433 1434 /* Tests crash on Win2k */ 1435 if (0) 1436 { 1437 ret = StrStrIW(NULL, NULL); 1438 ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret); 1439 1440 ret = StrStrIW(NULL, emptyW); 1441 ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret); 1442 1443 ret = StrStrIW(emptyW, NULL); 1444 ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret); 1445 } 1446 1447 ret = StrStrIW(emptyW, emptyW); 1448 ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret); 1449 1450 for (i = 0; i < ARRAY_SIZE(StrStrIW_cases); i++) 1451 { 1452 ret = StrStrIW(deadbeefW, StrStrIW_cases[i].search); 1453 ok(ret == StrStrIW_cases[i].expect, 1454 "[%d] Expected StrStrIW to return %p, got %p\n", 1455 i, StrStrIW_cases[i].expect, ret); 1456 } 1457} 1458 1459static void test_StrStrNW(void) 1460{ 1461 static const WCHAR emptyW[] = {0}; 1462 static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0}; 1463 static const WCHAR deadW[] = {'D','e','A','d',0}; 1464 static const WCHAR dead_lowerW[] = {'d','e','a','d',0}; 1465 static const WCHAR adbeW[] = {'A','d','B','e',0}; 1466 static const WCHAR adbe_lowerW[] = {'a','d','b','e',0}; 1467 static const WCHAR beefW[] = {'B','e','E','f',0}; 1468 static const WCHAR beef_lowerW[] = {'b','e','e','f',0}; 1469 1470 const struct 1471 { 1472 const WCHAR *search; 1473 const UINT count; 1474 const WCHAR *expect; 1475 } StrStrNW_cases[] = 1476 { 1477 {emptyW, ARRAY_SIZE(deadbeefW), NULL}, 1478 {deadW, ARRAY_SIZE(deadbeefW), deadbeefW}, 1479 {dead_lowerW, ARRAY_SIZE(deadbeefW), NULL}, 1480 {adbeW, ARRAY_SIZE(deadbeefW), deadbeefW + 2}, 1481 {adbe_lowerW, ARRAY_SIZE(deadbeefW), NULL}, 1482 {beefW, ARRAY_SIZE(deadbeefW), deadbeefW + 4}, 1483 {beef_lowerW, ARRAY_SIZE(deadbeefW), NULL}, 1484 {beefW, 0, NULL}, 1485 {beefW, 1, NULL}, 1486 {beefW, 2, NULL}, 1487 {beefW, 3, NULL}, 1488 {beefW, 4, NULL}, 1489 {beefW, 5, deadbeefW + 4}, 1490 {beefW, 6, deadbeefW + 4}, 1491 {beefW, 7, deadbeefW + 4}, 1492 {beefW, 8, deadbeefW + 4}, 1493 {beefW, 9, deadbeefW + 4}, 1494 }; 1495 1496 LPWSTR ret; 1497 UINT i; 1498 1499 if (!pStrStrNW) 1500 { 1501 win_skip("StrStrNW() is not available\n"); 1502 return; 1503 } 1504 1505 ret = pStrStrNW(NULL, NULL, 0); 1506 ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret); 1507 1508 ret = pStrStrNW(NULL, NULL, 10); 1509 ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret); 1510 1511 ret = pStrStrNW(NULL, emptyW, 10); 1512 ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret); 1513 1514 ret = pStrStrNW(emptyW, NULL, 10); 1515 ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret); 1516 1517 ret = pStrStrNW(emptyW, emptyW, 10); 1518 ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret); 1519 1520 for (i = 0; i < ARRAY_SIZE(StrStrNW_cases); i++) 1521 { 1522 ret = pStrStrNW(deadbeefW, StrStrNW_cases[i].search, StrStrNW_cases[i].count); 1523 ok(ret == StrStrNW_cases[i].expect, 1524 "[%d] Expected StrStrNW to return %p, got %p\n", 1525 i, StrStrNW_cases[i].expect, ret); 1526 } 1527 1528 /* StrStrNW accepts counts larger than the search string length but rejects 1529 * counts larger than around 2G. The limit seems to change based on the 1530 * caller executable itself. */ 1531 ret = pStrStrNW(deadbeefW, beefW, 100); 1532 ok(ret == deadbeefW + 4, "Expected StrStrNW to return deadbeefW + 4, got %p\n", ret); 1533 1534 if (0) 1535 { 1536 ret = pStrStrNW(deadbeefW, beefW, ~0U); 1537 ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret); 1538 } 1539} 1540 1541static void test_StrStrNIW(void) 1542{ 1543 static const WCHAR emptyW[] = {0}; 1544 static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0}; 1545 static const WCHAR deadW[] = {'D','e','A','d',0}; 1546 static const WCHAR dead_lowerW[] = {'d','e','a','d',0}; 1547 static const WCHAR adbeW[] = {'A','d','B','e',0}; 1548 static const WCHAR adbe_lowerW[] = {'a','d','b','e',0}; 1549 static const WCHAR beefW[] = {'B','e','E','f',0}; 1550 static const WCHAR beef_lowerW[] = {'b','e','e','f',0}; 1551 static const WCHAR cafeW[] = {'c','a','f','e',0}; 1552 1553 const struct 1554 { 1555 const WCHAR *search; 1556 const UINT count; 1557 const WCHAR *expect; 1558 } StrStrNIW_cases[] = 1559 { 1560 {emptyW, ARRAY_SIZE(deadbeefW), NULL}, 1561 {deadW, ARRAY_SIZE(deadbeefW), deadbeefW}, 1562 {dead_lowerW, ARRAY_SIZE(deadbeefW), deadbeefW}, 1563 {adbeW, ARRAY_SIZE(deadbeefW), deadbeefW + 2}, 1564 {adbe_lowerW, ARRAY_SIZE(deadbeefW), deadbeefW + 2}, 1565 {beefW, ARRAY_SIZE(deadbeefW), deadbeefW + 4}, 1566 {beef_lowerW, ARRAY_SIZE(deadbeefW), deadbeefW + 4}, 1567 {cafeW, ARRAY_SIZE(deadbeefW), NULL}, 1568 {beefW, 0, NULL}, 1569 {beefW, 1, NULL}, 1570 {beefW, 2, NULL}, 1571 {beefW, 3, NULL}, 1572 {beefW, 4, NULL}, 1573 {beefW, 5, deadbeefW + 4}, 1574 {beefW, 6, deadbeefW + 4}, 1575 {beefW, 7, deadbeefW + 4}, 1576 {beefW, 8, deadbeefW + 4}, 1577 {beefW, 9, deadbeefW + 4}, 1578 {beef_lowerW, 0, NULL}, 1579 {beef_lowerW, 1, NULL}, 1580 {beef_lowerW, 2, NULL}, 1581 {beef_lowerW, 3, NULL}, 1582 {beef_lowerW, 4, NULL}, 1583 {beef_lowerW, 5, deadbeefW + 4}, 1584 {beef_lowerW, 6, deadbeefW + 4}, 1585 {beef_lowerW, 7, deadbeefW + 4}, 1586 {beef_lowerW, 8, deadbeefW + 4}, 1587 {beef_lowerW, 9, deadbeefW + 4}, 1588 }; 1589 1590 LPWSTR ret; 1591 UINT i; 1592 1593 if (!pStrStrNIW) 1594 { 1595 win_skip("StrStrNIW() is not available\n"); 1596 return; 1597 } 1598 1599 ret = pStrStrNIW(NULL, NULL, 0); 1600 ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret); 1601 1602 ret = pStrStrNIW(NULL, NULL, 10); 1603 ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret); 1604 1605 ret = pStrStrNIW(NULL, emptyW, 10); 1606 ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret); 1607 1608 ret = pStrStrNIW(emptyW, NULL, 10); 1609 ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret); 1610 1611 ret = pStrStrNIW(emptyW, emptyW, 10); 1612 ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret); 1613 1614 for (i = 0; i < ARRAY_SIZE(StrStrNIW_cases); i++) 1615 { 1616 ret = pStrStrNIW(deadbeefW, StrStrNIW_cases[i].search, StrStrNIW_cases[i].count); 1617 ok(ret == StrStrNIW_cases[i].expect, 1618 "[%d] Expected StrStrNIW to return %p, got %p\n", 1619 i, StrStrNIW_cases[i].expect, ret); 1620 } 1621 1622 /* StrStrNIW accepts counts larger than the search string length but rejects 1623 * counts larger than around 2G. The limit seems to change based on the 1624 * caller executable itself. */ 1625 ret = pStrStrNIW(deadbeefW, beefW, 100); 1626 ok(ret == deadbeefW + 4, "Expected StrStrNIW to return deadbeefW + 4, got %p\n", ret); 1627 1628 if (0) 1629 { 1630 ret = pStrStrNIW(deadbeefW, beefW, ~0U); 1631 ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret); 1632 } 1633} 1634 1635static void test_StrCatChainW(void) 1636{ 1637 static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0}; 1638 static const WCHAR deadW[] = {'D','e','A','d',0}; 1639 static const WCHAR beefW[] = {'B','e','E','f',0}; 1640 1641 WCHAR buf[32 + 1]; 1642 DWORD ret; 1643 1644 if (!pStrCatChainW) 1645 { 1646 win_skip("StrCatChainW is not available\n"); 1647 return; 1648 } 1649 1650 /* Test with NULL buffer */ 1651 ret = pStrCatChainW(NULL, 0, 0, beefW); 1652 ok(ret == 0, "Expected StrCatChainW to return 0, got %lu\n", ret); 1653 1654 /* Test with empty buffer */ 1655 memset(buf, 0x11, sizeof(buf)); 1656 ret = pStrCatChainW(buf, 0, 0, beefW); 1657 ok(ret == 0, "Expected StrCatChainW to return 0, got %lu\n", ret); 1658 ok(buf[0] == 0x1111, "Expected buf[0] = 0x1111, got %x\n", buf[0]); 1659 1660 memcpy(buf, deadbeefW, sizeof(deadbeefW)); 1661 ret = pStrCatChainW(buf, 0, -1, beefW); 1662 ok(ret == 8, "Expected StrCatChainW to return 8, got %lu\n", ret); 1663 ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n"); 1664 1665 /* Append data to existing string with offset = -1 */ 1666 memset(buf, 0x11, sizeof(buf)); 1667 ret = pStrCatChainW(buf, 32, 0, deadW); 1668 ok(ret == 4, "Expected StrCatChainW to return 4, got %lu\n", ret); 1669 ok(!memcmp(buf, deadW, sizeof(deadW)), "Buffer contains wrong data\n"); 1670 1671 ret = pStrCatChainW(buf, 32, -1, beefW); 1672 ok(ret == 8, "Expected StrCatChainW to return 8, got %lu\n", ret); 1673 ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n"); 1674 1675 /* Append data at a fixed offset */ 1676 memset(buf, 0x11, sizeof(buf)); 1677 ret = pStrCatChainW(buf, 32, 0, deadW); 1678 ok(ret == 4, "Expected StrCatChainW to return 4, got %lu\n", ret); 1679 ok(!memcmp(buf, deadW, sizeof(deadW)), "Buffer contains wrong data\n"); 1680 1681 ret = pStrCatChainW(buf, 32, 4, beefW); 1682 ok(ret == 8, "Expected StrCatChainW to return 8, got %lu\n", ret); 1683 ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n"); 1684 1685 /* Buffer exactly sufficient for string + terminating null */ 1686 memset(buf, 0x11, sizeof(buf)); 1687 ret = pStrCatChainW(buf, 5, 0, deadW); 1688 ok(ret == 4, "Expected StrCatChainW to return 4, got %lu\n", ret); 1689 ok(!memcmp(buf, deadW, sizeof(deadW)), "Buffer contains wrong data\n"); 1690 1691 /* Buffer too small, string will be truncated */ 1692 memset(buf, 0x11, sizeof(buf)); 1693 ret = pStrCatChainW(buf, 4, 0, deadW); 1694 if (ret == 4) 1695 { 1696 /* Windows 2000 and XP uses a slightly different implementation 1697 * for StrCatChainW, which doesn't ensure that strings are null- 1698 * terminated. Skip test if we detect such an implementation. */ 1699 win_skip("Windows2000/XP behaviour detected for StrCatChainW, skipping tests\n"); 1700 return; 1701 } 1702 ok(ret == 3, "Expected StrCatChainW to return 3, got %lu\n", ret); 1703 ok(!memcmp(buf, deadW, 3 * sizeof(WCHAR)), "Buffer contains wrong data\n"); 1704 ok(!buf[3], "String is not nullterminated\n"); 1705 ok(buf[4] == 0x1111, "Expected buf[4] = 0x1111, got %x\n", buf[4]); 1706 1707 /* Overwrite part of an existing string */ 1708 ret = pStrCatChainW(buf, 4, 1, beefW); 1709 ok(ret == 3, "Expected StrCatChainW to return 3, got %lu\n", ret); 1710 ok(buf[0] == 'D', "Expected buf[0] = 'D', got %x\n", buf[0]); 1711 ok(buf[1] == 'B', "Expected buf[1] = 'B', got %x\n", buf[1]); 1712 ok(buf[2] == 'e', "Expected buf[2] = 'e', got %x\n", buf[2]); 1713 ok(!buf[3], "String is not nullterminated\n"); 1714 ok(buf[4] == 0x1111, "Expected buf[4] = 0x1111, got %x\n", buf[4]); 1715 1716 /* Test appending to full buffer */ 1717 memset(buf, 0x11, sizeof(buf)); 1718 memcpy(buf, deadbeefW, sizeof(deadbeefW)); 1719 memcpy(buf + 9, deadW, sizeof(deadW)); 1720 ret = pStrCatChainW(buf, 9, 8, beefW); 1721 ok(ret == 8, "Expected StrCatChainW to return 8, got %lu\n", ret); 1722 ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n"); 1723 ok(!memcmp(buf + 9, deadW, sizeof(deadW)), "Buffer contains wrong data\n"); 1724 1725 /* Offset points at the end of the buffer */ 1726 ret = pStrCatChainW(buf, 9, 9, beefW); 1727 ok(ret == 8, "Expected StrCatChainW to return 8, got %lu\n", ret); 1728 ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n"); 1729 ok(!memcmp(buf + 9, deadW, sizeof(deadW)), "Buffer contains wrong data\n"); 1730 1731 /* Offset points outside of the buffer */ 1732 ret = pStrCatChainW(buf, 9, 10, beefW); 1733 ok(ret == 10, "Expected StrCatChainW to return 10, got %lu\n", ret); 1734 ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n"); 1735 ok(!memcmp(buf + 9, deadW, sizeof(deadW)), "Buffer contains wrong data\n"); 1736 1737 /* The same but without nullterminated string */ 1738 memcpy(buf, deadbeefW, sizeof(deadbeefW)); 1739 ret = pStrCatChainW(buf, 5, -1, deadW); 1740 ok(ret == 8, "Expected StrCatChainW to return 8, got %lu\n", ret); 1741 ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n"); 1742 1743 ret = pStrCatChainW(buf, 5, 5, deadW); 1744 ok(ret == 4, "Expected StrCatChainW to return 4, got %lu\n", ret); 1745 ok(!memcmp(buf, deadW, sizeof(deadW)), "Buffer contains wrong data\n"); 1746 ok(buf[5] == 'e', "Expected buf[5] = 'e', got %x\n", buf[5]); 1747 1748 ret = pStrCatChainW(buf, 5, 6, deadW); 1749 ok(ret == 6, "Expected StrCatChainW to return 6, got %lu\n", ret); 1750 ok(!memcmp(buf, deadW, sizeof(deadW)), "Buffer contains wrong data\n"); 1751 ok(buf[5] == 'e', "Expected buf[5] = 'e', got %x\n", buf[5]); 1752} 1753 1754static void test_printf_format(void) 1755{ 1756 const struct 1757 { 1758 const char *spec; 1759 unsigned int arg_size; 1760 ULONG64 arg; 1761 const void *argw; 1762 } 1763 tests[] = 1764 { 1765 { "%qu", 0, 10 }, 1766 { "%ll", 0, 10 }, 1767 { "%lu", sizeof(ULONG), 65537 }, 1768 { "%llu", sizeof(ULONG64), 10 }, 1769 { "%lllllllu", sizeof(ULONG64), 10 }, 1770 { "%#lx", sizeof(ULONG), 10 }, 1771 { "%#llx", sizeof(ULONG64), 0x1000000000 }, 1772 { "%#lllx", sizeof(ULONG64), 0x1000000000 }, 1773 { "%hu", sizeof(ULONG), 65537 }, 1774 { "%hlu", sizeof(ULONG), 65537 }, 1775 { "%hllx", sizeof(ULONG64), 0x100000010 }, 1776 { "%hlllx", sizeof(ULONG64), 0x100000010 }, 1777 { "%llhx", sizeof(ULONG64), 0x100000010 }, 1778 { "%lllhx", sizeof(ULONG64), 0x100000010 }, 1779 { "%lhu", sizeof(ULONG), 65537 }, 1780 { "%hhu", sizeof(ULONG), 65537 }, 1781 { "%hwu", sizeof(ULONG), 65537 }, 1782 { "%whu", sizeof(ULONG), 65537 }, 1783 { "%##lhllwlx", sizeof(ULONG64), 0x1000000010 }, 1784 { "%##lhlwlx", sizeof(ULONG), 0x1000000010 }, 1785 { "%04lhlwllx", sizeof(ULONG64), 0x1000000010 }, 1786 { "%s", sizeof(ULONG_PTR), (ULONG_PTR)"str", L"str" }, 1787 { "%S", sizeof(ULONG_PTR), (ULONG_PTR)L"str", "str" }, 1788 { "%ls", sizeof(ULONG_PTR), (ULONG_PTR)L"str" }, 1789 { "%lS", sizeof(ULONG_PTR), (ULONG_PTR)L"str" }, 1790 { "%lls", sizeof(ULONG_PTR), (ULONG_PTR)"str", L"str" }, 1791 { "%llS", sizeof(ULONG_PTR), (ULONG_PTR)L"str", "str" }, 1792 { "%llls", sizeof(ULONG_PTR), (ULONG_PTR)L"str" }, 1793 { "%lllS", sizeof(ULONG_PTR), (ULONG_PTR)L"str" }, 1794 { "%lllls", sizeof(ULONG_PTR), (ULONG_PTR)"str", L"str" }, 1795 { "%llllS", sizeof(ULONG_PTR), (ULONG_PTR)L"str", "str" }, 1796 { "%hs", sizeof(ULONG_PTR), (ULONG_PTR)"str" }, 1797 { "%hS", sizeof(ULONG_PTR), (ULONG_PTR)"str" }, 1798 { "%ws", sizeof(ULONG_PTR), (ULONG_PTR)L"str" }, 1799 { "%wS", sizeof(ULONG_PTR), (ULONG_PTR)L"str" }, 1800 { "%hhs", sizeof(ULONG_PTR), (ULONG_PTR)"str" }, 1801 { "%hhS", sizeof(ULONG_PTR), (ULONG_PTR)"str" }, 1802 { "%wws", sizeof(ULONG_PTR), (ULONG_PTR)L"str" }, 1803 { "%wwS", sizeof(ULONG_PTR), (ULONG_PTR)L"str" }, 1804 { "%wwws", sizeof(ULONG_PTR), (ULONG_PTR)L"str" }, 1805 { "%wwwS", sizeof(ULONG_PTR), (ULONG_PTR)L"str" }, 1806 { "%hws", sizeof(ULONG_PTR), (ULONG_PTR)L"str", "str" }, 1807 { "%hwS", sizeof(ULONG_PTR), (ULONG_PTR)L"str", "str" }, 1808 { "%whs", sizeof(ULONG_PTR), (ULONG_PTR)L"str", "str" }, 1809 { "%whS", sizeof(ULONG_PTR), (ULONG_PTR)L"str", "str" }, 1810 { "%hwls", sizeof(ULONG_PTR), (ULONG_PTR)L"str", "str" }, 1811 { "%hwlls", sizeof(ULONG_PTR), (ULONG_PTR)L"str", "str" }, 1812 { "%hwlS", sizeof(ULONG_PTR), (ULONG_PTR)L"str", "str" }, 1813 { "%hwllS", sizeof(ULONG_PTR), (ULONG_PTR)L"str", "str" }, 1814 { "%lhws", sizeof(ULONG_PTR), (ULONG_PTR)L"str", "str" }, 1815 { "%llhws", sizeof(ULONG_PTR), (ULONG_PTR)L"str", "str" }, 1816 { "%lhwS", sizeof(ULONG_PTR), (ULONG_PTR)L"str", "str" }, 1817 { "%llhwS", sizeof(ULONG_PTR), (ULONG_PTR)L"str", "str" }, 1818 { "%c", sizeof(SHORT), 0x95c8 }, 1819 { "%lc", sizeof(SHORT), 0x95c8 }, 1820 { "%llc", sizeof(SHORT), 0x95c8 }, 1821 { "%lllc", sizeof(SHORT), 0x95c8 }, 1822 { "%llllc", sizeof(SHORT), 0x95c8 }, 1823 { "%lllllc", sizeof(SHORT), 0x95c8 }, 1824 { "%C", sizeof(SHORT), 0x95c8 }, 1825 { "%lC", sizeof(SHORT), 0x95c8 }, 1826 { "%llC", sizeof(SHORT), 0x95c8 }, 1827 { "%lllC", sizeof(SHORT), 0x95c8 }, 1828 { "%llllC", sizeof(SHORT), 0x95c8 }, 1829 { "%lllllC", sizeof(SHORT), 0x95c8 }, 1830 { "%hc", sizeof(BYTE), 0x95c8 }, 1831 { "%hhc", sizeof(BYTE), 0x95c8 }, 1832 { "%hhhc", sizeof(BYTE), 0x95c8 }, 1833 { "%wc", sizeof(BYTE), 0x95c8 }, 1834 { "%wC", sizeof(BYTE), 0x95c8 }, 1835 { "%hwc", sizeof(BYTE), 0x95c8 }, 1836 { "%whc", sizeof(BYTE), 0x95c8 }, 1837 { "%hwC", sizeof(BYTE), 0x95c8 }, 1838 { "%whC", sizeof(BYTE), 0x95c8 }, 1839 { "%I64u", sizeof(ULONG64), 10 }, 1840 { "%llI64u", sizeof(ULONG64), 10 }, 1841 { "%I64llu", sizeof(ULONG64), 10 }, 1842 { "%I64s", sizeof(ULONG_PTR), (ULONG_PTR)"str", L"str" }, 1843 { "%q%u", sizeof(ULONG), 10 }, 1844 { "%lhw%u", 0, 10 }, 1845 { "%u% ", sizeof(ULONG), 10 }, 1846 { "%u% %u", sizeof(ULONG), 10 }, 1847 { "% ll u", 0, 10 }, 1848 { "% llu", sizeof(ULONG64), 10 }, 1849 { "%# llx", sizeof(ULONG64), 10 }, 1850 { "% #llx", sizeof(ULONG64), 10 }, 1851 }; 1852 int (WINAPIV *ntdll__snprintf)(char *str, size_t len, const char *format, ...); 1853 int (WINAPIV *ntdll__snwprintf)( WCHAR *str, size_t len, const WCHAR *format, ... ); 1854 WCHAR ws[256], expectedw[256], specw[256]; 1855 unsigned int i, j; 1856 char expected[256], spec[256], s[256]; 1857 int len_a, len_w = 0, expected_len_a, expected_len_w = 0; 1858 HANDLE hntdll = GetModuleHandleW(L"ntdll.dll"); 1859 1860 ntdll__snprintf = (void *)GetProcAddress(hntdll, "_snprintf"); 1861 ok(!!ntdll__snprintf, "_snprintf not found.\n"); 1862 ntdll__snwprintf = (void *)GetProcAddress(hntdll, "_snwprintf"); 1863 ok(!!ntdll__snwprintf, "_snwprintf not found.\n"); 1864#ifdef __REACTOS__ 1865 DWORD _ntVersion = GetVersion(); 1866 BYTE _ntMajor = LOBYTE(LOWORD(_ntVersion)); 1867 BYTE _ntMinor = HIBYTE(LOWORD(_ntVersion)); 1868 1869 if (_ntMajor < 6 || (_ntMajor == 6 && _ntMinor == 0)) { 1870 skip("These tests are broken on WS03 and Vista.\n"); 1871 return; 1872 } 1873#endif 1874 1875 for (i = 0; i < ARRAY_SIZE(tests); ++i) 1876 { 1877 strcpy(spec, tests[i].spec); 1878 winetest_push_context("%s", spec); 1879 strcat(spec,"|%s"); 1880 *s = 0; 1881 *ws = 0; 1882 j = 0; 1883 do 1884 specw[j] = spec[j]; 1885 while (specw[j++]); 1886 if (tests[i].argw) 1887 { 1888 len_w = pwnsprintfW(ws, ARRAY_SIZE(ws), specw, tests[i].argw, L"end"); 1889 expected_len_w = ntdll__snwprintf(expectedw, ARRAY_SIZE(expectedw), specw, tests[i].argw, L"end"); 1890 } 1891 switch (tests[i].arg_size) 1892 { 1893 case 0: 1894 len_a = pwnsprintfA(s, ARRAY_SIZE(s), spec, "end"); 1895 expected_len_a = ntdll__snprintf(expected, ARRAY_SIZE(expected), spec, "end"); 1896 len_w = pwnsprintfW(ws, ARRAY_SIZE(ws), specw, L"end"); 1897 expected_len_w = ntdll__snwprintf(expectedw, ARRAY_SIZE(expectedw), specw, L"end"); 1898 break; 1899 case 1: 1900 case 2: 1901 case 4: 1902 len_a = pwnsprintfA(s, ARRAY_SIZE(s), spec, (ULONG)tests[i].arg, "end"); 1903 expected_len_a = ntdll__snprintf(expected, ARRAY_SIZE(expected), spec, (ULONG)tests[i].arg, "end"); 1904 if (!tests[i].argw) 1905 { 1906 len_w = pwnsprintfW(ws, ARRAY_SIZE(ws), specw, (ULONG)tests[i].arg, L"end"); 1907 expected_len_w = ntdll__snwprintf(expectedw, ARRAY_SIZE(expectedw), specw, (ULONG)tests[i].arg, L"end"); 1908 } 1909 break; 1910 case 8: 1911 len_a = pwnsprintfA(s, ARRAY_SIZE(s), spec, (ULONG64)tests[i].arg, "end"); 1912 expected_len_a = ntdll__snprintf(expected, ARRAY_SIZE(s), spec, (ULONG64)tests[i].arg, "end"); 1913 if (!tests[i].argw) 1914 { 1915 len_w = pwnsprintfW(ws, ARRAY_SIZE(ws), specw, (ULONG64)tests[i].arg, L"end"); 1916 expected_len_w = ntdll__snwprintf(expectedw, ARRAY_SIZE(expectedw), specw, (ULONG64)tests[i].arg, L"end"); 1917 } 1918 break; 1919 default: 1920 len_a = len_w = expected_len_a = expected_len_w = 0; 1921 ok(0, "unknown length %u.\n", tests[i].arg_size); 1922 break; 1923 } 1924 ok(len_a == expected_len_a, "got len %d, expected %d.\n", len_a, expected_len_a); 1925 ok(!strcmp(s, expected), "got %s, expected %s.\n", debugstr_a(s), debugstr_a(expected)); 1926 ok(len_w == expected_len_w, "got len %d, expected %d.\n", len_a, expected_len_a); 1927 ok(!wcscmp(ws, expectedw), "got %s, expected %s.\n", debugstr_w(ws), debugstr_w(expectedw)); 1928 winetest_pop_context(); 1929 } 1930} 1931 1932START_TEST(string) 1933{ 1934 HMODULE hShlwapi; 1935 CHAR thousandDelim[8]; 1936 CHAR decimalDelim[8]; 1937 CoInitialize(0); 1938 1939 GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, thousandDelim, 8); 1940 GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, decimalDelim, 8); 1941 1942 hShlwapi = GetModuleHandleA("shlwapi"); 1943 pChrCmpIA = (void *)GetProcAddress(hShlwapi, "ChrCmpIA"); 1944 pChrCmpIW = (void *)GetProcAddress(hShlwapi, "ChrCmpIW"); 1945 pIntlStrEqWorkerA = (void *)GetProcAddress(hShlwapi, "IntlStrEqWorkerA"); 1946 pIntlStrEqWorkerW = (void *)GetProcAddress(hShlwapi, "IntlStrEqWorkerW"); 1947 pSHAnsiToAnsi = (void *)GetProcAddress(hShlwapi, (LPSTR)345); 1948 pSHUnicodeToUnicode = (void *)GetProcAddress(hShlwapi, (LPSTR)346); 1949 pStrCatBuffA = (void *)GetProcAddress(hShlwapi, "StrCatBuffA"); 1950 pStrCatBuffW = (void *)GetProcAddress(hShlwapi, "StrCatBuffW"); 1951 pStrCatChainW = (void *)GetProcAddress(hShlwapi, "StrCatChainW"); 1952 pStrCpyNXA = (void *)GetProcAddress(hShlwapi, (LPSTR)399); 1953 pStrCpyNXW = (void *)GetProcAddress(hShlwapi, (LPSTR)400); 1954 pStrChrNW = (void *)GetProcAddress(hShlwapi, "StrChrNW"); 1955 pStrFormatByteSize64A = (void *)GetProcAddress(hShlwapi, "StrFormatByteSize64A"); 1956 pStrFormatByteSizeEx = (void *)GetProcAddress(hShlwapi, "StrFormatByteSizeEx"); 1957 pStrFormatKBSizeA = (void *)GetProcAddress(hShlwapi, "StrFormatKBSizeA"); 1958 pStrFormatKBSizeW = (void *)GetProcAddress(hShlwapi, "StrFormatKBSizeW"); 1959 pStrIsIntlEqualA = (void *)GetProcAddress(hShlwapi, "StrIsIntlEqualA"); 1960 pStrIsIntlEqualW = (void *)GetProcAddress(hShlwapi, "StrIsIntlEqualW"); 1961 pStrPBrkW = (void *)GetProcAddress(hShlwapi, "StrPBrkW"); 1962 pStrRChrA = (void *)GetProcAddress(hShlwapi, "StrRChrA"); 1963 pStrRetToBSTR = (void *)GetProcAddress(hShlwapi, "StrRetToBSTR"); 1964 pStrRetToBufA = (void *)GetProcAddress(hShlwapi, "StrRetToBufA"); 1965 pStrRetToBufW = (void *)GetProcAddress(hShlwapi, "StrRetToBufW"); 1966 pStrStrNW = (void *)GetProcAddress(hShlwapi, "StrStrNW"); 1967 pStrStrNIW = (void *)GetProcAddress(hShlwapi, "StrStrNIW"); 1968 pwnsprintfA = (void *)GetProcAddress(hShlwapi, "wnsprintfA"); 1969 pwnsprintfW = (void *)GetProcAddress(hShlwapi, "wnsprintfW"); 1970 pStrToInt64ExA = (void *)GetProcAddress(hShlwapi, "StrToInt64ExA"); 1971 pStrToInt64ExW = (void *)GetProcAddress(hShlwapi, "StrToInt64ExW"); 1972 1973 test_StrChrA(); 1974 test_StrChrW(); 1975 test_StrChrIA(); 1976 test_StrChrIW(); 1977 test_StrRChrA(); 1978 test_StrRChrW(); 1979 test_StrCpyW(); 1980 test_StrChrNW(); 1981 test_StrToIntA(); 1982 test_StrToIntW(); 1983 test_StrToIntExA(); 1984 test_StrToIntExW(); 1985 test_StrToInt64ExA(); 1986 test_StrToInt64ExW(); 1987 test_StrDupA(); 1988 1989 /* language-dependent test */ 1990 if (is_lang_english() && is_locale_english()) 1991 { 1992 test_StrFormatByteSize64A(); 1993 test_StrFormatByteSizeEx(); 1994 test_StrFormatKBSizeA(); 1995 test_StrFormatKBSizeW(); 1996 } 1997 else 1998 skip("An English UI and locale is required for the StrFormat*Size tests\n"); 1999 if (is_lang_english()) 2000 test_StrFromTimeIntervalA(); 2001 else 2002 skip("An English UI is required for the StrFromTimeInterval tests\n"); 2003 2004 test_StrCmpA(); 2005 test_StrCmpW(); 2006 test_StrRetToBSTR(); 2007 test_StrCpyNXA(); 2008 test_StrCpyNXW(); 2009 test_StrRStrI(); 2010 test_SHAnsiToAnsi(); 2011 test_SHUnicodeToUnicode(); 2012 test_StrXXX_overflows(); 2013 test_StrStrA(); 2014 test_StrStrW(); 2015 test_StrStrIA(); 2016 test_StrStrIW(); 2017 test_StrStrNW(); 2018 test_StrStrNIW(); 2019 test_StrCatChainW(); 2020 test_printf_format(); 2021 2022 CoUninitialize(); 2023}