ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

brsfolder.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 1999 Juergen Schmied
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00017  *
00018  * FIXME:
00019  *  - many memory leaks
00020  *  - many flags unimplemented
00021  *    - implement new dialog style "make new folder" button
00022  *    - implement editbox
00023  *    - implement new dialog style resizing
00024  */
00025 
00026 #include <precomp.h>
00027 
00028 
00029 WINE_DEFAULT_DEBUG_CHANNEL(shell);
00030 
00031 /* original margins and control size */
00032 typedef struct tagLAYOUT_DATA
00033 {
00034     LONG left, width, right;
00035     LONG top, height, bottom;
00036 } LAYOUT_DATA;
00037 
00038 typedef struct tagbrowse_info
00039 {
00040     HWND          hWnd;
00041     HWND          hwndTreeView;
00042     LPBROWSEINFOW lpBrowseInfo;
00043     LPITEMIDLIST  pidlRet;
00044     LAYOUT_DATA  *layout;  /* filled by LayoutInit, used by LayoutUpdate */
00045     SIZE          szMin;
00046 } browse_info;
00047 
00048 typedef struct tagTV_ITEMDATA
00049 {
00050    LPSHELLFOLDER lpsfParent; /* IShellFolder of the parent */
00051    LPITEMIDLIST  lpi;        /* PIDL relative to parent */
00052    LPITEMIDLIST  lpifq;      /* Fully qualified PIDL */
00053    IEnumIDList*  pEnumIL;    /* Children iterator */
00054 } TV_ITEMDATA, *LPTV_ITEMDATA;
00055 
00056 typedef struct tagLAYOUT_INFO
00057 {
00058     int iItemId;          /* control id */
00059     DWORD dwAnchor;       /* BF_* flags specifying which margins should remain constant */
00060 } LAYOUT_INFO;
00061 
00062 static const LAYOUT_INFO g_layout_info[] =
00063 {
00064     {IDC_BROWSE_FOR_FOLDER_TITLE,         BF_TOP|BF_LEFT|BF_RIGHT},
00065     {IDC_BROWSE_FOR_FOLDER_STATUS,        BF_TOP|BF_LEFT|BF_RIGHT},
00066     {IDC_BROWSE_FOR_FOLDER_FOLDER,        BF_TOP|BF_LEFT|BF_RIGHT},
00067     {IDC_BROWSE_FOR_FOLDER_TREEVIEW,      BF_TOP|BF_BOTTOM|BF_LEFT|BF_RIGHT},
00068     {IDC_BROWSE_FOR_FOLDER_FOLDER,        BF_BOTTOM|BF_LEFT},
00069     {IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT,    BF_BOTTOM|BF_LEFT|BF_RIGHT},
00070     {IDC_BROWSE_FOR_FOLDER_NEW_FOLDER, BF_BOTTOM|BF_LEFT},
00071     {IDOK,              BF_BOTTOM|BF_RIGHT},
00072     {IDCANCEL,          BF_BOTTOM|BF_RIGHT}
00073 };
00074 
00075 #define LAYOUT_INFO_COUNT (sizeof(g_layout_info)/sizeof(g_layout_info[0]))
00076 
00077 #define SUPPORTEDFLAGS (BIF_STATUSTEXT | \
00078                         BIF_BROWSEFORCOMPUTER | \
00079                         BIF_RETURNFSANCESTORS | \
00080                         BIF_RETURNONLYFSDIRS | \
00081                         BIF_NONEWFOLDERBUTTON | \
00082                         BIF_NEWDIALOGSTYLE | \
00083                         BIF_BROWSEINCLUDEFILES)
00084 
00085 static void FillTreeView(browse_info*, LPSHELLFOLDER,
00086                LPITEMIDLIST, HTREEITEM, IEnumIDList*);
00087 static HTREEITEM InsertTreeViewItem( browse_info*, IShellFolder *,
00088                LPCITEMIDLIST, LPCITEMIDLIST, IEnumIDList*, HTREEITEM);
00089 
00090 static const WCHAR szBrowseFolderInfo[] = L"__WINE_BRSFOLDERDLG_INFO";
00091 
00092 static DWORD __inline BrowseFlagsToSHCONTF(UINT ulFlags)
00093 {
00094     return SHCONTF_FOLDERS | (ulFlags & BIF_BROWSEINCLUDEFILES ? SHCONTF_NONFOLDERS : 0);
00095 }
00096 
00097 static void browsefolder_callback( LPBROWSEINFOW lpBrowseInfo, HWND hWnd,
00098                                    UINT msg, LPARAM param )
00099 {
00100     if (!lpBrowseInfo->lpfn)
00101         return;
00102     lpBrowseInfo->lpfn( hWnd, msg, param, lpBrowseInfo->lParam );
00103 }
00104 
00105 static LAYOUT_DATA *LayoutInit(HWND hwnd, const LAYOUT_INFO *layout_info, int layout_count)
00106 {
00107     LAYOUT_DATA *data;
00108     RECT rcWnd;
00109     int i;
00110 
00111     GetClientRect(hwnd, &rcWnd);
00112     data = (LAYOUT_DATA *)SHAlloc(sizeof(LAYOUT_DATA)*layout_count);
00113     for (i = 0; i < layout_count; i++)
00114     {
00115         RECT r;
00116         HWND hItem = GetDlgItem(hwnd, layout_info[i].iItemId);
00117 
00118         if (hItem == NULL)
00119             ERR("Item %d not found\n", i);
00120         GetWindowRect(hItem, &r);
00121         MapWindowPoints(HWND_DESKTOP, hwnd, (LPPOINT)&r, 2);
00122 
00123         data[i].left = r.left;
00124         data[i].right = rcWnd.right - r.right;
00125         data[i].width = r.right - r.left;
00126 
00127         data[i].top = r.top;
00128         data[i].bottom = rcWnd.bottom - r.bottom;
00129         data[i].height = r.bottom - r.top;
00130     }
00131     return data;
00132 }
00133 
00134 static void LayoutUpdate(HWND hwnd, LAYOUT_DATA *data, const LAYOUT_INFO *layout_info, int layout_count)
00135 {
00136     RECT rcWnd;
00137     int i;
00138 
00139     GetClientRect(hwnd, &rcWnd);
00140     for (i = 0; i < layout_count; i++)
00141     {
00142         RECT r;
00143         HWND hItem = GetDlgItem(hwnd, layout_info[i].iItemId);
00144 
00145         GetWindowRect(hItem, &r);
00146         MapWindowPoints(HWND_DESKTOP, hwnd, (LPPOINT)&r, 2);
00147 
00148         if (layout_info[i].dwAnchor & BF_RIGHT)
00149         {
00150             r.right = rcWnd.right - data[i].right;
00151             if (!(layout_info[i].dwAnchor & BF_LEFT))
00152                 r.left = r.right - data[i].width;
00153         }
00154 
00155         if (layout_info[i].dwAnchor & BF_BOTTOM)
00156         {
00157             r.bottom = rcWnd.bottom - data[i].bottom;
00158             if (!(layout_info[i].dwAnchor & BF_TOP))
00159                 r.top = r.bottom - data[i].height;
00160         }
00161 
00162         SetWindowPos(hItem, NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER);
00163     }
00164 }
00165 
00166 
00167 /******************************************************************************
00168  * InitializeTreeView [Internal]
00169  *
00170  * Called from WM_INITDIALOG handler.
00171  *
00172  * PARAMS
00173  *  hwndParent [I] The BrowseForFolder dialog
00174  *  root       [I] ITEMIDLIST of the root shell folder
00175  */
00176 static void InitializeTreeView( browse_info *info )
00177 {
00178     LPITEMIDLIST pidlParent, pidlChild;
00179     HIMAGELIST hImageList;
00180     HRESULT hr;
00181     IShellFolder *lpsfParent, *lpsfRoot;
00182     IEnumIDList * pEnumChildren = NULL;
00183     HTREEITEM item;
00184     DWORD flags;
00185     LPCITEMIDLIST root = info->lpBrowseInfo->pidlRoot;
00186 
00187     TRACE("%p\n", info );
00188 
00189     Shell_GetImageLists(NULL, &hImageList);
00190 
00191     if (hImageList)
00192         SendMessageW( info->hwndTreeView, TVM_SETIMAGELIST, 0, (LPARAM)hImageList );
00193 
00194     /* We want to call InsertTreeViewItem down the code, in order to insert
00195      * the root item of the treeview. Due to InsertTreeViewItem's signature,
00196      * we need the following to do this:
00197      *
00198      * + An ITEMIDLIST corresponding to _the parent_ of root.
00199      * + An ITEMIDLIST, which is a relative path from root's parent to root
00200      *   (containing a single SHITEMID).
00201      * + An IShellFolder interface pointer of root's parent folder.
00202      *
00203      * If root is 'Desktop', then root's parent is also 'Desktop'.
00204      */
00205 
00206     pidlParent = ILClone(root);
00207     ILRemoveLastID(pidlParent);
00208     pidlChild = ILClone(ILFindLastID(root));
00209 
00210     if (_ILIsDesktop(pidlParent)) {
00211         hr = SHGetDesktopFolder(&lpsfParent);
00212     } else {
00213         IShellFolder *lpsfDesktop;
00214         hr = SHGetDesktopFolder(&lpsfDesktop);
00215         if (FAILED(hr)) {
00216             WARN("SHGetDesktopFolder failed! hr = %08x\n", hr);
00217             ILFree(pidlChild);
00218             ILFree(pidlParent);
00219             return;
00220         }
00221         hr = lpsfDesktop->BindToObject(pidlParent, 0, IID_IShellFolder, (LPVOID *)&lpsfParent);
00222         lpsfDesktop->Release();
00223     }
00224 
00225     if (FAILED(hr)) {
00226         WARN("Could not bind to parent shell folder! hr = %08x\n", hr);
00227         ILFree(pidlChild);
00228         ILFree(pidlParent);
00229         return;
00230     }
00231 
00232     if (pidlChild && pidlChild->mkid.cb) {
00233         hr = lpsfParent->BindToObject(pidlChild, 0, IID_IShellFolder, (LPVOID *)&lpsfRoot);
00234     } else {
00235         lpsfRoot = lpsfParent;
00236         hr = lpsfParent->AddRef();
00237     }
00238 
00239     if (FAILED(hr)) {
00240         WARN("Could not bind to root shell folder! hr = %08x\n", hr);
00241         lpsfParent->Release();
00242         ILFree(pidlChild);
00243         ILFree(pidlParent);
00244         return;
00245     }
00246 
00247     flags = BrowseFlagsToSHCONTF( info->lpBrowseInfo->ulFlags );
00248     hr = lpsfRoot->EnumObjects(info->hWnd, flags, &pEnumChildren );
00249     if (FAILED(hr)) {
00250         WARN("Could not get child iterator! hr = %08x\n", hr);
00251         lpsfParent->Release();
00252         lpsfRoot->Release();
00253         ILFree(pidlChild);
00254         ILFree(pidlParent);
00255         return;
00256     }
00257 
00258     SendMessageW( info->hwndTreeView, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT );
00259     item = InsertTreeViewItem( info, lpsfParent, pidlChild,
00260                                pidlParent, pEnumChildren, TVI_ROOT );
00261     SendMessageW( info->hwndTreeView, TVM_EXPAND, TVE_EXPAND, (LPARAM)item );
00262 
00263     ILFree(pidlChild);
00264     ILFree(pidlParent);
00265     lpsfRoot->Release();
00266     lpsfParent->Release();
00267 }
00268 
00269 static int GetIcon(LPCITEMIDLIST lpi, UINT uFlags)
00270 {
00271     SHFILEINFOW sfi;
00272     SHGetFileInfoW((LPCWSTR)lpi, 0 ,&sfi, sizeof(SHFILEINFOW), uFlags);
00273     return sfi.iIcon;
00274 }
00275 
00276 static void GetNormalAndSelectedIcons(LPITEMIDLIST lpifq, LPTVITEMW lpTV_ITEM)
00277 {
00278     LPITEMIDLIST pidlDesktop = NULL;
00279     DWORD flags;
00280 
00281     TRACE("%p %p\n",lpifq, lpTV_ITEM);
00282 
00283     if (!lpifq)
00284     {
00285         pidlDesktop = _ILCreateDesktop();
00286         lpifq = pidlDesktop;
00287     }
00288 
00289     flags = SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON;
00290     lpTV_ITEM->iImage = GetIcon( lpifq, flags );
00291 
00292     flags = SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON;
00293     lpTV_ITEM->iSelectedImage = GetIcon( lpifq, flags );
00294 
00295     if (pidlDesktop)
00296         ILFree( pidlDesktop );
00297 }
00298 
00299 /******************************************************************************
00300  * GetName [Internal]
00301  *
00302  * Query a shell folder for the display name of one of it's children
00303  *
00304  * PARAMS
00305  *  lpsf           [I] IShellFolder interface of the folder to be queried.
00306  *  lpi            [I] ITEMIDLIST of the child, relative to parent
00307  *  dwFlags        [I] as in IShellFolder::GetDisplayNameOf
00308  *  lpFriendlyName [O] The desired display name in unicode
00309  *
00310  * RETURNS
00311  *  Success: TRUE
00312  *  Failure: FALSE
00313  */
00314 static BOOL GetName(LPSHELLFOLDER lpsf, LPCITEMIDLIST lpi, DWORD dwFlags, LPWSTR lpFriendlyName)
00315 {
00316     BOOL   bSuccess=TRUE;
00317     STRRET str;
00318 
00319     TRACE("%p %p %x %p\n", lpsf, lpi, dwFlags, lpFriendlyName);
00320     if (SUCCEEDED(lpsf->GetDisplayNameOf(lpi, dwFlags, &str)))
00321           bSuccess = StrRetToStrNW(lpFriendlyName, MAX_PATH, &str, lpi);
00322     else
00323       bSuccess = FALSE;
00324 
00325     TRACE("-- %s\n", debugstr_w(lpFriendlyName));
00326     return bSuccess;
00327 }
00328 
00329 /******************************************************************************
00330  * InsertTreeViewItem [Internal]
00331  *
00332  * PARAMS
00333  *  info       [I] data for the dialog
00334  *  lpsf       [I] IShellFolder interface of the item's parent shell folder
00335  *  pidl       [I] ITEMIDLIST of the child to insert, relative to parent
00336  *  pidlParent [I] ITEMIDLIST of the parent shell folder
00337  *  pEnumIL    [I] Iterator for the children of the item to be inserted
00338  *  hParent    [I] The treeview-item that represents the parent shell folder
00339  *
00340  * RETURNS
00341  *  Success: Handle to the created and inserted treeview-item
00342  *  Failure: NULL
00343  */
00344 static HTREEITEM InsertTreeViewItem( browse_info *info, IShellFolder * lpsf,
00345     LPCITEMIDLIST pidl, LPCITEMIDLIST pidlParent, IEnumIDList* pEnumIL,
00346     HTREEITEM hParent)
00347 {
00348     TVITEMW     tvi;
00349     TVINSERTSTRUCTW    tvins;
00350     WCHAR        szBuff[MAX_PATH];
00351     LPTV_ITEMDATA    lptvid=0;
00352 
00353     tvi.mask  = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
00354 
00355     tvi.cChildren= pEnumIL ? 1 : 0;
00356     tvi.mask |= TVIF_CHILDREN;
00357 
00358     lptvid = (TV_ITEMDATA *)SHAlloc( sizeof(TV_ITEMDATA) );
00359     if (!lptvid)
00360         return NULL;
00361 
00362     if (!GetName(lpsf, pidl, SHGDN_NORMAL, szBuff))
00363         return NULL;
00364 
00365     tvi.pszText    = szBuff;
00366     tvi.cchTextMax = MAX_PATH;
00367     tvi.lParam = (LPARAM)lptvid;
00368 
00369     lpsf->AddRef();
00370     lptvid->lpsfParent = lpsf;
00371     lptvid->lpi    = ILClone(pidl);
00372     lptvid->lpifq    = pidlParent ? ILCombine(pidlParent, pidl) : ILClone(pidl);
00373     lptvid->pEnumIL = pEnumIL;
00374     GetNormalAndSelectedIcons(lptvid->lpifq, &tvi);
00375 
00376     tvins.item         = tvi;
00377     tvins.hInsertAfter = NULL;
00378     tvins.hParent      = hParent;
00379 
00380     return TreeView_InsertItem( info->hwndTreeView, &tvins );
00381 }
00382 
00383 /******************************************************************************
00384  * FillTreeView [Internal]
00385  *
00386  * For each child (given by lpe) of the parent shell folder, which is given by
00387  * lpsf and whose PIDL is pidl, insert a treeview-item right under hParent
00388  *
00389  * PARAMS
00390  *  info    [I] data for the dialog
00391  *  lpsf    [I] IShellFolder interface of the parent shell folder
00392  *  pidl    [I] ITEMIDLIST of the parent shell folder
00393  *  hParent [I] The treeview item that represents the parent shell folder
00394  *  lpe     [I] An iterator for the children of the parent shell folder
00395  */
00396 static void FillTreeView( browse_info *info, IShellFolder * lpsf,
00397                  LPITEMIDLIST  pidl, HTREEITEM hParent, IEnumIDList* lpe)
00398 {
00399     LPITEMIDLIST    pidlTemp = 0;
00400     ULONG        ulFetched;
00401     HRESULT        hr;
00402     HWND        hwnd = GetParent( info->hwndTreeView );
00403 
00404     TRACE("%p %p %p %p\n",lpsf, pidl, hParent, lpe);
00405 
00406     /* No IEnumIDList -> No children */
00407     if (!lpe) return;
00408 
00409     SetCapture( hwnd );
00410     SetCursor( LoadCursorA( 0, (LPSTR)IDC_WAIT ) );
00411 
00412     while (S_OK == lpe->Next(1,&pidlTemp,&ulFetched))
00413     {
00414         ULONG ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER;
00415         IEnumIDList* pEnumIL = NULL;
00416         IShellFolder* pSFChild = NULL;
00417         lpsf->GetAttributesOf(1, (LPCITEMIDLIST*)&pidlTemp, &ulAttrs);
00418         if (ulAttrs & SFGAO_FOLDER)
00419         {
00420             hr = lpsf->BindToObject(pidlTemp, NULL, IID_IShellFolder, (LPVOID *)&pSFChild);
00421             if (SUCCEEDED(hr))
00422                 {
00423                 DWORD flags = BrowseFlagsToSHCONTF(info->lpBrowseInfo->ulFlags);
00424                 hr = pSFChild->EnumObjects(hwnd, flags, &pEnumIL);
00425                     if (hr == S_OK)
00426                     {
00427                         if ((pEnumIL->Skip(1) != S_OK) ||
00428                              FAILED(pEnumIL->Reset()))
00429                         {
00430                             pEnumIL->Release();
00431                             pEnumIL = NULL;
00432                         }
00433                     }
00434                     pSFChild->Release();
00435                 }
00436         }
00437 
00438         if (!InsertTreeViewItem(info, lpsf, pidlTemp, pidl, pEnumIL, hParent))
00439             goto done;
00440         SHFree(pidlTemp);  /* Finally, free the pidl that the shell gave us... */
00441         pidlTemp=NULL;
00442     }
00443 
00444 done:
00445     ReleaseCapture();
00446     SetCursor(LoadCursorW(0, (LPWSTR)IDC_ARROW));
00447     SHFree(pidlTemp);
00448 }
00449 
00450 static BOOL __inline PIDLIsType(LPCITEMIDLIST pidl, PIDLTYPE type)
00451 {
00452     LPPIDLDATA data = _ILGetDataPointer(pidl);
00453     if (!data)
00454         return FALSE;
00455     return (data->type == type);
00456 }
00457 
00458 static void BrsFolder_CheckValidSelection( browse_info *info, LPTV_ITEMDATA lptvid )
00459 {
00460     LPBROWSEINFOW lpBrowseInfo = info->lpBrowseInfo;
00461     LPCITEMIDLIST pidl = lptvid->lpi;
00462     BOOL bEnabled = TRUE;
00463     DWORD dwAttributes;
00464     HRESULT r;
00465 
00466     if ((lpBrowseInfo->ulFlags & BIF_BROWSEFORCOMPUTER) &&
00467         !PIDLIsType(pidl, PT_COMP))
00468         bEnabled = FALSE;
00469     if (lpBrowseInfo->ulFlags & BIF_RETURNFSANCESTORS)
00470     {
00471         dwAttributes = SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM;
00472         r = lptvid->lpsfParent->GetAttributesOf(1,
00473                                 (LPCITEMIDLIST*)&lptvid->lpi, &dwAttributes);
00474         if (FAILED(r) || !(dwAttributes & (SFGAO_FILESYSANCESTOR|SFGAO_FILESYSTEM)))
00475             bEnabled = FALSE;
00476     }
00477 
00478     dwAttributes = SFGAO_FOLDER | SFGAO_FILESYSTEM;
00479     r = lptvid->lpsfParent->GetAttributesOf(1,
00480                                             (LPCITEMIDLIST*)&lptvid->lpi,
00481                                             &dwAttributes);
00482     if (FAILED(r) ||
00483         ((dwAttributes & (SFGAO_FOLDER|SFGAO_FILESYSTEM)) != (SFGAO_FOLDER|SFGAO_FILESYSTEM)))
00484     {
00485         if (lpBrowseInfo->ulFlags & BIF_RETURNONLYFSDIRS)
00486             bEnabled = FALSE;
00487         EnableWindow(GetDlgItem(info->hWnd, IDC_BROWSE_FOR_FOLDER_NEW_FOLDER), FALSE);
00488     }
00489     else
00490         EnableWindow(GetDlgItem(info->hWnd, IDC_BROWSE_FOR_FOLDER_NEW_FOLDER), TRUE);
00491 
00492     SendMessageW(info->hWnd, BFFM_ENABLEOK, 0, bEnabled);
00493 }
00494 
00495 static LRESULT BrsFolder_Treeview_Delete( browse_info *info, NMTREEVIEWW *pnmtv )
00496 {
00497     LPTV_ITEMDATA lptvid = (LPTV_ITEMDATA)pnmtv->itemOld.lParam;
00498 
00499     TRACE("TVN_DELETEITEMA/W %p\n", lptvid);
00500 
00501     lptvid->lpsfParent->Release();
00502     if (lptvid->pEnumIL)
00503         lptvid->pEnumIL->Release();
00504     SHFree(lptvid->lpi);
00505     SHFree(lptvid->lpifq);
00506     SHFree(lptvid);
00507     return 0;
00508 }
00509 
00510 static LRESULT BrsFolder_Treeview_Expand( browse_info *info, NMTREEVIEWW *pnmtv )
00511 {
00512     IShellFolder *lpsf2 = NULL;
00513     LPTV_ITEMDATA lptvid = (LPTV_ITEMDATA) pnmtv->itemNew.lParam;
00514     HRESULT r;
00515 
00516     TRACE("TVN_ITEMEXPANDINGA/W\n");
00517 
00518     if ((pnmtv->itemNew.state & TVIS_EXPANDEDONCE))
00519         return 0;
00520 
00521     if (lptvid->lpi && lptvid->lpi->mkid.cb) {
00522         r = lptvid->lpsfParent->BindToObject(lptvid->lpi, 0,
00523                                       IID_IShellFolder, (LPVOID *)&lpsf2 );
00524     } else {
00525         lpsf2 = lptvid->lpsfParent;
00526         r = lpsf2->AddRef();
00527     }
00528 
00529     if (SUCCEEDED(r))
00530     {
00531         FillTreeView( info, lpsf2, lptvid->lpifq, pnmtv->itemNew.hItem, lptvid->pEnumIL);
00532         lpsf2->Release();
00533     }
00534 
00535     /* My Computer is already sorted and trying to do a simple text
00536      * sort will only mess things up */
00537     if (!_ILIsMyComputer(lptvid->lpi))
00538         SendMessageW( info->hwndTreeView, TVM_SORTCHILDREN,
00539                       FALSE, (LPARAM)pnmtv->itemNew.hItem );
00540 
00541     return 0;
00542 }
00543 
00544 static HRESULT BrsFolder_Treeview_Changed( browse_info *info, NMTREEVIEWW *pnmtv )
00545 {
00546     LPTV_ITEMDATA lptvid = (LPTV_ITEMDATA) pnmtv->itemNew.lParam;
00547     WCHAR name[MAX_PATH];
00548 
00549     ILFree(info->pidlRet);
00550     info->pidlRet = ILClone(lptvid->lpifq);
00551 
00552     if (GetName(lptvid->lpsfParent, lptvid->lpi, SHGDN_NORMAL, name))
00553             SetWindowTextW( GetDlgItem(info->hWnd, IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT), name );
00554 
00555     browsefolder_callback( info->lpBrowseInfo, info->hWnd, BFFM_SELCHANGED,
00556                            (LPARAM)info->pidlRet );
00557     BrsFolder_CheckValidSelection( info, lptvid );
00558     return 0;
00559 }
00560 
00561 static LRESULT BrsFolder_Treeview_Rename(browse_info *info, NMTVDISPINFOW *pnmtv)
00562 {
00563     LPTV_ITEMDATA item_data;
00564     WCHAR old_path[MAX_PATH], new_path[MAX_PATH], *p;
00565     NMTREEVIEWW nmtv;
00566     TVITEMW item;
00567 
00568     if(!pnmtv->item.pszText)
00569         return 0;
00570 
00571     item.mask = TVIF_HANDLE|TVIF_PARAM;
00572     item.hItem = (HTREEITEM)SendMessageW(info->hwndTreeView, TVM_GETNEXTITEM, TVGN_CARET, 0);
00573     SendMessageW(info->hwndTreeView, TVM_GETITEMW, 0, (LPARAM)&item);
00574     item_data = (LPTV_ITEMDATA)item.lParam;
00575 
00576     SHGetPathFromIDListW(item_data->lpifq, old_path);
00577     if(!(p = strrchrW(old_path, '\\')))
00578         return 0;
00579     p = new_path+(p-old_path+1);
00580     memcpy(new_path, old_path, (p-new_path)*sizeof(WCHAR));
00581     strcpyW(p, pnmtv->item.pszText);
00582 
00583     if(!MoveFileW(old_path, new_path))
00584         return 0;
00585 
00586     SHFree(item_data->lpifq);
00587     SHFree(item_data->lpi);
00588     item_data->lpifq = SHSimpleIDListFromPathW(new_path);
00589     item_data->lpsfParent->ParseDisplayName(NULL, NULL, pnmtv->item.pszText,
00590                                             NULL, &item_data->lpi, NULL);
00591 
00592     item.mask = TVIF_HANDLE|TVIF_TEXT;
00593     item.pszText = pnmtv->item.pszText;
00594     SendMessageW(info->hwndTreeView, TVM_SETITEMW, 0, (LPARAM)&item);
00595 
00596     nmtv.itemNew.lParam = item.lParam;
00597     BrsFolder_Treeview_Changed(info, &nmtv);
00598     return 0;
00599 }
00600 
00601 static LRESULT BrsFolder_OnNotify( browse_info *info, UINT CtlID, LPNMHDR lpnmh )
00602 {
00603     NMTREEVIEWW *pnmtv = (NMTREEVIEWW *)lpnmh;
00604 
00605     TRACE("%p %x %p msg=%x\n", info, CtlID, lpnmh, pnmtv->hdr.code);
00606 
00607     if (pnmtv->hdr.idFrom != IDC_BROWSE_FOR_FOLDER_TREEVIEW)
00608         return 0;
00609 
00610     switch (pnmtv->hdr.code)
00611     {
00612     case TVN_DELETEITEMA:
00613     case TVN_DELETEITEMW:
00614         return BrsFolder_Treeview_Delete( info, pnmtv );
00615 
00616     case TVN_ITEMEXPANDINGA:
00617     case TVN_ITEMEXPANDINGW:
00618         return BrsFolder_Treeview_Expand( info, pnmtv );
00619 
00620     case TVN_SELCHANGEDA:
00621     case TVN_SELCHANGEDW:
00622         return BrsFolder_Treeview_Changed( info, pnmtv );
00623 
00624     case TVN_ENDLABELEDITA:
00625     case TVN_ENDLABELEDITW:
00626         return BrsFolder_Treeview_Rename( info, (LPNMTVDISPINFOW)pnmtv );
00627 
00628     default:
00629         WARN("unhandled (%d)\n", pnmtv->hdr.code);
00630         break;
00631     }
00632 
00633     return 0;
00634 }
00635 
00636 
00637 static BOOL BrsFolder_OnCreate( HWND hWnd, browse_info *info )
00638 {
00639     LPBROWSEINFOW lpBrowseInfo = info->lpBrowseInfo;
00640 
00641     info->hWnd = hWnd;
00642     SetPropW( hWnd, szBrowseFolderInfo, info );
00643 
00644     if (lpBrowseInfo->ulFlags & BIF_NEWDIALOGSTYLE)
00645         FIXME("flags BIF_NEWDIALOGSTYLE partially implemented\n");
00646     if (lpBrowseInfo->ulFlags & ~SUPPORTEDFLAGS)
00647     FIXME("flags %x not implemented\n", lpBrowseInfo->ulFlags & ~SUPPORTEDFLAGS);
00648 
00649     if (lpBrowseInfo->ulFlags & BIF_NEWDIALOGSTYLE)
00650     {
00651         RECT rcWnd;
00652 
00653         info->layout = LayoutInit(hWnd, g_layout_info, LAYOUT_INFO_COUNT);
00654 
00655         /* TODO: Windows allows shrinking the windows a bit */
00656         GetWindowRect(hWnd, &rcWnd);
00657         info->szMin.cx = rcWnd.right - rcWnd.left;
00658         info->szMin.cy = rcWnd.bottom - rcWnd.top;
00659     }
00660     else
00661     {
00662         info->layout = NULL;
00663     }
00664 
00665     if (lpBrowseInfo->lpszTitle)
00666         SetWindowTextW( GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_TITLE), lpBrowseInfo->lpszTitle );
00667     else
00668         ShowWindow( GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_TITLE), SW_HIDE );
00669 
00670     if (!(lpBrowseInfo->ulFlags & BIF_STATUSTEXT)
00671         || (lpBrowseInfo->ulFlags & BIF_NEWDIALOGSTYLE))
00672         ShowWindow( GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_STATUS), SW_HIDE );
00673 
00674     /* Hide "Make New Folder" Button? */
00675     if ((lpBrowseInfo->ulFlags & BIF_NONEWFOLDERBUTTON)
00676         || !(lpBrowseInfo->ulFlags & BIF_NEWDIALOGSTYLE))
00677         ShowWindow( GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_NEW_FOLDER), SW_HIDE );
00678 
00679     /* Hide the editbox? */
00680     if (!(lpBrowseInfo->ulFlags & BIF_EDITBOX))
00681     {
00682         ShowWindow( GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_FOLDER), SW_HIDE );
00683         ShowWindow( GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT), SW_HIDE );
00684     }
00685 
00686     info->hwndTreeView = GetDlgItem( hWnd, IDC_BROWSE_FOR_FOLDER_TREEVIEW );
00687     if (info->hwndTreeView)
00688     {
00689         InitializeTreeView( info );
00690 
00691         /* Resize the treeview if there's not editbox */
00692         if ((lpBrowseInfo->ulFlags & BIF_NEWDIALOGSTYLE)
00693             && !(lpBrowseInfo->ulFlags & BIF_EDITBOX))
00694         {
00695             RECT rc;
00696             GetClientRect(info->hwndTreeView, &rc);
00697             SetWindowPos(info->hwndTreeView, HWND_TOP, 0, 0,
00698                          rc.right, rc.bottom + 40, SWP_NOMOVE);
00699         }
00700     }
00701     else
00702         ERR("treeview control missing!\n");
00703 
00704     browsefolder_callback( info->lpBrowseInfo, hWnd, BFFM_INITIALIZED, 0 );
00705 
00706     return TRUE;
00707 }
00708 
00709 static HRESULT BrsFolder_Rename(browse_info *info, HTREEITEM rename)
00710 {
00711     SendMessageW(info->hwndTreeView, TVM_SELECTITEM, TVGN_CARET, (LPARAM)rename);
00712     SendMessageW(info->hwndTreeView, TVM_EDITLABELW, 0, (LPARAM)rename);
00713     return S_OK;
00714 }
00715 
00716 static HRESULT BrsFolder_NewFolder(browse_info *info)
00717 {
00718     DWORD flags = BrowseFlagsToSHCONTF(info->lpBrowseInfo->ulFlags);
00719     IShellFolder *desktop, *cur;
00720     ISFHelper *sfhelper;
00721     WCHAR name[MAX_PATH];
00722     HTREEITEM parent, added;
00723     LPTV_ITEMDATA item_data;
00724     LPITEMIDLIST new_item;
00725     TVITEMW item;
00726     HRESULT hr;
00727     int len;
00728 
00729     if(!info->pidlRet) {
00730         ERR("Make new folder button should be disabled\n");
00731         return E_FAIL;
00732     }
00733 
00734     /* Create new directory */
00735     hr = SHGetDesktopFolder(&desktop);
00736     if(FAILED(hr))
00737         return hr;
00738     hr = desktop->BindToObject(info->pidlRet, 0, IID_IShellFolder, (LPVOID *)&cur);
00739     desktop->Release();
00740     if(FAILED(hr))
00741         return hr;
00742 
00743     hr = cur->QueryInterface(IID_ISFHelper, (LPVOID *)&sfhelper);
00744     if(FAILED(hr))
00745         return hr;
00746 
00747     hr = SHGetPathFromIDListW(info->pidlRet, name);
00748     if(FAILED(hr))
00749         goto cleanup;
00750 
00751     len = strlenW(name);
00752     if(len<MAX_PATH)
00753         name[len++] = '\\';
00754     hr = sfhelper->GetUniqueName(&name[len], MAX_PATH-len);
00755     sfhelper->Release();
00756     if(FAILED(hr))
00757         goto cleanup;
00758 
00759     hr = E_FAIL;
00760     if(!CreateDirectoryW(name, NULL))
00761         goto cleanup;
00762 
00763     /* Update parent of newly created directory */
00764     parent = (HTREEITEM)SendMessageW(info->hwndTreeView, TVM_GETNEXTITEM, TVGN_CARET, 0);
00765     if(!parent)
00766         goto cleanup;
00767 
00768     SendMessageW(info->hwndTreeView, TVM_EXPAND, TVE_EXPAND, (LPARAM)parent);
00769 
00770     memset(&item, 0, sizeof(TVITEMW));
00771     item.mask = TVIF_PARAM|TVIF_STATE;
00772     item.hItem = parent;
00773     SendMessageW(info->hwndTreeView, TVM_GETITEMW, 0, (LPARAM)&item);
00774     item_data = (LPTV_ITEMDATA)item.lParam;
00775     if(!item_data)
00776         goto cleanup;
00777 
00778     if(item_data->pEnumIL)
00779         item_data->pEnumIL->Release();
00780     hr = cur->EnumObjects(info->hwndTreeView, flags, &item_data->pEnumIL);
00781     if(FAILED(hr))
00782         goto cleanup;
00783 
00784     /* Update treeview */
00785     if(!(item.state&TVIS_EXPANDEDONCE)) {
00786         item.mask = TVIF_STATE;
00787         item.state = TVIS_EXPANDEDONCE;
00788         item.stateMask = TVIS_EXPANDEDONCE;
00789         SendMessageW(info->hwndTreeView, TVM_SETITEMW, 0, (LPARAM)&item);
00790     }
00791 
00792     hr = cur->ParseDisplayName(NULL, NULL, name+len, NULL, &new_item, NULL);
00793     if(FAILED(hr))
00794         goto cleanup;
00795 
00796     added = InsertTreeViewItem(info, cur, new_item, item_data->lpifq, NULL, parent);
00797     cur->Release();
00798     SHFree(new_item);
00799 
00800     SendMessageW(info->hwndTreeView, TVM_SORTCHILDREN, FALSE, (LPARAM)parent);
00801     return BrsFolder_Rename(info, added);
00802 
00803 cleanup:
00804     return hr;
00805 }
00806 
00807 static BOOL BrsFolder_OnCommand( browse_info *info, UINT id )
00808 {
00809     LPBROWSEINFOW lpBrowseInfo = info->lpBrowseInfo;
00810 
00811     switch (id)
00812     {
00813     case IDOK:
00814         /* The original pidl is owned by the treeview and will be free'd. */
00815         info->pidlRet = ILClone(info->pidlRet);
00816         if (info->pidlRet == NULL) /* A null pidl would mean a cancel */
00817             info->pidlRet = _ILCreateDesktop();
00818         pdump( info->pidlRet );
00819         if (lpBrowseInfo->pszDisplayName)
00820             SHGetPathFromIDListW( info->pidlRet, lpBrowseInfo->pszDisplayName );
00821         EndDialog( info->hWnd, 1 );
00822         return TRUE;
00823 
00824     case IDCANCEL:
00825         EndDialog( info->hWnd, 0 );
00826         return TRUE;
00827 
00828     case IDC_BROWSE_FOR_FOLDER_NEW_FOLDER:
00829         BrsFolder_NewFolder(info);
00830         return TRUE;
00831     }
00832     return FALSE;
00833 }
00834 
00835 static BOOL BrsFolder_OnSetExpanded(browse_info *info, LPVOID selection,
00836     BOOL is_str, HTREEITEM *pItem)
00837 {
00838     LPITEMIDLIST pidlSelection = (LPITEMIDLIST)selection;
00839     LPCITEMIDLIST pidlCurrent, pidlRoot;
00840     TVITEMEXW item;
00841     BOOL bResult = FALSE;
00842 
00843     memset(&item, 0, sizeof(item));
00844 
00845     /* If 'selection' is a string, convert to a Shell ID List. */ 
00846     if (is_str) {
00847         IShellFolder *psfDesktop;
00848         HRESULT hr;
00849 
00850         hr = SHGetDesktopFolder(&psfDesktop);
00851         if (FAILED(hr))
00852             goto done;
00853 
00854         hr = psfDesktop->ParseDisplayName(NULL, NULL, (LPOLESTR)selection,
00855                                           NULL, &pidlSelection, NULL);
00856         psfDesktop->Release();
00857         if (FAILED(hr))
00858             goto done;
00859     }
00860 
00861     /* Move pidlCurrent behind the SHITEMIDs in pidlSelection, which are the root of
00862      * the sub-tree currently displayed. */
00863     pidlRoot = info->lpBrowseInfo->pidlRoot;
00864     pidlCurrent = pidlSelection;
00865     while (!_ILIsEmpty(pidlRoot) && _ILIsEqualSimple(pidlRoot, pidlCurrent)) {
00866         pidlRoot = ILGetNext(pidlRoot);
00867         pidlCurrent = ILGetNext(pidlCurrent);
00868     }
00869 
00870     /* The given ID List is not part of the SHBrowseForFolder's current sub-tree. */
00871     if (!_ILIsEmpty(pidlRoot))
00872         goto done;
00873 
00874     /* Initialize item to point to the first child of the root folder. */
00875     item.mask = TVIF_PARAM;
00876     item.hItem = (HTREEITEM)SendMessageW(info->hwndTreeView, TVM_GETNEXTITEM, TVGN_ROOT, 0);
00877 
00878     if (item.hItem)
00879         item.hItem = (HTREEITEM)SendMessageW(info->hwndTreeView, TVM_GETNEXTITEM, TVGN_CHILD,
00880                                              (LPARAM)item.hItem);
00881 
00882     /* Walk the tree along the nodes corresponding to the remaining ITEMIDLIST */
00883     while (item.hItem && !_ILIsEmpty(pidlCurrent)) {
00884         LPTV_ITEMDATA pItemData;
00885 
00886         SendMessageW(info->hwndTreeView, TVM_GETITEMW, 0, (LPARAM)&item);
00887         pItemData = (LPTV_ITEMDATA)item.lParam;
00888 
00889         if (_ILIsEqualSimple(pItemData->lpi, pidlCurrent)) {
00890             pidlCurrent = ILGetNext(pidlCurrent);
00891             if (!_ILIsEmpty(pidlCurrent)) {
00892                 /* Only expand current node and move on to it's first child,
00893                  * if we didn't already reach the last SHITEMID */
00894                 SendMessageW(info->hwndTreeView, TVM_EXPAND, TVE_EXPAND, (LPARAM)item.hItem);
00895                 item.hItem = (HTREEITEM)SendMessageW(info->hwndTreeView, TVM_GETNEXTITEM, TVGN_CHILD,
00896                                                      (LPARAM)item.hItem);
00897             }
00898         } else {
00899             item.hItem = (HTREEITEM)SendMessageW(info->hwndTreeView, TVM_GETNEXTITEM, TVGN_NEXT,
00900                                                  (LPARAM)item.hItem);
00901         }
00902     }
00903 
00904     if (_ILIsEmpty(pidlCurrent) && item.hItem)
00905         bResult = TRUE;
00906 
00907 done:
00908     if (pidlSelection && pidlSelection != (LPITEMIDLIST)selection)
00909         ILFree(pidlSelection);
00910 
00911     if (pItem)
00912         *pItem = item.hItem;
00913 
00914     return bResult;
00915 }
00916 
00917 static BOOL BrsFolder_OnSetSelectionW(browse_info *info, LPVOID selection, BOOL is_str) {
00918     HTREEITEM hItem;
00919     BOOL bResult;
00920 
00921     if (!selection) return FALSE;
00922 
00923     bResult = BrsFolder_OnSetExpanded(info, selection, is_str, &hItem);
00924     if (bResult)
00925         SendMessageW(info->hwndTreeView, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hItem );
00926     return bResult;
00927 }
00928 
00929 static BOOL BrsFolder_OnSetSelectionA(browse_info *info, LPVOID selection, BOOL is_str) {
00930     LPWSTR selectionW = NULL;
00931     BOOL result = FALSE;
00932     int length;
00933 
00934     if (!is_str)
00935         return BrsFolder_OnSetSelectionW(info, selection, is_str);
00936 
00937     if ((length = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)selection, -1, NULL, 0)) &&
00938         (selectionW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, length * sizeof(WCHAR))) &&
00939         MultiByteToWideChar(CP_ACP, 0, (LPCSTR)selection, -1, selectionW, length))
00940     {
00941         result = BrsFolder_OnSetSelectionW(info, selectionW, is_str);
00942     }
00943 
00944     HeapFree(GetProcessHeap(), 0, selectionW);
00945     return result;
00946 }
00947 
00948 static BOOL BrsFolder_OnWindowPosChanging(browse_info *info, WINDOWPOS *pos)
00949 {
00950     if ((info->lpBrowseInfo->ulFlags & BIF_NEWDIALOGSTYLE) && !(pos->flags & SWP_NOSIZE))
00951     {
00952         if (pos->cx < info->szMin.cx)
00953             pos->cx = info->szMin.cx;
00954         if (pos->cy < info->szMin.cy)
00955             pos->cy = info->szMin.cy;
00956     }
00957     return 0;
00958 }
00959 
00960 static INT BrsFolder_OnDestroy(browse_info *info)
00961 {
00962     if (info->layout)
00963     {
00964         SHFree(info->layout);
00965         info->layout = NULL;
00966     }
00967 
00968     return 0;
00969 }
00970 
00971 /*************************************************************************
00972  *             BrsFolderDlgProc32  (not an exported API function)
00973  */
00974 static INT_PTR CALLBACK BrsFolderDlgProc( HWND hWnd, UINT msg, WPARAM wParam,
00975                                           LPARAM lParam )
00976 {
00977     browse_info *info;
00978 
00979     TRACE("hwnd=%p msg=%04x 0x%08lx 0x%08lx\n", hWnd, msg, wParam, lParam );
00980 
00981     if (msg == WM_INITDIALOG)
00982         return BrsFolder_OnCreate( hWnd, (browse_info*) lParam );
00983 
00984     info = (browse_info*) GetPropW( hWnd, szBrowseFolderInfo );
00985 
00986     switch (msg)
00987     {
00988     case WM_NOTIFY:
00989         return BrsFolder_OnNotify( info, (UINT)wParam, (LPNMHDR)lParam);
00990 
00991     case WM_COMMAND:
00992         return BrsFolder_OnCommand( info, wParam );
00993 
00994     case WM_WINDOWPOSCHANGING:
00995         return BrsFolder_OnWindowPosChanging( info, (WINDOWPOS *)lParam);
00996 
00997     case WM_SIZE:
00998         if (info->layout)  /* new style dialogs */
00999             LayoutUpdate(hWnd, info->layout, g_layout_info, LAYOUT_INFO_COUNT);
01000         return 0;
01001 
01002     case BFFM_SETSTATUSTEXTA:
01003         TRACE("Set status %s\n", debugstr_a((LPSTR)lParam));
01004         SetWindowTextA(GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_STATUS), (LPSTR)lParam);
01005         break;
01006 
01007     case BFFM_SETSTATUSTEXTW:
01008         TRACE("Set status %s\n", debugstr_w((LPWSTR)lParam));
01009         SetWindowTextW(GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_STATUS), (LPWSTR)lParam);
01010         break;
01011 
01012     case BFFM_ENABLEOK:
01013         TRACE("Enable %ld\n", lParam);
01014         EnableWindow(GetDlgItem(hWnd, 1), (lParam)?TRUE:FALSE);
01015         break;
01016 
01017     case BFFM_SETOKTEXT: /* unicode only */
01018         TRACE("Set OK text %s\n", debugstr_w((LPWSTR)wParam));
01019         SetWindowTextW(GetDlgItem(hWnd, 1), (LPWSTR)wParam);
01020         break;
01021 
01022     case BFFM_SETSELECTIONA:
01023         return BrsFolder_OnSetSelectionA(info, (LPVOID)lParam, (BOOL)wParam);
01024 
01025     case BFFM_SETSELECTIONW:
01026         return BrsFolder_OnSetSelectionW(info, (LPVOID)lParam, (BOOL)wParam);
01027 
01028     case BFFM_SETEXPANDED: /* unicode only */
01029         return BrsFolder_OnSetExpanded(info, (LPVOID)lParam, (BOOL)wParam, NULL);
01030 
01031     case WM_DESTROY:
01032         return BrsFolder_OnDestroy(info);
01033     }
01034     return FALSE;
01035 }
01036 
01037 
01038 
01039 
01040 /*************************************************************************
01041  * SHBrowseForFolderA [SHELL32.@]
01042  * SHBrowseForFolder  [SHELL32.@]
01043  */
01044 LPITEMIDLIST WINAPI SHBrowseForFolderA (LPBROWSEINFOA lpbi)
01045 {
01046     BROWSEINFOW bi;
01047     LPITEMIDLIST lpid;
01048     INT len;
01049     LPWSTR title;
01050 
01051     TRACE("%p\n", lpbi);
01052 
01053     bi.hwndOwner = lpbi->hwndOwner;
01054     bi.pidlRoot = lpbi->pidlRoot;
01055     if (lpbi->pszDisplayName)
01056     {
01057         bi.pszDisplayName = (WCHAR *)HeapAlloc( GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) );
01058         MultiByteToWideChar( CP_ACP, 0, lpbi->pszDisplayName, -1, bi.pszDisplayName, MAX_PATH );
01059     }
01060     else
01061         bi.pszDisplayName = NULL;
01062 
01063     if (lpbi->lpszTitle)
01064     {
01065         len = MultiByteToWideChar( CP_ACP, 0, lpbi->lpszTitle, -1, NULL, 0 );
01066         title = (WCHAR *)HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
01067         MultiByteToWideChar( CP_ACP, 0, lpbi->lpszTitle, -1, title, len );
01068     }
01069     else
01070         title = NULL;
01071 
01072     bi.lpszTitle = title;
01073     bi.ulFlags = lpbi->ulFlags;
01074     bi.lpfn = lpbi->lpfn;
01075     bi.lParam = lpbi->lParam;
01076     bi.iImage = lpbi->iImage;
01077     lpid = SHBrowseForFolderW( &bi );
01078     if (bi.pszDisplayName)
01079     {
01080         WideCharToMultiByte( CP_ACP, 0, bi.pszDisplayName, -1,
01081                              lpbi->pszDisplayName, MAX_PATH, 0, NULL);
01082         HeapFree( GetProcessHeap(), 0, bi.pszDisplayName );
01083     }
01084     HeapFree(GetProcessHeap(), 0, title);
01085     lpbi->iImage = bi.iImage;
01086     return lpid;
01087 }
01088 
01089 
01090 /*************************************************************************
01091  * SHBrowseForFolderW [SHELL32.@]
01092  *
01093  * NOTES
01094  *  crashes when passed a null pointer
01095  */
01096 LPITEMIDLIST WINAPI SHBrowseForFolderW (LPBROWSEINFOW lpbi)
01097 {
01098     browse_info info;
01099     DWORD r;
01100     HRESULT hr;
01101     WORD wDlgId;
01102 
01103     info.hWnd = 0;
01104     info.pidlRet = NULL;
01105     info.lpBrowseInfo = lpbi;
01106     info.hwndTreeView = NULL;
01107 
01108     hr = OleInitialize(NULL);
01109 
01110     if (lpbi->ulFlags & BIF_NEWDIALOGSTYLE)
01111         wDlgId = IDD_BROWSE_FOR_FOLDER_NEW;
01112     else
01113         wDlgId = IDD_BROWSE_FOR_FOLDER;
01114     r = DialogBoxParamW( shell32_hInstance, MAKEINTRESOURCEW(wDlgId), lpbi->hwndOwner,
01115                          BrsFolderDlgProc, (LPARAM)&info );
01116     if (SUCCEEDED(hr))
01117         OleUninitialize();
01118     if (!r)
01119     {
01120         ILFree(info.pidlRet);
01121         return NULL;
01122     }
01123 
01124     return info.pidlRet;
01125 }

Generated on Sat May 26 2012 04:24:52 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.