/* * PROJECT: ReactOS api tests * LICENSE: GPLv2+ - See COPYING in the top level directory * PURPOSE: Test for ACListISF objects * PROGRAMMER: Mark Jansen */ #define _UNICODE #define UNICODE #include #include #include #include // #include // These 3 includes only exist here to make gcc happy about (unused) templates.. #include // // Yes, gcc at it again, let's validate everything found inside unused templates! ULONG DbgPrint(PCH Format,...); #include #include #include static bool g_ShowHidden; static DWORD g_WinVersion; #define WINVER_VISTA 0x0600 #define ok_hr(status, expected) ok_hex(status, expected) // We do not want our results to originate from the helper functions, so have them originate from the calls to them #define test_at_end (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_at_end_imp #define test_ExpectDrives (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_ExpectDrives_imp #define test_ExpectFolders (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_ExpectFolders_imp #define winetest_ok_hr(expression, expected) \ do { \ int _value = (expression); \ winetest_ok(_value == (expected), "Wrong value for '%s', expected: " #expected " (0x%x), got: 0x%x\n", \ #expression, (int)(expected), _value); \ } while (0) static void test_at_end_imp(CComPtr& EnumStr) { CComHeapPtr Result; ULONG Fetched = 12345; HRESULT hr = EnumStr->Next(1, &Result, &Fetched); winetest_ok(hr == S_FALSE, "Expected hr to be S_FALSE, was 0x%lx\n", hr); winetest_ok(Fetched == 0u, "Expected Fetched to be 0, was: %lu\n", Fetched); if (Fetched == 1u) winetest_ok(0, "Expected there not to be a result, got: %s\n", wine_dbgstr_w(Result)); } static bool GetDisplayname(CComPtr& spDrives, CComHeapPtr& pidl, CComHeapPtr& DisplayName) { STRRET StrRet; HRESULT hr; winetest_ok_hr(hr = spDrives->GetDisplayNameOf(pidl, SHGDN_INFOLDER | SHGDN_FORPARSING | SHGDN_FORADDRESSBAR, &StrRet), S_OK); if (!SUCCEEDED(hr)) return false; winetest_ok_hr(hr = StrRetToStrW(&StrRet, NULL, &DisplayName), S_OK); if (!SUCCEEDED(hr)) return false; return true; } enum ExpectOptions { None = 0, IgnoreRoot = 1, CheckLast = 2, IgnoreHidden = 4, IgnoreFiles = 8, }; // wtf c++ ExpectOptions operator | (const ExpectOptions& left, const ExpectOptions& right) { return static_cast(static_cast(left) | static_cast(right)); } static void test_ExpectFolders_imp(CComPtr& EnumStr, LPITEMIDLIST pidlTarget, const WCHAR* Root, ExpectOptions options) { CComPtr spDesktop; HRESULT hr = SHGetDesktopFolder(&spDesktop); CComPtr spTarget; if (pidlTarget) { winetest_ok_hr(hr = spDesktop->BindToObject(pidlTarget, NULL, IID_PPV_ARG(IShellFolder, &spTarget)), S_OK); if (!SUCCEEDED(hr)) return; } else { spTarget = spDesktop; } SHCONTF EnumFlags = SHCONTF_FOLDERS | SHCONTF_INIT_ON_FIRST_NEXT; if (g_ShowHidden && !(options & IgnoreHidden)) EnumFlags |= SHCONTF_INCLUDEHIDDEN; if (!(options & IgnoreFiles)) EnumFlags |= SHCONTF_NONFOLDERS; CComPtr spEnumIDList; winetest_ok_hr(hr = spTarget->EnumObjects(NULL, EnumFlags, &spEnumIDList), S_OK); if (!SUCCEEDED(hr)) return; WCHAR Buffer[512]; CComHeapPtr pidl; INT Count = 0; while (spEnumIDList->Next(1, &pidl, NULL) == S_OK) { CComHeapPtr DisplayName; if (!GetDisplayname(spTarget, pidl, DisplayName)) break; CComHeapPtr Result; ULONG Fetched; hr = EnumStr->Next(1, &Result, &Fetched); winetest_ok_hr(hr, S_OK); if (hr != S_OK) break; StringCchPrintfW(Buffer, _ARRAYSIZE(Buffer), L"%s%s", (options & IgnoreRoot) ? L"" : Root, (WCHAR*)DisplayName); winetest_ok(!wcscmp(Buffer, Result), "Expected %s, got %s\n", wine_dbgstr_w(Buffer), wine_dbgstr_w(Result)); pidl.Free(); Count++; } if (options & CheckLast) { test_at_end_imp(EnumStr); } } static void test_ExpectDrives_imp(CComPtr& EnumStr, CComHeapPtr& pidlTarget) { test_ExpectFolders_imp(EnumStr, pidlTarget, NULL, IgnoreRoot | CheckLast); } static void test_ACListISF_NONE() { CComPtr EnumStr; HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr)); ok_hr(hr, S_OK); if (!SUCCEEDED(hr)) return; CComPtr ACList; ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK); if (!SUCCEEDED(hr)) return; ok_hr(hr = ACList->SetOptions(ACLO_NONE), S_OK); test_at_end(EnumStr); WCHAR Buffer[MAX_PATH]; GetSystemWindowsDirectoryW(Buffer, _ARRAYSIZE(Buffer)); Buffer[3] = '\0'; CComHeapPtr pidlDiskRoot; ok_hr(hr = SHParseDisplayName(Buffer, NULL, &pidlDiskRoot, NULL, NULL), S_OK); if (!SUCCEEDED(hr)) return; ok_hr(hr = ACList->Expand(Buffer), S_OK); test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, CheckLast | IgnoreHidden); ok_hr(hr = EnumStr->Reset(), S_OK); ok_hr(hr = ACList->Expand(Buffer), S_OK); ok_hr(hr = ACList->SetOptions(ACLO_NONE), S_OK); test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, CheckLast); } static void test_ACListISF_CURRENTDIR() { CComPtr EnumStr; HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr)); ok_hr(hr, S_OK); if (!SUCCEEDED(hr)) return; CComPtr ACList; ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK); if (!SUCCEEDED(hr)) return; CComPtr CurrentWorkingDir; ok_hr(hr = EnumStr->QueryInterface(IID_ICurrentWorkingDirectory, (void**)&CurrentWorkingDir), S_OK); if (!SUCCEEDED(hr)) return; ok_hr(hr = ACList->SetOptions(ACLO_CURRENTDIR), S_OK); test_at_end(EnumStr); WCHAR Buffer[MAX_PATH] = { 1, 1, 1, 1, 1, 0 }, Buffer2[MAX_PATH]; if (g_WinVersion < WINVER_VISTA) ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), E_NOTIMPL); else ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), E_UNEXPECTED); ok(!wcscmp(L"\x1\x1\x1\x1\x1", Buffer), "Expected %s, got %s\n", wine_dbgstr_w(L"\x1\x1\x1\x1\x1"), wine_dbgstr_w(Buffer)); GetSystemWindowsDirectoryW(Buffer2, _ARRAYSIZE(Buffer2)); // Windows 2k3 does not parse it without the trailing '\\' Buffer2[3] = '\0'; CComHeapPtr pidlDiskRoot; ok_hr(hr = SHParseDisplayName(Buffer2, NULL, &pidlDiskRoot, NULL, NULL), S_OK); if (!SUCCEEDED(hr)) return; ok_hr(hr = CurrentWorkingDir->SetDirectory(Buffer2), S_OK); test_at_end(EnumStr); Buffer[0] = '\0'; if (g_WinVersion < WINVER_VISTA) { ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), E_NOTIMPL); } else { ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), S_OK); ok(!wcscmp(Buffer2, Buffer), "Expected %s, got %s\n", wine_dbgstr_w(Buffer2), wine_dbgstr_w(Buffer)); } Buffer2[2] = '\0'; ok_hr(hr = CurrentWorkingDir->SetDirectory(Buffer2), S_OK); test_at_end(EnumStr); Buffer[0] = '\0'; Buffer2[2] = '\\'; if (g_WinVersion < WINVER_VISTA) { ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), E_NOTIMPL); } else { ok_hr(hr = CurrentWorkingDir->GetDirectory(Buffer, _ARRAYSIZE(Buffer)), S_OK); ok(!wcscmp(Buffer2, Buffer), "Expected %s, got %s\n", wine_dbgstr_w(Buffer2), wine_dbgstr_w(Buffer)); } ok_hr(hr = ACList->Expand(Buffer2), S_OK); // The first set of results are absolute paths, without hidden files?! test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer2, IgnoreHidden); test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer2, IgnoreHidden | IgnoreRoot | CheckLast); } static void test_ACListISF_MYCOMPUTER() { CComPtr ACList; HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IACList2, &ACList)); ok_hr(hr, S_OK); if (!SUCCEEDED(hr)) return; // Check the default DWORD CurrentOption = 0xdeadbeef; ok_hr(ACList->GetOptions(&CurrentOption), S_OK); ok(CurrentOption == (ACLO_CURRENTDIR|ACLO_MYCOMPUTER), "Expected the default to be %x, was %lx\n", (ACLO_CURRENTDIR|ACLO_MYCOMPUTER), CurrentOption); CComPtr EnumStr; ok_hr(hr = ACList->QueryInterface(IID_IEnumString, (void**)&EnumStr), S_OK); if (!SUCCEEDED(hr)) return; CComPtr PersistFolder; ok_hr(hr = EnumStr->QueryInterface(IID_IPersistFolder, (void**)&PersistFolder), S_OK); if (!SUCCEEDED(hr)) return; CComHeapPtr pidlMyComputer; ok_hr(hr = SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidlMyComputer), S_OK); if (!SUCCEEDED(hr)) return; hr = EnumStr->Reset(); if (g_WinVersion < WINVER_VISTA) ok_hr(hr, S_FALSE); else ok_hr(hr, S_OK); test_ExpectDrives(EnumStr, pidlMyComputer); ok_hr(hr = ACList->SetOptions(ACLO_MYCOMPUTER), S_OK); ok_hr(EnumStr->Reset(), S_OK); test_ExpectDrives(EnumStr, pidlMyComputer); WCHAR Buffer[MAX_PATH]; GetSystemWindowsDirectoryW(Buffer, _ARRAYSIZE(Buffer)); // Windows 2k3 does not parse it without the trailing '\\' Buffer[3] = '\0'; CComHeapPtr pidlDiskRoot; ok_hr(hr = SHParseDisplayName(Buffer, NULL, &pidlDiskRoot, NULL, NULL), S_OK); if (!SUCCEEDED(hr)) return; Buffer[2] = '\0'; ok_hr(hr = ACList->Expand(Buffer), S_OK); test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, None); test_ExpectDrives(EnumStr, pidlMyComputer); ok_hr(hr = ACList->Expand(Buffer), S_OK); ok_hr(EnumStr->Reset(), S_OK); // Pre vista does not remove the expanded data from the enumeration, it changes it to relative paths??? if (g_WinVersion < WINVER_VISTA) test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, IgnoreRoot); test_ExpectDrives(EnumStr, pidlMyComputer); ok_hr(EnumStr->Reset(), S_OK); ok_hr(hr = ACList->Expand(Buffer), S_OK); test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, None); test_ExpectDrives(EnumStr, pidlMyComputer); } static void test_ACListISF_DESKTOP() { CComPtr EnumStr; HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr)); ok_hr(hr, S_OK); if (!SUCCEEDED(hr)) return; CComPtr ACList; ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK); if (!SUCCEEDED(hr)) return; ok_hr(hr = ACList->SetOptions(ACLO_DESKTOP), S_OK); test_ExpectFolders(EnumStr, NULL, NULL, IgnoreRoot | CheckLast | IgnoreHidden); } static void test_ACListISF_FAVORITES() { CComPtr EnumStr; HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr)); ok_hr(hr, S_OK); if (!SUCCEEDED(hr)) return; CComPtr ACList; ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK); if (!SUCCEEDED(hr)) return; CComHeapPtr pidlFavorites; ok_hr(hr = SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidlFavorites), S_OK); if (!SUCCEEDED(hr)) return; ok_hr(hr = ACList->SetOptions(ACLO_FAVORITES), S_OK); test_ExpectFolders(EnumStr, pidlFavorites, NULL, IgnoreRoot | CheckLast | IgnoreHidden); } static void test_ACListISF_FILESYSONLY() { CComPtr EnumStr; HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr)); ok_hr(hr, S_OK); if (!SUCCEEDED(hr)) return; CComPtr ACList; ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK); if (!SUCCEEDED(hr)) return; WCHAR Buffer[MAX_PATH]; GetSystemWindowsDirectoryW(Buffer, _ARRAYSIZE(Buffer)); // Windows 2k3 does not parse it without the trailing '\\' Buffer[3] = '\0'; CComHeapPtr pidlDiskRoot; ok_hr(hr = SHParseDisplayName(Buffer, NULL, &pidlDiskRoot, NULL, NULL), S_OK); if (!SUCCEEDED(hr)) return; ok_hr(hr = ACList->SetOptions(ACLO_FILESYSONLY), S_OK); test_at_end(EnumStr); ok_hr(hr = ACList->Expand(Buffer), S_OK); test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, CheckLast | IgnoreHidden); } static void test_ACListISF_FILESYSDIRS() { CComPtr EnumStr; HRESULT hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_ALL, IID_PPV_ARG(IEnumString, &EnumStr)); ok_hr(hr, S_OK); if (!SUCCEEDED(hr)) return; CComPtr ACList; ok_hr(hr = EnumStr->QueryInterface(IID_IACList2, (void**)&ACList), S_OK); if (!SUCCEEDED(hr)) return; WCHAR Buffer[MAX_PATH]; GetSystemWindowsDirectoryW(Buffer, _ARRAYSIZE(Buffer)); // Windows 2k3 does not parse it without the trailing '\\' Buffer[3] = '\0'; CComHeapPtr pidlDiskRoot; ok_hr(hr = SHParseDisplayName(Buffer, NULL, &pidlDiskRoot, NULL, NULL), S_OK); if (!SUCCEEDED(hr)) return; ok_hr(hr = ACList->SetOptions(ACLO_FILESYSDIRS), S_OK); test_at_end(EnumStr); ok_hr(hr = ACList->Expand(Buffer), S_OK); test_ExpectFolders(EnumStr, pidlDiskRoot, Buffer, CheckLast | IgnoreFiles | IgnoreHidden); } static void GetEnvStatus() { RTL_OSVERSIONINFOEXW rtlinfo = {0}; void (__stdcall* pRtlGetVersion)(RTL_OSVERSIONINFOEXW*); pRtlGetVersion = (void (__stdcall*)(RTL_OSVERSIONINFOEXW*))GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion"); rtlinfo.dwOSVersionInfoSize = sizeof(rtlinfo); pRtlGetVersion(&rtlinfo); g_WinVersion = (rtlinfo.dwMajorVersion << 8) | rtlinfo.dwMinorVersion; SHELLFLAGSTATE sfs = {0}; SHGetSettings(&sfs, SSF_SHOWALLOBJECTS); g_ShowHidden = !!sfs.fShowAllObjects; trace("Show hidden folders: %s\n", g_ShowHidden ? "yes" : "no"); } struct CCoInit { CCoInit() { hres = CoInitialize(NULL); } ~CCoInit() { if (SUCCEEDED(hres)) { CoUninitialize(); } } HRESULT hres; }; START_TEST(ACListISF) { GetEnvStatus(); CCoInit init; ok_hr(init.hres, S_OK); if (!SUCCEEDED(init.hres)) return; test_ACListISF_NONE(); test_ACListISF_CURRENTDIR(); test_ACListISF_MYCOMPUTER(); test_ACListISF_DESKTOP(); test_ACListISF_FAVORITES(); test_ACListISF_FILESYSONLY(); test_ACListISF_FILESYSDIRS(); }