2 * PROJECT: ReactOS Search Shell Extension
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Search results folder
5 * COPYRIGHT: Copyright 2019 Brock Mammen
8 #include "CFindFolder.h"
10 WINE_DEFAULT_DEBUG_CHANNEL(shellfind
);
12 struct FolderViewColumns
20 static FolderViewColumns g_ColumnDefs
[] =
22 {L
"Name", SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 30},
23 {L
"In Folder", SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 30},
24 {L
"Relevance", SHCOLSTATE_TYPE_STR
, LVCFMT_LEFT
, 0}
27 static LPITEMIDLIST
_ILCreate(LPCWSTR lpszPath
, LPCITEMIDLIST lpcFindDataPidl
)
29 int pathLen
= (wcslen(lpszPath
) + 1) * sizeof(WCHAR
);
30 int cbData
= sizeof(WORD
) + pathLen
+ lpcFindDataPidl
->mkid
.cb
;
31 LPITEMIDLIST pidl
= (LPITEMIDLIST
) SHAlloc(cbData
+ sizeof(WORD
));
35 LPBYTE p
= (LPBYTE
) pidl
;
36 *((WORD
*) p
) = cbData
;
39 memcpy(p
, lpszPath
, pathLen
);
42 memcpy(p
, lpcFindDataPidl
, lpcFindDataPidl
->mkid
.cb
);
43 p
+= lpcFindDataPidl
->mkid
.cb
;
50 static LPCWSTR
_ILGetPath(LPCITEMIDLIST pidl
)
52 if (!pidl
|| !pidl
->mkid
.cb
)
54 return (LPCWSTR
) pidl
->mkid
.abID
;
57 static LPCITEMIDLIST
_ILGetFSPidl(LPCITEMIDLIST pidl
)
59 if (!pidl
|| !pidl
->mkid
.cb
)
61 return (LPCITEMIDLIST
) ((LPBYTE
) pidl
->mkid
.abID
62 + ((wcslen((LPCWSTR
) pidl
->mkid
.abID
) + 1) * sizeof(WCHAR
)));
65 LRESULT
CFindFolder::AddItem(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
71 LPWSTR path
= (LPWSTR
) lParam
;
73 CComPtr
<IShellFolder
> pShellFolder
;
74 hr
= SHGetDesktopFolder(&pShellFolder
);
75 if (FAILED_UNEXPECTEDLY(hr
))
81 LPITEMIDLIST lpFSPidl
;
83 hr
= pShellFolder
->ParseDisplayName(NULL
, NULL
, path
, &pchEaten
, &lpFSPidl
, NULL
);
84 if (FAILED_UNEXPECTEDLY(hr
))
90 LPITEMIDLIST lpLastFSPidl
= ILFindLastID(lpFSPidl
);
91 LPITEMIDLIST lpSearchPidl
= _ILCreate(path
, lpLastFSPidl
);
100 hr
= m_shellFolderView
->AddObject(lpSearchPidl
, &uItemIndex
);
101 ILFree(lpSearchPidl
);
106 // *** IShellFolder2 methods ***
107 STDMETHODIMP
CFindFolder::GetDefaultSearchGUID(GUID
*pguid
)
113 STDMETHODIMP
CFindFolder::EnumSearches(IEnumExtraSearch
**ppenum
)
119 STDMETHODIMP
CFindFolder::GetDefaultColumn(DWORD
, ULONG
*pSort
, ULONG
*pDisplay
)
128 STDMETHODIMP
CFindFolder::GetDefaultColumnState(UINT iColumn
, DWORD
*pcsFlags
)
132 if (iColumn
>= _countof(g_ColumnDefs
))
133 return m_pisfInner
->GetDefaultColumnState(iColumn
- _countof(g_ColumnDefs
) + 1, pcsFlags
);
134 *pcsFlags
= g_ColumnDefs
[iColumn
].dwDefaultState
;
138 STDMETHODIMP
CFindFolder::GetDetailsEx(PCUITEMID_CHILD pidl
, const SHCOLUMNID
*pscid
, VARIANT
*pv
)
140 return m_pisfInner
->GetDetailsEx(pidl
, pscid
, pv
);
143 STDMETHODIMP
CFindFolder::GetDetailsOf(PCUITEMID_CHILD pidl
, UINT iColumn
, SHELLDETAILS
*pDetails
)
145 if (iColumn
>= _countof(g_ColumnDefs
))
146 return m_pisfInner
->GetDetailsOf(_ILGetFSPidl(pidl
), iColumn
- _countof(g_ColumnDefs
) + 1, pDetails
);
148 pDetails
->cxChar
= g_ColumnDefs
[iColumn
].cxChar
;
149 pDetails
->fmt
= g_ColumnDefs
[iColumn
].fmt
;
152 return SHSetStrRet(&pDetails
->str
, g_ColumnDefs
[iColumn
].wzColumnName
);
156 WCHAR path
[MAX_PATH
];
157 wcscpy(path
, _ILGetPath(pidl
));
158 PathRemoveFileSpecW(path
);
159 return SHSetStrRet(&pDetails
->str
, path
);
162 return GetDisplayNameOf(pidl
, SHGDN_NORMAL
, &pDetails
->str
);
165 STDMETHODIMP
CFindFolder::MapColumnToSCID(UINT iColumn
, SHCOLUMNID
*pscid
)
171 // *** IShellFolder methods ***
172 STDMETHODIMP
CFindFolder::ParseDisplayName(HWND hwndOwner
, LPBC pbc
, LPOLESTR lpszDisplayName
, ULONG
*pchEaten
,
173 PIDLIST_RELATIVE
*ppidl
, ULONG
*pdwAttributes
)
179 STDMETHODIMP
CFindFolder::EnumObjects(HWND hwndOwner
, DWORD dwFlags
, LPENUMIDLIST
*ppEnumIDList
)
181 *ppEnumIDList
= NULL
;
185 STDMETHODIMP
CFindFolder::BindToObject(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
*ppvOut
)
191 STDMETHODIMP
CFindFolder::BindToStorage(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
*ppvOut
)
197 STDMETHODIMP
CFindFolder::CompareIDs(LPARAM lParam
, PCUIDLIST_RELATIVE pidl1
, PCUIDLIST_RELATIVE pidl2
)
199 return m_pisfInner
->CompareIDs(lParam
, _ILGetFSPidl(pidl1
), _ILGetFSPidl(pidl2
));
202 STDMETHODIMP
CFindFolder::CreateViewObject(HWND hwndOwner
, REFIID riid
, LPVOID
*ppvOut
)
204 if (riid
== IID_IShellView
)
206 SFV_CREATE sfvparams
= {};
207 sfvparams
.cbSize
= sizeof(SFV_CREATE
);
208 sfvparams
.pshf
= this;
209 sfvparams
.psfvcb
= this;
210 HRESULT hr
= SHCreateShellFolderView(&sfvparams
, (IShellView
**) ppvOut
);
211 if (FAILED_UNEXPECTEDLY(hr
))
216 return ((IShellView
* ) * ppvOut
)->QueryInterface(IID_PPV_ARG(IShellFolderView
, &m_shellFolderView
));
218 return E_NOINTERFACE
;
221 STDMETHODIMP
CFindFolder::GetAttributesOf(UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, DWORD
*rgfInOut
)
223 CComHeapPtr
<PCITEMID_CHILD
> aFSPidl
;
224 aFSPidl
.Allocate(cidl
);
225 for (UINT i
= 0; i
< cidl
; i
++)
227 aFSPidl
[i
] = _ILGetFSPidl(apidl
[i
]);
230 return m_pisfInner
->GetAttributesOf(cidl
, aFSPidl
, rgfInOut
);
233 STDMETHODIMP
CFindFolder::GetUIObjectOf(HWND hwndOwner
, UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, REFIID riid
,
234 UINT
*prgfInOut
, LPVOID
*ppvOut
)
238 return m_pisfInner
->GetUIObjectOf(hwndOwner
, cidl
, apidl
, riid
, prgfInOut
, ppvOut
);
241 PCITEMID_CHILD
*aFSPidl
= new PCITEMID_CHILD
[cidl
];
242 for (UINT i
= 0; i
< cidl
; i
++)
244 aFSPidl
[i
] = _ILGetFSPidl(apidl
[i
]);
247 HRESULT hr
= m_pisfInner
->GetUIObjectOf(hwndOwner
, cidl
, aFSPidl
, riid
, prgfInOut
, ppvOut
);
253 STDMETHODIMP
CFindFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET pName
)
255 return m_pisfInner
->GetDisplayNameOf(_ILGetFSPidl(pidl
), dwFlags
, pName
);
258 STDMETHODIMP
CFindFolder::SetNameOf(HWND hwndOwner
, PCUITEMID_CHILD pidl
, LPCOLESTR lpName
, DWORD dwFlags
,
259 PITEMID_CHILD
*pPidlOut
)
265 //// *** IShellFolderViewCB method ***
266 STDMETHODIMP
CFindFolder::MessageSFVCB(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
270 case SFVM_DEFVIEWMODE
:
272 FOLDERVIEWMODE
*pViewMode
= (FOLDERVIEWMODE
*) lParam
;
273 *pViewMode
= FVM_DETAILS
;
276 case SFVM_WINDOWCREATED
:
278 SubclassWindow((HWND
) wParam
);
285 //// *** IPersistFolder2 methods ***
286 STDMETHODIMP
CFindFolder::GetCurFolder(LPITEMIDLIST
*pidl
)
288 *pidl
= ILClone(m_pidl
);
292 // *** IPersistFolder methods ***
293 STDMETHODIMP
CFindFolder::Initialize(LPCITEMIDLIST pidl
)
295 m_pidl
= ILClone(pidl
);
297 return E_OUTOFMEMORY
;
299 return SHELL32_CoCreateInitSF(m_pidl
,
302 &CLSID_ShellFSFolder
,
303 IID_PPV_ARG(IShellFolder2
, &m_pisfInner
));
306 // *** IPersist methods ***
307 STDMETHODIMP
CFindFolder::GetClassID(CLSID
*pClassId
)
309 if (pClassId
== NULL
)
311 memcpy(pClassId
, &CLSID_FindFolder
, sizeof(CLSID
));