Skip to content

Commit dad3a09

Browse files
authored
[SHELL32][SHELL32_APITEST][SDK] Implement ShellExec_RunDLL (reactos#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>.
1 parent a25e7ee commit dad3a09

File tree

7 files changed

+171
-31
lines changed

7 files changed

+171
-31
lines changed

dll/win32/shell32/shell32.spec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@
354354
354 stdcall SheShortenPathW(wstr long)
355355
355 stdcall ShellAboutA(long str str long)
356356
356 stdcall ShellAboutW(long wstr wstr long)
357-
357 stdcall ShellExec_RunDLL(ptr ptr wstr long)
357+
357 stdcall ShellExec_RunDLL(ptr ptr str long) ShellExec_RunDLLA
358358
358 stdcall ShellExec_RunDLLA(ptr ptr str long)
359359
359 stdcall ShellExec_RunDLLW(ptr ptr wstr long)
360360
360 stdcall ShellExecuteA(long str str str str long)

dll/win32/shell32/shlexec.cpp

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2986,3 +2986,88 @@ RealShellExecuteW(
29862986
lphProcess,
29872987
0);
29882988
}
2989+
2990+
// The common helper of ShellExec_RunDLLA and ShellExec_RunDLLW
2991+
static VOID
2992+
ShellExec_RunDLL_Helper(
2993+
_In_opt_ HWND hwnd,
2994+
_In_opt_ HINSTANCE hInstance,
2995+
_In_ PCWSTR pszCmdLine,
2996+
_In_ INT nCmdShow)
2997+
{
2998+
TRACE("(%p, %p, %s, 0x%X)\n", hwnd, hInstance, wine_dbgstr_w(pszCmdLine), nCmdShow);
2999+
3000+
if (!pszCmdLine || !*pszCmdLine)
3001+
return;
3002+
3003+
// '?' enables us to specify the additional mask value
3004+
ULONG fNewMask = SEE_MASK_NOASYNC;
3005+
if (*pszCmdLine == L'?') // 1st question
3006+
{
3007+
INT MaskValue;
3008+
if (StrToIntExW(pszCmdLine + 1, STIF_SUPPORT_HEX, &MaskValue))
3009+
fNewMask |= MaskValue;
3010+
3011+
PCWSTR pch2ndQuestion = StrChrW(pszCmdLine + 1, L'?'); // 2nd question
3012+
if (pch2ndQuestion)
3013+
pszCmdLine = pch2ndQuestion + 1;
3014+
}
3015+
3016+
WCHAR szPath[2 * MAX_PATH];
3017+
if (PathProcessCommandAW(pszCmdLine, szPath, _countof(szPath), L'C') == -1)
3018+
StrCpyNW(szPath, pszCmdLine, _countof(szPath));
3019+
3020+
// Split arguments from the path
3021+
LPWSTR Args = PathGetArgsW(szPath);
3022+
if (*Args)
3023+
*(Args - 1) = UNICODE_NULL;
3024+
3025+
PathUnquoteSpacesW(szPath);
3026+
3027+
// Execute
3028+
SHELLEXECUTEINFOW execInfo = { sizeof(execInfo) };
3029+
execInfo.fMask = fNewMask;
3030+
execInfo.hwnd = hwnd;
3031+
execInfo.lpFile = szPath;
3032+
execInfo.lpParameters = Args;
3033+
execInfo.nShow = nCmdShow;
3034+
if (!ShellExecuteExW(&execInfo))
3035+
{
3036+
DWORD dwError = GetLastError();
3037+
if (SHELL_InRunDllProcess()) // Is it a RUNDLL process?
3038+
ExitProcess(dwError); // Terminate it now
3039+
}
3040+
}
3041+
3042+
/*************************************************************************
3043+
* ShellExec_RunDLLA [SHELL32.358]
3044+
*
3045+
* @see https://www.hexacorn.com/blog/2024/11/30/1-little-known-secret-of-shellexec_rundll/
3046+
*/
3047+
EXTERN_C
3048+
VOID WINAPI
3049+
ShellExec_RunDLLA(
3050+
_In_opt_ HWND hwnd,
3051+
_In_opt_ HINSTANCE hInstance,
3052+
_In_ PCSTR pszCmdLine,
3053+
_In_ INT nCmdShow)
3054+
{
3055+
CStringW strCmdLine = pszCmdLine; // Keep
3056+
ShellExec_RunDLL_Helper(hwnd, hInstance, strCmdLine, nCmdShow);
3057+
}
3058+
3059+
/*************************************************************************
3060+
* ShellExec_RunDLLW [SHELL32.359]
3061+
*
3062+
* @see https://www.hexacorn.com/blog/2024/11/30/1-little-known-secret-of-shellexec_rundll/
3063+
*/
3064+
EXTERN_C
3065+
VOID WINAPI
3066+
ShellExec_RunDLLW(
3067+
_In_opt_ HWND hwnd,
3068+
_In_opt_ HINSTANCE hInstance,
3069+
_In_ PCWSTR pszCmdLine,
3070+
_In_ INT nCmdShow)
3071+
{
3072+
ShellExec_RunDLL_Helper(hwnd, hInstance, pszCmdLine, nCmdShow);
3073+
}

dll/win32/shell32/stubs.cpp

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -297,36 +297,6 @@ ShellHookProc(INT iCode, WPARAM wParam, LPARAM lParam)
297297
return 0;
298298
}
299299

300-
/*
301-
* Unimplemented
302-
*/
303-
EXTERN_C VOID
304-
WINAPI
305-
ShellExec_RunDLL(HWND hwnd, HINSTANCE hInstance, LPWSTR pszCmdLine, int nCmdShow)
306-
{
307-
FIXME("ShellExec_RunDLL() stub\n");
308-
}
309-
310-
/*
311-
* Unimplemented
312-
*/
313-
EXTERN_C VOID
314-
WINAPI
315-
ShellExec_RunDLLA(HWND hwnd, HINSTANCE hInstance, LPSTR pszCmdLine, int nCmdShow)
316-
{
317-
FIXME("ShellExec_RunDLLA() stub\n");
318-
}
319-
320-
/*
321-
* Unimplemented
322-
*/
323-
EXTERN_C VOID
324-
WINAPI
325-
ShellExec_RunDLLW(HWND hwnd, HINSTANCE hInstance, LPWSTR pszCmdLine, int nCmdShow)
326-
{
327-
FIXME("ShellExec_RunDLLW() stub\n");
328-
}
329-
330300
/*
331301
* Unimplemented
332302
*/

modules/rostests/apitests/shell32/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ list(APPEND SOURCE
3535
SHRestricted.cpp
3636
SHShouldShowWizards.cpp
3737
She.cpp
38+
ShellExec_RunDLL.cpp
3839
ShellExecCmdLine.cpp
3940
ShellExecuteEx.cpp
4041
ShellExecuteW.cpp
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* PROJECT: ReactOS API tests
3+
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4+
* PURPOSE: Test for ShellExec_RunDLL
5+
* COPYRIGHT: Copyright 2025 Katayama Hirofumi MZ <[email protected]>
6+
*/
7+
8+
#include "shelltest.h"
9+
#include "closewnd.h"
10+
#include <undocshell.h>
11+
12+
static WINDOW_LIST s_List1, s_List2;
13+
14+
static VOID TEST_ShellExec_RunDLL(VOID)
15+
{
16+
ShellExec_RunDLL(NULL, NULL, "?0?notepad.exe", SW_SHOWNORMAL);
17+
}
18+
19+
static VOID TEST_ShellExec_RunDLLA(VOID)
20+
{
21+
ShellExec_RunDLLA(NULL, NULL, "?0?notepad.exe", SW_SHOWNORMAL);
22+
}
23+
24+
static VOID TEST_ShellExec_RunDLLW(VOID)
25+
{
26+
ShellExec_RunDLLW(NULL, NULL, L"?0?notepad.exe", SW_SHOWNORMAL);
27+
}
28+
29+
static VOID CleanupWindowList(VOID)
30+
{
31+
GetWindowListForClose(&s_List2);
32+
CloseNewWindows(&s_List1, &s_List2);
33+
FreeWindowList(&s_List1);
34+
FreeWindowList(&s_List2);
35+
}
36+
37+
START_TEST(ShellExec_RunDLL)
38+
{
39+
HWND hwndNotepad;
40+
41+
GetWindowList(&s_List1);
42+
TEST_ShellExec_RunDLL();
43+
Sleep(1000);
44+
hwndNotepad = FindWindowW(L"Notepad", NULL);
45+
ok(hwndNotepad != NULL, "Notepad not found\n");
46+
CleanupWindowList();
47+
48+
GetWindowList(&s_List1);
49+
TEST_ShellExec_RunDLLA();
50+
Sleep(1000);
51+
hwndNotepad = FindWindowW(L"Notepad", NULL);
52+
ok(hwndNotepad != NULL, "Notepad not found\n");
53+
CleanupWindowList();
54+
55+
GetWindowList(&s_List1);
56+
TEST_ShellExec_RunDLLW();
57+
Sleep(1000);
58+
hwndNotepad = FindWindowW(L"Notepad", NULL);
59+
ok(hwndNotepad != NULL, "Notepad not found\n");
60+
CleanupWindowList();
61+
}

modules/rostests/apitests/shell32/testlist.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ extern void func_SHCreateDataObject(void);
3535
extern void func_SHCreateFileDataObject(void);
3636
extern void func_SHCreateFileExtractIconW(void);
3737
extern void func_She(void);
38+
extern void func_ShellExec_RunDLL(void);
3839
extern void func_ShellExecCmdLine(void);
3940
extern void func_ShellExecuteEx(void);
4041
extern void func_ShellExecuteW(void);
@@ -83,6 +84,7 @@ const struct test winetest_testlist[] =
8384
{ "SHCreateFileDataObject", func_SHCreateFileDataObject },
8485
{ "SHCreateFileExtractIconW", func_SHCreateFileExtractIconW },
8586
{ "She", func_She },
87+
{ "ShellExec_RunDLL", func_ShellExec_RunDLL },
8688
{ "ShellExecCmdLine", func_ShellExecCmdLine },
8789
{ "ShellExecuteEx", func_ShellExecuteEx },
8890
{ "ShellExecuteW", func_ShellExecuteW },

sdk/include/reactos/undocshell.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,27 @@ RealShellExecuteExW(
712712
_Out_opt_ PHANDLE lphProcess,
713713
_In_ DWORD dwFlags);
714714

715+
VOID WINAPI
716+
ShellExec_RunDLL(
717+
_In_opt_ HWND hwnd,
718+
_In_opt_ HINSTANCE hInstance,
719+
_In_ PCSTR pszCmdLine,
720+
_In_ INT nCmdShow);
721+
722+
VOID WINAPI
723+
ShellExec_RunDLLA(
724+
_In_opt_ HWND hwnd,
725+
_In_opt_ HINSTANCE hInstance,
726+
_In_ PCSTR pszCmdLine,
727+
_In_ INT nCmdShow);
728+
729+
VOID WINAPI
730+
ShellExec_RunDLLW(
731+
_In_opt_ HWND hwnd,
732+
_In_opt_ HINSTANCE hInstance,
733+
_In_ PCWSTR pszCmdLine,
734+
_In_ INT nCmdShow);
735+
715736
/* RegisterShellHook types */
716737
#define RSH_DEREGISTER 0
717738
#define RSH_REGISTER 1

0 commit comments

Comments
 (0)