diff --git a/dlls/shell32/brsfolder.c b/dlls/shell32/brsfolder.c index 3170bebbc9b..651dc27abb1 100644 --- a/dlls/shell32/brsfolder.c +++ b/dlls/shell32/brsfolder.c @@ -37,11 +37,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell); -static HWND hwndTreeView; -static LPBROWSEINFOW lpBrowseInfo; -static LPITEMIDLIST pidlRet; +typedef struct tagbrowse_info +{ + HWND hWnd; + HWND hwndTreeView; + LPBROWSEINFOW lpBrowseInfo; + LPITEMIDLIST pidlRet; +} browse_info; -typedef struct tagID +typedef struct tagTV_ITEMDATA { LPSHELLFOLDER lpsfParent; /* IShellFolder of the parent */ LPITEMIDLIST lpi; /* PIDL relativ to parent */ @@ -49,20 +53,36 @@ typedef struct tagID IEnumIDList* pEnumIL; /* Children iterator */ } 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 | \ BIF_BROWSEFORCOMPUTER | \ BIF_RETURNFSANCESTORS | \ BIF_RETURNONLYFSDIRS | \ 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) { 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] * @@ -72,25 +92,23 @@ static inline DWORD BrowseFlagsToSHCONTF(UINT ulFlags) * hwndParent [I] The BrowseForFolder dialog * root [I] ITEMIDLIST of the root shell folder */ -static void InitializeTreeView(HWND hwndParent, LPCITEMIDLIST root) +static void InitializeTreeView( browse_info *info ) { LPITEMIDLIST pidlParent, pidlChild; HIMAGELIST hImageList; HRESULT hr; IShellFolder *lpsfParent, *lpsfRoot; 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); 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 * the root item of the treeview. Due to InsertTreeViewItem's signature, @@ -139,7 +157,8 @@ static void InitializeTreeView(HWND hwndParent, LPCITEMIDLIST root) 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)) { WARN("Could not get child iterator! hr = %08lx\n", hr); IShellFolder_Release(lpsfParent); @@ -147,8 +166,10 @@ static void InitializeTreeView(HWND hwndParent, LPCITEMIDLIST root) return; } - TreeView_DeleteAllItems(hwndTreeView); - TreeView_Expand(hwndTreeView, InsertTreeViewItem(lpsfParent, pidlChild, pidlParent, pEnumChildren, TVI_ROOT), TVE_EXPAND); + TreeView_DeleteAllItems( info->hwndTreeView ); + item = InsertTreeViewItem( info, lpsfParent, pidlChild, + pidlParent, pEnumChildren, TVI_ROOT ); + TreeView_Expand( info->hwndTreeView, item, TVE_EXPAND ); IShellFolder_Release(lpsfRoot); IShellFolder_Release(lpsfParent); @@ -156,30 +177,32 @@ static void InitializeTreeView(HWND hwndParent, LPCITEMIDLIST root) static int GetIcon(LPITEMIDLIST lpi, UINT uFlags) { - SHFILEINFOW sfi; - SHGetFileInfoW((LPCWSTR)lpi, 0 ,&sfi, sizeof(SHFILEINFOW), uFlags); - return sfi.iIcon; + SHFILEINFOW sfi; + SHGetFileInfoW((LPCWSTR)lpi, 0 ,&sfi, sizeof(SHFILEINFOW), uFlags); + return sfi.iIcon; } 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) - { - pidlDesktop = _ILCreateDesktop(); - lpifq = pidlDesktop; - } + if (!lpifq) + { + pidlDesktop = _ILCreateDesktop(); + lpifq = pidlDesktop; + } - lpTV_ITEM->iImage = GetIcon(lpifq, SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON); - lpTV_ITEM->iSelectedImage = GetIcon(lpifq, SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON); + flags = SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON; + lpTV_ITEM->iImage = GetIcon( lpifq, flags ); - if (pidlDesktop) - ILFree(pidlDesktop); + flags = SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON; + 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] * * PARAMS + * info [I] data for the dialog * lpsf [I] IShellFolder interface of the item's parent shell folder * pidl [I] ITEMIDLIST of the child to insert, relativ to parent * 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 * Failure: NULL */ -static HTREEITEM InsertTreeViewItem(IShellFolder * lpsf, LPCITEMIDLIST pidl, - LPCITEMIDLIST pidlParent, IEnumIDList* pEnumIL, HTREEITEM hParent) +static HTREEITEM InsertTreeViewItem( browse_info *info, IShellFolder * lpsf, + LPCITEMIDLIST pidl, LPCITEMIDLIST pidlParent, IEnumIDList* pEnumIL, + HTREEITEM hParent) { TVITEMW tvi; TVINSERTSTRUCTW tvins; @@ -244,7 +269,8 @@ static HTREEITEM InsertTreeViewItem(IShellFolder * lpsf, LPCITEMIDLIST pidl, tvi.cChildren= pEnumIL ? 1 : 0; tvi.mask |= TVIF_CHILDREN; - if (!(lptvid = (LPTV_ITEMDATA)SHAlloc(sizeof(TV_ITEMDATA)))) + lptvid = SHAlloc( sizeof(TV_ITEMDATA) ); + if (!lptvid) return NULL; if (!GetName(lpsf, pidl, SHGDN_NORMAL, szBuff)) @@ -265,7 +291,7 @@ static HTREEITEM InsertTreeViewItem(IShellFolder * lpsf, LPCITEMIDLIST pidl, tvins.hInsertAfter = NULL; 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 * * PARAMS + * info [I] data for the dialog * lpsf [I] IShellFolder interface of the parent shell folder * pidl [I] ITEMIDLIST of 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 */ -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; LPITEMIDLIST pidlTemp = 0; ULONG ulFetched; HRESULT hr; - HWND hwnd=GetParent(hwndTreeView); + HWND hwnd = GetParent( info->hwndTreeView ); TRACE("%p %p %x %p\n",lpsf, pidl, (INT)hParent, lpe); /* No IEnumIDList -> No children */ if (!lpe) return; - SetCapture(GetParent(hwndTreeView)); - SetCursor(LoadCursorA(0, (LPSTR)IDC_WAIT)); + SetCapture( hwnd ); + SetCursor( LoadCursorA( 0, (LPSTR)IDC_WAIT ) ); 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); 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 ((IEnumIDList_Skip(pEnumIL, 1) != S_OK) || FAILED(IEnumIDList_Reset(pEnumIL))) + if ((IEnumIDList_Skip(pEnumIL, 1) != S_OK) || + FAILED(IEnumIDList_Reset(pEnumIL))) { IEnumIDList_Release(pEnumIL); pEnumIL = NULL; @@ -320,13 +350,13 @@ static void FillTreeView(IShellFolder * lpsf, LPITEMIDLIST pidl, HTREEITEM hPar } } - if (!(hPrev = InsertTreeViewItem(lpsf, pidlTemp, pidl, pEnumIL, hParent))) - goto Done; + if (!(hPrev = InsertTreeViewItem(info, lpsf, pidlTemp, pidl, pEnumIL, hParent))) + goto done; SHFree(pidlTemp); /* Finally, free the pidl that the shell gave us... */ pidlTemp=NULL; } -Done: +done: ReleaseCapture(); SetCursor(LoadCursorW(0, (LPWSTR)IDC_ARROW)); @@ -342,8 +372,9 @@ static inline BOOL PIDLIsType(LPCITEMIDLIST pidl, PIDLTYPE 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; BOOL bEnabled = TRUE; DWORD dwAttributes; @@ -368,10 +399,10 @@ static void BrsFolder_CheckValidSelection(HWND hWndTree, LPTV_ITEMDATA lptvid) if (FAILED(r) || (dwAttributes != (SFGAO_FOLDER | SFGAO_FILESYSTEM))) 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; @@ -386,7 +417,7 @@ static LRESULT BrsFolder_Treeview_Delete( NMTREEVIEWW *pnmtv ) return 0; } -static LRESULT BrsFolder_Treeview_Expand( NMTREEVIEWW *pnmtv ) +static LRESULT BrsFolder_Treeview_Expand( browse_info *info, NMTREEVIEWW *pnmtv ) { IShellFolder *lpsf2 = NULL; 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, (REFIID)&IID_IShellFolder, (LPVOID *)&lpsf2 ); 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 * sort will only mess things up */ if (!_ILIsMyComputer(lptvid->lpi)) - TreeView_SortChildren(hwndTreeView, pnmtv->itemNew.hItem, FALSE); + TreeView_SortChildren(info->hwndTreeView, pnmtv->itemNew.hItem, FALSE); 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; lptvid = (LPTV_ITEMDATA) pnmtv->itemNew.lParam; - pidlRet = lptvid->lpifq; - if (lpBrowseInfo->lpfn) - (lpBrowseInfo->lpfn)(hWnd, BFFM_SELCHANGED, (LPARAM)pidlRet, lpBrowseInfo->lParam); - BrsFolder_CheckValidSelection(hWnd, lptvid); + info->pidlRet = lptvid->lpifq; + browsefolder_callback( info->lpBrowseInfo, info->hWnd, BFFM_SELCHANGED, + (LPARAM)info->pidlRet ); + BrsFolder_CheckValidSelection( info, lptvid ); 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; - 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) return 0; @@ -435,15 +466,15 @@ static LRESULT BrsFolder_OnNotify( HWND hWnd, UINT CtlID, LPNMHDR lpnmh ) { case TVN_DELETEITEMA: case TVN_DELETEITEMW: - return BrsFolder_Treeview_Delete( pnmtv ); + return BrsFolder_Treeview_Delete( info, pnmtv ); case TVN_ITEMEXPANDINGA: case TVN_ITEMEXPANDINGW: - return BrsFolder_Treeview_Expand( pnmtv ); + return BrsFolder_Treeview_Expand( info, pnmtv ); case TVN_SELCHANGEDA: case TVN_SELCHANGEDW: - return BrsFolder_Treeview_Changed( hWnd, pnmtv ); + return BrsFolder_Treeview_Changed( info, pnmtv ); default: 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; - lpBrowseInfo = lpbi; + LPBROWSEINFOW lpBrowseInfo = info->lpBrowseInfo; + + info->hWnd = hWnd; + SetPropW( hWnd, szBrowseFolderInfo, info ); if (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)) 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) - (lpBrowseInfo->lpfn)( hWnd, BFFM_INITIALIZED, 0, lpBrowseInfo->lParam ); + browsefolder_callback( info->lpBrowseInfo, hWnd, BFFM_INITIALIZED, 0 ); 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) { case IDOK: - pdump( pidlRet ); + pdump( info->pidlRet ); if (lpBrowseInfo->pszDisplayName) - SHGetPathFromIDListW( pidlRet, lpBrowseInfo->pszDisplayName ); - EndDialog(hWnd, (DWORD) ILClone(pidlRet)); + SHGetPathFromIDListW( info->pidlRet, lpBrowseInfo->pszDisplayName ); + EndDialog( info->hWnd, 1 ); return TRUE; case IDCANCEL: - EndDialog(hWnd, 0); + EndDialog( info->hWnd, 0 ); return TRUE; } 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, LPARAM lParam ) { + browse_info *info; + TRACE("hwnd=%p msg=%04x 0x%08x 0x%08lx\n", hWnd, msg, wParam, lParam ); 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) { case WM_NOTIFY: - return BrsFolder_OnNotify( hWnd, (UINT)wParam, (LPNMHDR)lParam); + return BrsFolder_OnNotify( info, (UINT)wParam, (LPNMHDR)lParam); case WM_COMMAND: - return BrsFolder_OnCommand( hWnd, wParam ); + return BrsFolder_OnCommand( info, wParam ); case BFFM_SETSTATUSTEXTA: 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; } -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}; /************************************************************************* @@ -568,66 +610,71 @@ static const WCHAR swBrowseTempName[] = { */ LPITEMIDLIST WINAPI SHBrowseForFolderA (LPBROWSEINFOA lpbi) { - BROWSEINFOW bi; - LPITEMIDLIST lpid; - INT len; - - TRACE("(%p{lpszTitle=%s,owner=%p})\n", lpbi, - lpbi ? debugstr_a(lpbi->lpszTitle) : NULL, lpbi ? lpbi->hwndOwner : NULL); + BROWSEINFOW bi; + LPITEMIDLIST lpid; + INT len; + + TRACE("%p\n", lpbi); - if (!lpbi) - return NULL; + bi.hwndOwner = lpbi->hwndOwner; + 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; - bi.pidlRoot = lpbi->pidlRoot; - if (lpbi->pszDisplayName) - { - /*lpbi->pszDisplayName is assumed to be MAX_PATH (MSDN) */ - bi.pszDisplayName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, lpbi->pszDisplayName, -1, bi.pszDisplayName, MAX_PATH); - } - else - bi.pszDisplayName = NULL; + if (lpbi->lpszTitle) + { + len = MultiByteToWideChar( CP_ACP, 0, lpbi->lpszTitle, -1, NULL, 0 ); + bi.lpszTitle = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, lpbi->lpszTitle, -1, (LPWSTR)bi.lpszTitle, len ); + } + else + bi.lpszTitle = NULL; - if (lpbi->lpszTitle) - { - len = MultiByteToWideChar(CP_ACP, 0, lpbi->lpszTitle, -1, NULL, 0); - bi.lpszTitle = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, lpbi->lpszTitle, -1, (LPWSTR)bi.lpszTitle, len); - } - else - bi.lpszTitle = NULL; - - bi.ulFlags = lpbi->ulFlags; - bi.lpfn = lpbi->lpfn; - bi.lParam = lpbi->lParam; - bi.iImage = lpbi->iImage; - lpid = (LPITEMIDLIST) DialogBoxParamW(shell32_hInstance, - 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; + bi.ulFlags = lpbi->ulFlags; + bi.lpfn = lpbi->lpfn; + bi.lParam = lpbi->lParam; + bi.iImage = lpbi->iImage; + lpid = SHBrowseForFolderW( &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.@] + * + * NOTES: + * crashes when passed a null pointer */ LPITEMIDLIST WINAPI SHBrowseForFolderW (LPBROWSEINFOW lpbi) { - TRACE("((%p->{lpszTitle=%s,owner=%p})\n", lpbi, - lpbi ? debugstr_w(lpbi->lpszTitle) : NULL, lpbi ? lpbi->hwndOwner : 0); + browse_info info; + DWORD r; - if (!lpbi) - return NULL; + ERR("%p\n", lpbi); - return (LPITEMIDLIST) DialogBoxParamW(shell32_hInstance, - swBrowseTempName, lpbi->hwndOwner, - BrsFolderDlgProc, (INT)lpbi); + info.hWnd = 0; + info.pidlRet = NULL; + info.lpBrowseInfo = lpbi; + info.hwndTreeView = NULL; + + r = DialogBoxParamW( shell32_hInstance, swBrowseTemplateName, lpbi->hwndOwner, + BrsFolderDlgProc, (LPARAM)&info ); + if (!r) + return NULL; + + return info.pidlRet; }