13b9508e9SBrock Mammen /*
23b9508e9SBrock Mammen  * PROJECT:     ReactOS Search Shell Extension
33b9508e9SBrock Mammen  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
43b9508e9SBrock Mammen  * PURPOSE:     Search results folder
53b9508e9SBrock Mammen  * COPYRIGHT:   Copyright 2019 Brock Mammen
63b9508e9SBrock Mammen  */
73b9508e9SBrock Mammen 
8ccf9ce32SBrock Mammen #include "CFindFolder.h"
941d7b370SBrock Mammen #include <exdispid.h>
10ccf9ce32SBrock Mammen 
11ccf9ce32SBrock Mammen WINE_DEFAULT_DEBUG_CHANNEL(shellfind);
12ccf9ce32SBrock Mammen 
SHELL32_CoCreateInitSF(LPCITEMIDLIST pidlRoot,PERSIST_FOLDER_TARGET_INFO * ppfti,LPCITEMIDLIST pidlChild,const GUID * clsid,REFIID riid,LPVOID * ppvOut)13312b628fSBrock Mammen static HRESULT SHELL32_CoCreateInitSF(LPCITEMIDLIST pidlRoot, PERSIST_FOLDER_TARGET_INFO* ppfti,
14312b628fSBrock Mammen                                 LPCITEMIDLIST pidlChild, const GUID* clsid, REFIID riid, LPVOID *ppvOut)
15312b628fSBrock Mammen {
16312b628fSBrock Mammen     HRESULT hr;
17312b628fSBrock Mammen     CComPtr<IShellFolder> pShellFolder;
18312b628fSBrock Mammen 
19312b628fSBrock Mammen     hr = SHCoCreateInstance(NULL, clsid, NULL, IID_PPV_ARG(IShellFolder, &pShellFolder));
20312b628fSBrock Mammen     if (FAILED(hr))
21312b628fSBrock Mammen         return hr;
22312b628fSBrock Mammen 
23312b628fSBrock Mammen     LPITEMIDLIST pidlAbsolute = ILCombine (pidlRoot, pidlChild);
24312b628fSBrock Mammen     CComPtr<IPersistFolder> ppf;
25312b628fSBrock Mammen     CComPtr<IPersistFolder3> ppf3;
26312b628fSBrock Mammen 
27312b628fSBrock Mammen     if (ppfti && SUCCEEDED(pShellFolder->QueryInterface(IID_PPV_ARG(IPersistFolder3, &ppf3))))
28312b628fSBrock Mammen     {
29312b628fSBrock Mammen         ppf3->InitializeEx(NULL, pidlAbsolute, ppfti);
30312b628fSBrock Mammen     }
31312b628fSBrock Mammen     else if (SUCCEEDED(pShellFolder->QueryInterface(IID_PPV_ARG(IPersistFolder, &ppf))))
32312b628fSBrock Mammen     {
33312b628fSBrock Mammen         ppf->Initialize(pidlAbsolute);
34312b628fSBrock Mammen     }
35312b628fSBrock Mammen     ILFree (pidlAbsolute);
36312b628fSBrock Mammen 
37312b628fSBrock Mammen     return pShellFolder->QueryInterface(riid, ppvOut);
38312b628fSBrock Mammen }
39312b628fSBrock Mammen 
_InsertMenuItemW(HMENU hMenu,UINT indexMenu,BOOL fByPosition,UINT wID,UINT fType,LPCWSTR dwTypeData,UINT fState)40312b628fSBrock Mammen static void WINAPI _InsertMenuItemW(
41312b628fSBrock Mammen         HMENU hMenu,
42312b628fSBrock Mammen         UINT indexMenu,
43312b628fSBrock Mammen         BOOL fByPosition,
44312b628fSBrock Mammen         UINT wID,
45312b628fSBrock Mammen         UINT fType,
46312b628fSBrock Mammen         LPCWSTR dwTypeData,
47312b628fSBrock Mammen         UINT fState)
48312b628fSBrock Mammen {
49312b628fSBrock Mammen     MENUITEMINFOW mii;
50312b628fSBrock Mammen     WCHAR wszText[100];
51312b628fSBrock Mammen 
52312b628fSBrock Mammen     ZeroMemory(&mii, sizeof(mii));
53312b628fSBrock Mammen     mii.cbSize = sizeof(mii);
54312b628fSBrock Mammen     if (fType == MFT_SEPARATOR)
55312b628fSBrock Mammen         mii.fMask = MIIM_ID | MIIM_TYPE;
56312b628fSBrock Mammen     else if (fType == MFT_STRING)
57312b628fSBrock Mammen     {
58312b628fSBrock Mammen         mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
599b75b67eSBrock Mammen         if (IS_INTRESOURCE(dwTypeData))
60312b628fSBrock Mammen         {
61312b628fSBrock Mammen             if (LoadStringW(_AtlBaseModule.GetResourceInstance(), LOWORD((ULONG_PTR)dwTypeData), wszText, _countof(wszText)))
62312b628fSBrock Mammen                 mii.dwTypeData = wszText;
63312b628fSBrock Mammen             else
64312b628fSBrock Mammen             {
65312b628fSBrock Mammen                 ERR("failed to load string %p\n", dwTypeData);
66312b628fSBrock Mammen                 return;
67312b628fSBrock Mammen             }
68312b628fSBrock Mammen         }
69312b628fSBrock Mammen         else
70312b628fSBrock Mammen             mii.dwTypeData = (LPWSTR)dwTypeData;
71312b628fSBrock Mammen         mii.fState = fState;
72312b628fSBrock Mammen     }
73312b628fSBrock Mammen 
74312b628fSBrock Mammen     mii.wID = wID;
75312b628fSBrock Mammen     mii.fType = fType;
76312b628fSBrock Mammen     InsertMenuItemW(hMenu, indexMenu, fByPosition, &mii);
77312b628fSBrock Mammen }
78312b628fSBrock Mammen 
79ccf9ce32SBrock Mammen struct FolderViewColumns
80ccf9ce32SBrock Mammen {
816c6fd6d9SBrock Mammen     int iResource;
82ccf9ce32SBrock Mammen     DWORD dwDefaultState;
83ccf9ce32SBrock Mammen     int fmt;
84ccf9ce32SBrock Mammen     int cxChar;
85ccf9ce32SBrock Mammen };
86ccf9ce32SBrock Mammen 
87ccf9ce32SBrock Mammen static FolderViewColumns g_ColumnDefs[] =
88ccf9ce32SBrock Mammen {
896c6fd6d9SBrock Mammen     {IDS_COL_NAME,      SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 30},
906c6fd6d9SBrock Mammen     {IDS_COL_LOCATION,  SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 30},
916c6fd6d9SBrock Mammen     {IDS_COL_RELEVANCE, SHCOLSTATE_TYPE_STR,                          LVCFMT_LEFT, 0}
92ccf9ce32SBrock Mammen };
93ccf9ce32SBrock Mammen 
CFindFolder()946d6bc885SBrock Mammen CFindFolder::CFindFolder() :
956d6bc885SBrock Mammen     m_hStopEvent(NULL)
966d6bc885SBrock Mammen {
976d6bc885SBrock Mammen }
986d6bc885SBrock Mammen 
_ILCreate(LPCWSTR lpszPath)992f3db8d9SBrock Mammen static LPITEMIDLIST _ILCreate(LPCWSTR lpszPath)
100666bf346SBrock Mammen {
1012f3db8d9SBrock Mammen     CComHeapPtr<ITEMIDLIST> lpFSPidl(ILCreateFromPathW(lpszPath));
1027ac9fd9fSBrock Mammen     if (!lpFSPidl)
1032f3db8d9SBrock Mammen     {
1042f3db8d9SBrock Mammen         ERR("Failed to create pidl from path\n");
1050311544bSBrock Mammen         return NULL;
1062f3db8d9SBrock Mammen     }
1072f3db8d9SBrock Mammen     LPITEMIDLIST lpLastFSPidl = ILFindLastID(lpFSPidl);
1082f3db8d9SBrock Mammen 
109a3ee648dSBrock Mammen     int pathLen = (PathFindFileNameW(lpszPath) - lpszPath) * sizeof(WCHAR);
1102f3db8d9SBrock Mammen     int cbData = sizeof(WORD) + pathLen + lpLastFSPidl->mkid.cb;
111666bf346SBrock Mammen     LPITEMIDLIST pidl = (LPITEMIDLIST) SHAlloc(cbData + sizeof(WORD));
112666bf346SBrock Mammen     if (!pidl)
113666bf346SBrock Mammen         return NULL;
114666bf346SBrock Mammen 
115666bf346SBrock Mammen     LPBYTE p = (LPBYTE) pidl;
116666bf346SBrock Mammen     *((WORD *) p) = cbData;
117666bf346SBrock Mammen     p += sizeof(WORD);
118666bf346SBrock Mammen 
119666bf346SBrock Mammen     memcpy(p, lpszPath, pathLen);
120a3ee648dSBrock Mammen     p += pathLen - sizeof(WCHAR);
121a3ee648dSBrock Mammen     *((WCHAR *) p) = '\0';
122a3ee648dSBrock Mammen     p += sizeof(WCHAR);
123666bf346SBrock Mammen 
1242f3db8d9SBrock Mammen     memcpy(p, lpLastFSPidl, lpLastFSPidl->mkid.cb);
1252f3db8d9SBrock Mammen     p += lpLastFSPidl->mkid.cb;
126666bf346SBrock Mammen 
127666bf346SBrock Mammen     *((WORD *) p) = 0;
128666bf346SBrock Mammen 
129666bf346SBrock Mammen     return pidl;
130666bf346SBrock Mammen }
131666bf346SBrock Mammen 
_ILGetPath(LPCITEMIDLIST pidl)132666bf346SBrock Mammen static LPCWSTR _ILGetPath(LPCITEMIDLIST pidl)
133666bf346SBrock Mammen {
134666bf346SBrock Mammen     if (!pidl || !pidl->mkid.cb)
135666bf346SBrock Mammen         return NULL;
136666bf346SBrock Mammen     return (LPCWSTR) pidl->mkid.abID;
137666bf346SBrock Mammen }
138666bf346SBrock Mammen 
_ILGetFSPidl(LPCITEMIDLIST pidl)139666bf346SBrock Mammen static LPCITEMIDLIST _ILGetFSPidl(LPCITEMIDLIST pidl)
140666bf346SBrock Mammen {
141666bf346SBrock Mammen     if (!pidl || !pidl->mkid.cb)
142666bf346SBrock Mammen         return pidl;
143666bf346SBrock Mammen     return (LPCITEMIDLIST) ((LPBYTE) pidl->mkid.abID
144666bf346SBrock Mammen                             + ((wcslen((LPCWSTR) pidl->mkid.abID) + 1) * sizeof(WCHAR)));
145666bf346SBrock Mammen }
146666bf346SBrock Mammen 
1472f3db8d9SBrock Mammen struct _SearchData
1482f3db8d9SBrock Mammen {
1492f3db8d9SBrock Mammen     HWND hwnd;
1502f3db8d9SBrock Mammen     HANDLE hStopEvent;
1518246cd4eSBrock Mammen     CStringW szPath;
1528246cd4eSBrock Mammen     CStringW szFileName;
1538246cd4eSBrock Mammen     CStringA szQueryA;
1548246cd4eSBrock Mammen     CStringW szQueryW;
1557376cdebSKatayama Hirofumi MZ     CStringW szQueryU16BE;
1567376cdebSKatayama Hirofumi MZ     CStringA szQueryU8;
157103c87d2SDoug Lyons     BOOL SearchHidden;
1588246cd4eSBrock Mammen     CComPtr<CFindFolder> pFindFolder;
1592f3db8d9SBrock Mammen };
1602f3db8d9SBrock Mammen 
1618246cd4eSBrock Mammen template<typename TChar, typename TString, int (&StrNCmp)(const TChar *, const TChar *, size_t)>
StrStrN(const TChar * lpFirst,const TString & lpSrch,UINT cchMax)1628246cd4eSBrock Mammen static const TChar* StrStrN(const TChar *lpFirst, const TString &lpSrch, UINT cchMax)
1632f3db8d9SBrock Mammen {
1648246cd4eSBrock Mammen     if (!lpFirst || lpSrch.IsEmpty() || !cchMax)
1652f3db8d9SBrock Mammen         return NULL;
1662f3db8d9SBrock Mammen 
1678246cd4eSBrock Mammen     for (UINT i = cchMax; i > 0 && *lpFirst; i--, lpFirst++)
1682f3db8d9SBrock Mammen     {
1698246cd4eSBrock Mammen         if (!StrNCmp(lpFirst, lpSrch, lpSrch.GetLength()))
1708246cd4eSBrock Mammen             return (const TChar*)lpFirst;
1712f3db8d9SBrock Mammen     }
1722f3db8d9SBrock Mammen 
1732f3db8d9SBrock Mammen     return NULL;
1742f3db8d9SBrock Mammen }
1752f3db8d9SBrock Mammen 
1767376cdebSKatayama Hirofumi MZ static inline BOOL
StrFindNIA(const CHAR * lpFirst,const CStringA & lpSrch,UINT cchMax)1777376cdebSKatayama Hirofumi MZ StrFindNIA(const CHAR *lpFirst, const CStringA &lpSrch, UINT cchMax)
1788246cd4eSBrock Mammen {
1797376cdebSKatayama Hirofumi MZ     return StrStrN<CHAR, CStringA, _strnicmp>(lpFirst, lpSrch, cchMax) != NULL;
1808246cd4eSBrock Mammen }
1818246cd4eSBrock Mammen 
1827376cdebSKatayama Hirofumi MZ static inline BOOL
StrFindNIW(const WCHAR * lpFirst,const CStringW & lpSrch,UINT cchMax)1837376cdebSKatayama Hirofumi MZ StrFindNIW(const WCHAR *lpFirst, const CStringW &lpSrch, UINT cchMax)
1848246cd4eSBrock Mammen {
1857376cdebSKatayama Hirofumi MZ     return StrStrN<WCHAR, CStringW, _wcsnicmp>(lpFirst, lpSrch, cchMax) != NULL;
1868246cd4eSBrock Mammen }
1878246cd4eSBrock Mammen 
188c8e3ef78SKatayama Hirofumi MZ /*
189c8e3ef78SKatayama Hirofumi MZ  * The following code is borrowed from base/applications/cmdutils/more/more.c .
190c8e3ef78SKatayama Hirofumi MZ  */
191c8e3ef78SKatayama Hirofumi MZ typedef enum
192c8e3ef78SKatayama Hirofumi MZ {
193c8e3ef78SKatayama Hirofumi MZ     ENCODING_ANSI    =  0,
194c8e3ef78SKatayama Hirofumi MZ     ENCODING_UTF16LE =  1,
195c8e3ef78SKatayama Hirofumi MZ     ENCODING_UTF16BE =  2,
196c8e3ef78SKatayama Hirofumi MZ     ENCODING_UTF8    =  3
197c8e3ef78SKatayama Hirofumi MZ } ENCODING;
198c8e3ef78SKatayama Hirofumi MZ 
199c8e3ef78SKatayama Hirofumi MZ static BOOL
IsDataUnicode(IN PVOID Buffer,IN DWORD BufferSize,OUT ENCODING * Encoding OPTIONAL,OUT PDWORD SkipBytes OPTIONAL)200c8e3ef78SKatayama Hirofumi MZ IsDataUnicode(
201c8e3ef78SKatayama Hirofumi MZ     IN PVOID Buffer,
202c8e3ef78SKatayama Hirofumi MZ     IN DWORD BufferSize,
203c8e3ef78SKatayama Hirofumi MZ     OUT ENCODING* Encoding OPTIONAL,
204c8e3ef78SKatayama Hirofumi MZ     OUT PDWORD SkipBytes OPTIONAL)
205c8e3ef78SKatayama Hirofumi MZ {
206c8e3ef78SKatayama Hirofumi MZ     PBYTE pBytes = (PBYTE)Buffer;
207c8e3ef78SKatayama Hirofumi MZ     ENCODING encFile = ENCODING_ANSI;
208c8e3ef78SKatayama Hirofumi MZ     DWORD dwPos = 0;
209c8e3ef78SKatayama Hirofumi MZ 
210c8e3ef78SKatayama Hirofumi MZ     /*
211c8e3ef78SKatayama Hirofumi MZ      * See http://archives.miloush.net/michkap/archive/2007/04/22/2239345.html
212c8e3ef78SKatayama Hirofumi MZ      * for more details about the algorithm and the pitfalls behind it.
213c8e3ef78SKatayama Hirofumi MZ      * Of course it would be actually great to make a nice function that
214c8e3ef78SKatayama Hirofumi MZ      * would work, once and for all, and put it into a library.
215c8e3ef78SKatayama Hirofumi MZ      */
216c8e3ef78SKatayama Hirofumi MZ 
217c8e3ef78SKatayama Hirofumi MZ     /* Look for Byte Order Marks */
218c8e3ef78SKatayama Hirofumi MZ     if ((BufferSize >= 2) && (pBytes[0] == 0xFF) && (pBytes[1] == 0xFE))
219c8e3ef78SKatayama Hirofumi MZ     {
220c8e3ef78SKatayama Hirofumi MZ         encFile = ENCODING_UTF16LE;
221c8e3ef78SKatayama Hirofumi MZ         dwPos = 2;
222c8e3ef78SKatayama Hirofumi MZ     }
223c8e3ef78SKatayama Hirofumi MZ     else if ((BufferSize >= 2) && (pBytes[0] == 0xFE) && (pBytes[1] == 0xFF))
224c8e3ef78SKatayama Hirofumi MZ     {
225c8e3ef78SKatayama Hirofumi MZ         encFile = ENCODING_UTF16BE;
226c8e3ef78SKatayama Hirofumi MZ         dwPos = 2;
227c8e3ef78SKatayama Hirofumi MZ     }
228c8e3ef78SKatayama Hirofumi MZ     else if ((BufferSize >= 3) && (pBytes[0] == 0xEF) && (pBytes[1] == 0xBB) && (pBytes[2] == 0xBF))
229c8e3ef78SKatayama Hirofumi MZ     {
230c8e3ef78SKatayama Hirofumi MZ         encFile = ENCODING_UTF8;
231c8e3ef78SKatayama Hirofumi MZ         dwPos = 3;
232c8e3ef78SKatayama Hirofumi MZ     }
233c8e3ef78SKatayama Hirofumi MZ     else
234c8e3ef78SKatayama Hirofumi MZ     {
235c8e3ef78SKatayama Hirofumi MZ         /*
236c8e3ef78SKatayama Hirofumi MZ          * Try using statistical analysis. Do not rely on the return value of
237c8e3ef78SKatayama Hirofumi MZ          * IsTextUnicode as we can get FALSE even if the text is in UTF-16 BE
238c8e3ef78SKatayama Hirofumi MZ          * (i.e. we have some of the IS_TEXT_UNICODE_REVERSE_MASK bits set).
239c8e3ef78SKatayama Hirofumi MZ          * Instead, set all the tests we want to perform, then just check
240c8e3ef78SKatayama Hirofumi MZ          * the passed tests and try to deduce the string properties.
241c8e3ef78SKatayama Hirofumi MZ          */
242c8e3ef78SKatayama Hirofumi MZ 
243c8e3ef78SKatayama Hirofumi MZ /*
244c8e3ef78SKatayama Hirofumi MZ  * This mask contains the 3 highest bits from IS_TEXT_UNICODE_NOT_ASCII_MASK
245c8e3ef78SKatayama Hirofumi MZ  * and the 1st highest bit from IS_TEXT_UNICODE_NOT_UNICODE_MASK.
246c8e3ef78SKatayama Hirofumi MZ  */
247c8e3ef78SKatayama Hirofumi MZ #define IS_TEXT_UNKNOWN_FLAGS_MASK  ((7 << 13) | (1 << 11))
248c8e3ef78SKatayama Hirofumi MZ 
249c8e3ef78SKatayama Hirofumi MZ         /* Flag out the unknown flags here, the passed tests will not have them either */
250c8e3ef78SKatayama Hirofumi MZ         INT Tests = (IS_TEXT_UNICODE_NOT_ASCII_MASK   |
251c8e3ef78SKatayama Hirofumi MZ                      IS_TEXT_UNICODE_NOT_UNICODE_MASK |
252c8e3ef78SKatayama Hirofumi MZ                      IS_TEXT_UNICODE_REVERSE_MASK | IS_TEXT_UNICODE_UNICODE_MASK)
253c8e3ef78SKatayama Hirofumi MZ                         & ~IS_TEXT_UNKNOWN_FLAGS_MASK;
254c8e3ef78SKatayama Hirofumi MZ         INT Results;
255c8e3ef78SKatayama Hirofumi MZ 
256c8e3ef78SKatayama Hirofumi MZ         IsTextUnicode(Buffer, BufferSize, &Tests);
257c8e3ef78SKatayama Hirofumi MZ         Results = Tests;
258c8e3ef78SKatayama Hirofumi MZ 
259c8e3ef78SKatayama Hirofumi MZ         /*
260c8e3ef78SKatayama Hirofumi MZ          * As the IS_TEXT_UNICODE_NULL_BYTES or IS_TEXT_UNICODE_ILLEGAL_CHARS
261c8e3ef78SKatayama Hirofumi MZ          * flags are expected to be potentially present in the result without
262c8e3ef78SKatayama Hirofumi MZ          * modifying our expectations, filter them out now.
263c8e3ef78SKatayama Hirofumi MZ          */
264c8e3ef78SKatayama Hirofumi MZ         Results &= ~(IS_TEXT_UNICODE_NULL_BYTES | IS_TEXT_UNICODE_ILLEGAL_CHARS);
265c8e3ef78SKatayama Hirofumi MZ 
266c8e3ef78SKatayama Hirofumi MZ         /*
267c8e3ef78SKatayama Hirofumi MZ          * NOTE: The flags IS_TEXT_UNICODE_ASCII16 and
268c8e3ef78SKatayama Hirofumi MZ          * IS_TEXT_UNICODE_REVERSE_ASCII16 are not reliable.
269c8e3ef78SKatayama Hirofumi MZ          *
270c8e3ef78SKatayama Hirofumi MZ          * NOTE2: Check for potential "bush hid the facts" effect by also
271c8e3ef78SKatayama Hirofumi MZ          * checking the original results (in 'Tests') for the absence of
272c8e3ef78SKatayama Hirofumi MZ          * the IS_TEXT_UNICODE_NULL_BYTES flag, as we may presumably expect
273c8e3ef78SKatayama Hirofumi MZ          * that in UTF-16 text there will be at some point some NULL bytes.
274c8e3ef78SKatayama Hirofumi MZ          * If not, fall back to ANSI. This shows the limitations of using the
275c8e3ef78SKatayama Hirofumi MZ          * IsTextUnicode API to perform such tests, and the usage of a more
276c8e3ef78SKatayama Hirofumi MZ          * improved encoding detection algorithm would be really welcome.
277c8e3ef78SKatayama Hirofumi MZ          */
278c8e3ef78SKatayama Hirofumi MZ         if (!(Results & IS_TEXT_UNICODE_NOT_UNICODE_MASK) &&
279c8e3ef78SKatayama Hirofumi MZ             !(Results & IS_TEXT_UNICODE_REVERSE_MASK)     &&
280c8e3ef78SKatayama Hirofumi MZ              (Results & IS_TEXT_UNICODE_UNICODE_MASK)     &&
281c8e3ef78SKatayama Hirofumi MZ              (Tests   & IS_TEXT_UNICODE_NULL_BYTES))
282c8e3ef78SKatayama Hirofumi MZ         {
283c8e3ef78SKatayama Hirofumi MZ             encFile = ENCODING_UTF16LE;
284c8e3ef78SKatayama Hirofumi MZ             dwPos = (Results & IS_TEXT_UNICODE_SIGNATURE) ? 2 : 0;
285c8e3ef78SKatayama Hirofumi MZ         }
286c8e3ef78SKatayama Hirofumi MZ         else
287c8e3ef78SKatayama Hirofumi MZ         if (!(Results & IS_TEXT_UNICODE_NOT_UNICODE_MASK) &&
288c8e3ef78SKatayama Hirofumi MZ             !(Results & IS_TEXT_UNICODE_UNICODE_MASK)     &&
289c8e3ef78SKatayama Hirofumi MZ              (Results & IS_TEXT_UNICODE_REVERSE_MASK)     &&
290c8e3ef78SKatayama Hirofumi MZ              (Tests   & IS_TEXT_UNICODE_NULL_BYTES))
291c8e3ef78SKatayama Hirofumi MZ         {
292c8e3ef78SKatayama Hirofumi MZ             encFile = ENCODING_UTF16BE;
293c8e3ef78SKatayama Hirofumi MZ             dwPos = (Results & IS_TEXT_UNICODE_REVERSE_SIGNATURE) ? 2 : 0;
294c8e3ef78SKatayama Hirofumi MZ         }
295c8e3ef78SKatayama Hirofumi MZ         else
296c8e3ef78SKatayama Hirofumi MZ         {
297c8e3ef78SKatayama Hirofumi MZ             /*
298c8e3ef78SKatayama Hirofumi MZ              * Either 'Results' has neither of those masks set, as it can be
299c8e3ef78SKatayama Hirofumi MZ              * the case for UTF-8 text (or ANSI), or it has both as can be the
300c8e3ef78SKatayama Hirofumi MZ              * case when analysing pure binary data chunk. This is therefore
301c8e3ef78SKatayama Hirofumi MZ              * invalid and we fall back to ANSI encoding.
302c8e3ef78SKatayama Hirofumi MZ              * FIXME: In case of failure, assume ANSI (as long as we do not have
303c8e3ef78SKatayama Hirofumi MZ              * correct tests for UTF8, otherwise we should do them, and at the
304c8e3ef78SKatayama Hirofumi MZ              * very end, assume ANSI).
305c8e3ef78SKatayama Hirofumi MZ              */
306c8e3ef78SKatayama Hirofumi MZ             encFile = ENCODING_ANSI; // ENCODING_UTF8;
307c8e3ef78SKatayama Hirofumi MZ             dwPos = 0;
308c8e3ef78SKatayama Hirofumi MZ         }
309c8e3ef78SKatayama Hirofumi MZ     }
310c8e3ef78SKatayama Hirofumi MZ 
311c8e3ef78SKatayama Hirofumi MZ     if (Encoding)
312c8e3ef78SKatayama Hirofumi MZ         *Encoding = encFile;
313c8e3ef78SKatayama Hirofumi MZ     if (SkipBytes)
314c8e3ef78SKatayama Hirofumi MZ         *SkipBytes = dwPos;
315c8e3ef78SKatayama Hirofumi MZ 
316c8e3ef78SKatayama Hirofumi MZ     return (encFile != ENCODING_ANSI);
317c8e3ef78SKatayama Hirofumi MZ }
318c8e3ef78SKatayama Hirofumi MZ 
SearchFile(LPCWSTR lpFilePath,_SearchData * pSearchData)3197376cdebSKatayama Hirofumi MZ static BOOL SearchFile(LPCWSTR lpFilePath, _SearchData *pSearchData)
3202f3db8d9SBrock Mammen {
3212f3db8d9SBrock Mammen     HANDLE hFile = CreateFileW(lpFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
3222f3db8d9SBrock Mammen     if (hFile == INVALID_HANDLE_VALUE)
3237376cdebSKatayama Hirofumi MZ         return FALSE;
3242f3db8d9SBrock Mammen 
3257376cdebSKatayama Hirofumi MZ     // FIXME: support large file
3262f3db8d9SBrock Mammen     DWORD size = GetFileSize(hFile, NULL);
3277376cdebSKatayama Hirofumi MZ     if (size == 0 || size == INVALID_FILE_SIZE)
3287376cdebSKatayama Hirofumi MZ     {
3297376cdebSKatayama Hirofumi MZ         CloseHandle(hFile);
3307376cdebSKatayama Hirofumi MZ         return FALSE;
3317376cdebSKatayama Hirofumi MZ     }
3327376cdebSKatayama Hirofumi MZ 
3337376cdebSKatayama Hirofumi MZ     HANDLE hFileMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, size, NULL);
3342f3db8d9SBrock Mammen     CloseHandle(hFile);
3352f3db8d9SBrock Mammen     if (hFileMap == INVALID_HANDLE_VALUE)
3367376cdebSKatayama Hirofumi MZ         return FALSE;
3372f3db8d9SBrock Mammen 
3387376cdebSKatayama Hirofumi MZ     LPBYTE pbContents = (LPBYTE)MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, size);
3392f3db8d9SBrock Mammen     CloseHandle(hFileMap);
3407376cdebSKatayama Hirofumi MZ     if (!pbContents)
3417376cdebSKatayama Hirofumi MZ         return FALSE;
3422f3db8d9SBrock Mammen 
343c8e3ef78SKatayama Hirofumi MZ     ENCODING encoding;
344c8e3ef78SKatayama Hirofumi MZ     IsDataUnicode(pbContents, size, &encoding, NULL);
345c8e3ef78SKatayama Hirofumi MZ 
3467376cdebSKatayama Hirofumi MZ     BOOL bFound;
347c8e3ef78SKatayama Hirofumi MZ     switch (encoding)
3482f3db8d9SBrock Mammen     {
349c8e3ef78SKatayama Hirofumi MZ         case ENCODING_UTF16LE:
3507376cdebSKatayama Hirofumi MZ             // UTF-16
3517376cdebSKatayama Hirofumi MZ             bFound = StrFindNIW((LPCWSTR)pbContents, pSearchData->szQueryW, size / sizeof(WCHAR));
352c8e3ef78SKatayama Hirofumi MZ             break;
353c8e3ef78SKatayama Hirofumi MZ         case ENCODING_UTF16BE:
3547376cdebSKatayama Hirofumi MZ             // UTF-16 BE
3557376cdebSKatayama Hirofumi MZ             bFound = StrFindNIW((LPCWSTR)pbContents, pSearchData->szQueryU16BE, size / sizeof(WCHAR));
356c8e3ef78SKatayama Hirofumi MZ             break;
357c8e3ef78SKatayama Hirofumi MZ         case ENCODING_UTF8:
3587376cdebSKatayama Hirofumi MZ             // UTF-8
3597376cdebSKatayama Hirofumi MZ             bFound = StrFindNIA((LPCSTR)pbContents, pSearchData->szQueryU8, size / sizeof(CHAR));
360c8e3ef78SKatayama Hirofumi MZ             break;
361c8e3ef78SKatayama Hirofumi MZ         case ENCODING_ANSI:
362c8e3ef78SKatayama Hirofumi MZ         default:
363c8e3ef78SKatayama Hirofumi MZ             // ANSI or UTF-8 without BOM
3647376cdebSKatayama Hirofumi MZ             bFound = StrFindNIA((LPCSTR)pbContents, pSearchData->szQueryA, size / sizeof(CHAR));
365c8e3ef78SKatayama Hirofumi MZ             if (!bFound && pSearchData->szQueryA != pSearchData->szQueryU8)
366c8e3ef78SKatayama Hirofumi MZ                 bFound = StrFindNIA((LPCSTR)pbContents, pSearchData->szQueryU8, size / sizeof(CHAR));
367c8e3ef78SKatayama Hirofumi MZ             break;
3682f3db8d9SBrock Mammen     }
3692f3db8d9SBrock Mammen 
3707376cdebSKatayama Hirofumi MZ     UnmapViewOfFile(pbContents);
3717376cdebSKatayama Hirofumi MZ     return bFound;
3722f3db8d9SBrock Mammen }
3732f3db8d9SBrock Mammen 
FileNameMatch(LPCWSTR FindDataFileName,_SearchData * pSearchData)374103c87d2SDoug Lyons static BOOL FileNameMatch(LPCWSTR FindDataFileName, _SearchData *pSearchData)
375103c87d2SDoug Lyons {
376103c87d2SDoug Lyons     if (pSearchData->szFileName.IsEmpty() || PathMatchSpecW(FindDataFileName, pSearchData->szFileName))
377103c87d2SDoug Lyons     {
378103c87d2SDoug Lyons         return TRUE;
379103c87d2SDoug Lyons     }
380103c87d2SDoug Lyons     return FALSE;
381103c87d2SDoug Lyons }
382103c87d2SDoug Lyons 
ContentsMatch(LPCWSTR szPath,_SearchData * pSearchData)383103c87d2SDoug Lyons static BOOL ContentsMatch(LPCWSTR szPath, _SearchData *pSearchData)
384103c87d2SDoug Lyons {
385103c87d2SDoug Lyons     if (pSearchData->szQueryA.IsEmpty() || SearchFile(szPath, pSearchData))
386103c87d2SDoug Lyons     {
387103c87d2SDoug Lyons         return TRUE;
388103c87d2SDoug Lyons     }
389103c87d2SDoug Lyons     return FALSE;
390103c87d2SDoug Lyons }
391103c87d2SDoug Lyons 
AttribHiddenMatch(DWORD FileAttributes,_SearchData * pSearchData)392103c87d2SDoug Lyons static BOOL AttribHiddenMatch(DWORD FileAttributes, _SearchData *pSearchData)
393103c87d2SDoug Lyons {
394103c87d2SDoug Lyons     if (!(FileAttributes & FILE_ATTRIBUTE_HIDDEN) || (pSearchData->SearchHidden))
395103c87d2SDoug Lyons     {
396103c87d2SDoug Lyons         return TRUE;
397103c87d2SDoug Lyons     }
398103c87d2SDoug Lyons     return FALSE;
399103c87d2SDoug Lyons }
400103c87d2SDoug Lyons 
RecursiveFind(LPCWSTR lpPath,_SearchData * pSearchData)401c46d6036SBrock Mammen static UINT RecursiveFind(LPCWSTR lpPath, _SearchData *pSearchData)
4022f3db8d9SBrock Mammen {
4032f3db8d9SBrock Mammen     if (WaitForSingleObject(pSearchData->hStopEvent, 0) != WAIT_TIMEOUT)
404c46d6036SBrock Mammen         return 0;
4052f3db8d9SBrock Mammen 
4062f3db8d9SBrock Mammen     WCHAR szPath[MAX_PATH];
4072f3db8d9SBrock Mammen     WIN32_FIND_DATAW FindData;
4082f3db8d9SBrock Mammen     HANDLE hFindFile;
4092f3db8d9SBrock Mammen     BOOL bMoreFiles = TRUE;
410c46d6036SBrock Mammen     UINT uTotalFound = 0;
4112f3db8d9SBrock Mammen 
4127376cdebSKatayama Hirofumi MZ     PathCombineW(szPath, lpPath, L"*");
4132f3db8d9SBrock Mammen 
4142f3db8d9SBrock Mammen     for (hFindFile = FindFirstFileW(szPath, &FindData);
4152f3db8d9SBrock Mammen         bMoreFiles && hFindFile != INVALID_HANDLE_VALUE;
4162f3db8d9SBrock Mammen         bMoreFiles = FindNextFileW(hFindFile, &FindData))
4172f3db8d9SBrock Mammen     {
4187376cdebSKatayama Hirofumi MZ #define IS_DOTS(psz) ((psz)[0] == L'.' && ((psz)[1] == 0 || ((psz)[1] == L'.' && (psz)[2] == 0)))
4197376cdebSKatayama Hirofumi MZ         if (IS_DOTS(FindData.cFileName))
4202f3db8d9SBrock Mammen             continue;
4212f3db8d9SBrock Mammen 
4222f3db8d9SBrock Mammen         PathCombineW(szPath, lpPath, FindData.cFileName);
4232f3db8d9SBrock Mammen 
4242f3db8d9SBrock Mammen         if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
4252f3db8d9SBrock Mammen         {
426c46d6036SBrock Mammen             CStringW status;
4272dd4f871SKatayama Hirofumi MZ             if (pSearchData->szQueryW.IsEmpty() &&
4282dd4f871SKatayama Hirofumi MZ                 FileNameMatch(FindData.cFileName, pSearchData) &&
4292dd4f871SKatayama Hirofumi MZ                 AttribHiddenMatch(FindData.dwFileAttributes, pSearchData))
430b6b7bda4SDoug Lyons             {
4310fbf4fb8SKatayama Hirofumi MZ                 LPWSTR pszPathDup;
4320fbf4fb8SKatayama Hirofumi MZ                 SHStrDupW(szPath, &pszPathDup);
4330fbf4fb8SKatayama Hirofumi MZ                 PostMessageW(pSearchData->hwnd, WM_SEARCH_ADD_RESULT, 0, (LPARAM)pszPathDup);
434b6b7bda4SDoug Lyons                 uTotalFound++;
435b6b7bda4SDoug Lyons             }
436c46d6036SBrock Mammen             status.Format(IDS_SEARCH_FOLDER, FindData.cFileName);
4370fbf4fb8SKatayama Hirofumi MZ             LPWSTR pszStatusDup;
4380fbf4fb8SKatayama Hirofumi MZ             SHStrDupW(status.GetBuffer(), &pszStatusDup);
4390fbf4fb8SKatayama Hirofumi MZ             PostMessageW(pSearchData->hwnd, WM_SEARCH_UPDATE_STATUS, 0, (LPARAM)pszStatusDup);
4402f3db8d9SBrock Mammen 
441c46d6036SBrock Mammen             uTotalFound += RecursiveFind(szPath, pSearchData);
4422f3db8d9SBrock Mammen         }
443103c87d2SDoug Lyons         else if (FileNameMatch(FindData.cFileName, pSearchData)
444103c87d2SDoug Lyons                 && AttribHiddenMatch(FindData.dwFileAttributes, pSearchData)
445103c87d2SDoug Lyons                 && ContentsMatch(szPath, pSearchData))
4462f3db8d9SBrock Mammen         {
4478246cd4eSBrock Mammen             uTotalFound++;
4480fbf4fb8SKatayama Hirofumi MZ             LPWSTR pszPathDup;
4490fbf4fb8SKatayama Hirofumi MZ             SHStrDupW(szPath, &pszPathDup);
4500fbf4fb8SKatayama Hirofumi MZ             PostMessageW(pSearchData->hwnd, WM_SEARCH_ADD_RESULT, 0, (LPARAM)pszPathDup);
4512f3db8d9SBrock Mammen         }
4522f3db8d9SBrock Mammen     }
4532f3db8d9SBrock Mammen 
4542f3db8d9SBrock Mammen     if (hFindFile != INVALID_HANDLE_VALUE)
4552f3db8d9SBrock Mammen         FindClose(hFindFile);
456c46d6036SBrock Mammen 
457c46d6036SBrock Mammen     return uTotalFound;
4582f3db8d9SBrock Mammen }
4592f3db8d9SBrock Mammen 
SearchThreadProc(LPVOID lpParameter)4608246cd4eSBrock Mammen DWORD WINAPI CFindFolder::SearchThreadProc(LPVOID lpParameter)
4612f3db8d9SBrock Mammen {
4622f3db8d9SBrock Mammen     _SearchData *data = static_cast<_SearchData*>(lpParameter);
4632f3db8d9SBrock Mammen 
4640aa2e82cSKatayama Hirofumi MZ     HRESULT hrCoInit = CoInitializeEx(NULL, COINIT_MULTITHREADED);
4650aa2e82cSKatayama Hirofumi MZ 
46641d7b370SBrock Mammen     data->pFindFolder->NotifyConnections(DISPID_SEARCHSTART);
46741d7b370SBrock Mammen 
468c46d6036SBrock Mammen     UINT uTotalFound = RecursiveFind(data->szPath, data);
4692f3db8d9SBrock Mammen 
47041d7b370SBrock Mammen     data->pFindFolder->NotifyConnections(DISPID_SEARCHCOMPLETE);
47141d7b370SBrock Mammen 
472c46d6036SBrock Mammen     CStringW status;
473c46d6036SBrock Mammen     status.Format(IDS_SEARCH_FILES_FOUND, uTotalFound);
4740fbf4fb8SKatayama Hirofumi MZ     LPWSTR pszStatusDup;
4750fbf4fb8SKatayama Hirofumi MZ     SHStrDupW(status.GetBuffer(), &pszStatusDup);
4760fbf4fb8SKatayama Hirofumi MZ     ::PostMessageW(data->hwnd, WM_SEARCH_UPDATE_STATUS, 0, (LPARAM)pszStatusDup);
477fe5c76a0SBrock Mammen     ::SendMessageW(data->hwnd, WM_SEARCH_STOP, 0, 0);
478c46d6036SBrock Mammen 
479fe5c76a0SBrock Mammen     CloseHandle(data->hStopEvent);
480c46d6036SBrock Mammen     delete data;
4812f3db8d9SBrock Mammen 
4820aa2e82cSKatayama Hirofumi MZ     if (SUCCEEDED(hrCoInit))
4830aa2e82cSKatayama Hirofumi MZ         CoUninitialize();
4840aa2e82cSKatayama Hirofumi MZ 
4852f3db8d9SBrock Mammen     return 0;
4862f3db8d9SBrock Mammen }
4872f3db8d9SBrock Mammen 
NotifyConnections(DISPID id)48841d7b370SBrock Mammen void CFindFolder::NotifyConnections(DISPID id)
48941d7b370SBrock Mammen {
49041d7b370SBrock Mammen     DISPPARAMS dispatchParams = {0};
49141d7b370SBrock Mammen     CComDynamicUnkArray &subscribers =
49241d7b370SBrock Mammen         IConnectionPointImpl<CFindFolder, &DIID_DSearchCommandEvents>::m_vec;
49341d7b370SBrock Mammen     for (IUnknown** pSubscriber = subscribers.begin(); pSubscriber < subscribers.end(); pSubscriber++)
49441d7b370SBrock Mammen     {
49541d7b370SBrock Mammen         if (!*pSubscriber)
49641d7b370SBrock Mammen             continue;
49741d7b370SBrock Mammen 
49841d7b370SBrock Mammen         CComPtr<IDispatch> pDispatch;
49941d7b370SBrock Mammen         HRESULT hResult = (*pSubscriber)->QueryInterface(IID_PPV_ARG(IDispatch, &pDispatch));
50041d7b370SBrock Mammen         if (!FAILED_UNEXPECTEDLY(hResult))
50141d7b370SBrock Mammen             pDispatch->Invoke(id, GUID_NULL, 0, DISPATCH_METHOD, &dispatchParams, NULL, NULL, NULL);
50241d7b370SBrock Mammen     }
50341d7b370SBrock Mammen }
50441d7b370SBrock Mammen 
StartSearch(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)5052f3db8d9SBrock Mammen LRESULT CFindFolder::StartSearch(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
506666bf346SBrock Mammen {
507103c87d2SDoug Lyons     HKEY hkey;
508103c87d2SDoug Lyons     DWORD size = sizeof(DWORD);
509103c87d2SDoug Lyons     DWORD result;
510103c87d2SDoug Lyons     DWORD SearchHiddenValue = 0;
511103c87d2SDoug Lyons 
512666bf346SBrock Mammen     if (!lParam)
513666bf346SBrock Mammen         return 0;
514666bf346SBrock Mammen 
5152f3db8d9SBrock Mammen     // Clear all previous search results
516666bf346SBrock Mammen     UINT uItemIndex;
5172f3db8d9SBrock Mammen     m_shellFolderView->RemoveObject(NULL, &uItemIndex);
518666bf346SBrock Mammen 
5192f3db8d9SBrock Mammen     _SearchData* pSearchData = new _SearchData();
5202f3db8d9SBrock Mammen     pSearchData->pFindFolder = this;
5212f3db8d9SBrock Mammen     pSearchData->hwnd = m_hWnd;
5228246cd4eSBrock Mammen 
5238246cd4eSBrock Mammen     SearchStart *pSearchParams = (SearchStart *) lParam;
5248246cd4eSBrock Mammen     pSearchData->szPath = pSearchParams->szPath;
5258246cd4eSBrock Mammen     pSearchData->szFileName = pSearchParams->szFileName;
5268246cd4eSBrock Mammen     pSearchData->szQueryA = pSearchParams->szQuery;
5278246cd4eSBrock Mammen     pSearchData->szQueryW = pSearchParams->szQuery;
5287376cdebSKatayama Hirofumi MZ 
5297376cdebSKatayama Hirofumi MZ     // UTF-16 BE
5307376cdebSKatayama Hirofumi MZ     {
5317376cdebSKatayama Hirofumi MZ         CStringW utf16 = pSearchData->szQueryW;
5327376cdebSKatayama Hirofumi MZ         LPWSTR psz = utf16.GetBuffer();
5337376cdebSKatayama Hirofumi MZ         for (SIZE_T i = 0; psz[i]; ++i)
5347376cdebSKatayama Hirofumi MZ         {
5357376cdebSKatayama Hirofumi MZ             psz[i] = MAKEWORD(HIBYTE(psz[i]), LOBYTE(psz[i]));
5367376cdebSKatayama Hirofumi MZ         }
5377376cdebSKatayama Hirofumi MZ         utf16.ReleaseBuffer();
5387376cdebSKatayama Hirofumi MZ         pSearchData->szQueryU16BE = utf16;
5397376cdebSKatayama Hirofumi MZ     }
5407376cdebSKatayama Hirofumi MZ 
5417376cdebSKatayama Hirofumi MZ     // UTF-8
5427376cdebSKatayama Hirofumi MZ     {
5437376cdebSKatayama Hirofumi MZ         CStringA utf8;
5447376cdebSKatayama Hirofumi MZ         INT cch = WideCharToMultiByte(CP_UTF8, 0, pSearchData->szQueryW, -1, NULL, 0, NULL, NULL);
5457376cdebSKatayama Hirofumi MZ         if (cch > 0)
5467376cdebSKatayama Hirofumi MZ         {
5477376cdebSKatayama Hirofumi MZ             LPSTR psz = utf8.GetBuffer(cch);
5487376cdebSKatayama Hirofumi MZ             WideCharToMultiByte(CP_UTF8, 0, pSearchData->szQueryW, -1, psz, cch, NULL, NULL);
5497376cdebSKatayama Hirofumi MZ             utf8.ReleaseBuffer();
5507376cdebSKatayama Hirofumi MZ             pSearchData->szQueryU8 = utf8;
5517376cdebSKatayama Hirofumi MZ         }
5527376cdebSKatayama Hirofumi MZ         else
5537376cdebSKatayama Hirofumi MZ         {
5547376cdebSKatayama Hirofumi MZ             pSearchData->szQueryU8 = pSearchData->szQueryA;
5557376cdebSKatayama Hirofumi MZ         }
5567376cdebSKatayama Hirofumi MZ     }
5577376cdebSKatayama Hirofumi MZ 
558103c87d2SDoug Lyons     pSearchData->SearchHidden = pSearchParams->SearchHidden;
5598246cd4eSBrock Mammen     SHFree(pSearchParams);
5608246cd4eSBrock Mammen 
561103c87d2SDoug Lyons     TRACE("pSearchParams->SearchHidden is '%d'.\n", pSearchData->SearchHidden);
562103c87d2SDoug Lyons 
563103c87d2SDoug Lyons     if (pSearchData->SearchHidden)
564103c87d2SDoug Lyons         SearchHiddenValue = 1;
565103c87d2SDoug Lyons     else
566103c87d2SDoug Lyons         SearchHiddenValue = 0;
567103c87d2SDoug Lyons 
568103c87d2SDoug Lyons     /* Placing the code to save the changed settings to the registry here has the effect of not saving any changes */
569103c87d2SDoug Lyons     /* to the registry unless the user clicks on the "Search" button. This is the same as what we see in Windows.  */
570103c87d2SDoug Lyons     result = RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer", 0, KEY_SET_VALUE, &hkey);
571103c87d2SDoug Lyons     if (result == ERROR_SUCCESS)
572103c87d2SDoug Lyons     {
573103c87d2SDoug Lyons         if (RegSetValueExW(hkey, L"SearchHidden", NULL, REG_DWORD, (const BYTE*)&SearchHiddenValue, size) == ERROR_SUCCESS)
574103c87d2SDoug Lyons         {
575103c87d2SDoug Lyons             TRACE("SearchHidden is '%d'.\n", SearchHiddenValue);
576103c87d2SDoug Lyons         }
577103c87d2SDoug Lyons         else
578103c87d2SDoug Lyons         {
579103c87d2SDoug Lyons             ERR("RegSetValueEx for \"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\SearchHidden\" Failed.\n");
580103c87d2SDoug Lyons         }
581103c87d2SDoug Lyons         RegCloseKey(hkey);
582103c87d2SDoug Lyons     }
583103c87d2SDoug Lyons     else
584103c87d2SDoug Lyons     {
585103c87d2SDoug Lyons         ERR("RegOpenKey for \"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\" Failed.\n");
586103c87d2SDoug Lyons     }
587103c87d2SDoug Lyons 
5882f3db8d9SBrock Mammen     if (m_hStopEvent)
5892f3db8d9SBrock Mammen         SetEvent(m_hStopEvent);
5902f3db8d9SBrock Mammen     pSearchData->hStopEvent = m_hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
5912f3db8d9SBrock Mammen 
5928246cd4eSBrock Mammen     if (!SHCreateThread(SearchThreadProc, pSearchData, NULL, NULL))
5932f3db8d9SBrock Mammen     {
5942f3db8d9SBrock Mammen         SHFree(pSearchData);
5950311544bSBrock Mammen         return 0;
5962f3db8d9SBrock Mammen     }
5972f3db8d9SBrock Mammen 
5980311544bSBrock Mammen     return 0;
5992f3db8d9SBrock Mammen }
6002f3db8d9SBrock Mammen 
StopSearch(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)60141f9ad12SBrock Mammen LRESULT CFindFolder::StopSearch(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
60241f9ad12SBrock Mammen {
60341f9ad12SBrock Mammen     if (m_hStopEvent)
60441f9ad12SBrock Mammen     {
60541f9ad12SBrock Mammen         SetEvent(m_hStopEvent);
60641f9ad12SBrock Mammen         m_hStopEvent = NULL;
60741f9ad12SBrock Mammen     }
60841f9ad12SBrock Mammen     return 0;
60941f9ad12SBrock Mammen }
61041f9ad12SBrock Mammen 
AddResult(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)6112f3db8d9SBrock Mammen LRESULT CFindFolder::AddResult(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
6122f3db8d9SBrock Mammen {
6132f3db8d9SBrock Mammen     if (!lParam)
6142f3db8d9SBrock Mammen         return 0;
6152f3db8d9SBrock Mammen 
6162f3db8d9SBrock Mammen     CComHeapPtr<WCHAR> lpPath((LPWSTR) lParam);
6172f3db8d9SBrock Mammen 
6182f3db8d9SBrock Mammen     CComHeapPtr<ITEMIDLIST> lpSearchPidl(_ILCreate(lpPath));
6192f3db8d9SBrock Mammen     if (lpSearchPidl)
6202f3db8d9SBrock Mammen     {
6212f3db8d9SBrock Mammen         UINT uItemIndex;
6222f3db8d9SBrock Mammen         m_shellFolderView->AddObject(lpSearchPidl, &uItemIndex);
6232f3db8d9SBrock Mammen     }
6242f3db8d9SBrock Mammen 
6252f3db8d9SBrock Mammen     return 0;
626666bf346SBrock Mammen }
627666bf346SBrock Mammen 
UpdateStatus(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)62804fcbe32SBrock Mammen LRESULT CFindFolder::UpdateStatus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
62904fcbe32SBrock Mammen {
630c46d6036SBrock Mammen     CComHeapPtr<WCHAR> status((LPWSTR) lParam);
63104fcbe32SBrock Mammen     if (m_shellBrowser)
63204fcbe32SBrock Mammen     {
633c46d6036SBrock Mammen         m_shellBrowser->SetStatusTextSB(status);
63404fcbe32SBrock Mammen     }
63504fcbe32SBrock Mammen 
6360311544bSBrock Mammen     return 0;
63704fcbe32SBrock Mammen }
63804fcbe32SBrock Mammen 
639ccf9ce32SBrock Mammen // *** IShellFolder2 methods ***
GetDefaultSearchGUID(GUID * pguid)640ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetDefaultSearchGUID(GUID *pguid)
641ccf9ce32SBrock Mammen {
642ccf9ce32SBrock Mammen     UNIMPLEMENTED;
643ccf9ce32SBrock Mammen     return E_NOTIMPL;
644ccf9ce32SBrock Mammen }
645ccf9ce32SBrock Mammen 
EnumSearches(IEnumExtraSearch ** ppenum)646ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::EnumSearches(IEnumExtraSearch **ppenum)
647ccf9ce32SBrock Mammen {
648ccf9ce32SBrock Mammen     UNIMPLEMENTED;
649ccf9ce32SBrock Mammen     return E_NOTIMPL;
650ccf9ce32SBrock Mammen }
651ccf9ce32SBrock Mammen 
GetDefaultColumn(DWORD,ULONG * pSort,ULONG * pDisplay)652ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetDefaultColumn(DWORD, ULONG *pSort, ULONG *pDisplay)
653ccf9ce32SBrock Mammen {
654ccf9ce32SBrock Mammen     if (pSort)
655ccf9ce32SBrock Mammen         *pSort = 0;
656ccf9ce32SBrock Mammen     if (pDisplay)
657ccf9ce32SBrock Mammen         *pDisplay = 0;
658ccf9ce32SBrock Mammen     return S_OK;
659ccf9ce32SBrock Mammen }
660ccf9ce32SBrock Mammen 
GetDefaultColumnState(UINT iColumn,DWORD * pcsFlags)661ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
662ccf9ce32SBrock Mammen {
663c0799cd2SBrock Mammen     if (!pcsFlags)
664ccf9ce32SBrock Mammen         return E_INVALIDARG;
665c0799cd2SBrock Mammen     if (iColumn >= _countof(g_ColumnDefs))
666c0799cd2SBrock Mammen         return m_pisfInner->GetDefaultColumnState(iColumn - _countof(g_ColumnDefs) + 1, pcsFlags);
667ccf9ce32SBrock Mammen     *pcsFlags = g_ColumnDefs[iColumn].dwDefaultState;
668ccf9ce32SBrock Mammen     return S_OK;
669ccf9ce32SBrock Mammen }
670ccf9ce32SBrock Mammen 
GetDetailsEx(PCUITEMID_CHILD pidl,const SHCOLUMNID * pscid,VARIANT * pv)671ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
672ccf9ce32SBrock Mammen {
673c0799cd2SBrock Mammen     return m_pisfInner->GetDetailsEx(pidl, pscid, pv);
674ccf9ce32SBrock Mammen }
675ccf9ce32SBrock Mammen 
GetDetailsOf(PCUITEMID_CHILD pidl,UINT iColumn,SHELLDETAILS * pDetails)676ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *pDetails)
677ccf9ce32SBrock Mammen {
678ccf9ce32SBrock Mammen     if (iColumn >= _countof(g_ColumnDefs))
679666bf346SBrock Mammen         return m_pisfInner->GetDetailsOf(_ILGetFSPidl(pidl), iColumn - _countof(g_ColumnDefs) + 1, pDetails);
680ccf9ce32SBrock Mammen 
681ccf9ce32SBrock Mammen     pDetails->cxChar = g_ColumnDefs[iColumn].cxChar;
682ccf9ce32SBrock Mammen     pDetails->fmt = g_ColumnDefs[iColumn].fmt;
683ccf9ce32SBrock Mammen 
684ccf9ce32SBrock Mammen     if (!pidl)
6856c6fd6d9SBrock Mammen         return SHSetStrRet(&pDetails->str, _AtlBaseModule.GetResourceInstance(), g_ColumnDefs[iColumn].iResource);
686ccf9ce32SBrock Mammen 
6872f6f24d0SAtharva Kulkarni     if (iColumn == COL_LOCATION_INDEX)
688666bf346SBrock Mammen     {
689a3ee648dSBrock Mammen         return SHSetStrRet(&pDetails->str, _ILGetPath(pidl));
690666bf346SBrock Mammen     }
691666bf346SBrock Mammen 
6922f6f24d0SAtharva Kulkarni     if (iColumn == COL_RELEVANCE_INDEX)
6932f6f24d0SAtharva Kulkarni     {
6942f6f24d0SAtharva Kulkarni         // TODO: Fill once the relevance is calculated
6952f6f24d0SAtharva Kulkarni         return SHSetStrRet(&pDetails->str, "");
6962f6f24d0SAtharva Kulkarni     }
6972f6f24d0SAtharva Kulkarni 
698ccf9ce32SBrock Mammen     return GetDisplayNameOf(pidl, SHGDN_NORMAL, &pDetails->str);
699ccf9ce32SBrock Mammen }
700ccf9ce32SBrock Mammen 
MapColumnToSCID(UINT iColumn,SHCOLUMNID * pscid)701ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::MapColumnToSCID(UINT iColumn, SHCOLUMNID *pscid)
702ccf9ce32SBrock Mammen {
703ccf9ce32SBrock Mammen     UNIMPLEMENTED;
704ccf9ce32SBrock Mammen     return E_NOTIMPL;
705ccf9ce32SBrock Mammen }
706ccf9ce32SBrock Mammen 
707ccf9ce32SBrock Mammen // *** IShellFolder methods ***
ParseDisplayName(HWND hwndOwner,LPBC pbc,LPOLESTR lpszDisplayName,ULONG * pchEaten,PIDLIST_RELATIVE * ppidl,ULONG * pdwAttributes)708ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, ULONG *pchEaten,
709ccf9ce32SBrock Mammen                                            PIDLIST_RELATIVE *ppidl, ULONG *pdwAttributes)
710ccf9ce32SBrock Mammen {
711ccf9ce32SBrock Mammen     UNIMPLEMENTED;
712ccf9ce32SBrock Mammen     return E_NOTIMPL;
713ccf9ce32SBrock Mammen }
714ccf9ce32SBrock Mammen 
EnumObjects(HWND hwndOwner,DWORD dwFlags,LPENUMIDLIST * ppEnumIDList)715ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
716ccf9ce32SBrock Mammen {
717ccf9ce32SBrock Mammen     *ppEnumIDList = NULL;
718ccf9ce32SBrock Mammen     return S_FALSE;
719ccf9ce32SBrock Mammen }
720ccf9ce32SBrock Mammen 
BindToObject(PCUIDLIST_RELATIVE pidl,LPBC pbcReserved,REFIID riid,LPVOID * ppvOut)721ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
722ccf9ce32SBrock Mammen {
723ccf9ce32SBrock Mammen     UNIMPLEMENTED;
724ccf9ce32SBrock Mammen     return E_NOTIMPL;
725ccf9ce32SBrock Mammen }
726ccf9ce32SBrock Mammen 
BindToStorage(PCUIDLIST_RELATIVE pidl,LPBC pbcReserved,REFIID riid,LPVOID * ppvOut)727ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
728ccf9ce32SBrock Mammen {
729ccf9ce32SBrock Mammen     UNIMPLEMENTED;
730ccf9ce32SBrock Mammen     return E_NOTIMPL;
731ccf9ce32SBrock Mammen }
732ccf9ce32SBrock Mammen 
CompareIDs(LPARAM lParam,PCUIDLIST_RELATIVE pidl1,PCUIDLIST_RELATIVE pidl2)733ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
734ccf9ce32SBrock Mammen {
735f0d6d989SBrock Mammen     WORD wColumn = LOWORD(lParam);
736f0d6d989SBrock Mammen     switch (wColumn)
737f0d6d989SBrock Mammen     {
7382f6f24d0SAtharva Kulkarni     case COL_NAME_INDEX: // Name
739f0d6d989SBrock Mammen         break;
7402f6f24d0SAtharva Kulkarni     case COL_LOCATION_INDEX: // Path
741f0d6d989SBrock Mammen         return MAKE_COMPARE_HRESULT(StrCmpW(_ILGetPath(pidl1), _ILGetPath(pidl2)));
7422f6f24d0SAtharva Kulkarni     case COL_RELEVANCE_INDEX: // Relevance
743f0d6d989SBrock Mammen         return E_NOTIMPL;
744f0d6d989SBrock Mammen     default: // Default columns
745f0d6d989SBrock Mammen         wColumn -= _countof(g_ColumnDefs) - 1;
746f0d6d989SBrock Mammen         break;
747f0d6d989SBrock Mammen     }
748f0d6d989SBrock Mammen     return m_pisfInner->CompareIDs(HIWORD(lParam) | wColumn, _ILGetFSPidl(pidl1), _ILGetFSPidl(pidl2));
749ccf9ce32SBrock Mammen }
750ccf9ce32SBrock Mammen 
CreateViewObject(HWND hwndOwner,REFIID riid,LPVOID * ppvOut)751ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
752ccf9ce32SBrock Mammen {
753ccf9ce32SBrock Mammen     if (riid == IID_IShellView)
754ccf9ce32SBrock Mammen     {
755ccf9ce32SBrock Mammen         SFV_CREATE sfvparams = {};
756ccf9ce32SBrock Mammen         sfvparams.cbSize = sizeof(SFV_CREATE);
757ccf9ce32SBrock Mammen         sfvparams.pshf = this;
7589c290040SBrock Mammen         sfvparams.psfvcb = this;
759666bf346SBrock Mammen         HRESULT hr = SHCreateShellFolderView(&sfvparams, (IShellView **) ppvOut);
760666bf346SBrock Mammen         if (FAILED_UNEXPECTEDLY(hr))
761666bf346SBrock Mammen         {
762666bf346SBrock Mammen             return hr;
763666bf346SBrock Mammen         }
764666bf346SBrock Mammen 
765666bf346SBrock Mammen         return ((IShellView * ) * ppvOut)->QueryInterface(IID_PPV_ARG(IShellFolderView, &m_shellFolderView));
766ccf9ce32SBrock Mammen     }
767ccf9ce32SBrock Mammen     return E_NOINTERFACE;
768ccf9ce32SBrock Mammen }
769ccf9ce32SBrock Mammen 
GetAttributesOf(UINT cidl,PCUITEMID_CHILD_ARRAY apidl,DWORD * rgfInOut)770ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut)
771ccf9ce32SBrock Mammen {
772666bf346SBrock Mammen     CComHeapPtr<PCITEMID_CHILD> aFSPidl;
773666bf346SBrock Mammen     aFSPidl.Allocate(cidl);
774666bf346SBrock Mammen     for (UINT i = 0; i < cidl; i++)
775666bf346SBrock Mammen     {
776666bf346SBrock Mammen         aFSPidl[i] = _ILGetFSPidl(apidl[i]);
777666bf346SBrock Mammen     }
778666bf346SBrock Mammen 
779666bf346SBrock Mammen     return m_pisfInner->GetAttributesOf(cidl, aFSPidl, rgfInOut);
780ccf9ce32SBrock Mammen }
781ccf9ce32SBrock Mammen 
782312b628fSBrock Mammen class CFindFolderContextMenu :
783312b628fSBrock Mammen         public IContextMenu,
784312b628fSBrock Mammen         public CComObjectRootEx<CComMultiThreadModelNoCS>
785ccf9ce32SBrock Mammen {
786312b628fSBrock Mammen     CComPtr<IContextMenu> m_pInner;
787312b628fSBrock Mammen     CComPtr<IShellFolderView> m_shellFolderView;
788312b628fSBrock Mammen     UINT m_firstCmdId;
789312b628fSBrock Mammen     static const UINT ADDITIONAL_MENU_ITEMS = 2;
790312b628fSBrock Mammen 
791312b628fSBrock Mammen     //// *** IContextMenu methods ***
QueryContextMenu(HMENU hMenu,UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags)792312b628fSBrock Mammen     STDMETHODIMP QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
793312b628fSBrock Mammen     {
794312b628fSBrock Mammen         m_firstCmdId = indexMenu;
795312b628fSBrock Mammen         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst++, MFT_STRING, MAKEINTRESOURCEW(IDS_SEARCH_OPEN_FOLDER), MFS_ENABLED);
796312b628fSBrock Mammen         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst++, MFT_SEPARATOR, NULL, 0);
797312b628fSBrock Mammen         return m_pInner->QueryContextMenu(hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
798312b628fSBrock Mammen     }
799312b628fSBrock Mammen 
InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)800312b628fSBrock Mammen     STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
801312b628fSBrock Mammen     {
802312b628fSBrock Mammen         if (!IS_INTRESOURCE(lpcmi->lpVerb))
803312b628fSBrock Mammen         {
804312b628fSBrock Mammen             return m_pInner->InvokeCommand(lpcmi);
805312b628fSBrock Mammen         }
806312b628fSBrock Mammen 
807312b628fSBrock Mammen         if (LOWORD(lpcmi->lpVerb) < m_firstCmdId + ADDITIONAL_MENU_ITEMS)
808312b628fSBrock Mammen         {
809312b628fSBrock Mammen             PCUITEMID_CHILD *apidl;
810312b628fSBrock Mammen             UINT cidl;
811312b628fSBrock Mammen             HRESULT hResult = m_shellFolderView->GetSelectedObjects(&apidl, &cidl);
812312b628fSBrock Mammen             if (FAILED_UNEXPECTEDLY(hResult))
813312b628fSBrock Mammen                 return hResult;
814312b628fSBrock Mammen 
815312b628fSBrock Mammen             for (UINT i = 0; i < cidl; i++)
8162fdaa386SBrock Mammen             {
817a3ee648dSBrock Mammen                 CComHeapPtr<ITEMIDLIST> folderPidl(ILCreateFromPathW(_ILGetPath(apidl[i])));
818312b628fSBrock Mammen                 if (!folderPidl)
8192fdaa386SBrock Mammen                     return E_OUTOFMEMORY;
8205be53f55SWhindmar Saksit                 LPCITEMIDLIST child = _ILGetFSPidl(apidl[i]);
8215be53f55SWhindmar Saksit                 SHOpenFolderAndSelectItems(folderPidl, 1, &child, 0);
822312b628fSBrock Mammen             }
8235be53f55SWhindmar Saksit             LocalFree(apidl); // Yes, LocalFree
824312b628fSBrock Mammen             return S_OK;
8252fdaa386SBrock Mammen         }
8262fdaa386SBrock Mammen 
827312b628fSBrock Mammen         CMINVOKECOMMANDINFOEX actualCmdInfo;
828312b628fSBrock Mammen         memcpy(&actualCmdInfo, lpcmi, lpcmi->cbSize);
829312b628fSBrock Mammen         actualCmdInfo.lpVerb -= ADDITIONAL_MENU_ITEMS;
830312b628fSBrock Mammen         return m_pInner->InvokeCommand((CMINVOKECOMMANDINFO *)&actualCmdInfo);
831312b628fSBrock Mammen     }
832312b628fSBrock Mammen 
GetCommandString(UINT_PTR idCommand,UINT uFlags,UINT * lpReserved,LPSTR lpszName,UINT uMaxNameLen)833312b628fSBrock Mammen     STDMETHODIMP GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen)
834312b628fSBrock Mammen     {
835312b628fSBrock Mammen         return m_pInner->GetCommandString(idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
836312b628fSBrock Mammen     }
837312b628fSBrock Mammen 
838312b628fSBrock Mammen public:
Create(IShellFolderView * pShellFolderView,IContextMenu * pInnerContextMenu,IContextMenu ** pContextMenu)839312b628fSBrock Mammen     static HRESULT Create(IShellFolderView *pShellFolderView, IContextMenu *pInnerContextMenu, IContextMenu **pContextMenu)
840312b628fSBrock Mammen     {
841312b628fSBrock Mammen         CComObject<CFindFolderContextMenu> *pObj;
842312b628fSBrock Mammen         HRESULT hResult = CComObject<CFindFolderContextMenu>::CreateInstance(&pObj);
843312b628fSBrock Mammen         if (FAILED_UNEXPECTEDLY(hResult))
844312b628fSBrock Mammen             return hResult;
845312b628fSBrock Mammen         pObj->m_shellFolderView = pShellFolderView;
846312b628fSBrock Mammen         pObj->m_pInner = pInnerContextMenu;
847312b628fSBrock Mammen         return pObj->QueryInterface(IID_PPV_ARG(IContextMenu, pContextMenu));
848312b628fSBrock Mammen     }
849312b628fSBrock Mammen 
850312b628fSBrock Mammen     BEGIN_COM_MAP(CFindFolderContextMenu)
851312b628fSBrock Mammen         COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
852312b628fSBrock Mammen     END_COM_MAP()
853312b628fSBrock Mammen };
854312b628fSBrock Mammen 
GetUIObjectOf(HWND hwndOwner,UINT cidl,PCUITEMID_CHILD_ARRAY apidl,REFIID riid,UINT * prgfInOut,LPVOID * ppvOut)855312b628fSBrock Mammen STDMETHODIMP CFindFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid,
856312b628fSBrock Mammen                                         UINT *prgfInOut, LPVOID *ppvOut)
857312b628fSBrock Mammen {
858666bf346SBrock Mammen     if (cidl <= 0)
859666bf346SBrock Mammen     {
860c0799cd2SBrock Mammen         return m_pisfInner->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut);
861ccf9ce32SBrock Mammen     }
862ccf9ce32SBrock Mammen 
863312b628fSBrock Mammen     CComHeapPtr<PCITEMID_CHILD> aFSPidl;
864312b628fSBrock Mammen     aFSPidl.Allocate(cidl);
865666bf346SBrock Mammen     for (UINT i = 0; i < cidl; i++)
866666bf346SBrock Mammen     {
867666bf346SBrock Mammen         aFSPidl[i] = _ILGetFSPidl(apidl[i]);
868666bf346SBrock Mammen     }
869666bf346SBrock Mammen 
8702fdaa386SBrock Mammen     if (riid == IID_IContextMenu)
8712fdaa386SBrock Mammen     {
872a3ee648dSBrock Mammen         CComHeapPtr<ITEMIDLIST> folderPidl(ILCreateFromPathW(_ILGetPath(apidl[0])));
873312b628fSBrock Mammen         if (!folderPidl)
874312b628fSBrock Mammen             return E_OUTOFMEMORY;
875312b628fSBrock Mammen         CComPtr<IShellFolder> pDesktopFolder;
876312b628fSBrock Mammen         HRESULT hResult = SHGetDesktopFolder(&pDesktopFolder);
877312b628fSBrock Mammen         if (FAILED_UNEXPECTEDLY(hResult))
878312b628fSBrock Mammen             return hResult;
879312b628fSBrock Mammen         CComPtr<IShellFolder> pShellFolder;
880312b628fSBrock Mammen         hResult = pDesktopFolder->BindToObject(folderPidl, NULL, IID_PPV_ARG(IShellFolder, &pShellFolder));
881312b628fSBrock Mammen         if (FAILED_UNEXPECTEDLY(hResult))
882312b628fSBrock Mammen             return hResult;
883312b628fSBrock Mammen         CComPtr<IContextMenu> pContextMenu;
884312b628fSBrock Mammen         hResult = pShellFolder->GetUIObjectOf(hwndOwner, cidl, aFSPidl, riid, prgfInOut, (LPVOID *)&pContextMenu);
885312b628fSBrock Mammen         if (FAILED_UNEXPECTEDLY(hResult))
886312b628fSBrock Mammen             return hResult;
887312b628fSBrock Mammen         return CFindFolderContextMenu::Create(m_shellFolderView, pContextMenu, (IContextMenu **)ppvOut);
8882fdaa386SBrock Mammen     }
8892fdaa386SBrock Mammen 
890312b628fSBrock Mammen     return m_pisfInner->GetUIObjectOf(hwndOwner, cidl, aFSPidl, riid, prgfInOut, ppvOut);
891666bf346SBrock Mammen }
892666bf346SBrock Mammen 
GetDisplayNameOf(PCUITEMID_CHILD pidl,DWORD dwFlags,LPSTRRET pName)893ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET pName)
894ccf9ce32SBrock Mammen {
895666bf346SBrock Mammen     return m_pisfInner->GetDisplayNameOf(_ILGetFSPidl(pidl), dwFlags, pName);
896ccf9ce32SBrock Mammen }
897ccf9ce32SBrock Mammen 
SetNameOf(HWND hwndOwner,PCUITEMID_CHILD pidl,LPCOLESTR lpName,DWORD dwFlags,PITEMID_CHILD * pPidlOut)898ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags,
899ccf9ce32SBrock Mammen                                     PITEMID_CHILD *pPidlOut)
900ccf9ce32SBrock Mammen {
901ccf9ce32SBrock Mammen     UNIMPLEMENTED;
902ccf9ce32SBrock Mammen     return E_NOTIMPL;
903ccf9ce32SBrock Mammen }
9049c290040SBrock Mammen 
9059c290040SBrock Mammen //// *** IShellFolderViewCB method ***
MessageSFVCB(UINT uMsg,WPARAM wParam,LPARAM lParam)9069c290040SBrock Mammen STDMETHODIMP CFindFolder::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
9079c290040SBrock Mammen {
9089c290040SBrock Mammen     switch (uMsg)
9099c290040SBrock Mammen     {
9109c290040SBrock Mammen         case SFVM_DEFVIEWMODE:
9119c290040SBrock Mammen         {
9129c290040SBrock Mammen             FOLDERVIEWMODE *pViewMode = (FOLDERVIEWMODE *) lParam;
9139c290040SBrock Mammen             *pViewMode = FVM_DETAILS;
9149c290040SBrock Mammen             return S_OK;
9159c290040SBrock Mammen         }
91606fd04d7SBrock Mammen         case SFVM_WINDOWCREATED:
91706fd04d7SBrock Mammen         {
91807d37180SBrock Mammen             // Subclass window to receive window messages
91906fd04d7SBrock Mammen             SubclassWindow((HWND) wParam);
92004fcbe32SBrock Mammen 
92107d37180SBrock Mammen             // Get shell browser for updating status bar text
92204fcbe32SBrock Mammen             CComPtr<IServiceProvider> pServiceProvider;
92304fcbe32SBrock Mammen             HRESULT hr = m_shellFolderView->QueryInterface(IID_PPV_ARG(IServiceProvider, &pServiceProvider));
92404fcbe32SBrock Mammen             if (FAILED_UNEXPECTEDLY(hr))
92504fcbe32SBrock Mammen                 return hr;
92607d37180SBrock Mammen             hr = pServiceProvider->QueryService(SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &m_shellBrowser));
92707d37180SBrock Mammen             if (FAILED_UNEXPECTEDLY(hr))
92807d37180SBrock Mammen                 return hr;
92907d37180SBrock Mammen 
93007d37180SBrock Mammen             // Open search bar
93107d37180SBrock Mammen             CComPtr<IWebBrowser2> pWebBrowser2;
93207d37180SBrock Mammen             hr = m_shellBrowser->QueryInterface(IID_PPV_ARG(IWebBrowser2, &pWebBrowser2));
93307d37180SBrock Mammen             if (FAILED_UNEXPECTEDLY(hr))
93407d37180SBrock Mammen                 return hr;
93507d37180SBrock Mammen             WCHAR pwszGuid[MAX_PATH];
93607d37180SBrock Mammen             StringFromGUID2(CLSID_FileSearchBand, pwszGuid, _countof(pwszGuid));
93707d37180SBrock Mammen             CComVariant searchBar(pwszGuid);
93807d37180SBrock Mammen             return pWebBrowser2->ShowBrowserBar(&searchBar, NULL, NULL);
93906fd04d7SBrock Mammen         }
940*a17b6e93SWhindmar Saksit         case SFVM_GETCOMMANDDIR:
941*a17b6e93SWhindmar Saksit         {
942*a17b6e93SWhindmar Saksit             HRESULT hr = E_FAIL;
943*a17b6e93SWhindmar Saksit             if (m_shellFolderView)
944*a17b6e93SWhindmar Saksit             {
945*a17b6e93SWhindmar Saksit                 PCUITEMID_CHILD *apidl;
946*a17b6e93SWhindmar Saksit                 UINT cidl = 0;
947*a17b6e93SWhindmar Saksit                 if (SUCCEEDED(hr = m_shellFolderView->GetSelectedObjects(&apidl, &cidl)))
948*a17b6e93SWhindmar Saksit                 {
949*a17b6e93SWhindmar Saksit                     if (cidl)
950*a17b6e93SWhindmar Saksit                         hr = StringCchCopyW((PWSTR)lParam, wParam, _ILGetPath(apidl[0]));
951*a17b6e93SWhindmar Saksit                     LocalFree(apidl);
952*a17b6e93SWhindmar Saksit                 }
953*a17b6e93SWhindmar Saksit             }
954*a17b6e93SWhindmar Saksit             return hr;
955*a17b6e93SWhindmar Saksit         }
9569c290040SBrock Mammen     }
9579c290040SBrock Mammen     return E_NOTIMPL;
9589c290040SBrock Mammen }
9599c290040SBrock Mammen 
960ccf9ce32SBrock Mammen //// *** IPersistFolder2 methods ***
GetCurFolder(PIDLIST_ABSOLUTE * pidl)961b90c24d6SThomas Faber STDMETHODIMP CFindFolder::GetCurFolder(PIDLIST_ABSOLUTE *pidl)
962ccf9ce32SBrock Mammen {
963ccf9ce32SBrock Mammen     *pidl = ILClone(m_pidl);
964ccf9ce32SBrock Mammen     return S_OK;
965ccf9ce32SBrock Mammen }
966ccf9ce32SBrock Mammen 
967ccf9ce32SBrock Mammen // *** IPersistFolder methods ***
Initialize(PCIDLIST_ABSOLUTE pidl)968c2b476bdSThomas Faber STDMETHODIMP CFindFolder::Initialize(PCIDLIST_ABSOLUTE pidl)
969ccf9ce32SBrock Mammen {
970ccf9ce32SBrock Mammen     m_pidl = ILClone(pidl);
971ccf9ce32SBrock Mammen     if (!m_pidl)
972ccf9ce32SBrock Mammen         return E_OUTOFMEMORY;
973ccf9ce32SBrock Mammen 
974c0799cd2SBrock Mammen     return SHELL32_CoCreateInitSF(m_pidl,
975c0799cd2SBrock Mammen                                   NULL,
976c0799cd2SBrock Mammen                                   NULL,
977c0799cd2SBrock Mammen                                   &CLSID_ShellFSFolder,
978c0799cd2SBrock Mammen                                   IID_PPV_ARG(IShellFolder2, &m_pisfInner));
979ccf9ce32SBrock Mammen }
980ccf9ce32SBrock Mammen 
981ccf9ce32SBrock Mammen // *** IPersist methods ***
GetClassID(CLSID * pClassId)982ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetClassID(CLSID *pClassId)
983ccf9ce32SBrock Mammen {
984ccf9ce32SBrock Mammen     if (pClassId == NULL)
985ccf9ce32SBrock Mammen         return E_INVALIDARG;
9868aa063b4SBrock Mammen     *pClassId = CLSID_FindFolder;
987ccf9ce32SBrock Mammen     return S_OK;
988ccf9ce32SBrock Mammen }
989