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