[BROWSEUI][SHDOCVW][SDK] Fix 'Add Favorite' command (#7804)

JIRA issue: CORE-19824
JIRA issue: CORE-19867
- Add shdocvw import to browseui.
- Half-implement shdocvw!
  AddUrlToFavorites function.
- Add AddUrlToFavorites prototype
  to <shdocvw_undoc.h>.
- Fix browseui!CShellBrowser::
  OnAddToFavorites and
  shdocvw!CNSCBand::_AddFavorite
  by using AddUrlToFavorites.
This commit is contained in:
Katayama Hirofumi MZ 2025-03-26 04:35:22 +09:00 committed by GitHub
parent 0c6423da8d
commit 151ba9ee8f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 122 additions and 99 deletions

View file

@ -48,7 +48,7 @@ add_library(browseui MODULE
set_module_type(browseui win32dll UNICODE)
target_link_libraries(browseui shellbars shellfind uuid wine cpprt atl_classes)
add_importlibs(browseui uxtheme shlwapi shell32 comctl32 gdi32 ole32 oleaut32 user32 advapi32 mpr msvcrt kernel32 ntdll)
add_importlibs(browseui uxtheme shdocvw shlwapi shell32 comctl32 gdi32 ole32 oleaut32 user32 advapi32 mpr msvcrt kernel32 ntdll)
add_pch(browseui precomp.h "${PCH_SKIP_SOURCE}")
add_cd_file(TARGET browseui DESTINATION reactos/system32 FOR all)

View file

@ -23,6 +23,7 @@
#include <shellapi.h>
#include <htiframe.h>
#include <strsafe.h>
#include <shdocvw_undoc.h>
extern HRESULT IUnknown_ShowDW(IUnknown * punk, BOOL fShow);
@ -3871,41 +3872,6 @@ LRESULT CShellBrowser::OnBackspace(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOO
return 0;
}
static BOOL
CreateShortcut(
IN LPCWSTR pszLnkFileName,
IN LPCITEMIDLIST pidl,
IN LPCWSTR pszDescription OPTIONAL)
{
IPersistFile *pPF;
IShellLinkW *pSL;
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
return hr;
hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
IID_IShellLinkW, (LPVOID*)&pSL);
if (SUCCEEDED(hr))
{
pSL->SetIDList(pidl);
if (pszDescription)
pSL->SetDescription(pszDescription);
hr = pSL->QueryInterface(IID_IPersistFile, (LPVOID*)&pPF);
if (SUCCEEDED(hr))
{
hr = pPF->Save(pszLnkFileName, TRUE);
pPF->Release();
}
pSL->Release();
}
CoUninitialize();
return SUCCEEDED(hr);
}
HRESULT GetFavsLocation(HWND hWnd, LPITEMIDLIST *pPidl)
{
HRESULT hr = SHGetSpecialFolderLocation(hWnd, CSIDL_FAVORITES, pPidl);
@ -3917,24 +3883,23 @@ HRESULT GetFavsLocation(HWND hWnd, LPITEMIDLIST *pPidl)
LRESULT CShellBrowser::OnAddToFavorites(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
{
LPITEMIDLIST pidlFavs;
HRESULT hr = GetFavsLocation(m_hWnd, &pidlFavs);
CComPtr<IShellFolder> pParent;
LPCITEMIDLIST pidlLast;
HRESULT hr = SHBindToParent(fCurrentDirectoryPIDL, IID_PPV_ARG(IShellFolder, &pParent), &pidlLast);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
STRRET strret;
hr = pParent->GetDisplayNameOf(pidlLast, SHGDN_FORPARSING, &strret);
if (FAILED_UNEXPECTEDLY(hr))
return 0;
SHFILEINFOW fileInfo = { NULL };
if (!SHGetFileInfoW((LPCWSTR)fCurrentDirectoryPIDL, 0, &fileInfo, sizeof(fileInfo),
SHGFI_PIDL | SHGFI_DISPLAYNAME))
{
CComHeapPtr<WCHAR> pszURL;
hr = StrRetToStrW(&strret, NULL, &pszURL);
if (FAILED_UNEXPECTEDLY(hr))
return 0;
}
WCHAR szPath[MAX_PATH];
SHGetPathFromIDListW(pidlFavs, szPath);
PathAppendW(szPath, fileInfo.szDisplayName);
PathAddExtensionW(szPath, L".lnk");
CreateShortcut(szPath, fCurrentDirectoryPIDL, NULL);
AddUrlToFavorites(m_hWnd, pszURL, NULL, TRUE);
return 0;
}

View file

@ -45,33 +45,6 @@ SHDOCVW_GetPathOfShortcut(
return S_OK;
}
HRESULT
SHDOCVW_CreateShortcut(
_In_ LPCWSTR pszLnkFileName,
_In_ PCIDLIST_ABSOLUTE pidlTarget,
_In_opt_ LPCWSTR pszDescription)
{
HRESULT hr;
CComPtr<IShellLink> psl;
hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARG(IShellLink, &psl));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
psl->SetIDList(pidlTarget);
if (pszDescription)
psl->SetDescription(pszDescription);
CComPtr<IPersistFile> ppf;
hr = psl->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return ppf->Save(pszLnkFileName, TRUE);
}
CNSCBand::CNSCBand()
{
SHDOCVW_LockModule();
@ -648,31 +621,23 @@ HRESULT CNSCBand::_AddFavorite()
CComHeapPtr<ITEMIDLIST> pidlCurrent;
_GetCurrentLocation(&pidlCurrent);
WCHAR szCurDir[MAX_PATH];
if (!ILGetDisplayName(pidlCurrent, szCurDir))
{
FIXME("\n");
return E_FAIL;
}
CComPtr<IShellFolder> pParent;
LPCITEMIDLIST pidlLast;
HRESULT hr = SHBindToParent(pidlCurrent, IID_PPV_ARG(IShellFolder, &pParent), &pidlLast);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
WCHAR szPath[MAX_PATH], szSuffix[32];
SHGetSpecialFolderPathW(m_hWnd, szPath, CSIDL_FAVORITES, TRUE);
PathAppendW(szPath, PathFindFileNameW(szCurDir));
STRRET strret;
hr = pParent->GetDisplayNameOf(pidlLast, SHGDN_FORPARSING, &strret);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
const INT ich = lstrlenW(szPath);
for (INT iTry = 2; iTry <= 9999; ++iTry)
{
PathAddExtensionW(szPath, L".lnk");
if (!PathFileExistsW(szPath))
break;
szPath[ich] = UNICODE_NULL;
wsprintfW(szSuffix, L" (%d)", iTry);
lstrcatW(szPath, szSuffix);
}
CComHeapPtr<WCHAR> pszURL;
hr = StrRetToStrW(&strret, NULL, &pszURL);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
TRACE("%S, %S\n", szCurDir, szPath);
return SHDOCVW_CreateShortcut(szPath, pidlCurrent, NULL);
return AddUrlToFavorites(m_hWnd, pszURL, NULL, TRUE);
}
LRESULT CNSCBand::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)

View file

@ -3,7 +3,7 @@
103 stub -noname CreateShortcutInDirW # FIXME: Inspect
104 stdcall -noname WhichPlatformFORWARD()
105 stub -noname CreateShortcutInDirEx # FIXME: Inspect
106 stub AddUrlToFavorites
106 stdcall AddUrlToFavorites(ptr wstr wstr long)
@ stdcall -private DllCanUnloadNow()
@ stdcall -private DllGetClassObject(ptr ptr ptr)
@ stdcall -private DllGetVersion(ptr)

View file

@ -139,3 +139,89 @@ IEILIsEqual(
FIXME("%p, %p\n", pidl1, pidl2);
return FALSE;
}
static VOID
SHDOCVW_PathDeleteInvalidChars(LPWSTR pszDisplayName)
{
#define PATH_VALID_ELEMENT ( \
PATH_CHAR_CLASS_DOT | PATH_CHAR_CLASS_SEMICOLON | PATH_CHAR_CLASS_COMMA | \
PATH_CHAR_CLASS_SPACE | PATH_CHAR_CLASS_OTHER_VALID \
)
PWCHAR pch, pchSrc;
for (pch = pchSrc = pszDisplayName; *pchSrc; ++pchSrc)
{
if (PathIsValidCharW(*pchSrc, PATH_VALID_ELEMENT))
*pch++ = *pchSrc;
}
*pch = UNICODE_NULL;
}
static HRESULT
SHDOCVW_CreateShortcut(
_In_ LPCWSTR pszLnkFileName,
_In_ PCIDLIST_ABSOLUTE pidlTarget,
_In_opt_ LPCWSTR pszDescription)
{
HRESULT hr;
CComPtr<IShellLink> psl;
hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARG(IShellLink, &psl));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
psl->SetIDList(pidlTarget);
if (pszDescription)
psl->SetDescription(pszDescription);
CComPtr<IPersistFile> ppf;
hr = psl->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return ppf->Save(pszLnkFileName, TRUE);
}
/*************************************************************************
* AddUrlToFavorites [SHDOCVW.106]
*/
EXTERN_C HRESULT WINAPI
AddUrlToFavorites(
_In_ HWND hwnd,
_In_ LPCWSTR pszUrlW,
_In_opt_ LPCWSTR pszTitleW,
_In_ BOOL fDisplayUI)
{
TRACE("%p, %s, %s, %d\n", hwnd, wine_dbgstr_w(pszUrlW), wine_dbgstr_w(pszTitleW), fDisplayUI);
if (fDisplayUI)
FIXME("fDisplayUI\n"); // NOTE: Use SHBrowseForFolder callback
if (PathIsURLW(pszUrlW))
FIXME("Internet Shortcut\n");
CComHeapPtr<ITEMIDLIST> pidl;
HRESULT hr = SHParseDisplayName(pszUrlW, NULL, &pidl, 0, NULL);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
// Get title
WCHAR szTitle[MAX_PATH];
if (pszTitleW)
lstrcpynW(szTitle, pszTitleW, _countof(szTitle));
else
ILGetDisplayNameEx(NULL, pidl, szTitle, ILGDN_NORMAL);
// Delete invalid characters
SHDOCVW_PathDeleteInvalidChars(szTitle);
// Build shortcut pathname
WCHAR szPath[MAX_PATH];
if (!SHGetSpecialFolderPathW(hwnd, szPath, CSIDL_FAVORITES, TRUE))
SHGetSpecialFolderPathW(hwnd, szPath, CSIDL_COMMON_FAVORITES, TRUE);
PathAppendW(szPath, szTitle);
PathAddExtensionW(szPath, L".lnk");
return SHDOCVW_CreateShortcut(szPath, pidl, NULL);
}

View file

@ -19,6 +19,13 @@ IEILIsEqual(
_In_ LPCITEMIDLIST pidl2,
_In_ BOOL bUnknown);
HRESULT WINAPI
AddUrlToFavorites(
_In_ HWND hwnd,
_In_opt_ LPCWSTR pszUrlW,
_In_ LPCWSTR pszTitleW,
_In_ BOOL fDisplayUI);
BOOL WINAPI WinList_Init(VOID);
VOID WINAPI WinList_Terminate(VOID);
HRESULT WINAPI WinList_Revoke(_In_ LONG lCookie);