[SHELL32][SHELL32_APITEST] ShellExecute should accept invalid directory (#7150)

Implement parsing SHELLEXECUTEINFO.lpDirectory.
Enhance ShellExecuteEx testcase for invalid directory.
This commit is contained in:
Katayama Hirofumi MZ 2024-07-19 17:40:36 +09:00 committed by GitHub
parent 466a19817f
commit 089788a52a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 62 additions and 18 deletions

View file

@ -1983,21 +1983,48 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
else
*wszParameters = L'\0';
// Get the working directory
WCHAR dirBuffer[MAX_PATH];
LPWSTR wszDir = dirBuffer;
wszDir[0] = UNICODE_NULL;
CHeapPtr<WCHAR, CLocalAllocator> wszDirAlloc;
if (sei_tmp.lpDirectory)
if (sei_tmp.lpDirectory && *sei_tmp.lpDirectory)
{
len = lstrlenW(sei_tmp.lpDirectory) + 1;
if (len > _countof(dirBuffer))
if (sei_tmp.fMask & SEE_MASK_DOENVSUBST)
{
wszDirAlloc.Allocate(len);
wszDir = wszDirAlloc;
LPWSTR tmp = expand_environment(sei_tmp.lpDirectory);
if (tmp)
{
wszDirAlloc.Attach(tmp);
wszDir = wszDirAlloc;
}
}
else
{
__SHCloneStrW(&wszDirAlloc, sei_tmp.lpDirectory);
if (wszDirAlloc)
wszDir = wszDirAlloc;
}
}
if (!wszDir[0])
{
::GetCurrentDirectoryW(_countof(dirBuffer), dirBuffer);
wszDir = dirBuffer;
}
// NOTE: ShellExecute should accept the invalid working directory for historical reason.
if (!PathIsDirectoryW(wszDir))
{
INT iDrive = PathGetDriveNumberW(wszDir);
if (iDrive >= 0)
{
PathStripToRootW(wszDir);
if (!PathIsDirectoryW(wszDir))
{
::GetWindowsDirectoryW(dirBuffer, _countof(dirBuffer));
wszDir = dirBuffer;
}
}
strcpyW(wszDir, sei_tmp.lpDirectory);
}
else
*wszDir = L'\0';
/* adjust string pointers to point to the new buffers */
sei_tmp.lpFile = wszApplicationName;
@ -2128,16 +2155,6 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
}
}
if (*sei_tmp.lpDirectory)
{
LPWSTR tmp = expand_environment(sei_tmp.lpDirectory);
if (tmp)
{
wszDirAlloc.Attach(tmp);
sei_tmp.lpDirectory = wszDir = wszDirAlloc;
}
}
/* Else, try to execute the filename */
TRACE("execute: %s,%s,%s\n", debugstr_w(wszApplicationName), debugstr_w(wszParameters), debugstr_w(wszDir));

View file

@ -14,6 +14,7 @@
#include <stdio.h>
#include <strsafe.h>
#include <versionhelpers.h>
#include "shell32_apitest_sub.h"
static WCHAR s_win_dir[MAX_PATH];
static WCHAR s_sys_dir[MAX_PATH];
@ -440,6 +441,31 @@ static void TEST_AppPath(void)
}
}
static void test_DoInvalidDir(void)
{
WCHAR szSubProgram[MAX_PATH];
if (!FindSubProgram(szSubProgram, _countof(szSubProgram)))
{
skip("shell32_apitest_sub.exe not found\n");
return;
}
DWORD dwExitCode;
SHELLEXECUTEINFOW sei = { sizeof(sei), SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS };
sei.lpFile = szSubProgram;
sei.lpParameters = L"TEST";
sei.nShow = SW_SHOWNORMAL;
// Test invalid path on sei.lpDirectory
WCHAR szInvalidPath[MAX_PATH] = L"M:\\This is an invalid path\n";
sei.lpDirectory = szInvalidPath;
ok_int(ShellExecuteExW(&sei), TRUE);
WaitForSingleObject(sei.hProcess, 20 * 1000);
GetExitCodeProcess(sei.hProcess, &dwExitCode);
ok_long(dwExitCode, 0);
CloseHandle(sei.hProcess);
}
START_TEST(ShellExecuteEx)
{
#ifdef _WIN64
@ -454,6 +480,7 @@ START_TEST(ShellExecuteEx)
TEST_DoTestEntries();
test_properties();
test_sei_lpIDList();
test_DoInvalidDir();
TEST_End();
}