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