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 typedef struct 41 { 42 IHlink IHlink_iface; 43 LONG ref; 44 45 IPersistStream IPersistStream_iface; 46 IDataObject IDataObject_iface; 47 48 LPWSTR FriendlyName; 49 LPWSTR Location; 50 LPWSTR TargetFrameName; 51 IMoniker *Moniker; 52 IHlinkSite *Site; 53 DWORD SiteData; 54 BOOL absolute; 55 56 IBindStatusCallback IBindStatusCallback_iface; 57 IBindStatusCallback *bind_callback; 58 IBindCtx *async_bind_ctx; 59 DWORD async_flags; 60 IHlinkBrowseContext *async_browse_ctx; 61 } HlinkImpl; 62 63 static inline HlinkImpl *impl_from_IHlink(IHlink *iface) 64 { 65 return CONTAINING_RECORD(iface, HlinkImpl, IHlink_iface); 66 } 67 68 69 static inline HlinkImpl* impl_from_IPersistStream( IPersistStream* iface) 70 { 71 return CONTAINING_RECORD(iface, HlinkImpl, IPersistStream_iface); 72 } 73 74 static inline HlinkImpl* impl_from_IDataObject( IDataObject* iface) 75 { 76 return CONTAINING_RECORD(iface, HlinkImpl, IDataObject_iface); 77 } 78 79 static HRESULT __GetMoniker(HlinkImpl* This, IMoniker** moniker, 80 DWORD ref_type) 81 { 82 HRESULT hres; 83 84 if (ref_type == HLINKGETREF_DEFAULT) 85 ref_type = HLINKGETREF_RELATIVE; 86 87 if (This->Moniker) 88 { 89 DWORD mktype = MKSYS_NONE; 90 91 hres = IMoniker_IsSystemMoniker(This->Moniker, &mktype); 92 if (hres == S_OK && mktype != MKSYS_NONE) 93 { 94 *moniker = This->Moniker; 95 IMoniker_AddRef(*moniker); 96 return S_OK; 97 } 98 } 99 100 if (ref_type == HLINKGETREF_ABSOLUTE && This->Site) 101 { 102 IMoniker *hls_moniker; 103 104 hres = IHlinkSite_GetMoniker(This->Site, This->SiteData, 105 OLEGETMONIKER_FORCEASSIGN, OLEWHICHMK_CONTAINER, &hls_moniker); 106 if (FAILED(hres)) 107 return hres; 108 109 if (This->Moniker) 110 { 111 hres = IMoniker_ComposeWith(hls_moniker, This->Moniker, FALSE, 112 moniker); 113 IMoniker_Release(hls_moniker); 114 return hres; 115 } 116 117 *moniker = hls_moniker; 118 return S_OK; 119 } 120 121 *moniker = This->Moniker; 122 if (*moniker) 123 IMoniker_AddRef(*moniker); 124 125 return S_OK; 126 } 127 128 static HRESULT WINAPI IHlink_fnQueryInterface(IHlink* iface, REFIID riid, 129 LPVOID *ppvObj) 130 { 131 HlinkImpl *This = impl_from_IHlink(iface); 132 133 TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppvObj); 134 135 *ppvObj = NULL; 136 137 if (IsEqualIID(riid, &IID_IUnknown) || (IsEqualIID(riid, &IID_IHlink))) 138 *ppvObj = &This->IHlink_iface; 139 else if (IsEqualIID(riid, &IID_IPersistStream)) 140 *ppvObj = &This->IPersistStream_iface; 141 else if (IsEqualIID(riid, &IID_IDataObject)) 142 *ppvObj = &This->IDataObject_iface; 143 144 if (*ppvObj) 145 { 146 IUnknown_AddRef((IUnknown*)(*ppvObj)); 147 return S_OK; 148 } 149 return E_NOINTERFACE; 150 } 151 152 static ULONG WINAPI IHlink_fnAddRef (IHlink* iface) 153 { 154 HlinkImpl *This = impl_from_IHlink(iface); 155 ULONG refCount = InterlockedIncrement(&This->ref); 156 157 TRACE("(%p)->(count=%u)\n", This, refCount - 1); 158 159 return refCount; 160 } 161 162 static ULONG WINAPI IHlink_fnRelease (IHlink* iface) 163 { 164 HlinkImpl *This = impl_from_IHlink(iface); 165 ULONG refCount = InterlockedDecrement(&This->ref); 166 167 TRACE("(%p)->(count=%u)\n", This, refCount + 1); 168 if (refCount) 169 return refCount; 170 171 TRACE("-- destroying IHlink (%p)\n", This); 172 heap_free(This->FriendlyName); 173 heap_free(This->TargetFrameName); 174 heap_free(This->Location); 175 if (This->Moniker) 176 IMoniker_Release(This->Moniker); 177 if (This->Site) 178 IHlinkSite_Release(This->Site); 179 heap_free(This); 180 return 0; 181 } 182 183 static HRESULT WINAPI IHlink_fnSetHlinkSite( IHlink* iface, 184 IHlinkSite* pihlSite, DWORD dwSiteData) 185 { 186 HlinkImpl *This = impl_from_IHlink(iface); 187 188 TRACE("(%p)->(%p %i)\n", This, pihlSite, dwSiteData); 189 190 if (This->Site) 191 IHlinkSite_Release(This->Site); 192 193 This->Site = pihlSite; 194 if (This->Site) 195 IHlinkSite_AddRef(This->Site); 196 197 This->SiteData = dwSiteData; 198 199 return S_OK; 200 } 201 202 static HRESULT WINAPI IHlink_fnGetHlinkSite( IHlink* iface, 203 IHlinkSite** ppihlSite, DWORD *pdwSiteData) 204 { 205 HlinkImpl *This = impl_from_IHlink(iface); 206 207 TRACE("(%p)->(%p %p)\n", This, ppihlSite, pdwSiteData); 208 209 *ppihlSite = This->Site; 210 211 if (This->Site) { 212 IHlinkSite_AddRef(This->Site); 213 *pdwSiteData = This->SiteData; 214 } 215 216 return S_OK; 217 } 218 219 static HRESULT WINAPI IHlink_fnSetMonikerReference( IHlink* iface, 220 DWORD rfHLSETF, IMoniker *pmkTarget, LPCWSTR pwzLocation) 221 { 222 HlinkImpl *This = impl_from_IHlink(iface); 223 224 TRACE("(%p)->(%i %p %s)\n", This, rfHLSETF, pmkTarget, 225 debugstr_w(pwzLocation)); 226 227 if(rfHLSETF == 0) 228 return E_INVALIDARG; 229 if(!(rfHLSETF & (HLINKSETF_TARGET | HLINKSETF_LOCATION))) 230 return rfHLSETF; 231 232 if(rfHLSETF & HLINKSETF_TARGET){ 233 if (This->Moniker) 234 IMoniker_Release(This->Moniker); 235 236 This->Moniker = pmkTarget; 237 if (This->Moniker) 238 { 239 IBindCtx *pbc; 240 LPOLESTR display_name; 241 IMoniker_AddRef(This->Moniker); 242 CreateBindCtx( 0, &pbc); 243 IMoniker_GetDisplayName(This->Moniker, pbc, NULL, &display_name); 244 IBindCtx_Release(pbc); 245 This->absolute = display_name && strchrW(display_name, ':'); 246 CoTaskMemFree(display_name); 247 } 248 } 249 250 if(rfHLSETF & HLINKSETF_LOCATION){ 251 heap_free(This->Location); 252 This->Location = hlink_strdupW( pwzLocation ); 253 } 254 255 return S_OK; 256 } 257 258 static HRESULT WINAPI IHlink_fnSetStringReference(IHlink* iface, 259 DWORD grfHLSETF, LPCWSTR pwzTarget, LPCWSTR pwzLocation) 260 { 261 HlinkImpl *This = impl_from_IHlink(iface); 262 263 TRACE("(%p)->(%i %s %s)\n", This, grfHLSETF, debugstr_w(pwzTarget), 264 debugstr_w(pwzLocation)); 265 266 if(grfHLSETF > (HLINKSETF_TARGET | HLINKSETF_LOCATION) && 267 grfHLSETF < -(HLINKSETF_TARGET | HLINKSETF_LOCATION)) 268 return grfHLSETF; 269 270 if (grfHLSETF & HLINKSETF_TARGET) 271 { 272 if (This->Moniker) 273 { 274 IMoniker_Release(This->Moniker); 275 This->Moniker = NULL; 276 } 277 if (pwzTarget && *pwzTarget) 278 { 279 IMoniker *pMon; 280 IBindCtx *pbc = NULL; 281 ULONG eaten; 282 HRESULT r; 283 284 r = CreateBindCtx(0, &pbc); 285 if (FAILED(r)) 286 return E_OUTOFMEMORY; 287 288 r = MkParseDisplayName(pbc, pwzTarget, &eaten, &pMon); 289 IBindCtx_Release(pbc); 290 291 if (FAILED(r)) 292 { 293 LPCWSTR p = strchrW(pwzTarget, ':'); 294 if (p && (p - pwzTarget > 1)) 295 r = CreateURLMoniker(NULL, pwzTarget, &pMon); 296 else 297 r = CreateFileMoniker(pwzTarget, &pMon); 298 if (FAILED(r)) 299 { 300 ERR("couldn't create moniker for %s, failed with error 0x%08x\n", 301 debugstr_w(pwzTarget), r); 302 return r; 303 } 304 } 305 306 IHlink_SetMonikerReference(iface, HLINKSETF_TARGET, pMon, NULL); 307 IMoniker_Release(pMon); 308 } 309 } 310 311 if (grfHLSETF & HLINKSETF_LOCATION) 312 { 313 heap_free(This->Location); 314 This->Location = NULL; 315 if (pwzLocation && *pwzLocation) 316 This->Location = hlink_strdupW( pwzLocation ); 317 } 318 319 return S_OK; 320 } 321 322 static HRESULT WINAPI IHlink_fnGetMonikerReference(IHlink* iface, 323 DWORD dwWhichRef, IMoniker **ppimkTarget, LPWSTR *ppwzLocation) 324 { 325 HlinkImpl *This = impl_from_IHlink(iface); 326 327 TRACE("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppimkTarget, 328 ppwzLocation); 329 330 if (ppimkTarget) 331 { 332 HRESULT hres = __GetMoniker(This, ppimkTarget, dwWhichRef); 333 if (FAILED(hres)) 334 { 335 if (ppwzLocation) 336 *ppwzLocation = NULL; 337 return hres; 338 } 339 } 340 341 if (ppwzLocation) 342 IHlink_GetStringReference(iface, dwWhichRef, NULL, ppwzLocation); 343 344 return S_OK; 345 } 346 347 static HRESULT WINAPI IHlink_fnGetStringReference (IHlink* iface, 348 DWORD dwWhichRef, LPWSTR *ppwzTarget, LPWSTR *ppwzLocation) 349 { 350 HlinkImpl *This = impl_from_IHlink(iface); 351 352 TRACE("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppwzTarget, ppwzLocation); 353 354 if(dwWhichRef != -1 && dwWhichRef & ~(HLINKGETREF_DEFAULT | HLINKGETREF_ABSOLUTE | HLINKGETREF_RELATIVE)) 355 { 356 if(ppwzTarget) 357 *ppwzTarget = NULL; 358 if(ppwzLocation) 359 *ppwzLocation = NULL; 360 return E_INVALIDARG; 361 } 362 363 if (ppwzTarget) 364 { 365 IMoniker* mon; 366 HRESULT hres = __GetMoniker(This, &mon, dwWhichRef); 367 if (FAILED(hres)) 368 { 369 if (ppwzLocation) 370 *ppwzLocation = NULL; 371 return hres; 372 } 373 if (mon) 374 { 375 IBindCtx *pbc; 376 377 CreateBindCtx( 0, &pbc); 378 IMoniker_GetDisplayName(mon, pbc, NULL, ppwzTarget); 379 IBindCtx_Release(pbc); 380 IMoniker_Release(mon); 381 } 382 else 383 *ppwzTarget = NULL; 384 } 385 if (ppwzLocation) 386 *ppwzLocation = hlink_co_strdupW( This->Location ); 387 388 TRACE("(Target: %s Location: %s)\n", 389 (ppwzTarget)?debugstr_w(*ppwzTarget):"<NULL>", 390 (ppwzLocation)?debugstr_w(*ppwzLocation):"<NULL>"); 391 392 return S_OK; 393 } 394 395 static HRESULT WINAPI IHlink_fnSetFriendlyName (IHlink *iface, 396 LPCWSTR pwzFriendlyName) 397 { 398 HlinkImpl *This = impl_from_IHlink(iface); 399 400 TRACE("(%p) -> (%s)\n", This, debugstr_w(pwzFriendlyName)); 401 402 heap_free(This->FriendlyName); 403 This->FriendlyName = hlink_strdupW( pwzFriendlyName ); 404 405 return S_OK; 406 } 407 408 static HRESULT WINAPI IHlink_fnGetFriendlyName (IHlink* iface, 409 DWORD grfHLFNAMEF, LPWSTR* ppwzFriendlyName) 410 { 411 HlinkImpl *This = impl_from_IHlink(iface); 412 413 TRACE("(%p) -> (%i %p)\n", This, grfHLFNAMEF, ppwzFriendlyName); 414 415 /* FIXME: Only using explicitly set and cached friendly names */ 416 417 if (This->FriendlyName) 418 *ppwzFriendlyName = hlink_co_strdupW( This->FriendlyName ); 419 else 420 { 421 IMoniker *moniker; 422 HRESULT hres = __GetMoniker(This, &moniker, HLINKGETREF_DEFAULT); 423 if (FAILED(hres)) 424 { 425 *ppwzFriendlyName = NULL; 426 return hres; 427 } 428 if (moniker) 429 { 430 IBindCtx *bcxt; 431 CreateBindCtx(0, &bcxt); 432 433 IMoniker_GetDisplayName(moniker, bcxt, NULL, ppwzFriendlyName); 434 IBindCtx_Release(bcxt); 435 IMoniker_Release(moniker); 436 } 437 else 438 *ppwzFriendlyName = NULL; 439 } 440 441 return S_OK; 442 } 443 444 static HRESULT WINAPI IHlink_fnSetTargetFrameName(IHlink* iface, 445 LPCWSTR pwzTargetFramename) 446 { 447 HlinkImpl *This = impl_from_IHlink(iface); 448 TRACE("(%p)->(%s)\n", This, debugstr_w(pwzTargetFramename)); 449 450 heap_free(This->TargetFrameName); 451 This->TargetFrameName = hlink_strdupW( pwzTargetFramename ); 452 453 return S_OK; 454 } 455 456 static HRESULT WINAPI IHlink_fnGetTargetFrameName(IHlink* iface, 457 LPWSTR *ppwzTargetFrameName) 458 { 459 HlinkImpl *This = impl_from_IHlink(iface); 460 461 TRACE("(%p)->(%p)\n", This, ppwzTargetFrameName); 462 463 if(!This->TargetFrameName) { 464 *ppwzTargetFrameName = NULL; 465 return S_FALSE; 466 } 467 468 *ppwzTargetFrameName = hlink_co_strdupW( This->TargetFrameName ); 469 if(!*ppwzTargetFrameName) 470 return E_OUTOFMEMORY; 471 472 return S_OK; 473 } 474 475 static HRESULT WINAPI IHlink_fnGetMiscStatus(IHlink* iface, DWORD* pdwStatus) 476 { 477 FIXME("\n"); 478 return E_NOTIMPL; 479 } 480 481 static HRESULT WINAPI IHlink_fnNavigate(IHlink *iface, DWORD flags, IBindCtx *user_bind_ctx, 482 IBindStatusCallback *bind_callback, IHlinkBrowseContext *browse_ctx) 483 { 484 HlinkImpl *This = impl_from_IHlink(iface); 485 IMoniker *mon = NULL; 486 HRESULT r; 487 488 TRACE("hlink %p, flags %#x, user_bind_ctx %p, bind_callback %p, browse_ctx %p.\n", 489 This, flags, user_bind_ctx, bind_callback, browse_ctx); 490 491 if (This->async_bind_ctx) 492 return E_UNEXPECTED; 493 494 r = __GetMoniker(This, &mon, HLINKGETREF_ABSOLUTE); 495 TRACE("Moniker %p\n", mon); 496 497 if (SUCCEEDED(r)) 498 { 499 IBindCtx *bind_ctx = NULL; 500 IUnknown *unk = NULL; 501 IHlinkTarget *target; 502 503 if (browse_ctx) 504 { 505 r = IHlinkBrowseContext_GetObject(browse_ctx, mon, TRUE, &unk); 506 if (r != S_OK) 507 { 508 CreateBindCtx(0, &bind_ctx); 509 RegisterBindStatusCallback(bind_ctx, &This->IBindStatusCallback_iface, NULL, 0); 510 This->bind_callback = bind_callback; 511 r = IMoniker_BindToObject(mon, bind_ctx, NULL, &IID_IUnknown, (void**)&unk); 512 if (r == MK_S_ASYNCHRONOUS) 513 { 514 This->async_bind_ctx = bind_ctx; 515 This->async_flags = flags; 516 if (bind_callback) 517 IBindStatusCallback_AddRef(bind_callback); 518 IHlinkBrowseContext_AddRef(This->async_browse_ctx = browse_ctx); 519 IMoniker_Release(mon); 520 return r; 521 } 522 } 523 if (r == S_OK) 524 { 525 r = IUnknown_QueryInterface(unk, &IID_IHlinkTarget, (void **)&target); 526 IUnknown_Release(unk); 527 } 528 if (r == S_OK) 529 { 530 if (bind_ctx) IHlinkTarget_SetBrowseContext(target, browse_ctx); 531 r = IHlinkTarget_Navigate(target, flags, This->Location); 532 IHlinkTarget_Release(target); 533 } 534 535 RevokeBindStatusCallback(bind_ctx, &This->IBindStatusCallback_iface); 536 if (bind_ctx) IBindCtx_Release(bind_ctx); 537 } 538 else 539 { 540 static const WCHAR szOpen[] = {'o','p','e','n',0}; 541 LPWSTR target = NULL; 542 543 r = IHlink_GetStringReference(iface, HLINKGETREF_DEFAULT, &target, NULL); 544 if (SUCCEEDED(r) && target) 545 { 546 ShellExecuteW(NULL, szOpen, target, NULL, NULL, SW_SHOW); 547 CoTaskMemFree(target); 548 r = DRAGDROP_S_DROP; 549 } 550 } 551 IMoniker_Release(mon); 552 } 553 554 if (This->Site) 555 IHlinkSite_OnNavigationComplete(This->Site, This->SiteData, 0, r, NULL); 556 557 TRACE("Finished Navigation\n"); 558 return r; 559 } 560 561 static HRESULT WINAPI IHlink_fnSetAdditionalParams(IHlink* iface, 562 LPCWSTR pwzAdditionalParams) 563 { 564 TRACE("Not implemented in native IHlink\n"); 565 return E_NOTIMPL; 566 } 567 568 static HRESULT WINAPI IHlink_fnGetAdditionalParams(IHlink* iface, 569 LPWSTR* ppwzAdditionalParams) 570 { 571 TRACE("Not implemented in native IHlink\n"); 572 return E_NOTIMPL; 573 } 574 575 static const IHlinkVtbl hlvt = 576 { 577 IHlink_fnQueryInterface, 578 IHlink_fnAddRef, 579 IHlink_fnRelease, 580 IHlink_fnSetHlinkSite, 581 IHlink_fnGetHlinkSite, 582 IHlink_fnSetMonikerReference, 583 IHlink_fnGetMonikerReference, 584 IHlink_fnSetStringReference, 585 IHlink_fnGetStringReference, 586 IHlink_fnSetFriendlyName, 587 IHlink_fnGetFriendlyName, 588 IHlink_fnSetTargetFrameName, 589 IHlink_fnGetTargetFrameName, 590 IHlink_fnGetMiscStatus, 591 IHlink_fnNavigate, 592 IHlink_fnSetAdditionalParams, 593 IHlink_fnGetAdditionalParams 594 }; 595 596 static HRESULT WINAPI IDataObject_fnQueryInterface(IDataObject* iface, 597 REFIID riid, LPVOID *ppvObj) 598 { 599 HlinkImpl *This = impl_from_IDataObject(iface); 600 TRACE("%p\n", This); 601 return IHlink_QueryInterface(&This->IHlink_iface, riid, ppvObj); 602 } 603 604 static ULONG WINAPI IDataObject_fnAddRef (IDataObject* iface) 605 { 606 HlinkImpl *This = impl_from_IDataObject(iface); 607 TRACE("%p\n", This); 608 return IHlink_AddRef(&This->IHlink_iface); 609 } 610 611 static ULONG WINAPI IDataObject_fnRelease (IDataObject* iface) 612 { 613 HlinkImpl *This = impl_from_IDataObject(iface); 614 TRACE("%p\n", This); 615 return IHlink_Release(&This->IHlink_iface); 616 } 617 618 static HRESULT WINAPI IDataObject_fnGetData(IDataObject* iface, 619 FORMATETC* pformatetcIn, STGMEDIUM* pmedium) 620 { 621 FIXME("\n"); 622 return E_NOTIMPL; 623 } 624 625 static HRESULT WINAPI IDataObject_fnGetDataHere(IDataObject* iface, 626 FORMATETC* pformatetc, STGMEDIUM* pmedium) 627 { 628 FIXME("\n"); 629 return E_NOTIMPL; 630 } 631 632 static HRESULT WINAPI IDataObject_fnQueryGetData(IDataObject* iface, 633 FORMATETC* pformatetc) 634 { 635 FIXME("\n"); 636 return E_NOTIMPL; 637 } 638 639 static HRESULT WINAPI IDataObject_fnGetConicalFormatEtc(IDataObject* iface, 640 FORMATETC* pformatetcIn, FORMATETC* pformatetcOut) 641 { 642 FIXME("\n"); 643 return E_NOTIMPL; 644 } 645 646 static HRESULT WINAPI IDataObject_fnSetData(IDataObject* iface, 647 FORMATETC* pformatetc, STGMEDIUM* pmedium, BOOL fRelease) 648 { 649 FIXME("\n"); 650 return E_NOTIMPL; 651 } 652 653 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(IDataObject* iface, 654 DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc) 655 { 656 FIXME("\n"); 657 return E_NOTIMPL; 658 } 659 660 static HRESULT WINAPI IDataObject_fnDAdvise(IDataObject* iface, 661 FORMATETC* pformatetc, DWORD advf, IAdviseSink* pAdvSink, 662 DWORD* pdwConnection) 663 { 664 FIXME("\n"); 665 return E_NOTIMPL; 666 } 667 668 static HRESULT WINAPI IDataObject_fnDUnadvise(IDataObject* iface, 669 DWORD dwConnection) 670 { 671 FIXME("\n"); 672 return E_NOTIMPL; 673 } 674 675 static HRESULT WINAPI IDataObject_fnEnumDAdvise(IDataObject* iface, 676 IEnumSTATDATA** ppenumAdvise) 677 { 678 FIXME("\n"); 679 return E_NOTIMPL; 680 } 681 682 static const IDataObjectVtbl dovt = 683 { 684 IDataObject_fnQueryInterface, 685 IDataObject_fnAddRef, 686 IDataObject_fnRelease, 687 IDataObject_fnGetData, 688 IDataObject_fnGetDataHere, 689 IDataObject_fnQueryGetData, 690 IDataObject_fnGetConicalFormatEtc, 691 IDataObject_fnSetData, 692 IDataObject_fnEnumFormatEtc, 693 IDataObject_fnDAdvise, 694 IDataObject_fnDUnadvise, 695 IDataObject_fnEnumDAdvise 696 }; 697 698 static HRESULT WINAPI IPersistStream_fnQueryInterface(IPersistStream* iface, 699 REFIID riid, LPVOID *ppvObj) 700 { 701 HlinkImpl *This = impl_from_IPersistStream(iface); 702 TRACE("(%p)\n", This); 703 return IHlink_QueryInterface(&This->IHlink_iface, riid, ppvObj); 704 } 705 706 static ULONG WINAPI IPersistStream_fnAddRef (IPersistStream* iface) 707 { 708 HlinkImpl *This = impl_from_IPersistStream(iface); 709 TRACE("(%p)\n", This); 710 return IHlink_AddRef(&This->IHlink_iface); 711 } 712 713 static ULONG WINAPI IPersistStream_fnRelease (IPersistStream* iface) 714 { 715 HlinkImpl *This = impl_from_IPersistStream(iface); 716 TRACE("(%p)\n", This); 717 return IHlink_Release(&This->IHlink_iface); 718 } 719 720 static HRESULT WINAPI IPersistStream_fnGetClassID(IPersistStream* iface, 721 CLSID* pClassID) 722 { 723 HlinkImpl *This = impl_from_IPersistStream(iface); 724 TRACE("(%p)\n", This); 725 *pClassID = CLSID_StdHlink; 726 return S_OK; 727 } 728 729 static HRESULT WINAPI IPersistStream_fnIsDirty(IPersistStream* iface) 730 { 731 FIXME("\n"); 732 return E_NOTIMPL; 733 } 734 735 static HRESULT write_hlink_string(IStream *pStm, LPCWSTR str) 736 { 737 DWORD len; 738 HRESULT hr; 739 740 TRACE("(%p, %s)\n", pStm, debugstr_w(str)); 741 742 len = strlenW(str) + 1; 743 744 hr = IStream_Write(pStm, &len, sizeof(len), NULL); 745 if (FAILED(hr)) return hr; 746 747 hr = IStream_Write(pStm, str, len * sizeof(WCHAR), NULL); 748 if (FAILED(hr)) return hr; 749 750 return S_OK; 751 } 752 753 static inline ULONG size_hlink_string(LPCWSTR str) 754 { 755 return sizeof(DWORD) + (strlenW(str) + 1) * sizeof(WCHAR); 756 } 757 758 static HRESULT read_hlink_string(IStream *pStm, LPWSTR *out_str) 759 { 760 LPWSTR str; 761 DWORD len; 762 ULONG read; 763 HRESULT hr; 764 765 hr = IStream_Read(pStm, &len, sizeof(len), &read); 766 if (FAILED(hr)) return hr; 767 if (read != sizeof(len)) return STG_E_READFAULT; 768 769 TRACE("read len %d\n", len); 770 771 str = heap_alloc(len * sizeof(WCHAR)); 772 if (!str) return E_OUTOFMEMORY; 773 774 hr = IStream_Read(pStm, str, len * sizeof(WCHAR), &read); 775 if (FAILED(hr)) 776 { 777 heap_free(str); 778 return hr; 779 } 780 if (read != len * sizeof(WCHAR)) 781 { 782 heap_free(str); 783 return STG_E_READFAULT; 784 } 785 TRACE("read string %s\n", debugstr_w(str)); 786 787 *out_str = str; 788 return S_OK; 789 } 790 791 static HRESULT WINAPI IPersistStream_fnLoad(IPersistStream* iface, 792 IStream* pStm) 793 { 794 HRESULT r; 795 DWORD hdr[2]; 796 DWORD read; 797 HlinkImpl *This = impl_from_IPersistStream(iface); 798 799 r = IStream_Read(pStm, hdr, sizeof(hdr), &read); 800 if (read != sizeof(hdr) || (hdr[0] != HLINK_SAVE_MAGIC)) 801 { 802 r = E_FAIL; 803 goto end; 804 } 805 if (hdr[1] & ~HLINK_SAVE_ALL) 806 FIXME("unknown flag(s) 0x%x\n", hdr[1] & ~HLINK_SAVE_ALL); 807 808 if (hdr[1] & HLINK_SAVE_TARGET_FRAME_PRESENT) 809 { 810 TRACE("loading target frame name\n"); 811 r = read_hlink_string(pStm, &This->TargetFrameName); 812 if (FAILED(r)) goto end; 813 } 814 815 if (hdr[1] & HLINK_SAVE_FRIENDLY_PRESENT) 816 { 817 TRACE("loading target friendly name\n"); 818 if (!(hdr[1] & 0x4)) 819 FIXME("0x4 flag not present with friendly name flag - not sure what this means\n"); 820 r = read_hlink_string(pStm, &This->FriendlyName); 821 if (FAILED(r)) goto end; 822 } 823 824 if (hdr[1] & HLINK_SAVE_MONIKER_PRESENT) 825 { 826 TRACE("loading moniker\n"); 827 r = OleLoadFromStream(pStm, &IID_IMoniker, (LPVOID*)&(This->Moniker)); 828 if (FAILED(r)) 829 goto end; 830 This->absolute = (hdr[1] & HLINK_SAVE_MONIKER_IS_ABSOLUTE) != 0; 831 } 832 833 if (hdr[1] & HLINK_SAVE_LOCATION_PRESENT) 834 { 835 TRACE("loading location\n"); 836 r = read_hlink_string(pStm, &This->Location); 837 if (FAILED(r)) goto end; 838 } 839 840 end: 841 TRACE("Load Result 0x%x (%p)\n", r, This->Moniker); 842 843 return r; 844 } 845 846 static HRESULT WINAPI IPersistStream_fnSave(IPersistStream* iface, 847 IStream* pStm, BOOL fClearDirty) 848 { 849 HRESULT r; 850 HlinkImpl *This = impl_from_IPersistStream(iface); 851 DWORD hdr[2]; 852 IMoniker *moniker; 853 854 TRACE("(%p) Moniker(%p)\n", This, This->Moniker); 855 856 r = __GetMoniker(This, &moniker, HLINKGETREF_DEFAULT); 857 if (FAILED(r)) 858 return r; 859 r = E_FAIL; 860 861 hdr[0] = HLINK_SAVE_MAGIC; 862 hdr[1] = 0; 863 864 if (moniker) 865 hdr[1] |= HLINK_SAVE_MONIKER_PRESENT; 866 if (This->absolute) 867 hdr[1] |= HLINK_SAVE_MONIKER_IS_ABSOLUTE; 868 if (This->Location) 869 hdr[1] |= HLINK_SAVE_LOCATION_PRESENT; 870 if (This->FriendlyName) 871 hdr[1] |= HLINK_SAVE_FRIENDLY_PRESENT | 4 /* FIXME */; 872 if (This->TargetFrameName) 873 hdr[1] |= HLINK_SAVE_TARGET_FRAME_PRESENT; 874 875 IStream_Write(pStm, hdr, sizeof(hdr), NULL); 876 877 if (This->TargetFrameName) 878 { 879 r = write_hlink_string(pStm, This->TargetFrameName); 880 if (FAILED(r)) goto end; 881 } 882 883 if (This->FriendlyName) 884 { 885 r = write_hlink_string(pStm, This->FriendlyName); 886 if (FAILED(r)) goto end; 887 } 888 889 if (moniker) 890 { 891 IPersistStream* monstream; 892 893 monstream = NULL; 894 IMoniker_QueryInterface(moniker, &IID_IPersistStream, 895 (LPVOID*)&monstream); 896 if (monstream) 897 { 898 r = OleSaveToStream(monstream, pStm); 899 IPersistStream_Release(monstream); 900 } 901 if (FAILED(r)) goto end; 902 } 903 904 if (This->Location) 905 { 906 r = write_hlink_string(pStm, This->Location); 907 if (FAILED(r)) goto end; 908 } 909 910 end: 911 if (moniker) IMoniker_Release(moniker); 912 TRACE("Save Result 0x%x\n", r); 913 914 return r; 915 } 916 917 static HRESULT WINAPI IPersistStream_fnGetSizeMax(IPersistStream* iface, 918 ULARGE_INTEGER* pcbSize) 919 { 920 HRESULT r; 921 HlinkImpl *This = impl_from_IPersistStream(iface); 922 IMoniker *moniker; 923 924 TRACE("(%p) Moniker(%p)\n", This, This->Moniker); 925 926 pcbSize->QuadPart = sizeof(DWORD)*2; 927 928 if (This->TargetFrameName) 929 pcbSize->QuadPart += size_hlink_string(This->TargetFrameName); 930 931 if (This->FriendlyName) 932 pcbSize->QuadPart += size_hlink_string(This->FriendlyName); 933 934 r = __GetMoniker(This, &moniker, HLINKGETREF_DEFAULT); 935 if (FAILED(r)) 936 return r; 937 r = E_FAIL; 938 939 if (moniker) 940 { 941 IPersistStream* monstream = NULL; 942 IMoniker_QueryInterface(moniker, &IID_IPersistStream, 943 (LPVOID*)&monstream); 944 if (monstream) 945 { 946 ULARGE_INTEGER mon_size; 947 r = IPersistStream_GetSizeMax(monstream, &mon_size); 948 pcbSize->QuadPart += mon_size.QuadPart; 949 IPersistStream_Release(monstream); 950 } 951 IMoniker_Release(moniker); 952 } 953 954 if (This->Location) 955 pcbSize->QuadPart += size_hlink_string(This->Location); 956 957 return r; 958 } 959 960 static const IPersistStreamVtbl psvt = 961 { 962 IPersistStream_fnQueryInterface, 963 IPersistStream_fnAddRef, 964 IPersistStream_fnRelease, 965 IPersistStream_fnGetClassID, 966 IPersistStream_fnIsDirty, 967 IPersistStream_fnLoad, 968 IPersistStream_fnSave, 969 IPersistStream_fnGetSizeMax, 970 }; 971 972 static HlinkImpl *impl_from_IBindStatusCallback(IBindStatusCallback *iface) 973 { 974 return CONTAINING_RECORD(iface, HlinkImpl, IBindStatusCallback_iface); 975 } 976 977 static HRESULT WINAPI bind_callback_QueryInterface(IBindStatusCallback *iface, REFIID iid, void **out) 978 { 979 if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IBindStatusCallback)) 980 { 981 IBindStatusCallback_AddRef(*out = iface); 982 return S_OK; 983 } 984 985 WARN("No interface for %s.\n", debugstr_guid(iid)); 986 return E_NOINTERFACE; 987 } 988 989 static ULONG WINAPI bind_callback_AddRef(IBindStatusCallback *iface) 990 { 991 HlinkImpl *hlink = impl_from_IBindStatusCallback(iface); 992 return IHlink_AddRef(&hlink->IHlink_iface); 993 } 994 995 static ULONG WINAPI bind_callback_Release(IBindStatusCallback *iface) 996 { 997 HlinkImpl *hlink = impl_from_IBindStatusCallback(iface); 998 return IHlink_Release(&hlink->IHlink_iface); 999 } 1000 1001 static HRESULT WINAPI bind_callback_OnStartBinding(IBindStatusCallback *iface, 1002 DWORD reserved, IBinding *binding) 1003 { 1004 HlinkImpl *hlink = impl_from_IBindStatusCallback(iface); 1005 1006 TRACE("hlink %p, reserved %#x, binding %p.\n", hlink, reserved, binding); 1007 1008 if (hlink->bind_callback) 1009 return IBindStatusCallback_OnStartBinding(hlink->bind_callback, reserved, binding); 1010 return S_OK; 1011 } 1012 1013 static HRESULT WINAPI bind_callback_GetPriority(IBindStatusCallback *iface, LONG *priority) 1014 { 1015 FIXME("iface %p, priority %p, stub!\n", iface, priority); 1016 return E_NOTIMPL; 1017 } 1018 1019 static HRESULT WINAPI bind_callback_OnLowResource(IBindStatusCallback *iface, DWORD reserved) 1020 { 1021 HlinkImpl *hlink = impl_from_IBindStatusCallback(iface); 1022 1023 TRACE("hlink %p, reserved %#x.\n", hlink, reserved); 1024 1025 if (hlink->bind_callback) 1026 return IBindStatusCallback_OnLowResource(hlink->bind_callback, reserved); 1027 return S_OK; 1028 } 1029 1030 static HRESULT WINAPI bind_callback_OnProgress(IBindStatusCallback *iface, 1031 ULONG progress, ULONG max, ULONG status, const WCHAR *text) 1032 { 1033 HlinkImpl *hlink = impl_from_IBindStatusCallback(iface); 1034 1035 TRACE("hlink %p, progress %u, max %u, status %u, text %s.\n", 1036 hlink, progress, max, status, debugstr_w(text)); 1037 1038 if (hlink->bind_callback) 1039 return IBindStatusCallback_OnProgress(hlink->bind_callback, progress, max, status, text); 1040 return S_OK; 1041 } 1042 1043 static HRESULT WINAPI bind_callback_OnStopBinding(IBindStatusCallback *iface, 1044 HRESULT hr, const WCHAR *error) 1045 { 1046 HlinkImpl *hlink = impl_from_IBindStatusCallback(iface); 1047 1048 TRACE("hlink %p, hr %#x, error %s.\n", hlink, hr, debugstr_w(error)); 1049 1050 if (hlink->bind_callback) 1051 IBindStatusCallback_OnStopBinding(hlink->bind_callback, hr, error); 1052 1053 if (hlink->async_bind_ctx) 1054 { 1055 if (hlink->bind_callback) 1056 IBindStatusCallback_Release(hlink->bind_callback); 1057 RevokeBindStatusCallback(hlink->async_bind_ctx, iface); 1058 IBindCtx_Release(hlink->async_bind_ctx); 1059 IHlinkBrowseContext_Release(hlink->async_browse_ctx); 1060 hlink->async_bind_ctx = NULL; 1061 } 1062 return S_OK; 1063 } 1064 1065 static HRESULT WINAPI bind_callback_GetBindInfo(IBindStatusCallback *iface, 1066 DWORD *bind_flags, BINDINFO *bind_info) 1067 { 1068 HlinkImpl *hlink = impl_from_IBindStatusCallback(iface); 1069 1070 TRACE("hlink %p, bind_flags %p, bind_info %p.\n", hlink, bind_flags, bind_info); 1071 1072 if (hlink->bind_callback) 1073 return IBindStatusCallback_GetBindInfo(hlink->bind_callback, bind_flags, bind_info); 1074 return S_OK; 1075 } 1076 1077 static HRESULT WINAPI bind_callback_OnDataAvailable(IBindStatusCallback *iface, 1078 DWORD flags, DWORD size, FORMATETC *formatetc, STGMEDIUM *stgmed) 1079 { 1080 FIXME("iface %p, flags %#x, size %d, formatetc %p, stgmed %p, stub!\n", 1081 iface, flags, size, formatetc, stgmed); 1082 return E_NOTIMPL; 1083 } 1084 1085 static HRESULT WINAPI bind_callback_OnObjectAvailable(IBindStatusCallback *iface, 1086 REFIID iid, IUnknown *unk) 1087 { 1088 HlinkImpl *hlink = impl_from_IBindStatusCallback(iface); 1089 IHlinkTarget *target; 1090 HRESULT hr; 1091 1092 TRACE("hlink %p, iid %s, unk %p.\n", hlink, debugstr_guid(iid), unk); 1093 1094 if (hlink->bind_callback) 1095 IBindStatusCallback_OnObjectAvailable(hlink->bind_callback, iid, unk); 1096 1097 if (hlink->async_bind_ctx) 1098 { 1099 hr = IUnknown_QueryInterface(unk, &IID_IHlinkTarget, (void **)&target); 1100 if (FAILED(hr)) 1101 return hr; 1102 1103 IHlinkTarget_SetBrowseContext(target, hlink->async_browse_ctx); 1104 hr = IHlinkTarget_Navigate(target, hlink->async_flags, hlink->Location); 1105 IHlinkTarget_Release(target); 1106 1107 if (hlink->Site) 1108 IHlinkSite_OnNavigationComplete(hlink->Site, hlink->SiteData, 0, hr, NULL); 1109 1110 return hr; 1111 } 1112 1113 return S_OK; 1114 } 1115 1116 static const IBindStatusCallbackVtbl bind_callback_vtbl = 1117 { 1118 bind_callback_QueryInterface, 1119 bind_callback_AddRef, 1120 bind_callback_Release, 1121 bind_callback_OnStartBinding, 1122 bind_callback_GetPriority, 1123 bind_callback_OnLowResource, 1124 bind_callback_OnProgress, 1125 bind_callback_OnStopBinding, 1126 bind_callback_GetBindInfo, 1127 bind_callback_OnDataAvailable, 1128 bind_callback_OnObjectAvailable, 1129 }; 1130 1131 HRESULT HLink_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv) 1132 { 1133 HlinkImpl * hl; 1134 1135 TRACE("unkOut=%p riid=%s\n", pUnkOuter, debugstr_guid(riid)); 1136 *ppv = NULL; 1137 1138 if (pUnkOuter) 1139 return CLASS_E_NOAGGREGATION; 1140 1141 hl = heap_alloc_zero(sizeof(HlinkImpl)); 1142 if (!hl) 1143 return E_OUTOFMEMORY; 1144 1145 hl->ref = 1; 1146 hl->IHlink_iface.lpVtbl = &hlvt; 1147 hl->IPersistStream_iface.lpVtbl = &psvt; 1148 hl->IDataObject_iface.lpVtbl = &dovt; 1149 hl->IBindStatusCallback_iface.lpVtbl = &bind_callback_vtbl; 1150 1151 *ppv = hl; 1152 return S_OK; 1153 } 1154