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