Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461/* * 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"
#include <shlwapi.h>#include <unknownbase.h>#include <shlguid_undoc.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);
BOOL CheckWindowClass(HWND hwnd, PCWSTR className){ ULONG size = (lstrlenW(className) + 1)* sizeof(WCHAR); PWCHAR buffer = (PWCHAR)malloc(size); if (GetClassNameW(hwnd, buffer, size ) == 0) { free(buffer); 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) :CUnknownBase( true, 0 ) { 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)UlongToPtr(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)UlongToHandle(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"); delete dummyWindow; 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 sequences 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) :CUnknownBase( true, 0 ) { 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 callbacks of this type * Note: this callback is invoked by shell32.dll!CMenuSFToolbar::_FilterPidl */ if (uMsg == 0x10000000 && m_results[m_iCallback-1].uMsg == 0x13) { return S_OK; }
m_iCallback++; if (m_iCallback > m_testsCount) { ok(FALSE, "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];
if (!g_bVista || uMsg != 0x38) // Vista bug ok(psmd != NULL, "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"); delete dummyWindow; return; }
if (GetNTVersion() <= _WIN32_WINNT_WS03) { struct _test_info cbtest_info[] = { {1, SMC_CREATE}, {2, SMC_GETSFOBJECT}, {3, SMC_SFEXEC_MIDDLE}, {4, SMC_INITMENU}, {4, 0x35}, {4, 0x13}, {4, 0x14}, {4, 0x13}, {4, 0x14}, {4, SMC_GETSFOBJECT}, {4, 0x18}, {4, SMC_GETINFO}, {4, SMC_GETINFO}, {4, SMC_GETINFO}, {4, SMC_GETINFO}, {4, SMC_GETINFO}, {4, SMC_GETINFO} };
callback = new CMenuCallback(cbtest_info, _countof(cbtest_info)); }
else { struct _test_info cbtest_info[] = { {1, SMC_CREATE}, {2, SMC_GETSFOBJECT}, {3, SMC_SFEXEC_MIDDLE}, {4, SMC_INITMENU}, {4, 0x38}, {4, 0x35}, {4, 0x13}, {4, 0x14}, {4, 0x13}, {4, 0x14}, {4, SMC_GETSFOBJECT}, {4, 0x18}, {4, SMC_GETINFO}, {4, SMC_GETINFO}, {4, SMC_GETINFO}, {4, SMC_GETINFO}, {4, SMC_GETINFO} };
callback = new CMenuCallback(cbtest_info, _countof(cbtest_info)); }
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);}