https://git.reactos.org/?p=reactos.git;a=commitdiff;h=dad3a0938afd502831a8e…
commit dad3a0938afd502831a8e401aae2b6b5a7fc3c92
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Fri Jan 17 22:51:18 2025 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Fri Jan 17 22:51:18 2025 +0900
[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>.
---
dll/win32/shell32/shell32.spec | 2 +-
dll/win32/shell32/shlexec.cpp | 85 ++++++++++++++++++++++
dll/win32/shell32/stubs.cpp | 30 --------
modules/rostests/apitests/shell32/CMakeLists.txt | 1 +
.../rostests/apitests/shell32/ShellExec_RunDLL.cpp | 61 ++++++++++++++++
modules/rostests/apitests/shell32/testlist.c | 2 +
sdk/include/reactos/undocshell.h | 21 ++++++
7 files changed, 171 insertions(+), 31 deletions(-)
diff --git a/dll/win32/shell32/shell32.spec b/dll/win32/shell32/shell32.spec
index 759f4676e94..9a4f8b07c43 100644
--- a/dll/win32/shell32/shell32.spec
+++ b/dll/win32/shell32/shell32.spec
@@ -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)
diff --git a/dll/win32/shell32/shlexec.cpp b/dll/win32/shell32/shlexec.cpp
index f03db3de0e7..646a2a6c84c 100644
--- a/dll/win32/shell32/shlexec.cpp
+++ b/dll/win32/shell32/shlexec.cpp
@@ -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…
+ */
+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…
+ */
+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);
+}
diff --git a/dll/win32/shell32/stubs.cpp b/dll/win32/shell32/stubs.cpp
index d54e80c14af..5fec3d1e342 100644
--- a/dll/win32/shell32/stubs.cpp
+++ b/dll/win32/shell32/stubs.cpp
@@ -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
*/
diff --git a/modules/rostests/apitests/shell32/CMakeLists.txt
b/modules/rostests/apitests/shell32/CMakeLists.txt
index 10ef4004e7c..39f1092027e 100644
--- a/modules/rostests/apitests/shell32/CMakeLists.txt
+++ b/modules/rostests/apitests/shell32/CMakeLists.txt
@@ -35,6 +35,7 @@ list(APPEND SOURCE
SHRestricted.cpp
SHShouldShowWizards.cpp
She.cpp
+ ShellExec_RunDLL.cpp
ShellExecCmdLine.cpp
ShellExecuteEx.cpp
ShellExecuteW.cpp
diff --git a/modules/rostests/apitests/shell32/ShellExec_RunDLL.cpp
b/modules/rostests/apitests/shell32/ShellExec_RunDLL.cpp
new file mode 100644
index 00000000000..bea1d8b0682
--- /dev/null
+++ b/modules/rostests/apitests/shell32/ShellExec_RunDLL.cpp
@@ -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(a)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();
+}
diff --git a/modules/rostests/apitests/shell32/testlist.c
b/modules/rostests/apitests/shell32/testlist.c
index 0da5972b358..134f01a7838 100644
--- a/modules/rostests/apitests/shell32/testlist.c
+++ b/modules/rostests/apitests/shell32/testlist.c
@@ -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 },
diff --git a/sdk/include/reactos/undocshell.h b/sdk/include/reactos/undocshell.h
index 3e685e08046..beb840c89e2 100644
--- a/sdk/include/reactos/undocshell.h
+++ b/sdk/include/reactos/undocshell.h
@@ -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