1 /* 2 * UrlMon 3 * 4 * Copyright (c) 2000 Patrik Stridvall 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 <stdarg.h> 22 23 #define NONAMELESSUNION 24 25 #include "urlmon_main.h" 26 27 #include "winreg.h" 28 29 #define NO_SHLWAPI_REG 30 #include "shlwapi.h" 31 #include "advpub.h" 32 #include "initguid.h" 33 34 #include "wine/debug.h" 35 36 #include "urlmon.h" 37 38 WINE_DEFAULT_DEBUG_CHANNEL(urlmon); 39 40 DEFINE_GUID(CLSID_CUri, 0xDF2FCE13, 0x25EC, 0x45BB, 0x9D,0x4C, 0xCE,0xCD,0x47,0xC2,0x43,0x0C); 41 42 LONG URLMON_refCount = 0; 43 HINSTANCE urlmon_instance; 44 45 static HMODULE hCabinet = NULL; 46 static DWORD urlmon_tls = TLS_OUT_OF_INDEXES; 47 48 static void init_session(void); 49 50 static struct list tls_list = LIST_INIT(tls_list); 51 52 static CRITICAL_SECTION tls_cs; 53 static CRITICAL_SECTION_DEBUG tls_cs_dbg = 54 { 55 0, 0, &tls_cs, 56 { &tls_cs_dbg.ProcessLocksList, &tls_cs_dbg.ProcessLocksList }, 57 0, 0, { (DWORD_PTR)(__FILE__ ": tls") } 58 }; 59 60 static CRITICAL_SECTION tls_cs = { &tls_cs_dbg, -1, 0, 0, 0, 0 }; 61 62 tls_data_t *get_tls_data(void) 63 { 64 tls_data_t *data; 65 66 if(urlmon_tls == TLS_OUT_OF_INDEXES) { 67 DWORD tls = TlsAlloc(); 68 if(tls == TLS_OUT_OF_INDEXES) 69 return NULL; 70 71 tls = InterlockedCompareExchange((LONG*)&urlmon_tls, tls, TLS_OUT_OF_INDEXES); 72 if(tls != urlmon_tls) 73 TlsFree(tls); 74 } 75 76 data = TlsGetValue(urlmon_tls); 77 if(!data) { 78 data = heap_alloc_zero(sizeof(tls_data_t)); 79 if(!data) 80 return NULL; 81 82 EnterCriticalSection(&tls_cs); 83 list_add_tail(&tls_list, &data->entry); 84 LeaveCriticalSection(&tls_cs); 85 86 TlsSetValue(urlmon_tls, data); 87 } 88 89 return data; 90 } 91 92 static void free_tls_list(void) 93 { 94 tls_data_t *data; 95 96 if(urlmon_tls == TLS_OUT_OF_INDEXES) 97 return; 98 99 while(!list_empty(&tls_list)) { 100 data = LIST_ENTRY(list_head(&tls_list), tls_data_t, entry); 101 list_remove(&data->entry); 102 heap_free(data); 103 } 104 105 TlsFree(urlmon_tls); 106 } 107 108 static void detach_thread(void) 109 { 110 tls_data_t *data; 111 112 if(urlmon_tls == TLS_OUT_OF_INDEXES) 113 return; 114 115 data = TlsGetValue(urlmon_tls); 116 if(!data) 117 return; 118 119 EnterCriticalSection(&tls_cs); 120 list_remove(&data->entry); 121 LeaveCriticalSection(&tls_cs); 122 123 if(data->notif_hwnd) { 124 WARN("notif_hwnd not destroyed\n"); 125 DestroyWindow(data->notif_hwnd); 126 } 127 128 heap_free(data); 129 } 130 131 static void process_detach(void) 132 { 133 HINTERNET internet_session; 134 135 internet_session = get_internet_session(NULL); 136 if(internet_session) 137 InternetCloseHandle(internet_session); 138 139 if (hCabinet) 140 FreeLibrary(hCabinet); 141 142 free_session(); 143 free_tls_list(); 144 unregister_notif_wnd_class(); 145 } 146 147 /*********************************************************************** 148 * DllMain (URLMON.init) 149 */ 150 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad) 151 { 152 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad); 153 154 URLMON_DllMain( hinstDLL, fdwReason, fImpLoad ); 155 156 switch(fdwReason) { 157 case DLL_PROCESS_ATTACH: 158 urlmon_instance = hinstDLL; 159 init_session(); 160 break; 161 162 case DLL_PROCESS_DETACH: 163 if (fImpLoad) break; 164 process_detach(); 165 DeleteCriticalSection(&tls_cs); 166 break; 167 168 case DLL_THREAD_DETACH: 169 detach_thread(); 170 break; 171 } 172 return TRUE; 173 } 174 175 const char *debugstr_bindstatus(ULONG status) 176 { 177 switch(status) { 178 #define X(x) case x: return #x 179 X(BINDSTATUS_FINDINGRESOURCE); 180 X(BINDSTATUS_CONNECTING); 181 X(BINDSTATUS_REDIRECTING); 182 X(BINDSTATUS_BEGINDOWNLOADDATA); 183 X(BINDSTATUS_DOWNLOADINGDATA); 184 X(BINDSTATUS_ENDDOWNLOADDATA); 185 X(BINDSTATUS_BEGINDOWNLOADCOMPONENTS); 186 X(BINDSTATUS_INSTALLINGCOMPONENTS); 187 X(BINDSTATUS_ENDDOWNLOADCOMPONENTS); 188 X(BINDSTATUS_USINGCACHEDCOPY); 189 X(BINDSTATUS_SENDINGREQUEST); 190 X(BINDSTATUS_CLASSIDAVAILABLE); 191 X(BINDSTATUS_MIMETYPEAVAILABLE); 192 X(BINDSTATUS_CACHEFILENAMEAVAILABLE); 193 X(BINDSTATUS_BEGINSYNCOPERATION); 194 X(BINDSTATUS_ENDSYNCOPERATION); 195 X(BINDSTATUS_BEGINUPLOADDATA); 196 X(BINDSTATUS_UPLOADINGDATA); 197 X(BINDSTATUS_ENDUPLOADINGDATA); 198 X(BINDSTATUS_PROTOCOLCLASSID); 199 X(BINDSTATUS_ENCODING); 200 X(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE); 201 X(BINDSTATUS_CLASSINSTALLLOCATION); 202 X(BINDSTATUS_DECODING); 203 X(BINDSTATUS_LOADINGMIMEHANDLER); 204 X(BINDSTATUS_CONTENTDISPOSITIONATTACH); 205 X(BINDSTATUS_FILTERREPORTMIMETYPE); 206 X(BINDSTATUS_CLSIDCANINSTANTIATE); 207 X(BINDSTATUS_IUNKNOWNAVAILABLE); 208 X(BINDSTATUS_DIRECTBIND); 209 X(BINDSTATUS_RAWMIMETYPE); 210 X(BINDSTATUS_PROXYDETECTING); 211 X(BINDSTATUS_ACCEPTRANGES); 212 X(BINDSTATUS_COOKIE_SENT); 213 X(BINDSTATUS_COMPACT_POLICY_RECEIVED); 214 X(BINDSTATUS_COOKIE_SUPPRESSED); 215 X(BINDSTATUS_COOKIE_STATE_UNKNOWN); 216 X(BINDSTATUS_COOKIE_STATE_ACCEPT); 217 X(BINDSTATUS_COOKIE_STATE_REJECT); 218 X(BINDSTATUS_COOKIE_STATE_PROMPT); 219 X(BINDSTATUS_COOKIE_STATE_LEASH); 220 X(BINDSTATUS_COOKIE_STATE_DOWNGRADE); 221 X(BINDSTATUS_POLICY_HREF); 222 X(BINDSTATUS_P3P_HEADER); 223 X(BINDSTATUS_SESSION_COOKIE_RECEIVED); 224 X(BINDSTATUS_PERSISTENT_COOKIE_RECEIVED); 225 X(BINDSTATUS_SESSION_COOKIES_ALLOWED); 226 X(BINDSTATUS_CACHECONTROL); 227 X(BINDSTATUS_CONTENTDISPOSITIONFILENAME); 228 X(BINDSTATUS_MIMETEXTPLAINMISMATCH); 229 X(BINDSTATUS_PUBLISHERAVAILABLE); 230 X(BINDSTATUS_DISPLAYNAMEAVAILABLE); 231 #undef X 232 default: 233 return wine_dbg_sprintf("(invalid status %u)", status); 234 } 235 } 236 237 /*********************************************************************** 238 * DllInstall (URLMON.@) 239 */ 240 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline) 241 { 242 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE", 243 debugstr_w(cmdline)); 244 245 return S_OK; 246 } 247 248 /*********************************************************************** 249 * DllCanUnloadNow (URLMON.@) 250 */ 251 HRESULT WINAPI DllCanUnloadNow(void) 252 { 253 return URLMON_refCount != 0 ? S_FALSE : S_OK; 254 } 255 256 257 258 /****************************************************************************** 259 * Urlmon ClassFactory 260 */ 261 typedef struct { 262 IClassFactory IClassFactory_iface; 263 264 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj); 265 } ClassFactory; 266 267 static inline ClassFactory *impl_from_IClassFactory(IClassFactory *iface) 268 { 269 return CONTAINING_RECORD(iface, ClassFactory, IClassFactory_iface); 270 } 271 272 static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv) 273 { 274 *ppv = NULL; 275 276 if(IsEqualGUID(riid, &IID_IUnknown)) { 277 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv); 278 *ppv = iface; 279 }else if(IsEqualGUID(riid, &IID_IClassFactory)) { 280 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv); 281 *ppv = iface; 282 } 283 284 if(*ppv) { 285 IUnknown_AddRef((IUnknown*)*ppv); 286 return S_OK; 287 } 288 289 WARN("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ppv); 290 return E_NOINTERFACE; 291 } 292 293 static ULONG WINAPI CF_AddRef(IClassFactory *iface) 294 { 295 URLMON_LockModule(); 296 return 2; 297 } 298 299 static ULONG WINAPI CF_Release(IClassFactory *iface) 300 { 301 URLMON_UnlockModule(); 302 return 1; 303 } 304 305 306 static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter, 307 REFIID riid, LPVOID *ppobj) 308 { 309 ClassFactory *This = impl_from_IClassFactory(iface); 310 HRESULT hres; 311 LPUNKNOWN punk; 312 313 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj); 314 315 *ppobj = NULL; 316 if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) { 317 hres = IUnknown_QueryInterface(punk, riid, ppobj); 318 IUnknown_Release(punk); 319 } 320 return hres; 321 } 322 323 static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock) 324 { 325 TRACE("(%d)\n", dolock); 326 327 if (dolock) 328 URLMON_LockModule(); 329 else 330 URLMON_UnlockModule(); 331 332 return S_OK; 333 } 334 335 static const IClassFactoryVtbl ClassFactoryVtbl = 336 { 337 CF_QueryInterface, 338 CF_AddRef, 339 CF_Release, 340 CF_CreateInstance, 341 CF_LockServer 342 }; 343 344 static ClassFactory FileProtocolCF = 345 { { &ClassFactoryVtbl }, FileProtocol_Construct}; 346 static ClassFactory FtpProtocolCF = 347 { { &ClassFactoryVtbl }, FtpProtocol_Construct}; 348 static ClassFactory GopherProtocolCF = 349 { { &ClassFactoryVtbl }, GopherProtocol_Construct}; 350 static ClassFactory HttpProtocolCF = 351 { { &ClassFactoryVtbl }, HttpProtocol_Construct}; 352 static ClassFactory HttpSProtocolCF = 353 { { &ClassFactoryVtbl }, HttpSProtocol_Construct}; 354 static ClassFactory MkProtocolCF = 355 { { &ClassFactoryVtbl }, MkProtocol_Construct}; 356 static ClassFactory SecurityManagerCF = 357 { { &ClassFactoryVtbl }, SecManagerImpl_Construct}; 358 static ClassFactory ZoneManagerCF = 359 { { &ClassFactoryVtbl }, ZoneMgrImpl_Construct}; 360 static ClassFactory StdURLMonikerCF = 361 { { &ClassFactoryVtbl }, StdURLMoniker_Construct}; 362 static ClassFactory MimeFilterCF = 363 { { &ClassFactoryVtbl }, MimeFilter_Construct}; 364 static ClassFactory CUriCF = 365 { { &ClassFactoryVtbl }, Uri_Construct}; 366 367 struct object_creation_info 368 { 369 const CLSID *clsid; 370 IClassFactory *cf; 371 LPCWSTR protocol; 372 }; 373 374 static const WCHAR wszFile[] = {'f','i','l','e',0}; 375 static const WCHAR wszFtp[] = {'f','t','p',0}; 376 static const WCHAR wszGopher[] = {'g','o','p','h','e','r',0}; 377 static const WCHAR wszHttp[] = {'h','t','t','p',0}; 378 static const WCHAR wszHttps[] = {'h','t','t','p','s',0}; 379 static const WCHAR wszMk[] = {'m','k',0}; 380 381 static const struct object_creation_info object_creation[] = 382 { 383 { &CLSID_FileProtocol, &FileProtocolCF.IClassFactory_iface, wszFile }, 384 { &CLSID_FtpProtocol, &FtpProtocolCF.IClassFactory_iface, wszFtp }, 385 { &CLSID_GopherProtocol, &GopherProtocolCF.IClassFactory_iface, wszGopher }, 386 { &CLSID_HttpProtocol, &HttpProtocolCF.IClassFactory_iface, wszHttp }, 387 { &CLSID_HttpSProtocol, &HttpSProtocolCF.IClassFactory_iface, wszHttps }, 388 { &CLSID_MkProtocol, &MkProtocolCF.IClassFactory_iface, wszMk }, 389 { &CLSID_InternetSecurityManager, &SecurityManagerCF.IClassFactory_iface, NULL }, 390 { &CLSID_InternetZoneManager, &ZoneManagerCF.IClassFactory_iface, NULL }, 391 { &CLSID_StdURLMoniker, &StdURLMonikerCF.IClassFactory_iface, NULL }, 392 { &CLSID_DeCompMimeFilter, &MimeFilterCF.IClassFactory_iface, NULL }, 393 { &CLSID_CUri, &CUriCF.IClassFactory_iface, NULL } 394 }; 395 396 static void init_session(void) 397 { 398 unsigned int i; 399 400 for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) { 401 if(object_creation[i].protocol) 402 register_namespace(object_creation[i].cf, object_creation[i].clsid, 403 object_creation[i].protocol, TRUE); 404 } 405 } 406 407 /******************************************************************************* 408 * DllGetClassObject [URLMON.@] 409 * Retrieves class object from a DLL object 410 * 411 * NOTES 412 * Docs say returns STDAPI 413 * 414 * PARAMS 415 * rclsid [I] CLSID for the class object 416 * riid [I] Reference to identifier of interface for class object 417 * ppv [O] Address of variable to receive interface pointer for riid 418 * 419 * RETURNS 420 * Success: S_OK 421 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG, 422 * E_UNEXPECTED 423 */ 424 425 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) 426 { 427 unsigned int i; 428 HRESULT hr; 429 430 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); 431 432 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) 433 { 434 if (IsEqualGUID(object_creation[i].clsid, rclsid)) 435 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv); 436 } 437 438 hr = URLMON_DllGetClassObject(rclsid, riid, ppv); 439 if(SUCCEEDED(hr)) 440 return hr; 441 442 FIXME("%s: no class found.\n", debugstr_guid(rclsid)); 443 return CLASS_E_CLASSNOTAVAILABLE; 444 } 445 446 static HRESULT register_inf(BOOL doregister) 447 { 448 HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable); 449 HMODULE hAdvpack; 450 451 static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0}; 452 453 hAdvpack = LoadLibraryW(wszAdvpack); 454 pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall"); 455 456 return pRegInstall(hProxyDll, doregister ? "RegisterDll" : "UnregisterDll", NULL); 457 } 458 459 /*********************************************************************** 460 * DllRegisterServer (URLMON.@) 461 */ 462 HRESULT WINAPI DllRegisterServer(void) 463 { 464 HRESULT hr; 465 466 TRACE("\n"); 467 468 hr = URLMON_DllRegisterServer(); 469 return SUCCEEDED(hr) ? register_inf(TRUE) : hr; 470 } 471 472 /*********************************************************************** 473 * DllUnregisterServer (URLMON.@) 474 */ 475 HRESULT WINAPI DllUnregisterServer(void) 476 { 477 HRESULT hr; 478 479 TRACE("\n"); 480 481 hr = URLMON_DllUnregisterServer(); 482 return SUCCEEDED(hr) ? register_inf(FALSE) : hr; 483 } 484 485 /*********************************************************************** 486 * DllRegisterServerEx (URLMON.@) 487 */ 488 HRESULT WINAPI DllRegisterServerEx(void) 489 { 490 FIXME("(void): stub\n"); 491 492 return E_FAIL; 493 } 494 495 /************************************************************************** 496 * IsValidURL (URLMON.@) 497 * 498 * Determines if a specified string is a valid URL. 499 * 500 * PARAMS 501 * pBC [I] ignored, should be NULL. 502 * szURL [I] string that represents the URL in question. 503 * dwReserved [I] reserved and must be zero. 504 * 505 * RETURNS 506 * Success: S_OK. 507 * Failure: S_FALSE. 508 * returns E_INVALIDARG if one or more of the args is invalid. 509 * 510 * TODO: 511 * test functionality against windows to see what a valid URL is. 512 */ 513 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved) 514 { 515 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved); 516 517 if (dwReserved || !szURL) 518 return E_INVALIDARG; 519 520 return S_OK; 521 } 522 523 /************************************************************************** 524 * FaultInIEFeature (URLMON.@) 525 * 526 * Undocumented. Appears to be used by native shdocvw.dll. 527 */ 528 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec, 529 QUERYCONTEXT *pQuery, DWORD flags ) 530 { 531 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags); 532 return E_NOTIMPL; 533 } 534 535 /************************************************************************** 536 * CoGetClassObjectFromURL (URLMON.@) 537 */ 538 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS, 539 DWORD dwFileVersionLS, LPCWSTR szContentType, 540 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved, 541 REFIID riid, LPVOID *ppv ) 542 { 543 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL), 544 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved, 545 debugstr_guid(riid), ppv); 546 return E_NOINTERFACE; 547 } 548 549 /*********************************************************************** 550 * ReleaseBindInfo (URLMON.@) 551 * 552 * Release the resources used by the specified BINDINFO structure. 553 * 554 * PARAMS 555 * pbindinfo [I] BINDINFO to release. 556 * 557 * RETURNS 558 * Nothing. 559 */ 560 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo) 561 { 562 DWORD size; 563 564 TRACE("(%p)\n", pbindinfo); 565 566 if(!pbindinfo || !(size = pbindinfo->cbSize)) 567 return; 568 569 CoTaskMemFree(pbindinfo->szExtraInfo); 570 ReleaseStgMedium(&pbindinfo->stgmedData); 571 572 if(offsetof(BINDINFO, szExtraInfo) < size) 573 CoTaskMemFree(pbindinfo->szCustomVerb); 574 575 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size) 576 IUnknown_Release(pbindinfo->pUnk); 577 578 memset(pbindinfo, 0, size); 579 pbindinfo->cbSize = size; 580 } 581 582 /*********************************************************************** 583 * CopyStgMedium (URLMON.@) 584 */ 585 HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst) 586 { 587 TRACE("(%p %p)\n", src, dst); 588 589 if(!src || !dst) 590 return E_POINTER; 591 592 *dst = *src; 593 594 switch(dst->tymed) { 595 case TYMED_NULL: 596 break; 597 case TYMED_FILE: 598 if(src->u.lpszFileName && !src->pUnkForRelease) { 599 DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR); 600 dst->u.lpszFileName = CoTaskMemAlloc(size); 601 if(!dst->u.lpszFileName) 602 return E_OUTOFMEMORY; 603 memcpy(dst->u.lpszFileName, src->u.lpszFileName, size); 604 } 605 break; 606 case TYMED_ISTREAM: 607 if(dst->u.pstm) 608 IStream_AddRef(dst->u.pstm); 609 break; 610 case TYMED_ISTORAGE: 611 if(dst->u.pstg) 612 IStorage_AddRef(dst->u.pstg); 613 break; 614 case TYMED_HGLOBAL: 615 if(dst->u.hGlobal) { 616 SIZE_T size = GlobalSize(src->u.hGlobal); 617 char *src_ptr, *dst_ptr; 618 619 dst->u.hGlobal = GlobalAlloc(GMEM_FIXED, size); 620 if(!dst->u.hGlobal) 621 return E_OUTOFMEMORY; 622 dst_ptr = GlobalLock(dst->u.hGlobal); 623 src_ptr = GlobalLock(src->u.hGlobal); 624 memcpy(dst_ptr, src_ptr, size); 625 GlobalUnlock(src_ptr); 626 GlobalUnlock(dst_ptr); 627 } 628 break; 629 default: 630 FIXME("Unimplemented tymed %d\n", src->tymed); 631 } 632 633 if(dst->pUnkForRelease) 634 IUnknown_AddRef(dst->pUnkForRelease); 635 636 return S_OK; 637 } 638 639 /*********************************************************************** 640 * CopyBindInfo (URLMON.@) 641 */ 642 HRESULT WINAPI CopyBindInfo(const BINDINFO *pcbiSrc, BINDINFO *pcbiDest) 643 { 644 DWORD size; 645 HRESULT hres; 646 647 TRACE("(%p %p)\n", pcbiSrc, pcbiDest); 648 649 if(!pcbiSrc || !pcbiDest) 650 return E_POINTER; 651 if(!pcbiSrc->cbSize || !pcbiDest->cbSize) 652 return E_INVALIDARG; 653 654 size = pcbiDest->cbSize; 655 if(size > pcbiSrc->cbSize) { 656 memcpy(pcbiDest, pcbiSrc, pcbiSrc->cbSize); 657 memset((char*)pcbiDest+pcbiSrc->cbSize, 0, size-pcbiSrc->cbSize); 658 } else { 659 memcpy(pcbiDest, pcbiSrc, size); 660 } 661 pcbiDest->cbSize = size; 662 663 size = FIELD_OFFSET(BINDINFO, szExtraInfo)+sizeof(void*); 664 if(pcbiSrc->cbSize>=size && pcbiDest->cbSize>=size && pcbiSrc->szExtraInfo) { 665 size = (strlenW(pcbiSrc->szExtraInfo)+1)*sizeof(WCHAR); 666 pcbiDest->szExtraInfo = CoTaskMemAlloc(size); 667 if(!pcbiDest->szExtraInfo) 668 return E_OUTOFMEMORY; 669 memcpy(pcbiDest->szExtraInfo, pcbiSrc->szExtraInfo, size); 670 } 671 672 size = FIELD_OFFSET(BINDINFO, stgmedData)+sizeof(STGMEDIUM); 673 if(pcbiSrc->cbSize>=size && pcbiDest->cbSize>=size) { 674 hres = CopyStgMedium(&pcbiSrc->stgmedData, &pcbiDest->stgmedData); 675 if(FAILED(hres)) { 676 CoTaskMemFree(pcbiDest->szExtraInfo); 677 return hres; 678 } 679 } 680 681 size = FIELD_OFFSET(BINDINFO, szCustomVerb)+sizeof(void*); 682 if(pcbiSrc->cbSize>=size && pcbiDest->cbSize>=size && pcbiSrc->szCustomVerb) { 683 size = (strlenW(pcbiSrc->szCustomVerb)+1)*sizeof(WCHAR); 684 pcbiDest->szCustomVerb = CoTaskMemAlloc(size); 685 if(!pcbiDest->szCustomVerb) { 686 CoTaskMemFree(pcbiDest->szExtraInfo); 687 ReleaseStgMedium(&pcbiDest->stgmedData); 688 return E_OUTOFMEMORY; 689 } 690 memcpy(pcbiDest->szCustomVerb, pcbiSrc->szCustomVerb, size); 691 } 692 693 size = FIELD_OFFSET(BINDINFO, securityAttributes)+sizeof(SECURITY_ATTRIBUTES); 694 if(pcbiDest->cbSize >= size) 695 memset(&pcbiDest->securityAttributes, 0, sizeof(SECURITY_ATTRIBUTES)); 696 697 if(pcbiSrc->pUnk) 698 IUnknown_AddRef(pcbiDest->pUnk); 699 700 return S_OK; 701 } 702 703 /*********************************************************************** 704 * GetClassFileOrMime (URLMON.@) 705 * 706 * Determines the class ID from the bind context, file name or MIME type. 707 */ 708 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename, 709 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved, 710 CLSID *pclsid) 711 { 712 FIXME("(%p, %s, %p, %d, %s, 0x%08x, %p): stub\n", pBC, debugstr_w(pszFilename), pBuffer, 713 cbBuffer, debugstr_w(pszMimeType), dwReserved, pclsid); 714 return E_NOTIMPL; 715 } 716 717 /*********************************************************************** 718 * Extract (URLMON.@) 719 */ 720 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName) 721 { 722 HRESULT (WINAPI *pExtract)(void *, LPCSTR); 723 724 if (!hCabinet) 725 hCabinet = LoadLibraryA("cabinet.dll"); 726 727 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError()); 728 pExtract = (void *)GetProcAddress(hCabinet, "Extract"); 729 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError()); 730 731 return pExtract(dest, szCabName); 732 } 733 734 /*********************************************************************** 735 * IsLoggingEnabledA (URLMON.@) 736 */ 737 BOOL WINAPI IsLoggingEnabledA(LPCSTR url) 738 { 739 FIXME("(%s)\n", debugstr_a(url)); 740 return FALSE; 741 } 742 743 /*********************************************************************** 744 * IsLoggingEnabledW (URLMON.@) 745 */ 746 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url) 747 { 748 FIXME("(%s)\n", debugstr_w(url)); 749 return FALSE; 750 } 751 752 /*********************************************************************** 753 * IsProtectedModeURL (URLMON.111) 754 * Undocumented, added in IE7 755 */ 756 BOOL WINAPI IsProtectedModeURL(const WCHAR *url) 757 { 758 FIXME("stub: %s\n", debugstr_w(url)); 759 return TRUE; 760 } 761 762 /*********************************************************************** 763 * LogSqmBits (URLMON.410) 764 * Undocumented, added in IE8 765 */ 766 int WINAPI LogSqmBits(DWORD unk1, DWORD unk2) 767 { 768 FIXME("stub: %d %d\n", unk1, unk2); 769 return 0; 770 } 771 772 /*********************************************************************** 773 * LogSqmUXCommandOffsetInternal (URLMON.423) 774 * Undocumented, added in IE8 775 */ 776 void WINAPI LogSqmUXCommandOffsetInternal(DWORD unk1, DWORD unk2, DWORD unk3, DWORD unk4) 777 { 778 FIXME("stub: %d %d %d %d\n", unk1, unk2, unk3, unk4); 779 } 780 781 /*********************************************************************** 782 * MapUriToBrowserEmulationState (URLMON.444) 783 * Undocumented, added in IE8 784 */ 785 int WINAPI MapUriToBrowserEmulationState(DWORD unk1, DWORD unk2, DWORD unk3) 786 { 787 FIXME("stub: %d %d %d\n", unk1, unk2, unk3); 788 return 0; 789 } 790 791 /*********************************************************************** 792 * MapBrowserEmulationModeToUserAgent (URLMON.445) 793 * Undocumented, added in IE8 794 */ 795 int WINAPI MapBrowserEmulationModeToUserAgent(DWORD unk1, DWORD unk2) 796 { 797 FIXME("stub: %d %d\n", unk1, unk2); 798 return 0; 799 } 800 801 /*********************************************************************** 802 * FlushUrlmonZonesCache (URLMON.455) 803 * Undocumented, added in IE8 804 */ 805 void WINAPI FlushUrlmonZonesCache(void) 806 { 807 FIXME("stub\n"); 808 } 809 810 /*********************************************************************** 811 * RegisterMediaTypes 812 * Added in IE3, registers known MIME-type strings. 813 */ 814 HRESULT WINAPI RegisterMediaTypes(UINT types, LPCSTR *szTypes, CLIPFORMAT *cfTypes) 815 { 816 FIXME("stub: %u %p %p\n", types, szTypes, cfTypes); 817 return E_INVALIDARG; 818 } 819