xref: /reactos/dll/win32/shell32/brfolder.cpp (revision 325d74c3)
1ed7c23fcSKatayama Hirofumi MZ /*
2ed7c23fcSKatayama Hirofumi MZ  * PROJECT:     ReactOS shell32
3ed7c23fcSKatayama Hirofumi MZ  * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4ed7c23fcSKatayama Hirofumi MZ  * PURPOSE:     SHBrowseForFolderA/W functions
5ed7c23fcSKatayama Hirofumi MZ  * COPYRIGHT:   Copyright 1999 Juergen Schmied
6ed7c23fcSKatayama Hirofumi MZ  *              Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
7ed7c23fcSKatayama Hirofumi MZ  */
8ed7c23fcSKatayama Hirofumi MZ 
9ed7c23fcSKatayama Hirofumi MZ // FIXME: Many flags unimplemented
10ed7c23fcSKatayama Hirofumi MZ 
11ed7c23fcSKatayama Hirofumi MZ #include "precomp.h"
12ed7c23fcSKatayama Hirofumi MZ 
13ed7c23fcSKatayama Hirofumi MZ #include <ui/layout.h> // Resizable window
14ed7c23fcSKatayama Hirofumi MZ 
15ed7c23fcSKatayama Hirofumi MZ WINE_DEFAULT_DEBUG_CHANNEL(shell);
16ed7c23fcSKatayama Hirofumi MZ 
17ed7c23fcSKatayama Hirofumi MZ #define SHV_CHANGE_NOTIFY (WM_USER + 0x1111)
18ed7c23fcSKatayama Hirofumi MZ 
19ed7c23fcSKatayama Hirofumi MZ struct BrFolder
20ed7c23fcSKatayama Hirofumi MZ {
21ed7c23fcSKatayama Hirofumi MZ     LPBROWSEINFOW    lpBrowseInfo;
22ed7c23fcSKatayama Hirofumi MZ     HWND             hWnd;
23ed7c23fcSKatayama Hirofumi MZ     HWND             hwndTreeView;
24ed7c23fcSKatayama Hirofumi MZ     PIDLIST_ABSOLUTE pidlRet;
25ed7c23fcSKatayama Hirofumi MZ     LAYOUT_DATA*     layout;  // Filled by LayoutInit, used by LayoutUpdate
26ed7c23fcSKatayama Hirofumi MZ     SIZE             szMin;
27ed7c23fcSKatayama Hirofumi MZ     ULONG            hChangeNotify; // Change notification handle
283da9e7e2SWhindmar Saksit     IContextMenu*    pContextMenu; // Active context menu
29ed7c23fcSKatayama Hirofumi MZ };
30ed7c23fcSKatayama Hirofumi MZ 
31ed7c23fcSKatayama Hirofumi MZ struct BrItemData
32ed7c23fcSKatayama Hirofumi MZ {
33ed7c23fcSKatayama Hirofumi MZ     CComPtr<IShellFolder>            lpsfParent; // IShellFolder of the parent
34dc0ed6deSWhindmar Saksit     PCIDLIST_RELATIVE                pidlChild;  // PIDL relative to parent
35ed7c23fcSKatayama Hirofumi MZ     CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidlFull;   // Fully qualified PIDL
36ed7c23fcSKatayama Hirofumi MZ };
37ed7c23fcSKatayama Hirofumi MZ 
38ed7c23fcSKatayama Hirofumi MZ static const LAYOUT_INFO g_layout_info[] =
39ed7c23fcSKatayama Hirofumi MZ {
40ed7c23fcSKatayama Hirofumi MZ     { IDC_BROWSE_FOR_FOLDER_TITLE,       BF_TOP | BF_LEFT | BF_RIGHT },
41ed7c23fcSKatayama Hirofumi MZ     { IDC_BROWSE_FOR_FOLDER_STATUS,      BF_TOP | BF_LEFT | BF_RIGHT },
42ed7c23fcSKatayama Hirofumi MZ     { IDC_BROWSE_FOR_FOLDER_TREEVIEW,    BF_TOP | BF_BOTTOM | BF_LEFT | BF_RIGHT },
43ed7c23fcSKatayama Hirofumi MZ     { IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT, BF_TOP | BF_LEFT | BF_RIGHT },
44ed7c23fcSKatayama Hirofumi MZ     { IDC_BROWSE_FOR_FOLDER_NEW_FOLDER,  BF_BOTTOM | BF_LEFT },
45ed7c23fcSKatayama Hirofumi MZ     { IDOK,                              BF_BOTTOM | BF_RIGHT },
46ed7c23fcSKatayama Hirofumi MZ     { IDCANCEL,                          BF_BOTTOM | BF_RIGHT },
47ed7c23fcSKatayama Hirofumi MZ };
48ed7c23fcSKatayama Hirofumi MZ 
49ed7c23fcSKatayama Hirofumi MZ #define SUPPORTED_FLAGS (BIF_STATUSTEXT | BIF_BROWSEFORCOMPUTER | BIF_RETURNFSANCESTORS | \
50ed7c23fcSKatayama Hirofumi MZ                          BIF_RETURNONLYFSDIRS | BIF_NONEWFOLDERBUTTON | BIF_NEWDIALOGSTYLE | \
51ed7c23fcSKatayama Hirofumi MZ                          BIF_BROWSEINCLUDEFILES)
52ed7c23fcSKatayama Hirofumi MZ 
53ed7c23fcSKatayama Hirofumi MZ static HTREEITEM
54ed7c23fcSKatayama Hirofumi MZ BrFolder_InsertItem(
554696996eSKatayama Hirofumi MZ     _Inout_ BrFolder *info,
564696996eSKatayama Hirofumi MZ     _Inout_ IShellFolder *lpsf,
574696996eSKatayama Hirofumi MZ     _In_ PCUITEMID_CHILD pidlChild,
584696996eSKatayama Hirofumi MZ     _In_ PCIDLIST_ABSOLUTE pidlParent,
594696996eSKatayama Hirofumi MZ     _In_ HTREEITEM hParent);
60ed7c23fcSKatayama Hirofumi MZ 
61ed7c23fcSKatayama Hirofumi MZ static inline DWORD
BrowseFlagsToSHCONTF(UINT ulFlags)62ed7c23fcSKatayama Hirofumi MZ BrowseFlagsToSHCONTF(UINT ulFlags)
63ed7c23fcSKatayama Hirofumi MZ {
64ed7c23fcSKatayama Hirofumi MZ     return SHCONTF_FOLDERS | ((ulFlags & BIF_BROWSEINCLUDEFILES) ? SHCONTF_NONFOLDERS : 0);
65ed7c23fcSKatayama Hirofumi MZ }
66ed7c23fcSKatayama Hirofumi MZ 
67ed7c23fcSKatayama Hirofumi MZ static void
BrFolder_Callback(LPBROWSEINFOW lpBrowseInfo,HWND hWnd,UINT uMsg,LPARAM lParam)68ed7c23fcSKatayama Hirofumi MZ BrFolder_Callback(LPBROWSEINFOW lpBrowseInfo, HWND hWnd, UINT uMsg, LPARAM lParam)
69ed7c23fcSKatayama Hirofumi MZ {
70ed7c23fcSKatayama Hirofumi MZ     if (!lpBrowseInfo->lpfn)
71ed7c23fcSKatayama Hirofumi MZ         return;
72ed7c23fcSKatayama Hirofumi MZ     lpBrowseInfo->lpfn(hWnd, uMsg, lParam, lpBrowseInfo->lParam);
73ed7c23fcSKatayama Hirofumi MZ }
74ed7c23fcSKatayama Hirofumi MZ 
75ed7c23fcSKatayama Hirofumi MZ static BrItemData *
BrFolder_GetItemData(BrFolder * info,HTREEITEM hItem)76ed7c23fcSKatayama Hirofumi MZ BrFolder_GetItemData(BrFolder *info, HTREEITEM hItem)
77ed7c23fcSKatayama Hirofumi MZ {
78ed7c23fcSKatayama Hirofumi MZ     TVITEMW item = { TVIF_HANDLE | TVIF_PARAM };
79ed7c23fcSKatayama Hirofumi MZ     item.hItem = hItem;
80ed7c23fcSKatayama Hirofumi MZ     if (!TreeView_GetItem(info->hwndTreeView, &item))
81ed7c23fcSKatayama Hirofumi MZ     {
82ed7c23fcSKatayama Hirofumi MZ         ERR("TreeView_GetItem failed\n");
83ed7c23fcSKatayama Hirofumi MZ         return NULL;
84ed7c23fcSKatayama Hirofumi MZ     }
85ed7c23fcSKatayama Hirofumi MZ     return (BrItemData *)item.lParam;
86ed7c23fcSKatayama Hirofumi MZ }
87ed7c23fcSKatayama Hirofumi MZ 
88dc0ed6deSWhindmar Saksit static SFGAOF
BrFolder_GetItemAttributes(BrFolder * info,HTREEITEM hItem,SFGAOF Att)89dc0ed6deSWhindmar Saksit BrFolder_GetItemAttributes(BrFolder *info, HTREEITEM hItem, SFGAOF Att)
90dc0ed6deSWhindmar Saksit {
91dc0ed6deSWhindmar Saksit     BrItemData *item = BrFolder_GetItemData(info, hItem);
92dc0ed6deSWhindmar Saksit     HRESULT hr = item ? item->lpsfParent->GetAttributesOf(1, &item->pidlChild, &Att) : E_FAIL;
93dc0ed6deSWhindmar Saksit     return SUCCEEDED(hr) ? Att : 0;
94dc0ed6deSWhindmar Saksit }
95dc0ed6deSWhindmar Saksit 
964696996eSKatayama Hirofumi MZ static HRESULT
BrFolder_GetChildrenEnum(_In_ BrFolder * info,_In_ BrItemData * pItemData,_Outptr_opt_ IEnumIDList ** ppEnum)974696996eSKatayama Hirofumi MZ BrFolder_GetChildrenEnum(
984696996eSKatayama Hirofumi MZ     _In_ BrFolder *info,
994696996eSKatayama Hirofumi MZ     _In_ BrItemData *pItemData,
1004696996eSKatayama Hirofumi MZ     _Outptr_opt_ IEnumIDList **ppEnum)
1014696996eSKatayama Hirofumi MZ {
1024696996eSKatayama Hirofumi MZ     if (!pItemData)
1034696996eSKatayama Hirofumi MZ         return E_FAIL;
1044696996eSKatayama Hirofumi MZ 
1054696996eSKatayama Hirofumi MZ     CComPtr<IEnumIDList> pEnumIL;
1064696996eSKatayama Hirofumi MZ     PCUITEMID_CHILD pidlRef = pItemData->pidlChild;
1074696996eSKatayama Hirofumi MZ     ULONG attrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER;
1084696996eSKatayama Hirofumi MZ     IShellFolder *lpsf = pItemData->lpsfParent;
1094696996eSKatayama Hirofumi MZ     HRESULT hr = lpsf->GetAttributesOf(1, &pidlRef, &attrs);
1104696996eSKatayama Hirofumi MZ     if (FAILED_UNEXPECTEDLY(hr) || !(attrs & SFGAO_FOLDER))
1114696996eSKatayama Hirofumi MZ         return E_FAIL;
1124696996eSKatayama Hirofumi MZ 
1134696996eSKatayama Hirofumi MZ     CComPtr<IShellFolder> psfChild;
1144696996eSKatayama Hirofumi MZ     if (_ILIsDesktop(pItemData->pidlFull))
1154696996eSKatayama Hirofumi MZ         hr = SHGetDesktopFolder(&psfChild);
1164696996eSKatayama Hirofumi MZ     else
1174696996eSKatayama Hirofumi MZ         hr = lpsf->BindToObject(pidlRef, NULL, IID_PPV_ARG(IShellFolder, &psfChild));
1184696996eSKatayama Hirofumi MZ     if (FAILED_UNEXPECTEDLY(hr))
1194696996eSKatayama Hirofumi MZ         return E_FAIL;
1204696996eSKatayama Hirofumi MZ 
1214696996eSKatayama Hirofumi MZ     DWORD flags = BrowseFlagsToSHCONTF(info->lpBrowseInfo->ulFlags);
1224696996eSKatayama Hirofumi MZ     hr = psfChild->EnumObjects(info->hWnd, flags, &pEnumIL);
1234696996eSKatayama Hirofumi MZ     if (hr == S_OK)
1244696996eSKatayama Hirofumi MZ     {
1254696996eSKatayama Hirofumi MZ         if ((pEnumIL->Skip(1) != S_OK) || FAILED(pEnumIL->Reset()))
1264696996eSKatayama Hirofumi MZ             pEnumIL = NULL;
1274696996eSKatayama Hirofumi MZ     }
1284696996eSKatayama Hirofumi MZ 
1294696996eSKatayama Hirofumi MZ     if (!pEnumIL || !(attrs & SFGAO_HASSUBFOLDER))
1304696996eSKatayama Hirofumi MZ         return E_FAIL; // No children
1314696996eSKatayama Hirofumi MZ 
1324696996eSKatayama Hirofumi MZ     if (ppEnum)
1334696996eSKatayama Hirofumi MZ         *ppEnum = pEnumIL.Detach();
1344696996eSKatayama Hirofumi MZ 
1354696996eSKatayama Hirofumi MZ     return S_OK; // There are children
1364696996eSKatayama Hirofumi MZ }
1374696996eSKatayama Hirofumi MZ 
138ed7c23fcSKatayama Hirofumi MZ /******************************************************************************
139ed7c23fcSKatayama Hirofumi MZ  * BrFolder_InitTreeView [Internal]
140ed7c23fcSKatayama Hirofumi MZ  *
141ed7c23fcSKatayama Hirofumi MZ  * Called from WM_INITDIALOG handler.
142ed7c23fcSKatayama Hirofumi MZ  */
143ed7c23fcSKatayama Hirofumi MZ static void
BrFolder_InitTreeView(BrFolder * info)144ed7c23fcSKatayama Hirofumi MZ BrFolder_InitTreeView(BrFolder *info)
145ed7c23fcSKatayama Hirofumi MZ {
146ed7c23fcSKatayama Hirofumi MZ     HIMAGELIST hImageList;
147ed7c23fcSKatayama Hirofumi MZ     HRESULT hr;
1484696996eSKatayama Hirofumi MZ     CComPtr<IShellFolder> lpsfParent;
149ed7c23fcSKatayama Hirofumi MZ     CComPtr<IEnumIDList> pEnumChildren;
150ed7c23fcSKatayama Hirofumi MZ     HTREEITEM hItem;
151ed7c23fcSKatayama Hirofumi MZ 
152ed7c23fcSKatayama Hirofumi MZ     Shell_GetImageLists(NULL, &hImageList);
153ed7c23fcSKatayama Hirofumi MZ 
154ed7c23fcSKatayama Hirofumi MZ     if (hImageList)
155ed7c23fcSKatayama Hirofumi MZ         TreeView_SetImageList(info->hwndTreeView, hImageList, 0);
156ed7c23fcSKatayama Hirofumi MZ 
157ed7c23fcSKatayama Hirofumi MZ     /* We want to call BrFolder_InsertItem down the code, in order to insert
158ed7c23fcSKatayama Hirofumi MZ      * the root item of the treeview. Due to BrFolder_InsertItem's signature,
159ed7c23fcSKatayama Hirofumi MZ      * we need the following to do this:
160ed7c23fcSKatayama Hirofumi MZ      *
161ed7c23fcSKatayama Hirofumi MZ      * + An ITEMIDLIST corresponding to _the parent_ of root.
162ed7c23fcSKatayama Hirofumi MZ      * + An ITEMIDLIST, which is a relative path from root's parent to root
163ed7c23fcSKatayama Hirofumi MZ      *   (containing a single SHITEMID).
164ed7c23fcSKatayama Hirofumi MZ      * + An IShellFolder interface pointer of root's parent folder.
165ed7c23fcSKatayama Hirofumi MZ      *
166ed7c23fcSKatayama Hirofumi MZ      * If root is 'Desktop', then root's parent is also 'Desktop'.
167ed7c23fcSKatayama Hirofumi MZ      */
168ed7c23fcSKatayama Hirofumi MZ 
169ed7c23fcSKatayama Hirofumi MZ     PCIDLIST_ABSOLUTE pidlRoot = info->lpBrowseInfo->pidlRoot;
170ed7c23fcSKatayama Hirofumi MZ     CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidlParent(ILClone(pidlRoot));
171ed7c23fcSKatayama Hirofumi MZ     ILRemoveLastID(pidlParent);
172dc0ed6deSWhindmar Saksit     PCIDLIST_RELATIVE pidlChild = ILFindLastID(pidlRoot);
173ed7c23fcSKatayama Hirofumi MZ 
174ed7c23fcSKatayama Hirofumi MZ     if (_ILIsDesktop(pidlParent))
175ed7c23fcSKatayama Hirofumi MZ     {
176ed7c23fcSKatayama Hirofumi MZ         hr = SHGetDesktopFolder(&lpsfParent);
177ed7c23fcSKatayama Hirofumi MZ         if (FAILED_UNEXPECTEDLY(hr))
178ed7c23fcSKatayama Hirofumi MZ             return;
179ed7c23fcSKatayama Hirofumi MZ     }
180ed7c23fcSKatayama Hirofumi MZ     else
181ed7c23fcSKatayama Hirofumi MZ     {
182ed7c23fcSKatayama Hirofumi MZ         CComPtr<IShellFolder> lpsfDesktop;
183ed7c23fcSKatayama Hirofumi MZ         hr = SHGetDesktopFolder(&lpsfDesktop);
184ed7c23fcSKatayama Hirofumi MZ         if (FAILED_UNEXPECTEDLY(hr))
185ed7c23fcSKatayama Hirofumi MZ             return;
186ed7c23fcSKatayama Hirofumi MZ 
187ed7c23fcSKatayama Hirofumi MZ         hr = lpsfDesktop->BindToObject(pidlParent, NULL, IID_PPV_ARG(IShellFolder, &lpsfParent));
188ed7c23fcSKatayama Hirofumi MZ         if (FAILED_UNEXPECTEDLY(hr))
189ed7c23fcSKatayama Hirofumi MZ             return;
190ed7c23fcSKatayama Hirofumi MZ     }
191ed7c23fcSKatayama Hirofumi MZ 
192ed7c23fcSKatayama Hirofumi MZ     TreeView_DeleteItem(info->hwndTreeView, TVI_ROOT);
1934696996eSKatayama Hirofumi MZ     hItem = BrFolder_InsertItem(info, lpsfParent, pidlChild, pidlParent, TVI_ROOT);
194ed7c23fcSKatayama Hirofumi MZ     TreeView_Expand(info->hwndTreeView, hItem, TVE_EXPAND);
195ed7c23fcSKatayama Hirofumi MZ }
196ed7c23fcSKatayama Hirofumi MZ 
197ed7c23fcSKatayama Hirofumi MZ static INT
BrFolder_GetIcon(PCIDLIST_ABSOLUTE pidl,UINT uFlags)198ed7c23fcSKatayama Hirofumi MZ BrFolder_GetIcon(PCIDLIST_ABSOLUTE pidl, UINT uFlags)
199ed7c23fcSKatayama Hirofumi MZ {
200ed7c23fcSKatayama Hirofumi MZ     SHFILEINFOW sfi;
201ed7c23fcSKatayama Hirofumi MZ     SHGetFileInfoW((LPCWSTR)pidl, 0, &sfi, sizeof(sfi), uFlags);
202ed7c23fcSKatayama Hirofumi MZ     return sfi.iIcon;
203ed7c23fcSKatayama Hirofumi MZ }
204ed7c23fcSKatayama Hirofumi MZ 
205ed7c23fcSKatayama Hirofumi MZ static void
BrFolder_GetIconPair(PCIDLIST_ABSOLUTE pidl,LPTVITEMW pItem)206ed7c23fcSKatayama Hirofumi MZ BrFolder_GetIconPair(PCIDLIST_ABSOLUTE pidl, LPTVITEMW pItem)
207ed7c23fcSKatayama Hirofumi MZ {
208ed7c23fcSKatayama Hirofumi MZ     DWORD flags;
209ed7c23fcSKatayama Hirofumi MZ 
210ed7c23fcSKatayama Hirofumi MZ     CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidlDesktop;
211ed7c23fcSKatayama Hirofumi MZ     if (!pidl)
212ed7c23fcSKatayama Hirofumi MZ     {
213ed7c23fcSKatayama Hirofumi MZ         pidlDesktop.Attach(_ILCreateDesktop());
214ed7c23fcSKatayama Hirofumi MZ         pidl = pidlDesktop;
215ed7c23fcSKatayama Hirofumi MZ     }
216ed7c23fcSKatayama Hirofumi MZ 
217ed7c23fcSKatayama Hirofumi MZ     flags = SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON;
218ed7c23fcSKatayama Hirofumi MZ     pItem->iImage = BrFolder_GetIcon(pidl, flags);
219ed7c23fcSKatayama Hirofumi MZ 
220ed7c23fcSKatayama Hirofumi MZ     flags = SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON;
221ed7c23fcSKatayama Hirofumi MZ     pItem->iSelectedImage = BrFolder_GetIcon(pidl, flags);
222ed7c23fcSKatayama Hirofumi MZ }
223ed7c23fcSKatayama Hirofumi MZ 
224ed7c23fcSKatayama Hirofumi MZ /******************************************************************************
225ed7c23fcSKatayama Hirofumi MZ  * BrFolder_GetName [Internal]
226ed7c23fcSKatayama Hirofumi MZ  *
227ed7c23fcSKatayama Hirofumi MZ  * Query a shell folder for the display name of one of its children
228ed7c23fcSKatayama Hirofumi MZ  *
229ed7c23fcSKatayama Hirofumi MZ  * PARAMS
230ed7c23fcSKatayama Hirofumi MZ  *  lpsf           [I] IShellFolder interface of the folder to be queried.
231ed7c23fcSKatayama Hirofumi MZ  *  pidlChild      [I] ITEMIDLIST of the child, relative to parent
232ed7c23fcSKatayama Hirofumi MZ  *  dwFlags        [I] as in IShellFolder::GetDisplayNameOf
233ed7c23fcSKatayama Hirofumi MZ  *  lpFriendlyName [O] The desired display name in unicode
234ed7c23fcSKatayama Hirofumi MZ  *
235ed7c23fcSKatayama Hirofumi MZ  * RETURNS
236ed7c23fcSKatayama Hirofumi MZ  *  Success: TRUE
237ed7c23fcSKatayama Hirofumi MZ  *  Failure: FALSE
238ed7c23fcSKatayama Hirofumi MZ  */
239ed7c23fcSKatayama Hirofumi MZ static BOOL
BrFolder_GetName(IShellFolder * lpsf,PCIDLIST_RELATIVE pidlChild,DWORD dwFlags,LPWSTR lpFriendlyName)240ed7c23fcSKatayama Hirofumi MZ BrFolder_GetName(
241ed7c23fcSKatayama Hirofumi MZ     IShellFolder *lpsf,
242ed7c23fcSKatayama Hirofumi MZ     PCIDLIST_RELATIVE pidlChild,
243ed7c23fcSKatayama Hirofumi MZ     DWORD dwFlags,
244ed7c23fcSKatayama Hirofumi MZ     LPWSTR lpFriendlyName)
245ed7c23fcSKatayama Hirofumi MZ {
246ed7c23fcSKatayama Hirofumi MZ     BOOL   bSuccess = FALSE;
247ed7c23fcSKatayama Hirofumi MZ     STRRET str;
248ed7c23fcSKatayama Hirofumi MZ 
249ed7c23fcSKatayama Hirofumi MZ     TRACE("%p %p %x %p\n", lpsf, pidlChild, dwFlags, lpFriendlyName);
250ed7c23fcSKatayama Hirofumi MZ     if (!FAILED_UNEXPECTEDLY(lpsf->GetDisplayNameOf(pidlChild, dwFlags, &str)))
251ed7c23fcSKatayama Hirofumi MZ         bSuccess = StrRetToStrNW(lpFriendlyName, MAX_PATH, &str, pidlChild);
252ed7c23fcSKatayama Hirofumi MZ 
253ed7c23fcSKatayama Hirofumi MZ     TRACE("-- %s\n", debugstr_w(lpFriendlyName));
254ed7c23fcSKatayama Hirofumi MZ     return bSuccess;
255ed7c23fcSKatayama Hirofumi MZ }
256ed7c23fcSKatayama Hirofumi MZ 
257b50ab0dcSKatayama Hirofumi MZ static BOOL
BrFolder_IsTreeItemInEnum(_Inout_ BrFolder * info,_In_ HTREEITEM hItem,_Inout_ IEnumIDList * pEnum)258b50ab0dcSKatayama Hirofumi MZ BrFolder_IsTreeItemInEnum(
259b50ab0dcSKatayama Hirofumi MZ     _Inout_ BrFolder *info,
260b50ab0dcSKatayama Hirofumi MZ     _In_ HTREEITEM hItem,
261b50ab0dcSKatayama Hirofumi MZ     _Inout_ IEnumIDList *pEnum)
262b50ab0dcSKatayama Hirofumi MZ {
263b50ab0dcSKatayama Hirofumi MZ     BrItemData *pItemData = BrFolder_GetItemData(info, hItem);
264b50ab0dcSKatayama Hirofumi MZ     if (!pItemData)
265b50ab0dcSKatayama Hirofumi MZ         return FALSE;
266b50ab0dcSKatayama Hirofumi MZ 
267b50ab0dcSKatayama Hirofumi MZ     pEnum->Reset();
268b50ab0dcSKatayama Hirofumi MZ 
269b50ab0dcSKatayama Hirofumi MZ     CComHeapPtr<ITEMIDLIST_RELATIVE> pidlTemp;
270b50ab0dcSKatayama Hirofumi MZ     while (pEnum->Next(1, &pidlTemp, NULL) == S_OK)
271b50ab0dcSKatayama Hirofumi MZ     {
272b50ab0dcSKatayama Hirofumi MZ         if (ILIsEqual(pidlTemp, pItemData->pidlChild))
273b50ab0dcSKatayama Hirofumi MZ             return TRUE;
274b50ab0dcSKatayama Hirofumi MZ 
275b50ab0dcSKatayama Hirofumi MZ         pidlTemp.Free();
276b50ab0dcSKatayama Hirofumi MZ     }
277b50ab0dcSKatayama Hirofumi MZ 
278b50ab0dcSKatayama Hirofumi MZ     return FALSE;
279b50ab0dcSKatayama Hirofumi MZ }
280b50ab0dcSKatayama Hirofumi MZ 
281b50ab0dcSKatayama Hirofumi MZ static BOOL
BrFolder_TreeItemHasThisChild(_In_ BrFolder * info,_In_ HTREEITEM hItem,_Outptr_opt_ PITEMID_CHILD pidlChild)282b50ab0dcSKatayama Hirofumi MZ BrFolder_TreeItemHasThisChild(
283b50ab0dcSKatayama Hirofumi MZ     _In_ BrFolder *info,
284b50ab0dcSKatayama Hirofumi MZ     _In_ HTREEITEM hItem,
285b50ab0dcSKatayama Hirofumi MZ     _Outptr_opt_ PITEMID_CHILD pidlChild)
286b50ab0dcSKatayama Hirofumi MZ {
287b50ab0dcSKatayama Hirofumi MZ     for (hItem = TreeView_GetChild(info->hwndTreeView, hItem); hItem;
288b50ab0dcSKatayama Hirofumi MZ          hItem = TreeView_GetNextSibling(info->hwndTreeView, hItem))
289b50ab0dcSKatayama Hirofumi MZ     {
290b50ab0dcSKatayama Hirofumi MZ         BrItemData *pItemData = BrFolder_GetItemData(info, hItem);
291b50ab0dcSKatayama Hirofumi MZ         if (ILIsEqual(pItemData->pidlChild, pidlChild))
292b50ab0dcSKatayama Hirofumi MZ             return TRUE;
293b50ab0dcSKatayama Hirofumi MZ     }
294b50ab0dcSKatayama Hirofumi MZ 
295b50ab0dcSKatayama Hirofumi MZ     return FALSE;
296b50ab0dcSKatayama Hirofumi MZ }
297b50ab0dcSKatayama Hirofumi MZ 
298b50ab0dcSKatayama Hirofumi MZ static void
BrFolder_UpdateItem(_In_ BrFolder * info,_In_ HTREEITEM hItem)299b50ab0dcSKatayama Hirofumi MZ BrFolder_UpdateItem(
300b50ab0dcSKatayama Hirofumi MZ     _In_ BrFolder *info,
301b50ab0dcSKatayama Hirofumi MZ     _In_ HTREEITEM hItem)
302b50ab0dcSKatayama Hirofumi MZ {
303b50ab0dcSKatayama Hirofumi MZ     BrItemData *pItemData = BrFolder_GetItemData(info, hItem);
304b50ab0dcSKatayama Hirofumi MZ     if (!pItemData)
305b50ab0dcSKatayama Hirofumi MZ         return;
306b50ab0dcSKatayama Hirofumi MZ 
307b50ab0dcSKatayama Hirofumi MZ     TVITEMW item = { TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN };
308b50ab0dcSKatayama Hirofumi MZ     item.hItem = hItem;
309b50ab0dcSKatayama Hirofumi MZ 
310b50ab0dcSKatayama Hirofumi MZ     BrFolder_GetIconPair(pItemData->pidlFull, &item);
311b50ab0dcSKatayama Hirofumi MZ 
312b50ab0dcSKatayama Hirofumi MZ     item.cChildren = 0;
313b50ab0dcSKatayama Hirofumi MZ     CComPtr<IEnumIDList> pEnum;
314b50ab0dcSKatayama Hirofumi MZ     if (BrFolder_GetChildrenEnum(info, pItemData, &pEnum) == S_OK)
315b50ab0dcSKatayama Hirofumi MZ     {
316b50ab0dcSKatayama Hirofumi MZ         CComHeapPtr<ITEMIDLIST_RELATIVE> pidlTemp;
317b50ab0dcSKatayama Hirofumi MZ         if (pEnum->Next(1, &pidlTemp, NULL) == S_OK)
318b50ab0dcSKatayama Hirofumi MZ             ++item.cChildren;
319b50ab0dcSKatayama Hirofumi MZ     }
320b50ab0dcSKatayama Hirofumi MZ 
321b50ab0dcSKatayama Hirofumi MZ     TreeView_SetItem(info->hwndTreeView, &item);
322b50ab0dcSKatayama Hirofumi MZ }
323b50ab0dcSKatayama Hirofumi MZ 
324ed7c23fcSKatayama Hirofumi MZ /******************************************************************************
325ed7c23fcSKatayama Hirofumi MZ  * BrFolder_InsertItem [Internal]
326ed7c23fcSKatayama Hirofumi MZ  *
327ed7c23fcSKatayama Hirofumi MZ  * PARAMS
328ed7c23fcSKatayama Hirofumi MZ  *  info       [I] data for the dialog
329ed7c23fcSKatayama Hirofumi MZ  *  lpsf       [I] IShellFolder interface of the item's parent shell folder
330ed7c23fcSKatayama Hirofumi MZ  *  pidlChild  [I] ITEMIDLIST of the child to insert, relative to parent
331ed7c23fcSKatayama Hirofumi MZ  *  pidlParent [I] ITEMIDLIST of the parent shell folder
332ed7c23fcSKatayama Hirofumi MZ  *  hParent    [I] The treeview-item that represents the parent shell folder
333ed7c23fcSKatayama Hirofumi MZ  *
334ed7c23fcSKatayama Hirofumi MZ  * RETURNS
335ed7c23fcSKatayama Hirofumi MZ  *  Success: Handle to the created and inserted treeview-item
336ed7c23fcSKatayama Hirofumi MZ  *  Failure: NULL
337ed7c23fcSKatayama Hirofumi MZ  */
338ed7c23fcSKatayama Hirofumi MZ static HTREEITEM
BrFolder_InsertItem(_Inout_ BrFolder * info,_Inout_ IShellFolder * lpsf,_In_ PCUITEMID_CHILD pidlChild,_In_ PCIDLIST_ABSOLUTE pidlParent,_In_ HTREEITEM hParent)339ed7c23fcSKatayama Hirofumi MZ BrFolder_InsertItem(
3404696996eSKatayama Hirofumi MZ     _Inout_ BrFolder *info,
3414696996eSKatayama Hirofumi MZ     _Inout_ IShellFolder *lpsf,
3424696996eSKatayama Hirofumi MZ     _In_ PCUITEMID_CHILD pidlChild,
3434696996eSKatayama Hirofumi MZ     _In_ PCIDLIST_ABSOLUTE pidlParent,
3444696996eSKatayama Hirofumi MZ     _In_ HTREEITEM hParent)
345ed7c23fcSKatayama Hirofumi MZ {
346*325d74c3SWhindmar Saksit     if (!(BrowseFlagsToSHCONTF(info->lpBrowseInfo->ulFlags) & SHCONTF_NONFOLDERS))
347*325d74c3SWhindmar Saksit     {
348*325d74c3SWhindmar Saksit #ifdef BIF_BROWSEFILEJUNCTIONS
349*325d74c3SWhindmar Saksit         if (!(info->lpBrowseInfo->ulFlags & BIF_BROWSEFILEJUNCTIONS))
350*325d74c3SWhindmar Saksit #endif
351*325d74c3SWhindmar Saksit             if (SHGetAttributes(lpsf, pidlChild, SFGAO_STREAM) & SFGAO_STREAM)
352*325d74c3SWhindmar Saksit                 return NULL; // .zip files have both FOLDER and STREAM attributes set
353*325d74c3SWhindmar Saksit     }
354*325d74c3SWhindmar Saksit 
355ed7c23fcSKatayama Hirofumi MZ     WCHAR szName[MAX_PATH];
356ed7c23fcSKatayama Hirofumi MZ     if (!BrFolder_GetName(lpsf, pidlChild, SHGDN_NORMAL, szName))
357ed7c23fcSKatayama Hirofumi MZ         return NULL;
358ed7c23fcSKatayama Hirofumi MZ 
359ed7c23fcSKatayama Hirofumi MZ     BrItemData *pItemData = new BrItemData();
360ed7c23fcSKatayama Hirofumi MZ 
361ed7c23fcSKatayama Hirofumi MZ     TVITEMW item = { TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_CHILDREN };
362ed7c23fcSKatayama Hirofumi MZ     item.pszText    = szName;
363ed7c23fcSKatayama Hirofumi MZ     item.cchTextMax = _countof(szName);
364ed7c23fcSKatayama Hirofumi MZ     item.lParam     = (LPARAM)pItemData;
365ed7c23fcSKatayama Hirofumi MZ 
366ed7c23fcSKatayama Hirofumi MZ     PIDLIST_ABSOLUTE pidlFull =
367ed7c23fcSKatayama Hirofumi MZ         (pidlParent ? ILCombine(pidlParent, pidlChild) : ILClone(pidlChild));
368ed7c23fcSKatayama Hirofumi MZ     BrFolder_GetIconPair(pidlFull, &item);
369ed7c23fcSKatayama Hirofumi MZ 
3708df5aac9SKatayama Hirofumi MZ     pItemData->lpsfParent = lpsf;
371ed7c23fcSKatayama Hirofumi MZ     pItemData->pidlFull.Attach(pidlFull);
372dc0ed6deSWhindmar Saksit     pItemData->pidlChild = ILFindLastID(pItemData->pidlFull);
3734696996eSKatayama Hirofumi MZ 
3744696996eSKatayama Hirofumi MZ     if (BrFolder_GetChildrenEnum(info, pItemData, NULL) == S_OK)
3754696996eSKatayama Hirofumi MZ         item.cChildren = 1;
376ed7c23fcSKatayama Hirofumi MZ 
377ed7c23fcSKatayama Hirofumi MZ     TVINSERTSTRUCTW tvins = { hParent };
378ed7c23fcSKatayama Hirofumi MZ     tvins.item = item;
379ed7c23fcSKatayama Hirofumi MZ     return TreeView_InsertItem(info->hwndTreeView, &tvins);
380ed7c23fcSKatayama Hirofumi MZ }
381ed7c23fcSKatayama Hirofumi MZ 
382ed7c23fcSKatayama Hirofumi MZ /******************************************************************************
383ed7c23fcSKatayama Hirofumi MZ  * BrFolder_Expand [Internal]
384ed7c23fcSKatayama Hirofumi MZ  *
385ed7c23fcSKatayama Hirofumi MZ  * For each child (given by pEnum) of the parent shell folder, which is given by
386ed7c23fcSKatayama Hirofumi MZ  * lpsf and whose PIDL is pidl, insert a treeview-item right under hParent
387ed7c23fcSKatayama Hirofumi MZ  *
388ed7c23fcSKatayama Hirofumi MZ  * PARAMS
389ed7c23fcSKatayama Hirofumi MZ  *  info    [I] data for the dialog
390ed7c23fcSKatayama Hirofumi MZ  *  lpsf    [I] IShellFolder interface of the parent shell folder
391ed7c23fcSKatayama Hirofumi MZ  *  pidl    [I] ITEMIDLIST of the parent shell folder
392ed7c23fcSKatayama Hirofumi MZ  *  hParent [I] The treeview item that represents the parent shell folder
393ed7c23fcSKatayama Hirofumi MZ  *  pEnum   [I] An iterator for the children of the parent shell folder
394ed7c23fcSKatayama Hirofumi MZ  */
395ed7c23fcSKatayama Hirofumi MZ static void
BrFolder_Expand(_In_ BrFolder * info,_In_ IShellFolder * lpsf,_In_ PCIDLIST_ABSOLUTE pidlFull,_In_ HTREEITEM hParent)396ed7c23fcSKatayama Hirofumi MZ BrFolder_Expand(
3974696996eSKatayama Hirofumi MZ     _In_ BrFolder *info,
3984696996eSKatayama Hirofumi MZ     _In_ IShellFolder *lpsf,
3994696996eSKatayama Hirofumi MZ     _In_ PCIDLIST_ABSOLUTE pidlFull,
4004696996eSKatayama Hirofumi MZ     _In_ HTREEITEM hParent)
401ed7c23fcSKatayama Hirofumi MZ {
4024696996eSKatayama Hirofumi MZ     TRACE("%p %p %p\n", lpsf, pidlFull, hParent);
403ed7c23fcSKatayama Hirofumi MZ 
404ed7c23fcSKatayama Hirofumi MZ     // No IEnumIDList -> No children
4054696996eSKatayama Hirofumi MZ     BrItemData *pItemData = BrFolder_GetItemData(info, hParent);
4064696996eSKatayama Hirofumi MZ     CComPtr<IEnumIDList> pEnum;
4074696996eSKatayama Hirofumi MZ     HRESULT hr = BrFolder_GetChildrenEnum(info, pItemData, &pEnum);
4084696996eSKatayama Hirofumi MZ     if (FAILED(hr))
409ed7c23fcSKatayama Hirofumi MZ         return;
410ed7c23fcSKatayama Hirofumi MZ 
4114696996eSKatayama Hirofumi MZ     SetCapture(info->hWnd);
412ed7c23fcSKatayama Hirofumi MZ     SetCursor(LoadCursorW(NULL, (LPWSTR)IDC_WAIT));
413ed7c23fcSKatayama Hirofumi MZ 
414b50ab0dcSKatayama Hirofumi MZ     CComHeapPtr<ITEMIDLIST_RELATIVE> pidlTemp;
4154696996eSKatayama Hirofumi MZ     ULONG ulFetched;
416ed7c23fcSKatayama Hirofumi MZ     while (S_OK == pEnum->Next(1, &pidlTemp, &ulFetched))
417ed7c23fcSKatayama Hirofumi MZ     {
4184696996eSKatayama Hirofumi MZ         if (!BrFolder_InsertItem(info, lpsf, pidlTemp, pidlFull, hParent))
4194696996eSKatayama Hirofumi MZ             break;
420ed7c23fcSKatayama Hirofumi MZ         pidlTemp.Free(); // Finally, free the pidl that the shell gave us...
421ed7c23fcSKatayama Hirofumi MZ     }
422ed7c23fcSKatayama Hirofumi MZ 
423ed7c23fcSKatayama Hirofumi MZ     ReleaseCapture();
424ed7c23fcSKatayama Hirofumi MZ     SetCursor(LoadCursorW(NULL, (LPWSTR)IDC_ARROW));
425ed7c23fcSKatayama Hirofumi MZ }
426ed7c23fcSKatayama Hirofumi MZ 
427ed7c23fcSKatayama Hirofumi MZ static inline BOOL
PIDLIsType(LPCITEMIDLIST pidl,PIDLTYPE type)428ed7c23fcSKatayama Hirofumi MZ PIDLIsType(LPCITEMIDLIST pidl, PIDLTYPE type)
429ed7c23fcSKatayama Hirofumi MZ {
430ed7c23fcSKatayama Hirofumi MZ     LPPIDLDATA data = _ILGetDataPointer(pidl);
431ed7c23fcSKatayama Hirofumi MZ     if (!data)
432ed7c23fcSKatayama Hirofumi MZ         return FALSE;
433ed7c23fcSKatayama Hirofumi MZ     return (data->type == type);
434ed7c23fcSKatayama Hirofumi MZ }
435ed7c23fcSKatayama Hirofumi MZ 
436ed7c23fcSKatayama Hirofumi MZ static void
BrFolder_CheckValidSelection(BrFolder * info,BrItemData * pItemData)437ed7c23fcSKatayama Hirofumi MZ BrFolder_CheckValidSelection(BrFolder *info, BrItemData *pItemData)
438ed7c23fcSKatayama Hirofumi MZ {
439ed7c23fcSKatayama Hirofumi MZ     LPBROWSEINFOW lpBrowseInfo = info->lpBrowseInfo;
440ed7c23fcSKatayama Hirofumi MZ     PCIDLIST_RELATIVE pidlChild = pItemData->pidlChild;
441ed7c23fcSKatayama Hirofumi MZ     DWORD dwAttributes;
442ed7c23fcSKatayama Hirofumi MZ     HRESULT hr;
443ed7c23fcSKatayama Hirofumi MZ 
444ed7c23fcSKatayama Hirofumi MZ     BOOL bEnabled = TRUE;
445ed7c23fcSKatayama Hirofumi MZ     if ((lpBrowseInfo->ulFlags & BIF_BROWSEFORCOMPUTER) && !PIDLIsType(pidlChild, PT_COMP))
446ed7c23fcSKatayama Hirofumi MZ         bEnabled = FALSE;
447ed7c23fcSKatayama Hirofumi MZ 
448ed7c23fcSKatayama Hirofumi MZ     if (lpBrowseInfo->ulFlags & BIF_RETURNFSANCESTORS)
449ed7c23fcSKatayama Hirofumi MZ     {
450ed7c23fcSKatayama Hirofumi MZ         dwAttributes = SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM;
4518df5aac9SKatayama Hirofumi MZ         hr = pItemData->lpsfParent->GetAttributesOf(1, &pidlChild, &dwAttributes);
452ed7c23fcSKatayama Hirofumi MZ         if (FAILED(hr) || !(dwAttributes & (SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM)))
453ed7c23fcSKatayama Hirofumi MZ             bEnabled = FALSE;
454ed7c23fcSKatayama Hirofumi MZ     }
455ed7c23fcSKatayama Hirofumi MZ 
456ed7c23fcSKatayama Hirofumi MZ     dwAttributes = SFGAO_FOLDER | SFGAO_FILESYSTEM;
4578df5aac9SKatayama Hirofumi MZ     hr = pItemData->lpsfParent->GetAttributesOf(1, &pidlChild, &dwAttributes);
458ed7c23fcSKatayama Hirofumi MZ     if (FAILED_UNEXPECTEDLY(hr) ||
459ed7c23fcSKatayama Hirofumi MZ         ((dwAttributes & (SFGAO_FOLDER | SFGAO_FILESYSTEM)) != (SFGAO_FOLDER | SFGAO_FILESYSTEM)))
460ed7c23fcSKatayama Hirofumi MZ     {
461ed7c23fcSKatayama Hirofumi MZ         if (lpBrowseInfo->ulFlags & BIF_RETURNONLYFSDIRS)
462ed7c23fcSKatayama Hirofumi MZ             bEnabled = FALSE;
463ed7c23fcSKatayama Hirofumi MZ         EnableWindow(GetDlgItem(info->hWnd, IDC_BROWSE_FOR_FOLDER_NEW_FOLDER), FALSE);
464ed7c23fcSKatayama Hirofumi MZ     }
465ed7c23fcSKatayama Hirofumi MZ     else
466ed7c23fcSKatayama Hirofumi MZ     {
467ed7c23fcSKatayama Hirofumi MZ         EnableWindow(GetDlgItem(info->hWnd, IDC_BROWSE_FOR_FOLDER_NEW_FOLDER), TRUE);
468ed7c23fcSKatayama Hirofumi MZ     }
469ed7c23fcSKatayama Hirofumi MZ 
470ed7c23fcSKatayama Hirofumi MZ     SendMessageW(info->hWnd, BFFM_ENABLEOK, 0, bEnabled);
471ed7c23fcSKatayama Hirofumi MZ }
472ed7c23fcSKatayama Hirofumi MZ 
473ed7c23fcSKatayama Hirofumi MZ static LRESULT
BrFolder_Treeview_Delete(BrFolder * info,NMTREEVIEWW * pnmtv)474ed7c23fcSKatayama Hirofumi MZ BrFolder_Treeview_Delete(BrFolder *info, NMTREEVIEWW *pnmtv)
475ed7c23fcSKatayama Hirofumi MZ {
476ed7c23fcSKatayama Hirofumi MZ     BrItemData *pItemData = (BrItemData *)pnmtv->itemOld.lParam;
477ed7c23fcSKatayama Hirofumi MZ 
478ed7c23fcSKatayama Hirofumi MZ     TRACE("TVN_DELETEITEMA/W %p\n", pItemData);
479ed7c23fcSKatayama Hirofumi MZ 
480ed7c23fcSKatayama Hirofumi MZ     delete pItemData;
481ed7c23fcSKatayama Hirofumi MZ     return 0;
482ed7c23fcSKatayama Hirofumi MZ }
483ed7c23fcSKatayama Hirofumi MZ 
484ed7c23fcSKatayama Hirofumi MZ static LRESULT
BrFolder_Treeview_Expand(BrFolder * info,NMTREEVIEWW * pnmtv)485ed7c23fcSKatayama Hirofumi MZ BrFolder_Treeview_Expand(BrFolder *info, NMTREEVIEWW *pnmtv)
486ed7c23fcSKatayama Hirofumi MZ {
487ed7c23fcSKatayama Hirofumi MZ     BrItemData *pItemData = (BrItemData *)pnmtv->itemNew.lParam;
488ed7c23fcSKatayama Hirofumi MZ 
489ed7c23fcSKatayama Hirofumi MZ     TRACE("TVN_ITEMEXPANDINGA/W\n");
490ed7c23fcSKatayama Hirofumi MZ 
491ed7c23fcSKatayama Hirofumi MZ     if ((pnmtv->itemNew.state & TVIS_EXPANDEDONCE))
492ed7c23fcSKatayama Hirofumi MZ         return 0;
493ed7c23fcSKatayama Hirofumi MZ 
494ed7c23fcSKatayama Hirofumi MZ     HRESULT hr = S_OK;
495ed7c23fcSKatayama Hirofumi MZ     CComPtr<IShellFolder> lpsf2;
496ed7c23fcSKatayama Hirofumi MZ     if (!_ILIsEmpty(pItemData->pidlChild))
497ed7c23fcSKatayama Hirofumi MZ     {
498ed7c23fcSKatayama Hirofumi MZ         hr = pItemData->lpsfParent->BindToObject(pItemData->pidlChild, NULL,
499ed7c23fcSKatayama Hirofumi MZ                                                  IID_PPV_ARG(IShellFolder, &lpsf2));
500ed7c23fcSKatayama Hirofumi MZ     }
501ed7c23fcSKatayama Hirofumi MZ     else
502ed7c23fcSKatayama Hirofumi MZ     {
5038df5aac9SKatayama Hirofumi MZ         lpsf2 = pItemData->lpsfParent;
504ed7c23fcSKatayama Hirofumi MZ     }
505ed7c23fcSKatayama Hirofumi MZ 
506ed7c23fcSKatayama Hirofumi MZ     HTREEITEM hItem = pnmtv->itemNew.hItem;
507ed7c23fcSKatayama Hirofumi MZ     if (!FAILED_UNEXPECTEDLY(hr))
5084696996eSKatayama Hirofumi MZ         BrFolder_Expand(info, lpsf2, pItemData->pidlFull, hItem);
509ed7c23fcSKatayama Hirofumi MZ 
510ed7c23fcSKatayama Hirofumi MZ     // My Computer is already sorted and trying to do a simple text
511ed7c23fcSKatayama Hirofumi MZ     // sort will only mess things up
512ed7c23fcSKatayama Hirofumi MZ     if (!_ILIsMyComputer(pItemData->pidlChild))
513ed7c23fcSKatayama Hirofumi MZ         TreeView_SortChildren(info->hwndTreeView, hItem, FALSE);
514ed7c23fcSKatayama Hirofumi MZ 
515ed7c23fcSKatayama Hirofumi MZ     return 0;
516ed7c23fcSKatayama Hirofumi MZ }
517ed7c23fcSKatayama Hirofumi MZ 
518ed7c23fcSKatayama Hirofumi MZ static HRESULT
BrFolder_Treeview_Changed(BrFolder * info,NMTREEVIEWW * pnmtv)519ed7c23fcSKatayama Hirofumi MZ BrFolder_Treeview_Changed(BrFolder *info, NMTREEVIEWW *pnmtv)
520ed7c23fcSKatayama Hirofumi MZ {
521ed7c23fcSKatayama Hirofumi MZ     BrItemData *pItemData = (BrItemData *)pnmtv->itemNew.lParam;
522ed7c23fcSKatayama Hirofumi MZ 
523ed7c23fcSKatayama Hirofumi MZ     ILFree(info->pidlRet);
524ed7c23fcSKatayama Hirofumi MZ     info->pidlRet = ILClone(pItemData->pidlFull);
525ed7c23fcSKatayama Hirofumi MZ 
526ed7c23fcSKatayama Hirofumi MZ     WCHAR szName[MAX_PATH];
527ed7c23fcSKatayama Hirofumi MZ     if (BrFolder_GetName(pItemData->lpsfParent, pItemData->pidlChild, SHGDN_NORMAL, szName))
528ed7c23fcSKatayama Hirofumi MZ         SetDlgItemTextW(info->hWnd, IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT, szName);
529ed7c23fcSKatayama Hirofumi MZ 
530ed7c23fcSKatayama Hirofumi MZ     BrFolder_Callback(info->lpBrowseInfo, info->hWnd, BFFM_SELCHANGED, (LPARAM)info->pidlRet);
531ed7c23fcSKatayama Hirofumi MZ     BrFolder_CheckValidSelection(info, pItemData);
532ed7c23fcSKatayama Hirofumi MZ     return S_OK;
533ed7c23fcSKatayama Hirofumi MZ }
534ed7c23fcSKatayama Hirofumi MZ 
535ed7c23fcSKatayama Hirofumi MZ static LRESULT
BrFolder_Treeview_Rename(BrFolder * info,NMTVDISPINFOW * pnmtv)536ed7c23fcSKatayama Hirofumi MZ BrFolder_Treeview_Rename(BrFolder *info, NMTVDISPINFOW *pnmtv)
537ed7c23fcSKatayama Hirofumi MZ {
538ed7c23fcSKatayama Hirofumi MZ     if (!pnmtv->item.pszText)
539dc0ed6deSWhindmar Saksit         return FALSE;
540ed7c23fcSKatayama Hirofumi MZ 
541dc0ed6deSWhindmar Saksit     HTREEITEM hItem = TreeView_GetSelection(info->hwndTreeView);
542dc0ed6deSWhindmar Saksit     BrItemData *data = BrFolder_GetItemData(info, hItem);
543dc0ed6deSWhindmar Saksit     ASSERT(data);
544dc0ed6deSWhindmar Saksit     ASSERT(BrFolder_GetItemAttributes(info, hItem, SFGAO_CANRENAME) & SFGAO_CANRENAME);
545ed7c23fcSKatayama Hirofumi MZ 
546dc0ed6deSWhindmar Saksit     PITEMID_CHILD newChild;
547dc0ed6deSWhindmar Saksit     HRESULT hr = data->lpsfParent->SetNameOf(info->hWnd, data->pidlChild,
548dc0ed6deSWhindmar Saksit                                              pnmtv->item.pszText, SHGDN_NORMAL, &newChild);
549dc0ed6deSWhindmar Saksit     if (FAILED(hr))
550dc0ed6deSWhindmar Saksit         return FALSE;
551ed7c23fcSKatayama Hirofumi MZ 
552dc0ed6deSWhindmar Saksit     LPITEMIDLIST newFull;
553b50ab0dcSKatayama Hirofumi MZ     if (SUCCEEDED(hr = SHILClone(data->pidlFull, &newFull)))
554dc0ed6deSWhindmar Saksit     {
555dc0ed6deSWhindmar Saksit         ILRemoveLastID(newFull);
556dc0ed6deSWhindmar Saksit         if (SUCCEEDED(hr = SHILAppend(newChild, &newFull)))
557dc0ed6deSWhindmar Saksit         {
558dc0ed6deSWhindmar Saksit             data->pidlFull.Free();
559dc0ed6deSWhindmar Saksit             data->pidlFull.Attach(newFull);
560dc0ed6deSWhindmar Saksit             data->pidlChild = ILFindLastID(data->pidlFull);
561dc0ed6deSWhindmar Saksit         }
562dc0ed6deSWhindmar Saksit         newChild = NULL; // SHILAppend is nuts and frees this
563dc0ed6deSWhindmar Saksit     }
564dc0ed6deSWhindmar Saksit     ILFree(newChild);
565ed7c23fcSKatayama Hirofumi MZ 
566dc0ed6deSWhindmar Saksit     NMTREEVIEWW nmtv;
567dc0ed6deSWhindmar Saksit     nmtv.itemNew.lParam = (LPARAM)data;
568ed7c23fcSKatayama Hirofumi MZ     BrFolder_Treeview_Changed(info, &nmtv);
569dc0ed6deSWhindmar Saksit     return TRUE;
570ed7c23fcSKatayama Hirofumi MZ }
571ed7c23fcSKatayama Hirofumi MZ 
572ed7c23fcSKatayama Hirofumi MZ static HRESULT
BrFolder_Rename(BrFolder * info,HTREEITEM hItem)573ed7c23fcSKatayama Hirofumi MZ BrFolder_Rename(BrFolder *info, HTREEITEM hItem)
574ed7c23fcSKatayama Hirofumi MZ {
575ed7c23fcSKatayama Hirofumi MZ     TreeView_SelectItem(info->hwndTreeView, hItem);
576ed7c23fcSKatayama Hirofumi MZ     TreeView_EditLabel(info->hwndTreeView, hItem);
577ed7c23fcSKatayama Hirofumi MZ     return S_OK;
578ed7c23fcSKatayama Hirofumi MZ }
579ed7c23fcSKatayama Hirofumi MZ 
580ed7c23fcSKatayama Hirofumi MZ static void
BrFolder_Delete(BrFolder * info,HTREEITEM hItem)581ed7c23fcSKatayama Hirofumi MZ BrFolder_Delete(BrFolder *info, HTREEITEM hItem)
582ed7c23fcSKatayama Hirofumi MZ {
583ed7c23fcSKatayama Hirofumi MZ     SHFILEOPSTRUCTW fileop = { info->hwndTreeView };
584ed7c23fcSKatayama Hirofumi MZ     WCHAR szzFrom[MAX_PATH + 1];
585ed7c23fcSKatayama Hirofumi MZ 
586ed7c23fcSKatayama Hirofumi MZ     // Get item_data
587ed7c23fcSKatayama Hirofumi MZ     BrItemData *item_data = BrFolder_GetItemData(info, hItem);
588ed7c23fcSKatayama Hirofumi MZ 
589ed7c23fcSKatayama Hirofumi MZ     // Get the path
590ed7c23fcSKatayama Hirofumi MZ     if (!SHGetPathFromIDListW(item_data->pidlFull, szzFrom))
591ed7c23fcSKatayama Hirofumi MZ     {
592ed7c23fcSKatayama Hirofumi MZ         ERR("SHGetPathFromIDListW failed\n");
593ed7c23fcSKatayama Hirofumi MZ         return;
594ed7c23fcSKatayama Hirofumi MZ     }
595ed7c23fcSKatayama Hirofumi MZ     szzFrom[lstrlenW(szzFrom) + 1] = UNICODE_NULL; // Double NULL-terminated
596ed7c23fcSKatayama Hirofumi MZ     fileop.pFrom = szzFrom;
597ed7c23fcSKatayama Hirofumi MZ 
598ed7c23fcSKatayama Hirofumi MZ     // Delete folder
599ed7c23fcSKatayama Hirofumi MZ     fileop.fFlags = FOF_ALLOWUNDO;
600ed7c23fcSKatayama Hirofumi MZ     fileop.wFunc = FO_DELETE;
601ed7c23fcSKatayama Hirofumi MZ     SHFileOperationW(&fileop);
602ed7c23fcSKatayama Hirofumi MZ }
603ed7c23fcSKatayama Hirofumi MZ 
604b50ab0dcSKatayama Hirofumi MZ static void
605b50ab0dcSKatayama Hirofumi MZ BrFolder_Refresh(_Inout_ BrFolder *info);
606b50ab0dcSKatayama Hirofumi MZ 
607ed7c23fcSKatayama Hirofumi MZ static LRESULT
BrFolder_Treeview_Keydown(BrFolder * info,LPNMTVKEYDOWN keydown)608ed7c23fcSKatayama Hirofumi MZ BrFolder_Treeview_Keydown(BrFolder *info, LPNMTVKEYDOWN keydown)
609ed7c23fcSKatayama Hirofumi MZ {
610ed7c23fcSKatayama Hirofumi MZ     // Old dialog doesn't support those advanced features
611ed7c23fcSKatayama Hirofumi MZ     if (!(info->lpBrowseInfo->ulFlags & BIF_USENEWUI))
612ed7c23fcSKatayama Hirofumi MZ         return 0;
613ed7c23fcSKatayama Hirofumi MZ 
614ed7c23fcSKatayama Hirofumi MZ     HTREEITEM hItem = TreeView_GetSelection(info->hwndTreeView);
615ed7c23fcSKatayama Hirofumi MZ 
616ed7c23fcSKatayama Hirofumi MZ     switch (keydown->wVKey)
617ed7c23fcSKatayama Hirofumi MZ     {
618ed7c23fcSKatayama Hirofumi MZ         case VK_F2:
619ed7c23fcSKatayama Hirofumi MZ             BrFolder_Rename(info, hItem);
620ed7c23fcSKatayama Hirofumi MZ             break;
621ed7c23fcSKatayama Hirofumi MZ         case VK_DELETE:
622ed7c23fcSKatayama Hirofumi MZ             BrFolder_Delete(info, hItem);
623ed7c23fcSKatayama Hirofumi MZ             break;
624b50ab0dcSKatayama Hirofumi MZ         case 'R':
625b50ab0dcSKatayama Hirofumi MZ         {
626b50ab0dcSKatayama Hirofumi MZ             if (GetKeyState(VK_CONTROL) < 0) // Ctrl+R
627b50ab0dcSKatayama Hirofumi MZ                 BrFolder_Refresh(info);
628b50ab0dcSKatayama Hirofumi MZ             break;
629b50ab0dcSKatayama Hirofumi MZ         }
630b50ab0dcSKatayama Hirofumi MZ         case VK_F5:
631b50ab0dcSKatayama Hirofumi MZ         {
632b50ab0dcSKatayama Hirofumi MZ             BrFolder_Refresh(info);
633b50ab0dcSKatayama Hirofumi MZ             break;
634b50ab0dcSKatayama Hirofumi MZ         }
635ed7c23fcSKatayama Hirofumi MZ     }
636ed7c23fcSKatayama Hirofumi MZ     return 0;
637ed7c23fcSKatayama Hirofumi MZ }
638ed7c23fcSKatayama Hirofumi MZ 
639ed7c23fcSKatayama Hirofumi MZ static LRESULT
BrFolder_OnNotify(BrFolder * info,UINT CtlID,LPNMHDR lpnmh)640ed7c23fcSKatayama Hirofumi MZ BrFolder_OnNotify(BrFolder *info, UINT CtlID, LPNMHDR lpnmh)
641ed7c23fcSKatayama Hirofumi MZ {
642ed7c23fcSKatayama Hirofumi MZ     NMTREEVIEWW *pnmtv = (NMTREEVIEWW *)lpnmh;
643ed7c23fcSKatayama Hirofumi MZ 
644ed7c23fcSKatayama Hirofumi MZ     TRACE("%p %x %p msg=%x\n", info, CtlID, lpnmh, pnmtv->hdr.code);
645ed7c23fcSKatayama Hirofumi MZ 
646ed7c23fcSKatayama Hirofumi MZ     if (pnmtv->hdr.idFrom != IDC_BROWSE_FOR_FOLDER_TREEVIEW)
647ed7c23fcSKatayama Hirofumi MZ         return 0;
648ed7c23fcSKatayama Hirofumi MZ 
649ed7c23fcSKatayama Hirofumi MZ     switch (pnmtv->hdr.code)
650ed7c23fcSKatayama Hirofumi MZ     {
651ed7c23fcSKatayama Hirofumi MZ         case TVN_DELETEITEMA:
652ed7c23fcSKatayama Hirofumi MZ         case TVN_DELETEITEMW:
653ed7c23fcSKatayama Hirofumi MZ             return BrFolder_Treeview_Delete(info, pnmtv);
654ed7c23fcSKatayama Hirofumi MZ 
655ed7c23fcSKatayama Hirofumi MZ         case TVN_ITEMEXPANDINGA:
656ed7c23fcSKatayama Hirofumi MZ         case TVN_ITEMEXPANDINGW:
657ed7c23fcSKatayama Hirofumi MZ             return BrFolder_Treeview_Expand(info, pnmtv);
658ed7c23fcSKatayama Hirofumi MZ 
659ed7c23fcSKatayama Hirofumi MZ         case TVN_SELCHANGEDA:
660ed7c23fcSKatayama Hirofumi MZ         case TVN_SELCHANGEDW:
661ed7c23fcSKatayama Hirofumi MZ             return BrFolder_Treeview_Changed(info, pnmtv);
662ed7c23fcSKatayama Hirofumi MZ 
663dc0ed6deSWhindmar Saksit         case TVN_BEGINLABELEDITA:
664dc0ed6deSWhindmar Saksit         case TVN_BEGINLABELEDITW:
665dc0ed6deSWhindmar Saksit         {
666dc0ed6deSWhindmar Saksit             NMTVDISPINFO &tvdi = *(NMTVDISPINFO*)lpnmh;
667dc0ed6deSWhindmar Saksit             UINT att = BrFolder_GetItemAttributes(info, tvdi.item.hItem, SFGAO_CANRENAME);
668dc0ed6deSWhindmar Saksit             return !(att & SFGAO_CANRENAME);
669dc0ed6deSWhindmar Saksit         }
670dc0ed6deSWhindmar Saksit 
671ed7c23fcSKatayama Hirofumi MZ         case TVN_ENDLABELEDITW:
672ed7c23fcSKatayama Hirofumi MZ             return BrFolder_Treeview_Rename(info, (LPNMTVDISPINFOW)pnmtv);
673ed7c23fcSKatayama Hirofumi MZ 
674ed7c23fcSKatayama Hirofumi MZ         case TVN_KEYDOWN:
675ed7c23fcSKatayama Hirofumi MZ             return BrFolder_Treeview_Keydown(info, (LPNMTVKEYDOWN)pnmtv);
676ed7c23fcSKatayama Hirofumi MZ 
677ed7c23fcSKatayama Hirofumi MZ         default:
678ed7c23fcSKatayama Hirofumi MZ             WARN("unhandled (%d)\n", pnmtv->hdr.code);
679ed7c23fcSKatayama Hirofumi MZ             break;
680ed7c23fcSKatayama Hirofumi MZ     }
681ed7c23fcSKatayama Hirofumi MZ 
682ed7c23fcSKatayama Hirofumi MZ     return 0;
683ed7c23fcSKatayama Hirofumi MZ }
684ed7c23fcSKatayama Hirofumi MZ 
685ed7c23fcSKatayama Hirofumi MZ static BOOL
BrFolder_OnInitDialog(HWND hWnd,BrFolder * info)686ed7c23fcSKatayama Hirofumi MZ BrFolder_OnInitDialog(HWND hWnd, BrFolder *info)
687ed7c23fcSKatayama Hirofumi MZ {
688ed7c23fcSKatayama Hirofumi MZ     CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidlDesktop;
689ed7c23fcSKatayama Hirofumi MZ     SHChangeNotifyEntry ntreg;
690ed7c23fcSKatayama Hirofumi MZ     LPBROWSEINFOW lpBrowseInfo = info->lpBrowseInfo;
691ed7c23fcSKatayama Hirofumi MZ 
692ed7c23fcSKatayama Hirofumi MZ     info->hWnd = hWnd;
693d4815873SWhindmar Saksit     SetWindowLongPtrW(hWnd, DWLP_USER, (LONG_PTR)info);
694ed7c23fcSKatayama Hirofumi MZ 
695ed7c23fcSKatayama Hirofumi MZ     if (lpBrowseInfo->ulFlags & BIF_NEWDIALOGSTYLE)
696ed7c23fcSKatayama Hirofumi MZ         FIXME("flags BIF_NEWDIALOGSTYLE partially implemented\n");
697ed7c23fcSKatayama Hirofumi MZ 
698ed7c23fcSKatayama Hirofumi MZ     if (lpBrowseInfo->ulFlags & ~SUPPORTED_FLAGS)
699ed7c23fcSKatayama Hirofumi MZ         FIXME("flags %x not implemented\n", (lpBrowseInfo->ulFlags & ~SUPPORTED_FLAGS));
700ed7c23fcSKatayama Hirofumi MZ 
7014696996eSKatayama Hirofumi MZ     info->layout = NULL;
702ed7c23fcSKatayama Hirofumi MZ     if (lpBrowseInfo->ulFlags & BIF_USENEWUI)
703ed7c23fcSKatayama Hirofumi MZ     {
704ed7c23fcSKatayama Hirofumi MZ         RECT rcWnd;
705ed7c23fcSKatayama Hirofumi MZ 
706ed7c23fcSKatayama Hirofumi MZ         // Resize the treeview if there's not editbox
707ed7c23fcSKatayama Hirofumi MZ         if ((lpBrowseInfo->ulFlags & BIF_NEWDIALOGSTYLE) &&
708ed7c23fcSKatayama Hirofumi MZ             !(lpBrowseInfo->ulFlags & BIF_EDITBOX))
709ed7c23fcSKatayama Hirofumi MZ         {
710ed7c23fcSKatayama Hirofumi MZ             RECT rcEdit, rcTreeView;
711ed7c23fcSKatayama Hirofumi MZ             GetWindowRect(GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT), &rcEdit);
712ed7c23fcSKatayama Hirofumi MZ             GetWindowRect(GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_TREEVIEW), &rcTreeView);
713ed7c23fcSKatayama Hirofumi MZ             LONG cy = rcTreeView.top - rcEdit.top;
714ed7c23fcSKatayama Hirofumi MZ             MapWindowPoints(NULL, hWnd, (LPPOINT)&rcTreeView, sizeof(RECT) / sizeof(POINT));
715ed7c23fcSKatayama Hirofumi MZ             rcTreeView.top -= cy;
716ed7c23fcSKatayama Hirofumi MZ             MoveWindow(GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_TREEVIEW),
717ed7c23fcSKatayama Hirofumi MZ                        rcTreeView.left, rcTreeView.top,
718ed7c23fcSKatayama Hirofumi MZ                        rcTreeView.right - rcTreeView.left,
719ed7c23fcSKatayama Hirofumi MZ                        rcTreeView.bottom - rcTreeView.top, TRUE);
720ed7c23fcSKatayama Hirofumi MZ         }
721ed7c23fcSKatayama Hirofumi MZ 
722ed7c23fcSKatayama Hirofumi MZ         if (lpBrowseInfo->ulFlags & BIF_NEWDIALOGSTYLE)
723ed7c23fcSKatayama Hirofumi MZ             info->layout = LayoutInit(hWnd, g_layout_info, _countof(g_layout_info));
724ed7c23fcSKatayama Hirofumi MZ 
725ed7c23fcSKatayama Hirofumi MZ         // TODO: Windows allows shrinking the windows a bit
726ed7c23fcSKatayama Hirofumi MZ         GetWindowRect(hWnd, &rcWnd);
727ed7c23fcSKatayama Hirofumi MZ         info->szMin.cx = rcWnd.right - rcWnd.left;
728ed7c23fcSKatayama Hirofumi MZ         info->szMin.cy = rcWnd.bottom - rcWnd.top;
729ed7c23fcSKatayama Hirofumi MZ     }
730ed7c23fcSKatayama Hirofumi MZ 
731ed7c23fcSKatayama Hirofumi MZ     if (lpBrowseInfo->lpszTitle)
732ed7c23fcSKatayama Hirofumi MZ         SetDlgItemTextW(hWnd, IDC_BROWSE_FOR_FOLDER_TITLE, lpBrowseInfo->lpszTitle);
733ed7c23fcSKatayama Hirofumi MZ     else
734ed7c23fcSKatayama Hirofumi MZ         ShowWindow(GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_TITLE), SW_HIDE);
735ed7c23fcSKatayama Hirofumi MZ 
736ed7c23fcSKatayama Hirofumi MZ     if (!(lpBrowseInfo->ulFlags & BIF_STATUSTEXT) || (lpBrowseInfo->ulFlags & BIF_USENEWUI))
737ed7c23fcSKatayama Hirofumi MZ         ShowWindow(GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_STATUS), SW_HIDE);
738ed7c23fcSKatayama Hirofumi MZ 
739ed7c23fcSKatayama Hirofumi MZ     // Hide "Make New Folder" Button?
740ed7c23fcSKatayama Hirofumi MZ     if ((lpBrowseInfo->ulFlags & BIF_NONEWFOLDERBUTTON) ||
741ed7c23fcSKatayama Hirofumi MZ         !(lpBrowseInfo->ulFlags & BIF_NEWDIALOGSTYLE))
742ed7c23fcSKatayama Hirofumi MZ     {
743ed7c23fcSKatayama Hirofumi MZ         ShowWindow(GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_NEW_FOLDER), SW_HIDE);
744ed7c23fcSKatayama Hirofumi MZ     }
745ed7c23fcSKatayama Hirofumi MZ 
746ed7c23fcSKatayama Hirofumi MZ     // Hide the editbox?
747ed7c23fcSKatayama Hirofumi MZ     if (!(lpBrowseInfo->ulFlags & BIF_EDITBOX))
748ed7c23fcSKatayama Hirofumi MZ     {
749ed7c23fcSKatayama Hirofumi MZ         ShowWindow(GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_FOLDER), SW_HIDE);
750ed7c23fcSKatayama Hirofumi MZ         ShowWindow(GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT), SW_HIDE);
751ed7c23fcSKatayama Hirofumi MZ     }
752ed7c23fcSKatayama Hirofumi MZ 
753ed7c23fcSKatayama Hirofumi MZ     info->hwndTreeView = GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_TREEVIEW);
754ed7c23fcSKatayama Hirofumi MZ     if (info->hwndTreeView)
755ed7c23fcSKatayama Hirofumi MZ         BrFolder_InitTreeView(info);
756ed7c23fcSKatayama Hirofumi MZ     else
757ed7c23fcSKatayama Hirofumi MZ         ERR("treeview control missing!\n");
758ed7c23fcSKatayama Hirofumi MZ 
759ed7c23fcSKatayama Hirofumi MZ     // Register for change notifications
760ed7c23fcSKatayama Hirofumi MZ     SHGetFolderLocation(NULL, CSIDL_DESKTOP, NULL, 0, &pidlDesktop);
761ed7c23fcSKatayama Hirofumi MZ 
762ed7c23fcSKatayama Hirofumi MZ     ntreg.pidl = pidlDesktop;
763ed7c23fcSKatayama Hirofumi MZ     ntreg.fRecursive = TRUE;
7644988de4bSKatayama Hirofumi MZ     info->hChangeNotify = SHChangeNotifyRegister(hWnd,
7654988de4bSKatayama Hirofumi MZ                                                  SHCNRF_ShellLevel | SHCNRF_NewDelivery,
7664988de4bSKatayama Hirofumi MZ                                                  SHCNE_ALLEVENTS,
767ed7c23fcSKatayama Hirofumi MZ                                                  SHV_CHANGE_NOTIFY, 1, &ntreg);
768ed7c23fcSKatayama Hirofumi MZ 
769ed7c23fcSKatayama Hirofumi MZ     BrFolder_Callback(info->lpBrowseInfo, hWnd, BFFM_INITIALIZED, 0);
770ed7c23fcSKatayama Hirofumi MZ 
771ed7c23fcSKatayama Hirofumi MZ     SHAutoComplete(GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT),
772ed7c23fcSKatayama Hirofumi MZ                    (SHACF_FILESYS_ONLY | SHACF_URLHISTORY | SHACF_FILESYSTEM));
773ed7c23fcSKatayama Hirofumi MZ     return TRUE;
774ed7c23fcSKatayama Hirofumi MZ }
775ed7c23fcSKatayama Hirofumi MZ 
776ed7c23fcSKatayama Hirofumi MZ static HRESULT
BrFolder_NewFolder(BrFolder * info)777ed7c23fcSKatayama Hirofumi MZ BrFolder_NewFolder(BrFolder *info)
778ed7c23fcSKatayama Hirofumi MZ {
779ed7c23fcSKatayama Hirofumi MZ     CComPtr<IShellFolder> desktop, cur;
780ed7c23fcSKatayama Hirofumi MZ     WCHAR wszNewFolder[25], path[MAX_PATH], name[MAX_PATH];
781ed7c23fcSKatayama Hirofumi MZ 
782ed7c23fcSKatayama Hirofumi MZ     HRESULT hr = SHGetDesktopFolder(&desktop);
783ed7c23fcSKatayama Hirofumi MZ     if (FAILED_UNEXPECTEDLY(hr))
784ed7c23fcSKatayama Hirofumi MZ         return hr;
785ed7c23fcSKatayama Hirofumi MZ 
786ed7c23fcSKatayama Hirofumi MZ     if (info->pidlRet)
787ed7c23fcSKatayama Hirofumi MZ     {
788ed7c23fcSKatayama Hirofumi MZ         hr = desktop->BindToObject(info->pidlRet, NULL, IID_PPV_ARG(IShellFolder, &cur));
789ed7c23fcSKatayama Hirofumi MZ         if (FAILED_UNEXPECTEDLY(hr))
790ed7c23fcSKatayama Hirofumi MZ             return hr;
791ed7c23fcSKatayama Hirofumi MZ 
792ed7c23fcSKatayama Hirofumi MZ         hr = SHGetPathFromIDListW(info->pidlRet, path);
793ed7c23fcSKatayama Hirofumi MZ     }
794ed7c23fcSKatayama Hirofumi MZ     else
795ed7c23fcSKatayama Hirofumi MZ     {
7968df5aac9SKatayama Hirofumi MZ         cur = desktop;
797ed7c23fcSKatayama Hirofumi MZ         hr = SHGetFolderPathW(NULL, CSIDL_DESKTOPDIRECTORY, NULL, SHGFP_TYPE_CURRENT, path);
798ed7c23fcSKatayama Hirofumi MZ     }
799ed7c23fcSKatayama Hirofumi MZ 
800ed7c23fcSKatayama Hirofumi MZ     if (FAILED_UNEXPECTEDLY(hr))
801ed7c23fcSKatayama Hirofumi MZ         return hr;
802ed7c23fcSKatayama Hirofumi MZ 
803ed7c23fcSKatayama Hirofumi MZ     hr = E_FAIL;
804ed7c23fcSKatayama Hirofumi MZ     if (!LoadStringW(shell32_hInstance, IDS_NEWFOLDER, wszNewFolder, _countof(wszNewFolder)))
805ed7c23fcSKatayama Hirofumi MZ         return hr;
806ed7c23fcSKatayama Hirofumi MZ 
807ed7c23fcSKatayama Hirofumi MZ     if (!PathYetAnotherMakeUniqueName(name, path, NULL, wszNewFolder))
808ed7c23fcSKatayama Hirofumi MZ         return hr;
809ed7c23fcSKatayama Hirofumi MZ 
810ed7c23fcSKatayama Hirofumi MZ     INT len = lstrlenW(path);
811ed7c23fcSKatayama Hirofumi MZ     if (len < MAX_PATH && name[len] == L'\\')
812ed7c23fcSKatayama Hirofumi MZ         len++;
813ed7c23fcSKatayama Hirofumi MZ 
814ed7c23fcSKatayama Hirofumi MZ     if (!CreateDirectoryW(name, NULL))
815ed7c23fcSKatayama Hirofumi MZ         return hr;
816ed7c23fcSKatayama Hirofumi MZ 
817ed7c23fcSKatayama Hirofumi MZ     // Update parent of newly created directory
818ed7c23fcSKatayama Hirofumi MZ     HTREEITEM hParent = TreeView_GetSelection(info->hwndTreeView);
819ed7c23fcSKatayama Hirofumi MZ     if (!hParent)
820ed7c23fcSKatayama Hirofumi MZ         return hr;
821ed7c23fcSKatayama Hirofumi MZ 
822ed7c23fcSKatayama Hirofumi MZ     TreeView_Expand(info->hwndTreeView, hParent, TVE_EXPAND);
823ed7c23fcSKatayama Hirofumi MZ 
824ed7c23fcSKatayama Hirofumi MZ     TVITEMW item = { TVIF_PARAM | TVIF_STATE };
825ed7c23fcSKatayama Hirofumi MZ     item.hItem = hParent;
826ed7c23fcSKatayama Hirofumi MZ     TreeView_GetItem(info->hwndTreeView, &item);
827ed7c23fcSKatayama Hirofumi MZ     BrItemData *item_data = (BrItemData *)item.lParam;
828ed7c23fcSKatayama Hirofumi MZ     if (!item_data)
829ed7c23fcSKatayama Hirofumi MZ         return hr;
830ed7c23fcSKatayama Hirofumi MZ 
831ed7c23fcSKatayama Hirofumi MZ     // Update treeview
832ed7c23fcSKatayama Hirofumi MZ     if (!(item.state & TVIS_EXPANDEDONCE))
833ed7c23fcSKatayama Hirofumi MZ     {
834ed7c23fcSKatayama Hirofumi MZ         item.mask = TVIF_STATE;
835ed7c23fcSKatayama Hirofumi MZ         item.state = item.stateMask = TVIS_EXPANDEDONCE;
836ed7c23fcSKatayama Hirofumi MZ         TreeView_SetItem(info->hwndTreeView, &item);
837ed7c23fcSKatayama Hirofumi MZ     }
838ed7c23fcSKatayama Hirofumi MZ 
839ed7c23fcSKatayama Hirofumi MZ     CComHeapPtr<ITEMIDLIST_RELATIVE> pidlNew;
840ed7c23fcSKatayama Hirofumi MZ     hr = cur->ParseDisplayName(NULL, NULL, name + len, NULL, &pidlNew, NULL);
841ed7c23fcSKatayama Hirofumi MZ     if (FAILED_UNEXPECTEDLY(hr))
842ed7c23fcSKatayama Hirofumi MZ         return hr;
843ed7c23fcSKatayama Hirofumi MZ 
8444696996eSKatayama Hirofumi MZ     HTREEITEM hAdded = BrFolder_InsertItem(info, cur, pidlNew, item_data->pidlFull, hParent);
845ed7c23fcSKatayama Hirofumi MZ     TreeView_SortChildren(info->hwndTreeView, hParent, FALSE);
846ed7c23fcSKatayama Hirofumi MZ     return BrFolder_Rename(info, hAdded);
847ed7c23fcSKatayama Hirofumi MZ }
848ed7c23fcSKatayama Hirofumi MZ 
849ed7c23fcSKatayama Hirofumi MZ static void
BrFolder_OnOK(BrFolder * info)8504696996eSKatayama Hirofumi MZ BrFolder_OnOK(BrFolder *info)
851ed7c23fcSKatayama Hirofumi MZ {
852ed7c23fcSKatayama Hirofumi MZ     // Get the text
8534696996eSKatayama Hirofumi MZ     WCHAR szPath[MAX_PATH];
854ed7c23fcSKatayama Hirofumi MZ     GetDlgItemTextW(info->hWnd, IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT, szPath, _countof(szPath));
855ed7c23fcSKatayama Hirofumi MZ     StrTrimW(szPath, L" \t");
856ed7c23fcSKatayama Hirofumi MZ 
857ed7c23fcSKatayama Hirofumi MZ     // The original pidl is owned by the treeview and will be free'd.
858ed7c23fcSKatayama Hirofumi MZ     if (!PathIsRelativeW(szPath) && PathIsDirectoryW(szPath))
8594696996eSKatayama Hirofumi MZ         info->pidlRet = ILCreateFromPathW(szPath); // It's valid path
860ed7c23fcSKatayama Hirofumi MZ     else
861ed7c23fcSKatayama Hirofumi MZ         info->pidlRet = ILClone(info->pidlRet);
8624696996eSKatayama Hirofumi MZ 
8634696996eSKatayama Hirofumi MZ     if (!info->pidlRet) // A null pidl would mean a cancel
864ed7c23fcSKatayama Hirofumi MZ         info->pidlRet = _ILCreateDesktop();
8654696996eSKatayama Hirofumi MZ 
866ed7c23fcSKatayama Hirofumi MZ     pdump(info->pidlRet);
8674696996eSKatayama Hirofumi MZ 
8684696996eSKatayama Hirofumi MZ     LPBROWSEINFOW lpBrowseInfo = info->lpBrowseInfo;
8694696996eSKatayama Hirofumi MZ     if (!lpBrowseInfo->pszDisplayName)
8704696996eSKatayama Hirofumi MZ         return;
8714696996eSKatayama Hirofumi MZ 
872ed7c23fcSKatayama Hirofumi MZ     SHFILEINFOW fileInfo = { NULL };
873ed7c23fcSKatayama Hirofumi MZ     lpBrowseInfo->pszDisplayName[0] = UNICODE_NULL;
874ed7c23fcSKatayama Hirofumi MZ     if (SHGetFileInfoW((LPCWSTR)info->pidlRet, 0, &fileInfo, sizeof(fileInfo),
875ed7c23fcSKatayama Hirofumi MZ                        SHGFI_PIDL | SHGFI_DISPLAYNAME))
876ed7c23fcSKatayama Hirofumi MZ     {
877ed7c23fcSKatayama Hirofumi MZ         lstrcpynW(lpBrowseInfo->pszDisplayName, fileInfo.szDisplayName, MAX_PATH);
878ed7c23fcSKatayama Hirofumi MZ     }
879ed7c23fcSKatayama Hirofumi MZ }
8804696996eSKatayama Hirofumi MZ 
8814696996eSKatayama Hirofumi MZ static void
BrFolder_OnCommand(BrFolder * info,UINT id)8824696996eSKatayama Hirofumi MZ BrFolder_OnCommand(BrFolder *info, UINT id)
8834696996eSKatayama Hirofumi MZ {
8844696996eSKatayama Hirofumi MZ     switch (id)
8854696996eSKatayama Hirofumi MZ     {
8864696996eSKatayama Hirofumi MZ         case IDOK:
8874696996eSKatayama Hirofumi MZ         {
8884696996eSKatayama Hirofumi MZ             BrFolder_OnOK(info);
889ed7c23fcSKatayama Hirofumi MZ             EndDialog(info->hWnd, IDOK);
890ed7c23fcSKatayama Hirofumi MZ             break;
891ed7c23fcSKatayama Hirofumi MZ         }
892ed7c23fcSKatayama Hirofumi MZ         case IDCANCEL:
893ed7c23fcSKatayama Hirofumi MZ         {
894ed7c23fcSKatayama Hirofumi MZ             EndDialog(info->hWnd, IDCANCEL);
895ed7c23fcSKatayama Hirofumi MZ             break;
896ed7c23fcSKatayama Hirofumi MZ         }
897ed7c23fcSKatayama Hirofumi MZ         case IDC_BROWSE_FOR_FOLDER_NEW_FOLDER:
898ed7c23fcSKatayama Hirofumi MZ         {
899ed7c23fcSKatayama Hirofumi MZ             BrFolder_NewFolder(info);
900ed7c23fcSKatayama Hirofumi MZ             break;
901ed7c23fcSKatayama Hirofumi MZ         }
902ed7c23fcSKatayama Hirofumi MZ     }
903ed7c23fcSKatayama Hirofumi MZ }
904ed7c23fcSKatayama Hirofumi MZ 
9053da9e7e2SWhindmar Saksit static void
GetTreeViewItemContextMenuPos(HWND hWnd,HTREEITEM hItem,POINT * ppt)9063da9e7e2SWhindmar Saksit GetTreeViewItemContextMenuPos(HWND hWnd, HTREEITEM hItem, POINT *ppt)
9073da9e7e2SWhindmar Saksit {
9083da9e7e2SWhindmar Saksit     RECT rc;
9093da9e7e2SWhindmar Saksit     if (TreeView_GetItemRect(hWnd, hItem, &rc, TRUE))
9103da9e7e2SWhindmar Saksit     {
9113da9e7e2SWhindmar Saksit         ppt->x = (rc.left + rc.right) / 2;
9123da9e7e2SWhindmar Saksit         ppt->y = (rc.top + rc.bottom) / 2;
9133da9e7e2SWhindmar Saksit     }
9143da9e7e2SWhindmar Saksit     ClientToScreen(hWnd, ppt);
9153da9e7e2SWhindmar Saksit }
9163da9e7e2SWhindmar Saksit 
9173da9e7e2SWhindmar Saksit static void
BrFolder_OnContextMenu(BrFolder & info,LPARAM lParam)9183da9e7e2SWhindmar Saksit BrFolder_OnContextMenu(BrFolder &info, LPARAM lParam)
9193da9e7e2SWhindmar Saksit {
9203da9e7e2SWhindmar Saksit     enum { IDC_TOGGLE = 1, ID_FIRSTCMD, ID_LASTCMD = 0xffff };
9213da9e7e2SWhindmar Saksit     HTREEITEM hSelected = TreeView_GetSelection(info.hwndTreeView);
9223da9e7e2SWhindmar Saksit     CMINVOKECOMMANDINFOEX ici = { sizeof(ici), CMIC_MASK_PTINVOKE, info.hWnd };
9233da9e7e2SWhindmar Saksit     ici.nShow = SW_SHOW;
9243da9e7e2SWhindmar Saksit     ici.ptInvoke.x = GET_X_LPARAM(lParam);
9253da9e7e2SWhindmar Saksit     ici.ptInvoke.y = GET_Y_LPARAM(lParam);
9263da9e7e2SWhindmar Saksit     if ((int)lParam == -1) // Keyboard
9273da9e7e2SWhindmar Saksit     {
9283da9e7e2SWhindmar Saksit         GetTreeViewItemContextMenuPos(info.hwndTreeView, hSelected, &ici.ptInvoke);
9293da9e7e2SWhindmar Saksit     }
9303da9e7e2SWhindmar Saksit     else // Get correct item for right-click on not current item
9313da9e7e2SWhindmar Saksit     {
9323da9e7e2SWhindmar Saksit         TVHITTESTINFO hti = { ici.ptInvoke };
9333da9e7e2SWhindmar Saksit         ScreenToClient(info.hwndTreeView, &hti.pt);
9343da9e7e2SWhindmar Saksit         hSelected = TreeView_HitTest(info.hwndTreeView, &hti);
9353da9e7e2SWhindmar Saksit     }
9363da9e7e2SWhindmar Saksit     BrItemData *item = BrFolder_GetItemData(&info, hSelected);
9373da9e7e2SWhindmar Saksit     if (!item)
9383da9e7e2SWhindmar Saksit         return; // Not on an item
9393da9e7e2SWhindmar Saksit 
9403da9e7e2SWhindmar Saksit     TV_ITEM tvi;
9413da9e7e2SWhindmar Saksit     tvi.mask = TVIF_STATE | TVIF_CHILDREN;
9423da9e7e2SWhindmar Saksit     tvi.stateMask = TVIS_EXPANDED;
9433da9e7e2SWhindmar Saksit     tvi.hItem = hSelected;
9443da9e7e2SWhindmar Saksit     TreeView_GetItem(info.hwndTreeView, &tvi);
9453da9e7e2SWhindmar Saksit 
9463da9e7e2SWhindmar Saksit     CComPtr<IContextMenu> pcm;
9473da9e7e2SWhindmar Saksit     HRESULT hr = item->lpsfParent->GetUIObjectOf(info.hWnd, 1, &item->pidlChild,
9483da9e7e2SWhindmar Saksit                                                  IID_IContextMenu, NULL, (void**)&pcm);
9493da9e7e2SWhindmar Saksit     if (FAILED(hr))
9503da9e7e2SWhindmar Saksit         return;
9513da9e7e2SWhindmar Saksit 
9523da9e7e2SWhindmar Saksit     HMENU hMenu = CreatePopupMenu();
9533da9e7e2SWhindmar Saksit     if (!hMenu)
9543da9e7e2SWhindmar Saksit         return;
9553da9e7e2SWhindmar Saksit     info.pContextMenu = pcm;
9567c3d3851SWhindmar Saksit     UINT cmf = ((GetKeyState(VK_SHIFT) < 0) ? CMF_EXTENDEDVERBS : 0) | CMF_CANRENAME;
95763935f85SWhindmar Saksit     hr = pcm->QueryContextMenu(hMenu, 0, ID_FIRSTCMD, ID_LASTCMD, CMF_EXPLORE | cmf);
9583da9e7e2SWhindmar Saksit     if (hr > 0)
9593da9e7e2SWhindmar Saksit         _InsertMenuItemW(hMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, 0);
9603da9e7e2SWhindmar Saksit     _InsertMenuItemW(hMenu, 0, TRUE, IDC_TOGGLE, MFT_STRING,
9613da9e7e2SWhindmar Saksit         MAKEINTRESOURCEW((tvi.state & TVIS_EXPANDED) ? IDS_COLLAPSE : IDS_EXPAND),
9623da9e7e2SWhindmar Saksit         MFS_DEFAULT | (tvi.cChildren ? 0 : MFS_GRAYED));
9633da9e7e2SWhindmar Saksit 
9643da9e7e2SWhindmar Saksit     UINT cmd = TrackPopupMenuEx(hMenu, TPM_RETURNCMD, ici.ptInvoke.x, ici.ptInvoke.y, info.hWnd, NULL);
9653da9e7e2SWhindmar Saksit     ici.lpVerb = MAKEINTRESOURCEA(cmd - ID_FIRSTCMD);
9663da9e7e2SWhindmar Saksit     if (cmd == IDC_TOGGLE)
9673da9e7e2SWhindmar Saksit     {
9683da9e7e2SWhindmar Saksit         TreeView_SelectItem(info.hwndTreeView, hSelected);
9693da9e7e2SWhindmar Saksit         TreeView_Expand(info.hwndTreeView, hSelected, TVE_TOGGLE);
9703da9e7e2SWhindmar Saksit     }
9713da9e7e2SWhindmar Saksit     else if (cmd != 0 && GetDfmCmd(pcm, ici.lpVerb) == DFM_CMD_RENAME)
9723da9e7e2SWhindmar Saksit     {
97363935f85SWhindmar Saksit         BrFolder_Rename(&info, hSelected);
9743da9e7e2SWhindmar Saksit     }
9753da9e7e2SWhindmar Saksit     else if (cmd != 0)
9763da9e7e2SWhindmar Saksit     {
9777c3d3851SWhindmar Saksit         if (GetKeyState(VK_SHIFT) < 0)
9787c3d3851SWhindmar Saksit             ici.fMask |= CMIC_MASK_SHIFT_DOWN;
9797c3d3851SWhindmar Saksit         if (GetKeyState(VK_CONTROL) < 0)
9807c3d3851SWhindmar Saksit             ici.fMask |= CMIC_MASK_CONTROL_DOWN;
9813da9e7e2SWhindmar Saksit         pcm->InvokeCommand((CMINVOKECOMMANDINFO*)&ici);
9823da9e7e2SWhindmar Saksit     }
9833da9e7e2SWhindmar Saksit     info.pContextMenu = NULL;
9843da9e7e2SWhindmar Saksit     DestroyMenu(hMenu);
9853da9e7e2SWhindmar Saksit }
9863da9e7e2SWhindmar Saksit 
987ed7c23fcSKatayama Hirofumi MZ static BOOL
BrFolder_OnSetExpandedPidl(BrFolder * info,LPITEMIDLIST pidlSelection,HTREEITEM * phItem)988ed7c23fcSKatayama Hirofumi MZ BrFolder_OnSetExpandedPidl(BrFolder *info, LPITEMIDLIST pidlSelection, HTREEITEM *phItem)
989ed7c23fcSKatayama Hirofumi MZ {
990ed7c23fcSKatayama Hirofumi MZ     if (_ILIsDesktop(pidlSelection))
991ed7c23fcSKatayama Hirofumi MZ     {
992ed7c23fcSKatayama Hirofumi MZ         if (phItem)
993ed7c23fcSKatayama Hirofumi MZ             *phItem = TVI_ROOT;
994ed7c23fcSKatayama Hirofumi MZ         return TRUE;
995ed7c23fcSKatayama Hirofumi MZ     }
996ed7c23fcSKatayama Hirofumi MZ 
997ed7c23fcSKatayama Hirofumi MZ     // Move pidlCurrent behind the SHITEMIDs in pidlSelection, which are the root of
998ed7c23fcSKatayama Hirofumi MZ     // the sub-tree currently displayed.
999ed7c23fcSKatayama Hirofumi MZ     PCIDLIST_ABSOLUTE pidlRoot = info->lpBrowseInfo->pidlRoot;
1000ed7c23fcSKatayama Hirofumi MZ     LPITEMIDLIST pidlCurrent = pidlSelection;
1001ed7c23fcSKatayama Hirofumi MZ     while (!_ILIsEmpty(pidlRoot) && _ILIsEqualSimple(pidlRoot, pidlCurrent))
1002ed7c23fcSKatayama Hirofumi MZ     {
1003ed7c23fcSKatayama Hirofumi MZ         pidlRoot = ILGetNext(pidlRoot);
1004ed7c23fcSKatayama Hirofumi MZ         pidlCurrent = ILGetNext(pidlCurrent);
1005ed7c23fcSKatayama Hirofumi MZ     }
1006ed7c23fcSKatayama Hirofumi MZ 
1007ed7c23fcSKatayama Hirofumi MZ     // The given ID List is not part of the SHBrowseForFolder's current sub-tree.
1008ed7c23fcSKatayama Hirofumi MZ     if (!_ILIsEmpty(pidlRoot))
1009ed7c23fcSKatayama Hirofumi MZ     {
1010ed7c23fcSKatayama Hirofumi MZ         if (phItem)
1011ed7c23fcSKatayama Hirofumi MZ             *phItem = NULL;
1012ed7c23fcSKatayama Hirofumi MZ         return FALSE;
1013ed7c23fcSKatayama Hirofumi MZ     }
1014ed7c23fcSKatayama Hirofumi MZ 
1015ed7c23fcSKatayama Hirofumi MZ     // Initialize item to point to the first child of the root folder.
1016ed7c23fcSKatayama Hirofumi MZ     TVITEMEXW item = { TVIF_PARAM };
1017ed7c23fcSKatayama Hirofumi MZ     item.hItem = TreeView_GetRoot(info->hwndTreeView);
1018ed7c23fcSKatayama Hirofumi MZ     if (item.hItem)
1019ed7c23fcSKatayama Hirofumi MZ         item.hItem = TreeView_GetChild(info->hwndTreeView, item.hItem);
1020ed7c23fcSKatayama Hirofumi MZ 
1021ed7c23fcSKatayama Hirofumi MZ     // Walk the tree along the nodes corresponding to the remaining ITEMIDLIST
1022ed7c23fcSKatayama Hirofumi MZ     while (item.hItem && !_ILIsEmpty(pidlCurrent))
1023ed7c23fcSKatayama Hirofumi MZ     {
1024ed7c23fcSKatayama Hirofumi MZ         TreeView_GetItem(info->hwndTreeView, &item);
1025ed7c23fcSKatayama Hirofumi MZ         BrItemData *pItemData = (BrItemData *)item.lParam;
1026ed7c23fcSKatayama Hirofumi MZ 
1027ed7c23fcSKatayama Hirofumi MZ         if (_ILIsEqualSimple(pItemData->pidlChild, pidlCurrent))
1028ed7c23fcSKatayama Hirofumi MZ         {
1029ed7c23fcSKatayama Hirofumi MZ             pidlCurrent = ILGetNext(pidlCurrent);
1030ed7c23fcSKatayama Hirofumi MZ             if (!_ILIsEmpty(pidlCurrent))
1031ed7c23fcSKatayama Hirofumi MZ             {
1032ed7c23fcSKatayama Hirofumi MZ                 // Only expand current node and move on to its first child,
1033ed7c23fcSKatayama Hirofumi MZ                 // if we didn't already reach the last SHITEMID
1034ed7c23fcSKatayama Hirofumi MZ                 TreeView_Expand(info->hwndTreeView, item.hItem, TVE_EXPAND);
1035ed7c23fcSKatayama Hirofumi MZ                 item.hItem = TreeView_GetChild(info->hwndTreeView, item.hItem);
1036ed7c23fcSKatayama Hirofumi MZ             }
1037ed7c23fcSKatayama Hirofumi MZ         }
1038ed7c23fcSKatayama Hirofumi MZ         else
1039ed7c23fcSKatayama Hirofumi MZ         {
1040ed7c23fcSKatayama Hirofumi MZ             item.hItem = TreeView_GetNextSibling(info->hwndTreeView, item.hItem);
1041ed7c23fcSKatayama Hirofumi MZ         }
1042ed7c23fcSKatayama Hirofumi MZ     }
1043ed7c23fcSKatayama Hirofumi MZ 
1044ed7c23fcSKatayama Hirofumi MZ     if (phItem)
1045ed7c23fcSKatayama Hirofumi MZ         *phItem = item.hItem;
1046ed7c23fcSKatayama Hirofumi MZ 
1047ed7c23fcSKatayama Hirofumi MZ     return (_ILIsEmpty(pidlCurrent) && item.hItem);
1048ed7c23fcSKatayama Hirofumi MZ }
1049ed7c23fcSKatayama Hirofumi MZ 
1050ed7c23fcSKatayama Hirofumi MZ static BOOL
BrFolder_OnSetExpandedString(BrFolder * info,LPWSTR pszString,HTREEITEM * phItem)1051ed7c23fcSKatayama Hirofumi MZ BrFolder_OnSetExpandedString(BrFolder *info, LPWSTR pszString, HTREEITEM *phItem)
1052ed7c23fcSKatayama Hirofumi MZ {
1053ed7c23fcSKatayama Hirofumi MZ     CComPtr<IShellFolder> psfDesktop;
1054ed7c23fcSKatayama Hirofumi MZ     HRESULT hr = SHGetDesktopFolder(&psfDesktop);
1055ed7c23fcSKatayama Hirofumi MZ     if (FAILED_UNEXPECTEDLY(hr))
1056ed7c23fcSKatayama Hirofumi MZ         return FALSE;
1057ed7c23fcSKatayama Hirofumi MZ 
1058ed7c23fcSKatayama Hirofumi MZ     CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidlSelection;
1059ed7c23fcSKatayama Hirofumi MZ     hr = psfDesktop->ParseDisplayName(NULL, NULL, pszString, NULL, &pidlSelection, NULL);
1060ed7c23fcSKatayama Hirofumi MZ     if (FAILED_UNEXPECTEDLY(hr))
1061ed7c23fcSKatayama Hirofumi MZ         return FALSE;
1062ed7c23fcSKatayama Hirofumi MZ 
1063ed7c23fcSKatayama Hirofumi MZ     return BrFolder_OnSetExpandedPidl(info, pidlSelection, phItem);
1064ed7c23fcSKatayama Hirofumi MZ }
1065ed7c23fcSKatayama Hirofumi MZ 
1066ed7c23fcSKatayama Hirofumi MZ static BOOL
BrFolder_OnSetSelectionPidl(BrFolder * info,LPITEMIDLIST pidlSelection)1067ed7c23fcSKatayama Hirofumi MZ BrFolder_OnSetSelectionPidl(BrFolder *info, LPITEMIDLIST pidlSelection)
1068ed7c23fcSKatayama Hirofumi MZ {
1069ed7c23fcSKatayama Hirofumi MZ     if (!pidlSelection)
1070ed7c23fcSKatayama Hirofumi MZ         return FALSE;
1071ed7c23fcSKatayama Hirofumi MZ 
1072ed7c23fcSKatayama Hirofumi MZ     HTREEITEM hItem;
1073ed7c23fcSKatayama Hirofumi MZ     BOOL ret = BrFolder_OnSetExpandedPidl(info, pidlSelection, &hItem);
1074ed7c23fcSKatayama Hirofumi MZ     if (ret)
1075ed7c23fcSKatayama Hirofumi MZ         TreeView_SelectItem(info->hwndTreeView, hItem);
1076ed7c23fcSKatayama Hirofumi MZ     return ret;
1077ed7c23fcSKatayama Hirofumi MZ }
1078ed7c23fcSKatayama Hirofumi MZ 
1079ed7c23fcSKatayama Hirofumi MZ static BOOL
BrFolder_OnSetSelectionW(BrFolder * info,LPWSTR pszSelection)1080ed7c23fcSKatayama Hirofumi MZ BrFolder_OnSetSelectionW(BrFolder *info, LPWSTR pszSelection)
1081ed7c23fcSKatayama Hirofumi MZ {
1082ed7c23fcSKatayama Hirofumi MZ     if (!pszSelection)
1083ed7c23fcSKatayama Hirofumi MZ         return FALSE;
1084ed7c23fcSKatayama Hirofumi MZ 
1085ed7c23fcSKatayama Hirofumi MZ     HTREEITEM hItem;
1086ed7c23fcSKatayama Hirofumi MZ     BOOL ret = BrFolder_OnSetExpandedString(info, pszSelection, &hItem);
1087ed7c23fcSKatayama Hirofumi MZ     if (ret)
1088ed7c23fcSKatayama Hirofumi MZ         TreeView_SelectItem(info->hwndTreeView, hItem);
1089ed7c23fcSKatayama Hirofumi MZ     return ret;
1090ed7c23fcSKatayama Hirofumi MZ }
1091ed7c23fcSKatayama Hirofumi MZ 
1092ed7c23fcSKatayama Hirofumi MZ static BOOL
BrFolder_OnSetSelectionA(BrFolder * info,LPSTR pszSelectionA)1093ed7c23fcSKatayama Hirofumi MZ BrFolder_OnSetSelectionA(BrFolder *info, LPSTR pszSelectionA)
1094ed7c23fcSKatayama Hirofumi MZ {
1095ed7c23fcSKatayama Hirofumi MZ     if (!pszSelectionA)
1096ed7c23fcSKatayama Hirofumi MZ         return FALSE;
1097ed7c23fcSKatayama Hirofumi MZ 
1098ed7c23fcSKatayama Hirofumi MZ     CComHeapPtr<WCHAR> pszSelectionW;
1099ed7c23fcSKatayama Hirofumi MZ     __SHCloneStrAtoW(&pszSelectionW, pszSelectionA);
1100ed7c23fcSKatayama Hirofumi MZ     if (!pszSelectionW)
1101ed7c23fcSKatayama Hirofumi MZ         return FALSE;
1102ed7c23fcSKatayama Hirofumi MZ 
1103ed7c23fcSKatayama Hirofumi MZ     return BrFolder_OnSetSelectionW(info, pszSelectionW);
1104ed7c23fcSKatayama Hirofumi MZ }
1105ed7c23fcSKatayama Hirofumi MZ 
1106ed7c23fcSKatayama Hirofumi MZ static void
BrFolder_OnDestroy(BrFolder * info)1107ed7c23fcSKatayama Hirofumi MZ BrFolder_OnDestroy(BrFolder *info)
1108ed7c23fcSKatayama Hirofumi MZ {
1109ed7c23fcSKatayama Hirofumi MZ     if (info->layout)
1110ed7c23fcSKatayama Hirofumi MZ     {
1111ed7c23fcSKatayama Hirofumi MZ         LayoutDestroy(info->layout);
1112ed7c23fcSKatayama Hirofumi MZ         info->layout = NULL;
1113ed7c23fcSKatayama Hirofumi MZ     }
1114ed7c23fcSKatayama Hirofumi MZ 
1115ed7c23fcSKatayama Hirofumi MZ     SHChangeNotifyDeregister(info->hChangeNotify);
1116ed7c23fcSKatayama Hirofumi MZ }
1117ed7c23fcSKatayama Hirofumi MZ 
1118b50ab0dcSKatayama Hirofumi MZ static void
BrFolder_RefreshRecurse(_Inout_ BrFolder * info,_In_ HTREEITEM hTarget)1119b50ab0dcSKatayama Hirofumi MZ BrFolder_RefreshRecurse(
1120b50ab0dcSKatayama Hirofumi MZ     _Inout_ BrFolder *info,
1121b50ab0dcSKatayama Hirofumi MZ     _In_ HTREEITEM hTarget)
1122ed7c23fcSKatayama Hirofumi MZ {
1123b50ab0dcSKatayama Hirofumi MZ     // Get enum
1124b50ab0dcSKatayama Hirofumi MZ     CComPtr<IEnumIDList> pEnum;
1125b50ab0dcSKatayama Hirofumi MZ     BrItemData *pItemData = BrFolder_GetItemData(info, hTarget);
1126b50ab0dcSKatayama Hirofumi MZ     HRESULT hrEnum = BrFolder_GetChildrenEnum(info, pItemData, &pEnum);
1127ed7c23fcSKatayama Hirofumi MZ 
1128b50ab0dcSKatayama Hirofumi MZ     // Insert new items
1129b50ab0dcSKatayama Hirofumi MZ     if (SUCCEEDED(hrEnum))
1130ed7c23fcSKatayama Hirofumi MZ     {
1131b50ab0dcSKatayama Hirofumi MZ         CComHeapPtr<ITEMIDLIST_RELATIVE> pidlTemp;
1132b50ab0dcSKatayama Hirofumi MZ         while (S_OK == pEnum->Next(1, &pidlTemp, NULL))
1133b50ab0dcSKatayama Hirofumi MZ         {
1134b50ab0dcSKatayama Hirofumi MZ             if (!BrFolder_TreeItemHasThisChild(info, hTarget, pidlTemp))
1135b50ab0dcSKatayama Hirofumi MZ             {
1136b50ab0dcSKatayama Hirofumi MZ                 BrFolder_InsertItem(info, pItemData->lpsfParent, pidlTemp, pItemData->pidlFull,
1137b50ab0dcSKatayama Hirofumi MZ                                     hTarget);
1138b50ab0dcSKatayama Hirofumi MZ             }
1139b50ab0dcSKatayama Hirofumi MZ             pidlTemp.Free();
1140b50ab0dcSKatayama Hirofumi MZ         }
1141ed7c23fcSKatayama Hirofumi MZ     }
1142ed7c23fcSKatayama Hirofumi MZ 
1143b50ab0dcSKatayama Hirofumi MZ     // Delete zombie items and update items
1144b50ab0dcSKatayama Hirofumi MZ     HTREEITEM hItem, hNextItem;
1145b50ab0dcSKatayama Hirofumi MZ     for (hItem = TreeView_GetChild(info->hwndTreeView, hTarget); hItem; hItem = hNextItem)
1146b50ab0dcSKatayama Hirofumi MZ     {
1147b50ab0dcSKatayama Hirofumi MZ         hNextItem = TreeView_GetNextSibling(info->hwndTreeView, hItem);
1148b50ab0dcSKatayama Hirofumi MZ 
1149b50ab0dcSKatayama Hirofumi MZ         if (FAILED(hrEnum) || !BrFolder_IsTreeItemInEnum(info, hItem, pEnum))
1150b50ab0dcSKatayama Hirofumi MZ         {
1151b50ab0dcSKatayama Hirofumi MZ             TreeView_DeleteItem(info->hwndTreeView, hItem);
1152b50ab0dcSKatayama Hirofumi MZ             hNextItem = TreeView_GetChild(info->hwndTreeView, hTarget);
1153b50ab0dcSKatayama Hirofumi MZ             continue;
1154b50ab0dcSKatayama Hirofumi MZ         }
1155b50ab0dcSKatayama Hirofumi MZ 
1156b50ab0dcSKatayama Hirofumi MZ         BrFolder_UpdateItem(info, hItem);
1157b50ab0dcSKatayama Hirofumi MZ         BrFolder_RefreshRecurse(info, hItem);
1158b50ab0dcSKatayama Hirofumi MZ     }
1159b50ab0dcSKatayama Hirofumi MZ 
1160b50ab0dcSKatayama Hirofumi MZ     if (SUCCEEDED(hrEnum))
1161b50ab0dcSKatayama Hirofumi MZ         TreeView_SortChildren(info->hwndTreeView, hTarget, FALSE);
1162b50ab0dcSKatayama Hirofumi MZ }
1163b50ab0dcSKatayama Hirofumi MZ 
1164b50ab0dcSKatayama Hirofumi MZ static void
BrFolder_Refresh(_Inout_ BrFolder * info)1165b50ab0dcSKatayama Hirofumi MZ BrFolder_Refresh(_Inout_ BrFolder *info)
1166b50ab0dcSKatayama Hirofumi MZ {
1167b50ab0dcSKatayama Hirofumi MZ     HTREEITEM hRoot = TreeView_GetRoot(info->hwndTreeView);
1168b50ab0dcSKatayama Hirofumi MZ 
1169b50ab0dcSKatayama Hirofumi MZ     SendMessageW(info->hwndTreeView, WM_SETREDRAW, FALSE, 0);
1170b50ab0dcSKatayama Hirofumi MZ 
1171b50ab0dcSKatayama Hirofumi MZ     BrFolder_RefreshRecurse(info, hRoot);
1172b50ab0dcSKatayama Hirofumi MZ 
1173b50ab0dcSKatayama Hirofumi MZ     SendMessageW(info->hwndTreeView, WM_SETREDRAW, TRUE, 0);
1174b50ab0dcSKatayama Hirofumi MZ     InvalidateRect(info->hwndTreeView, NULL, TRUE);
1175ed7c23fcSKatayama Hirofumi MZ }
1176ed7c23fcSKatayama Hirofumi MZ 
1177ed7c23fcSKatayama Hirofumi MZ static void
BrFolder_OnChangeEx(_Inout_ BrFolder * info,_In_ PCIDLIST_ABSOLUTE pidl0,_In_ PCIDLIST_ABSOLUTE pidl1,_In_ LONG event)11784988de4bSKatayama Hirofumi MZ BrFolder_OnChangeEx(
11794988de4bSKatayama Hirofumi MZ     _Inout_ BrFolder *info,
11804988de4bSKatayama Hirofumi MZ     _In_ PCIDLIST_ABSOLUTE pidl0,
11814988de4bSKatayama Hirofumi MZ     _In_ PCIDLIST_ABSOLUTE pidl1,
11824988de4bSKatayama Hirofumi MZ     _In_ LONG event)
1183ed7c23fcSKatayama Hirofumi MZ {
11844988de4bSKatayama Hirofumi MZ     TRACE("(%p)->(%p, %p, 0x%lX)\n", info, pidl0, pidl1, event);
1185ed7c23fcSKatayama Hirofumi MZ 
1186ed7c23fcSKatayama Hirofumi MZ     switch (event)
1187ed7c23fcSKatayama Hirofumi MZ     {
11884988de4bSKatayama Hirofumi MZ         case SHCNE_DRIVEADD:
11894988de4bSKatayama Hirofumi MZ         case SHCNE_MKDIR:
11904988de4bSKatayama Hirofumi MZ         case SHCNE_CREATE:
11914988de4bSKatayama Hirofumi MZ         case SHCNE_DRIVEREMOVED:
1192ed7c23fcSKatayama Hirofumi MZ         case SHCNE_RMDIR:
1193ed7c23fcSKatayama Hirofumi MZ         case SHCNE_DELETE:
11944988de4bSKatayama Hirofumi MZ         case SHCNE_RENAMEFOLDER:
11954988de4bSKatayama Hirofumi MZ         case SHCNE_RENAMEITEM:
11964988de4bSKatayama Hirofumi MZ         case SHCNE_UPDATEDIR:
11974988de4bSKatayama Hirofumi MZ         case SHCNE_UPDATEITEM:
11984988de4bSKatayama Hirofumi MZ         {
1199b50ab0dcSKatayama Hirofumi MZ             // FIXME: Avoid full refresh and optimize for speed. Use pidl0 and pidl1
1200b50ab0dcSKatayama Hirofumi MZ             BrFolder_Refresh(info);
1201ed7c23fcSKatayama Hirofumi MZ             break;
1202ed7c23fcSKatayama Hirofumi MZ         }
1203ed7c23fcSKatayama Hirofumi MZ     }
1204ed7c23fcSKatayama Hirofumi MZ }
1205ed7c23fcSKatayama Hirofumi MZ 
12064988de4bSKatayama Hirofumi MZ // SHV_CHANGE_NOTIFY
12074988de4bSKatayama Hirofumi MZ static void
BrFolder_OnChange(BrFolder * info,WPARAM wParam,LPARAM lParam)12084988de4bSKatayama Hirofumi MZ BrFolder_OnChange(BrFolder *info, WPARAM wParam, LPARAM lParam)
12094988de4bSKatayama Hirofumi MZ {
12104988de4bSKatayama Hirofumi MZ     // We use SHCNRF_NewDelivery method
12114988de4bSKatayama Hirofumi MZ     HANDLE hChange = (HANDLE)wParam;
12124988de4bSKatayama Hirofumi MZ     DWORD dwProcID = (DWORD)lParam;
12134988de4bSKatayama Hirofumi MZ 
12144988de4bSKatayama Hirofumi MZ     PIDLIST_ABSOLUTE *ppidl = NULL;
12154988de4bSKatayama Hirofumi MZ     LONG event;
12164988de4bSKatayama Hirofumi MZ     HANDLE hLock = SHChangeNotification_Lock(hChange, dwProcID, &ppidl, &event);
12174988de4bSKatayama Hirofumi MZ     if (hLock == NULL)
12184988de4bSKatayama Hirofumi MZ     {
12194988de4bSKatayama Hirofumi MZ         ERR("hLock == NULL\n");
12204988de4bSKatayama Hirofumi MZ         return;
12214988de4bSKatayama Hirofumi MZ     }
12224988de4bSKatayama Hirofumi MZ 
12234988de4bSKatayama Hirofumi MZ     BrFolder_OnChangeEx(info, ppidl[0], ppidl[1], (event & ~SHCNE_INTERRUPT));
12244988de4bSKatayama Hirofumi MZ 
12254988de4bSKatayama Hirofumi MZ     SHChangeNotification_Unlock(hLock);
12264988de4bSKatayama Hirofumi MZ }
12274988de4bSKatayama Hirofumi MZ 
1228ed7c23fcSKatayama Hirofumi MZ /*************************************************************************
1229ed7c23fcSKatayama Hirofumi MZ  *             BrFolderDlgProc32  (not an exported API function)
1230ed7c23fcSKatayama Hirofumi MZ  */
1231ed7c23fcSKatayama Hirofumi MZ static INT_PTR CALLBACK
BrFolderDlgProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)1232ed7c23fcSKatayama Hirofumi MZ BrFolderDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1233ed7c23fcSKatayama Hirofumi MZ {
1234ed7c23fcSKatayama Hirofumi MZ     if (uMsg == WM_INITDIALOG)
1235ed7c23fcSKatayama Hirofumi MZ         return BrFolder_OnInitDialog(hWnd, (BrFolder *)lParam);
1236ed7c23fcSKatayama Hirofumi MZ 
1237d4815873SWhindmar Saksit     BrFolder *info = (BrFolder *)GetWindowLongPtrW(hWnd, DWLP_USER);
1238ed7c23fcSKatayama Hirofumi MZ     if (!info)
1239ed7c23fcSKatayama Hirofumi MZ         return 0;
1240ed7c23fcSKatayama Hirofumi MZ 
12413da9e7e2SWhindmar Saksit     if (info->pContextMenu)
12423da9e7e2SWhindmar Saksit     {
12433da9e7e2SWhindmar Saksit         LRESULT result;
12443da9e7e2SWhindmar Saksit         if (SHForwardContextMenuMsg(info->pContextMenu, uMsg, wParam,
12453da9e7e2SWhindmar Saksit                                     lParam, &result, TRUE) == S_OK)
12463da9e7e2SWhindmar Saksit         {
12473da9e7e2SWhindmar Saksit             SetWindowLongPtr(hWnd, DWLP_MSGRESULT, result);
12483da9e7e2SWhindmar Saksit             return TRUE;
12493da9e7e2SWhindmar Saksit         }
12503da9e7e2SWhindmar Saksit     }
12513da9e7e2SWhindmar Saksit 
1252ed7c23fcSKatayama Hirofumi MZ     switch (uMsg)
1253ed7c23fcSKatayama Hirofumi MZ     {
1254ed7c23fcSKatayama Hirofumi MZ         case WM_NOTIFY:
1255dc0ed6deSWhindmar Saksit             SetWindowLongPtr(hWnd, DWLP_MSGRESULT, BrFolder_OnNotify(info, (UINT)wParam, (LPNMHDR)lParam));
1256dc0ed6deSWhindmar Saksit             return TRUE;
1257ed7c23fcSKatayama Hirofumi MZ 
1258ed7c23fcSKatayama Hirofumi MZ         case WM_COMMAND:
1259ed7c23fcSKatayama Hirofumi MZ             BrFolder_OnCommand(info, wParam);
1260ed7c23fcSKatayama Hirofumi MZ             break;
1261ed7c23fcSKatayama Hirofumi MZ 
12623da9e7e2SWhindmar Saksit         case WM_CONTEXTMENU:
12633da9e7e2SWhindmar Saksit             if (info->hwndTreeView == (HWND)wParam)
12643da9e7e2SWhindmar Saksit                 BrFolder_OnContextMenu(*info, lParam);
12653da9e7e2SWhindmar Saksit             break;
12663da9e7e2SWhindmar Saksit 
1267ed7c23fcSKatayama Hirofumi MZ         case WM_GETMINMAXINFO:
1268ed7c23fcSKatayama Hirofumi MZ             ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = info->szMin.cx;
1269ed7c23fcSKatayama Hirofumi MZ             ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = info->szMin.cy;
1270ed7c23fcSKatayama Hirofumi MZ             break;
1271ed7c23fcSKatayama Hirofumi MZ 
1272ed7c23fcSKatayama Hirofumi MZ         case WM_SIZE:
1273ed7c23fcSKatayama Hirofumi MZ             if (info->layout)  // New style dialogs
1274ed7c23fcSKatayama Hirofumi MZ                 LayoutUpdate(hWnd, info->layout, g_layout_info, _countof(g_layout_info));
1275ed7c23fcSKatayama Hirofumi MZ             break;
1276ed7c23fcSKatayama Hirofumi MZ 
1277ed7c23fcSKatayama Hirofumi MZ         case BFFM_SETSTATUSTEXTA:
1278ed7c23fcSKatayama Hirofumi MZ             SetDlgItemTextA(hWnd, IDC_BROWSE_FOR_FOLDER_STATUS, (LPSTR)lParam);
1279ed7c23fcSKatayama Hirofumi MZ             break;
1280ed7c23fcSKatayama Hirofumi MZ 
1281ed7c23fcSKatayama Hirofumi MZ         case BFFM_SETSTATUSTEXTW:
1282ed7c23fcSKatayama Hirofumi MZ             SetDlgItemTextW(hWnd, IDC_BROWSE_FOR_FOLDER_STATUS, (LPWSTR)lParam);
1283ed7c23fcSKatayama Hirofumi MZ             break;
1284ed7c23fcSKatayama Hirofumi MZ 
1285ed7c23fcSKatayama Hirofumi MZ         case BFFM_ENABLEOK:
1286ed7c23fcSKatayama Hirofumi MZ             EnableWindow(GetDlgItem(hWnd, IDOK), lParam != 0);
1287ed7c23fcSKatayama Hirofumi MZ             break;
1288ed7c23fcSKatayama Hirofumi MZ 
1289ed7c23fcSKatayama Hirofumi MZ         case BFFM_SETOKTEXT: // Unicode only
1290ed7c23fcSKatayama Hirofumi MZ             SetDlgItemTextW(hWnd, IDOK, (LPWSTR)lParam);
1291ed7c23fcSKatayama Hirofumi MZ             break;
1292ed7c23fcSKatayama Hirofumi MZ 
1293ed7c23fcSKatayama Hirofumi MZ         case BFFM_SETSELECTIONA:
1294ed7c23fcSKatayama Hirofumi MZ             if (wParam) // String
1295ed7c23fcSKatayama Hirofumi MZ                 return BrFolder_OnSetSelectionA(info, (LPSTR)lParam);
1296ed7c23fcSKatayama Hirofumi MZ             else // PIDL
1297ed7c23fcSKatayama Hirofumi MZ                 return BrFolder_OnSetSelectionPidl(info, (LPITEMIDLIST)lParam);
1298ed7c23fcSKatayama Hirofumi MZ 
1299ed7c23fcSKatayama Hirofumi MZ         case BFFM_SETSELECTIONW:
1300ed7c23fcSKatayama Hirofumi MZ             if (wParam) // String
1301ed7c23fcSKatayama Hirofumi MZ                 return BrFolder_OnSetSelectionW(info, (LPWSTR)lParam);
1302ed7c23fcSKatayama Hirofumi MZ             else // PIDL
1303ed7c23fcSKatayama Hirofumi MZ                 return BrFolder_OnSetSelectionPidl(info, (LPITEMIDLIST)lParam);
1304ed7c23fcSKatayama Hirofumi MZ 
1305ed7c23fcSKatayama Hirofumi MZ         case BFFM_SETEXPANDED: // Unicode only
1306ed7c23fcSKatayama Hirofumi MZ             if (wParam) // String
1307ed7c23fcSKatayama Hirofumi MZ                 return BrFolder_OnSetExpandedString(info, (LPWSTR)lParam, NULL);
1308ed7c23fcSKatayama Hirofumi MZ             else // PIDL
1309ed7c23fcSKatayama Hirofumi MZ                 return BrFolder_OnSetExpandedPidl(info, (LPITEMIDLIST)lParam, NULL);
1310ed7c23fcSKatayama Hirofumi MZ 
1311ed7c23fcSKatayama Hirofumi MZ         case SHV_CHANGE_NOTIFY:
13124988de4bSKatayama Hirofumi MZ             BrFolder_OnChange(info, wParam, lParam);
1313ed7c23fcSKatayama Hirofumi MZ             break;
1314ed7c23fcSKatayama Hirofumi MZ 
1315ed7c23fcSKatayama Hirofumi MZ         case WM_DESTROY:
1316ed7c23fcSKatayama Hirofumi MZ             BrFolder_OnDestroy(info);
1317ed7c23fcSKatayama Hirofumi MZ             break;
1318ed7c23fcSKatayama Hirofumi MZ     }
1319ed7c23fcSKatayama Hirofumi MZ 
1320ed7c23fcSKatayama Hirofumi MZ     return 0;
1321ed7c23fcSKatayama Hirofumi MZ }
1322ed7c23fcSKatayama Hirofumi MZ 
1323ed7c23fcSKatayama Hirofumi MZ /*************************************************************************
1324ed7c23fcSKatayama Hirofumi MZ  * SHBrowseForFolderA [SHELL32.@]
1325ed7c23fcSKatayama Hirofumi MZ  * SHBrowseForFolder  [SHELL32.@]
1326ed7c23fcSKatayama Hirofumi MZ  */
1327ed7c23fcSKatayama Hirofumi MZ EXTERN_C
1328ed7c23fcSKatayama Hirofumi MZ LPITEMIDLIST WINAPI
SHBrowseForFolderA(LPBROWSEINFOA lpbi)1329ed7c23fcSKatayama Hirofumi MZ SHBrowseForFolderA(LPBROWSEINFOA lpbi)
1330ed7c23fcSKatayama Hirofumi MZ {
1331ed7c23fcSKatayama Hirofumi MZ     BROWSEINFOW bi;
1332ed7c23fcSKatayama Hirofumi MZ     bi.hwndOwner = lpbi->hwndOwner;
1333ed7c23fcSKatayama Hirofumi MZ     bi.pidlRoot = lpbi->pidlRoot;
1334ed7c23fcSKatayama Hirofumi MZ 
1335ed7c23fcSKatayama Hirofumi MZ     WCHAR szName[MAX_PATH];
1336ed7c23fcSKatayama Hirofumi MZ     bi.pszDisplayName = (lpbi->pszDisplayName ? szName : NULL);
1337ed7c23fcSKatayama Hirofumi MZ 
1338ed7c23fcSKatayama Hirofumi MZ     CComHeapPtr<WCHAR> pszTitle;
1339ed7c23fcSKatayama Hirofumi MZ     if (lpbi->lpszTitle)
1340ed7c23fcSKatayama Hirofumi MZ         __SHCloneStrAtoW(&pszTitle, lpbi->lpszTitle);
1341ed7c23fcSKatayama Hirofumi MZ     bi.lpszTitle = pszTitle;
1342ed7c23fcSKatayama Hirofumi MZ 
1343ed7c23fcSKatayama Hirofumi MZ     bi.ulFlags = lpbi->ulFlags;
1344ed7c23fcSKatayama Hirofumi MZ     bi.lpfn = lpbi->lpfn;
1345ed7c23fcSKatayama Hirofumi MZ     bi.lParam = lpbi->lParam;
1346ed7c23fcSKatayama Hirofumi MZ     bi.iImage = lpbi->iImage;
1347ed7c23fcSKatayama Hirofumi MZ     PIDLIST_ABSOLUTE pidl = SHBrowseForFolderW(&bi);
1348ed7c23fcSKatayama Hirofumi MZ 
1349ed7c23fcSKatayama Hirofumi MZ     if (bi.pszDisplayName)
1350ed7c23fcSKatayama Hirofumi MZ         SHUnicodeToAnsi(bi.pszDisplayName, lpbi->pszDisplayName, MAX_PATH);
1351ed7c23fcSKatayama Hirofumi MZ 
1352ed7c23fcSKatayama Hirofumi MZ     lpbi->iImage = bi.iImage;
1353ed7c23fcSKatayama Hirofumi MZ     return pidl;
1354ed7c23fcSKatayama Hirofumi MZ }
1355ed7c23fcSKatayama Hirofumi MZ 
1356ed7c23fcSKatayama Hirofumi MZ /*************************************************************************
1357ed7c23fcSKatayama Hirofumi MZ  * SHBrowseForFolderW [SHELL32.@]
1358ed7c23fcSKatayama Hirofumi MZ  */
1359ed7c23fcSKatayama Hirofumi MZ EXTERN_C
1360ed7c23fcSKatayama Hirofumi MZ LPITEMIDLIST WINAPI
SHBrowseForFolderW(LPBROWSEINFOW lpbi)1361ed7c23fcSKatayama Hirofumi MZ SHBrowseForFolderW(LPBROWSEINFOW lpbi)
1362ed7c23fcSKatayama Hirofumi MZ {
1363ed7c23fcSKatayama Hirofumi MZ     TRACE("%p\n", lpbi);
1364ed7c23fcSKatayama Hirofumi MZ 
1365ed7c23fcSKatayama Hirofumi MZ     BrFolder info = { lpbi };
1366ed7c23fcSKatayama Hirofumi MZ 
1367ed7c23fcSKatayama Hirofumi MZ     HRESULT hr = OleInitialize(NULL);
1368ed7c23fcSKatayama Hirofumi MZ 
1369ed7c23fcSKatayama Hirofumi MZ     INT id = ((lpbi->ulFlags & BIF_USENEWUI) ? IDD_BROWSE_FOR_FOLDER_NEW : IDD_BROWSE_FOR_FOLDER);
1370ed7c23fcSKatayama Hirofumi MZ     INT_PTR ret = DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(id), lpbi->hwndOwner,
1371ed7c23fcSKatayama Hirofumi MZ                                   BrFolderDlgProc, (LPARAM)&info);
1372ed7c23fcSKatayama Hirofumi MZ     if (SUCCEEDED(hr))
1373ed7c23fcSKatayama Hirofumi MZ         OleUninitialize();
1374ed7c23fcSKatayama Hirofumi MZ 
1375ed7c23fcSKatayama Hirofumi MZ     if (ret != IDOK)
1376ed7c23fcSKatayama Hirofumi MZ     {
1377ed7c23fcSKatayama Hirofumi MZ         ILFree(info.pidlRet);
1378ed7c23fcSKatayama Hirofumi MZ         return NULL;
1379ed7c23fcSKatayama Hirofumi MZ     }
1380ed7c23fcSKatayama Hirofumi MZ 
1381ed7c23fcSKatayama Hirofumi MZ     return info.pidlRet;
1382ed7c23fcSKatayama Hirofumi MZ }
1383