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