1 /* 2 * UrlMon 3 * 4 * Copyright 1999 Ulrich Czekalla for Corel Corporation 5 * Copyright 2002 Huw D M Davies for CodeWeavers 6 * Copyright 2005 Jacek Caban for CodeWeavers 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21 */ 22 23 #include "urlmon_main.h" 24 25 #include <shellapi.h> 26 #include <hlink.h> 27 28 typedef struct { 29 IMoniker IMoniker_iface; 30 IUriContainer IUriContainer_iface; 31 32 LONG ref; 33 34 IUri *uri; 35 BSTR URLName; 36 } URLMoniker; 37 38 static inline URLMoniker *impl_from_IMoniker(IMoniker *iface) 39 { 40 return CONTAINING_RECORD(iface, URLMoniker, IMoniker_iface); 41 } 42 43 static HRESULT WINAPI URLMoniker_QueryInterface(IMoniker *iface, REFIID riid, void **ppv) 44 { 45 URLMoniker *This = impl_from_IMoniker(iface); 46 47 if(!ppv) 48 return E_INVALIDARG; 49 50 if(IsEqualIID(&IID_IUnknown, riid)) { 51 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 52 *ppv = iface; 53 }else if(IsEqualIID(&IID_IPersist, riid)) { 54 TRACE("(%p)->(IID_IPersist %p)\n", This, ppv); 55 *ppv = iface; 56 }else if(IsEqualIID(&IID_IPersistStream,riid)) { 57 TRACE("(%p)->(IID_IPersistStream %p)\n", This, ppv); 58 *ppv = iface; 59 }else if(IsEqualIID(&IID_IMoniker, riid)) { 60 TRACE("(%p)->(IID_IMoniker %p)\n", This, ppv); 61 *ppv = iface; 62 }else if(IsEqualIID(&IID_IAsyncMoniker, riid)) { 63 TRACE("(%p)->(IID_IAsyncMoniker %p)\n", This, ppv); 64 *ppv = iface; 65 }else if(IsEqualIID(&IID_IUriContainer, riid)) { 66 TRACE("(%p)->(IID_IUriContainer %p)\n", This, ppv); 67 *ppv = &This->IUriContainer_iface; 68 }else { 69 WARN("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppv); 70 *ppv = NULL; 71 return E_NOINTERFACE; 72 } 73 74 IUnknown_AddRef((IUnknown*)*ppv); 75 return S_OK; 76 } 77 78 static ULONG WINAPI URLMoniker_AddRef(IMoniker *iface) 79 { 80 URLMoniker *This = impl_from_IMoniker(iface); 81 ULONG refCount = InterlockedIncrement(&This->ref); 82 83 TRACE("(%p) ref=%u\n",This, refCount); 84 85 return refCount; 86 } 87 88 static ULONG WINAPI URLMoniker_Release(IMoniker *iface) 89 { 90 URLMoniker *This = impl_from_IMoniker(iface); 91 ULONG refCount = InterlockedDecrement(&This->ref); 92 93 TRACE("(%p) ref=%u\n",This, refCount); 94 95 if (!refCount) { 96 if(This->uri) 97 IUri_Release(This->uri); 98 SysFreeString(This->URLName); 99 heap_free(This); 100 101 URLMON_UnlockModule(); 102 } 103 104 return refCount; 105 } 106 107 static HRESULT WINAPI URLMoniker_GetClassID(IMoniker *iface, CLSID *pClassID) 108 { 109 URLMoniker *This = impl_from_IMoniker(iface); 110 111 TRACE("(%p,%p)\n", This, pClassID); 112 113 if(!pClassID) 114 return E_POINTER; 115 116 /* Windows always returns CLSID_StdURLMoniker */ 117 *pClassID = CLSID_StdURLMoniker; 118 return S_OK; 119 } 120 121 static HRESULT WINAPI URLMoniker_IsDirty(IMoniker *iface) 122 { 123 URLMoniker *This = impl_from_IMoniker(iface); 124 125 TRACE("(%p)\n",This); 126 127 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty 128 method in the OLE-provided moniker interfaces always return S_FALSE because 129 their internal state never changes. */ 130 return S_FALSE; 131 } 132 133 static HRESULT WINAPI URLMoniker_Load(IMoniker* iface,IStream* pStm) 134 { 135 URLMoniker *This = impl_from_IMoniker(iface); 136 WCHAR *new_uri_str; 137 IUri *new_uri; 138 BSTR new_url; 139 ULONG size; 140 ULONG got; 141 HRESULT hres; 142 143 TRACE("(%p,%p)\n",This,pStm); 144 145 if(!pStm) 146 return E_INVALIDARG; 147 148 /* 149 * NOTE 150 * Writes a ULONG containing length of unicode string, followed 151 * by that many unicode characters 152 */ 153 hres = IStream_Read(pStm, &size, sizeof(ULONG), &got); 154 if(FAILED(hres)) 155 return hres; 156 if(got != sizeof(ULONG)) 157 return E_FAIL; 158 159 new_uri_str = heap_alloc(size+sizeof(WCHAR)); 160 if(!new_uri_str) 161 return E_OUTOFMEMORY; 162 163 hres = IStream_Read(pStm, new_uri_str, size, NULL); 164 new_uri_str[size/sizeof(WCHAR)] = 0; 165 if(SUCCEEDED(hres)) 166 hres = CreateUri(new_uri_str, 0, 0, &new_uri); 167 heap_free(new_uri_str); 168 if(FAILED(hres)) 169 return hres; 170 171 hres = IUri_GetDisplayUri(new_uri, &new_url); 172 if(FAILED(hres)) { 173 IUri_Release(new_uri); 174 return hres; 175 } 176 177 SysFreeString(This->URLName); 178 if(This->uri) 179 IUri_Release(This->uri); 180 181 This->uri = new_uri; 182 This->URLName = new_url; 183 return S_OK; 184 } 185 186 static HRESULT WINAPI URLMoniker_Save(IMoniker *iface, IStream* pStm, BOOL fClearDirty) 187 { 188 URLMoniker *This = impl_from_IMoniker(iface); 189 HRESULT res; 190 ULONG size; 191 192 TRACE("(%p,%p,%d)\n", This, pStm, fClearDirty); 193 194 if(!pStm) 195 return E_INVALIDARG; 196 197 size = (SysStringLen(This->URLName) + 1)*sizeof(WCHAR); 198 res=IStream_Write(pStm,&size,sizeof(ULONG),NULL); 199 if(SUCCEEDED(res)) 200 res=IStream_Write(pStm,This->URLName,size,NULL); 201 202 return res; 203 204 } 205 206 static HRESULT WINAPI URLMoniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER *pcbSize) 207 { 208 URLMoniker *This = impl_from_IMoniker(iface); 209 210 TRACE("(%p,%p)\n",This,pcbSize); 211 212 if(!pcbSize) 213 return E_INVALIDARG; 214 215 pcbSize->QuadPart = sizeof(ULONG) + ((SysStringLen(This->URLName)+1) * sizeof(WCHAR)); 216 return S_OK; 217 } 218 219 static HRESULT WINAPI URLMoniker_BindToObject(IMoniker *iface, IBindCtx* pbc, IMoniker *pmkToLeft, 220 REFIID riid, void **ppv) 221 { 222 URLMoniker *This = impl_from_IMoniker(iface); 223 IRunningObjectTable *obj_tbl; 224 HRESULT hres; 225 226 TRACE("(%p)->(%p,%p,%s,%p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppv); 227 228 hres = IBindCtx_GetRunningObjectTable(pbc, &obj_tbl); 229 if(SUCCEEDED(hres)) { 230 hres = IRunningObjectTable_IsRunning(obj_tbl, &This->IMoniker_iface); 231 if(hres == S_OK) { 232 IUnknown *unk = NULL; 233 234 TRACE("Found in running object table\n"); 235 236 hres = IRunningObjectTable_GetObject(obj_tbl, &This->IMoniker_iface, &unk); 237 if(SUCCEEDED(hres)) { 238 hres = IUnknown_QueryInterface(unk, riid, ppv); 239 IUnknown_Release(unk); 240 } 241 242 IRunningObjectTable_Release(obj_tbl); 243 return hres; 244 } 245 246 IRunningObjectTable_Release(obj_tbl); 247 } 248 249 if(!This->uri) { 250 *ppv = NULL; 251 return MK_E_SYNTAX; 252 } 253 254 return bind_to_object(&This->IMoniker_iface, This->uri, pbc, riid, ppv); 255 } 256 257 static HRESULT WINAPI URLMoniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, 258 IMoniker* pmkToLeft, REFIID riid, void **ppvObject) 259 { 260 URLMoniker *This = impl_from_IMoniker(iface); 261 262 TRACE("(%p)->(%p %p %s %p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppvObject); 263 264 if(ppvObject) *ppvObject = NULL; 265 266 if(!pbc || !ppvObject) return E_INVALIDARG; 267 268 if(pmkToLeft) 269 FIXME("Unsupported pmkToLeft\n"); 270 271 if(!This->uri) 272 return MK_E_SYNTAX; 273 274 return bind_to_storage(This->uri, pbc, riid, ppvObject); 275 } 276 277 static HRESULT WINAPI URLMoniker_Reduce(IMoniker *iface, IBindCtx *pbc, 278 DWORD dwReduceHowFar, IMoniker **ppmkToLeft, IMoniker **ppmkReduced) 279 { 280 URLMoniker *This = impl_from_IMoniker(iface); 281 282 TRACE("(%p,%p,%d,%p,%p)\n", This, pbc, dwReduceHowFar, ppmkToLeft, ppmkReduced); 283 284 if(!ppmkReduced) 285 return E_INVALIDARG; 286 287 IMoniker_AddRef(iface); 288 *ppmkReduced = iface; 289 return MK_S_REDUCED_TO_SELF; 290 } 291 292 static HRESULT WINAPI URLMoniker_ComposeWith(IMoniker *iface, IMoniker *pmkRight, 293 BOOL fOnlyIfNotGeneric, IMoniker **ppmkComposite) 294 { 295 URLMoniker *This = impl_from_IMoniker(iface); 296 FIXME("(%p)->(%p,%d,%p): stub\n",This,pmkRight,fOnlyIfNotGeneric,ppmkComposite); 297 return E_NOTIMPL; 298 } 299 300 static HRESULT WINAPI URLMoniker_Enum(IMoniker *iface, BOOL fForward, IEnumMoniker **ppenumMoniker) 301 { 302 URLMoniker *This = impl_from_IMoniker(iface); 303 304 TRACE("(%p,%d,%p)\n", This, fForward, ppenumMoniker); 305 306 if(!ppenumMoniker) 307 return E_INVALIDARG; 308 309 /* Does not support sub-monikers */ 310 *ppenumMoniker = NULL; 311 return S_OK; 312 } 313 314 static HRESULT WINAPI URLMoniker_IsEqual(IMoniker *iface, IMoniker *pmkOtherMoniker) 315 { 316 URLMoniker *This = impl_from_IMoniker(iface); 317 CLSID clsid; 318 LPOLESTR urlPath; 319 IBindCtx* bind; 320 HRESULT res; 321 322 TRACE("(%p,%p)\n",This, pmkOtherMoniker); 323 324 if(pmkOtherMoniker==NULL) 325 return E_INVALIDARG; 326 327 IMoniker_GetClassID(pmkOtherMoniker,&clsid); 328 329 if(!IsEqualCLSID(&clsid,&CLSID_StdURLMoniker)) 330 return S_FALSE; 331 332 res = CreateBindCtx(0,&bind); 333 if(FAILED(res)) 334 return res; 335 336 res = S_FALSE; 337 if(SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&urlPath))) { 338 int result = lstrcmpiW(urlPath, This->URLName); 339 CoTaskMemFree(urlPath); 340 if(result == 0) 341 res = S_OK; 342 } 343 IBindCtx_Release(bind); 344 return res; 345 } 346 347 348 static HRESULT WINAPI URLMoniker_Hash(IMoniker *iface, DWORD *pdwHash) 349 { 350 URLMoniker *This = impl_from_IMoniker(iface); 351 int h = 0,i,skip,len; 352 int off = 0; 353 LPOLESTR val; 354 355 TRACE("(%p,%p)\n",This,pdwHash); 356 357 if(!pdwHash) 358 return E_INVALIDARG; 359 360 val = This->URLName; 361 len = lstrlenW(val); 362 363 if(len < 16) { 364 for(i = len ; i > 0; i--) { 365 h = (h * 37) + val[off++]; 366 } 367 }else { 368 /* only sample some characters */ 369 skip = len / 8; 370 for(i = len; i > 0; i -= skip, off += skip) { 371 h = (h * 39) + val[off]; 372 } 373 } 374 *pdwHash = h; 375 return S_OK; 376 } 377 378 static HRESULT WINAPI URLMoniker_IsRunning(IMoniker* iface, IBindCtx* pbc, 379 IMoniker *pmkToLeft, IMoniker *pmkNewlyRunning) 380 { 381 URLMoniker *This = impl_from_IMoniker(iface); 382 FIXME("(%p)->(%p,%p,%p): stub\n",This,pbc,pmkToLeft,pmkNewlyRunning); 383 return E_NOTIMPL; 384 } 385 386 static HRESULT WINAPI URLMoniker_GetTimeOfLastChange(IMoniker *iface, 387 IBindCtx *pbc, IMoniker *pmkToLeft, FILETIME *pFileTime) 388 { 389 URLMoniker *This = impl_from_IMoniker(iface); 390 FIXME("(%p)->(%p,%p,%p): stub\n", This, pbc, pmkToLeft, pFileTime); 391 return E_NOTIMPL; 392 } 393 394 static HRESULT WINAPI URLMoniker_Inverse(IMoniker *iface, IMoniker **ppmk) 395 { 396 URLMoniker *This = impl_from_IMoniker(iface); 397 TRACE("(%p,%p)\n",This,ppmk); 398 return MK_E_NOINVERSE; 399 } 400 401 static HRESULT WINAPI URLMoniker_CommonPrefixWith(IMoniker *iface, IMoniker *pmkOther, IMoniker **ppmkPrefix) 402 { 403 URLMoniker *This = impl_from_IMoniker(iface); 404 FIXME("(%p)->(%p,%p): stub\n",This,pmkOther,ppmkPrefix); 405 return E_NOTIMPL; 406 } 407 408 static HRESULT WINAPI URLMoniker_RelativePathTo(IMoniker *iface, IMoniker *pmOther, IMoniker **ppmkRelPath) 409 { 410 URLMoniker *This = impl_from_IMoniker(iface); 411 FIXME("(%p)->(%p,%p): stub\n",This,pmOther,ppmkRelPath); 412 return E_NOTIMPL; 413 } 414 415 static HRESULT WINAPI URLMoniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, 416 LPOLESTR *ppszDisplayName) 417 { 418 URLMoniker *This = impl_from_IMoniker(iface); 419 int len; 420 421 TRACE("(%p,%p,%p,%p)\n", This, pbc, pmkToLeft, ppszDisplayName); 422 423 if(!ppszDisplayName) 424 return E_INVALIDARG; 425 426 if(!This->URLName) 427 return E_OUTOFMEMORY; 428 429 /* FIXME: If this is a partial URL, try and get a URL moniker from SZ_URLCONTEXT in the bind context, 430 then look at pmkToLeft to try and complete the URL 431 */ 432 len = SysStringLen(This->URLName)+1; 433 *ppszDisplayName = CoTaskMemAlloc(len*sizeof(WCHAR)); 434 if(!*ppszDisplayName) 435 return E_OUTOFMEMORY; 436 lstrcpyW(*ppszDisplayName, This->URLName); 437 return S_OK; 438 } 439 440 static HRESULT WINAPI URLMoniker_ParseDisplayName(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, 441 LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut) 442 { 443 URLMoniker *This = impl_from_IMoniker(iface); 444 FIXME("(%p)->(%p,%p,%p,%p,%p): stub\n",This,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut); 445 return E_NOTIMPL; 446 } 447 448 static HRESULT WINAPI URLMoniker_IsSystemMoniker(IMoniker *iface, DWORD *pwdMksys) 449 { 450 URLMoniker *This = impl_from_IMoniker(iface); 451 452 TRACE("(%p,%p)\n",This,pwdMksys); 453 454 if(!pwdMksys) 455 return E_INVALIDARG; 456 457 *pwdMksys = MKSYS_URLMONIKER; 458 return S_OK; 459 } 460 461 static const IMonikerVtbl URLMonikerVtbl = 462 { 463 URLMoniker_QueryInterface, 464 URLMoniker_AddRef, 465 URLMoniker_Release, 466 URLMoniker_GetClassID, 467 URLMoniker_IsDirty, 468 URLMoniker_Load, 469 URLMoniker_Save, 470 URLMoniker_GetSizeMax, 471 URLMoniker_BindToObject, 472 URLMoniker_BindToStorage, 473 URLMoniker_Reduce, 474 URLMoniker_ComposeWith, 475 URLMoniker_Enum, 476 URLMoniker_IsEqual, 477 URLMoniker_Hash, 478 URLMoniker_IsRunning, 479 URLMoniker_GetTimeOfLastChange, 480 URLMoniker_Inverse, 481 URLMoniker_CommonPrefixWith, 482 URLMoniker_RelativePathTo, 483 URLMoniker_GetDisplayName, 484 URLMoniker_ParseDisplayName, 485 URLMoniker_IsSystemMoniker 486 }; 487 488 static inline URLMoniker *impl_from_IUriContainer(IUriContainer *iface) 489 { 490 return CONTAINING_RECORD(iface, URLMoniker, IUriContainer_iface); 491 } 492 493 static HRESULT WINAPI UriContainer_QueryInterface(IUriContainer *iface, REFIID riid, void **ppv) 494 { 495 URLMoniker *This = impl_from_IUriContainer(iface); 496 return IMoniker_QueryInterface(&This->IMoniker_iface, riid, ppv); 497 } 498 499 static ULONG WINAPI UriContainer_AddRef(IUriContainer *iface) 500 { 501 URLMoniker *This = impl_from_IUriContainer(iface); 502 return IMoniker_AddRef(&This->IMoniker_iface); 503 } 504 505 static ULONG WINAPI UriContainer_Release(IUriContainer *iface) 506 { 507 URLMoniker *This = impl_from_IUriContainer(iface); 508 return IMoniker_Release(&This->IMoniker_iface); 509 } 510 511 static HRESULT WINAPI UriContainer_GetIUri(IUriContainer *iface, IUri **ppIUri) 512 { 513 URLMoniker *This = impl_from_IUriContainer(iface); 514 515 TRACE("(%p)->(%p)\n", This, ppIUri); 516 517 if(!This->uri) { 518 *ppIUri = NULL; 519 return S_FALSE; 520 } 521 522 IUri_AddRef(This->uri); 523 *ppIUri = This->uri; 524 return S_OK; 525 } 526 527 static const IUriContainerVtbl UriContainerVtbl = { 528 UriContainer_QueryInterface, 529 UriContainer_AddRef, 530 UriContainer_Release, 531 UriContainer_GetIUri 532 }; 533 534 static HRESULT create_moniker(IUri *uri, URLMoniker **ret) 535 { 536 URLMoniker *mon; 537 HRESULT hres; 538 539 mon = heap_alloc(sizeof(*mon)); 540 if(!mon) 541 return E_OUTOFMEMORY; 542 543 mon->IMoniker_iface.lpVtbl = &URLMonikerVtbl; 544 mon->IUriContainer_iface.lpVtbl = &UriContainerVtbl; 545 mon->ref = 1; 546 547 if(uri) { 548 /* FIXME: try to avoid it */ 549 hres = IUri_GetDisplayUri(uri, &mon->URLName); 550 if(FAILED(hres)) { 551 heap_free(mon); 552 return hres; 553 } 554 555 IUri_AddRef(uri); 556 mon->uri = uri; 557 }else { 558 mon->URLName = NULL; 559 mon->uri = NULL; 560 } 561 562 URLMON_LockModule(); 563 *ret = mon; 564 return S_OK; 565 } 566 567 HRESULT StdURLMoniker_Construct(IUnknown *outer, void **ppv) 568 { 569 URLMoniker *mon; 570 HRESULT hres; 571 572 TRACE("(%p %p)\n", outer, ppv); 573 574 hres = create_moniker(NULL, &mon); 575 if(FAILED(hres)) 576 return hres; 577 578 *ppv = &mon->IMoniker_iface; 579 return S_OK; 580 } 581 582 static const DWORD create_flags_map[3] = { 583 Uri_CREATE_FILE_USE_DOS_PATH, /* URL_MK_LEGACY */ 584 0, /* URL_MK_UNIFORM */ 585 Uri_CREATE_NO_CANONICALIZE /* URL_MK_NO_CANONICALIZE */ 586 }; 587 588 static const DWORD combine_flags_map[3] = { 589 URL_FILE_USE_PATHURL, /* URL_MK_LEGACY */ 590 0, /* URL_MK_UNIFORM */ 591 URL_DONT_SIMPLIFY /* URL_MK_NO_CANONICALIZE */ 592 }; 593 594 /*********************************************************************** 595 * CreateURLMonikerEx (URLMON.@) 596 * 597 * Create a url moniker. 598 * 599 * PARAMS 600 * pmkContext [I] Context 601 * szURL [I] Url to create the moniker for 602 * ppmk [O] Destination for created moniker. 603 * dwFlags [I] Flags. 604 * 605 * RETURNS 606 * Success: S_OK. ppmk contains the created IMoniker object. 607 * Failure: MK_E_SYNTAX if szURL is not a valid url, or 608 * E_OUTOFMEMORY if memory allocation fails. 609 */ 610 HRESULT WINAPI CreateURLMonikerEx(IMoniker *pmkContext, LPCWSTR szURL, IMoniker **ppmk, DWORD dwFlags) 611 { 612 IUri *uri, *base_uri = NULL; 613 URLMoniker *obj; 614 HRESULT hres; 615 616 TRACE("(%p, %s, %p, %08x)\n", pmkContext, debugstr_w(szURL), ppmk, dwFlags); 617 618 if (ppmk) 619 *ppmk = NULL; 620 621 if (!szURL || !ppmk) 622 return E_INVALIDARG; 623 624 if(dwFlags >= sizeof(create_flags_map)/sizeof(*create_flags_map)) { 625 FIXME("Unsupported flags %x\n", dwFlags); 626 return E_INVALIDARG; 627 } 628 629 if(pmkContext) { 630 IUriContainer *uri_container; 631 632 hres = IMoniker_QueryInterface(pmkContext, &IID_IUriContainer, (void**)&uri_container); 633 if(SUCCEEDED(hres)) { 634 hres = IUriContainer_GetIUri(uri_container, &base_uri); 635 IUriContainer_Release(uri_container); 636 if(FAILED(hres)) 637 return hres; 638 } 639 } 640 641 if(base_uri) { 642 hres = CoInternetCombineUrlEx(base_uri, szURL, combine_flags_map[dwFlags], &uri, 0); 643 IUri_Release(base_uri); 644 }else { 645 hres = CreateUri(szURL, Uri_CREATE_ALLOW_RELATIVE|Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME|create_flags_map[dwFlags], 0, &uri); 646 } 647 if(FAILED(hres)) 648 return hres; 649 650 hres = create_moniker(uri, &obj); 651 IUri_Release(uri); 652 if(FAILED(hres)) 653 return hres; 654 655 *ppmk = &obj->IMoniker_iface; 656 return S_OK; 657 } 658 659 /*********************************************************************** 660 * CreateURLMonikerEx2 (URLMON.@) 661 */ 662 HRESULT WINAPI CreateURLMonikerEx2(IMoniker *pmkContext, IUri *pUri, IMoniker **ppmk, DWORD dwFlags) 663 { 664 IUri *context_uri = NULL, *uri; 665 IUriContainer *uri_container; 666 URLMoniker *ret; 667 HRESULT hres; 668 669 TRACE("(%p %p %p %x)\n", pmkContext, pUri, ppmk, dwFlags); 670 671 if (ppmk) 672 *ppmk = NULL; 673 674 if (!pUri || !ppmk) 675 return E_INVALIDARG; 676 677 if(dwFlags >= sizeof(create_flags_map)/sizeof(*create_flags_map)) { 678 FIXME("Unsupported flags %x\n", dwFlags); 679 return E_INVALIDARG; 680 } 681 682 if(pmkContext) { 683 hres = IMoniker_QueryInterface(pmkContext, &IID_IUriContainer, (void**)&uri_container); 684 if(SUCCEEDED(hres)) { 685 hres = IUriContainer_GetIUri(uri_container, &context_uri); 686 if(FAILED(hres)) 687 context_uri = NULL; 688 IUriContainer_Release(uri_container); 689 } 690 } 691 692 if(context_uri) { 693 hres = CoInternetCombineIUri(context_uri, pUri, combine_flags_map[dwFlags], &uri, 0); 694 IUri_Release(context_uri); 695 if(FAILED(hres)) 696 return hres; 697 }else { 698 uri = pUri; 699 IUri_AddRef(uri); 700 } 701 702 hres = create_moniker(uri, &ret); 703 IUri_Release(uri); 704 if(FAILED(hres)) 705 return hres; 706 707 *ppmk = &ret->IMoniker_iface; 708 return S_OK; 709 } 710 711 /********************************************************************** 712 * CreateURLMoniker (URLMON.@) 713 * 714 * Create a url moniker. 715 * 716 * PARAMS 717 * pmkContext [I] Context 718 * szURL [I] Url to create the moniker for 719 * ppmk [O] Destination for created moniker. 720 * 721 * RETURNS 722 * Success: S_OK. ppmk contains the created IMoniker object. 723 * Failure: MK_E_SYNTAX if szURL is not a valid url, or 724 * E_OUTOFMEMORY if memory allocation fails. 725 */ 726 HRESULT WINAPI CreateURLMoniker(IMoniker *pmkContext, LPCWSTR szURL, IMoniker **ppmk) 727 { 728 return CreateURLMonikerEx(pmkContext, szURL, ppmk, URL_MK_LEGACY); 729 } 730 731 /*********************************************************************** 732 * IsAsyncMoniker (URLMON.@) 733 */ 734 HRESULT WINAPI IsAsyncMoniker(IMoniker *pmk) 735 { 736 IUnknown *am; 737 738 TRACE("(%p)\n", pmk); 739 if(!pmk) 740 return E_INVALIDARG; 741 if(SUCCEEDED(IMoniker_QueryInterface(pmk, &IID_IAsyncMoniker, (void**)&am))) { 742 IUnknown_Release(am); 743 return S_OK; 744 } 745 return S_FALSE; 746 } 747 748 /*********************************************************************** 749 * BindAsyncMoniker (URLMON.@) 750 * 751 * Bind a bind status callback to an asynchronous URL Moniker. 752 * 753 * PARAMS 754 * pmk [I] Moniker object to bind status callback to 755 * grfOpt [I] Options, seems not used 756 * pbsc [I] Status callback to bind 757 * iidResult [I] Interface to return 758 * ppvResult [O] Resulting asynchronous moniker object 759 * 760 * RETURNS 761 * Success: S_OK. 762 * Failure: E_INVALIDARG, if any argument is invalid, or 763 * E_OUTOFMEMORY if memory allocation fails. 764 */ 765 HRESULT WINAPI BindAsyncMoniker(IMoniker *pmk, DWORD grfOpt, IBindStatusCallback *pbsc, REFIID iidResult, LPVOID *ppvResult) 766 { 767 LPBC pbc = NULL; 768 HRESULT hr = E_INVALIDARG; 769 770 TRACE("(%p %08x %p %s %p)\n", pmk, grfOpt, pbsc, debugstr_guid(iidResult), ppvResult); 771 772 if (pmk && ppvResult) 773 { 774 *ppvResult = NULL; 775 776 hr = CreateAsyncBindCtx(0, pbsc, NULL, &pbc); 777 if (hr == NOERROR) 778 { 779 hr = IMoniker_BindToObject(pmk, pbc, NULL, iidResult, ppvResult); 780 IBindCtx_Release(pbc); 781 } 782 } 783 return hr; 784 } 785 786 /*********************************************************************** 787 * MkParseDisplayNameEx (URLMON.@) 788 */ 789 HRESULT WINAPI MkParseDisplayNameEx(IBindCtx *pbc, LPCWSTR szDisplayName, ULONG *pchEaten, LPMONIKER *ppmk) 790 { 791 TRACE("(%p %s %p %p)\n", pbc, debugstr_w(szDisplayName), pchEaten, ppmk); 792 793 if (!pbc || !szDisplayName || !*szDisplayName || !pchEaten || !ppmk) 794 return E_INVALIDARG; 795 796 if(is_registered_protocol(szDisplayName)) { 797 HRESULT hres; 798 799 hres = CreateURLMoniker(NULL, szDisplayName, ppmk); 800 if(SUCCEEDED(hres)) { 801 *pchEaten = strlenW(szDisplayName); 802 return hres; 803 } 804 } 805 806 return MkParseDisplayName(pbc, szDisplayName, pchEaten, ppmk); 807 } 808 809 810 /*********************************************************************** 811 * URLDownloadToCacheFileA (URLMON.@) 812 */ 813 HRESULT WINAPI URLDownloadToCacheFileA(LPUNKNOWN lpUnkCaller, LPCSTR szURL, LPSTR szFileName, 814 DWORD dwBufLength, DWORD dwReserved, LPBINDSTATUSCALLBACK pBSC) 815 { 816 LPWSTR url = NULL, file_name = NULL; 817 int len; 818 HRESULT hres; 819 820 TRACE("(%p %s %p %d %d %p)\n", lpUnkCaller, debugstr_a(szURL), szFileName, 821 dwBufLength, dwReserved, pBSC); 822 823 if(szURL) { 824 len = MultiByteToWideChar(CP_ACP, 0, szURL, -1, NULL, 0); 825 url = heap_alloc(len*sizeof(WCHAR)); 826 MultiByteToWideChar(CP_ACP, 0, szURL, -1, url, len); 827 } 828 829 if(szFileName) 830 file_name = heap_alloc(dwBufLength*sizeof(WCHAR)); 831 832 hres = URLDownloadToCacheFileW(lpUnkCaller, url, file_name, dwBufLength*sizeof(WCHAR), 833 dwReserved, pBSC); 834 835 if(SUCCEEDED(hres) && file_name) 836 WideCharToMultiByte(CP_ACP, 0, file_name, -1, szFileName, dwBufLength, NULL, NULL); 837 838 heap_free(url); 839 heap_free(file_name); 840 841 return hres; 842 } 843 844 /*********************************************************************** 845 * URLDownloadToCacheFileW (URLMON.@) 846 */ 847 HRESULT WINAPI URLDownloadToCacheFileW(LPUNKNOWN lpUnkCaller, LPCWSTR szURL, LPWSTR szFileName, 848 DWORD dwBufLength, DWORD dwReserved, LPBINDSTATUSCALLBACK pBSC) 849 { 850 WCHAR cache_path[MAX_PATH + 1]; 851 FILETIME expire, modified; 852 HRESULT hr; 853 LPWSTR ext; 854 855 static WCHAR header[] = { 856 'H','T','T','P','/','1','.','0',' ','2','0','0',' ', 857 'O','K','\\','r','\\','n','\\','r','\\','n',0 858 }; 859 860 TRACE("(%p, %s, %p, %d, %d, %p)\n", lpUnkCaller, debugstr_w(szURL), 861 szFileName, dwBufLength, dwReserved, pBSC); 862 863 if (!szURL || !szFileName) 864 return E_INVALIDARG; 865 866 ext = PathFindExtensionW(szURL); 867 868 if (!CreateUrlCacheEntryW(szURL, 0, ext, cache_path, 0)) 869 return E_FAIL; 870 871 hr = URLDownloadToFileW(lpUnkCaller, szURL, cache_path, 0, pBSC); 872 if (FAILED(hr)) 873 return hr; 874 875 expire.dwHighDateTime = 0; 876 expire.dwLowDateTime = 0; 877 modified.dwHighDateTime = 0; 878 modified.dwLowDateTime = 0; 879 880 if (!CommitUrlCacheEntryW(szURL, cache_path, expire, modified, NORMAL_CACHE_ENTRY, 881 header, sizeof(header), NULL, NULL)) 882 return E_FAIL; 883 884 if (strlenW(cache_path) > dwBufLength) 885 return E_OUTOFMEMORY; 886 887 lstrcpyW(szFileName, cache_path); 888 889 return S_OK; 890 } 891 892 /*********************************************************************** 893 * HlinkSimpleNavigateToMoniker (URLMON.@) 894 */ 895 HRESULT WINAPI HlinkSimpleNavigateToMoniker(IMoniker *pmkTarget, 896 LPCWSTR szLocation, LPCWSTR szTargetFrameName, IUnknown *pUnk, 897 IBindCtx *pbc, IBindStatusCallback *pbsc, DWORD grfHLNF, DWORD dwReserved) 898 { 899 LPWSTR target; 900 HRESULT hres; 901 902 TRACE("\n"); 903 904 hres = IMoniker_GetDisplayName(pmkTarget, pbc, 0, &target); 905 if(hres == S_OK) 906 hres = HlinkSimpleNavigateToString( target, szLocation, szTargetFrameName, 907 pUnk, pbc, pbsc, grfHLNF, dwReserved ); 908 CoTaskMemFree(target); 909 910 return hres; 911 } 912 913 /*********************************************************************** 914 * HlinkSimpleNavigateToString (URLMON.@) 915 */ 916 HRESULT WINAPI HlinkSimpleNavigateToString( LPCWSTR szTarget, 917 LPCWSTR szLocation, LPCWSTR szTargetFrameName, IUnknown *pUnk, 918 IBindCtx *pbc, IBindStatusCallback *pbsc, DWORD grfHLNF, DWORD dwReserved) 919 { 920 FIXME("%s %s %s %p %p %p %u %u partial stub\n", debugstr_w( szTarget ), debugstr_w( szLocation ), 921 debugstr_w( szTargetFrameName ), pUnk, pbc, pbsc, grfHLNF, dwReserved); 922 923 /* undocumented: 0 means HLNF_OPENINNEWWINDOW*/ 924 if (!grfHLNF) grfHLNF = HLNF_OPENINNEWWINDOW; 925 926 if (grfHLNF == HLNF_OPENINNEWWINDOW) 927 { 928 SHELLEXECUTEINFOW sei; 929 static const WCHAR openW[] = { 'o', 'p', 'e', 'n', 0 }; 930 931 memset(&sei, 0, sizeof(sei)); 932 sei.cbSize = sizeof(sei); 933 sei.lpVerb = openW; 934 sei.nShow = SW_SHOWNORMAL; 935 sei.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NO_CONSOLE; 936 sei.lpFile = szTarget; 937 938 if (ShellExecuteExW(&sei)) return S_OK; 939 } 940 941 return E_NOTIMPL; 942 } 943 944 /*********************************************************************** 945 * HlinkNavigateString (URLMON.@) 946 */ 947 HRESULT WINAPI HlinkNavigateString( IUnknown *pUnk, LPCWSTR szTarget ) 948 { 949 TRACE("%p %s\n", pUnk, debugstr_w( szTarget ) ); 950 return HlinkSimpleNavigateToString( 951 szTarget, NULL, NULL, pUnk, NULL, NULL, 0, 0 ); 952 } 953 954 /*********************************************************************** 955 * GetSoftwareUpdateInfo (URLMON.@) 956 */ 957 HRESULT WINAPI GetSoftwareUpdateInfo( LPCWSTR szDistUnit, LPSOFTDISTINFO psdi ) 958 { 959 FIXME("%s %p\n", debugstr_w(szDistUnit), psdi ); 960 return E_FAIL; 961 } 962