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