mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +00:00
[SHELL32] Improve CShellLink a little (#651)
Improve the display and UI in the shortcut dialog. CORE-11407
This commit is contained in:
parent
33a65d45aa
commit
96c0ef4209
2 changed files with 373 additions and 237 deletions
|
@ -268,6 +268,8 @@ CShellLink::CShellLink()
|
||||||
m_bRunAs = FALSE;
|
m_bRunAs = FALSE;
|
||||||
m_bDirty = FALSE;
|
m_bDirty = FALSE;
|
||||||
m_pDBList = NULL;
|
m_pDBList = NULL;
|
||||||
|
m_bInInit = FALSE;
|
||||||
|
m_hIcon = NULL;
|
||||||
|
|
||||||
m_sLinkPath = NULL;
|
m_sLinkPath = NULL;
|
||||||
m_iIdOpen = -1;
|
m_iIdOpen = -1;
|
||||||
|
@ -347,12 +349,13 @@ HRESULT STDMETHODCALLTYPE CShellLink::Save(LPCOLESTR pszFileName, BOOL fRemember
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
if (m_sLinkPath)
|
if (pszFileName != m_sLinkPath)
|
||||||
HeapFree(GetProcessHeap(), 0, m_sLinkPath);
|
{
|
||||||
|
if (m_sLinkPath)
|
||||||
|
HeapFree(GetProcessHeap(), 0, m_sLinkPath);
|
||||||
|
|
||||||
m_sLinkPath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(pszFileName) + 1) * sizeof(WCHAR));
|
m_sLinkPath = strdupW(pszFileName);
|
||||||
if (m_sLinkPath)
|
}
|
||||||
wcscpy(m_sLinkPath, pszFileName);
|
|
||||||
|
|
||||||
m_bDirty = FALSE;
|
m_bDirty = FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1033,11 +1036,9 @@ static HRESULT ShellLink_UpdatePath(LPCWSTR sPathRel, LPCWSTR path, LPCWSTR sWor
|
||||||
if (!*abs_path)
|
if (!*abs_path)
|
||||||
wcscpy(abs_path, sPathRel);
|
wcscpy(abs_path, sPathRel);
|
||||||
|
|
||||||
*psPath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(abs_path) + 1) * sizeof(WCHAR));
|
*psPath = strdupW(abs_path);
|
||||||
if (!*psPath)
|
if (!*psPath)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
wcscpy(*psPath, abs_path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -1415,11 +1416,12 @@ HRESULT STDMETHODCALLTYPE CShellLink::Resolve(HWND hwnd, DWORD fFlags)
|
||||||
bSuccess = SHGetPathFromIDListW(m_pPidl, buffer);
|
bSuccess = SHGetPathFromIDListW(m_pPidl, buffer);
|
||||||
if (bSuccess && *buffer)
|
if (bSuccess && *buffer)
|
||||||
{
|
{
|
||||||
m_sPath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(buffer) + 1) * sizeof(WCHAR));
|
if (buffer != m_sPath)
|
||||||
if (!m_sPath)
|
{
|
||||||
return E_OUTOFMEMORY;
|
m_sPath = strdupW(buffer);
|
||||||
|
if (!m_sPath)
|
||||||
wcscpy(m_sPath, buffer);
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
m_bDirty = TRUE;
|
m_bDirty = TRUE;
|
||||||
}
|
}
|
||||||
|
@ -1432,11 +1434,13 @@ HRESULT STDMETHODCALLTYPE CShellLink::Resolve(HWND hwnd, DWORD fFlags)
|
||||||
// FIXME: Strange to do that here...
|
// FIXME: Strange to do that here...
|
||||||
if (!m_sIcoPath && m_sPath)
|
if (!m_sIcoPath && m_sPath)
|
||||||
{
|
{
|
||||||
m_sIcoPath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(m_sPath) + 1) * sizeof(WCHAR));
|
if (m_sIcoPath != m_sPath)
|
||||||
if (!m_sIcoPath)
|
{
|
||||||
return E_OUTOFMEMORY;
|
m_sIcoPath = strdupW(m_sPath);
|
||||||
|
if (!m_sIcoPath)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
wcscpy(m_sIcoPath, m_sPath);
|
|
||||||
m_Header.nIconIndex = 0;
|
m_Header.nIconIndex = 0;
|
||||||
|
|
||||||
m_bDirty = TRUE;
|
m_bDirty = TRUE;
|
||||||
|
@ -1561,12 +1565,12 @@ HRESULT STDMETHODCALLTYPE CShellLink::SetDescription(LPCWSTR pszName)
|
||||||
HeapFree(GetProcessHeap(), 0, m_sDescription);
|
HeapFree(GetProcessHeap(), 0, m_sDescription);
|
||||||
if (pszName)
|
if (pszName)
|
||||||
{
|
{
|
||||||
m_sDescription = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
|
if (m_sDescription != pszName)
|
||||||
(wcslen(pszName) + 1) * sizeof(WCHAR));
|
{
|
||||||
if (!m_sDescription)
|
m_sDescription = strdupW(pszName);
|
||||||
return E_OUTOFMEMORY;
|
if (!m_sDescription)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
wcscpy(m_sDescription, pszName);
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_sDescription = NULL;
|
m_sDescription = NULL;
|
||||||
|
@ -1596,11 +1600,12 @@ HRESULT STDMETHODCALLTYPE CShellLink::SetWorkingDirectory(LPCWSTR pszDir)
|
||||||
HeapFree(GetProcessHeap(), 0, m_sWorkDir);
|
HeapFree(GetProcessHeap(), 0, m_sWorkDir);
|
||||||
if (pszDir)
|
if (pszDir)
|
||||||
{
|
{
|
||||||
m_sWorkDir = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
|
if (m_sWorkDir != pszDir)
|
||||||
(wcslen(pszDir) + 1) * sizeof(WCHAR));
|
{
|
||||||
if (!m_sWorkDir)
|
m_sWorkDir = strdupW(pszDir);
|
||||||
return E_OUTOFMEMORY;
|
if (!m_sWorkDir)
|
||||||
wcscpy(m_sWorkDir, pszDir);
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_sWorkDir = NULL;
|
m_sWorkDir = NULL;
|
||||||
|
@ -1630,12 +1635,12 @@ HRESULT STDMETHODCALLTYPE CShellLink::SetArguments(LPCWSTR pszArgs)
|
||||||
HeapFree(GetProcessHeap(), 0, m_sArgs);
|
HeapFree(GetProcessHeap(), 0, m_sArgs);
|
||||||
if (pszArgs)
|
if (pszArgs)
|
||||||
{
|
{
|
||||||
m_sArgs = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
|
if (m_sArgs != pszArgs)
|
||||||
(wcslen(pszArgs) + 1) * sizeof(WCHAR));
|
{
|
||||||
if (!m_sArgs)
|
m_sArgs = strdupW(pszArgs);
|
||||||
return E_OUTOFMEMORY;
|
if (!m_sArgs)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
wcscpy(m_sArgs, pszArgs);
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_sArgs = NULL;
|
m_sArgs = NULL;
|
||||||
|
@ -1670,12 +1675,13 @@ HRESULT STDMETHODCALLTYPE CShellLink::GetIconLocation(LPWSTR pszIconPath, INT cc
|
||||||
|
|
||||||
SHExpandEnvironmentStringsW(pInfo->szwTarget, szPath, _countof(szPath));
|
SHExpandEnvironmentStringsW(pInfo->szwTarget, szPath, _countof(szPath));
|
||||||
|
|
||||||
m_sIcoPath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
|
if (m_sIcoPath != szPath)
|
||||||
(wcslen(szPath) + 1) * sizeof(WCHAR));
|
{
|
||||||
if (!m_sIcoPath)
|
m_sIcoPath = strdupW(szPath);
|
||||||
return E_OUTOFMEMORY;
|
if (!m_sIcoPath)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
wcscpy(m_sIcoPath, szPath);
|
|
||||||
m_Header.dwFlags |= SLDF_HAS_ICONLOCATION;
|
m_Header.dwFlags |= SLDF_HAS_ICONLOCATION;
|
||||||
|
|
||||||
m_bDirty = TRUE;
|
m_bDirty = TRUE;
|
||||||
|
@ -1768,27 +1774,42 @@ HRESULT STDMETHODCALLTYPE CShellLink::GetIconLocation(UINT uFlags, PWSTR pszIcon
|
||||||
HRESULT STDMETHODCALLTYPE
|
HRESULT STDMETHODCALLTYPE
|
||||||
CShellLink::Extract(PCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize)
|
CShellLink::Extract(PCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize)
|
||||||
{
|
{
|
||||||
SHFILEINFOW info;
|
HRESULT hr = NOERROR;
|
||||||
|
UINT cxyLarge = LOWORD(nIconSize), cxySmall = HIWORD(nIconSize);
|
||||||
|
|
||||||
if (phiconLarge)
|
if (phiconLarge)
|
||||||
{
|
{
|
||||||
SHGetFileInfoW(pszFile, 0, &info, sizeof(info),
|
*phiconLarge = NULL;
|
||||||
SHGFI_ICON | SHGFI_LARGEICON | SHGFI_LINKOVERLAY);
|
PrivateExtractIconsW(pszFile, nIconIndex, cxyLarge, cxyLarge, phiconLarge, NULL, 1, 0);
|
||||||
*phiconLarge = info.hIcon;
|
|
||||||
if (!info.hIcon)
|
if (*phiconLarge == NULL)
|
||||||
return E_FAIL;
|
hr = S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phiconSmall)
|
if (phiconSmall)
|
||||||
{
|
{
|
||||||
SHGetFileInfoW(pszFile, 0, &info, sizeof(info),
|
*phiconSmall = NULL;
|
||||||
SHGFI_ICON | SHGFI_SMALLICON | SHGFI_LINKOVERLAY);
|
PrivateExtractIconsW(pszFile, nIconIndex, cxySmall, cxySmall, phiconSmall, NULL, 1, 0);
|
||||||
*phiconSmall = info.hIcon;
|
|
||||||
if (!info.hIcon)
|
if (*phiconSmall == NULL)
|
||||||
return E_FAIL;
|
hr = S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
if (hr == S_FALSE)
|
||||||
|
{
|
||||||
|
if (phiconLarge && *phiconLarge)
|
||||||
|
{
|
||||||
|
DestroyIcon(*phiconLarge);
|
||||||
|
*phiconLarge = NULL;
|
||||||
|
}
|
||||||
|
if (phiconSmall && *phiconSmall)
|
||||||
|
{
|
||||||
|
DestroyIcon(*phiconSmall);
|
||||||
|
*phiconSmall = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -1945,12 +1966,13 @@ HRESULT STDMETHODCALLTYPE CShellLink::SetIconLocation(LPCWSTR pszIconPath, INT i
|
||||||
HeapFree(GetProcessHeap(), 0, m_sIcoPath);
|
HeapFree(GetProcessHeap(), 0, m_sIcoPath);
|
||||||
m_sIcoPath = NULL;
|
m_sIcoPath = NULL;
|
||||||
|
|
||||||
m_sIcoPath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
|
if (m_sIcoPath != pszIconPath)
|
||||||
(wcslen(pszIconPath) + 1) * sizeof(WCHAR));
|
{
|
||||||
if (!m_sIcoPath)
|
m_sIcoPath = strdupW(pszIconPath);
|
||||||
return E_OUTOFMEMORY;
|
if (!m_sIcoPath)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
wcscpy(m_sIcoPath, pszIconPath);
|
|
||||||
m_Header.dwFlags |= SLDF_HAS_ICONLOCATION;
|
m_Header.dwFlags |= SLDF_HAS_ICONLOCATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1969,11 +1991,12 @@ HRESULT STDMETHODCALLTYPE CShellLink::SetRelativePath(LPCWSTR pszPathRel, DWORD
|
||||||
HeapFree(GetProcessHeap(), 0, m_sPathRel);
|
HeapFree(GetProcessHeap(), 0, m_sPathRel);
|
||||||
if (pszPathRel)
|
if (pszPathRel)
|
||||||
{
|
{
|
||||||
m_sPathRel = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
|
if (m_sPathRel != pszPathRel)
|
||||||
(wcslen(pszPathRel) + 1) * sizeof(WCHAR));
|
{
|
||||||
if (!m_sPathRel)
|
m_sPathRel = strdupW(pszPathRel);
|
||||||
return E_OUTOFMEMORY;
|
if (!m_sPathRel)
|
||||||
wcscpy(m_sPathRel, pszPathRel);
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_sPathRel = NULL;
|
m_sPathRel = NULL;
|
||||||
|
@ -2315,11 +2338,13 @@ HRESULT CShellLink::SetTargetFromPIDLOrPath(LPCITEMIDLIST pidl, LPCWSTR pszFile)
|
||||||
|
|
||||||
/* Update the cached path (for link info) */
|
/* Update the cached path (for link info) */
|
||||||
ShellLink_GetVolumeInfo(pszFile, &volume);
|
ShellLink_GetVolumeInfo(pszFile, &volume);
|
||||||
m_sPath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
|
|
||||||
(wcslen(pszFile) + 1) * sizeof(WCHAR));
|
if (m_sPath != pszFile)
|
||||||
if (!m_sPath)
|
{
|
||||||
return E_OUTOFMEMORY;
|
m_sPath = strdupW(pszFile);
|
||||||
wcscpy(m_sPath, pszFile);
|
if (!m_sPath)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
m_bDirty = TRUE;
|
m_bDirty = TRUE;
|
||||||
return hr;
|
return hr;
|
||||||
|
@ -2756,203 +2781,245 @@ LPWSTR SH_GetTargetTypeByPath(LPCWSTR lpcwFullPath)
|
||||||
return wszBuf;
|
return wszBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL CShellLink::OnInitDialog(HWND hwndDlg, HWND hwndFocus, LPARAM lParam)
|
||||||
|
{
|
||||||
|
TRACE("CShellLink::OnInitDialog(hwnd %p hwndFocus %p lParam %p)\n", hwndDlg, hwndFocus, lParam);
|
||||||
|
|
||||||
|
TRACE("m_sArgs: %S sComponent: %S m_sDescription: %S m_sIcoPath: %S m_sPath: %S m_sPathRel: %S sProduct: %S m_sWorkDir: %S\n", m_sArgs, sComponent, m_sDescription,
|
||||||
|
m_sIcoPath, m_sPath, m_sPathRel, sProduct, m_sWorkDir);
|
||||||
|
|
||||||
|
m_bInInit = TRUE;
|
||||||
|
|
||||||
|
/* Get file information */
|
||||||
|
// FIXME! FIXME! Shouldn't we use m_sIcoPath, m_Header.nIconIndex instead???
|
||||||
|
SHFILEINFOW fi;
|
||||||
|
if (!SHGetFileInfoW(m_sLinkPath, 0, &fi, sizeof(fi), SHGFI_TYPENAME | SHGFI_ICON))
|
||||||
|
{
|
||||||
|
ERR("SHGetFileInfoW failed for %ls (%lu)\n", m_sLinkPath, GetLastError());
|
||||||
|
fi.szTypeName[0] = L'\0';
|
||||||
|
fi.hIcon = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fi.hIcon)
|
||||||
|
{
|
||||||
|
if (m_hIcon)
|
||||||
|
DestroyIcon(m_hIcon);
|
||||||
|
m_hIcon = fi.hIcon;
|
||||||
|
SendDlgItemMessageW(hwndDlg, IDC_SHORTCUT_ICON, STM_SETICON, (WPARAM)m_hIcon, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ERR("ExtractIconW failed %ls %u\n", m_sIcoPath, m_Header.nIconIndex);
|
||||||
|
|
||||||
|
/* Target type */
|
||||||
|
if (m_sPath)
|
||||||
|
SetDlgItemTextW(hwndDlg, IDC_SHORTCUT_TYPE_EDIT, SH_GetTargetTypeByPath(m_sPath));
|
||||||
|
|
||||||
|
/* Target location */
|
||||||
|
if (m_sPath)
|
||||||
|
{
|
||||||
|
WCHAR target[MAX_PATH];
|
||||||
|
StringCchCopyW(target, _countof(target), m_sPath);
|
||||||
|
PathRemoveFileSpecW(target);
|
||||||
|
SetDlgItemTextW(hwndDlg, IDC_SHORTCUT_LOCATION_EDIT, PathFindFileNameW(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Target path */
|
||||||
|
if (m_sPath)
|
||||||
|
{
|
||||||
|
WCHAR newpath[2*MAX_PATH] = L"\0";
|
||||||
|
if (wcschr(m_sPath, ' '))
|
||||||
|
StringCchPrintfExW(newpath, _countof(newpath), NULL, NULL, 0, L"\"%ls\"", m_sPath);
|
||||||
|
else
|
||||||
|
StringCchCopyExW(newpath, _countof(newpath), m_sPath, NULL, NULL, 0);
|
||||||
|
|
||||||
|
if (m_sArgs && m_sArgs[0])
|
||||||
|
{
|
||||||
|
StringCchCatW(newpath, _countof(newpath), L" ");
|
||||||
|
StringCchCatW(newpath, _countof(newpath), m_sArgs);
|
||||||
|
}
|
||||||
|
SetDlgItemTextW(hwndDlg, IDC_SHORTCUT_TARGET_TEXT, newpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Working dir */
|
||||||
|
if (m_sWorkDir)
|
||||||
|
SetDlgItemTextW(hwndDlg, IDC_SHORTCUT_START_IN_EDIT, m_sWorkDir);
|
||||||
|
|
||||||
|
/* Description */
|
||||||
|
if (m_sDescription)
|
||||||
|
SetDlgItemTextW(hwndDlg, IDC_SHORTCUT_COMMENT_EDIT, m_sDescription);
|
||||||
|
|
||||||
|
m_bInInit = FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CShellLink::OnCommand(HWND hwndDlg, int id, HWND hwndCtl, UINT codeNotify)
|
||||||
|
{
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case IDC_SHORTCUT_FIND:
|
||||||
|
SHOpenFolderAndSelectItems(m_pPidl, 0, NULL, 0);
|
||||||
|
///
|
||||||
|
/// FIXME
|
||||||
|
/// open target directory
|
||||||
|
///
|
||||||
|
return;
|
||||||
|
|
||||||
|
case IDC_SHORTCUT_CHANGE_ICON:
|
||||||
|
{
|
||||||
|
WCHAR wszPath[MAX_PATH] = L"";
|
||||||
|
|
||||||
|
if (m_sIcoPath)
|
||||||
|
wcscpy(wszPath, m_sIcoPath);
|
||||||
|
else
|
||||||
|
FindExecutableW(m_sPath, NULL, wszPath);
|
||||||
|
|
||||||
|
INT IconIndex = m_Header.nIconIndex;
|
||||||
|
if (PickIconDlg(hwndDlg, wszPath, _countof(wszPath), &IconIndex))
|
||||||
|
{
|
||||||
|
SetIconLocation(wszPath, IconIndex);
|
||||||
|
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
|
||||||
|
|
||||||
|
HICON hIconLarge = CreateShortcutIcon(wszPath, IconIndex);
|
||||||
|
if (hIconLarge)
|
||||||
|
{
|
||||||
|
if (m_hIcon)
|
||||||
|
DestroyIcon(m_hIcon);
|
||||||
|
m_hIcon = hIconLarge;
|
||||||
|
SendDlgItemMessageW(hwndDlg, IDC_SHORTCUT_ICON, STM_SETICON, (WPARAM)m_hIcon, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IDC_SHORTCUT_ADVANCED:
|
||||||
|
{
|
||||||
|
INT_PTR result = DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_SHORTCUT_EXTENDED_PROPERTIES), hwndDlg, ExtendedShortcutProc, (LPARAM)m_bRunAs);
|
||||||
|
if (result == 1 || result == 0)
|
||||||
|
{
|
||||||
|
if (m_bRunAs != result)
|
||||||
|
{
|
||||||
|
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bRunAs = result;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (codeNotify == EN_CHANGE)
|
||||||
|
{
|
||||||
|
if (!m_bInInit)
|
||||||
|
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CShellLink::OnNotify(HWND hwndDlg, int idFrom, LPNMHDR pnmhdr)
|
||||||
|
{
|
||||||
|
WCHAR wszBuf[MAX_PATH];
|
||||||
|
LPPSHNOTIFY lppsn = (LPPSHNOTIFY)pnmhdr;
|
||||||
|
|
||||||
|
if (lppsn->hdr.code == PSN_APPLY)
|
||||||
|
{
|
||||||
|
/* set working directory */
|
||||||
|
GetDlgItemTextW(hwndDlg, IDC_SHORTCUT_START_IN_EDIT, wszBuf, _countof(wszBuf));
|
||||||
|
SetWorkingDirectory(wszBuf);
|
||||||
|
|
||||||
|
/* set link destination */
|
||||||
|
GetDlgItemTextW(hwndDlg, IDC_SHORTCUT_TARGET_TEXT, wszBuf, _countof(wszBuf));
|
||||||
|
LPWSTR lpszArgs = NULL;
|
||||||
|
LPWSTR unquoted = strdupW(wszBuf);
|
||||||
|
StrTrimW(unquoted, L" ");
|
||||||
|
|
||||||
|
if (!PathFileExistsW(unquoted))
|
||||||
|
{
|
||||||
|
lpszArgs = PathGetArgsW(unquoted);
|
||||||
|
PathRemoveArgsW(unquoted);
|
||||||
|
StrTrimW(lpszArgs, L" ");
|
||||||
|
}
|
||||||
|
if (unquoted[0] == '"' && unquoted[wcslen(unquoted) - 1] == '"')
|
||||||
|
PathUnquoteSpacesW(unquoted);
|
||||||
|
|
||||||
|
WCHAR *pwszExt = PathFindExtensionW(unquoted);
|
||||||
|
if (!wcsicmp(pwszExt, L".lnk"))
|
||||||
|
{
|
||||||
|
// FIXME load localized error msg
|
||||||
|
MessageBoxW(hwndDlg, L"You cannot create a link to a shortcut", L"Error", MB_ICONERROR);
|
||||||
|
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PathFileExistsW(unquoted))
|
||||||
|
{
|
||||||
|
// FIXME load localized error msg
|
||||||
|
MessageBoxW(hwndDlg, L"The specified file name in the target box is invalid", L"Error", MB_ICONERROR);
|
||||||
|
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetPath(unquoted);
|
||||||
|
if (lpszArgs)
|
||||||
|
SetArguments(lpszArgs);
|
||||||
|
else
|
||||||
|
SetArguments(L"\0");
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, unquoted);
|
||||||
|
|
||||||
|
TRACE("This %p m_sLinkPath %S\n", this, m_sLinkPath);
|
||||||
|
Save(m_sLinkPath, TRUE);
|
||||||
|
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CShellLink::OnDestroy(HWND hwndDlg)
|
||||||
|
{
|
||||||
|
if (m_hIcon)
|
||||||
|
{
|
||||||
|
DestroyIcon(m_hIcon);
|
||||||
|
m_hIcon = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* SH_ShellLinkDlgProc
|
* SH_ShellLinkDlgProc
|
||||||
*
|
*
|
||||||
* dialog proc of the shortcut property dialog
|
* dialog proc of the shortcut property dialog
|
||||||
*/
|
*/
|
||||||
|
|
||||||
INT_PTR CALLBACK CShellLink::SH_ShellLinkDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
INT_PTR CALLBACK
|
||||||
|
CShellLink::SH_ShellLinkDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
|
LPPROPSHEETPAGEW ppsp;
|
||||||
CShellLink *pThis = reinterpret_cast<CShellLink *>(GetWindowLongPtr(hwndDlg, DWLP_USER));
|
CShellLink *pThis = reinterpret_cast<CShellLink *>(GetWindowLongPtr(hwndDlg, DWLP_USER));
|
||||||
|
|
||||||
switch(uMsg)
|
switch (uMsg)
|
||||||
{
|
{
|
||||||
case WM_INITDIALOG:
|
case WM_INITDIALOG:
|
||||||
{
|
ppsp = (LPPROPSHEETPAGEW)lParam;
|
||||||
LPPROPSHEETPAGEW ppsp = (LPPROPSHEETPAGEW)lParam;
|
|
||||||
if (ppsp == NULL)
|
if (ppsp == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
TRACE("ShellLink_DlgProc (WM_INITDIALOG hwnd %p lParam %p ppsplParam %x)\n", hwndDlg, lParam, ppsp->lParam);
|
|
||||||
|
|
||||||
pThis = reinterpret_cast<CShellLink *>(ppsp->lParam);
|
pThis = reinterpret_cast<CShellLink *>(ppsp->lParam);
|
||||||
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pThis);
|
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pThis);
|
||||||
|
return pThis->OnInitDialog(hwndDlg, (HWND)(wParam), lParam);
|
||||||
TRACE("m_sArgs: %S sComponent: %S m_sDescription: %S m_sIcoPath: %S m_sPath: %S m_sPathRel: %S sProduct: %S m_sWorkDir: %S\n", pThis->m_sArgs, pThis->sComponent, pThis->m_sDescription,
|
|
||||||
pThis->m_sIcoPath, pThis->m_sPath, pThis->m_sPathRel, pThis->sProduct, pThis->m_sWorkDir);
|
|
||||||
|
|
||||||
/* Get file information */
|
|
||||||
// FIXME! FIXME! Shouldn't we use pThis->m_sIcoPath, pThis->m_Header.nIconIndex instead???
|
|
||||||
SHFILEINFOW fi;
|
|
||||||
if (!SHGetFileInfoW(pThis->m_sLinkPath, 0, &fi, sizeof(fi), SHGFI_TYPENAME | SHGFI_ICON))
|
|
||||||
{
|
|
||||||
ERR("SHGetFileInfoW failed for %ls (%lu)\n", pThis->m_sLinkPath, GetLastError());
|
|
||||||
fi.szTypeName[0] = L'\0';
|
|
||||||
fi.hIcon = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fi.hIcon) // TODO: destroy icon
|
|
||||||
SendDlgItemMessageW(hwndDlg, IDC_SHORTCUT_ICON, STM_SETICON, (WPARAM)fi.hIcon, 0);
|
|
||||||
else
|
|
||||||
ERR("ExtractIconW failed %ls %u\n", pThis->m_sIcoPath, pThis->m_Header.nIconIndex);
|
|
||||||
|
|
||||||
/* Target type */
|
|
||||||
if (pThis->m_sPath)
|
|
||||||
SetDlgItemTextW(hwndDlg, IDC_SHORTCUT_TYPE_EDIT, SH_GetTargetTypeByPath(pThis->m_sPath));
|
|
||||||
|
|
||||||
/* Target location */
|
|
||||||
if (pThis->m_sPath)
|
|
||||||
{
|
|
||||||
WCHAR target[MAX_PATH];
|
|
||||||
StringCchCopyW(target, _countof(target), pThis->m_sPath);
|
|
||||||
PathRemoveFileSpecW(target);
|
|
||||||
SetDlgItemTextW(hwndDlg, IDC_SHORTCUT_LOCATION_EDIT, PathFindFileNameW(target));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Target path */
|
|
||||||
if (pThis->m_sPath)
|
|
||||||
{
|
|
||||||
WCHAR newpath[2*MAX_PATH] = L"\0";
|
|
||||||
if (wcschr(pThis->m_sPath, ' '))
|
|
||||||
StringCchPrintfExW(newpath, _countof(newpath), NULL, NULL, 0, L"\"%ls\"", pThis->m_sPath);
|
|
||||||
else
|
|
||||||
StringCchCopyExW(newpath, _countof(newpath), pThis->m_sPath, NULL, NULL, 0);
|
|
||||||
|
|
||||||
if (pThis->m_sArgs && pThis->m_sArgs[0])
|
|
||||||
{
|
|
||||||
StringCchCatW(newpath, _countof(newpath), L" ");
|
|
||||||
StringCchCatW(newpath, _countof(newpath), pThis->m_sArgs);
|
|
||||||
}
|
|
||||||
SetDlgItemTextW(hwndDlg, IDC_SHORTCUT_TARGET_TEXT, newpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Working dir */
|
|
||||||
if (pThis->m_sWorkDir)
|
|
||||||
SetDlgItemTextW(hwndDlg, IDC_SHORTCUT_START_IN_EDIT, pThis->m_sWorkDir);
|
|
||||||
|
|
||||||
/* Description */
|
|
||||||
if (pThis->m_sDescription)
|
|
||||||
SetDlgItemTextW(hwndDlg, IDC_SHORTCUT_COMMENT_EDIT, pThis->m_sDescription);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_NOTIFY:
|
case WM_NOTIFY:
|
||||||
{
|
return pThis->OnNotify(hwndDlg, (int)wParam, (NMHDR *)lParam);
|
||||||
LPPSHNOTIFY lppsn = (LPPSHNOTIFY)lParam;
|
|
||||||
if (lppsn->hdr.code == PSN_APPLY)
|
|
||||||
{
|
|
||||||
WCHAR wszBuf[MAX_PATH];
|
|
||||||
/* set working directory */
|
|
||||||
GetDlgItemTextW(hwndDlg, IDC_SHORTCUT_START_IN_EDIT, wszBuf, _countof(wszBuf));
|
|
||||||
pThis->SetWorkingDirectory(wszBuf);
|
|
||||||
/* set link destination */
|
|
||||||
GetDlgItemTextW(hwndDlg, IDC_SHORTCUT_TARGET_TEXT, wszBuf, _countof(wszBuf));
|
|
||||||
LPWSTR lpszArgs = NULL;
|
|
||||||
LPWSTR unquoted = strdupW(wszBuf);
|
|
||||||
StrTrimW(unquoted, L" ");
|
|
||||||
if (!PathFileExistsW(unquoted))
|
|
||||||
{
|
|
||||||
lpszArgs = PathGetArgsW(unquoted);
|
|
||||||
PathRemoveArgsW(unquoted);
|
|
||||||
StrTrimW(lpszArgs, L" ");
|
|
||||||
}
|
|
||||||
if (unquoted[0] == '"' && unquoted[wcslen(unquoted)-1] == '"')
|
|
||||||
PathUnquoteSpacesW(unquoted);
|
|
||||||
|
|
||||||
|
|
||||||
WCHAR *pwszExt = PathFindExtensionW(unquoted);
|
|
||||||
if (!wcsicmp(pwszExt, L".lnk"))
|
|
||||||
{
|
|
||||||
// FIXME load localized error msg
|
|
||||||
MessageBoxW(hwndDlg, L"You cannot create a link to a shortcut", L"Error", MB_ICONERROR);
|
|
||||||
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!PathFileExistsW(unquoted))
|
|
||||||
{
|
|
||||||
// FIXME load localized error msg
|
|
||||||
MessageBoxW(hwndDlg, L"The specified file name in the target box is invalid", L"Error", MB_ICONERROR);
|
|
||||||
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pThis->SetPath(unquoted);
|
|
||||||
if (lpszArgs)
|
|
||||||
pThis->SetArguments(lpszArgs);
|
|
||||||
else
|
|
||||||
pThis->SetArguments(L"\0");
|
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, unquoted);
|
|
||||||
|
|
||||||
TRACE("This %p m_sLinkPath %S\n", pThis, pThis->m_sLinkPath);
|
|
||||||
pThis->Save(pThis->m_sLinkPath, TRUE);
|
|
||||||
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_COMMAND:
|
case WM_COMMAND:
|
||||||
switch(LOWORD(wParam))
|
pThis->OnCommand(hwndDlg, LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
|
||||||
{
|
break;
|
||||||
case IDC_SHORTCUT_FIND:
|
|
||||||
SHOpenFolderAndSelectItems(pThis->m_pPidl, 0, NULL, 0);
|
|
||||||
///
|
|
||||||
/// FIXME
|
|
||||||
/// open target directory
|
|
||||||
///
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
case IDC_SHORTCUT_CHANGE_ICON:
|
case WM_DESTROY:
|
||||||
{
|
pThis->OnDestroy(hwndDlg);
|
||||||
WCHAR wszPath[MAX_PATH] = L"";
|
|
||||||
|
|
||||||
if (pThis->m_sIcoPath)
|
|
||||||
wcscpy(wszPath, pThis->m_sIcoPath);
|
|
||||||
else
|
|
||||||
FindExecutableW(pThis->m_sPath, NULL, wszPath);
|
|
||||||
|
|
||||||
INT IconIndex = pThis->m_Header.nIconIndex;
|
|
||||||
if (PickIconDlg(hwndDlg, wszPath, _countof(wszPath), &IconIndex))
|
|
||||||
{
|
|
||||||
pThis->SetIconLocation(wszPath, IconIndex);
|
|
||||||
|
|
||||||
HICON hIconLarge = NULL;
|
|
||||||
if (S_OK == pThis->Extract(wszPath, IconIndex, &hIconLarge, NULL, 0))
|
|
||||||
{
|
|
||||||
HICON hIconOld = (HICON)SendDlgItemMessageW(hwndDlg, IDC_SHORTCUT_ICON, STM_GETICON, 0, 0);
|
|
||||||
SendDlgItemMessageW(hwndDlg, IDC_SHORTCUT_ICON, STM_SETICON, (WPARAM)hIconLarge, 0);
|
|
||||||
DestroyIcon(hIconOld);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
case IDC_SHORTCUT_ADVANCED:
|
|
||||||
{
|
|
||||||
INT_PTR result = DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_SHORTCUT_EXTENDED_PROPERTIES), hwndDlg, ExtendedShortcutProc, (LPARAM)pThis->m_bRunAs);
|
|
||||||
if (result == 1 || result == 0)
|
|
||||||
{
|
|
||||||
if (pThis->m_bRunAs != result)
|
|
||||||
{
|
|
||||||
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
|
|
||||||
}
|
|
||||||
|
|
||||||
pThis->m_bRunAs = result;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (HIWORD(wParam) == EN_CHANGE)
|
|
||||||
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3083,3 +3150,64 @@ HRESULT WINAPI IShellLink_ConstructFromFile(IShellFolder * psf, LPCITEMIDLIST pi
|
||||||
|
|
||||||
return IShellLink_ConstructFromPath(path, riid, ppv);
|
return IShellLink_ConstructFromPath(path, riid, ppv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HICON CShellLink::CreateShortcutIcon(LPCWSTR wszIconPath, INT IconIndex)
|
||||||
|
{
|
||||||
|
const INT cx = GetSystemMetrics(SM_CXICON), cy = GetSystemMetrics(SM_CYICON);
|
||||||
|
const COLORREF crMask = GetSysColor(COLOR_3DFACE);
|
||||||
|
HDC hDC;
|
||||||
|
HIMAGELIST himl = ImageList_Create(cx, cy, ILC_COLOR32 | ILC_MASK, 1, 1);
|
||||||
|
HICON hIcon = NULL, hNewIcon = NULL;
|
||||||
|
HICON hShortcut = (HICON)LoadImageW(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_SHORTCUT),
|
||||||
|
IMAGE_ICON, cx, cy, 0);
|
||||||
|
|
||||||
|
::ExtractIconExW(wszIconPath, IconIndex, &hIcon, NULL, 1);
|
||||||
|
if (!hIcon || !hShortcut || !himl)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
hDC = CreateCompatibleDC(NULL);
|
||||||
|
if (hDC)
|
||||||
|
{
|
||||||
|
// create 32bpp bitmap
|
||||||
|
BITMAPINFO bi;
|
||||||
|
ZeroMemory(&bi, sizeof(bi));
|
||||||
|
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||||
|
bi.bmiHeader.biWidth = cx;
|
||||||
|
bi.bmiHeader.biHeight = cy;
|
||||||
|
bi.bmiHeader.biPlanes = 1;
|
||||||
|
bi.bmiHeader.biBitCount = 32;
|
||||||
|
LPVOID pvBits;
|
||||||
|
HBITMAP hbm = CreateDIBSection(hDC, &bi, DIB_RGB_COLORS, &pvBits, NULL, 0);
|
||||||
|
if (hbm)
|
||||||
|
{
|
||||||
|
// draw the icon image
|
||||||
|
HGDIOBJ hbmOld = SelectObject(hDC, hbm);
|
||||||
|
{
|
||||||
|
HBRUSH hbr = CreateSolidBrush(crMask);
|
||||||
|
RECT rc = { 0, 0, cx, cy };
|
||||||
|
FillRect(hDC, &rc, hbr);
|
||||||
|
DeleteObject(hbr);
|
||||||
|
|
||||||
|
DrawIconEx(hDC, 0, 0, hIcon, cx, cy, 0, NULL, DI_NORMAL);
|
||||||
|
DrawIconEx(hDC, 0, 0, hShortcut, cx, cy, 0, NULL, DI_NORMAL);
|
||||||
|
}
|
||||||
|
SelectObject(hDC, hbmOld);
|
||||||
|
|
||||||
|
INT iAdded = ImageList_AddMasked(himl, hbm, crMask);
|
||||||
|
hNewIcon = ImageList_GetIcon(himl, iAdded, ILD_NORMAL | ILD_TRANSPARENT);
|
||||||
|
|
||||||
|
DeleteObject(hbm);
|
||||||
|
}
|
||||||
|
DeleteDC(hDC);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (hIcon)
|
||||||
|
DestroyIcon(hIcon);
|
||||||
|
if (hShortcut)
|
||||||
|
DestroyIcon(hShortcut);
|
||||||
|
if (himl)
|
||||||
|
ImageList_Destroy(himl);
|
||||||
|
|
||||||
|
return hNewIcon;
|
||||||
|
}
|
||||||
|
|
|
@ -81,6 +81,8 @@ private:
|
||||||
BOOL m_bRunAs;
|
BOOL m_bRunAs;
|
||||||
BOOL m_bDirty;
|
BOOL m_bDirty;
|
||||||
LPDBLIST m_pDBList; /* Optional data block list (in the extra data section) */
|
LPDBLIST m_pDBList; /* Optional data block list (in the extra data section) */
|
||||||
|
BOOL m_bInInit; // in initialization or not
|
||||||
|
HICON m_hIcon;
|
||||||
|
|
||||||
/* Pointers to strings inside Logo3/Darwin info blocks, cached for debug info purposes only */
|
/* Pointers to strings inside Logo3/Darwin info blocks, cached for debug info purposes only */
|
||||||
LPWSTR sProduct;
|
LPWSTR sProduct;
|
||||||
|
@ -98,12 +100,18 @@ private:
|
||||||
HRESULT SetAdvertiseInfo(LPCWSTR str);
|
HRESULT SetAdvertiseInfo(LPCWSTR str);
|
||||||
HRESULT WriteAdvertiseInfo(LPCWSTR string, DWORD dwSig);
|
HRESULT WriteAdvertiseInfo(LPCWSTR string, DWORD dwSig);
|
||||||
HRESULT SetTargetFromPIDLOrPath(LPCITEMIDLIST pidl, LPCWSTR pszFile);
|
HRESULT SetTargetFromPIDLOrPath(LPCITEMIDLIST pidl, LPCWSTR pszFile);
|
||||||
|
HICON CreateShortcutIcon(LPCWSTR wszIconPath, INT IconIndex);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CShellLink();
|
CShellLink();
|
||||||
~CShellLink();
|
~CShellLink();
|
||||||
static INT_PTR CALLBACK SH_ShellLinkDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
static INT_PTR CALLBACK SH_ShellLinkDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
BOOL OnInitDialog(HWND hwndDlg, HWND hwndFocus, LPARAM lParam);
|
||||||
|
void OnCommand(HWND hwndDlg, int id, HWND hwndCtl, UINT codeNotify);
|
||||||
|
LRESULT OnNotify(HWND hwndDlg, int idFrom, LPNMHDR pnmhdr);
|
||||||
|
void OnDestroy(HWND hwndDlg);
|
||||||
|
|
||||||
// IPersistFile
|
// IPersistFile
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pclsid);
|
virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pclsid);
|
||||||
virtual HRESULT STDMETHODCALLTYPE IsDirty();
|
virtual HRESULT STDMETHODCALLTYPE IsDirty();
|
||||||
|
|
Loading…
Reference in a new issue