Author: cmihail
Date: Fri Sep  2 19:29:30 2011
New Revision: 53533

URL: http://svn.reactos.org/svn/reactos?rev=53533&view=rev
Log:
[shell32.dll]
- rewrite the parser to handle command line argument parsing
- include basic description of what the rules for parsing are
- some minor formatting here and there (couldn't be helped)

Modified:
    branches/shell32_new-bringup/dll/win32/shell32/shlexec.cpp

Modified: branches/shell32_new-bringup/dll/win32/shell32/shlexec.cpp
URL: 
http://svn.reactos.org/svn/reactos/branches/shell32_new-bringup/dll/win32/shell32/shlexec.cpp?rev=53533&r1=53532&r2=53533&view=diff
==============================================================================
--- branches/shell32_new-bringup/dll/win32/shell32/shlexec.cpp [iso-8859-1] 
(original)
+++ branches/shell32_new-bringup/dll/win32/shell32/shlexec.cpp [iso-8859-1] Fri 
Sep  2 19:29:30 2011
@@ -32,6 +32,125 @@
 
 #define SEE_MASK_CLASSALL (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY)
 
+static void ParseNoTildeEffect(PWSTR &res, LPCWSTR &args, DWORD &len, DWORD 
&used, int argNum)
+{
+    bool firstCharQuote = false;
+    bool quotes_opened = false;
+    bool backslash_encountered = false;
+
+    for (int curArg=0; curArg<=argNum && *args; ++curArg)
+    {
+        firstCharQuote = false;
+        if (*args == '"')
+        {
+            quotes_opened = true;
+            firstCharQuote = true;
+            args++;
+        }
+
+        while(*args)
+        {
+            if (*args == '\\')
+            {
+                // if we found a backslash then flip the variable
+                backslash_encountered = !backslash_encountered;
+            }
+            else if (*args == '"')
+            {
+                if (quotes_opened)
+                {
+                    if (*(args+1) != '"')
+                    {
+                        quotes_opened = false;
+                        args++;
+                        break;
+                    }
+                    else
+                    {
+                       args++;
+                    }
+                }
+                else
+                {
+                    quotes_opened = true;
+                }
+
+                backslash_encountered = false;
+            }
+            else
+            {
+                backslash_encountered = false;
+                if (*args == ' ' && !firstCharQuote)
+                    break;
+            }
+
+            if (curArg == argNum)
+            {
+                used++;
+                if (used < len)
+                    *res++ = *args;
+            }
+            
+            args++;
+        }
+
+        while(*args == ' ')
+            ++args;
+    }
+}
+
+static void ParseTildeEffect(PWSTR &res, LPCWSTR &args, DWORD &len, DWORD 
&used, int argNum)
+{
+    bool quotes_opened = false;
+    bool backslash_encountered = false;
+
+    for (int curArg=0; curArg<=argNum && *args; ++curArg)
+    {
+        while(*args)
+        {
+            if (*args == '\\')
+            {
+                // if we found a backslash then flip the variable
+                backslash_encountered = !backslash_encountered;
+            }
+            else if (*args == '"')
+            {
+                if (quotes_opened)
+                {
+                    if (*(args+1) != '"')
+                    {
+                        quotes_opened = false;
+                    }
+                    else
+                    {
+                       args++;
+                    }
+                }
+                else
+                {
+                    quotes_opened = true;
+                }
+
+                backslash_encountered = false;
+            }
+            else
+            {
+                backslash_encountered = false;
+                if (*args == ' ' && !quotes_opened && curArg!=argNum)
+                    break;
+            }
+
+            if (curArg == argNum)
+            {
+                used++;
+                if (used < len)
+                    *res++ = *args;
+            }
+            
+            args++;
+        }
+    }
+}
 
 /***********************************************************************
  *     SHELL_ArgifyW [Internal]
@@ -48,7 +167,18 @@
  * %S ???
  * %* all following parameters (see batfile)
  *
- */
+*       The way we parse the command line arguments was determined through 
extensive
+*  testing and can be summed up by the following rules"
+*
+*  - %2
+*       - if first letter is " break on first non literal " and include any 
white spaces
+*       - if first letter is NOT " break on first " or white space
+*       - if " is opened any pair of consecutive " results in ONE literal "
+*
+*  - %~2
+*       - use rules from here 
http://www.autohotkey.net/~deleyd/parameters/parameters.htm
+*/
+
 static BOOL SHELL_ArgifyW(WCHAR* out, DWORD len, const WCHAR* fmt, const 
WCHAR* lpFile, LPITEMIDLIST pidl, LPCWSTR args, DWORD* out_len)
 {
     WCHAR   xlpFile[1024];
@@ -57,175 +187,188 @@
     PWSTR   res = out;
     PCWSTR  cmd;
     DWORD   used = 0;
+    bool    tildeEffect = false;
 
     TRACE("%p, %d, %s, %s, %p, %p\n", out, len, debugstr_w(fmt),
           debugstr_w(lpFile), pidl, args);
 
+    DbgPrint("[shell32, SHELL_ArgifyW] Processing %ws\n", args);
+    DbgPrint("[shell32, SHELL_ArgifyW] fmt = %ws\n", fmt);
+
     while (*fmt)
     {
         if (*fmt == '%')
         {
             switch (*++fmt)
             {
-            case '\0':
-            case '%':
-                used++;
-                if (used < len)
-                    *res++ = '%';
-                break;
-
-            case '2':
-            case '3':
-            case '4':
-            case '5':
-            case '6':
-            case '7':
-            case '8':
-            case '9':
-            case '0':
-            case '*':
-                if (args)
+                case '\0':
+                case '%':
                 {
-                    if (*fmt == '*')
+                    used++;
+                    if (used < len)
+                        *res++ = '%';
+                }; break;
+
+                case '*':
+                {
+                    if (args)
                     {
-                        used++;
-                        if (used < len)
-                            *res++ = '"';
-                        while(*args)
+                        if (*fmt == '*')
                         {
                             used++;
-                            if (used < len)
-                                *res++ = *args++;
-                            else
-                                args++;
+                            while(*args)
+                            {
+                                used++;
+                                if (used < len)
+                                    *res++ = *args++;
+                                else
+                                    args++;
+                            }
+                            used++;
+                            break;
                         }
-                        used++;
-                        if (used < len)
-                            *res++ = '"';
-                        break;
                     }
-                    else
+                }; break;
+
+                case '~':
+
+                case '2':
+                case '3':
+                case '4':
+                case '5':
+                case '6':
+                case '7':
+                case '8':
+                case '9':
+                //case '0':
+                {
+                    if (*fmt == '~')
                     {
-                        while(*args && !isspace(*args))
+                        fmt++;
+                        tildeEffect = true;
+                    }
+
+                    if (args)
+                    {
+                        if (tildeEffect)
                         {
-                            used++;
-                            if (used < len)
-                                *res++ = *args++;
-                            else
-                                args++;
+                            ParseTildeEffect(res, args, len, used, *fmt - '2');
+                            tildeEffect = false;
                         }
-
-                        while(isspace(*args))
-                            ++args;
+                        else
+                        {
+                            ParseNoTildeEffect(res, args, len, used, *fmt - 
'2');
+                        }
                     }
-                    break;
-                }
-                else
-                {
-                    break;
-                }
-            case '1':
-                if (!done || (*fmt == '1'))
-                {
-                    /*FIXME Is the call to SearchPathW() really needed? We 
already have separated out the parameter string in args. */
-                    if (SearchPathW(NULL, lpFile, wszExe, 
sizeof(xlpFile)/sizeof(WCHAR), xlpFile, NULL))
-                        cmd = xlpFile;
-                    else
-                        cmd = lpFile;
-
-                    used += wcslen(cmd);
-                    if (used < len)
+                }; break;
+
+                case '1':
+                    if (!done || (*fmt == '1'))
                     {
-                        wcscpy(res, cmd);
-                        res += wcslen(cmd);
-                    }
-                }
-                found_p1 = TRUE;
-                break;
-
-            /*
-             * IE uses this a lot for activating things such as windows media
-             * player. This is not verified to be fully correct but it appears
-             * to work just fine.
-             */
-            case 'l':
-            case 'L':
-               if (lpFile) {
-                   used += wcslen(lpFile);
-                   if (used < len)
-                   {
-                       wcscpy(res, lpFile);
-                       res += wcslen(lpFile);
-                   }
-               }
-               found_p1 = TRUE;
-                break;
-
-            case 'i':
-            case 'I':
-               if (pidl) {
-                   DWORD chars = 0;
-                   /* %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;
-                   HGLOBAL hmem = SHAllocShared(pidl, ILGetSize(pidl), 0);
-                   pv = SHLockShared(hmem, 0);
-                   chars = swprintf(buf, wszILPtr, pv);
-                   if (chars >= sizeof(buf)/sizeof(WCHAR))
-                       ERR("pidl format buffer too small!\n");
-                   used += chars;
-                   if (used < len)
-                   {
-                       wcscpy(res,buf);
-                       res += chars;
-                   }
-                   SHUnlockShared(pv);
-               }
-                found_p1 = TRUE;
-                break;
-
-           default:
-                /*
-                 * Check if this is an env-variable here...
-                 */
-
-                /* Make sure that we have at least one more %.*/
-                if (strchrW(fmt, '%'))
-                {
-                    WCHAR   tmpBuffer[1024];
-                    PWSTR   tmpB = tmpBuffer;
-                    WCHAR   tmpEnvBuff[MAX_PATH];
-                    DWORD   envRet;
-
-                    while (*fmt != '%')
-                        *tmpB++ = *fmt++;
-                    *tmpB++ = 0;
-
-                    TRACE("Checking %s to be an env-var\n", 
debugstr_w(tmpBuffer));
-
-                    envRet = GetEnvironmentVariableW(tmpBuffer, tmpEnvBuff, 
MAX_PATH);
-                    if (envRet == 0 || envRet > MAX_PATH)
-                    {
-                        used += wcslen(tmpBuffer);
+                        /*FIXME Is the call to SearchPathW() really needed? We 
already have separated out the parameter string in args. */
+                        if (SearchPathW(NULL, lpFile, wszExe, 
sizeof(xlpFile)/sizeof(WCHAR), xlpFile, NULL))
+                            cmd = xlpFile;
+                        else
+                            cmd = lpFile;
+
+                        used += wcslen(cmd);
                         if (used < len)
                         {
-                            wcscpy( res, tmpBuffer );
-                            res += wcslen(tmpBuffer);
+                            wcscpy(res, cmd);
+                            res += wcslen(cmd);
                         }
                     }
-                    else
+                    found_p1 = TRUE;
+                    break;
+
+                /*
+                 * IE uses this a lot for activating things such as windows 
media
+                 * player. This is not verified to be fully correct but it 
appears
+                 * to work just fine.
+                 */
+                case 'l':
+                case 'L':
+                           if (lpFile)
                     {
-                        used += wcslen(tmpEnvBuff);
+                               used += wcslen(lpFile);
+                               if (used < len)
+                               {
+                                       wcscpy(res, lpFile);
+                                       res += wcslen(lpFile);
+                               }
+                           }
+                           found_p1 = TRUE;
+                    break;
+
+                case 'i':
+                case 'I':
+                           if (pidl)
+                    {
+                               DWORD chars = 0;
+                               /* %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;
+                               HGLOBAL hmem = SHAllocShared(pidl, 
ILGetSize(pidl), 0);
+                               pv = SHLockShared(hmem, 0);
+                               chars = swprintf(buf, wszILPtr, pv);
+                               
+                        if (chars >= sizeof(buf)/sizeof(WCHAR))
+                                       ERR("pidl format buffer too small!\n");
+                               
+                        used += chars;
+                               
                         if (used < len)
+                               {
+                                       wcscpy(res,buf);
+                                       res += chars;
+                               }
+                               SHUnlockShared(pv);
+                           }
+                    found_p1 = TRUE;
+                    break;
+
+                   default:
+                    /*
+                     * Check if this is an env-variable here...
+                     */
+
+                    /* Make sure that we have at least one more %.*/
+                    if (strchrW(fmt, '%'))
+                    {
+                        WCHAR   tmpBuffer[1024];
+                        PWSTR   tmpB = tmpBuffer;
+                        WCHAR   tmpEnvBuff[MAX_PATH];
+                        DWORD   envRet;
+
+                        while (*fmt != '%')
+                            *tmpB++ = *fmt++;
+                        *tmpB++ = 0;
+
+                        TRACE("Checking %s to be an env-var\n", 
debugstr_w(tmpBuffer));
+
+                        envRet = GetEnvironmentVariableW(tmpBuffer, 
tmpEnvBuff, MAX_PATH);
+                        if (envRet == 0 || envRet > MAX_PATH)
                         {
-                            wcscpy( res, tmpEnvBuff );
-                            res += wcslen(tmpEnvBuff);
+                            used += wcslen(tmpBuffer);
+                            if (used < len)
+                            {
+                                wcscpy( res, tmpBuffer );
+                                res += wcslen(tmpBuffer);
+                            }
+                        }
+                        else
+                        {
+                            used += wcslen(tmpEnvBuff);
+                            if (used < len)
+                            {
+                                wcscpy( res, tmpEnvBuff );
+                                res += wcslen(tmpEnvBuff);
+                            }
                         }
                     }
-                }
-                done = TRUE;
-                break;
+                    done = TRUE;
+                    break;
             }
             /* Don't skip past terminator (catch a single '%' at the end) */
             if (*fmt != '\0')
@@ -248,6 +391,8 @@
     if (out_len)
         *out_len = used;
 
+    DbgPrint("[shell32, SHELL_ArgifyW] Done result = %ws\n", out);
+
     return found_p1;
 }
 
@@ -258,13 +403,14 @@
 
     HRESULT hr = SHGetDesktopFolder(&desktop);
 
-    if (SUCCEEDED(hr)) {
-       hr = desktop->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strret);
-
-       if (SUCCEEDED(hr))
-           StrRetToStrNW(pszPath, uOutSize, &strret, pidl);
-
-       desktop->Release();
+    if (SUCCEEDED(hr))
+    {
+           hr = desktop->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strret);
+
+           if (SUCCEEDED(hr))
+               StrRetToStrNW(pszPath, uOutSize, &strret, pidl);
+
+           desktop->Release();
     }
 
     return hr;
@@ -298,17 +444,23 @@
 
     /* ShellExecute specifies the command from psei->lpDirectory
      * if present. Not from the current dir as CreateProcess does */
-    if( lpDirectory )
-        if( ( gcdret = GetCurrentDirectoryW( MAX_PATH, curdir)))
-            if( !SetCurrentDirectoryW( lpDirectory))
+    if ( lpDirectory )
+        if ( ( gcdret = GetCurrentDirectoryW( MAX_PATH, curdir)))
+            if ( !SetCurrentDirectoryW( lpDirectory))
                 ERR("cannot set directory %s\n", debugstr_w(lpDirectory));
+    
     ZeroMemory(&startup,sizeof(STARTUPINFOW));
     startup.cb = sizeof(STARTUPINFOW);
     startup.dwFlags = STARTF_USESHOWWINDOW;
     startup.wShowWindow = psei->nShow;
     dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
+    
     if (psei->fMask & SEE_MASK_NO_CONSOLE)
         dwCreationFlags |= CREATE_NEW_CONSOLE;
+    
+    //DbgPrint("[shell32, SHELL_ExecuteW] CreateProcessW cmd = %ws\n", 
(LPWSTR)lpCmd);
+    //DbgBreakPoint();
+
     if (CreateProcessW(NULL, (LPWSTR)lpCmd, NULL, NULL, FALSE, 
dwCreationFlags, env,
                        lpDirectory, &startup, &info))
     {
@@ -318,6 +470,7 @@
             if (WaitForInputIdle( info.hProcess, 30000 ) == WAIT_FAILED)
                 WARN("WaitForInputIdle failed: Error %d\n", GetLastError() );
         retval = 33;
+        
         if (psei->fMask & SEE_MASK_NOCLOSEPROCESS)
             psei_out->hProcess = info.hProcess;
         else
@@ -333,6 +486,7 @@
     TRACE("returning %lu\n", retval);
 
     psei_out->hInstApp = (HINSTANCE)retval;
+    
     if( gcdret )
         if( !SetCurrentDirectoryW( curdir))
             ERR("cannot return to directory %s\n", debugstr_w(curdir));
@@ -626,8 +780,9 @@
                            &filetypelen) == ERROR_SUCCESS)
         {
             filetypelen /= sizeof(WCHAR);
-           if (filetypelen == sizeof(filetype)/sizeof(WCHAR))
-               filetypelen--;
+               if (filetypelen == sizeof(filetype)/sizeof(WCHAR))
+                       filetypelen--;
+            
             filetype[filetypelen] = '\0';
             TRACE("File type: %s\n", debugstr_w(filetype));
         }
@@ -644,41 +799,41 @@
         filetype[filetypelen] = '\0';
         retval = SHELL_FindExecutableByOperation(lpOperation, key, filetype, 
command, sizeof(command));
 
-       if (retval > 32)
-       {
-           DWORD finishedLen;
-           SHELL_ArgifyW(lpResult, resultLen, command, xlpFile, pidl, args, 
&finishedLen);
-           if (finishedLen > resultLen)
-               ERR("Argify buffer not large enough.. truncated\n");
-
-           /* Remove double quotation marks and command line arguments */
-           if (*lpResult == '"')
+           if (retval > 32)
            {
-               WCHAR *p = lpResult;
-               while (*(p + 1) != '"')
-               {
-                   *p = *(p + 1);
-                   p++;
-               }
-               *p = '\0';
-           }
+               DWORD finishedLen;
+               SHELL_ArgifyW(lpResult, resultLen, command, xlpFile, pidl, 
args, &finishedLen);
+               if (finishedLen > resultLen)
+                       ERR("Argify buffer not large enough.. truncated\n");
+            DbgPrint("[shell32, SHELL_FindExecutable] Remove double quotation 
marks and command line arguments\n");
+               /* Remove double quotation marks and command line arguments */
+               if (*lpResult == '"')
+               {
+                       WCHAR *p = lpResult;
+                       while (*(p + 1) != '"')
+                       {
+                           *p = *(p + 1);
+                           p++;
+                       }
+                       *p = '\0';
+               }
             else
             {
                 /* Truncate on first space */
-               WCHAR *p = lpResult;
-               while (*p != ' ' && *p != '\0')
+                       WCHAR *p = lpResult;
+                       while (*p != ' ' && *p != '\0')
                     p++;
                 *p='\0';
             }
-       }
+           }
     }
     else /* Check win.ini */
     {
-       static const WCHAR wExtensions[] = 
{'e','x','t','e','n','s','i','o','n','s',0};
-
-       /* Toss the leading dot */
-       extension++;
-       if (GetProfileStringW(wExtensions, extension, wszEmpty, command, 
sizeof(command)/sizeof(WCHAR)) > 0)
+           static const WCHAR wExtensions[] = 
{'e','x','t','e','n','s','i','o','n','s',0};
+
+           /* Toss the leading dot */
+           extension++;
+           if (GetProfileStringW(wExtensions, extension, wszEmpty, command, 
sizeof(command)/sizeof(WCHAR)) > 0)
         {
             if (wcslen(command) != 0)
             {
@@ -1370,11 +1525,14 @@
     strcpyW(wszQuotedCmd, wQuote);
     strcatW(wszQuotedCmd, wcmd);
     strcatW(wszQuotedCmd, wQuote);
-    if (wszParameters[0]) {
+    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
@@ -1498,14 +1656,20 @@
     else if (*sei_tmp.lpFile == '\"')
     {
         DWORD l = strlenW(sei_tmp.lpFile+1);
-        if(l >= dwApplicationNameLen) dwApplicationNameLen = l+1;
+        if(l >= dwApplicationNameLen)
+            dwApplicationNameLen = l+1;
+        
         wszApplicationName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, 
dwApplicationNameLen*sizeof(WCHAR));
         memcpy(wszApplicationName, sei_tmp.lpFile+1, (l+1)*sizeof(WCHAR));
+        
         if (wszApplicationName[l-1] == '\"')
             wszApplicationName[l-1] = '\0';
         appKnownSingular = TRUE;
+        
         TRACE("wszApplicationName=%s\n",debugstr_w(wszApplicationName));
-    } else {
+    }
+    else
+    {
         DWORD l = strlenW(sei_tmp.lpFile)+1;
         if(l > dwApplicationNameLen) dwApplicationNameLen = l+1;
         wszApplicationName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, 
dwApplicationNameLen*sizeof(WCHAR));
@@ -1521,10 +1685,10 @@
             wszParameters = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * 
sizeof(WCHAR));
             parametersLen = len;
         }
-       strcpyW(wszParameters, sei_tmp.lpParameters);
+           strcpyW(wszParameters, sei_tmp.lpParameters);
     }
     else
-       *wszParameters = '\0';
+           *wszParameters = '\0';
 
     wszDir = dirBuffer;
     if (sei_tmp.lpDirectory)
@@ -1535,10 +1699,10 @@
             wszDir = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * 
sizeof(WCHAR));
             dirLen = len;
         }
-       strcpyW(wszDir, sei_tmp.lpDirectory);
+           strcpyW(wszDir, sei_tmp.lpDirectory);
     }
     else
-       *wszDir = '\0';
+           *wszDir = '\0';
 
     /* adjust string pointers to point to the new buffers */
     sei_tmp.lpFile = wszApplicationName;
@@ -1553,25 +1717,26 @@
     /* process the IDList */
     if (sei_tmp.fMask & SEE_MASK_IDLIST)
     {
-       IShellExecuteHookW* pSEH;
-
-       HRESULT hr = SHBindToParent((LPCITEMIDLIST)sei_tmp.lpIDList, 
IID_IShellExecuteHookW, (LPVOID*)&pSEH, NULL);
-
-       if (SUCCEEDED(hr))
-       {
-           hr = pSEH->Execute(&sei_tmp);
-
-           pSEH->Release();
-
-           if (hr == S_OK) {
+           IShellExecuteHookW* pSEH;
+
+           HRESULT hr = SHBindToParent((LPCITEMIDLIST)sei_tmp.lpIDList, 
IID_IShellExecuteHookW, (LPVOID*)&pSEH, NULL);
+
+           if (SUCCEEDED(hr))
+           {
+               hr = pSEH->Execute(&sei_tmp);
+
+               pSEH->Release();
+
+               if (hr == S_OK)
+            {
                 HeapFree(GetProcessHeap(), 0, wszApplicationName);
                 if (wszParameters != parametersBuffer)
                     HeapFree(GetProcessHeap(), 0, wszParameters);
                 if (wszDir != dirBuffer)
                     HeapFree(GetProcessHeap(), 0, wszDir);
-               return TRUE;
+                       return TRUE;
             }
-       }
+           }
 
         SHGetPathFromIDListW((LPCITEMIDLIST)sei_tmp.lpIDList, 
wszApplicationName);
         appKnownSingular = TRUE;
@@ -1677,65 +1842,71 @@
     TRACE("execute:%s,%s,%s\n", debugstr_w(wszApplicationName), 
debugstr_w(wszParameters), debugstr_w(wszDir));
 
     /* separate out command line arguments from executable file name */
-    if (!*sei_tmp.lpParameters && !appKnownSingular) {
-       /* If the executable path is quoted, handle the rest of the command 
line as parameters. */
-       if (sei_tmp.lpFile[0] == '"') {
-           LPWSTR src = wszApplicationName/*sei_tmp.lpFile*/ + 1;
-           LPWSTR dst = wfileName;
-           LPWSTR end;
-
-           /* copy the unquoted executable path to 'wfileName' */
-           while(*src && *src!='"')
-               *dst++ = *src++;
-
-           *dst = '\0';
-
-           if (*src == '"') {
-               end = ++src;
-
-               while(isspace(*src))
-                   ++src;
-           } else
-               end = src;
-
-           /* copy the parameter string to 'wszParameters' */
-           strcpyW(wszParameters, src);
-
-           /* terminate previous command string after the quote character */
-           *end = '\0';
-       }
-       else
-       {
-           /* If the executable name is not quoted, we have to use this search 
loop here,
-              that in CreateProcess() is not sufficient because it does not 
handle shell links. */
-           WCHAR buffer[MAX_PATH], xlpFile[MAX_PATH];
-           LPWSTR space, s;
-
-           LPWSTR beg = wszApplicationName/*sei_tmp.lpFile*/;
-           for(s=beg; (space= const_cast<LPWSTR>(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)/sizeof(xlpFile[0]), xlpFile, NULL))
-               {
-                   /* separate out command from parameter string */
-                   LPCWSTR p = space + 1;
-
-                   while(isspaceW(*p))
-                       ++p;
-
-                   strcpyW(wszParameters, p);
-                   *space = '\0';
-
-                   break;
-               }
+    if (!*sei_tmp.lpParameters && !appKnownSingular)
+    {
+           /* If the executable path is quoted, handle the rest of the command 
line as parameters. */
+           if (sei_tmp.lpFile[0] == '"')
+        {
+               LPWSTR src = wszApplicationName/*sei_tmp.lpFile*/ + 1;
+               LPWSTR dst = wfileName;
+               LPWSTR end;
+
+               /* copy the unquoted executable path to 'wfileName' */
+               while(*src && *src!='"')
+                   *dst++ = *src++;
+
+               *dst = '\0';
+
+               if (*src == '"')
+            {
+                       end = ++src;
+
+                       while(isspace(*src))
+                           ++src;
+               }
+            else
+                       end = src;
+
+               /* copy the parameter string to 'wszParameters' */
+               strcpyW(wszParameters, src);
+
+               /* terminate previous command string after the quote character 
*/
+               *end = '\0';
            }
-
-           lstrcpynW(wfileName, 
sei_tmp.lpFile,sizeof(wfileName)/sizeof(WCHAR));
-       }
-    } else
+           else
+           {
+               /* If the executable name is not quoted, we have to use this 
search loop here,
+                  that in CreateProcess() is not sufficient because it does 
not handle shell links. */
+               WCHAR buffer[MAX_PATH], xlpFile[MAX_PATH];
+               LPWSTR space, s;
+
+               LPWSTR beg = wszApplicationName/*sei_tmp.lpFile*/;
+               for(s=beg; (space= const_cast<LPWSTR>(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)/sizeof(xlpFile[0]), 
xlpFile, NULL))
+                       {
+                           /* separate out command from parameter string */
+                           LPCWSTR p = space + 1;
+
+                           while(isspaceW(*p))
+                                   ++p;
+
+                           strcpyW(wszParameters, p);
+                           *space = '\0';
+
+                           break;
+                       }
+               }
+
+               lstrcpynW(wfileName, 
sei_tmp.lpFile,sizeof(wfileName)/sizeof(WCHAR));
+           }
+    }
+    else
        lstrcpynW(wfileName, sei_tmp.lpFile,sizeof(wfileName)/sizeof(WCHAR));
 
     lpFile = wfileName;
@@ -1750,13 +1921,15 @@
         wcmdLen = len;
     }
     strcpyW(wcmd, wszApplicationName);
-    if (sei_tmp.lpParameters[0]) {
+    if (sei_tmp.lpParameters[0])
+    {
         strcatW(wcmd, wSpace);
         strcatW(wcmd, wszParameters);
     }
 
     retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
-    if (retval > 32) {
+    if (retval > 32)
+    {
         HeapFree(GetProcessHeap(), 0, wszApplicationName);
         if (wszParameters != parametersBuffer)
             HeapFree(GetProcessHeap(), 0, wszParameters);
@@ -1894,7 +2067,7 @@
     memcpy(&seiW, sei, sizeof(SHELLEXECUTEINFOW));
 
     if (sei->lpVerb)
-       seiW.lpVerb = __SHCloneStrAtoW(&wVerb, sei->lpVerb);
+           seiW.lpVerb = __SHCloneStrAtoW(&wVerb, sei->lpVerb);
 
     if (sei->lpFile)
         seiW.lpFile = __SHCloneStrAtoW(&wFile, sei->lpFile);


Reply via email to