push 27a9569132e9fc3a545aded7efca0a004a7b7ea9
[wine/hacks.git] / dlls / hlink / link.c
blobc450951ea8ae7d213f12a9b032e65d6503e88067
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 "wine/unicode.h"
37 #include "hlink.h"
38 #include "hlguids.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(hlink);
42 #define HLINK_SAVE_MAGIC 0x00000002
43 #define HLINK_SAVE_MONIKER_PRESENT 0x01
44 #define HLINK_SAVE_MONIKER_IS_ABSOLUTE 0x02
45 #define HLINK_SAVE_LOCATION_PRESENT 0x08
46 #define HLINK_SAVE_FRIENDLY_PRESENT 0x10
47 /* 0x20, 0x40 unknown */
48 #define HLINK_SAVE_TARGET_FRAME_PRESENT 0x80
49 /* known flags */
50 #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)
52 static const IHlinkVtbl hlvt;
53 static const IPersistStreamVtbl psvt;
54 static const IDataObjectVtbl dovt;
56 typedef struct
58 const IHlinkVtbl *lpVtbl;
59 LONG ref;
61 const IPersistStreamVtbl *lpPSVtbl;
62 const IDataObjectVtbl *lpDOVtbl;
64 LPWSTR FriendlyName;
65 LPWSTR Location;
66 LPWSTR Target;
67 LPWSTR TargetFrameName;
68 IMoniker *Moniker;
69 IHlinkSite *Site;
70 DWORD SiteData;
71 BOOL absolute;
72 } HlinkImpl;
75 static inline HlinkImpl* HlinkImpl_from_IPersistStream( IPersistStream* iface)
77 return (HlinkImpl*) ((CHAR*)iface - FIELD_OFFSET(HlinkImpl, lpPSVtbl));
80 static inline HlinkImpl* HlinkImpl_from_IDataObject( IDataObject* iface)
82 return (HlinkImpl*) ((CHAR*)iface - FIELD_OFFSET(HlinkImpl, lpDOVtbl));
85 static inline LPWSTR strdupW( LPCWSTR str )
87 LPWSTR r;
88 UINT len;
90 if (!str)
91 return NULL;
92 len = (lstrlenW(str)+1) * sizeof (WCHAR);
93 r = HeapAlloc(GetProcessHeap(), 0, len);
94 if (r)
95 memcpy(r, str, len);
96 return r;
99 static inline LPWSTR co_strdupW( LPCWSTR str )
101 LPWSTR r;
102 UINT len;
104 if (!str)
105 return NULL;
106 len = (lstrlenW(str)+1) * sizeof (WCHAR);
107 r = CoTaskMemAlloc(len);
108 if (r)
109 memcpy(r, str, len);
110 return r;
113 static inline void __GetMoniker(HlinkImpl* This, IMoniker** moniker)
115 *moniker = NULL;
116 if (This->Moniker)
118 *moniker = This->Moniker;
119 if (*moniker)
120 IMoniker_AddRef(*moniker);
122 else if (This->Site)
124 IHlinkSite_GetMoniker(This->Site, This->SiteData,
125 OLEGETMONIKER_FORCEASSIGN, OLEWHICHMK_CONTAINER,
126 (LPVOID)moniker);
130 HRESULT WINAPI HLink_Constructor(IUnknown *pUnkOuter, REFIID riid,
131 LPVOID *ppv)
133 HlinkImpl * hl;
135 TRACE("unkOut=%p riid=%s\n", pUnkOuter, debugstr_guid(riid));
136 *ppv = NULL;
138 if (pUnkOuter)
139 return CLASS_E_NOAGGREGATION;
141 hl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HlinkImpl));
142 if (!hl)
143 return E_OUTOFMEMORY;
145 hl->ref = 1;
146 hl->lpVtbl = &hlvt;
147 hl->lpPSVtbl = &psvt;
148 hl->lpDOVtbl = &dovt;
150 *ppv = hl;
151 return S_OK;
154 static HRESULT WINAPI IHlink_fnQueryInterface(IHlink* iface, REFIID riid,
155 LPVOID *ppvObj)
157 HlinkImpl *This = (HlinkImpl*)iface;
159 TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppvObj);
161 *ppvObj = NULL;
163 if (IsEqualIID(riid, &IID_IUnknown) || (IsEqualIID(riid, &IID_IHlink)))
164 *ppvObj = This;
165 else if (IsEqualIID(riid, &IID_IPersistStream))
166 *ppvObj = (LPVOID*)&(This->lpPSVtbl);
167 else if (IsEqualIID(riid, &IID_IDataObject))
168 *ppvObj = (LPVOID*)&(This->lpDOVtbl);
170 if (*ppvObj)
172 IUnknown_AddRef((IUnknown*)(*ppvObj));
173 return S_OK;
175 return E_NOINTERFACE;
178 static ULONG WINAPI IHlink_fnAddRef (IHlink* iface)
180 HlinkImpl *This = (HlinkImpl*)iface;
181 ULONG refCount = InterlockedIncrement(&This->ref);
183 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
185 return refCount;
188 static ULONG WINAPI IHlink_fnRelease (IHlink* iface)
190 HlinkImpl *This = (HlinkImpl*)iface;
191 ULONG refCount = InterlockedDecrement(&This->ref);
193 TRACE("(%p)->(count=%u)\n", This, refCount + 1);
194 if (refCount)
195 return refCount;
197 TRACE("-- destroying IHlink (%p)\n", This);
198 HeapFree(GetProcessHeap(), 0, This->FriendlyName);
199 HeapFree(GetProcessHeap(), 0, This->Target);
200 HeapFree(GetProcessHeap(), 0, This->TargetFrameName);
201 HeapFree(GetProcessHeap(), 0, This->Location);
202 if (This->Moniker)
203 IMoniker_Release(This->Moniker);
204 if (This->Site)
205 IHlinkSite_Release(This->Site);
206 HeapFree(GetProcessHeap(), 0, This);
207 return 0;
210 static HRESULT WINAPI IHlink_fnSetHlinkSite( IHlink* iface,
211 IHlinkSite* pihlSite, DWORD dwSiteData)
213 HlinkImpl *This = (HlinkImpl*)iface;
215 TRACE("(%p)->(%p %i)\n", This, pihlSite, dwSiteData);
217 if (This->Site)
218 IHlinkSite_Release(This->Site);
220 This->Site = pihlSite;
221 if (This->Site)
222 IHlinkSite_AddRef(This->Site);
224 This->SiteData = dwSiteData;
226 return S_OK;
229 static HRESULT WINAPI IHlink_fnGetHlinkSite( IHlink* iface,
230 IHlinkSite** ppihlSite, DWORD *pdwSiteData)
232 HlinkImpl *This = (HlinkImpl*)iface;
234 TRACE("(%p)->(%p %p)\n", This, ppihlSite, pdwSiteData);
236 *ppihlSite = This->Site;
237 *pdwSiteData = This->SiteData;
239 if (This->Site)
240 IHlinkSite_AddRef(This->Site);
242 return S_OK;
245 static HRESULT WINAPI IHlink_fnSetMonikerReference( IHlink* iface,
246 DWORD rfHLSETF, IMoniker *pmkTarget, LPCWSTR pwzLocation)
248 HlinkImpl *This = (HlinkImpl*)iface;
250 FIXME("(%p)->(%i %p %s)\n", This, rfHLSETF, pmkTarget,
251 debugstr_w(pwzLocation));
253 if (This->Moniker)
254 IMoniker_Release(This->Moniker);
256 This->Moniker = pmkTarget;
257 if (This->Moniker)
259 LPOLESTR display_name;
260 IMoniker_AddRef(This->Moniker);
261 IMoniker_GetDisplayName(This->Moniker, NULL, NULL, &display_name);
262 This->absolute = display_name && strchrW(display_name, ':');
263 CoTaskMemFree(display_name);
266 HeapFree(GetProcessHeap(), 0, This->Location);
267 This->Location = strdupW( pwzLocation );
269 return S_OK;
272 static HRESULT WINAPI IHlink_fnSetStringReference(IHlink* iface,
273 DWORD grfHLSETF, LPCWSTR pwzTarget, LPCWSTR pwzLocation)
275 HlinkImpl *This = (HlinkImpl*)iface;
277 TRACE("(%p)->(%i %s %s)\n", This, grfHLSETF, debugstr_w(pwzTarget),
278 debugstr_w(pwzLocation));
280 if (grfHLSETF & HLINKSETF_TARGET)
282 HeapFree(GetProcessHeap(), 0, This->Target);
283 This->Target = strdupW( pwzTarget );
285 if (grfHLSETF & HLINKSETF_LOCATION)
287 HeapFree(GetProcessHeap(), 0, This->Location);
288 This->Location = strdupW( pwzLocation );
291 return S_OK;
294 static HRESULT WINAPI IHlink_fnGetMonikerReference(IHlink* iface,
295 DWORD dwWhichRef, IMoniker **ppimkTarget, LPWSTR *ppwzLocation)
297 HlinkImpl *This = (HlinkImpl*)iface;
299 TRACE("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppimkTarget,
300 ppwzLocation);
302 if(ppimkTarget)
303 __GetMoniker(This, ppimkTarget);
305 if (ppwzLocation)
306 IHlink_GetStringReference(iface, dwWhichRef, NULL, ppwzLocation);
308 return S_OK;
311 static HRESULT WINAPI IHlink_fnGetStringReference (IHlink* iface,
312 DWORD dwWhichRef, LPWSTR *ppwzTarget, LPWSTR *ppwzLocation)
314 HlinkImpl *This = (HlinkImpl*)iface;
316 FIXME("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppwzTarget, ppwzLocation);
318 if (ppwzTarget)
320 *ppwzTarget = co_strdupW( This->Target );
322 if (!This->Target)
324 IMoniker* mon;
325 __GetMoniker(This, &mon);
326 if (mon)
328 IBindCtx *pbc;
330 CreateBindCtx( 0, &pbc);
331 IMoniker_GetDisplayName(mon, pbc, NULL, ppwzTarget);
332 IBindCtx_Release(pbc);
333 IMoniker_Release(mon);
335 else
336 FIXME("Unhandled case, no set Target and no moniker\n");
339 if (ppwzLocation)
340 *ppwzLocation = co_strdupW( This->Location );
342 TRACE("(Target: %s Location: %s)\n",
343 (ppwzTarget)?debugstr_w(*ppwzTarget):"<NULL>",
344 (ppwzLocation)?debugstr_w(*ppwzLocation):"<NULL>");
346 return S_OK;
349 static HRESULT WINAPI IHlink_fnSetFriendlyName (IHlink *iface,
350 LPCWSTR pwzFriendlyName)
352 HlinkImpl *This = (HlinkImpl*)iface;
354 TRACE("(%p) -> (%s)\n", This, debugstr_w(pwzFriendlyName));
356 HeapFree(GetProcessHeap(), 0, This->FriendlyName);
357 This->FriendlyName = strdupW( pwzFriendlyName );
359 return S_OK;
362 static HRESULT WINAPI IHlink_fnGetFriendlyName (IHlink* iface,
363 DWORD grfHLFNAMEF, LPWSTR* ppwzFriendlyName)
365 HlinkImpl *This = (HlinkImpl*)iface;
367 TRACE("(%p) -> (%i %p)\n", This, grfHLFNAMEF, ppwzFriendlyName);
369 /* FIXME: Only using explicitly set and cached friendly names */
371 if (This->FriendlyName)
372 *ppwzFriendlyName = co_strdupW( This->FriendlyName );
373 else
375 IMoniker *moniker;
376 __GetMoniker(This, &moniker);
377 if (moniker)
379 IBindCtx *bcxt;
380 CreateBindCtx(0, &bcxt);
382 IMoniker_GetDisplayName(moniker, bcxt, NULL, ppwzFriendlyName);
383 IBindCtx_Release(bcxt);
384 IMoniker_Release(moniker);
386 else
387 *ppwzFriendlyName = NULL;
390 return S_OK;
393 static HRESULT WINAPI IHlink_fnSetTargetFrameName(IHlink* iface,
394 LPCWSTR pwzTargetFramename)
396 HlinkImpl *This = (HlinkImpl*)iface;
397 TRACE("(%p)->(%s)\n", This, debugstr_w(pwzTargetFramename));
399 HeapFree(GetProcessHeap(), 0, This->TargetFrameName);
400 This->TargetFrameName = strdupW( pwzTargetFramename );
402 return S_OK;
405 static HRESULT WINAPI IHlink_fnGetTargetFrameName(IHlink* iface,
406 LPWSTR *ppwzTargetFrameName)
408 HlinkImpl *This = (HlinkImpl*)iface;
410 TRACE("(%p)->(%p)\n", This, ppwzTargetFrameName);
411 *ppwzTargetFrameName = co_strdupW( This->TargetFrameName );
413 return S_OK;
416 static HRESULT WINAPI IHlink_fnGetMiscStatus(IHlink* iface, DWORD* pdwStatus)
418 FIXME("\n");
419 return E_NOTIMPL;
422 static HRESULT WINAPI IHlink_fnNavigate(IHlink* iface, DWORD grfHLNF, LPBC pbc,
423 IBindStatusCallback *pbsc, IHlinkBrowseContext *phbc)
425 HlinkImpl *This = (HlinkImpl*)iface;
426 IMoniker *mon = NULL;
428 FIXME("Semi-Stub:(%p)->(%i %p %p %p)\n", This, grfHLNF, pbc, pbsc, phbc);
430 if (This->Site)
431 IHlinkSite_ReadyToNavigate(This->Site, This->SiteData, 0);
433 __GetMoniker(This, &mon);
434 TRACE("Moniker %p\n", mon);
436 if (mon)
438 IBindCtx *bcxt;
439 IHlinkTarget *target = NULL;
440 HRESULT r = S_OK;
442 CreateBindCtx(0, &bcxt);
444 RegisterBindStatusCallback(bcxt, pbsc, NULL, 0);
446 r = IMoniker_BindToObject(mon, bcxt, NULL, &IID_IHlinkTarget,
447 (LPVOID*)&target);
448 TRACE("IHlinkTarget returned 0x%x\n", r);
449 if (r == S_OK)
451 IHlinkTarget_SetBrowseContext(target, phbc);
452 IHlinkTarget_Navigate(target, grfHLNF, This->Location);
453 IHlinkTarget_Release(target);
455 else
457 static const WCHAR szOpen[] = {'o','p','e','n',0};
458 LPWSTR target = NULL;
460 r = IHlink_GetStringReference(iface, HLINKGETREF_DEFAULT, &target, NULL);
461 if (SUCCEEDED(r) && target)
463 ShellExecuteW(NULL, szOpen, target, NULL, NULL, SW_SHOW);
464 CoTaskMemFree(target);
468 RevokeBindStatusCallback(bcxt, pbsc);
470 IBindCtx_Release(bcxt);
471 IMoniker_Release(mon);
474 if (This->Site)
475 IHlinkSite_OnNavigationComplete(This->Site, This->SiteData, 0, 0, NULL);
477 TRACE("Finished Navigation\n");
478 return S_OK;
481 static HRESULT WINAPI IHlink_fnSetAdditonalParams(IHlink* iface,
482 LPCWSTR pwzAdditionalParams)
484 FIXME("\n");
485 return E_NOTIMPL;
488 static HRESULT WINAPI IHlink_fnGetAdditionalParams(IHlink* iface,
489 LPWSTR* ppwzAdditionalParams)
491 FIXME("\n");
492 return E_NOTIMPL;
495 static const IHlinkVtbl hlvt =
497 IHlink_fnQueryInterface,
498 IHlink_fnAddRef,
499 IHlink_fnRelease,
500 IHlink_fnSetHlinkSite,
501 IHlink_fnGetHlinkSite,
502 IHlink_fnSetMonikerReference,
503 IHlink_fnGetMonikerReference,
504 IHlink_fnSetStringReference,
505 IHlink_fnGetStringReference,
506 IHlink_fnSetFriendlyName,
507 IHlink_fnGetFriendlyName,
508 IHlink_fnSetTargetFrameName,
509 IHlink_fnGetTargetFrameName,
510 IHlink_fnGetMiscStatus,
511 IHlink_fnNavigate,
512 IHlink_fnSetAdditonalParams,
513 IHlink_fnGetAdditionalParams
516 static HRESULT WINAPI IDataObject_fnQueryInterface(IDataObject* iface,
517 REFIID riid, LPVOID *ppvObj)
519 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
520 TRACE("%p\n", This);
521 return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
524 static ULONG WINAPI IDataObject_fnAddRef (IDataObject* iface)
526 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
527 TRACE("%p\n", This);
528 return IHlink_AddRef((IHlink*)This);
531 static ULONG WINAPI IDataObject_fnRelease (IDataObject* iface)
533 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
534 TRACE("%p\n", This);
535 return IHlink_Release((IHlink*)This);
538 static HRESULT WINAPI IDataObject_fnGetData(IDataObject* iface,
539 FORMATETC* pformatetcIn, STGMEDIUM* pmedium)
541 FIXME("\n");
542 return E_NOTIMPL;
545 static HRESULT WINAPI IDataObject_fnGetDataHere(IDataObject* iface,
546 FORMATETC* pformatetc, STGMEDIUM* pmedium)
548 FIXME("\n");
549 return E_NOTIMPL;
552 static HRESULT WINAPI IDataObject_fnQueryGetData(IDataObject* iface,
553 FORMATETC* pformatetc)
555 FIXME("\n");
556 return E_NOTIMPL;
559 static HRESULT WINAPI IDataObject_fnGetConicalFormatEtc(IDataObject* iface,
560 FORMATETC* pformatetcIn, FORMATETC* pformatetcOut)
562 FIXME("\n");
563 return E_NOTIMPL;
566 static HRESULT WINAPI IDataObject_fnSetData(IDataObject* iface,
567 FORMATETC* pformatetc, STGMEDIUM* pmedium, BOOL fRelease)
569 FIXME("\n");
570 return E_NOTIMPL;
573 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(IDataObject* iface,
574 DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc)
576 FIXME("\n");
577 return E_NOTIMPL;
580 static HRESULT WINAPI IDataObject_fnDAdvise(IDataObject* iface,
581 FORMATETC* pformatetc, DWORD advf, IAdviseSink* pAdvSink,
582 DWORD* pdwConnection)
584 FIXME("\n");
585 return E_NOTIMPL;
588 static HRESULT WINAPI IDataObject_fnDUnadvise(IDataObject* iface,
589 DWORD dwConnection)
591 FIXME("\n");
592 return E_NOTIMPL;
595 static HRESULT WINAPI IDataObject_fnEnumDAdvise(IDataObject* iface,
596 IEnumSTATDATA** ppenumAdvise)
598 FIXME("\n");
599 return E_NOTIMPL;
602 static const IDataObjectVtbl dovt =
604 IDataObject_fnQueryInterface,
605 IDataObject_fnAddRef,
606 IDataObject_fnRelease,
607 IDataObject_fnGetData,
608 IDataObject_fnGetDataHere,
609 IDataObject_fnQueryGetData,
610 IDataObject_fnGetConicalFormatEtc,
611 IDataObject_fnSetData,
612 IDataObject_fnEnumFormatEtc,
613 IDataObject_fnDAdvise,
614 IDataObject_fnDUnadvise,
615 IDataObject_fnEnumDAdvise
618 static HRESULT WINAPI IPersistStream_fnQueryInterface(IPersistStream* iface,
619 REFIID riid, LPVOID *ppvObj)
621 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
622 TRACE("(%p)\n", This);
623 return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
626 static ULONG WINAPI IPersistStream_fnAddRef (IPersistStream* iface)
628 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
629 TRACE("(%p)\n", This);
630 return IHlink_AddRef((IHlink*)This);
633 static ULONG WINAPI IPersistStream_fnRelease (IPersistStream* iface)
635 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
636 TRACE("(%p)\n", This);
637 return IHlink_Release((IHlink*)This);
640 static HRESULT WINAPI IPersistStream_fnGetClassID(IPersistStream* iface,
641 CLSID* pClassID)
643 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
644 TRACE("(%p)\n", This);
645 memcpy(pClassID, &CLSID_StdHlink, sizeof(CLSID));
646 return S_OK;
649 static HRESULT WINAPI IPersistStream_fnIsDirty(IPersistStream* iface)
651 FIXME("\n");
652 return E_NOTIMPL;
655 static HRESULT write_hlink_string(IStream *pStm, LPCWSTR str)
657 DWORD len;
658 HRESULT hr;
660 TRACE("(%p, %s)\n", pStm, debugstr_w(str));
662 len = strlenW(str) + 1;
664 hr = IStream_Write(pStm, &len, sizeof(len), NULL);
665 if (FAILED(hr)) return hr;
667 hr = IStream_Write(pStm, str, len * sizeof(WCHAR), NULL);
668 if (FAILED(hr)) return hr;
670 return S_OK;
673 static inline ULONG size_hlink_string(LPCWSTR str)
675 return sizeof(DWORD) + (strlenW(str) + 1) * sizeof(WCHAR);
678 static HRESULT read_hlink_string(IStream *pStm, LPWSTR *out_str)
680 LPWSTR str;
681 DWORD len;
682 ULONG read;
683 HRESULT hr;
685 hr = IStream_Read(pStm, &len, sizeof(len), &read);
686 if (FAILED(hr)) return hr;
687 if (read != sizeof(len)) return STG_E_READFAULT;
689 TRACE("read len %d\n", len);
691 str = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
692 if (!str) return E_OUTOFMEMORY;
694 hr = IStream_Read(pStm, str, len * sizeof(WCHAR), &read);
695 if (FAILED(hr))
697 HeapFree(GetProcessHeap(), 0, str);
698 return hr;
700 if (read != len * sizeof(WCHAR))
702 HeapFree(GetProcessHeap(), 0, str);
703 return STG_E_READFAULT;
705 TRACE("read string %s\n", debugstr_w(str));
707 *out_str = str;
708 return S_OK;
711 static HRESULT WINAPI IPersistStream_fnLoad(IPersistStream* iface,
712 IStream* pStm)
714 HRESULT r;
715 DWORD hdr[2];
716 DWORD read;
717 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
719 r = IStream_Read(pStm, &hdr, sizeof(hdr), &read);
720 if (read != sizeof(hdr) || (hdr[0] != HLINK_SAVE_MAGIC))
722 r = E_FAIL;
723 goto end;
725 if (hdr[1] & ~HLINK_SAVE_ALL)
726 FIXME("unknown flag(s) 0x%x\n", hdr[1] & ~HLINK_SAVE_ALL);
728 if (hdr[1] & HLINK_SAVE_TARGET_FRAME_PRESENT)
730 TRACE("loading target frame name\n");
731 r = read_hlink_string(pStm, &This->TargetFrameName);
732 if (FAILED(r)) goto end;
735 if (hdr[1] & HLINK_SAVE_FRIENDLY_PRESENT)
737 TRACE("loading target friendly name\n");
738 if (!(hdr[1] & 0x4))
739 FIXME("0x4 flag not present with friendly name flag - not sure what this means\n");
740 r = read_hlink_string(pStm, &This->FriendlyName);
741 if (FAILED(r)) goto end;
744 if (hdr[1] & HLINK_SAVE_MONIKER_PRESENT)
746 TRACE("loading moniker\n");
747 r = OleLoadFromStream(pStm, &IID_IMoniker, (LPVOID*)&(This->Moniker));
748 if (FAILED(r))
749 goto end;
750 This->absolute = hdr[1] & HLINK_SAVE_MONIKER_IS_ABSOLUTE ? TRUE : FALSE;
753 if (hdr[1] & HLINK_SAVE_LOCATION_PRESENT)
755 TRACE("loading location\n");
756 r = read_hlink_string(pStm, &This->Location);
757 if (FAILED(r)) goto end;
760 end:
761 TRACE("Load Result 0x%x (%p)\n", r, This->Moniker);
763 return r;
766 static HRESULT WINAPI IPersistStream_fnSave(IPersistStream* iface,
767 IStream* pStm, BOOL fClearDirty)
769 HRESULT r = E_FAIL;
770 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
771 DWORD hdr[2];
772 IMoniker *moniker;
774 TRACE("(%p) Moniker(%p)\n", This, This->Moniker);
776 __GetMoniker(This, &moniker);
778 hdr[0] = HLINK_SAVE_MAGIC;
779 hdr[1] = 0;
781 if (moniker)
782 hdr[1] |= HLINK_SAVE_MONIKER_PRESENT;
783 if (This->absolute)
784 hdr[1] |= HLINK_SAVE_MONIKER_IS_ABSOLUTE;
785 if (This->Location)
786 hdr[1] |= HLINK_SAVE_LOCATION_PRESENT;
787 if (This->FriendlyName)
788 hdr[1] |= HLINK_SAVE_FRIENDLY_PRESENT | 4 /* FIXME */;
789 if (This->TargetFrameName)
790 hdr[1] |= HLINK_SAVE_TARGET_FRAME_PRESENT;
792 IStream_Write(pStm, &hdr, sizeof(hdr), NULL);
794 if (This->TargetFrameName)
796 r = write_hlink_string(pStm, This->TargetFrameName);
797 if (FAILED(r)) goto end;
800 if (This->FriendlyName)
802 r = write_hlink_string(pStm, This->FriendlyName);
803 if (FAILED(r)) goto end;
806 if (moniker)
808 IPersistStream* monstream;
810 monstream = NULL;
811 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
812 (LPVOID*)&monstream);
813 if (monstream)
815 r = OleSaveToStream(monstream, pStm);
816 IPersistStream_Release(monstream);
818 if (FAILED(r)) goto end;
821 if (This->Location)
823 r = write_hlink_string(pStm, This->Location);
824 if (FAILED(r)) goto end;
827 end:
828 if (moniker) IMoniker_Release(moniker);
829 TRACE("Save Result 0x%x\n", r);
831 return r;
834 static HRESULT WINAPI IPersistStream_fnGetSizeMax(IPersistStream* iface,
835 ULARGE_INTEGER* pcbSize)
837 HRESULT r = E_FAIL;
838 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
839 IMoniker *moniker;
841 TRACE("(%p) Moniker(%p)\n", This, This->Moniker);
843 pcbSize->QuadPart = sizeof(DWORD)*2;
845 if (This->TargetFrameName)
846 pcbSize->QuadPart += size_hlink_string(This->TargetFrameName);
848 if (This->FriendlyName)
849 pcbSize->QuadPart += size_hlink_string(This->FriendlyName);
851 __GetMoniker(This, &moniker);
852 if (moniker)
854 IPersistStream* monstream = NULL;
855 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
856 (LPVOID*)&monstream);
857 if (monstream)
859 ULARGE_INTEGER mon_size;
860 r = IPersistStream_GetSizeMax(monstream, &mon_size);
861 pcbSize->QuadPart += mon_size.QuadPart;
862 IPersistStream_Release(monstream);
864 IMoniker_Release(moniker);
867 if (This->Location)
868 pcbSize->QuadPart += size_hlink_string(This->Location);
870 return r;
873 static const IPersistStreamVtbl psvt =
875 IPersistStream_fnQueryInterface,
876 IPersistStream_fnAddRef,
877 IPersistStream_fnRelease,
878 IPersistStream_fnGetClassID,
879 IPersistStream_fnIsDirty,
880 IPersistStream_fnLoad,
881 IPersistStream_fnSave,
882 IPersistStream_fnGetSizeMax,