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
34 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(hlink);
40 static const IHlinkVtbl hlvt;
41 static const IPersistStreamVtbl psvt;
42 static const IDataObjectVtbl dovt;
46 const IHlinkVtbl *lpVtbl;
49 const IPersistStreamVtbl *lpPSVtbl;
50 const IDataObjectVtbl *lpDOVtbl;
55 LPWSTR TargetFrameName;
62 static inline HlinkImpl* HlinkImpl_from_IPersistStream( IPersistStream* iface)
64 return (HlinkImpl*) ((CHAR*)iface - FIELD_OFFSET(HlinkImpl, lpPSVtbl));
67 static inline HlinkImpl* HlinkImpl_from_IDataObject( IDataObject* iface)
69 return (HlinkImpl*) ((CHAR*)iface - FIELD_OFFSET(HlinkImpl, lpDOVtbl));
72 static inline LPWSTR strdupW( LPCWSTR str )
79 len = (lstrlenW(str)+1) * sizeof (WCHAR);
80 r = HeapAlloc(GetProcessHeap(), 0, len);
86 static inline LPWSTR co_strdupW( LPCWSTR str )
93 len = (lstrlenW(str)+1) * sizeof (WCHAR);
94 r = CoTaskMemAlloc(len);
100 static inline void __GetMoniker(HlinkImpl* This, IMoniker** moniker)
105 *moniker = This->Moniker;
107 IMoniker_AddRef(*moniker);
111 IHlinkSite_GetMoniker(This->Site, This->SiteData,
112 OLEGETMONIKER_FORCEASSIGN, OLEWHICHMK_CONTAINER,
117 HRESULT WINAPI HLink_Constructor(IUnknown *pUnkOuter, REFIID riid,
122 TRACE("unkOut=%p riid=%s\n", pUnkOuter, debugstr_guid(riid));
126 return CLASS_E_NOAGGREGATION;
128 hl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HlinkImpl));
130 return E_OUTOFMEMORY;
134 hl->lpPSVtbl = &psvt;
135 hl->lpDOVtbl = &dovt;
141 static HRESULT WINAPI IHlink_fnQueryInterface(IHlink* iface, REFIID riid,
144 HlinkImpl *This = (HlinkImpl*)iface;
146 TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppvObj);
150 if (IsEqualIID(riid, &IID_IUnknown) || (IsEqualIID(riid, &IID_IHlink)))
152 else if (IsEqualIID(riid, &IID_IPersistStream))
153 *ppvObj = (LPVOID*)&(This->lpPSVtbl);
154 else if (IsEqualIID(riid, &IID_IDataObject))
155 *ppvObj = (LPVOID*)&(This->lpDOVtbl);
159 IUnknown_AddRef((IUnknown*)(*ppvObj));
162 return E_NOINTERFACE;
165 static ULONG WINAPI IHlink_fnAddRef (IHlink* iface)
167 HlinkImpl *This = (HlinkImpl*)iface;
168 ULONG refCount = InterlockedIncrement(&This->ref);
170 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
175 static ULONG WINAPI IHlink_fnRelease (IHlink* iface)
177 HlinkImpl *This = (HlinkImpl*)iface;
178 ULONG refCount = InterlockedDecrement(&This->ref);
180 TRACE("(%p)->(count=%u)\n", This, refCount + 1);
184 TRACE("-- destroying IHlink (%p)\n", This);
185 HeapFree(GetProcessHeap(), 0, This->FriendlyName);
186 HeapFree(GetProcessHeap(), 0, This->Target);
187 HeapFree(GetProcessHeap(), 0, This->TargetFrameName);
188 HeapFree(GetProcessHeap(), 0, This->Location);
190 IMoniker_Release(This->Moniker);
192 IHlinkSite_Release(This->Site);
193 HeapFree(GetProcessHeap(), 0, This);
197 static HRESULT WINAPI IHlink_fnSetHlinkSite( IHlink* iface,
198 IHlinkSite* pihlSite, DWORD dwSiteData)
200 HlinkImpl *This = (HlinkImpl*)iface;
202 TRACE("(%p)->(%p %i)\n", This, pihlSite, dwSiteData);
205 IHlinkSite_Release(This->Site);
207 This->Site = pihlSite;
209 IHlinkSite_AddRef(This->Site);
211 This->SiteData = dwSiteData;
216 static HRESULT WINAPI IHlink_fnGetHlinkSite( IHlink* iface,
217 IHlinkSite** ppihlSite, DWORD *pdwSiteData)
219 HlinkImpl *This = (HlinkImpl*)iface;
221 TRACE("(%p)->(%p %p)\n", This, ppihlSite, pdwSiteData);
223 *ppihlSite = This->Site;
224 *pdwSiteData = This->SiteData;
227 IHlinkSite_AddRef(This->Site);
232 static HRESULT WINAPI IHlink_fnSetMonikerReference( IHlink* iface,
233 DWORD rfHLSETF, IMoniker *pmkTarget, LPCWSTR pwzLocation)
235 HlinkImpl *This = (HlinkImpl*)iface;
237 FIXME("(%p)->(%i %p %s)\n", This, rfHLSETF, pmkTarget,
238 debugstr_w(pwzLocation));
241 IMoniker_Release(This->Moniker);
243 This->Moniker = pmkTarget;
245 IMoniker_AddRef(This->Moniker);
247 HeapFree(GetProcessHeap(), 0, This->Location);
248 This->Location = strdupW( pwzLocation );
253 static HRESULT WINAPI IHlink_fnSetStringReference(IHlink* iface,
254 DWORD grfHLSETF, LPCWSTR pwzTarget, LPCWSTR pwzLocation)
256 HlinkImpl *This = (HlinkImpl*)iface;
258 TRACE("(%p)->(%i %s %s)\n", This, grfHLSETF, debugstr_w(pwzTarget),
259 debugstr_w(pwzLocation));
261 if (grfHLSETF & HLINKSETF_TARGET)
263 HeapFree(GetProcessHeap(), 0, This->Target);
264 This->Target = strdupW( pwzTarget );
266 if (grfHLSETF & HLINKSETF_LOCATION)
268 HeapFree(GetProcessHeap(), 0, This->Location);
269 This->Location = strdupW( pwzLocation );
275 static HRESULT WINAPI IHlink_fnGetMonikerReference(IHlink* iface,
276 DWORD dwWhichRef, IMoniker **ppimkTarget, LPWSTR *ppwzLocation)
278 HlinkImpl *This = (HlinkImpl*)iface;
280 TRACE("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppimkTarget,
284 __GetMoniker(This, ppimkTarget);
287 IHlink_GetStringReference(iface, dwWhichRef, NULL, ppwzLocation);
292 static HRESULT WINAPI IHlink_fnGetStringReference (IHlink* iface,
293 DWORD dwWhichRef, LPWSTR *ppwzTarget, LPWSTR *ppwzLocation)
295 HlinkImpl *This = (HlinkImpl*)iface;
297 FIXME("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppwzTarget, ppwzLocation);
301 *ppwzTarget = co_strdupW( This->Target );
306 __GetMoniker(This, &mon);
311 CreateBindCtx( 0, &pbc);
312 IMoniker_GetDisplayName(mon, pbc, NULL, ppwzTarget);
313 IBindCtx_Release(pbc);
314 IMoniker_Release(mon);
317 FIXME("Unhandled case, no set Target and no moniker\n");
321 *ppwzLocation = co_strdupW( This->Location );
323 TRACE("(Target: %s Location: %s)\n",
324 (ppwzTarget)?debugstr_w(*ppwzTarget):"<NULL>",
325 (ppwzLocation)?debugstr_w(*ppwzLocation):"<NULL>");
330 static HRESULT WINAPI IHlink_fnSetFriendlyName (IHlink *iface,
331 LPCWSTR pwzFriendlyName)
333 HlinkImpl *This = (HlinkImpl*)iface;
335 TRACE("(%p) -> (%s)\n", This, debugstr_w(pwzFriendlyName));
337 HeapFree(GetProcessHeap(), 0, This->FriendlyName);
338 This->FriendlyName = strdupW( pwzFriendlyName );
343 static HRESULT WINAPI IHlink_fnGetFriendlyName (IHlink* iface,
344 DWORD grfHLFNAMEF, LPWSTR* ppwzFriendlyName)
346 HlinkImpl *This = (HlinkImpl*)iface;
348 TRACE("(%p) -> (%i %p)\n", This, grfHLFNAMEF, ppwzFriendlyName);
350 /* FIXME: Only using explicitly set and cached friendly names */
352 if (This->FriendlyName)
353 *ppwzFriendlyName = co_strdupW( This->FriendlyName );
357 __GetMoniker(This, &moniker);
361 CreateBindCtx(0, &bcxt);
363 IMoniker_GetDisplayName(moniker, bcxt, NULL, ppwzFriendlyName);
364 IBindCtx_Release(bcxt);
365 IMoniker_Release(moniker);
368 *ppwzFriendlyName = NULL;
374 static HRESULT WINAPI IHlink_fnSetTargetFrameName(IHlink* iface,
375 LPCWSTR pwzTargetFramename)
377 HlinkImpl *This = (HlinkImpl*)iface;
378 TRACE("(%p)->(%s)\n", This, debugstr_w(pwzTargetFramename));
380 HeapFree(GetProcessHeap(), 0, This->TargetFrameName);
381 This->TargetFrameName = strdupW( pwzTargetFramename );
386 static HRESULT WINAPI IHlink_fnGetTargetFrameName(IHlink* iface,
387 LPWSTR *ppwzTargetFrameName)
389 HlinkImpl *This = (HlinkImpl*)iface;
391 TRACE("(%p)->(%p)\n", This, ppwzTargetFrameName);
392 *ppwzTargetFrameName = co_strdupW( This->TargetFrameName );
397 static HRESULT WINAPI IHlink_fnGetMiscStatus(IHlink* iface, DWORD* pdwStatus)
403 static HRESULT WINAPI IHlink_fnNavigate(IHlink* iface, DWORD grfHLNF, LPBC pbc,
404 IBindStatusCallback *pbsc, IHlinkBrowseContext *phbc)
406 HlinkImpl *This = (HlinkImpl*)iface;
407 IMoniker *mon = NULL;
409 FIXME("Semi-Stub:(%p)->(%i %p %p %p)\n", This, grfHLNF, pbc, pbsc, phbc);
412 IHlinkSite_ReadyToNavigate(This->Site, This->SiteData, 0);
414 __GetMoniker(This, &mon);
415 TRACE("Moniker %p\n", mon);
420 IHlinkTarget *target = NULL;
423 CreateBindCtx(0, &bcxt);
425 RegisterBindStatusCallback(bcxt, pbsc, NULL, 0);
427 r = IMoniker_BindToObject(mon, bcxt, NULL, &IID_IHlinkTarget,
429 TRACE("IHlinkTarget returned 0x%x\n", r);
432 IHlinkTarget_SetBrowseContext(target, phbc);
433 IHlinkTarget_Navigate(target, grfHLNF, This->Location);
434 IHlinkTarget_Release(target);
438 static const WCHAR szOpen[] = {'o','p','e','n',0};
439 LPWSTR target = NULL;
441 r = IHlink_GetStringReference(iface, HLINKGETREF_DEFAULT, &target, NULL);
442 if (SUCCEEDED(r) && target)
444 ShellExecuteW(NULL, szOpen, target, NULL, NULL, SW_SHOW);
445 CoTaskMemFree(target);
449 RevokeBindStatusCallback(bcxt, pbsc);
451 IBindCtx_Release(bcxt);
452 IMoniker_Release(mon);
456 IHlinkSite_OnNavigationComplete(This->Site, This->SiteData, 0, 0, NULL);
458 TRACE("Finished Navigation\n");
462 static HRESULT WINAPI IHlink_fnSetAdditonalParams(IHlink* iface,
463 LPCWSTR pwzAdditionalParams)
469 static HRESULT WINAPI IHlink_fnGetAdditionalParams(IHlink* iface,
470 LPWSTR* ppwzAdditionalParams)
476 static const IHlinkVtbl hlvt =
478 IHlink_fnQueryInterface,
481 IHlink_fnSetHlinkSite,
482 IHlink_fnGetHlinkSite,
483 IHlink_fnSetMonikerReference,
484 IHlink_fnGetMonikerReference,
485 IHlink_fnSetStringReference,
486 IHlink_fnGetStringReference,
487 IHlink_fnSetFriendlyName,
488 IHlink_fnGetFriendlyName,
489 IHlink_fnSetTargetFrameName,
490 IHlink_fnGetTargetFrameName,
491 IHlink_fnGetMiscStatus,
493 IHlink_fnSetAdditonalParams,
494 IHlink_fnGetAdditionalParams
497 static HRESULT WINAPI IDataObject_fnQueryInterface(IDataObject* iface,
498 REFIID riid, LPVOID *ppvObj)
500 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
502 return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
505 static ULONG WINAPI IDataObject_fnAddRef (IDataObject* iface)
507 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
509 return IHlink_AddRef((IHlink*)This);
512 static ULONG WINAPI IDataObject_fnRelease (IDataObject* iface)
514 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
516 return IHlink_Release((IHlink*)This);
519 static HRESULT WINAPI IDataObject_fnGetData(IDataObject* iface,
520 FORMATETC* pformatetcIn, STGMEDIUM* pmedium)
526 static HRESULT WINAPI IDataObject_fnGetDataHere(IDataObject* iface,
527 FORMATETC* pformatetc, STGMEDIUM* pmedium)
533 static HRESULT WINAPI IDataObject_fnQueryGetData(IDataObject* iface,
534 FORMATETC* pformatetc)
540 static HRESULT WINAPI IDataObject_fnGetConicalFormatEtc(IDataObject* iface,
541 FORMATETC* pformatetcIn, FORMATETC* pformatetcOut)
547 static HRESULT WINAPI IDataObject_fnSetData(IDataObject* iface,
548 FORMATETC* pformatetc, STGMEDIUM* pmedium, BOOL fRelease)
554 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(IDataObject* iface,
555 DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc)
561 static HRESULT WINAPI IDataObject_fnDAdvise(IDataObject* iface,
562 FORMATETC* pformatetc, DWORD advf, IAdviseSink* pAdvSink,
563 DWORD* pdwConnection)
569 static HRESULT WINAPI IDataObject_fnDUnadvise(IDataObject* iface,
576 static HRESULT WINAPI IDataObject_fnEnumDAdvise(IDataObject* iface,
577 IEnumSTATDATA** ppenumAdvise)
583 static const IDataObjectVtbl dovt =
585 IDataObject_fnQueryInterface,
586 IDataObject_fnAddRef,
587 IDataObject_fnRelease,
588 IDataObject_fnGetData,
589 IDataObject_fnGetDataHere,
590 IDataObject_fnQueryGetData,
591 IDataObject_fnGetConicalFormatEtc,
592 IDataObject_fnSetData,
593 IDataObject_fnEnumFormatEtc,
594 IDataObject_fnDAdvise,
595 IDataObject_fnDUnadvise,
596 IDataObject_fnEnumDAdvise
599 static HRESULT WINAPI IPersistStream_fnQueryInterface(IPersistStream* iface,
600 REFIID riid, LPVOID *ppvObj)
602 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
603 TRACE("(%p)\n", This);
604 return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
607 static ULONG WINAPI IPersistStream_fnAddRef (IPersistStream* iface)
609 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
610 TRACE("(%p)\n", This);
611 return IHlink_AddRef((IHlink*)This);
614 static ULONG WINAPI IPersistStream_fnRelease (IPersistStream* iface)
616 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
617 TRACE("(%p)\n", This);
618 return IHlink_Release((IHlink*)This);
621 static HRESULT WINAPI IPersistStream_fnGetClassID(IPersistStream* iface,
624 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
625 TRACE("(%p)\n", This);
626 memcpy(pClassID, &CLSID_StdHlink, sizeof(CLSID));
630 static HRESULT WINAPI IPersistStream_fnIsDirty(IPersistStream* iface)
636 static HRESULT WINAPI IPersistStream_fnLoad(IPersistStream* iface,
639 HRESULT r = E_NOTIMPL;
642 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
644 IStream_Read(pStm, &hdr, sizeof(hdr), &read);
645 /* FIXME: unknown header values */
647 r = OleLoadFromStream(pStm, &IID_IMoniker, (LPVOID*)&(This->Moniker));
648 TRACE("Load Result 0x%x (%p)\n", r, This->Moniker);
653 static HRESULT WINAPI IPersistStream_fnSave(IPersistStream* iface,
654 IStream* pStm, BOOL fClearDirty)
657 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
661 FIXME("(%p) Moniker(%p)\n", This, This->Moniker);
663 __GetMoniker(This, &moniker);
666 IPersistStream* monstream;
667 /* FIXME: Unknown values in the header */
671 IStream_Write(pStm, &hdr, sizeof(hdr), NULL);
674 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
675 (LPVOID*)&monstream);
678 r = OleSaveToStream(monstream, pStm);
679 IPersistStream_Release(monstream);
681 IMoniker_Release(moniker);
683 TRACE("Save Result 0x%x\n", r);
688 static HRESULT WINAPI IPersistStream_fnGetSizeMax(IPersistStream* iface,
689 ULARGE_INTEGER* pcbSize)
692 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
695 FIXME("(%p) Moniker(%p)\n", This, This->Moniker);
697 __GetMoniker(This, &moniker);
700 IPersistStream* monstream = NULL;
701 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
702 (LPVOID*)&monstream);
705 r = IPersistStream_GetSizeMax(monstream, pcbSize);
706 /* FIXME: Handle ULARGE_INTEGER correctly */
707 pcbSize->u.LowPart += sizeof(DWORD)*2;
708 IPersistStream_Release(monstream);
710 IMoniker_Release(moniker);
716 static const IPersistStreamVtbl psvt =
718 IPersistStream_fnQueryInterface,
719 IPersistStream_fnAddRef,
720 IPersistStream_fnRelease,
721 IPersistStream_fnGetClassID,
722 IPersistStream_fnIsDirty,
723 IPersistStream_fnLoad,
724 IPersistStream_fnSave,
725 IPersistStream_fnGetSizeMax,