Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenbrsfolder.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
1.7.6.1
|