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]