wer: Add new stubbed wer.dll.
[wine/hramrach.git] / dlls / shell32 / tests / shlview.c
blob09922522e3191d484fbd0f0f7318d7cbf8a589f3
1 /*
2 * Unit test of the IShellView
4 * Copyright 2010 Nikolay Sivov for CodeWeavers
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.
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.
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
21 #include <stdarg.h>
22 #include <stdio.h>
24 #define COBJMACROS
25 #define CONST_VTABLE
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wtypes.h"
30 #include "shellapi.h"
32 #include "shlguid.h"
33 #include "shlobj.h"
34 #include "shobjidl.h"
35 #include "shlwapi.h"
36 #include "ocidl.h"
37 #include "oleauto.h"
39 #include "initguid.h"
41 #include "wine/test.h"
43 #include "msg.h"
45 #define LISTVIEW_SEQ_INDEX 0
46 #define NUM_MSG_SEQUENCES 1
48 DEFINE_GUID(IID_IPersistHistory, 0x91a565c1, 0xe38f, 0x11d0, 0x94, 0xbf, 0x00, 0xa0, 0xc9, 0x05, 0x5c, 0xbf);
50 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
52 static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
54 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
55 static LONG defwndproc_counter = 0;
56 LRESULT ret;
57 struct message msg;
59 trace("listview: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
61 msg.message = message;
62 msg.flags = sent|wparam|lparam;
63 if (defwndproc_counter) msg.flags |= defwinproc;
64 msg.wParam = wParam;
65 msg.lParam = lParam;
66 add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
68 defwndproc_counter++;
69 ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
70 defwndproc_counter--;
71 return ret;
74 static HWND subclass_listview(HWND hwnd)
76 WNDPROC oldproc;
77 HWND listview;
79 /* listview is a first child */
80 listview = FindWindowExA(hwnd, NULL, WC_LISTVIEWA, NULL);
81 if(!listview)
83 /* .. except for some versions of Windows XP, where things
84 are slightly more complicated. */
85 HWND hwnd_tmp;
86 hwnd_tmp = FindWindowExA(hwnd, NULL, "DUIViewWndClassName", NULL);
87 hwnd_tmp = FindWindowExA(hwnd_tmp, NULL, "DirectUIHWND", NULL);
88 hwnd_tmp = FindWindowExA(hwnd_tmp, NULL, "CtrlNotifySink", NULL);
89 listview = FindWindowExA(hwnd_tmp, NULL, WC_LISTVIEWA, NULL);
92 oldproc = (WNDPROC)SetWindowLongPtrA(listview, GWLP_WNDPROC,
93 (LONG_PTR)listview_subclass_proc);
94 SetWindowLongPtrA(listview, GWLP_USERDATA, (LONG_PTR)oldproc);
96 return listview;
99 static UINT get_msg_count(struct msg_sequence **seq, int sequence_index, UINT message)
101 struct msg_sequence *msg_seq = seq[sequence_index];
102 UINT i, count = 0;
104 for(i = 0; i < msg_seq->count ; i++)
105 if(msg_seq->sequence[i].message == message)
106 count++;
108 return count;
111 /* Checks that every message in the sequence seq is also present in
112 * the UINT array msgs */
113 static void verify_msgs_in_(struct msg_sequence *seq, const UINT *msgs,
114 const char *file, int line)
116 UINT i, j, msg, failcount = 0;
117 for(i = 0; i < seq->count; i++)
119 BOOL found = FALSE;
120 msg = seq->sequence[i].message;
121 for(j = 0; msgs[j] != 0; j++)
122 if(msgs[j] == msg) found = TRUE;
124 if(!found)
126 failcount++;
127 trace("Unexpected message %d\n", msg);
130 ok_(file, line) (!failcount, "%d failures.\n", failcount);
131 flush_sequences(sequences, NUM_MSG_SEQUENCES);
134 #define verify_msgs_in(seq, msgs) \
135 verify_msgs_in_(seq, msgs, __FILE__, __LINE__)
137 /* dummy IDataObject implementation */
138 typedef struct {
139 const IDataObjectVtbl *lpVtbl;
140 LONG ref;
141 } IDataObjectImpl;
143 static const IDataObjectVtbl IDataObjectImpl_Vtbl;
145 static IDataObject* IDataObjectImpl_Construct(void)
147 IDataObjectImpl *obj;
149 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
150 obj->lpVtbl = &IDataObjectImpl_Vtbl;
151 obj->ref = 1;
153 return (IDataObject*)obj;
156 static HRESULT WINAPI IDataObjectImpl_QueryInterface(IDataObject *iface, REFIID riid, void **ppvObj)
158 IDataObjectImpl *This = (IDataObjectImpl *)iface;
160 if (IsEqualIID(riid, &IID_IUnknown) ||
161 IsEqualIID(riid, &IID_IDataObject))
163 *ppvObj = This;
166 if(*ppvObj)
168 IUnknown_AddRef(iface);
169 return S_OK;
172 return E_NOINTERFACE;
175 static ULONG WINAPI IDataObjectImpl_AddRef(IDataObject * iface)
177 IDataObjectImpl *This = (IDataObjectImpl *)iface;
178 return InterlockedIncrement(&This->ref);
181 static ULONG WINAPI IDataObjectImpl_Release(IDataObject * iface)
183 IDataObjectImpl *This = (IDataObjectImpl *)iface;
184 ULONG ref = InterlockedDecrement(&This->ref);
186 if (!ref)
188 HeapFree(GetProcessHeap(), 0, This);
189 return 0;
191 return ref;
194 static HRESULT WINAPI IDataObjectImpl_GetData(IDataObject *iface, FORMATETC *pformat, STGMEDIUM *pmedium)
196 return E_NOTIMPL;
199 static HRESULT WINAPI IDataObjectImpl_GetDataHere(IDataObject *iface, FORMATETC *pformat, STGMEDIUM *pmedium)
201 return E_NOTIMPL;
204 static HRESULT WINAPI IDataObjectImpl_QueryGetData(IDataObject *iface, FORMATETC *pformat)
206 return E_NOTIMPL;
209 static HRESULT WINAPI IDataObjectImpl_GetCanonicalFormatEtc(
210 IDataObject *iface, FORMATETC *pformatIn, FORMATETC *pformatOut)
212 return E_NOTIMPL;
215 static HRESULT WINAPI IDataObjectImpl_SetData(
216 IDataObject *iface, FORMATETC *pformat, STGMEDIUM *pmedium, BOOL release)
218 return E_NOTIMPL;
221 static HRESULT WINAPI IDataObjectImpl_EnumFormatEtc(
222 IDataObject *iface, DWORD direction, IEnumFORMATETC **ppenumFormatEtc)
224 return E_NOTIMPL;
227 static HRESULT WINAPI IDataObjectImpl_DAdvise(
228 IDataObject *iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pSink, DWORD *pConnection)
230 return E_NOTIMPL;
233 static HRESULT WINAPI IDataObjectImpl_DUnadvise(IDataObject *iface, DWORD connection)
235 return E_NOTIMPL;
238 static HRESULT WINAPI IDataObjectImpl_EnumDAdvise(IDataObject *iface, IEnumSTATDATA **ppenumAdvise)
240 return E_NOTIMPL;
243 static const IDataObjectVtbl IDataObjectImpl_Vtbl =
245 IDataObjectImpl_QueryInterface,
246 IDataObjectImpl_AddRef,
247 IDataObjectImpl_Release,
248 IDataObjectImpl_GetData,
249 IDataObjectImpl_GetDataHere,
250 IDataObjectImpl_QueryGetData,
251 IDataObjectImpl_GetCanonicalFormatEtc,
252 IDataObjectImpl_SetData,
253 IDataObjectImpl_EnumFormatEtc,
254 IDataObjectImpl_DAdvise,
255 IDataObjectImpl_DUnadvise,
256 IDataObjectImpl_EnumDAdvise
259 /* dummy IShellBrowser implementation */
260 typedef struct {
261 const IShellBrowserVtbl *lpVtbl;
262 LONG ref;
263 } IShellBrowserImpl;
265 static const IShellBrowserVtbl IShellBrowserImpl_Vtbl;
267 static IShellBrowser* IShellBrowserImpl_Construct(void)
269 IShellBrowserImpl *browser;
271 browser = HeapAlloc(GetProcessHeap(), 0, sizeof(*browser));
272 browser->lpVtbl = &IShellBrowserImpl_Vtbl;
273 browser->ref = 1;
275 return (IShellBrowser*)browser;
278 static HRESULT WINAPI IShellBrowserImpl_QueryInterface(IShellBrowser *iface,
279 REFIID riid,
280 LPVOID *ppvObj)
282 IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
284 *ppvObj = NULL;
286 if(IsEqualIID(riid, &IID_IUnknown) ||
287 IsEqualIID(riid, &IID_IOleWindow) ||
288 IsEqualIID(riid, &IID_IShellBrowser))
290 *ppvObj = This;
293 if(*ppvObj)
295 IUnknown_AddRef(iface);
296 return S_OK;
299 return E_NOINTERFACE;
302 static ULONG WINAPI IShellBrowserImpl_AddRef(IShellBrowser * iface)
304 IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
305 return InterlockedIncrement(&This->ref);
308 static ULONG WINAPI IShellBrowserImpl_Release(IShellBrowser * iface)
310 IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
311 ULONG ref = InterlockedDecrement(&This->ref);
313 if (!ref)
315 HeapFree(GetProcessHeap(), 0, This);
316 return 0;
318 return ref;
321 static HRESULT WINAPI IShellBrowserImpl_GetWindow(IShellBrowser *iface,
322 HWND *phwnd)
324 if (phwnd) *phwnd = GetDesktopWindow();
325 return S_OK;
328 static HRESULT WINAPI IShellBrowserImpl_ContextSensitiveHelp(IShellBrowser *iface,
329 BOOL fEnterMode)
331 return E_NOTIMPL;
334 static HRESULT WINAPI IShellBrowserImpl_BrowseObject(IShellBrowser *iface,
335 LPCITEMIDLIST pidl,
336 UINT wFlags)
338 return E_NOTIMPL;
341 static HRESULT WINAPI IShellBrowserImpl_EnableModelessSB(IShellBrowser *iface,
342 BOOL fEnable)
345 return E_NOTIMPL;
348 static HRESULT WINAPI IShellBrowserImpl_GetControlWindow(IShellBrowser *iface,
349 UINT id,
350 HWND *lphwnd)
353 return E_NOTIMPL;
356 static HRESULT WINAPI IShellBrowserImpl_GetViewStateStream(IShellBrowser *iface,
357 DWORD mode,
358 LPSTREAM *pStrm)
361 return E_NOTIMPL;
364 static HRESULT WINAPI IShellBrowserImpl_InsertMenusSB(IShellBrowser *iface,
365 HMENU hmenuShared,
366 LPOLEMENUGROUPWIDTHS lpMenuWidths)
369 return E_NOTIMPL;
372 static HRESULT WINAPI IShellBrowserImpl_OnViewWindowActive(IShellBrowser *iface,
373 IShellView *ppshv)
376 return E_NOTIMPL;
379 static HRESULT WINAPI IShellBrowserImpl_QueryActiveShellView(IShellBrowser *iface,
380 IShellView **ppshv)
383 return E_NOTIMPL;
386 static HRESULT WINAPI IShellBrowserImpl_RemoveMenusSB(IShellBrowser *iface,
387 HMENU hmenuShared)
390 return E_NOTIMPL;
393 static HRESULT WINAPI IShellBrowserImpl_SendControlMsg(IShellBrowser *iface,
394 UINT id,
395 UINT uMsg,
396 WPARAM wParam,
397 LPARAM lParam,
398 LRESULT *pret)
401 return E_NOTIMPL;
404 static HRESULT WINAPI IShellBrowserImpl_SetMenuSB(IShellBrowser *iface,
405 HMENU hmenuShared,
406 HOLEMENU holemenuReserved,
407 HWND hwndActiveObject)
410 return E_NOTIMPL;
413 static HRESULT WINAPI IShellBrowserImpl_SetStatusTextSB(IShellBrowser *iface,
414 LPCOLESTR lpszStatusText)
417 return E_NOTIMPL;
420 static HRESULT WINAPI IShellBrowserImpl_SetToolbarItems(IShellBrowser *iface,
421 LPTBBUTTON lpButtons,
422 UINT nButtons,
423 UINT uFlags)
426 return E_NOTIMPL;
429 static HRESULT WINAPI IShellBrowserImpl_TranslateAcceleratorSB(IShellBrowser *iface,
430 LPMSG lpmsg,
431 WORD wID)
434 return E_NOTIMPL;
437 static const IShellBrowserVtbl IShellBrowserImpl_Vtbl =
439 IShellBrowserImpl_QueryInterface,
440 IShellBrowserImpl_AddRef,
441 IShellBrowserImpl_Release,
442 IShellBrowserImpl_GetWindow,
443 IShellBrowserImpl_ContextSensitiveHelp,
444 IShellBrowserImpl_InsertMenusSB,
445 IShellBrowserImpl_SetMenuSB,
446 IShellBrowserImpl_RemoveMenusSB,
447 IShellBrowserImpl_SetStatusTextSB,
448 IShellBrowserImpl_EnableModelessSB,
449 IShellBrowserImpl_TranslateAcceleratorSB,
450 IShellBrowserImpl_BrowseObject,
451 IShellBrowserImpl_GetViewStateStream,
452 IShellBrowserImpl_GetControlWindow,
453 IShellBrowserImpl_SendControlMsg,
454 IShellBrowserImpl_QueryActiveShellView,
455 IShellBrowserImpl_OnViewWindowActive,
456 IShellBrowserImpl_SetToolbarItems
459 static const struct message empty_seq[] = {
460 { 0 }
463 static const struct message folderview_getspacing_seq[] = {
464 { LVM_GETITEMSPACING, wparam|sent, FALSE },
465 { 0 }
468 static const struct message folderview_getselectionmarked_seq[] = {
469 { LVM_GETSELECTIONMARK, sent },
470 { 0 }
473 static const struct message folderview_getfocused_seq[] = {
474 { LVM_GETNEXTITEM, sent|wparam|lparam, -1, LVNI_FOCUSED },
475 { 0 }
478 static const struct message folderview_itemcount_seq[] = {
479 { LVM_GETITEMCOUNT, sent },
480 { 0 }
483 static void test_IShellView_CreateViewWindow(void)
485 IShellFolder *desktop;
486 FOLDERSETTINGS settings;
487 IShellView *view;
488 IDropTarget *dt;
489 HWND hwnd_view;
490 HRESULT hr;
491 RECT r = {0};
493 hr = SHGetDesktopFolder(&desktop);
494 ok(hr == S_OK, "got (0x%08x)\n", hr);
496 hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
497 ok(hr == S_OK, "got (0x%08x)\n", hr);
499 if (0)
501 /* crashes on native */
502 hr = IShellView_CreateViewWindow(view, NULL, &settings, NULL, NULL, NULL);
505 settings.ViewMode = FVM_ICON;
506 settings.fFlags = 0;
507 hwnd_view = (HWND)0xdeadbeef;
508 hr = IShellView_CreateViewWindow(view, NULL, &settings, NULL, NULL, &hwnd_view);
509 ok(hr == E_UNEXPECTED, "got (0x%08x)\n", hr);
510 ok(hwnd_view == 0, "got %p\n", hwnd_view);
512 hwnd_view = (HWND)0xdeadbeef;
513 hr = IShellView_CreateViewWindow(view, NULL, &settings, NULL, &r, &hwnd_view);
514 ok(hr == E_UNEXPECTED, "got (0x%08x)\n", hr);
515 ok(hwnd_view == 0, "got %p\n", hwnd_view);
517 /* ::DragLeave without drag operation */
518 hr = IShellView_QueryInterface(view, &IID_IDropTarget, (void**)&dt);
519 ok(hr == S_OK, "got (0x%08x)\n", hr);
520 hr = IDropTarget_DragLeave(dt);
521 ok(hr == S_OK, "got (0x%08x)\n", hr);
522 IDropTarget_Release(dt);
524 IShellView_Release(view);
525 IShellFolder_Release(desktop);
528 static void test_IFolderView(void)
530 IShellFolder *desktop, *folder;
531 FOLDERSETTINGS settings;
532 IShellView *view;
533 IShellBrowser *browser;
534 IFolderView *fv;
535 HWND hwnd_view, hwnd_list;
536 PITEMID_CHILD pidl;
537 HRESULT hr;
538 INT ret;
539 POINT pt;
540 LONG ref1, ref2;
541 RECT r;
543 hr = SHGetDesktopFolder(&desktop);
544 ok(hr == S_OK, "got (0x%08x)\n", hr);
546 hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
547 ok(hr == S_OK, "got (0x%08x)\n", hr);
549 hr = IShellView_QueryInterface(view, &IID_IFolderView, (void**)&fv);
550 if (hr != S_OK)
552 win_skip("IFolderView not supported by desktop folder\n");
553 IShellView_Release(view);
554 IShellFolder_Release(desktop);
555 return;
558 /* call methods before window creation */
559 hr = IFolderView_GetSpacing(fv, NULL);
560 ok(hr == S_FALSE || broken(hr == S_OK) /* win7 */, "got (0x%08x)\n", hr);
562 pidl = (void*)0xdeadbeef;
563 hr = IFolderView_Item(fv, 0, &pidl);
564 ok(hr == E_INVALIDARG || broken(hr == E_FAIL) /* < Vista */, "got (0x%08x)\n", hr);
565 ok(pidl == 0 || broken(pidl == (void*)0xdeadbeef) /* < Vista */, "got %p\n", pidl);
567 if (0)
569 /* crashes on Vista and Win2k8 - List not created yet case */
570 hr = IFolderView_GetSpacing(fv, &pt);
572 /* crashes on XP */
573 hr = IFolderView_GetSelectionMarkedItem(fv, NULL);
574 hr = IFolderView_GetFocusedItem(fv, NULL);
576 /* crashes on Vista+ */
577 hr = IFolderView_Item(fv, 0, NULL);
580 browser = IShellBrowserImpl_Construct();
582 settings.ViewMode = FVM_ICON;
583 settings.fFlags = 0;
584 hwnd_view = (HWND)0xdeadbeef;
585 r.left = r.top = 0;
586 r.right = r.bottom = 100;
587 hr = IShellView_CreateViewWindow(view, NULL, &settings, browser, &r, &hwnd_view);
588 ok(hr == S_OK, "got (0x%08x)\n", hr);
589 ok(IsWindow(hwnd_view), "got %p\n", hwnd_view);
591 hwnd_list = subclass_listview(hwnd_view);
592 if (!hwnd_list)
594 win_skip("Failed to subclass ListView control\n");
595 IShellBrowser_Release(browser);
596 IFolderView_Release(fv);
597 IShellView_Release(view);
598 IShellFolder_Release(desktop);
599 return;
602 /* IFolderView::GetSpacing */
603 flush_sequences(sequences, NUM_MSG_SEQUENCES);
604 hr = IFolderView_GetSpacing(fv, NULL);
605 ok(hr == S_OK, "got (0x%08x)\n", hr);
606 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, empty_seq, "IFolderView::GetSpacing, empty", FALSE);
608 flush_sequences(sequences, NUM_MSG_SEQUENCES);
609 hr = IFolderView_GetSpacing(fv, &pt);
610 ok(hr == S_OK, "got (0x%08x)\n", hr);
611 /* fails with empty sequence on win7 for unknown reason */
612 if (sequences[LISTVIEW_SEQ_INDEX]->count)
614 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_getspacing_seq, "IFolderView::GetSpacing", FALSE);
615 ok(pt.x > 0, "got %d\n", pt.x);
616 ok(pt.y > 0, "got %d\n", pt.y);
617 ret = SendMessageA(hwnd_list, LVM_GETITEMSPACING, 0, 0);
618 ok(pt.x == LOWORD(ret) && pt.y == HIWORD(ret), "got (%d, %d)\n", LOWORD(ret), HIWORD(ret));
621 /* IFolderView::GetSelectionMarkedItem */
622 if (0)
624 /* crashes on XP */
625 hr = IFolderView_GetSelectionMarkedItem(fv, NULL);
628 flush_sequences(sequences, NUM_MSG_SEQUENCES);
629 hr = IFolderView_GetSelectionMarkedItem(fv, &ret);
630 ok(hr == S_OK, "got (0x%08x)\n", hr);
631 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_getselectionmarked_seq,
632 "IFolderView::GetSelectionMarkedItem", FALSE);
634 /* IFolderView::GetFocusedItem */
635 flush_sequences(sequences, NUM_MSG_SEQUENCES);
636 hr = IFolderView_GetFocusedItem(fv, &ret);
637 ok(hr == S_OK, "got (0x%08x)\n", hr);
638 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_getfocused_seq,
639 "IFolderView::GetFocusedItem", FALSE);
641 /* IFolderView::GetFolder, just return pointer */
642 if (0)
644 /* crashes on XP */
645 hr = IFolderView_GetFolder(fv, NULL, (void**)&folder);
646 hr = IFolderView_GetFolder(fv, NULL, NULL);
649 hr = IFolderView_GetFolder(fv, &IID_IShellFolder, NULL);
650 ok(hr == E_POINTER, "got (0x%08x)\n", hr);
652 ref1 = IShellFolder_AddRef(desktop);
653 IShellFolder_Release(desktop);
654 hr = IFolderView_GetFolder(fv, &IID_IShellFolder, (void**)&folder);
655 ok(hr == S_OK, "got (0x%08x)\n", hr);
656 ref2 = IShellFolder_AddRef(desktop);
657 IShellFolder_Release(desktop);
658 ok(ref1 == ref2, "expected same refcount, got %d\n", ref2);
659 ok(desktop == folder, "\n");
661 /* IFolderView::ItemCount */
662 if (0)
664 /* crashes on XP */
665 hr = IFolderView_ItemCount(fv, SVGIO_ALLVIEW, NULL);
668 flush_sequences(sequences, NUM_MSG_SEQUENCES);
669 hr = IFolderView_ItemCount(fv, SVGIO_ALLVIEW, &ret);
670 ok(hr == S_OK, "got (0x%08x)\n", hr);
671 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_itemcount_seq,
672 "IFolderView::ItemCount", FALSE);
674 IShellBrowser_Release(browser);
675 IFolderView_Release(fv);
676 IShellView_Release(view);
677 IShellFolder_Release(desktop);
680 static void test_GetItemObject(void)
682 IShellFolder *desktop;
683 IShellView *view;
684 IUnknown *unk;
685 HRESULT hr;
687 hr = SHGetDesktopFolder(&desktop);
688 ok(hr == S_OK, "got (0x%08x)\n", hr);
690 hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
691 ok(hr == S_OK, "got (0x%08x)\n", hr);
693 /* from documentation three interfaces are supported for SVGIO_BACKGROUND:
694 IContextMenu, IDispatch, IPersistHistory */
695 hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IContextMenu, (void**)&unk);
696 ok(hr == S_OK, "got (0x%08x)\n", hr);
697 IUnknown_Release(unk);
699 unk = NULL;
700 hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IDispatch, (void**)&unk);
701 todo_wine ok(hr == S_OK || broken(hr == E_NOTIMPL) /* NT4 */, "got (0x%08x)\n", hr);
702 if (unk) IUnknown_Release(unk);
704 unk = NULL;
705 hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IPersistHistory, (void**)&unk);
706 todo_wine ok(hr == S_OK || broken(hr == E_NOTIMPL) /* W9x, NT4 */, "got (0x%08x)\n", hr);
707 if (unk) IUnknown_Release(unk);
709 /* example of unsupported interface, base for IPersistHistory */
710 hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IPersist, (void**)&unk);
711 ok(hr == E_NOINTERFACE || broken(hr == E_NOTIMPL) /* W2K */, "got (0x%08x)\n", hr);
713 IShellView_Release(view);
714 IShellFolder_Release(desktop);
717 static void test_IShellFolderView(void)
719 IShellFolderView *folderview;
720 IShellFolder *desktop;
721 IShellView *view;
722 IDataObject *obj;
723 UINT i;
724 HRESULT hr;
726 hr = SHGetDesktopFolder(&desktop);
727 ok(hr == S_OK, "got (0x%08x)\n", hr);
729 hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
730 ok(hr == S_OK, "got (0x%08x)\n", hr);
732 hr = IShellView_QueryInterface(view, &IID_IShellFolderView, (void**)&folderview);
733 if (hr != S_OK)
735 win_skip("IShellView doesn't provide IShellFolderView on this platform\n");
736 IShellView_Release(view);
737 IShellFolder_Release(desktop);
738 return;
741 /* ::MoveIcons */
742 obj = IDataObjectImpl_Construct();
743 hr = IShellFolderView_MoveIcons(folderview, obj);
744 ok(hr == E_NOTIMPL || broken(hr == S_OK) /* W98 */, "got (0x%08x)\n", hr);
745 IDataObject_Release(obj);
747 /* ::SetRedraw without list created */
748 hr = IShellFolderView_SetRedraw(folderview, TRUE);
749 ok(hr == S_OK, "got (0x%08x)\n", hr);
751 /* ::QuerySupport */
752 hr = IShellFolderView_QuerySupport(folderview, NULL);
753 ok(hr == S_OK, "got (0x%08x)\n", hr);
754 i = 0xdeadbeef;
755 hr = IShellFolderView_QuerySupport(folderview, &i);
756 ok(hr == S_OK, "got (0x%08x)\n", hr);
757 ok(i == 0xdeadbeef, "got %d\n", i);
759 /* ::RemoveObject */
760 i = 0xdeadbeef;
761 hr = IShellFolderView_RemoveObject(folderview, NULL, &i);
762 ok(hr == S_OK, "got (0x%08x)\n", hr);
763 ok(i == 0 || i == -1 /* Win7 */ || broken(i == 0xdeadbeef) /* Vista, 2k8 */,
764 "got %d\n", i);
766 IShellFolderView_Release(folderview);
768 IShellView_Release(view);
769 IShellFolder_Release(desktop);
772 static void test_IOleWindow(void)
774 IShellFolder *desktop;
775 IShellView *view;
776 HRESULT hr;
778 hr = SHGetDesktopFolder(&desktop);
779 ok(hr == S_OK, "got (0x%08x)\n", hr);
781 hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
782 ok(hr == S_OK, "got (0x%08x)\n", hr);
784 /* IShellView::ContextSensitiveHelp */
785 hr = IShellView_ContextSensitiveHelp(view, TRUE);
786 ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
787 hr = IShellView_ContextSensitiveHelp(view, FALSE);
788 ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
790 IShellView_Release(view);
791 IShellFolder_Release(desktop);
794 static const struct message folderview_setcurrentviewmode1_2_prevista[] = {
795 { LVM_SETVIEW, sent|wparam, LV_VIEW_ICON},
796 { LVM_SETIMAGELIST, sent|wparam, 0},
797 { LVM_SETIMAGELIST, sent|wparam, 1},
798 { 0x105a, sent},
799 { LVM_SETBKIMAGEW, sent|optional}, /* w2k3 */
800 { LVM_GETBKCOLOR, sent|optional}, /* w2k3 */
801 { LVM_GETTEXTBKCOLOR, sent|optional}, /* w2k3 */
802 { LVM_GETTEXTCOLOR, sent|optional}, /* w2k3 */
803 { LVM_SETEXTENDEDLISTVIEWSTYLE, sent|optional|wparam, 0xc8}, /* w2k3 */
804 { LVM_ARRANGE, sent },
805 { LVM_ARRANGE, sent|optional }, /* WinXP */
806 { 0 }
809 static const struct message folderview_setcurrentviewmode3_prevista[] = {
810 { LVM_SETVIEW, sent|wparam, LV_VIEW_LIST},
811 { LVM_SETIMAGELIST, sent|wparam, 0},
812 { LVM_SETIMAGELIST, sent|wparam, 1},
813 { 0x105a, sent},
814 { LVM_SETBKIMAGEW, sent|optional}, /* w2k3 */
815 { LVM_GETBKCOLOR, sent|optional}, /* w2k3 */
816 { LVM_GETTEXTBKCOLOR, sent|optional}, /* w2k3 */
817 { LVM_GETTEXTCOLOR, sent|optional}, /* w2k3 */
818 { LVM_SETEXTENDEDLISTVIEWSTYLE, sent|optional|wparam, 0xc8}, /* w2k3 */
819 { 0 }
822 static const struct message folderview_setcurrentviewmode4_prevista[] = {
823 { LVM_GETHEADER, sent},
824 { LVM_GETITEMCOUNT, sent},
825 { LVM_SETSELECTEDCOLUMN, sent},
826 { WM_NOTIFY, sent },
827 { WM_NOTIFY, sent },
828 { WM_NOTIFY, sent },
829 { WM_NOTIFY, sent },
830 { LVM_SETVIEW, sent|wparam, LV_VIEW_DETAILS},
831 { LVM_SETIMAGELIST, sent|wparam, 0},
832 { LVM_SETIMAGELIST, sent|wparam, 1},
833 { 0x105a, sent},
834 { LVM_SETBKIMAGEW, sent|optional}, /* w2k3 */
835 { LVM_GETBKCOLOR, sent|optional}, /* w2k3 */
836 { LVM_GETTEXTBKCOLOR, sent|optional}, /* w2k3 */
837 { LVM_GETTEXTCOLOR, sent|optional}, /* w2k3 */
838 { LVM_SETEXTENDEDLISTVIEWSTYLE, sent|optional|wparam, 0xc8}, /* w2k3 */
839 { 0 }
842 /* XP, SetCurrentViewMode(5)
843 108e - LVM_SETVIEW (LV_VIEW_ICON);
844 1036 - LVM_SETEXTEDEDLISTVIEWSTYLE (0x8000, 0)
845 100c/104c repeated X times
846 1003 - LVM_SETIMAGELIST
847 1035 - LVM_SETICONSPACING
848 1004 - LVM_GETITEMCOUNT
849 105a - ?
850 1016 - LVM_ARRANGE
851 1016 - LVM_ARRANGE
854 /* XP, SetCurrentViewMode(6)
855 1036 - LVM_SETEXTENDEDLISTVIEWSTYLE (0x8000, 0)
856 1035 - LVM_SETICONSPACING
857 1003 - LVM_SETIMAGELIST
858 1003 - LVM_SETIMAGELIST
859 100c/104c repeated X times
860 10a2 - LVM_SETTILEVIEWINFO
861 108e - LVM_SETVIEW (LV_VIEW_TILE)
862 1003 - LVM_SETIMAGELIST
863 105a - ?
864 1016 - LVM_ARRANGE
865 1016 - LVM_ARRANGE
868 /* XP, SetCurrentViewMode (7)
869 10a2 - LVM_SETTILEVIEWINFO
870 108e - LVM_SETVIEW (LV_VIEW_ICON)
871 1004/10a4 (LVM_GETITEMCOUNT/LVM_SETTILEINFO) X times
872 1016 - LVM_ARRANGE
873 1016 - LVM_ARRANGE
875 LVM_SETEXTENDEDLISTVIEWSTYLE (0x40000, 0x40000)
877 LVM_SETEXTENDEDLISTVIEWSTYLE (0x8000, 0x8000)
880 static void test_GetSetCurrentViewMode(void)
882 IShellFolder *desktop;
883 IShellView *sview;
884 IFolderView *fview;
885 IShellBrowser *browser;
886 FOLDERSETTINGS fs;
887 UINT viewmode;
888 HWND hwnd;
889 RECT rc = {0, 0, 10, 10};
890 HRESULT hr;
891 UINT i;
892 static const int winxp_res[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
893 static const int win2k3_res[11] = {0, 1, 2, 3, 4, 5, 6, 5, 8, 0, 0};
894 static const int vista_res[11] = {0, 1, 5, 3, 4, 5, 6, 7, 7, 0, 0};
895 static const int win7_res[11] = {1, 1, 1, 3, 4, 1, 6, 1, 8, 8, 8};
897 hr = SHGetDesktopFolder(&desktop);
898 ok(hr == S_OK, "got (0x%08x)\n", hr);
900 hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&sview);
901 ok(hr == S_OK, "got (0x%08x)\n", hr);
903 fs.ViewMode = 1;
904 fs.fFlags = 0;
905 browser = IShellBrowserImpl_Construct();
906 hr = IShellView_CreateViewWindow(sview, NULL, &fs, browser, &rc, &hwnd);
907 ok(hr == S_OK || broken(hr == S_FALSE /*Win2k*/ ), "got (0x%08x)\n", hr);
909 hr = IShellView_QueryInterface(sview, &IID_IFolderView, (void**)&fview);
910 ok(hr == S_OK || broken(hr == E_NOINTERFACE), "got (0x%08x)\n", hr);
911 if(SUCCEEDED(hr))
913 HWND hwnd_lv;
914 UINT count;
916 if(0)
918 /* Crashes under Win7/WinXP */
919 hr = IFolderView_GetCurrentViewMode(fview, NULL);
922 hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
923 ok(hr == S_OK, "got (0x%08x)\n", hr);
924 ok(viewmode == 1, "ViewMode was %d\n", viewmode);
926 hr = IFolderView_SetCurrentViewMode(fview, FVM_AUTO);
927 ok(hr == S_OK, "got (0x%08x)\n", hr);
929 hr = IFolderView_SetCurrentViewMode(fview, 0);
930 ok(hr == E_INVALIDARG || broken(hr == S_OK),
931 "got (0x%08x)\n", hr);
933 hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
934 ok(hr == S_OK, "got (0x%08x)\n", hr);
936 for(i = 1; i < 9; i++)
938 hr = IFolderView_SetCurrentViewMode(fview, i);
939 ok(hr == S_OK || (i == 8 && hr == E_INVALIDARG /*Vista*/),
940 "(%d) got (0x%08x)\n", i, hr);
942 hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
943 ok(hr == S_OK, "(%d) got (0x%08x)\n", i, hr);
945 /* Wine currently behaves like winxp here. */
946 ok((viewmode == win7_res[i]) || (viewmode == vista_res[i]) ||
947 (viewmode == win2k3_res[i]) || (viewmode == winxp_res[i]),
948 "(%d) got %d\n",i , viewmode);
951 hr = IFolderView_SetCurrentViewMode(fview, 9);
952 ok(hr == E_INVALIDARG || broken(hr == S_OK),
953 "got (0x%08x)\n", hr);
955 /* Test messages */
956 hwnd_lv = subclass_listview(hwnd);
957 ok(hwnd_lv != NULL, "Failed to subclass listview\n");
958 if(hwnd_lv)
960 /* Vista seems to set the viewmode by other means than
961 sending messages. At least no related messages are
962 captured by subclassing.
964 BOOL vista_plus = FALSE;
965 static const UINT vista_plus_msgs[] = {
966 WM_SETREDRAW, WM_NOTIFY, WM_NOTIFYFORMAT, WM_QUERYUISTATE,
967 WM_MENUCHAR, WM_WINDOWPOSCHANGING, WM_NCCALCSIZE, WM_WINDOWPOSCHANGED,
968 WM_PARENTNOTIFY, LVM_GETHEADER, 0 };
970 flush_sequences(sequences, NUM_MSG_SEQUENCES);
971 hr = IFolderView_SetCurrentViewMode(fview, 1);
972 ok(hr == S_OK, "got 0x%08x\n", hr);
974 /* WM_SETREDRAW is not sent in versions before Vista. */
975 vista_plus = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, WM_SETREDRAW);
976 if(vista_plus)
977 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
978 else
979 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_setcurrentviewmode1_2_prevista,
980 "IFolderView::SetCurrentViewMode(1)", TRUE);
982 hr = IFolderView_SetCurrentViewMode(fview, 2);
983 ok(hr == S_OK, "got 0x%08x\n", hr);
984 if(vista_plus)
985 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
986 else
987 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_setcurrentviewmode1_2_prevista,
988 "IFolderView::SetCurrentViewMode(2)", TRUE);
990 hr = IFolderView_SetCurrentViewMode(fview, 3);
991 ok(hr == S_OK, "got 0x%08x\n", hr);
992 if(vista_plus)
993 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
994 else
995 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_setcurrentviewmode3_prevista,
996 "IFolderView::SetCurrentViewMode(3)", TRUE);
998 hr = IFolderView_SetCurrentViewMode(fview, 4);
999 ok(hr == S_OK, "got 0x%08x\n", hr);
1000 if(vista_plus)
1001 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
1002 else
1003 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_setcurrentviewmode4_prevista,
1004 "IFolderView::SetCurrentViewMode(4)", TRUE);
1006 hr = IFolderView_SetCurrentViewMode(fview, 5);
1007 ok(hr == S_OK, "got 0x%08x\n", hr);
1008 todo_wine
1010 if(vista_plus)
1012 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
1014 else
1016 count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETVIEW);
1017 ok(count == 1, "LVM_SETVIEW sent %d times.\n", count);
1018 count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETEXTENDEDLISTVIEWSTYLE);
1019 ok(count == 1 || count == 2, "LVM_SETEXTENDEDLISTVIEWSTYLE sent %d times.\n", count);
1020 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1024 hr = IFolderView_SetCurrentViewMode(fview, 6);
1025 ok(hr == S_OK, "got 0x%08x\n", hr);
1026 todo_wine
1028 if(vista_plus)
1030 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
1032 else
1034 count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETVIEW);
1035 ok(count == 1, "LVM_SETVIEW sent %d times.\n", count);
1036 count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETEXTENDEDLISTVIEWSTYLE);
1037 ok(count == 1 || count == 2, "LVM_SETEXTENDEDLISTVIEWSTYLE sent %d times.\n", count);
1038 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1042 hr = IFolderView_SetCurrentViewMode(fview, 7);
1043 ok(hr == S_OK, "got 0x%08x\n", hr);
1044 todo_wine
1046 if(vista_plus)
1048 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
1050 else
1052 count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETVIEW);
1053 ok(count == 1, "LVM_SETVIEW sent %d times.\n", count);
1054 count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETEXTENDEDLISTVIEWSTYLE);
1055 ok(count == 2, "LVM_SETEXTENDEDLISTVIEWSTYLE sent %d times.\n", count);
1056 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1060 hr = IFolderView_SetCurrentViewMode(fview, 8);
1061 ok(hr == S_OK || broken(hr == E_INVALIDARG /* Vista */), "got 0x%08x\n", hr);
1062 todo_wine
1064 if(vista_plus)
1066 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
1068 else
1070 count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETVIEW);
1071 ok(count == 1, "LVM_SETVIEW sent %d times.\n", count);
1072 count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETEXTENDEDLISTVIEWSTYLE);
1073 ok(count == 2, "LVM_SETEXTENDEDLISTVIEWSTYLE sent %d times.\n", count);
1074 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1078 hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
1079 ok(hr == S_OK, "Failed to get current viewmode.\n");
1080 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, empty_seq,
1081 "IFolderView::GetCurrentViewMode", FALSE);
1084 IFolderView_Release(fview);
1086 else
1088 skip("No IFolderView for the desktop folder.\n");
1091 IShellView_DestroyViewWindow(sview);
1092 IShellView_Release(sview);
1093 IShellFolder_Release(desktop);
1096 START_TEST(shlview)
1098 OleInitialize(NULL);
1100 init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
1102 test_IShellView_CreateViewWindow();
1103 test_IFolderView();
1104 test_GetItemObject();
1105 test_IShellFolderView();
1106 test_IOleWindow();
1107 test_GetSetCurrentViewMode();
1109 OleUninitialize();