1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Test for ACListISF objects 5 * COPYRIGHT: Copyright 2016 Mark Jansen <mark.jansen@reactos.org> 6 * Copyright 2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 7 */ 8 9 #define _UNICODE 10 #define UNICODE 11 #include <apitest.h> 12 #include <shlobj.h> 13 #include <atlbase.h> 14 #include <tchar.h> // 15 #include <atlcom.h> // These 3 includes only exist here to make gcc happy about (unused) templates.. 16 #include <atlwin.h> // 17 18 // Yes, gcc at it again, let's validate everything found inside unused templates! 19 ULONG DbgPrint(PCH Format,...); 20 21 #include <stdio.h> 22 #include <shellutils.h> 23 #include <shlwapi.h> 24 #include <strsafe.h> 25 26 static bool g_ShowHidden; 27 static DWORD g_WinVersion; 28 #define WINVER_VISTA 0x0600 29 30 31 #define ok_hr(status, expected) ok_hex(status, expected) 32 33 // We do not want our results to originate from the helper functions, so have them originate from the calls to them 34 #define test_at_end (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_at_end_imp 35 #define test_ExpectDrives (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_ExpectDrives_imp 36 #define test_ExpectFolders (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_ExpectFolders_imp 37 #define winetest_ok_hr(expression, expected) \ 38 do { \ 39 int _value = (expression); \ 40 winetest_ok(_value == (expected), "Wrong value for '%s', expected: " #expected " (0x%x), got: 0x%x\n", \ 41 #expression, (int)(expected), _value); \ 42 } while (0) 43 44 static void test_at_end_imp(CComPtr<IEnumString>& EnumStr) 45 { 46 CComHeapPtr<OLECHAR> Result; 47 ULONG Fetched = 12345; 48 HRESULT hr = EnumStr->Next(1, &Result, &Fetched); 49 winetest_ok(hr == S_FALSE, "Expected hr to be S_FALSE, was 0x%lx\n", hr); 50 winetest_ok(Fetched == 0u, "Expected Fetched to be 0, was: %lu\n", Fetched); 51 if (Fetched == 1u) 52 winetest_ok(0, "Expected there not to be a result, got: %s\n", wine_dbgstr_w(Result)); 53 } 54 55 static bool GetDisplayname(CComPtr<IShellFolder>& spDrives, CComHeapPtr<ITEMIDLIST>& pidl, CComHeapPtr<WCHAR>& DisplayName) 56 { 57 STRRET StrRet; 58 HRESULT hr; 59 winetest_ok_hr(hr = spDrives->GetDisplayNameOf(pidl, SHGDN_INFOLDER | SHGDN_FORPARSING | SHGDN_FORADDRESSBAR, &StrRet), S_OK); 60 if (!SUCCEEDED(hr)) 61 return false; 62 63 winetest_ok_hr(hr = StrRetToStrW(&StrRet, NULL, &DisplayName), S_OK); 64 if (!SUCCEEDED(hr)) 65 return false; 66 return true; 67 } 68 69 enum ExpectOptions 70 { 71 None = 0, 72 IgnoreRoot = 1, 73 CheckLast = 2, 74 IgnoreHidden = 4, 75 IgnoreFiles = 8, 76 }; 77 78 // wtf c++ 79 ExpectOptions operator | (const ExpectOptions& left, const ExpectOptions& right) 80 { 81 return static_cast<ExpectOptions>(static_cast<int>(left) | static_cast<int>(right)); 82 } 83 84 85 static void 86 test_ExpectFolders_imp(CComPtr<IEnumString>& EnumStr, LPITEMIDLIST pidlTarget, const WCHAR* Root, ExpectOptions options) 87 { 88 CComPtr<IShellFolder> spDesktop; 89 HRESULT hr = SHGetDesktopFolder(&spDesktop); 90 91 CComPtr<IShellFolder> spTarget; 92 if (pidlTarget) 93 { 94 winetest_ok_hr(hr = spDesktop->BindToObject(pidlTarget, NULL, IID_PPV_ARG(IShellFolder, &spTarget)), S_OK); 95 if (!SUCCEEDED(hr)) 96 return; 97 } 98 else 99 { 100 spTarget = spDesktop; 101 } 102 103 SHCONTF EnumFlags = SHCONTF_FOLDERS | SHCONTF_INIT_ON_FIRST_NEXT; 104 if (g_ShowHidden && !(options & IgnoreHidden)) 105 EnumFlags |= SHCONTF_INCLUDEHIDDEN; 106 if (!(options & IgnoreFiles)) 107 EnumFlags |= SHCONTF_NONFOLDERS; 108 109 CComPtr<IEnumIDList> spEnumIDList; 110 winetest_ok_hr(hr = spTarget->EnumObjects(NULL, EnumFlags, &spEnumIDList), S_OK); 111 if (!SUCCEEDED(hr)) 112 return; 113 114 WCHAR Buffer[512]; 115 CComHeapPtr<ITEMIDLIST> pidl; 116 INT Count = 0; 117 while (spEnumIDList->Next(1, &pidl, NULL) == S_OK) 118 { 119 CComHeapPtr<WCHAR> DisplayName; 120 if (!GetDisplayname(spTarget, pidl, DisplayName)) 121 break; 122 123 CComHeapPtr<OLECHAR> Result; 124 ULONG Fetched; 125 hr = EnumStr->Next(1, &Result, &Fetched); 126 winetest_ok_hr(hr, S_OK); 127 128 if (hr != S_OK) 129 break; 130 131 StringCchPrintfW(Buffer, _ARRAYSIZE(Buffer), L"%s%s", (options & IgnoreRoot) ? L"" : Root, (WCHAR*)DisplayName); 132 133 winetest_ok(!wcscmp(Buffer, Result), "Expected %s, got %s\n", wine_dbgstr_w(Buffer), wine_dbgstr_w(Result)); 134 135 pidl.Free(); 136 Count++; 137 } 138 if (options & CheckLast) 139 { 140 test_at_end_imp(EnumStr); 141 } 142 } 143 144 static void 145 test_ExpectDrives_imp(CComPtr<IEnumString>& EnumStr, CComHeapPtr<ITEMIDLIST>& pidlTarget) 146 { 147 test_ExpectFolders_imp(EnumStr, pidlTarget, NULL, IgnoreRoot | CheckLast); 148 } 149 150 static void 151 test_ACListISF_NONE() 152 { 153 CComPtr<IEnumString> EnumStr; 154 HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr)); 155 ok_hr(hr, S_OK); 156 if (!SUCCEEDED(hr)) 157 { 158 skip("CoCreateInstance failed\n"); 159 return; 160 } 161 162 CComPtr<IACList2> ACList; 163 ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK); 164 if (!SUCCEEDED(hr)) 165 { 166 skip("QueryInterface failed\n"); 167 return; 168 } 169 170 ok_hr(hr = ACList->SetOptions(ACLO_NONE), S_OK); 171 test_at_end(EnumStr); 172 173 174 WCHAR Buffer[MAX_PATH]; 175 GetSystemWindowsDirectoryW(Buffer, _ARRAYSIZE(Buffer)); 176 Buffer[3] = '\0'; 177 178 CComHeapPtr<ITEMIDLIST> pidlDiskRoot; 179 ok_hr(hr = SHParseDisplayName(Buffer, NULL, &pidlDiskRoot, NULL, NULL), S_OK); 180 if (!SUCCEEDED(hr)) 181 { 182 skip("SHParseDisplayName failed\n"); 183 return; 184 } 185 186 ok_hr(hr = ACList->Expand(Buffer), S_OK); 187 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, CheckLast | IgnoreHidden); 188 189 ok_hr(hr = EnumStr->Reset(), S_OK); 190 ok_hr(hr = ACList->Expand(Buffer), S_OK); 191 ok_hr(hr = ACList->SetOptions(ACLO_NONE), S_OK); 192 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, CheckLast); 193 } 194 195 static void 196 test_ACListISF_CURRENTDIR() 197 { 198 CComPtr<IEnumString> EnumStr; 199 HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr)); 200 ok_hr(hr, S_OK); 201 if (!SUCCEEDED(hr)) 202 { 203 skip("CoCreateInstance failed\n"); 204 return; 205 } 206 207 CComPtr<IACList2> ACList; 208 ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK); 209 if (!SUCCEEDED(hr)) 210 { 211 skip("QueryInterface failed\n"); 212 return; 213 } 214 215 CComPtr<ICurrentWorkingDirectory> CurrentWorkingDir; 216 ok_hr(hr = EnumStr->QueryInterface(IID_ICurrentWorkingDirectory, (void**)&CurrentWorkingDir), S_OK); 217 if (!SUCCEEDED(hr)) 218 { 219 skip("QueryInterface failed\n"); 220 return; 221 } 222 223 ok_hr(hr = ACList->SetOptions(ACLO_CURRENTDIR), S_OK); 224 test_at_end(EnumStr); 225 226 227 WCHAR Buffer[MAX_PATH] = { 1, 1, 1, 1, 1, 0 }, Buffer2[MAX_PATH]; 228 if (g_WinVersion < WINVER_VISTA) 229 ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), E_NOTIMPL); 230 else 231 ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), E_UNEXPECTED); 232 ok(!wcscmp(L"\x1\x1\x1\x1\x1", Buffer), "Expected %s, got %s\n", wine_dbgstr_w(L"\x1\x1\x1\x1\x1"), wine_dbgstr_w(Buffer)); 233 234 GetSystemWindowsDirectoryW(Buffer2, _ARRAYSIZE(Buffer2)); 235 // Windows 2k3 does not parse it without the trailing '\\' 236 Buffer2[3] = '\0'; 237 CComHeapPtr<ITEMIDLIST> pidlDiskRoot; 238 ok_hr(hr = SHParseDisplayName(Buffer2, NULL, &pidlDiskRoot, NULL, NULL), S_OK); 239 if (!SUCCEEDED(hr)) 240 return; 241 242 ok_hr(hr = CurrentWorkingDir->SetDirectory(Buffer2), S_OK); 243 test_at_end(EnumStr); 244 245 Buffer[0] = '\0'; 246 if (g_WinVersion < WINVER_VISTA) 247 { 248 ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), E_NOTIMPL); 249 } 250 else 251 { 252 ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), S_OK); 253 ok(!wcscmp(Buffer2, Buffer), "Expected %s, got %s\n", wine_dbgstr_w(Buffer2), wine_dbgstr_w(Buffer)); 254 } 255 256 Buffer2[2] = '\0'; 257 ok_hr(hr = CurrentWorkingDir->SetDirectory(Buffer2), S_OK); 258 test_at_end(EnumStr); 259 260 Buffer[0] = '\0'; 261 Buffer2[2] = '\\'; 262 if (g_WinVersion < WINVER_VISTA) 263 { 264 ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), E_NOTIMPL); 265 } 266 else 267 { 268 ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), S_OK); 269 ok(!wcscmp(Buffer2, Buffer), "Expected %s, got %s\n", wine_dbgstr_w(Buffer2), wine_dbgstr_w(Buffer)); 270 } 271 272 ok_hr(hr = ACList->Expand(Buffer2), S_OK); 273 // The first set of results are absolute paths, without hidden files?! 274 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer2, IgnoreHidden); 275 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer2, IgnoreHidden | IgnoreRoot | CheckLast); 276 277 WCHAR szDir[MAX_PATH], szPath[MAX_PATH]; 278 Buffer2[2] = 0; 279 StringCbCopyW(szDir, sizeof(szDir), Buffer2); 280 281 StringCbCopyW(szPath, sizeof(szPath), szDir); 282 StringCbCatW(szPath, sizeof(szPath), L"\\BROWSEUI-1"); 283 CreateDirectoryW(szPath, NULL); 284 285 StringCbCopyW(szPath, sizeof(szPath), szDir); 286 StringCbCatW(szPath, sizeof(szPath), L"\\BROWSEUI-1\\TEST1"); 287 CreateDirectoryW(szPath, NULL); 288 289 StringCbCopyW(szPath, sizeof(szPath), szDir); 290 StringCbCatW(szPath, sizeof(szPath), L"\\BROWSEUI-1\\TEST2"); 291 CreateDirectoryW(szPath, NULL); 292 293 StringCbCopyW(szPath, sizeof(szPath), szDir); 294 StringCbCatW(szPath, sizeof(szPath), L"\\BROWSEUI-2"); 295 CreateDirectoryW(szPath, NULL); 296 297 StringCbCopyW(szPath, sizeof(szPath), szDir); 298 StringCbCatW(szPath, sizeof(szPath), L"\\BROWSEUI-2\\tes1"); 299 CreateDirectoryW(szPath, NULL); 300 301 StringCbCopyW(szPath, sizeof(szPath), szDir); 302 StringCbCatW(szPath, sizeof(szPath), L"\\BROWSEUI-2\\tes2"); 303 CreateDirectoryW(szPath, NULL); 304 305 ULONG cGot; 306 LPWSTR psz = NULL; 307 EnumStr->Reset(); 308 309 StringCbCopyW(szPath, sizeof(szPath), szDir); 310 StringCbCatW(szPath, sizeof(szPath), L"\\BROWSEUI-1\\"); 311 ok_hr(hr = ACList->Expand(szPath), S_OK); 312 313 hr = EnumStr->Next(1, &psz, &cGot); 314 ok_hr(hr, S_OK); 315 StringCbCopyW(szPath, sizeof(szPath), szDir); 316 StringCbCatW(szPath, sizeof(szPath), L"\\BROWSEUI-1\\TEST1"); 317 ok_wstr(szPath, psz); 318 CoTaskMemFree(psz); 319 320 hr = EnumStr->Next(1, &psz, &cGot); 321 ok_hr(hr, S_OK); 322 StringCbCopyW(szPath, sizeof(szPath), szDir); 323 StringCbCatW(szPath, sizeof(szPath), L"\\BROWSEUI-1\\TEST2"); 324 ok_wstr(szPath, psz); 325 CoTaskMemFree(psz); 326 327 StringCbCopyW(szPath, sizeof(szPath), szDir); 328 StringCbCatW(szPath, sizeof(szPath), L"\\BROWSEUI-2\\"); 329 ok_hr(hr = CurrentWorkingDir->SetDirectory(szPath), S_OK); 330 331 hr = EnumStr->Next(1, &psz, &cGot); 332 ok_hr(hr, S_OK); 333 ok_wstr(psz, L"tes1"); 334 CoTaskMemFree(psz); 335 336 hr = EnumStr->Next(1, &psz, &cGot); 337 ok_hr(hr, S_OK); 338 ok_wstr(psz, L"tes2"); 339 CoTaskMemFree(psz); 340 341 StringCbCopyW(szPath, sizeof(szPath), szDir); 342 StringCbCatW(szPath, sizeof(szPath), L"\\BROWSEUI-2"); 343 ok_hr(hr = CurrentWorkingDir->SetDirectory(szPath), S_OK); 344 345 EnumStr->Reset(); 346 347 hr = EnumStr->Next(1, &psz, &cGot); 348 ok_hr(hr, S_OK); 349 ok_wstr(psz, L"tes1"); 350 CoTaskMemFree(psz); 351 352 hr = EnumStr->Next(1, &psz, &cGot); 353 ok_hr(hr, S_OK); 354 ok_wstr(psz, L"tes2"); 355 CoTaskMemFree(psz); 356 357 StringCbCopyW(szPath, sizeof(szPath), szDir); 358 StringCbCatW(szPath, sizeof(szPath), L"\\BROWSEUI-1\\TEST1"); 359 RemoveDirectoryW(szPath); 360 361 StringCbCopyW(szPath, sizeof(szPath), szDir); 362 StringCbCatW(szPath, sizeof(szPath), L"\\BROWSEUI-1\\TEST2"); 363 RemoveDirectoryW(szPath); 364 365 StringCbCopyW(szPath, sizeof(szPath), szDir); 366 StringCbCatW(szPath, sizeof(szPath), L"\\BROWSEUI-1"); 367 RemoveDirectoryW(szPath); 368 369 StringCbCopyW(szPath, sizeof(szPath), szDir); 370 StringCbCatW(szPath, sizeof(szPath), L"\\BROWSEUI-2\\tes1"); 371 RemoveDirectoryW(szPath); 372 373 StringCbCopyW(szPath, sizeof(szPath), szDir); 374 StringCbCatW(szPath, sizeof(szPath), L"\\BROWSEUI-2\\tes2"); 375 RemoveDirectoryW(szPath); 376 377 StringCbCopyW(szPath, sizeof(szPath), szDir); 378 StringCbCatW(szPath, sizeof(szPath), L"\\BROWSEUI-2"); 379 RemoveDirectoryW(szPath); 380 } 381 382 static void 383 test_ACListISF_CURRENTDIR2() 384 { 385 CComPtr<IEnumString> EnumStr; 386 HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr)); 387 ok_hr(hr, S_OK); 388 if (!SUCCEEDED(hr)) 389 { 390 skip("CoCreateInstance failed\n"); 391 return; 392 } 393 394 CComPtr<IACList2> ACList; 395 ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK); 396 if (!SUCCEEDED(hr)) 397 { 398 skip("QueryInterface failed\n"); 399 return; 400 } 401 402 CComPtr<ICurrentWorkingDirectory> CurrentWorkingDir; 403 ok_hr(hr = EnumStr->QueryInterface(IID_ICurrentWorkingDirectory, (void**)&CurrentWorkingDir), S_OK); 404 if (!SUCCEEDED(hr)) 405 { 406 skip("QueryInterface failed\n"); 407 return; 408 } 409 410 ok_hr(hr = ACList->SetOptions(ACLO_CURRENTDIR), S_OK); 411 test_at_end(EnumStr); 412 413 CreateDirectoryW(L"C:\\BROWSEUI-1", NULL); 414 CreateDirectoryW(L"C:\\BROWSEUI-1\\TEST1", NULL); 415 CreateDirectoryW(L"C:\\BROWSEUI-1\\TEST2", NULL); 416 CreateDirectoryW(L"C:\\BROWSEUI-1\\TEST1\\TEST3", NULL); 417 CreateDirectoryW(L"C:\\BROWSEUI-2", NULL); 418 CreateDirectoryW(L"C:\\BROWSEUI-2\\TEST1", NULL); 419 CreateDirectoryW(L"C:\\BROWSEUI-2\\TEST2", NULL); 420 CreateDirectoryW(L"C:\\BROWSEUI-2\\TEST1\\TEST4", NULL); 421 422 ok_hr(hr = CurrentWorkingDir->SetDirectory(L"C:\\BROWSEUI-1\\TEST1"), S_OK); 423 test_at_end(EnumStr); 424 425 ok_hr(hr = ACList->Expand(L"C:\\BROWSEUI-2\\TEST1\\"), S_OK); 426 427 LPWSTR psz; 428 ULONG cGot; 429 430 hr = EnumStr->Next(1, &psz, &cGot); 431 ok_hr(hr, S_OK); 432 ok_wstr(psz, L"C:\\BROWSEUI-2\\TEST1\\TEST4"); 433 CoTaskMemFree(psz); 434 435 hr = EnumStr->Next(1, &psz, &cGot); 436 ok_hr(hr, S_OK); 437 ok_wstr(psz, L"TEST3"); 438 CoTaskMemFree(psz); 439 440 test_at_end(EnumStr); 441 442 ok_hr(hr = ACList->Expand(L"C:\\BROWSEUI-1\\TEST1\\"), S_OK); 443 444 hr = EnumStr->Next(1, &psz, &cGot); 445 ok_hr(hr, S_OK); 446 ok_wstr(psz, L"C:\\BROWSEUI-1\\TEST1\\TEST3"); 447 CoTaskMemFree(psz); 448 449 hr = EnumStr->Next(1, &psz, &cGot); 450 ok_hr(hr, S_OK); 451 ok_wstr(psz, L"TEST3"); 452 CoTaskMemFree(psz); 453 454 test_at_end(EnumStr); 455 456 ok_hr(hr = CurrentWorkingDir->SetDirectory(L"C:\\BROWSEUI-2\\TEST1"), S_OK); 457 test_at_end(EnumStr); 458 459 ok_hr(hr = ACList->Expand(L"..\\TEST1\\"), S_OK); 460 461 hr = EnumStr->Next(1, &psz, &cGot); 462 ok_hr(hr, S_OK); 463 ok_wstr(psz, L"..\\TEST1\\TEST4"); 464 CoTaskMemFree(psz); 465 466 hr = EnumStr->Next(1, &psz, &cGot); 467 ok_hr(hr, S_OK); 468 ok_wstr(psz, L"TEST4"); 469 CoTaskMemFree(psz); 470 471 test_at_end(EnumStr); 472 473 ok_hr(hr = ACList->Expand(L"\\BROWSEUI-2\\TEST1\\"), S_OK); 474 475 hr = EnumStr->Next(1, &psz, &cGot); 476 ok_hr(hr, S_OK); 477 ok_wstr(psz, L"\\BROWSEUI-2\\TEST1\\TEST4"); 478 CoTaskMemFree(psz); 479 480 hr = EnumStr->Next(1, &psz, &cGot); 481 ok_hr(hr, S_OK); 482 ok_wstr(psz, L"TEST4"); 483 CoTaskMemFree(psz); 484 485 test_at_end(EnumStr); 486 487 RemoveDirectoryW(L"C:\\BROWSEUI-1\\TEST1\\TEST3"); 488 RemoveDirectoryW(L"C:\\BROWSEUI-1\\TEST1"); 489 RemoveDirectoryW(L"C:\\BROWSEUI-1\\TEST2"); 490 RemoveDirectoryW(L"C:\\BROWSEUI-1"); 491 RemoveDirectoryW(L"C:\\BROWSEUI-2\\TEST1\\TEST4"); 492 RemoveDirectoryW(L"C:\\BROWSEUI-2\\TEST1"); 493 RemoveDirectoryW(L"C:\\BROWSEUI-2\\TEST2"); 494 RemoveDirectoryW(L"C:\\BROWSEUI-2"); 495 } 496 497 static void 498 test_ACListISF_MYCOMPUTER() 499 { 500 CComPtr<IACList2> ACList; 501 HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IACList2, &ACList)); 502 ok_hr(hr, S_OK); 503 if (!SUCCEEDED(hr)) 504 { 505 skip("CoCreateInstance failed\n"); 506 return; 507 } 508 509 // Check the default 510 DWORD CurrentOption = 0xdeadbeef; 511 ok_hr(ACList->GetOptions(&CurrentOption), S_OK); 512 ok(CurrentOption == (ACLO_CURRENTDIR|ACLO_MYCOMPUTER), "Expected the default to be %x, was %lx\n", 513 (ACLO_CURRENTDIR|ACLO_MYCOMPUTER), CurrentOption); 514 515 516 CComPtr<IEnumString> EnumStr; 517 ok_hr(hr = ACList->QueryInterface(IID_IEnumString, (void**)&EnumStr), S_OK); 518 if (!SUCCEEDED(hr)) 519 { 520 skip("QueryInterface failed\n"); 521 return; 522 } 523 524 CComPtr<IPersistFolder> PersistFolder; 525 ok_hr(hr = EnumStr->QueryInterface(IID_IPersistFolder, (void**)&PersistFolder), S_OK); 526 if (!SUCCEEDED(hr)) 527 { 528 skip("QueryInterface failed\n"); 529 return; 530 } 531 532 CComHeapPtr<ITEMIDLIST> pidlMyComputer; 533 ok_hr(hr = SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidlMyComputer), S_OK); 534 if (!SUCCEEDED(hr)) 535 { 536 skip("SHGetSpecialFolderLocation failed\n"); 537 return; 538 } 539 540 hr = EnumStr->Reset(); 541 if (g_WinVersion < WINVER_VISTA) 542 ok_hr(hr, S_FALSE); 543 else 544 ok_hr(hr, S_OK); 545 test_ExpectDrives(EnumStr, pidlMyComputer); 546 547 ok_hr(hr = ACList->SetOptions(ACLO_MYCOMPUTER), S_OK); 548 ok_hr(EnumStr->Reset(), S_OK); 549 test_ExpectDrives(EnumStr, pidlMyComputer); 550 551 WCHAR Buffer[MAX_PATH]; 552 GetSystemWindowsDirectoryW(Buffer, _ARRAYSIZE(Buffer)); 553 // Windows 2k3 does not parse it without the trailing '\\' 554 Buffer[3] = '\0'; 555 CComHeapPtr<ITEMIDLIST> pidlDiskRoot; 556 ok_hr(hr = SHParseDisplayName(Buffer, NULL, &pidlDiskRoot, NULL, NULL), S_OK); 557 if (!SUCCEEDED(hr)) 558 return; 559 Buffer[2] = '\0'; 560 561 ok_hr(hr = ACList->Expand(Buffer), S_OK); 562 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, None); 563 test_ExpectDrives(EnumStr, pidlMyComputer); 564 565 ok_hr(hr = ACList->Expand(Buffer), S_OK); 566 ok_hr(EnumStr->Reset(), S_OK); 567 // Pre vista does not remove the expanded data from the enumeration, it changes it to relative paths??? 568 if (g_WinVersion < WINVER_VISTA) 569 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, IgnoreRoot); 570 test_ExpectDrives(EnumStr, pidlMyComputer); 571 572 ok_hr(EnumStr->Reset(), S_OK); 573 ok_hr(hr = ACList->Expand(Buffer), S_OK); 574 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, None); 575 test_ExpectDrives(EnumStr, pidlMyComputer); 576 } 577 578 static void 579 test_ACListISF_DESKTOP() 580 { 581 CComPtr<IEnumString> EnumStr; 582 HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr)); 583 ok_hr(hr, S_OK); 584 if (!SUCCEEDED(hr)) 585 { 586 skip("CoCreateInstance failed\n"); 587 return; 588 } 589 590 CComPtr<IACList2> ACList; 591 ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK); 592 if (!SUCCEEDED(hr)) 593 { 594 skip("QueryInterface failed\n"); 595 return; 596 } 597 598 ok_hr(hr = ACList->SetOptions(ACLO_DESKTOP), S_OK); 599 test_ExpectFolders(EnumStr, NULL, NULL, IgnoreRoot | CheckLast | IgnoreHidden); 600 } 601 602 static void 603 test_ACListISF_FAVORITES() 604 { 605 CComPtr<IEnumString> EnumStr; 606 HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr)); 607 ok_hr(hr, S_OK); 608 if (!SUCCEEDED(hr)) 609 { 610 skip("CoCreateInstance failed\n"); 611 return; 612 } 613 614 CComPtr<IACList2> ACList; 615 ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK); 616 if (!SUCCEEDED(hr)) 617 { 618 skip("QueryInterface failed\n"); 619 return; 620 } 621 622 CComHeapPtr<ITEMIDLIST> pidlFavorites; 623 ok_hr(hr = SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidlFavorites), S_OK); 624 if (!SUCCEEDED(hr)) 625 { 626 skip("SHGetSpecialFolderLocation failed\n"); 627 return; 628 } 629 630 ok_hr(hr = ACList->SetOptions(ACLO_FAVORITES), S_OK); 631 test_ExpectFolders(EnumStr, pidlFavorites, NULL, IgnoreRoot | CheckLast | IgnoreHidden); 632 } 633 634 static void 635 test_ACListISF_FILESYSONLY() 636 { 637 CComPtr<IEnumString> EnumStr; 638 HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr)); 639 ok_hr(hr, S_OK); 640 if (!SUCCEEDED(hr)) 641 { 642 skip("CoCreateInstance failed\n"); 643 return; 644 } 645 646 CComPtr<IACList2> ACList; 647 ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK); 648 if (!SUCCEEDED(hr)) 649 { 650 skip("QueryInterface failed\n"); 651 return; 652 } 653 654 WCHAR Buffer[MAX_PATH]; 655 GetSystemWindowsDirectoryW(Buffer, _ARRAYSIZE(Buffer)); 656 // Windows 2k3 does not parse it without the trailing '\\' 657 Buffer[3] = '\0'; 658 CComHeapPtr<ITEMIDLIST> pidlDiskRoot; 659 ok_hr(hr = SHParseDisplayName(Buffer, NULL, &pidlDiskRoot, NULL, NULL), S_OK); 660 if (!SUCCEEDED(hr)) 661 { 662 skip("SHParseDisplayName failed\n"); 663 return; 664 } 665 666 ok_hr(hr = ACList->SetOptions(ACLO_FILESYSONLY), S_OK); 667 test_at_end(EnumStr); 668 669 ok_hr(hr = ACList->Expand(Buffer), S_OK); 670 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, CheckLast | IgnoreHidden); 671 } 672 673 static void 674 test_ACListISF_FILESYSDIRS() 675 { 676 CComPtr<IEnumString> EnumStr; 677 HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr)); 678 ok_hr(hr, S_OK); 679 if (!SUCCEEDED(hr)) 680 { 681 skip("CoCreateInstance failed\n"); 682 return; 683 } 684 685 CComPtr<IACList2> ACList; 686 ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK); 687 if (!SUCCEEDED(hr)) 688 { 689 skip("QueryInterface failed\n"); 690 return; 691 } 692 693 WCHAR Buffer[MAX_PATH]; 694 GetSystemWindowsDirectoryW(Buffer, _ARRAYSIZE(Buffer)); 695 // Windows 2k3 does not parse it without the trailing '\\' 696 Buffer[3] = '\0'; 697 CComHeapPtr<ITEMIDLIST> pidlDiskRoot; 698 ok_hr(hr = SHParseDisplayName(Buffer, NULL, &pidlDiskRoot, NULL, NULL), S_OK); 699 if (!SUCCEEDED(hr)) 700 return; 701 702 ok_hr(hr = ACList->SetOptions(ACLO_FILESYSDIRS), S_OK); 703 test_at_end(EnumStr); 704 705 ok_hr(hr = ACList->Expand(Buffer), S_OK); 706 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, CheckLast | IgnoreFiles | IgnoreHidden); 707 } 708 709 static void GetEnvStatus() 710 { 711 RTL_OSVERSIONINFOEXW rtlinfo = {0}; 712 void (__stdcall* pRtlGetVersion)(RTL_OSVERSIONINFOEXW*); 713 pRtlGetVersion = (void (__stdcall*)(RTL_OSVERSIONINFOEXW*))GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion"); 714 715 rtlinfo.dwOSVersionInfoSize = sizeof(rtlinfo); 716 pRtlGetVersion(&rtlinfo); 717 g_WinVersion = (rtlinfo.dwMajorVersion << 8) | rtlinfo.dwMinorVersion; 718 719 SHELLFLAGSTATE sfs = {0}; 720 SHGetSettings(&sfs, SSF_SHOWALLOBJECTS); 721 g_ShowHidden = !!sfs.fShowAllObjects; 722 trace("Show hidden folders: %s\n", g_ShowHidden ? "yes" : "no"); 723 } 724 725 struct CCoInit 726 { 727 CCoInit() { hres = CoInitialize(NULL); } 728 ~CCoInit() { if (SUCCEEDED(hres)) { CoUninitialize(); } } 729 HRESULT hres; 730 }; 731 732 START_TEST(ACListISF) 733 { 734 GetEnvStatus(); 735 CCoInit init; 736 ok_hr(init.hres, S_OK); 737 if (!SUCCEEDED(init.hres)) 738 { 739 skip("CoInitialize failed\n"); 740 return; 741 } 742 743 test_ACListISF_NONE(); 744 test_ACListISF_CURRENTDIR(); 745 test_ACListISF_CURRENTDIR2(); 746 test_ACListISF_MYCOMPUTER(); 747 test_ACListISF_DESKTOP(); 748 test_ACListISF_FAVORITES(); 749 test_ACListISF_FILESYSONLY(); 750 test_ACListISF_FILESYSDIRS(); 751 } 752