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