push 52d6b63ba2f2d4f9b02b6b922d27bff05a60596f
[wine/hacks.git] / dlls / hlink / link.c
blob30530ca715f9f808fde8de91877b10bd204d6afa
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, moniker);
89 HRESULT WINAPI HLink_Constructor(IUnknown *pUnkOuter, REFIID riid,
90 LPVOID *ppv)
92 HlinkImpl * hl;
94 TRACE("unkOut=%p riid=%s\n", pUnkOuter, debugstr_guid(riid));
95 *ppv = NULL;
97 if (pUnkOuter)
98 return CLASS_E_NOAGGREGATION;
100 hl = heap_alloc_zero(sizeof(HlinkImpl));
101 if (!hl)
102 return E_OUTOFMEMORY;
104 hl->ref = 1;
105 hl->lpVtbl = &hlvt;
106 hl->lpPSVtbl = &psvt;
107 hl->lpDOVtbl = &dovt;
109 *ppv = hl;
110 return S_OK;
113 static HRESULT WINAPI IHlink_fnQueryInterface(IHlink* iface, REFIID riid,
114 LPVOID *ppvObj)
116 HlinkImpl *This = (HlinkImpl*)iface;
118 TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppvObj);
120 *ppvObj = NULL;
122 if (IsEqualIID(riid, &IID_IUnknown) || (IsEqualIID(riid, &IID_IHlink)))
123 *ppvObj = This;
124 else if (IsEqualIID(riid, &IID_IPersistStream))
125 *ppvObj = &(This->lpPSVtbl);
126 else if (IsEqualIID(riid, &IID_IDataObject))
127 *ppvObj = &(This->lpDOVtbl);
129 if (*ppvObj)
131 IUnknown_AddRef((IUnknown*)(*ppvObj));
132 return S_OK;
134 return E_NOINTERFACE;
137 static ULONG WINAPI IHlink_fnAddRef (IHlink* iface)
139 HlinkImpl *This = (HlinkImpl*)iface;
140 ULONG refCount = InterlockedIncrement(&This->ref);
142 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
144 return refCount;
147 static ULONG WINAPI IHlink_fnRelease (IHlink* iface)
149 HlinkImpl *This = (HlinkImpl*)iface;
150 ULONG refCount = InterlockedDecrement(&This->ref);
152 TRACE("(%p)->(count=%u)\n", This, refCount + 1);
153 if (refCount)
154 return refCount;
156 TRACE("-- destroying IHlink (%p)\n", This);
157 heap_free(This->FriendlyName);
158 heap_free(This->Target);
159 heap_free(This->TargetFrameName);
160 heap_free(This->Location);
161 if (This->Moniker)
162 IMoniker_Release(This->Moniker);
163 if (This->Site)
164 IHlinkSite_Release(This->Site);
165 heap_free(This);
166 return 0;
169 static HRESULT WINAPI IHlink_fnSetHlinkSite( IHlink* iface,
170 IHlinkSite* pihlSite, DWORD dwSiteData)
172 HlinkImpl *This = (HlinkImpl*)iface;
174 TRACE("(%p)->(%p %i)\n", This, pihlSite, dwSiteData);
176 if (This->Site)
177 IHlinkSite_Release(This->Site);
179 This->Site = pihlSite;
180 if (This->Site)
181 IHlinkSite_AddRef(This->Site);
183 This->SiteData = dwSiteData;
185 return S_OK;
188 static HRESULT WINAPI IHlink_fnGetHlinkSite( IHlink* iface,
189 IHlinkSite** ppihlSite, DWORD *pdwSiteData)
191 HlinkImpl *This = (HlinkImpl*)iface;
193 TRACE("(%p)->(%p %p)\n", This, ppihlSite, pdwSiteData);
195 *ppihlSite = This->Site;
196 *pdwSiteData = This->SiteData;
198 if (This->Site)
199 IHlinkSite_AddRef(This->Site);
201 return S_OK;
204 static HRESULT WINAPI IHlink_fnSetMonikerReference( IHlink* iface,
205 DWORD rfHLSETF, IMoniker *pmkTarget, LPCWSTR pwzLocation)
207 HlinkImpl *This = (HlinkImpl*)iface;
209 TRACE("(%p)->(%i %p %s)\n", This, rfHLSETF, pmkTarget,
210 debugstr_w(pwzLocation));
212 if(rfHLSETF == 0)
213 return E_INVALIDARG;
214 if(!(rfHLSETF & (HLINKSETF_TARGET | HLINKSETF_LOCATION)))
215 return rfHLSETF;
217 if(rfHLSETF & HLINKSETF_TARGET){
218 if (This->Moniker)
219 IMoniker_Release(This->Moniker);
221 This->Moniker = pmkTarget;
222 if (This->Moniker)
224 LPOLESTR display_name;
225 IMoniker_AddRef(This->Moniker);
226 IMoniker_GetDisplayName(This->Moniker, NULL, NULL, &display_name);
227 This->absolute = display_name && strchrW(display_name, ':');
228 CoTaskMemFree(display_name);
232 if(rfHLSETF & HLINKSETF_LOCATION){
233 heap_free(This->Location);
234 This->Location = hlink_strdupW( pwzLocation );
237 return S_OK;
240 static HRESULT WINAPI IHlink_fnSetStringReference(IHlink* iface,
241 DWORD grfHLSETF, LPCWSTR pwzTarget, LPCWSTR pwzLocation)
243 HlinkImpl *This = (HlinkImpl*)iface;
245 TRACE("(%p)->(%i %s %s)\n", This, grfHLSETF, debugstr_w(pwzTarget),
246 debugstr_w(pwzLocation));
248 if (grfHLSETF & HLINKSETF_TARGET)
250 heap_free(This->Target);
251 This->Target = hlink_strdupW( pwzTarget );
253 if (grfHLSETF & HLINKSETF_LOCATION)
255 heap_free(This->Location);
256 This->Location = hlink_strdupW( pwzLocation );
259 return S_OK;
262 static HRESULT WINAPI IHlink_fnGetMonikerReference(IHlink* iface,
263 DWORD dwWhichRef, IMoniker **ppimkTarget, LPWSTR *ppwzLocation)
265 HlinkImpl *This = (HlinkImpl*)iface;
267 TRACE("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppimkTarget,
268 ppwzLocation);
270 if(ppimkTarget)
271 __GetMoniker(This, ppimkTarget);
273 if (ppwzLocation)
274 IHlink_GetStringReference(iface, dwWhichRef, NULL, ppwzLocation);
276 return S_OK;
279 static HRESULT WINAPI IHlink_fnGetStringReference (IHlink* iface,
280 DWORD dwWhichRef, LPWSTR *ppwzTarget, LPWSTR *ppwzLocation)
282 HlinkImpl *This = (HlinkImpl*)iface;
284 FIXME("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppwzTarget, ppwzLocation);
286 if (ppwzTarget)
288 *ppwzTarget = hlink_co_strdupW( This->Target );
290 if (!This->Target)
292 IMoniker* mon;
293 __GetMoniker(This, &mon);
294 if (mon)
296 IBindCtx *pbc;
298 CreateBindCtx( 0, &pbc);
299 IMoniker_GetDisplayName(mon, pbc, NULL, ppwzTarget);
300 IBindCtx_Release(pbc);
301 IMoniker_Release(mon);
303 else
304 FIXME("Unhandled case, no set Target and no moniker\n");
307 if (ppwzLocation)
308 *ppwzLocation = hlink_co_strdupW( This->Location );
310 TRACE("(Target: %s Location: %s)\n",
311 (ppwzTarget)?debugstr_w(*ppwzTarget):"<NULL>",
312 (ppwzLocation)?debugstr_w(*ppwzLocation):"<NULL>");
314 return S_OK;
317 static HRESULT WINAPI IHlink_fnSetFriendlyName (IHlink *iface,
318 LPCWSTR pwzFriendlyName)
320 HlinkImpl *This = (HlinkImpl*)iface;
322 TRACE("(%p) -> (%s)\n", This, debugstr_w(pwzFriendlyName));
324 heap_free(This->FriendlyName);
325 This->FriendlyName = hlink_strdupW( pwzFriendlyName );
327 return S_OK;
330 static HRESULT WINAPI IHlink_fnGetFriendlyName (IHlink* iface,
331 DWORD grfHLFNAMEF, LPWSTR* ppwzFriendlyName)
333 HlinkImpl *This = (HlinkImpl*)iface;
335 TRACE("(%p) -> (%i %p)\n", This, grfHLFNAMEF, ppwzFriendlyName);
337 /* FIXME: Only using explicitly set and cached friendly names */
339 if (This->FriendlyName)
340 *ppwzFriendlyName = hlink_co_strdupW( This->FriendlyName );
341 else
343 IMoniker *moniker;
344 __GetMoniker(This, &moniker);
345 if (moniker)
347 IBindCtx *bcxt;
348 CreateBindCtx(0, &bcxt);
350 IMoniker_GetDisplayName(moniker, bcxt, NULL, ppwzFriendlyName);
351 IBindCtx_Release(bcxt);
352 IMoniker_Release(moniker);
354 else
355 *ppwzFriendlyName = NULL;
358 return S_OK;
361 static HRESULT WINAPI IHlink_fnSetTargetFrameName(IHlink* iface,
362 LPCWSTR pwzTargetFramename)
364 HlinkImpl *This = (HlinkImpl*)iface;
365 TRACE("(%p)->(%s)\n", This, debugstr_w(pwzTargetFramename));
367 heap_free(This->TargetFrameName);
368 This->TargetFrameName = hlink_strdupW( pwzTargetFramename );
370 return S_OK;
373 static HRESULT WINAPI IHlink_fnGetTargetFrameName(IHlink* iface,
374 LPWSTR *ppwzTargetFrameName)
376 HlinkImpl *This = (HlinkImpl*)iface;
378 TRACE("(%p)->(%p)\n", This, ppwzTargetFrameName);
379 *ppwzTargetFrameName = hlink_co_strdupW( This->TargetFrameName );
381 return S_OK;
384 static HRESULT WINAPI IHlink_fnGetMiscStatus(IHlink* iface, DWORD* pdwStatus)
386 FIXME("\n");
387 return E_NOTIMPL;
390 static HRESULT WINAPI IHlink_fnNavigate(IHlink* iface, DWORD grfHLNF, LPBC pbc,
391 IBindStatusCallback *pbsc, IHlinkBrowseContext *phbc)
393 HlinkImpl *This = (HlinkImpl*)iface;
394 IMoniker *mon = NULL;
396 FIXME("Semi-Stub:(%p)->(%i %p %p %p)\n", This, grfHLNF, pbc, pbsc, phbc);
398 if (This->Site)
399 IHlinkSite_ReadyToNavigate(This->Site, This->SiteData, 0);
401 __GetMoniker(This, &mon);
402 TRACE("Moniker %p\n", mon);
404 if (mon)
406 IBindCtx *bcxt;
407 IHlinkTarget *target = NULL;
408 HRESULT r = S_OK;
410 CreateBindCtx(0, &bcxt);
412 RegisterBindStatusCallback(bcxt, pbsc, NULL, 0);
414 r = IMoniker_BindToObject(mon, bcxt, NULL, &IID_IHlinkTarget,
415 (LPVOID*)&target);
416 TRACE("IHlinkTarget returned 0x%x\n", r);
417 if (r == S_OK)
419 IHlinkTarget_SetBrowseContext(target, phbc);
420 IHlinkTarget_Navigate(target, grfHLNF, This->Location);
421 IHlinkTarget_Release(target);
423 else
425 static const WCHAR szOpen[] = {'o','p','e','n',0};
426 LPWSTR target = NULL;
428 r = IHlink_GetStringReference(iface, HLINKGETREF_DEFAULT, &target, NULL);
429 if (SUCCEEDED(r) && target)
431 ShellExecuteW(NULL, szOpen, target, NULL, NULL, SW_SHOW);
432 CoTaskMemFree(target);
436 RevokeBindStatusCallback(bcxt, pbsc);
438 IBindCtx_Release(bcxt);
439 IMoniker_Release(mon);
442 if (This->Site)
443 IHlinkSite_OnNavigationComplete(This->Site, This->SiteData, 0, 0, NULL);
445 TRACE("Finished Navigation\n");
446 return S_OK;
449 static HRESULT WINAPI IHlink_fnSetAdditonalParams(IHlink* iface,
450 LPCWSTR pwzAdditionalParams)
452 TRACE("Not implemented in native IHlink\n");
453 return E_NOTIMPL;
456 static HRESULT WINAPI IHlink_fnGetAdditionalParams(IHlink* iface,
457 LPWSTR* ppwzAdditionalParams)
459 TRACE("Not implemented in native IHlink\n");
460 return E_NOTIMPL;
463 static const IHlinkVtbl hlvt =
465 IHlink_fnQueryInterface,
466 IHlink_fnAddRef,
467 IHlink_fnRelease,
468 IHlink_fnSetHlinkSite,
469 IHlink_fnGetHlinkSite,
470 IHlink_fnSetMonikerReference,
471 IHlink_fnGetMonikerReference,
472 IHlink_fnSetStringReference,
473 IHlink_fnGetStringReference,
474 IHlink_fnSetFriendlyName,
475 IHlink_fnGetFriendlyName,
476 IHlink_fnSetTargetFrameName,
477 IHlink_fnGetTargetFrameName,
478 IHlink_fnGetMiscStatus,
479 IHlink_fnNavigate,
480 IHlink_fnSetAdditonalParams,
481 IHlink_fnGetAdditionalParams
484 static HRESULT WINAPI IDataObject_fnQueryInterface(IDataObject* iface,
485 REFIID riid, LPVOID *ppvObj)
487 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
488 TRACE("%p\n", This);
489 return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
492 static ULONG WINAPI IDataObject_fnAddRef (IDataObject* iface)
494 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
495 TRACE("%p\n", This);
496 return IHlink_AddRef((IHlink*)This);
499 static ULONG WINAPI IDataObject_fnRelease (IDataObject* iface)
501 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
502 TRACE("%p\n", This);
503 return IHlink_Release((IHlink*)This);
506 static HRESULT WINAPI IDataObject_fnGetData(IDataObject* iface,
507 FORMATETC* pformatetcIn, STGMEDIUM* pmedium)
509 FIXME("\n");
510 return E_NOTIMPL;
513 static HRESULT WINAPI IDataObject_fnGetDataHere(IDataObject* iface,
514 FORMATETC* pformatetc, STGMEDIUM* pmedium)
516 FIXME("\n");
517 return E_NOTIMPL;
520 static HRESULT WINAPI IDataObject_fnQueryGetData(IDataObject* iface,
521 FORMATETC* pformatetc)
523 FIXME("\n");
524 return E_NOTIMPL;
527 static HRESULT WINAPI IDataObject_fnGetConicalFormatEtc(IDataObject* iface,
528 FORMATETC* pformatetcIn, FORMATETC* pformatetcOut)
530 FIXME("\n");
531 return E_NOTIMPL;
534 static HRESULT WINAPI IDataObject_fnSetData(IDataObject* iface,
535 FORMATETC* pformatetc, STGMEDIUM* pmedium, BOOL fRelease)
537 FIXME("\n");
538 return E_NOTIMPL;
541 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(IDataObject* iface,
542 DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc)
544 FIXME("\n");
545 return E_NOTIMPL;
548 static HRESULT WINAPI IDataObject_fnDAdvise(IDataObject* iface,
549 FORMATETC* pformatetc, DWORD advf, IAdviseSink* pAdvSink,
550 DWORD* pdwConnection)
552 FIXME("\n");
553 return E_NOTIMPL;
556 static HRESULT WINAPI IDataObject_fnDUnadvise(IDataObject* iface,
557 DWORD dwConnection)
559 FIXME("\n");
560 return E_NOTIMPL;
563 static HRESULT WINAPI IDataObject_fnEnumDAdvise(IDataObject* iface,
564 IEnumSTATDATA** ppenumAdvise)
566 FIXME("\n");
567 return E_NOTIMPL;
570 static const IDataObjectVtbl dovt =
572 IDataObject_fnQueryInterface,
573 IDataObject_fnAddRef,
574 IDataObject_fnRelease,
575 IDataObject_fnGetData,
576 IDataObject_fnGetDataHere,
577 IDataObject_fnQueryGetData,
578 IDataObject_fnGetConicalFormatEtc,
579 IDataObject_fnSetData,
580 IDataObject_fnEnumFormatEtc,
581 IDataObject_fnDAdvise,
582 IDataObject_fnDUnadvise,
583 IDataObject_fnEnumDAdvise
586 static HRESULT WINAPI IPersistStream_fnQueryInterface(IPersistStream* iface,
587 REFIID riid, LPVOID *ppvObj)
589 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
590 TRACE("(%p)\n", This);
591 return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
594 static ULONG WINAPI IPersistStream_fnAddRef (IPersistStream* iface)
596 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
597 TRACE("(%p)\n", This);
598 return IHlink_AddRef((IHlink*)This);
601 static ULONG WINAPI IPersistStream_fnRelease (IPersistStream* iface)
603 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
604 TRACE("(%p)\n", This);
605 return IHlink_Release((IHlink*)This);
608 static HRESULT WINAPI IPersistStream_fnGetClassID(IPersistStream* iface,
609 CLSID* pClassID)
611 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
612 TRACE("(%p)\n", This);
613 *pClassID = CLSID_StdHlink;
614 return S_OK;
617 static HRESULT WINAPI IPersistStream_fnIsDirty(IPersistStream* iface)
619 FIXME("\n");
620 return E_NOTIMPL;
623 static HRESULT write_hlink_string(IStream *pStm, LPCWSTR str)
625 DWORD len;
626 HRESULT hr;
628 TRACE("(%p, %s)\n", pStm, debugstr_w(str));
630 len = strlenW(str) + 1;
632 hr = IStream_Write(pStm, &len, sizeof(len), NULL);
633 if (FAILED(hr)) return hr;
635 hr = IStream_Write(pStm, str, len * sizeof(WCHAR), NULL);
636 if (FAILED(hr)) return hr;
638 return S_OK;
641 static inline ULONG size_hlink_string(LPCWSTR str)
643 return sizeof(DWORD) + (strlenW(str) + 1) * sizeof(WCHAR);
646 static HRESULT read_hlink_string(IStream *pStm, LPWSTR *out_str)
648 LPWSTR str;
649 DWORD len;
650 ULONG read;
651 HRESULT hr;
653 hr = IStream_Read(pStm, &len, sizeof(len), &read);
654 if (FAILED(hr)) return hr;
655 if (read != sizeof(len)) return STG_E_READFAULT;
657 TRACE("read len %d\n", len);
659 str = heap_alloc(len * sizeof(WCHAR));
660 if (!str) return E_OUTOFMEMORY;
662 hr = IStream_Read(pStm, str, len * sizeof(WCHAR), &read);
663 if (FAILED(hr))
665 heap_free(str);
666 return hr;
668 if (read != len * sizeof(WCHAR))
670 heap_free(str);
671 return STG_E_READFAULT;
673 TRACE("read string %s\n", debugstr_w(str));
675 *out_str = str;
676 return S_OK;
679 static HRESULT WINAPI IPersistStream_fnLoad(IPersistStream* iface,
680 IStream* pStm)
682 HRESULT r;
683 DWORD hdr[2];
684 DWORD read;
685 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
687 r = IStream_Read(pStm, hdr, sizeof(hdr), &read);
688 if (read != sizeof(hdr) || (hdr[0] != HLINK_SAVE_MAGIC))
690 r = E_FAIL;
691 goto end;
693 if (hdr[1] & ~HLINK_SAVE_ALL)
694 FIXME("unknown flag(s) 0x%x\n", hdr[1] & ~HLINK_SAVE_ALL);
696 if (hdr[1] & HLINK_SAVE_TARGET_FRAME_PRESENT)
698 TRACE("loading target frame name\n");
699 r = read_hlink_string(pStm, &This->TargetFrameName);
700 if (FAILED(r)) goto end;
703 if (hdr[1] & HLINK_SAVE_FRIENDLY_PRESENT)
705 TRACE("loading target friendly name\n");
706 if (!(hdr[1] & 0x4))
707 FIXME("0x4 flag not present with friendly name flag - not sure what this means\n");
708 r = read_hlink_string(pStm, &This->FriendlyName);
709 if (FAILED(r)) goto end;
712 if (hdr[1] & HLINK_SAVE_MONIKER_PRESENT)
714 TRACE("loading moniker\n");
715 r = OleLoadFromStream(pStm, &IID_IMoniker, (LPVOID*)&(This->Moniker));
716 if (FAILED(r))
717 goto end;
718 This->absolute = hdr[1] & HLINK_SAVE_MONIKER_IS_ABSOLUTE ? TRUE : FALSE;
721 if (hdr[1] & HLINK_SAVE_LOCATION_PRESENT)
723 TRACE("loading location\n");
724 r = read_hlink_string(pStm, &This->Location);
725 if (FAILED(r)) goto end;
728 end:
729 TRACE("Load Result 0x%x (%p)\n", r, This->Moniker);
731 return r;
734 static HRESULT WINAPI IPersistStream_fnSave(IPersistStream* iface,
735 IStream* pStm, BOOL fClearDirty)
737 HRESULT r = E_FAIL;
738 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
739 DWORD hdr[2];
740 IMoniker *moniker;
742 TRACE("(%p) Moniker(%p)\n", This, This->Moniker);
744 __GetMoniker(This, &moniker);
746 hdr[0] = HLINK_SAVE_MAGIC;
747 hdr[1] = 0;
749 if (moniker)
750 hdr[1] |= HLINK_SAVE_MONIKER_PRESENT;
751 if (This->absolute)
752 hdr[1] |= HLINK_SAVE_MONIKER_IS_ABSOLUTE;
753 if (This->Location)
754 hdr[1] |= HLINK_SAVE_LOCATION_PRESENT;
755 if (This->FriendlyName)
756 hdr[1] |= HLINK_SAVE_FRIENDLY_PRESENT | 4 /* FIXME */;
757 if (This->TargetFrameName)
758 hdr[1] |= HLINK_SAVE_TARGET_FRAME_PRESENT;
760 IStream_Write(pStm, hdr, sizeof(hdr), NULL);
762 if (This->TargetFrameName)
764 r = write_hlink_string(pStm, This->TargetFrameName);
765 if (FAILED(r)) goto end;
768 if (This->FriendlyName)
770 r = write_hlink_string(pStm, This->FriendlyName);
771 if (FAILED(r)) goto end;
774 if (moniker)
776 IPersistStream* monstream;
778 monstream = NULL;
779 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
780 (LPVOID*)&monstream);
781 if (monstream)
783 r = OleSaveToStream(monstream, pStm);
784 IPersistStream_Release(monstream);
786 if (FAILED(r)) goto end;
789 if (This->Location)
791 r = write_hlink_string(pStm, This->Location);
792 if (FAILED(r)) goto end;
795 end:
796 if (moniker) IMoniker_Release(moniker);
797 TRACE("Save Result 0x%x\n", r);
799 return r;
802 static HRESULT WINAPI IPersistStream_fnGetSizeMax(IPersistStream* iface,
803 ULARGE_INTEGER* pcbSize)
805 HRESULT r = E_FAIL;
806 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
807 IMoniker *moniker;
809 TRACE("(%p) Moniker(%p)\n", This, This->Moniker);
811 pcbSize->QuadPart = sizeof(DWORD)*2;
813 if (This->TargetFrameName)
814 pcbSize->QuadPart += size_hlink_string(This->TargetFrameName);
816 if (This->FriendlyName)
817 pcbSize->QuadPart += size_hlink_string(This->FriendlyName);
819 __GetMoniker(This, &moniker);
820 if (moniker)
822 IPersistStream* monstream = NULL;
823 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
824 (LPVOID*)&monstream);
825 if (monstream)
827 ULARGE_INTEGER mon_size;
828 r = IPersistStream_GetSizeMax(monstream, &mon_size);
829 pcbSize->QuadPart += mon_size.QuadPart;
830 IPersistStream_Release(monstream);
832 IMoniker_Release(moniker);
835 if (This->Location)
836 pcbSize->QuadPart += size_hlink_string(This->Location);
838 return r;
841 static const IPersistStreamVtbl psvt =
843 IPersistStream_fnQueryInterface,
844 IPersistStream_fnAddRef,
845 IPersistStream_fnRelease,
846 IPersistStream_fnGetClassID,
847 IPersistStream_fnIsDirty,
848 IPersistStream_fnLoad,
849 IPersistStream_fnSave,
850 IPersistStream_fnGetSizeMax,