Skip to content

Commit 151ba9e

Browse files
authored
[BROWSEUI][SHDOCVW][SDK] Fix 'Add Favorite' command (reactos#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.
1 parent 0c6423d commit 151ba9e

File tree

6 files changed

+122
-99
lines changed

6 files changed

+122
-99
lines changed

dll/win32/browseui/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ add_library(browseui MODULE
4848

4949
set_module_type(browseui win32dll UNICODE)
5050
target_link_libraries(browseui shellbars shellfind uuid wine cpprt atl_classes)
51-
add_importlibs(browseui uxtheme shlwapi shell32 comctl32 gdi32 ole32 oleaut32 user32 advapi32 mpr msvcrt kernel32 ntdll)
51+
add_importlibs(browseui uxtheme shdocvw shlwapi shell32 comctl32 gdi32 ole32 oleaut32 user32 advapi32 mpr msvcrt kernel32 ntdll)
5252
add_pch(browseui precomp.h "${PCH_SKIP_SOURCE}")
5353
add_cd_file(TARGET browseui DESTINATION reactos/system32 FOR all)
5454

dll/win32/browseui/shellbrowser.cpp

Lines changed: 13 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <shellapi.h>
2424
#include <htiframe.h>
2525
#include <strsafe.h>
26+
#include <shdocvw_undoc.h>
2627

2728
extern HRESULT IUnknown_ShowDW(IUnknown * punk, BOOL fShow);
2829

@@ -3871,41 +3872,6 @@ LRESULT CShellBrowser::OnBackspace(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOO
38713872
return 0;
38723873
}
38733874

3874-
static BOOL
3875-
CreateShortcut(
3876-
IN LPCWSTR pszLnkFileName,
3877-
IN LPCITEMIDLIST pidl,
3878-
IN LPCWSTR pszDescription OPTIONAL)
3879-
{
3880-
IPersistFile *pPF;
3881-
IShellLinkW *pSL;
3882-
HRESULT hr = CoInitialize(NULL);
3883-
if (FAILED(hr))
3884-
return hr;
3885-
3886-
hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
3887-
IID_IShellLinkW, (LPVOID*)&pSL);
3888-
if (SUCCEEDED(hr))
3889-
{
3890-
pSL->SetIDList(pidl);
3891-
3892-
if (pszDescription)
3893-
pSL->SetDescription(pszDescription);
3894-
3895-
hr = pSL->QueryInterface(IID_IPersistFile, (LPVOID*)&pPF);
3896-
if (SUCCEEDED(hr))
3897-
{
3898-
hr = pPF->Save(pszLnkFileName, TRUE);
3899-
pPF->Release();
3900-
}
3901-
pSL->Release();
3902-
}
3903-
3904-
CoUninitialize();
3905-
3906-
return SUCCEEDED(hr);
3907-
}
3908-
39093875
HRESULT GetFavsLocation(HWND hWnd, LPITEMIDLIST *pPidl)
39103876
{
39113877
HRESULT hr = SHGetSpecialFolderLocation(hWnd, CSIDL_FAVORITES, pPidl);
@@ -3917,24 +3883,23 @@ HRESULT GetFavsLocation(HWND hWnd, LPITEMIDLIST *pPidl)
39173883

39183884
LRESULT CShellBrowser::OnAddToFavorites(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
39193885
{
3920-
LPITEMIDLIST pidlFavs;
3921-
HRESULT hr = GetFavsLocation(m_hWnd, &pidlFavs);
3886+
CComPtr<IShellFolder> pParent;
3887+
LPCITEMIDLIST pidlLast;
3888+
HRESULT hr = SHBindToParent(fCurrentDirectoryPIDL, IID_PPV_ARG(IShellFolder, &pParent), &pidlLast);
39223889
if (FAILED_UNEXPECTEDLY(hr))
3923-
return 0;
3890+
return hr;
39243891

3925-
SHFILEINFOW fileInfo = { NULL };
3926-
if (!SHGetFileInfoW((LPCWSTR)fCurrentDirectoryPIDL, 0, &fileInfo, sizeof(fileInfo),
3927-
SHGFI_PIDL | SHGFI_DISPLAYNAME))
3928-
{
3892+
STRRET strret;
3893+
hr = pParent->GetDisplayNameOf(pidlLast, SHGDN_FORPARSING, &strret);
3894+
if (FAILED_UNEXPECTEDLY(hr))
39293895
return 0;
3930-
}
39313896

3932-
WCHAR szPath[MAX_PATH];
3933-
SHGetPathFromIDListW(pidlFavs, szPath);
3934-
PathAppendW(szPath, fileInfo.szDisplayName);
3935-
PathAddExtensionW(szPath, L".lnk");
3897+
CComHeapPtr<WCHAR> pszURL;
3898+
hr = StrRetToStrW(&strret, NULL, &pszURL);
3899+
if (FAILED_UNEXPECTEDLY(hr))
3900+
return 0;
39363901

3937-
CreateShortcut(szPath, fCurrentDirectoryPIDL, NULL);
3902+
AddUrlToFavorites(m_hWnd, pszURL, NULL, TRUE);
39383903
return 0;
39393904
}
39403905

dll/win32/shdocvw/CNSCBand.cpp

Lines changed: 14 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -45,33 +45,6 @@ SHDOCVW_GetPathOfShortcut(
4545
return S_OK;
4646
}
4747

48-
HRESULT
49-
SHDOCVW_CreateShortcut(
50-
_In_ LPCWSTR pszLnkFileName,
51-
_In_ PCIDLIST_ABSOLUTE pidlTarget,
52-
_In_opt_ LPCWSTR pszDescription)
53-
{
54-
HRESULT hr;
55-
56-
CComPtr<IShellLink> psl;
57-
hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
58-
IID_PPV_ARG(IShellLink, &psl));
59-
if (FAILED_UNEXPECTEDLY(hr))
60-
return hr;
61-
62-
psl->SetIDList(pidlTarget);
63-
64-
if (pszDescription)
65-
psl->SetDescription(pszDescription);
66-
67-
CComPtr<IPersistFile> ppf;
68-
hr = psl->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf));
69-
if (FAILED_UNEXPECTEDLY(hr))
70-
return hr;
71-
72-
return ppf->Save(pszLnkFileName, TRUE);
73-
}
74-
7548
CNSCBand::CNSCBand()
7649
{
7750
SHDOCVW_LockModule();
@@ -648,31 +621,23 @@ HRESULT CNSCBand::_AddFavorite()
648621
CComHeapPtr<ITEMIDLIST> pidlCurrent;
649622
_GetCurrentLocation(&pidlCurrent);
650623

651-
WCHAR szCurDir[MAX_PATH];
652-
if (!ILGetDisplayName(pidlCurrent, szCurDir))
653-
{
654-
FIXME("\n");
655-
return E_FAIL;
656-
}
657-
658-
WCHAR szPath[MAX_PATH], szSuffix[32];
659-
SHGetSpecialFolderPathW(m_hWnd, szPath, CSIDL_FAVORITES, TRUE);
660-
PathAppendW(szPath, PathFindFileNameW(szCurDir));
624+
CComPtr<IShellFolder> pParent;
625+
LPCITEMIDLIST pidlLast;
626+
HRESULT hr = SHBindToParent(pidlCurrent, IID_PPV_ARG(IShellFolder, &pParent), &pidlLast);
627+
if (FAILED_UNEXPECTEDLY(hr))
628+
return hr;
661629

662-
const INT ich = lstrlenW(szPath);
663-
for (INT iTry = 2; iTry <= 9999; ++iTry)
664-
{
665-
PathAddExtensionW(szPath, L".lnk");
666-
if (!PathFileExistsW(szPath))
667-
break;
668-
szPath[ich] = UNICODE_NULL;
669-
wsprintfW(szSuffix, L" (%d)", iTry);
670-
lstrcatW(szPath, szSuffix);
671-
}
630+
STRRET strret;
631+
hr = pParent->GetDisplayNameOf(pidlLast, SHGDN_FORPARSING, &strret);
632+
if (FAILED_UNEXPECTEDLY(hr))
633+
return hr;
672634

673-
TRACE("%S, %S\n", szCurDir, szPath);
635+
CComHeapPtr<WCHAR> pszURL;
636+
hr = StrRetToStrW(&strret, NULL, &pszURL);
637+
if (FAILED_UNEXPECTEDLY(hr))
638+
return hr;
674639

675-
return SHDOCVW_CreateShortcut(szPath, pidlCurrent, NULL);
640+
return AddUrlToFavorites(m_hWnd, pszURL, NULL, TRUE);
676641
}
677642

678643
LRESULT CNSCBand::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)

dll/win32/shdocvw/shdocvw.spec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
103 stub -noname CreateShortcutInDirW # FIXME: Inspect
44
104 stdcall -noname WhichPlatformFORWARD()
55
105 stub -noname CreateShortcutInDirEx # FIXME: Inspect
6-
106 stub AddUrlToFavorites
6+
106 stdcall AddUrlToFavorites(ptr wstr wstr long)
77
@ stdcall -private DllCanUnloadNow()
88
@ stdcall -private DllGetClassObject(ptr ptr ptr)
99
@ stdcall -private DllGetVersion(ptr)

dll/win32/shdocvw/utility.cpp

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,89 @@ IEILIsEqual(
139139
FIXME("%p, %p\n", pidl1, pidl2);
140140
return FALSE;
141141
}
142+
143+
static VOID
144+
SHDOCVW_PathDeleteInvalidChars(LPWSTR pszDisplayName)
145+
{
146+
#define PATH_VALID_ELEMENT ( \
147+
PATH_CHAR_CLASS_DOT | PATH_CHAR_CLASS_SEMICOLON | PATH_CHAR_CLASS_COMMA | \
148+
PATH_CHAR_CLASS_SPACE | PATH_CHAR_CLASS_OTHER_VALID \
149+
)
150+
PWCHAR pch, pchSrc;
151+
for (pch = pchSrc = pszDisplayName; *pchSrc; ++pchSrc)
152+
{
153+
if (PathIsValidCharW(*pchSrc, PATH_VALID_ELEMENT))
154+
*pch++ = *pchSrc;
155+
}
156+
*pch = UNICODE_NULL;
157+
}
158+
159+
static HRESULT
160+
SHDOCVW_CreateShortcut(
161+
_In_ LPCWSTR pszLnkFileName,
162+
_In_ PCIDLIST_ABSOLUTE pidlTarget,
163+
_In_opt_ LPCWSTR pszDescription)
164+
{
165+
HRESULT hr;
166+
167+
CComPtr<IShellLink> psl;
168+
hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
169+
IID_PPV_ARG(IShellLink, &psl));
170+
if (FAILED_UNEXPECTEDLY(hr))
171+
return hr;
172+
173+
psl->SetIDList(pidlTarget);
174+
175+
if (pszDescription)
176+
psl->SetDescription(pszDescription);
177+
178+
CComPtr<IPersistFile> ppf;
179+
hr = psl->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf));
180+
if (FAILED_UNEXPECTEDLY(hr))
181+
return hr;
182+
183+
return ppf->Save(pszLnkFileName, TRUE);
184+
}
185+
186+
/*************************************************************************
187+
* AddUrlToFavorites [SHDOCVW.106]
188+
*/
189+
EXTERN_C HRESULT WINAPI
190+
AddUrlToFavorites(
191+
_In_ HWND hwnd,
192+
_In_ LPCWSTR pszUrlW,
193+
_In_opt_ LPCWSTR pszTitleW,
194+
_In_ BOOL fDisplayUI)
195+
{
196+
TRACE("%p, %s, %s, %d\n", hwnd, wine_dbgstr_w(pszUrlW), wine_dbgstr_w(pszTitleW), fDisplayUI);
197+
198+
if (fDisplayUI)
199+
FIXME("fDisplayUI\n"); // NOTE: Use SHBrowseForFolder callback
200+
201+
if (PathIsURLW(pszUrlW))
202+
FIXME("Internet Shortcut\n");
203+
204+
CComHeapPtr<ITEMIDLIST> pidl;
205+
HRESULT hr = SHParseDisplayName(pszUrlW, NULL, &pidl, 0, NULL);
206+
if (FAILED_UNEXPECTEDLY(hr))
207+
return hr;
208+
209+
// Get title
210+
WCHAR szTitle[MAX_PATH];
211+
if (pszTitleW)
212+
lstrcpynW(szTitle, pszTitleW, _countof(szTitle));
213+
else
214+
ILGetDisplayNameEx(NULL, pidl, szTitle, ILGDN_NORMAL);
215+
216+
// Delete invalid characters
217+
SHDOCVW_PathDeleteInvalidChars(szTitle);
218+
219+
// Build shortcut pathname
220+
WCHAR szPath[MAX_PATH];
221+
if (!SHGetSpecialFolderPathW(hwnd, szPath, CSIDL_FAVORITES, TRUE))
222+
SHGetSpecialFolderPathW(hwnd, szPath, CSIDL_COMMON_FAVORITES, TRUE);
223+
PathAppendW(szPath, szTitle);
224+
PathAddExtensionW(szPath, L".lnk");
225+
226+
return SHDOCVW_CreateShortcut(szPath, pidl, NULL);
227+
}

sdk/include/reactos/shdocvw_undoc.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ IEILIsEqual(
1919
_In_ LPCITEMIDLIST pidl2,
2020
_In_ BOOL bUnknown);
2121

22+
HRESULT WINAPI
23+
AddUrlToFavorites(
24+
_In_ HWND hwnd,
25+
_In_opt_ LPCWSTR pszUrlW,
26+
_In_ LPCWSTR pszTitleW,
27+
_In_ BOOL fDisplayUI);
28+
2229
BOOL WINAPI WinList_Init(VOID);
2330
VOID WINAPI WinList_Terminate(VOID);
2431
HRESULT WINAPI WinList_Revoke(_In_ LONG lCookie);

0 commit comments

Comments
 (0)