[SHELL32][SHELL32_APITEST][SDK] Implement ShellExec_RunDLL (#7615)

Implementing missing features...
JIRA issue: CORE-19278
- Modify shell32.spec.
- Move function definitions
  from stubs.cpp into shlexec.cpp.
- Add prototypes to <undocshell.h>.
This commit is contained in:
Katayama Hirofumi MZ 2025-01-17 22:51:18 +09:00 committed by GitHub
parent a25e7ee9d7
commit dad3a0938a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 171 additions and 31 deletions

View file

@ -354,7 +354,7 @@
354 stdcall SheShortenPathW(wstr long)
355 stdcall ShellAboutA(long str str long)
356 stdcall ShellAboutW(long wstr wstr long)
357 stdcall ShellExec_RunDLL(ptr ptr wstr long)
357 stdcall ShellExec_RunDLL(ptr ptr str long) ShellExec_RunDLLA
358 stdcall ShellExec_RunDLLA(ptr ptr str long)
359 stdcall ShellExec_RunDLLW(ptr ptr wstr long)
360 stdcall ShellExecuteA(long str str str str long)

View file

@ -2986,3 +2986,88 @@ RealShellExecuteW(
lphProcess,
0);
}
// The common helper of ShellExec_RunDLLA and ShellExec_RunDLLW
static VOID
ShellExec_RunDLL_Helper(
_In_opt_ HWND hwnd,
_In_opt_ HINSTANCE hInstance,
_In_ PCWSTR pszCmdLine,
_In_ INT nCmdShow)
{
TRACE("(%p, %p, %s, 0x%X)\n", hwnd, hInstance, wine_dbgstr_w(pszCmdLine), nCmdShow);
if (!pszCmdLine || !*pszCmdLine)
return;
// '?' enables us to specify the additional mask value
ULONG fNewMask = SEE_MASK_NOASYNC;
if (*pszCmdLine == L'?') // 1st question
{
INT MaskValue;
if (StrToIntExW(pszCmdLine + 1, STIF_SUPPORT_HEX, &MaskValue))
fNewMask |= MaskValue;
PCWSTR pch2ndQuestion = StrChrW(pszCmdLine + 1, L'?'); // 2nd question
if (pch2ndQuestion)
pszCmdLine = pch2ndQuestion + 1;
}
WCHAR szPath[2 * MAX_PATH];
if (PathProcessCommandAW(pszCmdLine, szPath, _countof(szPath), L'C') == -1)
StrCpyNW(szPath, pszCmdLine, _countof(szPath));
// Split arguments from the path
LPWSTR Args = PathGetArgsW(szPath);
if (*Args)
*(Args - 1) = UNICODE_NULL;
PathUnquoteSpacesW(szPath);
// Execute
SHELLEXECUTEINFOW execInfo = { sizeof(execInfo) };
execInfo.fMask = fNewMask;
execInfo.hwnd = hwnd;
execInfo.lpFile = szPath;
execInfo.lpParameters = Args;
execInfo.nShow = nCmdShow;
if (!ShellExecuteExW(&execInfo))
{
DWORD dwError = GetLastError();
if (SHELL_InRunDllProcess()) // Is it a RUNDLL process?
ExitProcess(dwError); // Terminate it now
}
}
/*************************************************************************
* ShellExec_RunDLLA [SHELL32.358]
*
* @see https://www.hexacorn.com/blog/2024/11/30/1-little-known-secret-of-shellexec_rundll/
*/
EXTERN_C
VOID WINAPI
ShellExec_RunDLLA(
_In_opt_ HWND hwnd,
_In_opt_ HINSTANCE hInstance,
_In_ PCSTR pszCmdLine,
_In_ INT nCmdShow)
{
CStringW strCmdLine = pszCmdLine; // Keep
ShellExec_RunDLL_Helper(hwnd, hInstance, strCmdLine, nCmdShow);
}
/*************************************************************************
* ShellExec_RunDLLW [SHELL32.359]
*
* @see https://www.hexacorn.com/blog/2024/11/30/1-little-known-secret-of-shellexec_rundll/
*/
EXTERN_C
VOID WINAPI
ShellExec_RunDLLW(
_In_opt_ HWND hwnd,
_In_opt_ HINSTANCE hInstance,
_In_ PCWSTR pszCmdLine,
_In_ INT nCmdShow)
{
ShellExec_RunDLL_Helper(hwnd, hInstance, pszCmdLine, nCmdShow);
}

View file

@ -297,36 +297,6 @@ ShellHookProc(INT iCode, WPARAM wParam, LPARAM lParam)
return 0;
}
/*
* Unimplemented
*/
EXTERN_C VOID
WINAPI
ShellExec_RunDLL(HWND hwnd, HINSTANCE hInstance, LPWSTR pszCmdLine, int nCmdShow)
{
FIXME("ShellExec_RunDLL() stub\n");
}
/*
* Unimplemented
*/
EXTERN_C VOID
WINAPI
ShellExec_RunDLLA(HWND hwnd, HINSTANCE hInstance, LPSTR pszCmdLine, int nCmdShow)
{
FIXME("ShellExec_RunDLLA() stub\n");
}
/*
* Unimplemented
*/
EXTERN_C VOID
WINAPI
ShellExec_RunDLLW(HWND hwnd, HINSTANCE hInstance, LPWSTR pszCmdLine, int nCmdShow)
{
FIXME("ShellExec_RunDLLW() stub\n");
}
/*
* Unimplemented
*/

View file

@ -35,6 +35,7 @@ list(APPEND SOURCE
SHRestricted.cpp
SHShouldShowWizards.cpp
She.cpp
ShellExec_RunDLL.cpp
ShellExecCmdLine.cpp
ShellExecuteEx.cpp
ShellExecuteW.cpp

View file

@ -0,0 +1,61 @@
/*
* PROJECT: ReactOS API tests
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Test for ShellExec_RunDLL
* COPYRIGHT: Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include "shelltest.h"
#include "closewnd.h"
#include <undocshell.h>
static WINDOW_LIST s_List1, s_List2;
static VOID TEST_ShellExec_RunDLL(VOID)
{
ShellExec_RunDLL(NULL, NULL, "?0?notepad.exe", SW_SHOWNORMAL);
}
static VOID TEST_ShellExec_RunDLLA(VOID)
{
ShellExec_RunDLLA(NULL, NULL, "?0?notepad.exe", SW_SHOWNORMAL);
}
static VOID TEST_ShellExec_RunDLLW(VOID)
{
ShellExec_RunDLLW(NULL, NULL, L"?0?notepad.exe", SW_SHOWNORMAL);
}
static VOID CleanupWindowList(VOID)
{
GetWindowListForClose(&s_List2);
CloseNewWindows(&s_List1, &s_List2);
FreeWindowList(&s_List1);
FreeWindowList(&s_List2);
}
START_TEST(ShellExec_RunDLL)
{
HWND hwndNotepad;
GetWindowList(&s_List1);
TEST_ShellExec_RunDLL();
Sleep(1000);
hwndNotepad = FindWindowW(L"Notepad", NULL);
ok(hwndNotepad != NULL, "Notepad not found\n");
CleanupWindowList();
GetWindowList(&s_List1);
TEST_ShellExec_RunDLLA();
Sleep(1000);
hwndNotepad = FindWindowW(L"Notepad", NULL);
ok(hwndNotepad != NULL, "Notepad not found\n");
CleanupWindowList();
GetWindowList(&s_List1);
TEST_ShellExec_RunDLLW();
Sleep(1000);
hwndNotepad = FindWindowW(L"Notepad", NULL);
ok(hwndNotepad != NULL, "Notepad not found\n");
CleanupWindowList();
}

View file

@ -35,6 +35,7 @@ extern void func_SHCreateDataObject(void);
extern void func_SHCreateFileDataObject(void);
extern void func_SHCreateFileExtractIconW(void);
extern void func_She(void);
extern void func_ShellExec_RunDLL(void);
extern void func_ShellExecCmdLine(void);
extern void func_ShellExecuteEx(void);
extern void func_ShellExecuteW(void);
@ -83,6 +84,7 @@ const struct test winetest_testlist[] =
{ "SHCreateFileDataObject", func_SHCreateFileDataObject },
{ "SHCreateFileExtractIconW", func_SHCreateFileExtractIconW },
{ "She", func_She },
{ "ShellExec_RunDLL", func_ShellExec_RunDLL },
{ "ShellExecCmdLine", func_ShellExecCmdLine },
{ "ShellExecuteEx", func_ShellExecuteEx },
{ "ShellExecuteW", func_ShellExecuteW },

View file

@ -712,6 +712,27 @@ RealShellExecuteExW(
_Out_opt_ PHANDLE lphProcess,
_In_ DWORD dwFlags);
VOID WINAPI
ShellExec_RunDLL(
_In_opt_ HWND hwnd,
_In_opt_ HINSTANCE hInstance,
_In_ PCSTR pszCmdLine,
_In_ INT nCmdShow);
VOID WINAPI
ShellExec_RunDLLA(
_In_opt_ HWND hwnd,
_In_opt_ HINSTANCE hInstance,
_In_ PCSTR pszCmdLine,
_In_ INT nCmdShow);
VOID WINAPI
ShellExec_RunDLLW(
_In_opt_ HWND hwnd,
_In_opt_ HINSTANCE hInstance,
_In_ PCWSTR pszCmdLine,
_In_ INT nCmdShow);
/* RegisterShellHook types */
#define RSH_DEREGISTER 0
#define RSH_REGISTER 1