Author: gadamopoulos Date: Thu Oct 10 09:36:13 2013 New Revision: 60596
URL: http://svn.reactos.org/svn/reactos?rev=60596&view=rev Log: [shell32_apitest] - Add tests for shell menu classes ( so far only CShellMenu is tested)
Added: trunk/rostests/apitests/shell32/ trunk/rostests/apitests/shell32/CMakeLists.txt (with props) trunk/rostests/apitests/shell32/menu.cpp (with props) trunk/rostests/apitests/shell32/shelltest.h (with props) trunk/rostests/apitests/shell32/testlist.c (with props) Modified: trunk/rostests/apitests/CMakeLists.txt
Modified: trunk/rostests/apitests/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/CMakeLists.txt?re... ============================================================================== --- trunk/rostests/apitests/CMakeLists.txt [iso-8859-1] (original) +++ trunk/rostests/apitests/CMakeLists.txt [iso-8859-1] Thu Oct 10 09:36:13 2013 @@ -13,7 +13,7 @@ add_subdirectory(msvcrt) add_subdirectory(ntdll) add_subdirectory(powrprof) -add_subdirectory(psapi) +add_subdirectory(shell32)add_subdirectory(psapi) add_subdirectory(user32) if((NOT MSVC) AND (ARCH STREQUAL "i386")) add_subdirectory(w32kdll)
Added: trunk/rostests/apitests/shell32/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/shell32/CMakeList... ============================================================================== --- trunk/rostests/apitests/shell32/CMakeLists.txt (added) +++ trunk/rostests/apitests/shell32/CMakeLists.txt [iso-8859-1] Thu Oct 10 09:36:13 2013 @@ -0,0 +1,12 @@ + +set_cpp(WITH_RUNTIME) + +list(APPEND SOURCE + menu.cpp + testlist.c) + +add_executable(shell32_apitest ${SOURCE}) +target_link_libraries(shell32_apitest wine uuid) +set_module_type(shell32_apitest win32cui) +add_importlibs(shell32_apitest msvcrt kernel32 user32 gdi32 shell32 ole32 shlwapi) +add_cd_file(TARGET shell32_apitest DESTINATION reactos/bin FOR all)
Propchange: trunk/rostests/apitests/shell32/CMakeLists.txt ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/rostests/apitests/shell32/menu.cpp URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/shell32/menu.cpp?... ============================================================================== --- trunk/rostests/apitests/shell32/menu.cpp (added) +++ trunk/rostests/apitests/shell32/menu.cpp [iso-8859-1] Thu Oct 10 09:36:13 2013 @@ -0,0 +1,418 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPL - See COPYING in the top level directory + * PURPOSE: Test for shell menu objects + * PROGRAMMERS: Giannis Adamopoulos + */ + +#include "shelltest.h" + +BOOL CheckWindowClass(HWND hwnd, PCWSTR className) +{ + ULONG size = (wcslen(className) + 1)* sizeof(WCHAR); + PWCHAR buffer = (PWCHAR)malloc(size); + if (GetClassNameW(hwnd, buffer, size ) == 0) return FALSE; + int res = wcscmp(buffer, className); + free(buffer); + return res == 0; +} + +class CDummyWindow : public CUnknownBase<IOleWindow> +{ +protected: + HWND m_hwnd; + + const QITAB* GetQITab() + { + static const QITAB tab[] = {{ &IID_IOleWindow, OFFSETOFCLASS(IOleWindow, CDummyWindow) }, {0}}; + return tab; + } + +public: + CDummyWindow(HWND hwnd) + { + m_hwnd = hwnd; + } + + HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd) + { + *phwnd = m_hwnd; + return S_OK; + } + + HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode) + { + return S_OK; + } +}; + +BOOL CreateCShellMenu(IShellMenu** shellMenu, IDockingWindow** dockingMenu, IObjectWithSite **menuWithSite) +{ + HRESULT hResult; + hResult = CoCreateInstance(CLSID_MenuBand, NULL, CLSCTX_INPROC_SERVER, IID_IShellMenu, reinterpret_cast<void **>(shellMenu)); + test_S_OK(hResult, "Failed to instantiate CLSID_MenuBand"); + if (!shellMenu) return FALSE; + + hResult = (*shellMenu)->QueryInterface(IID_IDockingWindow, reinterpret_cast<void **>(dockingMenu)); + test_S_OK(hResult, "Failed to query IID_IDockingWindow"); + hResult = (*shellMenu)->QueryInterface(IID_IObjectWithSite, reinterpret_cast<void **>(menuWithSite)); + test_S_OK(hResult, "Failed to query IID_IObjectWithSite"); + if (!dockingMenu || !menuWithSite) return FALSE; + return TRUE; +} + + +void test_CShellMenu_params() +{ + HRESULT hResult; + IShellMenu* shellMenu; + IDockingWindow* dockingMenu; + IObjectWithSite* menuWithSite; + + IShellMenuCallback *psmc; + UINT uId; + UINT uIdAncestor; + DWORD dwFlags; + HWND hwndToolbar; + HMENU hmenu; + HWND hwndOwner; + DWORD menuFlagss; + IShellFolder *shellFolder; + + if (!CreateCShellMenu(&shellMenu, &dockingMenu, &menuWithSite)) + { + skip("failed to create CShellMenuObject\n"); + return; + } + + hResult = shellMenu->Initialize(NULL, 11, 22, 0xdeadbeef); + test_S_OK(hResult, "Initialize failed"); + + hResult = shellMenu->GetMenuInfo(&psmc, &uId, &uIdAncestor, &dwFlags); + test_S_OK(hResult, "GetMenuInfo failed"); + ok (psmc == NULL, "wrong psmc\n"); + ok (uId == 11, "wrong uid\n"); + ok (uIdAncestor == 22, "wrong uIdAncestor\n"); + ok (dwFlags == 0xdeadbeef, "wrong dwFlags\n"); + + hResult = shellMenu->Initialize(NULL, 0, ANCESTORDEFAULT, SMINIT_TOPLEVEL|SMINIT_VERTICAL); + test_S_OK(hResult, "Initialize failed"); + + hResult = dockingMenu->GetWindow(&hwndToolbar); + test_HRES(hResult, E_FAIL, "GetWindow should fail"); + + hResult = shellMenu->GetMenu(&hmenu, &hwndOwner, &menuFlagss); + test_HRES(hResult, E_FAIL, "GetMenu should fail"); + + hmenu = CreatePopupMenu(); + hResult = shellMenu->SetMenu(hmenu, NULL, 0); + test_S_OK(hResult, "SetMenu failed"); + + hwndToolbar = (HWND)0xdeadbeef; + hResult = dockingMenu->GetWindow(&hwndToolbar); + test_S_OK(hResult, "GetWindow failed"); + ok (hwndToolbar == NULL, "Expected NULL window\n"); + + hResult = shellMenu->SetMenu(NULL, NULL, 0); + test_S_OK(hResult, "SetMenu failed"); + + hResult = shellMenu->GetMenu(&hmenu, &hwndOwner, &menuFlagss); + test_S_OK(hResult, "GetMenu failed"); + ok (hmenu == NULL, "Got a menu\n"); + + hResult = dockingMenu->GetWindow(&hwndToolbar); + test_S_OK(hResult, "GetWindow failed"); + + hResult = SHGetDesktopFolder(&shellFolder); + test_S_OK(hResult, "SHGetDesktopFolder failed"); + + hResult = shellMenu->SetShellFolder(shellFolder, NULL, 0, 0); + test_S_OK(hResult, "SetShellFolder failed"); + + hResult = shellMenu->SetShellFolder(NULL, NULL, 0, 0); + test_HRES(hResult, E_INVALIDARG, "SetShellFolder should fail"); + + hwndToolbar = (HWND)0xdeadbeef; + hResult = dockingMenu->GetWindow(&hwndToolbar); + test_S_OK(hResult, "GetWindow failed"); + ok (hwndToolbar == NULL, "Expected NULL window\n"); + + hResult = dockingMenu->ShowDW(TRUE); + test_HRES(hResult, S_FALSE, "ShowDW should fail"); + + menuWithSite->Release(); + dockingMenu->Release(); + shellMenu->Release(); +} + +void test_CShellMenu() +{ + HRESULT hResult; + IShellMenu* shellMenu; + IDockingWindow* dockingMenu; + IShellFolder *shellFolder; + IObjectWithSite *menuWithSite; + HWND hwndToolbar; + + HWND hWndParent = CreateWindowExW(0, L"EDIT", L"miau", 0, CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), NULL); + CDummyWindow* dummyWindow = new CDummyWindow(hWndParent); + + if (!CreateCShellMenu(&shellMenu, &dockingMenu, &menuWithSite)) + { + skip("failed to create CShellMenuObject\n"); + return; + } + + hResult = SHGetDesktopFolder(&shellFolder); + test_S_OK(hResult, "SHGetDesktopFolder failed"); + + hResult = shellMenu->Initialize(NULL, 0, ANCESTORDEFAULT, SMINIT_TOPLEVEL|SMINIT_VERTICAL); + test_S_OK(hResult, "Initialize failed"); + + hResult = shellMenu->SetShellFolder(shellFolder, NULL, NULL, 0); + test_S_OK(hResult, "SetShellFolder failed"); + + hResult = menuWithSite->SetSite(dummyWindow); + test_S_OK(hResult, "SetSite failed"); + + hResult = dockingMenu->GetWindow(&hwndToolbar); + test_S_OK(hResult, "GetWindow failed"); + ok(hwndToolbar != NULL, "GetWindow should return a window\n"); + + HWND hwndRealParent = GetParent(hwndToolbar); + ok(GetParent(hwndRealParent) == hWndParent, "Wrong parent\n"); + ok(CheckWindowClass(hwndToolbar, L"ToolbarWindow32"), "Wrong class\n"); + ok(CheckWindowClass(hwndRealParent, L"SysPager"), "Wrong class\n"); + + menuWithSite->Release(); + dockingMenu->Release(); + shellMenu->Release(); + ok(!IsWindow(hwndToolbar), "The toolbar window should not exist\n"); + + DestroyWindow(hWndParent); +} + +/* The folowing struct holds info about the order callbacks are called */ +/* By passing different arrays of results to CMenuCallback, we can test different sequenses of callbacks */ + struct _test_info{ + int iTest; + UINT uMsg;}; + +class CMenuCallback : public CUnknownBase<IShellMenuCallback> +{ +protected: + int m_iTest; + int m_iCallback; + struct _test_info *m_results; + int m_testsCount; + + const QITAB* GetQITab() + { + static const QITAB tab[] = {{ &IID_IShellMenuCallback, OFFSETOFCLASS(IShellMenuCallback, CMenuCallback) }, {0}}; + return tab; + } + +public: + CMenuCallback(struct _test_info *testResults, int testsCount) + { + m_iTest = 0; + m_iCallback = 0; + m_results = testResults; + m_testsCount = testsCount; + } + + void SetTest(int i) + { + m_iTest = i; + } + + HRESULT STDMETHODCALLTYPE CallbackSM(LPSMDATA psmd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + /*trace ("callback type %d\n", uMsg);*/ + + /* + * it seems callback 0x10000000 is called for every item added so + * we will ignore consecutive callbacks of this type + * Note: this callback is invoked by shell32.dll!CMenuSFToolbar::_FilterPidl + */ + if (uMsg == 0x10000000 && m_results[m_iCallback-1].uMsg == 0x10000000) + { + return S_OK; + } + + m_iCallback++; + if (m_iCallback > m_testsCount) + { + ok(0, "Got more callbacks than expected! (%d not %d). uMsg: %d\n", m_iCallback, m_testsCount, uMsg); + return S_OK; + } + + struct _test_info *result = &m_results[m_iCallback-1]; + + ok(psmd != S_OK, "Got NULL psmd\n"); + ok(m_iTest == result->iTest, "Wrong test number (%d not %d)\n", m_iTest, result->iTest); + ok(result->uMsg == uMsg, "%d: Got wrong uMsg (%d instead of %d)\n", m_iCallback, uMsg, result->uMsg); + + if(uMsg == SMC_CREATE) + { + ok(psmd->dwFlags == 0, "wrong dwFlags\n"); + ok(psmd->dwMask == 0, "wrong dwMask\n"); + ok(psmd->hmenu == 0, "wrong hmenu\n"); + ok(psmd->hwnd == 0, "wrong hwnd\n"); + ok(psmd->punk != NULL, "punk is null\n"); + } + + if (uMsg == SMC_GETSFOBJECT) + { + ok(psmd->psf != 0, "wrong dwFlags\n"); + } + + return S_FALSE; + } +}; + +void test_CShellMenu_callbacks(IShellFolder *shellFolder, HMENU hmenu) +{ + HRESULT hResult; + IShellMenu* shellMenu; + IDockingWindow* dockingMenu; + IObjectWithSite *menuWithSite; + CMenuCallback *callback; + + HWND hWndParent = CreateWindowExW(0, L"EDIT", L"miau", 0, CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), NULL); + CDummyWindow* dummyWindow = new CDummyWindow(hWndParent); + ShowWindow(hWndParent, SW_SHOW); + + if (!CreateCShellMenu(&shellMenu, &dockingMenu, &menuWithSite)) + { + skip("failed to create CShellMenuObject\n"); + return; + } + + struct _test_info cbtest_info[] = { {1, SMC_CREATE}, + {2, SMC_GETSFOBJECT}, + {3, 0x31}, + {4, SMC_INITMENU}, + {4, 53}, + {4, 19}, + {4, 0x10000000}, + {4, SMC_NEWITEM}, + {4, 20}, + {4, 19}, + {4, 6}, + {4, 20}, + {4, 8}, + {4, 24}, + {4, 5}, + {4, 5}, + {4, 5}}; + + callback = new CMenuCallback(cbtest_info,18); + + callback->SetTest(1); + hResult = shellMenu->Initialize(callback, 0,ANCESTORDEFAULT, SMINIT_TOPLEVEL|SMINIT_VERTICAL); + test_S_OK(hResult, "Initialize failed"); + + callback->SetTest(2); + hResult = shellMenu->SetShellFolder(shellFolder, NULL, NULL, 0); + test_S_OK(hResult, "SetShellFolder failed"); + + callback->SetTest(3); + hResult = shellMenu->SetMenu(hmenu, hWndParent, SMSET_TOP); + test_S_OK(hResult, "SetMenu failed"); + + hResult = menuWithSite->SetSite(dummyWindow); + test_S_OK(hResult, "SetSite failed"); + + callback->SetTest(4); + hResult = dockingMenu->ShowDW(TRUE); + test_HRES(hResult, S_FALSE, "ShowDW failed"); +} + +void test_CShellMenu_with_DeskBar(IShellFolder *shellFolder, HMENU hmenu) +{ + HRESULT hResult; + IShellMenu* shellMenu; + IDockingWindow* dockingMenu; + IObjectWithSite *menuWithSite; + IMenuPopup* menuPopup; + IBandSite* bandSite; + + /* Create the tree objects and query the nescesary interfaces */ + BOOL bCreated = CreateCShellMenu(&shellMenu, &dockingMenu, &menuWithSite); + hResult = CoCreateInstance(CLSID_MenuDeskBar, NULL, CLSCTX_INPROC_SERVER, IID_IMenuPopup, reinterpret_cast<void **>(&menuPopup)); + test_S_OK(hResult, "Failed to instantiate CLSID_MenuDeskBar"); + hResult = CoCreateInstance(CLSID_MenuBandSite, NULL, CLSCTX_INPROC_SERVER, IID_IBandSite, reinterpret_cast<void **>(&bandSite)); + test_S_OK(hResult, "Failed to instantiate CLSID_MenuBandSite"); + if (!bCreated || !menuPopup || !bandSite) + { + skip("failed to create MenuBandSite object\n"); + return; + } + + /* Create the popup menu */ + hResult = shellMenu->Initialize(NULL, 0, ANCESTORDEFAULT, SMINIT_TOPLEVEL|SMINIT_VERTICAL); + test_S_OK(hResult, "Initialize failed"); + hResult = shellMenu->SetMenu( hmenu, NULL, SMSET_TOP); + test_S_OK(hResult, "SetMenu failed"); + hResult = menuPopup->SetClient(bandSite); + test_S_OK(hResult, "SetClient failed"); + hResult = bandSite->AddBand(shellMenu); + test_S_OK(hResult, "AddBand failed"); + + /* Show the popum menu */ + POINTL p = {10,10}; + hResult = menuPopup->Popup(&p, NULL, 0); + test_HRES(hResult, S_FALSE, "Popup failed"); + + HWND hWndToolbar, hWndToplevel; + + /* Ensure that the created windows are correct */ + hResult = dockingMenu->GetWindow(&hWndToolbar); + test_S_OK(hResult, "GetWindow failed"); + ok(hWndToolbar != NULL, "GetWindow should return a window\n"); + + hResult = menuPopup->GetWindow(&hWndToplevel); + test_S_OK(hResult, "GetWindow failed"); + ok(hWndToolbar != NULL, "GetWindow should return a window\n"); + + HWND hwndRealParent = GetParent(hWndToolbar); + ok(GetParent(hwndRealParent) == hWndToplevel, "Wrong parent\n"); + ok(CheckWindowClass(hWndToolbar, L"ToolbarWindow32"), "Wrong class\n"); + ok(CheckWindowClass(hwndRealParent, L"MenuSite"), "Wrong class\n"); + ok(CheckWindowClass(hWndToplevel, L"BaseBar"), "Wrong class\n"); + + ok(GetAncestor (hWndToplevel, GA_PARENT) == GetDesktopWindow(), "Expected the BaseBar window to be top level\n"); +} + +START_TEST(menu) +{ + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + IShellFolder *shellFolder; + HRESULT hResult; + hResult = SHGetDesktopFolder(&shellFolder); + test_S_OK(hResult, "SHGetDesktopFolder failed"); + + HMENU hSubMenu = CreatePopupMenu(); + AppendMenuW(hSubMenu, 0,0, L"Submenu item1"); + AppendMenuW(hSubMenu, 0,0, L"Submenu item2"); + HMENU hmenu = CreatePopupMenu(); + AppendMenuW(hmenu, 0,0, L"test"); + AppendMenuW(hmenu, 0,1, L"test1"); + MENUITEMINFOW iteminfo = {0}; + iteminfo.cbSize = sizeof(iteminfo); + iteminfo.hSubMenu = hSubMenu; + iteminfo.fMask = MIIM_STRING | MIIM_SUBMENU; + iteminfo.dwTypeData = const_cast<LPWSTR>(L"submenu"); + iteminfo.cch = 7; + InsertMenuItemW(hmenu, 0, TRUE, &iteminfo); + + test_CShellMenu_params(); + test_CShellMenu(); + test_CShellMenu_callbacks(shellFolder, hmenu); + test_CShellMenu_with_DeskBar(shellFolder, hmenu); +} +
Propchange: trunk/rostests/apitests/shell32/menu.cpp ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/rostests/apitests/shell32/shelltest.h URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/shell32/shelltest... ============================================================================== --- trunk/rostests/apitests/shell32/shelltest.h (added) +++ trunk/rostests/apitests/shell32/shelltest.h [iso-8859-1] Thu Oct 10 09:36:13 2013 @@ -0,0 +1,65 @@ +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H + +#include <stdio.h> +#include <wine/test.h> + + +#include <winuser.h> +#include <winreg.h> + +#include <CommCtrl.h> +#include <shellapi.h> +#include <shlobj.h> +#include <shlwapi.h> + +#include <stdlib.h> +#include <malloc.h> +#include <memory.h> +#include <string.h> +#include <tchar.h> + +#include <initguid.h> + +#define test_S_OK(hres, message) ok(hres == S_OK, "%s (0x%lx instead of S_OK)\n",message, hResult); +#define test_HRES(hres, hresExpected, message) ok(hres == hresExpected, "%s (0x%lx instead of 0x%lx)\n",message, hResult,hresExpected); + +DEFINE_GUID(CLSID_MenuDeskBar, 0xECD4FC4F, 0x521C, 0x11D0, 0xB7, 0x92, 0x00, 0xA0, 0xC9, 0x03, 0x12, 0xE1); +DEFINE_GUID(CLSID_MenuBandSite, 0xE13EF4E4, 0xD2F2, 0x11D0, 0x98, 0x16, 0x00, 0xC0, 0x4F, 0xD9, 0x19, 0x72); + +template<typename Interface> +class CUnknownBase : public Interface +{ + LONG m_lRef; +protected: + virtual const QITAB* GetQITab() = 0; +public: + + CUnknownBase() + { + m_lRef = 0; + } + + ULONG STDMETHODCALLTYPE AddRef () + { + return InterlockedIncrement( &m_lRef ); + } + + ULONG STDMETHODCALLTYPE Release() + { + long newref = InterlockedDecrement( &m_lRef ); + if (newref<=0) delete this; + return newref; + } + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv) + { + HRESULT hresult = QISearch(this, GetQITab(), riid, ppv); + if(SUCCEEDED(hresult)) AddRef(); + return hresult; + } + + virtual ~CUnknownBase() {} +}; +
Propchange: trunk/rostests/apitests/shell32/shelltest.h ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/rostests/apitests/shell32/testlist.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/shell32/testlist.... ============================================================================== --- trunk/rostests/apitests/shell32/testlist.c (added) +++ trunk/rostests/apitests/shell32/testlist.c [iso-8859-1] Thu Oct 10 09:36:13 2013 @@ -0,0 +1,13 @@ +#define __ROS_LONG64__ + +#define STANDALONE +#include <wine/test.h> + +extern void func_menu(void); + +const struct test winetest_testlist[] = +{ + { "menu", func_menu }, + + { 0, 0 } +};
Propchange: trunk/rostests/apitests/shell32/testlist.c ------------------------------------------------------------------------------ svn:eol-style = native