https://git.reactos.org/?p=reactos.git;a=commitdiff;h=dad3a0938afd502831a8e401aae2b6b5a7fc3c92

commit dad3a0938afd502831a8e401aae2b6b5a7fc3c92
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Fri Jan 17 22:51:18 2025 +0900
Commit:     GitHub <nore...@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_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);
+}
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...@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

Reply via email to