mirror of
https://github.com/reactos/reactos.git
synced 2025-04-20 12:29:56 +00:00
[SHELL32] Finally fix the icon location path (un)expansion for shell links, and explain why I originally used SHExpandEnvironmentStringsW().
CORE-14009 CORE-14982
This commit is contained in:
parent
1e20a3e5b5
commit
2cbac3d049
1 changed files with 55 additions and 16 deletions
|
@ -143,6 +143,14 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allows to define whether or not Windows-compatible behaviour
|
||||||
|
* should be adopted when setting and retrieving icon location paths.
|
||||||
|
* See CShellLink::SetIconLocation(LPCWSTR pszIconPath, INT iIcon)
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
#define ICON_LINK_WINDOWS_COMPAT
|
||||||
|
|
||||||
#define SHLINK_LOCAL 0
|
#define SHLINK_LOCAL 0
|
||||||
#define SHLINK_REMOTE 1
|
#define SHLINK_REMOTE 1
|
||||||
|
|
||||||
|
@ -1715,7 +1723,7 @@ HRESULT STDMETHODCALLTYPE CShellLink::GetIconLocation(UINT uFlags, PWSTR pszIcon
|
||||||
uFlags |= GIL_FORSHORTCUT;
|
uFlags |= GIL_FORSHORTCUT;
|
||||||
|
|
||||||
if (uFlags & GIL_DEFAULTICON)
|
if (uFlags & GIL_DEFAULTICON)
|
||||||
return E_FAIL;
|
return S_FALSE;
|
||||||
|
|
||||||
hr = GetIconLocation(pszIconFile, cchMax, piIndex);
|
hr = GetIconLocation(pszIconFile, cchMax, piIndex);
|
||||||
if (FAILED(hr) || pszIconFile[0] == UNICODE_NULL)
|
if (FAILED(hr) || pszIconFile[0] == UNICODE_NULL)
|
||||||
|
@ -1849,15 +1857,12 @@ BOOL PathFullyUnExpandEnvStringsW(
|
||||||
HRESULT STDMETHODCALLTYPE CShellLink::SetIconLocation(LPCWSTR pszIconPath, INT iIcon)
|
HRESULT STDMETHODCALLTYPE CShellLink::SetIconLocation(LPCWSTR pszIconPath, INT iIcon)
|
||||||
{
|
{
|
||||||
HRESULT hr = E_FAIL;
|
HRESULT hr = E_FAIL;
|
||||||
WCHAR szUnExpIconPath[MAX_PATH];
|
WCHAR szIconPath[MAX_PATH];
|
||||||
BOOL bSuccess;
|
|
||||||
|
|
||||||
TRACE("(%p)->(path=%s iicon=%u)\n", this, debugstr_w(pszIconPath), iIcon);
|
TRACE("(%p)->(path=%s iicon=%u)\n", this, debugstr_w(pszIconPath), iIcon);
|
||||||
|
|
||||||
if (pszIconPath)
|
if (pszIconPath)
|
||||||
{
|
{
|
||||||
/* Try to fully unexpand the icon path */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check whether the user-given file path contains unexpanded
|
* Check whether the user-given file path contains unexpanded
|
||||||
* environment variables. If so, create a target environment block.
|
* environment variables. If so, create a target environment block.
|
||||||
|
@ -1868,16 +1873,35 @@ HRESULT STDMETHODCALLTYPE CShellLink::SetIconLocation(LPCWSTR pszIconPath, INT i
|
||||||
* refer to the same place even if the would-be corresponding
|
* refer to the same place even if the would-be corresponding
|
||||||
* environment variable could change).
|
* environment variable could change).
|
||||||
*/
|
*/
|
||||||
// FIXME: http://stackoverflow.com/questions/2976489/ishelllinkseticonlocation-translates-my-icon-path-into-program-files-which-i
|
#ifdef ICON_LINK_WINDOWS_COMPAT
|
||||||
// if (PathFullyUnExpandEnvStringsW(pszIconPath, szUnExpIconPath, _countof(szUnExpIconPath)))
|
/* Try to fully unexpand the icon path */
|
||||||
bSuccess = PathUnExpandEnvStringsW(pszIconPath, szUnExpIconPath, _countof(szUnExpIconPath));
|
// if (PathFullyUnExpandEnvStringsW(pszIconPath, szIconPath, _countof(szIconPath)))
|
||||||
if (bSuccess && wcscmp(pszIconPath, szUnExpIconPath) != 0)
|
BOOL bSuccess = PathUnExpandEnvStringsW(pszIconPath, szIconPath, _countof(szIconPath));
|
||||||
|
if (bSuccess && wcscmp(pszIconPath, szIconPath) != 0)
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* In some situations, described in http://stackoverflow.com/questions/2976489/ishelllinkseticonlocation-translates-my-icon-path-into-program-files-which-i
|
||||||
|
* the result of PathUnExpandEnvStringsW() could be wrong, and instead
|
||||||
|
* one would have to store the actual provided icon location path, while
|
||||||
|
* creating an icon environment block ONLY if that path already contains
|
||||||
|
* environment variables. This is what the present case is trying to implement.
|
||||||
|
*/
|
||||||
|
SHExpandEnvironmentStringsW(pszIconPath, szIconPath, _countof(szIconPath));
|
||||||
|
if (wcscmp(pszIconPath, szIconPath) != 0)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/* Unexpansion succeeded, so we need an icon environment block */
|
/*
|
||||||
|
* The user-given file path contains unexpanded environment
|
||||||
|
* variables, so we need an icon environment block.
|
||||||
|
*/
|
||||||
EXP_SZ_LINK buffer;
|
EXP_SZ_LINK buffer;
|
||||||
LPEXP_SZ_LINK pInfo;
|
LPEXP_SZ_LINK pInfo;
|
||||||
|
|
||||||
pszIconPath = szUnExpIconPath;
|
#ifdef ICON_LINK_WINDOWS_COMPAT
|
||||||
|
/* Make pszIconPath point to the unexpanded path */
|
||||||
|
LPCWSTR pszOrgIconPath = pszIconPath;
|
||||||
|
pszIconPath = szIconPath;
|
||||||
|
#endif
|
||||||
pInfo = (LPEXP_SZ_LINK)SHFindDataBlock(m_pDBList, EXP_SZ_ICON_SIG);
|
pInfo = (LPEXP_SZ_LINK)SHFindDataBlock(m_pDBList, EXP_SZ_ICON_SIG);
|
||||||
if (pInfo)
|
if (pInfo)
|
||||||
{
|
{
|
||||||
|
@ -1902,8 +1926,8 @@ HRESULT STDMETHODCALLTYPE CShellLink::SetIconLocation(LPCWSTR pszIconPath, INT i
|
||||||
buffer.dwSignature = EXP_SZ_ICON_SIG;
|
buffer.dwSignature = EXP_SZ_ICON_SIG;
|
||||||
}
|
}
|
||||||
|
|
||||||
lstrcpynW(pInfo->szwTarget, szUnExpIconPath, _countof(pInfo->szwTarget));
|
lstrcpynW(pInfo->szwTarget, pszIconPath, _countof(pInfo->szwTarget));
|
||||||
WideCharToMultiByte(CP_ACP, 0, szUnExpIconPath, -1,
|
WideCharToMultiByte(CP_ACP, 0, pszIconPath, -1,
|
||||||
pInfo->szTarget, _countof(pInfo->szTarget), NULL, NULL);
|
pInfo->szTarget, _countof(pInfo->szTarget), NULL, NULL);
|
||||||
|
|
||||||
hr = S_OK;
|
hr = S_OK;
|
||||||
|
@ -1911,16 +1935,31 @@ HRESULT STDMETHODCALLTYPE CShellLink::SetIconLocation(LPCWSTR pszIconPath, INT i
|
||||||
hr = AddDataBlock(pInfo);
|
hr = AddDataBlock(pInfo);
|
||||||
if (hr == S_OK)
|
if (hr == S_OK)
|
||||||
m_Header.dwFlags |= SLDF_HAS_EXP_ICON_SZ;
|
m_Header.dwFlags |= SLDF_HAS_EXP_ICON_SZ;
|
||||||
|
|
||||||
|
#ifdef ICON_LINK_WINDOWS_COMPAT
|
||||||
|
/* Set pszIconPath back to the original one */
|
||||||
|
pszIconPath = pszOrgIconPath;
|
||||||
|
#else
|
||||||
|
/* Now, make pszIconPath point to the expanded path */
|
||||||
|
pszIconPath = szIconPath;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Unexpansion failed, so we need to remove any icon environment block */
|
/*
|
||||||
|
* The user-given file path does not contain unexpanded environment
|
||||||
|
* variables, so we need to remove any icon environment block.
|
||||||
|
*/
|
||||||
m_Header.dwFlags &= ~SLDF_HAS_EXP_ICON_SZ;
|
m_Header.dwFlags &= ~SLDF_HAS_EXP_ICON_SZ;
|
||||||
RemoveDataBlock(EXP_SZ_ICON_SIG);
|
RemoveDataBlock(EXP_SZ_ICON_SIG);
|
||||||
|
|
||||||
|
/* pszIconPath points to the user path */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store the original icon path location (this one may contain unexpanded environment strings) */
|
#ifdef ICON_LINK_WINDOWS_COMPAT
|
||||||
|
/* Store the original icon path location (may contain unexpanded environment strings) */
|
||||||
|
#endif
|
||||||
if (pszIconPath)
|
if (pszIconPath)
|
||||||
{
|
{
|
||||||
m_Header.dwFlags &= ~SLDF_HAS_ICONLOCATION;
|
m_Header.dwFlags &= ~SLDF_HAS_ICONLOCATION;
|
||||||
|
@ -2404,7 +2443,7 @@ HRESULT STDMETHODCALLTYPE CShellLink::SetPath(LPCWSTR pszFile)
|
||||||
if (hr == S_OK)
|
if (hr == S_OK)
|
||||||
m_Header.dwFlags |= SLDF_HAS_EXP_SZ;
|
m_Header.dwFlags |= SLDF_HAS_EXP_SZ;
|
||||||
|
|
||||||
/* Now, make pszFile point to the expanded buffer */
|
/* Now, make pszFile point to the expanded path */
|
||||||
pszFile = szPath;
|
pszFile = szPath;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue