SHELL32: Implement IContextMenu::QueryContextMenu and IContextMenu::InvokeCommand.

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

SHELL32: Implement IContextMenu::QueryContextMenu and IContextMenu::InvokeCommand.

Mike McCormack
ChangeLog:
Implement IContextMenu::QueryContextMenu and IContextMenu::InvokeCommand.

bb74acbb33b361d3199cc0eb54fe7f4ca44308ce
diff --git a/dlls/shell32/shelllink.c b/dlls/shell32/shelllink.c
--- a/dlls/shell32/shelllink.c
+++ b/dlls/shell32/shelllink.c
@@ -157,6 +157,7 @@ typedef struct
  volume_info   volume;
 
  BOOL          bDirty;
+        INT           iIdOpen;  /* id of the "Open" entry in the context menu */
  IUnknown      *site;
 } IShellLinkImpl;
 
@@ -1189,6 +1190,7 @@ HRESULT WINAPI IShellLink_Constructor( I
  sl->lpvtblObjectWithSite = &owsvt;
  sl->iShowCmd = SW_SHOWNORMAL;
  sl->bDirty = FALSE;
+ sl->iIdOpen = -1;
  sl->site = NULL;
 
  TRACE("(%p)->()\n",sl);
@@ -2372,21 +2374,98 @@ ShellLink_QueryContextMenu( IContextMenu
                             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 HRESULT WINAPI
 ShellLink_InvokeCommand( IContextMenu* iface, LPCMINVOKECOMMANDINFO lpici )
 {
     IShellLinkImpl *This = impl_from_IContextMenu(iface);
+    SHELLEXECUTEINFOW sei;
+    HWND hwnd = NULL; /* FIXME: get using interface set from IObjectWithSite */
+    LPWSTR args = 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->sProduct || This->sComponent )
+    {
+        FIXME("MSI advertised shortcut %s %s\n",
+              debugstr_w( This->sProduct ),
+              debugstr_w( This->sComponent ) );
+        return E_NOTIMPL;
+    }
+
+    if ( lpici->cbSize == sizeof (CMINVOKECOMMANDINFOEX) &&
+         ( lpici->fMask & CMIC_MASK_UNICODE ) )
+    {
+        LPCMINVOKECOMMANDINFOEX iciex = (LPCMINVOKECOMMANDINFOEX) lpici;
+        DWORD len = 0;
+
+        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 )
+            lstrcatW( args, iciex->lpParametersW );
+    }
+
+    memset( &sei, 0, sizeof sei );
+    sei.cbSize = sizeof sei;
+    sei.lpFile = This->sPath;
+    sei.nShow = This->iShowCmd;
+    sei.lpIDList = This->pPidl;
+    sei.lpDirectory = This->sWorkDir;
+    sei.lpParameters = args;
+
+    if( ShellExecuteExW( &sei ) )
+        r = S_OK;
+    else
+        r = E_FAIL;
+
+    HeapFree( GetProcessHeap(), 0, args );
+
+    return r;
 }
 
 static HRESULT WINAPI