mirror of
https://github.com/reactos/reactos.git
synced 2025-04-04 04:26:32 +00:00
[SHELL32] Implement PathProcessCommandW (#7818)
Follow-up of #7815. This function affects ShellExec_RunDLLA/W implementation. JIRA issue: CORE-17659 - Implement PathProcessCommandW in shlexec.cpp. - Adapt utils.h to non-C++.
This commit is contained in:
parent
467dec4d16
commit
81d845fb2c
4 changed files with 143 additions and 5 deletions
|
@ -2976,6 +2976,127 @@ RealShellExecuteW(
|
|||
0);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* PathProcessCommandW [Internal]
|
||||
*
|
||||
* @see https://learn.microsoft.com/en-us/windows/win32/api/shlobj/nf-shlobj-pathprocesscommand
|
||||
* @see ./wine/shellpath.c
|
||||
*/
|
||||
EXTERN_C LONG
|
||||
PathProcessCommandW(
|
||||
_In_ PCWSTR pszSrc,
|
||||
_Out_writes_opt_(dwBuffSize) PWSTR pszDest,
|
||||
_In_ INT cchDest,
|
||||
_In_ DWORD dwFlags)
|
||||
{
|
||||
TRACE("%s, %p, %d, 0x%X\n", wine_dbgstr_w(pszSrc), pszDest, cchDest, dwFlags);
|
||||
|
||||
if (!pszSrc)
|
||||
return -1;
|
||||
|
||||
CStringW szPath;
|
||||
PCWSTR pchArg = NULL;
|
||||
|
||||
if (*pszSrc == L'"') // Quoted?
|
||||
{
|
||||
++pszSrc;
|
||||
|
||||
PCWSTR pch = wcschr(pszSrc, L'"');
|
||||
if (pch)
|
||||
{
|
||||
szPath.SetString(pszSrc, pch - pszSrc);
|
||||
pchArg = pch + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
szPath = pszSrc;
|
||||
}
|
||||
|
||||
if ((dwFlags & PPCF_FORCEQUALIFY) || PathIsRelativeW(szPath))
|
||||
{
|
||||
BOOL ret = PathResolveW(szPath.GetBuffer(MAX_PATH), NULL, PRF_TRYPROGRAMEXTENSIONS);
|
||||
szPath.ReleaseBuffer();
|
||||
if (!ret)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else // Not quoted?
|
||||
{
|
||||
BOOL resolved = FALSE;
|
||||
BOOL resolveRelative = PathIsRelativeW(pszSrc) || (dwFlags & PPCF_FORCEQUALIFY);
|
||||
INT cchPath = 0;
|
||||
|
||||
for (INT ich = 0; ; ++ich)
|
||||
{
|
||||
szPath += pszSrc[ich];
|
||||
|
||||
if (pszSrc[ich] && pszSrc[ich] != L' ')
|
||||
continue;
|
||||
|
||||
szPath = szPath.Left(ich);
|
||||
|
||||
if (resolveRelative &&
|
||||
!PathResolveW(szPath.GetBuffer(MAX_PATH), NULL, PRF_TRYPROGRAMEXTENSIONS))
|
||||
{
|
||||
szPath.ReleaseBuffer();
|
||||
szPath += pszSrc[ich];
|
||||
}
|
||||
else
|
||||
{
|
||||
szPath.ReleaseBuffer();
|
||||
|
||||
DWORD attrs = GetFileAttributesW(szPath);
|
||||
if (attrs != INVALID_FILE_ATTRIBUTES &&
|
||||
(!(attrs & FILE_ATTRIBUTE_DIRECTORY) || !(dwFlags & PPCF_NODIRECTORIES)))
|
||||
{
|
||||
resolved = TRUE;
|
||||
pchArg = pszSrc + ich;
|
||||
|
||||
if (!(dwFlags & PPCF_LONGESTPOSSIBLE))
|
||||
break;
|
||||
|
||||
cchPath = ich;
|
||||
break;
|
||||
}
|
||||
else if (!resolveRelative)
|
||||
{
|
||||
szPath += pszSrc[ich];
|
||||
}
|
||||
}
|
||||
|
||||
if (!szPath[ich])
|
||||
{
|
||||
szPath.ReleaseBuffer(); // Remove excessive '\0'
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!resolved)
|
||||
return -1;
|
||||
|
||||
if (cchPath && (dwFlags & PPCF_LONGESTPOSSIBLE))
|
||||
{
|
||||
szPath = szPath.Left(cchPath);
|
||||
pchArg = pszSrc + cchPath;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL needsQuoting = (dwFlags & PPCF_ADDQUOTES) && wcschr(szPath, L' ');
|
||||
CStringW result = needsQuoting ? (L"\"" + szPath + L"\"") : szPath;
|
||||
|
||||
if (pchArg && (dwFlags & PPCF_ADDARGUMENTS))
|
||||
result += pchArg;
|
||||
|
||||
LONG requiredSize = result.GetLength() + 1;
|
||||
if (!pszDest)
|
||||
return requiredSize;
|
||||
|
||||
if (requiredSize > cchDest || StringCchCopyW(pszDest, cchDest, result) != S_OK)
|
||||
return -1;
|
||||
|
||||
return requiredSize;
|
||||
}
|
||||
|
||||
// The common helper of ShellExec_RunDLLA and ShellExec_RunDLLW
|
||||
static VOID
|
||||
ShellExec_RunDLL_Helper(
|
||||
|
@ -3003,7 +3124,8 @@ ShellExec_RunDLL_Helper(
|
|||
}
|
||||
|
||||
WCHAR szPath[2 * MAX_PATH];
|
||||
if (PathProcessCommandAW(pszCmdLine, szPath, _countof(szPath), L'C') == -1)
|
||||
DWORD dwFlags = PPCF_FORCEQUALIFY | PPCF_INCLUDEARGS | PPCF_ADDQUOTES;
|
||||
if (PathProcessCommandW(pszCmdLine, szPath, _countof(szPath), dwFlags) == -1)
|
||||
StrCpyNW(szPath, pszCmdLine, _countof(szPath));
|
||||
|
||||
// Split arguments from the path
|
||||
|
|
|
@ -7,6 +7,14 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifndef OPTIONAL_
|
||||
#ifdef __cplusplus
|
||||
#define OPTIONAL_(arg) = arg
|
||||
#else
|
||||
#define OPTIONAL_(arg)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
static inline LPWSTR
|
||||
SHStrDupW(LPCWSTR Src)
|
||||
|
@ -50,15 +58,15 @@ inline DWORD
|
|||
RegSetOrDelete(HKEY hKey, LPCWSTR Name, DWORD Type, LPCVOID Data, DWORD Size)
|
||||
{
|
||||
if (Data)
|
||||
return RegSetValueExW(hKey, Name, 0, Type, LPBYTE(Data), Size);
|
||||
return RegSetValueExW(hKey, Name, 0, Type, (LPBYTE)Data, Size);
|
||||
else
|
||||
return RegDeleteValueW(hKey, Name);
|
||||
}
|
||||
|
||||
static inline DWORD
|
||||
RegSetString(HKEY hKey, LPCWSTR Name, LPCWSTR Str, DWORD Type = REG_SZ)
|
||||
RegSetString(HKEY hKey, LPCWSTR Name, LPCWSTR Str, DWORD Type OPTIONAL_(REG_SZ))
|
||||
{
|
||||
return RegSetValueExW(hKey, Name, 0, Type, LPBYTE(Str), (lstrlenW(Str) + 1) * sizeof(WCHAR));
|
||||
return RegSetValueExW(hKey, Name, 0, Type, (LPBYTE)Str, (lstrlenW(Str) + 1) * sizeof(WCHAR));
|
||||
}
|
||||
|
||||
typedef struct
|
||||
|
|
|
@ -76,10 +76,16 @@ BOOL HCR_GetFolderAttributes(LPCITEMIDLIST pidlFolder, LPDWORD dwAttributes) DEC
|
|||
HRESULT SHELL32_AssocGetFSDirectoryDescription(PWSTR Buf, UINT cchBuf);
|
||||
HRESULT SHELL32_AssocGetFileDescription(PCWSTR Name, PWSTR Buf, UINT cchBuf);
|
||||
|
||||
|
||||
DWORD WINAPI ParseFieldA(LPCSTR src, DWORD nField, LPSTR dst, DWORD len) DECLSPEC_HIDDEN;
|
||||
DWORD WINAPI ParseFieldW(LPCWSTR src, DWORD nField, LPWSTR dst, DWORD len) DECLSPEC_HIDDEN;
|
||||
|
||||
LONG
|
||||
PathProcessCommandW(
|
||||
_In_ PCWSTR pszSrc,
|
||||
_Out_writes_opt_(dwBuffSize) PWSTR pszDest,
|
||||
_In_ INT cchDest,
|
||||
_In_ DWORD dwFlags);
|
||||
|
||||
/****************************************************************************
|
||||
* Class constructors
|
||||
*/
|
||||
|
|
|
@ -1130,6 +1130,7 @@ static LONG PathProcessCommandA (
|
|||
return strlen(lpszPath);
|
||||
}
|
||||
|
||||
#ifndef __REACTOS__ // See ../shlexec.cpp
|
||||
/*************************************************************************
|
||||
* PathProcessCommandW
|
||||
*/
|
||||
|
@ -1145,6 +1146,7 @@ static LONG PathProcessCommandW (
|
|||
if(lpszBuff) strcpyW(lpszBuff, lpszPath);
|
||||
return strlenW(lpszPath);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
* PathProcessCommand (SHELL32.653)
|
||||
|
|
Loading…
Reference in a new issue