/* * PROJECT: ReactOS api tests * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory * PURPOSE: Test for CShellDesktop * PROGRAMMER: Thomas Faber * Mark Jansen */ #include "shelltest.h" #include #include #include // We would normally use S_LESSTHAN and S_GREATERTHAN, but w2k3 returns numbers like 3 and -3... // So instead we check on the sign bit (compare result is the low word of the hresult). #define SHORT_SIGN_BIT 0x8000 static VOID compare_imp(IShellFolder* psf, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2, HRESULT expected) { HRESULT hr; _SEH2_TRY { hr = psf->CompareIDs(0, pidl1, pidl2); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { winetest_ok(0, "Exception %lx!\n", _SEH2_GetExceptionCode()); hr = HRESULT_FROM_WIN32(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); } _SEH2_END; if (expected == S_LESSTHAN) winetest_ok(SUCCEEDED(hr) && (hr & SHORT_SIGN_BIT), "hr = %lx\n", hr); else if (expected == S_EQUAL) winetest_ok(hr == S_EQUAL, "hr = %lx\n", hr); else if (expected == S_GREATERTHAN) winetest_ok(SUCCEEDED(hr) && !(hr & SHORT_SIGN_BIT), "hr = %lx\n", hr); else winetest_ok(hr == expected, "hr = %lx\n", hr); } // 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 :) #define compare (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : compare_imp static VOID TestCompareIDList(IShellFolder* psf) { compare(psf, NULL, NULL, E_INVALIDARG); CComHeapPtr desktop; HRESULT hr = SHGetFolderLocation(NULL, CSIDL_DESKTOP, NULL, NULL, &desktop); ok(hr == S_OK, "hr = %lx\n", hr); compare(psf, desktop, NULL, E_INVALIDARG); compare(psf, NULL, desktop, E_INVALIDARG); compare(psf, desktop, desktop, S_EQUAL); // First check the ordering of some special folders against eachother CComHeapPtr internet; hr = SHGetFolderLocation(NULL, CSIDL_INTERNET, NULL, NULL, &internet); ok(hr == S_OK, "hr = %lx\n", hr); compare(psf, internet, desktop, S_LESSTHAN); compare(psf, desktop, internet, S_GREATERTHAN); CComHeapPtr programs; hr = SHGetFolderLocation(NULL, CSIDL_PROGRAMS, NULL, NULL, &programs); ok(hr == S_OK, "hr = %lx\n", hr); compare(psf, programs, desktop, S_LESSTHAN); compare(psf, desktop, programs, S_GREATERTHAN); compare(psf, internet, programs, S_GREATERTHAN); compare(psf, programs, internet, S_LESSTHAN); // Verify that an idlist retrieved from GetCurFolder is equal to the original one. CComPtr persist; hr = psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &persist)); ok(hr == S_OK, "hr = %lx\n", hr); if (hr == S_OK) { CComHeapPtr cur; hr = persist->GetCurFolder(&cur); ok(hr == S_OK, "hr = %lx\n", hr); compare(psf, cur, desktop, S_EQUAL); compare(psf, desktop, cur, S_EQUAL); } // Compare special folders against full paths CComHeapPtr dir1, dir2; PathToIDList(L"A:\\AAA.AAA", &dir1); PathToIDList(L"A:\\ZZZ.ZZZ", &dir2); compare(psf, dir1, desktop, S_LESSTHAN); compare(psf, desktop, dir1, S_GREATERTHAN); compare(psf, dir1, programs, S_LESSTHAN); compare(psf, programs, dir1, S_GREATERTHAN); compare(psf, dir1, dir1, S_EQUAL); compare(psf, dir2, desktop, S_LESSTHAN); compare(psf, desktop, dir2, S_GREATERTHAN); compare(psf, dir2, programs, S_LESSTHAN); compare(psf, programs, dir2, S_GREATERTHAN); compare(psf, dir2, dir2, S_EQUAL); CComHeapPtr dir3, dir4; PathToIDList(L"Z:\\AAA.AAA", &dir3); PathToIDList(L"Z:\\ZZZ.ZZZ", &dir4); compare(psf, dir3, desktop, S_LESSTHAN); compare(psf, desktop, dir3, S_GREATERTHAN); compare(psf, dir3, programs, S_GREATERTHAN); compare(psf, programs, dir3, S_LESSTHAN); compare(psf, dir3, dir3, S_EQUAL); compare(psf, dir4, desktop, S_LESSTHAN); compare(psf, desktop, dir4, S_GREATERTHAN); compare(psf, dir4, programs, S_GREATERTHAN); compare(psf, programs, dir4, S_LESSTHAN); compare(psf, dir4, dir4, S_EQUAL); // Now compare the paths against eachother. compare(psf, dir1, dir2, S_LESSTHAN); compare(psf, dir2, dir1, S_GREATERTHAN); compare(psf, dir2, dir3, S_LESSTHAN); compare(psf, dir3, dir2, S_GREATERTHAN); compare(psf, dir3, dir4, S_LESSTHAN); compare(psf, dir4, dir3, S_GREATERTHAN); // Check that comparing desktop pidl with another one with another IShellFolder fails CComPtr psf2; hr = psf->BindToObject(programs, NULL, IID_IShellFolder, reinterpret_cast(&psf2)); ok(hr == S_OK, "Impossible to bind to Programs pidl"); if (hr == S_OK) { // Compare desktop pidl in programs scope should fail since it's relative pidl compare(psf2, desktop, programs, E_INVALIDARG); compare(psf2, programs, desktop, E_INVALIDARG); // For the same reasons, filesystem paths can't be compared with special shell // folders that don't have CFSFolder in children compare(psf2, dir1, dir2, E_INVALIDARG); compare(psf2, dir2, dir1, E_INVALIDARG); } } static VOID TestDesktopFolder( _In_ IShellFolder2 *psf2) { HRESULT hr; CComPtr pdt; CComPtr pdt_2; CComPtr pcm; CComPtr pcm_2; CComPtr psv; CComPtr psv_2; hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget, &pdt)); ok(hr == S_OK, "hr = %lx\n", hr); hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget, &pdt_2)); ok(hr == S_OK, "hr = %lx\n", hr); ok(pdt != pdt_2, "Expected %p != %p\n", static_cast(pdt), static_cast(pdt_2)); hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IContextMenu, &pcm)); ok(hr == S_OK, "hr = %lx\n", hr); hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IContextMenu, &pcm_2)); ok(hr == S_OK, "hr = %lx\n", hr); ok(pcm != pcm_2, "Expected %p != %p\n", static_cast(pcm), static_cast(pcm_2)); hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IShellView, &psv)); ok(hr == S_OK, "hr = %lx\n", hr); hr = psf2->CreateViewObject(NULL, IID_PPV_ARG(IShellView, &psv_2)); ok(hr == S_OK, "hr = %lx\n", hr); ok(psv != psv_2, "Expected %p != %p\n", static_cast(psv), static_cast(psv_2)); STRRET strret; hr = psf2->GetDisplayNameOf(NULL, 0, &strret); ok(hr == S_OK, "hr = %lx\n", hr); } VOID TestInitialize(_In_ IShellFolder *psf) { CComPtr ppf2; HRESULT hr = psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2)); ok(hr == S_OK, "hr = %lx\n", hr); /* Create a tiny pidl with no contents */ LPITEMIDLIST testpidl = (LPITEMIDLIST)SHAlloc(3 * sizeof(WORD)); testpidl->mkid.cb = 2 * sizeof(WORD); *(WORD*)((char*)testpidl + (int)(2 * sizeof(WORD))) = 0; hr = ppf2->Initialize(testpidl); ok(hr == E_INVALIDARG, "hr = %lx\n", hr); //crashes in xp, works on win10 //hr = ppf2->Initialize(NULL); //ok(hr == S_OK, "hr = %lx\n", hr); //hr = ppf2->Initialize((LPCITEMIDLIST)0xdeaddead); //ok(hr == S_OK, "hr = %lx\n", hr); //hr = ppf2->GetCurFolder(NULL); //ok(hr == E_INVALIDARG, "hr = %lx\n", hr); CComHeapPtr pidl; hr = ppf2->GetCurFolder(&pidl); ok(hr == S_OK, "hr = %lx\n", hr); ok(pidl->mkid.cb == 0, "expected empty pidl got cb = %x\n", pidl->mkid.cb); } START_TEST(CShellDesktop) { HRESULT hr; CComPtr psf2; CComPtr psf2_2; CComPtr psf; CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); hr = CoCreateInstance(CLSID_ShellDesktop, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellFolder2, &psf2)); ok(hr == S_OK, "hr = %lx\n", hr); if (FAILED(hr)) { skip("Could not instantiate CShellDesktop\n"); return; } /* second create should give us a pointer to the same object */ hr = CoCreateInstance(CLSID_ShellDesktop, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellFolder2, &psf2_2)); ok(hr == S_OK, "hr = %lx\n", hr); ok(psf2 == psf2_2, "Expected %p == %p\n", static_cast(psf2), static_cast(psf2_2)); /* SHGetDesktopFolder should also give us the same pointer */ hr = SHGetDesktopFolder(&psf); ok(hr == S_OK, "hr = %lx\n", hr); ok(psf == static_cast(psf2), "Expected %p == %p\n", static_cast(psf), static_cast(psf2)); TestDesktopFolder(psf2); TestCompareIDList(psf); TestInitialize(psf); }