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)
19 int res
= wcscmp(buffer
, className
);
24 class CDummyWindow
: public CUnknownBase
<IOleWindow
>
29 const QITAB
* GetQITab()
31 static const QITAB tab
[] = {{ &IID_IOleWindow
, OFFSETOFCLASS(IOleWindow
, CDummyWindow
) }, {0}};
36 CDummyWindow(HWND hwnd
)
41 HRESULT STDMETHODCALLTYPE
GetWindow(HWND
*phwnd
)
47 HRESULT STDMETHODCALLTYPE
ContextSensitiveHelp(BOOL fEnterMode
)
53 BOOL
CreateCShellMenu(IShellMenu
** shellMenu
, IDockingWindow
** dockingMenu
, IObjectWithSite
**menuWithSite
)
56 hResult
= CoCreateInstance(CLSID_MenuBand
, NULL
, CLSCTX_INPROC_SERVER
, IID_IShellMenu
, reinterpret_cast<void **>(shellMenu
));
57 test_S_OK(hResult
, "Failed to instantiate CLSID_MenuBand");
58 if (!shellMenu
) return FALSE
;
60 hResult
= (*shellMenu
)->QueryInterface(IID_IDockingWindow
, reinterpret_cast<void **>(dockingMenu
));
61 test_S_OK(hResult
, "Failed to query IID_IDockingWindow");
62 hResult
= (*shellMenu
)->QueryInterface(IID_IObjectWithSite
, reinterpret_cast<void **>(menuWithSite
));
63 test_S_OK(hResult
, "Failed to query IID_IObjectWithSite");
64 if (!dockingMenu
|| !menuWithSite
) return FALSE
;
69 void test_CShellMenu_params()
72 IShellMenu
* shellMenu
;
73 IDockingWindow
* dockingMenu
;
74 IObjectWithSite
* menuWithSite
;
76 IShellMenuCallback
*psmc
;
84 IShellFolder
*shellFolder
;
86 if (!CreateCShellMenu(&shellMenu
, &dockingMenu
, &menuWithSite
))
88 skip("failed to create CShellMenuObject\n");
92 hResult
= shellMenu
->Initialize(NULL
, 11, 22, 0xdeadbeef);
93 test_S_OK(hResult
, "Initialize failed");
95 hResult
= shellMenu
->GetMenuInfo(&psmc
, &uId
, &uIdAncestor
, &dwFlags
);
96 test_S_OK(hResult
, "GetMenuInfo failed");
97 ok (psmc
== NULL
, "wrong psmc\n");
98 ok (uId
== 11, "wrong uid\n");
99 ok (uIdAncestor
== 22, "wrong uIdAncestor\n");
100 ok (dwFlags
== 0xdeadbeef, "wrong dwFlags\n");
102 hResult
= shellMenu
->Initialize(NULL
, 0, ANCESTORDEFAULT
, SMINIT_TOPLEVEL
|SMINIT_VERTICAL
);
103 test_S_OK(hResult
, "Initialize failed");
105 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
106 test_HRES(hResult
, E_FAIL
, "GetWindow should fail");
108 hResult
= shellMenu
->GetMenu(&hmenu
, &hwndOwner
, &menuFlagss
);
109 test_HRES(hResult
, E_FAIL
, "GetMenu should fail");
111 hmenu
= CreatePopupMenu();
112 hResult
= shellMenu
->SetMenu(hmenu
, NULL
, 0);
113 test_S_OK(hResult
, "SetMenu failed");
115 hwndToolbar
= (HWND
)0xdeadbeef;
116 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
117 test_S_OK(hResult
, "GetWindow failed");
118 ok (hwndToolbar
== NULL
, "Expected NULL window\n");
120 hResult
= shellMenu
->SetMenu(NULL
, NULL
, 0);
121 test_S_OK(hResult
, "SetMenu failed");
123 hResult
= shellMenu
->GetMenu(&hmenu
, &hwndOwner
, &menuFlagss
);
124 test_S_OK(hResult
, "GetMenu failed");
125 ok (hmenu
== NULL
, "Got a menu\n");
127 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
128 test_S_OK(hResult
, "GetWindow failed");
130 hResult
= SHGetDesktopFolder(&shellFolder
);
131 test_S_OK(hResult
, "SHGetDesktopFolder failed");
133 hResult
= shellMenu
->SetShellFolder(shellFolder
, NULL
, 0, 0);
134 test_S_OK(hResult
, "SetShellFolder failed");
136 hResult
= shellMenu
->SetShellFolder(NULL
, NULL
, 0, 0);
137 test_HRES(hResult
, E_INVALIDARG
, "SetShellFolder should fail");
139 hwndToolbar
= (HWND
)0xdeadbeef;
140 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
141 test_S_OK(hResult
, "GetWindow failed");
142 ok (hwndToolbar
== NULL
, "Expected NULL window\n");
144 hResult
= dockingMenu
->ShowDW(TRUE
);
145 test_HRES(hResult
, S_FALSE
, "ShowDW should fail");
147 menuWithSite
->Release();
148 dockingMenu
->Release();
149 shellMenu
->Release();
152 void test_CShellMenu()
155 IShellMenu
* shellMenu
;
156 IDockingWindow
* dockingMenu
;
157 IShellFolder
*shellFolder
;
158 IObjectWithSite
*menuWithSite
;
161 HWND hWndParent
= CreateWindowExW(0, L
"EDIT", L
"miau", 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
162 CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, GetModuleHandle(NULL
), NULL
);
163 CDummyWindow
* dummyWindow
= new CDummyWindow(hWndParent
);
165 if (!CreateCShellMenu(&shellMenu
, &dockingMenu
, &menuWithSite
))
167 skip("failed to create CShellMenuObject\n");
172 hResult
= SHGetDesktopFolder(&shellFolder
);
173 test_S_OK(hResult
, "SHGetDesktopFolder failed");
175 hResult
= shellMenu
->Initialize(NULL
, 0, ANCESTORDEFAULT
, SMINIT_TOPLEVEL
|SMINIT_VERTICAL
);
176 test_S_OK(hResult
, "Initialize failed");
178 hResult
= shellMenu
->SetShellFolder(shellFolder
, NULL
, NULL
, 0);
179 test_S_OK(hResult
, "SetShellFolder failed");
181 hResult
= menuWithSite
->SetSite(dummyWindow
);
182 test_S_OK(hResult
, "SetSite failed");
184 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
185 test_S_OK(hResult
, "GetWindow failed");
186 ok(hwndToolbar
!= NULL
, "GetWindow should return a window\n");
188 HWND hwndRealParent
= GetParent(hwndToolbar
);
189 ok(GetParent(hwndRealParent
) == hWndParent
, "Wrong parent\n");
190 ok(CheckWindowClass(hwndToolbar
, L
"ToolbarWindow32"), "Wrong class\n");
191 ok(CheckWindowClass(hwndRealParent
, L
"SysPager"), "Wrong class\n");
193 menuWithSite
->Release();
194 dockingMenu
->Release();
195 shellMenu
->Release();
196 ok(!IsWindow(hwndToolbar
), "The toolbar window should not exist\n");
198 DestroyWindow(hWndParent
);
201 /* The folowing struct holds info about the order callbacks are called */
202 /* By passing different arrays of results to CMenuCallback, we can test different sequenses of callbacks */
207 class CMenuCallback
: public CUnknownBase
<IShellMenuCallback
>
212 struct _test_info
*m_results
;
215 const QITAB
* GetQITab()
217 static const QITAB tab
[] = {{ &IID_IShellMenuCallback
, OFFSETOFCLASS(IShellMenuCallback
, CMenuCallback
) }, {0}};
222 CMenuCallback(struct _test_info
*testResults
, int testsCount
)
226 m_results
= testResults
;
227 m_testsCount
= testsCount
;
235 HRESULT STDMETHODCALLTYPE
CallbackSM(LPSMDATA psmd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
237 /*trace ("callback type %d\n", uMsg);*/
240 * it seems callback 0x10000000 is called for every item added so
241 * we will ignore consecutive callbacks of this type
242 * Note: this callback is invoked by shell32.dll!CMenuSFToolbar::_FilterPidl
244 if (uMsg
== 0x10000000 && m_results
[m_iCallback
-1].uMsg
== 0x10000000)
250 if (m_iCallback
> m_testsCount
)
252 ok(0, "Got more callbacks than expected! (%d not %d). uMsg: %d\n", m_iCallback
, m_testsCount
, uMsg
);
256 struct _test_info
*result
= &m_results
[m_iCallback
-1];
258 ok(psmd
!= S_OK
, "Got NULL psmd\n");
259 ok(m_iTest
== result
->iTest
, "Wrong test number (%d not %d)\n", m_iTest
, result
->iTest
);
260 ok(result
->uMsg
== uMsg
, "%d: Got wrong uMsg (%d instead of %d)\n", m_iCallback
, uMsg
, result
->uMsg
);
262 if(uMsg
== SMC_CREATE
)
264 ok(psmd
->dwFlags
== 0, "wrong dwFlags\n");
265 ok(psmd
->dwMask
== 0, "wrong dwMask\n");
266 ok(psmd
->hmenu
== 0, "wrong hmenu\n");
267 ok(psmd
->hwnd
== 0, "wrong hwnd\n");
268 ok(psmd
->punk
!= NULL
, "punk is null\n");
271 if (uMsg
== SMC_GETSFOBJECT
)
273 ok(psmd
->psf
!= 0, "wrong dwFlags\n");
280 void test_CShellMenu_callbacks(IShellFolder
*shellFolder
, HMENU hmenu
)
283 IShellMenu
* shellMenu
;
284 IDockingWindow
* dockingMenu
;
285 IObjectWithSite
*menuWithSite
;
286 CMenuCallback
*callback
;
288 HWND hWndParent
= CreateWindowExW(0, L
"EDIT", L
"miau", 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
289 CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, GetModuleHandle(NULL
), NULL
);
290 CDummyWindow
* dummyWindow
= new CDummyWindow(hWndParent
);
291 ShowWindow(hWndParent
, SW_SHOW
);
293 if (!CreateCShellMenu(&shellMenu
, &dockingMenu
, &menuWithSite
))
295 skip("failed to create CShellMenuObject\n");
300 struct _test_info cbtest_info
[] = { {1, SMC_CREATE
},
301 {2, SMC_GETSFOBJECT
},
318 callback
= new CMenuCallback(cbtest_info
,18);
320 callback
->SetTest(1);
321 hResult
= shellMenu
->Initialize(callback
, 0,ANCESTORDEFAULT
, SMINIT_TOPLEVEL
|SMINIT_VERTICAL
);
322 test_S_OK(hResult
, "Initialize failed");
324 callback
->SetTest(2);
325 hResult
= shellMenu
->SetShellFolder(shellFolder
, NULL
, NULL
, 0);
326 test_S_OK(hResult
, "SetShellFolder failed");
328 callback
->SetTest(3);
329 hResult
= shellMenu
->SetMenu(hmenu
, hWndParent
, SMSET_TOP
);
330 test_S_OK(hResult
, "SetMenu failed");
332 hResult
= menuWithSite
->SetSite(dummyWindow
);
333 test_S_OK(hResult
, "SetSite failed");
335 callback
->SetTest(4);
336 hResult
= dockingMenu
->ShowDW(TRUE
);
337 test_HRES(hResult
, S_FALSE
, "ShowDW failed");
340 void test_CShellMenu_with_DeskBar(IShellFolder
*shellFolder
, HMENU hmenu
)
343 IShellMenu
* shellMenu
;
344 IDockingWindow
* dockingMenu
;
345 IObjectWithSite
*menuWithSite
;
346 IMenuPopup
* menuPopup
;
349 /* Create the tree objects and query the nescesary interfaces */
350 BOOL bCreated
= CreateCShellMenu(&shellMenu
, &dockingMenu
, &menuWithSite
);
351 hResult
= CoCreateInstance(CLSID_MenuDeskBar
, NULL
, CLSCTX_INPROC_SERVER
, IID_IMenuPopup
, reinterpret_cast<void **>(&menuPopup
));
352 test_S_OK(hResult
, "Failed to instantiate CLSID_MenuDeskBar");
353 hResult
= CoCreateInstance(CLSID_MenuBandSite
, NULL
, CLSCTX_INPROC_SERVER
, IID_IBandSite
, reinterpret_cast<void **>(&bandSite
));
354 test_S_OK(hResult
, "Failed to instantiate CLSID_MenuBandSite");
355 if (!bCreated
|| !menuPopup
|| !bandSite
)
357 skip("failed to create MenuBandSite object\n");
361 /* Create the popup menu */
362 hResult
= shellMenu
->Initialize(NULL
, 0, ANCESTORDEFAULT
, SMINIT_TOPLEVEL
|SMINIT_VERTICAL
);
363 test_S_OK(hResult
, "Initialize failed");
364 hResult
= shellMenu
->SetMenu( hmenu
, NULL
, SMSET_TOP
);
365 test_S_OK(hResult
, "SetMenu failed");
366 hResult
= menuPopup
->SetClient(bandSite
);
367 test_S_OK(hResult
, "SetClient failed");
368 hResult
= bandSite
->AddBand(shellMenu
);
369 test_S_OK(hResult
, "AddBand failed");
371 /* Show the popum menu */
373 hResult
= menuPopup
->Popup(&p
, NULL
, 0);
374 test_HRES(hResult
, S_FALSE
, "Popup failed");
376 HWND hWndToolbar
, hWndToplevel
;
378 /* Ensure that the created windows are correct */
379 hResult
= dockingMenu
->GetWindow(&hWndToolbar
);
380 test_S_OK(hResult
, "GetWindow failed");
381 ok(hWndToolbar
!= NULL
, "GetWindow should return a window\n");
383 hResult
= menuPopup
->GetWindow(&hWndToplevel
);
384 test_S_OK(hResult
, "GetWindow failed");
385 ok(hWndToolbar
!= NULL
, "GetWindow should return a window\n");
387 HWND hwndRealParent
= GetParent(hWndToolbar
);
388 ok(GetParent(hwndRealParent
) == hWndToplevel
, "Wrong parent\n");
389 ok(CheckWindowClass(hWndToolbar
, L
"ToolbarWindow32"), "Wrong class\n");
390 ok(CheckWindowClass(hwndRealParent
, L
"MenuSite"), "Wrong class\n");
391 ok(CheckWindowClass(hWndToplevel
, L
"BaseBar"), "Wrong class\n");
393 ok(GetAncestor (hWndToplevel
, GA_PARENT
) == GetDesktopWindow(), "Expected the BaseBar window to be top level\n");
398 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
400 IShellFolder
*shellFolder
;
402 hResult
= SHGetDesktopFolder(&shellFolder
);
403 test_S_OK(hResult
, "SHGetDesktopFolder failed");
405 HMENU hSubMenu
= CreatePopupMenu();
406 AppendMenuW(hSubMenu
, 0,0, L
"Submenu item1");
407 AppendMenuW(hSubMenu
, 0,0, L
"Submenu item2");
408 HMENU hmenu
= CreatePopupMenu();
409 AppendMenuW(hmenu
, 0,0, L
"test");
410 AppendMenuW(hmenu
, 0,1, L
"test1");
411 MENUITEMINFOW iteminfo
= {0};
412 iteminfo
.cbSize
= sizeof(iteminfo
);
413 iteminfo
.hSubMenu
= hSubMenu
;
414 iteminfo
.fMask
= MIIM_STRING
| MIIM_SUBMENU
;
415 iteminfo
.dwTypeData
= const_cast<LPWSTR
>(L
"submenu");
417 InsertMenuItemW(hmenu
, 0, TRUE
, &iteminfo
);
419 test_CShellMenu_params();
421 test_CShellMenu_callbacks(shellFolder
, hmenu
);
422 test_CShellMenu_with_DeskBar(shellFolder
, hmenu
);