1 /* 2 * Unit test of the IShellView 3 * 4 * Copyright 2010 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 #include <stdarg.h> 22 #include <stdio.h> 23 24 #define COBJMACROS 25 #define CONST_VTABLE 26 27 #include "windef.h" 28 #include "winbase.h" 29 #include "wtypes.h" 30 #include "shellapi.h" 31 32 #include "shlguid.h" 33 #include "shlobj.h" 34 #include "shobjidl.h" 35 #include "shlwapi.h" 36 #include "ocidl.h" 37 #include "oleauto.h" 38 39 #include "initguid.h" 40 41 #include "wine/heap.h" 42 #include "wine/test.h" 43 44 #include "msg.h" 45 46 #ifdef __REACTOS__ 47 #include <reactos/undocshell.h> 48 #endif 49 50 #define LISTVIEW_SEQ_INDEX 0 51 #define NUM_MSG_SEQUENCES 1 52 53 DEFINE_GUID(IID_IPersistHistory, 0x91a565c1, 0xe38f, 0x11d0, 0x94, 0xbf, 0x00, 0xa0, 0xc9, 0x05, 0x5c, 0xbf); 54 55 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES]; 56 57 static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 58 { 59 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); 60 static LONG defwndproc_counter = 0; 61 struct message msg = { 0 }; 62 LRESULT ret; 63 64 msg.message = message; 65 msg.flags = sent|wparam|lparam; 66 if (defwndproc_counter) msg.flags |= defwinproc; 67 msg.wParam = wParam; 68 msg.lParam = lParam; 69 add_message(sequences, LISTVIEW_SEQ_INDEX, &msg); 70 71 defwndproc_counter++; 72 ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam); 73 defwndproc_counter--; 74 return ret; 75 } 76 77 static HWND subclass_listview(HWND hwnd) 78 { 79 WNDPROC oldproc; 80 HWND listview; 81 82 /* listview is a first child */ 83 listview = FindWindowExA(hwnd, NULL, WC_LISTVIEWA, NULL); 84 if(!listview) 85 { 86 /* .. except for some versions of Windows XP, where things 87 are slightly more complicated. */ 88 HWND hwnd_tmp; 89 hwnd_tmp = FindWindowExA(hwnd, NULL, "DUIViewWndClassName", NULL); 90 hwnd_tmp = FindWindowExA(hwnd_tmp, NULL, "DirectUIHWND", NULL); 91 hwnd_tmp = FindWindowExA(hwnd_tmp, NULL, "CtrlNotifySink", NULL); 92 listview = FindWindowExA(hwnd_tmp, NULL, WC_LISTVIEWA, NULL); 93 } 94 95 oldproc = (WNDPROC)SetWindowLongPtrA(listview, GWLP_WNDPROC, 96 (LONG_PTR)listview_subclass_proc); 97 SetWindowLongPtrA(listview, GWLP_USERDATA, (LONG_PTR)oldproc); 98 99 return listview; 100 } 101 102 static UINT get_msg_count(struct msg_sequence **seq, int sequence_index, UINT message) 103 { 104 struct msg_sequence *msg_seq = seq[sequence_index]; 105 UINT i, count = 0; 106 107 for(i = 0; i < msg_seq->count ; i++) 108 if(msg_seq->sequence[i].message == message) 109 count++; 110 111 return count; 112 } 113 114 /* Checks that every message in the sequence seq is also present in 115 * the UINT array msgs */ 116 static void verify_msgs_in_(struct msg_sequence *seq, const UINT *msgs, 117 const char *file, int line) 118 { 119 UINT i, j, msg, failcount = 0; 120 for(i = 0; i < seq->count; i++) 121 { 122 BOOL found = FALSE; 123 msg = seq->sequence[i].message; 124 for(j = 0; msgs[j] != 0; j++) 125 if(msgs[j] == msg) found = TRUE; 126 127 if(!found) 128 { 129 failcount++; 130 trace("Unexpected message %d\n", msg); 131 } 132 } 133 ok_(file, line) (!failcount, "%d failures.\n", failcount); 134 flush_sequences(sequences, NUM_MSG_SEQUENCES); 135 } 136 137 #define verify_msgs_in(seq, msgs) \ 138 verify_msgs_in_(seq, msgs, __FILE__, __LINE__) 139 140 /* dummy IDataObject implementation */ 141 typedef struct { 142 IDataObject IDataObject_iface; 143 LONG ref; 144 } IDataObjectImpl; 145 146 static const IDataObjectVtbl IDataObjectImpl_Vtbl; 147 148 static inline IDataObjectImpl *impl_from_IDataObject(IDataObject *iface) 149 { 150 return CONTAINING_RECORD(iface, IDataObjectImpl, IDataObject_iface); 151 } 152 153 static IDataObject* IDataObjectImpl_Construct(void) 154 { 155 IDataObjectImpl *obj; 156 157 obj = heap_alloc(sizeof(*obj)); 158 obj->IDataObject_iface.lpVtbl = &IDataObjectImpl_Vtbl; 159 obj->ref = 1; 160 161 return &obj->IDataObject_iface; 162 } 163 164 static HRESULT WINAPI IDataObjectImpl_QueryInterface(IDataObject *iface, REFIID riid, void **ppvObj) 165 { 166 IDataObjectImpl *This = impl_from_IDataObject(iface); 167 168 if (IsEqualIID(riid, &IID_IUnknown) || 169 IsEqualIID(riid, &IID_IDataObject)) 170 { 171 *ppvObj = &This->IDataObject_iface; 172 } 173 174 if(*ppvObj) 175 { 176 IDataObject_AddRef(iface); 177 return S_OK; 178 } 179 180 return E_NOINTERFACE; 181 } 182 183 static ULONG WINAPI IDataObjectImpl_AddRef(IDataObject * iface) 184 { 185 IDataObjectImpl *This = impl_from_IDataObject(iface); 186 return InterlockedIncrement(&This->ref); 187 } 188 189 static ULONG WINAPI IDataObjectImpl_Release(IDataObject * iface) 190 { 191 IDataObjectImpl *This = impl_from_IDataObject(iface); 192 ULONG ref = InterlockedDecrement(&This->ref); 193 194 if (!ref) 195 heap_free(This); 196 197 return ref; 198 } 199 200 static HRESULT WINAPI IDataObjectImpl_GetData(IDataObject *iface, FORMATETC *pformat, STGMEDIUM *pmedium) 201 { 202 return E_NOTIMPL; 203 } 204 205 static HRESULT WINAPI IDataObjectImpl_GetDataHere(IDataObject *iface, FORMATETC *pformat, STGMEDIUM *pmedium) 206 { 207 return E_NOTIMPL; 208 } 209 210 static HRESULT WINAPI IDataObjectImpl_QueryGetData(IDataObject *iface, FORMATETC *pformat) 211 { 212 return E_NOTIMPL; 213 } 214 215 static HRESULT WINAPI IDataObjectImpl_GetCanonicalFormatEtc( 216 IDataObject *iface, FORMATETC *pformatIn, FORMATETC *pformatOut) 217 { 218 return E_NOTIMPL; 219 } 220 221 static HRESULT WINAPI IDataObjectImpl_SetData( 222 IDataObject *iface, FORMATETC *pformat, STGMEDIUM *pmedium, BOOL release) 223 { 224 return E_NOTIMPL; 225 } 226 227 static HRESULT WINAPI IDataObjectImpl_EnumFormatEtc( 228 IDataObject *iface, DWORD direction, IEnumFORMATETC **ppenumFormatEtc) 229 { 230 return E_NOTIMPL; 231 } 232 233 static HRESULT WINAPI IDataObjectImpl_DAdvise( 234 IDataObject *iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pSink, DWORD *pConnection) 235 { 236 return E_NOTIMPL; 237 } 238 239 static HRESULT WINAPI IDataObjectImpl_DUnadvise(IDataObject *iface, DWORD connection) 240 { 241 return E_NOTIMPL; 242 } 243 244 static HRESULT WINAPI IDataObjectImpl_EnumDAdvise(IDataObject *iface, IEnumSTATDATA **ppenumAdvise) 245 { 246 return E_NOTIMPL; 247 } 248 249 static const IDataObjectVtbl IDataObjectImpl_Vtbl = 250 { 251 IDataObjectImpl_QueryInterface, 252 IDataObjectImpl_AddRef, 253 IDataObjectImpl_Release, 254 IDataObjectImpl_GetData, 255 IDataObjectImpl_GetDataHere, 256 IDataObjectImpl_QueryGetData, 257 IDataObjectImpl_GetCanonicalFormatEtc, 258 IDataObjectImpl_SetData, 259 IDataObjectImpl_EnumFormatEtc, 260 IDataObjectImpl_DAdvise, 261 IDataObjectImpl_DUnadvise, 262 IDataObjectImpl_EnumDAdvise 263 }; 264 265 /* dummy IShellBrowser implementation */ 266 typedef struct { 267 IShellBrowser IShellBrowser_iface; 268 LONG ref; 269 } IShellBrowserImpl; 270 271 static const IShellBrowserVtbl IShellBrowserImpl_Vtbl; 272 273 static inline IShellBrowserImpl *impl_from_IShellBrowser(IShellBrowser *iface) 274 { 275 return CONTAINING_RECORD(iface, IShellBrowserImpl, IShellBrowser_iface); 276 } 277 278 static IShellBrowser* IShellBrowserImpl_Construct(void) 279 { 280 IShellBrowserImpl *browser; 281 282 browser = heap_alloc(sizeof(*browser)); 283 browser->IShellBrowser_iface.lpVtbl = &IShellBrowserImpl_Vtbl; 284 browser->ref = 1; 285 286 return &browser->IShellBrowser_iface; 287 } 288 289 static HRESULT WINAPI IShellBrowserImpl_QueryInterface(IShellBrowser *iface, 290 REFIID riid, 291 LPVOID *ppvObj) 292 { 293 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 294 295 *ppvObj = NULL; 296 297 if(IsEqualIID(riid, &IID_IUnknown) || 298 IsEqualIID(riid, &IID_IOleWindow) || 299 IsEqualIID(riid, &IID_IShellBrowser)) 300 { 301 *ppvObj = &This->IShellBrowser_iface; 302 } 303 304 if(*ppvObj) 305 { 306 IShellBrowser_AddRef(iface); 307 return S_OK; 308 } 309 310 return E_NOINTERFACE; 311 } 312 313 static ULONG WINAPI IShellBrowserImpl_AddRef(IShellBrowser * iface) 314 { 315 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 316 return InterlockedIncrement(&This->ref); 317 } 318 319 static ULONG WINAPI IShellBrowserImpl_Release(IShellBrowser * iface) 320 { 321 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 322 ULONG ref = InterlockedDecrement(&This->ref); 323 324 if (!ref) 325 heap_free(This); 326 327 return ref; 328 } 329 330 static HRESULT WINAPI IShellBrowserImpl_GetWindow(IShellBrowser *iface, 331 HWND *phwnd) 332 { 333 if (phwnd) *phwnd = GetDesktopWindow(); 334 return S_OK; 335 } 336 337 static HRESULT WINAPI IShellBrowserImpl_ContextSensitiveHelp(IShellBrowser *iface, 338 BOOL fEnterMode) 339 { 340 return E_NOTIMPL; 341 } 342 343 static HRESULT WINAPI IShellBrowserImpl_BrowseObject(IShellBrowser *iface, 344 LPCITEMIDLIST pidl, 345 UINT wFlags) 346 { 347 return E_NOTIMPL; 348 } 349 350 static HRESULT WINAPI IShellBrowserImpl_EnableModelessSB(IShellBrowser *iface, 351 BOOL fEnable) 352 353 { 354 return E_NOTIMPL; 355 } 356 357 static HRESULT WINAPI IShellBrowserImpl_GetControlWindow(IShellBrowser *iface, 358 UINT id, 359 HWND *lphwnd) 360 361 { 362 return E_NOTIMPL; 363 } 364 365 static HRESULT WINAPI IShellBrowserImpl_GetViewStateStream(IShellBrowser *iface, 366 DWORD mode, 367 LPSTREAM *pStrm) 368 369 { 370 return E_NOTIMPL; 371 } 372 373 static HRESULT WINAPI IShellBrowserImpl_InsertMenusSB(IShellBrowser *iface, 374 HMENU hmenuShared, 375 LPOLEMENUGROUPWIDTHS lpMenuWidths) 376 377 { 378 return E_NOTIMPL; 379 } 380 381 static HRESULT WINAPI IShellBrowserImpl_OnViewWindowActive(IShellBrowser *iface, 382 IShellView *ppshv) 383 384 { 385 return E_NOTIMPL; 386 } 387 388 static HRESULT WINAPI IShellBrowserImpl_QueryActiveShellView(IShellBrowser *iface, 389 IShellView **ppshv) 390 391 { 392 return E_NOTIMPL; 393 } 394 395 static HRESULT WINAPI IShellBrowserImpl_RemoveMenusSB(IShellBrowser *iface, 396 HMENU hmenuShared) 397 398 { 399 return E_NOTIMPL; 400 } 401 402 static HRESULT WINAPI IShellBrowserImpl_SendControlMsg(IShellBrowser *iface, 403 UINT id, 404 UINT uMsg, 405 WPARAM wParam, 406 LPARAM lParam, 407 LRESULT *pret) 408 409 { 410 return E_NOTIMPL; 411 } 412 413 static HRESULT WINAPI IShellBrowserImpl_SetMenuSB(IShellBrowser *iface, 414 HMENU hmenuShared, 415 HOLEMENU holemenuReserved, 416 HWND hwndActiveObject) 417 418 { 419 return E_NOTIMPL; 420 } 421 422 static HRESULT WINAPI IShellBrowserImpl_SetStatusTextSB(IShellBrowser *iface, 423 LPCOLESTR lpszStatusText) 424 425 { 426 return E_NOTIMPL; 427 } 428 429 static HRESULT WINAPI IShellBrowserImpl_SetToolbarItems(IShellBrowser *iface, 430 LPTBBUTTON lpButtons, 431 UINT nButtons, 432 UINT uFlags) 433 434 { 435 return E_NOTIMPL; 436 } 437 438 static HRESULT WINAPI IShellBrowserImpl_TranslateAcceleratorSB(IShellBrowser *iface, 439 LPMSG lpmsg, 440 WORD wID) 441 442 { 443 return E_NOTIMPL; 444 } 445 446 static const IShellBrowserVtbl IShellBrowserImpl_Vtbl = 447 { 448 IShellBrowserImpl_QueryInterface, 449 IShellBrowserImpl_AddRef, 450 IShellBrowserImpl_Release, 451 IShellBrowserImpl_GetWindow, 452 IShellBrowserImpl_ContextSensitiveHelp, 453 IShellBrowserImpl_InsertMenusSB, 454 IShellBrowserImpl_SetMenuSB, 455 IShellBrowserImpl_RemoveMenusSB, 456 IShellBrowserImpl_SetStatusTextSB, 457 IShellBrowserImpl_EnableModelessSB, 458 IShellBrowserImpl_TranslateAcceleratorSB, 459 IShellBrowserImpl_BrowseObject, 460 IShellBrowserImpl_GetViewStateStream, 461 IShellBrowserImpl_GetControlWindow, 462 IShellBrowserImpl_SendControlMsg, 463 IShellBrowserImpl_QueryActiveShellView, 464 IShellBrowserImpl_OnViewWindowActive, 465 IShellBrowserImpl_SetToolbarItems 466 }; 467 468 static const struct message empty_seq[] = { 469 { 0 } 470 }; 471 472 static const struct message folderview_getspacing_seq[] = { 473 { LVM_GETITEMSPACING, wparam|sent, FALSE }, 474 { 0 } 475 }; 476 477 static const struct message folderview_getselectionmarked_seq[] = { 478 { LVM_GETSELECTIONMARK, sent }, 479 { 0 } 480 }; 481 482 static const struct message folderview_getfocused_seq[] = { 483 { LVM_GETNEXTITEM, sent|wparam|lparam|optional, -1, LVNI_FOCUSED }, 484 { 0 } 485 }; 486 487 static HRESULT WINAPI shellbrowser_QueryInterface(IShellBrowser *iface, REFIID riid, void **ppv) 488 { 489 *ppv = NULL; 490 491 if (IsEqualGUID(&IID_IShellBrowser, riid) || 492 IsEqualGUID(&IID_IOleWindow, riid) || 493 IsEqualGUID(&IID_IUnknown, riid)) 494 { 495 *ppv = iface; 496 } 497 498 if (*ppv) 499 { 500 IUnknown_AddRef((IUnknown*)*ppv); 501 return S_OK; 502 } 503 504 return E_NOINTERFACE; 505 } 506 507 static ULONG WINAPI shellbrowser_AddRef(IShellBrowser *iface) 508 { 509 return 2; 510 } 511 512 static ULONG WINAPI shellbrowser_Release(IShellBrowser *iface) 513 { 514 return 1; 515 } 516 517 static HRESULT WINAPI shellbrowser_GetWindow(IShellBrowser *iface, HWND *phwnd) 518 { 519 *phwnd = GetDesktopWindow(); 520 return S_OK; 521 } 522 523 static HRESULT WINAPI shellbrowser_ContextSensitiveHelp(IShellBrowser *iface, BOOL mode) 524 { 525 ok(0, "unexpected\n"); 526 return E_NOTIMPL; 527 } 528 529 static HRESULT WINAPI shellbrowser_InsertMenusSB(IShellBrowser *iface, HMENU hmenuShared, 530 OLEMENUGROUPWIDTHS *menuwidths) 531 { 532 return E_NOTIMPL; 533 } 534 535 static HRESULT WINAPI shellbrowser_SetMenuSB(IShellBrowser *iface, HMENU hmenuShared, 536 HOLEMENU holemenuReserved, HWND hwndActiveObject) 537 { 538 return E_NOTIMPL; 539 } 540 541 static HRESULT WINAPI shellbrowser_RemoveMenusSB(IShellBrowser *iface, HMENU hmenuShared) 542 { 543 return E_NOTIMPL; 544 } 545 546 static HRESULT WINAPI shellbrowser_SetStatusTextSB(IShellBrowser *iface, LPCOLESTR text) 547 { 548 ok(0, "unexpected\n"); 549 return E_NOTIMPL; 550 } 551 552 static HRESULT WINAPI shellbrowser_EnableModelessSB(IShellBrowser *iface, BOOL enable) 553 { 554 ok(0, "unexpected\n"); 555 return E_NOTIMPL; 556 } 557 558 static HRESULT WINAPI shellbrowser_TranslateAcceleratorSB(IShellBrowser *iface, MSG *pmsg, WORD wID) 559 { 560 ok(0, "unexpected\n"); 561 return E_NOTIMPL; 562 } 563 564 static HRESULT WINAPI shellbrowser_BrowseObject(IShellBrowser *iface, LPCITEMIDLIST pidl, UINT flags) 565 { 566 ok(0, "unexpected\n"); 567 return E_NOTIMPL; 568 } 569 570 static HRESULT WINAPI shellbrowser_GetViewStateStream(IShellBrowser *iface, DWORD mode, IStream **stream) 571 { 572 return E_NOTIMPL; 573 } 574 575 static HRESULT WINAPI shellbrowser_GetControlWindow(IShellBrowser *iface, UINT id, HWND *phwnd) 576 { 577 return E_NOTIMPL; 578 } 579 580 static HRESULT WINAPI shellbrowser_SendControlMsg(IShellBrowser *iface, UINT id, UINT uMsg, 581 WPARAM wParam, LPARAM lParam, LRESULT *pret) 582 { 583 return E_NOTIMPL; 584 } 585 586 static HRESULT WINAPI shellbrowser_QueryActiveShellView(IShellBrowser *iface, IShellView **view) 587 { 588 ok(0, "unexpected\n"); 589 return E_NOTIMPL; 590 } 591 592 static HRESULT WINAPI shellbrowser_OnViewWindowActive(IShellBrowser *iface, IShellView *view) 593 { 594 ok(0, "unexpected\n"); 595 return E_NOTIMPL; 596 } 597 598 static HRESULT WINAPI shellbrowser_SetToolbarItems(IShellBrowser *iface, LPTBBUTTONSB buttons, 599 UINT count, UINT flags) 600 { 601 return E_NOTIMPL; 602 } 603 604 static const IShellBrowserVtbl shellbrowservtbl = { 605 shellbrowser_QueryInterface, 606 shellbrowser_AddRef, 607 shellbrowser_Release, 608 shellbrowser_GetWindow, 609 shellbrowser_ContextSensitiveHelp, 610 shellbrowser_InsertMenusSB, 611 shellbrowser_SetMenuSB, 612 shellbrowser_RemoveMenusSB, 613 shellbrowser_SetStatusTextSB, 614 shellbrowser_EnableModelessSB, 615 shellbrowser_TranslateAcceleratorSB, 616 shellbrowser_BrowseObject, 617 shellbrowser_GetViewStateStream, 618 shellbrowser_GetControlWindow, 619 shellbrowser_SendControlMsg, 620 shellbrowser_QueryActiveShellView, 621 shellbrowser_OnViewWindowActive, 622 shellbrowser_SetToolbarItems 623 }; 624 625 static IShellBrowser test_shellbrowser = { &shellbrowservtbl }; 626 627 static void test_CreateViewWindow(void) 628 { 629 IShellFolder *desktop; 630 HWND hwnd_view, hwnd2; 631 FOLDERSETTINGS settings; 632 IShellView *view; 633 IDropTarget *dt; 634 HRESULT hr; 635 RECT r = {0}; 636 ULONG ref1, ref2; 637 IUnknown *unk; 638 639 hr = SHGetDesktopFolder(&desktop); 640 ok(hr == S_OK, "got (0x%08x)\n", hr); 641 642 hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view); 643 ok(hr == S_OK, "got (0x%08x)\n", hr); 644 645 hr = IShellView_QueryInterface(view, &IID_CDefView, (void **)&unk); 646 ok(hr == S_OK, "got (0x%08x)\n", hr); 647 ok(unk == (IUnknown *)view, "got %p\n", unk); 648 IUnknown_Release(unk); 649 650 if (0) 651 { 652 /* crashes on native */ 653 IShellView_CreateViewWindow(view, NULL, &settings, NULL, NULL, NULL); 654 } 655 656 settings.ViewMode = FVM_ICON; 657 settings.fFlags = 0; 658 hwnd_view = (HWND)0xdeadbeef; 659 hr = IShellView_CreateViewWindow(view, NULL, &settings, NULL, NULL, &hwnd_view); 660 ok(hr == E_UNEXPECTED, "got (0x%08x)\n", hr); 661 ok(hwnd_view == 0, "got %p\n", hwnd_view); 662 663 hwnd_view = (HWND)0xdeadbeef; 664 hr = IShellView_CreateViewWindow(view, NULL, &settings, NULL, &r, &hwnd_view); 665 ok(hr == E_UNEXPECTED, "got (0x%08x)\n", hr); 666 ok(hwnd_view == 0, "got %p\n", hwnd_view); 667 668 hwnd_view = NULL; 669 hr = IShellView_CreateViewWindow(view, NULL, &settings, &test_shellbrowser, &r, &hwnd_view); 670 ok(hr == S_OK || broken(hr == S_FALSE), "got (0x%08x)\n", hr); 671 ok(hwnd_view != 0, "got %p\n", hwnd_view); 672 673 hwnd2 = (HWND)0xdeadbeef; 674 hr = IShellView_CreateViewWindow(view, NULL, &settings, &test_shellbrowser, &r, &hwnd2); 675 ok(hr == E_UNEXPECTED, "got (0x%08x)\n", hr); 676 ok(hwnd2 == NULL, "got %p\n", hwnd2); 677 678 /* ::DragLeave without drag operation */ 679 hr = IShellView_QueryInterface(view, &IID_IDropTarget, (void**)&dt); 680 ok(hr == S_OK, "got (0x%08x)\n", hr); 681 hr = IDropTarget_DragLeave(dt); 682 ok(hr == S_OK, "got (0x%08x)\n", hr); 683 IDropTarget_Release(dt); 684 685 IShellView_AddRef(view); 686 ref1 = IShellView_Release(view); 687 hr = IShellView_DestroyViewWindow(view); 688 ok(hr == S_OK, "got (0x%08x)\n", hr); 689 ok(!IsWindow(hwnd_view), "hwnd %p still valid\n", hwnd_view); 690 ref2 = IShellView_Release(view); 691 ok(ref1 > ref2, "expected %u > %u\n", ref1, ref2); 692 ref1 = ref2; 693 694 /* Show that releasing the shell view does not destroy the window */ 695 hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view); 696 ok(hr == S_OK, "got (0x%08x)\n", hr); 697 hwnd_view = NULL; 698 hr = IShellView_CreateViewWindow(view, NULL, &settings, &test_shellbrowser, &r, &hwnd_view); 699 ok(hr == S_OK || broken(hr == S_FALSE), "got (0x%08x)\n", hr); 700 ok(hwnd_view != NULL, "got %p\n", hwnd_view); 701 ok(IsWindow(hwnd_view), "hwnd %p still valid\n", hwnd_view); 702 ref2 = IShellView_Release(view); 703 ok(ref2 != 0, "ref2 = %u\n", ref2); 704 ok(ref2 > ref1, "expected %u > %u\n", ref2, ref1); 705 ok(IsWindow(hwnd_view), "hwnd %p still valid\n", hwnd_view); 706 DestroyWindow(hwnd_view); 707 708 IShellFolder_Release(desktop); 709 } 710 711 static void test_IFolderView(void) 712 { 713 IShellFolder *desktop, *folder; 714 FOLDERSETTINGS settings; 715 IShellView *view; 716 IShellBrowser *browser; 717 IFolderView2 *fv2; 718 IFolderView *fv; 719 IUnknown *unk; 720 HWND hwnd_view, hwnd_list; 721 PITEMID_CHILD pidl; 722 HRESULT hr; 723 INT ret, count; 724 POINT pt; 725 RECT r; 726 727 hr = SHGetDesktopFolder(&desktop); 728 ok(hr == S_OK, "got (0x%08x)\n", hr); 729 730 hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view); 731 ok(hr == S_OK, "got (0x%08x)\n", hr); 732 733 hr = IShellView_QueryInterface(view, &IID_IFolderView, (void**)&fv); 734 if (hr != S_OK) 735 { 736 win_skip("IFolderView not supported by desktop folder\n"); 737 IShellView_Release(view); 738 IShellFolder_Release(desktop); 739 return; 740 } 741 742 /* call methods before window creation */ 743 hr = IFolderView_GetSpacing(fv, NULL); 744 ok(hr == S_FALSE || broken(hr == S_OK) /* win7 */, "got (0x%08x)\n", hr); 745 746 pidl = (void*)0xdeadbeef; 747 hr = IFolderView_Item(fv, 0, &pidl); 748 ok(hr == E_INVALIDARG || broken(hr == E_FAIL) /* < Vista */, "got (0x%08x)\n", hr); 749 ok(pidl == 0 || broken(pidl == (void*)0xdeadbeef) /* < Vista */, "got %p\n", pidl); 750 751 if (0) 752 { 753 /* crashes on Vista and Win2k8 - List not created yet case */ 754 IFolderView_GetSpacing(fv, &pt); 755 756 /* crashes on XP */ 757 IFolderView_GetSelectionMarkedItem(fv, NULL); 758 IFolderView_GetFocusedItem(fv, NULL); 759 760 /* crashes on Vista+ */ 761 IFolderView_Item(fv, 0, NULL); 762 } 763 764 browser = IShellBrowserImpl_Construct(); 765 766 settings.ViewMode = FVM_ICON; 767 settings.fFlags = 0; 768 hwnd_view = (HWND)0xdeadbeef; 769 SetRect(&r, 0, 0, 100, 100); 770 hr = IShellView_CreateViewWindow(view, NULL, &settings, browser, &r, &hwnd_view); 771 ok(hr == S_OK, "got (0x%08x)\n", hr); 772 ok(IsWindow(hwnd_view), "got %p\n", hwnd_view); 773 774 hwnd_list = subclass_listview(hwnd_view); 775 if (!hwnd_list) 776 { 777 win_skip("Failed to subclass ListView control\n"); 778 IShellBrowser_Release(browser); 779 IFolderView_Release(fv); 780 IShellView_Release(view); 781 IShellFolder_Release(desktop); 782 return; 783 } 784 785 /* IFolderView::GetSpacing */ 786 flush_sequences(sequences, NUM_MSG_SEQUENCES); 787 hr = IFolderView_GetSpacing(fv, NULL); 788 ok(hr == S_OK, "got (0x%08x)\n", hr); 789 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, empty_seq, "IFolderView::GetSpacing, empty", FALSE); 790 791 flush_sequences(sequences, NUM_MSG_SEQUENCES); 792 hr = IFolderView_GetSpacing(fv, &pt); 793 ok(hr == S_OK, "got (0x%08x)\n", hr); 794 /* fails with empty sequence on win7 for unknown reason */ 795 if (sequences[LISTVIEW_SEQ_INDEX]->count) 796 { 797 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_getspacing_seq, "IFolderView::GetSpacing", FALSE); 798 ok(pt.x > 0, "got %d\n", pt.x); 799 ok(pt.y > 0, "got %d\n", pt.y); 800 ret = SendMessageA(hwnd_list, LVM_GETITEMSPACING, 0, 0); 801 ok(pt.x == LOWORD(ret) && pt.y == HIWORD(ret), "got (%d, %d)\n", LOWORD(ret), HIWORD(ret)); 802 } 803 804 /* IFolderView::ItemCount */ 805 if (0) 806 { 807 /* crashes on XP */ 808 IFolderView_ItemCount(fv, SVGIO_ALLVIEW, NULL); 809 } 810 811 flush_sequences(sequences, NUM_MSG_SEQUENCES); 812 IFolderView_ItemCount(fv, SVGIO_ALLVIEW, &count); 813 814 /* IFolderView::GetSelectionMarkedItem */ 815 if (0) 816 { 817 /* crashes on XP */ 818 IFolderView_GetSelectionMarkedItem(fv, NULL); 819 } 820 821 flush_sequences(sequences, NUM_MSG_SEQUENCES); 822 hr = IFolderView_GetSelectionMarkedItem(fv, &ret); 823 if (count) 824 ok(hr == S_OK, "got (0x%08x)\n", hr); 825 else 826 ok(hr == S_FALSE, "got (0x%08x)\n", hr); 827 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_getselectionmarked_seq, 828 "IFolderView::GetSelectionMarkedItem", FALSE); 829 830 /* IFolderView::GetFocusedItem */ 831 flush_sequences(sequences, NUM_MSG_SEQUENCES); 832 hr = IFolderView_GetFocusedItem(fv, &ret); 833 if (count) 834 ok(hr == S_OK, "got (0x%08x)\n", hr); 835 else 836 ok(hr == S_FALSE, "got (0x%08x)\n", hr); 837 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_getfocused_seq, 838 "IFolderView::GetFocusedItem", FALSE); 839 840 /* IFolderView::GetFolder, just return pointer */ 841 if (0) 842 { 843 /* crashes on XP */ 844 IFolderView_GetFolder(fv, NULL, (void**)&folder); 845 IFolderView_GetFolder(fv, NULL, NULL); 846 } 847 848 hr = IFolderView_GetFolder(fv, &IID_IShellFolder, NULL); 849 ok(hr == E_POINTER, "got (0x%08x)\n", hr); 850 851 hr = IFolderView_GetFolder(fv, &IID_IShellFolder, (void**)&folder); 852 ok(hr == S_OK, "got (0x%08x)\n", hr); 853 ok(desktop == folder, "\n"); 854 if (folder) IShellFolder_Release(folder); 855 856 hr = IFolderView_GetFolder(fv, &IID_IUnknown, (void**)&unk); 857 ok(hr == S_OK, "got (0x%08x)\n", hr); 858 if (unk) IUnknown_Release(unk); 859 860 hr = IFolderView_QueryInterface(fv, &IID_IFolderView2, (void**)&fv2); 861 if (hr != S_OK) 862 win_skip("IFolderView2 is not supported.\n"); 863 if (fv2) IFolderView2_Release(fv2); 864 865 hr = IShellView_DestroyViewWindow(view); 866 ok(hr == S_OK, "got (0x%08x)\n", hr); 867 ok(!IsWindow(hwnd_view), "hwnd %p still valid\n", hwnd_view); 868 869 IShellBrowser_Release(browser); 870 IFolderView_Release(fv); 871 IShellView_Release(view); 872 IShellFolder_Release(desktop); 873 } 874 875 static void test_GetItemObject(void) 876 { 877 IShellFolder *desktop; 878 IShellView *view; 879 IUnknown *unk; 880 HRESULT hr; 881 882 hr = SHGetDesktopFolder(&desktop); 883 ok(hr == S_OK, "got (0x%08x)\n", hr); 884 885 hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view); 886 ok(hr == S_OK, "got (0x%08x)\n", hr); 887 888 /* from documentation three interfaces are supported for SVGIO_BACKGROUND: 889 IContextMenu, IDispatch, IPersistHistory */ 890 hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IContextMenu, (void**)&unk); 891 ok(hr == S_OK, "got (0x%08x)\n", hr); 892 IUnknown_Release(unk); 893 894 unk = NULL; 895 hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IDispatch, (void**)&unk); 896 ok(hr == S_OK || broken(hr == E_NOTIMPL) /* NT4 */, "got (0x%08x)\n", hr); 897 if (unk) IUnknown_Release(unk); 898 899 unk = NULL; 900 hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IPersistHistory, (void**)&unk); 901 todo_wine ok(hr == S_OK || broken(hr == E_NOTIMPL) /* W9x, NT4 */, "got (0x%08x)\n", hr); 902 if (unk) IUnknown_Release(unk); 903 904 /* example of unsupported interface, base for IPersistHistory */ 905 hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IPersist, (void**)&unk); 906 ok(hr == E_NOINTERFACE || broken(hr == E_NOTIMPL) /* W2K */, "got (0x%08x)\n", hr); 907 908 IShellView_Release(view); 909 IShellFolder_Release(desktop); 910 } 911 912 static void test_IShellFolderView(void) 913 { 914 IShellFolderView *folderview; 915 IShellFolder *desktop; 916 IShellView *view; 917 IDataObject *obj; 918 UINT i; 919 HRESULT hr; 920 921 hr = SHGetDesktopFolder(&desktop); 922 ok(hr == S_OK, "got (0x%08x)\n", hr); 923 924 hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view); 925 ok(hr == S_OK, "got (0x%08x)\n", hr); 926 927 hr = IShellView_QueryInterface(view, &IID_IShellFolderView, (void**)&folderview); 928 if (hr != S_OK) 929 { 930 win_skip("IShellView doesn't provide IShellFolderView on this platform\n"); 931 IShellView_Release(view); 932 IShellFolder_Release(desktop); 933 return; 934 } 935 936 /* ::MoveIcons */ 937 obj = IDataObjectImpl_Construct(); 938 hr = IShellFolderView_MoveIcons(folderview, obj); 939 ok(hr == E_NOTIMPL || broken(hr == S_OK) /* W98 */, "got (0x%08x)\n", hr); 940 IDataObject_Release(obj); 941 942 /* ::SetRedraw without list created */ 943 hr = IShellFolderView_SetRedraw(folderview, TRUE); 944 ok(hr == S_OK, "got (0x%08x)\n", hr); 945 946 /* ::QuerySupport */ 947 hr = IShellFolderView_QuerySupport(folderview, NULL); 948 ok(hr == S_OK, "got (0x%08x)\n", hr); 949 i = 0xdeadbeef; 950 hr = IShellFolderView_QuerySupport(folderview, &i); 951 ok(hr == S_OK, "got (0x%08x)\n", hr); 952 ok(i == 0xdeadbeef, "got %d\n", i); 953 954 /* ::RemoveObject */ 955 i = 0xdeadbeef; 956 hr = IShellFolderView_RemoveObject(folderview, NULL, &i); 957 ok(hr == S_OK || hr == E_FAIL, "got (0x%08x)\n", hr); 958 if (hr == S_OK) ok(i == 0 || broken(i == 0xdeadbeef) /* Vista, 2k8 */, 959 "got %d\n", i); 960 961 IShellFolderView_Release(folderview); 962 963 IShellView_Release(view); 964 IShellFolder_Release(desktop); 965 } 966 967 static void test_IOleWindow(void) 968 { 969 IShellFolder *desktop; 970 IShellView *view; 971 IOleWindow *wnd; 972 HRESULT hr; 973 974 hr = SHGetDesktopFolder(&desktop); 975 ok(hr == S_OK, "got (0x%08x)\n", hr); 976 977 hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view); 978 ok(hr == S_OK, "got (0x%08x)\n", hr); 979 980 hr = IShellView_QueryInterface(view, &IID_IOleWindow, (void**)&wnd); 981 ok(hr == E_NOINTERFACE, "got (0x%08x)\n", hr); 982 983 /* IShellView::ContextSensitiveHelp */ 984 hr = IShellView_ContextSensitiveHelp(view, TRUE); 985 ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr); 986 hr = IShellView_ContextSensitiveHelp(view, FALSE); 987 ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr); 988 989 IShellView_Release(view); 990 IShellFolder_Release(desktop); 991 } 992 993 static const struct message folderview_setcurrentviewmode1_2_prevista[] = { 994 { LVM_SETVIEW, sent|wparam, LV_VIEW_ICON}, 995 { LVM_SETIMAGELIST, sent|wparam, 0}, 996 { LVM_SETIMAGELIST, sent|wparam, 1}, 997 { 0x105a, sent}, 998 { LVM_SETBKIMAGEW, sent|optional}, /* w2k3 */ 999 { LVM_GETBKCOLOR, sent|optional}, /* w2k3 */ 1000 { LVM_GETTEXTBKCOLOR, sent|optional}, /* w2k3 */ 1001 { LVM_GETTEXTCOLOR, sent|optional}, /* w2k3 */ 1002 { LVM_SETEXTENDEDLISTVIEWSTYLE, sent|optional|wparam, 0xc8}, /* w2k3 */ 1003 { LVM_ARRANGE, sent }, 1004 { LVM_ARRANGE, sent|optional }, /* WinXP */ 1005 { 0 } 1006 }; 1007 1008 static const struct message folderview_setcurrentviewmode3_prevista[] = { 1009 { LVM_SETVIEW, sent|wparam, LV_VIEW_LIST}, 1010 { LVM_SETIMAGELIST, sent|wparam, 0}, 1011 { LVM_SETIMAGELIST, sent|wparam, 1}, 1012 { 0x105a, sent}, 1013 { LVM_SETBKIMAGEW, sent|optional}, /* w2k3 */ 1014 { LVM_GETBKCOLOR, sent|optional}, /* w2k3 */ 1015 { LVM_GETTEXTBKCOLOR, sent|optional}, /* w2k3 */ 1016 { LVM_GETTEXTCOLOR, sent|optional}, /* w2k3 */ 1017 { LVM_SETEXTENDEDLISTVIEWSTYLE, sent|optional|wparam, 0xc8}, /* w2k3 */ 1018 { 0 } 1019 }; 1020 1021 static const struct message folderview_setcurrentviewmode4_prevista[] = { 1022 { LVM_GETHEADER, sent}, 1023 { LVM_GETITEMCOUNT, sent|optional }, 1024 { LVM_SETSELECTEDCOLUMN, sent}, 1025 { WM_NOTIFY, sent }, 1026 { WM_NOTIFY, sent }, 1027 { WM_NOTIFY, sent }, 1028 { WM_NOTIFY, sent }, 1029 { LVM_SETVIEW, sent|wparam, LV_VIEW_DETAILS}, 1030 { LVM_SETIMAGELIST, sent|wparam, 0}, 1031 { LVM_SETIMAGELIST, sent|wparam, 1}, 1032 { 0x105a, sent}, 1033 { LVM_SETBKIMAGEW, sent|optional}, /* w2k3 */ 1034 { LVM_GETBKCOLOR, sent|optional}, /* w2k3 */ 1035 { LVM_GETTEXTBKCOLOR, sent|optional}, /* w2k3 */ 1036 { LVM_GETTEXTCOLOR, sent|optional}, /* w2k3 */ 1037 { LVM_SETEXTENDEDLISTVIEWSTYLE, sent|optional|wparam, 0xc8}, /* w2k3 */ 1038 { 0 } 1039 }; 1040 1041 /* XP, SetCurrentViewMode(5) 1042 108e - LVM_SETVIEW (LV_VIEW_ICON); 1043 1036 - LVM_SETEXTEDEDLISTVIEWSTYLE (0x8000, 0) 1044 100c/104c repeated X times 1045 1003 - LVM_SETIMAGELIST 1046 1035 - LVM_SETICONSPACING 1047 1004 - LVM_GETITEMCOUNT 1048 105a - ? 1049 1016 - LVM_ARRANGE 1050 1016 - LVM_ARRANGE 1051 */ 1052 1053 /* XP, SetCurrentViewMode(6) 1054 1036 - LVM_SETEXTENDEDLISTVIEWSTYLE (0x8000, 0) 1055 1035 - LVM_SETICONSPACING 1056 1003 - LVM_SETIMAGELIST 1057 1003 - LVM_SETIMAGELIST 1058 100c/104c repeated X times 1059 10a2 - LVM_SETTILEVIEWINFO 1060 108e - LVM_SETVIEW (LV_VIEW_TILE) 1061 1003 - LVM_SETIMAGELIST 1062 105a - ? 1063 1016 - LVM_ARRANGE 1064 1016 - LVM_ARRANGE 1065 */ 1066 1067 /* XP, SetCurrentViewMode (7) 1068 10a2 - LVM_SETTILEVIEWINFO 1069 108e - LVM_SETVIEW (LV_VIEW_ICON) 1070 1004/10a4 (LVM_GETITEMCOUNT/LVM_SETTILEINFO) X times 1071 1016 - LVM_ARRANGE 1072 1016 - LVM_ARRANGE 1073 ... 1074 LVM_SETEXTENDEDLISTVIEWSTYLE (0x40000, 0x40000) 1075 ... 1076 LVM_SETEXTENDEDLISTVIEWSTYLE (0x8000, 0x8000) 1077 */ 1078 1079 static void test_GetSetCurrentViewMode(void) 1080 { 1081 IShellFolder *desktop; 1082 IShellView *sview; 1083 IFolderView *fview; 1084 IShellBrowser *browser; 1085 FOLDERSETTINGS fs; 1086 UINT viewmode; 1087 HWND hwnd; 1088 RECT rc = {0, 0, 10, 10}; 1089 HRESULT hr; 1090 UINT i; 1091 static const int winxp_res[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 1092 static const int win2k3_res[11] = {0, 1, 2, 3, 4, 5, 6, 5, 8, 0, 0}; 1093 static const int vista_res[11] = {0, 1, 5, 3, 4, 5, 6, 7, 7, 0, 0}; 1094 static const int win7_res[11] = {1, 1, 1, 3, 4, 1, 6, 1, 8, 8, 8}; 1095 1096 hr = SHGetDesktopFolder(&desktop); 1097 ok(hr == S_OK, "got (0x%08x)\n", hr); 1098 1099 hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&sview); 1100 ok(hr == S_OK, "got (0x%08x)\n", hr); 1101 1102 fs.ViewMode = 1; 1103 fs.fFlags = 0; 1104 browser = IShellBrowserImpl_Construct(); 1105 hr = IShellView_CreateViewWindow(sview, NULL, &fs, browser, &rc, &hwnd); 1106 ok(hr == S_OK || broken(hr == S_FALSE /*Win2k*/ ), "got (0x%08x)\n", hr); 1107 1108 hr = IShellView_QueryInterface(sview, &IID_IFolderView, (void**)&fview); 1109 ok(hr == S_OK || broken(hr == E_NOINTERFACE), "got (0x%08x)\n", hr); 1110 if(SUCCEEDED(hr)) 1111 { 1112 HWND hwnd_lv; 1113 UINT count; 1114 1115 if (0) 1116 { 1117 /* Crashes under Win7/WinXP */ 1118 IFolderView_GetCurrentViewMode(fview, NULL); 1119 } 1120 1121 hr = IFolderView_GetCurrentViewMode(fview, &viewmode); 1122 ok(hr == S_OK, "got (0x%08x)\n", hr); 1123 ok(viewmode == 1, "ViewMode was %d\n", viewmode); 1124 1125 hr = IFolderView_SetCurrentViewMode(fview, FVM_AUTO); 1126 ok(hr == S_OK, "got (0x%08x)\n", hr); 1127 1128 hr = IFolderView_SetCurrentViewMode(fview, 0); 1129 ok(hr == E_INVALIDARG || broken(hr == S_OK), 1130 "got (0x%08x)\n", hr); 1131 1132 hr = IFolderView_GetCurrentViewMode(fview, &viewmode); 1133 ok(hr == S_OK, "got (0x%08x)\n", hr); 1134 1135 for(i = 1; i < 9; i++) 1136 { 1137 hr = IFolderView_SetCurrentViewMode(fview, i); 1138 ok(hr == S_OK || (i == 8 && hr == E_INVALIDARG /*Vista*/), 1139 "(%d) got (0x%08x)\n", i, hr); 1140 1141 hr = IFolderView_GetCurrentViewMode(fview, &viewmode); 1142 ok(hr == S_OK, "(%d) got (0x%08x)\n", i, hr); 1143 1144 /* Wine currently behaves like winxp here. */ 1145 ok((viewmode == win7_res[i]) || (viewmode == vista_res[i]) || 1146 (viewmode == win2k3_res[i]) || (viewmode == winxp_res[i]), 1147 "(%d) got %d\n",i , viewmode); 1148 } 1149 1150 hr = IFolderView_SetCurrentViewMode(fview, 9); 1151 ok(hr == E_INVALIDARG || broken(hr == S_OK), 1152 "got (0x%08x)\n", hr); 1153 1154 /* Test messages */ 1155 hwnd_lv = subclass_listview(hwnd); 1156 ok(hwnd_lv != NULL, "Failed to subclass listview\n"); 1157 if(hwnd_lv) 1158 { 1159 /* Vista seems to set the viewmode by other means than 1160 sending messages. At least no related messages are 1161 captured by subclassing. 1162 */ 1163 BOOL vista_plus = FALSE; 1164 static const UINT vista_plus_msgs[] = { 1165 WM_SETREDRAW, WM_NOTIFY, WM_NOTIFYFORMAT, WM_QUERYUISTATE, 1166 WM_MENUCHAR, WM_WINDOWPOSCHANGING, WM_NCCALCSIZE, WM_WINDOWPOSCHANGED, 1167 WM_PARENTNOTIFY, LVM_GETHEADER, 0 }; 1168 1169 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1170 hr = IFolderView_SetCurrentViewMode(fview, 1); 1171 ok(hr == S_OK, "got 0x%08x\n", hr); 1172 1173 /* WM_SETREDRAW is not sent in versions before Vista. */ 1174 vista_plus = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, WM_SETREDRAW); 1175 if(vista_plus) 1176 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs); 1177 else 1178 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_setcurrentviewmode1_2_prevista, 1179 "IFolderView::SetCurrentViewMode(1)", TRUE); 1180 1181 hr = IFolderView_SetCurrentViewMode(fview, 2); 1182 ok(hr == S_OK, "got 0x%08x\n", hr); 1183 if(vista_plus) 1184 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs); 1185 else 1186 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_setcurrentviewmode1_2_prevista, 1187 "IFolderView::SetCurrentViewMode(2)", TRUE); 1188 1189 hr = IFolderView_SetCurrentViewMode(fview, 3); 1190 ok(hr == S_OK, "got 0x%08x\n", hr); 1191 if(vista_plus) 1192 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs); 1193 else 1194 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_setcurrentviewmode3_prevista, 1195 "IFolderView::SetCurrentViewMode(3)", TRUE); 1196 1197 hr = IFolderView_SetCurrentViewMode(fview, 4); 1198 ok(hr == S_OK, "got 0x%08x\n", hr); 1199 if(vista_plus) 1200 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs); 1201 else 1202 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_setcurrentviewmode4_prevista, 1203 "IFolderView::SetCurrentViewMode(4)", TRUE); 1204 1205 hr = IFolderView_SetCurrentViewMode(fview, 5); 1206 ok(hr == S_OK, "got 0x%08x\n", hr); 1207 todo_wine 1208 { 1209 if(vista_plus) 1210 { 1211 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs); 1212 } 1213 else 1214 { 1215 count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETVIEW); 1216 ok(count == 1, "LVM_SETVIEW sent %d times.\n", count); 1217 count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETEXTENDEDLISTVIEWSTYLE); 1218 ok(count == 1 || count == 2, "LVM_SETEXTENDEDLISTVIEWSTYLE sent %d times.\n", count); 1219 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1220 } 1221 } 1222 1223 hr = IFolderView_SetCurrentViewMode(fview, 6); 1224 ok(hr == S_OK, "got 0x%08x\n", hr); 1225 todo_wine 1226 { 1227 if(vista_plus) 1228 { 1229 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs); 1230 } 1231 else 1232 { 1233 count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETVIEW); 1234 ok(count == 1, "LVM_SETVIEW sent %d times.\n", count); 1235 count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETEXTENDEDLISTVIEWSTYLE); 1236 ok(count == 1 || count == 2, "LVM_SETEXTENDEDLISTVIEWSTYLE sent %d times.\n", count); 1237 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1238 } 1239 } 1240 1241 hr = IFolderView_SetCurrentViewMode(fview, 7); 1242 ok(hr == S_OK, "got 0x%08x\n", hr); 1243 todo_wine 1244 { 1245 if(vista_plus) 1246 { 1247 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs); 1248 } 1249 else 1250 { 1251 count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETVIEW); 1252 ok(count == 1, "LVM_SETVIEW sent %d times.\n", count); 1253 count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETEXTENDEDLISTVIEWSTYLE); 1254 ok(count == 2, "LVM_SETEXTENDEDLISTVIEWSTYLE sent %d times.\n", count); 1255 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1256 } 1257 } 1258 1259 hr = IFolderView_SetCurrentViewMode(fview, 8); 1260 ok(hr == S_OK || broken(hr == E_INVALIDARG /* Vista */), "got 0x%08x\n", hr); 1261 todo_wine 1262 { 1263 if(vista_plus) 1264 { 1265 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs); 1266 } 1267 else 1268 { 1269 count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETVIEW); 1270 ok(count == 1, "LVM_SETVIEW sent %d times.\n", count); 1271 count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETEXTENDEDLISTVIEWSTYLE); 1272 ok(count == 2, "LVM_SETEXTENDEDLISTVIEWSTYLE sent %d times.\n", count); 1273 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1274 } 1275 } 1276 1277 hr = IFolderView_GetCurrentViewMode(fview, &viewmode); 1278 ok(hr == S_OK, "Failed to get current viewmode.\n"); 1279 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, empty_seq, 1280 "IFolderView::GetCurrentViewMode", FALSE); 1281 } 1282 1283 IFolderView_Release(fview); 1284 } 1285 else 1286 { 1287 skip("No IFolderView for the desktop folder.\n"); 1288 } 1289 1290 IShellBrowser_Release(browser); 1291 IShellView_DestroyViewWindow(sview); 1292 IShellView_Release(sview); 1293 IShellFolder_Release(desktop); 1294 } 1295 1296 static void test_IOleCommandTarget(void) 1297 { 1298 IShellFolder *psf_desktop; 1299 IShellView *psv; 1300 IOleCommandTarget *poct; 1301 HRESULT hr; 1302 1303 hr = SHGetDesktopFolder(&psf_desktop); 1304 ok(hr == S_OK, "got (0x%08x)\n", hr); 1305 1306 hr = IShellFolder_CreateViewObject(psf_desktop, NULL, &IID_IShellView, (void**)&psv); 1307 ok(hr == S_OK, "got (0x%08x)\n", hr); 1308 if(SUCCEEDED(hr)) 1309 { 1310 hr = IShellView_QueryInterface(psv, &IID_IOleCommandTarget, (void**)&poct); 1311 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Win95/NT4 */, "Got 0x%08x\n", hr); 1312 if(SUCCEEDED(hr)) 1313 { 1314 OLECMD oc; 1315 1316 hr = IOleCommandTarget_QueryStatus(poct, NULL, 0, NULL, NULL); 1317 ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr); 1318 1319 oc.cmdID = 1; 1320 hr = IOleCommandTarget_QueryStatus(poct, NULL, 0, &oc, NULL); 1321 ok(hr == OLECMDERR_E_UNKNOWNGROUP, "Got 0x%08x\n", hr); 1322 1323 oc.cmdID = 1; 1324 hr = IOleCommandTarget_QueryStatus(poct, NULL, 1, &oc, NULL); 1325 ok(hr == OLECMDERR_E_UNKNOWNGROUP, "Got 0x%08x\n", hr); 1326 1327 hr = IOleCommandTarget_Exec(poct, NULL, 0, 0, NULL, NULL); 1328 ok(hr == OLECMDERR_E_UNKNOWNGROUP, "Got 0x%08x\n", hr); 1329 1330 IOleCommandTarget_Release(poct); 1331 } 1332 1333 IShellView_Release(psv); 1334 } 1335 1336 IShellFolder_Release(psf_desktop); 1337 } 1338 1339 static void test_SHCreateShellFolderView(void) 1340 { 1341 IShellFolder *desktop; 1342 IShellView *psv; 1343 SFV_CREATE sfvc; 1344 ULONG refCount; 1345 IUnknown *unk; 1346 HRESULT hr; 1347 1348 hr = SHGetDesktopFolder(&desktop); 1349 ok(hr == S_OK, "got (0x%08x)\n", hr); 1350 1351 if (0) 1352 { 1353 /* crash on win7 */ 1354 SHCreateShellFolderView(NULL, NULL); 1355 } 1356 1357 psv = (void *)0xdeadbeef; 1358 hr = SHCreateShellFolderView(NULL, &psv); 1359 ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr); 1360 ok(psv == NULL, "psv = %p\n", psv); 1361 1362 memset(&sfvc, 0, sizeof(sfvc)); 1363 psv = (void *)0xdeadbeef; 1364 hr = SHCreateShellFolderView(&sfvc, &psv); 1365 ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr); 1366 ok(psv == NULL, "psv = %p\n", psv); 1367 1368 memset(&sfvc, 0, sizeof(sfvc)); 1369 sfvc.cbSize = sizeof(sfvc) - 1; 1370 psv = (void *)0xdeadbeef; 1371 hr = SHCreateShellFolderView(&sfvc, &psv); 1372 ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr); 1373 ok(psv == NULL, "psv = %p\n", psv); 1374 1375 memset(&sfvc, 0, sizeof(sfvc)); 1376 sfvc.cbSize = sizeof(sfvc) + 1; 1377 psv = (void *)0xdeadbeef; 1378 hr = SHCreateShellFolderView(&sfvc, &psv); 1379 ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr); 1380 ok(psv == NULL, "psv = %p\n", psv); 1381 1382 if (0) 1383 { 1384 /* Crashes on NULL 'pshf' on XP/2k3 */ 1385 memset(&sfvc, 0, sizeof(sfvc)); 1386 sfvc.cbSize = sizeof(sfvc); 1387 psv = (void *)0xdeadbeef; 1388 hr = SHCreateShellFolderView(&sfvc, &psv); 1389 ok(hr == E_UNEXPECTED, "Got 0x%08x\n", hr); 1390 ok(psv == NULL, "psv = %p\n", psv); 1391 } 1392 memset(&sfvc, 0, sizeof(sfvc)); 1393 sfvc.cbSize = sizeof(sfvc) - 1; 1394 sfvc.pshf = desktop; 1395 psv = (void *)0xdeadbeef; 1396 hr = SHCreateShellFolderView(&sfvc, &psv); 1397 ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr); 1398 ok(psv == NULL, "psv = %p\n", psv); 1399 1400 memset(&sfvc, 0, sizeof(sfvc)); 1401 sfvc.cbSize = sizeof(sfvc); 1402 sfvc.pshf = desktop; 1403 psv = NULL; 1404 hr = SHCreateShellFolderView(&sfvc, &psv); 1405 ok(hr == S_OK, "Got 0x%08x\n", hr); 1406 ok(psv != NULL, "psv = %p\n", psv); 1407 1408 hr = IShellView_QueryInterface(psv, &IID_CDefView, (void **)&unk); 1409 ok(hr == S_OK, "got (0x%08x)\n", hr); 1410 ok(unk == (IUnknown *)psv, "got %p\n", unk); 1411 IUnknown_Release(unk); 1412 1413 refCount = IShellView_Release(psv); 1414 ok(refCount == 0, "refCount = %u\n", refCount); 1415 1416 IShellFolder_Release(desktop); 1417 } 1418 1419 static void test_SHCreateShellFolderViewEx(void) 1420 { 1421 IShellFolder *desktop; 1422 IShellView *psv; 1423 ULONG refCount; 1424 IUnknown *unk; 1425 HRESULT hr; 1426 CSFV csfv; 1427 1428 hr = SHGetDesktopFolder(&desktop); 1429 ok(hr == S_OK, "got (0x%08x)\n", hr); 1430 1431 if (0) 1432 { 1433 /* crash on win7 */ 1434 SHCreateShellFolderViewEx(NULL, NULL); 1435 SHCreateShellFolderViewEx(NULL, &psv); 1436 SHCreateShellFolderViewEx(&csfv, NULL); 1437 } 1438 1439 memset(&csfv, 0, sizeof(csfv)); 1440 csfv.pshf = desktop; 1441 psv = NULL; 1442 hr = SHCreateShellFolderViewEx(&csfv, &psv); 1443 ok(hr == S_OK, "Got 0x%08x\n", hr); 1444 ok(psv != NULL, "psv = %p\n", psv); 1445 1446 hr = IShellView_QueryInterface(psv, &IID_CDefView, (void **)&unk); 1447 ok(hr == S_OK, "got (0x%08x)\n", hr); 1448 ok(unk == (IUnknown *)psv, "got %p\n", unk); 1449 IUnknown_Release(unk); 1450 1451 refCount = IShellView_Release(psv); 1452 ok(refCount == 0, "refCount = %u\n", refCount); 1453 1454 if (0) 1455 { 1456 /* Crashes on null shellfolder, on XP/2k3 */ 1457 memset(&csfv, 0, sizeof(csfv)); 1458 csfv.pshf = NULL; 1459 psv = (void *)0xdeadbeef; 1460 hr = SHCreateShellFolderViewEx(&csfv, &psv); 1461 ok(hr == E_UNEXPECTED, "Got 0x%08x\n", hr); 1462 ok(psv == NULL, "psv = %p\n", psv); 1463 } 1464 memset(&csfv, 0, sizeof(csfv)); 1465 csfv.cbSize = sizeof(csfv); 1466 csfv.pshf = desktop; 1467 psv = NULL; 1468 hr = SHCreateShellFolderViewEx(&csfv, &psv); 1469 ok(hr == S_OK, "Got 0x%08x\n", hr); 1470 ok(psv != NULL, "psv = %p\n", psv); 1471 if (psv) 1472 { 1473 refCount = IShellView_Release(psv); 1474 ok(refCount == 0, "refCount = %u\n", refCount); 1475 } 1476 1477 IShellFolder_Release(desktop); 1478 } 1479 1480 static void test_newmenu(void) 1481 { 1482 IUnknown *unk, *unk2; 1483 HRESULT hr; 1484 1485 hr = CoCreateInstance(&CLSID_NewMenu, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk); 1486 todo_wine 1487 ok(hr == S_OK, "Failed to create NewMenu object, hr %#x.\n", hr); 1488 if (hr != S_OK) 1489 { 1490 skip("NewMenu is not supported.\n"); 1491 return; 1492 } 1493 1494 hr = IUnknown_QueryInterface(unk, &IID_IShellExtInit, (void **)&unk2); 1495 ok(hr == S_OK, "Failed to get IShellExtInit, hr %#x.\n", hr); 1496 IUnknown_Release(unk2); 1497 1498 hr = IUnknown_QueryInterface(unk, &IID_IContextMenu3, (void **)&unk2); 1499 ok(hr == S_OK, "Failed to get IContextMenu3, hr %#x.\n", hr); 1500 IUnknown_Release(unk2); 1501 1502 hr = IUnknown_QueryInterface(unk, &IID_IObjectWithSite, (void **)&unk2); 1503 ok(hr == S_OK, "Failed to get IObjectWithSite, hr %#x.\n", hr); 1504 IUnknown_Release(unk2); 1505 1506 IUnknown_Release(unk); 1507 } 1508 1509 START_TEST(shlview) 1510 { 1511 OleInitialize(NULL); 1512 1513 init_msg_sequences(sequences, NUM_MSG_SEQUENCES); 1514 1515 test_CreateViewWindow(); 1516 test_IFolderView(); 1517 test_GetItemObject(); 1518 test_IShellFolderView(); 1519 test_IOleWindow(); 1520 test_GetSetCurrentViewMode(); 1521 test_IOleCommandTarget(); 1522 test_SHCreateShellFolderView(); 1523 test_SHCreateShellFolderViewEx(); 1524 test_newmenu(); 1525 1526 OleUninitialize(); 1527 } 1528