[SHELL32] Store target FS attributes in .lnk header (#7302)

This commit is contained in:
Whindmar Saksit 2024-09-12 19:28:15 +02:00 committed by GitHub
parent 44bdafa17e
commit bad0dd5991
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -882,6 +882,21 @@ HRESULT STDMETHODCALLTYPE CShellLink::Save(IStream *stm, BOOL fClearDirty)
m_Header.dwSize = sizeof(m_Header); m_Header.dwSize = sizeof(m_Header);
m_Header.clsid = CLSID_ShellLink; 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 * Reset the flags: keep only the flags related to data blocks as they were
* already set in accordance by the different mutator member functions. * 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)); this, pszFile, cchMaxPath, pfd, fFlags, debugstr_w(m_sPath));
/* Allocate a temporary UNICODE buffer */ /* 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) if (!pszFileW)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
@ -2690,31 +2705,24 @@ INT_PTR CALLBACK ExtendedShortcutProc(HWND hwndDlg, UINT uMsg,
return FALSE; return FALSE;
} }
/************************************************************************** static void GetTypeDescriptionByPath(PCWSTR pszFullPath, DWORD fAttributes, PWSTR szBuf, UINT cchBuf)
* SH_GetTargetTypeByPath
*
* Function to get target type by passing full path to it
*/
void SH_GetTargetTypeByPath(LPCWSTR lpcwFullPath, LPWSTR szBuf, UINT cchBuf)
{ {
LPCWSTR pwszExt; if (fAttributes == INVALID_FILE_ATTRIBUTES && !PathFileExistsAndAttributesW(pszFullPath, &fAttributes))
BOOL fFolderTarget = PathIsDirectoryW(lpcwFullPath); fAttributes = 0;
DWORD fAttribs = fFolderTarget ? FILE_ATTRIBUTE_DIRECTORY : 0;
/* Get file information */
SHFILEINFOW fi; 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()); ERR("SHGetFileInfoW failed for %ls (%lu)\n", pszFullPath, GetLastError());
fi.szTypeName[0] = L'\0'; fi.szTypeName[0] = UNICODE_NULL;
fi.hIcon = NULL;
} }
pwszExt = fFolderTarget ? L"" : PathFindExtensionW(lpcwFullPath); BOOL fFolder = (fAttributes & FILE_ATTRIBUTE_DIRECTORY);
LPCWSTR pwszExt = fFolder ? L"" : PathFindExtensionW(pszFullPath);
if (pwszExt[0]) if (pwszExt[0])
{ {
if (!fi.szTypeName[0]) if (!fi.szTypeName[0])
StringCchPrintfW(szBuf, cchBuf,L"%s ", pwszExt + 1); StringCchPrintfW(szBuf, cchBuf, L"%s", pwszExt + 1);
else else
StringCchPrintfW(szBuf, cchBuf, L"%s (%s)", fi.szTypeName, pwszExt); 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) if (m_sPath)
{ {
WCHAR buf[MAX_PATH]; 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); SetDlgItemTextW(hwndDlg, IDC_SHORTCUT_TYPE_EDIT, buf);
} }