Reactos
at master 257 lines 9.3 kB view raw
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 11#include <ndk/rtlfuncs.h> 12#include <stdio.h> 13#include <shellutils.h> 14 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 18 19static 20VOID 21compare_imp(IShellFolder* psf, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2, HRESULT expected) 22{ 23 HRESULT hr; 24 _SEH2_TRY 25 { 26 hr = psf->CompareIDs(0, pidl1, pidl2); 27 } 28 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 29 { 30 winetest_ok(0, "Exception %lx!\n", _SEH2_GetExceptionCode()); 31 hr = HRESULT_FROM_WIN32(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); 32 } 33 _SEH2_END; 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); 40 else 41 winetest_ok(hr == expected, "hr = %lx\n", hr); 42} 43 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 46 47static 48VOID 49TestCompareIDList(IShellFolder* psf) 50{ 51 compare(psf, NULL, NULL, E_INVALIDARG); 52 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); 59 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); 66 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); 74 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); 79 if (hr == S_OK) 80 { 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); 86 } 87 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); 92 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); 98 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); 104 105 CComHeapPtr<ITEMIDLIST> dir3, dir4; 106 PathToIDList(L"Z:\\AAA.AAA", &dir3); 107 PathToIDList(L"Z:\\ZZZ.ZZZ", &dir4); 108 109 compare(psf, dir3, desktop, S_LESSTHAN); 110 compare(psf, desktop, dir3, S_GREATERTHAN); 111 if (!g_bVista) // Only Vista fails on a default install 112 { 113 compare(psf, dir3, programs, S_GREATERTHAN); 114 compare(psf, programs, dir3, S_LESSTHAN); 115 } 116 compare(psf, dir3, dir3, S_EQUAL); 117 118 compare(psf, dir4, desktop, S_LESSTHAN); 119 compare(psf, desktop, dir4, S_GREATERTHAN); 120 if (!g_bVista) // Only Vista fails on a default install 121 { 122 compare(psf, dir4, programs, S_GREATERTHAN); 123 compare(psf, programs, dir4, S_LESSTHAN); 124 } 125 compare(psf, dir4, dir4, S_EQUAL); 126 127 // Now compare the paths against eachother. 128 compare(psf, dir1, dir2, S_LESSTHAN); 129 compare(psf, dir2, dir1, S_GREATERTHAN); 130 if (!g_bVista) // Only Vista fails on a default install 131 { 132 compare(psf, dir2, dir3, S_LESSTHAN); 133 compare(psf, dir3, dir2, S_GREATERTHAN); 134 } 135 compare(psf, dir3, dir4, S_LESSTHAN); 136 compare(psf, dir4, dir3, S_GREATERTHAN); 137 138 // Check that comparing desktop pidl with another one with another IShellFolder fails 139 CComPtr<IShellFolder> psf2; 140 hr = psf->BindToObject(programs, NULL, IID_IShellFolder, reinterpret_cast<void**>(&psf2)); 141 ok(hr == S_OK, "Impossible to bind to Programs pidl"); 142 if (hr == S_OK) 143 { 144 // Compare desktop pidl in programs scope should fail since it's relative pidl 145 compare(psf2, desktop, programs, E_INVALIDARG); 146 compare(psf2, programs, desktop, E_INVALIDARG); 147 // For the same reasons, filesystem paths can't be compared with special shell 148 // folders that don't have CFSFolder in children 149 compare(psf2, dir1, dir2, E_INVALIDARG); 150 compare(psf2, dir2, dir1, E_INVALIDARG); 151 } 152} 153 154static 155VOID 156TestDesktopFolder( 157 _In_ IShellFolder2 *psf2) 158{ 159 HRESULT hr; 160 CComPtr<IDropTarget> pdt; 161 CComPtr<IDropTarget> pdt_2; 162 CComPtr<IContextMenu> pcm; 163 CComPtr<IContextMenu> pcm_2; 164 CComPtr<IShellView> psv; 165 CComPtr<IShellView> psv_2; 166 167 hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget, &pdt)); 168 ok(hr == S_OK, "hr = %lx\n", hr); 169 170 hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget, &pdt_2)); 171 ok(hr == S_OK, "hr = %lx\n", hr); 172 ok(pdt != pdt_2, "Expected %p != %p\n", static_cast<PVOID>(pdt), static_cast<PVOID>(pdt_2)); 173 174 hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IContextMenu, &pcm)); 175 ok(hr == S_OK, "hr = %lx\n", hr); 176 177 hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IContextMenu, &pcm_2)); 178 ok(hr == S_OK, "hr = %lx\n", hr); 179 ok(pcm != pcm_2, "Expected %p != %p\n", static_cast<PVOID>(pcm), static_cast<PVOID>(pcm_2)); 180 181 hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IShellView, &psv)); 182 ok(hr == S_OK, "hr = %lx\n", hr); 183 184 hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IShellView, &psv_2)); 185 ok(hr == S_OK, "hr = %lx\n", hr); 186 ok(psv != psv_2, "Expected %p != %p\n", static_cast<PVOID>(psv), static_cast<PVOID>(psv_2)); 187 188 STRRET strret; 189 hr = psf2->GetDisplayNameOf(NULL, 0, &strret); 190 ok(hr == S_OK, "hr = %lx\n", hr); 191} 192 193VOID TestInitialize(_In_ IShellFolder *psf) 194{ 195 CComPtr<IPersistFolder2> ppf2; 196 HRESULT hr = psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2)); 197 ok(hr == S_OK, "hr = %lx\n", hr); 198 199 /* Create a tiny pidl with no contents */ 200 LPITEMIDLIST testpidl = (LPITEMIDLIST)SHAlloc(3 * sizeof(WORD)); 201 testpidl->mkid.cb = 2 * sizeof(WORD); 202 *(WORD*)((char*)testpidl + (int)(2 * sizeof(WORD))) = 0; 203 204 hr = ppf2->Initialize(testpidl); 205 ok(hr == E_INVALIDARG, "hr = %lx\n", hr); 206 207 //crashes in xp, works on win10 208 //hr = ppf2->Initialize(NULL); 209 //ok(hr == S_OK, "hr = %lx\n", hr); 210 //hr = ppf2->Initialize((LPCITEMIDLIST)0xdeaddead); 211 //ok(hr == S_OK, "hr = %lx\n", hr); 212 //hr = ppf2->GetCurFolder(NULL); 213 //ok(hr == E_INVALIDARG, "hr = %lx\n", hr); 214 215 CComHeapPtr<ITEMIDLIST> pidl; 216 hr = ppf2->GetCurFolder(&pidl); 217 ok(hr == S_OK, "hr = %lx\n", hr); 218 ok(pidl->mkid.cb == 0, "expected empty pidl got cb = %x\n", pidl->mkid.cb); 219} 220 221START_TEST(CShellDesktop) 222{ 223 HRESULT hr; 224 CComPtr<IShellFolder2> psf2; 225 CComPtr<IShellFolder2> psf2_2; 226 CComPtr<IShellFolder> psf; 227 228 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 229 230 hr = CoCreateInstance(CLSID_ShellDesktop, 231 NULL, 232 CLSCTX_INPROC_SERVER, 233 IID_PPV_ARG(IShellFolder2, &psf2)); 234 ok(hr == S_OK, "hr = %lx\n", hr); 235 if (FAILED(hr)) 236 { 237 skip("Could not instantiate CShellDesktop\n"); 238 return; 239 } 240 241 /* second create should give us a pointer to the same object */ 242 hr = CoCreateInstance(CLSID_ShellDesktop, 243 NULL, 244 CLSCTX_INPROC_SERVER, 245 IID_PPV_ARG(IShellFolder2, &psf2_2)); 246 ok(hr == S_OK, "hr = %lx\n", hr); 247 ok(psf2 == psf2_2, "Expected %p == %p\n", static_cast<PVOID>(psf2), static_cast<PVOID>(psf2_2)); 248 249 /* SHGetDesktopFolder should also give us the same pointer */ 250 hr = SHGetDesktopFolder(&psf); 251 ok(hr == S_OK, "hr = %lx\n", hr); 252 ok(psf == static_cast<IShellFolder *>(psf2), "Expected %p == %p\n", static_cast<PVOID>(psf), static_cast<PVOID>(psf2)); 253 254 TestDesktopFolder(psf2); 255 TestCompareIDList(psf); 256 TestInitialize(psf); 257}