[RAPPS] Stopped GCC whining (fixed GCC build)
[reactos.git] / rostests / apitests / shell32 / CShellDesktop.cpp
1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test for CShellDesktop
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6 * Mark Jansen
7 */
8
9 #include "shelltest.h"
10 #include <atlbase.h>
11 #include <atlcom.h>
12 #include <strsafe.h>
13 #include <ndk/rtlfuncs.h>
14
15 #define NDEBUG
16 #include <debug.h>
17 #include <shellutils.h>
18
19
20 // We would normally use S_LESSTHAN and S_GREATERTHAN, but w2k3 returns numbers like 3 and -3...
21 // So instead we check on the sign bit (compare result is the low word of the hresult).
22 #define SHORT_SIGN_BIT 0x8000
23
24 static
25 VOID
26 compare_imp(IShellFolder* psf, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2, HRESULT expected)
27 {
28 HRESULT hr;
29 _SEH2_TRY
30 {
31 hr = psf->CompareIDs(0, pidl1, pidl2);
32 }
33 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
34 {
35 winetest_ok(0, "Exception %lx!\n", _SEH2_GetExceptionCode());
36 hr = HRESULT_FROM_WIN32(RtlNtStatusToDosError(_SEH2_GetExceptionCode()));
37 }
38 _SEH2_END;
39 if (expected == S_LESSTHAN)
40 winetest_ok(SUCCEEDED(hr) && (hr & SHORT_SIGN_BIT), "hr = %lx\n", hr);
41 else if (expected == S_EQUAL)
42 winetest_ok(hr == S_EQUAL, "hr = %lx\n", hr);
43 else if (expected == S_GREATERTHAN)
44 winetest_ok(SUCCEEDED(hr) && !(hr & SHORT_SIGN_BIT), "hr = %lx\n", hr);
45 else
46 winetest_ok(hr == expected, "hr = %lx\n", hr);
47 }
48
49 // make the winetest_ok look like it came from the line where the compare function was called, and not from inside the compare_imp function :)
50 #define compare (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : compare_imp
51
52 static
53 VOID
54 TestCompareIDList(IShellFolder* psf)
55 {
56 compare(psf, NULL, NULL, E_INVALIDARG);
57
58 CComHeapPtr<ITEMIDLIST> desktop;
59 HRESULT hr = SHGetFolderLocation(NULL, CSIDL_DESKTOP, NULL, NULL, &desktop);
60 ok(hr == S_OK, "hr = %lx\n", hr);
61 compare(psf, desktop, NULL, E_INVALIDARG);
62 compare(psf, NULL, desktop, E_INVALIDARG);
63 compare(psf, desktop, desktop, S_EQUAL);
64
65 // First check the ordering of some special folders against eachother
66 CComHeapPtr<ITEMIDLIST> internet;
67 hr = SHGetFolderLocation(NULL, CSIDL_INTERNET, NULL, NULL, &internet);
68 ok(hr == S_OK, "hr = %lx\n", hr);
69 compare(psf, internet, desktop, S_LESSTHAN);
70 compare(psf, desktop, internet, S_GREATERTHAN);
71
72 CComHeapPtr<ITEMIDLIST> programs;
73 hr = SHGetFolderLocation(NULL, CSIDL_PROGRAMS, NULL, NULL, &programs);
74 ok(hr == S_OK, "hr = %lx\n", hr);
75 compare(psf, programs, desktop, S_LESSTHAN);
76 compare(psf, desktop, programs, S_GREATERTHAN);
77 compare(psf, internet, programs, S_GREATERTHAN);
78 compare(psf, programs, internet, S_LESSTHAN);
79
80 // Verify that an idlist retrieved from GetCurFolder is equal to the original one.
81 CComPtr<IPersistFolder2> persist;
82 hr = psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &persist));
83 ok(hr == S_OK, "hr = %lx\n", hr);
84 if (hr == S_OK)
85 {
86 CComHeapPtr<ITEMIDLIST> cur;
87 hr = persist->GetCurFolder(&cur);
88 ok(hr == S_OK, "hr = %lx\n", hr);
89 compare(psf, cur, desktop, S_EQUAL);
90 compare(psf, desktop, cur, S_EQUAL);
91 }
92
93 // Compare special folders against full paths
94 CComHeapPtr<ITEMIDLIST> dir1, dir2;
95 PathToIDList(L"A:\\AAA.AAA", &dir1);
96 PathToIDList(L"A:\\ZZZ.ZZZ", &dir2);
97
98 compare(psf, dir1, desktop, S_LESSTHAN);
99 compare(psf, desktop, dir1, S_GREATERTHAN);
100 compare(psf, dir1, programs, S_LESSTHAN);
101 compare(psf, programs, dir1, S_GREATERTHAN);
102 compare(psf, dir1, dir1, S_EQUAL);
103
104 compare(psf, dir2, desktop, S_LESSTHAN);
105 compare(psf, desktop, dir2, S_GREATERTHAN);
106 compare(psf, dir2, programs, S_LESSTHAN);
107 compare(psf, programs, dir2, S_GREATERTHAN);
108 compare(psf, dir2, dir2, S_EQUAL);
109
110 CComHeapPtr<ITEMIDLIST> dir3, dir4;
111 PathToIDList(L"Z:\\AAA.AAA", &dir3);
112 PathToIDList(L"Z:\\ZZZ.ZZZ", &dir4);
113
114 compare(psf, dir3, desktop, S_LESSTHAN);
115 compare(psf, desktop, dir3, S_GREATERTHAN);
116 compare(psf, dir3, programs, S_GREATERTHAN);
117 compare(psf, programs, dir3, S_LESSTHAN);
118 compare(psf, dir3, dir3, S_EQUAL);
119
120 compare(psf, dir4, desktop, S_LESSTHAN);
121 compare(psf, desktop, dir4, S_GREATERTHAN);
122 compare(psf, dir4, programs, S_GREATERTHAN);
123 compare(psf, programs, dir4, S_LESSTHAN);
124 compare(psf, dir4, dir4, S_EQUAL);
125
126 // Now compare the paths against eachother.
127 compare(psf, dir1, dir2, S_LESSTHAN);
128 compare(psf, dir2, dir1, S_GREATERTHAN);
129
130 compare(psf, dir2, dir3, S_LESSTHAN);
131 compare(psf, dir3, dir2, S_GREATERTHAN);
132
133 compare(psf, dir3, dir4, S_LESSTHAN);
134 compare(psf, dir4, dir3, S_GREATERTHAN);
135
136 // Check that comparing desktop pidl with another one with another IShellFolder fails
137 CComPtr<IShellFolder> psf2;
138 hr = psf->BindToObject(programs, NULL, IID_IShellFolder, reinterpret_cast<void**>(&psf2));
139 ok(hr == S_OK, "Impossible to bind to Programs pidl");
140 if (hr == S_OK)
141 {
142 // Compare desktop pidl in programs scope should fail since it's relative pidl
143 compare(psf2, desktop, programs, E_INVALIDARG);
144 compare(psf2, programs, desktop, E_INVALIDARG);
145 // For the same reasons, filesystem paths can't be compared with special shell
146 // folders that don't have CFSFolder in children
147 compare(psf2, dir1, dir2, E_INVALIDARG);
148 compare(psf2, dir2, dir1, E_INVALIDARG);
149 }
150 }
151
152 static
153 VOID
154 TestShellFolder(
155 _In_ IShellFolder2 *psf2)
156 {
157 HRESULT hr;
158 CComPtr<IDropTarget> pdt;
159 CComPtr<IDropTarget> pdt_2;
160 CComPtr<IContextMenu> pcm;
161 CComPtr<IContextMenu> pcm_2;
162 CComPtr<IShellView> psv;
163 CComPtr<IShellView> psv_2;
164
165 hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget, &pdt));
166 ok(hr == S_OK, "hr = %lx\n", hr);
167
168 hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget, &pdt_2));
169 ok(hr == S_OK, "hr = %lx\n", hr);
170 ok(pdt != pdt_2, "Expected %p != %p\n", static_cast<PVOID>(pdt), static_cast<PVOID>(pdt_2));
171
172 hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IContextMenu, &pcm));
173 ok(hr == S_OK, "hr = %lx\n", hr);
174
175 hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IContextMenu, &pcm_2));
176 ok(hr == S_OK, "hr = %lx\n", hr);
177 ok(pcm != pcm_2, "Expected %p != %p\n", static_cast<PVOID>(pcm), static_cast<PVOID>(pcm_2));
178
179 hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IShellView, &psv));
180 ok(hr == S_OK, "hr = %lx\n", hr);
181
182 hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IShellView, &psv_2));
183 ok(hr == S_OK, "hr = %lx\n", hr);
184 ok(psv != psv_2, "Expected %p != %p\n", static_cast<PVOID>(psv), static_cast<PVOID>(psv_2));
185
186 STRRET strret;
187 hr = psf2->GetDisplayNameOf(NULL, 0, &strret);
188 ok(hr == S_OK, "hr = %lx\n", hr);
189 }
190
191 VOID TestInitialize(_In_ IShellFolder *psf)
192 {
193 CComPtr<IPersistFolder2> ppf2;
194 HRESULT hr = psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
195 ok(hr == S_OK, "hr = %lx\n", hr);
196
197 /* Create a tiny pidl with no contents */
198 LPITEMIDLIST testpidl = (LPITEMIDLIST)SHAlloc(3 * sizeof(WORD));
199 testpidl->mkid.cb = 2 * sizeof(WORD);
200 *(WORD*)((char*)testpidl + (int)(2 * sizeof(WORD))) = 0;
201
202 hr = ppf2->Initialize(testpidl);
203 ok(hr == E_INVALIDARG, "hr = %lx\n", hr);
204
205 //crashes in xp, works on win10
206 //hr = ppf2->Initialize(NULL);
207 //ok(hr == S_OK, "hr = %lx\n", hr);
208 //hr = ppf2->Initialize((LPCITEMIDLIST)0xdeaddead);
209 //ok(hr == S_OK, "hr = %lx\n", hr);
210 //hr = ppf2->GetCurFolder(NULL);
211 //ok(hr == E_INVALIDARG, "hr = %lx\n", hr);
212
213 LPITEMIDLIST pidl;
214 hr = ppf2->GetCurFolder(&pidl);
215 ok(hr == S_OK, "hr = %lx\n", hr);
216 ok(pidl->mkid.cb == 0, "expected empty pidl got cb = %x\n", pidl->mkid.cb);
217 }
218
219 START_TEST(CShellDesktop)
220 {
221 HRESULT hr;
222 CComPtr<IShellFolder2> psf2;
223 CComPtr<IShellFolder2> psf2_2;
224 CComPtr<IShellFolder> psf;
225
226 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
227
228 hr = CoCreateInstance(CLSID_ShellDesktop,
229 NULL,
230 CLSCTX_INPROC_SERVER,
231 IID_PPV_ARG(IShellFolder2, &psf2));
232 ok(hr == S_OK, "hr = %lx\n", hr);
233 if (FAILED(hr))
234 {
235 skip("Could not instantiate CShellDesktop\n");
236 return;
237 }
238
239 /* second create should give us a pointer to the same object */
240 hr = CoCreateInstance(CLSID_ShellDesktop,
241 NULL,
242 CLSCTX_INPROC_SERVER,
243 IID_PPV_ARG(IShellFolder2, &psf2_2));
244 ok(hr == S_OK, "hr = %lx\n", hr);
245 ok(psf2 == psf2_2, "Expected %p == %p\n", static_cast<PVOID>(psf2), static_cast<PVOID>(psf2_2));
246
247 /* SHGetDesktopFolder should also give us the same pointer */
248 hr = SHGetDesktopFolder(&psf);
249 ok(hr == S_OK, "hr = %lx\n", hr);
250 ok(psf == static_cast<IShellFolder *>(psf2), "Expected %p == %p\n", static_cast<PVOID>(psf), static_cast<PVOID>(psf2));
251
252 TestShellFolder(psf2);
253 TestCompareIDList(psf);
254 TestInitialize(psf);
255 }