urlmon: Implemented IUri_GetUserName.
[wine] / dlls / shell32 / tests / shlview.c
1 /*
2  * Unit test of the IShellView
3  *
4  * Copyright 2010 Nikolay Sivov for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define COBJMACROS
25 #define CONST_VTABLE
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wtypes.h"
30 #include "shellapi.h"
31
32 #include "shlguid.h"
33 #include "shlobj.h"
34 #include "shobjidl.h"
35 #include "shlwapi.h"
36 #include "ocidl.h"
37 #include "oleauto.h"
38
39 #include "initguid.h"
40
41 #include "wine/test.h"
42
43 #include "msg.h"
44
45 #define LISTVIEW_SEQ_INDEX  0
46 #define NUM_MSG_SEQUENCES   1
47
48 DEFINE_GUID(IID_IPersistHistory, 0x91a565c1, 0xe38f, 0x11d0, 0x94, 0xbf, 0x00, 0xa0, 0xc9, 0x05, 0x5c, 0xbf);
49
50 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
51
52 static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
53 {
54     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
55     static LONG defwndproc_counter = 0;
56     LRESULT ret;
57     struct message msg;
58
59     trace("listview: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
60
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);
67
68     defwndproc_counter++;
69     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
70     defwndproc_counter--;
71     return ret;
72 }
73
74 static HWND subclass_listview(HWND hwnd)
75 {
76     WNDPROC oldproc;
77     HWND listview;
78
79     /* listview is a first child */
80     listview = FindWindowExA(hwnd, NULL, WC_LISTVIEWA, NULL);
81     if(!listview)
82     {
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);
90     }
91
92     oldproc = (WNDPROC)SetWindowLongPtrA(listview, GWLP_WNDPROC,
93                                         (LONG_PTR)listview_subclass_proc);
94     SetWindowLongPtrA(listview, GWLP_USERDATA, (LONG_PTR)oldproc);
95
96     return listview;
97 }
98
99 /* dummy IDataObject implementation */
100 typedef struct {
101     const IDataObjectVtbl *lpVtbl;
102     LONG ref;
103 } IDataObjectImpl;
104
105 static const IDataObjectVtbl IDataObjectImpl_Vtbl;
106
107 static IDataObject* IDataObjectImpl_Construct(void)
108 {
109     IDataObjectImpl *obj;
110
111     obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
112     obj->lpVtbl = &IDataObjectImpl_Vtbl;
113     obj->ref = 1;
114
115     return (IDataObject*)obj;
116 }
117
118 static HRESULT WINAPI IDataObjectImpl_QueryInterface(IDataObject *iface, REFIID riid, void **ppvObj)
119 {
120     IDataObjectImpl *This = (IDataObjectImpl *)iface;
121
122     if (IsEqualIID(riid, &IID_IUnknown) ||
123         IsEqualIID(riid, &IID_IDataObject))
124     {
125         *ppvObj = This;
126     }
127
128     if(*ppvObj)
129     {
130         IUnknown_AddRef(iface);
131         return S_OK;
132     }
133
134     return E_NOINTERFACE;
135 }
136
137 static ULONG WINAPI IDataObjectImpl_AddRef(IDataObject * iface)
138 {
139     IDataObjectImpl *This = (IDataObjectImpl *)iface;
140     return InterlockedIncrement(&This->ref);
141 }
142
143 static ULONG WINAPI IDataObjectImpl_Release(IDataObject * iface)
144 {
145     IDataObjectImpl *This = (IDataObjectImpl *)iface;
146     ULONG ref = InterlockedDecrement(&This->ref);
147
148     if (!ref)
149     {
150         HeapFree(GetProcessHeap(), 0, This);
151         return 0;
152     }
153     return ref;
154 }
155
156 static HRESULT WINAPI IDataObjectImpl_GetData(IDataObject *iface, FORMATETC *pformat, STGMEDIUM *pmedium)
157 {
158     return E_NOTIMPL;
159 }
160
161 static HRESULT WINAPI IDataObjectImpl_GetDataHere(IDataObject *iface, FORMATETC *pformat, STGMEDIUM *pmedium)
162 {
163     return E_NOTIMPL;
164 }
165
166 static HRESULT WINAPI IDataObjectImpl_QueryGetData(IDataObject *iface, FORMATETC *pformat)
167 {
168     return E_NOTIMPL;
169 }
170
171 static HRESULT WINAPI IDataObjectImpl_GetCanonicalFormatEtc(
172     IDataObject *iface, FORMATETC *pformatIn, FORMATETC *pformatOut)
173 {
174     return E_NOTIMPL;
175 }
176
177 static HRESULT WINAPI IDataObjectImpl_SetData(
178     IDataObject *iface, FORMATETC *pformat, STGMEDIUM *pmedium, BOOL release)
179 {
180     return E_NOTIMPL;
181 }
182
183 static HRESULT WINAPI IDataObjectImpl_EnumFormatEtc(
184     IDataObject *iface, DWORD direction, IEnumFORMATETC **ppenumFormatEtc)
185 {
186     return E_NOTIMPL;
187 }
188
189 static HRESULT WINAPI IDataObjectImpl_DAdvise(
190     IDataObject *iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pSink, DWORD *pConnection)
191 {
192     return E_NOTIMPL;
193 }
194
195 static HRESULT WINAPI IDataObjectImpl_DUnadvise(IDataObject *iface, DWORD connection)
196 {
197     return E_NOTIMPL;
198 }
199
200 static HRESULT WINAPI IDataObjectImpl_EnumDAdvise(IDataObject *iface, IEnumSTATDATA **ppenumAdvise)
201 {
202     return E_NOTIMPL;
203 }
204
205 static const IDataObjectVtbl IDataObjectImpl_Vtbl =
206 {
207     IDataObjectImpl_QueryInterface,
208     IDataObjectImpl_AddRef,
209     IDataObjectImpl_Release,
210     IDataObjectImpl_GetData,
211     IDataObjectImpl_GetDataHere,
212     IDataObjectImpl_QueryGetData,
213     IDataObjectImpl_GetCanonicalFormatEtc,
214     IDataObjectImpl_SetData,
215     IDataObjectImpl_EnumFormatEtc,
216     IDataObjectImpl_DAdvise,
217     IDataObjectImpl_DUnadvise,
218     IDataObjectImpl_EnumDAdvise
219 };
220
221 /* dummy IShellBrowser implementation */
222 typedef struct {
223     const IShellBrowserVtbl *lpVtbl;
224     LONG ref;
225 } IShellBrowserImpl;
226
227 static const IShellBrowserVtbl IShellBrowserImpl_Vtbl;
228
229 static IShellBrowser* IShellBrowserImpl_Construct(void)
230 {
231     IShellBrowserImpl *browser;
232
233     browser = HeapAlloc(GetProcessHeap(), 0, sizeof(*browser));
234     browser->lpVtbl = &IShellBrowserImpl_Vtbl;
235     browser->ref = 1;
236
237     return (IShellBrowser*)browser;
238 }
239
240 static HRESULT WINAPI IShellBrowserImpl_QueryInterface(IShellBrowser *iface,
241                                             REFIID riid,
242                                             LPVOID *ppvObj)
243 {
244     IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
245
246     *ppvObj = NULL;
247
248     if(IsEqualIID(riid, &IID_IUnknown)   ||
249        IsEqualIID(riid, &IID_IOleWindow) ||
250        IsEqualIID(riid, &IID_IShellBrowser))
251     {
252         *ppvObj = This;
253     }
254
255     if(*ppvObj)
256     {
257         IUnknown_AddRef(iface);
258         return S_OK;
259     }
260
261     return E_NOINTERFACE;
262 }
263
264 static ULONG WINAPI IShellBrowserImpl_AddRef(IShellBrowser * iface)
265 {
266     IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
267     return InterlockedIncrement(&This->ref);
268 }
269
270 static ULONG WINAPI IShellBrowserImpl_Release(IShellBrowser * iface)
271 {
272     IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
273     ULONG ref = InterlockedDecrement(&This->ref);
274
275     if (!ref)
276     {
277         HeapFree(GetProcessHeap(), 0, This);
278         return 0;
279     }
280     return ref;
281 }
282
283 static HRESULT WINAPI IShellBrowserImpl_GetWindow(IShellBrowser *iface,
284                                            HWND *phwnd)
285 {
286     if (phwnd) *phwnd = GetDesktopWindow();
287     return S_OK;
288 }
289
290 static HRESULT WINAPI IShellBrowserImpl_ContextSensitiveHelp(IShellBrowser *iface,
291                                                       BOOL fEnterMode)
292 {
293     return E_NOTIMPL;
294 }
295
296 static HRESULT WINAPI IShellBrowserImpl_BrowseObject(IShellBrowser *iface,
297                                               LPCITEMIDLIST pidl,
298                                               UINT wFlags)
299 {
300     return E_NOTIMPL;
301 }
302
303 static HRESULT WINAPI IShellBrowserImpl_EnableModelessSB(IShellBrowser *iface,
304                                               BOOL fEnable)
305
306 {
307     return E_NOTIMPL;
308 }
309
310 static HRESULT WINAPI IShellBrowserImpl_GetControlWindow(IShellBrowser *iface,
311                                               UINT id,
312                                               HWND *lphwnd)
313
314 {
315     return E_NOTIMPL;
316 }
317
318 static HRESULT WINAPI IShellBrowserImpl_GetViewStateStream(IShellBrowser *iface,
319                                                 DWORD mode,
320                                                 LPSTREAM *pStrm)
321
322 {
323     return E_NOTIMPL;
324 }
325
326 static HRESULT WINAPI IShellBrowserImpl_InsertMenusSB(IShellBrowser *iface,
327                                            HMENU hmenuShared,
328                                            LPOLEMENUGROUPWIDTHS lpMenuWidths)
329
330 {
331     return E_NOTIMPL;
332 }
333
334 static HRESULT WINAPI IShellBrowserImpl_OnViewWindowActive(IShellBrowser *iface,
335                                                 IShellView *ppshv)
336
337 {
338     return E_NOTIMPL;
339 }
340
341 static HRESULT WINAPI IShellBrowserImpl_QueryActiveShellView(IShellBrowser *iface,
342                                                   IShellView **ppshv)
343
344 {
345     return E_NOTIMPL;
346 }
347
348 static HRESULT WINAPI IShellBrowserImpl_RemoveMenusSB(IShellBrowser *iface,
349                                            HMENU hmenuShared)
350
351 {
352     return E_NOTIMPL;
353 }
354
355 static HRESULT WINAPI IShellBrowserImpl_SendControlMsg(IShellBrowser *iface,
356                                             UINT id,
357                                             UINT uMsg,
358                                             WPARAM wParam,
359                                             LPARAM lParam,
360                                             LRESULT *pret)
361
362 {
363     return E_NOTIMPL;
364 }
365
366 static HRESULT WINAPI IShellBrowserImpl_SetMenuSB(IShellBrowser *iface,
367                                        HMENU hmenuShared,
368                                        HOLEMENU holemenuReserved,
369                                        HWND hwndActiveObject)
370
371 {
372     return E_NOTIMPL;
373 }
374
375 static HRESULT WINAPI IShellBrowserImpl_SetStatusTextSB(IShellBrowser *iface,
376                                              LPCOLESTR lpszStatusText)
377
378 {
379     return E_NOTIMPL;
380 }
381
382 static HRESULT WINAPI IShellBrowserImpl_SetToolbarItems(IShellBrowser *iface,
383                                              LPTBBUTTON lpButtons,
384                                              UINT nButtons,
385                                              UINT uFlags)
386
387 {
388     return E_NOTIMPL;
389 }
390
391 static HRESULT WINAPI IShellBrowserImpl_TranslateAcceleratorSB(IShellBrowser *iface,
392                                                     LPMSG lpmsg,
393                                                     WORD wID)
394
395 {
396     return E_NOTIMPL;
397 }
398
399 static const IShellBrowserVtbl IShellBrowserImpl_Vtbl =
400 {
401     IShellBrowserImpl_QueryInterface,
402     IShellBrowserImpl_AddRef,
403     IShellBrowserImpl_Release,
404     IShellBrowserImpl_GetWindow,
405     IShellBrowserImpl_ContextSensitiveHelp,
406     IShellBrowserImpl_InsertMenusSB,
407     IShellBrowserImpl_SetMenuSB,
408     IShellBrowserImpl_RemoveMenusSB,
409     IShellBrowserImpl_SetStatusTextSB,
410     IShellBrowserImpl_EnableModelessSB,
411     IShellBrowserImpl_TranslateAcceleratorSB,
412     IShellBrowserImpl_BrowseObject,
413     IShellBrowserImpl_GetViewStateStream,
414     IShellBrowserImpl_GetControlWindow,
415     IShellBrowserImpl_SendControlMsg,
416     IShellBrowserImpl_QueryActiveShellView,
417     IShellBrowserImpl_OnViewWindowActive,
418     IShellBrowserImpl_SetToolbarItems
419 };
420
421 static const struct message empty_seq[] = {
422     { 0 }
423 };
424
425 static const struct message folderview_getspacing_seq[] = {
426     { LVM_GETITEMSPACING, wparam|sent, FALSE },
427     { 0 }
428 };
429
430 static const struct message folderview_getselectionmarked_seq[] = {
431     { LVM_GETSELECTIONMARK, sent },
432     { 0 }
433 };
434
435 static const struct message folderview_getfocused_seq[] = {
436     { LVM_GETNEXTITEM, sent|wparam|lparam, -1, LVNI_FOCUSED },
437     { 0 }
438 };
439
440 static const struct message folderview_itemcount_seq[] = {
441     { LVM_GETITEMCOUNT, sent },
442     { 0 }
443 };
444
445 static void test_IShellView_CreateViewWindow(void)
446 {
447     IShellFolder *desktop;
448     FOLDERSETTINGS settings;
449     IShellView *view;
450     IDropTarget *dt;
451     HWND hwnd_view;
452     HRESULT hr;
453     RECT r = {0};
454
455     hr = SHGetDesktopFolder(&desktop);
456     ok(hr == S_OK, "got (0x%08x)\n", hr);
457
458     hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
459     ok(hr == S_OK, "got (0x%08x)\n", hr);
460
461 if (0)
462 {
463     /* crashes on native */
464     hr = IShellView_CreateViewWindow(view, NULL, &settings, NULL, NULL, NULL);
465 }
466
467     settings.ViewMode = FVM_ICON;
468     settings.fFlags = 0;
469     hwnd_view = (HWND)0xdeadbeef;
470     hr = IShellView_CreateViewWindow(view, NULL, &settings, NULL, NULL, &hwnd_view);
471     ok(hr == E_UNEXPECTED, "got (0x%08x)\n", hr);
472     ok(hwnd_view == 0, "got %p\n", hwnd_view);
473
474     hwnd_view = (HWND)0xdeadbeef;
475     hr = IShellView_CreateViewWindow(view, NULL, &settings, NULL, &r, &hwnd_view);
476     ok(hr == E_UNEXPECTED, "got (0x%08x)\n", hr);
477     ok(hwnd_view == 0, "got %p\n", hwnd_view);
478
479     /* ::DragLeave without drag operation */
480     hr = IShellView_QueryInterface(view, &IID_IDropTarget, (void**)&dt);
481     ok(hr == S_OK, "got (0x%08x)\n", hr);
482     hr = IDropTarget_DragLeave(dt);
483     ok(hr == S_OK, "got (0x%08x)\n", hr);
484     IDropTarget_Release(dt);
485
486     IShellView_Release(view);
487     IShellFolder_Release(desktop);
488 }
489
490 static void test_IFolderView(void)
491 {
492     IShellFolder *desktop, *folder;
493     FOLDERSETTINGS settings;
494     IShellView *view;
495     IShellBrowser *browser;
496     IFolderView *fv;
497     HWND hwnd_view, hwnd_list;
498     PITEMID_CHILD pidl;
499     HRESULT hr;
500     INT ret;
501     POINT pt;
502     LONG ref1, ref2;
503     RECT r;
504
505     hr = SHGetDesktopFolder(&desktop);
506     ok(hr == S_OK, "got (0x%08x)\n", hr);
507
508     hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
509     ok(hr == S_OK, "got (0x%08x)\n", hr);
510
511     hr = IShellView_QueryInterface(view, &IID_IFolderView, (void**)&fv);
512     if (hr != S_OK)
513     {
514         win_skip("IFolderView not supported by desktop folder\n");
515         IShellView_Release(view);
516         IShellFolder_Release(desktop);
517         return;
518     }
519
520     /* call methods before window creation */
521     hr = IFolderView_GetSpacing(fv, NULL);
522     ok(hr == S_FALSE || broken(hr == S_OK) /* win7 */, "got (0x%08x)\n", hr);
523
524     pidl = (void*)0xdeadbeef;
525     hr = IFolderView_Item(fv, 0, &pidl);
526     ok(hr == E_INVALIDARG || broken(hr == E_FAIL) /* < Vista */, "got (0x%08x)\n", hr);
527     ok(pidl == 0 || broken(pidl == (void*)0xdeadbeef) /* < Vista */, "got %p\n", pidl);
528
529 if (0)
530 {
531     /* crashes on Vista and Win2k8 - List not created yet case */
532     hr = IFolderView_GetSpacing(fv, &pt);
533
534     /* crashes on XP */
535     hr = IFolderView_GetSelectionMarkedItem(fv, NULL);
536     hr = IFolderView_GetFocusedItem(fv, NULL);
537
538     /* crashes on Vista+ */
539     hr = IFolderView_Item(fv, 0, NULL);
540 }
541
542     browser = IShellBrowserImpl_Construct();
543
544     settings.ViewMode = FVM_ICON;
545     settings.fFlags = 0;
546     hwnd_view = (HWND)0xdeadbeef;
547     r.left = r.top = 0;
548     r.right = r.bottom = 100;
549     hr = IShellView_CreateViewWindow(view, NULL, &settings, browser, &r, &hwnd_view);
550     ok(hr == S_OK, "got (0x%08x)\n", hr);
551     ok(IsWindow(hwnd_view), "got %p\n", hwnd_view);
552
553     hwnd_list = subclass_listview(hwnd_view);
554     if (!hwnd_list)
555     {
556         win_skip("Failed to subclass ListView control\n");
557         IShellBrowser_Release(browser);
558         IFolderView_Release(fv);
559         IShellView_Release(view);
560         IShellFolder_Release(desktop);
561         return;
562     }
563
564     /* IFolderView::GetSpacing */
565     flush_sequences(sequences, NUM_MSG_SEQUENCES);
566     hr = IFolderView_GetSpacing(fv, NULL);
567     ok(hr == S_OK, "got (0x%08x)\n", hr);
568     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, empty_seq, "IFolderView::GetSpacing, empty", FALSE);
569
570     flush_sequences(sequences, NUM_MSG_SEQUENCES);
571     hr = IFolderView_GetSpacing(fv, &pt);
572     ok(hr == S_OK, "got (0x%08x)\n", hr);
573     /* fails with empty sequence on win7 for unknown reason */
574     if (sequences[LISTVIEW_SEQ_INDEX]->count)
575     {
576         ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_getspacing_seq, "IFolderView::GetSpacing", FALSE);
577         ok(pt.x > 0, "got %d\n", pt.x);
578         ok(pt.y > 0, "got %d\n", pt.y);
579         ret = SendMessageA(hwnd_list, LVM_GETITEMSPACING, 0, 0);
580         ok(pt.x == LOWORD(ret) && pt.y == HIWORD(ret), "got (%d, %d)\n", LOWORD(ret), HIWORD(ret));
581     }
582
583     /* IFolderView::GetSelectionMarkedItem */
584 if (0)
585 {
586     /* crashes on XP */
587     hr = IFolderView_GetSelectionMarkedItem(fv, NULL);
588 }
589
590     flush_sequences(sequences, NUM_MSG_SEQUENCES);
591     hr = IFolderView_GetSelectionMarkedItem(fv, &ret);
592     ok(hr == S_OK, "got (0x%08x)\n", hr);
593     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_getselectionmarked_seq,
594                                   "IFolderView::GetSelectionMarkedItem", FALSE);
595
596     /* IFolderView::GetFocusedItem */
597     flush_sequences(sequences, NUM_MSG_SEQUENCES);
598     hr = IFolderView_GetFocusedItem(fv, &ret);
599     ok(hr == S_OK, "got (0x%08x)\n", hr);
600     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_getfocused_seq,
601                                   "IFolderView::GetFocusedItem", FALSE);
602
603     /* IFolderView::GetFolder, just return pointer */
604 if (0)
605 {
606     /* crashes on XP */
607     hr = IFolderView_GetFolder(fv, NULL, (void**)&folder);
608     hr = IFolderView_GetFolder(fv, NULL, NULL);
609 }
610
611     hr = IFolderView_GetFolder(fv, &IID_IShellFolder, NULL);
612     ok(hr == E_POINTER, "got (0x%08x)\n", hr);
613
614     ref1 = IShellFolder_AddRef(desktop);
615     IShellFolder_Release(desktop);
616     hr = IFolderView_GetFolder(fv, &IID_IShellFolder, (void**)&folder);
617     ok(hr == S_OK, "got (0x%08x)\n", hr);
618     ref2 = IShellFolder_AddRef(desktop);
619     IShellFolder_Release(desktop);
620     ok(ref1 == ref2, "expected same refcount, got %d\n", ref2);
621     ok(desktop == folder, "\n");
622
623     /* IFolderView::ItemCount */
624 if (0)
625 {
626     /* crashes on XP */
627     hr = IFolderView_ItemCount(fv, SVGIO_ALLVIEW, NULL);
628 }
629
630     flush_sequences(sequences, NUM_MSG_SEQUENCES);
631     hr = IFolderView_ItemCount(fv, SVGIO_ALLVIEW, &ret);
632     ok(hr == S_OK, "got (0x%08x)\n", hr);
633     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_itemcount_seq,
634                                   "IFolderView::ItemCount", FALSE);
635
636     IShellBrowser_Release(browser);
637     IFolderView_Release(fv);
638     IShellView_Release(view);
639     IShellFolder_Release(desktop);
640 }
641
642 static void test_GetItemObject(void)
643 {
644     IShellFolder *desktop;
645     IShellView *view;
646     IUnknown *unk;
647     HRESULT hr;
648
649     hr = SHGetDesktopFolder(&desktop);
650     ok(hr == S_OK, "got (0x%08x)\n", hr);
651
652     hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
653     ok(hr == S_OK, "got (0x%08x)\n", hr);
654
655     /* from documentation three interfaces are supported for SVGIO_BACKGROUND:
656        IContextMenu, IDispatch, IPersistHistory */
657     hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IContextMenu, (void**)&unk);
658     ok(hr == S_OK, "got (0x%08x)\n", hr);
659     IUnknown_Release(unk);
660
661     unk = NULL;
662     hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IDispatch, (void**)&unk);
663     todo_wine ok(hr == S_OK || broken(hr == E_NOTIMPL) /* NT4 */, "got (0x%08x)\n", hr);
664     if (unk) IUnknown_Release(unk);
665
666     unk = NULL;
667     hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IPersistHistory, (void**)&unk);
668     todo_wine ok(hr == S_OK || broken(hr == E_NOTIMPL) /* W9x, NT4 */, "got (0x%08x)\n", hr);
669     if (unk) IUnknown_Release(unk);
670
671     /* example of unsupported interface, base for IPersistHistory */
672     hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IPersist, (void**)&unk);
673     ok(hr == E_NOINTERFACE || broken(hr == E_NOTIMPL) /* W2K */, "got (0x%08x)\n", hr);
674
675     IShellView_Release(view);
676     IShellFolder_Release(desktop);
677 }
678
679 static void test_IShellFolderView(void)
680 {
681     IShellFolderView *folderview;
682     IShellFolder *desktop;
683     IShellView *view;
684     IDataObject *obj;
685     UINT i;
686     HRESULT hr;
687
688     hr = SHGetDesktopFolder(&desktop);
689     ok(hr == S_OK, "got (0x%08x)\n", hr);
690
691     hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
692     ok(hr == S_OK, "got (0x%08x)\n", hr);
693
694     hr = IShellView_QueryInterface(view, &IID_IShellFolderView, (void**)&folderview);
695     if (hr != S_OK)
696     {
697         win_skip("IShellView doesn't provide IShellFolderView on this platform\n");
698         IShellView_Release(view);
699         IShellFolder_Release(desktop);
700         return;
701     }
702
703     /* ::MoveIcons */
704     obj = IDataObjectImpl_Construct();
705     hr = IShellFolderView_MoveIcons(folderview, obj);
706     ok(hr == E_NOTIMPL || broken(hr == S_OK) /* W98 */, "got (0x%08x)\n", hr);
707     IDataObject_Release(obj);
708
709     /* ::SetRedraw without list created */
710     hr = IShellFolderView_SetRedraw(folderview, TRUE);
711     ok(hr == S_OK, "got (0x%08x)\n", hr);
712
713     /* ::QuerySupport */
714     hr = IShellFolderView_QuerySupport(folderview, NULL);
715     ok(hr == S_OK, "got (0x%08x)\n", hr);
716     i = 0xdeadbeef;
717     hr = IShellFolderView_QuerySupport(folderview, &i);
718     ok(hr == S_OK, "got (0x%08x)\n", hr);
719     ok(i == 0xdeadbeef, "got %d\n", i);
720
721     /* ::RemoveObject */
722     i = 0xdeadbeef;
723     hr = IShellFolderView_RemoveObject(folderview, NULL, &i);
724     ok(hr == S_OK, "got (0x%08x)\n", hr);
725     ok(i == 0 || i == -1 /* Win7 */ || broken(i == 0xdeadbeef) /* Vista, 2k8 */,
726         "got %d\n", i);
727
728     IShellFolderView_Release(folderview);
729
730     IShellView_Release(view);
731     IShellFolder_Release(desktop);
732 }
733
734 static void test_IOleWindow(void)
735 {
736     IShellFolder *desktop;
737     IShellView *view;
738     HRESULT hr;
739
740     hr = SHGetDesktopFolder(&desktop);
741     ok(hr == S_OK, "got (0x%08x)\n", hr);
742
743     hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
744     ok(hr == S_OK, "got (0x%08x)\n", hr);
745
746     /* IShellView::ContextSensitiveHelp */
747     hr = IShellView_ContextSensitiveHelp(view, TRUE);
748     ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
749     hr = IShellView_ContextSensitiveHelp(view, FALSE);
750     ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
751
752     IShellView_Release(view);
753     IShellFolder_Release(desktop);
754 }
755
756 START_TEST(shlview)
757 {
758     OleInitialize(NULL);
759
760     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
761
762     test_IShellView_CreateViewWindow();
763     test_IFolderView();
764     test_GetItemObject();
765     test_IShellFolderView();
766     test_IOleWindow();
767
768     OleUninitialize();
769 }