include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / shell32 / tests / shlview.c
blob2cacc3b8f87539fe18790a852bc635d3a0de0c3e
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 struct message msg = { 0 };
57 LRESULT ret;
59 msg.message = message;
60 msg.flags = sent|wparam|lparam;
61 if (defwndproc_counter) msg.flags |= defwinproc;
62 msg.wParam = wParam;
63 msg.lParam = lParam;
64 add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
66 defwndproc_counter++;
67 ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
68 defwndproc_counter--;
69 return ret;
72 static HWND subclass_listview(HWND hwnd)
74 WNDPROC oldproc;
75 HWND listview;
77 /* listview is a first child */
78 listview = FindWindowExA(hwnd, NULL, WC_LISTVIEWA, NULL);
79 if(!listview)
81 /* .. except for some versions of Windows XP, where things
82 are slightly more complicated. */
83 HWND hwnd_tmp;
84 hwnd_tmp = FindWindowExA(hwnd, NULL, "DUIViewWndClassName", NULL);
85 hwnd_tmp = FindWindowExA(hwnd_tmp, NULL, "DirectUIHWND", NULL);
86 hwnd_tmp = FindWindowExA(hwnd_tmp, NULL, "CtrlNotifySink", NULL);
87 listview = FindWindowExA(hwnd_tmp, NULL, WC_LISTVIEWA, NULL);
90 oldproc = (WNDPROC)SetWindowLongPtrA(listview, GWLP_WNDPROC,
91 (LONG_PTR)listview_subclass_proc);
92 SetWindowLongPtrA(listview, GWLP_USERDATA, (LONG_PTR)oldproc);
94 return listview;
97 static UINT get_msg_count(struct msg_sequence **seq, int sequence_index, UINT message)
99 struct msg_sequence *msg_seq = seq[sequence_index];
100 UINT i, count = 0;
102 for(i = 0; i < msg_seq->count ; i++)
103 if(msg_seq->sequence[i].message == message)
104 count++;
106 return count;
109 /* Checks that every message in the sequence seq is also present in
110 * the UINT array msgs */
111 static void verify_msgs_in_(struct msg_sequence *seq, const UINT *msgs,
112 const char *file, int line)
114 UINT i, j, msg, failcount = 0;
115 for(i = 0; i < seq->count; i++)
117 BOOL found = FALSE;
118 msg = seq->sequence[i].message;
119 for(j = 0; msgs[j] != 0; j++)
120 if(msgs[j] == msg) found = TRUE;
122 if(!found)
124 failcount++;
125 trace("Unexpected message %d\n", msg);
128 ok_(file, line) (!failcount, "%d failures.\n", failcount);
129 flush_sequences(sequences, NUM_MSG_SEQUENCES);
132 #define verify_msgs_in(seq, msgs) \
133 verify_msgs_in_(seq, msgs, __FILE__, __LINE__)
135 /* dummy IDataObject implementation */
136 typedef struct {
137 IDataObject IDataObject_iface;
138 LONG ref;
139 } IDataObjectImpl;
141 static const IDataObjectVtbl IDataObjectImpl_Vtbl;
143 static inline IDataObjectImpl *impl_from_IDataObject(IDataObject *iface)
145 return CONTAINING_RECORD(iface, IDataObjectImpl, IDataObject_iface);
148 static IDataObject* IDataObjectImpl_Construct(void)
150 IDataObjectImpl *obj;
152 obj = malloc(sizeof(*obj));
153 obj->IDataObject_iface.lpVtbl = &IDataObjectImpl_Vtbl;
154 obj->ref = 1;
156 return &obj->IDataObject_iface;
159 static HRESULT WINAPI IDataObjectImpl_QueryInterface(IDataObject *iface, REFIID riid, void **ppvObj)
161 IDataObjectImpl *This = impl_from_IDataObject(iface);
163 if (IsEqualIID(riid, &IID_IUnknown) ||
164 IsEqualIID(riid, &IID_IDataObject))
166 *ppvObj = &This->IDataObject_iface;
169 if(*ppvObj)
171 IDataObject_AddRef(iface);
172 return S_OK;
175 return E_NOINTERFACE;
178 static ULONG WINAPI IDataObjectImpl_AddRef(IDataObject * iface)
180 IDataObjectImpl *This = impl_from_IDataObject(iface);
181 return InterlockedIncrement(&This->ref);
184 static ULONG WINAPI IDataObjectImpl_Release(IDataObject * iface)
186 IDataObjectImpl *This = impl_from_IDataObject(iface);
187 ULONG ref = InterlockedDecrement(&This->ref);
189 if (!ref)
190 free(This);
192 return ref;
195 static HRESULT WINAPI IDataObjectImpl_GetData(IDataObject *iface, FORMATETC *pformat, STGMEDIUM *pmedium)
197 return E_NOTIMPL;
200 static HRESULT WINAPI IDataObjectImpl_GetDataHere(IDataObject *iface, FORMATETC *pformat, STGMEDIUM *pmedium)
202 return E_NOTIMPL;
205 static HRESULT WINAPI IDataObjectImpl_QueryGetData(IDataObject *iface, FORMATETC *pformat)
207 return E_NOTIMPL;
210 static HRESULT WINAPI IDataObjectImpl_GetCanonicalFormatEtc(
211 IDataObject *iface, FORMATETC *pformatIn, FORMATETC *pformatOut)
213 return E_NOTIMPL;
216 static HRESULT WINAPI IDataObjectImpl_SetData(
217 IDataObject *iface, FORMATETC *pformat, STGMEDIUM *pmedium, BOOL release)
219 return E_NOTIMPL;
222 static HRESULT WINAPI IDataObjectImpl_EnumFormatEtc(
223 IDataObject *iface, DWORD direction, IEnumFORMATETC **ppenumFormatEtc)
225 return E_NOTIMPL;
228 static HRESULT WINAPI IDataObjectImpl_DAdvise(
229 IDataObject *iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pSink, DWORD *pConnection)
231 return E_NOTIMPL;
234 static HRESULT WINAPI IDataObjectImpl_DUnadvise(IDataObject *iface, DWORD connection)
236 return E_NOTIMPL;
239 static HRESULT WINAPI IDataObjectImpl_EnumDAdvise(IDataObject *iface, IEnumSTATDATA **ppenumAdvise)
241 return E_NOTIMPL;
244 static const IDataObjectVtbl IDataObjectImpl_Vtbl =
246 IDataObjectImpl_QueryInterface,
247 IDataObjectImpl_AddRef,
248 IDataObjectImpl_Release,
249 IDataObjectImpl_GetData,
250 IDataObjectImpl_GetDataHere,
251 IDataObjectImpl_QueryGetData,
252 IDataObjectImpl_GetCanonicalFormatEtc,
253 IDataObjectImpl_SetData,
254 IDataObjectImpl_EnumFormatEtc,
255 IDataObjectImpl_DAdvise,
256 IDataObjectImpl_DUnadvise,
257 IDataObjectImpl_EnumDAdvise
260 /* dummy IShellBrowser implementation */
261 typedef struct {
262 IShellBrowser IShellBrowser_iface;
263 LONG ref;
264 } IShellBrowserImpl;
266 static const IShellBrowserVtbl IShellBrowserImpl_Vtbl;
268 static inline IShellBrowserImpl *impl_from_IShellBrowser(IShellBrowser *iface)
270 return CONTAINING_RECORD(iface, IShellBrowserImpl, IShellBrowser_iface);
273 static IShellBrowser* IShellBrowserImpl_Construct(void)
275 IShellBrowserImpl *browser;
277 browser = malloc(sizeof(*browser));
278 browser->IShellBrowser_iface.lpVtbl = &IShellBrowserImpl_Vtbl;
279 browser->ref = 1;
281 return &browser->IShellBrowser_iface;
284 static HRESULT WINAPI IShellBrowserImpl_QueryInterface(IShellBrowser *iface,
285 REFIID riid,
286 LPVOID *ppvObj)
288 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
290 *ppvObj = NULL;
292 if(IsEqualIID(riid, &IID_IUnknown) ||
293 IsEqualIID(riid, &IID_IOleWindow) ||
294 IsEqualIID(riid, &IID_IShellBrowser))
296 *ppvObj = &This->IShellBrowser_iface;
299 if(*ppvObj)
301 IShellBrowser_AddRef(iface);
302 return S_OK;
305 return E_NOINTERFACE;
308 static ULONG WINAPI IShellBrowserImpl_AddRef(IShellBrowser * iface)
310 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
311 return InterlockedIncrement(&This->ref);
314 static ULONG WINAPI IShellBrowserImpl_Release(IShellBrowser * iface)
316 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
317 ULONG ref = InterlockedDecrement(&This->ref);
319 if (!ref)
320 free(This);
322 return ref;
325 static HRESULT WINAPI IShellBrowserImpl_GetWindow(IShellBrowser *iface,
326 HWND *phwnd)
328 if (phwnd) *phwnd = GetDesktopWindow();
329 return S_OK;
332 static HRESULT WINAPI IShellBrowserImpl_ContextSensitiveHelp(IShellBrowser *iface,
333 BOOL fEnterMode)
335 return E_NOTIMPL;
338 static HRESULT WINAPI IShellBrowserImpl_BrowseObject(IShellBrowser *iface,
339 LPCITEMIDLIST pidl,
340 UINT wFlags)
342 return E_NOTIMPL;
345 static HRESULT WINAPI IShellBrowserImpl_EnableModelessSB(IShellBrowser *iface,
346 BOOL fEnable)
349 return E_NOTIMPL;
352 static HRESULT WINAPI IShellBrowserImpl_GetControlWindow(IShellBrowser *iface,
353 UINT id,
354 HWND *lphwnd)
357 return E_NOTIMPL;
360 static HRESULT WINAPI IShellBrowserImpl_GetViewStateStream(IShellBrowser *iface,
361 DWORD mode,
362 LPSTREAM *pStrm)
365 return E_NOTIMPL;
368 static HRESULT WINAPI IShellBrowserImpl_InsertMenusSB(IShellBrowser *iface,
369 HMENU hmenuShared,
370 LPOLEMENUGROUPWIDTHS lpMenuWidths)
373 return E_NOTIMPL;
376 static HRESULT WINAPI IShellBrowserImpl_OnViewWindowActive(IShellBrowser *iface,
377 IShellView *ppshv)
380 return E_NOTIMPL;
383 static HRESULT WINAPI IShellBrowserImpl_QueryActiveShellView(IShellBrowser *iface,
384 IShellView **ppshv)
387 return E_NOTIMPL;
390 static HRESULT WINAPI IShellBrowserImpl_RemoveMenusSB(IShellBrowser *iface,
391 HMENU hmenuShared)
394 return E_NOTIMPL;
397 static HRESULT WINAPI IShellBrowserImpl_SendControlMsg(IShellBrowser *iface,
398 UINT id,
399 UINT uMsg,
400 WPARAM wParam,
401 LPARAM lParam,
402 LRESULT *pret)
405 return E_NOTIMPL;
408 static HRESULT WINAPI IShellBrowserImpl_SetMenuSB(IShellBrowser *iface,
409 HMENU hmenuShared,
410 HOLEMENU holemenuReserved,
411 HWND hwndActiveObject)
414 return E_NOTIMPL;
417 static HRESULT WINAPI IShellBrowserImpl_SetStatusTextSB(IShellBrowser *iface,
418 LPCOLESTR lpszStatusText)
421 return E_NOTIMPL;
424 static HRESULT WINAPI IShellBrowserImpl_SetToolbarItems(IShellBrowser *iface,
425 LPTBBUTTON lpButtons,
426 UINT nButtons,
427 UINT uFlags)
430 return E_NOTIMPL;
433 static HRESULT WINAPI IShellBrowserImpl_TranslateAcceleratorSB(IShellBrowser *iface,
434 LPMSG lpmsg,
435 WORD wID)
438 return E_NOTIMPL;
441 static const IShellBrowserVtbl IShellBrowserImpl_Vtbl =
443 IShellBrowserImpl_QueryInterface,
444 IShellBrowserImpl_AddRef,
445 IShellBrowserImpl_Release,
446 IShellBrowserImpl_GetWindow,
447 IShellBrowserImpl_ContextSensitiveHelp,
448 IShellBrowserImpl_InsertMenusSB,
449 IShellBrowserImpl_SetMenuSB,
450 IShellBrowserImpl_RemoveMenusSB,
451 IShellBrowserImpl_SetStatusTextSB,
452 IShellBrowserImpl_EnableModelessSB,
453 IShellBrowserImpl_TranslateAcceleratorSB,
454 IShellBrowserImpl_BrowseObject,
455 IShellBrowserImpl_GetViewStateStream,
456 IShellBrowserImpl_GetControlWindow,
457 IShellBrowserImpl_SendControlMsg,
458 IShellBrowserImpl_QueryActiveShellView,
459 IShellBrowserImpl_OnViewWindowActive,
460 IShellBrowserImpl_SetToolbarItems
463 static const struct message empty_seq[] = {
464 { 0 }
467 static const struct message folderview_getspacing_seq[] = {
468 { LVM_GETITEMSPACING, wparam|sent, FALSE },
469 { 0 }
472 static const struct message folderview_getselectionmarked_seq[] = {
473 { LVM_GETSELECTIONMARK, sent },
474 { 0 }
477 static const struct message folderview_getfocused_seq[] = {
478 { LVM_GETNEXTITEM, sent|wparam|lparam|optional, -1, LVNI_FOCUSED },
479 { 0 }
482 static HRESULT WINAPI shellbrowser_QueryInterface(IShellBrowser *iface, REFIID riid, void **ppv)
484 *ppv = NULL;
486 if (IsEqualGUID(&IID_IShellBrowser, riid) ||
487 IsEqualGUID(&IID_IOleWindow, riid) ||
488 IsEqualGUID(&IID_IUnknown, riid))
490 *ppv = iface;
493 if (*ppv)
495 IUnknown_AddRef((IUnknown*)*ppv);
496 return S_OK;
499 return E_NOINTERFACE;
502 static ULONG WINAPI shellbrowser_AddRef(IShellBrowser *iface)
504 return 2;
507 static ULONG WINAPI shellbrowser_Release(IShellBrowser *iface)
509 return 1;
512 static HRESULT WINAPI shellbrowser_GetWindow(IShellBrowser *iface, HWND *phwnd)
514 *phwnd = GetDesktopWindow();
515 return S_OK;
518 static HRESULT WINAPI shellbrowser_ContextSensitiveHelp(IShellBrowser *iface, BOOL mode)
520 ok(0, "unexpected\n");
521 return E_NOTIMPL;
524 static HRESULT WINAPI shellbrowser_InsertMenusSB(IShellBrowser *iface, HMENU hmenuShared,
525 OLEMENUGROUPWIDTHS *menuwidths)
527 return E_NOTIMPL;
530 static HRESULT WINAPI shellbrowser_SetMenuSB(IShellBrowser *iface, HMENU hmenuShared,
531 HOLEMENU holemenuReserved, HWND hwndActiveObject)
533 return E_NOTIMPL;
536 static HRESULT WINAPI shellbrowser_RemoveMenusSB(IShellBrowser *iface, HMENU hmenuShared)
538 return E_NOTIMPL;
541 static HRESULT WINAPI shellbrowser_SetStatusTextSB(IShellBrowser *iface, LPCOLESTR text)
543 ok(0, "unexpected\n");
544 return E_NOTIMPL;
547 static HRESULT WINAPI shellbrowser_EnableModelessSB(IShellBrowser *iface, BOOL enable)
549 ok(0, "unexpected\n");
550 return E_NOTIMPL;
553 static HRESULT WINAPI shellbrowser_TranslateAcceleratorSB(IShellBrowser *iface, MSG *pmsg, WORD wID)
555 ok(0, "unexpected\n");
556 return E_NOTIMPL;
559 static HRESULT WINAPI shellbrowser_BrowseObject(IShellBrowser *iface, LPCITEMIDLIST pidl, UINT flags)
561 ok(0, "unexpected\n");
562 return E_NOTIMPL;
565 static HRESULT WINAPI shellbrowser_GetViewStateStream(IShellBrowser *iface, DWORD mode, IStream **stream)
567 return E_NOTIMPL;
570 static HRESULT WINAPI shellbrowser_GetControlWindow(IShellBrowser *iface, UINT id, HWND *phwnd)
572 return E_NOTIMPL;
575 static HRESULT WINAPI shellbrowser_SendControlMsg(IShellBrowser *iface, UINT id, UINT uMsg,
576 WPARAM wParam, LPARAM lParam, LRESULT *pret)
578 return E_NOTIMPL;
581 static HRESULT WINAPI shellbrowser_QueryActiveShellView(IShellBrowser *iface, IShellView **view)
583 ok(0, "unexpected\n");
584 return E_NOTIMPL;
587 static HRESULT WINAPI shellbrowser_OnViewWindowActive(IShellBrowser *iface, IShellView *view)
589 ok(0, "unexpected\n");
590 return E_NOTIMPL;
593 static HRESULT WINAPI shellbrowser_SetToolbarItems(IShellBrowser *iface, LPTBBUTTONSB buttons,
594 UINT count, UINT flags)
596 return E_NOTIMPL;
599 static const IShellBrowserVtbl shellbrowservtbl = {
600 shellbrowser_QueryInterface,
601 shellbrowser_AddRef,
602 shellbrowser_Release,
603 shellbrowser_GetWindow,
604 shellbrowser_ContextSensitiveHelp,
605 shellbrowser_InsertMenusSB,
606 shellbrowser_SetMenuSB,
607 shellbrowser_RemoveMenusSB,
608 shellbrowser_SetStatusTextSB,
609 shellbrowser_EnableModelessSB,
610 shellbrowser_TranslateAcceleratorSB,
611 shellbrowser_BrowseObject,
612 shellbrowser_GetViewStateStream,
613 shellbrowser_GetControlWindow,
614 shellbrowser_SendControlMsg,
615 shellbrowser_QueryActiveShellView,
616 shellbrowser_OnViewWindowActive,
617 shellbrowser_SetToolbarItems
620 static IShellBrowser test_shellbrowser = { &shellbrowservtbl };
622 static void create_interfaces(IShellFolder **desktop, IShellView **view)
624 HRESULT hr;
626 hr = SHGetDesktopFolder(desktop);
627 ok(hr == S_OK, "Got hr %#lx.\n", hr);
628 hr = IShellFolder_CreateViewObject(*desktop, NULL, &IID_IShellView, (void **)view);
629 ok(hr == S_OK, "Got hr %#lx.\n", hr);
632 static void destroy_interfaces(IShellFolder *desktop, IShellView *view)
634 IShellFolder_Release(desktop);
635 IShellView_Release(view);
638 static void test_CreateViewWindow(void)
640 IShellFolder *desktop;
641 HWND hwnd_view, hwnd2;
642 FOLDERSETTINGS settings;
643 IShellView *view;
644 IDropTarget *dt;
645 HRESULT hr;
646 RECT r = {0};
647 ULONG ref1, ref2;
648 IUnknown *unk;
650 create_interfaces(&desktop, &view);
652 hr = IShellView_QueryInterface(view, &IID_CDefView, (void **)&unk);
653 ok(hr == S_OK, "got (0x%08lx)\n", hr);
654 ok(unk == (IUnknown *)view, "got %p\n", unk);
655 IUnknown_Release(unk);
657 if (0)
659 /* crashes on native */
660 IShellView_CreateViewWindow(view, NULL, &settings, NULL, NULL, NULL);
663 settings.ViewMode = FVM_ICON;
664 settings.fFlags = 0;
665 hwnd_view = (HWND)0xdeadbeef;
666 hr = IShellView_CreateViewWindow(view, NULL, &settings, NULL, NULL, &hwnd_view);
667 ok(hr == E_UNEXPECTED, "got (0x%08lx)\n", hr);
668 ok(hwnd_view == 0, "got %p\n", hwnd_view);
670 hwnd_view = (HWND)0xdeadbeef;
671 hr = IShellView_CreateViewWindow(view, NULL, &settings, NULL, &r, &hwnd_view);
672 ok(hr == E_UNEXPECTED, "got (0x%08lx)\n", hr);
673 ok(hwnd_view == 0, "got %p\n", hwnd_view);
675 hwnd_view = NULL;
676 hr = IShellView_CreateViewWindow(view, NULL, &settings, &test_shellbrowser, &r, &hwnd_view);
677 ok(hr == S_OK || broken(hr == S_FALSE), "got (0x%08lx)\n", hr);
678 ok(hwnd_view != 0, "got %p\n", hwnd_view);
680 hwnd2 = (HWND)0xdeadbeef;
681 hr = IShellView_CreateViewWindow(view, NULL, &settings, &test_shellbrowser, &r, &hwnd2);
682 ok(hr == E_UNEXPECTED, "got (0x%08lx)\n", hr);
683 ok(hwnd2 == NULL, "got %p\n", hwnd2);
685 /* ::DragLeave without drag operation */
686 hr = IShellView_QueryInterface(view, &IID_IDropTarget, (void**)&dt);
687 ok(hr == S_OK, "got (0x%08lx)\n", hr);
688 hr = IDropTarget_DragLeave(dt);
689 ok(hr == S_OK, "got (0x%08lx)\n", hr);
690 IDropTarget_Release(dt);
692 IShellView_AddRef(view);
693 ref1 = IShellView_Release(view);
694 hr = IShellView_DestroyViewWindow(view);
695 ok(hr == S_OK, "got (0x%08lx)\n", hr);
696 ok(!IsWindow(hwnd_view), "hwnd %p still valid\n", hwnd_view);
697 ref2 = IShellView_Release(view);
698 ok(ref1 > ref2, "expected %lu > %lu\n", ref1, ref2);
699 ref1 = ref2;
701 /* Show that releasing the shell view does not destroy the window */
702 hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
703 ok(hr == S_OK, "got (0x%08lx)\n", hr);
704 hwnd_view = NULL;
705 hr = IShellView_CreateViewWindow(view, NULL, &settings, &test_shellbrowser, &r, &hwnd_view);
706 ok(hr == S_OK || broken(hr == S_FALSE), "got (0x%08lx)\n", hr);
707 ok(hwnd_view != NULL, "got %p\n", hwnd_view);
708 ok(IsWindow(hwnd_view), "hwnd %p still valid\n", hwnd_view);
709 ref2 = IShellView_Release(view);
710 ok(ref2 != 0, "ref2 = %lu\n", ref2);
711 ok(ref2 > ref1, "expected %lu > %lu\n", ref2, ref1);
712 ok(IsWindow(hwnd_view), "hwnd %p still valid\n", hwnd_view);
713 DestroyWindow(hwnd_view);
715 IShellFolder_Release(desktop);
718 static void test_IFolderView(void)
720 IShellFolder *desktop, *folder;
721 FOLDERSETTINGS settings;
722 IShellView *view;
723 IShellBrowser *browser;
724 IFolderView2 *fv2;
725 IFolderView *fv;
726 IUnknown *unk;
727 HWND hwnd_view, hwnd_list;
728 PITEMID_CHILD pidl;
729 HRESULT hr;
730 INT ret, count;
731 POINT pt;
732 RECT r;
734 create_interfaces(&desktop, &view);
736 hr = IShellView_QueryInterface(view, &IID_IFolderView, (void**)&fv);
737 if (hr != S_OK)
739 win_skip("IFolderView not supported by desktop folder\n");
740 destroy_interfaces(desktop, view);
741 return;
744 /* call methods before window creation */
745 hr = IFolderView_GetSpacing(fv, NULL);
746 ok(hr == S_FALSE || broken(hr == S_OK) /* win7 */, "got (0x%08lx)\n", hr);
748 pidl = (void*)0xdeadbeef;
749 hr = IFolderView_Item(fv, 0, &pidl);
750 ok(hr == E_INVALIDARG || broken(hr == E_FAIL) /* < Vista */, "got (0x%08lx)\n", hr);
751 ok(pidl == 0 || broken(pidl == (void*)0xdeadbeef) /* < Vista */, "got %p\n", pidl);
753 if (0)
755 /* crashes on Vista and Win2k8 - List not created yet case */
756 IFolderView_GetSpacing(fv, &pt);
758 /* crashes on XP */
759 IFolderView_GetSelectionMarkedItem(fv, NULL);
760 IFolderView_GetFocusedItem(fv, NULL);
762 /* crashes on Vista+ */
763 IFolderView_Item(fv, 0, NULL);
766 browser = IShellBrowserImpl_Construct();
768 settings.ViewMode = FVM_ICON;
769 settings.fFlags = 0;
770 hwnd_view = (HWND)0xdeadbeef;
771 SetRect(&r, 0, 0, 100, 100);
772 hr = IShellView_CreateViewWindow(view, NULL, &settings, browser, &r, &hwnd_view);
773 ok(hr == S_OK, "got (0x%08lx)\n", hr);
774 ok(IsWindow(hwnd_view), "got %p\n", hwnd_view);
776 hwnd_list = subclass_listview(hwnd_view);
777 if (!hwnd_list)
779 win_skip("Failed to subclass ListView control\n");
780 IShellBrowser_Release(browser);
781 IFolderView_Release(fv);
782 destroy_interfaces(desktop, view);
783 return;
786 /* IFolderView::GetSpacing */
787 flush_sequences(sequences, NUM_MSG_SEQUENCES);
788 hr = IFolderView_GetSpacing(fv, NULL);
789 ok(hr == S_OK, "got (0x%08lx)\n", hr);
790 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, empty_seq, "IFolderView::GetSpacing, empty", FALSE);
792 flush_sequences(sequences, NUM_MSG_SEQUENCES);
793 hr = IFolderView_GetSpacing(fv, &pt);
794 ok(hr == S_OK, "got (0x%08lx)\n", hr);
795 /* fails with empty sequence on win7 for unknown reason */
796 if (sequences[LISTVIEW_SEQ_INDEX]->count)
798 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_getspacing_seq, "IFolderView::GetSpacing", FALSE);
799 ok(pt.x > 0, "got %ld\n", pt.x);
800 ok(pt.y > 0, "got %ld\n", pt.y);
801 ret = SendMessageA(hwnd_list, LVM_GETITEMSPACING, 0, 0);
802 ok(pt.x == LOWORD(ret) && pt.y == HIWORD(ret), "got (%d, %d)\n", LOWORD(ret), HIWORD(ret));
805 /* IFolderView::ItemCount */
806 if (0)
808 /* crashes on XP */
809 IFolderView_ItemCount(fv, SVGIO_ALLVIEW, NULL);
812 flush_sequences(sequences, NUM_MSG_SEQUENCES);
813 IFolderView_ItemCount(fv, SVGIO_ALLVIEW, &count);
815 /* IFolderView::GetSelectionMarkedItem */
816 if (0)
818 /* crashes on XP */
819 IFolderView_GetSelectionMarkedItem(fv, NULL);
822 flush_sequences(sequences, NUM_MSG_SEQUENCES);
823 hr = IFolderView_GetSelectionMarkedItem(fv, &ret);
824 if (count)
825 ok(hr == S_OK, "got (0x%08lx)\n", hr);
826 else
827 ok(hr == S_FALSE, "got (0x%08lx)\n", hr);
828 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_getselectionmarked_seq,
829 "IFolderView::GetSelectionMarkedItem", FALSE);
831 /* IFolderView::GetFocusedItem */
832 flush_sequences(sequences, NUM_MSG_SEQUENCES);
833 hr = IFolderView_GetFocusedItem(fv, &ret);
834 if (count)
835 ok(hr == S_OK, "got (0x%08lx)\n", hr);
836 else
837 ok(hr == S_FALSE, "got (0x%08lx)\n", hr);
838 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_getfocused_seq,
839 "IFolderView::GetFocusedItem", FALSE);
841 /* IFolderView::GetFolder, just return pointer */
842 if (0)
844 /* crashes on XP */
845 IFolderView_GetFolder(fv, NULL, (void**)&folder);
846 IFolderView_GetFolder(fv, NULL, NULL);
849 hr = IFolderView_GetFolder(fv, &IID_IShellFolder, NULL);
850 ok(hr == E_POINTER, "got (0x%08lx)\n", hr);
852 hr = IFolderView_GetFolder(fv, &IID_IShellFolder, (void**)&folder);
853 ok(hr == S_OK, "got (0x%08lx)\n", hr);
854 ok(desktop == folder, "\n");
855 if (folder) IShellFolder_Release(folder);
857 hr = IFolderView_GetFolder(fv, &IID_IUnknown, (void**)&unk);
858 ok(hr == S_OK, "got (0x%08lx)\n", hr);
859 if (unk) IUnknown_Release(unk);
861 hr = IFolderView_QueryInterface(fv, &IID_IFolderView2, (void**)&fv2);
862 if (hr != S_OK)
863 win_skip("IFolderView2 is not supported.\n");
864 if (fv2) IFolderView2_Release(fv2);
866 hr = IShellView_DestroyViewWindow(view);
867 ok(hr == S_OK, "got (0x%08lx)\n", hr);
868 ok(!IsWindow(hwnd_view), "hwnd %p still valid\n", hwnd_view);
870 IShellBrowser_Release(browser);
871 IFolderView_Release(fv);
872 destroy_interfaces(desktop, view);
875 static void test_GetItemObject(void)
877 IShellFolder *desktop;
878 IShellView *view;
879 IUnknown *unk;
880 HRESULT hr;
882 create_interfaces(&desktop, &view);
884 /* from documentation three interfaces are supported for SVGIO_BACKGROUND:
885 IContextMenu, IDispatch, IPersistHistory */
886 hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IContextMenu, (void**)&unk);
887 ok(hr == S_OK, "got (0x%08lx)\n", hr);
888 IUnknown_Release(unk);
890 unk = NULL;
891 hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IDispatch, (void**)&unk);
892 ok(hr == S_OK || broken(hr == E_NOTIMPL) /* NT4 */, "got (0x%08lx)\n", hr);
893 if (unk) IUnknown_Release(unk);
895 unk = NULL;
896 hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IPersistHistory, (void**)&unk);
897 todo_wine ok(hr == S_OK || broken(hr == E_NOTIMPL) /* W9x, NT4 */, "got (0x%08lx)\n", hr);
898 if (unk) IUnknown_Release(unk);
900 /* example of unsupported interface, base for IPersistHistory */
901 hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IPersist, (void**)&unk);
902 ok(hr == E_NOINTERFACE || broken(hr == E_NOTIMPL) /* W2K */, "got (0x%08lx)\n", hr);
904 destroy_interfaces(desktop, view);
907 static void test_IShellFolderView(void)
909 IShellFolderView *folderview;
910 IShellFolder *desktop;
911 IShellView *view;
912 IDataObject *obj;
913 UINT i;
914 HRESULT hr;
916 create_interfaces(&desktop, &view);
918 hr = IShellView_QueryInterface(view, &IID_IShellFolderView, (void**)&folderview);
919 if (hr != S_OK)
921 win_skip("IShellView doesn't provide IShellFolderView on this platform\n");
922 destroy_interfaces(desktop, view);
923 return;
926 /* ::MoveIcons */
927 obj = IDataObjectImpl_Construct();
928 hr = IShellFolderView_MoveIcons(folderview, obj);
929 ok(hr == E_NOTIMPL || broken(hr == S_OK) /* W98 */, "got (0x%08lx)\n", hr);
930 IDataObject_Release(obj);
932 /* ::SetRedraw without list created */
933 hr = IShellFolderView_SetRedraw(folderview, TRUE);
934 ok(hr == S_OK, "got (0x%08lx)\n", hr);
936 /* ::QuerySupport */
937 hr = IShellFolderView_QuerySupport(folderview, NULL);
938 ok(hr == S_OK, "got (0x%08lx)\n", hr);
939 i = 0xdeadbeef;
940 hr = IShellFolderView_QuerySupport(folderview, &i);
941 ok(hr == S_OK, "got (0x%08lx)\n", hr);
942 ok(i == 0xdeadbeef, "got %d\n", i);
944 /* ::RemoveObject */
945 i = 0xdeadbeef;
946 hr = IShellFolderView_RemoveObject(folderview, NULL, &i);
947 ok(hr == S_OK || hr == E_FAIL, "got (0x%08lx)\n", hr);
948 if (hr == S_OK) ok(i == 0 || broken(i == 0xdeadbeef) /* Vista, 2k8 */,
949 "got %d\n", i);
951 IShellFolderView_Release(folderview);
953 destroy_interfaces(desktop, view);
956 static void test_IOleWindow(void)
958 IShellFolder *desktop;
959 IShellView *view;
960 IOleWindow *wnd;
961 HRESULT hr;
963 create_interfaces(&desktop, &view);
965 hr = IShellView_QueryInterface(view, &IID_IOleWindow, (void**)&wnd);
966 ok(hr == E_NOINTERFACE, "got (0x%08lx)\n", hr);
968 /* IShellView::ContextSensitiveHelp */
969 hr = IShellView_ContextSensitiveHelp(view, TRUE);
970 ok(hr == E_NOTIMPL, "got (0x%08lx)\n", hr);
971 hr = IShellView_ContextSensitiveHelp(view, FALSE);
972 ok(hr == E_NOTIMPL, "got (0x%08lx)\n", hr);
974 destroy_interfaces(desktop, view);
977 static const struct message folderview_setcurrentviewmode1_2_prevista[] = {
978 { LVM_SETVIEW, sent|wparam, LV_VIEW_ICON},
979 { LVM_SETIMAGELIST, sent|wparam, 0},
980 { LVM_SETIMAGELIST, sent|wparam, 1},
981 { 0x105a, sent},
982 { LVM_SETBKIMAGEW, sent|optional}, /* w2k3 */
983 { LVM_GETBKCOLOR, sent|optional}, /* w2k3 */
984 { LVM_GETTEXTBKCOLOR, sent|optional}, /* w2k3 */
985 { LVM_GETTEXTCOLOR, sent|optional}, /* w2k3 */
986 { LVM_SETEXTENDEDLISTVIEWSTYLE, sent|optional|wparam, 0xc8}, /* w2k3 */
987 { LVM_ARRANGE, sent },
988 { LVM_ARRANGE, sent|optional }, /* WinXP */
989 { 0 }
992 static const struct message folderview_setcurrentviewmode3_prevista[] = {
993 { LVM_SETVIEW, sent|wparam, LV_VIEW_LIST},
994 { LVM_SETIMAGELIST, sent|wparam, 0},
995 { LVM_SETIMAGELIST, sent|wparam, 1},
996 { 0x105a, sent},
997 { LVM_SETBKIMAGEW, sent|optional}, /* w2k3 */
998 { LVM_GETBKCOLOR, sent|optional}, /* w2k3 */
999 { LVM_GETTEXTBKCOLOR, sent|optional}, /* w2k3 */
1000 { LVM_GETTEXTCOLOR, sent|optional}, /* w2k3 */
1001 { LVM_SETEXTENDEDLISTVIEWSTYLE, sent|optional|wparam, 0xc8}, /* w2k3 */
1002 { 0 }
1005 static const struct message folderview_setcurrentviewmode4_prevista[] = {
1006 { LVM_GETHEADER, sent},
1007 { LVM_GETITEMCOUNT, sent|optional },
1008 { LVM_SETSELECTEDCOLUMN, sent},
1009 { WM_NOTIFY, sent },
1010 { WM_NOTIFY, sent },
1011 { WM_NOTIFY, sent },
1012 { WM_NOTIFY, sent },
1013 { LVM_SETVIEW, sent|wparam, LV_VIEW_DETAILS},
1014 { LVM_SETIMAGELIST, sent|wparam, 0},
1015 { LVM_SETIMAGELIST, sent|wparam, 1},
1016 { 0x105a, sent},
1017 { LVM_SETBKIMAGEW, sent|optional}, /* w2k3 */
1018 { LVM_GETBKCOLOR, sent|optional}, /* w2k3 */
1019 { LVM_GETTEXTBKCOLOR, sent|optional}, /* w2k3 */
1020 { LVM_GETTEXTCOLOR, sent|optional}, /* w2k3 */
1021 { LVM_SETEXTENDEDLISTVIEWSTYLE, sent|optional|wparam, 0xc8}, /* w2k3 */
1022 { 0 }
1025 /* XP, SetCurrentViewMode(5)
1026 108e - LVM_SETVIEW (LV_VIEW_ICON);
1027 1036 - LVM_SETEXTEDEDLISTVIEWSTYLE (0x8000, 0)
1028 100c/104c repeated X times
1029 1003 - LVM_SETIMAGELIST
1030 1035 - LVM_SETICONSPACING
1031 1004 - LVM_GETITEMCOUNT
1032 105a - ?
1033 1016 - LVM_ARRANGE
1034 1016 - LVM_ARRANGE
1037 /* XP, SetCurrentViewMode(6)
1038 1036 - LVM_SETEXTENDEDLISTVIEWSTYLE (0x8000, 0)
1039 1035 - LVM_SETICONSPACING
1040 1003 - LVM_SETIMAGELIST
1041 1003 - LVM_SETIMAGELIST
1042 100c/104c repeated X times
1043 10a2 - LVM_SETTILEVIEWINFO
1044 108e - LVM_SETVIEW (LV_VIEW_TILE)
1045 1003 - LVM_SETIMAGELIST
1046 105a - ?
1047 1016 - LVM_ARRANGE
1048 1016 - LVM_ARRANGE
1051 /* XP, SetCurrentViewMode (7)
1052 10a2 - LVM_SETTILEVIEWINFO
1053 108e - LVM_SETVIEW (LV_VIEW_ICON)
1054 1004/10a4 (LVM_GETITEMCOUNT/LVM_SETTILEINFO) X times
1055 1016 - LVM_ARRANGE
1056 1016 - LVM_ARRANGE
1058 LVM_SETEXTENDEDLISTVIEWSTYLE (0x40000, 0x40000)
1060 LVM_SETEXTENDEDLISTVIEWSTYLE (0x8000, 0x8000)
1063 static void test_GetSetCurrentViewMode(void)
1065 IShellFolder *desktop;
1066 IShellView *sview;
1067 IFolderView *fview;
1068 IShellBrowser *browser;
1069 FOLDERSETTINGS fs;
1070 UINT viewmode;
1071 HWND hwnd;
1072 RECT rc = {0, 0, 10, 10};
1073 HRESULT hr;
1074 UINT i;
1075 static const int winxp_res[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
1076 static const int win2k3_res[11] = {0, 1, 2, 3, 4, 5, 6, 5, 8, 0, 0};
1077 static const int vista_res[11] = {0, 1, 5, 3, 4, 5, 6, 7, 7, 0, 0};
1078 static const int win7_res[11] = {1, 1, 1, 3, 4, 1, 6, 1, 8, 8, 8};
1080 create_interfaces(&desktop, &sview);
1082 hr = IShellView_QueryInterface(sview, &IID_IFolderView, (void **)&fview);
1083 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1085 viewmode = 0xdeadbeef;
1086 hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
1087 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1088 ok(viewmode == FVM_TILE || broken(viewmode == 0) /* pre win7 */, "Got view mode %u.\n", viewmode);
1090 fs.ViewMode = 1;
1091 fs.fFlags = 0;
1092 browser = IShellBrowserImpl_Construct();
1093 hr = IShellView_CreateViewWindow(sview, NULL, &fs, browser, &rc, &hwnd);
1094 ok(hr == S_OK || broken(hr == S_FALSE /*Win2k*/ ), "got (0x%08lx)\n", hr);
1096 if(SUCCEEDED(hr))
1098 HWND hwnd_lv;
1099 UINT count;
1101 if (0)
1103 /* Crashes under Win7/WinXP */
1104 IFolderView_GetCurrentViewMode(fview, NULL);
1107 hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
1108 ok(hr == S_OK, "got (0x%08lx)\n", hr);
1109 ok(viewmode == 1, "ViewMode was %d\n", viewmode);
1111 hr = IFolderView_SetCurrentViewMode(fview, FVM_AUTO);
1112 ok(hr == S_OK, "got (0x%08lx)\n", hr);
1113 viewmode = 0xdeadbeef;
1114 hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
1115 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1116 ok(viewmode == FVM_ICON || broken(viewmode == FVM_AUTO) /* pre vista */, "Got view mode %d.\n", viewmode);
1118 hr = IFolderView_SetCurrentViewMode(fview, FVM_LIST);
1119 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1120 viewmode = 0xdeadbeef;
1121 hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
1122 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1123 ok(viewmode == FVM_LIST, "Got view mode %d.\n", viewmode);
1124 hr = IFolderView_SetCurrentViewMode(fview, 0);
1125 ok(hr == S_OK || broken(hr == E_INVALIDARG) /* pre win7 */, "Got hr %#lx.\n", hr);
1126 viewmode = 0xdeadbeef;
1127 hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
1128 ok(hr == S_OK, "got (0x%08lx)\n", hr);
1129 ok(viewmode == FVM_LIST || broken(viewmode == 0) /* pre vista */, "Got view mode %d.\n", viewmode);
1131 for(i = 1; i < 9; i++)
1133 hr = IFolderView_SetCurrentViewMode(fview, i);
1134 ok(hr == S_OK || (i == 8 && hr == E_INVALIDARG /*Vista*/),
1135 "(%d) got (0x%08lx)\n", i, hr);
1137 hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
1138 ok(hr == S_OK, "(%d) got (0x%08lx)\n", i, hr);
1140 /* Wine currently behaves like winxp here. */
1141 ok((viewmode == win7_res[i]) || (viewmode == vista_res[i]) ||
1142 (viewmode == win2k3_res[i]) || (viewmode == winxp_res[i]),
1143 "(%d) got %d\n",i , viewmode);
1146 hr = IFolderView_SetCurrentViewMode(fview, 9);
1147 ok(hr == S_OK || broken(hr == E_INVALIDARG) /* pre win7 */, "Got hr %#lx.\n", hr);
1148 viewmode = 0xdeadbeef;
1149 hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
1150 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1151 ok(viewmode == FVM_CONTENT || broken(viewmode == 9) /* pre vista */ ||
1152 broken(viewmode == FVM_THUMBSTRIP) /* vista */, "Got view mode %d.\n", viewmode);
1154 /* Test messages */
1155 hwnd_lv = subclass_listview(hwnd);
1156 ok(hwnd_lv != NULL, "Failed to subclass listview\n");
1157 if(hwnd_lv)
1159 /* Vista seems to set the viewmode by other means than
1160 sending messages. At least no related messages are
1161 captured by subclassing.
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 };
1169 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1170 hr = IFolderView_SetCurrentViewMode(fview, 1);
1171 ok(hr == S_OK, "got 0x%08lx\n", hr);
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);
1181 hr = IFolderView_SetCurrentViewMode(fview, 2);
1182 ok(hr == S_OK, "got 0x%08lx\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);
1189 hr = IFolderView_SetCurrentViewMode(fview, 3);
1190 ok(hr == S_OK, "got 0x%08lx\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);
1197 hr = IFolderView_SetCurrentViewMode(fview, 4);
1198 ok(hr == S_OK, "got 0x%08lx\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);
1205 hr = IFolderView_SetCurrentViewMode(fview, 5);
1206 ok(hr == S_OK, "got 0x%08lx\n", hr);
1207 todo_wine
1209 if(vista_plus)
1211 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
1213 else
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);
1223 hr = IFolderView_SetCurrentViewMode(fview, 6);
1224 ok(hr == S_OK, "got 0x%08lx\n", hr);
1225 todo_wine
1227 if(vista_plus)
1229 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
1231 else
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);
1241 hr = IFolderView_SetCurrentViewMode(fview, 7);
1242 ok(hr == S_OK, "got 0x%08lx\n", hr);
1243 todo_wine
1245 if(vista_plus)
1247 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
1249 else
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);
1259 hr = IFolderView_SetCurrentViewMode(fview, 8);
1260 ok(hr == S_OK || broken(hr == E_INVALIDARG /* Vista */), "got 0x%08lx\n", hr);
1261 todo_wine
1263 if(vista_plus)
1265 verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
1267 else
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);
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);
1283 IFolderView_Release(fview);
1285 else
1287 skip("No IFolderView for the desktop folder.\n");
1290 IShellBrowser_Release(browser);
1291 IShellView_DestroyViewWindow(sview);
1292 destroy_interfaces(desktop, sview);
1295 static void test_IOleCommandTarget(void)
1297 IShellFolder *psf_desktop;
1298 IShellView *psv;
1299 IOleCommandTarget *poct;
1300 HRESULT hr;
1302 hr = SHGetDesktopFolder(&psf_desktop);
1303 ok(hr == S_OK, "got (0x%08lx)\n", hr);
1305 hr = IShellFolder_CreateViewObject(psf_desktop, NULL, &IID_IShellView, (void**)&psv);
1306 ok(hr == S_OK, "got (0x%08lx)\n", hr);
1307 if(SUCCEEDED(hr))
1309 hr = IShellView_QueryInterface(psv, &IID_IOleCommandTarget, (void**)&poct);
1310 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Win95/NT4 */, "Got 0x%08lx\n", hr);
1311 if(SUCCEEDED(hr))
1313 OLECMD oc;
1315 hr = IOleCommandTarget_QueryStatus(poct, NULL, 0, NULL, NULL);
1316 ok(hr == E_INVALIDARG, "Got 0x%08lx\n", hr);
1318 oc.cmdID = 1;
1319 hr = IOleCommandTarget_QueryStatus(poct, NULL, 0, &oc, NULL);
1320 ok(hr == OLECMDERR_E_UNKNOWNGROUP, "Got 0x%08lx\n", hr);
1322 oc.cmdID = 1;
1323 hr = IOleCommandTarget_QueryStatus(poct, NULL, 1, &oc, NULL);
1324 ok(hr == OLECMDERR_E_UNKNOWNGROUP, "Got 0x%08lx\n", hr);
1326 hr = IOleCommandTarget_Exec(poct, NULL, 0, 0, NULL, NULL);
1327 ok(hr == OLECMDERR_E_UNKNOWNGROUP, "Got 0x%08lx\n", hr);
1329 IOleCommandTarget_Release(poct);
1332 IShellView_Release(psv);
1335 IShellFolder_Release(psf_desktop);
1338 static void test_SHCreateShellFolderView(void)
1340 IShellFolder *desktop;
1341 IShellView *psv;
1342 SFV_CREATE sfvc;
1343 ULONG refCount;
1344 IUnknown *unk;
1345 HRESULT hr;
1347 hr = SHGetDesktopFolder(&desktop);
1348 ok(hr == S_OK, "got (0x%08lx)\n", hr);
1350 if (0)
1352 /* crash on win7 */
1353 SHCreateShellFolderView(NULL, NULL);
1356 psv = (void *)0xdeadbeef;
1357 hr = SHCreateShellFolderView(NULL, &psv);
1358 ok(hr == E_INVALIDARG, "Got 0x%08lx\n", hr);
1359 ok(psv == NULL, "psv = %p\n", psv);
1361 memset(&sfvc, 0, sizeof(sfvc));
1362 psv = (void *)0xdeadbeef;
1363 hr = SHCreateShellFolderView(&sfvc, &psv);
1364 ok(hr == E_INVALIDARG, "Got 0x%08lx\n", hr);
1365 ok(psv == NULL, "psv = %p\n", psv);
1367 memset(&sfvc, 0, sizeof(sfvc));
1368 sfvc.cbSize = sizeof(sfvc) - 1;
1369 psv = (void *)0xdeadbeef;
1370 hr = SHCreateShellFolderView(&sfvc, &psv);
1371 ok(hr == E_INVALIDARG, "Got 0x%08lx\n", hr);
1372 ok(psv == NULL, "psv = %p\n", psv);
1374 memset(&sfvc, 0, sizeof(sfvc));
1375 sfvc.cbSize = sizeof(sfvc) + 1;
1376 psv = (void *)0xdeadbeef;
1377 hr = SHCreateShellFolderView(&sfvc, &psv);
1378 ok(hr == E_INVALIDARG, "Got 0x%08lx\n", hr);
1379 ok(psv == NULL, "psv = %p\n", psv);
1381 if (0)
1383 /* Crashes on NULL 'pshf' on XP/2k3 */
1384 memset(&sfvc, 0, sizeof(sfvc));
1385 sfvc.cbSize = sizeof(sfvc);
1386 psv = (void *)0xdeadbeef;
1387 hr = SHCreateShellFolderView(&sfvc, &psv);
1388 ok(hr == E_UNEXPECTED, "Got 0x%08lx\n", hr);
1389 ok(psv == NULL, "psv = %p\n", psv);
1391 memset(&sfvc, 0, sizeof(sfvc));
1392 sfvc.cbSize = sizeof(sfvc) - 1;
1393 sfvc.pshf = desktop;
1394 psv = (void *)0xdeadbeef;
1395 hr = SHCreateShellFolderView(&sfvc, &psv);
1396 ok(hr == E_INVALIDARG, "Got 0x%08lx\n", hr);
1397 ok(psv == NULL, "psv = %p\n", psv);
1399 memset(&sfvc, 0, sizeof(sfvc));
1400 sfvc.cbSize = sizeof(sfvc);
1401 sfvc.pshf = desktop;
1402 psv = NULL;
1403 hr = SHCreateShellFolderView(&sfvc, &psv);
1404 ok(hr == S_OK, "Got 0x%08lx\n", hr);
1405 ok(psv != NULL, "psv = %p\n", psv);
1407 hr = IShellView_QueryInterface(psv, &IID_CDefView, (void **)&unk);
1408 ok(hr == S_OK, "got (0x%08lx)\n", hr);
1409 ok(unk == (IUnknown *)psv, "got %p\n", unk);
1410 IUnknown_Release(unk);
1412 refCount = IShellView_Release(psv);
1413 ok(refCount == 0, "refCount = %lu\n", refCount);
1415 IShellFolder_Release(desktop);
1418 static void test_SHCreateShellFolderViewEx(void)
1420 IShellFolder *desktop;
1421 IShellView *psv;
1422 ULONG refCount;
1423 IUnknown *unk;
1424 HRESULT hr;
1425 CSFV csfv;
1427 hr = SHGetDesktopFolder(&desktop);
1428 ok(hr == S_OK, "got (0x%08lx)\n", hr);
1430 if (0)
1432 /* crash on win7 */
1433 SHCreateShellFolderViewEx(NULL, NULL);
1434 SHCreateShellFolderViewEx(NULL, &psv);
1435 SHCreateShellFolderViewEx(&csfv, NULL);
1438 memset(&csfv, 0, sizeof(csfv));
1439 csfv.pshf = desktop;
1440 psv = NULL;
1441 hr = SHCreateShellFolderViewEx(&csfv, &psv);
1442 ok(hr == S_OK, "Got 0x%08lx\n", hr);
1443 ok(psv != NULL, "psv = %p\n", psv);
1445 hr = IShellView_QueryInterface(psv, &IID_CDefView, (void **)&unk);
1446 ok(hr == S_OK, "got (0x%08lx)\n", hr);
1447 ok(unk == (IUnknown *)psv, "got %p\n", unk);
1448 IUnknown_Release(unk);
1450 refCount = IShellView_Release(psv);
1451 ok(refCount == 0, "refCount = %lu\n", refCount);
1453 if (0)
1455 /* Crashes on null shellfolder, on XP/2k3 */
1456 memset(&csfv, 0, sizeof(csfv));
1457 csfv.pshf = NULL;
1458 psv = (void *)0xdeadbeef;
1459 hr = SHCreateShellFolderViewEx(&csfv, &psv);
1460 ok(hr == E_UNEXPECTED, "Got 0x%08lx\n", hr);
1461 ok(psv == NULL, "psv = %p\n", psv);
1463 memset(&csfv, 0, sizeof(csfv));
1464 csfv.cbSize = sizeof(csfv);
1465 csfv.pshf = desktop;
1466 psv = NULL;
1467 hr = SHCreateShellFolderViewEx(&csfv, &psv);
1468 ok(hr == S_OK, "Got 0x%08lx\n", hr);
1469 ok(psv != NULL, "psv = %p\n", psv);
1470 if (psv)
1472 refCount = IShellView_Release(psv);
1473 ok(refCount == 0, "refCount = %lu\n", refCount);
1476 IShellFolder_Release(desktop);
1479 static void test_newmenu(void)
1481 CMINVOKECOMMANDINFO invoke_info = {.cbSize = sizeof(CMINVOKECOMMANDINFO)};
1482 IObjectWithSite *ows;
1483 WCHAR path[MAX_PATH];
1484 IShellExtInit *init;
1485 IContextMenu3 *menu;
1486 MENUITEMINFOA info;
1487 ITEMIDLIST *pidl;
1488 IUnknown *unk;
1489 HMENU hmenu;
1490 HRESULT hr;
1491 ULONG ref;
1492 int count;
1493 BOOL ret;
1495 hmenu = CreatePopupMenu();
1497 hr = CoCreateInstance(&CLSID_NewMenu, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk);
1498 ok(hr == S_OK, "Failed to create NewMenu object, hr %#lx.\n", hr);
1499 hr = IUnknown_QueryInterface(unk, &IID_IShellExtInit, (void **)&init);
1500 ok(hr == S_OK, "Failed to get IShellExtInit, hr %#lx.\n", hr);
1501 hr = IUnknown_QueryInterface(unk, &IID_IContextMenu3, (void **)&menu);
1502 ok(hr == S_OK, "Failed to get IContextMenu3, hr %#lx.\n", hr);
1503 hr = IUnknown_QueryInterface(unk, &IID_IObjectWithSite, (void **)&ows);
1504 ok(hr == S_OK, "Failed to get IObjectWithSite, hr %#lx.\n", hr);
1506 GetTempPathW(ARRAY_SIZE(path), path);
1507 hr = SHParseDisplayName(path, NULL, &pidl, 0, NULL);
1508 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1510 hr = IShellExtInit_Initialize(init, NULL, NULL, NULL);
1511 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
1513 hr = IShellExtInit_Initialize(init, pidl, NULL, NULL);
1514 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1516 hr = IContextMenu3_QueryContextMenu(menu, hmenu, 0, 1, 1000, CMF_EXPLORE);
1517 ok(hr == 0x40, "Got hr %#lx.\n", hr);
1519 count = GetMenuItemCount(hmenu);
1520 ok(count == 1, "Got count %d.\n", count);
1522 info.cbSize = sizeof(info);
1523 info.fMask = MIIM_ID | MIIM_FTYPE | MIIM_SUBMENU;
1524 ret = GetMenuItemInfoA(hmenu, 0, TRUE, &info);
1525 ok(ret == TRUE, "Got error %lu.\n", GetLastError());
1526 ok(info.wID == 1, "Got ID %u.\n", info.wID);
1527 ok(!info.fType, "Got type %#x.\n", info.fType);
1528 ok(!!info.hSubMenu, "Got sub-menu %p.\n", info.hSubMenu);
1530 invoke_info.lpVerb = (const char *)1234;
1531 hr = IContextMenu3_InvokeCommand(menu, &invoke_info);
1532 ok(hr == E_FAIL, "Got hr %#lx.\n", hr);
1534 ILFree(pidl);
1535 IObjectWithSite_Release(ows);
1536 IContextMenu3_Release(menu);
1537 IShellExtInit_Release(init);
1538 ref = IUnknown_Release(unk);
1539 ok(!ref, "Got refcount %ld.\n", ref);
1541 /* Test with a virtual folder that can't create new items. */
1543 hmenu = CreatePopupMenu();
1545 hr = CoCreateInstance(&CLSID_NewMenu, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk);
1546 ok(hr == S_OK, "Failed to create NewMenu object, hr %#lx.\n", hr);
1547 hr = IUnknown_QueryInterface(unk, &IID_IShellExtInit, (void **)&init);
1548 ok(hr == S_OK, "Failed to get IShellExtInit, hr %#lx.\n", hr);
1549 hr = IUnknown_QueryInterface(unk, &IID_IContextMenu3, (void **)&menu);
1550 ok(hr == S_OK, "Failed to get IContextMenu3, hr %#lx.\n", hr);
1552 hr = SHGetKnownFolderIDList(&FOLDERID_ComputerFolder, 0, NULL, &pidl);
1553 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1555 hr = IShellExtInit_Initialize(init, pidl, NULL, NULL);
1556 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1558 hr = IContextMenu3_QueryContextMenu(menu, hmenu, 0, 1, 1000, CMF_EXPLORE);
1559 ok(hr == 0, "Got hr %#lx.\n", hr);
1561 count = GetMenuItemCount(hmenu);
1562 ok(!count, "Got count %d.\n", count);
1564 ILFree(pidl);
1565 IContextMenu3_Release(menu);
1566 IShellExtInit_Release(init);
1567 ref = IUnknown_Release(unk);
1568 ok(!ref, "Got refcount %ld.\n", ref);
1571 static void test_folder_flags(void)
1573 IFolderView2 *folderview;
1574 FOLDERSETTINGS settings;
1575 IShellFolder *desktop;
1576 IShellView *shellview;
1577 DWORD flags;
1578 HRESULT hr;
1579 int i;
1580 static const struct
1582 DWORD mask, flags;
1583 DWORD expected;
1584 } tests[] =
1586 { FWF_USESEARCHFOLDER, FWF_NONE, FWF_NONE },
1587 { FWF_NONE, FWF_AUTOARRANGE, FWF_NONE },
1588 { FWF_AUTOARRANGE, FWF_AUTOARRANGE, FWF_AUTOARRANGE },
1589 { FWF_OWNERDATA, FWF_AUTOARRANGE, FWF_NONE },
1590 { FWF_AUTOARRANGE, FWF_OWNERDATA | FWF_AUTOARRANGE, FWF_AUTOARRANGE },
1591 { ~FWF_NONE, FWF_AUTOARRANGE, FWF_AUTOARRANGE },
1594 create_interfaces(&desktop, &shellview);
1596 hr = IShellView_GetCurrentInfo(shellview, &settings);
1597 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1598 ok(settings.ViewMode == FVM_TILE || broken(!settings.ViewMode) /* pre win7 */,
1599 "Got view mode %u.\n", settings.ViewMode);
1600 ok(settings.fFlags == FWF_USESEARCHFOLDER || broken(!settings.fFlags) /* pre vista */,
1601 "Got flags %#x.\n", settings.fFlags);
1603 hr = IShellView_QueryInterface(shellview, &IID_IFolderView2, (void **)&folderview);
1604 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* pre vista */, "Got hr %#lx.\n", hr);
1605 if (hr != S_OK)
1607 win_skip("No IFolderView2 for the desktop folder.\n");
1608 destroy_interfaces(desktop, shellview);
1609 return;
1612 hr = IFolderView2_GetCurrentFolderFlags(folderview, NULL);
1613 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1615 flags = 0xdeadbeef;
1616 hr = IFolderView2_GetCurrentFolderFlags(folderview, &flags);
1617 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1618 ok(flags == FWF_USESEARCHFOLDER, "Got flags %#lx.\n", flags);
1620 for (i = 0; i < ARRAY_SIZE(tests); ++i)
1622 hr = IFolderView2_SetCurrentFolderFlags(folderview, tests[i].mask, tests[i].flags);
1623 ok(hr == S_OK, "Test %u: Got hr %#lx.\n", i, hr);
1624 flags = 0xdeadbeef;
1625 hr = IFolderView2_GetCurrentFolderFlags(folderview, &flags);
1626 ok(hr == S_OK, "Test %u: Got hr %#lx.\n", i, hr);
1627 ok(flags == tests[i].expected, "Test %u: Got flags %#lx.\n", i, flags);
1629 hr = IFolderView2_SetCurrentFolderFlags(folderview, ~FWF_NONE, FWF_NONE);
1630 ok(hr == S_OK, "Test %u: Got hr %#lx.\n", i, hr);
1633 IFolderView2_Release(folderview);
1634 destroy_interfaces(desktop, shellview);
1637 START_TEST(shlview)
1639 OleInitialize(NULL);
1641 init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
1643 test_CreateViewWindow();
1644 test_IFolderView();
1645 test_GetItemObject();
1646 test_IShellFolderView();
1647 test_IOleWindow();
1648 test_GetSetCurrentViewMode();
1649 test_IOleCommandTarget();
1650 test_SHCreateShellFolderView();
1651 test_SHCreateShellFolderViewEx();
1652 test_newmenu();
1653 test_folder_flags();
1655 OleUninitialize();