@@ -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+ }
0 commit comments