stash
[wine/wine64.git] / dlls / hlink / hlink_main.c
blob213506e15f15fca03bc56b1bb72aa134d484aa9b
1 /*
2 * Implementation of hyperlinking (hlink.dll)
4 * Copyright 2005 Aric Stewart for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "hlink_private.h"
23 #include "winreg.h"
24 #include "hlguids.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(hlink);
30 typedef HRESULT (CALLBACK *LPFNCREATEINSTANCE)(IUnknown*, REFIID, LPVOID*);
32 typedef struct
34 const IClassFactoryVtbl *lpVtbl;
35 LPFNCREATEINSTANCE lpfnCI;
36 } CFImpl;
38 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
40 TRACE("%p %d %p\n", hinstDLL, fdwReason, lpvReserved);
42 switch (fdwReason)
44 case DLL_PROCESS_ATTACH:
45 DisableThreadLibraryCalls(hinstDLL);
46 break;
47 case DLL_PROCESS_DETACH:
48 break;
50 return TRUE;
53 /***********************************************************************
54 * DllCanUnloadNow (HLINK.@)
56 HRESULT WINAPI DllCanUnloadNow( void )
58 FIXME("\n");
59 return S_OK;
62 /***********************************************************************
63 * HlinkCreateFromMoniker (HLINK.@)
65 HRESULT WINAPI HlinkCreateFromMoniker( IMoniker *pimkTrgt, LPCWSTR pwzLocation,
66 LPCWSTR pwzFriendlyName, IHlinkSite* pihlsite, DWORD dwSiteData,
67 IUnknown* piunkOuter, REFIID riid, void** ppvObj)
69 IHlink *hl = NULL;
70 HRESULT r = S_OK;
72 TRACE("%p %s %s %p %i %p %s %p\n", pimkTrgt, debugstr_w(pwzLocation),
73 debugstr_w(pwzFriendlyName), pihlsite, dwSiteData, piunkOuter,
74 debugstr_guid(riid), ppvObj);
76 r = CoCreateInstance(&CLSID_StdHlink, piunkOuter, CLSCTX_INPROC_SERVER, riid, (LPVOID*)&hl);
77 if (FAILED(r))
78 return r;
80 if (pwzLocation)
81 IHlink_SetStringReference(hl, HLINKSETF_LOCATION, NULL, pwzLocation);
82 if (pwzFriendlyName)
83 IHlink_SetFriendlyName(hl, pwzFriendlyName);
84 if (pihlsite)
85 IHlink_SetHlinkSite(hl, pihlsite, dwSiteData);
86 if (pimkTrgt)
87 IHlink_SetMonikerReference(hl, 0, pimkTrgt, pwzLocation);
89 *ppvObj = hl;
91 TRACE("Returning %i\n",r);
93 return r;
96 /***********************************************************************
97 * HlinkCreateFromString (HLINK.@)
99 HRESULT WINAPI HlinkCreateFromString( LPCWSTR pwzTarget, LPCWSTR pwzLocation,
100 LPCWSTR pwzFriendlyName, IHlinkSite* pihlsite, DWORD dwSiteData,
101 IUnknown* piunkOuter, REFIID riid, void** ppvObj)
103 IHlink *hl = NULL;
104 HRESULT r = S_OK;
106 TRACE("%s %s %s %p %i %p %s %p\n", debugstr_w(pwzTarget),
107 debugstr_w(pwzLocation), debugstr_w(pwzFriendlyName), pihlsite,
108 dwSiteData, piunkOuter, debugstr_guid(riid), ppvObj);
110 r = CoCreateInstance(&CLSID_StdHlink, piunkOuter, CLSCTX_INPROC_SERVER, riid, (LPVOID*)&hl);
111 if (FAILED(r))
112 return r;
114 if (pwzLocation)
115 IHlink_SetStringReference(hl, HLINKSETF_LOCATION, NULL, pwzLocation);
117 if (pwzTarget)
119 IMoniker *pTgtMk = NULL;
120 IBindCtx *pbc = NULL;
121 ULONG eaten;
123 CreateBindCtx(0, &pbc);
124 r = MkParseDisplayName(pbc, pwzTarget, &eaten, &pTgtMk);
125 IBindCtx_Release(pbc);
127 if (FAILED(r))
129 LPCWSTR p = strchrW(pwzTarget, ':');
130 if (p && (p - pwzTarget > 1))
131 r = CreateURLMoniker(NULL, pwzTarget, &pTgtMk);
132 else
133 r = CreateFileMoniker(pwzTarget,&pTgtMk);
136 if (FAILED(r))
138 ERR("couldn't create moniker for %s, failed with error 0x%08x\n",
139 debugstr_w(pwzTarget), r);
140 return r;
143 IHlink_SetMonikerReference(hl, 0, pTgtMk, pwzLocation);
144 IMoniker_Release(pTgtMk);
146 IHlink_SetStringReference(hl, HLINKSETF_TARGET, pwzTarget, NULL);
149 if (pwzFriendlyName)
150 IHlink_SetFriendlyName(hl, pwzFriendlyName);
151 if (pihlsite)
152 IHlink_SetHlinkSite(hl, pihlsite, dwSiteData);
154 TRACE("Returning %i\n",r);
155 *ppvObj = hl;
157 return r;
161 /***********************************************************************
162 * HlinkNavigate (HLINK.@)
164 HRESULT WINAPI HlinkCreateBrowseContext( IUnknown* piunkOuter, REFIID riid, void** ppvObj)
166 HRESULT r = S_OK;
168 TRACE("%p %s %p\n", piunkOuter, debugstr_guid(riid), ppvObj);
170 r = CoCreateInstance(&CLSID_StdHlinkBrowseContext, piunkOuter, CLSCTX_INPROC_SERVER, riid, ppvObj);
172 TRACE("returning %i\n",r);
174 return r;
177 /***********************************************************************
178 * HlinkNavigate (HLINK.@)
180 HRESULT WINAPI HlinkNavigate(IHlink *phl, IHlinkFrame *phlFrame,
181 DWORD grfHLNF, LPBC pbc, IBindStatusCallback *pbsc,
182 IHlinkBrowseContext *phlbc)
184 HRESULT r = S_OK;
186 TRACE("%p %p %i %p %p %p\n", phl, phlFrame, grfHLNF, pbc, pbsc, phlbc);
188 if (phlFrame)
189 r = IHlinkFrame_Navigate(phlFrame, grfHLNF, pbc, pbsc, phl);
190 else if (phl)
191 r = IHlink_Navigate(phl, grfHLNF, pbc, pbsc, phlbc);
193 return r;
196 /***********************************************************************
197 * HlinkOnNavigate (HLINK.@)
199 HRESULT WINAPI HlinkOnNavigate( IHlinkFrame *phlFrame,
200 IHlinkBrowseContext* phlbc, DWORD grfHLNF, IMoniker *pmkTarget,
201 LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName, ULONG* puHLID)
203 HRESULT r = S_OK;
205 TRACE("%p %p %i %p %s %s %p\n",phlFrame, phlbc, grfHLNF, pmkTarget,
206 debugstr_w(pwzLocation), debugstr_w(pwzFriendlyName), puHLID);
208 r = IHlinkBrowseContext_OnNavigateHlink(phlbc, grfHLNF, pmkTarget,
209 pwzLocation, pwzFriendlyName, puHLID);
211 if (phlFrame)
212 r = IHlinkFrame_OnNavigate(phlFrame,grfHLNF,pmkTarget, pwzLocation,
213 pwzFriendlyName, 0);
215 return r;
218 /***********************************************************************
219 * HlinkCreateFromData (HLINK.@)
221 HRESULT WINAPI HlinkCreateFromData(IDataObject *piDataObj,
222 IHlinkSite *pihlsite, DWORD dwSiteData, IUnknown *piunkOuter,
223 REFIID riid, void **ppvObj)
225 FIXME("%p %p %d %p %p %p\n",
226 piDataObj, pihlsite, dwSiteData, piunkOuter, riid, ppvObj);
227 *ppvObj = NULL;
228 return E_NOTIMPL;
231 /***********************************************************************
232 * HlinkQueryCreateFromData (HLINK.@)
234 HRESULT WINAPI HlinkQueryCreateFromData(IDataObject* piDataObj)
236 FIXME("%p\n", piDataObj);
237 return E_NOTIMPL;
240 /***********************************************************************
241 * HlinkNavigateToStringReference (HLINK.@)
243 HRESULT WINAPI HlinkNavigateToStringReference( LPCWSTR pwzTarget,
244 LPCWSTR pwzLocation, IHlinkSite *pihlsite, DWORD dwSiteData,
245 IHlinkFrame *pihlframe, DWORD grfHLNF, LPBC pibc,
246 IBindStatusCallback *pibsc, IHlinkBrowseContext *pihlbc)
248 HRESULT r;
249 IHlink *hlink = NULL;
251 FIXME("%s %s %p %08x %p %08x %p %p %p\n",
252 debugstr_w(pwzTarget), debugstr_w(pwzLocation), pihlsite,
253 dwSiteData, pihlframe, grfHLNF, pibc, pibsc, pihlbc);
255 r = HlinkCreateFromString( pwzTarget, pwzLocation, NULL, pihlsite,
256 dwSiteData, NULL, &IID_IHlink, (LPVOID*) &hlink );
257 if (SUCCEEDED(r))
258 r = HlinkNavigate(hlink, pihlframe, grfHLNF, pibc, pibsc, pihlbc);
260 return r;
263 /***********************************************************************
264 * HlinkIsShortcut (HLINK.@)
266 HRESULT WINAPI HlinkIsShortcut(LPCWSTR pwzFileName)
268 int len;
270 static const WCHAR url_ext[] = {'.','u','r','l',0};
272 TRACE("(%s)\n", debugstr_w(pwzFileName));
274 if(!pwzFileName)
275 return E_INVALIDARG;
277 len = strlenW(pwzFileName)-4;
278 if(len < 0)
279 return S_FALSE;
281 return strcmpiW(pwzFileName+len, url_ext) ? S_FALSE : S_OK;
284 /***********************************************************************
285 * HlinkGetSpecialReference (HLINK.@)
287 HRESULT WINAPI HlinkGetSpecialReference(ULONG uReference, LPWSTR *ppwzReference)
289 DWORD res, type, size = 100;
290 LPCWSTR value_name;
291 WCHAR *buf;
292 HKEY hkey;
294 static const WCHAR start_pageW[] = {'S','t','a','r','t',' ','P','a','g','e',0};
295 static const WCHAR search_pageW[] = {'S','e','a','r','c','h',' ','P','a','g','e',0};
297 static const WCHAR ie_main_keyW[] =
298 {'S','o','f','t','w','a','r','e',
299 '\\','M','i','c','r','o','s','o','f','t','\\',
300 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r',
301 '\\','M','a','i','n',0};
303 TRACE("(%u %p)\n", uReference, ppwzReference);
305 *ppwzReference = NULL;
307 switch(uReference) {
308 case HLSR_HOME:
309 value_name = start_pageW;
310 break;
311 case HLSR_SEARCHPAGE:
312 value_name = search_pageW;
313 break;
314 case HLSR_HISTORYFOLDER:
315 return E_NOTIMPL;
316 default:
317 return E_INVALIDARG;
320 res = RegOpenKeyW(HKEY_CURRENT_USER, ie_main_keyW, &hkey);
321 if(res != ERROR_SUCCESS) {
322 WARN("Could not open key: %u\n", res);
323 return HRESULT_FROM_WIN32(res);
326 buf = CoTaskMemAlloc(size);
327 res = RegQueryValueExW(hkey, value_name, NULL, &type, (PBYTE)buf, &size);
328 buf = CoTaskMemRealloc(buf, size);
329 if(res == ERROR_MORE_DATA)
330 res = RegQueryValueExW(hkey, value_name, NULL, &type, (PBYTE)buf, &size);
331 RegCloseKey(hkey);
332 if(res != ERROR_SUCCESS) {
333 WARN("Could not query value %s: %u\n", debugstr_w(value_name), res);
334 CoTaskMemFree(buf);
335 return HRESULT_FROM_WIN32(res);
338 *ppwzReference = buf;
339 return S_OK;
342 /***********************************************************************
343 * HlinkTranslateURL (HLINK.@)
345 HRESULT WINAPI HlinkTranslateURL(LPCWSTR pwzURL, DWORD grfFlags, LPWSTR *ppwzTranslatedURL)
347 FIXME("(%s %08x %p)\n", debugstr_w(pwzURL), grfFlags, ppwzTranslatedURL);
348 return E_NOTIMPL;
351 /***********************************************************************
352 * HlinkUpdateStackItem (HLINK.@)
354 HRESULT WINAPI HlinkUpdateStackItem(IHlinkFrame *pihlframe, IHlinkBrowseContext *pihlbc,
355 ULONG uHLID, IMoniker *pimkTrgt, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName)
357 FIXME("(%p %p %u %p %s %s)\n", pihlframe, pihlbc, uHLID, pimkTrgt, debugstr_w(pwzLocation),
358 debugstr_w(pwzFriendlyName));
359 return E_NOTIMPL;
362 /***********************************************************************
363 * HlinkParseDisplayName (HLINK.@)
365 HRESULT WINAPI HlinkParseDisplayName(LPBC pibc, LPCWSTR pwzDisplayName, BOOL fNoForceAbs,
366 ULONG *pcchEaten, IMoniker **ppimk)
368 HRESULT hres;
370 TRACE("(%p %s %x %p %p)\n", pibc, debugstr_w(pwzDisplayName), fNoForceAbs, pcchEaten, ppimk);
372 if(fNoForceAbs)
373 FIXME("Unsupported fNoForceAbs\n");
375 hres = MkParseDisplayNameEx(pibc, pwzDisplayName, pcchEaten, ppimk);
376 if(SUCCEEDED(hres))
377 return hres;
379 hres = MkParseDisplayName(pibc, pwzDisplayName, pcchEaten, ppimk);
380 if(SUCCEEDED(hres))
381 return hres;
383 hres = CreateFileMoniker(pwzDisplayName, ppimk);
384 if(SUCCEEDED(hres))
385 *pcchEaten = strlenW(pwzDisplayName);
387 return hres;
390 /***********************************************************************
391 * HlinkResolveMonikerForData (HLINK.@)
393 HRESULT WINAPI HlinkResolveMonikerForData(LPMONIKER pimkReference, DWORD reserved, LPBC pibc,
394 ULONG cFmtetc, FORMATETC *rgFmtetc, IBindStatusCallback *pibsc, LPMONIKER pimkBase)
396 LPOLESTR name = NULL;
397 IBindCtx *bctx;
398 DWORD mksys = 0;
399 void *obj = NULL;
400 HRESULT hres;
402 TRACE("(%p %x %p %d %p %p %p)\n", pimkReference, reserved, pibc, cFmtetc, rgFmtetc, pibsc, pimkBase);
404 if(cFmtetc || rgFmtetc || pimkBase)
405 FIXME("Unsupported args\n");
407 hres = RegisterBindStatusCallback(pibc, pibsc, NULL /* FIXME */, 0);
408 if(FAILED(hres))
409 return hres;
411 hres = IMoniker_IsSystemMoniker(pimkReference, &mksys);
412 if(SUCCEEDED(hres) && mksys != MKSYS_URLMONIKER)
413 WARN("sysmk = %x\n", mksys);
415 /* FIXME: What is it for? */
416 CreateBindCtx(0, &bctx);
417 hres = IMoniker_GetDisplayName(pimkReference, bctx, NULL, &name);
418 IBindCtx_Release(bctx);
419 if(SUCCEEDED(hres)) {
420 TRACE("got display name %s\n", debugstr_w(name));
421 CoTaskMemFree(name);
424 return IMoniker_BindToStorage(pimkReference, pibc, NULL, &IID_IUnknown, &obj);
427 static HRESULT WINAPI HLinkCF_fnQueryInterface ( LPCLASSFACTORY iface,
428 REFIID riid, LPVOID *ppvObj)
430 CFImpl *This = (CFImpl *)iface;
432 TRACE("(%p)->(%s)\n",This,debugstr_guid(riid));
434 *ppvObj = NULL;
436 if (IsEqualIID(riid, &IID_IUnknown) ||
437 IsEqualIID(riid, &IID_IClassFactory))
439 *ppvObj = This;
440 return S_OK;
443 TRACE("-- E_NOINTERFACE\n");
444 return E_NOINTERFACE;
447 static ULONG WINAPI HLinkCF_fnAddRef (LPCLASSFACTORY iface)
449 return 2;
452 static ULONG WINAPI HLinkCF_fnRelease(LPCLASSFACTORY iface)
454 return 1;
457 static HRESULT WINAPI HLinkCF_fnCreateInstance( LPCLASSFACTORY iface,
458 LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject)
460 CFImpl *This = (CFImpl *)iface;
462 TRACE("%p->(%p,%s,%p)\n", This, pUnkOuter, debugstr_guid(riid), ppvObject);
464 *ppvObject = NULL;
466 return This->lpfnCI(pUnkOuter, riid, ppvObject);
469 static HRESULT WINAPI HLinkCF_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
471 FIXME("%p %d\n", iface, fLock);
472 return E_NOTIMPL;
475 static const IClassFactoryVtbl hlcfvt =
477 HLinkCF_fnQueryInterface,
478 HLinkCF_fnAddRef,
479 HLinkCF_fnRelease,
480 HLinkCF_fnCreateInstance,
481 HLinkCF_fnLockServer
484 static CFImpl HLink_cf = { &hlcfvt, HLink_Constructor };
485 static CFImpl HLinkBrowseContext_cf = { &hlcfvt, HLinkBrowseContext_Constructor };
487 /***********************************************************************
488 * DllGetClassObject (HLINK.@)
490 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
492 IClassFactory *pcf = NULL;
494 TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv);
496 if (!ppv)
497 return E_INVALIDARG;
498 *ppv = NULL;
500 if (IsEqualIID(rclsid, &CLSID_StdHlink))
501 pcf = (IClassFactory*) &HLink_cf;
502 else if (IsEqualIID(rclsid, &CLSID_StdHlinkBrowseContext))
503 pcf = (IClassFactory*) &HLinkBrowseContext_cf;
504 else
505 return CLASS_E_CLASSNOTAVAILABLE;
507 return IClassFactory_QueryInterface(pcf, iid, ppv);
510 static HRESULT register_clsid(LPCGUID guid)
512 static const WCHAR clsid[] =
513 {'C','L','S','I','D','\\',0};
514 static const WCHAR ips[] =
515 {'\\','I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
516 static const WCHAR hlink[] =
517 {'h','l','i','n','k','.','d','l','l',0};
518 static const WCHAR threading_model[] =
519 {'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
520 static const WCHAR apartment[] =
521 {'A','p','a','r','t','m','e','n','t',0};
522 WCHAR path[80];
523 HKEY key = NULL;
524 LONG r;
526 lstrcpyW(path, clsid);
527 StringFromGUID2(guid, &path[6], 80);
528 lstrcatW(path, ips);
529 r = RegCreateKeyW(HKEY_CLASSES_ROOT, path, &key);
530 if (r != ERROR_SUCCESS)
531 return E_FAIL;
533 RegSetValueExW(key, NULL, 0, REG_SZ, (const BYTE *)hlink, sizeof hlink);
534 RegSetValueExW(key, threading_model, 0, REG_SZ, (const BYTE *)apartment, sizeof apartment);
535 RegCloseKey(key);
537 return S_OK;
540 /***********************************************************************
541 * DllRegisterServer (HLINK.@)
543 HRESULT WINAPI DllRegisterServer(void)
545 HRESULT r;
547 r = register_clsid(&CLSID_StdHlink);
548 if (SUCCEEDED(r))
549 r = register_clsid(&CLSID_StdHlinkBrowseContext);
551 return S_OK;