includes: Fix alignment for 64-bits
[wine/wine64.git] / dlls / hlink / link.c
blob20841f8f89e5ac4f642c6b119fefdf24093327ca
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 Target;
55 LPWSTR TargetFrameName;
56 IMoniker *Moniker;
57 IHlinkSite *Site;
58 DWORD SiteData;
59 BOOL absolute;
60 } HlinkImpl;
63 static inline HlinkImpl* HlinkImpl_from_IPersistStream( IPersistStream* iface)
65 return (HlinkImpl*) ((CHAR*)iface - FIELD_OFFSET(HlinkImpl, lpPSVtbl));
68 static inline HlinkImpl* HlinkImpl_from_IDataObject( IDataObject* iface)
70 return (HlinkImpl*) ((CHAR*)iface - FIELD_OFFSET(HlinkImpl, lpDOVtbl));
73 static inline void __GetMoniker(HlinkImpl* This, IMoniker** moniker)
75 *moniker = NULL;
76 if (This->Moniker)
78 *moniker = This->Moniker;
79 if (*moniker)
80 IMoniker_AddRef(*moniker);
82 else if (This->Site)
84 IHlinkSite_GetMoniker(This->Site, This->SiteData,
85 OLEGETMONIKER_FORCEASSIGN, OLEWHICHMK_CONTAINER,
86 (LPVOID)moniker);
90 HRESULT WINAPI HLink_Constructor(IUnknown *pUnkOuter, REFIID riid,
91 LPVOID *ppv)
93 HlinkImpl * hl;
95 TRACE("unkOut=%p riid=%s\n", pUnkOuter, debugstr_guid(riid));
96 *ppv = NULL;
98 if (pUnkOuter)
99 return CLASS_E_NOAGGREGATION;
101 hl = heap_alloc_zero(sizeof(HlinkImpl));
102 if (!hl)
103 return E_OUTOFMEMORY;
105 hl->ref = 1;
106 hl->lpVtbl = &hlvt;
107 hl->lpPSVtbl = &psvt;
108 hl->lpDOVtbl = &dovt;
110 *ppv = hl;
111 return S_OK;
114 static HRESULT WINAPI IHlink_fnQueryInterface(IHlink* iface, REFIID riid,
115 LPVOID *ppvObj)
117 HlinkImpl *This = (HlinkImpl*)iface;
119 TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppvObj);
121 *ppvObj = NULL;
123 if (IsEqualIID(riid, &IID_IUnknown) || (IsEqualIID(riid, &IID_IHlink)))
124 *ppvObj = This;
125 else if (IsEqualIID(riid, &IID_IPersistStream))
126 *ppvObj = (LPVOID*)&(This->lpPSVtbl);
127 else if (IsEqualIID(riid, &IID_IDataObject))
128 *ppvObj = (LPVOID*)&(This->lpDOVtbl);
130 if (*ppvObj)
132 IUnknown_AddRef((IUnknown*)(*ppvObj));
133 return S_OK;
135 return E_NOINTERFACE;
138 static ULONG WINAPI IHlink_fnAddRef (IHlink* iface)
140 HlinkImpl *This = (HlinkImpl*)iface;
141 ULONG refCount = InterlockedIncrement(&This->ref);
143 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
145 return refCount;
148 static ULONG WINAPI IHlink_fnRelease (IHlink* iface)
150 HlinkImpl *This = (HlinkImpl*)iface;
151 ULONG refCount = InterlockedDecrement(&This->ref);
153 TRACE("(%p)->(count=%u)\n", This, refCount + 1);
154 if (refCount)
155 return refCount;
157 TRACE("-- destroying IHlink (%p)\n", This);
158 heap_free(This->FriendlyName);
159 heap_free(This->Target);
160 heap_free(This->TargetFrameName);
161 heap_free(This->Location);
162 if (This->Moniker)
163 IMoniker_Release(This->Moniker);
164 if (This->Site)
165 IHlinkSite_Release(This->Site);
166 heap_free(This);
167 return 0;
170 static HRESULT WINAPI IHlink_fnSetHlinkSite( IHlink* iface,
171 IHlinkSite* pihlSite, DWORD dwSiteData)
173 HlinkImpl *This = (HlinkImpl*)iface;
175 TRACE("(%p)->(%p %i)\n", This, pihlSite, dwSiteData);
177 if (This->Site)
178 IHlinkSite_Release(This->Site);
180 This->Site = pihlSite;
181 if (This->Site)
182 IHlinkSite_AddRef(This->Site);
184 This->SiteData = dwSiteData;
186 return S_OK;
189 static HRESULT WINAPI IHlink_fnGetHlinkSite( IHlink* iface,
190 IHlinkSite** ppihlSite, DWORD *pdwSiteData)
192 HlinkImpl *This = (HlinkImpl*)iface;
194 TRACE("(%p)->(%p %p)\n", This, ppihlSite, pdwSiteData);
196 *ppihlSite = This->Site;
197 *pdwSiteData = This->SiteData;
199 if (This->Site)
200 IHlinkSite_AddRef(This->Site);
202 return S_OK;
205 static HRESULT WINAPI IHlink_fnSetMonikerReference( IHlink* iface,
206 DWORD rfHLSETF, IMoniker *pmkTarget, LPCWSTR pwzLocation)
208 HlinkImpl *This = (HlinkImpl*)iface;
210 FIXME("(%p)->(%i %p %s)\n", This, rfHLSETF, pmkTarget,
211 debugstr_w(pwzLocation));
213 if (This->Moniker)
214 IMoniker_Release(This->Moniker);
216 This->Moniker = pmkTarget;
217 if (This->Moniker)
219 LPOLESTR display_name;
220 IMoniker_AddRef(This->Moniker);
221 IMoniker_GetDisplayName(This->Moniker, NULL, NULL, &display_name);
222 This->absolute = display_name && strchrW(display_name, ':');
223 CoTaskMemFree(display_name);
226 heap_free(This->Location);
227 This->Location = hlink_strdupW( pwzLocation );
229 return S_OK;
232 static HRESULT WINAPI IHlink_fnSetStringReference(IHlink* iface,
233 DWORD grfHLSETF, LPCWSTR pwzTarget, LPCWSTR pwzLocation)
235 HlinkImpl *This = (HlinkImpl*)iface;
237 TRACE("(%p)->(%i %s %s)\n", This, grfHLSETF, debugstr_w(pwzTarget),
238 debugstr_w(pwzLocation));
240 if (grfHLSETF & HLINKSETF_TARGET)
242 heap_free(This->Target);
243 This->Target = hlink_strdupW( pwzTarget );
245 if (grfHLSETF & HLINKSETF_LOCATION)
247 heap_free(This->Location);
248 This->Location = hlink_strdupW( pwzLocation );
251 return S_OK;
254 static HRESULT WINAPI IHlink_fnGetMonikerReference(IHlink* iface,
255 DWORD dwWhichRef, IMoniker **ppimkTarget, LPWSTR *ppwzLocation)
257 HlinkImpl *This = (HlinkImpl*)iface;
259 TRACE("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppimkTarget,
260 ppwzLocation);
262 if(ppimkTarget)
263 __GetMoniker(This, ppimkTarget);
265 if (ppwzLocation)
266 IHlink_GetStringReference(iface, dwWhichRef, NULL, ppwzLocation);
268 return S_OK;
271 static HRESULT WINAPI IHlink_fnGetStringReference (IHlink* iface,
272 DWORD dwWhichRef, LPWSTR *ppwzTarget, LPWSTR *ppwzLocation)
274 HlinkImpl *This = (HlinkImpl*)iface;
276 FIXME("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppwzTarget, ppwzLocation);
278 if (ppwzTarget)
280 *ppwzTarget = hlink_co_strdupW( This->Target );
282 if (!This->Target)
284 IMoniker* mon;
285 __GetMoniker(This, &mon);
286 if (mon)
288 IBindCtx *pbc;
290 CreateBindCtx( 0, &pbc);
291 IMoniker_GetDisplayName(mon, pbc, NULL, ppwzTarget);
292 IBindCtx_Release(pbc);
293 IMoniker_Release(mon);
295 else
296 FIXME("Unhandled case, no set Target and no moniker\n");
299 if (ppwzLocation)
300 *ppwzLocation = hlink_co_strdupW( This->Location );
302 TRACE("(Target: %s Location: %s)\n",
303 (ppwzTarget)?debugstr_w(*ppwzTarget):"<NULL>",
304 (ppwzLocation)?debugstr_w(*ppwzLocation):"<NULL>");
306 return S_OK;
309 static HRESULT WINAPI IHlink_fnSetFriendlyName (IHlink *iface,
310 LPCWSTR pwzFriendlyName)
312 HlinkImpl *This = (HlinkImpl*)iface;
314 TRACE("(%p) -> (%s)\n", This, debugstr_w(pwzFriendlyName));
316 heap_free(This->FriendlyName);
317 This->FriendlyName = hlink_strdupW( pwzFriendlyName );
319 return S_OK;
322 static HRESULT WINAPI IHlink_fnGetFriendlyName (IHlink* iface,
323 DWORD grfHLFNAMEF, LPWSTR* ppwzFriendlyName)
325 HlinkImpl *This = (HlinkImpl*)iface;
327 TRACE("(%p) -> (%i %p)\n", This, grfHLFNAMEF, ppwzFriendlyName);
329 /* FIXME: Only using explicitly set and cached friendly names */
331 if (This->FriendlyName)
332 *ppwzFriendlyName = hlink_co_strdupW( This->FriendlyName );
333 else
335 IMoniker *moniker;
336 __GetMoniker(This, &moniker);
337 if (moniker)
339 IBindCtx *bcxt;
340 CreateBindCtx(0, &bcxt);
342 IMoniker_GetDisplayName(moniker, bcxt, NULL, ppwzFriendlyName);
343 IBindCtx_Release(bcxt);
344 IMoniker_Release(moniker);
346 else
347 *ppwzFriendlyName = NULL;
350 return S_OK;
353 static HRESULT WINAPI IHlink_fnSetTargetFrameName(IHlink* iface,
354 LPCWSTR pwzTargetFramename)
356 HlinkImpl *This = (HlinkImpl*)iface;
357 TRACE("(%p)->(%s)\n", This, debugstr_w(pwzTargetFramename));
359 heap_free(This->TargetFrameName);
360 This->TargetFrameName = hlink_strdupW( pwzTargetFramename );
362 return S_OK;
365 static HRESULT WINAPI IHlink_fnGetTargetFrameName(IHlink* iface,
366 LPWSTR *ppwzTargetFrameName)
368 HlinkImpl *This = (HlinkImpl*)iface;
370 TRACE("(%p)->(%p)\n", This, ppwzTargetFrameName);
371 *ppwzTargetFrameName = hlink_co_strdupW( This->TargetFrameName );
373 return S_OK;
376 static HRESULT WINAPI IHlink_fnGetMiscStatus(IHlink* iface, DWORD* pdwStatus)
378 FIXME("\n");
379 return E_NOTIMPL;
382 static HRESULT WINAPI IHlink_fnNavigate(IHlink* iface, DWORD grfHLNF, LPBC pbc,
383 IBindStatusCallback *pbsc, IHlinkBrowseContext *phbc)
385 HlinkImpl *This = (HlinkImpl*)iface;
386 IMoniker *mon = NULL;
388 FIXME("Semi-Stub:(%p)->(%i %p %p %p)\n", This, grfHLNF, pbc, pbsc, phbc);
390 if (This->Site)
391 IHlinkSite_ReadyToNavigate(This->Site, This->SiteData, 0);
393 __GetMoniker(This, &mon);
394 TRACE("Moniker %p\n", mon);
396 if (mon)
398 IBindCtx *bcxt;
399 IHlinkTarget *target = NULL;
400 HRESULT r = S_OK;
402 CreateBindCtx(0, &bcxt);
404 RegisterBindStatusCallback(bcxt, pbsc, NULL, 0);
406 r = IMoniker_BindToObject(mon, bcxt, NULL, &IID_IHlinkTarget,
407 (LPVOID*)&target);
408 TRACE("IHlinkTarget returned 0x%x\n", r);
409 if (r == S_OK)
411 IHlinkTarget_SetBrowseContext(target, phbc);
412 IHlinkTarget_Navigate(target, grfHLNF, This->Location);
413 IHlinkTarget_Release(target);
415 else
417 static const WCHAR szOpen[] = {'o','p','e','n',0};
418 LPWSTR target = NULL;
420 r = IHlink_GetStringReference(iface, HLINKGETREF_DEFAULT, &target, NULL);
421 if (SUCCEEDED(r) && target)
423 ShellExecuteW(NULL, szOpen, target, NULL, NULL, SW_SHOW);
424 CoTaskMemFree(target);
428 RevokeBindStatusCallback(bcxt, pbsc);
430 IBindCtx_Release(bcxt);
431 IMoniker_Release(mon);
434 if (This->Site)
435 IHlinkSite_OnNavigationComplete(This->Site, This->SiteData, 0, 0, NULL);
437 TRACE("Finished Navigation\n");
438 return S_OK;
441 static HRESULT WINAPI IHlink_fnSetAdditonalParams(IHlink* iface,
442 LPCWSTR pwzAdditionalParams)
444 TRACE("Not implemented in native IHlink\n");
445 return E_NOTIMPL;
448 static HRESULT WINAPI IHlink_fnGetAdditionalParams(IHlink* iface,
449 LPWSTR* ppwzAdditionalParams)
451 TRACE("Not implemented in native IHlink\n");
452 return E_NOTIMPL;
455 static const IHlinkVtbl hlvt =
457 IHlink_fnQueryInterface,
458 IHlink_fnAddRef,
459 IHlink_fnRelease,
460 IHlink_fnSetHlinkSite,
461 IHlink_fnGetHlinkSite,
462 IHlink_fnSetMonikerReference,
463 IHlink_fnGetMonikerReference,
464 IHlink_fnSetStringReference,
465 IHlink_fnGetStringReference,
466 IHlink_fnSetFriendlyName,
467 IHlink_fnGetFriendlyName,
468 IHlink_fnSetTargetFrameName,
469 IHlink_fnGetTargetFrameName,
470 IHlink_fnGetMiscStatus,
471 IHlink_fnNavigate,
472 IHlink_fnSetAdditonalParams,
473 IHlink_fnGetAdditionalParams
476 static HRESULT WINAPI IDataObject_fnQueryInterface(IDataObject* iface,
477 REFIID riid, LPVOID *ppvObj)
479 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
480 TRACE("%p\n", This);
481 return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
484 static ULONG WINAPI IDataObject_fnAddRef (IDataObject* iface)
486 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
487 TRACE("%p\n", This);
488 return IHlink_AddRef((IHlink*)This);
491 static ULONG WINAPI IDataObject_fnRelease (IDataObject* iface)
493 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
494 TRACE("%p\n", This);
495 return IHlink_Release((IHlink*)This);
498 static HRESULT WINAPI IDataObject_fnGetData(IDataObject* iface,
499 FORMATETC* pformatetcIn, STGMEDIUM* pmedium)
501 FIXME("\n");
502 return E_NOTIMPL;
505 static HRESULT WINAPI IDataObject_fnGetDataHere(IDataObject* iface,
506 FORMATETC* pformatetc, STGMEDIUM* pmedium)
508 FIXME("\n");
509 return E_NOTIMPL;
512 static HRESULT WINAPI IDataObject_fnQueryGetData(IDataObject* iface,
513 FORMATETC* pformatetc)
515 FIXME("\n");
516 return E_NOTIMPL;
519 static HRESULT WINAPI IDataObject_fnGetConicalFormatEtc(IDataObject* iface,
520 FORMATETC* pformatetcIn, FORMATETC* pformatetcOut)
522 FIXME("\n");
523 return E_NOTIMPL;
526 static HRESULT WINAPI IDataObject_fnSetData(IDataObject* iface,
527 FORMATETC* pformatetc, STGMEDIUM* pmedium, BOOL fRelease)
529 FIXME("\n");
530 return E_NOTIMPL;
533 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(IDataObject* iface,
534 DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc)
536 FIXME("\n");
537 return E_NOTIMPL;
540 static HRESULT WINAPI IDataObject_fnDAdvise(IDataObject* iface,
541 FORMATETC* pformatetc, DWORD advf, IAdviseSink* pAdvSink,
542 DWORD* pdwConnection)
544 FIXME("\n");
545 return E_NOTIMPL;
548 static HRESULT WINAPI IDataObject_fnDUnadvise(IDataObject* iface,
549 DWORD dwConnection)
551 FIXME("\n");
552 return E_NOTIMPL;
555 static HRESULT WINAPI IDataObject_fnEnumDAdvise(IDataObject* iface,
556 IEnumSTATDATA** ppenumAdvise)
558 FIXME("\n");
559 return E_NOTIMPL;
562 static const IDataObjectVtbl dovt =
564 IDataObject_fnQueryInterface,
565 IDataObject_fnAddRef,
566 IDataObject_fnRelease,
567 IDataObject_fnGetData,
568 IDataObject_fnGetDataHere,
569 IDataObject_fnQueryGetData,
570 IDataObject_fnGetConicalFormatEtc,
571 IDataObject_fnSetData,
572 IDataObject_fnEnumFormatEtc,
573 IDataObject_fnDAdvise,
574 IDataObject_fnDUnadvise,
575 IDataObject_fnEnumDAdvise
578 static HRESULT WINAPI IPersistStream_fnQueryInterface(IPersistStream* iface,
579 REFIID riid, LPVOID *ppvObj)
581 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
582 TRACE("(%p)\n", This);
583 return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
586 static ULONG WINAPI IPersistStream_fnAddRef (IPersistStream* iface)
588 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
589 TRACE("(%p)\n", This);
590 return IHlink_AddRef((IHlink*)This);
593 static ULONG WINAPI IPersistStream_fnRelease (IPersistStream* iface)
595 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
596 TRACE("(%p)\n", This);
597 return IHlink_Release((IHlink*)This);
600 static HRESULT WINAPI IPersistStream_fnGetClassID(IPersistStream* iface,
601 CLSID* pClassID)
603 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
604 TRACE("(%p)\n", This);
605 *pClassID = CLSID_StdHlink;
606 return S_OK;
609 static HRESULT WINAPI IPersistStream_fnIsDirty(IPersistStream* iface)
611 FIXME("\n");
612 return E_NOTIMPL;
615 static HRESULT write_hlink_string(IStream *pStm, LPCWSTR str)
617 DWORD len;
618 HRESULT hr;
620 TRACE("(%p, %s)\n", pStm, debugstr_w(str));
622 len = strlenW(str) + 1;
624 hr = IStream_Write(pStm, &len, sizeof(len), NULL);
625 if (FAILED(hr)) return hr;
627 hr = IStream_Write(pStm, str, len * sizeof(WCHAR), NULL);
628 if (FAILED(hr)) return hr;
630 return S_OK;
633 static inline ULONG size_hlink_string(LPCWSTR str)
635 return sizeof(DWORD) + (strlenW(str) + 1) * sizeof(WCHAR);
638 static HRESULT read_hlink_string(IStream *pStm, LPWSTR *out_str)
640 LPWSTR str;
641 DWORD len;
642 ULONG read;
643 HRESULT hr;
645 hr = IStream_Read(pStm, &len, sizeof(len), &read);
646 if (FAILED(hr)) return hr;
647 if (read != sizeof(len)) return STG_E_READFAULT;
649 TRACE("read len %d\n", len);
651 str = heap_alloc(len * sizeof(WCHAR));
652 if (!str) return E_OUTOFMEMORY;
654 hr = IStream_Read(pStm, str, len * sizeof(WCHAR), &read);
655 if (FAILED(hr))
657 heap_free(str);
658 return hr;
660 if (read != len * sizeof(WCHAR))
662 heap_free(str);
663 return STG_E_READFAULT;
665 TRACE("read string %s\n", debugstr_w(str));
667 *out_str = str;
668 return S_OK;
671 static HRESULT WINAPI IPersistStream_fnLoad(IPersistStream* iface,
672 IStream* pStm)
674 HRESULT r;
675 DWORD hdr[2];
676 DWORD read;
677 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
679 r = IStream_Read(pStm, hdr, sizeof(hdr), &read);
680 if (read != sizeof(hdr) || (hdr[0] != HLINK_SAVE_MAGIC))
682 r = E_FAIL;
683 goto end;
685 if (hdr[1] & ~HLINK_SAVE_ALL)
686 FIXME("unknown flag(s) 0x%x\n", hdr[1] & ~HLINK_SAVE_ALL);
688 if (hdr[1] & HLINK_SAVE_TARGET_FRAME_PRESENT)
690 TRACE("loading target frame name\n");
691 r = read_hlink_string(pStm, &This->TargetFrameName);
692 if (FAILED(r)) goto end;
695 if (hdr[1] & HLINK_SAVE_FRIENDLY_PRESENT)
697 TRACE("loading target friendly name\n");
698 if (!(hdr[1] & 0x4))
699 FIXME("0x4 flag not present with friendly name flag - not sure what this means\n");
700 r = read_hlink_string(pStm, &This->FriendlyName);
701 if (FAILED(r)) goto end;
704 if (hdr[1] & HLINK_SAVE_MONIKER_PRESENT)
706 TRACE("loading moniker\n");
707 r = OleLoadFromStream(pStm, &IID_IMoniker, (LPVOID*)&(This->Moniker));
708 if (FAILED(r))
709 goto end;
710 This->absolute = hdr[1] & HLINK_SAVE_MONIKER_IS_ABSOLUTE ? TRUE : FALSE;
713 if (hdr[1] & HLINK_SAVE_LOCATION_PRESENT)
715 TRACE("loading location\n");
716 r = read_hlink_string(pStm, &This->Location);
717 if (FAILED(r)) goto end;
720 end:
721 TRACE("Load Result 0x%x (%p)\n", r, This->Moniker);
723 return r;
726 static HRESULT WINAPI IPersistStream_fnSave(IPersistStream* iface,
727 IStream* pStm, BOOL fClearDirty)
729 HRESULT r = E_FAIL;
730 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
731 DWORD hdr[2];
732 IMoniker *moniker;
734 TRACE("(%p) Moniker(%p)\n", This, This->Moniker);
736 __GetMoniker(This, &moniker);
738 hdr[0] = HLINK_SAVE_MAGIC;
739 hdr[1] = 0;
741 if (moniker)
742 hdr[1] |= HLINK_SAVE_MONIKER_PRESENT;
743 if (This->absolute)
744 hdr[1] |= HLINK_SAVE_MONIKER_IS_ABSOLUTE;
745 if (This->Location)
746 hdr[1] |= HLINK_SAVE_LOCATION_PRESENT;
747 if (This->FriendlyName)
748 hdr[1] |= HLINK_SAVE_FRIENDLY_PRESENT | 4 /* FIXME */;
749 if (This->TargetFrameName)
750 hdr[1] |= HLINK_SAVE_TARGET_FRAME_PRESENT;
752 IStream_Write(pStm, hdr, sizeof(hdr), NULL);
754 if (This->TargetFrameName)
756 r = write_hlink_string(pStm, This->TargetFrameName);
757 if (FAILED(r)) goto end;
760 if (This->FriendlyName)
762 r = write_hlink_string(pStm, This->FriendlyName);
763 if (FAILED(r)) goto end;
766 if (moniker)
768 IPersistStream* monstream;
770 monstream = NULL;
771 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
772 (LPVOID*)&monstream);
773 if (monstream)
775 r = OleSaveToStream(monstream, pStm);
776 IPersistStream_Release(monstream);
778 if (FAILED(r)) goto end;
781 if (This->Location)
783 r = write_hlink_string(pStm, This->Location);
784 if (FAILED(r)) goto end;
787 end:
788 if (moniker) IMoniker_Release(moniker);
789 TRACE("Save Result 0x%x\n", r);
791 return r;
794 static HRESULT WINAPI IPersistStream_fnGetSizeMax(IPersistStream* iface,
795 ULARGE_INTEGER* pcbSize)
797 HRESULT r = E_FAIL;
798 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
799 IMoniker *moniker;
801 TRACE("(%p) Moniker(%p)\n", This, This->Moniker);
803 pcbSize->QuadPart = sizeof(DWORD)*2;
805 if (This->TargetFrameName)
806 pcbSize->QuadPart += size_hlink_string(This->TargetFrameName);
808 if (This->FriendlyName)
809 pcbSize->QuadPart += size_hlink_string(This->FriendlyName);
811 __GetMoniker(This, &moniker);
812 if (moniker)
814 IPersistStream* monstream = NULL;
815 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
816 (LPVOID*)&monstream);
817 if (monstream)
819 ULARGE_INTEGER mon_size;
820 r = IPersistStream_GetSizeMax(monstream, &mon_size);
821 pcbSize->QuadPart += mon_size.QuadPart;
822 IPersistStream_Release(monstream);
824 IMoniker_Release(moniker);
827 if (This->Location)
828 pcbSize->QuadPart += size_hlink_string(This->Location);
830 return r;
833 static const IPersistStreamVtbl psvt =
835 IPersistStream_fnQueryInterface,
836 IPersistStream_fnAddRef,
837 IPersistStream_fnRelease,
838 IPersistStream_fnGetClassID,
839 IPersistStream_fnIsDirty,
840 IPersistStream_fnLoad,
841 IPersistStream_fnSave,
842 IPersistStream_fnGetSizeMax,