Only use the Folder class handler if we're actually executing a folder.
[reactos.git] / reactos / lib / shell32 / shlexec.c
index 14bab16..2a9b12a 100644 (file)
@@ -57,6 +57,8 @@ static const WCHAR wszShell[] = {'\\','s','h','e','l','l','\\',0};
 static const WCHAR wszFolder[] = {'F','o','l','d','e','r',0};
 static const WCHAR wszEmpty[] = {0};
 
+#define SEE_MASK_CLASSALL (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY)
+
 
 /***********************************************************************
  *     SHELL_ArgifyW [Internal]
@@ -80,6 +82,7 @@ static BOOL SHELL_ArgifyW(WCHAR* out, int len, const WCHAR* fmt, const WCHAR* lp
 {
     WCHAR   xlpFile[1024];
     BOOL    done = FALSE;
+    BOOL    found_p1 = FALSE;
     PWSTR   res = out;
     PCWSTR  cmd;
     LPVOID  pv;
@@ -153,6 +156,7 @@ static BOOL SHELL_ArgifyW(WCHAR* out, int len, const WCHAR* fmt, const WCHAR* lp
                         res += strlenW(cmd);
                     }
                 }
+                found_p1 = TRUE;
                 break;
 
             /*
@@ -166,6 +170,7 @@ static BOOL SHELL_ArgifyW(WCHAR* out, int len, const WCHAR* fmt, const WCHAR* lp
                    strcpyW(res, lpFile);
                    res += strlenW(lpFile);
                }
+                found_p1 = TRUE;
                 break;
 
             case 'i':
@@ -176,11 +181,12 @@ static BOOL SHELL_ArgifyW(WCHAR* out, int len, const WCHAR* fmt, const WCHAR* lp
                    res += sprintfW(res, wszILPtr, pv);
                    SHUnlockShared(pv);
                }
+                found_p1 = TRUE;
                 break;
 
            default:
                 /*
-                 * Check if this is a env-variable here...
+                 * Check if this is an env-variable here...
                  */
 
                 /* Make sure that we have at least one more %.*/
@@ -195,7 +201,7 @@ static BOOL SHELL_ArgifyW(WCHAR* out, int len, const WCHAR* fmt, const WCHAR* lp
                         *tmpB++ = *fmt++;
                     *tmpB++ = 0;
 
-                    TRACE("Checking %s to be a env-var\n", debugstr_w(tmpBuffer));
+                    TRACE("Checking %s to be an env-var\n", debugstr_w(tmpBuffer));
 
                     envRet = GetEnvironmentVariableW(tmpBuffer, tmpEnvBuff, MAX_PATH);
                     if (envRet == 0 || envRet > MAX_PATH)
@@ -219,7 +225,7 @@ static BOOL SHELL_ArgifyW(WCHAR* out, int len, const WCHAR* fmt, const WCHAR* lp
 
     *res = '\0';
 
-    return done;
+    return found_p1;
 }
 
 HRESULT SHELL_GetPathFromIDListForExecuteA(LPCITEMIDLIST pidl, LPSTR pszPath, UINT uOutSize)
@@ -260,80 +266,16 @@ HRESULT SHELL_GetPathFromIDListForExecuteW(LPCITEMIDLIST pidl, LPWSTR pszPath, U
     return hr;
 }
 
-/*************************************************************************
- *     SHELL_ResolveShortCutW [Internal]
- *     read shortcut file at 'wcmd'
- */
-static HRESULT SHELL_ResolveShortCutW(LPWSTR wcmd, LPWSTR wargs, LPWSTR wdir, HWND hwnd, LPCWSTR lpVerb, int* pshowcmd, LPITEMIDLIST* ppidl)
-{
-    IShellFolder* psf;
-
-    HRESULT hr = SHGetDesktopFolder(&psf);
-
-    *ppidl = NULL;
-
-    if (SUCCEEDED(hr)) {
-       LPITEMIDLIST pidl;
-       ULONG l;
-
-       hr = IShellFolder_ParseDisplayName(psf, 0, 0, wcmd, &l, &pidl, 0);
-
-       if (SUCCEEDED(hr)) {
-           IShellLinkW* psl;
-
-           hr = IShellFolder_GetUIObjectOf(psf, NULL, 1, (LPCITEMIDLIST*)&pidl, &IID_IShellLinkW, NULL, (LPVOID*)&psl);
-
-           if (SUCCEEDED(hr)) {
-               hr = IShellLinkW_Resolve(psl, hwnd, 0);
-
-               if (SUCCEEDED(hr)) {
-                   hr = IShellLinkW_GetPath(psl, wcmd, MAX_PATH, NULL, SLGP_UNCPRIORITY);
-
-                   if (SUCCEEDED(hr)) {
-                       if (!*wcmd) {
-                           /* We could not translate the PIDL in the shell link into a valid file system path - so return the PIDL instead. */
-                           hr = IShellLinkW_GetIDList(psl, ppidl);
-
-                           if (SUCCEEDED(hr) && *ppidl) {
-                               /* We got a PIDL instead of a file system path - try to translate it. */
-                               if (SUCCEEDED(SHELL_GetPathFromIDListW(*ppidl, wcmd, MAX_PATH))) {
-                                   SHFree(*ppidl);
-                                   *ppidl = NULL;
-                               }
-                           }
-                       }
-
-                       if (SUCCEEDED(hr)) {
-                           /* get command line arguments, working directory and display mode if available */
-                           IShellLinkW_GetWorkingDirectory(psl, wdir, MAX_PATH);
-                           IShellLinkW_GetArguments(psl, wargs, MAX_PATH);
-                           IShellLinkW_GetShowCmd(psl, pshowcmd);
-                       }
-                   }
-               }
-
-               IShellLinkW_Release(psl);
-           }
-
-           SHFree(pidl);
-       }
-
-       IShellFolder_Release(psf);
-    }
-
-    return hr;
-}
-
 /*************************************************************************
  *     SHELL_ExecuteW [Internal]
  *
  */
-static UINT SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
+static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
                            LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
 {
     STARTUPINFOW  startup;
     PROCESS_INFORMATION info;
-    UINT retval = 31;
+    UINT_PTR retval = 31;
     UINT gcdret = 0;
     WCHAR curdir[MAX_PATH];
 
@@ -365,7 +307,7 @@ static UINT SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
     }
     else if ((retval = GetLastError()) >= 32)
     {
-        FIXME("Strange error set by CreateProcess: %d\n", retval);
+        TRACE("CreateProcess returned error %d\n", retval);
         retval = ERROR_BAD_FORMAT;
     }
 
@@ -743,7 +685,7 @@ UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation,
 /******************************************************************
  *             dde_cb
  *
- * callback for the DDE connection. not really usefull
+ * callback for the DDE connection. not really useful
  */
 static HDDEDATA CALLBACK dde_cb(UINT uType, UINT uFmt, HCONV hConv,
                                 HSZ hsz1, HSZ hsz2, HDDEDATA hData,
@@ -766,7 +708,7 @@ static HDDEDATA CALLBACK dde_cb(UINT uType, UINT uFmt, HCONV hConv,
 static unsigned dde_connect(WCHAR* key, WCHAR* start, WCHAR* ddeexec,
                             const WCHAR* lpFile, WCHAR *env,
                            LPCWSTR szCommandline, LPITEMIDLIST pidl, SHELL_ExecuteW32 execfunc,
-                           LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
+                            LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
 {
     static const WCHAR wApplication[] = {'\\','a','p','p','l','i','c','a','t','i','o','n',0};
     static const WCHAR wTopic[] = {'\\','t','o','p','i','c',0};
@@ -780,6 +722,7 @@ static unsigned dde_connect(WCHAR* key, WCHAR* start, WCHAR* ddeexec,
     HCONV       hConv;
     HDDEDATA    hDdeData;
     unsigned    ret = 31;
+    BOOL unicode = !(GetVersion() & 0x80000000);
 
     strcpyW(endkey, wApplication);
     applen = sizeof(app);
@@ -797,9 +740,15 @@ static unsigned dde_connect(WCHAR* key, WCHAR* start, WCHAR* ddeexec,
         strcpyW(topic, wSystem);
     }
 
-    if (DdeInitializeW(&ddeInst, dde_cb, APPCMD_CLIENTONLY, 0L) != DMLERR_NO_ERROR)
+    if (unicode)
     {
-        return 2;
+        if (DdeInitializeW(&ddeInst, dde_cb, APPCMD_CLIENTONLY, 0L) != DMLERR_NO_ERROR)
+            return 2;
+    }
+    else
+    {
+        if (DdeInitializeA(&ddeInst, dde_cb, APPCMD_CLIENTONLY, 0L) != DMLERR_NO_ERROR)
+            return 2;
     }
 
     hszApp = DdeCreateStringHandleW(ddeInst, app, CP_WINUNICODE);
@@ -839,8 +788,18 @@ static unsigned dde_connect(WCHAR* key, WCHAR* start, WCHAR* ddeexec,
     /* It's documented in the KB 330337 that IE has a bug and returns
      * error DMLERR_NOTPROCESSED on XTYP_EXECUTE request.
      */
-    hDdeData = DdeClientTransaction((LPBYTE)res, (strlenW(res) + 1) * sizeof(WCHAR), hConv, 0L, 0,
-                                     XTYP_EXECUTE, 10000, &tid);
+    if (unicode)
+        hDdeData = DdeClientTransaction((LPBYTE)res, (strlenW(res) + 1) * sizeof(WCHAR), hConv, 0L, 0,
+                                         XTYP_EXECUTE, 10000, &tid);
+    else
+    {
+        DWORD lenA = WideCharToMultiByte(CP_ACP, 0, res, -1, NULL, 0, NULL, NULL);
+        char *resA = HeapAlloc(GetProcessHeap(), 0, lenA);
+        WideCharToMultiByte(CP_ACP, 0, res, -1, resA, lenA, NULL, NULL);
+        hDdeData = DdeClientTransaction( (LPBYTE)resA, lenA, hConv, 0L, 0,
+                                         XTYP_EXECUTE, 10000, &tid );
+        HeapFree(GetProcessHeap(), 0, resA);
+    }
     if (hDdeData)
         DdeFreeDataHandle(hDdeData);
     else
@@ -858,13 +817,13 @@ static unsigned dde_connect(WCHAR* key, WCHAR* start, WCHAR* ddeexec,
 /*************************************************************************
  *     execute_from_key [Internal]
  */
-static UINT execute_from_key(LPWSTR key, LPCWSTR lpFile, WCHAR *env, LPCWSTR szCommandline,
+static UINT_PTR execute_from_key(LPWSTR key, LPCWSTR lpFile, WCHAR *env, LPCWSTR szCommandline,
                             SHELL_ExecuteW32 execfunc,
-                            LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
+                             LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
 {
     WCHAR cmd[1024];
     LONG cmdlen = sizeof(cmd);
-    UINT retval = 31;
+    UINT_PTR retval = 31;
 
     cmd[0] = '\0';
 
@@ -922,7 +881,7 @@ HINSTANCE WINAPI FindExecutableA(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResu
     if (wDirectory) SHFree( wDirectory );
 
     TRACE("returning %s\n", lpResult);
-    return (HINSTANCE)retval;
+    return retval;
 }
 
 /*************************************************************************
@@ -930,7 +889,7 @@ HINSTANCE WINAPI FindExecutableA(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResu
  */
 HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory, LPWSTR lpResult)
 {
-    UINT retval = 31;    /* default - 'No association was found' */
+    UINT_PTR retval = 31;    /* default - 'No association was found' */
     WCHAR old_dir[1024];
 
     TRACE("File %s, Dir %s\n",
@@ -959,18 +918,278 @@ HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory, LPWSTR lpR
     return (HINSTANCE)retval;
 }
 
+/* FIXME: is this already implemented somewhere else? */
+static HKEY ShellExecute_GetClassKey( LPSHELLEXECUTEINFOW sei )
+{
+    LPCWSTR ext = NULL, lpClass = NULL;
+    LPWSTR cls = NULL;
+    DWORD type = 0, sz = 0;
+    HKEY hkey = 0;
+    LONG r;
+
+    if (sei->fMask & SEE_MASK_CLASSALL)
+        return sei->hkeyClass;
+    if (sei->fMask & SEE_MASK_CLASSNAME)
+        lpClass = sei->lpClass;
+    else
+    {
+        ext = PathFindExtensionW( sei->lpFile );
+        TRACE("ext = %s\n", debugstr_w( ext ) );
+        if (!ext)
+            return hkey;
+
+        r = RegOpenKeyW( HKEY_CLASSES_ROOT, ext, &hkey );
+        if (r != ERROR_SUCCESS )
+            return hkey;
+
+        r = RegQueryValueExW( hkey, NULL, 0, &type, NULL, &sz );
+        if ( r == ERROR_SUCCESS && type == REG_SZ )
+        {
+            sz += sizeof (WCHAR);
+            cls = HeapAlloc( GetProcessHeap(), 0, sz );
+            cls[0] = 0;
+            RegQueryValueExW( hkey, NULL, 0, &type, (LPBYTE) cls, &sz );
+        }
+
+        RegCloseKey( hkey );
+        lpClass = cls;
+    }
+
+    TRACE("class = %s\n", debugstr_w(lpClass) );
+
+    hkey = 0;
+    if ( lpClass )
+        RegOpenKeyW( HKEY_CLASSES_ROOT, lpClass, &hkey );
+
+    HeapFree( GetProcessHeap(), 0, cls );
+
+    return hkey;
+}
+
+static IDataObject *shellex_get_dataobj( LPSHELLEXECUTEINFOW sei )
+{
+    LPCITEMIDLIST pidllast = NULL;
+    IDataObject *dataobj = NULL;
+    IShellFolder *shf = NULL;
+    LPITEMIDLIST pidl = NULL;
+    HRESULT r;
+
+    if (sei->fMask & SEE_MASK_CLASSALL)
+        pidl = sei->lpIDList;
+    else
+    {
+        WCHAR fullpath[MAX_PATH];
+
+        fullpath[0] = 0;
+        r = GetFullPathNameW( sei->lpFile, MAX_PATH, fullpath, NULL );
+        if (!r)
+            goto end;
+
+        pidl = ILCreateFromPathW( fullpath );
+    }
+
+    r = SHBindToParent( pidl, &IID_IShellFolder, (LPVOID*)&shf, &pidllast );
+    if ( FAILED( r ) )
+        goto end;
+
+    IShellFolder_GetUIObjectOf( shf, NULL, 1, &pidllast,
+                                &IID_IDataObject, NULL, (LPVOID*) &dataobj );
+
+end:
+    if ( pidl != sei->lpIDList )
+        ILFree( pidl );
+    if ( shf )
+        IShellFolder_Release( shf );
+    return dataobj;
+}
+
+static HRESULT shellex_run_context_menu_default( IShellExtInit *obj,
+                                                 LPSHELLEXECUTEINFOW sei )
+{
+    IContextMenu *cm = NULL;
+    CMINVOKECOMMANDINFOEX ici;
+    MENUITEMINFOW info;
+    WCHAR string[0x80];
+    INT i, n, def = -1;
+    HMENU hmenu = 0;
+    HRESULT r;
+
+    TRACE("%p %p\n", obj, sei );
+
+    r = IShellExtInit_QueryInterface( obj, &IID_IContextMenu, (LPVOID*) &cm );
+    if ( FAILED( r ) )
+        return r;
+
+    hmenu = CreateMenu();
+    if ( !hmenu )
+        goto end;
+
+    /* the number of the last menu added is returned in r */
+    r = IContextMenu_QueryContextMenu( cm, hmenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY );
+    if ( FAILED( r ) )
+        goto end;
+
+    n = GetMenuItemCount( hmenu );
+    for ( i = 0; i < n; i++ )
+    {
+        memset( &info, 0, sizeof info );
+        info.cbSize = sizeof info;
+        info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE | MIIM_DATA | MIIM_ID;
+        info.dwTypeData = string;
+        info.cch = sizeof string;
+        string[0] = 0;
+        GetMenuItemInfoW( hmenu, i, TRUE, &info );
+
+        TRACE("menu %d %s %08x %08lx %08x %08x\n", i, debugstr_w(string),
+            info.fState, info.dwItemData, info.fType, info.wID );
+        if ( ( !sei->lpVerb && (info.fState & MFS_DEFAULT) ) ||
+             ( sei->lpVerb && !lstrcmpiW( sei->lpVerb, string ) ) )
+        {
+            def = i;
+            break;
+        }
+    }
+
+    r = E_FAIL;
+    if ( def == -1 )
+        goto end;
+
+    memset( &ici, 0, sizeof ici );
+    ici.cbSize = sizeof ici;
+    ici.fMask = CMIC_MASK_UNICODE;
+    ici.nShow = sei->nShow;
+    ici.lpVerb = MAKEINTRESOURCEA( def );
+    ici.hwnd = sei->hwnd;
+    ici.lpParametersW = sei->lpParameters;
+    
+    r = IContextMenu_InvokeCommand( cm, (LPCMINVOKECOMMANDINFO) &ici );
+
+    TRACE("invoke command returned %08lx\n", r );
+
+end:
+    if ( hmenu )
+        DestroyMenu( hmenu );
+    if ( cm )
+        IContextMenu_Release( cm );
+    return r;
+}
+
+static HRESULT shellex_load_object_and_run( HKEY hkey, LPCGUID guid, LPSHELLEXECUTEINFOW sei )
+{
+    IDataObject *dataobj = NULL;
+    IObjectWithSite *ows = NULL;
+    IShellExtInit *obj = NULL;
+    HRESULT r;
+
+    TRACE("%p %s %p\n", hkey, debugstr_guid( guid ), sei );
+
+    r = CoInitialize( NULL );
+    if ( FAILED( r ) )
+        goto end;
+
+    r = CoCreateInstance( guid, NULL, CLSCTX_INPROC_SERVER,
+                           &IID_IShellExtInit, (LPVOID*)&obj );
+    if ( FAILED( r ) )
+    {
+        ERR("failed %08lx\n", r );
+        goto end;
+    }
+
+    dataobj = shellex_get_dataobj( sei );
+    if ( !dataobj )
+    {
+        ERR("failed to get data object\n");
+        goto end;
+    }
+
+    r = IShellExtInit_Initialize( obj, NULL, dataobj, hkey );
+    if ( FAILED( r ) )
+        goto end;
+
+    r = IShellExtInit_QueryInterface( obj, &IID_IObjectWithSite, (LPVOID*) &ows );
+    if ( FAILED( r ) )
+        goto end;
+
+    IObjectWithSite_SetSite( ows, NULL );
+
+    r = shellex_run_context_menu_default( obj, sei );
+
+end:
+    if ( ows )
+        IObjectWithSite_Release( ows );
+    if ( dataobj )
+        IDataObject_Release( dataobj );
+    if ( obj )
+        IShellExtInit_Release( obj );
+    CoUninitialize();
+    return r;
+}
+
+
+/*************************************************************************
+ *     ShellExecute_FromContextMenu [Internal]
+ */
+static LONG ShellExecute_FromContextMenu( LPSHELLEXECUTEINFOW sei )
+{
+    static const WCHAR szcm[] = { 's','h','e','l','l','e','x','\\',
+        'C','o','n','t','e','x','t','M','e','n','u','H','a','n','d','l','e','r','s',0 };
+    HKEY hkey, hkeycm = 0;
+    WCHAR szguid[39];
+    HRESULT hr;
+    GUID guid;
+    DWORD i;
+    LONG r;
+
+    TRACE("%s\n", debugstr_w(sei->lpFile) );
+
+    hkey = ShellExecute_GetClassKey( sei );
+    if ( !hkey )
+        return ERROR_FUNCTION_FAILED;
+
+    r = RegOpenKeyW( hkey, szcm, &hkeycm );
+    if ( r == ERROR_SUCCESS )
+    {
+        i = 0;
+        while ( 1 )
+        {
+            r = RegEnumKeyW( hkeycm, i++, szguid, 39 );
+            if ( r != ERROR_SUCCESS )
+                break;
+
+            hr = CLSIDFromString( szguid, &guid );
+            if (SUCCEEDED(hr))
+            {
+                /* stop at the first one that succeeds in running */
+                hr = shellex_load_object_and_run( hkey, &guid, sei );
+                if ( SUCCEEDED( hr ) )
+                    break;
+            }
+        }
+        RegCloseKey( hkeycm );
+    }
+
+    if ( hkey != sei->hkeyClass )
+        RegCloseKey( hkey );
+    return r;
+}
+
 /*************************************************************************
- *     ShellExecuteExW32 [Internal]
+ *     SHELL_execute [Internal]
  */
-BOOL WINAPI ShellExecuteExW32 (LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
+BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
 {
     static const WCHAR wQuote[] = {'"',0};
     static const WCHAR wSpace[] = {' ',0};
     static const WCHAR wWww[] = {'w','w','w',0};
     static const WCHAR wFile[] = {'f','i','l','e',0};
     static const WCHAR wHttp[] = {'h','t','t','p',':','/','/',0};
-    static const WCHAR wExtLnk[] = {'.','l','n','k',0};
     static const WCHAR wExplorer[] = {'e','x','p','l','o','r','e','r','.','e','x','e',0};
+    static const DWORD unsupportedFlags =
+        SEE_MASK_INVOKEIDLIST  | SEE_MASK_ICON         | SEE_MASK_HOTKEY |
+        SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI |
+        SEE_MASK_UNICODE       | SEE_MASK_NO_CONSOLE   | SEE_MASK_ASYNCOK |
+        SEE_MASK_HMONITOR;
 
     WCHAR wszApplicationName[MAX_PATH+2], wszParameters[1024], wszDir[MAX_PATH];
     SHELLEXECUTEINFOW sei_tmp; /* modifiable copy of SHELLEXECUTEINFO struct */
@@ -978,11 +1197,12 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfun
     WCHAR *env;
     WCHAR lpstrProtocol[256];
     LPCWSTR lpFile;
-    UINT retval = 31;
+    UINT_PTR retval = 31;
     WCHAR wcmd[1024];
     WCHAR buffer[MAX_PATH];
-    const WCHAR* ext;
+    WCHAR target[MAX_PATH];
     BOOL done;
+    DWORD attribs;
 
     /* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */
     memcpy(&sei_tmp, sei, sizeof(sei_tmp));
@@ -991,15 +1211,25 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfun
             sei_tmp.fMask, sei_tmp.hwnd, debugstr_w(sei_tmp.lpVerb),
             debugstr_w(sei_tmp.lpFile), debugstr_w(sei_tmp.lpParameters),
             debugstr_w(sei_tmp.lpDirectory), sei_tmp.nShow,
-            (sei_tmp.fMask & SEE_MASK_CLASSNAME) ? debugstr_w(sei_tmp.lpClass) : "not used");
+            ((sei_tmp.fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSNAME) ?
+                debugstr_w(sei_tmp.lpClass) : "not used");
 
     sei->hProcess = NULL;
 
     /* make copies of all path/command strings */
-    if (sei_tmp.lpFile)
-       strcpyW(wszApplicationName, sei_tmp.lpFile);
+    if (!sei_tmp.lpFile)
+        *wszApplicationName = '\0';
+    else if (*sei_tmp.lpFile == '\"')
+    {
+        UINT l;
+        strcpyW(wszApplicationName, sei_tmp.lpFile+1);
+        l=lstrlenW(wszApplicationName);
+        if (wszApplicationName[l-1] == '\"')
+            wszApplicationName[l-1] = '\0';
+        TRACE("wszApplicationName=%s\n",debugstr_w(wszApplicationName));
+    }
     else
-       *wszApplicationName = '\0';
+        strcpyW(wszApplicationName, sei_tmp.lpFile);
 
     if (sei_tmp.lpParameters)
        strcpyW(wszParameters, sei_tmp.lpParameters);
@@ -1016,12 +1246,9 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfun
     sei_tmp.lpParameters = wszParameters;
     sei_tmp.lpDirectory = wszDir;
 
-    if (sei_tmp.fMask & (SEE_MASK_INVOKEIDLIST | SEE_MASK_ICON | SEE_MASK_HOTKEY |
-        SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT |
-        SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_NO_UI | SEE_MASK_UNICODE |
-        SEE_MASK_NO_CONSOLE | SEE_MASK_ASYNCOK | SEE_MASK_HMONITOR ))
+    if (sei_tmp.fMask & unsupportedFlags)
     {
-        FIXME("flags ignored: 0x%08lx\n", sei_tmp.fMask);
+        FIXME("flags ignored: 0x%08lx\n", sei_tmp.fMask & unsupportedFlags);
     }
 
     /* process the IDList */
@@ -1033,7 +1260,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfun
 
        if (SUCCEEDED(hr))
        {
-           hr = IShellExecuteHookW_Execute(pSEH, sei);
+           hr = IShellExecuteHookW_Execute(pSEH, &sei_tmp);
 
            IShellExecuteHookW_Release(pSEH);
 
@@ -1041,19 +1268,24 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfun
                return TRUE;
        }
 
-        wszApplicationName[0] = '"';
-        SHGetPathFromIDListW(sei_tmp.lpIDList, wszApplicationName+1);
-        strcatW(wszApplicationName, wQuote);
+        SHGetPathFromIDListW(sei_tmp.lpIDList, wszApplicationName);
         TRACE("-- idlist=%p (%s)\n", sei_tmp.lpIDList, debugstr_w(wszApplicationName));
     }
 
-    if (sei_tmp.fMask & (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY))
+    if ( ERROR_SUCCESS == ShellExecute_FromContextMenu( &sei_tmp ) )
+    {
+        sei->hInstApp = (HINSTANCE) 33;
+        return TRUE;
+    }
+
+    if (sei_tmp.fMask & SEE_MASK_CLASSALL)
     {
        /* launch a document by fileclass like 'WordPad.Document.1' */
         /* the Commandline contains 'c:\Path\wordpad.exe "%1"' */
         /* FIXME: szCommandline should not be of a fixed size. Fixed to 1024, MAX_PATH is way too short! */
-        HCR_GetExecuteCommandW((sei_tmp.fMask & SEE_MASK_CLASSKEY) ? sei_tmp.hkeyClass : NULL,
-                               (sei_tmp.fMask & SEE_MASK_CLASSNAME) ? sei_tmp.lpClass: NULL,
+        ULONG cmask=(sei_tmp.fMask & SEE_MASK_CLASSALL);
+        HCR_GetExecuteCommandW((cmask == SEE_MASK_CLASSKEY) ? sei_tmp.hkeyClass : NULL,
+                               (cmask == SEE_MASK_CLASSNAME) ? sei_tmp.lpClass: NULL,
                                (sei_tmp.lpVerb) ? sei_tmp.lpVerb : wszOpen,
                                wszParameters, sizeof(wszParameters)/sizeof(WCHAR));
 
@@ -1074,78 +1306,6 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfun
             return FALSE;
     }
 
-
-    /* resolve shell shortcuts */
-    ext = PathFindExtensionW(sei_tmp.lpFile);
-
-    if (ext && !strncmpiW(ext, wExtLnk, sizeof(wExtLnk) / sizeof(WCHAR) - 1) &&
-        (ext[sizeof(wExtLnk) / sizeof(WCHAR) - 1] == '\0' ||
-         (sei_tmp.lpFile[0] == '"' && ext[sizeof(wExtLnk) / sizeof(WCHAR) - 1] == '"')))       /* or check for: shell_attribs & SFGAO_LINK */
-    {
-       HRESULT hr;
-       BOOL Quoted;
-
-       if (wszApplicationName[0] == '"')
-       {
-           if (wszApplicationName[strlenW(wszApplicationName) - 1] == '"')
-           {
-               wszApplicationName[strlenW(wszApplicationName) - 1] = '\0';
-               Quoted = TRUE;
-           }
-           else
-           {
-               Quoted = FALSE;
-           }
-       }
-       else
-       {
-           Quoted = FALSE;
-       }
-       /* expand paths before reading shell link */
-       if (ExpandEnvironmentStringsW(Quoted ? sei_tmp.lpFile + 1 : sei_tmp.lpFile, buffer, MAX_PATH))
-           lstrcpyW(Quoted ? wszApplicationName + 1 : wszApplicationName/*sei_tmp.lpFile*/, buffer);
-
-       if (*sei_tmp.lpParameters)
-           if (ExpandEnvironmentStringsW(sei_tmp.lpParameters, buffer, MAX_PATH))
-               lstrcpyW(wszParameters/*sei_tmp.lpParameters*/, buffer);
-
-       hr = SHELL_ResolveShortCutW((LPWSTR)(Quoted ? sei_tmp.lpFile + 1 : sei_tmp.lpFile),
-                                   (LPWSTR)sei_tmp.lpParameters, (LPWSTR)sei_tmp.lpDirectory,
-                                   sei_tmp.hwnd, sei_tmp.lpVerb?sei_tmp.lpVerb:wszEmpty, &sei_tmp.nShow, (LPITEMIDLIST*)&sei_tmp.lpIDList);
-       if (Quoted)
-       {
-           wszApplicationName[strlenW(wszApplicationName) + 1] = '\0';
-           wszApplicationName[strlenW(wszApplicationName)] = '"';
-       }
-
-       if (sei->lpIDList)
-           sei->fMask |= SEE_MASK_IDLIST;
-
-       if (SUCCEEDED(hr))
-       {
-           /* repeat IDList processing if needed */
-           if (sei_tmp.fMask & SEE_MASK_IDLIST)
-           {
-               IShellExecuteHookW* pSEH;
-
-               HRESULT hr = SHBindToParent(sei_tmp.lpIDList, &IID_IShellExecuteHookW, (LPVOID*)&pSEH, NULL);
-
-               if (SUCCEEDED(hr))
-               {
-                   hr = IShellExecuteHookW_Execute(pSEH, sei);
-
-                   IShellExecuteHookW_Release(pSEH);
-
-                   if (hr == S_OK)
-                       return TRUE;
-               }
-
-               TRACE("-- idlist=%p (%s)\n", debugstr_w(sei_tmp.lpIDList), debugstr_w(sei_tmp.lpFile));
-           }
-       }
-    }
-
-
     /* Has the IDList not yet been translated? */
     if (sei_tmp.fMask & SEE_MASK_IDLIST)
     {
@@ -1157,9 +1317,20 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfun
                strcpyW(wszApplicationName, wExplorer);
 
                sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST;
-           } else if (HCR_GetExecuteCommandW(0, wszFolder, sei_tmp.lpVerb?sei_tmp.lpVerb:wszOpen, buffer, sizeof(buffer))) {
-               SHELL_ArgifyW(wszApplicationName, sizeof(wszApplicationName)/sizeof(WCHAR), buffer, NULL, sei_tmp.lpIDList, NULL);
-
+           } else {
+               /* Check if we're executing a directory and if so use the
+                  handler for the Folder class */
+               strcpyW(target, buffer);
+               attribs = GetFileAttributesW(buffer);
+               if (attribs != INVALID_FILE_ATTRIBUTES &&
+                   0 != (attribs & FILE_ATTRIBUTE_DIRECTORY) &&
+                   HCR_GetExecuteCommandW(0, wszFolder,
+                                          sei_tmp.lpVerb?sei_tmp.lpVerb:wszOpen,
+                                          buffer, sizeof(buffer))) {
+                   SHELL_ArgifyW(wszApplicationName,
+                                 sizeof(wszApplicationName)/sizeof(WCHAR),
+                                 buffer, target, sei_tmp.lpIDList, NULL);
+               }
                sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST;
            }
        }
@@ -1218,7 +1389,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfun
            LPWSTR beg = wszApplicationName/*sei_tmp.lpFile*/;
            for(s=beg; (space=strchrW(s, ' ')); s=space+1) {
                int idx = space-sei_tmp.lpFile;
-               strncpyW(buffer, sei_tmp.lpFile, idx);
+               memcpy(buffer, sei_tmp.lpFile, idx * sizeof(WCHAR));
                buffer[idx] = '\0';
 
                /*FIXME This finds directory paths if the targeted file name contains spaces. */
@@ -1244,9 +1415,10 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfun
 
     lpFile = wfileName;
 
+    strcpyW(wcmd, wszApplicationName);
     if (sei_tmp.lpParameters[0]) {
-        strcatW(wszApplicationName, wSpace);
-        strcatW(wszApplicationName, wszParameters);
+        strcatW(wcmd, wSpace);
+        strcatW(wcmd, wszParameters);
     }
 
     /* We set the default to open, and that should generally work.
@@ -1254,7 +1426,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfun
     if (!sei_tmp.lpVerb)
         sei_tmp.lpVerb = wszOpen;
 
-    retval = execfunc(wszApplicationName, NULL, FALSE, &sei_tmp, sei);
+    retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
     if (retval > 32)
         return TRUE;
 
@@ -1296,7 +1468,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfun
 
         TRACE("Got URL: %s\n", debugstr_w(lpFile));
         /* Looking for ...protocol\shell\lpOperation\command */
-        strncpyW(lpstrProtocol, lpFile, iSize);
+        memcpy(lpstrProtocol, lpFile, iSize*sizeof(WCHAR));
         lpstrProtocol[iSize] = '\0';
         strcatW(lpstrProtocol, wShell);
         strcatW(lpstrProtocol, sei_tmp.lpVerb? sei_tmp.lpVerb: wszOpen);
@@ -1318,7 +1490,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfun
         WCHAR lpstrTmpFile[256];
         strcpyW(lpstrTmpFile, wHttp);
         strcatW(lpstrTmpFile, lpFile);
-        retval = (UINT)ShellExecuteW(sei_tmp.hwnd, sei_tmp.lpVerb, lpstrTmpFile, NULL, NULL, 0);
+        retval = (UINT_PTR)ShellExecuteW(sei_tmp.hwnd, sei_tmp.lpVerb, lpstrTmpFile, NULL, NULL, 0);
     }
 
     TRACE("retval %u\n", retval);
@@ -1340,10 +1512,10 @@ HINSTANCE WINAPI ShellExecuteA(HWND hWnd, LPCSTR lpOperation,LPCSTR lpFile,
                                LPCSTR lpParameters,LPCSTR lpDirectory, INT iShowCmd)
 {
     SHELLEXECUTEINFOA sei;
-    HANDLE hProcess = 0;
 
     TRACE("%p,%s,%s,%s,%s,%d\n",
-           hWnd, lpOperation, lpFile, lpParameters, lpDirectory, iShowCmd);
+          hWnd, debugstr_a(lpOperation), debugstr_a(lpFile),
+          debugstr_a(lpParameters), debugstr_a(lpDirectory), iShowCmd);
 
     sei.cbSize = sizeof(sei);
     sei.fMask = 0;
@@ -1357,7 +1529,7 @@ HINSTANCE WINAPI ShellExecuteA(HWND hWnd, LPCSTR lpOperation,LPCSTR lpFile,
     sei.lpClass = 0;
     sei.hkeyClass = 0;
     sei.dwHotKey = 0;
-    sei.hProcess = hProcess;
+    sei.hProcess = 0;
 
     ShellExecuteExA (&sei);
     return sei.hInstApp;
@@ -1389,15 +1561,18 @@ BOOL WINAPI ShellExecuteExA (LPSHELLEXECUTEINFOA sei)
     if (sei->lpDirectory)
         seiW.lpDirectory = __SHCloneStrAtoW(&wDirectory, sei->lpDirectory);
 
-    if ((sei->fMask & SEE_MASK_CLASSNAME) && sei->lpClass)
+    if ((sei->fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSNAME && sei->lpClass)
         seiW.lpClass = __SHCloneStrAtoW(&wClass, sei->lpClass);
     else
         seiW.lpClass = NULL;
 
-    ret = ShellExecuteExW32 (&seiW, SHELL_ExecuteW);
+    ret = SHELL_execute( &seiW, SHELL_ExecuteW );
 
     sei->hInstApp = seiW.hInstApp;
 
+    if (sei->fMask & SEE_MASK_NOCLOSEPROCESS)
+        sei->hProcess = seiW.hProcess;
+
     if (wVerb) SHFree(wVerb);
     if (wFile) SHFree(wFile);
     if (wParameters) SHFree(wParameters);
@@ -1413,7 +1588,7 @@ BOOL WINAPI ShellExecuteExA (LPSHELLEXECUTEINFOA sei)
  */
 BOOL WINAPI ShellExecuteExW (LPSHELLEXECUTEINFOW sei)
 {
-    return  ShellExecuteExW32 (sei, SHELL_ExecuteW);
+    return SHELL_execute( sei, SHELL_ExecuteW );
 }
 
 /*************************************************************************
@@ -1426,7 +1601,6 @@ HINSTANCE WINAPI ShellExecuteW(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile,
                                LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd)
 {
     SHELLEXECUTEINFOW sei;
-    HANDLE hProcess = 0;
 
     TRACE("\n");
     sei.cbSize = sizeof(sei);
@@ -1441,8 +1615,8 @@ HINSTANCE WINAPI ShellExecuteW(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile,
     sei.lpClass = 0;
     sei.hkeyClass = 0;
     sei.dwHotKey = 0;
-    sei.hProcess = hProcess;
+    sei.hProcess = 0;
 
-    ShellExecuteExW32 (&sei, SHELL_ExecuteW);
+    SHELL_execute( &sei, SHELL_ExecuteW );
     return sei.hInstApp;
 }