xref: /reactos/dll/win32/shell32/CDefViewUtil.cpp (revision d326ca1f)
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 
18     CObjectWithSiteBase() : m_pUnkSite(NULL) {}
19     virtual ~CObjectWithSiteBase() { SetSite(NULL); }
20 
21     // IObjectWithSite
22     STDMETHODIMP SetSite(IUnknown *pUnkSite) override
23     {
24         IUnknown_Set(&m_pUnkSite, pUnkSite);
25         return S_OK;
26     }
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:
50     CShellFolderViewCBWrapper() : m_hWndMain(NULL), m_Pidl(NULL) {}
51 
52     virtual ~CShellFolderViewCBWrapper()
53     {
54         ILFree(m_Pidl);
55     }
56 
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
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
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
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