Visual C++ backend for rbuild (for now just a hacked mingw backend) and related compi...
[reactos.git] / dll / win32 / hlink / link.c
1 /*
2 * Implementation of hyperlinking (hlink.dll)
3 *
4 * Copyright 2005 Aric Stewart for CodeWeavers
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include "hlink_private.h"
22
23 #include "shellapi.h"
24 #include "hlguids.h"
25
26 #include "wine/debug.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(hlink);
29
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)
39
40 static const IHlinkVtbl hlvt;
41 static const IPersistStreamVtbl psvt;
42 static const IDataObjectVtbl dovt;
43
44 typedef struct
45 {
46 const IHlinkVtbl *lpVtbl;
47 LONG ref;
48
49 const IPersistStreamVtbl *lpPSVtbl;
50 const IDataObjectVtbl *lpDOVtbl;
51
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;
61
62
63 static inline HlinkImpl* HlinkImpl_from_IPersistStream( IPersistStream* iface)
64 {
65 return (HlinkImpl*) ((CHAR*)iface - FIELD_OFFSET(HlinkImpl, lpPSVtbl));
66 }
67
68 static inline HlinkImpl* HlinkImpl_from_IDataObject( IDataObject* iface)
69 {
70 return (HlinkImpl*) ((CHAR*)iface - FIELD_OFFSET(HlinkImpl, lpDOVtbl));
71 }
72
73 static inline void __GetMoniker(HlinkImpl* This, IMoniker** moniker)
74 {
75 *moniker = NULL;
76 if (This->Moniker)
77 {
78 *moniker = This->Moniker;
79 if (*moniker)
80 IMoniker_AddRef(*moniker);
81 }
82 else if (This->Site)
83 {
84 IHlinkSite_GetMoniker(This->Site, This->SiteData,
85 OLEGETMONIKER_FORCEASSIGN, OLEWHICHMK_CONTAINER,
86 (LPVOID)moniker);
87 }
88 }
89
90 HRESULT WINAPI HLink_Constructor(IUnknown *pUnkOuter, REFIID riid,
91 LPVOID *ppv)
92 {
93 HlinkImpl * hl;
94
95 TRACE("unkOut=%p riid=%s\n", pUnkOuter, debugstr_guid(riid));
96 *ppv = NULL;
97
98 if (pUnkOuter)
99 return CLASS_E_NOAGGREGATION;
100
101 hl = heap_alloc_zero(sizeof(HlinkImpl));
102 if (!hl)
103 return E_OUTOFMEMORY;
104
105 hl->ref = 1;
106 hl->lpVtbl = &hlvt;
107 hl->lpPSVtbl = &psvt;
108 hl->lpDOVtbl = &dovt;
109
110 *ppv = hl;
111 return S_OK;
112 }
113
114 static HRESULT WINAPI IHlink_fnQueryInterface(IHlink* iface, REFIID riid,
115 LPVOID *ppvObj)
116 {
117 HlinkImpl *This = (HlinkImpl*)iface;
118
119 TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppvObj);
120
121 *ppvObj = NULL;
122
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);
129
130 if (*ppvObj)
131 {
132 IUnknown_AddRef((IUnknown*)(*ppvObj));
133 return S_OK;
134 }
135 return E_NOINTERFACE;
136 }
137
138 static ULONG WINAPI IHlink_fnAddRef (IHlink* iface)
139 {
140 HlinkImpl *This = (HlinkImpl*)iface;
141 ULONG refCount = InterlockedIncrement(&This->ref);
142
143 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
144
145 return refCount;
146 }
147
148 static ULONG WINAPI IHlink_fnRelease (IHlink* iface)
149 {
150 HlinkImpl *This = (HlinkImpl*)iface;
151 ULONG refCount = InterlockedDecrement(&This->ref);
152
153 TRACE("(%p)->(count=%u)\n", This, refCount + 1);
154 if (refCount)
155 return refCount;
156
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;
168 }
169
170 static HRESULT WINAPI IHlink_fnSetHlinkSite( IHlink* iface,
171 IHlinkSite* pihlSite, DWORD dwSiteData)
172 {
173 HlinkImpl *This = (HlinkImpl*)iface;
174
175 TRACE("(%p)->(%p %i)\n", This, pihlSite, dwSiteData);
176
177 if (This->Site)
178 IHlinkSite_Release(This->Site);
179
180 This->Site = pihlSite;
181 if (This->Site)
182 IHlinkSite_AddRef(This->Site);
183
184 This->SiteData = dwSiteData;
185
186 return S_OK;
187 }
188
189 static HRESULT WINAPI IHlink_fnGetHlinkSite( IHlink* iface,
190 IHlinkSite** ppihlSite, DWORD *pdwSiteData)
191 {
192 HlinkImpl *This = (HlinkImpl*)iface;
193
194 TRACE("(%p)->(%p %p)\n", This, ppihlSite, pdwSiteData);
195
196 *ppihlSite = This->Site;
197 *pdwSiteData = This->SiteData;
198
199 if (This->Site)
200 IHlinkSite_AddRef(This->Site);
201
202 return S_OK;
203 }
204
205 static HRESULT WINAPI IHlink_fnSetMonikerReference( IHlink* iface,
206 DWORD rfHLSETF, IMoniker *pmkTarget, LPCWSTR pwzLocation)
207 {
208 HlinkImpl *This = (HlinkImpl*)iface;
209
210 FIXME("(%p)->(%i %p %s)\n", This, rfHLSETF, pmkTarget,
211 debugstr_w(pwzLocation));
212
213 if (This->Moniker)
214 IMoniker_Release(This->Moniker);
215
216 This->Moniker = pmkTarget;
217 if (This->Moniker)
218 {
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);
224 }
225
226 heap_free(This->Location);
227 This->Location = hlink_strdupW( pwzLocation );
228
229 return S_OK;
230 }
231
232 static HRESULT WINAPI IHlink_fnSetStringReference(IHlink* iface,
233 DWORD grfHLSETF, LPCWSTR pwzTarget, LPCWSTR pwzLocation)
234 {
235 HlinkImpl *This = (HlinkImpl*)iface;
236
237 TRACE("(%p)->(%i %s %s)\n", This, grfHLSETF, debugstr_w(pwzTarget),
238 debugstr_w(pwzLocation));
239
240 if (grfHLSETF & HLINKSETF_TARGET)
241 {
242 heap_free(This->Target);
243 This->Target = hlink_strdupW( pwzTarget );
244 }
245 if (grfHLSETF & HLINKSETF_LOCATION)
246 {
247 heap_free(This->Location);
248 This->Location = hlink_strdupW( pwzLocation );
249 }
250
251 return S_OK;
252 }
253
254 static HRESULT WINAPI IHlink_fnGetMonikerReference(IHlink* iface,
255 DWORD dwWhichRef, IMoniker **ppimkTarget, LPWSTR *ppwzLocation)
256 {
257 HlinkImpl *This = (HlinkImpl*)iface;
258
259 TRACE("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppimkTarget,
260 ppwzLocation);
261
262 if(ppimkTarget)
263 __GetMoniker(This, ppimkTarget);
264
265 if (ppwzLocation)
266 IHlink_GetStringReference(iface, dwWhichRef, NULL, ppwzLocation);
267
268 return S_OK;
269 }
270
271 static HRESULT WINAPI IHlink_fnGetStringReference (IHlink* iface,
272 DWORD dwWhichRef, LPWSTR *ppwzTarget, LPWSTR *ppwzLocation)
273 {
274 HlinkImpl *This = (HlinkImpl*)iface;
275
276 FIXME("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppwzTarget, ppwzLocation);
277
278 if (ppwzTarget)
279 {
280 *ppwzTarget = hlink_co_strdupW( This->Target );
281
282 if (!This->Target)
283 {
284 IMoniker* mon;
285 __GetMoniker(This, &mon);
286 if (mon)
287 {
288 IBindCtx *pbc;
289
290 CreateBindCtx( 0, &pbc);
291 IMoniker_GetDisplayName(mon, pbc, NULL, ppwzTarget);
292 IBindCtx_Release(pbc);
293 IMoniker_Release(mon);
294 }
295 else
296 FIXME("Unhandled case, no set Target and no moniker\n");
297 }
298 }
299 if (ppwzLocation)
300 *ppwzLocation = hlink_co_strdupW( This->Location );
301
302 TRACE("(Target: %s Location: %s)\n",
303 (ppwzTarget)?debugstr_w(*ppwzTarget):"<NULL>",
304 (ppwzLocation)?debugstr_w(*ppwzLocation):"<NULL>");
305
306 return S_OK;
307 }
308
309 static HRESULT WINAPI IHlink_fnSetFriendlyName (IHlink *iface,
310 LPCWSTR pwzFriendlyName)
311 {
312 HlinkImpl *This = (HlinkImpl*)iface;
313
314 TRACE("(%p) -> (%s)\n", This, debugstr_w(pwzFriendlyName));
315
316 heap_free(This->FriendlyName);
317 This->FriendlyName = hlink_strdupW( pwzFriendlyName );
318
319 return S_OK;
320 }
321
322 static HRESULT WINAPI IHlink_fnGetFriendlyName (IHlink* iface,
323 DWORD grfHLFNAMEF, LPWSTR* ppwzFriendlyName)
324 {
325 HlinkImpl *This = (HlinkImpl*)iface;
326
327 TRACE("(%p) -> (%i %p)\n", This, grfHLFNAMEF, ppwzFriendlyName);
328
329 /* FIXME: Only using explicitly set and cached friendly names */
330
331 if (This->FriendlyName)
332 *ppwzFriendlyName = hlink_co_strdupW( This->FriendlyName );
333 else
334 {
335 IMoniker *moniker;
336 __GetMoniker(This, &moniker);
337 if (moniker)
338 {
339 IBindCtx *bcxt;
340 CreateBindCtx(0, &bcxt);
341
342 IMoniker_GetDisplayName(moniker, bcxt, NULL, ppwzFriendlyName);
343 IBindCtx_Release(bcxt);
344 IMoniker_Release(moniker);
345 }
346 else
347 *ppwzFriendlyName = NULL;
348 }
349
350 return S_OK;
351 }
352
353 static HRESULT WINAPI IHlink_fnSetTargetFrameName(IHlink* iface,
354 LPCWSTR pwzTargetFramename)
355 {
356 HlinkImpl *This = (HlinkImpl*)iface;
357 TRACE("(%p)->(%s)\n", This, debugstr_w(pwzTargetFramename));
358
359 heap_free(This->TargetFrameName);
360 This->TargetFrameName = hlink_strdupW( pwzTargetFramename );
361
362 return S_OK;
363 }
364
365 static HRESULT WINAPI IHlink_fnGetTargetFrameName(IHlink* iface,
366 LPWSTR *ppwzTargetFrameName)
367 {
368 HlinkImpl *This = (HlinkImpl*)iface;
369
370 TRACE("(%p)->(%p)\n", This, ppwzTargetFrameName);
371 *ppwzTargetFrameName = hlink_co_strdupW( This->TargetFrameName );
372
373 return S_OK;
374 }
375
376 static HRESULT WINAPI IHlink_fnGetMiscStatus(IHlink* iface, DWORD* pdwStatus)
377 {
378 FIXME("\n");
379 return E_NOTIMPL;
380 }
381
382 static HRESULT WINAPI IHlink_fnNavigate(IHlink* iface, DWORD grfHLNF, LPBC pbc,
383 IBindStatusCallback *pbsc, IHlinkBrowseContext *phbc)
384 {
385 HlinkImpl *This = (HlinkImpl*)iface;
386 IMoniker *mon = NULL;
387
388 FIXME("Semi-Stub:(%p)->(%i %p %p %p)\n", This, grfHLNF, pbc, pbsc, phbc);
389
390 if (This->Site)
391 IHlinkSite_ReadyToNavigate(This->Site, This->SiteData, 0);
392
393 __GetMoniker(This, &mon);
394 TRACE("Moniker %p\n", mon);
395
396 if (mon)
397 {
398 IBindCtx *bcxt;
399 IHlinkTarget *target = NULL;
400 HRESULT r = S_OK;
401
402 CreateBindCtx(0, &bcxt);
403
404 RegisterBindStatusCallback(bcxt, pbsc, NULL, 0);
405
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)
410 {
411 IHlinkTarget_SetBrowseContext(target, phbc);
412 IHlinkTarget_Navigate(target, grfHLNF, This->Location);
413 IHlinkTarget_Release(target);
414 }
415 else
416 {
417 static const WCHAR szOpen[] = {'o','p','e','n',0};
418 LPWSTR target = NULL;
419
420 r = IHlink_GetStringReference(iface, HLINKGETREF_DEFAULT, &target, NULL);
421 if (SUCCEEDED(r) && target)
422 {
423 ShellExecuteW(NULL, szOpen, target, NULL, NULL, SW_SHOW);
424 CoTaskMemFree(target);
425 }
426 }
427
428 RevokeBindStatusCallback(bcxt, pbsc);
429
430 IBindCtx_Release(bcxt);
431 IMoniker_Release(mon);
432 }
433
434 if (This->Site)
435 IHlinkSite_OnNavigationComplete(This->Site, This->SiteData, 0, 0, NULL);
436
437 TRACE("Finished Navigation\n");
438 return S_OK;
439 }
440
441 static HRESULT WINAPI IHlink_fnSetAdditonalParams(IHlink* iface,
442 LPCWSTR pwzAdditionalParams)
443 {
444 FIXME("\n");
445 return E_NOTIMPL;
446 }
447
448 static HRESULT WINAPI IHlink_fnGetAdditionalParams(IHlink* iface,
449 LPWSTR* ppwzAdditionalParams)
450 {
451 FIXME("\n");
452 return E_NOTIMPL;
453 }
454
455 static const IHlinkVtbl hlvt =
456 {
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
474 };
475
476 static HRESULT WINAPI IDataObject_fnQueryInterface(IDataObject* iface,
477 REFIID riid, LPVOID *ppvObj)
478 {
479 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
480 TRACE("%p\n", This);
481 return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
482 }
483
484 static ULONG WINAPI IDataObject_fnAddRef (IDataObject* iface)
485 {
486 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
487 TRACE("%p\n", This);
488 return IHlink_AddRef((IHlink*)This);
489 }
490
491 static ULONG WINAPI IDataObject_fnRelease (IDataObject* iface)
492 {
493 HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
494 TRACE("%p\n", This);
495 return IHlink_Release((IHlink*)This);
496 }
497
498 static HRESULT WINAPI IDataObject_fnGetData(IDataObject* iface,
499 FORMATETC* pformatetcIn, STGMEDIUM* pmedium)
500 {
501 FIXME("\n");
502 return E_NOTIMPL;
503 }
504
505 static HRESULT WINAPI IDataObject_fnGetDataHere(IDataObject* iface,
506 FORMATETC* pformatetc, STGMEDIUM* pmedium)
507 {
508 FIXME("\n");
509 return E_NOTIMPL;
510 }
511
512 static HRESULT WINAPI IDataObject_fnQueryGetData(IDataObject* iface,
513 FORMATETC* pformatetc)
514 {
515 FIXME("\n");
516 return E_NOTIMPL;
517 }
518
519 static HRESULT WINAPI IDataObject_fnGetConicalFormatEtc(IDataObject* iface,
520 FORMATETC* pformatetcIn, FORMATETC* pformatetcOut)
521 {
522 FIXME("\n");
523 return E_NOTIMPL;
524 }
525
526 static HRESULT WINAPI IDataObject_fnSetData(IDataObject* iface,
527 FORMATETC* pformatetc, STGMEDIUM* pmedium, BOOL fRelease)
528 {
529 FIXME("\n");
530 return E_NOTIMPL;
531 }
532
533 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(IDataObject* iface,
534 DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc)
535 {
536 FIXME("\n");
537 return E_NOTIMPL;
538 }
539
540 static HRESULT WINAPI IDataObject_fnDAdvise(IDataObject* iface,
541 FORMATETC* pformatetc, DWORD advf, IAdviseSink* pAdvSink,
542 DWORD* pdwConnection)
543 {
544 FIXME("\n");
545 return E_NOTIMPL;
546 }
547
548 static HRESULT WINAPI IDataObject_fnDUnadvise(IDataObject* iface,
549 DWORD dwConnection)
550 {
551 FIXME("\n");
552 return E_NOTIMPL;
553 }
554
555 static HRESULT WINAPI IDataObject_fnEnumDAdvise(IDataObject* iface,
556 IEnumSTATDATA** ppenumAdvise)
557 {
558 FIXME("\n");
559 return E_NOTIMPL;
560 }
561
562 static const IDataObjectVtbl dovt =
563 {
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
576 };
577
578 static HRESULT WINAPI IPersistStream_fnQueryInterface(IPersistStream* iface,
579 REFIID riid, LPVOID *ppvObj)
580 {
581 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
582 TRACE("(%p)\n", This);
583 return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
584 }
585
586 static ULONG WINAPI IPersistStream_fnAddRef (IPersistStream* iface)
587 {
588 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
589 TRACE("(%p)\n", This);
590 return IHlink_AddRef((IHlink*)This);
591 }
592
593 static ULONG WINAPI IPersistStream_fnRelease (IPersistStream* iface)
594 {
595 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
596 TRACE("(%p)\n", This);
597 return IHlink_Release((IHlink*)This);
598 }
599
600 static HRESULT WINAPI IPersistStream_fnGetClassID(IPersistStream* iface,
601 CLSID* pClassID)
602 {
603 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
604 TRACE("(%p)\n", This);
605 *pClassID = CLSID_StdHlink;
606 return S_OK;
607 }
608
609 static HRESULT WINAPI IPersistStream_fnIsDirty(IPersistStream* iface)
610 {
611 FIXME("\n");
612 return E_NOTIMPL;
613 }
614
615 static HRESULT write_hlink_string(IStream *pStm, LPCWSTR str)
616 {
617 DWORD len;
618 HRESULT hr;
619
620 TRACE("(%p, %s)\n", pStm, debugstr_w(str));
621
622 len = strlenW(str) + 1;
623
624 hr = IStream_Write(pStm, &len, sizeof(len), NULL);
625 if (FAILED(hr)) return hr;
626
627 hr = IStream_Write(pStm, str, len * sizeof(WCHAR), NULL);
628 if (FAILED(hr)) return hr;
629
630 return S_OK;
631 }
632
633 static inline ULONG size_hlink_string(LPCWSTR str)
634 {
635 return sizeof(DWORD) + (strlenW(str) + 1) * sizeof(WCHAR);
636 }
637
638 static HRESULT read_hlink_string(IStream *pStm, LPWSTR *out_str)
639 {
640 LPWSTR str;
641 DWORD len;
642 ULONG read;
643 HRESULT hr;
644
645 hr = IStream_Read(pStm, &len, sizeof(len), &read);
646 if (FAILED(hr)) return hr;
647 if (read != sizeof(len)) return STG_E_READFAULT;
648
649 TRACE("read len %d\n", len);
650
651 str = heap_alloc(len * sizeof(WCHAR));
652 if (!str) return E_OUTOFMEMORY;
653
654 hr = IStream_Read(pStm, str, len * sizeof(WCHAR), &read);
655 if (FAILED(hr))
656 {
657 heap_free(str);
658 return hr;
659 }
660 if (read != len * sizeof(WCHAR))
661 {
662 heap_free(str);
663 return STG_E_READFAULT;
664 }
665 TRACE("read string %s\n", debugstr_w(str));
666
667 *out_str = str;
668 return S_OK;
669 }
670
671 static HRESULT WINAPI IPersistStream_fnLoad(IPersistStream* iface,
672 IStream* pStm)
673 {
674 HRESULT r;
675 DWORD hdr[2];
676 DWORD read;
677 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
678
679 r = IStream_Read(pStm, hdr, sizeof(hdr), &read);
680 if (read != sizeof(hdr) || (hdr[0] != HLINK_SAVE_MAGIC))
681 {
682 r = E_FAIL;
683 goto end;
684 }
685 if (hdr[1] & ~HLINK_SAVE_ALL)
686 FIXME("unknown flag(s) 0x%x\n", hdr[1] & ~HLINK_SAVE_ALL);
687
688 if (hdr[1] & HLINK_SAVE_TARGET_FRAME_PRESENT)
689 {
690 TRACE("loading target frame name\n");
691 r = read_hlink_string(pStm, &This->TargetFrameName);
692 if (FAILED(r)) goto end;
693 }
694
695 if (hdr[1] & HLINK_SAVE_FRIENDLY_PRESENT)
696 {
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;
702 }
703
704 if (hdr[1] & HLINK_SAVE_MONIKER_PRESENT)
705 {
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;
711 }
712
713 if (hdr[1] & HLINK_SAVE_LOCATION_PRESENT)
714 {
715 TRACE("loading location\n");
716 r = read_hlink_string(pStm, &This->Location);
717 if (FAILED(r)) goto end;
718 }
719
720 end:
721 TRACE("Load Result 0x%x (%p)\n", r, This->Moniker);
722
723 return r;
724 }
725
726 static HRESULT WINAPI IPersistStream_fnSave(IPersistStream* iface,
727 IStream* pStm, BOOL fClearDirty)
728 {
729 HRESULT r = E_FAIL;
730 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
731 DWORD hdr[2];
732 IMoniker *moniker;
733
734 TRACE("(%p) Moniker(%p)\n", This, This->Moniker);
735
736 __GetMoniker(This, &moniker);
737
738 hdr[0] = HLINK_SAVE_MAGIC;
739 hdr[1] = 0;
740
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;
751
752 IStream_Write(pStm, hdr, sizeof(hdr), NULL);
753
754 if (This->TargetFrameName)
755 {
756 r = write_hlink_string(pStm, This->TargetFrameName);
757 if (FAILED(r)) goto end;
758 }
759
760 if (This->FriendlyName)
761 {
762 r = write_hlink_string(pStm, This->FriendlyName);
763 if (FAILED(r)) goto end;
764 }
765
766 if (moniker)
767 {
768 IPersistStream* monstream;
769
770 monstream = NULL;
771 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
772 (LPVOID*)&monstream);
773 if (monstream)
774 {
775 r = OleSaveToStream(monstream, pStm);
776 IPersistStream_Release(monstream);
777 }
778 if (FAILED(r)) goto end;
779 }
780
781 if (This->Location)
782 {
783 r = write_hlink_string(pStm, This->Location);
784 if (FAILED(r)) goto end;
785 }
786
787 end:
788 if (moniker) IMoniker_Release(moniker);
789 TRACE("Save Result 0x%x\n", r);
790
791 return r;
792 }
793
794 static HRESULT WINAPI IPersistStream_fnGetSizeMax(IPersistStream* iface,
795 ULARGE_INTEGER* pcbSize)
796 {
797 HRESULT r = E_FAIL;
798 HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
799 IMoniker *moniker;
800
801 TRACE("(%p) Moniker(%p)\n", This, This->Moniker);
802
803 pcbSize->QuadPart = sizeof(DWORD)*2;
804
805 if (This->TargetFrameName)
806 pcbSize->QuadPart += size_hlink_string(This->TargetFrameName);
807
808 if (This->FriendlyName)
809 pcbSize->QuadPart += size_hlink_string(This->FriendlyName);
810
811 __GetMoniker(This, &moniker);
812 if (moniker)
813 {
814 IPersistStream* monstream = NULL;
815 IMoniker_QueryInterface(moniker, &IID_IPersistStream,
816 (LPVOID*)&monstream);
817 if (monstream)
818 {
819 ULARGE_INTEGER mon_size;
820 r = IPersistStream_GetSizeMax(monstream, &mon_size);
821 pcbSize->QuadPart += mon_size.QuadPart;
822 IPersistStream_Release(monstream);
823 }
824 IMoniker_Release(moniker);
825 }
826
827 if (This->Location)
828 pcbSize->QuadPart += size_hlink_string(This->Location);
829
830 return r;
831 }
832
833 static const IPersistStreamVtbl psvt =
834 {
835 IPersistStream_fnQueryInterface,
836 IPersistStream_fnAddRef,
837 IPersistStream_fnRelease,
838 IPersistStream_fnGetClassID,
839 IPersistStream_fnIsDirty,
840 IPersistStream_fnLoad,
841 IPersistStream_fnSave,
842 IPersistStream_fnGetSizeMax,
843 };