2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PURPOSE: Test for shell menu objects
5 * PROGRAMMERS: Giannis Adamopoulos
11 #include <unknownbase.h>
12 #include <shlguid_undoc.h>
14 #define test_S_OK(hres, message) ok(hres == S_OK, "%s (0x%lx instead of S_OK)\n",message, hResult);
15 #define test_HRES(hres, hresExpected, message) ok(hres == hresExpected, "%s (0x%lx instead of 0x%lx)\n",message, hResult,hresExpected);
17 BOOL
CheckWindowClass(HWND hwnd
, PCWSTR className
)
19 ULONG size
= (wcslen(className
) + 1)* sizeof(WCHAR
);
20 PWCHAR buffer
= (PWCHAR
)malloc(size
);
21 if (GetClassNameW(hwnd
, buffer
, size
) == 0)
26 int res
= wcscmp(buffer
, className
);
31 class CDummyWindow
: public CUnknownBase
<IOleWindow
>
36 const QITAB
* GetQITab()
38 static const QITAB tab
[] = {{ &IID_IOleWindow
, OFFSETOFCLASS(IOleWindow
, CDummyWindow
) }, {0}};
43 CDummyWindow(HWND hwnd
)
44 :CUnknownBase( true, 0 )
49 HRESULT STDMETHODCALLTYPE
GetWindow(HWND
*phwnd
)
55 HRESULT STDMETHODCALLTYPE
ContextSensitiveHelp(BOOL fEnterMode
)
61 BOOL
CreateCShellMenu(IShellMenu
** shellMenu
, IDockingWindow
** dockingMenu
, IObjectWithSite
**menuWithSite
)
64 hResult
= CoCreateInstance(CLSID_MenuBand
, NULL
, CLSCTX_INPROC_SERVER
, IID_IShellMenu
, reinterpret_cast<void **>(shellMenu
));
65 test_S_OK(hResult
, "Failed to instantiate CLSID_MenuBand");
66 if (!shellMenu
) return FALSE
;
68 hResult
= (*shellMenu
)->QueryInterface(IID_IDockingWindow
, reinterpret_cast<void **>(dockingMenu
));
69 test_S_OK(hResult
, "Failed to query IID_IDockingWindow");
70 hResult
= (*shellMenu
)->QueryInterface(IID_IObjectWithSite
, reinterpret_cast<void **>(menuWithSite
));
71 test_S_OK(hResult
, "Failed to query IID_IObjectWithSite");
72 if (!dockingMenu
|| !menuWithSite
) return FALSE
;
77 void test_CShellMenu_params()
80 IShellMenu
* shellMenu
;
81 IDockingWindow
* dockingMenu
;
82 IObjectWithSite
* menuWithSite
;
84 IShellMenuCallback
*psmc
;
92 IShellFolder
*shellFolder
;
94 if (!CreateCShellMenu(&shellMenu
, &dockingMenu
, &menuWithSite
))
96 skip("failed to create CShellMenuObject\n");
100 hResult
= shellMenu
->Initialize(NULL
, 11, 22, 0xdeadbeef);
101 test_S_OK(hResult
, "Initialize failed");
103 hResult
= shellMenu
->GetMenuInfo(&psmc
, &uId
, &uIdAncestor
, &dwFlags
);
104 test_S_OK(hResult
, "GetMenuInfo failed");
105 ok (psmc
== NULL
, "wrong psmc\n");
106 ok (uId
== 11, "wrong uid\n");
107 ok (uIdAncestor
== 22, "wrong uIdAncestor\n");
108 ok (dwFlags
== 0xdeadbeef, "wrong dwFlags\n");
110 hResult
= shellMenu
->Initialize(NULL
, 0, ANCESTORDEFAULT
, SMINIT_TOPLEVEL
|SMINIT_VERTICAL
);
111 test_S_OK(hResult
, "Initialize failed");
113 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
114 test_HRES(hResult
, E_FAIL
, "GetWindow should fail");
116 hResult
= shellMenu
->GetMenu(&hmenu
, &hwndOwner
, &menuFlagss
);
117 test_HRES(hResult
, E_FAIL
, "GetMenu should fail");
119 hmenu
= CreatePopupMenu();
120 hResult
= shellMenu
->SetMenu(hmenu
, NULL
, 0);
121 test_S_OK(hResult
, "SetMenu failed");
123 hwndToolbar
= (HWND
)0xdeadbeef;
124 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
125 test_S_OK(hResult
, "GetWindow failed");
126 ok (hwndToolbar
== NULL
, "Expected NULL window\n");
128 hResult
= shellMenu
->SetMenu(NULL
, NULL
, 0);
129 test_S_OK(hResult
, "SetMenu failed");
131 hResult
= shellMenu
->GetMenu(&hmenu
, &hwndOwner
, &menuFlagss
);
132 test_S_OK(hResult
, "GetMenu failed");
133 ok (hmenu
== NULL
, "Got a menu\n");
135 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
136 test_S_OK(hResult
, "GetWindow failed");
138 hResult
= SHGetDesktopFolder(&shellFolder
);
139 test_S_OK(hResult
, "SHGetDesktopFolder failed");
141 hResult
= shellMenu
->SetShellFolder(shellFolder
, NULL
, 0, 0);
142 test_S_OK(hResult
, "SetShellFolder failed");
144 hResult
= shellMenu
->SetShellFolder(NULL
, NULL
, 0, 0);
145 test_HRES(hResult
, E_INVALIDARG
, "SetShellFolder should fail");
147 hwndToolbar
= (HWND
)0xdeadbeef;
148 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
149 test_S_OK(hResult
, "GetWindow failed");
150 ok (hwndToolbar
== NULL
, "Expected NULL window\n");
152 hResult
= dockingMenu
->ShowDW(TRUE
);
153 test_HRES(hResult
, S_FALSE
, "ShowDW should fail");
155 menuWithSite
->Release();
156 dockingMenu
->Release();
157 shellMenu
->Release();
160 void test_CShellMenu()
163 IShellMenu
* shellMenu
;
164 IDockingWindow
* dockingMenu
;
165 IShellFolder
*shellFolder
;
166 IObjectWithSite
*menuWithSite
;
169 HWND hWndParent
= CreateWindowExW(0, L
"EDIT", L
"miau", 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
170 CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, GetModuleHandle(NULL
), NULL
);
171 CDummyWindow
* dummyWindow
= new CDummyWindow(hWndParent
);
173 if (!CreateCShellMenu(&shellMenu
, &dockingMenu
, &menuWithSite
))
175 skip("failed to create CShellMenuObject\n");
180 hResult
= SHGetDesktopFolder(&shellFolder
);
181 test_S_OK(hResult
, "SHGetDesktopFolder failed");
183 hResult
= shellMenu
->Initialize(NULL
, 0, ANCESTORDEFAULT
, SMINIT_TOPLEVEL
|SMINIT_VERTICAL
);
184 test_S_OK(hResult
, "Initialize failed");
186 hResult
= shellMenu
->SetShellFolder(shellFolder
, NULL
, NULL
, 0);
187 test_S_OK(hResult
, "SetShellFolder failed");
189 hResult
= menuWithSite
->SetSite(dummyWindow
);
190 test_S_OK(hResult
, "SetSite failed");
192 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
193 test_S_OK(hResult
, "GetWindow failed");
194 ok(hwndToolbar
!= NULL
, "GetWindow should return a window\n");
196 HWND hwndRealParent
= GetParent(hwndToolbar
);
197 ok(GetParent(hwndRealParent
) == hWndParent
, "Wrong parent\n");
198 ok(CheckWindowClass(hwndToolbar
, L
"ToolbarWindow32"), "Wrong class\n");
199 ok(CheckWindowClass(hwndRealParent
, L
"SysPager"), "Wrong class\n");
201 menuWithSite
->Release();
202 dockingMenu
->Release();
203 shellMenu
->Release();
204 ok(!IsWindow(hwndToolbar
), "The toolbar window should not exist\n");
206 DestroyWindow(hWndParent
);
209 /* The folowing struct holds info about the order callbacks are called */
210 /* By passing different arrays of results to CMenuCallback, we can test different sequenses of callbacks */
215 class CMenuCallback
: public CUnknownBase
<IShellMenuCallback
>
220 struct _test_info
*m_results
;
223 const QITAB
* GetQITab()
225 static const QITAB tab
[] = {{ &IID_IShellMenuCallback
, OFFSETOFCLASS(IShellMenuCallback
, CMenuCallback
) }, {0}};
230 CMenuCallback(struct _test_info
*testResults
, int testsCount
)
231 :CUnknownBase( true, 0 )
235 m_results
= testResults
;
236 m_testsCount
= testsCount
;
244 HRESULT STDMETHODCALLTYPE
CallbackSM(LPSMDATA psmd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
246 /*trace ("callback type %d\n", uMsg);*/
249 * it seems callback 0x10000000 is called for every item added so
250 * we will ignore consecutive callbacks of this type
251 * Note: this callback is invoked by shell32.dll!CMenuSFToolbar::_FilterPidl
253 if (uMsg
== 0x10000000 && m_results
[m_iCallback
-1].uMsg
== 0x10000000)
259 if (m_iCallback
> m_testsCount
)
261 ok(0, "Got more callbacks than expected! (%d not %d). uMsg: %d\n", m_iCallback
, m_testsCount
, uMsg
);
265 struct _test_info
*result
= &m_results
[m_iCallback
-1];
267 ok(psmd
!= NULL
, "Got NULL psmd\n");
268 ok(m_iTest
== result
->iTest
, "Wrong test number (%d not %d)\n", m_iTest
, result
->iTest
);
269 ok(result
->uMsg
== uMsg
, "%d: Got wrong uMsg (%d instead of %d)\n", m_iCallback
, uMsg
, result
->uMsg
);
271 if(uMsg
== SMC_CREATE
)
273 ok(psmd
->dwFlags
== 0, "wrong dwFlags\n");
274 ok(psmd
->dwMask
== 0, "wrong dwMask\n");
275 ok(psmd
->hmenu
== 0, "wrong hmenu\n");
276 ok(psmd
->hwnd
== 0, "wrong hwnd\n");
277 ok(psmd
->punk
!= NULL
, "punk is null\n");
280 if (uMsg
== SMC_GETSFOBJECT
)
282 ok(psmd
->psf
!= 0, "wrong dwFlags\n");
289 void test_CShellMenu_callbacks(IShellFolder
*shellFolder
, HMENU hmenu
)
292 IShellMenu
* shellMenu
;
293 IDockingWindow
* dockingMenu
;
294 IObjectWithSite
*menuWithSite
;
295 CMenuCallback
*callback
;
297 HWND hWndParent
= CreateWindowExW(0, L
"EDIT", L
"miau", 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
298 CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, GetModuleHandle(NULL
), NULL
);
299 CDummyWindow
* dummyWindow
= new CDummyWindow(hWndParent
);
300 ShowWindow(hWndParent
, SW_SHOW
);
302 if (!CreateCShellMenu(&shellMenu
, &dockingMenu
, &menuWithSite
))
304 skip("failed to create CShellMenuObject\n");
309 struct _test_info cbtest_info
[] = { {1, SMC_CREATE
},
310 {2, SMC_GETSFOBJECT
},
327 callback
= new CMenuCallback(cbtest_info
,18);
329 callback
->SetTest(1);
330 hResult
= shellMenu
->Initialize(callback
, 0,ANCESTORDEFAULT
, SMINIT_TOPLEVEL
|SMINIT_VERTICAL
);
331 test_S_OK(hResult
, "Initialize failed");
333 callback
->SetTest(2);
334 hResult
= shellMenu
->SetShellFolder(shellFolder
, NULL
, NULL
, 0);
335 test_S_OK(hResult
, "SetShellFolder failed");
337 callback
->SetTest(3);
338 hResult
= shellMenu
->SetMenu(hmenu
, hWndParent
, SMSET_TOP
);
339 test_S_OK(hResult
, "SetMenu failed");
341 hResult
= menuWithSite
->SetSite(dummyWindow
);
342 test_S_OK(hResult
, "SetSite failed");
344 callback
->SetTest(4);
345 hResult
= dockingMenu
->ShowDW(TRUE
);
346 test_HRES(hResult
, S_FALSE
, "ShowDW failed");
349 void test_CShellMenu_with_DeskBar(IShellFolder
*shellFolder
, HMENU hmenu
)
352 IShellMenu
* shellMenu
;
353 IDockingWindow
* dockingMenu
;
354 IObjectWithSite
*menuWithSite
;
355 IMenuPopup
* menuPopup
;
358 /* Create the tree objects and query the nescesary interfaces */
359 BOOL bCreated
= CreateCShellMenu(&shellMenu
, &dockingMenu
, &menuWithSite
);
360 hResult
= CoCreateInstance(CLSID_MenuDeskBar
, NULL
, CLSCTX_INPROC_SERVER
, IID_IMenuPopup
, reinterpret_cast<void **>(&menuPopup
));
361 test_S_OK(hResult
, "Failed to instantiate CLSID_MenuDeskBar");
362 hResult
= CoCreateInstance(CLSID_MenuBandSite
, NULL
, CLSCTX_INPROC_SERVER
, IID_IBandSite
, reinterpret_cast<void **>(&bandSite
));
363 test_S_OK(hResult
, "Failed to instantiate CLSID_MenuBandSite");
364 if (!bCreated
|| !menuPopup
|| !bandSite
)
366 skip("failed to create MenuBandSite object\n");
370 /* Create the popup menu */
371 hResult
= shellMenu
->Initialize(NULL
, 0, ANCESTORDEFAULT
, SMINIT_TOPLEVEL
|SMINIT_VERTICAL
);
372 test_S_OK(hResult
, "Initialize failed");
373 hResult
= shellMenu
->SetMenu( hmenu
, NULL
, SMSET_TOP
);
374 test_S_OK(hResult
, "SetMenu failed");
375 hResult
= menuPopup
->SetClient(bandSite
);
376 test_S_OK(hResult
, "SetClient failed");
377 hResult
= bandSite
->AddBand(shellMenu
);
378 test_S_OK(hResult
, "AddBand failed");
380 /* Show the popum menu */
382 hResult
= menuPopup
->Popup(&p
, NULL
, 0);
383 test_HRES(hResult
, S_FALSE
, "Popup failed");
385 HWND hWndToolbar
, hWndToplevel
;
387 /* Ensure that the created windows are correct */
388 hResult
= dockingMenu
->GetWindow(&hWndToolbar
);
389 test_S_OK(hResult
, "GetWindow failed");
390 ok(hWndToolbar
!= NULL
, "GetWindow should return a window\n");
392 hResult
= menuPopup
->GetWindow(&hWndToplevel
);
393 test_S_OK(hResult
, "GetWindow failed");
394 ok(hWndToolbar
!= NULL
, "GetWindow should return a window\n");
396 HWND hwndRealParent
= GetParent(hWndToolbar
);
397 ok(GetParent(hwndRealParent
) == hWndToplevel
, "Wrong parent\n");
398 ok(CheckWindowClass(hWndToolbar
, L
"ToolbarWindow32"), "Wrong class\n");
399 ok(CheckWindowClass(hwndRealParent
, L
"MenuSite"), "Wrong class\n");
400 ok(CheckWindowClass(hWndToplevel
, L
"BaseBar"), "Wrong class\n");
402 ok(GetAncestor (hWndToplevel
, GA_PARENT
) == GetDesktopWindow(), "Expected the BaseBar window to be top level\n");
407 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
409 IShellFolder
*shellFolder
;
411 hResult
= SHGetDesktopFolder(&shellFolder
);
412 test_S_OK(hResult
, "SHGetDesktopFolder failed");
414 HMENU hSubMenu
= CreatePopupMenu();
415 AppendMenuW(hSubMenu
, 0,0, L
"Submenu item1");
416 AppendMenuW(hSubMenu
, 0,0, L
"Submenu item2");
417 HMENU hmenu
= CreatePopupMenu();
418 AppendMenuW(hmenu
, 0,0, L
"test");
419 AppendMenuW(hmenu
, 0,1, L
"test1");
420 MENUITEMINFOW iteminfo
= {0};
421 iteminfo
.cbSize
= sizeof(iteminfo
);
422 iteminfo
.hSubMenu
= hSubMenu
;
423 iteminfo
.fMask
= MIIM_STRING
| MIIM_SUBMENU
;
424 iteminfo
.dwTypeData
= const_cast<LPWSTR
>(L
"submenu");
426 InsertMenuItemW(hmenu
, 0, TRUE
, &iteminfo
);
428 test_CShellMenu_params();
430 test_CShellMenu_callbacks(shellFolder
, hmenu
);
431 test_CShellMenu_with_DeskBar(shellFolder
, hmenu
);