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
test_at_end_imp(CComPtr<IEnumString> & EnumStr)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
GetDisplayname(CComPtr<IShellFolder> & spDrives,CComHeapPtr<ITEMIDLIST> & pidl,CComHeapPtr<WCHAR> & DisplayName)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++
operator |(const ExpectOptions & left,const ExpectOptions & right)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
test_ExpectFolders_imp(CComPtr<IEnumString> & EnumStr,LPITEMIDLIST pidlTarget,const WCHAR * Root,ExpectOptions options)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
test_ExpectDrives_imp(CComPtr<IEnumString> & EnumStr,CComHeapPtr<ITEMIDLIST> & pidlTarget)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
test_ACListISF_NONE()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
test_ACListISF_CURRENTDIR()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
test_ACListISF_CURRENTDIR2()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
test_ACListISF_MYCOMPUTER()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
test_ACListISF_DESKTOP()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
test_ACListISF_FAVORITES()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
test_ACListISF_FILESYSONLY()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
test_ACListISF_FILESYSDIRS()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
GetEnvStatus()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
START_TEST(ACListISF)725 START_TEST(ACListISF)
726 {
727 GetEnvStatus();
728 CCoInit init;
729 ok_hr(init.hr, S_OK);
730 if (!SUCCEEDED(init.hr))
731 {
732 skip("CoInitialize failed\n");
733 return;
734 }
735
736 test_ACListISF_NONE();
737 test_ACListISF_CURRENTDIR();
738 test_ACListISF_CURRENTDIR2();
739 test_ACListISF_MYCOMPUTER();
740 test_ACListISF_DESKTOP();
741 test_ACListISF_FAVORITES();
742 test_ACListISF_FILESYSONLY();
743 test_ACListISF_FILESYSDIRS();
744 }
745