wine.inf: We should not override existing associations.
[wine/hacks.git] / dlls / hlink / link.c
blob4d3b074a7f062f0037c570d64738b0f018009e07
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 <stdarg.h>
23 #define COBJMACROS
25 #include "winerror.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "ole2.h"
30 #include "unknwn.h"
31 #include "objidl.h"
32 #include "shellapi.h"
34 #include "wine/debug.h"
35 #include "hlink.h"
36 #include "hlguids.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(hlink);
40 static const IHlinkVtbl hlvt;
41 static const IPersistStreamVtbl psvt;
42 static const IDataObjectVtbl dovt;
44 typedef struct
46 const IHlinkVtbl *lpVtbl;
47 LONG ref;
49 const IPersistStreamVtbl *lpPSVtbl;
50 const IDataObjectVtbl *lpDOVtbl;
52 LPWSTR FriendlyName;
53 LPWSTR Location;
54 LPWSTR Target;
55 LPWSTR TargetFrameName;
56 IMoniker *Moniker;
57 IHlinkSite *Site;
58 DWORD SiteData;
59 } HlinkImpl;
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 )
74 LPWSTR r;
75 UINT len;
77 if (!str)
78 return NULL;
79 len = (lstrlenW(str)+1) * sizeof (WCHAR);
80 r = HeapAlloc(GetProcessHeap(), 0, len);
81 if (r)
82 memcpy(r, str, len);
83 return r;
86 static inline LPWSTR co_strdupW( LPCWSTR str )
88 LPWSTR r;
89 UINT len;
91 if (!str)
92 return NULL;
93 len = (lstrlenW(str)+1) * sizeof (WCHAR);
94 r = CoTaskMemAlloc(len);
95 if (r)
96 memcpy(r, str, len);
97 return r;
100 static inline void __GetMoniker(HlinkImpl* This, IMoniker** moniker)
102 *moniker = NULL;
103 if (This->Moniker)
105 *moniker = This->Moniker;
106 if (*moniker)
107 IMoniker_AddRef(*moniker);
109 else if (This->Site)
111 IHlinkSite_GetMoniker(This->Site, This->SiteData,
112 OLEGETMONIKER_FORCEASSIGN, OLEWHICHMK_CONTAINER,
113 (LPVOID)moniker);
117 HRESULT WINAPI HLink_Constructor(IUnknown *pUnkOuter, REFIID riid,
118 LPVOID *ppv)
120 HlinkImpl * hl;
122 TRACE("unkOut=%p riid=%s\n", pUnkOuter, debugstr_guid(riid));
123 *ppv = NULL;
125 if (pUnkOuter)
126 return CLASS_E_NOAGGREGATION;
128 hl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HlinkImpl));
129 if (!hl)
130 return E_OUTOFMEMORY;
132 hl->ref = 1;
133 hl->lpVtbl = &hlvt;
134 hl->lpPSVtbl = &psvt;
135 hl->lpDOVtbl = &dovt;
137 *ppv = hl;
138 return S_OK;
141 static HRESULT WINAPI IHlink_fnQueryInterface(IHlink* iface, REFIID riid,
142 LPVOID *ppvObj)
144 HlinkImpl *This = (HlinkImpl*)iface;
146 TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppvObj);
148 *ppvObj = NULL;
150 if (IsEqualIID(riid, &IID_IUnknown) || (IsEqualIID(riid, &IID_IHlink)))
151 *ppvObj = This;
152 else if (IsEqualIID(riid, &IID_IPersistStream))
153 *ppvObj = (LPVOID*)&(This->lpPSVtbl);
154 else if (IsEqualIID(riid, &IID_IDataObject))
155 *ppvObj = (LPVOID*)&(This->lpDOVtbl);
157 if (*ppvObj)
159 IUnknown_AddRef((IUnknown*)(*ppvObj));
160 return S_OK;
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=%lu)\n", This, refCount - 1);
172 return refCount;
175 static ULONG WINAPI IHlink_fnRelease (IHlink* iface)
177 HlinkImpl *This = (HlinkImpl*)iface;
178 ULONG refCount = InterlockedDecrement(&This->ref);
180 TRACE("(%p)->(count=%lu)\n", This, refCount + 1);
181 if (refCount)
182 return refCount;
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);
189 if (This->Moniker)
190 IMoniker_Release(This->Moniker);
191 if (This->Site)
192 IHlinkSite_Release(This->Site);
193 HeapFree(GetProcessHeap(), 0, This);
194 return 0;
197 static HRESULT WINAPI IHlink_fnSetHlinkSite( IHlink* iface,
198 IHlinkSite* pihlSite, DWORD dwSiteData)
200 HlinkImpl *This = (HlinkImpl*)iface;
202 TRACE("(%p)->(%p %li)\n", This, pihlSite, dwSiteData);
204 if (This->Site)
205 IHlinkSite_Release(This->Site);
207 This->Site = pihlSite;
208 if (This->Site)
209 IHlinkSite_AddRef(This->Site);
211 This->SiteData = dwSiteData;
213 return S_OK;
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;
226 if (This->Site)
227 IHlinkSite_AddRef(This->Site);
229 return S_OK;
232 static HRESULT WINAPI IHlink_fnSetMonikerReference( IHlink* iface,
233 DWORD rfHLSETF, IMoniker *pmkTarget, LPCWSTR pwzLocation)
235 HlinkImpl *This = (HlinkImpl*)iface;
237 FIXME("(%p)->(%li %p %s)\n", This, rfHLSETF, pmkTarget,
238 debugstr_w(pwzLocation));
240 if (This->Moniker)
241 IMoniker_Release(This->Moniker);
243 This->Moniker = pmkTarget;
244 if (This->Moniker)
245 IMoniker_AddRef(This->Moniker);
247 HeapFree(GetProcessHeap(), 0, This->Location);
248 This->Location = strdupW( pwzLocation );
250 return S_OK;
253 static HRESULT WINAPI IHlink_fnSetStringReference(IHlink* iface,
254 DWORD grfHLSETF, LPCWSTR pwzTarget, LPCWSTR pwzLocation)
256 HlinkImpl *This = (HlinkImpl*)iface;
258 TRACE("(%p)->(%li %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 );
272 return S_OK;
275 static HRESULT WINAPI IHlink_fnGetMonikerReference(IHlink* iface,
276 DWORD dwWhichRef, IMoniker **ppimkTarget, LPWSTR *ppwzLocation)
278 HlinkImpl *This = (HlinkImpl*)iface;
280 TRACE("(%p) -> (%li %p %p)\n", This, dwWhichRef, ppimkTarget,
281 ppwzLocation);
283 if(ppimkTarget)
284 __GetMoniker(This, ppimkTarget);
286 if (ppwzLocation)
287 IHlink_GetStringReference(iface, dwWhichRef, NULL, ppwzLocation);
289 return S_OK;
292 static HRESULT WINAPI IHlink_fnGetStringReference (IHlink* iface,
293 DWORD dwWhichRef, LPWSTR *ppwzTarget, LPWSTR *ppwzLocation)
295 HlinkImpl *This = (HlinkImpl*)iface;
297 FIXME("(%p) -> (%li %p %p)\n", This, dwWhichRef, ppwzTarget, ppwzLocation);
299 if (ppwzTarget)
301 *ppwzTarget = co_strdupW( This->Target );
303 if (!This->Target)
305 IMoniker* mon;
306 __GetMoniker(This, &mon);
307 if (mon)
309 IBindCtx *pbc;
311 CreateBindCtx( 0, &pbc);
312 IMoniker_GetDisplayName(mon, pbc, NULL, ppwzTarget);
313 IBindCtx_Release(pbc);
314 IMoniker_Release(mon);
316 else
317 FIXME("Unhandled case, no set Target and no moniker\n");
320 if (ppwzLocation)
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>");
327 return S_OK;
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 );
340 return S_OK;
343 static HRESULT WINAPI IHlink_fnGetFriendlyName (IHlink* iface,
344 DWORD grfHLFNAMEF, LPWSTR* ppwzFriendlyName)
346 HlinkImpl *This = (HlinkImpl*)iface;
348 TRACE("(%p) -> (%li %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 );
354 else
356 IMoniker *moniker;
357 __GetMoniker(This, &moniker);
358 if (moniker)
360 IBindCtx *bcxt;
361 CreateBindCtx(0, &bcxt);
363 IMoniker_GetDisplayName(moniker, bcxt, NULL, ppwzFriendlyName);
364 IBindCtx_Release(bcxt);
365 IMoniker_Release(moniker);
367 else
368 *ppwzFriendlyName = NULL;
371 return S_OK;
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 );
383 return S_OK;
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 );
394 return S_OK;
397 static HRESULT WINAPI IHlink_fnGetMiscStatus(IHlink* iface, DWORD* pdwStatus)
399 FIXME("\n");
400 return E_NOTIMPL;
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)->(%li %p %p %p)\n", This, grfHLNF, pbc, pbsc, phbc);
411 if (This->Site)
412 IHlinkSite_ReadyToNavigate(This->Site, This->SiteData, 0);
414 __GetMoniker(This, &mon);
415 TRACE("Moniker %p\n", mon);
417 if (mon)
419 IBindCtx *bcxt;
420 IHlinkTarget *target = NULL;
421 HRESULT r = S_OK;
423 CreateBindCtx(0, &bcxt);
425 RegisterBindStatusCallback(bcxt, pbsc, NULL, 0);
427 r = IMoniker_BindToObject(mon, bcxt, NULL, &IID_IHlinkTarget,
428 (LPVOID*)&target);
429 TRACE("IHlinkTarget returned 0x%lx\n", r);
430 if (r == S_OK)
432 IHlinkTarget_SetBrowseContext(target, phbc);
433 IHlinkTarget_Navigate(target, grfHLNF, This->Location);
434 IHlinkTarget_Release(target);
436 else
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);
455 if (This->Site)
456 IHlinkSite_OnNavigationComplete(This->Site, This->SiteData, 0, 0, NULL);
458 TRACE("Finished Navigation\n");
459 return S_OK;
462 static HRESULT WINAPI IHlink_fnSetAdditonalParams(IHlink* iface,
463 LPCWSTR pwzAdditionalParams)
465 FIXME("\n");
466 return E_NOTIMPL;
469 static HRESULT WINAPI IHlink_fnGetAdditionalParams(IHlink* iface,
470 LPWSTR* ppwzAdditionalParams)
472 FIXME("\n");
473 return E_NOTIMPL;
476 static const IHlinkVtbl hlvt =
478 IHlink_fnQueryInterface,
479 IHlink_fnAddRef,
480 IHlink_fnRelease,
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,
492 IHlink_fnNavigate,
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);
501 TRACE("%p\n", This);
502 return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
505 static ULONG WINAPI IDataObject_fnAddRef (IDataObject* iface)
507 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
508 TRACE("%p\n", This);
509 return IHlink_AddRef((IHlink*)This);
512 static ULONG WINAPI IDataObject_fnRelease (IDataObject* iface)
514 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
515 TRACE("%p\n", This);
516 return IHlink_Release((IHlink*)This);
519 static HRESULT WINAPI IDataObject_fnGetData(IDataObject* iface,
520 FORMATETC* pformatetcIn, STGMEDIUM* pmedium)
522 FIXME("\n");
523 return E_NOTIMPL;
526 static HRESULT WINAPI IDataObject_fnGetDataHere(IDataObject* iface,
527 FORMATETC* pformatetc, STGMEDIUM* pmedium)
529 FIXME("\n");
530 return E_NOTIMPL;
533 static HRESULT WINAPI IDataObject_fnQueryGetData(IDataObject* iface,
534 FORMATETC* pformatetc)
536 FIXME("\n");
537 return E_NOTIMPL;
540 static HRESULT WINAPI IDataObject_fnGetConicalFormatEtc(IDataObject* iface,
541 FORMATETC* pformatetcIn, FORMATETC* pformatetcOut)
543 FIXME("\n");
544 return E_NOTIMPL;
547 static HRESULT WINAPI IDataObject_fnSetData(IDataObject* iface,
548 FORMATETC* pformatetc, STGMEDIUM* pmedium, BOOL fRelease)
550 FIXME("\n");
551 return E_NOTIMPL;
554 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(IDataObject* iface,
555 DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc)
557 FIXME("\n");
558 return E_NOTIMPL;
561 static HRESULT WINAPI IDataObject_fnDAdvise(IDataObject* iface,
562 FORMATETC* pformatetc, DWORD advf, IAdviseSink* pAdvSink,
563 DWORD* pdwConnection)
565 FIXME("\n");
566 return E_NOTIMPL;
569 static HRESULT WINAPI IDataObject_fnDUnadvise(IDataObject* iface,
570 DWORD dwConnection)
572 FIXME("\n");
573 return E_NOTIMPL;
576 static HRESULT WINAPI IDataObject_fnEnumDAdvise(IDataObject* iface,
577 IEnumSTATDATA** ppenumAdvise)
579 FIXME("\n");
580 return E_NOTIMPL;
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,
622 CLSID* pClassID)
624 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
625 TRACE("(%p)\n", This);
626 memcpy(pClassID, &CLSID_StdHlink, sizeof(CLSID));
627 return S_OK;
630 static HRESULT WINAPI IPersistStream_fnIsDirty(IPersistStream* iface)
632 FIXME("\n");
633 return E_NOTIMPL;
636 static HRESULT WINAPI IPersistStream_fnLoad(IPersistStream* iface,
637 IStream* pStm)
639 HRESULT r = E_NOTIMPL;
640 DWORD hdr[2];
641 DWORD read;
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%lx (%p)\n", r, This->Moniker);
650 return r;
653 static HRESULT WINAPI IPersistStream_fnSave(IPersistStream* iface,
654 IStream* pStm, BOOL fClearDirty)
656 HRESULT r = E_FAIL;
657 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
658 DWORD hdr[2];
659 IMoniker *moniker;
661 FIXME("(%p) Moniker(%p)\n", This, This->Moniker);
663 __GetMoniker(This, &moniker);
664 if (moniker)
666 IPersistStream* monstream;
667 /* FIXME: Unknown values in the header */
668 hdr[0] = 2;
669 hdr[1] = 2;
671 IStream_Write(pStm, &hdr, sizeof(hdr), NULL);
673 monstream = NULL;
674 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
675 (LPVOID*)&monstream);
676 if (monstream)
678 r = OleSaveToStream(monstream, pStm);
679 IPersistStream_Release(monstream);
681 IMoniker_Release(moniker);
683 TRACE("Save Result 0x%lx\n", r);
685 return r;
688 static HRESULT WINAPI IPersistStream_fnGetSizeMax(IPersistStream* iface,
689 ULARGE_INTEGER* pcbSize)
691 HRESULT r = E_FAIL;
692 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
693 IMoniker *moniker;
695 FIXME("(%p) Moniker(%p)\n", This, This->Moniker);
697 __GetMoniker(This, &moniker);
698 if (moniker)
700 IPersistStream* monstream = NULL;
701 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
702 (LPVOID*)&monstream);
703 if (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);
713 return r;
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,