[SHELL32_APITEST] -Add some tests for SHParseDisplayName for CORE-12882.
[reactos.git] / rostests / apitests / browseui / ACListISF.cpp
1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for ACListISF objects
5 * PROGRAMMER: Mark Jansen
6 */
7
8 #define _UNICODE
9 #define UNICODE
10 #include <apitest.h>
11 #include <shlobj.h>
12 #include <atlbase.h>
13 #include <tchar.h> //
14 #include <atlcom.h> // These 3 includes only exist here to make gcc happy about (unused) templates..
15 #include <atlwin.h> //
16
17 // Yes, gcc at it again, let's validate everything found inside unused templates!
18 ULONG DbgPrint(PCH Format,...);
19
20 #include <shellutils.h>
21 #include <shlwapi.h>
22 #include <strsafe.h>
23
24 static bool g_ShowHidden;
25 static DWORD g_WinVersion;
26 #define WINVER_VISTA 0x0600
27
28
29 #define ok_hr(status, expected) ok_hex(status, expected)
30
31 // We do not want our results to originate from the helper functions, so have them originate from the calls to them
32 #define test_at_end (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_at_end_imp
33 #define test_ExpectDrives (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_ExpectDrives_imp
34 #define test_ExpectFolders (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_ExpectFolders_imp
35 #define winetest_ok_hr(expression, expected) \
36 do { \
37 int _value = (expression); \
38 winetest_ok(_value == (expected), "Wrong value for '%s', expected: " #expected " (0x%x), got: 0x%x\n", \
39 #expression, (int)(expected), _value); \
40 } while (0)
41
42
43
44
45 static void test_at_end_imp(CComPtr<IEnumString>& EnumStr)
46 {
47 CComHeapPtr<OLECHAR> Result;
48 ULONG Fetched = 12345;
49 HRESULT hr = EnumStr->Next(1, &Result, &Fetched);
50 winetest_ok(hr == S_FALSE, "Expected hr to be S_FALSE, was 0x%lx\n", hr);
51 winetest_ok(Fetched == 0u, "Expected Fetched to be 0, was: %lu\n", Fetched);
52 if (Fetched == 1u)
53 winetest_ok(0, "Expected there not to be a result, got: %s\n", wine_dbgstr_w(Result));
54 }
55
56 static bool GetDisplayname(CComPtr<IShellFolder>& spDrives, CComHeapPtr<ITEMIDLIST>& pidl, CComHeapPtr<WCHAR>& DisplayName)
57 {
58 STRRET StrRet;
59 HRESULT hr;
60 winetest_ok_hr(hr = spDrives->GetDisplayNameOf(pidl, SHGDN_INFOLDER | SHGDN_FORPARSING | SHGDN_FORADDRESSBAR, &StrRet), S_OK);
61 if (!SUCCEEDED(hr))
62 return false;
63
64 winetest_ok_hr(hr = StrRetToStrW(&StrRet, NULL, &DisplayName), S_OK);
65 if (!SUCCEEDED(hr))
66 return false;
67 return true;
68 }
69
70 enum ExpectOptions
71 {
72 None = 0,
73 IgnoreRoot = 1,
74 CheckLast = 2,
75 IgnoreHidden = 4,
76 IgnoreFiles = 8,
77 };
78
79 // wtf c++
80 ExpectOptions operator | (const ExpectOptions& left, const ExpectOptions& right)
81 {
82 return static_cast<ExpectOptions>(static_cast<int>(left) | static_cast<int>(right));
83 }
84
85
86 static void
87 test_ExpectFolders_imp(CComPtr<IEnumString>& EnumStr, LPITEMIDLIST pidlTarget, const WCHAR* Root, ExpectOptions options)
88 {
89 CComPtr<IShellFolder> spDesktop;
90 HRESULT hr = SHGetDesktopFolder(&spDesktop);
91
92 CComPtr<IShellFolder> spTarget;
93 if (pidlTarget)
94 {
95 winetest_ok_hr(hr = spDesktop->BindToObject(pidlTarget, NULL, IID_PPV_ARG(IShellFolder, &spTarget)), S_OK);
96 if (!SUCCEEDED(hr))
97 return;
98 }
99 else
100 {
101 spTarget = spDesktop;
102 }
103
104 SHCONTF EnumFlags = SHCONTF_FOLDERS | SHCONTF_INIT_ON_FIRST_NEXT;
105 if (g_ShowHidden && !(options & IgnoreHidden))
106 EnumFlags |= SHCONTF_INCLUDEHIDDEN;
107 if (!(options & IgnoreFiles))
108 EnumFlags |= SHCONTF_NONFOLDERS;
109
110 CComPtr<IEnumIDList> spEnumIDList;
111 winetest_ok_hr(hr = spTarget->EnumObjects(NULL, EnumFlags, &spEnumIDList), S_OK);
112 if (!SUCCEEDED(hr))
113 return;
114
115 WCHAR Buffer[512];
116 CComHeapPtr<ITEMIDLIST> pidl;
117 INT Count = 0;
118 while (spEnumIDList->Next(1, &pidl, NULL) == S_OK)
119 {
120 CComHeapPtr<WCHAR> DisplayName;
121 if (!GetDisplayname(spTarget, pidl, DisplayName))
122 break;
123
124 CComHeapPtr<OLECHAR> Result;
125 ULONG Fetched;
126 hr = EnumStr->Next(1, &Result, &Fetched);
127 winetest_ok_hr(hr, S_OK);
128
129
130 if (hr != S_OK)
131 break;
132
133
134 StringCchPrintfW(Buffer, _ARRAYSIZE(Buffer), L"%s%s", (options & IgnoreRoot) ? L"" : Root, (WCHAR*)DisplayName);
135
136 winetest_ok(!wcscmp(Buffer, Result), "Expected %s, got %s\n", wine_dbgstr_w(Buffer), wine_dbgstr_w(Result));
137
138 pidl.Free();
139 Count++;
140 }
141 if (options & CheckLast)
142 {
143 test_at_end_imp(EnumStr);
144 }
145 }
146
147 static void
148 test_ExpectDrives_imp(CComPtr<IEnumString>& EnumStr, CComHeapPtr<ITEMIDLIST>& pidlTarget)
149 {
150 test_ExpectFolders_imp(EnumStr, pidlTarget, NULL, IgnoreRoot | CheckLast);
151 }
152
153 static void
154 test_ACListISF_NONE()
155 {
156 CComPtr<IEnumString> EnumStr;
157 HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr));
158 ok_hr(hr, S_OK);
159 if (!SUCCEEDED(hr))
160 return;
161
162 CComPtr<IACList2> ACList;
163 ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK);
164 if (!SUCCEEDED(hr))
165 return;
166
167 ok_hr(hr = ACList->SetOptions(ACLO_NONE), S_OK);
168 test_at_end(EnumStr);
169
170
171 WCHAR Buffer[MAX_PATH];
172 GetSystemWindowsDirectoryW(Buffer, _ARRAYSIZE(Buffer));
173 Buffer[3] = '\0';
174
175 CComHeapPtr<ITEMIDLIST> pidlDiskRoot;
176 ok_hr(hr = SHParseDisplayName(Buffer, NULL, &pidlDiskRoot, NULL, NULL), S_OK);
177 if (!SUCCEEDED(hr))
178 return;
179
180 ok_hr(hr = ACList->Expand(Buffer), S_OK);
181 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, CheckLast | IgnoreHidden);
182
183 ok_hr(hr = EnumStr->Reset(), S_OK);
184 ok_hr(hr = ACList->Expand(Buffer), S_OK);
185 ok_hr(hr = ACList->SetOptions(ACLO_NONE), S_OK);
186 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, CheckLast);
187 }
188
189 static void
190 test_ACListISF_CURRENTDIR()
191 {
192 CComPtr<IEnumString> EnumStr;
193 HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr));
194 ok_hr(hr, S_OK);
195 if (!SUCCEEDED(hr))
196 return;
197
198 CComPtr<IACList2> ACList;
199 ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK);
200 if (!SUCCEEDED(hr))
201 return;
202
203 CComPtr<ICurrentWorkingDirectory> CurrentWorkingDir;
204 ok_hr(hr = EnumStr->QueryInterface(IID_ICurrentWorkingDirectory, (void**)&CurrentWorkingDir), S_OK);
205 if (!SUCCEEDED(hr))
206 return;
207
208 ok_hr(hr = ACList->SetOptions(ACLO_CURRENTDIR), S_OK);
209 test_at_end(EnumStr);
210
211
212 WCHAR Buffer[MAX_PATH] = { 1, 1, 1, 1, 1, 0 }, Buffer2[MAX_PATH];
213 if (g_WinVersion < WINVER_VISTA)
214 ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), E_NOTIMPL);
215 else
216 ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), E_UNEXPECTED);
217 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));
218
219 GetSystemWindowsDirectoryW(Buffer2, _ARRAYSIZE(Buffer2));
220 // Windows 2k3 does not parse it without the trailing '\\'
221 Buffer2[3] = '\0';
222 CComHeapPtr<ITEMIDLIST> pidlDiskRoot;
223 ok_hr(hr = SHParseDisplayName(Buffer2, NULL, &pidlDiskRoot, NULL, NULL), S_OK);
224 if (!SUCCEEDED(hr))
225 return;
226
227 ok_hr(hr = CurrentWorkingDir->SetDirectory(Buffer2), S_OK);
228 test_at_end(EnumStr);
229
230 Buffer[0] = '\0';
231 if (g_WinVersion < WINVER_VISTA)
232 {
233 ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), E_NOTIMPL);
234 }
235 else
236 {
237 ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), S_OK);
238 ok(!wcscmp(Buffer2, Buffer), "Expected %s, got %s\n", wine_dbgstr_w(Buffer2), wine_dbgstr_w(Buffer));
239 }
240
241 Buffer2[2] = '\0';
242 ok_hr(hr = CurrentWorkingDir->SetDirectory(Buffer2), S_OK);
243 test_at_end(EnumStr);
244
245 Buffer[0] = '\0';
246 Buffer2[2] = '\\';
247 if (g_WinVersion < WINVER_VISTA)
248 {
249 ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), E_NOTIMPL);
250 }
251 else
252 {
253 ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), S_OK);
254 ok(!wcscmp(Buffer2, Buffer), "Expected %s, got %s\n", wine_dbgstr_w(Buffer2), wine_dbgstr_w(Buffer));
255 }
256
257 ok_hr(hr = ACList->Expand(Buffer2), S_OK);
258 // The first set of results are absolute paths, without hidden files?!
259 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer2, IgnoreHidden);
260 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer2, IgnoreHidden | IgnoreRoot | CheckLast);
261 }
262
263 static void
264 test_ACListISF_MYCOMPUTER()
265 {
266 CComPtr<IACList2> ACList;
267 HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IACList2, &ACList));
268 ok_hr(hr, S_OK);
269 if (!SUCCEEDED(hr))
270 return;
271
272 // Check the default
273 DWORD CurrentOption = 0xdeadbeef;
274 ok_hr(ACList->GetOptions(&CurrentOption), S_OK);
275 ok(CurrentOption == (ACLO_CURRENTDIR|ACLO_MYCOMPUTER), "Expected the default to be %x, was %lx\n",
276 (ACLO_CURRENTDIR|ACLO_MYCOMPUTER), CurrentOption);
277
278
279 CComPtr<IEnumString> EnumStr;
280 ok_hr(hr = ACList->QueryInterface(IID_IEnumString, (void**)&EnumStr), S_OK);
281 if (!SUCCEEDED(hr))
282 return;
283
284 CComPtr<IPersistFolder> PersistFolder;
285 ok_hr(hr = EnumStr->QueryInterface(IID_IPersistFolder, (void**)&PersistFolder), S_OK);
286 if (!SUCCEEDED(hr))
287 return;
288
289 CComHeapPtr<ITEMIDLIST> pidlMyComputer;
290 ok_hr(hr = SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidlMyComputer), S_OK);
291 if (!SUCCEEDED(hr))
292 return;
293
294
295 hr = EnumStr->Reset();
296 if (g_WinVersion < WINVER_VISTA)
297 ok_hr(hr, S_FALSE);
298 else
299 ok_hr(hr, S_OK);
300 test_ExpectDrives(EnumStr, pidlMyComputer);
301
302 ok_hr(hr = ACList->SetOptions(ACLO_MYCOMPUTER), S_OK);
303 ok_hr(EnumStr->Reset(), S_OK);
304 test_ExpectDrives(EnumStr, pidlMyComputer);
305
306 WCHAR Buffer[MAX_PATH];
307 GetSystemWindowsDirectoryW(Buffer, _ARRAYSIZE(Buffer));
308 // Windows 2k3 does not parse it without the trailing '\\'
309 Buffer[3] = '\0';
310 CComHeapPtr<ITEMIDLIST> pidlDiskRoot;
311 ok_hr(hr = SHParseDisplayName(Buffer, NULL, &pidlDiskRoot, NULL, NULL), S_OK);
312 if (!SUCCEEDED(hr))
313 return;
314 Buffer[2] = '\0';
315
316 ok_hr(hr = ACList->Expand(Buffer), S_OK);
317 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, None);
318 test_ExpectDrives(EnumStr, pidlMyComputer);
319
320 ok_hr(hr = ACList->Expand(Buffer), S_OK);
321 ok_hr(EnumStr->Reset(), S_OK);
322 // Pre vista does not remove the expanded data from the enumeration, it changes it to relative paths???
323 if (g_WinVersion < WINVER_VISTA)
324 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, IgnoreRoot);
325 test_ExpectDrives(EnumStr, pidlMyComputer);
326
327 ok_hr(EnumStr->Reset(), S_OK);
328 ok_hr(hr = ACList->Expand(Buffer), S_OK);
329 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, None);
330 test_ExpectDrives(EnumStr, pidlMyComputer);
331 }
332
333 static void
334 test_ACListISF_DESKTOP()
335 {
336 CComPtr<IEnumString> EnumStr;
337 HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr));
338 ok_hr(hr, S_OK);
339 if (!SUCCEEDED(hr))
340 return;
341
342 CComPtr<IACList2> ACList;
343 ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK);
344 if (!SUCCEEDED(hr))
345 return;
346
347 ok_hr(hr = ACList->SetOptions(ACLO_DESKTOP), S_OK);
348 test_ExpectFolders(EnumStr, NULL, NULL, IgnoreRoot | CheckLast | IgnoreHidden);
349 }
350
351 static void
352 test_ACListISF_FAVORITES()
353 {
354 CComPtr<IEnumString> EnumStr;
355 HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr));
356 ok_hr(hr, S_OK);
357 if (!SUCCEEDED(hr))
358 return;
359
360 CComPtr<IACList2> ACList;
361 ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK);
362 if (!SUCCEEDED(hr))
363 return;
364
365 CComHeapPtr<ITEMIDLIST> pidlFavorites;
366 ok_hr(hr = SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidlFavorites), S_OK);
367 if (!SUCCEEDED(hr))
368 return;
369
370 ok_hr(hr = ACList->SetOptions(ACLO_FAVORITES), S_OK);
371 test_ExpectFolders(EnumStr, pidlFavorites, NULL, IgnoreRoot | CheckLast | IgnoreHidden);
372 }
373
374 static void
375 test_ACListISF_FILESYSONLY()
376 {
377 CComPtr<IEnumString> EnumStr;
378 HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr));
379 ok_hr(hr, S_OK);
380 if (!SUCCEEDED(hr))
381 return;
382
383 CComPtr<IACList2> ACList;
384 ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK);
385 if (!SUCCEEDED(hr))
386 return;
387
388 WCHAR Buffer[MAX_PATH];
389 GetSystemWindowsDirectoryW(Buffer, _ARRAYSIZE(Buffer));
390 // Windows 2k3 does not parse it without the trailing '\\'
391 Buffer[3] = '\0';
392 CComHeapPtr<ITEMIDLIST> pidlDiskRoot;
393 ok_hr(hr = SHParseDisplayName(Buffer, NULL, &pidlDiskRoot, NULL, NULL), S_OK);
394 if (!SUCCEEDED(hr))
395 return;
396
397 ok_hr(hr = ACList->SetOptions(ACLO_FILESYSONLY), S_OK);
398 test_at_end(EnumStr);
399
400 ok_hr(hr = ACList->Expand(Buffer), S_OK);
401 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, CheckLast | IgnoreHidden);
402 }
403
404 static void
405 test_ACListISF_FILESYSDIRS()
406 {
407 CComPtr<IEnumString> EnumStr;
408 HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr));
409 ok_hr(hr, S_OK);
410 if (!SUCCEEDED(hr))
411 return;
412
413 CComPtr<IACList2> ACList;
414 ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK);
415 if (!SUCCEEDED(hr))
416 return;
417
418 WCHAR Buffer[MAX_PATH];
419 GetSystemWindowsDirectoryW(Buffer, _ARRAYSIZE(Buffer));
420 // Windows 2k3 does not parse it without the trailing '\\'
421 Buffer[3] = '\0';
422 CComHeapPtr<ITEMIDLIST> pidlDiskRoot;
423 ok_hr(hr = SHParseDisplayName(Buffer, NULL, &pidlDiskRoot, NULL, NULL), S_OK);
424 if (!SUCCEEDED(hr))
425 return;
426
427 ok_hr(hr = ACList->SetOptions(ACLO_FILESYSDIRS), S_OK);
428 test_at_end(EnumStr);
429
430 ok_hr(hr = ACList->Expand(Buffer), S_OK);
431 test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, CheckLast | IgnoreFiles | IgnoreHidden);
432 }
433
434 static void GetEnvStatus()
435 {
436 RTL_OSVERSIONINFOEXW rtlinfo = {0};
437 void (__stdcall* pRtlGetVersion)(RTL_OSVERSIONINFOEXW*);
438 pRtlGetVersion = (void (__stdcall*)(RTL_OSVERSIONINFOEXW*))GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");
439
440 rtlinfo.dwOSVersionInfoSize = sizeof(rtlinfo);
441 pRtlGetVersion(&rtlinfo);
442 g_WinVersion = (rtlinfo.dwMajorVersion << 8) | rtlinfo.dwMinorVersion;
443
444 SHELLFLAGSTATE sfs = {0};
445 SHGetSettings(&sfs, SSF_SHOWALLOBJECTS);
446 g_ShowHidden = !!sfs.fShowAllObjects;
447 trace("Show hidden folders: %s\n", g_ShowHidden ? "yes" : "no");
448 }
449
450 struct CCoInit
451 {
452 CCoInit() { hres = CoInitialize(NULL); }
453 ~CCoInit() { if (SUCCEEDED(hres)) { CoUninitialize(); } }
454 HRESULT hres;
455 };
456
457 START_TEST(ACListISF)
458 {
459 GetEnvStatus();
460 CCoInit init;
461 ok_hr(init.hres, S_OK);
462 if (!SUCCEEDED(init.hres))
463 return;
464
465 test_ACListISF_NONE();
466 test_ACListISF_CURRENTDIR();
467 test_ACListISF_MYCOMPUTER();
468 test_ACListISF_DESKTOP();
469 test_ACListISF_FAVORITES();
470 test_ACListISF_FILESYSONLY();
471 test_ACListISF_FILESYSDIRS();
472 }