Remove static variables in SHBrowseForFolder implementation.

oldstable
Mike McCormack 2005-05-04 09:48:15 +00:00 committed by Alexandre Julliard
parent 8091790717
commit 2b2c6f2fba
1 changed files with 173 additions and 126 deletions

View File

@ -37,11 +37,15 @@
WINE_DEFAULT_DEBUG_CHANNEL(shell); WINE_DEFAULT_DEBUG_CHANNEL(shell);
static HWND hwndTreeView; typedef struct tagbrowse_info
static LPBROWSEINFOW lpBrowseInfo; {
static LPITEMIDLIST pidlRet; HWND hWnd;
HWND hwndTreeView;
LPBROWSEINFOW lpBrowseInfo;
LPITEMIDLIST pidlRet;
} browse_info;
typedef struct tagID typedef struct tagTV_ITEMDATA
{ {
LPSHELLFOLDER lpsfParent; /* IShellFolder of the parent */ LPSHELLFOLDER lpsfParent; /* IShellFolder of the parent */
LPITEMIDLIST lpi; /* PIDL relativ to parent */ LPITEMIDLIST lpi; /* PIDL relativ to parent */
@ -49,20 +53,36 @@ typedef struct tagID
IEnumIDList* pEnumIL; /* Children iterator */ IEnumIDList* pEnumIL; /* Children iterator */
} TV_ITEMDATA, *LPTV_ITEMDATA; } TV_ITEMDATA, *LPTV_ITEMDATA;
static void FillTreeView(LPSHELLFOLDER lpsf, LPITEMIDLIST lpifq, HTREEITEM hParent, IEnumIDList* lpe);
static HTREEITEM InsertTreeViewItem(IShellFolder * lpsf, LPCITEMIDLIST pidl, LPCITEMIDLIST pidlParent, IEnumIDList* pEnumIL, HTREEITEM hParent);
#define SUPPORTEDFLAGS (BIF_STATUSTEXT | \ #define SUPPORTEDFLAGS (BIF_STATUSTEXT | \
BIF_BROWSEFORCOMPUTER | \ BIF_BROWSEFORCOMPUTER | \
BIF_RETURNFSANCESTORS | \ BIF_RETURNFSANCESTORS | \
BIF_RETURNONLYFSDIRS | \ BIF_RETURNONLYFSDIRS | \
BIF_BROWSEINCLUDEFILES) BIF_BROWSEINCLUDEFILES)
static void FillTreeView(browse_info*, LPSHELLFOLDER,
LPITEMIDLIST, HTREEITEM, IEnumIDList*);
static HTREEITEM InsertTreeViewItem( browse_info*, IShellFolder *,
LPCITEMIDLIST, LPCITEMIDLIST, IEnumIDList*, HTREEITEM);
const WCHAR szBrowseFolderInfo[] = {
'_','_','W','I','N','E','_',
'B','R','S','F','O','L','D','E','R','D','L','G','_',
'I','N','F','O',0
};
static inline DWORD BrowseFlagsToSHCONTF(UINT ulFlags) static inline DWORD BrowseFlagsToSHCONTF(UINT ulFlags)
{ {
return SHCONTF_FOLDERS | (ulFlags & BIF_BROWSEINCLUDEFILES ? SHCONTF_NONFOLDERS : 0); return SHCONTF_FOLDERS | (ulFlags & BIF_BROWSEINCLUDEFILES ? SHCONTF_NONFOLDERS : 0);
} }
static void browsefolder_callback( LPBROWSEINFOW lpBrowseInfo, HWND hWnd,
UINT msg, LPARAM param )
{
if (!lpBrowseInfo->lpfn)
return;
lpBrowseInfo->lpfn( hWnd, BFFM_INITIALIZED, param, lpBrowseInfo->lParam );
}
/****************************************************************************** /******************************************************************************
* InitializeTreeView [Internal] * InitializeTreeView [Internal]
* *
@ -72,25 +92,23 @@ static inline DWORD BrowseFlagsToSHCONTF(UINT ulFlags)
* hwndParent [I] The BrowseForFolder dialog * hwndParent [I] The BrowseForFolder dialog
* root [I] ITEMIDLIST of the root shell folder * root [I] ITEMIDLIST of the root shell folder
*/ */
static void InitializeTreeView(HWND hwndParent, LPCITEMIDLIST root) static void InitializeTreeView( browse_info *info )
{ {
LPITEMIDLIST pidlParent, pidlChild; LPITEMIDLIST pidlParent, pidlChild;
HIMAGELIST hImageList; HIMAGELIST hImageList;
HRESULT hr; HRESULT hr;
IShellFolder *lpsfParent, *lpsfRoot; IShellFolder *lpsfParent, *lpsfRoot;
IEnumIDList * pEnumChildren = NULL; IEnumIDList * pEnumChildren = NULL;
HTREEITEM item;
DWORD flags;
LPCITEMIDLIST root = info->lpBrowseInfo->pidlRoot;
TRACE("dlg=%p tree=%p\n", hwndParent, hwndTreeView ); TRACE("%p\n", info );
hwndTreeView = GetDlgItem (hwndParent, IDD_TREEVIEW);
if (!hwndTreeView) {
FIXME("Could not get handle to treeview control! Error: %08lx\n", GetLastError());
return;
}
Shell_GetImageList(NULL, &hImageList); Shell_GetImageList(NULL, &hImageList);
if (hImageList) if (hImageList)
TreeView_SetImageList(hwndTreeView, hImageList, 0); TreeView_SetImageList( info->hwndTreeView, hImageList, 0 );
/* We want to call InsertTreeViewItem down the code, in order to insert /* We want to call InsertTreeViewItem down the code, in order to insert
* the root item of the treeview. Due to InsertTreeViewItem's signature, * the root item of the treeview. Due to InsertTreeViewItem's signature,
@ -139,7 +157,8 @@ static void InitializeTreeView(HWND hwndParent, LPCITEMIDLIST root)
return; return;
} }
hr = IShellFolder_EnumObjects(lpsfRoot, hwndParent, BrowseFlagsToSHCONTF(lpBrowseInfo->ulFlags), &pEnumChildren); flags = BrowseFlagsToSHCONTF( info->lpBrowseInfo->ulFlags );
hr = IShellFolder_EnumObjects( lpsfRoot, info->hWnd, flags, &pEnumChildren );
if (!SUCCEEDED(hr)) { if (!SUCCEEDED(hr)) {
WARN("Could not get child iterator! hr = %08lx\n", hr); WARN("Could not get child iterator! hr = %08lx\n", hr);
IShellFolder_Release(lpsfParent); IShellFolder_Release(lpsfParent);
@ -147,8 +166,10 @@ static void InitializeTreeView(HWND hwndParent, LPCITEMIDLIST root)
return; return;
} }
TreeView_DeleteAllItems(hwndTreeView); TreeView_DeleteAllItems( info->hwndTreeView );
TreeView_Expand(hwndTreeView, InsertTreeViewItem(lpsfParent, pidlChild, pidlParent, pEnumChildren, TVI_ROOT), TVE_EXPAND); item = InsertTreeViewItem( info, lpsfParent, pidlChild,
pidlParent, pEnumChildren, TVI_ROOT );
TreeView_Expand( info->hwndTreeView, item, TVE_EXPAND );
IShellFolder_Release(lpsfRoot); IShellFolder_Release(lpsfRoot);
IShellFolder_Release(lpsfParent); IShellFolder_Release(lpsfParent);
@ -156,30 +177,32 @@ static void InitializeTreeView(HWND hwndParent, LPCITEMIDLIST root)
static int GetIcon(LPITEMIDLIST lpi, UINT uFlags) static int GetIcon(LPITEMIDLIST lpi, UINT uFlags)
{ {
SHFILEINFOW sfi; SHFILEINFOW sfi;
SHGetFileInfoW((LPCWSTR)lpi, 0 ,&sfi, sizeof(SHFILEINFOW), uFlags); SHGetFileInfoW((LPCWSTR)lpi, 0 ,&sfi, sizeof(SHFILEINFOW), uFlags);
return sfi.iIcon; return sfi.iIcon;
} }
static void GetNormalAndSelectedIcons(LPITEMIDLIST lpifq, LPTVITEMW lpTV_ITEM) static void GetNormalAndSelectedIcons(LPITEMIDLIST lpifq, LPTVITEMW lpTV_ITEM)
{ {
LPITEMIDLIST pidlDesktop = NULL; LPITEMIDLIST pidlDesktop = NULL;
DWORD flags;
TRACE("%p %p\n",lpifq, lpTV_ITEM); TRACE("%p %p\n",lpifq, lpTV_ITEM);
if (!lpifq) if (!lpifq)
{ {
pidlDesktop = _ILCreateDesktop(); pidlDesktop = _ILCreateDesktop();
lpifq = pidlDesktop; lpifq = pidlDesktop;
} }
lpTV_ITEM->iImage = GetIcon(lpifq, SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON); flags = SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON;
lpTV_ITEM->iSelectedImage = GetIcon(lpifq, SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON); lpTV_ITEM->iImage = GetIcon( lpifq, flags );
if (pidlDesktop) flags = SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON;
ILFree(pidlDesktop); lpTV_ITEM->iSelectedImage = GetIcon( lpifq, flags );
return; if (pidlDesktop)
ILFree( pidlDesktop );
} }
/****************************************************************************** /******************************************************************************
@ -221,6 +244,7 @@ static BOOL GetName(LPSHELLFOLDER lpsf, LPCITEMIDLIST lpi, DWORD dwFlags, LPWSTR
* InsertTreeViewItem [Internal] * InsertTreeViewItem [Internal]
* *
* PARAMS * PARAMS
* info [I] data for the dialog
* lpsf [I] IShellFolder interface of the item's parent shell folder * lpsf [I] IShellFolder interface of the item's parent shell folder
* pidl [I] ITEMIDLIST of the child to insert, relativ to parent * pidl [I] ITEMIDLIST of the child to insert, relativ to parent
* pidlParent [I] ITEMIDLIST of the parent shell folder * pidlParent [I] ITEMIDLIST of the parent shell folder
@ -231,8 +255,9 @@ static BOOL GetName(LPSHELLFOLDER lpsf, LPCITEMIDLIST lpi, DWORD dwFlags, LPWSTR
* Success: Handle to the created and inserted treeview-item * Success: Handle to the created and inserted treeview-item
* Failure: NULL * Failure: NULL
*/ */
static HTREEITEM InsertTreeViewItem(IShellFolder * lpsf, LPCITEMIDLIST pidl, static HTREEITEM InsertTreeViewItem( browse_info *info, IShellFolder * lpsf,
LPCITEMIDLIST pidlParent, IEnumIDList* pEnumIL, HTREEITEM hParent) LPCITEMIDLIST pidl, LPCITEMIDLIST pidlParent, IEnumIDList* pEnumIL,
HTREEITEM hParent)
{ {
TVITEMW tvi; TVITEMW tvi;
TVINSERTSTRUCTW tvins; TVINSERTSTRUCTW tvins;
@ -244,7 +269,8 @@ static HTREEITEM InsertTreeViewItem(IShellFolder * lpsf, LPCITEMIDLIST pidl,
tvi.cChildren= pEnumIL ? 1 : 0; tvi.cChildren= pEnumIL ? 1 : 0;
tvi.mask |= TVIF_CHILDREN; tvi.mask |= TVIF_CHILDREN;
if (!(lptvid = (LPTV_ITEMDATA)SHAlloc(sizeof(TV_ITEMDATA)))) lptvid = SHAlloc( sizeof(TV_ITEMDATA) );
if (!lptvid)
return NULL; return NULL;
if (!GetName(lpsf, pidl, SHGDN_NORMAL, szBuff)) if (!GetName(lpsf, pidl, SHGDN_NORMAL, szBuff))
@ -265,7 +291,7 @@ static HTREEITEM InsertTreeViewItem(IShellFolder * lpsf, LPCITEMIDLIST pidl,
tvins.hInsertAfter = NULL; tvins.hInsertAfter = NULL;
tvins.hParent = hParent; tvins.hParent = hParent;
return (HTREEITEM)TreeView_InsertItemW(hwndTreeView, &tvins); return (HTREEITEM)TreeView_InsertItemW( info->hwndTreeView, &tvins );
} }
/****************************************************************************** /******************************************************************************
@ -275,26 +301,28 @@ static HTREEITEM InsertTreeViewItem(IShellFolder * lpsf, LPCITEMIDLIST pidl,
* lpsf and whose PIDL is pidl, insert a treeview-item right under hParent * lpsf and whose PIDL is pidl, insert a treeview-item right under hParent
* *
* PARAMS * PARAMS
* info [I] data for the dialog
* lpsf [I] IShellFolder interface of the parent shell folder * lpsf [I] IShellFolder interface of the parent shell folder
* pidl [I] ITEMIDLIST of the parent shell folder * pidl [I] ITEMIDLIST of the parent shell folder
* hParent [I] The treeview item that represents the parent shell folder * hParent [I] The treeview item that represents the parent shell folder
* lpe [I] An iterator for the children of the parent shell folder * lpe [I] An iterator for the children of the parent shell folder
*/ */
static void FillTreeView(IShellFolder * lpsf, LPITEMIDLIST pidl, HTREEITEM hParent, IEnumIDList* lpe) static void FillTreeView( browse_info *info, IShellFolder * lpsf,
LPITEMIDLIST pidl, HTREEITEM hParent, IEnumIDList* lpe)
{ {
HTREEITEM hPrev = 0; HTREEITEM hPrev = 0;
LPITEMIDLIST pidlTemp = 0; LPITEMIDLIST pidlTemp = 0;
ULONG ulFetched; ULONG ulFetched;
HRESULT hr; HRESULT hr;
HWND hwnd=GetParent(hwndTreeView); HWND hwnd = GetParent( info->hwndTreeView );
TRACE("%p %p %x %p\n",lpsf, pidl, (INT)hParent, lpe); TRACE("%p %p %x %p\n",lpsf, pidl, (INT)hParent, lpe);
/* No IEnumIDList -> No children */ /* No IEnumIDList -> No children */
if (!lpe) return; if (!lpe) return;
SetCapture(GetParent(hwndTreeView)); SetCapture( hwnd );
SetCursor(LoadCursorA(0, (LPSTR)IDC_WAIT)); SetCursor( LoadCursorA( 0, (LPSTR)IDC_WAIT ) );
while (NOERROR == IEnumIDList_Next(lpe,1,&pidlTemp,&ulFetched)) while (NOERROR == IEnumIDList_Next(lpe,1,&pidlTemp,&ulFetched))
{ {
@ -307,10 +335,12 @@ static void FillTreeView(IShellFolder * lpsf, LPITEMIDLIST pidl, HTREEITEM hPar
hr = IShellFolder_BindToObject(lpsf,pidlTemp,NULL,&IID_IShellFolder,(LPVOID*)&pSFChild); hr = IShellFolder_BindToObject(lpsf,pidlTemp,NULL,&IID_IShellFolder,(LPVOID*)&pSFChild);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = IShellFolder_EnumObjects(pSFChild, hwnd, BrowseFlagsToSHCONTF(lpBrowseInfo->ulFlags), &pEnumIL); DWORD flags = BrowseFlagsToSHCONTF(info->lpBrowseInfo->ulFlags);
hr = IShellFolder_EnumObjects(pSFChild, hwnd, flags, &pEnumIL);
if (hr == S_OK) if (hr == S_OK)
{ {
if ((IEnumIDList_Skip(pEnumIL, 1) != S_OK) || FAILED(IEnumIDList_Reset(pEnumIL))) if ((IEnumIDList_Skip(pEnumIL, 1) != S_OK) ||
FAILED(IEnumIDList_Reset(pEnumIL)))
{ {
IEnumIDList_Release(pEnumIL); IEnumIDList_Release(pEnumIL);
pEnumIL = NULL; pEnumIL = NULL;
@ -320,13 +350,13 @@ static void FillTreeView(IShellFolder * lpsf, LPITEMIDLIST pidl, HTREEITEM hPar
} }
} }
if (!(hPrev = InsertTreeViewItem(lpsf, pidlTemp, pidl, pEnumIL, hParent))) if (!(hPrev = InsertTreeViewItem(info, lpsf, pidlTemp, pidl, pEnumIL, hParent)))
goto Done; goto done;
SHFree(pidlTemp); /* Finally, free the pidl that the shell gave us... */ SHFree(pidlTemp); /* Finally, free the pidl that the shell gave us... */
pidlTemp=NULL; pidlTemp=NULL;
} }
Done: done:
ReleaseCapture(); ReleaseCapture();
SetCursor(LoadCursorW(0, (LPWSTR)IDC_ARROW)); SetCursor(LoadCursorW(0, (LPWSTR)IDC_ARROW));
@ -342,8 +372,9 @@ static inline BOOL PIDLIsType(LPCITEMIDLIST pidl, PIDLTYPE type)
return (data->type == type); return (data->type == type);
} }
static void BrsFolder_CheckValidSelection(HWND hWndTree, LPTV_ITEMDATA lptvid) static void BrsFolder_CheckValidSelection( browse_info *info, LPTV_ITEMDATA lptvid )
{ {
LPBROWSEINFOW lpBrowseInfo = info->lpBrowseInfo;
LPCITEMIDLIST pidl = lptvid->lpi; LPCITEMIDLIST pidl = lptvid->lpi;
BOOL bEnabled = TRUE; BOOL bEnabled = TRUE;
DWORD dwAttributes; DWORD dwAttributes;
@ -368,10 +399,10 @@ static void BrsFolder_CheckValidSelection(HWND hWndTree, LPTV_ITEMDATA lptvid)
if (FAILED(r) || (dwAttributes != (SFGAO_FOLDER | SFGAO_FILESYSTEM))) if (FAILED(r) || (dwAttributes != (SFGAO_FOLDER | SFGAO_FILESYSTEM)))
bEnabled = FALSE; bEnabled = FALSE;
} }
SendMessageW(hWndTree, BFFM_ENABLEOK, 0, (LPARAM)bEnabled); SendMessageW(info->hWnd, BFFM_ENABLEOK, 0, (LPARAM)bEnabled);
} }
static LRESULT BrsFolder_Treeview_Delete( NMTREEVIEWW *pnmtv ) static LRESULT BrsFolder_Treeview_Delete( browse_info *info, NMTREEVIEWW *pnmtv )
{ {
LPTV_ITEMDATA lptvid = (LPTV_ITEMDATA)pnmtv->itemOld.lParam; LPTV_ITEMDATA lptvid = (LPTV_ITEMDATA)pnmtv->itemOld.lParam;
@ -386,7 +417,7 @@ static LRESULT BrsFolder_Treeview_Delete( NMTREEVIEWW *pnmtv )
return 0; return 0;
} }
static LRESULT BrsFolder_Treeview_Expand( NMTREEVIEWW *pnmtv ) static LRESULT BrsFolder_Treeview_Expand( browse_info *info, NMTREEVIEWW *pnmtv )
{ {
IShellFolder *lpsf2 = NULL; IShellFolder *lpsf2 = NULL;
LPTV_ITEMDATA lptvid = (LPTV_ITEMDATA) pnmtv->itemNew.lParam; LPTV_ITEMDATA lptvid = (LPTV_ITEMDATA) pnmtv->itemNew.lParam;
@ -400,33 +431,33 @@ static LRESULT BrsFolder_Treeview_Expand( NMTREEVIEWW *pnmtv )
r = IShellFolder_BindToObject( lptvid->lpsfParent, lptvid->lpi, 0, r = IShellFolder_BindToObject( lptvid->lpsfParent, lptvid->lpi, 0,
(REFIID)&IID_IShellFolder, (LPVOID *)&lpsf2 ); (REFIID)&IID_IShellFolder, (LPVOID *)&lpsf2 );
if (SUCCEEDED(r)) if (SUCCEEDED(r))
FillTreeView( lpsf2, lptvid->lpifq, pnmtv->itemNew.hItem, lptvid->pEnumIL); FillTreeView( info, lpsf2, lptvid->lpifq, pnmtv->itemNew.hItem, lptvid->pEnumIL);
/* My Computer is already sorted and trying to do a simple text /* My Computer is already sorted and trying to do a simple text
* sort will only mess things up */ * sort will only mess things up */
if (!_ILIsMyComputer(lptvid->lpi)) if (!_ILIsMyComputer(lptvid->lpi))
TreeView_SortChildren(hwndTreeView, pnmtv->itemNew.hItem, FALSE); TreeView_SortChildren(info->hwndTreeView, pnmtv->itemNew.hItem, FALSE);
return 0; return 0;
} }
static HRESULT BrsFolder_Treeview_Changed( HWND hWnd, NMTREEVIEWW *pnmtv ) static HRESULT BrsFolder_Treeview_Changed( browse_info *info, NMTREEVIEWW *pnmtv )
{ {
LPTV_ITEMDATA lptvid = (LPTV_ITEMDATA) pnmtv->itemNew.lParam; LPTV_ITEMDATA lptvid = (LPTV_ITEMDATA) pnmtv->itemNew.lParam;
lptvid = (LPTV_ITEMDATA) pnmtv->itemNew.lParam; lptvid = (LPTV_ITEMDATA) pnmtv->itemNew.lParam;
pidlRet = lptvid->lpifq; info->pidlRet = lptvid->lpifq;
if (lpBrowseInfo->lpfn) browsefolder_callback( info->lpBrowseInfo, info->hWnd, BFFM_SELCHANGED,
(lpBrowseInfo->lpfn)(hWnd, BFFM_SELCHANGED, (LPARAM)pidlRet, lpBrowseInfo->lParam); (LPARAM)info->pidlRet );
BrsFolder_CheckValidSelection(hWnd, lptvid); BrsFolder_CheckValidSelection( info, lptvid );
return 0; return 0;
} }
static LRESULT BrsFolder_OnNotify( HWND hWnd, UINT CtlID, LPNMHDR lpnmh ) static LRESULT BrsFolder_OnNotify( browse_info *info, UINT CtlID, LPNMHDR lpnmh )
{ {
NMTREEVIEWW *pnmtv = (NMTREEVIEWW *)lpnmh; NMTREEVIEWW *pnmtv = (NMTREEVIEWW *)lpnmh;
TRACE("%p %x %p msg=%x\n", hWnd, CtlID, lpnmh, pnmtv->hdr.code); TRACE("%p %x %p msg=%x\n", info, CtlID, lpnmh, pnmtv->hdr.code);
if (pnmtv->hdr.idFrom != IDD_TREEVIEW) if (pnmtv->hdr.idFrom != IDD_TREEVIEW)
return 0; return 0;
@ -435,15 +466,15 @@ static LRESULT BrsFolder_OnNotify( HWND hWnd, UINT CtlID, LPNMHDR lpnmh )
{ {
case TVN_DELETEITEMA: case TVN_DELETEITEMA:
case TVN_DELETEITEMW: case TVN_DELETEITEMW:
return BrsFolder_Treeview_Delete( pnmtv ); return BrsFolder_Treeview_Delete( info, pnmtv );
case TVN_ITEMEXPANDINGA: case TVN_ITEMEXPANDINGA:
case TVN_ITEMEXPANDINGW: case TVN_ITEMEXPANDINGW:
return BrsFolder_Treeview_Expand( pnmtv ); return BrsFolder_Treeview_Expand( info, pnmtv );
case TVN_SELCHANGEDA: case TVN_SELCHANGEDA:
case TVN_SELCHANGEDW: case TVN_SELCHANGEDW:
return BrsFolder_Treeview_Changed( hWnd, pnmtv ); return BrsFolder_Treeview_Changed( info, pnmtv );
default: default:
WARN("unhandled (%d)\n", pnmtv->hdr.code); WARN("unhandled (%d)\n", pnmtv->hdr.code);
@ -454,10 +485,12 @@ static LRESULT BrsFolder_OnNotify( HWND hWnd, UINT CtlID, LPNMHDR lpnmh )
} }
static BOOL BrsFolder_OnCreate( HWND hWnd, LPBROWSEINFOW lpbi ) static BOOL BrsFolder_OnCreate( HWND hWnd, browse_info *info )
{ {
pidlRet = NULL; LPBROWSEINFOW lpBrowseInfo = info->lpBrowseInfo;
lpBrowseInfo = lpbi;
info->hWnd = hWnd;
SetPropW( hWnd, szBrowseFolderInfo, info );
if (lpBrowseInfo->ulFlags & ~SUPPORTEDFLAGS) if (lpBrowseInfo->ulFlags & ~SUPPORTEDFLAGS)
FIXME("flags %x not implemented\n", lpBrowseInfo->ulFlags & ~SUPPORTEDFLAGS); FIXME("flags %x not implemented\n", lpBrowseInfo->ulFlags & ~SUPPORTEDFLAGS);
@ -470,27 +503,32 @@ static BOOL BrsFolder_OnCreate( HWND hWnd, LPBROWSEINFOW lpbi )
if (!(lpBrowseInfo->ulFlags & BIF_STATUSTEXT)) if (!(lpBrowseInfo->ulFlags & BIF_STATUSTEXT))
ShowWindow( GetDlgItem(hWnd, IDD_STATUS), SW_HIDE ); ShowWindow( GetDlgItem(hWnd, IDD_STATUS), SW_HIDE );
InitializeTreeView( hWnd, lpBrowseInfo->pidlRoot ); info->hwndTreeView = GetDlgItem( hWnd, IDD_TREEVIEW );
if (info->hwndTreeView)
InitializeTreeView( info );
else
ERR("treeview control missing!\n");
if (lpBrowseInfo->lpfn) browsefolder_callback( info->lpBrowseInfo, hWnd, BFFM_INITIALIZED, 0 );
(lpBrowseInfo->lpfn)( hWnd, BFFM_INITIALIZED, 0, lpBrowseInfo->lParam );
return TRUE; return TRUE;
} }
static BOOL BrsFolder_OnCommand( HWND hWnd, UINT id ) static BOOL BrsFolder_OnCommand( browse_info *info, UINT id )
{ {
LPBROWSEINFOW lpBrowseInfo = info->lpBrowseInfo;
switch (id) switch (id)
{ {
case IDOK: case IDOK:
pdump( pidlRet ); pdump( info->pidlRet );
if (lpBrowseInfo->pszDisplayName) if (lpBrowseInfo->pszDisplayName)
SHGetPathFromIDListW( pidlRet, lpBrowseInfo->pszDisplayName ); SHGetPathFromIDListW( info->pidlRet, lpBrowseInfo->pszDisplayName );
EndDialog(hWnd, (DWORD) ILClone(pidlRet)); EndDialog( info->hWnd, 1 );
return TRUE; return TRUE;
case IDCANCEL: case IDCANCEL:
EndDialog(hWnd, 0); EndDialog( info->hWnd, 0 );
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
@ -502,18 +540,22 @@ static BOOL BrsFolder_OnCommand( HWND hWnd, UINT id )
static INT_PTR CALLBACK BrsFolderDlgProc( HWND hWnd, UINT msg, WPARAM wParam, static INT_PTR CALLBACK BrsFolderDlgProc( HWND hWnd, UINT msg, WPARAM wParam,
LPARAM lParam ) LPARAM lParam )
{ {
browse_info *info;
TRACE("hwnd=%p msg=%04x 0x%08x 0x%08lx\n", hWnd, msg, wParam, lParam ); TRACE("hwnd=%p msg=%04x 0x%08x 0x%08lx\n", hWnd, msg, wParam, lParam );
if (msg == WM_INITDIALOG) if (msg == WM_INITDIALOG)
return BrsFolder_OnCreate( hWnd, (LPBROWSEINFOW) lParam ); return BrsFolder_OnCreate( hWnd, (browse_info*) lParam );
info = (browse_info*) GetPropW( hWnd, szBrowseFolderInfo );
switch (msg) switch (msg)
{ {
case WM_NOTIFY: case WM_NOTIFY:
return BrsFolder_OnNotify( hWnd, (UINT)wParam, (LPNMHDR)lParam); return BrsFolder_OnNotify( info, (UINT)wParam, (LPNMHDR)lParam);
case WM_COMMAND: case WM_COMMAND:
return BrsFolder_OnCommand( hWnd, wParam ); return BrsFolder_OnCommand( info, wParam );
case BFFM_SETSTATUSTEXTA: case BFFM_SETSTATUSTEXTA:
TRACE("Set status %s\n", debugstr_a((LPSTR)lParam)); TRACE("Set status %s\n", debugstr_a((LPSTR)lParam));
@ -559,7 +601,7 @@ static INT_PTR CALLBACK BrsFolderDlgProc( HWND hWnd, UINT msg, WPARAM wParam,
return FALSE; return FALSE;
} }
static const WCHAR swBrowseTempName[] = { static const WCHAR swBrowseTemplateName[] = {
'S','H','B','R','S','F','O','R','F','O','L','D','E','R','_','M','S','G','B','O','X',0}; 'S','H','B','R','S','F','O','R','F','O','L','D','E','R','_','M','S','G','B','O','X',0};
/************************************************************************* /*************************************************************************
@ -568,66 +610,71 @@ static const WCHAR swBrowseTempName[] = {
*/ */
LPITEMIDLIST WINAPI SHBrowseForFolderA (LPBROWSEINFOA lpbi) LPITEMIDLIST WINAPI SHBrowseForFolderA (LPBROWSEINFOA lpbi)
{ {
BROWSEINFOW bi; BROWSEINFOW bi;
LPITEMIDLIST lpid; LPITEMIDLIST lpid;
INT len; INT len;
TRACE("(%p{lpszTitle=%s,owner=%p})\n", lpbi, TRACE("%p\n", lpbi);
lpbi ? debugstr_a(lpbi->lpszTitle) : NULL, lpbi ? lpbi->hwndOwner : NULL);
if (!lpbi) bi.hwndOwner = lpbi->hwndOwner;
return NULL; bi.pidlRoot = lpbi->pidlRoot;
if (lpbi->pszDisplayName)
{
len = MultiByteToWideChar( CP_ACP, 0, lpbi->pszDisplayName, -1, NULL, 0 );
bi.pszDisplayName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, lpbi->pszDisplayName, -1, bi.pszDisplayName, len );
}
else
bi.pszDisplayName = NULL;
bi.hwndOwner = lpbi->hwndOwner; if (lpbi->lpszTitle)
bi.pidlRoot = lpbi->pidlRoot; {
if (lpbi->pszDisplayName) len = MultiByteToWideChar( CP_ACP, 0, lpbi->lpszTitle, -1, NULL, 0 );
{ bi.lpszTitle = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
/*lpbi->pszDisplayName is assumed to be MAX_PATH (MSDN) */ MultiByteToWideChar( CP_ACP, 0, lpbi->lpszTitle, -1, (LPWSTR)bi.lpszTitle, len );
bi.pszDisplayName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); }
MultiByteToWideChar(CP_ACP, 0, lpbi->pszDisplayName, -1, bi.pszDisplayName, MAX_PATH); else
} bi.lpszTitle = NULL;
else
bi.pszDisplayName = NULL;
if (lpbi->lpszTitle) bi.ulFlags = lpbi->ulFlags;
{ bi.lpfn = lpbi->lpfn;
len = MultiByteToWideChar(CP_ACP, 0, lpbi->lpszTitle, -1, NULL, 0); bi.lParam = lpbi->lParam;
bi.lpszTitle = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); bi.iImage = lpbi->iImage;
MultiByteToWideChar(CP_ACP, 0, lpbi->lpszTitle, -1, (LPWSTR)bi.lpszTitle, len); lpid = SHBrowseForFolderW( &bi );
} if (bi.pszDisplayName)
else {
bi.lpszTitle = NULL; WideCharToMultiByte( CP_ACP, 0, bi.pszDisplayName, -1,
lpbi->pszDisplayName, MAX_PATH, 0, NULL);
bi.ulFlags = lpbi->ulFlags; HeapFree( GetProcessHeap(), 0, bi.pszDisplayName );
bi.lpfn = lpbi->lpfn; }
bi.lParam = lpbi->lParam; HeapFree(GetProcessHeap(), 0, (LPVOID)bi.lpszTitle);
bi.iImage = lpbi->iImage; lpbi->iImage = bi.iImage;
lpid = (LPITEMIDLIST) DialogBoxParamW(shell32_hInstance, return lpid;
swBrowseTempName, lpbi->hwndOwner,
BrsFolderDlgProc, (INT)&bi);
if (bi.pszDisplayName)
{
WideCharToMultiByte(CP_ACP, 0, bi.pszDisplayName, -1, lpbi->pszDisplayName, MAX_PATH, 0, NULL);
HeapFree(GetProcessHeap(), 0, bi.pszDisplayName);
}
HeapFree(GetProcessHeap(), 0, (LPVOID)bi.lpszTitle);
lpbi->iImage = bi.iImage;
return lpid;
} }
/************************************************************************* /*************************************************************************
* SHBrowseForFolderW [SHELL32.@] * SHBrowseForFolderW [SHELL32.@]
*
* NOTES:
* crashes when passed a null pointer
*/ */
LPITEMIDLIST WINAPI SHBrowseForFolderW (LPBROWSEINFOW lpbi) LPITEMIDLIST WINAPI SHBrowseForFolderW (LPBROWSEINFOW lpbi)
{ {
TRACE("((%p->{lpszTitle=%s,owner=%p})\n", lpbi, browse_info info;
lpbi ? debugstr_w(lpbi->lpszTitle) : NULL, lpbi ? lpbi->hwndOwner : 0); DWORD r;
if (!lpbi) ERR("%p\n", lpbi);
return NULL;
return (LPITEMIDLIST) DialogBoxParamW(shell32_hInstance, info.hWnd = 0;
swBrowseTempName, lpbi->hwndOwner, info.pidlRet = NULL;
BrsFolderDlgProc, (INT)lpbi); info.lpBrowseInfo = lpbi;
info.hwndTreeView = NULL;
r = DialogBoxParamW( shell32_hInstance, swBrowseTemplateName, lpbi->hwndOwner,
BrsFolderDlgProc, (LPARAM)&info );
if (!r)
return NULL;
return info.pidlRet;
} }