Skip to content

Commit 81d845f

Browse files
authored
[SHELL32] Implement PathProcessCommandW (reactos#7818)
Follow-up of reactos#7815. This function affects ShellExec_RunDLLA/W implementation. JIRA issue: CORE-17659 - Implement PathProcessCommandW in shlexec.cpp. - Adapt utils.h to non-C++.
1 parent 467dec4 commit 81d845f

File tree

4 files changed

+143
-5
lines changed

4 files changed

+143
-5
lines changed

dll/win32/shell32/shlexec.cpp

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2976,6 +2976,127 @@ RealShellExecuteW(
29762976
0);
29772977
}
29782978

2979+
/*************************************************************************
2980+
* PathProcessCommandW [Internal]
2981+
*
2982+
* @see https://learn.microsoft.com/en-us/windows/win32/api/shlobj/nf-shlobj-pathprocesscommand
2983+
* @see ./wine/shellpath.c
2984+
*/
2985+
EXTERN_C LONG
2986+
PathProcessCommandW(
2987+
_In_ PCWSTR pszSrc,
2988+
_Out_writes_opt_(dwBuffSize) PWSTR pszDest,
2989+
_In_ INT cchDest,
2990+
_In_ DWORD dwFlags)
2991+
{
2992+
TRACE("%s, %p, %d, 0x%X\n", wine_dbgstr_w(pszSrc), pszDest, cchDest, dwFlags);
2993+
2994+
if (!pszSrc)
2995+
return -1;
2996+
2997+
CStringW szPath;
2998+
PCWSTR pchArg = NULL;
2999+
3000+
if (*pszSrc == L'"') // Quoted?
3001+
{
3002+
++pszSrc;
3003+
3004+
PCWSTR pch = wcschr(pszSrc, L'"');
3005+
if (pch)
3006+
{
3007+
szPath.SetString(pszSrc, pch - pszSrc);
3008+
pchArg = pch + 1;
3009+
}
3010+
else
3011+
{
3012+
szPath = pszSrc;
3013+
}
3014+
3015+
if ((dwFlags & PPCF_FORCEQUALIFY) || PathIsRelativeW(szPath))
3016+
{
3017+
BOOL ret = PathResolveW(szPath.GetBuffer(MAX_PATH), NULL, PRF_TRYPROGRAMEXTENSIONS);
3018+
szPath.ReleaseBuffer();
3019+
if (!ret)
3020+
return -1;
3021+
}
3022+
}
3023+
else // Not quoted?
3024+
{
3025+
BOOL resolved = FALSE;
3026+
BOOL resolveRelative = PathIsRelativeW(pszSrc) || (dwFlags & PPCF_FORCEQUALIFY);
3027+
INT cchPath = 0;
3028+
3029+
for (INT ich = 0; ; ++ich)
3030+
{
3031+
szPath += pszSrc[ich];
3032+
3033+
if (pszSrc[ich] && pszSrc[ich] != L' ')
3034+
continue;
3035+
3036+
szPath = szPath.Left(ich);
3037+
3038+
if (resolveRelative &&
3039+
!PathResolveW(szPath.GetBuffer(MAX_PATH), NULL, PRF_TRYPROGRAMEXTENSIONS))
3040+
{
3041+
szPath.ReleaseBuffer();
3042+
szPath += pszSrc[ich];
3043+
}
3044+
else
3045+
{
3046+
szPath.ReleaseBuffer();
3047+
3048+
DWORD attrs = GetFileAttributesW(szPath);
3049+
if (attrs != INVALID_FILE_ATTRIBUTES &&
3050+
(!(attrs & FILE_ATTRIBUTE_DIRECTORY) || !(dwFlags & PPCF_NODIRECTORIES)))
3051+
{
3052+
resolved = TRUE;
3053+
pchArg = pszSrc + ich;
3054+
3055+
if (!(dwFlags & PPCF_LONGESTPOSSIBLE))
3056+
break;
3057+
3058+
cchPath = ich;
3059+
break;
3060+
}
3061+
else if (!resolveRelative)
3062+
{
3063+
szPath += pszSrc[ich];
3064+
}
3065+
}
3066+
3067+
if (!szPath[ich])
3068+
{
3069+
szPath.ReleaseBuffer(); // Remove excessive '\0'
3070+
break;
3071+
}
3072+
}
3073+
3074+
if (!resolved)
3075+
return -1;
3076+
3077+
if (cchPath && (dwFlags & PPCF_LONGESTPOSSIBLE))
3078+
{
3079+
szPath = szPath.Left(cchPath);
3080+
pchArg = pszSrc + cchPath;
3081+
}
3082+
}
3083+
3084+
BOOL needsQuoting = (dwFlags & PPCF_ADDQUOTES) && wcschr(szPath, L' ');
3085+
CStringW result = needsQuoting ? (L"\"" + szPath + L"\"") : szPath;
3086+
3087+
if (pchArg && (dwFlags & PPCF_ADDARGUMENTS))
3088+
result += pchArg;
3089+
3090+
LONG requiredSize = result.GetLength() + 1;
3091+
if (!pszDest)
3092+
return requiredSize;
3093+
3094+
if (requiredSize > cchDest || StringCchCopyW(pszDest, cchDest, result) != S_OK)
3095+
return -1;
3096+
3097+
return requiredSize;
3098+
}
3099+
29793100
// The common helper of ShellExec_RunDLLA and ShellExec_RunDLLW
29803101
static VOID
29813102
ShellExec_RunDLL_Helper(
@@ -3003,7 +3124,8 @@ ShellExec_RunDLL_Helper(
30033124
}
30043125

30053126
WCHAR szPath[2 * MAX_PATH];
3006-
if (PathProcessCommandAW(pszCmdLine, szPath, _countof(szPath), L'C') == -1)
3127+
DWORD dwFlags = PPCF_FORCEQUALIFY | PPCF_INCLUDEARGS | PPCF_ADDQUOTES;
3128+
if (PathProcessCommandW(pszCmdLine, szPath, _countof(szPath), dwFlags) == -1)
30073129
StrCpyNW(szPath, pszCmdLine, _countof(szPath));
30083130

30093131
// Split arguments from the path

dll/win32/shell32/utils.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@
77

88
#pragma once
99

10+
#ifndef OPTIONAL_
11+
#ifdef __cplusplus
12+
#define OPTIONAL_(arg) = arg
13+
#else
14+
#define OPTIONAL_(arg)
15+
#endif
16+
#endif
17+
1018
#ifdef __cplusplus
1119
static inline LPWSTR
1220
SHStrDupW(LPCWSTR Src)
@@ -50,15 +58,15 @@ inline DWORD
5058
RegSetOrDelete(HKEY hKey, LPCWSTR Name, DWORD Type, LPCVOID Data, DWORD Size)
5159
{
5260
if (Data)
53-
return RegSetValueExW(hKey, Name, 0, Type, LPBYTE(Data), Size);
61+
return RegSetValueExW(hKey, Name, 0, Type, (LPBYTE)Data, Size);
5462
else
5563
return RegDeleteValueW(hKey, Name);
5664
}
5765

5866
static inline DWORD
59-
RegSetString(HKEY hKey, LPCWSTR Name, LPCWSTR Str, DWORD Type = REG_SZ)
67+
RegSetString(HKEY hKey, LPCWSTR Name, LPCWSTR Str, DWORD Type OPTIONAL_(REG_SZ))
6068
{
61-
return RegSetValueExW(hKey, Name, 0, Type, LPBYTE(Str), (lstrlenW(Str) + 1) * sizeof(WCHAR));
69+
return RegSetValueExW(hKey, Name, 0, Type, (LPBYTE)Str, (lstrlenW(Str) + 1) * sizeof(WCHAR));
6270
}
6371

6472
typedef struct

dll/win32/shell32/wine/shell32_main.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,16 @@ BOOL HCR_GetFolderAttributes(LPCITEMIDLIST pidlFolder, LPDWORD dwAttributes) DEC
7676
HRESULT SHELL32_AssocGetFSDirectoryDescription(PWSTR Buf, UINT cchBuf);
7777
HRESULT SHELL32_AssocGetFileDescription(PCWSTR Name, PWSTR Buf, UINT cchBuf);
7878

79-
8079
DWORD WINAPI ParseFieldA(LPCSTR src, DWORD nField, LPSTR dst, DWORD len) DECLSPEC_HIDDEN;
8180
DWORD WINAPI ParseFieldW(LPCWSTR src, DWORD nField, LPWSTR dst, DWORD len) DECLSPEC_HIDDEN;
8281

82+
LONG
83+
PathProcessCommandW(
84+
_In_ PCWSTR pszSrc,
85+
_Out_writes_opt_(dwBuffSize) PWSTR pszDest,
86+
_In_ INT cchDest,
87+
_In_ DWORD dwFlags);
88+
8389
/****************************************************************************
8490
* Class constructors
8591
*/

dll/win32/shell32/wine/shellpath.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,7 @@ static LONG PathProcessCommandA (
11301130
return strlen(lpszPath);
11311131
}
11321132

1133+
#ifndef __REACTOS__ // See ../shlexec.cpp
11331134
/*************************************************************************
11341135
* PathProcessCommandW
11351136
*/
@@ -1145,6 +1146,7 @@ static LONG PathProcessCommandW (
11451146
if(lpszBuff) strcpyW(lpszBuff, lpszPath);
11461147
return strlenW(lpszPath);
11471148
}
1149+
#endif
11481150

11491151
/*************************************************************************
11501152
* PathProcessCommand (SHELL32.653)

0 commit comments

Comments
 (0)