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
10 BOOL
CheckWindowClass(HWND hwnd
, PCWSTR className
)
12 ULONG size
= (wcslen(className
) + 1)* sizeof(WCHAR
);
13 PWCHAR buffer
= (PWCHAR
)malloc(size
);
14 if (GetClassNameW(hwnd
, buffer
, size
) == 0) return FALSE
;
15 int res
= wcscmp(buffer
, className
);
20 class CDummyWindow
: public CUnknownBase
<IOleWindow
>
25 const QITAB
* GetQITab()
27 static const QITAB tab
[] = {{ &IID_IOleWindow
, OFFSETOFCLASS(IOleWindow
, CDummyWindow
) }, {0}};
32 CDummyWindow(HWND hwnd
)
37 HRESULT STDMETHODCALLTYPE
GetWindow(HWND
*phwnd
)
43 HRESULT STDMETHODCALLTYPE
ContextSensitiveHelp(BOOL fEnterMode
)
49 BOOL
CreateCShellMenu(IShellMenu
** shellMenu
, IDockingWindow
** dockingMenu
, IObjectWithSite
**menuWithSite
)
52 hResult
= CoCreateInstance(CLSID_MenuBand
, NULL
, CLSCTX_INPROC_SERVER
, IID_IShellMenu
, reinterpret_cast<void **>(shellMenu
));
53 test_S_OK(hResult
, "Failed to instantiate CLSID_MenuBand");
54 if (!shellMenu
) return FALSE
;
56 hResult
= (*shellMenu
)->QueryInterface(IID_IDockingWindow
, reinterpret_cast<void **>(dockingMenu
));
57 test_S_OK(hResult
, "Failed to query IID_IDockingWindow");
58 hResult
= (*shellMenu
)->QueryInterface(IID_IObjectWithSite
, reinterpret_cast<void **>(menuWithSite
));
59 test_S_OK(hResult
, "Failed to query IID_IObjectWithSite");
60 if (!dockingMenu
|| !menuWithSite
) return FALSE
;
65 void test_CShellMenu_params()
68 IShellMenu
* shellMenu
;
69 IDockingWindow
* dockingMenu
;
70 IObjectWithSite
* menuWithSite
;
72 IShellMenuCallback
*psmc
;
80 IShellFolder
*shellFolder
;
82 if (!CreateCShellMenu(&shellMenu
, &dockingMenu
, &menuWithSite
))
84 skip("failed to create CShellMenuObject\n");
88 hResult
= shellMenu
->Initialize(NULL
, 11, 22, 0xdeadbeef);
89 test_S_OK(hResult
, "Initialize failed");
91 hResult
= shellMenu
->GetMenuInfo(&psmc
, &uId
, &uIdAncestor
, &dwFlags
);
92 test_S_OK(hResult
, "GetMenuInfo failed");
93 ok (psmc
== NULL
, "wrong psmc\n");
94 ok (uId
== 11, "wrong uid\n");
95 ok (uIdAncestor
== 22, "wrong uIdAncestor\n");
96 ok (dwFlags
== 0xdeadbeef, "wrong dwFlags\n");
98 hResult
= shellMenu
->Initialize(NULL
, 0, ANCESTORDEFAULT
, SMINIT_TOPLEVEL
|SMINIT_VERTICAL
);
99 test_S_OK(hResult
, "Initialize failed");
101 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
102 test_HRES(hResult
, E_FAIL
, "GetWindow should fail");
104 hResult
= shellMenu
->GetMenu(&hmenu
, &hwndOwner
, &menuFlagss
);
105 test_HRES(hResult
, E_FAIL
, "GetMenu should fail");
107 hmenu
= CreatePopupMenu();
108 hResult
= shellMenu
->SetMenu(hmenu
, NULL
, 0);
109 test_S_OK(hResult
, "SetMenu failed");
111 hwndToolbar
= (HWND
)0xdeadbeef;
112 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
113 test_S_OK(hResult
, "GetWindow failed");
114 ok (hwndToolbar
== NULL
, "Expected NULL window\n");
116 hResult
= shellMenu
->SetMenu(NULL
, NULL
, 0);
117 test_S_OK(hResult
, "SetMenu failed");
119 hResult
= shellMenu
->GetMenu(&hmenu
, &hwndOwner
, &menuFlagss
);
120 test_S_OK(hResult
, "GetMenu failed");
121 ok (hmenu
== NULL
, "Got a menu\n");
123 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
124 test_S_OK(hResult
, "GetWindow failed");
126 hResult
= SHGetDesktopFolder(&shellFolder
);
127 test_S_OK(hResult
, "SHGetDesktopFolder failed");
129 hResult
= shellMenu
->SetShellFolder(shellFolder
, NULL
, 0, 0);
130 test_S_OK(hResult
, "SetShellFolder failed");
132 hResult
= shellMenu
->SetShellFolder(NULL
, NULL
, 0, 0);
133 test_HRES(hResult
, E_INVALIDARG
, "SetShellFolder should fail");
135 hwndToolbar
= (HWND
)0xdeadbeef;
136 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
137 test_S_OK(hResult
, "GetWindow failed");
138 ok (hwndToolbar
== NULL
, "Expected NULL window\n");
140 hResult
= dockingMenu
->ShowDW(TRUE
);
141 test_HRES(hResult
, S_FALSE
, "ShowDW should fail");
143 menuWithSite
->Release();
144 dockingMenu
->Release();
145 shellMenu
->Release();
148 void test_CShellMenu()
151 IShellMenu
* shellMenu
;
152 IDockingWindow
* dockingMenu
;
153 IShellFolder
*shellFolder
;
154 IObjectWithSite
*menuWithSite
;
157 HWND hWndParent
= CreateWindowExW(0, L
"EDIT", L
"miau", 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
158 CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, GetModuleHandle(NULL
), NULL
);
159 CDummyWindow
* dummyWindow
= new CDummyWindow(hWndParent
);
161 if (!CreateCShellMenu(&shellMenu
, &dockingMenu
, &menuWithSite
))
163 skip("failed to create CShellMenuObject\n");
167 hResult
= SHGetDesktopFolder(&shellFolder
);
168 test_S_OK(hResult
, "SHGetDesktopFolder failed");
170 hResult
= shellMenu
->Initialize(NULL
, 0, ANCESTORDEFAULT
, SMINIT_TOPLEVEL
|SMINIT_VERTICAL
);
171 test_S_OK(hResult
, "Initialize failed");
173 hResult
= shellMenu
->SetShellFolder(shellFolder
, NULL
, NULL
, 0);
174 test_S_OK(hResult
, "SetShellFolder failed");
176 hResult
= menuWithSite
->SetSite(dummyWindow
);
177 test_S_OK(hResult
, "SetSite failed");
179 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
180 test_S_OK(hResult
, "GetWindow failed");
181 ok(hwndToolbar
!= NULL
, "GetWindow should return a window\n");
183 HWND hwndRealParent
= GetParent(hwndToolbar
);
184 ok(GetParent(hwndRealParent
) == hWndParent
, "Wrong parent\n");
185 ok(CheckWindowClass(hwndToolbar
, L
"ToolbarWindow32"), "Wrong class\n");
186 ok(CheckWindowClass(hwndRealParent
, L
"SysPager"), "Wrong class\n");
188 menuWithSite
->Release();
189 dockingMenu
->Release();
190 shellMenu
->Release();
191 ok(!IsWindow(hwndToolbar
), "The toolbar window should not exist\n");
193 DestroyWindow(hWndParent
);
196 /* The folowing struct holds info about the order callbacks are called */
197 /* By passing different arrays of results to CMenuCallback, we can test different sequenses of callbacks */
202 class CMenuCallback
: public CUnknownBase
<IShellMenuCallback
>
207 struct _test_info
*m_results
;
210 const QITAB
* GetQITab()
212 static const QITAB tab
[] = {{ &IID_IShellMenuCallback
, OFFSETOFCLASS(IShellMenuCallback
, CMenuCallback
) }, {0}};
217 CMenuCallback(struct _test_info
*testResults
, int testsCount
)
221 m_results
= testResults
;
222 m_testsCount
= testsCount
;
230 HRESULT STDMETHODCALLTYPE
CallbackSM(LPSMDATA psmd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
232 /*trace ("callback type %d\n", uMsg);*/
235 * it seems callback 0x10000000 is called for every item added so
236 * we will ignore consecutive callbacks of this type
237 * Note: this callback is invoked by shell32.dll!CMenuSFToolbar::_FilterPidl
239 if (uMsg
== 0x10000000 && m_results
[m_iCallback
-1].uMsg
== 0x10000000)
245 if (m_iCallback
> m_testsCount
)
247 ok(0, "Got more callbacks than expected! (%d not %d). uMsg: %d\n", m_iCallback
, m_testsCount
, uMsg
);
251 struct _test_info
*result
= &m_results
[m_iCallback
-1];
253 ok(psmd
!= S_OK
, "Got NULL psmd\n");
254 ok(m_iTest
== result
->iTest
, "Wrong test number (%d not %d)\n", m_iTest
, result
->iTest
);
255 ok(result
->uMsg
== uMsg
, "%d: Got wrong uMsg (%d instead of %d)\n", m_iCallback
, uMsg
, result
->uMsg
);
257 if(uMsg
== SMC_CREATE
)
259 ok(psmd
->dwFlags
== 0, "wrong dwFlags\n");
260 ok(psmd
->dwMask
== 0, "wrong dwMask\n");
261 ok(psmd
->hmenu
== 0, "wrong hmenu\n");
262 ok(psmd
->hwnd
== 0, "wrong hwnd\n");
263 ok(psmd
->punk
!= NULL
, "punk is null\n");
266 if (uMsg
== SMC_GETSFOBJECT
)
268 ok(psmd
->psf
!= 0, "wrong dwFlags\n");
275 void test_CShellMenu_callbacks(IShellFolder
*shellFolder
, HMENU hmenu
)
278 IShellMenu
* shellMenu
;
279 IDockingWindow
* dockingMenu
;
280 IObjectWithSite
*menuWithSite
;
281 CMenuCallback
*callback
;
283 HWND hWndParent
= CreateWindowExW(0, L
"EDIT", L
"miau", 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
284 CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, GetModuleHandle(NULL
), NULL
);
285 CDummyWindow
* dummyWindow
= new CDummyWindow(hWndParent
);
286 ShowWindow(hWndParent
, SW_SHOW
);
288 if (!CreateCShellMenu(&shellMenu
, &dockingMenu
, &menuWithSite
))
290 skip("failed to create CShellMenuObject\n");
294 struct _test_info cbtest_info
[] = { {1, SMC_CREATE
},
295 {2, SMC_GETSFOBJECT
},
312 callback
= new CMenuCallback(cbtest_info
,18);
314 callback
->SetTest(1);
315 hResult
= shellMenu
->Initialize(callback
, 0,ANCESTORDEFAULT
, SMINIT_TOPLEVEL
|SMINIT_VERTICAL
);
316 test_S_OK(hResult
, "Initialize failed");
318 callback
->SetTest(2);
319 hResult
= shellMenu
->SetShellFolder(shellFolder
, NULL
, NULL
, 0);
320 test_S_OK(hResult
, "SetShellFolder failed");
322 callback
->SetTest(3);
323 hResult
= shellMenu
->SetMenu(hmenu
, hWndParent
, SMSET_TOP
);
324 test_S_OK(hResult
, "SetMenu failed");
326 hResult
= menuWithSite
->SetSite(dummyWindow
);
327 test_S_OK(hResult
, "SetSite failed");
329 callback
->SetTest(4);
330 hResult
= dockingMenu
->ShowDW(TRUE
);
331 test_HRES(hResult
, S_FALSE
, "ShowDW failed");
334 void test_CShellMenu_with_DeskBar(IShellFolder
*shellFolder
, HMENU hmenu
)
337 IShellMenu
* shellMenu
;
338 IDockingWindow
* dockingMenu
;
339 IObjectWithSite
*menuWithSite
;
340 IMenuPopup
* menuPopup
;
343 /* Create the tree objects and query the nescesary interfaces */
344 BOOL bCreated
= CreateCShellMenu(&shellMenu
, &dockingMenu
, &menuWithSite
);
345 hResult
= CoCreateInstance(CLSID_MenuDeskBar
, NULL
, CLSCTX_INPROC_SERVER
, IID_IMenuPopup
, reinterpret_cast<void **>(&menuPopup
));
346 test_S_OK(hResult
, "Failed to instantiate CLSID_MenuDeskBar");
347 hResult
= CoCreateInstance(CLSID_MenuBandSite
, NULL
, CLSCTX_INPROC_SERVER
, IID_IBandSite
, reinterpret_cast<void **>(&bandSite
));
348 test_S_OK(hResult
, "Failed to instantiate CLSID_MenuBandSite");
349 if (!bCreated
|| !menuPopup
|| !bandSite
)
351 skip("failed to create MenuBandSite object\n");
355 /* Create the popup menu */
356 hResult
= shellMenu
->Initialize(NULL
, 0, ANCESTORDEFAULT
, SMINIT_TOPLEVEL
|SMINIT_VERTICAL
);
357 test_S_OK(hResult
, "Initialize failed");
358 hResult
= shellMenu
->SetMenu( hmenu
, NULL
, SMSET_TOP
);
359 test_S_OK(hResult
, "SetMenu failed");
360 hResult
= menuPopup
->SetClient(bandSite
);
361 test_S_OK(hResult
, "SetClient failed");
362 hResult
= bandSite
->AddBand(shellMenu
);
363 test_S_OK(hResult
, "AddBand failed");
365 /* Show the popum menu */
367 hResult
= menuPopup
->Popup(&p
, NULL
, 0);
368 test_HRES(hResult
, S_FALSE
, "Popup failed");
370 HWND hWndToolbar
, hWndToplevel
;
372 /* Ensure that the created windows are correct */
373 hResult
= dockingMenu
->GetWindow(&hWndToolbar
);
374 test_S_OK(hResult
, "GetWindow failed");
375 ok(hWndToolbar
!= NULL
, "GetWindow should return a window\n");
377 hResult
= menuPopup
->GetWindow(&hWndToplevel
);
378 test_S_OK(hResult
, "GetWindow failed");
379 ok(hWndToolbar
!= NULL
, "GetWindow should return a window\n");
381 HWND hwndRealParent
= GetParent(hWndToolbar
);
382 ok(GetParent(hwndRealParent
) == hWndToplevel
, "Wrong parent\n");
383 ok(CheckWindowClass(hWndToolbar
, L
"ToolbarWindow32"), "Wrong class\n");
384 ok(CheckWindowClass(hwndRealParent
, L
"MenuSite"), "Wrong class\n");
385 ok(CheckWindowClass(hWndToplevel
, L
"BaseBar"), "Wrong class\n");
387 ok(GetAncestor (hWndToplevel
, GA_PARENT
) == GetDesktopWindow(), "Expected the BaseBar window to be top level\n");
392 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
394 IShellFolder
*shellFolder
;
396 hResult
= SHGetDesktopFolder(&shellFolder
);
397 test_S_OK(hResult
, "SHGetDesktopFolder failed");
399 HMENU hSubMenu
= CreatePopupMenu();
400 AppendMenuW(hSubMenu
, 0,0, L
"Submenu item1");
401 AppendMenuW(hSubMenu
, 0,0, L
"Submenu item2");
402 HMENU hmenu
= CreatePopupMenu();
403 AppendMenuW(hmenu
, 0,0, L
"test");
404 AppendMenuW(hmenu
, 0,1, L
"test1");
405 MENUITEMINFOW iteminfo
= {0};
406 iteminfo
.cbSize
= sizeof(iteminfo
);
407 iteminfo
.hSubMenu
= hSubMenu
;
408 iteminfo
.fMask
= MIIM_STRING
| MIIM_SUBMENU
;
409 iteminfo
.dwTypeData
= const_cast<LPWSTR
>(L
"submenu");
411 InsertMenuItemW(hmenu
, 0, TRUE
, &iteminfo
);
413 test_CShellMenu_params();
415 test_CShellMenu_callbacks(shellFolder
, hmenu
);
416 test_CShellMenu_with_DeskBar(shellFolder
, hmenu
);