mshtml: Correctly handle document with already loaded moniker in set_moniker.
[wine/hacks.git] / dlls / hlink / link.c
blob52197ccf6fd54e3a54b48bbb6db26ed5710bda68
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 "shellapi.h"
24 #include "hlguids.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(hlink);
30 #define HLINK_SAVE_MAGIC 0x00000002
31 #define HLINK_SAVE_MONIKER_PRESENT 0x01
32 #define HLINK_SAVE_MONIKER_IS_ABSOLUTE 0x02
33 #define HLINK_SAVE_LOCATION_PRESENT 0x08
34 #define HLINK_SAVE_FRIENDLY_PRESENT 0x10
35 /* 0x20, 0x40 unknown */
36 #define HLINK_SAVE_TARGET_FRAME_PRESENT 0x80
37 /* known flags */
38 #define HLINK_SAVE_ALL (HLINK_SAVE_TARGET_FRAME_PRESENT|HLINK_SAVE_FRIENDLY_PRESENT|HLINK_SAVE_LOCATION_PRESENT|0x04|HLINK_SAVE_MONIKER_IS_ABSOLUTE|HLINK_SAVE_MONIKER_PRESENT)
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 TargetFrameName;
55 IMoniker *Moniker;
56 IHlinkSite *Site;
57 DWORD SiteData;
58 BOOL absolute;
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 void __GetMoniker(HlinkImpl* This, IMoniker** moniker)
74 *moniker = NULL;
75 if (This->Moniker)
77 *moniker = This->Moniker;
78 if (*moniker)
79 IMoniker_AddRef(*moniker);
81 else if (This->Site)
83 IHlinkSite_GetMoniker(This->Site, This->SiteData,
84 OLEGETMONIKER_FORCEASSIGN, OLEWHICHMK_CONTAINER, moniker);
88 HRESULT WINAPI HLink_Constructor(IUnknown *pUnkOuter, REFIID riid,
89 LPVOID *ppv)
91 HlinkImpl * hl;
93 TRACE("unkOut=%p riid=%s\n", pUnkOuter, debugstr_guid(riid));
94 *ppv = NULL;
96 if (pUnkOuter)
97 return CLASS_E_NOAGGREGATION;
99 hl = heap_alloc_zero(sizeof(HlinkImpl));
100 if (!hl)
101 return E_OUTOFMEMORY;
103 hl->ref = 1;
104 hl->lpVtbl = &hlvt;
105 hl->lpPSVtbl = &psvt;
106 hl->lpDOVtbl = &dovt;
108 *ppv = hl;
109 return S_OK;
112 static HRESULT WINAPI IHlink_fnQueryInterface(IHlink* iface, REFIID riid,
113 LPVOID *ppvObj)
115 HlinkImpl *This = (HlinkImpl*)iface;
117 TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppvObj);
119 *ppvObj = NULL;
121 if (IsEqualIID(riid, &IID_IUnknown) || (IsEqualIID(riid, &IID_IHlink)))
122 *ppvObj = This;
123 else if (IsEqualIID(riid, &IID_IPersistStream))
124 *ppvObj = &(This->lpPSVtbl);
125 else if (IsEqualIID(riid, &IID_IDataObject))
126 *ppvObj = &(This->lpDOVtbl);
128 if (*ppvObj)
130 IUnknown_AddRef((IUnknown*)(*ppvObj));
131 return S_OK;
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=%u)\n", This, refCount - 1);
143 return refCount;
146 static ULONG WINAPI IHlink_fnRelease (IHlink* iface)
148 HlinkImpl *This = (HlinkImpl*)iface;
149 ULONG refCount = InterlockedDecrement(&This->ref);
151 TRACE("(%p)->(count=%u)\n", This, refCount + 1);
152 if (refCount)
153 return refCount;
155 TRACE("-- destroying IHlink (%p)\n", This);
156 heap_free(This->FriendlyName);
157 heap_free(This->TargetFrameName);
158 heap_free(This->Location);
159 if (This->Moniker)
160 IMoniker_Release(This->Moniker);
161 if (This->Site)
162 IHlinkSite_Release(This->Site);
163 heap_free(This);
164 return 0;
167 static HRESULT WINAPI IHlink_fnSetHlinkSite( IHlink* iface,
168 IHlinkSite* pihlSite, DWORD dwSiteData)
170 HlinkImpl *This = (HlinkImpl*)iface;
172 TRACE("(%p)->(%p %i)\n", This, pihlSite, dwSiteData);
174 if (This->Site)
175 IHlinkSite_Release(This->Site);
177 This->Site = pihlSite;
178 if (This->Site)
179 IHlinkSite_AddRef(This->Site);
181 This->SiteData = dwSiteData;
183 return S_OK;
186 static HRESULT WINAPI IHlink_fnGetHlinkSite( IHlink* iface,
187 IHlinkSite** ppihlSite, DWORD *pdwSiteData)
189 HlinkImpl *This = (HlinkImpl*)iface;
191 TRACE("(%p)->(%p %p)\n", This, ppihlSite, pdwSiteData);
193 *ppihlSite = This->Site;
194 *pdwSiteData = This->SiteData;
196 if (This->Site)
197 IHlinkSite_AddRef(This->Site);
199 return S_OK;
202 static HRESULT WINAPI IHlink_fnSetMonikerReference( IHlink* iface,
203 DWORD rfHLSETF, IMoniker *pmkTarget, LPCWSTR pwzLocation)
205 HlinkImpl *This = (HlinkImpl*)iface;
207 TRACE("(%p)->(%i %p %s)\n", This, rfHLSETF, pmkTarget,
208 debugstr_w(pwzLocation));
210 if(rfHLSETF == 0)
211 return E_INVALIDARG;
212 if(!(rfHLSETF & (HLINKSETF_TARGET | HLINKSETF_LOCATION)))
213 return rfHLSETF;
215 if(rfHLSETF & HLINKSETF_TARGET){
216 if (This->Moniker)
217 IMoniker_Release(This->Moniker);
219 This->Moniker = pmkTarget;
220 if (This->Moniker)
222 LPOLESTR display_name;
223 IMoniker_AddRef(This->Moniker);
224 IMoniker_GetDisplayName(This->Moniker, NULL, NULL, &display_name);
225 This->absolute = display_name && strchrW(display_name, ':');
226 CoTaskMemFree(display_name);
230 if(rfHLSETF & HLINKSETF_LOCATION){
231 heap_free(This->Location);
232 This->Location = hlink_strdupW( pwzLocation );
235 return S_OK;
238 static HRESULT WINAPI IHlink_fnSetStringReference(IHlink* iface,
239 DWORD grfHLSETF, LPCWSTR pwzTarget, LPCWSTR pwzLocation)
241 HlinkImpl *This = (HlinkImpl*)iface;
243 TRACE("(%p)->(%i %s %s)\n", This, grfHLSETF, debugstr_w(pwzTarget),
244 debugstr_w(pwzLocation));
246 if(grfHLSETF > (HLINKSETF_TARGET | HLINKSETF_LOCATION) &&
247 grfHLSETF < -(HLINKSETF_TARGET | HLINKSETF_LOCATION))
248 return grfHLSETF;
250 if (grfHLSETF & HLINKSETF_TARGET)
252 if (This->Moniker)
254 IMoniker_Release(This->Moniker);
255 This->Moniker = NULL;
257 if (pwzTarget && *pwzTarget)
259 IMoniker *pMon;
260 IBindCtx *pbc = NULL;
261 ULONG eaten;
262 HRESULT r;
264 r = CreateBindCtx(0, &pbc);
265 if (FAILED(r))
266 return E_OUTOFMEMORY;
268 r = MkParseDisplayName(pbc, pwzTarget, &eaten, &pMon);
269 IBindCtx_Release(pbc);
271 if (FAILED(r))
273 LPCWSTR p = strchrW(pwzTarget, ':');
274 if (p && (p - pwzTarget > 1))
275 r = CreateURLMoniker(NULL, pwzTarget, &pMon);
276 else
277 r = CreateFileMoniker(pwzTarget, &pMon);
278 if (FAILED(r))
280 ERR("couldn't create moniker for %s, failed with error 0x%08x\n",
281 debugstr_w(pwzTarget), r);
282 return r;
286 IHlink_SetMonikerReference(iface, HLINKSETF_TARGET, pMon, NULL);
287 IMoniker_Release(pMon);
291 if (grfHLSETF & HLINKSETF_LOCATION)
293 heap_free(This->Location);
294 This->Location = hlink_strdupW( pwzLocation );
297 return S_OK;
300 static HRESULT WINAPI IHlink_fnGetMonikerReference(IHlink* iface,
301 DWORD dwWhichRef, IMoniker **ppimkTarget, LPWSTR *ppwzLocation)
303 HlinkImpl *This = (HlinkImpl*)iface;
305 TRACE("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppimkTarget,
306 ppwzLocation);
308 if(ppimkTarget)
309 __GetMoniker(This, ppimkTarget);
311 if (ppwzLocation)
312 IHlink_GetStringReference(iface, dwWhichRef, NULL, ppwzLocation);
314 return S_OK;
317 static HRESULT WINAPI IHlink_fnGetStringReference (IHlink* iface,
318 DWORD dwWhichRef, LPWSTR *ppwzTarget, LPWSTR *ppwzLocation)
320 HlinkImpl *This = (HlinkImpl*)iface;
322 TRACE("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppwzTarget, ppwzLocation);
324 /* note: undocumented behavior with dwWhichRef == -1 */
325 if(dwWhichRef != -1 && dwWhichRef & ~(HLINKGETREF_DEFAULT | HLINKGETREF_ABSOLUTE | HLINKGETREF_RELATIVE))
327 if(ppwzTarget)
328 *ppwzTarget = NULL;
329 if(ppwzLocation)
330 *ppwzLocation = NULL;
331 return E_INVALIDARG;
334 if(dwWhichRef != HLINKGETREF_DEFAULT)
335 FIXME("unhandled flags: 0x%x\n", dwWhichRef);
337 if (ppwzTarget)
339 IMoniker* mon;
340 __GetMoniker(This, &mon);
341 if (mon)
343 IBindCtx *pbc;
345 CreateBindCtx( 0, &pbc);
346 IMoniker_GetDisplayName(mon, pbc, NULL, ppwzTarget);
347 IBindCtx_Release(pbc);
348 IMoniker_Release(mon);
350 else
351 *ppwzTarget = NULL;
353 if (ppwzLocation)
354 *ppwzLocation = hlink_co_strdupW( This->Location );
356 TRACE("(Target: %s Location: %s)\n",
357 (ppwzTarget)?debugstr_w(*ppwzTarget):"<NULL>",
358 (ppwzLocation)?debugstr_w(*ppwzLocation):"<NULL>");
360 return S_OK;
363 static HRESULT WINAPI IHlink_fnSetFriendlyName (IHlink *iface,
364 LPCWSTR pwzFriendlyName)
366 HlinkImpl *This = (HlinkImpl*)iface;
368 TRACE("(%p) -> (%s)\n", This, debugstr_w(pwzFriendlyName));
370 heap_free(This->FriendlyName);
371 This->FriendlyName = hlink_strdupW( pwzFriendlyName );
373 return S_OK;
376 static HRESULT WINAPI IHlink_fnGetFriendlyName (IHlink* iface,
377 DWORD grfHLFNAMEF, LPWSTR* ppwzFriendlyName)
379 HlinkImpl *This = (HlinkImpl*)iface;
381 TRACE("(%p) -> (%i %p)\n", This, grfHLFNAMEF, ppwzFriendlyName);
383 /* FIXME: Only using explicitly set and cached friendly names */
385 if (This->FriendlyName)
386 *ppwzFriendlyName = hlink_co_strdupW( This->FriendlyName );
387 else
389 IMoniker *moniker;
390 __GetMoniker(This, &moniker);
391 if (moniker)
393 IBindCtx *bcxt;
394 CreateBindCtx(0, &bcxt);
396 IMoniker_GetDisplayName(moniker, bcxt, NULL, ppwzFriendlyName);
397 IBindCtx_Release(bcxt);
398 IMoniker_Release(moniker);
400 else
401 *ppwzFriendlyName = NULL;
404 return S_OK;
407 static HRESULT WINAPI IHlink_fnSetTargetFrameName(IHlink* iface,
408 LPCWSTR pwzTargetFramename)
410 HlinkImpl *This = (HlinkImpl*)iface;
411 TRACE("(%p)->(%s)\n", This, debugstr_w(pwzTargetFramename));
413 heap_free(This->TargetFrameName);
414 This->TargetFrameName = hlink_strdupW( pwzTargetFramename );
416 return S_OK;
419 static HRESULT WINAPI IHlink_fnGetTargetFrameName(IHlink* iface,
420 LPWSTR *ppwzTargetFrameName)
422 HlinkImpl *This = (HlinkImpl*)iface;
424 TRACE("(%p)->(%p)\n", This, ppwzTargetFrameName);
425 *ppwzTargetFrameName = hlink_co_strdupW( This->TargetFrameName );
427 return S_OK;
430 static HRESULT WINAPI IHlink_fnGetMiscStatus(IHlink* iface, DWORD* pdwStatus)
432 FIXME("\n");
433 return E_NOTIMPL;
436 static HRESULT WINAPI IHlink_fnNavigate(IHlink* iface, DWORD grfHLNF, LPBC pbc,
437 IBindStatusCallback *pbsc, IHlinkBrowseContext *phbc)
439 HlinkImpl *This = (HlinkImpl*)iface;
440 IMoniker *mon = NULL;
442 FIXME("Semi-Stub:(%p)->(%i %p %p %p)\n", This, grfHLNF, pbc, pbsc, phbc);
444 if (This->Site)
445 IHlinkSite_ReadyToNavigate(This->Site, This->SiteData, 0);
447 __GetMoniker(This, &mon);
448 TRACE("Moniker %p\n", mon);
450 if (mon)
452 IBindCtx *bcxt;
453 IHlinkTarget *target = NULL;
454 HRESULT r = S_OK;
456 CreateBindCtx(0, &bcxt);
458 RegisterBindStatusCallback(bcxt, pbsc, NULL, 0);
460 r = IMoniker_BindToObject(mon, bcxt, NULL, &IID_IHlinkTarget,
461 (LPVOID*)&target);
462 TRACE("IHlinkTarget returned 0x%x\n", r);
463 if (r == S_OK)
465 IHlinkTarget_SetBrowseContext(target, phbc);
466 IHlinkTarget_Navigate(target, grfHLNF, This->Location);
467 IHlinkTarget_Release(target);
469 else
471 static const WCHAR szOpen[] = {'o','p','e','n',0};
472 LPWSTR target = NULL;
474 r = IHlink_GetStringReference(iface, HLINKGETREF_DEFAULT, &target, NULL);
475 if (SUCCEEDED(r) && target)
477 ShellExecuteW(NULL, szOpen, target, NULL, NULL, SW_SHOW);
478 CoTaskMemFree(target);
482 RevokeBindStatusCallback(bcxt, pbsc);
484 IBindCtx_Release(bcxt);
485 IMoniker_Release(mon);
488 if (This->Site)
489 IHlinkSite_OnNavigationComplete(This->Site, This->SiteData, 0, 0, NULL);
491 TRACE("Finished Navigation\n");
492 return S_OK;
495 static HRESULT WINAPI IHlink_fnSetAdditonalParams(IHlink* iface,
496 LPCWSTR pwzAdditionalParams)
498 TRACE("Not implemented in native IHlink\n");
499 return E_NOTIMPL;
502 static HRESULT WINAPI IHlink_fnGetAdditionalParams(IHlink* iface,
503 LPWSTR* ppwzAdditionalParams)
505 TRACE("Not implemented in native IHlink\n");
506 return E_NOTIMPL;
509 static const IHlinkVtbl hlvt =
511 IHlink_fnQueryInterface,
512 IHlink_fnAddRef,
513 IHlink_fnRelease,
514 IHlink_fnSetHlinkSite,
515 IHlink_fnGetHlinkSite,
516 IHlink_fnSetMonikerReference,
517 IHlink_fnGetMonikerReference,
518 IHlink_fnSetStringReference,
519 IHlink_fnGetStringReference,
520 IHlink_fnSetFriendlyName,
521 IHlink_fnGetFriendlyName,
522 IHlink_fnSetTargetFrameName,
523 IHlink_fnGetTargetFrameName,
524 IHlink_fnGetMiscStatus,
525 IHlink_fnNavigate,
526 IHlink_fnSetAdditonalParams,
527 IHlink_fnGetAdditionalParams
530 static HRESULT WINAPI IDataObject_fnQueryInterface(IDataObject* iface,
531 REFIID riid, LPVOID *ppvObj)
533 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
534 TRACE("%p\n", This);
535 return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
538 static ULONG WINAPI IDataObject_fnAddRef (IDataObject* iface)
540 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
541 TRACE("%p\n", This);
542 return IHlink_AddRef((IHlink*)This);
545 static ULONG WINAPI IDataObject_fnRelease (IDataObject* iface)
547 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
548 TRACE("%p\n", This);
549 return IHlink_Release((IHlink*)This);
552 static HRESULT WINAPI IDataObject_fnGetData(IDataObject* iface,
553 FORMATETC* pformatetcIn, STGMEDIUM* pmedium)
555 FIXME("\n");
556 return E_NOTIMPL;
559 static HRESULT WINAPI IDataObject_fnGetDataHere(IDataObject* iface,
560 FORMATETC* pformatetc, STGMEDIUM* pmedium)
562 FIXME("\n");
563 return E_NOTIMPL;
566 static HRESULT WINAPI IDataObject_fnQueryGetData(IDataObject* iface,
567 FORMATETC* pformatetc)
569 FIXME("\n");
570 return E_NOTIMPL;
573 static HRESULT WINAPI IDataObject_fnGetConicalFormatEtc(IDataObject* iface,
574 FORMATETC* pformatetcIn, FORMATETC* pformatetcOut)
576 FIXME("\n");
577 return E_NOTIMPL;
580 static HRESULT WINAPI IDataObject_fnSetData(IDataObject* iface,
581 FORMATETC* pformatetc, STGMEDIUM* pmedium, BOOL fRelease)
583 FIXME("\n");
584 return E_NOTIMPL;
587 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(IDataObject* iface,
588 DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc)
590 FIXME("\n");
591 return E_NOTIMPL;
594 static HRESULT WINAPI IDataObject_fnDAdvise(IDataObject* iface,
595 FORMATETC* pformatetc, DWORD advf, IAdviseSink* pAdvSink,
596 DWORD* pdwConnection)
598 FIXME("\n");
599 return E_NOTIMPL;
602 static HRESULT WINAPI IDataObject_fnDUnadvise(IDataObject* iface,
603 DWORD dwConnection)
605 FIXME("\n");
606 return E_NOTIMPL;
609 static HRESULT WINAPI IDataObject_fnEnumDAdvise(IDataObject* iface,
610 IEnumSTATDATA** ppenumAdvise)
612 FIXME("\n");
613 return E_NOTIMPL;
616 static const IDataObjectVtbl dovt =
618 IDataObject_fnQueryInterface,
619 IDataObject_fnAddRef,
620 IDataObject_fnRelease,
621 IDataObject_fnGetData,
622 IDataObject_fnGetDataHere,
623 IDataObject_fnQueryGetData,
624 IDataObject_fnGetConicalFormatEtc,
625 IDataObject_fnSetData,
626 IDataObject_fnEnumFormatEtc,
627 IDataObject_fnDAdvise,
628 IDataObject_fnDUnadvise,
629 IDataObject_fnEnumDAdvise
632 static HRESULT WINAPI IPersistStream_fnQueryInterface(IPersistStream* iface,
633 REFIID riid, LPVOID *ppvObj)
635 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
636 TRACE("(%p)\n", This);
637 return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
640 static ULONG WINAPI IPersistStream_fnAddRef (IPersistStream* iface)
642 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
643 TRACE("(%p)\n", This);
644 return IHlink_AddRef((IHlink*)This);
647 static ULONG WINAPI IPersistStream_fnRelease (IPersistStream* iface)
649 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
650 TRACE("(%p)\n", This);
651 return IHlink_Release((IHlink*)This);
654 static HRESULT WINAPI IPersistStream_fnGetClassID(IPersistStream* iface,
655 CLSID* pClassID)
657 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
658 TRACE("(%p)\n", This);
659 *pClassID = CLSID_StdHlink;
660 return S_OK;
663 static HRESULT WINAPI IPersistStream_fnIsDirty(IPersistStream* iface)
665 FIXME("\n");
666 return E_NOTIMPL;
669 static HRESULT write_hlink_string(IStream *pStm, LPCWSTR str)
671 DWORD len;
672 HRESULT hr;
674 TRACE("(%p, %s)\n", pStm, debugstr_w(str));
676 len = strlenW(str) + 1;
678 hr = IStream_Write(pStm, &len, sizeof(len), NULL);
679 if (FAILED(hr)) return hr;
681 hr = IStream_Write(pStm, str, len * sizeof(WCHAR), NULL);
682 if (FAILED(hr)) return hr;
684 return S_OK;
687 static inline ULONG size_hlink_string(LPCWSTR str)
689 return sizeof(DWORD) + (strlenW(str) + 1) * sizeof(WCHAR);
692 static HRESULT read_hlink_string(IStream *pStm, LPWSTR *out_str)
694 LPWSTR str;
695 DWORD len;
696 ULONG read;
697 HRESULT hr;
699 hr = IStream_Read(pStm, &len, sizeof(len), &read);
700 if (FAILED(hr)) return hr;
701 if (read != sizeof(len)) return STG_E_READFAULT;
703 TRACE("read len %d\n", len);
705 str = heap_alloc(len * sizeof(WCHAR));
706 if (!str) return E_OUTOFMEMORY;
708 hr = IStream_Read(pStm, str, len * sizeof(WCHAR), &read);
709 if (FAILED(hr))
711 heap_free(str);
712 return hr;
714 if (read != len * sizeof(WCHAR))
716 heap_free(str);
717 return STG_E_READFAULT;
719 TRACE("read string %s\n", debugstr_w(str));
721 *out_str = str;
722 return S_OK;
725 static HRESULT WINAPI IPersistStream_fnLoad(IPersistStream* iface,
726 IStream* pStm)
728 HRESULT r;
729 DWORD hdr[2];
730 DWORD read;
731 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
733 r = IStream_Read(pStm, hdr, sizeof(hdr), &read);
734 if (read != sizeof(hdr) || (hdr[0] != HLINK_SAVE_MAGIC))
736 r = E_FAIL;
737 goto end;
739 if (hdr[1] & ~HLINK_SAVE_ALL)
740 FIXME("unknown flag(s) 0x%x\n", hdr[1] & ~HLINK_SAVE_ALL);
742 if (hdr[1] & HLINK_SAVE_TARGET_FRAME_PRESENT)
744 TRACE("loading target frame name\n");
745 r = read_hlink_string(pStm, &This->TargetFrameName);
746 if (FAILED(r)) goto end;
749 if (hdr[1] & HLINK_SAVE_FRIENDLY_PRESENT)
751 TRACE("loading target friendly name\n");
752 if (!(hdr[1] & 0x4))
753 FIXME("0x4 flag not present with friendly name flag - not sure what this means\n");
754 r = read_hlink_string(pStm, &This->FriendlyName);
755 if (FAILED(r)) goto end;
758 if (hdr[1] & HLINK_SAVE_MONIKER_PRESENT)
760 TRACE("loading moniker\n");
761 r = OleLoadFromStream(pStm, &IID_IMoniker, (LPVOID*)&(This->Moniker));
762 if (FAILED(r))
763 goto end;
764 This->absolute = hdr[1] & HLINK_SAVE_MONIKER_IS_ABSOLUTE ? TRUE : FALSE;
767 if (hdr[1] & HLINK_SAVE_LOCATION_PRESENT)
769 TRACE("loading location\n");
770 r = read_hlink_string(pStm, &This->Location);
771 if (FAILED(r)) goto end;
774 end:
775 TRACE("Load Result 0x%x (%p)\n", r, This->Moniker);
777 return r;
780 static HRESULT WINAPI IPersistStream_fnSave(IPersistStream* iface,
781 IStream* pStm, BOOL fClearDirty)
783 HRESULT r = E_FAIL;
784 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
785 DWORD hdr[2];
786 IMoniker *moniker;
788 TRACE("(%p) Moniker(%p)\n", This, This->Moniker);
790 __GetMoniker(This, &moniker);
792 hdr[0] = HLINK_SAVE_MAGIC;
793 hdr[1] = 0;
795 if (moniker)
796 hdr[1] |= HLINK_SAVE_MONIKER_PRESENT;
797 if (This->absolute)
798 hdr[1] |= HLINK_SAVE_MONIKER_IS_ABSOLUTE;
799 if (This->Location)
800 hdr[1] |= HLINK_SAVE_LOCATION_PRESENT;
801 if (This->FriendlyName)
802 hdr[1] |= HLINK_SAVE_FRIENDLY_PRESENT | 4 /* FIXME */;
803 if (This->TargetFrameName)
804 hdr[1] |= HLINK_SAVE_TARGET_FRAME_PRESENT;
806 IStream_Write(pStm, hdr, sizeof(hdr), NULL);
808 if (This->TargetFrameName)
810 r = write_hlink_string(pStm, This->TargetFrameName);
811 if (FAILED(r)) goto end;
814 if (This->FriendlyName)
816 r = write_hlink_string(pStm, This->FriendlyName);
817 if (FAILED(r)) goto end;
820 if (moniker)
822 IPersistStream* monstream;
824 monstream = NULL;
825 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
826 (LPVOID*)&monstream);
827 if (monstream)
829 r = OleSaveToStream(monstream, pStm);
830 IPersistStream_Release(monstream);
832 if (FAILED(r)) goto end;
835 if (This->Location)
837 r = write_hlink_string(pStm, This->Location);
838 if (FAILED(r)) goto end;
841 end:
842 if (moniker) IMoniker_Release(moniker);
843 TRACE("Save Result 0x%x\n", r);
845 return r;
848 static HRESULT WINAPI IPersistStream_fnGetSizeMax(IPersistStream* iface,
849 ULARGE_INTEGER* pcbSize)
851 HRESULT r = E_FAIL;
852 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
853 IMoniker *moniker;
855 TRACE("(%p) Moniker(%p)\n", This, This->Moniker);
857 pcbSize->QuadPart = sizeof(DWORD)*2;
859 if (This->TargetFrameName)
860 pcbSize->QuadPart += size_hlink_string(This->TargetFrameName);
862 if (This->FriendlyName)
863 pcbSize->QuadPart += size_hlink_string(This->FriendlyName);
865 __GetMoniker(This, &moniker);
866 if (moniker)
868 IPersistStream* monstream = NULL;
869 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
870 (LPVOID*)&monstream);
871 if (monstream)
873 ULARGE_INTEGER mon_size;
874 r = IPersistStream_GetSizeMax(monstream, &mon_size);
875 pcbSize->QuadPart += mon_size.QuadPart;
876 IPersistStream_Release(monstream);
878 IMoniker_Release(moniker);
881 if (This->Location)
882 pcbSize->QuadPart += size_hlink_string(This->Location);
884 return r;
887 static const IPersistStreamVtbl psvt =
889 IPersistStream_fnQueryInterface,
890 IPersistStream_fnAddRef,
891 IPersistStream_fnRelease,
892 IPersistStream_fnGetClassID,
893 IPersistStream_fnIsDirty,
894 IPersistStream_fnLoad,
895 IPersistStream_fnSave,
896 IPersistStream_fnGetSizeMax,