Author: janderwald
Date: Thu Apr 23 16:39:11 2009
New Revision: 40666

URL: http://svn.reactos.org/svn/reactos?rev=40666&view=rev
Log:
- Call OpenWith dialog when no file association is found
- Partial wine syncAlexandre Julliard <[email protected]>
shell32: Add implementation of WOWShellExecute.
The callback is probably not fully compatible, but apps are not
supposed to use that function anyway.
Vincent Povirk <[email protected]>
shell32: Add a message for opening files with no association.
Marcus Meissner <[email protected]>
shell32: Fixed potential buffer overwrite in execute_from_key (Coverity).
Vincent Povirk <[email protected]>
shell32: Use the NO_UI flag in ShellExecute.
In my testing on Windows, I wasn't able to make ShellExecute display
any error dialogs.
Paul Chitescu <[email protected]>
shell32.dll: Return SE_ERR_FNF if file not found before checking for 
associations.

Modified:
    trunk/reactos/dll/win32/shell32/shell32_main.h
    trunk/reactos/dll/win32/shell32/shlexec.c
    trunk/reactos/dll/win32/shell32/shresdef.h
    trunk/reactos/dll/win32/shell32/stubs.c

Modified: trunk/reactos/dll/win32/shell32/shell32_main.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shell32_main.h?rev=40666&r1=40665&r2=40666&view=diff
==============================================================================
--- trunk/reactos/dll/win32/shell32/shell32_main.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/shell32/shell32_main.h [iso-8859-1] Thu Apr 23 
16:39:11 2009
@@ -213,7 +213,7 @@
 #define HINSTANCE_16(h32)      (LOWORD(h32))
 
 typedef UINT_PTR (*SHELL_ExecuteW32)(const WCHAR *lpCmd, WCHAR *env, BOOL 
shWait,
-                           LPSHELLEXECUTEINFOW sei, LPSHELLEXECUTEINFOW 
sei_out);
+                           const SHELLEXECUTEINFOW *sei, LPSHELLEXECUTEINFOW 
sei_out);
 
 BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc);
 

Modified: trunk/reactos/dll/win32/shell32/shlexec.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shlexec.c?rev=40666&r1=40665&r2=40666&view=diff
==============================================================================
--- trunk/reactos/dll/win32/shell32/shlexec.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/shell32/shlexec.c [iso-8859-1] Thu Apr 23 16:39:11 
2009
@@ -165,7 +165,7 @@
             case 'I':
                if (pidl) {
                    INT chars = 0;
-                   /* %p should not exceed 8, maybe 16 when looking foward to 
64bit.
+                   /* %p should not exceed 8, maybe 16 when looking forward to 
64bit.
                     * allowing a buffer of 100 should more than exceed all 
needs */
                    WCHAR buf[100];
                    LPVOID  pv;
@@ -191,7 +191,7 @@
                  */
 
                 /* Make sure that we have at least one more %.*/
-                if (wcschr(fmt, '%'))
+                if (strchrW(fmt, '%'))
                 {
                     WCHAR   tmpBuffer[1024];
                     PWSTR   tmpB = tmpBuffer;
@@ -275,7 +275,7 @@
  *
  */
 static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
-                           LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW 
psei_out)
+                           const SHELLEXECUTEINFOW *psei, LPSHELLEXECUTEINFOW 
psei_out)
 {
     STARTUPINFOW  startup;
     PROCESS_INFORMATION info;
@@ -664,9 +664,7 @@
            }
             else
             {
-                /* Truncate on first space, like Windows:
-                 * http://support.microsoft.com/?scid=kb%3Ben-us%3B140724
-                 */
+                /* Truncate on first space */
                WCHAR *p = lpResult;
                while (*p != ' ' && *p != '\0')
                     p++;
@@ -728,10 +726,10 @@
  * launching an application and trying (#2) to connect to it
  *
  */
-static unsigned dde_connect(WCHAR* key, const WCHAR* start, WCHAR* ddeexec,
+static unsigned dde_connect(const WCHAR* key, const WCHAR* start, WCHAR* 
ddeexec,
                             const WCHAR* lpFile, WCHAR *env,
                            LPCWSTR szCommandline, LPITEMIDLIST pidl, 
SHELL_ExecuteW32 execfunc,
-                            LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW 
psei_out)
+                            const SHELLEXECUTEINFOW *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};
@@ -771,7 +769,7 @@
         else
         {
             LPWSTR p,space;
-            for (p=(LPWSTR)start; (space=wcschr(p, ' ')); p=space+1)
+            for (p=(LPWSTR)start; (space=strchrW(p, ' ')); p=space+1)
             {
                 int idx = space-start;
                 memcpy(command, start, idx*sizeof(WCHAR));
@@ -796,7 +794,7 @@
             !wcscmp(ptr, wSo))
             *ptr = 0;
 
-        ptr = wcschr(app, '.');
+        ptr = strrchrW(app, '.');
         assert(ptr);
         *ptr = 0;
     }
@@ -843,7 +841,7 @@
             SetLastError(ERROR_DDE_FAIL);
             return 30; /* whatever */
         }
-        wcscpy(endkey, wIfexec);
+        strcpyW(endkey, wIfexec);
         ifexeclen = sizeof(ifexec);
         if (RegQueryValueW(HKEY_CLASSES_ROOT, regkey, ifexec, &ifexeclen) == 
ERROR_SUCCESS)
         {
@@ -860,7 +858,7 @@
      * error DMLERR_NOTPROCESSED on XTYP_EXECUTE request.
      */
     if (unicode)
-        hDdeData = DdeClientTransaction((LPBYTE)res, (wcslen(res) + 1) * 
sizeof(WCHAR), hConv, 0L, 0,
+        hDdeData = DdeClientTransaction((LPBYTE)res, (strlenW(res) + 1) * 
sizeof(WCHAR), hConv, 0L, 0,
                                          XTYP_EXECUTE, 30000, &tid);
     else
     {
@@ -888,7 +886,7 @@
 /*************************************************************************
  *     execute_from_key [Internal]
  */
-static UINT_PTR execute_from_key(LPWSTR key, LPCWSTR lpFile, WCHAR *env, 
LPCWSTR szCommandline,
+static UINT_PTR execute_from_key(LPCWSTR key, LPCWSTR lpFile, WCHAR *env, 
LPCWSTR szCommandline,
                              LPCWSTR executable_name,
                             SHELL_ExecuteW32 execfunc,
                              LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW 
psei_out)
@@ -914,8 +912,8 @@
 
         /* Is there a replace() function anywhere? */
         cmdlen /= sizeof(WCHAR);
-        if (cmdlen >= sizeof(cmd)/sizeof(WCHAR))
-            cmdlen = sizeof(cmd)/sizeof(WCHAR)-1;
+       if (cmdlen >= sizeof(cmd)/sizeof(WCHAR))
+           cmdlen = sizeof(cmd)/sizeof(WCHAR)-1;
         cmd[cmdlen] = '\0';
         SHELL_ArgifyW(param, sizeof(param)/sizeof(WCHAR), cmd, lpFile, 
psei->lpIDList, szCommandline, &resultLen);
         if (resultLen > sizeof(param)/sizeof(WCHAR))
@@ -924,14 +922,14 @@
 
     /* Get the parameters needed by the application
        from the associated ddeexec key */
-    tmp = wcsstr(key, wCommand);
+    tmp = strstrW(key, wCommand);
     assert(tmp);
     wcscpy(tmp, wDdeexec);
 
     if (RegQueryValueW(HKEY_CLASSES_ROOT, key, ddeexec, &ddeexeclen) == 
ERROR_SUCCESS)
     {
         TRACE("Got ddeexec %s => %s\n", debugstr_w(key), debugstr_w(ddeexec));
-        if (!param[0]) wcscpy(param, executable_name);
+        if (!param[0]) strcpyW(param, executable_name);
         retval = dde_connect(key, param, ddeexec, lpFile, env, szCommandline, 
psei->lpIDList, execfunc, psei, psei_out);
     }
     else if (param[0])
@@ -1017,7 +1015,7 @@
 }
 
 /* FIXME: is this already implemented somewhere else? */
-static HKEY ShellExecute_GetClassKey( LPSHELLEXECUTEINFOW sei )
+static HKEY ShellExecute_GetClassKey( const SHELLEXECUTEINFOW *sei )
 {
     LPCWSTR ext = NULL, lpClass = NULL;
     LPWSTR cls = NULL;
@@ -1078,10 +1076,11 @@
     else
     {
         WCHAR fullpath[MAX_PATH];
+        BOOL ret;
 
         fullpath[0] = 0;
-        r = GetFullPathNameW( sei->lpFile, MAX_PATH, fullpath, NULL );
-        if (!r)
+        ret = GetFullPathNameW( sei->lpFile, MAX_PATH, fullpath, NULL );
+        if (!ret)
             goto end;
 
         pidl = ILCreateFromPathW( fullpath );
@@ -1272,25 +1271,196 @@
     return r;
 }
 
+static UINT_PTR SHELL_execute_class( LPCWSTR wszApplicationName, 
LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 
execfunc )
+{
+    static const WCHAR wSpace[] = {' ',0};
+    WCHAR execCmd[1024], wcmd[1024];
+    /* launch a document by fileclass like 'WordPad.Document.1' */
+    /* the Commandline contains 'c:\Path\wordpad.exe "%1"' */
+    /* FIXME: wcmd should not be of a fixed size. Fixed to 1024, MAX_PATH is 
way too short! */
+    ULONG cmask=(psei->fMask & SEE_MASK_CLASSALL);
+    DWORD resultLen;
+    BOOL done;
+
+    HCR_GetExecuteCommandW((cmask == SEE_MASK_CLASSKEY) ? psei->hkeyClass : 
NULL,
+                           (cmask == SEE_MASK_CLASSNAME) ? psei->lpClass: NULL,
+                           psei->lpVerb,
+                           execCmd, sizeof(execCmd));
+
+    /* FIXME: get the extension of lpFile, check if it fits to the lpClass */
+    TRACE("SEE_MASK_CLASSNAME->%s, doc->%s\n", debugstr_w(execCmd), 
debugstr_w(wszApplicationName));
+
+    wcmd[0] = '\0';
+    done = SHELL_ArgifyW(wcmd, sizeof(wcmd)/sizeof(WCHAR), execCmd, 
wszApplicationName, psei->lpIDList, NULL, &resultLen);
+    if (!done && wszApplicationName[0])
+    {
+        strcatW(wcmd, wSpace);
+        strcatW(wcmd, wszApplicationName);
+    }
+    if (resultLen > sizeof(wcmd)/sizeof(WCHAR))
+        ERR("Argify buffer not large enough... truncating\n");
+    return execfunc(wcmd, NULL, FALSE, psei, psei_out);
+}
+
+static BOOL SHELL_translate_idlist( LPSHELLEXECUTEINFOW sei, LPWSTR 
wszParameters, DWORD parametersLen, LPWSTR wszApplicationName, DWORD 
dwApplicationNameLen )
+{
+    static const WCHAR wExplorer[] = 
{'e','x','p','l','o','r','e','r','.','e','x','e',0};
+    WCHAR buffer[MAX_PATH];
+    BOOL appKnownSingular = FALSE;
+
+    /* last chance to translate IDList: now also allow CLSID paths */
+    if (SUCCEEDED(SHELL_GetPathFromIDListForExecuteW(sei->lpIDList, buffer, 
sizeof(buffer)))) {
+        if (buffer[0]==':' && buffer[1]==':') {
+            /* open shell folder for the specified class GUID */
+            if (strlenW(buffer) + 1 > parametersLen)
+                ERR("parameters len exceeds buffer size (%i > %i), 
truncating\n",
+                    lstrlenW(buffer) + 1, parametersLen);
+            lstrcpynW(wszParameters, buffer, parametersLen);
+            if (strlenW(wExplorer) > dwApplicationNameLen)
+                ERR("application len exceeds buffer size (%i > %i), 
truncating\n",
+                    lstrlenW(wExplorer) + 1, dwApplicationNameLen);
+            lstrcpynW(wszApplicationName, wExplorer, dwApplicationNameLen);
+            appKnownSingular = TRUE;
+
+            sei->fMask &= ~SEE_MASK_INVOKEIDLIST;
+        } else {
+            WCHAR target[MAX_PATH];
+            DWORD attribs;
+            DWORD resultLen;
+            /* 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 &&
+                (attribs & FILE_ATTRIBUTE_DIRECTORY) &&
+                HCR_GetExecuteCommandW(0, wszFolder,
+                                       sei->lpVerb,
+                                       buffer, sizeof(buffer))) {
+                SHELL_ArgifyW(wszApplicationName, dwApplicationNameLen,
+                              buffer, target, sei->lpIDList, NULL, &resultLen);
+                if (resultLen > dwApplicationNameLen)
+                    ERR("Argify buffer not large enough... truncating\n");
+                appKnownSingular = FALSE;
+            }
+            sei->fMask &= ~SEE_MASK_INVOKEIDLIST;
+        }
+    }
+    return appKnownSingular;
+}
+
+static UINT_PTR SHELL_quote_and_execute( LPCWSTR wcmd, LPCWSTR wszParameters, 
LPCWSTR lpstrProtocol, LPCWSTR wszApplicationName, LPWSTR env, 
LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 
execfunc )
+{
+    static const WCHAR wQuote[] = {'"',0};
+    static const WCHAR wSpace[] = {' ',0};
+    UINT_PTR retval;
+    DWORD len;
+    WCHAR *wszQuotedCmd;
+
+    /* Length of quotes plus length of command plus NULL terminator */
+    len = 2 + lstrlenW(wcmd) + 1;
+    if (wszParameters[0])
+    {
+        /* Length of space plus length of parameters */
+        len += 1 + lstrlenW(wszParameters);
+    }
+    wszQuotedCmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+    /* Must quote to handle case where cmd contains spaces,
+     * else security hole if malicious user creates executable file 
"C:\\Program"
+     */
+    strcpyW(wszQuotedCmd, wQuote);
+    strcatW(wszQuotedCmd, wcmd);
+    strcatW(wszQuotedCmd, wQuote);
+    if (wszParameters[0]) {
+        strcatW(wszQuotedCmd, wSpace);
+        strcatW(wszQuotedCmd, wszParameters);
+    }
+    TRACE("%s/%s => %s/%s\n", debugstr_w(wszApplicationName), 
debugstr_w(psei->lpVerb), debugstr_w(wszQuotedCmd), debugstr_w(lpstrProtocol));
+    if (*lpstrProtocol)
+        retval = execute_from_key(lpstrProtocol, wszApplicationName, env, 
psei->lpParameters, wcmd, execfunc, psei, psei_out);
+    else
+        retval = execfunc(wszQuotedCmd, env, FALSE, psei, psei_out);
+    HeapFree(GetProcessHeap(), 0, wszQuotedCmd);
+    return retval;
+}
+
+static UINT_PTR SHELL_execute_url( LPCWSTR lpFile, LPCWSTR wFile, LPCWSTR 
wcmd, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 
execfunc )
+{
+    static const WCHAR wShell[] = {'\\','s','h','e','l','l','\\',0};
+    static const WCHAR wCommand[] = {'\\','c','o','m','m','a','n','d',0};
+    UINT_PTR retval;
+    WCHAR *lpstrProtocol;
+    LPCWSTR lpstrRes;
+    INT iSize;
+    DWORD len;
+
+    lpstrRes = strchrW(lpFile, ':');
+    if (lpstrRes)
+        iSize = lpstrRes - lpFile;
+    else
+        iSize = strlenW(lpFile);
+
+    TRACE("Got URL: %s\n", debugstr_w(lpFile));
+    /* Looking for ...protocol\shell\lpOperation\command */
+    len = iSize + lstrlenW(wShell) + lstrlenW(wCommand) + 1;
+    if (psei->lpVerb)
+        len += lstrlenW(psei->lpVerb);
+    else
+        len += lstrlenW(wszOpen);
+    lpstrProtocol = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+    memcpy(lpstrProtocol, lpFile, iSize*sizeof(WCHAR));
+    lpstrProtocol[iSize] = '\0';
+    strcatW(lpstrProtocol, wShell);
+    strcatW(lpstrProtocol, psei->lpVerb? psei->lpVerb: wszOpen);
+    strcatW(lpstrProtocol, wCommand);
+
+    /* Remove File Protocol from lpFile */
+    /* In the case file://path/file     */
+    if (!strncmpiW(lpFile, wFile, iSize))
+    {
+        lpFile += iSize;
+        while (*lpFile == ':') lpFile++;
+    }
+    retval = execute_from_key(lpstrProtocol, lpFile, NULL, psei->lpParameters,
+                              wcmd, execfunc, psei, psei_out);
+    HeapFree(GetProcessHeap(), 0, lpstrProtocol);
+    return retval;
+}
+
+void do_error_dialog( UINT_PTR retval, HWND hwnd )
+{
+    WCHAR msg[2048];
+    int error_code=GetLastError();
+
+    //FIXME
+    // call SHOpenWithDialog
+    if (retval == SE_ERR_NOASSOC)
+        LoadStringW(shell32_hInstance, IDS_SHLEXEC_NOASSOC, msg, 
sizeof(msg)/sizeof(WCHAR));
+    else
+        FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, 0, msg, 
sizeof(msg)/sizeof(WCHAR), NULL);
+
+    MessageBoxW(hwnd, msg, NULL, MB_ICONERROR);
+}
+
 /*************************************************************************
  *     SHELL_execute [Internal]
  */
 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 wExplorer[] = 
{'e','x','p','l','o','r','e','r','.','e','x','e',0};
-    //static const WCHAR wProperties[] = { 
'p','r','o','p','e','r','t','i','e','s',0 };
     static const DWORD unsupportedFlags =
-        SEE_MASK_INVOKEIDLIST  | SEE_MASK_HOTKEY |
-        SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI |
+        SEE_MASK_INVOKEIDLIST  | SEE_MASK_ICON         | SEE_MASK_HOTKEY |
+        SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT |
         SEE_MASK_UNICODE       | SEE_MASK_ASYNCOK      | SEE_MASK_HMONITOR;
 
-    WCHAR *wszApplicationName, wszParameters[1024], wszDir[MAX_PATH];
+    WCHAR parametersBuffer[1024], dirBuffer[MAX_PATH], wcmdBuffer[1024];
+    WCHAR *wszApplicationName, *wszParameters, *wszDir, *wcmd;
     DWORD dwApplicationNameLen = MAX_PATH+2;
+    DWORD parametersLen = sizeof(parametersBuffer) / sizeof(WCHAR);
+    DWORD dirLen = sizeof(dirBuffer) / sizeof(WCHAR);
+    DWORD wcmdLen = sizeof(wcmdBuffer) / sizeof(WCHAR);
     DWORD len;
     SHELLEXECUTEINFOW sei_tmp; /* modifiable copy of SHELLEXECUTEINFO struct */
     WCHAR wfileName[MAX_PATH];
@@ -1298,13 +1468,10 @@
     WCHAR lpstrProtocol[256];
     LPCWSTR lpFile;
     UINT_PTR retval = SE_ERR_NOASSOC;
-    WCHAR wcmd[1024];
-    WCHAR buffer[MAX_PATH];
-    BOOL done;
     BOOL appKnownSingular = FALSE;
 
     /* make a local copy of the LPSHELLEXECUTEINFO structure and work with 
this from now on */
-    memcpy(&sei_tmp, sei, sizeof(sei_tmp));
+    sei_tmp = *sei;
 
     TRACE("mask=0x%08x hwnd=%p verb=%s file=%s parm=%s dir=%s show=0x%08x 
class=%s\n",
             sei_tmp.fMask, sei_tmp.hwnd, debugstr_w(sei_tmp.lpVerb),
@@ -1323,7 +1490,7 @@
     }
     else if (*sei_tmp.lpFile == '\"')
     {
-        DWORD l = wcslen(sei_tmp.lpFile+1);
+        DWORD l = strlenW(sei_tmp.lpFile+1);
         if(l >= dwApplicationNameLen) dwApplicationNameLen = l+1;
         wszApplicationName = HeapAlloc(GetProcessHeap(), 0, 
dwApplicationNameLen*sizeof(WCHAR));
         memcpy(wszApplicationName, sei_tmp.lpFile+1, (l+1)*sizeof(WCHAR));
@@ -1332,19 +1499,37 @@
         appKnownSingular = TRUE;
         TRACE("wszApplicationName=%s\n",debugstr_w(wszApplicationName));
     } else {
-        DWORD l = wcslen(sei_tmp.lpFile)+1;
+        DWORD l = strlenW(sei_tmp.lpFile)+1;
         if(l > dwApplicationNameLen) dwApplicationNameLen = l+1;
         wszApplicationName = HeapAlloc(GetProcessHeap(), 0, 
dwApplicationNameLen*sizeof(WCHAR));
         memcpy(wszApplicationName, sei_tmp.lpFile, l*sizeof(WCHAR));
     }
 
+    wszParameters = parametersBuffer;
     if (sei_tmp.lpParameters)
-       wcscpy(wszParameters, sei_tmp.lpParameters);
+    {
+        len = lstrlenW(sei_tmp.lpParameters) + 1;
+        if (len > parametersLen)
+        {
+            wszParameters = HeapAlloc(GetProcessHeap(), 0, len * 
sizeof(WCHAR));
+            parametersLen = len;
+        }
+       strcpyW(wszParameters, sei_tmp.lpParameters);
+    }
     else
        *wszParameters = '\0';
 
+    wszDir = dirBuffer;
     if (sei_tmp.lpDirectory)
-       wcscpy(wszDir, sei_tmp.lpDirectory);
+    {
+        len = lstrlenW(sei_tmp.lpDirectory) + 1;
+        if (len > dirLen)
+        {
+            wszDir = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+            dirLen = len;
+        }
+       strcpyW(wszDir, sei_tmp.lpDirectory);
+    }
     else
        *wszDir = '\0';
 
@@ -1367,12 +1552,16 @@
 
        if (SUCCEEDED(hr))
        {
-           hr = pSEH->lpVtbl->Execute(pSEH, &sei_tmp);
-
-           pSEH->lpVtbl->Release(pSEH);
+           hr = IShellExecuteHookW_Execute(pSEH, &sei_tmp);
+
+           IShellExecuteHookW_Release(pSEH);
 
            if (hr == S_OK) {
                 HeapFree(GetProcessHeap(), 0, wszApplicationName);
+                if (wszParameters != parametersBuffer)
+                    HeapFree(GetProcessHeap(), 0, wszParameters);
+                if (wszDir != dirBuffer)
+                    HeapFree(GetProcessHeap(), 0, wszDir);
                return TRUE;
             }
        }
@@ -1386,80 +1575,48 @@
     {
         sei->hInstApp = (HINSTANCE) 33;
         HeapFree(GetProcessHeap(), 0, wszApplicationName);
+        if (wszParameters != parametersBuffer)
+            HeapFree(GetProcessHeap(), 0, wszParameters);
+        if (wszDir != dirBuffer)
+            HeapFree(GetProcessHeap(), 0, wszDir);
         return TRUE;
     }
-#if 0
-    if (sei_tmp.lpVerb && !wcscmp(sei_tmp.lpVerb, wProperties))
-    {
-        SH_ShowPropertiesDialog(sei_tmp.lpFile);
-        sei->hInstApp = (HINSTANCE) 33;
-        return TRUE;
-    }
-#endif
+
     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! */
-        ULONG cmask=(sei_tmp.fMask & SEE_MASK_CLASSALL);
-        DWORD resultLen;
-        HCR_GetExecuteCommandW((cmask == SEE_MASK_CLASSKEY) ? 
sei_tmp.hkeyClass : NULL,
-                               (cmask == SEE_MASK_CLASSNAME) ? 
sei_tmp.lpClass: NULL,
-                               sei_tmp.lpVerb,
-                               wszParameters, 
sizeof(wszParameters)/sizeof(WCHAR));
-
-        /* FIXME: get the extension of lpFile, check if it fits to the lpClass 
*/
-        TRACE("SEE_MASK_CLASSNAME->%s, doc->%s\n", debugstr_w(wszParameters), 
debugstr_w(wszApplicationName));
-
-        wcmd[0] = '\0';
-        done = SHELL_ArgifyW(wcmd, sizeof(wcmd)/sizeof(WCHAR), wszParameters, 
wszApplicationName, sei_tmp.lpIDList, NULL, &resultLen);
-        if (!done && wszApplicationName[0])
-        {
-            wcscat(wcmd, wSpace);
-            wcscat(wcmd, wszApplicationName);
-        }
-        if (resultLen > sizeof(wcmd)/sizeof(WCHAR))
-            ERR("Argify buffer not large enough... truncating\n");
-        retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
-
+        retval = SHELL_execute_class( wszApplicationName, &sei_tmp, sei,
+                                      execfunc );
+        if (retval <= 32 && !(sei_tmp.fMask & SEE_MASK_FLAG_NO_UI))
+        {
+            OPENASINFO Info;
+
+            //FIXME
+            // need full path
+
+            Info.pcszFile = wszApplicationName;
+            Info.pcszClass = NULL;
+            Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_EXEC;
+
+            if (SHOpenWithDialog(sei_tmp.hwnd, &Info))
+                retval = 33; //FIXME
+            else
+               do_error_dialog(retval, sei_tmp.hwnd);
+        }
         HeapFree(GetProcessHeap(), 0, wszApplicationName);
+        if (wszParameters != parametersBuffer)
+            HeapFree(GetProcessHeap(), 0, wszParameters);
+        if (wszDir != dirBuffer)
+            HeapFree(GetProcessHeap(), 0, wszDir);
         return retval > 32;
     }
 
     /* Has the IDList not yet been translated? */
     if (sei_tmp.fMask & SEE_MASK_IDLIST)
     {
-       /* last chance to translate IDList: now also allow CLSID paths */
-       if (SUCCEEDED(SHELL_GetPathFromIDListForExecuteW(sei_tmp.lpIDList, 
buffer, sizeof(buffer)))) {
-           if (buffer[0]==':' && buffer[1]==':') {
-               /* open shell folder for the specified class GUID */
-               wcscpy(wszParameters, buffer);
-               wcscpy(wszApplicationName, wExplorer);
-               appKnownSingular = TRUE;
-
-               sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST;
-           } else {
-                WCHAR target[MAX_PATH];
-                DWORD attribs;
-                DWORD resultLen;
-               /* Check if we're executing a directory and if so use the
-                  handler for the Folder class */
-               wcscpy(target, buffer);
-               attribs = GetFileAttributesW(buffer);
-               if (attribs != INVALID_FILE_ATTRIBUTES &&
-                   (attribs & FILE_ATTRIBUTE_DIRECTORY) &&
-                   HCR_GetExecuteCommandW(0, wszFolder,
-                                          sei_tmp.lpVerb,
-                                          buffer, sizeof(buffer))) {
-                   SHELL_ArgifyW(wszApplicationName, dwApplicationNameLen,
-                                 buffer, target, sei_tmp.lpIDList, NULL, 
&resultLen);
-                   if (resultLen > dwApplicationNameLen)
-                       ERR("Argify buffer not large enough... truncating\n");
-                   appKnownSingular = FALSE;
-               }
-               sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST;
-           }
-       }
+        appKnownSingular = SHELL_translate_idlist( &sei_tmp, wszParameters,
+                                                   parametersLen,
+                                                   wszApplicationName,
+                                                   dwApplicationNameLen );
     }
 
     /* expand environment strings */
@@ -1487,10 +1644,11 @@
             len++;
             buf = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
             ExpandEnvironmentStringsW(sei_tmp.lpParameters, buf, len);
-            if (len > 1024)
-                ERR("Parameters exceeds buffer size (%i > 1024)\n",len);
-            lstrcpynW(wszParameters, buf, min(1024,len));
-            HeapFree(GetProcessHeap(),0,buf);
+            if (wszParameters != parametersBuffer)
+                HeapFree(GetProcessHeap(), 0, wszParameters);
+            wszParameters = buf;
+            parametersLen = len;
+            sei_tmp.lpParameters = wszParameters;
         }
     }
 
@@ -1503,10 +1661,10 @@
             len++;
             buf = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
             ExpandEnvironmentStringsW(sei_tmp.lpDirectory, buf, len);
-            if (len > 1024)
-                ERR("Directory exceeds buffer size (%i > 1024)\n",len);
-            lstrcpynW(wszDir, buf, min(1024,len));
-            HeapFree(GetProcessHeap(),0,buf);
+            if (wszDir != dirBuffer)
+                HeapFree(GetProcessHeap(), 0, wszDir);
+            wszDir = buf;
+            sei_tmp.lpDirectory = wszDir;
         }
     }
 
@@ -1536,7 +1694,7 @@
                end = src;
 
            /* copy the parameter string to 'wszParameters' */
-           wcscpy(wszParameters, src);
+           strcpyW(wszParameters, src);
 
            /* terminate previous command string after the quote character */
            *end = '\0';
@@ -1549,114 +1707,142 @@
            LPWSTR space, s;
 
            LPWSTR beg = wszApplicationName/*sei_tmp.lpFile*/;
-           for(s=beg; (space=wcschr(s, ' ')); s=space+1) {
+           for(s=beg; (space=strchrW(s, ' ')); s=space+1) {
                int idx = space-sei_tmp.lpFile;
                memcpy(buffer, sei_tmp.lpFile, idx * sizeof(WCHAR));
                buffer[idx] = '\0';
 
                /*FIXME This finds directory paths if the targeted file name 
contains spaces. */
-               if (SearchPathW(*sei_tmp.lpDirectory? sei_tmp.lpDirectory: 
NULL, buffer, wszExe, sizeof(xlpFile), xlpFile, NULL))
+               if (SearchPathW(*sei_tmp.lpDirectory? sei_tmp.lpDirectory: 
NULL, buffer, wszExe, sizeof(xlpFile)/sizeof(xlpFile[0]), xlpFile, NULL))
                {
                    /* separate out command from parameter string */
                    LPCWSTR p = space + 1;
 
-                   while(iswspace(*p))
+                   while(isspaceW(*p))
                        ++p;
 
-                   wcscpy(wszParameters, p);
+                   strcpyW(wszParameters, p);
                    *space = '\0';
 
                    break;
                }
            }
 
-           wcscpy(wfileName, sei_tmp.lpFile);
+           lstrcpynW(wfileName, 
sei_tmp.lpFile,sizeof(wfileName)/sizeof(WCHAR));
        }
     } else
-       wcscpy(wfileName, sei_tmp.lpFile);
+       lstrcpynW(wfileName, sei_tmp.lpFile,sizeof(wfileName)/sizeof(WCHAR));
 
     lpFile = wfileName;
 
-    wcscpy(wcmd, wszApplicationName);
+    wcmd = wcmdBuffer;
+    len = lstrlenW(wszApplicationName) + 1;
+    if (sei_tmp.lpParameters[0])
+        len += 1 + lstrlenW(wszParameters);
+    if (len > wcmdLen)
+    {
+        wcmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+        wcmdLen = len;
+    }
+    strcpyW(wcmd, wszApplicationName);
     if (sei_tmp.lpParameters[0]) {
-        wcscat(wcmd, wSpace);
-        wcscat(wcmd, wszParameters);
+        strcatW(wcmd, wSpace);
+        strcatW(wcmd, wszParameters);
     }
 
     retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
     if (retval > 32) {
         HeapFree(GetProcessHeap(), 0, wszApplicationName);
+        if (wszParameters != parametersBuffer)
+            HeapFree(GetProcessHeap(), 0, wszParameters);
+        if (wszDir != dirBuffer)
+            HeapFree(GetProcessHeap(), 0, wszDir);
+        if (wcmd != wcmdBuffer)
+            HeapFree(GetProcessHeap(), 0, wcmd);
         return TRUE;
     }
 
     /* Else, try to find the executable */
     wcmd[0] = '\0';
-    retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, 
wcmd, 1024, lpstrProtocol, &env, sei_tmp.lpIDList, sei_tmp.lpParameters);
+    retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, 
wcmd, wcmdLen, lpstrProtocol, &env, sei_tmp.lpIDList, sei_tmp.lpParameters);
     if (retval > 32)  /* Found */
     {
-        WCHAR wszQuotedCmd[MAX_PATH+2];
-        /* Must quote to handle case where cmd contains spaces,
-         * else security hole if malicious user creates executable file 
"C:\\Program"
-         */
-        wcscpy(wszQuotedCmd, wQuote);
-        wcscat(wszQuotedCmd, wcmd);
-        wcscat(wszQuotedCmd, wQuote);
-        if (wszParameters[0]) {
-            wcscat(wszQuotedCmd, wSpace);
-            wcscat(wszQuotedCmd, wszParameters);
-        }
-        TRACE("%s/%s => %s/%s\n", debugstr_w(wszApplicationName), 
debugstr_w(sei_tmp.lpVerb), debugstr_w(wszQuotedCmd), 
debugstr_w(lpstrProtocol));
-        if (*lpstrProtocol)
-            retval = execute_from_key(lpstrProtocol, wszApplicationName, env, 
sei_tmp.lpParameters, wcmd, execfunc, &sei_tmp, sei);
+        retval = SHELL_quote_and_execute( wcmd, wszParameters, lpstrProtocol,
+                                          wszApplicationName, env, &sei_tmp,
+                                          sei, execfunc );
+        HeapFree( GetProcessHeap(), 0, env );
+    }
+    else if (PathIsDirectoryW(lpFile))
+    {
+        static const WCHAR wExplorer[] = {'e','x','p','l','o','r','e','r',0};
+        static const WCHAR wQuote[] = {'"',0};
+        WCHAR wExec[MAX_PATH];
+        WCHAR * lpQuotedFile = HeapAlloc( GetProcessHeap(), 0, sizeof(WCHAR) * 
(strlenW(lpFile) + 3) );
+
+        if (lpQuotedFile)
+        {
+            retval = SHELL_FindExecutable( sei_tmp.lpDirectory, wExplorer,
+                                           wszOpen, wExec, MAX_PATH,
+                                           NULL, &env, NULL, NULL );
+            if (retval > 32)
+            {
+                strcpyW(lpQuotedFile, wQuote);
+                strcatW(lpQuotedFile, lpFile);
+                strcatW(lpQuotedFile, wQuote);
+                retval = SHELL_quote_and_execute( wExec, lpQuotedFile,
+                                                  lpstrProtocol,
+                                                  wszApplicationName, env,
+                                                  &sei_tmp, sei, execfunc );
+                HeapFree( GetProcessHeap(), 0, env );
+            }
+            HeapFree( GetProcessHeap(), 0, lpQuotedFile );
+        }
         else
-            retval = execfunc(wszQuotedCmd, env, FALSE, &sei_tmp, sei);
-        HeapFree( GetProcessHeap(), 0, env );
+            retval = 0; /* Out of memory */
     }
     else if (PathIsURLW(lpFile))    /* File not found, check for URL */
     {
-       static const WCHAR wShell[] = {'\\','s','h','e','l','l','\\',0};
-       static const WCHAR wCommand[] = {'\\','c','o','m','m','a','n','d',0};
-        LPWSTR lpstrRes;
-        INT iSize;
-
-        lpstrRes = wcschr(lpFile, ':');
-        if (lpstrRes)
-            iSize = lpstrRes - lpFile;
-        else
-            iSize = wcslen(lpFile);
-
-        TRACE("Got URL: %s\n", debugstr_w(lpFile));
-        /* Looking for ...protocol\shell\lpOperation\command */
-        memcpy(lpstrProtocol, lpFile, iSize*sizeof(WCHAR));
-        lpstrProtocol[iSize] = '\0';
-        wcscat(lpstrProtocol, wShell);
-        wcscat(lpstrProtocol, sei_tmp.lpVerb? sei_tmp.lpVerb: wszOpen);
-        wcscat(lpstrProtocol, wCommand);
-
-        /* Remove File Protocol from lpFile */
-        /* In the case file://path/file     */
-        if (!_wcsnicmp(lpFile, wFile, iSize))
-        {
-            lpFile += iSize;
-            while (*lpFile == ':') lpFile++;
-        }
-        retval = execute_from_key(lpstrProtocol, lpFile, NULL, 
sei_tmp.lpParameters, wcmd, execfunc, &sei_tmp, sei);
+        retval = SHELL_execute_url( lpFile, wFile, wcmd, &sei_tmp, sei, 
execfunc );
     }
     /* Check if file specified is in the form www.??????.*** */
-    else if (!_wcsnicmp(lpFile, wWww, 3))
+    else if (!strncmpiW(lpFile, wWww, 3))
     {
         /* if so, append lpFile http:// and call ShellExecute */
         WCHAR lpstrTmpFile[256];
-        wcscpy(lpstrTmpFile, wHttp);
-        wcscat(lpstrTmpFile, lpFile);
+        strcpyW(lpstrTmpFile, wHttp);
+        strcatW(lpstrTmpFile, lpFile);
         retval = (UINT_PTR)ShellExecuteW(sei_tmp.hwnd, sei_tmp.lpVerb, 
lpstrTmpFile, NULL, NULL, 0);
     }
 
     TRACE("retval %lu\n", retval);
 
+    if (retval <= 32 && !(sei_tmp.fMask & SEE_MASK_FLAG_NO_UI))
+    {
+        OPENASINFO Info;
+
+        //FIXME
+        // need full path
+
+        Info.pcszFile = wszApplicationName;
+        Info.pcszClass = NULL;
+        Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_EXEC;
+
+        if (SHOpenWithDialog(sei_tmp.hwnd, &Info))
+            retval = 33; //FIXME
+        else
+            do_error_dialog(retval, sei_tmp.hwnd);
+    }
+
     HeapFree(GetProcessHeap(), 0, wszApplicationName);
+    if (wszParameters != parametersBuffer)
+        HeapFree(GetProcessHeap(), 0, wszParameters);
+    if (wszDir != dirBuffer)
+        HeapFree(GetProcessHeap(), 0, wszDir);
+    if (wcmd != wcmdBuffer)
+        HeapFree(GetProcessHeap(), 0, wcmd);
 
     sei->hInstApp = (HINSTANCE)(retval > 32 ? 33 : retval);
+
     return retval > 32;
 }
 
@@ -1673,7 +1859,7 @@
           debugstr_a(lpParameters), debugstr_a(lpDirectory), iShowCmd);
 
     sei.cbSize = sizeof(sei);
-    sei.fMask = 0;
+    sei.fMask = SEE_MASK_FLAG_NO_UI;
     sei.hwnd = hWnd;
     sei.lpVerb = lpOperation;
     sei.lpFile = lpFile;
@@ -1759,7 +1945,7 @@
 
     TRACE("\n");
     sei.cbSize = sizeof(sei);
-    sei.fMask = 0;
+    sei.fMask = SEE_MASK_FLAG_NO_UI;
     sei.hwnd = hwnd;
     sei.lpVerb = lpOperation;
     sei.lpFile = lpFile;
@@ -1777,6 +1963,42 @@
 }
 
 /*************************************************************************
+ * WOWShellExecute                     [shell...@]
+ *
+ * FIXME: the callback function most likely doesn't work the same way on 
Windows.
+ */
+HINSTANCE WINAPI WOWShellExecute(HWND hWnd, LPCSTR lpOperation,LPCSTR lpFile,
+                                 LPCSTR lpParameters,LPCSTR lpDirectory, INT 
iShowCmd, void *callback)
+{
+    SHELLEXECUTEINFOW seiW;
+    WCHAR *wVerb = NULL, *wFile = NULL, *wParameters = NULL, *wDirectory = 
NULL;
+    HANDLE hProcess = 0;
+
+    seiW.lpVerb = lpOperation ? __SHCloneStrAtoW(&wVerb, lpOperation) : NULL;
+    seiW.lpFile = lpFile ? __SHCloneStrAtoW(&wFile, lpFile) : NULL;
+    seiW.lpParameters = lpParameters ? __SHCloneStrAtoW(&wParameters, 
lpParameters) : NULL;
+    seiW.lpDirectory = lpDirectory ? __SHCloneStrAtoW(&wDirectory, 
lpDirectory) : NULL;
+
+    seiW.cbSize = sizeof(seiW);
+    seiW.fMask = 0;
+    seiW.hwnd = hWnd;
+    seiW.nShow = iShowCmd;
+    seiW.lpIDList = 0;
+    seiW.lpClass = 0;
+    seiW.hkeyClass = 0;
+    seiW.dwHotKey = 0;
+    seiW.hProcess = hProcess;
+
+    SHELL_execute( &seiW, callback );
+
+    SHFree(wVerb);
+    SHFree(wFile);
+    SHFree(wParameters);
+    SHFree(wDirectory);
+    return seiW.hInstApp;
+}
+
+/*************************************************************************
  * OpenAs_RunDLLA          [shell...@]
  */
 void WINAPI OpenAs_RunDLLA(HWND hwnd, HINSTANCE hinst, LPCSTR cmdline, int 
cmdshow)

Modified: trunk/reactos/dll/win32/shell32/shresdef.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shresdef.h?rev=40666&r1=40665&r2=40666&view=diff
==============================================================================
--- trunk/reactos/dll/win32/shell32/shresdef.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/shell32/shresdef.h [iso-8859-1] Thu Apr 23 16:39:11 
2009
@@ -135,6 +135,8 @@
 #define IDS_LNK_FILE                170
 #define IDS_SYS_FILE                171
 #define IDS_EMPTY_BITBUCKET         172
+#define IDS_SHLEXEC_NOASSOC         173
+
 #define IDS_OPEN_VERB               300
 #define IDS_RUNAS_VERB              301
 #define IDS_EDIT_VERB               302
@@ -165,6 +167,7 @@
 #define IDS_FORMATDRIVE             327
 #define IDS_RENAME                  328
 #define IDS_INSERT                  329
+#define IDS_DESCRIPTION             330
 
 /* Note: this string is referenced from the registry */
 #define IDS_RECYCLEBIN_FOLDER_NAME   8964

Modified: trunk/reactos/dll/win32/shell32/stubs.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/stubs.c?rev=40666&r1=40665&r2=40666&view=diff
==============================================================================
--- trunk/reactos/dll/win32/shell32/stubs.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/shell32/stubs.c [iso-8859-1] Thu Apr 23 16:39:11 
2009
@@ -409,23 +409,6 @@
 {
     FIXME("RealDriveTypeFlags() stub\n");
     return 1;
-}
-
-/*
- * Unimplemented
- */
-HINSTANCE
-WINAPI
-WOWShellExecute(HWND hwnd,
-                LPCWSTR lpOperation,
-                LPCWSTR lpFile,
-                LPCWSTR lpParameters,
-                LPCWSTR lpDirectory,
-                INT nShowCmd,
-                void *lpfnCBWinExec)
-{
-    FIXME("WOWShellExecute() stub\n");
-    return NULL;
 }
 
 /*

Reply via email to