[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) set_module_type(browseui win32dll UNICODE)
target_link_libraries(browseui shellbars shellfind uuid wine cpprt atl_classes) 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_pch(browseui precomp.h "${PCH_SKIP_SOURCE}")
add_cd_file(TARGET browseui DESTINATION reactos/system32 FOR all) add_cd_file(TARGET browseui DESTINATION reactos/system32 FOR all)

View file

@ -23,6 +23,7 @@
#include <shellapi.h> #include <shellapi.h>
#include <htiframe.h> #include <htiframe.h>
#include <strsafe.h> #include <strsafe.h>
#include <shdocvw_undoc.h>
extern HRESULT IUnknown_ShowDW(IUnknown * punk, BOOL fShow); extern HRESULT IUnknown_ShowDW(IUnknown * punk, BOOL fShow);
@ -3871,41 +3872,6 @@ LRESULT CShellBrowser::OnBackspace(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOO
return 0; 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 GetFavsLocation(HWND hWnd, LPITEMIDLIST *pPidl)
{ {
HRESULT hr = SHGetSpecialFolderLocation(hWnd, CSIDL_FAVORITES, 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) LRESULT CShellBrowser::OnAddToFavorites(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
{ {
LPITEMIDLIST pidlFavs; CComPtr<IShellFolder> pParent;
HRESULT hr = GetFavsLocation(m_hWnd, &pidlFavs); 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)) if (FAILED_UNEXPECTEDLY(hr))
return 0; return 0;
SHFILEINFOW fileInfo = { NULL }; CComHeapPtr<WCHAR> pszURL;
if (!SHGetFileInfoW((LPCWSTR)fCurrentDirectoryPIDL, 0, &fileInfo, sizeof(fileInfo), hr = StrRetToStrW(&strret, NULL, &pszURL);
SHGFI_PIDL | SHGFI_DISPLAYNAME)) if (FAILED_UNEXPECTEDLY(hr))
{
return 0; return 0;
}
WCHAR szPath[MAX_PATH]; AddUrlToFavorites(m_hWnd, pszURL, NULL, TRUE);
SHGetPathFromIDListW(pidlFavs, szPath);
PathAppendW(szPath, fileInfo.szDisplayName);
PathAddExtensionW(szPath, L".lnk");
CreateShortcut(szPath, fCurrentDirectoryPIDL, NULL);
return 0; return 0;
} }

View file

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

View file

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

View file

@ -139,3 +139,89 @@ IEILIsEqual(
FIXME("%p, %p\n", pidl1, pidl2); FIXME("%p, %p\n", pidl1, pidl2);
return FALSE; 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_ LPCITEMIDLIST pidl2,
_In_ BOOL bUnknown); _In_ BOOL bUnknown);
HRESULT WINAPI
AddUrlToFavorites(
_In_ HWND hwnd,
_In_opt_ LPCWSTR pszUrlW,
_In_ LPCWSTR pszTitleW,
_In_ BOOL fDisplayUI);
BOOL WINAPI WinList_Init(VOID); BOOL WINAPI WinList_Init(VOID);
VOID WINAPI WinList_Terminate(VOID); VOID WINAPI WinList_Terminate(VOID);
HRESULT WINAPI WinList_Revoke(_In_ LONG lCookie); HRESULT WINAPI WinList_Revoke(_In_ LONG lCookie);