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
33 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(hlink);
39 static const IHlinkVtbl hlvt;
40 static const IPersistStreamVtbl psvt;
41 static const IDataObjectVtbl dovt;
45 const IHlinkVtbl *lpVtbl;
48 const IPersistStreamVtbl *lpPSVtbl;
49 const IDataObjectVtbl *lpDOVtbl;
54 LPWSTR TargetFrameName;
61 static inline HlinkImpl* HlinkImpl_from_IPersistStream( IPersistStream* iface)
63 return (HlinkImpl*) ((CHAR*)iface - FIELD_OFFSET(HlinkImpl, lpPSVtbl));
66 static inline HlinkImpl* HlinkImpl_from_IDataObject( IDataObject* iface)
68 return (HlinkImpl*) ((CHAR*)iface - FIELD_OFFSET(HlinkImpl, lpDOVtbl));
71 static inline void __GetMoniker(HlinkImpl* This, IMoniker** moniker)
76 *moniker = This->Moniker;
78 IMoniker_AddRef(*moniker);
82 IHlinkSite_GetMoniker(This->Site, This->SiteData,
83 OLEGETMONIKER_FORCEASSIGN, OLEWHICHMK_CONTAINER,
88 HRESULT WINAPI HLink_Constructor(IUnknown *pUnkOuter, REFIID riid,
93 TRACE("unkOut=%p riid=%s\n", pUnkOuter, debugstr_guid(riid));
97 return CLASS_E_NOAGGREGATION;
99 hl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HlinkImpl));
101 return E_OUTOFMEMORY;
105 hl->lpPSVtbl = &psvt;
106 hl->lpDOVtbl = &dovt;
112 static HRESULT WINAPI IHlink_fnQueryInterface(IHlink* iface, REFIID riid,
115 HlinkImpl *This = (HlinkImpl*)iface;
117 TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppvObj);
121 if (IsEqualIID(riid, &IID_IUnknown) || (IsEqualIID(riid, &IID_IHlink)))
123 else if (IsEqualIID(riid, &IID_IPersistStream))
124 *ppvObj = (LPVOID*)&(This->lpPSVtbl);
125 else if (IsEqualIID(riid, &IID_IDataObject))
126 *ppvObj = (LPVOID*)&(This->lpDOVtbl);
130 IUnknown_AddRef((IUnknown*)(*ppvObj));
133 return E_NOINTERFACE;
136 static ULONG WINAPI IHlink_fnAddRef (IHlink* iface)
138 HlinkImpl *This = (HlinkImpl*)iface;
139 ULONG refCount = InterlockedIncrement(&This->ref);
141 TRACE("(%p)->(count=%lu)\n", This, refCount - 1);
146 static ULONG WINAPI IHlink_fnRelease (IHlink* iface)
148 HlinkImpl *This = (HlinkImpl*)iface;
149 ULONG refCount = InterlockedDecrement(&This->ref);
151 TRACE("(%p)->(count=%lu)\n", This, refCount + 1);
155 TRACE("-- destroying IHlink (%p)\n", This);
156 HeapFree(GetProcessHeap(), 0, This->FriendlyName);
157 HeapFree(GetProcessHeap(), 0, This->Target);
158 HeapFree(GetProcessHeap(), 0, This->TargetFrameName);
159 HeapFree(GetProcessHeap(), 0, This->Location);
161 IMoniker_Release(This->Moniker);
163 IHlinkSite_Release(This->Site);
164 HeapFree(GetProcessHeap(), 0, This);
168 static HRESULT WINAPI IHlink_fnSetHlinkSite( IHlink* iface,
169 IHlinkSite* pihlSite, DWORD dwSiteData)
171 HlinkImpl *This = (HlinkImpl*)iface;
173 TRACE("(%p)->(%p %li)\n", This, pihlSite, dwSiteData);
176 IHlinkSite_Release(This->Site);
178 This->Site = pihlSite;
180 IHlinkSite_AddRef(This->Site);
182 This->SiteData = dwSiteData;
187 static HRESULT WINAPI IHlink_fnGetHlinkSite( IHlink* iface,
188 IHlinkSite** ppihlSite, DWORD *pdwSiteData)
190 HlinkImpl *This = (HlinkImpl*)iface;
192 TRACE("(%p)->(%p %p)\n", This, ppihlSite, pdwSiteData);
194 *ppihlSite = This->Site;
195 *pdwSiteData = This->SiteData;
198 IHlinkSite_AddRef(This->Site);
203 static HRESULT WINAPI IHlink_fnSetMonikerReference( IHlink* iface,
204 DWORD rfHLSETF, IMoniker *pmkTarget, LPCWSTR pwzLocation)
206 HlinkImpl *This = (HlinkImpl*)iface;
208 FIXME("(%p)->(%li %p %s)\n", This, rfHLSETF, pmkTarget,
209 debugstr_w(pwzLocation));
212 IMoniker_Release(This->Moniker);
214 This->Moniker = pmkTarget;
216 IMoniker_AddRef(This->Moniker);
218 HeapFree(GetProcessHeap(), 0, This->Location);
219 This->Location = NULL;
222 This->Location = HeapAlloc(GetProcessHeap(), 0,
223 (lstrlenW(pwzLocation)+1)*sizeof(WCHAR));
224 lstrcpyW(This->Location, pwzLocation);
230 static HRESULT WINAPI IHlink_fnSetStringReference(IHlink* iface,
231 DWORD grfHLSETF, LPCWSTR pwzTarget, LPCWSTR pwzLocation)
233 HlinkImpl *This = (HlinkImpl*)iface;
235 TRACE("(%p)->(%li %s %s)\n", This, grfHLSETF, debugstr_w(pwzTarget),
236 debugstr_w(pwzLocation));
238 if (grfHLSETF & HLINKSETF_TARGET)
240 HeapFree(GetProcessHeap(), 0, This->Target);
244 This->Target = HeapAlloc(GetProcessHeap(), 0,
245 (lstrlenW(pwzTarget)+1)*sizeof(WCHAR));
246 lstrcpyW(This->Target, pwzTarget);
249 if (grfHLSETF & HLINKSETF_LOCATION)
251 HeapFree(GetProcessHeap(), 0, This->Location);
252 This->Location = NULL;
256 HeapAlloc(GetProcessHeap(), 0, (lstrlenW(pwzLocation)+1)
258 lstrcpyW(This->Location, pwzLocation);
265 static HRESULT WINAPI IHlink_fnGetMonikerReference(IHlink* iface,
266 DWORD dwWhichRef, IMoniker **ppimkTarget, LPWSTR *ppwzLocation)
268 HlinkImpl *This = (HlinkImpl*)iface;
270 TRACE("(%p) -> (%li %p %p)\n", This, dwWhichRef, ppimkTarget,
274 __GetMoniker(This, ppimkTarget);
277 IHlink_GetStringReference(iface, dwWhichRef, NULL, ppwzLocation);
282 static HRESULT WINAPI IHlink_fnGetStringReference (IHlink* iface,
283 DWORD dwWhichRef, LPWSTR *ppwzTarget, LPWSTR *ppwzLocation)
285 HlinkImpl *This = (HlinkImpl*)iface;
287 FIXME("(%p) -> (%li %p %p)\n", This, dwWhichRef, ppwzTarget, ppwzLocation);
293 *ppwzTarget = HeapAlloc(GetProcessHeap(), 0,
294 (lstrlenW(This->Target)+1) * sizeof(WCHAR));
295 lstrcpyW(*ppwzTarget, This->Target);
300 __GetMoniker(This, &mon);
305 CreateBindCtx( 0, &pbc);
306 IMoniker_GetDisplayName(mon, pbc, NULL, &This->Target);
307 IBindCtx_Release(pbc);
308 *ppwzTarget = HeapAlloc(GetProcessHeap(), 0,
309 (lstrlenW(This->Target)+1) * sizeof(WCHAR));
310 lstrcpyW(*ppwzTarget, This->Target);
311 IMoniker_Release(mon);
315 FIXME("Unhandled case, no set Target and no moniker\n");
324 *ppwzLocation = HeapAlloc(GetProcessHeap(), 0,
325 (lstrlenW(This->Location)+1) * sizeof(WCHAR));
326 lstrcpyW(*ppwzLocation, This->Location);
330 FIXME("Unhandled case, no explicitly set Location\n");
331 *ppwzLocation = NULL;
335 TRACE("(Target: %s Location: %s)\n",
336 (ppwzTarget)?debugstr_w(*ppwzTarget):"<NULL>",
337 (ppwzLocation)?debugstr_w(*ppwzLocation):"<NULL>");
342 static HRESULT WINAPI IHlink_fnSetFriendlyName (IHlink *iface,
343 LPCWSTR pwzFriendlyName)
345 HlinkImpl *This = (HlinkImpl*)iface;
347 TRACE("(%p) -> (%s)\n", This, debugstr_w(pwzFriendlyName));
349 HeapFree(GetProcessHeap(), 0, This->FriendlyName);
350 This->FriendlyName = HeapAlloc(GetProcessHeap(), 0,
351 (lstrlenW(pwzFriendlyName)+1) * sizeof(WCHAR));
352 lstrcpyW(This->FriendlyName, pwzFriendlyName);
357 static HRESULT WINAPI IHlink_fnGetFriendlyName (IHlink* iface,
358 DWORD grfHLFNAMEF, LPWSTR* ppwzFriendlyName)
360 HlinkImpl *This = (HlinkImpl*)iface;
362 TRACE("(%p) -> (%li %p)\n", This, grfHLFNAMEF, ppwzFriendlyName);
364 /* FIXME: Only using explicitly set and cached friendly names */
366 if (This->FriendlyName)
368 *ppwzFriendlyName = HeapAlloc(GetProcessHeap(), 0,
369 (lstrlenW(This->FriendlyName)+1) * sizeof(WCHAR));
370 lstrcpyW(*ppwzFriendlyName, This->FriendlyName);
375 __GetMoniker(This, &moniker);
379 CreateBindCtx(0, &bcxt);
381 IMoniker_GetDisplayName(moniker, bcxt, NULL, ppwzFriendlyName);
382 IBindCtx_Release(bcxt);
383 IMoniker_Release(moniker);
386 *ppwzFriendlyName = NULL;
392 static HRESULT WINAPI IHlink_fnSetTargetFrameName(IHlink* iface,
393 LPCWSTR pwzTargetFramename)
395 HlinkImpl *This = (HlinkImpl*)iface;
396 TRACE("(%p)->(%s)\n", This, debugstr_w(pwzTargetFramename));
398 HeapFree(GetProcessHeap(), 0, This->TargetFrameName);
399 This->TargetFrameName = HeapAlloc(GetProcessHeap(), 0,
400 (lstrlenW(pwzTargetFramename)+1) * sizeof(WCHAR));
401 lstrcpyW(This->TargetFrameName, pwzTargetFramename);
406 static HRESULT WINAPI IHlink_fnGetTargetFrameName(IHlink* iface,
407 LPWSTR *ppwzTargetFrameName)
409 HlinkImpl *This = (HlinkImpl*)iface;
411 TRACE("(%p)->(%p)\n", This, ppwzTargetFrameName);
412 if (This->TargetFrameName)
414 *ppwzTargetFrameName = HeapAlloc(GetProcessHeap(), 0,
415 (lstrlenW(This->TargetFrameName)+1) * sizeof(WCHAR));
416 lstrcpyW(*ppwzTargetFrameName, This->TargetFrameName);
419 *ppwzTargetFrameName = NULL;
424 static HRESULT WINAPI IHlink_fnGetMiscStatus(IHlink* iface, DWORD* pdwStatus)
430 static HRESULT WINAPI IHlink_fnNavigate(IHlink* iface, DWORD grfHLNF, LPBC pbc,
431 IBindStatusCallback *pbsc, IHlinkBrowseContext *phbc)
433 HlinkImpl *This = (HlinkImpl*)iface;
434 IMoniker *mon = NULL;
436 FIXME("Semi-Stub:(%p)->(%li %p %p %p)\n", This, grfHLNF, pbc, pbsc, phbc);
439 IHlinkSite_ReadyToNavigate(This->Site, This->SiteData, 0);
441 __GetMoniker(This, &mon);
442 TRACE("Moniker %p\n", mon);
447 IHlinkTarget *target;
450 CreateBindCtx(0, &bcxt);
452 RegisterBindStatusCallback(bcxt, pbsc, NULL, 0);
454 r = IMoniker_BindToObject(mon, bcxt, NULL, &IID_IHlinkTarget,
456 TRACE("IHlinkTarget returned 0x%lx\n", r);
459 IHlinkTarget_SetBrowseContext(target, phbc);
460 IHlinkTarget_Navigate(target, grfHLNF, This->Location);
463 RevokeBindStatusCallback(bcxt, pbsc);
465 IBindCtx_Release(bcxt);
466 IHlinkTarget_Release(target);
467 IMoniker_Release(mon);
471 IHlinkSite_OnNavigationComplete(This->Site, This->SiteData, 0, 0, NULL);
473 TRACE("Finished Navigation\n");
477 static HRESULT WINAPI IHlink_fnSetAdditonalParams(IHlink* iface,
478 LPCWSTR pwzAdditionalParams)
484 static HRESULT WINAPI IHlink_fnGetAdditionalParams(IHlink* iface,
485 LPWSTR* ppwzAdditionalParams)
491 static const IHlinkVtbl hlvt =
493 IHlink_fnQueryInterface,
496 IHlink_fnSetHlinkSite,
497 IHlink_fnGetHlinkSite,
498 IHlink_fnSetMonikerReference,
499 IHlink_fnGetMonikerReference,
500 IHlink_fnSetStringReference,
501 IHlink_fnGetStringReference,
502 IHlink_fnSetFriendlyName,
503 IHlink_fnGetFriendlyName,
504 IHlink_fnSetTargetFrameName,
505 IHlink_fnGetTargetFrameName,
506 IHlink_fnGetMiscStatus,
508 IHlink_fnSetAdditonalParams,
509 IHlink_fnGetAdditionalParams
512 static HRESULT WINAPI IDataObject_fnQueryInterface(IDataObject* iface,
513 REFIID riid, LPVOID *ppvObj)
515 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
517 return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
520 static ULONG WINAPI IDataObject_fnAddRef (IDataObject* iface)
522 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
524 return IHlink_AddRef((IHlink*)This);
527 static ULONG WINAPI IDataObject_fnRelease (IDataObject* iface)
529 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
531 return IHlink_Release((IHlink*)This);
534 static HRESULT WINAPI IDataObject_fnGetData(IDataObject* iface,
535 FORMATETC* pformatetcIn, STGMEDIUM* pmedium)
541 static HRESULT WINAPI IDataObject_fnGetDataHere(IDataObject* iface,
542 FORMATETC* pformatetc, STGMEDIUM* pmedium)
548 static HRESULT WINAPI IDataObject_fnQueryGetData(IDataObject* iface,
549 FORMATETC* pformatetc)
555 static HRESULT WINAPI IDataObject_fnGetConicalFormatEtc(IDataObject* iface,
556 FORMATETC* pformatetcIn, FORMATETC* pformatetcOut)
562 static HRESULT WINAPI IDataObject_fnSetData(IDataObject* iface,
563 FORMATETC* pformatetc, STGMEDIUM* pmedium, BOOL fRelease)
569 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(IDataObject* iface,
570 DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc)
576 static HRESULT WINAPI IDataObject_fnDAdvise(IDataObject* iface,
577 FORMATETC* pformatetc, DWORD advf, IAdviseSink* pAdvSink,
578 DWORD* pdwConnection)
584 static HRESULT WINAPI IDataObject_fnDUnadvise(IDataObject* iface,
591 static HRESULT WINAPI IDataObject_fnEnumDAdvise(IDataObject* iface,
592 IEnumSTATDATA** ppenumAdvise)
598 static const IDataObjectVtbl dovt =
600 IDataObject_fnQueryInterface,
601 IDataObject_fnAddRef,
602 IDataObject_fnRelease,
603 IDataObject_fnGetData,
604 IDataObject_fnGetDataHere,
605 IDataObject_fnQueryGetData,
606 IDataObject_fnGetConicalFormatEtc,
607 IDataObject_fnSetData,
608 IDataObject_fnEnumFormatEtc,
609 IDataObject_fnDAdvise,
610 IDataObject_fnDUnadvise,
611 IDataObject_fnEnumDAdvise
614 static HRESULT WINAPI IPersistStream_fnQueryInterface(IPersistStream* iface,
615 REFIID riid, LPVOID *ppvObj)
617 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
618 TRACE("(%p)\n", This);
619 return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
622 static ULONG WINAPI IPersistStream_fnAddRef (IPersistStream* iface)
624 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
625 TRACE("(%p)\n", This);
626 return IHlink_AddRef((IHlink*)This);
629 static ULONG WINAPI IPersistStream_fnRelease (IPersistStream* iface)
631 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
632 TRACE("(%p)\n", This);
633 return IHlink_Release((IHlink*)This);
636 static HRESULT WINAPI IPersistStream_fnGetClassID(IPersistStream* iface,
639 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
640 TRACE("(%p)\n", This);
641 memcpy(pClassID, &CLSID_StdHlink, sizeof(CLSID));
645 static HRESULT WINAPI IPersistStream_fnIsDirty(IPersistStream* iface)
651 static HRESULT WINAPI IPersistStream_fnLoad(IPersistStream* iface,
654 HRESULT r = E_NOTIMPL;
657 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
659 IStream_Read(pStm, &hdr, sizeof(hdr), &read);
660 /* FIXME: unknown header values */
662 r = OleLoadFromStream(pStm, &IID_IMoniker, (LPVOID*)&(This->Moniker));
663 TRACE("Load Result 0x%lx (%p)\n", r, This->Moniker);
668 static HRESULT WINAPI IPersistStream_fnSave(IPersistStream* iface,
669 IStream* pStm, BOOL fClearDirty)
672 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
676 FIXME("(%p) Moniker(%p)\n", This, This->Moniker);
678 __GetMoniker(This, &moniker);
681 IPersistStream* monstream;
682 /* FIXME: Unknown values in the header */
686 IStream_Write(pStm, &hdr, sizeof(hdr), NULL);
689 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
690 (LPVOID*)&monstream);
693 r = OleSaveToStream(monstream, pStm);
694 IPersistStream_Release(monstream);
696 IMoniker_Release(moniker);
698 TRACE("Save Result 0x%lx\n", r);
703 static HRESULT WINAPI IPersistStream_fnGetSizeMax(IPersistStream* iface,
704 ULARGE_INTEGER* pcbSize)
707 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
710 FIXME("(%p) Moniker(%p)\n", This, This->Moniker);
712 __GetMoniker(This, &moniker);
715 IPersistStream* monstream = NULL;
716 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
717 (LPVOID*)&monstream);
720 r = IPersistStream_GetSizeMax(monstream, pcbSize);
721 /* FIXME: Handle ULARGE_INTEGER correctly */
722 pcbSize->u.LowPart += sizeof(DWORD)*2;
723 IPersistStream_Release(monstream);
725 IMoniker_Release(moniker);
731 static const IPersistStreamVtbl psvt =
733 IPersistStream_fnQueryInterface,
734 IPersistStream_fnAddRef,
735 IPersistStream_fnRelease,
736 IPersistStream_fnGetClassID,
737 IPersistStream_fnIsDirty,
738 IPersistStream_fnLoad,
739 IPersistStream_fnSave,
740 IPersistStream_fnGetSizeMax,