1 /* 2 * oledlg tests 3 * 4 * Copyright 2015 Nikolay Sivov for CodeWeavers 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #define COBJMACROS 22 23 #include "wine/test.h" 24 #include <stdio.h> 25 26 #include "initguid.h" 27 #include "oledlg.h" 28 29 static const WCHAR *strstrW( const WCHAR *str, const WCHAR *sub ) 30 { 31 while (*str) 32 { 33 const WCHAR *p1 = str, *p2 = sub; 34 while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; } 35 if (!*p2) return str; 36 str++; 37 } 38 return NULL; 39 } 40 41 static HRESULT WINAPI enumverbs_QueryInterface(IEnumOLEVERB *iface, REFIID riid, void **ppv) 42 { 43 if (IsEqualIID(riid, &IID_IEnumOLEVERB) || IsEqualIID(riid, &IID_IUnknown)) { 44 *ppv = iface; 45 IEnumOLEVERB_AddRef(iface); 46 return S_OK; 47 } 48 49 *ppv = NULL; 50 return E_NOINTERFACE; 51 } 52 53 static ULONG WINAPI enumverbs_AddRef(IEnumOLEVERB *iface) 54 { 55 return 2; 56 } 57 58 static ULONG WINAPI enumverbs_Release(IEnumOLEVERB *iface) 59 { 60 return 1; 61 } 62 63 static int g_enumpos; 64 static const WCHAR verbW[] = {'v','e','r','b',0}; 65 static HRESULT WINAPI enumverbs_Next(IEnumOLEVERB *iface, ULONG count, OLEVERB *verbs, ULONG *fetched) 66 { 67 ok(count == 1, "got %u\n", count); 68 ok(fetched == NULL, "got %p\n", fetched); 69 ok(g_enumpos == 0 || g_enumpos == 1, "got pos %d\n", g_enumpos); 70 71 if (g_enumpos++ == 0) { 72 verbs->lVerb = 123; 73 verbs->lpszVerbName = CoTaskMemAlloc(sizeof(verbW)); 74 lstrcpyW(verbs->lpszVerbName, verbW); 75 verbs->fuFlags = MF_ENABLED; 76 verbs->grfAttribs = OLEVERBATTRIB_ONCONTAINERMENU; 77 if (fetched) *fetched = 1; 78 return S_OK; 79 } 80 81 return S_FALSE; 82 } 83 84 static HRESULT WINAPI enumverbs_Skip(IEnumOLEVERB *iface, ULONG count) 85 { 86 ok(0, "unexpected call\n"); 87 return E_NOTIMPL; 88 } 89 90 static HRESULT WINAPI enumverbs_Reset(IEnumOLEVERB *iface) 91 { 92 ok(0, "unexpected call\n"); 93 return E_NOTIMPL; 94 } 95 96 static HRESULT WINAPI enumverbs_Clone(IEnumOLEVERB *iface, IEnumOLEVERB **ppenum) 97 { 98 ok(0, "unexpected call\n"); 99 return E_NOTIMPL; 100 } 101 102 static IEnumOLEVERBVtbl enumverbsvtbl = { 103 enumverbs_QueryInterface, 104 enumverbs_AddRef, 105 enumverbs_Release, 106 enumverbs_Next, 107 enumverbs_Skip, 108 enumverbs_Reset, 109 enumverbs_Clone 110 }; 111 112 static IEnumOLEVERB enumverbs = { &enumverbsvtbl }; 113 114 static HRESULT WINAPI oleobject_QueryInterface(IOleObject *iface, REFIID riid, void **ppv) 115 { 116 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IOleObject)) { 117 *ppv = iface; 118 IOleObject_AddRef(iface); 119 return S_OK; 120 } 121 122 *ppv = NULL; 123 return E_NOINTERFACE; 124 } 125 126 static ULONG WINAPI oleobject_AddRef(IOleObject *iface) 127 { 128 return 2; 129 } 130 131 static ULONG WINAPI oleobject_Release(IOleObject *iface) 132 { 133 return 1; 134 } 135 136 static HRESULT WINAPI oleobject_SetClientSite(IOleObject *iface, IOleClientSite *site) 137 { 138 ok(0, "unexpected call\n"); 139 return E_NOTIMPL; 140 } 141 142 static HRESULT WINAPI oleobject_GetClientSite(IOleObject *iface, IOleClientSite **site) 143 { 144 ok(0, "unexpected call\n"); 145 return E_NOTIMPL; 146 } 147 148 static HRESULT WINAPI oleobject_SetHostNames(IOleObject *iface, LPCOLESTR containerapp, 149 LPCOLESTR containerObj) 150 { 151 ok(0, "unexpected call\n"); 152 return E_NOTIMPL; 153 } 154 155 static HRESULT WINAPI oleobject_Close(IOleObject *iface, DWORD saveopt) 156 { 157 ok(0, "unexpected call\n"); 158 return E_NOTIMPL; 159 } 160 161 static HRESULT WINAPI oleobject_SetMoniker(IOleObject *iface, DWORD whichmoniker, IMoniker *mk) 162 { 163 ok(0, "unexpected call\n"); 164 return E_NOTIMPL; 165 } 166 167 static HRESULT WINAPI oleobject_GetMoniker(IOleObject *iface, DWORD assign, DWORD whichmoniker, 168 IMoniker **mk) 169 { 170 ok(0, "unexpected call\n"); 171 return E_NOTIMPL; 172 } 173 174 static HRESULT WINAPI oleobject_InitFromData(IOleObject *iface, IDataObject *dataobject, 175 BOOL creation, DWORD reserved) 176 { 177 ok(0, "unexpected call\n"); 178 return E_NOTIMPL; 179 } 180 181 static HRESULT WINAPI oleobject_GetClipboardData(IOleObject *iface, DWORD reserved, IDataObject **dataobject) 182 { 183 ok(0, "unexpected call\n"); 184 return E_NOTIMPL; 185 } 186 187 static HRESULT WINAPI oleobject_DoVerb(IOleObject *iface, LONG verb, MSG *msg, IOleClientSite *activesite, 188 LONG index, HWND hwndParent, LPCRECT rect) 189 { 190 ok(0, "unexpected call\n"); 191 return E_NOTIMPL; 192 } 193 194 static BOOL g_enumverbsfail; 195 static HRESULT WINAPI oleobject_EnumVerbs(IOleObject *iface, IEnumOLEVERB **enumverb) 196 { 197 if (g_enumverbsfail) { 198 *enumverb = NULL; 199 return E_FAIL; 200 } 201 *enumverb = &enumverbs; 202 return S_OK; 203 } 204 205 static HRESULT WINAPI oleobject_Update(IOleObject *iface) 206 { 207 ok(0, "unexpected call\n"); 208 return E_NOTIMPL; 209 } 210 211 static HRESULT WINAPI oleobject_IsUpToDate(IOleObject *iface) 212 { 213 ok(0, "unexpected call\n"); 214 return E_NOTIMPL; 215 } 216 217 static HRESULT WINAPI oleobject_GetUserClassID(IOleObject *iface, CLSID *clsid) 218 { 219 ok(0, "unexpected call\n"); 220 return E_NOTIMPL; 221 } 222 223 static const WCHAR testW[] = {'t','e','s','t',0}; 224 static HRESULT WINAPI oleobject_GetUserType(IOleObject *iface, DWORD formoftype, 225 LPOLESTR *usertype) 226 { 227 ok(formoftype == USERCLASSTYPE_SHORT, "got %d\n", formoftype); 228 *usertype = CoTaskMemAlloc(sizeof(testW)); 229 lstrcpyW(*usertype, testW); 230 return S_OK; 231 } 232 233 static HRESULT WINAPI oleobject_SetExtent(IOleObject *iface, DWORD aspect, SIZEL *size) 234 { 235 ok(0, "unexpected call\n"); 236 return E_NOTIMPL; 237 } 238 239 static HRESULT WINAPI oleobject_GetExtent(IOleObject *iface, DWORD aspect, SIZEL *size) 240 { 241 ok(0, "unexpected call\n"); 242 return E_NOTIMPL; 243 } 244 245 static HRESULT WINAPI oleobject_Advise(IOleObject *iface, IAdviseSink *sink, DWORD *connection) 246 { 247 ok(0, "unexpected call\n"); 248 return E_NOTIMPL; 249 } 250 251 static HRESULT WINAPI oleobject_Unadvise(IOleObject *iface, DWORD connection) 252 { 253 ok(0, "unexpected call\n"); 254 return E_NOTIMPL; 255 } 256 257 static HRESULT WINAPI oleobject_EnumAdvise(IOleObject *iface, IEnumSTATDATA **enumadvise) 258 { 259 ok(0, "unexpected call\n"); 260 return E_NOTIMPL; 261 } 262 263 static HRESULT WINAPI oleobject_GetMiscStatus(IOleObject *iface, DWORD aspect, DWORD *status) 264 { 265 ok(0, "unexpected call\n"); 266 return E_NOTIMPL; 267 } 268 269 static HRESULT WINAPI oleobject_SetColorScheme(IOleObject *iface, LOGPALETTE *pal) 270 { 271 ok(0, "unexpected call\n"); 272 return E_NOTIMPL; 273 } 274 275 static IOleObjectVtbl oleobjectvtbl = { 276 oleobject_QueryInterface, 277 oleobject_AddRef, 278 oleobject_Release, 279 oleobject_SetClientSite, 280 oleobject_GetClientSite, 281 oleobject_SetHostNames, 282 oleobject_Close, 283 oleobject_SetMoniker, 284 oleobject_GetMoniker, 285 oleobject_InitFromData, 286 oleobject_GetClipboardData, 287 oleobject_DoVerb, 288 oleobject_EnumVerbs, 289 oleobject_Update, 290 oleobject_IsUpToDate, 291 oleobject_GetUserClassID, 292 oleobject_GetUserType, 293 oleobject_SetExtent, 294 oleobject_GetExtent, 295 oleobject_Advise, 296 oleobject_Unadvise, 297 oleobject_EnumAdvise, 298 oleobject_GetMiscStatus, 299 oleobject_SetColorScheme 300 }; 301 302 static IOleObject oleobject = { &oleobjectvtbl }; 303 304 static void test_OleUIAddVerbMenu(void) 305 { 306 static const WCHAR cadabraW[] = {'c','a','d','a','b','r','a',0}; 307 HMENU hMenu, verbmenu; 308 MENUITEMINFOW info; 309 WCHAR buffW[50]; 310 int count; 311 BOOL ret; 312 313 ret = OleUIAddVerbMenuW(NULL, NULL, NULL, 0, 0, 0, FALSE, 0, NULL); 314 ok(!ret, "got %d\n", ret); 315 316 verbmenu = (HMENU)0xdeadbeef; 317 ret = OleUIAddVerbMenuW(NULL, NULL, NULL, 0, 0, 0, FALSE, 0, &verbmenu); 318 ok(!ret, "got %d\n", ret); 319 ok(verbmenu == NULL, "got %p\n", verbmenu); 320 321 g_enumpos = 0; 322 ret = OleUIAddVerbMenuW(&oleobject, NULL, NULL, 0, 0, 0, FALSE, 0, NULL); 323 ok(!ret, "got %d\n", ret); 324 325 hMenu = CreatePopupMenu(); 326 327 memset(&info, 0, sizeof(info)); 328 info.cbSize = sizeof(info); 329 ret = InsertMenuItemW(hMenu, 0, TRUE, &info); 330 ok(ret, "got %d\n", ret); 331 332 count = GetMenuItemCount(hMenu); 333 ok(count == 1, "got %d\n", count); 334 335 g_enumpos = 0; 336 ret = OleUIAddVerbMenuW(&oleobject, NULL, hMenu, 0, 0, 0, FALSE, 0, NULL); 337 ok(!ret, "got %d\n", ret); 338 339 count = GetMenuItemCount(hMenu); 340 ok(count == 1, "got %d\n", count); 341 342 ret = InsertMenuItemW(hMenu, 0, TRUE, &info); 343 ok(ret, "got %d\n", ret); 344 345 count = GetMenuItemCount(hMenu); 346 ok(count == 2, "got %d\n", count); 347 348 verbmenu = (HMENU)0xdeadbeef; 349 g_enumpos = 0; 350 ret = OleUIAddVerbMenuW(&oleobject, NULL, hMenu, 1, 0, 0, FALSE, 0, &verbmenu); 351 ok(ret, "got %d\n", ret); 352 ok(verbmenu == NULL, "got %p\n", verbmenu); 353 354 count = GetMenuItemCount(hMenu); 355 ok(count == 2, "got %d\n", count); 356 357 /* object doesn't support EnumVerbs() */ 358 g_enumverbsfail = TRUE; 359 g_enumpos = 0; 360 verbmenu = (HMENU)0xdeadbeef; 361 ret = OleUIAddVerbMenuW(&oleobject, NULL, hMenu, 2, 0, 0, FALSE, 0, &verbmenu); 362 ok(!ret, "got %d\n", ret); 363 ok(verbmenu == NULL, "got %p\n", verbmenu); 364 g_enumverbsfail = FALSE; 365 366 /* added disabled item */ 367 memset(&info, 0, sizeof(info)); 368 info.cbSize = sizeof(info); 369 info.fMask = MIIM_STATE|MIIM_SUBMENU; 370 ret = GetMenuItemInfoW(hMenu, 2, TRUE, &info); 371 ok(ret, "got %d\n", ret); 372 ok(info.fState & MFS_DISABLED, "got state 0x%08x\n", info.fState); 373 ok(info.hSubMenu == NULL, "got submenu %p\n", info.hSubMenu); 374 375 count = GetMenuItemCount(hMenu); 376 ok(count == 3, "got %d\n", count); 377 378 /* now without object */ 379 verbmenu = (HMENU)0xdeadbeef; 380 ret = OleUIAddVerbMenuW(NULL, testW, hMenu, 3, 42, 0, FALSE, 0, &verbmenu); 381 ok(!ret, "got %d\n", ret); 382 ok(verbmenu == NULL, "got %p\n", verbmenu); 383 384 memset(&info, 0, sizeof(info)); 385 info.cbSize = sizeof(info); 386 info.fMask = MIIM_STATE|MIIM_ID|MIIM_STRING|MIIM_SUBMENU; 387 info.dwTypeData = buffW; 388 info.cch = sizeof(buffW)/sizeof(WCHAR); 389 ret = GetMenuItemInfoW(hMenu, 3, TRUE, &info); 390 ok(ret, "got %d\n", ret); 391 ok(info.fState == MF_GRAYED, "got state 0x%08x\n", info.fState); 392 ok(info.wID == 42, "got id %d\n", info.wID); 393 ok(info.hSubMenu == NULL, "got submenu %p\n", info.hSubMenu); 394 395 count = GetMenuItemCount(hMenu); 396 ok(count == 4, "got %d\n", count); 397 398 verbmenu = (HMENU)0xdeadbeef; 399 g_enumpos = 0; 400 ret = OleUIAddVerbMenuW(&oleobject, NULL, hMenu, 4, 0, 0, FALSE, 0, &verbmenu); 401 ok(ret, "got %d\n", ret); 402 ok(verbmenu == NULL, "got %p\n", verbmenu); 403 404 /* check newly added item */ 405 memset(&info, 0, sizeof(info)); 406 info.cbSize = sizeof(info); 407 info.fMask = MIIM_STRING|MIIM_STATE|MIIM_SUBMENU; 408 info.dwTypeData = buffW; 409 info.cch = sizeof(buffW)/sizeof(WCHAR); 410 ret = GetMenuItemInfoW(hMenu, 4, TRUE, &info); 411 ok(ret, "got %d\n", ret); 412 /* Item string contains verb, usertype and localized string for 'Object' word, 413 exact format depends on localization. */ 414 ok(strstrW(buffW, verbW) != NULL, "str %s\n", wine_dbgstr_w(buffW)); 415 ok(info.fState == 0, "got state 0x%08x\n", info.fState); 416 ok(info.hSubMenu == NULL, "got submenu %p\n", info.hSubMenu); 417 418 count = GetMenuItemCount(hMenu); 419 ok(count == 5, "got %d\n", count); 420 421 DestroyMenu(hMenu); 422 423 /* try to add verb menu repeatedly, with same id */ 424 hMenu = CreatePopupMenu(); 425 426 count = GetMenuItemCount(hMenu); 427 ok(count == 0, "got %d\n", count); 428 429 verbmenu = NULL; 430 ret = OleUIAddVerbMenuW(NULL, NULL, hMenu, 0, 5, 10, TRUE, 3, &verbmenu); 431 ok(!ret, "got %d\n", ret); 432 ok(verbmenu == NULL, "got %p\n", verbmenu); 433 434 count = GetMenuItemCount(hMenu); 435 ok(count == 1, "got %d\n", count); 436 437 verbmenu = NULL; 438 ret = OleUIAddVerbMenuW(NULL, NULL, hMenu, 0, 5, 10, TRUE, 3, &verbmenu); 439 ok(!ret, "got %d\n", ret); 440 ok(verbmenu == NULL, "got %p\n", verbmenu); 441 442 count = GetMenuItemCount(hMenu); 443 ok(count == 1, "got %d\n", count); 444 445 /* same position, different id */ 446 verbmenu = NULL; 447 ret = OleUIAddVerbMenuW(NULL, NULL, hMenu, 0, 6, 10, TRUE, 3, &verbmenu); 448 ok(!ret, "got %d\n", ret); 449 ok(verbmenu == NULL, "got %p\n", verbmenu); 450 451 count = GetMenuItemCount(hMenu); 452 ok(count == 1, "got %d\n", count); 453 454 /* change added item string and state */ 455 memset(&info, 0, sizeof(info)); 456 info.cbSize = sizeof(info); 457 info.fMask = MIIM_STRING|MIIM_STATE; 458 info.fState = MFS_ENABLED; 459 info.dwTypeData = buffW; 460 lstrcpyW(buffW, cadabraW); 461 ret = SetMenuItemInfoW(hMenu, 0, TRUE, &info); 462 ok(ret, "got %d\n", ret); 463 464 buffW[0] = 0; 465 GetMenuStringW(hMenu, 0, buffW, sizeof(buffW)/sizeof(buffW[0]), MF_BYPOSITION); 466 ok(!lstrcmpW(buffW, cadabraW), "got %s\n", wine_dbgstr_w(buffW)); 467 468 verbmenu = NULL; 469 ret = OleUIAddVerbMenuW(NULL, NULL, hMenu, 0, 5, 10, TRUE, 3, &verbmenu); 470 ok(!ret, "got %d\n", ret); 471 ok(verbmenu == NULL, "got %p\n", verbmenu); 472 473 memset(&info, 0, sizeof(info)); 474 info.cbSize = sizeof(info); 475 info.fMask = MIIM_STRING|MIIM_STATE; 476 buffW[0] = 0; 477 info.dwTypeData = buffW; 478 info.cch = sizeof(buffW)/sizeof(WCHAR); 479 ret = GetMenuItemInfoW(hMenu, 0, TRUE, &info); 480 ok(ret, "got %d\n", ret); 481 ok(lstrcmpW(buffW, cadabraW), "got %s\n", wine_dbgstr_w(buffW)); 482 ok(info.fState == MF_GRAYED, "got state 0x%08x\n", info.fState); 483 484 count = GetMenuItemCount(hMenu); 485 ok(count == 1, "got %d\n", count); 486 487 DestroyMenu(hMenu); 488 } 489 490 START_TEST(main) 491 { 492 test_OleUIAddVerbMenu(); 493 } 494