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
)
37 :CUnknownBase( true, 0 )
42 HRESULT STDMETHODCALLTYPE
GetWindow(HWND
*phwnd
)
48 HRESULT STDMETHODCALLTYPE
ContextSensitiveHelp(BOOL fEnterMode
)
54 BOOL
CreateCShellMenu(IShellMenu
** shellMenu
, IDockingWindow
** dockingMenu
, IObjectWithSite
**menuWithSite
)
57 hResult
= CoCreateInstance(CLSID_MenuBand
, NULL
, CLSCTX_INPROC_SERVER
, IID_IShellMenu
, reinterpret_cast<void **>(shellMenu
));
58 test_S_OK(hResult
, "Failed to instantiate CLSID_MenuBand");
59 if (!shellMenu
) return FALSE
;
61 hResult
= (*shellMenu
)->QueryInterface(IID_IDockingWindow
, reinterpret_cast<void **>(dockingMenu
));
62 test_S_OK(hResult
, "Failed to query IID_IDockingWindow");
63 hResult
= (*shellMenu
)->QueryInterface(IID_IObjectWithSite
, reinterpret_cast<void **>(menuWithSite
));
64 test_S_OK(hResult
, "Failed to query IID_IObjectWithSite");
65 if (!dockingMenu
|| !menuWithSite
) return FALSE
;
70 void test_CShellMenu_params()
73 IShellMenu
* shellMenu
;
74 IDockingWindow
* dockingMenu
;
75 IObjectWithSite
* menuWithSite
;
77 IShellMenuCallback
*psmc
;
85 IShellFolder
*shellFolder
;
87 if (!CreateCShellMenu(&shellMenu
, &dockingMenu
, &menuWithSite
))
89 skip("failed to create CShellMenuObject\n");
93 hResult
= shellMenu
->Initialize(NULL
, 11, 22, 0xdeadbeef);
94 test_S_OK(hResult
, "Initialize failed");
96 hResult
= shellMenu
->GetMenuInfo(&psmc
, &uId
, &uIdAncestor
, &dwFlags
);
97 test_S_OK(hResult
, "GetMenuInfo failed");
98 ok (psmc
== NULL
, "wrong psmc\n");
99 ok (uId
== 11, "wrong uid\n");
100 ok (uIdAncestor
== 22, "wrong uIdAncestor\n");
101 ok (dwFlags
== 0xdeadbeef, "wrong dwFlags\n");
103 hResult
= shellMenu
->Initialize(NULL
, 0, ANCESTORDEFAULT
, SMINIT_TOPLEVEL
|SMINIT_VERTICAL
);
104 test_S_OK(hResult
, "Initialize failed");
106 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
107 test_HRES(hResult
, E_FAIL
, "GetWindow should fail");
109 hResult
= shellMenu
->GetMenu(&hmenu
, &hwndOwner
, &menuFlagss
);
110 test_HRES(hResult
, E_FAIL
, "GetMenu should fail");
112 hmenu
= CreatePopupMenu();
113 hResult
= shellMenu
->SetMenu(hmenu
, NULL
, 0);
114 test_S_OK(hResult
, "SetMenu failed");
116 hwndToolbar
= (HWND
)0xdeadbeef;
117 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
118 test_S_OK(hResult
, "GetWindow failed");
119 ok (hwndToolbar
== NULL
, "Expected NULL window\n");
121 hResult
= shellMenu
->SetMenu(NULL
, NULL
, 0);
122 test_S_OK(hResult
, "SetMenu failed");
124 hResult
= shellMenu
->GetMenu(&hmenu
, &hwndOwner
, &menuFlagss
);
125 test_S_OK(hResult
, "GetMenu failed");
126 ok (hmenu
== NULL
, "Got a menu\n");
128 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
129 test_S_OK(hResult
, "GetWindow failed");
131 hResult
= SHGetDesktopFolder(&shellFolder
);
132 test_S_OK(hResult
, "SHGetDesktopFolder failed");
134 hResult
= shellMenu
->SetShellFolder(shellFolder
, NULL
, 0, 0);
135 test_S_OK(hResult
, "SetShellFolder failed");
137 hResult
= shellMenu
->SetShellFolder(NULL
, NULL
, 0, 0);
138 test_HRES(hResult
, E_INVALIDARG
, "SetShellFolder should fail");
140 hwndToolbar
= (HWND
)0xdeadbeef;
141 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
142 test_S_OK(hResult
, "GetWindow failed");
143 ok (hwndToolbar
== NULL
, "Expected NULL window\n");
145 hResult
= dockingMenu
->ShowDW(TRUE
);
146 test_HRES(hResult
, S_FALSE
, "ShowDW should fail");
148 menuWithSite
->Release();
149 dockingMenu
->Release();
150 shellMenu
->Release();
153 void test_CShellMenu()
156 IShellMenu
* shellMenu
;
157 IDockingWindow
* dockingMenu
;
158 IShellFolder
*shellFolder
;
159 IObjectWithSite
*menuWithSite
;
162 HWND hWndParent
= CreateWindowExW(0, L
"EDIT", L
"miau", 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
163 CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, GetModuleHandle(NULL
), NULL
);
164 CDummyWindow
* dummyWindow
= new CDummyWindow(hWndParent
);
166 if (!CreateCShellMenu(&shellMenu
, &dockingMenu
, &menuWithSite
))
168 skip("failed to create CShellMenuObject\n");
173 hResult
= SHGetDesktopFolder(&shellFolder
);
174 test_S_OK(hResult
, "SHGetDesktopFolder failed");
176 hResult
= shellMenu
->Initialize(NULL
, 0, ANCESTORDEFAULT
, SMINIT_TOPLEVEL
|SMINIT_VERTICAL
);
177 test_S_OK(hResult
, "Initialize failed");
179 hResult
= shellMenu
->SetShellFolder(shellFolder
, NULL
, NULL
, 0);
180 test_S_OK(hResult
, "SetShellFolder failed");
182 hResult
= menuWithSite
->SetSite(dummyWindow
);
183 test_S_OK(hResult
, "SetSite failed");
185 hResult
= dockingMenu
->GetWindow(&hwndToolbar
);
186 test_S_OK(hResult
, "GetWindow failed");
187 ok(hwndToolbar
!= NULL
, "GetWindow should return a window\n");
189 HWND hwndRealParent
= GetParent(hwndToolbar
);
190 ok(GetParent(hwndRealParent
) == hWndParent
, "Wrong parent\n");
191 ok(CheckWindowClass(hwndToolbar
, L
"ToolbarWindow32"), "Wrong class\n");
192 ok(CheckWindowClass(hwndRealParent
, L
"SysPager"), "Wrong class\n");
194 menuWithSite
->Release();
195 dockingMenu
->Release();
196 shellMenu
->Release();
197 ok(!IsWindow(hwndToolbar
), "The toolbar window should not exist\n");
199 DestroyWindow(hWndParent
);
202 /* The folowing struct holds info about the order callbacks are called */
203 /* By passing different arrays of results to CMenuCallback, we can test different sequenses of callbacks */
208 class CMenuCallback
: public CUnknownBase
<IShellMenuCallback
>
213 struct _test_info
*m_results
;
216 const QITAB
* GetQITab()
218 static const QITAB tab
[] = {{ &IID_IShellMenuCallback
, OFFSETOFCLASS(IShellMenuCallback
, CMenuCallback
) }, {0}};
223 CMenuCallback(struct _test_info
*testResults
, int testsCount
)
224 :CUnknownBase( true, 0 )
228 m_results
= testResults
;
229 m_testsCount
= testsCount
;
237 HRESULT STDMETHODCALLTYPE
CallbackSM(LPSMDATA psmd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
239 /*trace ("callback type %d\n", uMsg);*/
242 * it seems callback 0x10000000 is called for every item added so
243 * we will ignore consecutive callbacks of this type
244 * Note: this callback is invoked by shell32.dll!CMenuSFToolbar::_FilterPidl
246 if (uMsg
== 0x10000000 && m_results
[m_iCallback
-1].uMsg
== 0x10000000)
252 if (m_iCallback
> m_testsCount
)
254 ok(0, "Got more callbacks than expected! (%d not %d). uMsg: %d\n", m_iCallback
, m_testsCount
, uMsg
);
258 struct _test_info
*result
= &m_results
[m_iCallback
-1];
260 ok(psmd
!= S_OK
, "Got NULL psmd\n");
261 ok(m_iTest
== result
->iTest
, "Wrong test number (%d not %d)\n", m_iTest
, result
->iTest
);
262 ok(result
->uMsg
== uMsg
, "%d: Got wrong uMsg (%d instead of %d)\n", m_iCallback
, uMsg
, result
->uMsg
);
264 if(uMsg
== SMC_CREATE
)
266 ok(psmd
->dwFlags
== 0, "wrong dwFlags\n");
267 ok(psmd
->dwMask
== 0, "wrong dwMask\n");
268 ok(psmd
->hmenu
== 0, "wrong hmenu\n");
269 ok(psmd
->hwnd
== 0, "wrong hwnd\n");
270 ok(psmd
->punk
!= NULL
, "punk is null\n");
273 if (uMsg
== SMC_GETSFOBJECT
)
275 ok(psmd
->psf
!= 0, "wrong dwFlags\n");
282 void test_CShellMenu_callbacks(IShellFolder
*shellFolder
, HMENU hmenu
)
285 IShellMenu
* shellMenu
;
286 IDockingWindow
* dockingMenu
;
287 IObjectWithSite
*menuWithSite
;
288 CMenuCallback
*callback
;
290 HWND hWndParent
= CreateWindowExW(0, L
"EDIT", L
"miau", 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
291 CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, GetModuleHandle(NULL
), NULL
);
292 CDummyWindow
* dummyWindow
= new CDummyWindow(hWndParent
);
293 ShowWindow(hWndParent
, SW_SHOW
);
295 if (!CreateCShellMenu(&shellMenu
, &dockingMenu
, &menuWithSite
))
297 skip("failed to create CShellMenuObject\n");
302 struct _test_info cbtest_info
[] = { {1, SMC_CREATE
},
303 {2, SMC_GETSFOBJECT
},
320 callback
= new CMenuCallback(cbtest_info
,18);
322 callback
->SetTest(1);
323 hResult
= shellMenu
->Initialize(callback
, 0,ANCESTORDEFAULT
, SMINIT_TOPLEVEL
|SMINIT_VERTICAL
);
324 test_S_OK(hResult
, "Initialize failed");
326 callback
->SetTest(2);
327 hResult
= shellMenu
->SetShellFolder(shellFolder
, NULL
, NULL
, 0);
328 test_S_OK(hResult
, "SetShellFolder failed");
330 callback
->SetTest(3);
331 hResult
= shellMenu
->SetMenu(hmenu
, hWndParent
, SMSET_TOP
);
332 test_S_OK(hResult
, "SetMenu failed");
334 hResult
= menuWithSite
->SetSite(dummyWindow
);
335 test_S_OK(hResult
, "SetSite failed");
337 callback
->SetTest(4);
338 hResult
= dockingMenu
->ShowDW(TRUE
);
339 test_HRES(hResult
, S_FALSE
, "ShowDW failed");
342 void test_CShellMenu_with_DeskBar(IShellFolder
*shellFolder
, HMENU hmenu
)
345 IShellMenu
* shellMenu
;
346 IDockingWindow
* dockingMenu
;
347 IObjectWithSite
*menuWithSite
;
348 IMenuPopup
* menuPopup
;
351 /* Create the tree objects and query the nescesary interfaces */
352 BOOL bCreated
= CreateCShellMenu(&shellMenu
, &dockingMenu
, &menuWithSite
);
353 hResult
= CoCreateInstance(CLSID_MenuDeskBar
, NULL
, CLSCTX_INPROC_SERVER
, IID_IMenuPopup
, reinterpret_cast<void **>(&menuPopup
));
354 test_S_OK(hResult
, "Failed to instantiate CLSID_MenuDeskBar");
355 hResult
= CoCreateInstance(CLSID_MenuBandSite
, NULL
, CLSCTX_INPROC_SERVER
, IID_IBandSite
, reinterpret_cast<void **>(&bandSite
));
356 test_S_OK(hResult
, "Failed to instantiate CLSID_MenuBandSite");
357 if (!bCreated
|| !menuPopup
|| !bandSite
)
359 skip("failed to create MenuBandSite object\n");
363 /* Create the popup menu */
364 hResult
= shellMenu
->Initialize(NULL
, 0, ANCESTORDEFAULT
, SMINIT_TOPLEVEL
|SMINIT_VERTICAL
);
365 test_S_OK(hResult
, "Initialize failed");
366 hResult
= shellMenu
->SetMenu( hmenu
, NULL
, SMSET_TOP
);
367 test_S_OK(hResult
, "SetMenu failed");
368 hResult
= menuPopup
->SetClient(bandSite
);
369 test_S_OK(hResult
, "SetClient failed");
370 hResult
= bandSite
->AddBand(shellMenu
);
371 test_S_OK(hResult
, "AddBand failed");
373 /* Show the popum menu */
375 hResult
= menuPopup
->Popup(&p
, NULL
, 0);
376 test_HRES(hResult
, S_FALSE
, "Popup failed");
378 HWND hWndToolbar
, hWndToplevel
;
380 /* Ensure that the created windows are correct */
381 hResult
= dockingMenu
->GetWindow(&hWndToolbar
);
382 test_S_OK(hResult
, "GetWindow failed");
383 ok(hWndToolbar
!= NULL
, "GetWindow should return a window\n");
385 hResult
= menuPopup
->GetWindow(&hWndToplevel
);
386 test_S_OK(hResult
, "GetWindow failed");
387 ok(hWndToolbar
!= NULL
, "GetWindow should return a window\n");
389 HWND hwndRealParent
= GetParent(hWndToolbar
);
390 ok(GetParent(hwndRealParent
) == hWndToplevel
, "Wrong parent\n");
391 ok(CheckWindowClass(hWndToolbar
, L
"ToolbarWindow32"), "Wrong class\n");
392 ok(CheckWindowClass(hwndRealParent
, L
"MenuSite"), "Wrong class\n");
393 ok(CheckWindowClass(hWndToplevel
, L
"BaseBar"), "Wrong class\n");
395 ok(GetAncestor (hWndToplevel
, GA_PARENT
) == GetDesktopWindow(), "Expected the BaseBar window to be top level\n");
400 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
402 IShellFolder
*shellFolder
;
404 hResult
= SHGetDesktopFolder(&shellFolder
);
405 test_S_OK(hResult
, "SHGetDesktopFolder failed");
407 HMENU hSubMenu
= CreatePopupMenu();
408 AppendMenuW(hSubMenu
, 0,0, L
"Submenu item1");
409 AppendMenuW(hSubMenu
, 0,0, L
"Submenu item2");
410 HMENU hmenu
= CreatePopupMenu();
411 AppendMenuW(hmenu
, 0,0, L
"test");
412 AppendMenuW(hmenu
, 0,1, L
"test1");
413 MENUITEMINFOW iteminfo
= {0};
414 iteminfo
.cbSize
= sizeof(iteminfo
);
415 iteminfo
.hSubMenu
= hSubMenu
;
416 iteminfo
.fMask
= MIIM_STRING
| MIIM_SUBMENU
;
417 iteminfo
.dwTypeData
= const_cast<LPWSTR
>(L
"submenu");
419 InsertMenuItemW(hmenu
, 0, TRUE
, &iteminfo
);
421 test_CShellMenu_params();
423 test_CShellMenu_callbacks(shellFolder
, hmenu
);
424 test_CShellMenu_with_DeskBar(shellFolder
, hmenu
);