Reactos
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
10WINE_DEFAULT_DEBUG_CHANNEL(shell);
11
12HRESULT
13ShellViewIdToFolderViewMode(const SHELLVIEWID *pVid)
14{
15 if (IsEqualIID(*pVid, VID_LargeIcons))
16 return FVM_ICON;
17 else if (IsEqualIID(*pVid, VID_SmallIcons))
18 return FVM_SMALLICON;
19 else if (IsEqualIID(*pVid, VID_List))
20 return FVM_LIST;
21 else if (IsEqualIID(*pVid, VID_Details))
22 return FVM_DETAILS;
23 else if (IsEqualIID(*pVid, VID_Thumbnails))
24 return FVM_THUMBNAIL;
25 else if (IsEqualIID(*pVid, VID_Tile))
26 return FVM_TILE;
27 else if (IsEqualIID(*pVid, VID_ThumbStrip))
28 return FVM_THUMBSTRIP;
29 return E_UNEXPECTED;
30}
31
32const SHELLVIEWID *
33FolderViewModeToShellViewId(UINT FVM)
34{
35 static const SHELLVIEWID *vids[] = {
36 &VID_LargeIcons, &VID_SmallIcons,
37 &VID_Details, &VID_Thumbnails,
38 &VID_Tile, &VID_ThumbStrip,
39 };
40 FVM -= FVM_FIRST;
41 return FVM < _countof(vids) ? vids[FVM] : NULL;
42}
43
44// This class adapts the legacy function callback to work as an IShellFolderViewCB
45class CShellFolderViewCBWrapper :
46 public CComObjectRootEx<CComMultiThreadModelNoCS>,
47 public IShellFolderViewCB,
48 public CObjectWithSiteBase
49{
50protected:
51 HWND m_hWndMain;
52 PIDLIST_ABSOLUTE m_Pidl;
53 CComPtr<IShellFolder> m_psf;
54 CComPtr<IShellView> m_psvOuter;
55 LPFNVIEWCALLBACK m_Callback;
56 FOLDERVIEWMODE m_FVM;
57 LONG m_Events;
58
59public:
60 CShellFolderViewCBWrapper() : m_hWndMain(NULL), m_Pidl(NULL) {}
61
62 virtual ~CShellFolderViewCBWrapper()
63 {
64 ILFree(m_Pidl);
65 }
66
67 HRESULT WINAPI Initialize(LPCSFV psvcbi)
68 {
69 m_psf = psvcbi->pshf;
70 m_psvOuter = psvcbi->psvOuter;
71 m_Pidl = psvcbi->pidl ? ILClone(psvcbi->pidl) : NULL;
72 m_Callback = psvcbi->pfnCallback;
73 m_FVM = psvcbi->fvm;
74 m_Events = psvcbi->lEvents;
75 return S_OK;
76 }
77
78 // IShellFolderViewCB
79 STDMETHODIMP MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam) override
80 {
81 switch (uMsg)
82 {
83 case SFVM_HWNDMAIN:
84 m_hWndMain = (HWND)lParam;
85 break;
86
87 case SFVM_DEFVIEWMODE:
88 if (m_FVM)
89 *(FOLDERVIEWMODE*)lParam = m_FVM;
90 break;
91 }
92
93 HRESULT hr = m_Callback(m_psvOuter, m_psf, m_hWndMain, uMsg, wParam, lParam);
94 if (SUCCEEDED(hr))
95 return hr;
96
97 switch (uMsg)
98 {
99 case SFVM_GETNOTIFY:
100 *(LPITEMIDLIST*)wParam = m_Pidl;
101 *(LONG*)lParam = m_Events;
102 return S_OK;
103 }
104 return hr;
105 }
106
107 // IObjectWithSite
108 STDMETHODIMP SetSite(IUnknown *pUnkSite) override
109 {
110 // learn.microsoft.com/en-us/windows/win32/shell/sfvm-setisfv
111 HRESULT hr = CObjectWithSiteBase::SetSite(pUnkSite);
112 MessageSFVCB(SFVM_SETISFV, 0, (LPARAM)pUnkSite);
113 return hr;
114 }
115
116 DECLARE_NO_REGISTRY()
117 DECLARE_NOT_AGGREGATABLE(CShellFolderViewCBWrapper)
118 BEGIN_COM_MAP(CShellFolderViewCBWrapper)
119 COM_INTERFACE_ENTRY_IID(IID_IShellFolderViewCB, IShellFolderViewCB)
120 COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
121 END_COM_MAP()
122};
123
124/*************************************************************************
125 * SHCreateShellFolderViewEx [SHELL32.174] (Win95+)
126 */
127EXTERN_C HRESULT WINAPI
128SHCreateShellFolderViewEx(_In_ LPCSFV pcsfv, _Out_ IShellView **ppsv)
129{
130 if (!ppsv)
131 return E_INVALIDARG;
132 *ppsv = NULL;
133
134 TRACE("sf=%p pidl=%p cb=%p mode=0x%08x outer=%p\n",
135 pcsfv->pshf, pcsfv->pidl, pcsfv->pfnCallback,
136 pcsfv->fvm, pcsfv->psvOuter);
137
138 CComPtr<IShellFolderViewCB> psfvcb;
139 SFV_CREATE create = { sizeof(create), pcsfv->pshf, pcsfv->psvOuter };
140
141 if (pcsfv->pfnCallback)
142 {
143 HRESULT hr = ShellObjectCreatorInit<CShellFolderViewCBWrapper>(pcsfv,
144 IID_PPV_ARG(IShellFolderViewCB, &psfvcb));
145 if (FAILED(hr))
146 return hr;
147 create.psfvcb = psfvcb;
148 }
149 return SHCreateShellFolderView(&create, ppsv);
150}