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"
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
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;
46 const IHlinkVtbl *lpVtbl;
49 const IPersistStreamVtbl *lpPSVtbl;
50 const IDataObjectVtbl *lpDOVtbl;
55 LPWSTR TargetFrameName;
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)
78 *moniker = This->Moniker;
80 IMoniker_AddRef(*moniker);
84 IHlinkSite_GetMoniker(This->Site, This->SiteData,
85 OLEGETMONIKER_FORCEASSIGN, OLEWHICHMK_CONTAINER, moniker);
89 HRESULT WINAPI HLink_Constructor(IUnknown *pUnkOuter, REFIID riid,
94 TRACE("unkOut=%p riid=%s\n", pUnkOuter, debugstr_guid(riid));
98 return CLASS_E_NOAGGREGATION;
100 hl = heap_alloc_zero(sizeof(HlinkImpl));
102 return E_OUTOFMEMORY;
106 hl->lpPSVtbl = &psvt;
107 hl->lpDOVtbl = &dovt;
113 static HRESULT WINAPI IHlink_fnQueryInterface(IHlink* iface, REFIID riid,
116 HlinkImpl *This = (HlinkImpl*)iface;
118 TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppvObj);
122 if (IsEqualIID(riid, &IID_IUnknown) || (IsEqualIID(riid, &IID_IHlink)))
124 else if (IsEqualIID(riid, &IID_IPersistStream))
125 *ppvObj = &(This->lpPSVtbl);
126 else if (IsEqualIID(riid, &IID_IDataObject))
127 *ppvObj = &(This->lpDOVtbl);
131 IUnknown_AddRef((IUnknown*)(*ppvObj));
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);
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);
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);
162 IMoniker_Release(This->Moniker);
164 IHlinkSite_Release(This->Site);
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);
177 IHlinkSite_Release(This->Site);
179 This->Site = pihlSite;
181 IHlinkSite_AddRef(This->Site);
183 This->SiteData = dwSiteData;
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;
199 IHlinkSite_AddRef(This->Site);
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));
214 if(!(rfHLSETF & (HLINKSETF_TARGET | HLINKSETF_LOCATION)))
217 if(rfHLSETF & HLINKSETF_TARGET){
219 IMoniker_Release(This->Moniker);
221 This->Moniker = pmkTarget;
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 );
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 | HLINKSETF_LOCATION) &&
249 grfHLSETF < -(HLINKSETF_TARGET | HLINKSETF_LOCATION))
252 if (grfHLSETF & HLINKSETF_TARGET)
254 heap_free(This->Target);
255 This->Target = hlink_strdupW( pwzTarget );
257 if (grfHLSETF & HLINKSETF_LOCATION)
259 heap_free(This->Location);
260 This->Location = hlink_strdupW( pwzLocation );
266 static HRESULT WINAPI IHlink_fnGetMonikerReference(IHlink* iface,
267 DWORD dwWhichRef, IMoniker **ppimkTarget, LPWSTR *ppwzLocation)
269 HlinkImpl *This = (HlinkImpl*)iface;
271 TRACE("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppimkTarget,
275 __GetMoniker(This, ppimkTarget);
278 IHlink_GetStringReference(iface, dwWhichRef, NULL, ppwzLocation);
283 static HRESULT WINAPI IHlink_fnGetStringReference (IHlink* iface,
284 DWORD dwWhichRef, LPWSTR *ppwzTarget, LPWSTR *ppwzLocation)
286 HlinkImpl *This = (HlinkImpl*)iface;
288 TRACE("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppwzTarget, ppwzLocation);
290 /* note: undocumented behavior with dwWhichRef == -1 */
291 if(dwWhichRef != -1 && dwWhichRef & ~(HLINKGETREF_DEFAULT | HLINKGETREF_ABSOLUTE | HLINKGETREF_RELATIVE))
296 *ppwzLocation = NULL;
300 if(dwWhichRef != HLINKGETREF_DEFAULT)
301 FIXME("unhandled flags: 0x%x\n", dwWhichRef);
305 *ppwzTarget = hlink_co_strdupW( This->Target );
310 __GetMoniker(This, &mon);
315 CreateBindCtx( 0, &pbc);
316 IMoniker_GetDisplayName(mon, pbc, NULL, ppwzTarget);
317 IBindCtx_Release(pbc);
318 IMoniker_Release(mon);
323 *ppwzLocation = hlink_co_strdupW( This->Location );
325 TRACE("(Target: %s Location: %s)\n",
326 (ppwzTarget)?debugstr_w(*ppwzTarget):"<NULL>",
327 (ppwzLocation)?debugstr_w(*ppwzLocation):"<NULL>");
332 static HRESULT WINAPI IHlink_fnSetFriendlyName (IHlink *iface,
333 LPCWSTR pwzFriendlyName)
335 HlinkImpl *This = (HlinkImpl*)iface;
337 TRACE("(%p) -> (%s)\n", This, debugstr_w(pwzFriendlyName));
339 heap_free(This->FriendlyName);
340 This->FriendlyName = hlink_strdupW( pwzFriendlyName );
345 static HRESULT WINAPI IHlink_fnGetFriendlyName (IHlink* iface,
346 DWORD grfHLFNAMEF, LPWSTR* ppwzFriendlyName)
348 HlinkImpl *This = (HlinkImpl*)iface;
350 TRACE("(%p) -> (%i %p)\n", This, grfHLFNAMEF, ppwzFriendlyName);
352 /* FIXME: Only using explicitly set and cached friendly names */
354 if (This->FriendlyName)
355 *ppwzFriendlyName = hlink_co_strdupW( This->FriendlyName );
359 __GetMoniker(This, &moniker);
363 CreateBindCtx(0, &bcxt);
365 IMoniker_GetDisplayName(moniker, bcxt, NULL, ppwzFriendlyName);
366 IBindCtx_Release(bcxt);
367 IMoniker_Release(moniker);
370 *ppwzFriendlyName = NULL;
376 static HRESULT WINAPI IHlink_fnSetTargetFrameName(IHlink* iface,
377 LPCWSTR pwzTargetFramename)
379 HlinkImpl *This = (HlinkImpl*)iface;
380 TRACE("(%p)->(%s)\n", This, debugstr_w(pwzTargetFramename));
382 heap_free(This->TargetFrameName);
383 This->TargetFrameName = hlink_strdupW( pwzTargetFramename );
388 static HRESULT WINAPI IHlink_fnGetTargetFrameName(IHlink* iface,
389 LPWSTR *ppwzTargetFrameName)
391 HlinkImpl *This = (HlinkImpl*)iface;
393 TRACE("(%p)->(%p)\n", This, ppwzTargetFrameName);
394 *ppwzTargetFrameName = hlink_co_strdupW( This->TargetFrameName );
399 static HRESULT WINAPI IHlink_fnGetMiscStatus(IHlink* iface, DWORD* pdwStatus)
405 static HRESULT WINAPI IHlink_fnNavigate(IHlink* iface, DWORD grfHLNF, LPBC pbc,
406 IBindStatusCallback *pbsc, IHlinkBrowseContext *phbc)
408 HlinkImpl *This = (HlinkImpl*)iface;
409 IMoniker *mon = NULL;
411 FIXME("Semi-Stub:(%p)->(%i %p %p %p)\n", This, grfHLNF, pbc, pbsc, phbc);
414 IHlinkSite_ReadyToNavigate(This->Site, This->SiteData, 0);
416 __GetMoniker(This, &mon);
417 TRACE("Moniker %p\n", mon);
422 IHlinkTarget *target = NULL;
425 CreateBindCtx(0, &bcxt);
427 RegisterBindStatusCallback(bcxt, pbsc, NULL, 0);
429 r = IMoniker_BindToObject(mon, bcxt, NULL, &IID_IHlinkTarget,
431 TRACE("IHlinkTarget returned 0x%x\n", r);
434 IHlinkTarget_SetBrowseContext(target, phbc);
435 IHlinkTarget_Navigate(target, grfHLNF, This->Location);
436 IHlinkTarget_Release(target);
440 static const WCHAR szOpen[] = {'o','p','e','n',0};
441 LPWSTR target = NULL;
443 r = IHlink_GetStringReference(iface, HLINKGETREF_DEFAULT, &target, NULL);
444 if (SUCCEEDED(r) && target)
446 ShellExecuteW(NULL, szOpen, target, NULL, NULL, SW_SHOW);
447 CoTaskMemFree(target);
451 RevokeBindStatusCallback(bcxt, pbsc);
453 IBindCtx_Release(bcxt);
454 IMoniker_Release(mon);
458 IHlinkSite_OnNavigationComplete(This->Site, This->SiteData, 0, 0, NULL);
460 TRACE("Finished Navigation\n");
464 static HRESULT WINAPI IHlink_fnSetAdditonalParams(IHlink* iface,
465 LPCWSTR pwzAdditionalParams)
467 TRACE("Not implemented in native IHlink\n");
471 static HRESULT WINAPI IHlink_fnGetAdditionalParams(IHlink* iface,
472 LPWSTR* ppwzAdditionalParams)
474 TRACE("Not implemented in native IHlink\n");
478 static const IHlinkVtbl hlvt =
480 IHlink_fnQueryInterface,
483 IHlink_fnSetHlinkSite,
484 IHlink_fnGetHlinkSite,
485 IHlink_fnSetMonikerReference,
486 IHlink_fnGetMonikerReference,
487 IHlink_fnSetStringReference,
488 IHlink_fnGetStringReference,
489 IHlink_fnSetFriendlyName,
490 IHlink_fnGetFriendlyName,
491 IHlink_fnSetTargetFrameName,
492 IHlink_fnGetTargetFrameName,
493 IHlink_fnGetMiscStatus,
495 IHlink_fnSetAdditonalParams,
496 IHlink_fnGetAdditionalParams
499 static HRESULT WINAPI IDataObject_fnQueryInterface(IDataObject* iface,
500 REFIID riid, LPVOID *ppvObj)
502 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
504 return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
507 static ULONG WINAPI IDataObject_fnAddRef (IDataObject* iface)
509 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
511 return IHlink_AddRef((IHlink*)This);
514 static ULONG WINAPI IDataObject_fnRelease (IDataObject* iface)
516 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
518 return IHlink_Release((IHlink*)This);
521 static HRESULT WINAPI IDataObject_fnGetData(IDataObject* iface,
522 FORMATETC* pformatetcIn, STGMEDIUM* pmedium)
528 static HRESULT WINAPI IDataObject_fnGetDataHere(IDataObject* iface,
529 FORMATETC* pformatetc, STGMEDIUM* pmedium)
535 static HRESULT WINAPI IDataObject_fnQueryGetData(IDataObject* iface,
536 FORMATETC* pformatetc)
542 static HRESULT WINAPI IDataObject_fnGetConicalFormatEtc(IDataObject* iface,
543 FORMATETC* pformatetcIn, FORMATETC* pformatetcOut)
549 static HRESULT WINAPI IDataObject_fnSetData(IDataObject* iface,
550 FORMATETC* pformatetc, STGMEDIUM* pmedium, BOOL fRelease)
556 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(IDataObject* iface,
557 DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc)
563 static HRESULT WINAPI IDataObject_fnDAdvise(IDataObject* iface,
564 FORMATETC* pformatetc, DWORD advf, IAdviseSink* pAdvSink,
565 DWORD* pdwConnection)
571 static HRESULT WINAPI IDataObject_fnDUnadvise(IDataObject* iface,
578 static HRESULT WINAPI IDataObject_fnEnumDAdvise(IDataObject* iface,
579 IEnumSTATDATA** ppenumAdvise)
585 static const IDataObjectVtbl dovt =
587 IDataObject_fnQueryInterface,
588 IDataObject_fnAddRef,
589 IDataObject_fnRelease,
590 IDataObject_fnGetData,
591 IDataObject_fnGetDataHere,
592 IDataObject_fnQueryGetData,
593 IDataObject_fnGetConicalFormatEtc,
594 IDataObject_fnSetData,
595 IDataObject_fnEnumFormatEtc,
596 IDataObject_fnDAdvise,
597 IDataObject_fnDUnadvise,
598 IDataObject_fnEnumDAdvise
601 static HRESULT WINAPI IPersistStream_fnQueryInterface(IPersistStream* iface,
602 REFIID riid, LPVOID *ppvObj)
604 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
605 TRACE("(%p)\n", This);
606 return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
609 static ULONG WINAPI IPersistStream_fnAddRef (IPersistStream* iface)
611 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
612 TRACE("(%p)\n", This);
613 return IHlink_AddRef((IHlink*)This);
616 static ULONG WINAPI IPersistStream_fnRelease (IPersistStream* iface)
618 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
619 TRACE("(%p)\n", This);
620 return IHlink_Release((IHlink*)This);
623 static HRESULT WINAPI IPersistStream_fnGetClassID(IPersistStream* iface,
626 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
627 TRACE("(%p)\n", This);
628 *pClassID = CLSID_StdHlink;
632 static HRESULT WINAPI IPersistStream_fnIsDirty(IPersistStream* iface)
638 static HRESULT write_hlink_string(IStream *pStm, LPCWSTR str)
643 TRACE("(%p, %s)\n", pStm, debugstr_w(str));
645 len = strlenW(str) + 1;
647 hr = IStream_Write(pStm, &len, sizeof(len), NULL);
648 if (FAILED(hr)) return hr;
650 hr = IStream_Write(pStm, str, len * sizeof(WCHAR), NULL);
651 if (FAILED(hr)) return hr;
656 static inline ULONG size_hlink_string(LPCWSTR str)
658 return sizeof(DWORD) + (strlenW(str) + 1) * sizeof(WCHAR);
661 static HRESULT read_hlink_string(IStream *pStm, LPWSTR *out_str)
668 hr = IStream_Read(pStm, &len, sizeof(len), &read);
669 if (FAILED(hr)) return hr;
670 if (read != sizeof(len)) return STG_E_READFAULT;
672 TRACE("read len %d\n", len);
674 str = heap_alloc(len * sizeof(WCHAR));
675 if (!str) return E_OUTOFMEMORY;
677 hr = IStream_Read(pStm, str, len * sizeof(WCHAR), &read);
683 if (read != len * sizeof(WCHAR))
686 return STG_E_READFAULT;
688 TRACE("read string %s\n", debugstr_w(str));
694 static HRESULT WINAPI IPersistStream_fnLoad(IPersistStream* iface,
700 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
702 r = IStream_Read(pStm, hdr, sizeof(hdr), &read);
703 if (read != sizeof(hdr) || (hdr[0] != HLINK_SAVE_MAGIC))
708 if (hdr[1] & ~HLINK_SAVE_ALL)
709 FIXME("unknown flag(s) 0x%x\n", hdr[1] & ~HLINK_SAVE_ALL);
711 if (hdr[1] & HLINK_SAVE_TARGET_FRAME_PRESENT)
713 TRACE("loading target frame name\n");
714 r = read_hlink_string(pStm, &This->TargetFrameName);
715 if (FAILED(r)) goto end;
718 if (hdr[1] & HLINK_SAVE_FRIENDLY_PRESENT)
720 TRACE("loading target friendly name\n");
722 FIXME("0x4 flag not present with friendly name flag - not sure what this means\n");
723 r = read_hlink_string(pStm, &This->FriendlyName);
724 if (FAILED(r)) goto end;
727 if (hdr[1] & HLINK_SAVE_MONIKER_PRESENT)
729 TRACE("loading moniker\n");
730 r = OleLoadFromStream(pStm, &IID_IMoniker, (LPVOID*)&(This->Moniker));
733 This->absolute = hdr[1] & HLINK_SAVE_MONIKER_IS_ABSOLUTE ? TRUE : FALSE;
736 if (hdr[1] & HLINK_SAVE_LOCATION_PRESENT)
738 TRACE("loading location\n");
739 r = read_hlink_string(pStm, &This->Location);
740 if (FAILED(r)) goto end;
744 TRACE("Load Result 0x%x (%p)\n", r, This->Moniker);
749 static HRESULT WINAPI IPersistStream_fnSave(IPersistStream* iface,
750 IStream* pStm, BOOL fClearDirty)
753 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
757 TRACE("(%p) Moniker(%p)\n", This, This->Moniker);
759 __GetMoniker(This, &moniker);
761 hdr[0] = HLINK_SAVE_MAGIC;
765 hdr[1] |= HLINK_SAVE_MONIKER_PRESENT;
767 hdr[1] |= HLINK_SAVE_MONIKER_IS_ABSOLUTE;
769 hdr[1] |= HLINK_SAVE_LOCATION_PRESENT;
770 if (This->FriendlyName)
771 hdr[1] |= HLINK_SAVE_FRIENDLY_PRESENT | 4 /* FIXME */;
772 if (This->TargetFrameName)
773 hdr[1] |= HLINK_SAVE_TARGET_FRAME_PRESENT;
775 IStream_Write(pStm, hdr, sizeof(hdr), NULL);
777 if (This->TargetFrameName)
779 r = write_hlink_string(pStm, This->TargetFrameName);
780 if (FAILED(r)) goto end;
783 if (This->FriendlyName)
785 r = write_hlink_string(pStm, This->FriendlyName);
786 if (FAILED(r)) goto end;
791 IPersistStream* monstream;
794 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
795 (LPVOID*)&monstream);
798 r = OleSaveToStream(monstream, pStm);
799 IPersistStream_Release(monstream);
801 if (FAILED(r)) goto end;
806 r = write_hlink_string(pStm, This->Location);
807 if (FAILED(r)) goto end;
811 if (moniker) IMoniker_Release(moniker);
812 TRACE("Save Result 0x%x\n", r);
817 static HRESULT WINAPI IPersistStream_fnGetSizeMax(IPersistStream* iface,
818 ULARGE_INTEGER* pcbSize)
821 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
824 TRACE("(%p) Moniker(%p)\n", This, This->Moniker);
826 pcbSize->QuadPart = sizeof(DWORD)*2;
828 if (This->TargetFrameName)
829 pcbSize->QuadPart += size_hlink_string(This->TargetFrameName);
831 if (This->FriendlyName)
832 pcbSize->QuadPart += size_hlink_string(This->FriendlyName);
834 __GetMoniker(This, &moniker);
837 IPersistStream* monstream = NULL;
838 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
839 (LPVOID*)&monstream);
842 ULARGE_INTEGER mon_size;
843 r = IPersistStream_GetSizeMax(monstream, &mon_size);
844 pcbSize->QuadPart += mon_size.QuadPart;
845 IPersistStream_Release(monstream);
847 IMoniker_Release(moniker);
851 pcbSize->QuadPart += size_hlink_string(This->Location);
856 static const IPersistStreamVtbl psvt =
858 IPersistStream_fnQueryInterface,
859 IPersistStream_fnAddRef,
860 IPersistStream_fnRelease,
861 IPersistStream_fnGetClassID,
862 IPersistStream_fnIsDirty,
863 IPersistStream_fnLoad,
864 IPersistStream_fnSave,
865 IPersistStream_fnGetSizeMax,