1 /*
2  * PROJECT:     ReactOS API tests
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Test for IShellFolderViewCB
5  * COPYRIGHT:   Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
6  */
7 
8 #include "shelltest.h"
9 #include <atlsimpcoll.h>
10 #include <stdio.h>
11 
12 #if 1
13 #define DbgPrint(...)   trace(__VA_ARGS__)
14 #else
15 EXTERN_C
16 void DbgPrint(PCSTR, ...);
17 #endif
18 #include <shellutils.h>
19 //#include <msgtrace.h>
20 
21 static DWORD g_WinVersion;
22 #define WINVER_VISTA   0x0600
23 
24 #ifndef SFVM_SELECTIONCHANGED
25 #define SFVM_SELECTIONCHANGED          8 /* undocumented */
26 #define SFVM_DRAWMENUITEM              9 /* undocumented */
27 #define SFVM_MEASUREMENUITEM          10 /* undocumented */
28 #define SFVM_EXITMENULOOP             11 /* undocumented */
29 #define SFVM_VIEWRELEASE              12 /* undocumented */
30 #define SFVM_GETNAMELENGTH            13 /* undocumented */
31 #define SFVM_WINDOWCLOSING            16 /* undocumented */
32 #define SFVM_LISTREFRESHED            17 /* undocumented */
33 #define SFVM_WINDOWFOCUSED            18 /* undocumented */
34 #define SFVM_REGISTERCOPYHOOK         20 /* undocumented */
35 #define SFVM_COPYHOOKCALLBACK         21 /* undocumented */
36 #define SFVM_UNMERGEFROMMENU          28 /* undocumented */
37 #define SFVM_ADDINGOBJECT             29 /* undocumented */
38 #define SFVM_REMOVINGOBJECT           30 /* undocumented */
39 #define SFVM_GETCOMMANDDIR            33 /* undocumented */
40 #define SFVM_GETCOLUMNSTREAM          34 /* undocumented */
41 #define SFVM_CANSELECTALL             35 /* undocumented */
42 #define SFVM_ISSTRICTREFRESH          37 /* undocumented */
43 #define SFVM_ISCHILDOBJECT            38 /* undocumented */
44 #define SFVM_GETEXTVIEWS              40 /* undocumented */
45 #define SFVM_GET_CUSTOMVIEWINFO       77 /* undocumented */
46 #define SFVM_ENUMERATEDITEMS          79 /* undocumented */
47 #define SFVM_GET_VIEW_DATA            80 /* undocumented */
48 #define SFVM_GET_WEBVIEW_LAYOUT       82 /* undocumented */
49 #define SFVM_GET_WEBVIEW_CONTENT      83 /* undocumented */
50 #define SFVM_GET_WEBVIEW_TASKS        84 /* undocumented */
51 #define SFVM_GET_WEBVIEW_THEME        86 /* undocumented */
52 #define SFVM_GETDEFERREDVIEWSETTINGS  92 /* undocumented */
53 #endif
54 
55 #define DUM_MSG_GetWindow               400
56 #define DUM_MSG_ContextSensitiveHelp    401
57 #define DUM_MSG_InsertMenusSB           402
58 #define DUM_MSG_SetMenuSB               403
59 #define DUM_MSG_RemoveMenusSB           404
60 #define DUM_MSG_SetStatusTextSB         405
61 #define DUM_MSG_EnableModelessSB        406
62 #define DUM_MSG_TranslateAcceleratorSB  407
63 #define DUM_MSG_BrowseObject            408
64 #define DUM_MSG_GetViewStateStream      409
65 #define DUM_MSG_GetControlWindow        410
66 #define DUM_MSG_SendControlMsg          411
67 #define DUM_MSG_QueryActiveShellView    412
68 #define DUM_MSG_OnViewWindowActive      413
69 #define DUM_MSG_SetToolbarItems         414
70 
71 
72 const char* msg2str(UINT uMsg)
73 {
74     static char buf[2][50];
75     static int index = 0;
76     index ^= 1;
77 
78     switch (uMsg)
79     {
80     case SFVM_MERGEMENU: return "SFVM_MERGEMENU";
81     case SFVM_INVOKECOMMAND: return "SFVM_INVOKECOMMAND";
82     case SFVM_GETHELPTEXT: return "SFVM_GETHELPTEXT";
83     case SFVM_GETTOOLTIPTEXT: return "SFVM_GETTOOLTIPTEXT";
84     case SFVM_GETBUTTONINFO: return "SFVM_GETBUTTONINFO";
85     case SFVM_GETBUTTONS: return "SFVM_GETBUTTONS";
86     case SFVM_INITMENUPOPUP: return "SFVM_INITMENUPOPUP";
87     case SFVM_SELECTIONCHANGED: return "SFVM_SELECTIONCHANGED";
88     case SFVM_DRAWMENUITEM: return "SFVM_DRAWMENUITEM";
89     case SFVM_MEASUREMENUITEM: return "SFVM_MEASUREMENUITEM";
90     case SFVM_EXITMENULOOP: return "SFVM_EXITMENULOOP";
91     case SFVM_VIEWRELEASE: return "SFVM_VIEWRELEASE";
92     case SFVM_GETNAMELENGTH: return "SFVM_GETNAMELENGTH";
93     case SFVM_FSNOTIFY: return "SFVM_FSNOTIFY";
94     case SFVM_WINDOWCREATED: return "SFVM_WINDOWCREATED";
95     case SFVM_WINDOWCLOSING: return "SFVM_WINDOWCLOSING";
96     case SFVM_LISTREFRESHED: return "SFVM_LISTREFRESHED";
97     case SFVM_WINDOWFOCUSED: return "SFVM_WINDOWFOCUSED";
98     case SFVM_REGISTERCOPYHOOK: return "SFVM_REGISTERCOPYHOOK";
99     case SFVM_COPYHOOKCALLBACK: return "SFVM_COPYHOOKCALLBACK";
100     case SFVM_GETDETAILSOF: return "SFVM_GETDETAILSOF";
101     case SFVM_COLUMNCLICK: return "SFVM_COLUMNCLICK";
102     case SFVM_QUERYFSNOTIFY: return "SFVM_QUERYFSNOTIFY";
103     case SFVM_DEFITEMCOUNT: return "SFVM_DEFITEMCOUNT";
104     case SFVM_DEFVIEWMODE: return "SFVM_DEFVIEWMODE";
105     case SFVM_UNMERGEFROMMENU: return "SFVM_UNMERGEFROMMENU";
106     case SFVM_ADDINGOBJECT: return "SFVM_ADDINGOBJECT";
107     case SFVM_REMOVINGOBJECT: return "SFVM_REMOVINGOBJECT";
108     case SFVM_UPDATESTATUSBAR: return "SFVM_UPDATESTATUSBAR";
109     case SFVM_BACKGROUNDENUM: return "SFVM_BACKGROUNDENUM";
110     case SFVM_GETCOMMANDDIR: return "SFVM_GETCOMMANDDIR";
111     case SFVM_GETCOLUMNSTREAM: return "SFVM_GETCOLUMNSTREAM";
112     case SFVM_CANSELECTALL: return "SFVM_CANSELECTALL";
113     case SFVM_DIDDRAGDROP: return "SFVM_DIDDRAGDROP";
114     case SFVM_ISSTRICTREFRESH: return "SFVM_ISSTRICTREFRESH";
115     case SFVM_ISCHILDOBJECT: return "SFVM_ISCHILDOBJECT";
116     case SFVM_SETISFV: return "SFVM_SETISFV";
117     case SFVM_GETEXTVIEWS: return "SFVM_GETEXTVIEWS";
118     case SFVM_THISIDLIST: return "SFVM_THISIDLIST";
119     case SFVM_ADDPROPERTYPAGES: return "SFVM_ADDPROPERTYPAGES";
120     case SFVM_BACKGROUNDENUMDONE: return "SFVM_BACKGROUNDENUMDONE";
121     case SFVM_GETNOTIFY: return "SFVM_GETNOTIFY";
122     case SFVM_GETSORTDEFAULTS: return "SFVM_GETSORTDEFAULTS";
123     case SFVM_SIZE: return "SFVM_SIZE";
124     case SFVM_GETZONE: return "SFVM_GETZONE";
125     case SFVM_GETPANE: return "SFVM_GETPANE";
126     case SFVM_GETHELPTOPIC: return "SFVM_GETHELPTOPIC";
127     case SFVM_GETANIMATION: return "SFVM_GETANIMATION";
128     case SFVM_GET_CUSTOMVIEWINFO: return "SFVM_GET_CUSTOMVIEWINFO";
129     case SFVM_ENUMERATEDITEMS: return "SFVM_ENUMERATEDITEMS";
130     case SFVM_GET_VIEW_DATA: return "SFVM_GET_VIEW_DATA";
131     case SFVM_GET_WEBVIEW_LAYOUT: return "SFVM_GET_WEBVIEW_LAYOUT";
132     case SFVM_GET_WEBVIEW_CONTENT: return "SFVM_GET_WEBVIEW_CONTENT";
133     case SFVM_GET_WEBVIEW_TASKS: return "SFVM_GET_WEBVIEW_TASKS";
134     case SFVM_GET_WEBVIEW_THEME: return "SFVM_GET_WEBVIEW_THEME";
135     case SFVM_GETDEFERREDVIEWSETTINGS: return "SFVM_GET_WEBVIEW_THEME";
136 
137     case DUM_MSG_GetWindow: return "|GetWindow|";
138     case DUM_MSG_ContextSensitiveHelp: return "|ContextSensitiveHelp|";
139     case DUM_MSG_InsertMenusSB: return "|InsertMenusSB|";
140     case DUM_MSG_SetMenuSB: return "|SetMenuSB|";
141     case DUM_MSG_RemoveMenusSB: return "|RemoveMenusSB|";
142     case DUM_MSG_SetStatusTextSB: return "|SetStatusTextSB|";
143     case DUM_MSG_EnableModelessSB: return "|EnableModelessSB|";
144     case DUM_MSG_TranslateAcceleratorSB: return "|TranslateAcceleratorSB|";
145     case DUM_MSG_BrowseObject: return "|BrowseObject|";
146     case DUM_MSG_GetViewStateStream: return "|GetViewStateStream|";
147     case DUM_MSG_GetControlWindow: return "|GetControlWindow|";
148     case DUM_MSG_SendControlMsg: return "|SendControlMsg|";
149     case DUM_MSG_QueryActiveShellView: return "|QueryActiveShellView|";
150     case DUM_MSG_OnViewWindowActive: return "|OnViewWindowActive|";
151     case DUM_MSG_SetToolbarItems: return "|SetToolbarItems|";
152     default:
153         sprintf(buf[index], "[%u]", uMsg);
154         return buf[index];
155     }
156 }
157 
158 
159 #define PTR_VALUE   0xf7f7f7f7
160 
161 struct message
162 {
163     message(UINT msg, WPARAM wp, LPARAM lp) : uMsg(msg), wParam(wp), lParam(lp) { ; }
164 
165     UINT uMsg;
166     WPARAM wParam;
167     LPARAM lParam;
168 };
169 
170 CSimpleArray<message> g_Received;
171 
172 void clear_list()
173 {
174     g_Received.RemoveAll();
175 }
176 
177 void add_msg(UINT uMsg, WPARAM wParam, LPARAM lParam)
178 {
179     g_Received.Add(message(uMsg, wParam, lParam));
180 }
181 
182 void print_list_(const CSimpleArray<message>& input, const char* file, int line)
183 {
184     trace_(file, line)("Got list:\n");
185     for (int n = 0; n < input.GetSize(); ++n)
186     {
187         const message& msg = input[n];
188         trace_(file, line)("msg: %d(%s), wParam:0x%x, lParam:0x%lx\n", msg.uMsg, msg2str(msg.uMsg), msg.wParam, msg.lParam);
189     }
190     trace_(file, line)("End of list.\n");
191 }
192 
193 void compare_list_(const CSimpleArray<message>& input, const message* compare, const char* file, int line)
194 {
195     int input_item = 0;
196     int compare_item = 0;
197     LONG old_failures = winetest_get_failures();
198     while (compare[compare_item].uMsg && input_item < input.GetSize())
199     {
200         const message& inp = input[input_item];
201         const message& cmp = compare[compare_item];
202         if (cmp.uMsg == inp.uMsg)
203         {
204             if (cmp.lParam != (LPARAM)PTR_VALUE)
205             {
206                 ok_(file, line)(cmp.lParam == inp.lParam, "Expected lParam to be 0x%lx, was 0x%lx for %i(%s)\n",
207                                 cmp.lParam, inp.lParam, compare_item, msg2str(cmp.uMsg));
208             }
209             else
210             {
211                 ok_(file, line)(inp.lParam != 0, "Expected lParam to be a pointer, was 0 for %i(%s)\n",
212                                 compare_item, msg2str(cmp.uMsg));
213             }
214             if (cmp.wParam != PTR_VALUE)
215             {
216                 ok_(file, line)(cmp.wParam == inp.wParam, "Expected wParam to be 0x%x, was 0x%x for %i(%s)\n",
217                                 cmp.wParam, inp.wParam, compare_item, msg2str(cmp.uMsg));
218             }
219             else
220             {
221                 ok_(file, line)(inp.wParam != 0, "Expected wParam to be a pointer, was 0 for %i(%s)\n",
222                                 compare_item, msg2str(cmp.uMsg));
223             }
224             compare_item++;
225         }
226         else
227         {
228             /* We skip unknown items for now */
229         }
230 
231         input_item++;
232     }
233 
234     while (compare[compare_item].uMsg)
235     {
236         ok_(file, line)(0, "Message %i(%s) not found\n", compare_item, msg2str(compare[compare_item].uMsg));
237         compare_item++;
238     }
239     if (old_failures != winetest_get_failures())
240     {
241         print_list_(input, file, line);
242     }
243 }
244 
245 #define compare_list(cmp)   compare_list_(g_Received, cmp, __FILE__, __LINE__)
246 #define print_list()        print_list_(g_Received, __FILE__, __LINE__)
247 
248 
249 LONG g_AddRef = 0;
250 LONG g_Release = 0;
251 
252 class CFolderViewCB :
253     public IShellFolderViewCB
254 {
255 public:
256     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void  **ppvObject)
257     {
258         if (riid == IID_IShellFolderViewCB || riid == IID_IUnknown)
259         {
260             *ppvObject = this;
261             AddRef();
262             return S_OK;
263         }
264         return E_NOINTERFACE;
265     }
266     virtual ULONG STDMETHODCALLTYPE AddRef(void)
267     {
268         InterlockedIncrement(&g_AddRef);
269         return 2;
270     }
271     virtual ULONG STDMETHODCALLTYPE Release(void)
272     {
273         InterlockedIncrement(&g_Release);
274         return 1;
275     }
276     virtual HRESULT STDMETHODCALLTYPE MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
277     {
278         //DbgPrint("MessageSFVCB(uMsg:%s, wParam:%u, lParam:%u\n", msg2str(uMsg), wParam, lParam);
279         add_msg(uMsg, wParam, lParam);
280         return E_NOTIMPL;
281     }
282 };
283 
284 
285 static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
286 {
287     if (msg == WM_DESTROY)
288     {
289         PostQuitMessage(0);
290         return 0;
291     }
292     return DefWindowProc(hwnd, msg, wParam, lParam);
293 }
294 
295 
296 class CDummyShellBrowser : public IShellBrowser
297 {
298 public:
299     HWND m_hwnd;
300     CDummyShellBrowser()
301     {
302         static const TCHAR* class_name = TEXT("DUMMY_TEST_CLASS");
303         WNDCLASSEX wx = {};
304         wx.cbSize = sizeof(WNDCLASSEX);
305         wx.lpfnWndProc = WndProc;
306         wx.hInstance = GetModuleHandle(NULL);
307         wx.lpszClassName = class_name;
308         wx.style = CS_DBLCLKS;
309         RegisterClassEx(&wx);
310         m_hwnd = CreateWindowEx(0, class_name, TEXT("dummy_name"), WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
311         ShowWindow(m_hwnd, SW_SHOW);
312     }
313 
314     // *** IUnknown methods ***
315     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void  **ppvObject)
316     {
317         if (riid == IID_IShellBrowser || riid == IID_IUnknown)
318         {
319             *ppvObject = this;
320             return S_OK;
321         }
322         return E_NOINTERFACE;
323     }
324     virtual ULONG STDMETHODCALLTYPE AddRef(void)
325     {
326         return 2;
327     }
328     virtual ULONG STDMETHODCALLTYPE Release(void)
329     {
330         return 1;
331     }
332 
333     // *** IOleWindow methods ***
334     virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd)
335     {
336         //DbgPrint("%s()\n", __FUNCTION__);
337         *phwnd = m_hwnd;
338         add_msg(DUM_MSG_GetWindow, NULL, NULL);
339         return S_OK;
340     }
341     virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode)
342     {
343         //DbgPrint("%s()\n", __FUNCTION__);
344         add_msg(DUM_MSG_ContextSensitiveHelp, NULL, NULL);
345         return E_NOTIMPL;
346     }
347 
348     // *** IShellBrowser methods ***
349     virtual HRESULT STDMETHODCALLTYPE InsertMenusSB(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
350     {
351         //DbgPrint("%s()\n", __FUNCTION__);
352         add_msg(DUM_MSG_InsertMenusSB, NULL, NULL);
353         return S_OK;
354     }
355     virtual HRESULT STDMETHODCALLTYPE SetMenuSB(HMENU hmenuShared, HOLEMENU holemenuRes, HWND hwndActiveObject)
356     {
357         //DbgPrint("%s()\n", __FUNCTION__);
358         add_msg(DUM_MSG_SetMenuSB, NULL, NULL);
359         return S_OK;
360     }
361     virtual HRESULT STDMETHODCALLTYPE RemoveMenusSB(HMENU hmenuShared)
362     {
363         //DbgPrint("%s()\n", __FUNCTION__);
364         add_msg(DUM_MSG_RemoveMenusSB, NULL, NULL);
365         return E_NOTIMPL;
366     }
367     virtual HRESULT STDMETHODCALLTYPE SetStatusTextSB(LPCWSTR pszStatusText)
368     {
369         //DbgPrint("%s()\n", __FUNCTION__);
370         add_msg(DUM_MSG_SetStatusTextSB, NULL, NULL);
371         return E_NOTIMPL;
372     }
373     virtual HRESULT STDMETHODCALLTYPE EnableModelessSB(BOOL fEnable)
374     {
375         //DbgPrint("%s()\n", __FUNCTION__);
376         add_msg(DUM_MSG_EnableModelessSB, NULL, NULL);
377         return E_NOTIMPL;
378     }
379     virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorSB(MSG *pmsg, WORD wID)
380     {
381         //DbgPrint("%s()\n", __FUNCTION__);
382         add_msg(DUM_MSG_TranslateAcceleratorSB, NULL, NULL);
383         return E_NOTIMPL;
384     }
385     virtual HRESULT STDMETHODCALLTYPE BrowseObject(PCUIDLIST_RELATIVE pidl,UINT wFlags)
386     {
387         //DbgPrint("%s()\n", __FUNCTION__);
388         add_msg(DUM_MSG_BrowseObject, NULL, NULL);
389         return E_NOTIMPL;
390     }
391     virtual HRESULT STDMETHODCALLTYPE GetViewStateStream(DWORD grfMode,IStream **ppStrm)
392     {
393         //DbgPrint("%s()\n", __FUNCTION__);
394         add_msg(DUM_MSG_GetViewStateStream, NULL, NULL);
395         return E_NOTIMPL;
396     }
397     virtual HRESULT STDMETHODCALLTYPE GetControlWindow(UINT id,HWND *phwnd)
398     {
399         //DbgPrint("%s()\n", __FUNCTION__);
400         add_msg(DUM_MSG_GetControlWindow, NULL, NULL);
401         return E_NOTIMPL;
402     }
403     virtual HRESULT STDMETHODCALLTYPE SendControlMsg(UINT id,UINT uMsg,WPARAM wParam,LPARAM lParam,LRESULT *pret)
404     {
405         //DbgPrint("%s()\n", __FUNCTION__);
406         add_msg(DUM_MSG_SendControlMsg, NULL, NULL);
407         return E_NOTIMPL;
408     }
409     virtual HRESULT STDMETHODCALLTYPE QueryActiveShellView(IShellView **ppshv)
410     {
411         //DbgPrint("%s()\n", __FUNCTION__);
412         add_msg(DUM_MSG_QueryActiveShellView, NULL, NULL);
413         return E_NOTIMPL;
414     }
415     virtual HRESULT STDMETHODCALLTYPE OnViewWindowActive(IShellView *pshv)
416     {
417         //DbgPrint("%s()\n", __FUNCTION__);
418         add_msg(DUM_MSG_OnViewWindowActive, NULL, NULL);
419         return E_NOTIMPL;
420     }
421     virtual HRESULT STDMETHODCALLTYPE SetToolbarItems(LPTBBUTTONSB lpButtons,UINT nButtons,UINT uFlags)
422     {
423         //DbgPrint("%s()\n", __FUNCTION__);
424         add_msg(DUM_MSG_SetToolbarItems, NULL, NULL);
425         return E_NOTIMPL;
426     }
427 };
428 
429 
430 START_TEST(IShellFolderViewCB)
431 {
432     RTL_OSVERSIONINFOEXW rtlinfo = { sizeof(rtlinfo) };
433     void (__stdcall* pRtlGetVersion)(RTL_OSVERSIONINFOEXW*);
434     pRtlGetVersion = (void (__stdcall*)(RTL_OSVERSIONINFOEXW*))GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");
435     pRtlGetVersion(&rtlinfo);
436     g_WinVersion = (rtlinfo.dwMajorVersion << 8) | rtlinfo.dwMinorVersion;
437 
438     CoInitialize(NULL);
439     CFolderViewCB cb;
440 
441     CComPtr<IShellFolder> desktop;
442 
443     HRESULT hr = SHGetDesktopFolder(&desktop);
444     ok_hex(hr, S_OK);
445     if (!desktop)
446         return;
447 
448     SFV_CREATE sfvc = { sizeof(sfvc), desktop };
449     sfvc.psfvcb = &cb;
450     IShellView* psv = NULL;
451 
452     g_AddRef = 0;
453     g_Release = 0;
454 
455     hr = SHCreateShellFolderView(&sfvc, &psv);
456     ok_hex(hr, S_OK);
457     if (!SUCCEEDED(hr))
458         return;
459 
460     ok_int(g_AddRef, 2);
461     ok_int(g_Release, 0);
462 
463     clear_list();
464 
465     HWND wnd;
466     RECT rc = { 0 };
467     FOLDERSETTINGS fs = { FVM_DETAILS, 0 };
468     CDummyShellBrowser dum;
469     hr = psv->CreateViewWindow(NULL, &fs, &dum, &rc, &wnd);
470 
471 
472     static message init_list[] =
473     {
474         /* ... */
475         message(DUM_MSG_GetWindow, 0, 0),
476         /* Some unknown messages here, and multiple SFVM_GET_WEBVIEW_THEME + SFVM_GETSORTDEFAULTS + SFVM_GETCOLUMNSTREAM */
477         message(SFVM_SIZE, 0, 0),
478         /* ... */
479         message(DUM_MSG_InsertMenusSB, 0, 0),
480         message(SFVM_MERGEMENU, 0, PTR_VALUE),
481         message(DUM_MSG_SetMenuSB, 0, 0),
482         /* ... */
483         message(SFVM_WINDOWCREATED, PTR_VALUE, 0),
484         /* ... */
485 
486         message(SFVM_GETBUTTONINFO, 0, PTR_VALUE),
487         message(SFVM_GETBUTTONS, PTR_VALUE, PTR_VALUE),
488         message(DUM_MSG_SetToolbarItems, 0, 0),
489 
490         message(0, 0, 0)
491     };
492 
493 
494     static message init_list_vista[] =
495     {
496         /* Some unknown messages here */
497         message(DUM_MSG_GetWindow, 0, 0),
498         /* Some unknown messages here, and multiple SFVM_GET_WEBVIEW_THEME + SFVM_GETSORTDEFAULTS + SFVM_GETCOLUMNSTREAM */
499         message(SFVM_SIZE, 0, 0),
500         message(SFVM_WINDOWCREATED, PTR_VALUE, 0),
501         /* Some unknown messages here */
502         message(DUM_MSG_InsertMenusSB, 0, 0),
503         message(SFVM_MERGEMENU, 0, PTR_VALUE),
504         message(DUM_MSG_SetMenuSB, 0, 0),
505 
506         message(0, 0, 0)
507     };
508 
509     if (g_WinVersion < WINVER_VISTA)
510     {
511         compare_list(init_list);
512     }
513     else
514     {
515         compare_list(init_list_vista);
516     }
517     clear_list();
518 
519     hr = psv->Refresh();
520     //ok_hex(hr, S_FALSE);
521 
522     static message refresh_list[] =
523     {
524         message(SFVM_LISTREFRESHED, 1, 0),
525 
526         message(SFVM_UNMERGEFROMMENU, 0, PTR_VALUE),
527         message(DUM_MSG_SetMenuSB, 0, 0),
528         message(DUM_MSG_RemoveMenusSB, 0, 0),
529         message(DUM_MSG_InsertMenusSB, 0, 0),
530         message(SFVM_MERGEMENU, 0, PTR_VALUE),
531         message(DUM_MSG_SetMenuSB, 0, 0),
532 
533         message(0, 0, 0)
534     };
535 
536     static message refresh_list_vista[] =
537     {
538         message(SFVM_LISTREFRESHED, 1, 0),
539 
540         message(SFVM_UNMERGEFROMMENU, 0, PTR_VALUE),
541         message(DUM_MSG_SetMenuSB, 0, 0),
542         message(DUM_MSG_RemoveMenusSB, 0, 0),
543         message(DUM_MSG_InsertMenusSB, 0, 0),
544         message(SFVM_MERGEMENU, 0, PTR_VALUE),
545         message(DUM_MSG_SetMenuSB, 0, 0),
546         /* Some messages here, like SFVM_GET_WEBVIEW_THEME, SFVM_GETSORTDEFAULTS, SFVM_GETCOLUMNSTREAM */
547         message(SFVM_UNMERGEFROMMENU, 0, PTR_VALUE),
548         message(DUM_MSG_SetMenuSB, 0, 0),
549         message(DUM_MSG_RemoveMenusSB, 0, 0),
550         message(DUM_MSG_InsertMenusSB, 0, 0),
551         message(SFVM_MERGEMENU, 0, PTR_VALUE),
552         message(DUM_MSG_SetMenuSB, 0, 0),
553 
554         message(0, 0, 0)
555     };
556 
557     if (g_WinVersion < WINVER_VISTA)
558     {
559         compare_list(refresh_list);
560     }
561     else
562     {
563         compare_list(refresh_list_vista);
564     }
565     clear_list();
566 
567     hr = psv->DestroyViewWindow();
568 
569     static message destroy_list[] =
570     {
571         message(SFVM_UNMERGEFROMMENU, 0, PTR_VALUE),
572         message(DUM_MSG_SetMenuSB, 0, 0),
573         message(DUM_MSG_RemoveMenusSB, 0, 0),
574         message(SFVM_WINDOWCLOSING, PTR_VALUE, 0),
575 
576         message(0, 0, 0)
577     };
578 
579     compare_list(destroy_list);
580     clear_list();
581 
582     CComPtr<IShellFolderView> folderView;
583     hr = psv->QueryInterface(IID_PPV_ARG(IShellFolderView, &folderView));
584     ok_hex(hr, S_OK);
585     if (SUCCEEDED(hr))
586     {
587         IShellFolderViewCB* oldPtr;
588 
589         g_AddRef = 0;
590         g_Release = 0;
591 
592         hr = folderView->SetCallback(NULL, &oldPtr);
593         ok_int(g_AddRef, 0);
594         ok_int(g_Release, 0);
595 
596         g_AddRef = 0;
597         g_Release = 0;
598 
599         /* Last pointer is not optional! */
600         IShellFolderViewCB* oldPtr2;
601         hr = folderView->SetCallback(oldPtr, &oldPtr2);
602         ok_int(g_AddRef, 1);
603         ok_int(g_Release, 0);
604     }
605 
606 
607     ULONG refCount = psv->Release();
608     ok(refCount == 0, "refCount = %lu\n", refCount);
609 
610     static message release_list[] =
611     {
612         message(SFVM_VIEWRELEASE, 0, 0),
613 
614         message(0, 0, 0)
615     };
616 
617     /* Investigate why this fails */
618     if (refCount == 0)
619     {
620         compare_list(release_list);
621     }
622 }
623