[PATCH] shell32: Don't specify the startup directory for CreateProcessW() in SHELL_ExecuteW().

Paul Gofman pgofman at codeweavers.com
Wed Jun 16 13:15:41 CDT 2021


Doing so fails process creation for relative current directory as the
directory already made current.

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/shell32/shlexec.c       | 17 ++++++-----------
 dlls/shell32/tests/shlexec.c | 12 ++++++++++++
 2 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/dlls/shell32/shlexec.c b/dlls/shell32/shlexec.c
index ee1e832df33..49f7867ef7e 100644
--- a/dlls/shell32/shlexec.c
+++ b/dlls/shell32/shlexec.c
@@ -318,7 +318,6 @@ static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
     UINT gcdret = 0;
     WCHAR curdir[MAX_PATH];
     DWORD dwCreationFlags;
-    const WCHAR *lpDirectory = NULL;
 
     TRACE("Execute %s from directory %s\n", debugstr_w(lpCmd), debugstr_w(psei->lpDirectory));
 
@@ -326,17 +325,13 @@ static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
      * a bad working directory */
     if (psei->lpDirectory && psei->lpDirectory[0])
     {
-        DWORD attr = GetFileAttributesW(psei->lpDirectory);
-        if (attr != INVALID_FILE_ATTRIBUTES && attr & FILE_ATTRIBUTE_DIRECTORY)
-            lpDirectory = psei->lpDirectory;
+        /* ShellExecute specifies the command from psei->lpDirectory
+         * if present. Not from the current dir as CreateProcess does */
+        if( ( gcdret = GetCurrentDirectoryW( MAX_PATH, curdir )))
+            if( !SetCurrentDirectoryW( psei->lpDirectory ))
+                ERR("cannot set directory %s\n", debugstr_w(psei->lpDirectory ));
     }
 
-    /* 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))
-                ERR("cannot set directory %s\n", debugstr_w(lpDirectory));
     ZeroMemory(&startup,sizeof(STARTUPINFOW));
     startup.cb = sizeof(STARTUPINFOW);
     startup.dwFlags = STARTF_USESHOWWINDOW;
@@ -345,7 +340,7 @@ static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
     if (!(psei->fMask & SEE_MASK_NO_CONSOLE))
         dwCreationFlags |= CREATE_NEW_CONSOLE;
     if (CreateProcessW(NULL, (LPWSTR)lpCmd, NULL, NULL, FALSE, dwCreationFlags, env,
-                       lpDirectory, &startup, &info))
+                       NULL, &startup, &info))
     {
         /* Give 30 seconds to the app to come up, if desired. Probably only needed
            when starting app immediately before making a DDE connection. */
diff --git a/dlls/shell32/tests/shlexec.c b/dlls/shell32/tests/shlexec.c
index 2481fb6faa2..968953f9abb 100644
--- a/dlls/shell32/tests/shlexec.c
+++ b/dlls/shell32/tests/shlexec.c
@@ -2816,6 +2816,7 @@ static void test_directory(void)
     char path[MAX_PATH + 10], curdir[MAX_PATH];
     char params[1024], dirpath[1024];
     INT_PTR rc;
+    BOOL ret;
 
     sprintf(path, "%s\\test2.exe", tmpdir);
     CopyFileA(argv0, path, FALSE);
@@ -2876,7 +2877,18 @@ static void test_directory(void)
     okChildString("argvA0", path);
     okChildString("argvA3", "Exec");
     okChildPath("longPath", path);
+
+    SetCurrentDirectoryA(tmpdir);
+    ret = CreateDirectoryA( "tmp", NULL );
+    ok(ret || GetLastError() == ERROR_ALREADY_EXISTS, "Failed to create 'tmp' err %u\n", GetLastError());
+    rc=shell_execute_ex(SEE_MASK_NOZONECHECKS|SEE_MASK_FLAG_NO_UI,
+                        NULL, path, params, "tmp", NULL);
+    okShell(rc > 32, "returned %lu\n", rc);
+
     DeleteFileA(path);
+
+    RemoveDirectoryA("tmp");
+    SetCurrentDirectoryA(curdir);
 }
 
 START_TEST(shlexec)
-- 
2.31.1




More information about the wine-devel mailing list