From e4216bd015965ab45b7a4cb1e35a7eeb3f43c666 Mon Sep 17 00:00:00 2001 From: Whindmar Saksit Date: Sun, 9 Feb 2025 20:07:17 +0100 Subject: [PATCH] [SHELL32] Expand .lnk working directory string before checking if it's valid (#7710) Handles the case where SEE_MASK_DOENVSUBST will expand it later inside ShellExeute. CORE-19987 --- dll/win32/shell32/CShellLink.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/dll/win32/shell32/CShellLink.cpp b/dll/win32/shell32/CShellLink.cpp index 6ad2dec1e9a..b60987d40a3 100644 --- a/dll/win32/shell32/CShellLink.cpp +++ b/dll/win32/shell32/CShellLink.cpp @@ -216,6 +216,22 @@ static LPWSTR __inline strdupW(LPCWSTR src) return dest; } +static BOOL PathEnvSubstIsDirectory(LPCWSTR pszPath) +{ + // Note: Don't call SHExpandEnvironmentStringsW here, we need the required length + WCHAR szStack[MAX_PATH]; + DWORD cch = ExpandEnvironmentStringsW(pszPath, szStack, _countof(szStack)); + if (cch <= _countof(szStack)) + return cch && PathIsDirectory(szStack); + + PWSTR szHeap = (PWSTR)SHAlloc(cch); + if (!szHeap) + return FALSE; + BOOL bResult = ExpandEnvironmentStringsW(pszPath, szHeap, cch) && PathIsDirectory(szHeap); + SHFree(szHeap); + return bResult; +} + // TODO: Use it for constructor & destructor too VOID CShellLink::Reset() { @@ -2667,7 +2683,7 @@ HRESULT CShellLink::DoOpen(LPCMINVOKECOMMANDINFO lpici) sei.nShow = lpici->nShow; // Allow invoker to override .lnk show mode // Use the invoker specified working directory if the link did not specify one - if (StrIsNullOrEmpty(sei.lpDirectory) || !PathIsDirectoryW(sei.lpDirectory)) + if (StrIsNullOrEmpty(sei.lpDirectory) || !PathEnvSubstIsDirectory(sei.lpDirectory)) { LPCSTR pszDirA = lpici->lpDirectory; if (unicode && !StrIsNullOrEmpty(iciex->lpDirectoryW))