From 151ba9ee8f666cb1b518a576f164a6eb5602956f Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Wed, 26 Mar 2025 04:35:22 +0900 Subject: [PATCH] [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 . - Fix browseui!CShellBrowser:: OnAddToFavorites and shdocvw!CNSCBand::_AddFavorite by using AddUrlToFavorites. --- dll/win32/browseui/CMakeLists.txt | 2 +- dll/win32/browseui/shellbrowser.cpp | 61 +++++--------------- dll/win32/shdocvw/CNSCBand.cpp | 63 +++++---------------- dll/win32/shdocvw/shdocvw.spec | 2 +- dll/win32/shdocvw/utility.cpp | 86 +++++++++++++++++++++++++++++ sdk/include/reactos/shdocvw_undoc.h | 7 +++ 6 files changed, 122 insertions(+), 99 deletions(-) diff --git a/dll/win32/browseui/CMakeLists.txt b/dll/win32/browseui/CMakeLists.txt index e420dc69686..c138e897a50 100644 --- a/dll/win32/browseui/CMakeLists.txt +++ b/dll/win32/browseui/CMakeLists.txt @@ -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) diff --git a/dll/win32/browseui/shellbrowser.cpp b/dll/win32/browseui/shellbrowser.cpp index bd58da36ab0..00b98cd07f3 100644 --- a/dll/win32/browseui/shellbrowser.cpp +++ b/dll/win32/browseui/shellbrowser.cpp @@ -23,6 +23,7 @@ #include #include #include +#include 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 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 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; } diff --git a/dll/win32/shdocvw/CNSCBand.cpp b/dll/win32/shdocvw/CNSCBand.cpp index a2ecb4830ef..8868931bb1e 100644 --- a/dll/win32/shdocvw/CNSCBand.cpp +++ b/dll/win32/shdocvw/CNSCBand.cpp @@ -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 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 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 pidlCurrent; _GetCurrentLocation(&pidlCurrent); - WCHAR szCurDir[MAX_PATH]; - if (!ILGetDisplayName(pidlCurrent, szCurDir)) - { - FIXME("\n"); - return E_FAIL; - } + CComPtr 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 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) diff --git a/dll/win32/shdocvw/shdocvw.spec b/dll/win32/shdocvw/shdocvw.spec index e0b72b28de3..22f99fa9dda 100644 --- a/dll/win32/shdocvw/shdocvw.spec +++ b/dll/win32/shdocvw/shdocvw.spec @@ -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) diff --git a/dll/win32/shdocvw/utility.cpp b/dll/win32/shdocvw/utility.cpp index 018d1177fad..bd4b522c420 100644 --- a/dll/win32/shdocvw/utility.cpp +++ b/dll/win32/shdocvw/utility.cpp @@ -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 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 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 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); +} diff --git a/sdk/include/reactos/shdocvw_undoc.h b/sdk/include/reactos/shdocvw_undoc.h index 31be12fa29c..76c8970006e 100644 --- a/sdk/include/reactos/shdocvw_undoc.h +++ b/sdk/include/reactos/shdocvw_undoc.h @@ -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);