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>
11 #include <ndk/rtlfuncs.h>
13 #include <shellutils.h>
15 // We would normally use S_LESSTHAN and S_GREATERTHAN, but w2k3 returns numbers like 3 and -3...
16 // So instead we check on the sign bit (compare result is the low word of the hresult).
17 #define SHORT_SIGN_BIT 0x8000
21 compare_imp(IShellFolder
* psf
, LPCITEMIDLIST pidl1
, LPCITEMIDLIST pidl2
, HRESULT expected
)
26 hr
= psf
->CompareIDs(0, pidl1
, pidl2
);
28 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
30 winetest_ok(0, "Exception %lx!\n", _SEH2_GetExceptionCode());
31 hr
= HRESULT_FROM_WIN32(RtlNtStatusToDosError(_SEH2_GetExceptionCode()));
34 if (expected
== S_LESSTHAN
)
35 winetest_ok(SUCCEEDED(hr
) && (hr
& SHORT_SIGN_BIT
), "hr = %lx\n", hr
);
36 else if (expected
== S_EQUAL
)
37 winetest_ok(hr
== S_EQUAL
, "hr = %lx\n", hr
);
38 else if (expected
== S_GREATERTHAN
)
39 winetest_ok(SUCCEEDED(hr
) && !(hr
& SHORT_SIGN_BIT
), "hr = %lx\n", hr
);
41 winetest_ok(hr
== expected
, "hr = %lx\n", hr
);
44 // 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 :)
45 #define compare (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : compare_imp
49 TestCompareIDList(IShellFolder
* psf
)
51 compare(psf
, NULL
, NULL
, E_INVALIDARG
);
53 CComHeapPtr
<ITEMIDLIST
> desktop
;
54 HRESULT hr
= SHGetFolderLocation(NULL
, CSIDL_DESKTOP
, NULL
, NULL
, &desktop
);
55 ok(hr
== S_OK
, "hr = %lx\n", hr
);
56 compare(psf
, desktop
, NULL
, E_INVALIDARG
);
57 compare(psf
, NULL
, desktop
, E_INVALIDARG
);
58 compare(psf
, desktop
, desktop
, S_EQUAL
);
60 // First check the ordering of some special folders against eachother
61 CComHeapPtr
<ITEMIDLIST
> internet
;
62 hr
= SHGetFolderLocation(NULL
, CSIDL_INTERNET
, NULL
, NULL
, &internet
);
63 ok(hr
== S_OK
, "hr = %lx\n", hr
);
64 compare(psf
, internet
, desktop
, S_LESSTHAN
);
65 compare(psf
, desktop
, internet
, S_GREATERTHAN
);
67 CComHeapPtr
<ITEMIDLIST
> programs
;
68 hr
= SHGetFolderLocation(NULL
, CSIDL_PROGRAMS
, NULL
, NULL
, &programs
);
69 ok(hr
== S_OK
, "hr = %lx\n", hr
);
70 compare(psf
, programs
, desktop
, S_LESSTHAN
);
71 compare(psf
, desktop
, programs
, S_GREATERTHAN
);
72 compare(psf
, internet
, programs
, S_GREATERTHAN
);
73 compare(psf
, programs
, internet
, S_LESSTHAN
);
75 // Verify that an idlist retrieved from GetCurFolder is equal to the original one.
76 CComPtr
<IPersistFolder2
> persist
;
77 hr
= psf
->QueryInterface(IID_PPV_ARG(IPersistFolder2
, &persist
));
78 ok(hr
== S_OK
, "hr = %lx\n", hr
);
81 CComHeapPtr
<ITEMIDLIST
> cur
;
82 hr
= persist
->GetCurFolder(&cur
);
83 ok(hr
== S_OK
, "hr = %lx\n", hr
);
84 compare(psf
, cur
, desktop
, S_EQUAL
);
85 compare(psf
, desktop
, cur
, S_EQUAL
);
88 // Compare special folders against full paths
89 CComHeapPtr
<ITEMIDLIST
> dir1
, dir2
;
90 PathToIDList(L
"A:\\AAA.AAA", &dir1
);
91 PathToIDList(L
"A:\\ZZZ.ZZZ", &dir2
);
93 compare(psf
, dir1
, desktop
, S_LESSTHAN
);
94 compare(psf
, desktop
, dir1
, S_GREATERTHAN
);
95 compare(psf
, dir1
, programs
, S_LESSTHAN
);
96 compare(psf
, programs
, dir1
, S_GREATERTHAN
);
97 compare(psf
, dir1
, dir1
, S_EQUAL
);
99 compare(psf
, dir2
, desktop
, S_LESSTHAN
);
100 compare(psf
, desktop
, dir2
, S_GREATERTHAN
);
101 compare(psf
, dir2
, programs
, S_LESSTHAN
);
102 compare(psf
, programs
, dir2
, S_GREATERTHAN
);
103 compare(psf
, dir2
, dir2
, S_EQUAL
);
105 CComHeapPtr
<ITEMIDLIST
> dir3
, dir4
;
106 PathToIDList(L
"Z:\\AAA.AAA", &dir3
);
107 PathToIDList(L
"Z:\\ZZZ.ZZZ", &dir4
);
109 compare(psf
, dir3
, desktop
, S_LESSTHAN
);
110 compare(psf
, desktop
, dir3
, S_GREATERTHAN
);
111 compare(psf
, dir3
, programs
, S_GREATERTHAN
);
112 compare(psf
, programs
, dir3
, S_LESSTHAN
);
113 compare(psf
, dir3
, dir3
, S_EQUAL
);
115 compare(psf
, dir4
, desktop
, S_LESSTHAN
);
116 compare(psf
, desktop
, dir4
, S_GREATERTHAN
);
117 compare(psf
, dir4
, programs
, S_GREATERTHAN
);
118 compare(psf
, programs
, dir4
, S_LESSTHAN
);
119 compare(psf
, dir4
, dir4
, S_EQUAL
);
121 // Now compare the paths against eachother.
122 compare(psf
, dir1
, dir2
, S_LESSTHAN
);
123 compare(psf
, dir2
, dir1
, S_GREATERTHAN
);
125 compare(psf
, dir2
, dir3
, S_LESSTHAN
);
126 compare(psf
, dir3
, dir2
, S_GREATERTHAN
);
128 compare(psf
, dir3
, dir4
, S_LESSTHAN
);
129 compare(psf
, dir4
, dir3
, S_GREATERTHAN
);
131 // Check that comparing desktop pidl with another one with another IShellFolder fails
132 CComPtr
<IShellFolder
> psf2
;
133 hr
= psf
->BindToObject(programs
, NULL
, IID_IShellFolder
, reinterpret_cast<void**>(&psf2
));
134 ok(hr
== S_OK
, "Impossible to bind to Programs pidl");
137 // Compare desktop pidl in programs scope should fail since it's relative pidl
138 compare(psf2
, desktop
, programs
, E_INVALIDARG
);
139 compare(psf2
, programs
, desktop
, E_INVALIDARG
);
140 // For the same reasons, filesystem paths can't be compared with special shell
141 // folders that don't have CFSFolder in children
142 compare(psf2
, dir1
, dir2
, E_INVALIDARG
);
143 compare(psf2
, dir2
, dir1
, E_INVALIDARG
);
150 _In_ IShellFolder2
*psf2
)
153 CComPtr
<IDropTarget
> pdt
;
154 CComPtr
<IDropTarget
> pdt_2
;
155 CComPtr
<IContextMenu
> pcm
;
156 CComPtr
<IContextMenu
> pcm_2
;
157 CComPtr
<IShellView
> psv
;
158 CComPtr
<IShellView
> psv_2
;
160 hr
= psf2
->CreateViewObject(NULL
, IID_PPV_ARG(IDropTarget
, &pdt
));
161 ok(hr
== S_OK
, "hr = %lx\n", hr
);
163 hr
= psf2
->CreateViewObject(NULL
, IID_PPV_ARG(IDropTarget
, &pdt_2
));
164 ok(hr
== S_OK
, "hr = %lx\n", hr
);
165 ok(pdt
!= pdt_2
, "Expected %p != %p\n", static_cast<PVOID
>(pdt
), static_cast<PVOID
>(pdt_2
));
167 hr
= psf2
->CreateViewObject(NULL
, IID_PPV_ARG(IContextMenu
, &pcm
));
168 ok(hr
== S_OK
, "hr = %lx\n", hr
);
170 hr
= psf2
->CreateViewObject(NULL
, IID_PPV_ARG(IContextMenu
, &pcm_2
));
171 ok(hr
== S_OK
, "hr = %lx\n", hr
);
172 ok(pcm
!= pcm_2
, "Expected %p != %p\n", static_cast<PVOID
>(pcm
), static_cast<PVOID
>(pcm_2
));
174 hr
= psf2
->CreateViewObject(NULL
, IID_PPV_ARG(IShellView
, &psv
));
175 ok(hr
== S_OK
, "hr = %lx\n", hr
);
177 hr
= psf2
->CreateViewObject(NULL
, IID_PPV_ARG(IShellView
, &psv_2
));
178 ok(hr
== S_OK
, "hr = %lx\n", hr
);
179 ok(psv
!= psv_2
, "Expected %p != %p\n", static_cast<PVOID
>(psv
), static_cast<PVOID
>(psv_2
));
182 hr
= psf2
->GetDisplayNameOf(NULL
, 0, &strret
);
183 ok(hr
== S_OK
, "hr = %lx\n", hr
);
186 VOID
TestInitialize(_In_ IShellFolder
*psf
)
188 CComPtr
<IPersistFolder2
> ppf2
;
189 HRESULT hr
= psf
->QueryInterface(IID_PPV_ARG(IPersistFolder2
, &ppf2
));
190 ok(hr
== S_OK
, "hr = %lx\n", hr
);
192 /* Create a tiny pidl with no contents */
193 LPITEMIDLIST testpidl
= (LPITEMIDLIST
)SHAlloc(3 * sizeof(WORD
));
194 testpidl
->mkid
.cb
= 2 * sizeof(WORD
);
195 *(WORD
*)((char*)testpidl
+ (int)(2 * sizeof(WORD
))) = 0;
197 hr
= ppf2
->Initialize(testpidl
);
198 ok(hr
== E_INVALIDARG
, "hr = %lx\n", hr
);
200 //crashes in xp, works on win10
201 //hr = ppf2->Initialize(NULL);
202 //ok(hr == S_OK, "hr = %lx\n", hr);
203 //hr = ppf2->Initialize((LPCITEMIDLIST)0xdeaddead);
204 //ok(hr == S_OK, "hr = %lx\n", hr);
205 //hr = ppf2->GetCurFolder(NULL);
206 //ok(hr == E_INVALIDARG, "hr = %lx\n", hr);
208 CComHeapPtr
<ITEMIDLIST
> pidl
;
209 hr
= ppf2
->GetCurFolder(&pidl
);
210 ok(hr
== S_OK
, "hr = %lx\n", hr
);
211 ok(pidl
->mkid
.cb
== 0, "expected empty pidl got cb = %x\n", pidl
->mkid
.cb
);
214 START_TEST(CShellDesktop
)
217 CComPtr
<IShellFolder2
> psf2
;
218 CComPtr
<IShellFolder2
> psf2_2
;
219 CComPtr
<IShellFolder
> psf
;
221 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
223 hr
= CoCreateInstance(CLSID_ShellDesktop
,
225 CLSCTX_INPROC_SERVER
,
226 IID_PPV_ARG(IShellFolder2
, &psf2
));
227 ok(hr
== S_OK
, "hr = %lx\n", hr
);
230 skip("Could not instantiate CShellDesktop\n");
234 /* second create should give us a pointer to the same object */
235 hr
= CoCreateInstance(CLSID_ShellDesktop
,
237 CLSCTX_INPROC_SERVER
,
238 IID_PPV_ARG(IShellFolder2
, &psf2_2
));
239 ok(hr
== S_OK
, "hr = %lx\n", hr
);
240 ok(psf2
== psf2_2
, "Expected %p == %p\n", static_cast<PVOID
>(psf2
), static_cast<PVOID
>(psf2_2
));
242 /* SHGetDesktopFolder should also give us the same pointer */
243 hr
= SHGetDesktopFolder(&psf
);
244 ok(hr
== S_OK
, "hr = %lx\n", hr
);
245 ok(psf
== static_cast<IShellFolder
*>(psf2
), "Expected %p == %p\n", static_cast<PVOID
>(psf
), static_cast<PVOID
>(psf2
));
247 TestDesktopFolder(psf2
);
248 TestCompareIDList(psf
);