Ge van Geldorp gvg@reactos.com - Overlay icons for .lnk files with a small arrow in the lower left corner. Alexandre Julliard julliard@winehq.org - Added rules for building import libraries in the individual dll makefiles, and added support for building a .def.a static import library too. - Removed unnecessary code in the 16-bit DllEntryPoint function of some dlls, and also fixed its ordinal in a few places. - Comment out stub WEP entry points so that we can call WEP for builtin dlls too. Juan Lang juan_lang@yahoo.com - Fixes to IShellFolder::GetAttributesOf implementations, spotted by silverblade_: - a count of zero is allowed to GetAttributesOf if apidl is NULL - SFGAO_VALIDATE must be cleared upon return - only log unsupported flags in ShellExecute - environment variables are expanded, so SEE_MASK_DOENVSUBST is supported Michael Jung mjung@iss.tu-darmstadt.de - Add a new CLSID for UnixDosFolder, which is identical to UnixFolder, but does unix <-> dos path conversion for GetDisplayNameOf and ParseDisplayName. - Make the root of the shell extension map to the root of the unix filesystem. - More robustly query the SHGDN_FORPARSING flag in the shell32's folders GetDisplayNameOf methods. - Fixed GetDisplayNameOf method to not depend on incorrect behaviour regarding the SHGDN_INFOLDER flag. - Fixed MyComputer's GetDisplayNameOf method. - Return a cloned PIDL by SHBrowseForFolder to avoid heap corruption. - Fixed incorrect IShellFolder::EnumOjects API usage. - Support for regular files (as opposed to directories). - Display a drive icon for the unix root directory. - Consider only the GIL_FORSHORTCUT flag in SIC_CompareEntries. Stefan Doesinger stefandoesinger@gmx.at - Handle cidl==0 in shfldr_desktop, shfldr_fs and shfldr_mycomp. - Remove the dwAttributes member from the IGenericSFImpl class, it's not needed and can't be initialised in Initialize and InitializeEx. Mike McCormack mike@codeweavers.com - Split SHGetFileInfoW into two functions. - Remove static variables in SHBrowseForFolder implementation. - Split up the window procedure. - Remove some unused include files. - MSI advertised shortcuts don't require a product ID. Peter Berg Larsen pebl@math.ku.dk - Rewritten DoEnvironmentSubst16. Kouji Sasaki taro-x@justsystem.co.jp - Added the processing for determination of SFGAO_HASSUBFOLDER flag in SHELL32_GetItemAttribute function. Francois Gouget fgouget@free.fr - Assorted spelling fixes. Huw Davies huw@codeweavers.com - It makes no sense to have a left pointing arrow as the desktop icon. Replace it with something more appropiate. Mike Hearn mh@codeweavers.com - Fix SHELL_GetPathFromIDList[AW] to return the desktop path given an empty PIDL. Modified: trunk/reactos/lib/shell32/Makefile.in Modified: trunk/reactos/lib/shell32/brsfolder.c Modified: trunk/reactos/lib/shell32/cpanelfolder.c Modified: trunk/reactos/lib/shell32/folders.c Modified: trunk/reactos/lib/shell32/iconcache.c Modified: trunk/reactos/lib/shell32/pidl.c Modified: trunk/reactos/lib/shell32/regsvr.c Modified: trunk/reactos/lib/shell32/shell.c Modified: trunk/reactos/lib/shell32/shell.spec Modified: trunk/reactos/lib/shell32/shell32_De.rc Modified: trunk/reactos/lib/shell32/shell32_En.rc Modified: trunk/reactos/lib/shell32/shell32_main.c Modified: trunk/reactos/lib/shell32/shell32_main.h Modified: trunk/reactos/lib/shell32/shelllink.c Modified: trunk/reactos/lib/shell32/shfldr_desktop.c Modified: trunk/reactos/lib/shell32/shfldr_fs.c Modified: trunk/reactos/lib/shell32/shfldr_mycomp.c Modified: trunk/reactos/lib/shell32/shlexec.c Modified: trunk/reactos/lib/shell32/shlfileop.c Modified: trunk/reactos/lib/shell32/shlfolder.c Modified: trunk/reactos/lib/shell32/shres.rc Modified: trunk/reactos/lib/shell32/shresdef.h _____
Modified: trunk/reactos/lib/shell32/Makefile.in --- trunk/reactos/lib/shell32/Makefile.in 2005-05-28 21:30:02 UTC (rev 15616) +++ trunk/reactos/lib/shell32/Makefile.in 2005-05-28 21:30:32 UTC (rev 15617) @@ -4,6 +4,7 @@
SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = shell32.dll +IMPORTLIB = libshell32.$(IMPLIBEXT) IMPORTS = shlwapi comctl32 user32 gdi32 advapi32 kernel32 DELAYIMPORTS = ole32 EXTRALIBS = -luuid $(LIBUNICODE) @@ -63,7 +64,8 @@ netdrive.ico \ netdrive2.ico \ printer.ico \ - ramdisk.ico + ramdisk.ico \ + shortcut.ico
C_SRCS16 = shell.c RC_SRCS16 = version16.rc _____
Modified: trunk/reactos/lib/shell32/brsfolder.c --- trunk/reactos/lib/shell32/brsfolder.c 2005-05-28 21:30:02 UTC (rev 15616) +++ trunk/reactos/lib/shell32/brsfolder.c 2005-05-28 21:30:32 UTC (rev 15617) @@ -37,12 +37,21 @@
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;
-static void FillTreeView(LPSHELLFOLDER lpsf, LPITEMIDLIST lpifq, HTREEITEM hParent, IEnumIDList* lpe); -static HTREEITEM InsertTreeViewItem(IShellFolder * lpsf, LPCITEMIDLIST pidl, LPCITEMIDLIST pidlParent, IEnumIDList* pEnumIL, HTREEITEM hParent); +typedef struct tagTV_ITEMDATA +{ + LPSHELLFOLDER lpsfParent; /* IShellFolder of the parent */ + LPITEMIDLIST lpi; /* PIDL relativ to parent */ + LPITEMIDLIST lpifq; /* Fully qualified PIDL */ + IEnumIDList* pEnumIL; /* Children iterator */ +} TV_ITEMDATA, *LPTV_ITEMDATA;
#define SUPPORTEDFLAGS (BIF_STATUSTEXT | \ BIF_BROWSEFORCOMPUTER | \ @@ -50,11 +59,30 @@ 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] * @@ -64,25 +92,23 @@ * 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, @@ -131,7 +157,8 @@ 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); @@ -139,8 +166,10 @@ 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); @@ -148,40 +177,34 @@
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 ); }
-typedef struct tagID -{ - LPSHELLFOLDER lpsfParent; /* IShellFolder of the parent */ - LPITEMIDLIST lpi; /* PIDL relativ to parent */ - LPITEMIDLIST lpifq; /* Fully qualified PIDL */ - IEnumIDList* pEnumIL; /* Children iterator */ -} TV_ITEMDATA, *LPTV_ITEMDATA; -
/*********************************************************************** ******* * GetName [Internal] * @@ -221,6 +244,7 @@ * 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 @@ * 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 @@ 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 @@ tvins.hInsertAfter = NULL; tvins.hParent = hParent;
- return (HTREEITEM)TreeView_InsertItemW(hwndTreeView, &tvins); + return (HTREEITEM)TreeView_InsertItemW( info->hwndTreeView, &tvins ); }
/*********************************************************************** ******* @@ -275,26 +301,28 @@ * 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 @@ hr = IShellFolder_BindToObject(lpsf,pidlTemp,NULL,&IID_IShellFolder,(LPVOID*) &pSFChild); if (SUCCEEDED(hr)) { - hr = IShellFolder_EnumObjects(pSFChild, hwnd, BrowseFlagsToSHCONTF(lpBrowseInfo->ulFlags), &pEnumIL); - if (SUCCEEDED(hr)) + 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 @@ } }
- 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,182 +372,238 @@ 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; + HRESULT r; + if ((lpBrowseInfo->ulFlags & BIF_BROWSEFORCOMPUTER) && !PIDLIsType(pidl, PT_COMP)) bEnabled = FALSE; if (lpBrowseInfo->ulFlags & BIF_RETURNFSANCESTORS) { dwAttributes = SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM; - if (FAILED(IShellFolder_GetAttributesOf(lptvid->lpsfParent, 1, (LPCITEMIDLIST*)&lptvid->lpi, &dwAttributes)) || - !dwAttributes) + r = IShellFolder_GetAttributesOf(lptvid->lpsfParent, 1, + (LPCITEMIDLIST*)&lptvid->lpi, &dwAttributes); + if (FAILED(r) || !dwAttributes) bEnabled = FALSE; } if (lpBrowseInfo->ulFlags & BIF_RETURNONLYFSDIRS) { dwAttributes = SFGAO_FOLDER | SFGAO_FILESYSTEM; - if (FAILED(IShellFolder_GetAttributesOf(lptvid->lpsfParent, 1, (LPCITEMIDLIST*)&lptvid->lpi, &dwAttributes)) || - (dwAttributes != (SFGAO_FOLDER | SFGAO_FILESYSTEM))) + r = IShellFolder_GetAttributesOf(lptvid->lpsfParent, 1, + (LPCITEMIDLIST*)&lptvid->lpi, &dwAttributes); + 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 MsgNotify(HWND hWnd, UINT CtlID, LPNMHDR lpnmh) +static LRESULT BrsFolder_Treeview_Delete( browse_info *info, NMTREEVIEWW *pnmtv ) { - NMTREEVIEWW *pnmtv = (NMTREEVIEWW *)lpnmh; - LPTV_ITEMDATA lptvid; /* Long pointer to TreeView item data */ - IShellFolder * lpsf2=0; + LPTV_ITEMDATA lptvid = (LPTV_ITEMDATA)pnmtv->itemOld.lParam;
+ TRACE("TVN_DELETEITEMA/W %p\n", lptvid);
- TRACE("%p %x %p msg=%x\n", hWnd, CtlID, lpnmh, pnmtv->hdr.code); + IShellFolder_Release(lptvid->lpsfParent); + if (lptvid->pEnumIL) + IEnumIDList_Release(lptvid->pEnumIL); + SHFree(lptvid->lpi); + SHFree(lptvid->lpifq); + SHFree(lptvid); + return 0; +}
- switch (pnmtv->hdr.idFrom) - { case IDD_TREEVIEW: - switch (pnmtv->hdr.code) - { - case TVN_DELETEITEMA: - case TVN_DELETEITEMW: - TRACE("TVN_DELETEITEMA/W\n"); - lptvid=(LPTV_ITEMDATA)pnmtv->itemOld.lParam; - IShellFolder_Release(lptvid->lpsfParent); - if (lptvid->pEnumIL) - IEnumIDList_Release(lptvid->pEnumIL); - SHFree(lptvid->lpi); - SHFree(lptvid->lpifq); - SHFree(lptvid); - break; +static LRESULT BrsFolder_Treeview_Expand( browse_info *info, NMTREEVIEWW *pnmtv ) +{ + IShellFolder *lpsf2 = NULL; + LPTV_ITEMDATA lptvid = (LPTV_ITEMDATA) pnmtv->itemNew.lParam; + HRESULT r;
- case TVN_ITEMEXPANDINGA: - case TVN_ITEMEXPANDINGW: - { - TRACE("TVN_ITEMEXPANDINGA/W\n"); - if ((pnmtv->itemNew.state & TVIS_EXPANDEDONCE)) - break; + TRACE("TVN_ITEMEXPANDINGA/W\n");
- lptvid=(LPTV_ITEMDATA)pnmtv->itemNew.lParam; - if (SUCCEEDED(IShellFolder_BindToObject(lptvid->lpsfParent, lptvid->lpi,0,(REFIID)&IID_IShellFolder,(LPVOID *)&lpsf2))) - { FillTreeView( 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); - } - break; - case TVN_SELCHANGEDA: - case TVN_SELCHANGEDW: - 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); - break; + if ((pnmtv->itemNew.state & TVIS_EXPANDEDONCE)) + return 0;
- default: - WARN("unhandled (%d)\n", pnmtv->hdr.code); - break; - } - break; + r = IShellFolder_BindToObject( lptvid->lpsfParent, lptvid->lpi, 0, + (REFIID)&IID_IShellFolder, (LPVOID *)&lpsf2 ); + if (SUCCEEDED(r)) + FillTreeView( info, lpsf2, lptvid->lpifq, pnmtv->itemNew.hItem, lptvid->pEnumIL);
- default: - break; - } + /* My Computer is already sorted and trying to do a simple text + * sort will only mess things up */ + if (!_ILIsMyComputer(lptvid->lpi)) + TreeView_SortChildren(info->hwndTreeView, pnmtv->itemNew.hItem, FALSE);
- return 0; + return 0; }
+static HRESULT BrsFolder_Treeview_Changed( browse_info *info, NMTREEVIEWW *pnmtv ) +{ + LPTV_ITEMDATA lptvid = (LPTV_ITEMDATA) pnmtv->itemNew.lParam;
+ lptvid = (LPTV_ITEMDATA) pnmtv->itemNew.lParam; + 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( browse_info *info, UINT CtlID, LPNMHDR lpnmh ) +{ + NMTREEVIEWW *pnmtv = (NMTREEVIEWW *)lpnmh; + + TRACE("%p %x %p msg=%x\n", info, CtlID, lpnmh, pnmtv->hdr.code); + + if (pnmtv->hdr.idFrom != IDD_TREEVIEW) + return 0; + + switch (pnmtv->hdr.code) + { + case TVN_DELETEITEMA: + case TVN_DELETEITEMW: + return BrsFolder_Treeview_Delete( info, pnmtv ); + + case TVN_ITEMEXPANDINGA: + case TVN_ITEMEXPANDINGW: + return BrsFolder_Treeview_Expand( info, pnmtv ); + + case TVN_SELCHANGEDA: + case TVN_SELCHANGEDW: + return BrsFolder_Treeview_Changed( info, pnmtv ); + + default: + WARN("unhandled (%d)\n", pnmtv->hdr.code); + break; + } + + return 0; +} + + +static BOOL BrsFolder_OnCreate( HWND hWnd, browse_info *info ) +{ + LPBROWSEINFOW lpBrowseInfo = info->lpBrowseInfo; + + info->hWnd = hWnd; + SetPropW( hWnd, szBrowseFolderInfo, info ); + + if (lpBrowseInfo->ulFlags & ~SUPPORTEDFLAGS) + FIXME("flags %x not implemented\n", lpBrowseInfo->ulFlags & ~SUPPORTEDFLAGS); + + if (lpBrowseInfo->lpszTitle) + SetWindowTextW( GetDlgItem(hWnd, IDD_TITLE), lpBrowseInfo->lpszTitle ); + else + ShowWindow( GetDlgItem(hWnd, IDD_TITLE), SW_HIDE ); + + if (!(lpBrowseInfo->ulFlags & BIF_STATUSTEXT)) + ShowWindow( GetDlgItem(hWnd, IDD_STATUS), SW_HIDE ); + + info->hwndTreeView = GetDlgItem( hWnd, IDD_TREEVIEW ); + if (info->hwndTreeView) + InitializeTreeView( info ); + else + ERR("treeview control missing!\n"); + + browsefolder_callback( info->lpBrowseInfo, hWnd, BFFM_INITIALIZED, 0 ); + + return TRUE; +} + +static BOOL BrsFolder_OnCommand( browse_info *info, UINT id ) +{ + LPBROWSEINFOW lpBrowseInfo = info->lpBrowseInfo; + + switch (id) + { + case IDOK: + info->pidlRet = ILClone(info->pidlRet); /* The original pidl will be free'd. */ + pdump( info->pidlRet ); + if (lpBrowseInfo->pszDisplayName) + SHGetPathFromIDListW( info->pidlRet, lpBrowseInfo->pszDisplayName ); + EndDialog( info->hWnd, 1 ); + return TRUE; + + case IDCANCEL: + EndDialog( info->hWnd, 0 ); + return TRUE; + } + return FALSE; +} +
/*********************************************************************** ** * BrsFolderDlgProc32 (not an exported API function) */ -static INT_PTR CALLBACK BrsFolderDlgProc(HWND hWnd, UINT msg, WPARAM wParam, - LPARAM lParam ) +static INT_PTR CALLBACK BrsFolderDlgProc( HWND hWnd, UINT msg, WPARAM wParam, + LPARAM lParam ) { - TRACE("hwnd=%p msg=%04x 0x%08x 0x%08lx\n", hWnd, msg, wParam, lParam ); + browse_info *info;
- switch(msg) - { case WM_INITDIALOG: - pidlRet = NULL; - lpBrowseInfo = (LPBROWSEINFOW) lParam; - if (lpBrowseInfo->ulFlags & ~SUPPORTEDFLAGS) - FIXME("flags %x not implemented\n", lpBrowseInfo->ulFlags & ~SUPPORTEDFLAGS); - if (lpBrowseInfo->lpszTitle) { - SetWindowTextW(GetDlgItem(hWnd, IDD_TITLE), lpBrowseInfo->lpszTitle); - } else { - ShowWindow(GetDlgItem(hWnd, IDD_TITLE), SW_HIDE); - } - if (!(lpBrowseInfo->ulFlags & BIF_STATUSTEXT)) - ShowWindow(GetDlgItem(hWnd, IDD_STATUS), SW_HIDE); + TRACE("hwnd=%p msg=%04x 0x%08x 0x%08lx\n", hWnd, msg, wParam, lParam );
- InitializeTreeView(hWnd, lpBrowseInfo->pidlRoot); + if (msg == WM_INITDIALOG) + return BrsFolder_OnCreate( hWnd, (browse_info*) lParam );
- if (lpBrowseInfo->lpfn) - (lpBrowseInfo->lpfn)(hWnd, BFFM_INITIALIZED, 0, lpBrowseInfo->lParam); + info = (browse_info*) GetPropW( hWnd, szBrowseFolderInfo );
- return TRUE; + switch (msg) + { + case WM_NOTIFY: + return BrsFolder_OnNotify( info, (UINT)wParam, (LPNMHDR)lParam);
- case WM_NOTIFY: - MsgNotify( hWnd, (UINT)wParam, (LPNMHDR)lParam); - break; + case WM_COMMAND: + return BrsFolder_OnCommand( info, wParam );
- case WM_COMMAND: - switch (wParam) - { case IDOK: - pdump ( pidlRet ); - if (lpBrowseInfo->pszDisplayName) - SHGetPathFromIDListW(pidlRet, lpBrowseInfo->pszDisplayName); - EndDialog(hWnd, (DWORD) ILClone(pidlRet)); - return TRUE; + case BFFM_SETSTATUSTEXTA: + TRACE("Set status %s\n", debugstr_a((LPSTR)lParam)); + SetWindowTextA(GetDlgItem(hWnd, IDD_STATUS), (LPSTR)lParam); + break;
- case IDCANCEL: - EndDialog(hWnd, 0); - return TRUE; - } - break; - case BFFM_SETSTATUSTEXTA: - TRACE("Set status %s\n", debugstr_a((LPSTR)lParam)); - SetWindowTextA(GetDlgItem(hWnd, IDD_STATUS), (LPSTR)lParam); - break; - case BFFM_SETSTATUSTEXTW: - TRACE("Set status %s\n", debugstr_w((LPWSTR)lParam)); - SetWindowTextW(GetDlgItem(hWnd, IDD_STATUS), (LPWSTR)lParam); - break; - case BFFM_ENABLEOK: - TRACE("Enable %ld\n", lParam); - EnableWindow(GetDlgItem(hWnd, 1), (lParam)?TRUE:FALSE); - break; - case BFFM_SETOKTEXT: /* unicode only */ - TRACE("Set OK text %s\n", debugstr_w((LPWSTR)wParam)); - SetWindowTextW(GetDlgItem(hWnd, 1), (LPWSTR)wParam); - break; - case BFFM_SETSELECTIONA: - if (wParam) - FIXME("Set selection %s\n", debugstr_a((LPSTR)lParam)); - else - FIXME("Set selection %p\n", (void*)lParam); - break; - case BFFM_SETSELECTIONW: - if (wParam) - FIXME("Set selection %s\n", debugstr_w((LPWSTR)lParam)); - else - FIXME("Set selection %p\n", (void*)lParam); - break; - case BFFM_SETEXPANDED: /* unicode only */ - if (wParam) - FIXME("Set expanded %s\n", debugstr_w((LPWSTR)lParam)); - else - FIXME("Set expanded %p\n", (void*)lParam); - break; - } - return FALSE; + case BFFM_SETSTATUSTEXTW: + TRACE("Set status %s\n", debugstr_w((LPWSTR)lParam)); + SetWindowTextW(GetDlgItem(hWnd, IDD_STATUS), (LPWSTR)lParam); + break; + + case BFFM_ENABLEOK: + TRACE("Enable %ld\n", lParam); + EnableWindow(GetDlgItem(hWnd, 1), (lParam)?TRUE:FALSE); + break; + + case BFFM_SETOKTEXT: /* unicode only */ + TRACE("Set OK text %s\n", debugstr_w((LPWSTR)wParam)); + SetWindowTextW(GetDlgItem(hWnd, 1), (LPWSTR)wParam); + break; + + case BFFM_SETSELECTIONA: + if (wParam) + FIXME("Set selection %s\n", debugstr_a((LPSTR)lParam)); + else + FIXME("Set selection %p\n", (void*)lParam); + break; + + case BFFM_SETSELECTIONW: + if (wParam) + FIXME("Set selection %s\n", debugstr_w((LPWSTR)lParam)); + else + FIXME("Set selection %p\n", (void*)lParam); + break; + + case BFFM_SETEXPANDED: /* unicode only */ + if (wParam) + FIXME("Set expanded %s\n", debugstr_w((LPWSTR)lParam)); + else + FIXME("Set expanded %p\n", (void*)lParam); + break; + } + return FALSE; }
-static const WCHAR swBrowseTempName[] = {'S','H','B','R','S','F','O','R','F','O','L','D','E','R','_','M','S','G' ,'B','O','X',0}; +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};
/*********************************************************************** ** * SHBrowseForFolderA [SHELL32.@] @@ -525,66 +611,69 @@ */ 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; + info.hWnd = 0; + info.pidlRet = NULL; + info.lpBrowseInfo = lpbi; + info.hwndTreeView = NULL;
- return (LPITEMIDLIST) DialogBoxParamW(shell32_hInstance, - swBrowseTempName, lpbi->hwndOwner, - BrsFolderDlgProc, (INT)lpbi); + r = DialogBoxParamW( shell32_hInstance, swBrowseTemplateName, lpbi->hwndOwner, + BrsFolderDlgProc, (LPARAM)&info ); + if (!r) + return NULL; + + return info.pidlRet; } _____
Modified: trunk/reactos/lib/shell32/cpanelfolder.c --- trunk/reactos/lib/shell32/cpanelfolder.c 2005-05-28 21:30:02 UTC (rev 15616) +++ trunk/reactos/lib/shell32/cpanelfolder.c 2005-05-28 21:30:32 UTC (rev 15617) @@ -552,10 +552,13 @@
HRESULT hr = S_OK;
- TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n", This, cidl, apidl, *rgfInOut); + TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08lx))\n", + This, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
- if ((!cidl) ||(!apidl) ||(!rgfInOut)) - return E_INVALIDARG; + if (!rgfInOut) + return E_INVALIDARG; + if (cidl && !apidl) + return E_INVALIDARG;
if (*rgfInOut == 0) *rgfInOut = ~0; @@ -566,6 +569,8 @@ apidl++; cidl--; } + /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */ + *rgfInOut &= ~SFGAO_VALIDATE;
TRACE("-- result=0x%08lx\n", *rgfInOut); return hr; _____
Modified: trunk/reactos/lib/shell32/folders.c --- trunk/reactos/lib/shell32/folders.c 2005-05-28 21:30:02 UTC (rev 15616) +++ trunk/reactos/lib/shell32/folders.c 2005-05-28 21:30:32 UTC (rev 15617) @@ -383,7 +383,7 @@
FIXME("(%p) (file=%p index=%d %p %p size=%08x) semi-stub\n", This, debugstr_w(pszFile), (signed)nIconIndex, phiconLarge, phiconSmall, nIconSize);
- index = SIC_GetIconIndex(pszFile, nIconIndex); + index = SIC_GetIconIndex(pszFile, nIconIndex, 0);
if (phiconLarge) *phiconLarge = ImageList_GetIcon(ShellBigIconList, index, ILD_TRANSPARENT); _____
Modified: trunk/reactos/lib/shell32/iconcache.c --- trunk/reactos/lib/shell32/iconcache.c 2005-05-28 21:30:02 UTC (rev 15616) +++ trunk/reactos/lib/shell32/iconcache.c 2005-05-28 21:30:32 UTC (rev 15617) @@ -43,6 +43,7 @@
#include "pidl.h" #include "shell32_main.h" #include "undocshell.h" +#include "shresdef.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
@@ -77,23 +78,165 @@ * Callback for DPA_Search */ static INT CALLBACK SIC_CompareEntries( LPVOID p1, LPVOID p2, LPARAM lparam) -{ TRACE("%p %p %8lx\n", p1, p2, lparam); +{ LPSIC_ENTRY e1 = (LPSIC_ENTRY)p1, e2 = (LPSIC_ENTRY)p2; + + TRACE("%p %p %8lx\n", p1, p2, lparam);
- if (((LPSIC_ENTRY)p1)->dwSourceIndex != ((LPSIC_ENTRY)p2)->dwSourceIndex) /* first the faster one*/ + /* Icons in the cache are keyed by the name of the file they are + * loaded from, their resource index and the fact if they have a shortcut + * icon overlay or not. + */ + if (e1->dwSourceIndex != e2->dwSourceIndex || /* first the faster one */ + (e1->dwFlags & GIL_FORSHORTCUT) != (e2->dwFlags & GIL_FORSHORTCUT)) return 1;
- if (strcmpiW(((LPSIC_ENTRY)p1)->sSourceFile,((LPSIC_ENTRY)p2)->sSourceFile) ) + if (strcmpiW(e1->sSourceFile,e2->sSourceFile)) return 1;
return 0; } +
/*********************************************************************** ****** + * SIC_OverlayShortcutImage [internal] + * + * NOTES + * Creates a new icon as a copy of the passed-in icon, overlayed with a + * shortcut image. + */ +static HICON SIC_OverlayShortcutImage(HICON SourceIcon) +{ ICONINFO SourceIconInfo, ShortcutIconInfo, TargetIconInfo; + HICON ShortcutIcon, TargetIcon; + BITMAP SourceBitmapInfo, ShortcutBitmapInfo; + HDC SourceDC = NULL, + ShortcutDC = NULL, + TargetDC = NULL, + ScreenDC = NULL; + HBITMAP OldSourceBitmap = NULL, + OldShortcutBitmap = NULL, + OldTargetBitmap = NULL; + + /* Get information about the source icon and shortcut overlay */ + if (! GetIconInfo(SourceIcon, &SourceIconInfo) + || 0 == GetObjectW(SourceIconInfo.hbmColor, sizeof(BITMAP), &SourceBitmapInfo)) + { + return NULL; + } + ShortcutIcon = LoadImageW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_SHORTCUT), + IMAGE_ICON, SourceBitmapInfo.bmWidth, SourceBitmapInfo.bmWidth, + LR_SHARED); + if (NULL == ShortcutIcon + || ! GetIconInfo(ShortcutIcon, &ShortcutIconInfo) + || 0 == GetObjectW(ShortcutIconInfo.hbmColor, sizeof(BITMAP), &ShortcutBitmapInfo)) + { + return NULL; + } + + TargetIconInfo = SourceIconInfo; + TargetIconInfo.hbmMask = NULL; + TargetIconInfo.hbmColor = NULL; + + /* Setup the source, shortcut and target masks */ + SourceDC = CreateCompatibleDC(NULL); + if (NULL == SourceDC) goto fail; + OldSourceBitmap = SelectObject(SourceDC, SourceIconInfo.hbmMask); + if (NULL == OldSourceBitmap) goto fail; + + ShortcutDC = CreateCompatibleDC(NULL); + if (NULL == ShortcutDC) goto fail; + OldShortcutBitmap = SelectObject(ShortcutDC, ShortcutIconInfo.hbmMask); + if (NULL == OldShortcutBitmap) goto fail; + + TargetDC = CreateCompatibleDC(NULL); + if (NULL == TargetDC) goto fail; + TargetIconInfo.hbmMask = CreateCompatibleBitmap(TargetDC, SourceBitmapInfo.bmWidth, + SourceBitmapInfo.bmHeight); + if (NULL == TargetIconInfo.hbmMask) goto fail; + ScreenDC = GetDC(NULL); + if (NULL == ScreenDC) goto fail; + TargetIconInfo.hbmColor = CreateCompatibleBitmap(ScreenDC, SourceBitmapInfo.bmWidth, + SourceBitmapInfo.bmHeight); + ReleaseDC(NULL, ScreenDC); + if (NULL == TargetIconInfo.hbmColor) goto fail; + OldTargetBitmap = SelectObject(TargetDC, TargetIconInfo.hbmMask); + if (NULL == OldTargetBitmap) goto fail; + + /* Create the target mask by ANDing the source and shortcut masks */ + if (! BitBlt(TargetDC, 0, 0, SourceBitmapInfo.bmWidth, SourceBitmapInfo.bmHeight, + SourceDC, 0, 0, SRCCOPY) || + ! BitBlt(TargetDC, 0, SourceBitmapInfo.bmHeight - ShortcutBitmapInfo.bmHeight, + ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight, + ShortcutDC, 0, 0, SRCAND)) + { + goto fail; + } + + /* Setup the source and target xor bitmap */ + if (NULL == SelectObject(SourceDC, SourceIconInfo.hbmColor) || + NULL == SelectObject(TargetDC, TargetIconInfo.hbmColor)) + { + goto fail; + } + + /* Copy the source xor bitmap to the target and clear out part of it by using + the shortcut mask */ + if (! BitBlt(TargetDC, 0, 0, SourceBitmapInfo.bmWidth, SourceBitmapInfo.bmHeight, + SourceDC, 0, 0, SRCCOPY) || + ! BitBlt(TargetDC, 0, SourceBitmapInfo.bmHeight - ShortcutBitmapInfo.bmHeight, + ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight, + ShortcutDC, 0, 0, SRCAND)) + { + goto fail; + } + + if (NULL == SelectObject(ShortcutDC, ShortcutIconInfo.hbmColor)) goto fail; + + /* Now put in the shortcut xor mask */ + if (! BitBlt(TargetDC, 0, SourceBitmapInfo.bmHeight - ShortcutBitmapInfo.bmHeight, + ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight, + ShortcutDC, 0, 0, SRCINVERT)) + { + goto fail; + } + + /* Clean up, we're not goto'ing to 'fail' after this so we can be lazy and not set + handles to NULL */ + SelectObject(TargetDC, OldTargetBitmap); + DeleteObject(TargetDC); + SelectObject(ShortcutDC, OldShortcutBitmap); + DeleteObject(ShortcutDC); + SelectObject(SourceDC, OldSourceBitmap); + DeleteObject(SourceDC); + + /* Create the icon using the bitmaps prepared earlier */ + TargetIcon = CreateIconIndirect(&TargetIconInfo); + + /* CreateIconIndirect copies the bitmaps, so we can release our bitmaps now */ + DeleteObject(TargetIconInfo.hbmColor); + DeleteObject(TargetIconInfo.hbmMask); + + return TargetIcon; + +fail: + /* Clean up scratch resources we created */ + if (NULL != OldTargetBitmap) SelectObject(TargetDC, OldTargetBitmap); + if (NULL != TargetIconInfo.hbmColor) DeleteObject(TargetIconInfo.hbmColor); + if (NULL != TargetIconInfo.hbmMask) DeleteObject(TargetIconInfo.hbmMask); + if (NULL != TargetDC) DeleteObject(TargetDC); + if (NULL != OldShortcutBitmap) SelectObject(ShortcutDC, OldShortcutBitmap); + if (NULL != ShortcutDC) DeleteObject(ShortcutDC); [truncated at 1000 lines; 1448 more skipped]