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 START_TEST(CShellDesktop
)
190 CComPtr
<IShellFolder2
> psf2
;
191 CComPtr
<IShellFolder2
> psf2_2
;
192 CComPtr
<IShellFolder
> psf
;
194 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
196 hr
= CoCreateInstance(CLSID_ShellDesktop
,
198 CLSCTX_INPROC_SERVER
,
199 IID_PPV_ARG(IShellFolder2
, &psf2
));
200 ok(hr
== S_OK
, "hr = %lx\n", hr
);
203 skip("Could not instantiate CShellDesktop\n");
207 /* second create should give us a pointer to the same object */
208 hr
= CoCreateInstance(CLSID_ShellDesktop
,
210 CLSCTX_INPROC_SERVER
,
211 IID_PPV_ARG(IShellFolder2
, &psf2_2
));
212 ok(hr
== S_OK
, "hr = %lx\n", hr
);
213 ok(psf2
== psf2_2
, "Expected %p == %p\n", static_cast<PVOID
>(psf2
), static_cast<PVOID
>(psf2_2
));
215 /* SHGetDesktopFolder should also give us the same pointer */
216 hr
= SHGetDesktopFolder(&psf
);
217 ok(hr
== S_OK
, "hr = %lx\n", hr
);
218 ok(psf
== static_cast<IShellFolder
*>(psf2
), "Expected %p == %p\n", static_cast<PVOID
>(psf
), static_cast<PVOID
>(psf2
));
220 TestShellFolder(psf2
);
221 TestCompareIDList(psf
);