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
,