From bad0dd599179eb7212749a0aaae1275fd20b570f Mon Sep 17 00:00:00 2001 From: Whindmar Saksit Date: Thu, 12 Sep 2024 19:28:15 +0200 Subject: [PATCH] [SHELL32] Store target FS attributes in .lnk header (#7302) --- dll/win32/shell32/CShellLink.cpp | 44 +++++++++++++++++++------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/dll/win32/shell32/CShellLink.cpp b/dll/win32/shell32/CShellLink.cpp index ca1f6b1a3ef..d438fa204ff 100644 --- a/dll/win32/shell32/CShellLink.cpp +++ b/dll/win32/shell32/CShellLink.cpp @@ -882,6 +882,21 @@ HRESULT STDMETHODCALLTYPE CShellLink::Save(IStream *stm, BOOL fClearDirty) m_Header.dwSize = sizeof(m_Header); m_Header.clsid = CLSID_ShellLink; + /* Store target attributes */ + WIN32_FIND_DATAW wfd = {}; + WCHAR FsTarget[MAX_PATH]; + if (GetPath(FsTarget, _countof(FsTarget), NULL, 0) == S_OK && PathFileExistsW(FsTarget)) + { + HANDLE hFind = FindFirstFileW(FsTarget, &wfd); + if (hFind != INVALID_HANDLE_VALUE) + FindClose(hFind); + } + m_Header.dwFileAttributes = wfd.dwFileAttributes; + m_Header.ftCreationTime = wfd.ftCreationTime; + m_Header.ftLastAccessTime = wfd.ftLastAccessTime; + m_Header.ftLastWriteTime = wfd.ftLastWriteTime; + m_Header.nFileSizeLow = wfd.nFileSizeLow; + /* * Reset the flags: keep only the flags related to data blocks as they were * already set in accordance by the different mutator member functions. @@ -1077,7 +1092,7 @@ HRESULT STDMETHODCALLTYPE CShellLink::GetPath(LPSTR pszFile, INT cchMaxPath, WIN this, pszFile, cchMaxPath, pfd, fFlags, debugstr_w(m_sPath)); /* Allocate a temporary UNICODE buffer */ - pszFileW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, cchMaxPath * sizeof(WCHAR)); + pszFileW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, max(cchMaxPath, MAX_PATH) * sizeof(WCHAR)); if (!pszFileW) return E_OUTOFMEMORY; @@ -2690,31 +2705,24 @@ INT_PTR CALLBACK ExtendedShortcutProc(HWND hwndDlg, UINT uMsg, return FALSE; } -/************************************************************************** -* SH_GetTargetTypeByPath -* -* Function to get target type by passing full path to it -*/ -void SH_GetTargetTypeByPath(LPCWSTR lpcwFullPath, LPWSTR szBuf, UINT cchBuf) +static void GetTypeDescriptionByPath(PCWSTR pszFullPath, DWORD fAttributes, PWSTR szBuf, UINT cchBuf) { - LPCWSTR pwszExt; - BOOL fFolderTarget = PathIsDirectoryW(lpcwFullPath); - DWORD fAttribs = fFolderTarget ? FILE_ATTRIBUTE_DIRECTORY : 0; + if (fAttributes == INVALID_FILE_ATTRIBUTES && !PathFileExistsAndAttributesW(pszFullPath, &fAttributes)) + fAttributes = 0; - /* Get file information */ SHFILEINFOW fi; - if (!SHGetFileInfoW(lpcwFullPath, fAttribs, &fi, sizeof(fi), SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES)) + if (!SHGetFileInfoW(pszFullPath, fAttributes, &fi, sizeof(fi), SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES)) { - ERR("SHGetFileInfoW failed for %ls (%lu)\n", lpcwFullPath, GetLastError()); - fi.szTypeName[0] = L'\0'; - fi.hIcon = NULL; + ERR("SHGetFileInfoW failed for %ls (%lu)\n", pszFullPath, GetLastError()); + fi.szTypeName[0] = UNICODE_NULL; } - pwszExt = fFolderTarget ? L"" : PathFindExtensionW(lpcwFullPath); + BOOL fFolder = (fAttributes & FILE_ATTRIBUTE_DIRECTORY); + LPCWSTR pwszExt = fFolder ? L"" : PathFindExtensionW(pszFullPath); if (pwszExt[0]) { if (!fi.szTypeName[0]) - StringCchPrintfW(szBuf, cchBuf,L"%s ", pwszExt + 1); + StringCchPrintfW(szBuf, cchBuf, L"%s", pwszExt + 1); else StringCchPrintfW(szBuf, cchBuf, L"%s (%s)", fi.szTypeName, pwszExt); } @@ -2764,7 +2772,7 @@ BOOL CShellLink::OnInitDialog(HWND hwndDlg, HWND hwndFocus, LPARAM lParam) if (m_sPath) { WCHAR buf[MAX_PATH]; - SH_GetTargetTypeByPath(m_sPath, buf, _countof(buf)); + GetTypeDescriptionByPath(m_sPath, m_Header.dwFileAttributes, buf, _countof(buf)); SetDlgItemTextW(hwndDlg, IDC_SHORTCUT_TYPE_EDIT, buf); }