Author: tfaber Date: Mon Mar 28 15:35:21 2016 New Revision: 71064
URL: http://svn.reactos.org/svn/reactos?rev=71064&view=rev Log: [SHELL32_APITEST] - Add tests for IShellFolder::CompareIDs. Patch by Mark Jansen, with additional test cases by Sylvain Deverre. CORE-10747
Added: trunk/rostests/apitests/shell32/shelltest.cpp (with props) Modified: trunk/rostests/apitests/shell32/CMakeLists.txt trunk/rostests/apitests/shell32/CShellDesktop.cpp trunk/rostests/apitests/shell32/shelltest.h
Modified: trunk/rostests/apitests/shell32/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/shell32/CMakeList... ============================================================================== --- trunk/rostests/apitests/shell32/CMakeLists.txt [iso-8859-1] (original) +++ trunk/rostests/apitests/shell32/CMakeLists.txt [iso-8859-1] Mon Mar 28 15:35:21 2016 @@ -7,8 +7,9 @@ CMyComputer.cpp CShellDesktop.cpp menu.cpp + shelltest.cpp testlist.c) -target_link_libraries(shell32_apitest wine uuid) +target_link_libraries(shell32_apitest wine uuid ${PSEH_LIB}) set_module_type(shell32_apitest win32cui) -add_importlibs(shell32_apitest user32 gdi32 shell32 ole32 oleaut32 shlwapi msvcrt kernel32) +add_importlibs(shell32_apitest user32 gdi32 shell32 ole32 oleaut32 shlwapi msvcrt kernel32 ntdll) add_cd_file(TARGET shell32_apitest DESTINATION reactos/bin FOR all)
Modified: trunk/rostests/apitests/shell32/CShellDesktop.cpp URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/shell32/CShellDes... ============================================================================== --- trunk/rostests/apitests/shell32/CShellDesktop.cpp [iso-8859-1] (original) +++ trunk/rostests/apitests/shell32/CShellDesktop.cpp [iso-8859-1] Mon Mar 28 15:35:21 2016 @@ -3,16 +3,151 @@ * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory * PURPOSE: Test for CShellDesktop * PROGRAMMER: Thomas Faber thomas.faber@reactos.org + * Mark Jansen */
#include "shelltest.h" #include <atlbase.h> #include <atlcom.h> #include <strsafe.h> +#include <ndk/rtlfuncs.h>
#define NDEBUG #include <debug.h> #include <shellutils.h> + + +// 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<ITEMIDLIST> 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<ITEMIDLIST> 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<ITEMIDLIST> 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<IPersistFolder2> persist; + hr = psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &persist)); + ok(hr == S_OK, "hr = %lx\n", hr); + if (hr == S_OK) + { + CComHeapPtr<ITEMIDLIST> 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<ITEMIDLIST> 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<ITEMIDLIST> 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<IShellFolder> psf2; + hr = psf->BindToObject(programs, NULL, IID_IShellFolder, reinterpret_cast<void**>(&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 @@ -83,4 +218,5 @@ ok(psf == static_cast<IShellFolder *>(psf2), "Expected %p == %p\n", static_cast<PVOID>(psf), static_cast<PVOID>(psf2));
TestShellFolder(psf2); -} + TestCompareIDList(psf); +}
Added: trunk/rostests/apitests/shell32/shelltest.cpp URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/shell32/shelltest... ============================================================================== --- trunk/rostests/apitests/shell32/shelltest.cpp (added) +++ trunk/rostests/apitests/shell32/shelltest.cpp [iso-8859-1] Mon Mar 28 15:35:21 2016 @@ -0,0 +1,98 @@ +#include "shelltest.h" +#include <atlbase.h> +#include <atlcom.h> + + +// + Adapted from https://blogs.msdn.microsoft.com/oldnewthing/20130503-00/?p=4463/ +// In short: We want to create an IDLIST from an item that does not exist, +// so we have to provide WIN32_FIND_DATAW in a bind context. +// If we don't, the FS will be queried, and we do not get a valid IDLIST for a non-existing path. + +CComModule gModule; + +class CFileSysBindData : + public CComCoClass<CFileSysBindData>, + public CComObjectRootEx<CComMultiThreadModelNoCS>, + public IFileSystemBindData +{ +public: + virtual HRESULT STDMETHODCALLTYPE SetFindData(const WIN32_FIND_DATAW *pfd) + { + m_Data = *pfd; + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE GetFindData(WIN32_FIND_DATAW *pfd) + { + *pfd = m_Data; + return S_OK; + } + + DECLARE_NOT_AGGREGATABLE(CFileSysBindData) + DECLARE_PROTECT_FINAL_CONSTRUCT() + BEGIN_COM_MAP(CFileSysBindData) + COM_INTERFACE_ENTRY_IID(IID_IFileSystemBindData, IFileSystemBindData) + END_COM_MAP() +private: + WIN32_FIND_DATAW m_Data; +}; + +static +HRESULT +AddFileSysBindCtx(_In_ IBindCtx *pbc) +{ + CComPtr<IFileSystemBindData> spfsbc(new CComObject<CFileSysBindData>()); + WIN32_FIND_DATAW wfd = { 0 }; + wfd.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + spfsbc->SetFindData(&wfd); + HRESULT hr = pbc->RegisterObjectParam((LPOLESTR)STR_FILE_SYS_BIND_DATA, spfsbc); + ok(hr == S_OK, "hr = %lx\n", hr); + return hr; +} + +static +HRESULT +CreateBindCtxWithOpts(_In_ BIND_OPTS *pbo, _Outptr_ IBindCtx **ppbc) +{ + CComPtr<IBindCtx> spbc; + HRESULT hr = CreateBindCtx(0, &spbc); + ok(hr == S_OK, "hr = %lx\n", hr); + if (SUCCEEDED(hr)) + { + hr = spbc->SetBindOptions(pbo); + ok(hr == S_OK, "hr = %lx\n", hr); + } + *ppbc = SUCCEEDED(hr) ? spbc.Detach() : NULL; + return hr; +} + +static HRESULT +CreateFileSysBindCtx(_Outptr_ IBindCtx **ppbc) +{ + CComPtr<IBindCtx> spbc; + BIND_OPTS bo = { sizeof(bo), 0, STGM_CREATE, 0 }; + HRESULT hr = CreateBindCtxWithOpts(&bo, &spbc); + ok(hr == S_OK, "hr = %lx\n", hr); + if (SUCCEEDED(hr)) + { + hr = AddFileSysBindCtx(spbc); + ok(hr == S_OK, "hr = %lx\n", hr); + } + *ppbc = SUCCEEDED(hr) ? spbc.Detach() : NULL; + return hr; +} + +VOID +PathToIDList(LPCWSTR pszPath, ITEMIDLIST** ppidl) +{ + CComPtr<IBindCtx> spbc; + HRESULT hr = CreateFileSysBindCtx(&spbc); + ok(hr == S_OK, "hr = %lx\n", hr); + if (SUCCEEDED(hr)) + { + hr = SHParseDisplayName(pszPath, spbc, ppidl, 0, NULL); + ok(hr == S_OK, "hr = %lx\n", hr); + } +} + +// - Adapted from https://blogs.msdn.microsoft.com/oldnewthing/20130503-00/?p=4463/
Propchange: trunk/rostests/apitests/shell32/shelltest.cpp ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/rostests/apitests/shell32/shelltest.h URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/shell32/shelltest... ============================================================================== --- trunk/rostests/apitests/shell32/shelltest.h [iso-8859-1] (original) +++ trunk/rostests/apitests/shell32/shelltest.h [iso-8859-1] Mon Mar 28 15:35:21 2016 @@ -28,3 +28,5 @@ DEFINE_GUID(CLSID_MenuBandSite, 0xE13EF4E4, 0xD2F2, 0x11D0, 0x98, 0x16, 0x00, 0xC0, 0x4F, 0xD9, 0x19, 0x72);
#include "unknownbase.h" + +VOID PathToIDList(LPCWSTR pszPath, ITEMIDLIST** ppidl);