Vitaliy Margolen <wine-patch@kievinfo.com>
- Michael Jung <mjung@iss.tu-darmstadt.de>
  Set all capability flags supported by the shellfolder, disregarding
  the flag mask given to GetAttributesOf.
  Unit tests to demonstrate this behaviour.
Michael Jung <mjung@iss.tu-darmstadt.de>
- Added some comments to document unixfs.
- Fixed crash in unixfs shellfolder handling with winamp.
- Implemented UnixFolder's IPersistPropertyBag::Load method.
- Initialize COM prior to displaying the SHBrowseForFolder dialog.
- More robust code for querying ShellFolder attributes (some
  ShellFolders ignore the flag mask in GetAttributesOf).
- Remove iconcache pre-initialization hack, it's not necessary any
  more.
- Move target folder initialization to a dedicated function.
- Use this function in BindToObject (should be faster).
- Special handling for FolderShortcut objects in Initialize method.
- Removed a todo_wine from a no longer failing unit test.
- Replaced tabs with spaces.
Robert Shearman <rob@codeweavers.com>
- Convert SHELL32_BindToChild to Unicode and fix up the callers.
Vincent Bén <vberon@mecano.gme.usherb.ca>
- Unicodify systray.c.
- Move functions a bit to get rid of a static declaration.
Dmitry Timoshkov <dmitry@codeweavers.com>
- Correctly handle flags parameter in SHAddToRecentDocs.
Martin Fuchs <martin-fuchs@gmx.net>
- Correct WINAPI position for MSVC portability.
Mike McCormack <mike@codeweavers.com>
- Partially implement and test the shelllink object's
  IShellLinkDataList::CopyDataBlock and GetFlags methods.
- Use advapi32.CommandLineFromMsiDescriptor to get msi component paths.
- Pass the correct verb.
  Add a space between extra parameters.
  Wait for ShellExecute to complete.
- Handle MSI advertised shortcuts in the shelllink object.
- Implement IContextMenu::QueryContextMenu and
  IContextMenu::InvokeCommand.
- Add the IObjectWithSite interface.
- Invoke shortcuts through IContextMenu, rather than trying to access
  them directly.
- Fix a problem spotted by Dmitry and another one stopping correctly
  formatted lnk files from being generated.
Modified: trunk/reactos/bootdata/hivecls.inf
Modified: trunk/reactos/include/wine/shobjidl.h
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/enumidlist.c
Modified: trunk/reactos/lib/shell32/iconcache.c
Modified: trunk/reactos/lib/shell32/pidl.c
Modified: trunk/reactos/lib/shell32/shell.c
Modified: trunk/reactos/lib/shell32/shell32_main.h
Modified: trunk/reactos/lib/shell32/shelllink.c
Modified: trunk/reactos/lib/shell32/shellole.c
Modified: trunk/reactos/lib/shell32/shellord.c
Modified: trunk/reactos/lib/shell32/shellpath.c
Modified: trunk/reactos/lib/shell32/shellstring.c
Modified: trunk/reactos/lib/shell32/shfldr.h
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/shlmenu.c
Modified: trunk/reactos/lib/shell32/systray.c
Added: trunk/reactos/w32api/include/appmgmt.h
Modified: trunk/reactos/w32api/include/shlobj.h

Modified: trunk/reactos/bootdata/hivecls.inf
--- trunk/reactos/bootdata/hivecls.inf	2005-11-20 03:16:26 UTC (rev 19355)
+++ trunk/reactos/bootdata/hivecls.inf	2005-11-20 08:41:46 UTC (rev 19356)
@@ -21,6 +21,7 @@
 HKCR,"lnkfile","IsShortcut",0x00000000,"yes"
 HKCR,"lnkfile\CLSID","",0x00000000,"{00021401-0000-0000-C000-000000000046}"
 HKCR,"lnkfile\shellex\IconHandler","",0x00000000,"{00021401-0000-0000-C000-000000000046}"
+HKCR,lnkfile\shellex\ContextMenuHandlers\{00021401-0000-0000-C000-000000000046},,,
 
 ; shell command files (e.g. "Show Desktop" in quicklaunch bar)
 HKCR,".scf","",0x00000000,"SHCmdFile"

Modified: trunk/reactos/include/wine/shobjidl.h
--- trunk/reactos/include/wine/shobjidl.h	2005-11-20 03:16:26 UTC (rev 19355)
+++ trunk/reactos/include/wine/shobjidl.h	2005-11-20 08:41:46 UTC (rev 19356)
@@ -43,4 +43,13 @@
 /*** IShellExecuteHookW methods ***/
 #define IShellExecuteHookW_Execute(p,a) (p)->lpVtbl->Execute(p,a)
 
+#ifdef COBJMACROS
+/*** IUnknown methods ***/
+#define IShellExtInit_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IShellExtInit_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IShellExtInit_Release(p) (p)->lpVtbl->Release(p)
+/*** IShellExtInit methods ***/
+#define IShellExtInit_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c)
+#endif
+
 #endif /* __WINE_SHOBJIDL_H */

Modified: trunk/reactos/lib/shell32/Makefile.in
--- trunk/reactos/lib/shell32/Makefile.in	2005-11-20 03:16:26 UTC (rev 19355)
+++ trunk/reactos/lib/shell32/Makefile.in	2005-11-20 08:41:46 UTC (rev 19356)
@@ -6,7 +6,7 @@
 MODULE    = shell32.dll
 IMPORTLIB = libshell32.$(IMPLIBEXT)
 IMPORTS   = shlwapi comctl32 user32 gdi32 advapi32 kernel32 ntdll
-DELAYIMPORTS = ole32
+DELAYIMPORTS = ole32 oleaut32
 EXTRALIBS = -luuid $(LIBUNICODE)
 
 C_SRCS = \

Modified: trunk/reactos/lib/shell32/brsfolder.c
--- trunk/reactos/lib/shell32/brsfolder.c	2005-11-20 03:16:26 UTC (rev 19355)
+++ trunk/reactos/lib/shell32/brsfolder.c	2005-11-20 08:41:46 UTC (rev 19356)
@@ -388,7 +388,7 @@
         dwAttributes = SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM;
         r = IShellFolder_GetAttributesOf(lptvid->lpsfParent, 1,
                                 (LPCITEMIDLIST*)&lptvid->lpi, &dwAttributes);
-        if (FAILED(r) || !dwAttributes)
+        if (FAILED(r) || !(dwAttributes & (SFGAO_FILESYSANCESTOR|SFGAO_FILESYSTEM)))
             bEnabled = FALSE;
     }
     if (lpBrowseInfo->ulFlags & BIF_RETURNONLYFSDIRS)
@@ -396,8 +396,11 @@
         dwAttributes = SFGAO_FOLDER | SFGAO_FILESYSTEM;
         r = IShellFolder_GetAttributesOf(lptvid->lpsfParent, 1,
                                 (LPCITEMIDLIST*)&lptvid->lpi, &dwAttributes);
-        if (FAILED(r) || (dwAttributes != (SFGAO_FOLDER | SFGAO_FILESYSTEM)))
+        if (FAILED(r) || 
+            ((dwAttributes & (SFGAO_FOLDER|SFGAO_FILESYSTEM)) != (SFGAO_FOLDER|SFGAO_FILESYSTEM)))
+        {
             bEnabled = FALSE;
+        }
     }
     SendMessageW(info->hWnd, BFFM_ENABLEOK, 0, (LPARAM)bEnabled);
 }
@@ -662,21 +665,25 @@
 /*************************************************************************
  * SHBrowseForFolderW [SHELL32.@]
  *
- * NOTES:
+ * NOTES
  *  crashes when passed a null pointer
  */
 LPITEMIDLIST WINAPI SHBrowseForFolderW (LPBROWSEINFOW lpbi)
 {
     browse_info info;
     DWORD r;
+    HRESULT hr;
 
     info.hWnd = 0;
     info.pidlRet = NULL;
     info.lpBrowseInfo = lpbi;
     info.hwndTreeView = NULL;
 
+    hr = CoInitialize(NULL);
     r = DialogBoxParamW( shell32_hInstance, swBrowseTemplateName, lpbi->hwndOwner,
 	                 BrsFolderDlgProc, (LPARAM)&info );
+    if (SUCCEEDED(hr)) 
+        CoUninitialize();
     if (!r)
         return NULL;
 

Modified: trunk/reactos/lib/shell32/cpanelfolder.c
--- trunk/reactos/lib/shell32/cpanelfolder.c	2005-11-20 03:16:26 UTC (rev 19355)
+++ trunk/reactos/lib/shell32/cpanelfolder.c	2005-11-20 08:41:46 UTC (rev 19356)
@@ -410,7 +410,7 @@
     WIN32_FIND_DATAA wfd;
     HANDLE hFile;
 
-    TRACE("(%p)->(flags=0x%08lx) \n",iface,dwFlags);
+    TRACE("(%p)->(flags=0x%08lx)\n", iface, dwFlags);
 
     /* enumerate control panel folders folders */
     if (dwFlags & SHCONTF_FOLDERS)

Modified: trunk/reactos/lib/shell32/enumidlist.c
--- trunk/reactos/lib/shell32/enumidlist.c	2005-11-20 03:16:26 UTC (rev 19355)
+++ trunk/reactos/lib/shell32/enumidlist.c	2005-11-20 08:41:46 UTC (rev 19356)
@@ -116,7 +116,7 @@
     static const WCHAR dot[] = { '.',0 };
     static const WCHAR dotdot[] = { '.','.',0 };
 
-    TRACE("(%p)->(path=%s flags=0x%08lx) \n",list,debugstr_w(lpszPath),dwFlags);
+    TRACE("(%p)->(path=%s flags=0x%08lx)\n", list, debugstr_w(lpszPath), dwFlags);
 
     if(!lpszPath || !lpszPath[0]) return FALSE;
 

Modified: trunk/reactos/lib/shell32/iconcache.c
--- trunk/reactos/lib/shell32/iconcache.c	2005-11-20 03:16:26 UTC (rev 19355)
+++ trunk/reactos/lib/shell32/iconcache.c	2005-11-20 08:41:46 UTC (rev 19356)
@@ -365,7 +365,7 @@
 
 	if ( INVALID_INDEX == index )
 	{
-	  ret = SIC_LoadIcon (sSourceFile, dwSourceIndex, dwFlags);
+          ret = SIC_LoadIcon (sSourceFile, dwSourceIndex, dwFlags);
 	}
 	else
 	{
@@ -378,15 +378,10 @@
 }
 /*****************************************************************************
  * SIC_Initialize			[internal]
- *
- * NOTES
- *  hack to load the resources from the shell32.dll under a different dll name
- *  will be removed when the resource-compiler is ready
  */
 BOOL SIC_Initialize(void)
 {
 	HICON		hSm, hLg;
-	UINT		index;
 	int		cx_small, cy_small;
 	int		cx_large, cy_large;
 
@@ -407,29 +402,27 @@
 	  return(FALSE);
 	}
 
-	ShellSmallIconList = ImageList_Create(16,16,ILC_COLOR32|ILC_MASK,0,0x20);
-	ShellBigIconList = ImageList_Create(32,32,ILC_COLOR32|ILC_MASK,0,0x20);
+        ShellSmallIconList = ImageList_Create(cx_small,cy_small,ILC_COLOR32|ILC_MASK,0,0x20);
+        ShellBigIconList = ImageList_Create(cx_large,cy_large,ILC_COLOR32|ILC_MASK,0,0x20);
 
-	ImageList_SetBkColor(ShellSmallIconList, CLR_NONE);
-	ImageList_SetBkColor(ShellBigIconList, CLR_NONE);
+        ImageList_SetBkColor(ShellSmallIconList, CLR_NONE);
+        ImageList_SetBkColor(ShellBigIconList, CLR_NONE);
 
-	/*
-	 * Wine will extract and cache all shell32 icons here. That's because
-	 * they are unable to extract resources from their built-in DLLs.
-	 * We don't need that, but we still want to make sure that the very
-	 * first icon in the image lists is icon 1 from shell32.dll, since
-	 * that's the default icon.
-	 */
-	index = 1;
-	hSm = (HICON)LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(index), IMAGE_ICON, cx_small, cy_small, LR_SHARED);
-	hLg = (HICON)LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(index), IMAGE_ICON, cx_large, cy_large, LR_SHARED);
+        /* Load the document icon, which is used as the default if an icon isn't found. */
+        hSm = (HICON)LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(IDI_SHELL_DOCUMENT), 
+                                IMAGE_ICON, cx_small, cy_small, LR_SHARED);
+        hLg = (HICON)LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(IDI_SHELL_DOCUMENT), 
+                                IMAGE_ICON, cx_large, cy_large, LR_SHARED);
 
-	if(hSm)
-	{
-          SIC_IconAppend (swShell32Name, index - 1, hSm, hLg, 0);
-          SIC_IconAppend (swShell32Name, -index, hSm, hLg, 0);
-	}
+        if (!hSm || !hLg) 
+        {
+          FIXME("Failed to load IDI_SHELL_DOCUMENT icon!\n");
+          return FALSE;
+        }
 
+        SIC_IconAppend (swShell32Name, IDI_SHELL_DOCUMENT-1, hSm, hLg, 0);
+        SIC_IconAppend (swShell32Name, -IDI_SHELL_DOCUMENT, hSm, hLg, 0);
+   
 	TRACE("hIconSmall=%p hIconBig=%p\n",ShellSmallIconList, ShellBigIconList);
 
 	return TRUE;

Modified: trunk/reactos/lib/shell32/pidl.c
--- trunk/reactos/lib/shell32/pidl.c	2005-11-20 03:16:26 UTC (rev 19355)
+++ trunk/reactos/lib/shell32/pidl.c	2005-11-20 08:41:46 UTC (rev 19356)
@@ -254,7 +254,7 @@
     DWORD len;
     LPITEMIDLIST pidlNew = NULL;
 
-    TRACE("pidl=%p \n",pidl);
+    TRACE("pidl=%p\n", pidl);
     pdump(pidl);
 
     if (pidl)
@@ -885,6 +885,9 @@
  * PARAMS
  *  pidl         [I]
  *
+ * RETURNS
+ *  Nothing
+ *
  * NOTES
  *  exported by ordinal
  */
@@ -903,6 +906,9 @@
  * PARAMS
  *  pidl         [I]
  *
+ * RETURNS
+ *  Nothing
+ *
  * NOTES
  *  exported by ordinal.
  */
@@ -941,6 +947,8 @@
 
 /*************************************************************************
  * ILCreateFromPathW         [SHELL32.190]
+ *
+ * See ILCreateFromPathA.
  */
 LPITEMIDLIST WINAPI ILCreateFromPathW (LPCWSTR path)
 {
@@ -1238,6 +1246,8 @@
 
 /*************************************************************************
  * SHGetPathFromIDListW             [SHELL32.@]
+ *
+ * See SHGetPathFromIDListA.
  */
 BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
 {

Modified: trunk/reactos/lib/shell32/shell.c
--- trunk/reactos/lib/shell32/shell.c	2005-11-20 03:16:26 UTC (rev 19355)
+++ trunk/reactos/lib/shell32/shell.c	2005-11-20 08:41:46 UTC (rev 19356)
@@ -335,12 +335,13 @@
  * from "DOS" environment. If it is not found the %KEYWORD% is left
  * intact. If the buffer is too small, str is not modified.
  *
- * str         [I] '\0' terminated string with %keyword%.
+ * PARAMS
+ *  str        [I] '\0' terminated string with %keyword%.
  *             [O] '\0' terminated string with %keyword% substituted.
- * length      [I] size of str.
+ *  length     [I] size of str.
  *
- * Return
- *     str length in the LOWORD and 1 in HIWORD if subst was successful.
+ * RETURNS
+ *  str length in the LOWORD and 1 in HIWORD if subst was successful.
  */
 DWORD WINAPI DoEnvironmentSubst16(LPSTR str,WORD length)
 {
@@ -625,7 +626,7 @@
     seiW.dwHotKey = 0;
     seiW.hProcess = hProcess;
 
-    SHELL_execute( &seiW, SHELL_Execute16, FALSE );
+    SHELL_execute( &seiW, SHELL_Execute16 );
 
     if (wVerb) SHFree(wVerb);
     if (wFile) SHFree(wFile);

Modified: trunk/reactos/lib/shell32/shell32_main.h
--- trunk/reactos/lib/shell32/shell32_main.h	2005-11-20 03:16:26 UTC (rev 19355)
+++ trunk/reactos/lib/shell32/shell32_main.h	2005-11-20 08:41:46 UTC (rev 19356)
@@ -213,7 +213,7 @@
 typedef UINT_PTR (*SHELL_ExecuteW32)(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
 			    LPSHELLEXECUTEINFOW sei, LPSHELLEXECUTEINFOW sei_out);
 
-BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc, BOOL unicode);
+BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc);
 
 UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation,
                           LPWSTR lpResult, int resultLen, LPWSTR key, WCHAR **env, LPITEMIDLIST pidl, LPCWSTR args);

Modified: trunk/reactos/lib/shell32/shelllink.c
--- trunk/reactos/lib/shell32/shelllink.c	2005-11-20 03:16:26 UTC (rev 19355)
+++ trunk/reactos/lib/shell32/shelllink.c	2005-11-20 08:41:46 UTC (rev 19356)
@@ -51,6 +51,8 @@
 #include "shell32_main.h"
 #include "shlguid.h"
 #include "shlwapi.h"
+#include "msi.h"
+#include "appmgmt.h"
 
 #include "initguid.h"
 
@@ -120,6 +122,7 @@
 static const IShellLinkDataListVtbl dlvt;
 static const IShellExtInitVtbl eivt;
 static const IContextMenuVtbl cmvt;
+static const IObjectWithSiteVtbl owsvt;
 
 /* IShellLink Implementation */
 
@@ -132,6 +135,7 @@
 	const IShellLinkDataListVtbl *lpvtblShellLinkDataList;
 	const IShellExtInitVtbl *lpvtblShellExtInit;
 	const IContextMenuVtbl *lpvtblContextMenu;
+	const IObjectWithSiteVtbl *lpvtblObjectWithSite;
 
 	LONG            ref;
 
@@ -154,7 +158,9 @@
  	LPWSTR        sComponent;
 	volume_info   volume;
 
-	BOOL		bDirty;
+	BOOL          bDirty;
+        INT           iIdOpen;  /* id of the "Open" entry in the context menu */
+	IUnknown      *site;
 } IShellLinkImpl;
 
 static inline IShellLinkImpl *impl_from_IShellLinkW( IShellLinkW *iface )
@@ -187,6 +193,11 @@
     return (IShellLinkImpl *)((char*)iface - FIELD_OFFSET(IShellLinkImpl, lpvtblContextMenu));
 }
 
+static inline IShellLinkImpl *impl_from_IObjectWithSite( IObjectWithSite *iface )
+{
+    return (IShellLinkImpl *)((char*)iface - FIELD_OFFSET(IShellLinkImpl, lpvtblObjectWithSite));
+}
+
 static HRESULT ShellLink_UpdatePath(LPWSTR sPathRel, LPCWSTR path, LPCWSTR sWorkDir, LPWSTR* psPath);
 
 /* strdup on the process heap */
@@ -200,6 +211,16 @@
     return p;
 }
 
+inline static LPWSTR strdupW( LPCWSTR src )
+{
+    LPWSTR dest;
+    if (!src) return NULL;
+    dest = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(src)+1)*sizeof(WCHAR) );
+    if (dest)
+        lstrcpyW(dest, src);
+    return dest;
+}
+
 /**************************************************************************
  *  ShellLink::QueryInterface implementation
  */
@@ -237,6 +258,10 @@
     {
         *ppvObj = &(This->lpvtblContextMenu);
     }
+    else if(IsEqualIID(riid, &IID_IObjectWithSite))
+    {
+        *ppvObj = &(This->lpvtblObjectWithSite);
+    }
 
     if(*ppvObj)
     {
@@ -280,6 +305,9 @@
     HeapFree(GetProcessHeap(), 0, This->sDescription);
     HeapFree(GetProcessHeap(),0,This->sPath);
 
+    if (This->site)
+        IUnknown_Release( This->site );
+
     if (This->pPidl)
         ILFree(This->pPidl);
 
@@ -986,20 +1014,29 @@
     return IStream_Write( stm, loc, total_size, &count );
 }
 
+static EXP_DARWIN_LINK* shelllink_build_darwinid( LPCWSTR string, DWORD magic )
+{
+    EXP_DARWIN_LINK *buffer;
+    
+    buffer = LocalAlloc( LMEM_ZEROINIT, sizeof *buffer );
+    buffer->dbh.cbSize = sizeof *buffer;
+    buffer->dbh.dwSignature = magic;
+    lstrcpynW( buffer->szwDarwinID, string, MAX_PATH );
+    WideCharToMultiByte(CP_ACP, 0, string, -1, buffer->szDarwinID, MAX_PATH, NULL, NULL );
+
+    return buffer;
+}
+
 static HRESULT Stream_WriteAdvertiseInfo( IStream* stm, LPCWSTR string, DWORD magic )
 {
+    EXP_DARWIN_LINK *buffer;
     ULONG count;
-    EXP_DARWIN_LINK buffer;
     
     TRACE("%p\n",stm);
 
-    memset( &buffer, 0, sizeof buffer );
-    buffer.dbh.cbSize = sizeof buffer;
-    buffer.dbh.dwSignature = magic;
-    lstrcpynW( buffer.szwDarwinID, string, MAX_PATH );
-    WideCharToMultiByte(CP_ACP, 0, string, -1, buffer.szDarwinID, MAX_PATH, NULL, NULL );
+    buffer = shelllink_build_darwinid( string, magic );
 
-    return IStream_Write( stm, &buffer, buffer.dbh.cbSize, &count );
+    return IStream_Write( stm, buffer, buffer->dbh.cbSize, &count );
 }
 
 /************************************************************************
@@ -1075,7 +1112,7 @@
         return r;
     }
 
-    TRACE("Writing pidl \n");
+    TRACE("Writing pidl\n");
 
     /* write the PIDL to the shortcut */
     if( This->pPidl )
@@ -1172,8 +1209,11 @@
 	sl->lpvtblShellLinkDataList = &dlvt;
 	sl->lpvtblShellExtInit = &eivt;
 	sl->lpvtblContextMenu = &cmvt;
+	sl->lpvtblObjectWithSite = &owsvt;
 	sl->iShowCmd = SW_SHOWNORMAL;
 	sl->bDirty = FALSE;
+	sl->iIdOpen = -1;
+	sl->site = NULL;
 
 	TRACE("(%p)->()\n",sl);
 
@@ -2215,8 +2255,32 @@
 static HRESULT WINAPI
 ShellLink_CopyDataBlock( IShellLinkDataList* iface, DWORD dwSig, void** ppDataBlock )
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    IShellLinkImpl *This = impl_from_IShellLinkDataList(iface);
+    LPVOID block = NULL;
+    HRESULT r = E_FAIL;
+
+    TRACE("%p %08lx %p\n", iface, dwSig, ppDataBlock );
+
+    switch (dwSig)
+    {
+    case EXP_DARWIN_ID_SIG:
+        if (!This->sComponent)
+            break;
+        block = shelllink_build_darwinid( This->sComponent, dwSig );
+        r = S_OK;
+        break;
+    case EXP_SZ_LINK_SIG:
+    case NT_CONSOLE_PROPS_SIG:
+    case NT_FE_CONSOLE_PROPS_SIG:
+    case EXP_SPECIAL_FOLDER_SIG:
+    case EXP_SZ_ICON_SIG:
+        FIXME("valid but unhandled datablock %08lx\n", dwSig);
+        break;
+    default:
+        ERR("unknown datablock %08lx\n", dwSig);
+    }
+    *ppDataBlock = block;
+    return r;
 }
 
 static HRESULT WINAPI
@@ -2229,8 +2293,26 @@
 static HRESULT WINAPI
 ShellLink_GetFlags( IShellLinkDataList* iface, DWORD* pdwFlags )
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    IShellLinkImpl *This = impl_from_IShellLinkDataList(iface);
+    DWORD flags = 0;
+
+    FIXME("%p %p\n", This, pdwFlags );
+
+    /* FIXME: add more */
+    if (This->sArgs)
+        flags |= SLDF_HAS_ARGS;
+    if (This->sComponent)
+        flags |= SLDF_HAS_DARWINID;
+    if (This->sIcoPath)
+        flags |= SLDF_HAS_ICONLOCATION;
+    if (This->sProduct)
+        flags |= SLDF_HAS_LOGO3ID;
+    if (This->pPidl)
+        flags |= SLDF_HAS_ID_LIST;
+
+    *pdwFlags = flags;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI
@@ -2358,21 +2440,139 @@
                             UINT idCmdFirst, UINT idCmdLast, UINT uFlags )
 {
     IShellLinkImpl *This = impl_from_IContextMenu(iface);
+    static const WCHAR szOpen[] = { 'O','p','e','n',0 };
+    MENUITEMINFOW mii;
+    int id = 1;
 
-    FIXME("%p %p %u %u %u %u\n", This,
+    TRACE("%p %p %u %u %u %u\n", This,
           hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags );
 
-    return E_NOTIMPL;
+    if ( !hmenu )
+        return E_INVALIDARG;
+
+    memset( &mii, 0, sizeof mii );
+    mii.cbSize = sizeof mii;
+    mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
+    mii.dwTypeData = (LPWSTR)szOpen;
+    mii.cch = strlenW( mii.dwTypeData );
+    mii.wID = idCmdFirst + id++;
+    mii.fState = MFS_DEFAULT | MFS_ENABLED;
+    mii.fType = MFT_STRING;
+    if (!InsertMenuItemW( hmenu, indexMenu, TRUE, &mii ))
+        return E_FAIL;
+    This->iIdOpen = 0;
+
+    return MAKE_HRESULT( SEVERITY_SUCCESS, 0, id );
 }
 
+static LPWSTR
+shelllink_get_msi_component_path( LPWSTR component )
+{
+    LPWSTR path = NULL;
+    DWORD r, sz = 0;
+
+    r = CommandLineFromMsiDescriptor( component, NULL, &sz );
+    if (r != ERROR_SUCCESS)
+         return path;
+
+    sz++;
+    path = HeapAlloc( GetProcessHeap(), 0, sz*sizeof(WCHAR) );
+    r = CommandLineFromMsiDescriptor( component, path, &sz );
+    if (r != ERROR_SUCCESS)
+    {
+        HeapFree( GetProcessHeap(), 0, path );
+        path = NULL;
+    }
+
+    TRACE("returning %s\n", debugstr_w( path ) );
+
+    return path;
+}
+
 static HRESULT WINAPI
 ShellLink_InvokeCommand( IContextMenu* iface, LPCMINVOKECOMMANDINFO lpici )
 {
     IShellLinkImpl *This = impl_from_IContextMenu(iface);
+    static const WCHAR szOpen[] = { 'O','p','e','n',0 };
+    SHELLEXECUTEINFOW sei;
+    HWND hwnd = NULL; /* FIXME: get using interface set from IObjectWithSite */
+    LPWSTR args = NULL;
+    LPWSTR path = NULL;
+    HRESULT r;
 
-    FIXME("%p %p\n", This, lpici );
+    TRACE("%p %p\n", This, lpici );
 
-    return E_NOTIMPL;
+    if ( lpici->cbSize < sizeof (CMINVOKECOMMANDINFO) )
+        return E_INVALIDARG;
+
+    if ( lpici->lpVerb != MAKEINTRESOURCEA(This->iIdOpen) )
+    {
+        ERR("Unknown id %d != %d\n", (INT)lpici->lpVerb, This->iIdOpen );
+        return E_INVALIDARG;
+    }
+
+    r = IShellLinkW_Resolve( (IShellLinkW*)&(This->lpvtblw), hwnd, 0 );
+    if ( FAILED( r ) )
+        return r;
+
+    if ( This->sComponent )
+    {
+        path = shelllink_get_msi_component_path( This->sComponent );
+        if (!path)
+            return E_FAIL;
+    }
+    else
+        path = strdupW( This->sPath );
+
+    if ( lpici->cbSize == sizeof (CMINVOKECOMMANDINFOEX) &&
+         ( lpici->fMask & CMIC_MASK_UNICODE ) )
+    {
+        LPCMINVOKECOMMANDINFOEX iciex = (LPCMINVOKECOMMANDINFOEX) lpici;
+        DWORD len = 2;
+
+        if ( This->sArgs )
+            len += lstrlenW( This->sArgs );
+        if ( iciex->lpParametersW )
+            len += lstrlenW( iciex->lpParametersW );
+
+        args = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
+        args[0] = 0;
+        if ( This->sArgs )
+            lstrcatW( args, This->sArgs );
+        if ( iciex->lpParametersW )
+        {
+            static const WCHAR space[] = { ' ', 0 };
+            lstrcatW( args, space );
+            lstrcatW( args, iciex->lpParametersW );
+        }
+    }
+
+    memset( &sei, 0, sizeof sei );
+    sei.cbSize = sizeof sei;
+    sei.fMask = SEE_MASK_UNICODE | SEE_MASK_NOCLOSEPROCESS;
+    sei.lpFile = path;
+    sei.nShow = This->iShowCmd;
+    sei.lpIDList = This->pPidl;
+    sei.lpDirectory = This->sWorkDir;
+    sei.lpParameters = args;
+    sei.lpVerb = szOpen;
+
+    if( ShellExecuteExW( &sei ) )
+    {
+        if ( sei.hProcess )
+        {
+            WaitForSingleObject( sei.hProcess, 10000 );
+            CloseHandle( sei.hProcess );
+        }
+        r = S_OK;
+    }
+    else
+        r = E_FAIL;
+
+    HeapFree( GetProcessHeap(), 0, args );
+    HeapFree( GetProcessHeap(), 0, path );
+
+    return r;
 }
 
 static HRESULT WINAPI
@@ -2396,3 +2596,59 @@
     ShellLink_InvokeCommand,
     ShellLink_GetCommandString
 };
+
+static HRESULT WINAPI
+ShellLink_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
+{
+    IShellLinkImpl *This = impl_from_IObjectWithSite(iface);
+    return ShellLink_QueryInterface( This, riid, ppvObject );
+}
+
+static ULONG WINAPI
+ShellLink_ObjectWithSite_AddRef( IObjectWithSite* iface )
+{
+    IShellLinkImpl *This = impl_from_IObjectWithSite(iface);
+    return ShellLink_AddRef( This );
+}
+
+static ULONG WINAPI
+ShellLink_ObjectWithSite_Release( IObjectWithSite* iface )
+{
+    IShellLinkImpl *This = impl_from_IObjectWithSite(iface);
+    return ShellLink_Release( This );
+}
+
+static HRESULT WINAPI
+ShellLink_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
+{
+    IShellLinkImpl *This = impl_from_IObjectWithSite(iface);
+
+    TRACE("%p %s %p\n", This, debugstr_guid( iid ), ppvSite );
+
+    if ( !This->site )
+        return E_FAIL;
+    return IUnknown_QueryInterface( This->site, iid, ppvSite );
+}
+
+static HRESULT WINAPI
+ShellLink_SetSite( IObjectWithSite *iface, IUnknown *punk )
+{
+    IShellLinkImpl *This = impl_from_IObjectWithSite(iface);
+
+    TRACE("%p %p\n", iface, punk);
+
+    if ( punk )
+        IUnknown_AddRef( punk );
+    This->site = punk;
+
+    return S_OK;
+}
+
+static const IObjectWithSiteVtbl owsvt =
+{
+    ShellLink_ObjectWithSite_QueryInterface,
+    ShellLink_ObjectWithSite_AddRef,
+    ShellLink_ObjectWithSite_Release,
+    ShellLink_SetSite,
+    ShellLink_GetSite,
+};

Modified: trunk/reactos/lib/shell32/shellole.c
--- trunk/reactos/lib/shell32/shellole.c	2005-11-20 03:16:26 UTC (rev 19355)
+++ trunk/reactos/lib/shell32/shellole.c	2005-11-20 08:41:46 UTC (rev 19356)
@@ -689,8 +689,8 @@
 }
 
 /*************************************************************************
+ *  DragQueryFileA		[SHELL32.@]
  *  DragQueryFile 		[SHELL32.@]
- *  DragQueryFileA		[SHELL32.@]
  */
 UINT WINAPI DragQueryFileA(
 	HDROP hDrop,

Modified: trunk/reactos/lib/shell32/shellord.c
--- trunk/reactos/lib/shell32/shellord.c	2005-11-20 03:16:26 UTC (rev 19355)
+++ trunk/reactos/lib/shell32/shellord.c	2005-11-20 08:41:46 UTC (rev 19356)
@@ -622,12 +622,17 @@
 /*************************************************************************
  * SHAddToRecentDocs				[SHELL32.@]
  *
+ * Modify (add/clear) Shell's list of recently used documents.
+ *
  * PARAMETERS
- *   uFlags  [IN] SHARD_PATH or SHARD_PIDL
+ *   uFlags  [IN] SHARD_PATHA, SHARD_PATHW or SHARD_PIDL
  *   pv      [IN] string or pidl, NULL clears the list
  *
  * NOTES
  *     exported by name
+ *
+ * FIXME
+ *  convert to unicode
  */
 void WINAPI SHAddToRecentDocs (UINT uFlags,LPCVOID pv)
 {
@@ -652,6 +657,8 @@
     INT ret;
     DWORD data[64], datalen, type;
 
+    TRACE("%04x %p\n", uFlags, pv);
+
     /*FIXME: Document:
      *  RecentDocs MRU data structure seems to be:
      *    +0h   document file name w/ terminating 0h
@@ -732,7 +739,7 @@
 	 *    DeleteFileA(old_lnk_name);
 	 * }
 	 */
-	FIXME("should delete all files in %s\\ \n", link_dir);
+	FIXME("should delete all files in %s\\\n", link_dir);
 
 	/* clear MRU list
 	 */
@@ -757,15 +764,28 @@
 
     /* Get the pure document name from the input
      */
-    if (uFlags & SHARD_PIDL) {
+    switch (uFlags)
+    {
+    case SHARD_PIDL:
 	SHGetPathFromIDListA((LPCITEMIDLIST) pv, doc_name);
+        break;
+
+    case SHARD_PATHA:
+        lstrcpynA(doc_name, (LPCSTR)pv, MAX_PATH);
+        break;
+
+    case SHARD_PATHW:
+        WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)pv, -1, doc_name, MAX_PATH, NULL, NULL);
+        break;
+
+    default:
+        FIXME("Unsupported flags: %u\n", uFlags);
+        return;
     }
-    else {
-	lstrcpyA(doc_name, (LPCSTR) pv);
-    }
-    TRACE("full document name %s\n", doc_name);
+
+    TRACE("full document name %s\n", debugstr_a(doc_name));
     PathStripPathA(doc_name);
-    TRACE("stripped document name %s\n", doc_name);
+    TRACE("stripped document name %s\n", debugstr_a(doc_name));
 
 
     /* ***  JOB 1: Update registry for ...\Explorer\RecentDocs list  *** */
@@ -902,7 +922,7 @@
 	    }
 
 	    /* Set the document path or pidl */
-	    if (uFlags & SHARD_PIDL) {
+	    if (uFlags == SHARD_PIDL) {
 		hres = IShellLinkA_SetIDList(psl, (LPCITEMIDLIST) pv);
 	    } else {
 		hres = IShellLinkA_SetPath(psl, (LPCSTR) pv);
@@ -955,6 +975,12 @@
 /*************************************************************************
  * SHCreateShellFolderViewEx			[SHELL32.174]
  *
+ * Create a new instance of the default Shell folder view object.
+ *
+ * RETURNS
+ *  Success: S_OK
+ *  Failure: error value
+ *
  * NOTES
  *  see IShellFolder::CreateViewObject
  */
@@ -1125,7 +1151,7 @@
 	HKEY hkey = 0;
 	DWORD type, r;
 
-	TRACE("%p %d \n",cs,length);
+	TRACE("%p %d\n", cs, length);
 
 	if( (cs == NULL) || (length < (int)sizeof(*cs))  )
 		return FALSE;
@@ -1319,10 +1345,11 @@
 /************************************************************************
  *	@				[SHELL32.654]
  *
- * NOTES: first parameter seems to be a pointer (same as passed to WriteCabinetState)
- * second one could be a size (0x0c). The size is the same as the structure saved to
- * HCU\Software\Microsoft\Windows\CurrentVersion\Explorer\CabinetState
- * I'm (js) guessing: this one is just ReadCabinetState ;-)
+ * NOTES
+ *  first parameter seems to be a pointer (same as passed to WriteCabinetState)
+ *  second one could be a size (0x0c). The size is the same as the structure saved to
+ *  HCU\Software\Microsoft\Windows\CurrentVersion\Explorer\CabinetState
+ *  I'm (js) guessing: this one is just ReadCabinetState ;-)
  */
 HRESULT WINAPI shell32_654 (CABINETSTATE *cs, int length)
 {
@@ -1357,11 +1384,12 @@
  * from environment. If it is not found the %KEYWORD% is left
  * intact. If the buffer is too small, str is not modified.
  *
- * pszString   [I] '\0' terminated string with %keyword%.
+ * PARAMS
+ *  pszString  [I] '\0' terminated string with %keyword%.
  *             [O] '\0' terminated string with %keyword% substituted.
- * cchString   [I] size of str.
+ *  cchString  [I] size of str.
  *
- * Return
+ * RETURNS
  *     cchString length in the HIWORD;
  *     TRUE in LOWORD if subst was successful and FALSE in other case
  */
@@ -1388,6 +1416,7 @@
 /************************************************************************
  *	DoEnvironmentSubstW			[SHELL32.@]
  *
+ * See DoEnvironmentSubstA.  
  */
 DWORD WINAPI DoEnvironmentSubstW(LPWSTR pszString, UINT cchString)
 {
@@ -1398,6 +1427,7 @@
 /************************************************************************
  *	DoEnvironmentSubst			[SHELL32.53]
  *
+ * See DoEnvironmentSubstA.  
  */
 DWORD WINAPI DoEnvironmentSubstAW(LPVOID x, UINT y)
 {
@@ -1563,6 +1593,9 @@
  *  uFlags      [I] Flags determining the icon attributes. See notes.
  *  iImageIndex [I] Index of the icon in the system image list.
  *
+ * RETURNS
+ *  Nothing
+ *
  * NOTES
  *  uFlags can be one or more of the following flags:
  *  GIL_NOTFILENAME - pszHashItem is not a file name.
@@ -1573,6 +1606,11 @@
     FIXME("%s, %d, 0x%x, %d - stub\n", debugstr_w(pszHashItem), iIndex, uFlags, iImageIndex);
 }
 
+/*************************************************************************
+ *		SHUpdateImageA (SHELL32.191)
+ *
+ * See SHUpdateImageW.
+ */
 VOID WINAPI SHUpdateImageA(LPCSTR pszHashItem, INT iIndex, UINT uFlags, INT iImageIndex)
 {
     FIXME("%s, %d, 0x%x, %d - stub\n", debugstr_a(pszHashItem), iIndex, uFlags, iImageIndex);

Modified: trunk/reactos/lib/shell32/shellpath.c
--- trunk/reactos/lib/shell32/shellpath.c	2005-11-20 03:16:26 UTC (rev 19355)
+++ trunk/reactos/lib/shell32/shellpath.c	2005-11-20 08:41:46 UTC (rev 19356)
@@ -1562,8 +1562,14 @@
 /*************************************************************************
  * SHGetFolderPathW			[SHELL32.@]
  *
+ * Convert nFolder to path.  
+ *
+ * RETURNS
+ *  Success: S_OK
+ *  Failure: standard HRESULT error codes.
+ *
  * NOTES
- * Converts nFolder to path.  Most values can be overridden in either
+ * Most values can be overridden in either
  * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
  * or in the same location in HKLM.
  * The registry usage is explained by the following tech note:
@@ -1577,13 +1583,13 @@
  * http://www.microsoft.com/windows2000/techinfo/reskit/en-us/default.asp?url=/windows2000/techinfo/reskit/en-us/regentry/36276.asp
  * the HKCU paths take precedence over the HKLM paths.
  *
- **********************************************************************/
+ */
 HRESULT WINAPI SHGetFolderPathW(
-	HWND hwndOwner,
-	int nFolder,
-	HANDLE hToken,
-	DWORD dwFlags,
-	LPWSTR pszPath)
+	HWND hwndOwner,    /* [I] owner window */
+	int nFolder,       /* [I] CSIDL identifing the folder */
+	HANDLE hToken,     /* [I] access token */
+	DWORD dwFlags,     /* [I] which path to return */
+	LPWSTR pszPath)    /* [O] converted path */
 {
     HRESULT    hr;
     WCHAR      szBuildPath[MAX_PATH], szTemp[MAX_PATH];
@@ -1689,6 +1695,8 @@
 
 /*************************************************************************
  * SHGetFolderPathA			[SHELL32.@]
+ *
+ * See SHGetFolderPathW.
  */
 HRESULT WINAPI SHGetFolderPathA(
 	HWND hwndOwner,
@@ -1928,11 +1936,7 @@
 /*************************************************************************
  * SHGetFolderLocation [SHELL32.@]
  *
- * NOTES
  * Gets the folder locations from the registry and creates a pidl.
- * Creates missing reg keys and directories.
- * Mostly forwards to SHGetFolderPathW, but a few values of nFolder return
- * virtual folders that are handled here.
  *
  * PARAMS
  *   hwndOwner  [I]
@@ -1942,7 +1946,14 @@
  *   dwReserved [I] must be zero
  *   ppidl      [O] PIDL of a special folder
  *
+ * RETURNS
+ *  Success: S_OK
+ *  Failure: Standard OLE-defined error result, S_FALSE or E_INVALIDARG
+ *
  * NOTES
+ *  Creates missing reg keys and directories.
+ *  Mostly forwards to SHGetFolderPathW, but a few values of nFolder return
+ *  virtual folders that are handled here.
  */
 HRESULT WINAPI SHGetFolderLocation(
 	HWND hwndOwner,

Modified: trunk/reactos/lib/shell32/shellstring.c
--- trunk/reactos/lib/shell32/shellstring.c	2005-11-20 03:16:26 UTC (rev 19355)
+++ trunk/reactos/lib/shell32/shellstring.c	2005-11-20 08:41:46 UTC (rev 19356)
@@ -260,7 +260,7 @@
 /*************************************************************************
  * CheckEscapesW             [SHELL32.@]
  *
- * see CheckEscapesA
+ * See CheckEscapesA.
  */
 DWORD WINAPI CheckEscapesW(
 	LPWSTR	string,

Modified: trunk/reactos/lib/shell32/shfldr.h
--- trunk/reactos/lib/shell32/shfldr.h	2005-11-20 03:16:26 UTC (rev 19355)
+++ trunk/reactos/lib/shell32/shfldr.h	2005-11-20 08:41:46 UTC (rev 19356)
@@ -43,7 +43,7 @@
 				       DWORD dwOutLen);
 
 HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot,
-			     LPCSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut);
+			     LPCWSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut);
 
[truncated at 1000 lines; 1222 more skipped]