https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e639d7c1e7e0215e865a8…
commit e639d7c1e7e0215e865a82535457a8de602b8785
Author: Whindmar Saksit <whindsaks(a)proton.me>
AuthorDate: Mon Aug 19 00:34:05 2024 +0200
Commit: GitHub <noreply(a)github.com>
CommitDate: Mon Aug 19 00:34:05 2024 +0200
[SHELL32] Handle SHCreateShellFolderViewEx callback function (#7240)
The caller supplied callback function is wrapped in a IShellFolderViewCB so we can use
(the newer) SHCreateShellFolderView.
---
dll/win32/shell32/CDefView.cpp | 25 +------
dll/win32/shell32/CDefViewUtil.cpp | 140 +++++++++++++++++++++++++++++++++++++
dll/win32/shell32/CMakeLists.txt | 1 +
sdk/include/psdk/shlobj.h | 1 +
4 files changed, 145 insertions(+), 22 deletions(-)
diff --git a/dll/win32/shell32/CDefView.cpp b/dll/win32/shell32/CDefView.cpp
index 3ada8ae10b7..7617f85e5d7 100644
--- a/dll/win32/shell32/CDefView.cpp
+++ b/dll/win32/shell32/CDefView.cpp
@@ -1733,7 +1733,7 @@ LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam,
BOOL &bHandl
LPITEMIDLIST pidlTarget = NULL;
LONG fEvents = 0;
HRESULT hr = _DoFolderViewCB(SFVM_GETNOTIFY, (WPARAM)&pidlTarget,
(LPARAM)&fEvents);
- if (FAILED(hr) || (!pidlTarget && !fEvents))
+ if (FAILED(hr) || (!pidlTarget && !fEvents)) // FIXME: MSDN says both zero
means no notifications
{
pidlTarget = m_pidlParent;
fEvents = SHCNE_ALLEVENTS;
@@ -3464,7 +3464,7 @@ HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid,
LPVOID *ppvOut)
FOLDERVIEWMODE CDefView::GetDefaultViewMode()
{
FOLDERVIEWMODE mode = ((m_FolderSettings.fFlags & FWF_DESKTOP) ||
!IsOS(OS_SERVERADMINUI)) ? FVM_ICON : FVM_DETAILS;
- FOLDERVIEWMODE temp;
+ FOLDERVIEWMODE temp = mode;
if (SUCCEEDED(_DoFolderViewCB(SFVM_DEFVIEWMODE, 0, (LPARAM)&temp)) &&
temp >= FVM_FIRST && temp <= FVM_LAST)
mode = temp;
return mode;
@@ -3753,6 +3753,7 @@ HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow3(IShellBrowser
*psb, IShell
/* Get our parent window */
m_pShellBrowser->GetWindow(&m_hWndParent);
+ _DoFolderViewCB(SFVM_HWNDMAIN, 0, (LPARAM)m_hWndParent);
/* Try to get the ICommDlgBrowserInterface, adds a reference !!! */
m_pCommDlgBrowser = NULL;
@@ -4656,26 +4657,6 @@ HRESULT CDefView_CreateInstance(IShellFolder *pFolder, REFIID riid,
LPVOID * ppv
return ShellObjectCreatorInit<CDefView>(pFolder, riid, ppvOut);
}
-HRESULT WINAPI SHCreateShellFolderViewEx(
- LPCSFV psvcbi, // [in] shelltemplate struct
- IShellView **ppsv) // [out] IShellView pointer
-{
- CComPtr<IShellView> psv;
- HRESULT hRes;
-
- TRACE("sf=%p pidl=%p cb=%p mode=0x%08x parm=%p\n",
- psvcbi->pshf, psvcbi->pidl, psvcbi->pfnCallback,
- psvcbi->fvm, psvcbi->psvOuter);
-
- *ppsv = NULL;
- hRes = CDefView_CreateInstance(psvcbi->pshf, IID_PPV_ARG(IShellView, &psv));
- if (FAILED_UNEXPECTEDLY(hRes))
- return hRes;
-
- *ppsv = psv.Detach();
- return hRes;
-}
-
HRESULT WINAPI SHCreateShellFolderView(const SFV_CREATE *pcsfv,
IShellView **ppsv)
{
diff --git a/dll/win32/shell32/CDefViewUtil.cpp b/dll/win32/shell32/CDefViewUtil.cpp
new file mode 100644
index 00000000000..3996b0d3891
--- /dev/null
+++ b/dll/win32/shell32/CDefViewUtil.cpp
@@ -0,0 +1,140 @@
+/*
+ * PROJECT: shell32
+ * LICENSE: LGPL-2.1+ (
https://spdx.org/licenses/LGPL-2.1+)
+ * PURPOSE: DefView utility functions
+ * COPYRIGHT: Copyright 2024 Whindmar Saksit <whindsaks(a)proton.me>
+ */
+
+#include "precomp.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(shell);
+
+class CObjectWithSiteBase :
+ public IObjectWithSite
+{
+public:
+ IUnknown* m_pUnkSite;
+
+ CObjectWithSiteBase() : m_pUnkSite(NULL) {}
+ virtual ~CObjectWithSiteBase() { SetSite(NULL); }
+
+ // IObjectWithSite
+ STDMETHODIMP SetSite(IUnknown *pUnkSite) override
+ {
+ IUnknown_Set(&m_pUnkSite, pUnkSite);
+ return S_OK;
+ }
+ STDMETHODIMP GetSite(REFIID riid, void **ppvSite) override
+ {
+ *ppvSite = NULL;
+ return m_pUnkSite ? m_pUnkSite->QueryInterface(riid, ppvSite) : E_FAIL;
+ }
+};
+
+// This class adapts the legacy function callback to work as an IShellFolderViewCB
+class CShellFolderViewCBWrapper :
+ public CComObjectRootEx<CComMultiThreadModelNoCS>,
+ public IShellFolderViewCB,
+ public CObjectWithSiteBase
+{
+protected:
+ HWND m_hWndMain;
+ PIDLIST_ABSOLUTE m_Pidl;
+ CComPtr<IShellFolder> m_psf;
+ CComPtr<IShellView> m_psvOuter;
+ LPFNVIEWCALLBACK m_Callback;
+ FOLDERVIEWMODE m_FVM;
+ LONG m_Events;
+
+public:
+ CShellFolderViewCBWrapper() : m_hWndMain(NULL), m_Pidl(NULL) {}
+
+ virtual ~CShellFolderViewCBWrapper()
+ {
+ ILFree(m_Pidl);
+ }
+
+ HRESULT WINAPI Initialize(LPCSFV psvcbi)
+ {
+ m_psf = psvcbi->pshf;
+ m_psvOuter = psvcbi->psvOuter;
+ m_Pidl = psvcbi->pidl ? ILClone(psvcbi->pidl) : NULL;
+ m_Callback = psvcbi->pfnCallback;
+ m_FVM = psvcbi->fvm;
+ m_Events = psvcbi->lEvents;
+ return S_OK;
+ }
+
+ // IShellFolderViewCB
+ STDMETHODIMP MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam) override
+ {
+ switch (uMsg)
+ {
+ case SFVM_HWNDMAIN:
+ m_hWndMain = (HWND)lParam;
+ break;
+
+ case SFVM_DEFVIEWMODE:
+ if (m_FVM)
+ *(FOLDERVIEWMODE*)lParam = m_FVM;
+ break;
+ }
+
+ HRESULT hr = m_Callback(m_psvOuter, m_psf, m_hWndMain, uMsg, wParam, lParam);
+ if (SUCCEEDED(hr))
+ return hr;
+
+ switch (uMsg)
+ {
+ case SFVM_GETNOTIFY:
+ *(LPITEMIDLIST*)wParam = m_Pidl;
+ *(LONG*)lParam = m_Events;
+ return S_OK;
+ }
+ return hr;
+ }
+
+ // IObjectWithSite
+ STDMETHODIMP SetSite(IUnknown *pUnkSite) override
+ {
+ //
learn.microsoft.com/en-us/windows/win32/shell/sfvm-setisfv
+ HRESULT hr = CObjectWithSiteBase::SetSite(pUnkSite);
+ MessageSFVCB(SFVM_SETISFV, 0, (LPARAM)pUnkSite);
+ return hr;
+ }
+
+ DECLARE_NO_REGISTRY()
+ DECLARE_NOT_AGGREGATABLE(CShellFolderViewCBWrapper)
+ BEGIN_COM_MAP(CShellFolderViewCBWrapper)
+ COM_INTERFACE_ENTRY_IID(IID_IShellFolderViewCB, IShellFolderViewCB)
+ COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
+ END_COM_MAP()
+};
+
+/*************************************************************************
+ * SHCreateShellFolderViewEx [SHELL32.174] (Win95+)
+ */
+EXTERN_C HRESULT WINAPI
+SHCreateShellFolderViewEx(_In_ LPCSFV pcsfv, _Out_ IShellView **ppsv)
+{
+ if (!ppsv)
+ return E_INVALIDARG;
+ *ppsv = NULL;
+
+ TRACE("sf=%p pidl=%p cb=%p mode=0x%08x outer=%p\n",
+ pcsfv->pshf, pcsfv->pidl, pcsfv->pfnCallback,
+ pcsfv->fvm, pcsfv->psvOuter);
+
+ CComPtr<IShellFolderViewCB> psfvcb;
+ SFV_CREATE create = { sizeof(create), pcsfv->pshf, pcsfv->psvOuter };
+
+ if (pcsfv->pfnCallback)
+ {
+ HRESULT hr = ShellObjectCreatorInit<CShellFolderViewCBWrapper>(pcsfv,
+ IID_PPV_ARG(IShellFolderViewCB, &psfvcb));
+ if (FAILED(hr))
+ return hr;
+ create.psfvcb = psfvcb;
+ }
+ return SHCreateShellFolderView(&create, ppsv);
+}
diff --git a/dll/win32/shell32/CMakeLists.txt b/dll/win32/shell32/CMakeLists.txt
index 1b76acb0560..7226ba4105d 100644
--- a/dll/win32/shell32/CMakeLists.txt
+++ b/dll/win32/shell32/CMakeLists.txt
@@ -65,6 +65,7 @@ list(APPEND SOURCE
shlfolder.cpp
CFileSysBindData.cpp
CDefView.cpp
+ CDefViewUtil.cpp
CDefViewDual.cpp
CDefViewBckgrndMenu.cpp
stubs.cpp
diff --git a/sdk/include/psdk/shlobj.h b/sdk/include/psdk/shlobj.h
index 608e78618f0..10e73f0ddcd 100644
--- a/sdk/include/psdk/shlobj.h
+++ b/sdk/include/psdk/shlobj.h
@@ -1331,6 +1331,7 @@ SHCreateShellFolderViewEx(
#define SFVM_GETEXTVIEWS 40 /* undocumented */
#define SFVM_THISIDLIST 41
#define SFVM_UPDATINGOBJECT 43 /* undocumented */
+#define SFVM_HWNDMAIN 46 /* undocumented */
#define SFVM_ADDPROPERTYPAGES 47
#define SFVM_BACKGROUNDENUMDONE 48
#define SFVM_GETNOTIFY 49