https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e639d7c1e7e0215e865a82535457a8de602b8785

commit e639d7c1e7e0215e865a82535457a8de602b8785
Author:     Whindmar Saksit <whinds...@proton.me>
AuthorDate: Mon Aug 19 00:34:05 2024 +0200
Commit:     GitHub <nore...@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 <whinds...@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

Reply via email to