1 /*
2 * PROJECT: shell32
3 * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
4 * PURPOSE: DefView utility functions
5 * COPYRIGHT: Copyright 2024 Whindmar Saksit <whindsaks@proton.me>
6 */
7
8 #include "precomp.h"
9
10 WINE_DEFAULT_DEBUG_CHANNEL(shell);
11
12 class CObjectWithSiteBase :
13 public IObjectWithSite
14 {
15 public:
16 IUnknown* m_pUnkSite;
17
CObjectWithSiteBase()18 CObjectWithSiteBase() : m_pUnkSite(NULL) {}
~CObjectWithSiteBase()19 virtual ~CObjectWithSiteBase() { SetSite(NULL); }
20
21 // IObjectWithSite
SetSite(IUnknown * pUnkSite)22 STDMETHODIMP SetSite(IUnknown *pUnkSite) override
23 {
24 IUnknown_Set(&m_pUnkSite, pUnkSite);
25 return S_OK;
26 }
GetSite(REFIID riid,void ** ppvSite)27 STDMETHODIMP GetSite(REFIID riid, void **ppvSite) override
28 {
29 *ppvSite = NULL;
30 return m_pUnkSite ? m_pUnkSite->QueryInterface(riid, ppvSite) : E_FAIL;
31 }
32 };
33
34 // This class adapts the legacy function callback to work as an IShellFolderViewCB
35 class CShellFolderViewCBWrapper :
36 public CComObjectRootEx<CComMultiThreadModelNoCS>,
37 public IShellFolderViewCB,
38 public CObjectWithSiteBase
39 {
40 protected:
41 HWND m_hWndMain;
42 PIDLIST_ABSOLUTE m_Pidl;
43 CComPtr<IShellFolder> m_psf;
44 CComPtr<IShellView> m_psvOuter;
45 LPFNVIEWCALLBACK m_Callback;
46 FOLDERVIEWMODE m_FVM;
47 LONG m_Events;
48
49 public:
CShellFolderViewCBWrapper()50 CShellFolderViewCBWrapper() : m_hWndMain(NULL), m_Pidl(NULL) {}
51
~CShellFolderViewCBWrapper()52 virtual ~CShellFolderViewCBWrapper()
53 {
54 ILFree(m_Pidl);
55 }
56
Initialize(LPCSFV psvcbi)57 HRESULT WINAPI Initialize(LPCSFV psvcbi)
58 {
59 m_psf = psvcbi->pshf;
60 m_psvOuter = psvcbi->psvOuter;
61 m_Pidl = psvcbi->pidl ? ILClone(psvcbi->pidl) : NULL;
62 m_Callback = psvcbi->pfnCallback;
63 m_FVM = psvcbi->fvm;
64 m_Events = psvcbi->lEvents;
65 return S_OK;
66 }
67
68 // IShellFolderViewCB
MessageSFVCB(UINT uMsg,WPARAM wParam,LPARAM lParam)69 STDMETHODIMP MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam) override
70 {
71 switch (uMsg)
72 {
73 case SFVM_HWNDMAIN:
74 m_hWndMain = (HWND)lParam;
75 break;
76
77 case SFVM_DEFVIEWMODE:
78 if (m_FVM)
79 *(FOLDERVIEWMODE*)lParam = m_FVM;
80 break;
81 }
82
83 HRESULT hr = m_Callback(m_psvOuter, m_psf, m_hWndMain, uMsg, wParam, lParam);
84 if (SUCCEEDED(hr))
85 return hr;
86
87 switch (uMsg)
88 {
89 case SFVM_GETNOTIFY:
90 *(LPITEMIDLIST*)wParam = m_Pidl;
91 *(LONG*)lParam = m_Events;
92 return S_OK;
93 }
94 return hr;
95 }
96
97 // IObjectWithSite
SetSite(IUnknown * pUnkSite)98 STDMETHODIMP SetSite(IUnknown *pUnkSite) override
99 {
100 // learn.microsoft.com/en-us/windows/win32/shell/sfvm-setisfv
101 HRESULT hr = CObjectWithSiteBase::SetSite(pUnkSite);
102 MessageSFVCB(SFVM_SETISFV, 0, (LPARAM)pUnkSite);
103 return hr;
104 }
105
106 DECLARE_NO_REGISTRY()
107 DECLARE_NOT_AGGREGATABLE(CShellFolderViewCBWrapper)
108 BEGIN_COM_MAP(CShellFolderViewCBWrapper)
109 COM_INTERFACE_ENTRY_IID(IID_IShellFolderViewCB, IShellFolderViewCB)
110 COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
111 END_COM_MAP()
112 };
113
114 /*************************************************************************
115 * SHCreateShellFolderViewEx [SHELL32.174] (Win95+)
116 */
117 EXTERN_C HRESULT WINAPI
SHCreateShellFolderViewEx(_In_ LPCSFV pcsfv,_Out_ IShellView ** ppsv)118 SHCreateShellFolderViewEx(_In_ LPCSFV pcsfv, _Out_ IShellView **ppsv)
119 {
120 if (!ppsv)
121 return E_INVALIDARG;
122 *ppsv = NULL;
123
124 TRACE("sf=%p pidl=%p cb=%p mode=0x%08x outer=%p\n",
125 pcsfv->pshf, pcsfv->pidl, pcsfv->pfnCallback,
126 pcsfv->fvm, pcsfv->psvOuter);
127
128 CComPtr<IShellFolderViewCB> psfvcb;
129 SFV_CREATE create = { sizeof(create), pcsfv->pshf, pcsfv->psvOuter };
130
131 if (pcsfv->pfnCallback)
132 {
133 HRESULT hr = ShellObjectCreatorInit<CShellFolderViewCBWrapper>(pcsfv,
134 IID_PPV_ARG(IShellFolderViewCB, &psfvcb));
135 if (FAILED(hr))
136 return hr;
137 create.psfvcb = psfvcb;
138 }
139 return SHCreateShellFolderView(&create, ppsv);
140 }
141