| /* |
| * UrlMon |
| * |
| * Copyright (c) 2000 Patrik Stridvall |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include <stdarg.h> |
| |
| #define NONAMELESSUNION |
| |
| #include "urlmon_main.h" |
| |
| #include "winreg.h" |
| |
| #define NO_SHLWAPI_REG |
| #include "shlwapi.h" |
| #include "advpub.h" |
| #include "initguid.h" |
| |
| #include "wine/debug.h" |
| |
| #include "urlmon.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(urlmon); |
| |
| DEFINE_GUID(CLSID_CUri, 0xDF2FCE13, 0x25EC, 0x45BB, 0x9D,0x4C, 0xCE,0xCD,0x47,0xC2,0x43,0x0C); |
| |
| LONG URLMON_refCount = 0; |
| HINSTANCE urlmon_instance; |
| |
| static HMODULE hCabinet = NULL; |
| static DWORD urlmon_tls = TLS_OUT_OF_INDEXES; |
| |
| static void init_session(void); |
| |
| static struct list tls_list = LIST_INIT(tls_list); |
| |
| static CRITICAL_SECTION tls_cs; |
| static CRITICAL_SECTION_DEBUG tls_cs_dbg = |
| { |
| 0, 0, &tls_cs, |
| { &tls_cs_dbg.ProcessLocksList, &tls_cs_dbg.ProcessLocksList }, |
| 0, 0, { (DWORD_PTR)(__FILE__ ": tls") } |
| }; |
| |
| static CRITICAL_SECTION tls_cs = { &tls_cs_dbg, -1, 0, 0, 0, 0 }; |
| |
| tls_data_t *get_tls_data(void) |
| { |
| tls_data_t *data; |
| |
| if(urlmon_tls == TLS_OUT_OF_INDEXES) { |
| DWORD tls = TlsAlloc(); |
| if(tls == TLS_OUT_OF_INDEXES) |
| return NULL; |
| |
| tls = InterlockedCompareExchange((LONG*)&urlmon_tls, tls, TLS_OUT_OF_INDEXES); |
| if(tls != urlmon_tls) |
| TlsFree(tls); |
| } |
| |
| data = TlsGetValue(urlmon_tls); |
| if(!data) { |
| data = heap_alloc_zero(sizeof(tls_data_t)); |
| if(!data) |
| return NULL; |
| |
| EnterCriticalSection(&tls_cs); |
| list_add_tail(&tls_list, &data->entry); |
| LeaveCriticalSection(&tls_cs); |
| |
| TlsSetValue(urlmon_tls, data); |
| } |
| |
| return data; |
| } |
| |
| static void free_tls_list(void) |
| { |
| tls_data_t *data; |
| |
| if(urlmon_tls == TLS_OUT_OF_INDEXES) |
| return; |
| |
| while(!list_empty(&tls_list)) { |
| data = LIST_ENTRY(list_head(&tls_list), tls_data_t, entry); |
| list_remove(&data->entry); |
| heap_free(data); |
| } |
| |
| TlsFree(urlmon_tls); |
| } |
| |
| static void detach_thread(void) |
| { |
| tls_data_t *data; |
| |
| if(urlmon_tls == TLS_OUT_OF_INDEXES) |
| return; |
| |
| data = TlsGetValue(urlmon_tls); |
| if(!data) |
| return; |
| |
| EnterCriticalSection(&tls_cs); |
| list_remove(&data->entry); |
| LeaveCriticalSection(&tls_cs); |
| |
| if(data->notif_hwnd) { |
| WARN("notif_hwnd not destroyed\n"); |
| DestroyWindow(data->notif_hwnd); |
| } |
| |
| heap_free(data); |
| } |
| |
| static void process_detach(void) |
| { |
| HINTERNET internet_session; |
| |
| internet_session = get_internet_session(NULL); |
| if(internet_session) |
| InternetCloseHandle(internet_session); |
| |
| if (hCabinet) |
| FreeLibrary(hCabinet); |
| |
| free_session(); |
| free_tls_list(); |
| unregister_notif_wnd_class(); |
| } |
| |
| /*********************************************************************** |
| * DllMain (URLMON.init) |
| */ |
| BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad) |
| { |
| TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad); |
| |
| URLMON_DllMain( hinstDLL, fdwReason, fImpLoad ); |
| |
| switch(fdwReason) { |
| case DLL_PROCESS_ATTACH: |
| urlmon_instance = hinstDLL; |
| init_session(); |
| break; |
| |
| case DLL_PROCESS_DETACH: |
| if (fImpLoad) break; |
| process_detach(); |
| DeleteCriticalSection(&tls_cs); |
| break; |
| |
| case DLL_THREAD_DETACH: |
| detach_thread(); |
| break; |
| } |
| return TRUE; |
| } |
| |
| const char *debugstr_bindstatus(ULONG status) |
| { |
| switch(status) { |
| #define X(x) case x: return #x |
| X(BINDSTATUS_FINDINGRESOURCE); |
| X(BINDSTATUS_CONNECTING); |
| X(BINDSTATUS_REDIRECTING); |
| X(BINDSTATUS_BEGINDOWNLOADDATA); |
| X(BINDSTATUS_DOWNLOADINGDATA); |
| X(BINDSTATUS_ENDDOWNLOADDATA); |
| X(BINDSTATUS_BEGINDOWNLOADCOMPONENTS); |
| X(BINDSTATUS_INSTALLINGCOMPONENTS); |
| X(BINDSTATUS_ENDDOWNLOADCOMPONENTS); |
| X(BINDSTATUS_USINGCACHEDCOPY); |
| X(BINDSTATUS_SENDINGREQUEST); |
| X(BINDSTATUS_CLASSIDAVAILABLE); |
| X(BINDSTATUS_MIMETYPEAVAILABLE); |
| X(BINDSTATUS_CACHEFILENAMEAVAILABLE); |
| X(BINDSTATUS_BEGINSYNCOPERATION); |
| X(BINDSTATUS_ENDSYNCOPERATION); |
| X(BINDSTATUS_BEGINUPLOADDATA); |
| X(BINDSTATUS_UPLOADINGDATA); |
| X(BINDSTATUS_ENDUPLOADINGDATA); |
| X(BINDSTATUS_PROTOCOLCLASSID); |
| X(BINDSTATUS_ENCODING); |
| X(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE); |
| X(BINDSTATUS_CLASSINSTALLLOCATION); |
| X(BINDSTATUS_DECODING); |
| X(BINDSTATUS_LOADINGMIMEHANDLER); |
| X(BINDSTATUS_CONTENTDISPOSITIONATTACH); |
| X(BINDSTATUS_FILTERREPORTMIMETYPE); |
| X(BINDSTATUS_CLSIDCANINSTANTIATE); |
| X(BINDSTATUS_IUNKNOWNAVAILABLE); |
| X(BINDSTATUS_DIRECTBIND); |
| X(BINDSTATUS_RAWMIMETYPE); |
| X(BINDSTATUS_PROXYDETECTING); |
| X(BINDSTATUS_ACCEPTRANGES); |
| X(BINDSTATUS_COOKIE_SENT); |
| X(BINDSTATUS_COMPACT_POLICY_RECEIVED); |
| X(BINDSTATUS_COOKIE_SUPPRESSED); |
| X(BINDSTATUS_COOKIE_STATE_UNKNOWN); |
| X(BINDSTATUS_COOKIE_STATE_ACCEPT); |
| X(BINDSTATUS_COOKIE_STATE_REJECT); |
| X(BINDSTATUS_COOKIE_STATE_PROMPT); |
| X(BINDSTATUS_COOKIE_STATE_LEASH); |
| X(BINDSTATUS_COOKIE_STATE_DOWNGRADE); |
| X(BINDSTATUS_POLICY_HREF); |
| X(BINDSTATUS_P3P_HEADER); |
| X(BINDSTATUS_SESSION_COOKIE_RECEIVED); |
| X(BINDSTATUS_PERSISTENT_COOKIE_RECEIVED); |
| X(BINDSTATUS_SESSION_COOKIES_ALLOWED); |
| X(BINDSTATUS_CACHECONTROL); |
| X(BINDSTATUS_CONTENTDISPOSITIONFILENAME); |
| X(BINDSTATUS_MIMETEXTPLAINMISMATCH); |
| X(BINDSTATUS_PUBLISHERAVAILABLE); |
| X(BINDSTATUS_DISPLAYNAMEAVAILABLE); |
| #undef X |
| default: |
| return wine_dbg_sprintf("(invalid status %u)", status); |
| } |
| } |
| |
| /*********************************************************************** |
| * DllInstall (URLMON.@) |
| */ |
| HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline) |
| { |
| FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE", |
| debugstr_w(cmdline)); |
| |
| return S_OK; |
| } |
| |
| /*********************************************************************** |
| * DllCanUnloadNow (URLMON.@) |
| */ |
| HRESULT WINAPI DllCanUnloadNow(void) |
| { |
| return URLMON_refCount != 0 ? S_FALSE : S_OK; |
| } |
| |
| |
| |
| /****************************************************************************** |
| * Urlmon ClassFactory |
| */ |
| typedef struct { |
| IClassFactory IClassFactory_iface; |
| |
| HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj); |
| } ClassFactory; |
| |
| static inline ClassFactory *impl_from_IClassFactory(IClassFactory *iface) |
| { |
| return CONTAINING_RECORD(iface, ClassFactory, IClassFactory_iface); |
| } |
| |
| static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv) |
| { |
| *ppv = NULL; |
| |
| if(IsEqualGUID(riid, &IID_IUnknown)) { |
| TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv); |
| *ppv = iface; |
| }else if(IsEqualGUID(riid, &IID_IClassFactory)) { |
| TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv); |
| *ppv = iface; |
| } |
| |
| if(*ppv) { |
| IUnknown_AddRef((IUnknown*)*ppv); |
| return S_OK; |
| } |
| |
| WARN("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ppv); |
| return E_NOINTERFACE; |
| } |
| |
| static ULONG WINAPI CF_AddRef(IClassFactory *iface) |
| { |
| URLMON_LockModule(); |
| return 2; |
| } |
| |
| static ULONG WINAPI CF_Release(IClassFactory *iface) |
| { |
| URLMON_UnlockModule(); |
| return 1; |
| } |
| |
| |
| static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter, |
| REFIID riid, LPVOID *ppobj) |
| { |
| ClassFactory *This = impl_from_IClassFactory(iface); |
| HRESULT hres; |
| LPUNKNOWN punk; |
| |
| TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj); |
| |
| *ppobj = NULL; |
| if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) { |
| hres = IUnknown_QueryInterface(punk, riid, ppobj); |
| IUnknown_Release(punk); |
| } |
| return hres; |
| } |
| |
| static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock) |
| { |
| TRACE("(%d)\n", dolock); |
| |
| if (dolock) |
| URLMON_LockModule(); |
| else |
| URLMON_UnlockModule(); |
| |
| return S_OK; |
| } |
| |
| static const IClassFactoryVtbl ClassFactoryVtbl = |
| { |
| CF_QueryInterface, |
| CF_AddRef, |
| CF_Release, |
| CF_CreateInstance, |
| CF_LockServer |
| }; |
| |
| static ClassFactory FileProtocolCF = |
| { { &ClassFactoryVtbl }, FileProtocol_Construct}; |
| static ClassFactory FtpProtocolCF = |
| { { &ClassFactoryVtbl }, FtpProtocol_Construct}; |
| static ClassFactory GopherProtocolCF = |
| { { &ClassFactoryVtbl }, GopherProtocol_Construct}; |
| static ClassFactory HttpProtocolCF = |
| { { &ClassFactoryVtbl }, HttpProtocol_Construct}; |
| static ClassFactory HttpSProtocolCF = |
| { { &ClassFactoryVtbl }, HttpSProtocol_Construct}; |
| static ClassFactory MkProtocolCF = |
| { { &ClassFactoryVtbl }, MkProtocol_Construct}; |
| static ClassFactory SecurityManagerCF = |
| { { &ClassFactoryVtbl }, SecManagerImpl_Construct}; |
| static ClassFactory ZoneManagerCF = |
| { { &ClassFactoryVtbl }, ZoneMgrImpl_Construct}; |
| static ClassFactory StdURLMonikerCF = |
| { { &ClassFactoryVtbl }, StdURLMoniker_Construct}; |
| static ClassFactory MimeFilterCF = |
| { { &ClassFactoryVtbl }, MimeFilter_Construct}; |
| static ClassFactory CUriCF = |
| { { &ClassFactoryVtbl }, Uri_Construct}; |
| |
| struct object_creation_info |
| { |
| const CLSID *clsid; |
| IClassFactory *cf; |
| LPCWSTR protocol; |
| }; |
| |
| static const WCHAR wszFile[] = {'f','i','l','e',0}; |
| static const WCHAR wszFtp[] = {'f','t','p',0}; |
| static const WCHAR wszGopher[] = {'g','o','p','h','e','r',0}; |
| static const WCHAR wszHttp[] = {'h','t','t','p',0}; |
| static const WCHAR wszHttps[] = {'h','t','t','p','s',0}; |
| static const WCHAR wszMk[] = {'m','k',0}; |
| |
| static const struct object_creation_info object_creation[] = |
| { |
| { &CLSID_FileProtocol, &FileProtocolCF.IClassFactory_iface, wszFile }, |
| { &CLSID_FtpProtocol, &FtpProtocolCF.IClassFactory_iface, wszFtp }, |
| { &CLSID_GopherProtocol, &GopherProtocolCF.IClassFactory_iface, wszGopher }, |
| { &CLSID_HttpProtocol, &HttpProtocolCF.IClassFactory_iface, wszHttp }, |
| { &CLSID_HttpSProtocol, &HttpSProtocolCF.IClassFactory_iface, wszHttps }, |
| { &CLSID_MkProtocol, &MkProtocolCF.IClassFactory_iface, wszMk }, |
| { &CLSID_InternetSecurityManager, &SecurityManagerCF.IClassFactory_iface, NULL }, |
| { &CLSID_InternetZoneManager, &ZoneManagerCF.IClassFactory_iface, NULL }, |
| { &CLSID_StdURLMoniker, &StdURLMonikerCF.IClassFactory_iface, NULL }, |
| { &CLSID_DeCompMimeFilter, &MimeFilterCF.IClassFactory_iface, NULL }, |
| { &CLSID_CUri, &CUriCF.IClassFactory_iface, NULL } |
| }; |
| |
| static void init_session(void) |
| { |
| unsigned int i; |
| |
| for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) { |
| if(object_creation[i].protocol) |
| register_namespace(object_creation[i].cf, object_creation[i].clsid, |
| object_creation[i].protocol, TRUE); |
| } |
| } |
| |
| /******************************************************************************* |
| * DllGetClassObject [URLMON.@] |
| * Retrieves class object from a DLL object |
| * |
| * NOTES |
| * Docs say returns STDAPI |
| * |
| * PARAMS |
| * rclsid [I] CLSID for the class object |
| * riid [I] Reference to identifier of interface for class object |
| * ppv [O] Address of variable to receive interface pointer for riid |
| * |
| * RETURNS |
| * Success: S_OK |
| * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG, |
| * E_UNEXPECTED |
| */ |
| |
| HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) |
| { |
| unsigned int i; |
| HRESULT hr; |
| |
| TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); |
| |
| for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) |
| { |
| if (IsEqualGUID(object_creation[i].clsid, rclsid)) |
| return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv); |
| } |
| |
| hr = URLMON_DllGetClassObject(rclsid, riid, ppv); |
| if(SUCCEEDED(hr)) |
| return hr; |
| |
| FIXME("%s: no class found.\n", debugstr_guid(rclsid)); |
| return CLASS_E_CLASSNOTAVAILABLE; |
| } |
| |
| static HRESULT register_inf(BOOL doregister) |
| { |
| HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable); |
| HMODULE hAdvpack; |
| |
| static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0}; |
| |
| hAdvpack = LoadLibraryW(wszAdvpack); |
| pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall"); |
| |
| return pRegInstall(hProxyDll, doregister ? "RegisterDll" : "UnregisterDll", NULL); |
| } |
| |
| /*********************************************************************** |
| * DllRegisterServer (URLMON.@) |
| */ |
| HRESULT WINAPI DllRegisterServer(void) |
| { |
| HRESULT hr; |
| |
| TRACE("\n"); |
| |
| hr = URLMON_DllRegisterServer(); |
| return SUCCEEDED(hr) ? register_inf(TRUE) : hr; |
| } |
| |
| /*********************************************************************** |
| * DllUnregisterServer (URLMON.@) |
| */ |
| HRESULT WINAPI DllUnregisterServer(void) |
| { |
| HRESULT hr; |
| |
| TRACE("\n"); |
| |
| hr = URLMON_DllUnregisterServer(); |
| return SUCCEEDED(hr) ? register_inf(FALSE) : hr; |
| } |
| |
| /*********************************************************************** |
| * DllRegisterServerEx (URLMON.@) |
| */ |
| HRESULT WINAPI DllRegisterServerEx(void) |
| { |
| FIXME("(void): stub\n"); |
| |
| return E_FAIL; |
| } |
| |
| /************************************************************************** |
| * IsValidURL (URLMON.@) |
| * |
| * Determines if a specified string is a valid URL. |
| * |
| * PARAMS |
| * pBC [I] ignored, should be NULL. |
| * szURL [I] string that represents the URL in question. |
| * dwReserved [I] reserved and must be zero. |
| * |
| * RETURNS |
| * Success: S_OK. |
| * Failure: S_FALSE. |
| * returns E_INVALIDARG if one or more of the args is invalid. |
| * |
| * TODO: |
| * test functionality against windows to see what a valid URL is. |
| */ |
| HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved) |
| { |
| FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved); |
| |
| if (dwReserved || !szURL) |
| return E_INVALIDARG; |
| |
| return S_OK; |
| } |
| |
| /************************************************************************** |
| * FaultInIEFeature (URLMON.@) |
| * |
| * Undocumented. Appears to be used by native shdocvw.dll. |
| */ |
| HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec, |
| QUERYCONTEXT *pQuery, DWORD flags ) |
| { |
| FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags); |
| return E_NOTIMPL; |
| } |
| |
| /************************************************************************** |
| * CoGetClassObjectFromURL (URLMON.@) |
| */ |
| HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS, |
| DWORD dwFileVersionLS, LPCWSTR szContentType, |
| LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved, |
| REFIID riid, LPVOID *ppv ) |
| { |
| FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL), |
| dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved, |
| debugstr_guid(riid), ppv); |
| return E_NOINTERFACE; |
| } |
| |
| /*********************************************************************** |
| * ReleaseBindInfo (URLMON.@) |
| * |
| * Release the resources used by the specified BINDINFO structure. |
| * |
| * PARAMS |
| * pbindinfo [I] BINDINFO to release. |
| * |
| * RETURNS |
| * Nothing. |
| */ |
| void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo) |
| { |
| DWORD size; |
| |
| TRACE("(%p)\n", pbindinfo); |
| |
| if(!pbindinfo || !(size = pbindinfo->cbSize)) |
| return; |
| |
| CoTaskMemFree(pbindinfo->szExtraInfo); |
| ReleaseStgMedium(&pbindinfo->stgmedData); |
| |
| if(offsetof(BINDINFO, szExtraInfo) < size) |
| CoTaskMemFree(pbindinfo->szCustomVerb); |
| |
| if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size) |
| IUnknown_Release(pbindinfo->pUnk); |
| |
| memset(pbindinfo, 0, size); |
| pbindinfo->cbSize = size; |
| } |
| |
| /*********************************************************************** |
| * CopyStgMedium (URLMON.@) |
| */ |
| HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst) |
| { |
| TRACE("(%p %p)\n", src, dst); |
| |
| if(!src || !dst) |
| return E_POINTER; |
| |
| *dst = *src; |
| |
| switch(dst->tymed) { |
| case TYMED_NULL: |
| break; |
| case TYMED_FILE: |
| if(src->u.lpszFileName && !src->pUnkForRelease) { |
| DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR); |
| dst->u.lpszFileName = CoTaskMemAlloc(size); |
| if(!dst->u.lpszFileName) |
| return E_OUTOFMEMORY; |
| memcpy(dst->u.lpszFileName, src->u.lpszFileName, size); |
| } |
| break; |
| case TYMED_ISTREAM: |
| if(dst->u.pstm) |
| IStream_AddRef(dst->u.pstm); |
| break; |
| case TYMED_ISTORAGE: |
| if(dst->u.pstg) |
| IStorage_AddRef(dst->u.pstg); |
| break; |
| case TYMED_HGLOBAL: |
| if(dst->u.hGlobal) { |
| SIZE_T size = GlobalSize(src->u.hGlobal); |
| char *src_ptr, *dst_ptr; |
| |
| dst->u.hGlobal = GlobalAlloc(GMEM_FIXED, size); |
| if(!dst->u.hGlobal) |
| return E_OUTOFMEMORY; |
| dst_ptr = GlobalLock(dst->u.hGlobal); |
| src_ptr = GlobalLock(src->u.hGlobal); |
| memcpy(dst_ptr, src_ptr, size); |
| GlobalUnlock(src_ptr); |
| GlobalUnlock(dst_ptr); |
| } |
| break; |
| default: |
| FIXME("Unimplemented tymed %d\n", src->tymed); |
| } |
| |
| if(dst->pUnkForRelease) |
| IUnknown_AddRef(dst->pUnkForRelease); |
| |
| return S_OK; |
| } |
| |
| /*********************************************************************** |
| * CopyBindInfo (URLMON.@) |
| */ |
| HRESULT WINAPI CopyBindInfo(const BINDINFO *pcbiSrc, BINDINFO *pcbiDest) |
| { |
| DWORD size; |
| HRESULT hres; |
| |
| TRACE("(%p %p)\n", pcbiSrc, pcbiDest); |
| |
| if(!pcbiSrc || !pcbiDest) |
| return E_POINTER; |
| if(!pcbiSrc->cbSize || !pcbiDest->cbSize) |
| return E_INVALIDARG; |
| |
| size = pcbiDest->cbSize; |
| if(size > pcbiSrc->cbSize) { |
| memcpy(pcbiDest, pcbiSrc, pcbiSrc->cbSize); |
| memset((char*)pcbiDest+pcbiSrc->cbSize, 0, size-pcbiSrc->cbSize); |
| } else { |
| memcpy(pcbiDest, pcbiSrc, size); |
| } |
| pcbiDest->cbSize = size; |
| |
| size = FIELD_OFFSET(BINDINFO, szExtraInfo)+sizeof(void*); |
| if(pcbiSrc->cbSize>=size && pcbiDest->cbSize>=size && pcbiSrc->szExtraInfo) { |
| size = (strlenW(pcbiSrc->szExtraInfo)+1)*sizeof(WCHAR); |
| pcbiDest->szExtraInfo = CoTaskMemAlloc(size); |
| if(!pcbiDest->szExtraInfo) |
| return E_OUTOFMEMORY; |
| memcpy(pcbiDest->szExtraInfo, pcbiSrc->szExtraInfo, size); |
| } |
| |
| size = FIELD_OFFSET(BINDINFO, stgmedData)+sizeof(STGMEDIUM); |
| if(pcbiSrc->cbSize>=size && pcbiDest->cbSize>=size) { |
| hres = CopyStgMedium(&pcbiSrc->stgmedData, &pcbiDest->stgmedData); |
| if(FAILED(hres)) { |
| CoTaskMemFree(pcbiDest->szExtraInfo); |
| return hres; |
| } |
| } |
| |
| size = FIELD_OFFSET(BINDINFO, szCustomVerb)+sizeof(void*); |
| if(pcbiSrc->cbSize>=size && pcbiDest->cbSize>=size && pcbiSrc->szCustomVerb) { |
| size = (strlenW(pcbiSrc->szCustomVerb)+1)*sizeof(WCHAR); |
| pcbiDest->szCustomVerb = CoTaskMemAlloc(size); |
| if(!pcbiDest->szCustomVerb) { |
| CoTaskMemFree(pcbiDest->szExtraInfo); |
| ReleaseStgMedium(&pcbiDest->stgmedData); |
| return E_OUTOFMEMORY; |
| } |
| memcpy(pcbiDest->szCustomVerb, pcbiSrc->szCustomVerb, size); |
| } |
| |
| size = FIELD_OFFSET(BINDINFO, securityAttributes)+sizeof(SECURITY_ATTRIBUTES); |
| if(pcbiDest->cbSize >= size) |
| memset(&pcbiDest->securityAttributes, 0, sizeof(SECURITY_ATTRIBUTES)); |
| |
| if(pcbiSrc->pUnk) |
| IUnknown_AddRef(pcbiDest->pUnk); |
| |
| return S_OK; |
| } |
| |
| /*********************************************************************** |
| * GetClassFileOrMime (URLMON.@) |
| * |
| * Determines the class ID from the bind context, file name or MIME type. |
| */ |
| HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename, |
| LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved, |
| CLSID *pclsid) |
| { |
| FIXME("(%p, %s, %p, %d, %s, 0x%08x, %p): stub\n", pBC, debugstr_w(pszFilename), pBuffer, |
| cbBuffer, debugstr_w(pszMimeType), dwReserved, pclsid); |
| return E_NOTIMPL; |
| } |
| |
| /*********************************************************************** |
| * Extract (URLMON.@) |
| */ |
| HRESULT WINAPI Extract(void *dest, LPCSTR szCabName) |
| { |
| HRESULT (WINAPI *pExtract)(void *, LPCSTR); |
| |
| if (!hCabinet) |
| hCabinet = LoadLibraryA("cabinet.dll"); |
| |
| if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError()); |
| pExtract = (void *)GetProcAddress(hCabinet, "Extract"); |
| if (!pExtract) return HRESULT_FROM_WIN32(GetLastError()); |
| |
| return pExtract(dest, szCabName); |
| } |
| |
| /*********************************************************************** |
| * IsLoggingEnabledA (URLMON.@) |
| */ |
| BOOL WINAPI IsLoggingEnabledA(LPCSTR url) |
| { |
| FIXME("(%s)\n", debugstr_a(url)); |
| return FALSE; |
| } |
| |
| /*********************************************************************** |
| * IsLoggingEnabledW (URLMON.@) |
| */ |
| BOOL WINAPI IsLoggingEnabledW(LPCWSTR url) |
| { |
| FIXME("(%s)\n", debugstr_w(url)); |
| return FALSE; |
| } |
| |
| /*********************************************************************** |
| * IsProtectedModeURL (URLMON.111) |
| * Undocumented, added in IE7 |
| */ |
| BOOL WINAPI IsProtectedModeURL(const WCHAR *url) |
| { |
| FIXME("stub: %s\n", debugstr_w(url)); |
| return TRUE; |
| } |
| |
| /*********************************************************************** |
| * LogSqmBits (URLMON.410) |
| * Undocumented, added in IE8 |
| */ |
| int WINAPI LogSqmBits(DWORD unk1, DWORD unk2) |
| { |
| FIXME("stub: %d %d\n", unk1, unk2); |
| return 0; |
| } |
| |
| /*********************************************************************** |
| * LogSqmUXCommandOffsetInternal (URLMON.423) |
| * Undocumented, added in IE8 |
| */ |
| void WINAPI LogSqmUXCommandOffsetInternal(DWORD unk1, DWORD unk2, DWORD unk3, DWORD unk4) |
| { |
| FIXME("stub: %d %d %d %d\n", unk1, unk2, unk3, unk4); |
| } |
| |
| /*********************************************************************** |
| * MapUriToBrowserEmulationState (URLMON.444) |
| * Undocumented, added in IE8 |
| */ |
| int WINAPI MapUriToBrowserEmulationState(DWORD unk1, DWORD unk2, DWORD unk3) |
| { |
| FIXME("stub: %d %d %d\n", unk1, unk2, unk3); |
| return 0; |
| } |
| |
| /*********************************************************************** |
| * MapBrowserEmulationModeToUserAgent (URLMON.445) |
| * Undocumented, added in IE8 |
| */ |
| int WINAPI MapBrowserEmulationModeToUserAgent(DWORD unk1, DWORD unk2) |
| { |
| FIXME("stub: %d %d\n", unk1, unk2); |
| return 0; |
| } |
| |
| /*********************************************************************** |
| * FlushUrlmonZonesCache (URLMON.455) |
| * Undocumented, added in IE8 |
| */ |
| void WINAPI FlushUrlmonZonesCache(void) |
| { |
| FIXME("stub\n"); |
| } |
| |
| /*********************************************************************** |
| * RegisterMediaTypes |
| * Added in IE3, registers known MIME-type strings. |
| */ |
| HRESULT WINAPI RegisterMediaTypes(UINT types, LPCSTR *szTypes, CLIPFORMAT *cfTypes) |
| { |
| FIXME("stub: %u %p %p\n", types, szTypes, cfTypes); |
| return E_INVALIDARG; |
| } |