196c0f7d3SMark Jansen /*
296c0f7d3SMark Jansen  * PROJECT:     ReactOS API tests
396c0f7d3SMark Jansen  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
496c0f7d3SMark Jansen  * PURPOSE:     Test for IShellFolderViewCB
596c0f7d3SMark Jansen  * COPYRIGHT:   Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
696c0f7d3SMark Jansen  */
796c0f7d3SMark Jansen 
896c0f7d3SMark Jansen #include "shelltest.h"
996c0f7d3SMark Jansen #include <atlsimpcoll.h>
1096c0f7d3SMark Jansen #include <stdio.h>
1196c0f7d3SMark Jansen #include <shellutils.h>
1296c0f7d3SMark Jansen //#include <msgtrace.h>
1396c0f7d3SMark Jansen 
1496c0f7d3SMark Jansen static DWORD g_WinVersion;
1596c0f7d3SMark Jansen #define WINVER_VISTA   0x0600
1696c0f7d3SMark Jansen 
1796c0f7d3SMark Jansen #ifndef SFVM_SELECTIONCHANGED
1896c0f7d3SMark Jansen #define SFVM_SELECTIONCHANGED          8 /* undocumented */
1996c0f7d3SMark Jansen #define SFVM_DRAWMENUITEM              9 /* undocumented */
2096c0f7d3SMark Jansen #define SFVM_MEASUREMENUITEM          10 /* undocumented */
2196c0f7d3SMark Jansen #define SFVM_EXITMENULOOP             11 /* undocumented */
2296c0f7d3SMark Jansen #define SFVM_VIEWRELEASE              12 /* undocumented */
2396c0f7d3SMark Jansen #define SFVM_GETNAMELENGTH            13 /* undocumented */
2496c0f7d3SMark Jansen #define SFVM_WINDOWCLOSING            16 /* undocumented */
2596c0f7d3SMark Jansen #define SFVM_LISTREFRESHED            17 /* undocumented */
2696c0f7d3SMark Jansen #define SFVM_WINDOWFOCUSED            18 /* undocumented */
2796c0f7d3SMark Jansen #define SFVM_REGISTERCOPYHOOK         20 /* undocumented */
2896c0f7d3SMark Jansen #define SFVM_COPYHOOKCALLBACK         21 /* undocumented */
2996c0f7d3SMark Jansen #define SFVM_UNMERGEFROMMENU          28 /* undocumented */
3096c0f7d3SMark Jansen #define SFVM_ADDINGOBJECT             29 /* undocumented */
3196c0f7d3SMark Jansen #define SFVM_REMOVINGOBJECT           30 /* undocumented */
3296c0f7d3SMark Jansen #define SFVM_GETCOMMANDDIR            33 /* undocumented */
3396c0f7d3SMark Jansen #define SFVM_GETCOLUMNSTREAM          34 /* undocumented */
3496c0f7d3SMark Jansen #define SFVM_CANSELECTALL             35 /* undocumented */
3596c0f7d3SMark Jansen #define SFVM_ISSTRICTREFRESH          37 /* undocumented */
3696c0f7d3SMark Jansen #define SFVM_ISCHILDOBJECT            38 /* undocumented */
3796c0f7d3SMark Jansen #define SFVM_GETEXTVIEWS              40 /* undocumented */
3896c0f7d3SMark Jansen #define SFVM_GET_CUSTOMVIEWINFO       77 /* undocumented */
3996c0f7d3SMark Jansen #define SFVM_ENUMERATEDITEMS          79 /* undocumented */
4096c0f7d3SMark Jansen #define SFVM_GET_VIEW_DATA            80 /* undocumented */
4196c0f7d3SMark Jansen #define SFVM_GET_WEBVIEW_LAYOUT       82 /* undocumented */
4296c0f7d3SMark Jansen #define SFVM_GET_WEBVIEW_CONTENT      83 /* undocumented */
4396c0f7d3SMark Jansen #define SFVM_GET_WEBVIEW_TASKS        84 /* undocumented */
4496c0f7d3SMark Jansen #define SFVM_GET_WEBVIEW_THEME        86 /* undocumented */
4596c0f7d3SMark Jansen #define SFVM_GETDEFERREDVIEWSETTINGS  92 /* undocumented */
4696c0f7d3SMark Jansen #endif
4796c0f7d3SMark Jansen 
4896c0f7d3SMark Jansen #define DUM_MSG_GetWindow               400
4996c0f7d3SMark Jansen #define DUM_MSG_ContextSensitiveHelp    401
5096c0f7d3SMark Jansen #define DUM_MSG_InsertMenusSB           402
5196c0f7d3SMark Jansen #define DUM_MSG_SetMenuSB               403
5296c0f7d3SMark Jansen #define DUM_MSG_RemoveMenusSB           404
5396c0f7d3SMark Jansen #define DUM_MSG_SetStatusTextSB         405
5496c0f7d3SMark Jansen #define DUM_MSG_EnableModelessSB        406
5596c0f7d3SMark Jansen #define DUM_MSG_TranslateAcceleratorSB  407
5696c0f7d3SMark Jansen #define DUM_MSG_BrowseObject            408
5796c0f7d3SMark Jansen #define DUM_MSG_GetViewStateStream      409
5896c0f7d3SMark Jansen #define DUM_MSG_GetControlWindow        410
5996c0f7d3SMark Jansen #define DUM_MSG_SendControlMsg          411
6096c0f7d3SMark Jansen #define DUM_MSG_QueryActiveShellView    412
6196c0f7d3SMark Jansen #define DUM_MSG_OnViewWindowActive      413
6296c0f7d3SMark Jansen #define DUM_MSG_SetToolbarItems         414
6396c0f7d3SMark Jansen 
6496c0f7d3SMark Jansen 
msg2str(UINT uMsg)6596c0f7d3SMark Jansen const char* msg2str(UINT uMsg)
6696c0f7d3SMark Jansen {
6796c0f7d3SMark Jansen     static char buf[2][50];
6896c0f7d3SMark Jansen     static int index = 0;
6996c0f7d3SMark Jansen     index ^= 1;
7096c0f7d3SMark Jansen 
7196c0f7d3SMark Jansen     switch (uMsg)
7296c0f7d3SMark Jansen     {
7396c0f7d3SMark Jansen     case SFVM_MERGEMENU: return "SFVM_MERGEMENU";
7496c0f7d3SMark Jansen     case SFVM_INVOKECOMMAND: return "SFVM_INVOKECOMMAND";
7596c0f7d3SMark Jansen     case SFVM_GETHELPTEXT: return "SFVM_GETHELPTEXT";
7696c0f7d3SMark Jansen     case SFVM_GETTOOLTIPTEXT: return "SFVM_GETTOOLTIPTEXT";
7796c0f7d3SMark Jansen     case SFVM_GETBUTTONINFO: return "SFVM_GETBUTTONINFO";
7896c0f7d3SMark Jansen     case SFVM_GETBUTTONS: return "SFVM_GETBUTTONS";
7996c0f7d3SMark Jansen     case SFVM_INITMENUPOPUP: return "SFVM_INITMENUPOPUP";
8096c0f7d3SMark Jansen     case SFVM_SELECTIONCHANGED: return "SFVM_SELECTIONCHANGED";
8196c0f7d3SMark Jansen     case SFVM_DRAWMENUITEM: return "SFVM_DRAWMENUITEM";
8296c0f7d3SMark Jansen     case SFVM_MEASUREMENUITEM: return "SFVM_MEASUREMENUITEM";
8396c0f7d3SMark Jansen     case SFVM_EXITMENULOOP: return "SFVM_EXITMENULOOP";
8496c0f7d3SMark Jansen     case SFVM_VIEWRELEASE: return "SFVM_VIEWRELEASE";
8596c0f7d3SMark Jansen     case SFVM_GETNAMELENGTH: return "SFVM_GETNAMELENGTH";
8696c0f7d3SMark Jansen     case SFVM_FSNOTIFY: return "SFVM_FSNOTIFY";
8796c0f7d3SMark Jansen     case SFVM_WINDOWCREATED: return "SFVM_WINDOWCREATED";
8896c0f7d3SMark Jansen     case SFVM_WINDOWCLOSING: return "SFVM_WINDOWCLOSING";
8996c0f7d3SMark Jansen     case SFVM_LISTREFRESHED: return "SFVM_LISTREFRESHED";
9096c0f7d3SMark Jansen     case SFVM_WINDOWFOCUSED: return "SFVM_WINDOWFOCUSED";
9196c0f7d3SMark Jansen     case SFVM_REGISTERCOPYHOOK: return "SFVM_REGISTERCOPYHOOK";
9296c0f7d3SMark Jansen     case SFVM_COPYHOOKCALLBACK: return "SFVM_COPYHOOKCALLBACK";
9396c0f7d3SMark Jansen     case SFVM_GETDETAILSOF: return "SFVM_GETDETAILSOF";
9496c0f7d3SMark Jansen     case SFVM_COLUMNCLICK: return "SFVM_COLUMNCLICK";
9596c0f7d3SMark Jansen     case SFVM_QUERYFSNOTIFY: return "SFVM_QUERYFSNOTIFY";
9696c0f7d3SMark Jansen     case SFVM_DEFITEMCOUNT: return "SFVM_DEFITEMCOUNT";
9796c0f7d3SMark Jansen     case SFVM_DEFVIEWMODE: return "SFVM_DEFVIEWMODE";
9896c0f7d3SMark Jansen     case SFVM_UNMERGEFROMMENU: return "SFVM_UNMERGEFROMMENU";
9996c0f7d3SMark Jansen     case SFVM_ADDINGOBJECT: return "SFVM_ADDINGOBJECT";
10096c0f7d3SMark Jansen     case SFVM_REMOVINGOBJECT: return "SFVM_REMOVINGOBJECT";
10196c0f7d3SMark Jansen     case SFVM_UPDATESTATUSBAR: return "SFVM_UPDATESTATUSBAR";
10296c0f7d3SMark Jansen     case SFVM_BACKGROUNDENUM: return "SFVM_BACKGROUNDENUM";
10396c0f7d3SMark Jansen     case SFVM_GETCOMMANDDIR: return "SFVM_GETCOMMANDDIR";
10496c0f7d3SMark Jansen     case SFVM_GETCOLUMNSTREAM: return "SFVM_GETCOLUMNSTREAM";
10596c0f7d3SMark Jansen     case SFVM_CANSELECTALL: return "SFVM_CANSELECTALL";
10696c0f7d3SMark Jansen     case SFVM_DIDDRAGDROP: return "SFVM_DIDDRAGDROP";
10796c0f7d3SMark Jansen     case SFVM_ISSTRICTREFRESH: return "SFVM_ISSTRICTREFRESH";
10896c0f7d3SMark Jansen     case SFVM_ISCHILDOBJECT: return "SFVM_ISCHILDOBJECT";
10996c0f7d3SMark Jansen     case SFVM_SETISFV: return "SFVM_SETISFV";
11096c0f7d3SMark Jansen     case SFVM_GETEXTVIEWS: return "SFVM_GETEXTVIEWS";
11196c0f7d3SMark Jansen     case SFVM_THISIDLIST: return "SFVM_THISIDLIST";
11296c0f7d3SMark Jansen     case SFVM_ADDPROPERTYPAGES: return "SFVM_ADDPROPERTYPAGES";
11396c0f7d3SMark Jansen     case SFVM_BACKGROUNDENUMDONE: return "SFVM_BACKGROUNDENUMDONE";
11496c0f7d3SMark Jansen     case SFVM_GETNOTIFY: return "SFVM_GETNOTIFY";
11596c0f7d3SMark Jansen     case SFVM_GETSORTDEFAULTS: return "SFVM_GETSORTDEFAULTS";
11696c0f7d3SMark Jansen     case SFVM_SIZE: return "SFVM_SIZE";
11796c0f7d3SMark Jansen     case SFVM_GETZONE: return "SFVM_GETZONE";
11896c0f7d3SMark Jansen     case SFVM_GETPANE: return "SFVM_GETPANE";
11996c0f7d3SMark Jansen     case SFVM_GETHELPTOPIC: return "SFVM_GETHELPTOPIC";
12096c0f7d3SMark Jansen     case SFVM_GETANIMATION: return "SFVM_GETANIMATION";
12196c0f7d3SMark Jansen     case SFVM_GET_CUSTOMVIEWINFO: return "SFVM_GET_CUSTOMVIEWINFO";
12296c0f7d3SMark Jansen     case SFVM_ENUMERATEDITEMS: return "SFVM_ENUMERATEDITEMS";
12396c0f7d3SMark Jansen     case SFVM_GET_VIEW_DATA: return "SFVM_GET_VIEW_DATA";
12496c0f7d3SMark Jansen     case SFVM_GET_WEBVIEW_LAYOUT: return "SFVM_GET_WEBVIEW_LAYOUT";
12596c0f7d3SMark Jansen     case SFVM_GET_WEBVIEW_CONTENT: return "SFVM_GET_WEBVIEW_CONTENT";
12696c0f7d3SMark Jansen     case SFVM_GET_WEBVIEW_TASKS: return "SFVM_GET_WEBVIEW_TASKS";
12796c0f7d3SMark Jansen     case SFVM_GET_WEBVIEW_THEME: return "SFVM_GET_WEBVIEW_THEME";
12896c0f7d3SMark Jansen     case SFVM_GETDEFERREDVIEWSETTINGS: return "SFVM_GET_WEBVIEW_THEME";
12996c0f7d3SMark Jansen 
13096c0f7d3SMark Jansen     case DUM_MSG_GetWindow: return "|GetWindow|";
13196c0f7d3SMark Jansen     case DUM_MSG_ContextSensitiveHelp: return "|ContextSensitiveHelp|";
13296c0f7d3SMark Jansen     case DUM_MSG_InsertMenusSB: return "|InsertMenusSB|";
13396c0f7d3SMark Jansen     case DUM_MSG_SetMenuSB: return "|SetMenuSB|";
13496c0f7d3SMark Jansen     case DUM_MSG_RemoveMenusSB: return "|RemoveMenusSB|";
13596c0f7d3SMark Jansen     case DUM_MSG_SetStatusTextSB: return "|SetStatusTextSB|";
13696c0f7d3SMark Jansen     case DUM_MSG_EnableModelessSB: return "|EnableModelessSB|";
13796c0f7d3SMark Jansen     case DUM_MSG_TranslateAcceleratorSB: return "|TranslateAcceleratorSB|";
13896c0f7d3SMark Jansen     case DUM_MSG_BrowseObject: return "|BrowseObject|";
13996c0f7d3SMark Jansen     case DUM_MSG_GetViewStateStream: return "|GetViewStateStream|";
14096c0f7d3SMark Jansen     case DUM_MSG_GetControlWindow: return "|GetControlWindow|";
14196c0f7d3SMark Jansen     case DUM_MSG_SendControlMsg: return "|SendControlMsg|";
14296c0f7d3SMark Jansen     case DUM_MSG_QueryActiveShellView: return "|QueryActiveShellView|";
14396c0f7d3SMark Jansen     case DUM_MSG_OnViewWindowActive: return "|OnViewWindowActive|";
14496c0f7d3SMark Jansen     case DUM_MSG_SetToolbarItems: return "|SetToolbarItems|";
14596c0f7d3SMark Jansen     default:
14696c0f7d3SMark Jansen         sprintf(buf[index], "[%u]", uMsg);
14796c0f7d3SMark Jansen         return buf[index];
14896c0f7d3SMark Jansen     }
14996c0f7d3SMark Jansen }
15096c0f7d3SMark Jansen 
15196c0f7d3SMark Jansen 
15296c0f7d3SMark Jansen #define PTR_VALUE   0xf7f7f7f7
15396c0f7d3SMark Jansen 
15496c0f7d3SMark Jansen struct message
15596c0f7d3SMark Jansen {
messagemessage15696c0f7d3SMark Jansen     message(UINT msg, WPARAM wp, LPARAM lp) : uMsg(msg), wParam(wp), lParam(lp) { ; }
15796c0f7d3SMark Jansen 
15896c0f7d3SMark Jansen     UINT uMsg;
15996c0f7d3SMark Jansen     WPARAM wParam;
16096c0f7d3SMark Jansen     LPARAM lParam;
16196c0f7d3SMark Jansen };
16296c0f7d3SMark Jansen 
16396c0f7d3SMark Jansen CSimpleArray<message> g_Received;
16496c0f7d3SMark Jansen 
clear_list()16596c0f7d3SMark Jansen void clear_list()
16696c0f7d3SMark Jansen {
16796c0f7d3SMark Jansen     g_Received.RemoveAll();
16896c0f7d3SMark Jansen }
16996c0f7d3SMark Jansen 
add_msg(UINT uMsg,WPARAM wParam,LPARAM lParam)17096c0f7d3SMark Jansen void add_msg(UINT uMsg, WPARAM wParam, LPARAM lParam)
17196c0f7d3SMark Jansen {
17296c0f7d3SMark Jansen     g_Received.Add(message(uMsg, wParam, lParam));
17396c0f7d3SMark Jansen }
17496c0f7d3SMark Jansen 
print_list_(const CSimpleArray<message> & input,const char * file,int line)17596c0f7d3SMark Jansen void print_list_(const CSimpleArray<message>& input, const char* file, int line)
17696c0f7d3SMark Jansen {
17796c0f7d3SMark Jansen     trace_(file, line)("Got list:\n");
17896c0f7d3SMark Jansen     for (int n = 0; n < input.GetSize(); ++n)
17996c0f7d3SMark Jansen     {
18096c0f7d3SMark Jansen         const message& msg = input[n];
18196c0f7d3SMark Jansen         trace_(file, line)("msg: %d(%s), wParam:0x%x, lParam:0x%lx\n", msg.uMsg, msg2str(msg.uMsg), msg.wParam, msg.lParam);
18296c0f7d3SMark Jansen     }
18396c0f7d3SMark Jansen     trace_(file, line)("End of list.\n");
18496c0f7d3SMark Jansen }
18596c0f7d3SMark Jansen 
compare_list_(const CSimpleArray<message> & input,const message * compare,const char * file,int line)18696c0f7d3SMark Jansen void compare_list_(const CSimpleArray<message>& input, const message* compare, const char* file, int line)
18796c0f7d3SMark Jansen {
18896c0f7d3SMark Jansen     int input_item = 0;
18996c0f7d3SMark Jansen     int compare_item = 0;
19096c0f7d3SMark Jansen     LONG old_failures = winetest_get_failures();
19196c0f7d3SMark Jansen     while (compare[compare_item].uMsg && input_item < input.GetSize())
19296c0f7d3SMark Jansen     {
19396c0f7d3SMark Jansen         const message& inp = input[input_item];
19496c0f7d3SMark Jansen         const message& cmp = compare[compare_item];
19596c0f7d3SMark Jansen         if (cmp.uMsg == inp.uMsg)
19696c0f7d3SMark Jansen         {
19796c0f7d3SMark Jansen             if (cmp.lParam != (LPARAM)PTR_VALUE)
19896c0f7d3SMark Jansen             {
19996c0f7d3SMark Jansen                 ok_(file, line)(cmp.lParam == inp.lParam, "Expected lParam to be 0x%lx, was 0x%lx for %i(%s)\n",
20096c0f7d3SMark Jansen                                 cmp.lParam, inp.lParam, compare_item, msg2str(cmp.uMsg));
20196c0f7d3SMark Jansen             }
20296c0f7d3SMark Jansen             else
20396c0f7d3SMark Jansen             {
20496c0f7d3SMark Jansen                 ok_(file, line)(inp.lParam != 0, "Expected lParam to be a pointer, was 0 for %i(%s)\n",
20596c0f7d3SMark Jansen                                 compare_item, msg2str(cmp.uMsg));
20696c0f7d3SMark Jansen             }
20796c0f7d3SMark Jansen             if (cmp.wParam != PTR_VALUE)
20896c0f7d3SMark Jansen             {
20996c0f7d3SMark Jansen                 ok_(file, line)(cmp.wParam == inp.wParam, "Expected wParam to be 0x%x, was 0x%x for %i(%s)\n",
21096c0f7d3SMark Jansen                                 cmp.wParam, inp.wParam, compare_item, msg2str(cmp.uMsg));
21196c0f7d3SMark Jansen             }
21296c0f7d3SMark Jansen             else
21396c0f7d3SMark Jansen             {
21496c0f7d3SMark Jansen                 ok_(file, line)(inp.wParam != 0, "Expected wParam to be a pointer, was 0 for %i(%s)\n",
21596c0f7d3SMark Jansen                                 compare_item, msg2str(cmp.uMsg));
21696c0f7d3SMark Jansen             }
21796c0f7d3SMark Jansen             compare_item++;
21896c0f7d3SMark Jansen         }
21996c0f7d3SMark Jansen         else
22096c0f7d3SMark Jansen         {
22196c0f7d3SMark Jansen             /* We skip unknown items for now */
22296c0f7d3SMark Jansen         }
22396c0f7d3SMark Jansen 
22496c0f7d3SMark Jansen         input_item++;
22596c0f7d3SMark Jansen     }
22696c0f7d3SMark Jansen 
22796c0f7d3SMark Jansen     while (compare[compare_item].uMsg)
22896c0f7d3SMark Jansen     {
22996c0f7d3SMark Jansen         ok_(file, line)(0, "Message %i(%s) not found\n", compare_item, msg2str(compare[compare_item].uMsg));
23096c0f7d3SMark Jansen         compare_item++;
23196c0f7d3SMark Jansen     }
23296c0f7d3SMark Jansen     if (old_failures != winetest_get_failures())
23396c0f7d3SMark Jansen     {
23496c0f7d3SMark Jansen         print_list_(input, file, line);
23596c0f7d3SMark Jansen     }
23696c0f7d3SMark Jansen }
23796c0f7d3SMark Jansen 
23896c0f7d3SMark Jansen #define compare_list(cmp)   compare_list_(g_Received, cmp, __FILE__, __LINE__)
23996c0f7d3SMark Jansen #define print_list()        print_list_(g_Received, __FILE__, __LINE__)
24096c0f7d3SMark Jansen 
24196c0f7d3SMark Jansen 
24296c0f7d3SMark Jansen LONG g_AddRef = 0;
24396c0f7d3SMark Jansen LONG g_Release = 0;
24496c0f7d3SMark Jansen 
24596c0f7d3SMark Jansen class CFolderViewCB :
24696c0f7d3SMark Jansen     public IShellFolderViewCB
24796c0f7d3SMark Jansen {
24896c0f7d3SMark Jansen public:
CFolderViewCB(void)249*465745b6STimo Kreuzer     CFolderViewCB(void) :
250*465745b6STimo Kreuzer         m_RefCount(1)
251*465745b6STimo Kreuzer     {
252*465745b6STimo Kreuzer     }
QueryInterface(REFIID riid,void ** ppvObject)25396c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void  **ppvObject)
25496c0f7d3SMark Jansen     {
255*465745b6STimo Kreuzer         if (riid == IID_IShellFolderViewCB)
25696c0f7d3SMark Jansen         {
257*465745b6STimo Kreuzer             *ppvObject = static_cast<IShellFolderViewCB*>(this);
25896c0f7d3SMark Jansen             AddRef();
25996c0f7d3SMark Jansen             return S_OK;
26096c0f7d3SMark Jansen         }
26196c0f7d3SMark Jansen         return E_NOINTERFACE;
26296c0f7d3SMark Jansen     }
AddRef(void)26396c0f7d3SMark Jansen     virtual ULONG STDMETHODCALLTYPE AddRef(void)
26496c0f7d3SMark Jansen     {
26596c0f7d3SMark Jansen         InterlockedIncrement(&g_AddRef);
266*465745b6STimo Kreuzer         return InterlockedIncrement(&m_RefCount);
26796c0f7d3SMark Jansen     }
Release(void)26896c0f7d3SMark Jansen     virtual ULONG STDMETHODCALLTYPE Release(void)
26996c0f7d3SMark Jansen     {
27096c0f7d3SMark Jansen         InterlockedIncrement(&g_Release);
271*465745b6STimo Kreuzer         return InterlockedDecrement(&m_RefCount);
27296c0f7d3SMark Jansen     }
MessageSFVCB(UINT uMsg,WPARAM wParam,LPARAM lParam)27396c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
27496c0f7d3SMark Jansen     {
27596c0f7d3SMark Jansen         //DbgPrint("MessageSFVCB(uMsg:%s, wParam:%u, lParam:%u\n", msg2str(uMsg), wParam, lParam);
27696c0f7d3SMark Jansen         add_msg(uMsg, wParam, lParam);
27796c0f7d3SMark Jansen         return E_NOTIMPL;
27896c0f7d3SMark Jansen     }
279*465745b6STimo Kreuzer private:
280*465745b6STimo Kreuzer     LONG m_RefCount;
28196c0f7d3SMark Jansen };
28296c0f7d3SMark Jansen 
28396c0f7d3SMark Jansen 
WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)28496c0f7d3SMark Jansen static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
28596c0f7d3SMark Jansen {
28696c0f7d3SMark Jansen     if (msg == WM_DESTROY)
28796c0f7d3SMark Jansen     {
28896c0f7d3SMark Jansen         PostQuitMessage(0);
28996c0f7d3SMark Jansen         return 0;
29096c0f7d3SMark Jansen     }
29196c0f7d3SMark Jansen     return DefWindowProc(hwnd, msg, wParam, lParam);
29296c0f7d3SMark Jansen }
29396c0f7d3SMark Jansen 
29496c0f7d3SMark Jansen 
29596c0f7d3SMark Jansen class CDummyShellBrowser : public IShellBrowser
29696c0f7d3SMark Jansen {
29796c0f7d3SMark Jansen public:
29896c0f7d3SMark Jansen     HWND m_hwnd;
CDummyShellBrowser()29996c0f7d3SMark Jansen     CDummyShellBrowser()
30096c0f7d3SMark Jansen     {
30196c0f7d3SMark Jansen         static const TCHAR* class_name = TEXT("DUMMY_TEST_CLASS");
30296c0f7d3SMark Jansen         WNDCLASSEX wx = {};
30396c0f7d3SMark Jansen         wx.cbSize = sizeof(WNDCLASSEX);
30496c0f7d3SMark Jansen         wx.lpfnWndProc = WndProc;
30596c0f7d3SMark Jansen         wx.hInstance = GetModuleHandle(NULL);
30696c0f7d3SMark Jansen         wx.lpszClassName = class_name;
30796c0f7d3SMark Jansen         wx.style = CS_DBLCLKS;
30896c0f7d3SMark Jansen         RegisterClassEx(&wx);
30996c0f7d3SMark Jansen         m_hwnd = CreateWindowEx(0, class_name, TEXT("dummy_name"), WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
31096c0f7d3SMark Jansen         ShowWindow(m_hwnd, SW_SHOW);
31196c0f7d3SMark Jansen     }
31296c0f7d3SMark Jansen 
31396c0f7d3SMark Jansen     // *** IUnknown methods ***
QueryInterface(REFIID riid,void ** ppvObject)31496c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void  **ppvObject)
31596c0f7d3SMark Jansen     {
31696c0f7d3SMark Jansen         if (riid == IID_IShellBrowser || riid == IID_IUnknown)
31796c0f7d3SMark Jansen         {
31896c0f7d3SMark Jansen             *ppvObject = this;
31996c0f7d3SMark Jansen             return S_OK;
32096c0f7d3SMark Jansen         }
32196c0f7d3SMark Jansen         return E_NOINTERFACE;
32296c0f7d3SMark Jansen     }
AddRef(void)32396c0f7d3SMark Jansen     virtual ULONG STDMETHODCALLTYPE AddRef(void)
32496c0f7d3SMark Jansen     {
32596c0f7d3SMark Jansen         return 2;
32696c0f7d3SMark Jansen     }
Release(void)32796c0f7d3SMark Jansen     virtual ULONG STDMETHODCALLTYPE Release(void)
32896c0f7d3SMark Jansen     {
32996c0f7d3SMark Jansen         return 1;
33096c0f7d3SMark Jansen     }
33196c0f7d3SMark Jansen 
33296c0f7d3SMark Jansen     // *** IOleWindow methods ***
GetWindow(HWND * phwnd)33396c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd)
33496c0f7d3SMark Jansen     {
33596c0f7d3SMark Jansen         //DbgPrint("%s()\n", __FUNCTION__);
33696c0f7d3SMark Jansen         *phwnd = m_hwnd;
33796c0f7d3SMark Jansen         add_msg(DUM_MSG_GetWindow, NULL, NULL);
33896c0f7d3SMark Jansen         return S_OK;
33996c0f7d3SMark Jansen     }
ContextSensitiveHelp(BOOL fEnterMode)34096c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode)
34196c0f7d3SMark Jansen     {
34296c0f7d3SMark Jansen         //DbgPrint("%s()\n", __FUNCTION__);
34396c0f7d3SMark Jansen         add_msg(DUM_MSG_ContextSensitiveHelp, NULL, NULL);
34496c0f7d3SMark Jansen         return E_NOTIMPL;
34596c0f7d3SMark Jansen     }
34696c0f7d3SMark Jansen 
34796c0f7d3SMark Jansen     // *** IShellBrowser methods ***
InsertMenusSB(HMENU hmenuShared,LPOLEMENUGROUPWIDTHS lpMenuWidths)34896c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE InsertMenusSB(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
34996c0f7d3SMark Jansen     {
35096c0f7d3SMark Jansen         //DbgPrint("%s()\n", __FUNCTION__);
35196c0f7d3SMark Jansen         add_msg(DUM_MSG_InsertMenusSB, NULL, NULL);
35296c0f7d3SMark Jansen         return S_OK;
35396c0f7d3SMark Jansen     }
SetMenuSB(HMENU hmenuShared,HOLEMENU holemenuRes,HWND hwndActiveObject)35496c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE SetMenuSB(HMENU hmenuShared, HOLEMENU holemenuRes, HWND hwndActiveObject)
35596c0f7d3SMark Jansen     {
35696c0f7d3SMark Jansen         //DbgPrint("%s()\n", __FUNCTION__);
35796c0f7d3SMark Jansen         add_msg(DUM_MSG_SetMenuSB, NULL, NULL);
35896c0f7d3SMark Jansen         return S_OK;
35996c0f7d3SMark Jansen     }
RemoveMenusSB(HMENU hmenuShared)36096c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE RemoveMenusSB(HMENU hmenuShared)
36196c0f7d3SMark Jansen     {
36296c0f7d3SMark Jansen         //DbgPrint("%s()\n", __FUNCTION__);
36396c0f7d3SMark Jansen         add_msg(DUM_MSG_RemoveMenusSB, NULL, NULL);
36496c0f7d3SMark Jansen         return E_NOTIMPL;
36596c0f7d3SMark Jansen     }
SetStatusTextSB(LPCWSTR pszStatusText)36696c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE SetStatusTextSB(LPCWSTR pszStatusText)
36796c0f7d3SMark Jansen     {
36896c0f7d3SMark Jansen         //DbgPrint("%s()\n", __FUNCTION__);
36996c0f7d3SMark Jansen         add_msg(DUM_MSG_SetStatusTextSB, NULL, NULL);
37096c0f7d3SMark Jansen         return E_NOTIMPL;
37196c0f7d3SMark Jansen     }
EnableModelessSB(BOOL fEnable)37296c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE EnableModelessSB(BOOL fEnable)
37396c0f7d3SMark Jansen     {
37496c0f7d3SMark Jansen         //DbgPrint("%s()\n", __FUNCTION__);
37596c0f7d3SMark Jansen         add_msg(DUM_MSG_EnableModelessSB, NULL, NULL);
37696c0f7d3SMark Jansen         return E_NOTIMPL;
37796c0f7d3SMark Jansen     }
TranslateAcceleratorSB(MSG * pmsg,WORD wID)37896c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorSB(MSG *pmsg, WORD wID)
37996c0f7d3SMark Jansen     {
38096c0f7d3SMark Jansen         //DbgPrint("%s()\n", __FUNCTION__);
38196c0f7d3SMark Jansen         add_msg(DUM_MSG_TranslateAcceleratorSB, NULL, NULL);
38296c0f7d3SMark Jansen         return E_NOTIMPL;
38396c0f7d3SMark Jansen     }
BrowseObject(PCUIDLIST_RELATIVE pidl,UINT wFlags)38496c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE BrowseObject(PCUIDLIST_RELATIVE pidl,UINT wFlags)
38596c0f7d3SMark Jansen     {
38696c0f7d3SMark Jansen         //DbgPrint("%s()\n", __FUNCTION__);
38796c0f7d3SMark Jansen         add_msg(DUM_MSG_BrowseObject, NULL, NULL);
38896c0f7d3SMark Jansen         return E_NOTIMPL;
38996c0f7d3SMark Jansen     }
GetViewStateStream(DWORD grfMode,IStream ** ppStrm)39096c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE GetViewStateStream(DWORD grfMode,IStream **ppStrm)
39196c0f7d3SMark Jansen     {
39296c0f7d3SMark Jansen         //DbgPrint("%s()\n", __FUNCTION__);
39396c0f7d3SMark Jansen         add_msg(DUM_MSG_GetViewStateStream, NULL, NULL);
39496c0f7d3SMark Jansen         return E_NOTIMPL;
39596c0f7d3SMark Jansen     }
GetControlWindow(UINT id,HWND * phwnd)39696c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE GetControlWindow(UINT id,HWND *phwnd)
39796c0f7d3SMark Jansen     {
39896c0f7d3SMark Jansen         //DbgPrint("%s()\n", __FUNCTION__);
39996c0f7d3SMark Jansen         add_msg(DUM_MSG_GetControlWindow, NULL, NULL);
40096c0f7d3SMark Jansen         return E_NOTIMPL;
40196c0f7d3SMark Jansen     }
SendControlMsg(UINT id,UINT uMsg,WPARAM wParam,LPARAM lParam,LRESULT * pret)40296c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE SendControlMsg(UINT id,UINT uMsg,WPARAM wParam,LPARAM lParam,LRESULT *pret)
40396c0f7d3SMark Jansen     {
40496c0f7d3SMark Jansen         //DbgPrint("%s()\n", __FUNCTION__);
40596c0f7d3SMark Jansen         add_msg(DUM_MSG_SendControlMsg, NULL, NULL);
40696c0f7d3SMark Jansen         return E_NOTIMPL;
40796c0f7d3SMark Jansen     }
QueryActiveShellView(IShellView ** ppshv)40896c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE QueryActiveShellView(IShellView **ppshv)
40996c0f7d3SMark Jansen     {
41096c0f7d3SMark Jansen         //DbgPrint("%s()\n", __FUNCTION__);
41196c0f7d3SMark Jansen         add_msg(DUM_MSG_QueryActiveShellView, NULL, NULL);
41296c0f7d3SMark Jansen         return E_NOTIMPL;
41396c0f7d3SMark Jansen     }
OnViewWindowActive(IShellView * pshv)41496c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE OnViewWindowActive(IShellView *pshv)
41596c0f7d3SMark Jansen     {
41696c0f7d3SMark Jansen         //DbgPrint("%s()\n", __FUNCTION__);
41796c0f7d3SMark Jansen         add_msg(DUM_MSG_OnViewWindowActive, NULL, NULL);
41896c0f7d3SMark Jansen         return E_NOTIMPL;
41996c0f7d3SMark Jansen     }
SetToolbarItems(LPTBBUTTONSB lpButtons,UINT nButtons,UINT uFlags)42096c0f7d3SMark Jansen     virtual HRESULT STDMETHODCALLTYPE SetToolbarItems(LPTBBUTTONSB lpButtons,UINT nButtons,UINT uFlags)
42196c0f7d3SMark Jansen     {
42296c0f7d3SMark Jansen         //DbgPrint("%s()\n", __FUNCTION__);
42396c0f7d3SMark Jansen         add_msg(DUM_MSG_SetToolbarItems, NULL, NULL);
42496c0f7d3SMark Jansen         return E_NOTIMPL;
42596c0f7d3SMark Jansen     }
42696c0f7d3SMark Jansen };
42796c0f7d3SMark Jansen 
42896c0f7d3SMark Jansen 
START_TEST(IShellFolderViewCB)42996c0f7d3SMark Jansen START_TEST(IShellFolderViewCB)
43096c0f7d3SMark Jansen {
43196c0f7d3SMark Jansen     RTL_OSVERSIONINFOEXW rtlinfo = { sizeof(rtlinfo) };
43296c0f7d3SMark Jansen     void (__stdcall* pRtlGetVersion)(RTL_OSVERSIONINFOEXW*);
43396c0f7d3SMark Jansen     pRtlGetVersion = (void (__stdcall*)(RTL_OSVERSIONINFOEXW*))GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");
43496c0f7d3SMark Jansen     pRtlGetVersion(&rtlinfo);
43596c0f7d3SMark Jansen     g_WinVersion = (rtlinfo.dwMajorVersion << 8) | rtlinfo.dwMinorVersion;
43696c0f7d3SMark Jansen 
43796c0f7d3SMark Jansen     CoInitialize(NULL);
43896c0f7d3SMark Jansen     CFolderViewCB cb;
43996c0f7d3SMark Jansen 
44096c0f7d3SMark Jansen     CComPtr<IShellFolder> desktop;
44196c0f7d3SMark Jansen 
44296c0f7d3SMark Jansen     HRESULT hr = SHGetDesktopFolder(&desktop);
44396c0f7d3SMark Jansen     ok_hex(hr, S_OK);
44496c0f7d3SMark Jansen     if (!desktop)
44596c0f7d3SMark Jansen         return;
44696c0f7d3SMark Jansen 
44796c0f7d3SMark Jansen     SFV_CREATE sfvc = { sizeof(sfvc), desktop };
44896c0f7d3SMark Jansen     sfvc.psfvcb = &cb;
44996c0f7d3SMark Jansen     IShellView* psv = NULL;
45096c0f7d3SMark Jansen 
45196c0f7d3SMark Jansen     g_AddRef = 0;
45296c0f7d3SMark Jansen     g_Release = 0;
45396c0f7d3SMark Jansen 
45496c0f7d3SMark Jansen     hr = SHCreateShellFolderView(&sfvc, &psv);
45596c0f7d3SMark Jansen     ok_hex(hr, S_OK);
45696c0f7d3SMark Jansen     if (!SUCCEEDED(hr))
45796c0f7d3SMark Jansen         return;
45896c0f7d3SMark Jansen 
459*465745b6STimo Kreuzer     ok_int(g_AddRef, 1);
46096c0f7d3SMark Jansen     ok_int(g_Release, 0);
46196c0f7d3SMark Jansen 
46296c0f7d3SMark Jansen     clear_list();
46396c0f7d3SMark Jansen 
46496c0f7d3SMark Jansen     HWND wnd;
46596c0f7d3SMark Jansen     RECT rc = { 0 };
46696c0f7d3SMark Jansen     FOLDERSETTINGS fs = { FVM_DETAILS, 0 };
46796c0f7d3SMark Jansen     CDummyShellBrowser dum;
46896c0f7d3SMark Jansen     hr = psv->CreateViewWindow(NULL, &fs, &dum, &rc, &wnd);
46996c0f7d3SMark Jansen 
47096c0f7d3SMark Jansen 
47196c0f7d3SMark Jansen     static message init_list[] =
47296c0f7d3SMark Jansen     {
47396c0f7d3SMark Jansen         /* ... */
47496c0f7d3SMark Jansen         message(DUM_MSG_GetWindow, 0, 0),
47596c0f7d3SMark Jansen         /* Some unknown messages here, and multiple SFVM_GET_WEBVIEW_THEME + SFVM_GETSORTDEFAULTS + SFVM_GETCOLUMNSTREAM */
47696c0f7d3SMark Jansen         message(SFVM_SIZE, 0, 0),
47796c0f7d3SMark Jansen         /* ... */
47896c0f7d3SMark Jansen         message(DUM_MSG_InsertMenusSB, 0, 0),
47996c0f7d3SMark Jansen         message(SFVM_MERGEMENU, 0, PTR_VALUE),
48096c0f7d3SMark Jansen         message(DUM_MSG_SetMenuSB, 0, 0),
48196c0f7d3SMark Jansen         /* ... */
48296c0f7d3SMark Jansen         message(SFVM_WINDOWCREATED, PTR_VALUE, 0),
48396c0f7d3SMark Jansen         /* ... */
48496c0f7d3SMark Jansen 
48596c0f7d3SMark Jansen         message(SFVM_GETBUTTONINFO, 0, PTR_VALUE),
48696c0f7d3SMark Jansen         message(SFVM_GETBUTTONS, PTR_VALUE, PTR_VALUE),
48796c0f7d3SMark Jansen         message(DUM_MSG_SetToolbarItems, 0, 0),
48896c0f7d3SMark Jansen 
48996c0f7d3SMark Jansen         message(0, 0, 0)
49096c0f7d3SMark Jansen     };
49196c0f7d3SMark Jansen 
49296c0f7d3SMark Jansen 
49396c0f7d3SMark Jansen     static message init_list_vista[] =
49496c0f7d3SMark Jansen     {
49596c0f7d3SMark Jansen         /* Some unknown messages here */
49696c0f7d3SMark Jansen         message(DUM_MSG_GetWindow, 0, 0),
49796c0f7d3SMark Jansen         /* Some unknown messages here, and multiple SFVM_GET_WEBVIEW_THEME + SFVM_GETSORTDEFAULTS + SFVM_GETCOLUMNSTREAM */
49896c0f7d3SMark Jansen         message(SFVM_SIZE, 0, 0),
49996c0f7d3SMark Jansen         message(SFVM_WINDOWCREATED, PTR_VALUE, 0),
50096c0f7d3SMark Jansen         /* Some unknown messages here */
50196c0f7d3SMark Jansen         message(DUM_MSG_InsertMenusSB, 0, 0),
50296c0f7d3SMark Jansen         message(SFVM_MERGEMENU, 0, PTR_VALUE),
50396c0f7d3SMark Jansen         message(DUM_MSG_SetMenuSB, 0, 0),
50496c0f7d3SMark Jansen 
50596c0f7d3SMark Jansen         message(0, 0, 0)
50696c0f7d3SMark Jansen     };
50796c0f7d3SMark Jansen 
50896c0f7d3SMark Jansen     if (g_WinVersion < WINVER_VISTA)
50996c0f7d3SMark Jansen     {
51096c0f7d3SMark Jansen         compare_list(init_list);
51196c0f7d3SMark Jansen     }
51296c0f7d3SMark Jansen     else
51396c0f7d3SMark Jansen     {
51496c0f7d3SMark Jansen         compare_list(init_list_vista);
51596c0f7d3SMark Jansen     }
51696c0f7d3SMark Jansen     clear_list();
51796c0f7d3SMark Jansen 
51896c0f7d3SMark Jansen     hr = psv->Refresh();
51996c0f7d3SMark Jansen     //ok_hex(hr, S_FALSE);
52096c0f7d3SMark Jansen 
52196c0f7d3SMark Jansen     static message refresh_list[] =
52296c0f7d3SMark Jansen     {
52396c0f7d3SMark Jansen         message(SFVM_LISTREFRESHED, 1, 0),
52496c0f7d3SMark Jansen 
52596c0f7d3SMark Jansen         message(SFVM_UNMERGEFROMMENU, 0, PTR_VALUE),
52696c0f7d3SMark Jansen         message(DUM_MSG_SetMenuSB, 0, 0),
52796c0f7d3SMark Jansen         message(DUM_MSG_RemoveMenusSB, 0, 0),
52896c0f7d3SMark Jansen         message(DUM_MSG_InsertMenusSB, 0, 0),
52996c0f7d3SMark Jansen         message(SFVM_MERGEMENU, 0, PTR_VALUE),
53096c0f7d3SMark Jansen         message(DUM_MSG_SetMenuSB, 0, 0),
53196c0f7d3SMark Jansen 
53296c0f7d3SMark Jansen         message(0, 0, 0)
53396c0f7d3SMark Jansen     };
53496c0f7d3SMark Jansen 
53596c0f7d3SMark Jansen     static message refresh_list_vista[] =
53696c0f7d3SMark Jansen     {
53796c0f7d3SMark Jansen         message(SFVM_LISTREFRESHED, 1, 0),
53896c0f7d3SMark Jansen 
53996c0f7d3SMark Jansen         message(SFVM_UNMERGEFROMMENU, 0, PTR_VALUE),
54096c0f7d3SMark Jansen         message(DUM_MSG_SetMenuSB, 0, 0),
54196c0f7d3SMark Jansen         message(DUM_MSG_RemoveMenusSB, 0, 0),
54296c0f7d3SMark Jansen         message(DUM_MSG_InsertMenusSB, 0, 0),
54396c0f7d3SMark Jansen         message(SFVM_MERGEMENU, 0, PTR_VALUE),
54496c0f7d3SMark Jansen         message(DUM_MSG_SetMenuSB, 0, 0),
54596c0f7d3SMark Jansen         /* Some messages here, like SFVM_GET_WEBVIEW_THEME, SFVM_GETSORTDEFAULTS, SFVM_GETCOLUMNSTREAM */
54696c0f7d3SMark Jansen         message(SFVM_UNMERGEFROMMENU, 0, PTR_VALUE),
54796c0f7d3SMark Jansen         message(DUM_MSG_SetMenuSB, 0, 0),
54896c0f7d3SMark Jansen         message(DUM_MSG_RemoveMenusSB, 0, 0),
54996c0f7d3SMark Jansen         message(DUM_MSG_InsertMenusSB, 0, 0),
55096c0f7d3SMark Jansen         message(SFVM_MERGEMENU, 0, PTR_VALUE),
55196c0f7d3SMark Jansen         message(DUM_MSG_SetMenuSB, 0, 0),
55296c0f7d3SMark Jansen 
55396c0f7d3SMark Jansen         message(0, 0, 0)
55496c0f7d3SMark Jansen     };
55596c0f7d3SMark Jansen 
55696c0f7d3SMark Jansen     if (g_WinVersion < WINVER_VISTA)
55796c0f7d3SMark Jansen     {
55896c0f7d3SMark Jansen         compare_list(refresh_list);
55996c0f7d3SMark Jansen     }
56096c0f7d3SMark Jansen     else
56196c0f7d3SMark Jansen     {
56296c0f7d3SMark Jansen         compare_list(refresh_list_vista);
56396c0f7d3SMark Jansen     }
56496c0f7d3SMark Jansen     clear_list();
56596c0f7d3SMark Jansen 
56696c0f7d3SMark Jansen     hr = psv->DestroyViewWindow();
56796c0f7d3SMark Jansen 
56896c0f7d3SMark Jansen     static message destroy_list[] =
56996c0f7d3SMark Jansen     {
57096c0f7d3SMark Jansen         message(SFVM_UNMERGEFROMMENU, 0, PTR_VALUE),
57196c0f7d3SMark Jansen         message(DUM_MSG_SetMenuSB, 0, 0),
57296c0f7d3SMark Jansen         message(DUM_MSG_RemoveMenusSB, 0, 0),
57396c0f7d3SMark Jansen         message(SFVM_WINDOWCLOSING, PTR_VALUE, 0),
57496c0f7d3SMark Jansen 
57596c0f7d3SMark Jansen         message(0, 0, 0)
57696c0f7d3SMark Jansen     };
57796c0f7d3SMark Jansen 
57896c0f7d3SMark Jansen     compare_list(destroy_list);
57996c0f7d3SMark Jansen     clear_list();
58096c0f7d3SMark Jansen 
58196c0f7d3SMark Jansen     CComPtr<IShellFolderView> folderView;
58296c0f7d3SMark Jansen     hr = psv->QueryInterface(IID_PPV_ARG(IShellFolderView, &folderView));
58396c0f7d3SMark Jansen     ok_hex(hr, S_OK);
58496c0f7d3SMark Jansen     if (SUCCEEDED(hr))
58596c0f7d3SMark Jansen     {
58696c0f7d3SMark Jansen         IShellFolderViewCB* oldPtr;
58796c0f7d3SMark Jansen 
58896c0f7d3SMark Jansen         hr = folderView->SetCallback(NULL, &oldPtr);
589*465745b6STimo Kreuzer         ok_int(g_AddRef, 1);
59096c0f7d3SMark Jansen         ok_int(g_Release, 0);
59196c0f7d3SMark Jansen 
59296c0f7d3SMark Jansen         /* Last pointer is not optional! */
59396c0f7d3SMark Jansen         IShellFolderViewCB* oldPtr2;
59496c0f7d3SMark Jansen         hr = folderView->SetCallback(oldPtr, &oldPtr2);
595*465745b6STimo Kreuzer         ok_int(g_AddRef, 2);
59696c0f7d3SMark Jansen         ok_int(g_Release, 0);
59796c0f7d3SMark Jansen     }
59896c0f7d3SMark Jansen 
59996c0f7d3SMark Jansen     ULONG refCount = psv->Release();
600*465745b6STimo Kreuzer     ok(refCount == 1, "refCount = %lu\n", refCount);
60196c0f7d3SMark Jansen 
60296c0f7d3SMark Jansen     static message release_list[] =
60396c0f7d3SMark Jansen     {
60496c0f7d3SMark Jansen         message(SFVM_VIEWRELEASE, 0, 0),
60596c0f7d3SMark Jansen 
60696c0f7d3SMark Jansen         message(0, 0, 0)
60796c0f7d3SMark Jansen     };
60896c0f7d3SMark Jansen 
60996c0f7d3SMark Jansen     /* Investigate why this fails */
61096c0f7d3SMark Jansen     if (refCount == 0)
61196c0f7d3SMark Jansen     {
61296c0f7d3SMark Jansen         compare_list(release_list);
61396c0f7d3SMark Jansen     }
61496c0f7d3SMark Jansen }
615