diff --git a/dlls/urlmon/urlmon.spec b/dlls/urlmon/urlmon.spec index 575bdc08487..72bd21d3165 100644 --- a/dlls/urlmon/urlmon.spec +++ b/dlls/urlmon/urlmon.spec @@ -28,7 +28,7 @@ @ stdcall CoInternetQueryInfo(ptr long long ptr long ptr long) @ stdcall CoInternetSetFeatureEnabled(long long long) @ stdcall CompareSecurityIds(ptr long ptr long long) -@ stub CopyBindInfo +@ stdcall CopyBindInfo(ptr ptr) @ stdcall CopyStgMedium(ptr ptr) @ stdcall CreateAsyncBindCtx(long ptr ptr ptr) @ stdcall CreateAsyncBindCtxEx(ptr long ptr ptr ptr long) diff --git a/dlls/urlmon/urlmon_main.c b/dlls/urlmon/urlmon_main.c index a3d1c10668c..94c4b44941f 100644 --- a/dlls/urlmon/urlmon_main.c +++ b/dlls/urlmon/urlmon_main.c @@ -533,6 +533,8 @@ HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst) 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; @@ -554,6 +556,69 @@ HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst) 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; + } + } + + 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; +} + static BOOL text_richtext_filter(const BYTE *b, DWORD size) { return size > 5 && !memcmp(b, "{\\rtf", 5);