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>
13 #include <ndk/rtlfuncs.h>
17 #include <shellutils.h>
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
26 compare_imp(IShellFolder
* psf
, LPCITEMIDLIST pidl1
, LPCITEMIDLIST pidl2
, HRESULT expected
)
31 hr
= psf
->CompareIDs(0, pidl1
, pidl2
);
33 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
35 winetest_ok(0, "Exception %lx!\n", _SEH2_GetExceptionCode());
36 hr
= HRESULT_FROM_WIN32(RtlNtStatusToDosError(_SEH2_GetExceptionCode()));
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
);
46 winetest_ok(hr
== expected
, "hr = %lx\n", hr
);
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
54 TestCompareIDList(IShellFolder
* psf
)
56 compare(psf
, NULL
, NULL
, E_INVALIDARG
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
110 CComHeapPtr
<ITEMIDLIST
> dir3
, dir4
;
111 PathToIDList(L
"Z:\\AAA.AAA", &dir3
);
112 PathToIDList(L
"Z:\\ZZZ.ZZZ", &dir4
);
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
);
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
);
126 // Now compare the paths against eachother.
127 compare(psf
, dir1
, dir2
, S_LESSTHAN
);
128 compare(psf
, dir2
, dir1
, S_GREATERTHAN
);
130 compare(psf
, dir2
, dir3
, S_LESSTHAN
);
131 compare(psf
, dir3
, dir2
, S_GREATERTHAN
);
133 compare(psf
, dir3
, dir4
, S_LESSTHAN
);
134 compare(psf
, dir4
, dir3
, S_GREATERTHAN
);
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");
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
);
155 _In_ IShellFolder2
*psf2
)
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
;
165 hr
= psf2
->CreateViewObject(NULL
, IID_PPV_ARG(IDropTarget
, &pdt
));
166 ok(hr
== S_OK
, "hr = %lx\n", hr
);
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
));
172 hr
= psf2
->CreateViewObject(NULL
, IID_PPV_ARG(IContextMenu
, &pcm
));
173 ok(hr
== S_OK
, "hr = %lx\n", hr
);
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
));
179 hr
= psf2
->CreateViewObject(NULL
, IID_PPV_ARG(IShellView
, &psv
));
180 ok(hr
== S_OK
, "hr = %lx\n", hr
);
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
));
187 hr
= psf2
->GetDisplayNameOf(NULL
, 0, &strret
);
188 ok(hr
== S_OK
, "hr = %lx\n", hr
);
191 VOID
TestInitialize(_In_ IShellFolder
*psf
)
193 CComPtr
<IPersistFolder2
> ppf2
;
194 HRESULT hr
= psf
->QueryInterface(IID_PPV_ARG(IPersistFolder2
, &ppf2
));
195 ok(hr
== S_OK
, "hr = %lx\n", hr
);
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;
202 hr
= ppf2
->Initialize(testpidl
);
203 ok(hr
== E_INVALIDARG
, "hr = %lx\n", hr
);
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);
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
);
219 START_TEST(CShellDesktop
)
222 CComPtr
<IShellFolder2
> psf2
;
223 CComPtr
<IShellFolder2
> psf2_2
;
224 CComPtr
<IShellFolder
> psf
;
226 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
228 hr
= CoCreateInstance(CLSID_ShellDesktop
,
230 CLSCTX_INPROC_SERVER
,
231 IID_PPV_ARG(IShellFolder2
, &psf2
));
232 ok(hr
== S_OK
, "hr = %lx\n", hr
);
235 skip("Could not instantiate CShellDesktop\n");
239 /* second create should give us a pointer to the same object */
240 hr
= CoCreateInstance(CLSID_ShellDesktop
,
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
));
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
));
252 TestShellFolder(psf2
);
253 TestCompareIDList(psf
);