From 9debcb8f49a97d5db3a4d24e5f3eb13c367590d6 Mon Sep 17 00:00:00 2001 From: Rob Shearman Date: Fri, 3 Aug 2007 22:11:31 +0100 Subject: [PATCH] urlmon: Implement URLOpenBlockingStreamA/W and URLOpenStreamA/W. --- dlls/urlmon/umstream.c | 241 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 227 insertions(+), 14 deletions(-) diff --git a/dlls/urlmon/umstream.c b/dlls/urlmon/umstream.c index ec2b3061cf5..9ebf23274f5 100644 --- a/dlls/urlmon/umstream.c +++ b/dlls/urlmon/umstream.c @@ -379,6 +379,173 @@ static const IStreamVtbl stvt = }; +typedef struct ProxyBindStatusCallback +{ + const IBindStatusCallbackVtbl *lpVtbl; + + IBindStatusCallback *pBSC; +} ProxyBindStatusCallback; + +static HRESULT WINAPI ProxyBindStatusCallback_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv) +{ + if (IsEqualGUID(&IID_IBindStatusCallback, riid) || + IsEqualGUID(&IID_IUnknown, riid)) + { + *ppv = iface; + IUnknown_AddRef(iface); + return S_OK; + } + + *ppv = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI ProxyBindStatusCallback_AddRef(IBindStatusCallback *iface) +{ + return 2; +} + +static ULONG WINAPI ProxyBindStatusCallback_Release(IBindStatusCallback *iface) +{ + return 1; +} + +static HRESULT WINAPI ProxyBindStatusCallback_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved, + IBinding *pib) +{ + ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface; + return IBindStatusCallback_OnStartBinding(This->pBSC, dwReserved, pib); +} + +static HRESULT WINAPI ProxyBindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority) +{ + ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface; + return IBindStatusCallback_GetPriority(This->pBSC, pnPriority); +} + +static HRESULT WINAPI ProxyBindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved) +{ + ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface; + return IBindStatusCallback_OnLowResource(This->pBSC, reserved); +} + +static HRESULT WINAPI ProxyBindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress, + ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) +{ + ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface; + return IBindStatusCallback_OnProgress(This->pBSC, ulProgress, + ulProgressMax, ulStatusCode, + szStatusText); +} + +static HRESULT WINAPI ProxyBindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError) +{ + ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface; + return IBindStatusCallback_OnStopBinding(This->pBSC, hresult, szError); +} + +static HRESULT WINAPI ProxyBindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo) +{ + ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface; + return IBindStatusCallback_GetBindInfo(This->pBSC, grfBINDF, pbindinfo); +} + +static HRESULT WINAPI ProxyBindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF, + DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed) +{ + ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface; + return IBindStatusCallback_OnDataAvailable(This->pBSC, grfBSCF, dwSize, + pformatetc, pstgmed); +} + +static HRESULT WINAPI ProxyBindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk) +{ + ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface; + return IBindStatusCallback_OnObjectAvailable(This->pBSC, riid, punk); +} + +static HRESULT WINAPI BlockingBindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF, + DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed) +{ + return S_OK; +} + +static const IBindStatusCallbackVtbl BlockingBindStatusCallbackVtbl = +{ + ProxyBindStatusCallback_QueryInterface, + ProxyBindStatusCallback_AddRef, + ProxyBindStatusCallback_Release, + ProxyBindStatusCallback_OnStartBinding, + ProxyBindStatusCallback_GetPriority, + ProxyBindStatusCallback_OnLowResource, + ProxyBindStatusCallback_OnProgress, + ProxyBindStatusCallback_OnStopBinding, + ProxyBindStatusCallback_GetBindInfo, + BlockingBindStatusCallback_OnDataAvailable, + ProxyBindStatusCallback_OnObjectAvailable +}; + +static HRESULT WINAPI AsyncBindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo) +{ + ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface; + HRESULT hr = IBindStatusCallback_GetBindInfo(This->pBSC, grfBINDF, pbindinfo); + *grfBINDF |= BINDF_PULLDATA | BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE; + return hr; +} + +static const IBindStatusCallbackVtbl AsyncBindStatusCallbackVtbl = +{ + ProxyBindStatusCallback_QueryInterface, + ProxyBindStatusCallback_AddRef, + ProxyBindStatusCallback_Release, + ProxyBindStatusCallback_OnStartBinding, + ProxyBindStatusCallback_GetPriority, + ProxyBindStatusCallback_OnLowResource, + ProxyBindStatusCallback_OnProgress, + ProxyBindStatusCallback_OnStopBinding, + AsyncBindStatusCallback_GetBindInfo, + ProxyBindStatusCallback_OnDataAvailable, + ProxyBindStatusCallback_OnObjectAvailable +}; + +static HRESULT URLStartDownload(LPCWSTR szURL, LPSTREAM *ppStream, IBindStatusCallback *pBSC) +{ + HRESULT hr; + IMoniker *pMoniker; + IBindCtx *pbc; + + *ppStream = NULL; + + hr = CreateURLMoniker(NULL, szURL, &pMoniker); + if (FAILED(hr)) + return hr; + + hr = CreateBindCtx(0, &pbc); + if (FAILED(hr)) + { + IMoniker_Release(pMoniker); + return hr; + } + + hr = RegisterBindStatusCallback(pbc, pBSC, NULL, 0); + if (FAILED(hr)) + { + IBindCtx_Release(pbc); + IMoniker_Release(pMoniker); + return hr; + } + + hr = IMoniker_BindToStorage(pMoniker, pbc, NULL, &IID_IStream, (void **)ppStream); + + /* BindToStorage returning E_PENDING because it's asynchronous is not an error */ + if (hr == E_PENDING) hr = S_OK; + + IBindCtx_Release(pbc); + IMoniker_Release(pMoniker); + + return hr; +} + /*********************************************************************** * URLOpenBlockingStreamA (URLMON.@) */ @@ -386,9 +553,23 @@ HRESULT WINAPI URLOpenBlockingStreamA(LPUNKNOWN pCaller, LPCSTR szURL, LPSTREAM *ppStream, DWORD dwReserved, LPBINDSTATUSCALLBACK lpfnCB) { - FIXME("(%p, %s, %p, 0x%x, %p): stub\n", pCaller, szURL, ppStream, dwReserved, lpfnCB); - *ppStream = NULL; - return E_NOTIMPL; + LPWSTR szURLW; + int len; + HRESULT hr; + + TRACE("(%p, %s, %p, 0x%x, %p)\n", pCaller, szURL, ppStream, dwReserved, lpfnCB); + + len = MultiByteToWideChar(CP_ACP, 0, szURL, -1, NULL, 0); + szURLW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!szURLW) + return E_OUTOFMEMORY; + MultiByteToWideChar(CP_ACP, 0, szURL, -1, szURLW, len); + + hr = URLOpenBlockingStreamW(pCaller, szURLW, ppStream, dwReserved, lpfnCB); + + HeapFree(GetProcessHeap(), 0, szURLW); + + return hr; } /*********************************************************************** @@ -398,29 +579,61 @@ HRESULT WINAPI URLOpenBlockingStreamW(LPUNKNOWN pCaller, LPCWSTR szURL, LPSTREAM *ppStream, DWORD dwReserved, LPBINDSTATUSCALLBACK lpfnCB) { - FIXME("(%p, %s, %p, 0x%x, %p): stub\n", pCaller, debugstr_w(szURL), ppStream, + ProxyBindStatusCallback blocking_bsc; + + TRACE("(%p, %s, %p, 0x%x, %p)\n", pCaller, debugstr_w(szURL), ppStream, dwReserved, lpfnCB); - *ppStream = NULL; - return E_NOTIMPL; + + blocking_bsc.lpVtbl = &BlockingBindStatusCallbackVtbl; + blocking_bsc.pBSC = lpfnCB; + + return URLStartDownload(szURL, ppStream, (IBindStatusCallback *)&blocking_bsc); } /*********************************************************************** -* URLOpenStreamA (URLMON.@) -*/ + * URLOpenStreamA (URLMON.@) + */ HRESULT WINAPI URLOpenStreamA(LPUNKNOWN pCaller, LPCSTR szURL, DWORD dwReserved, LPBINDSTATUSCALLBACK lpfnCB) { - FIXME("(%p, %s, 0x%x, %p): stub\n", pCaller, szURL, dwReserved, lpfnCB); - return E_NOTIMPL; + LPWSTR szURLW; + int len; + HRESULT hr; + + TRACE("(%p, %s, 0x%x, %p)\n", pCaller, szURL, dwReserved, lpfnCB); + + len = MultiByteToWideChar(CP_ACP, 0, szURL, -1, NULL, 0); + szURLW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!szURLW) + return E_OUTOFMEMORY; + MultiByteToWideChar(CP_ACP, 0, szURL, -1, szURLW, len); + + hr = URLOpenStreamW(pCaller, szURLW, dwReserved, lpfnCB); + + HeapFree(GetProcessHeap(), 0, szURLW); + + return hr; } /*********************************************************************** -* URLOpenStreamW (URLMON.@) -*/ + * URLOpenStreamW (URLMON.@) + */ HRESULT WINAPI URLOpenStreamW(LPUNKNOWN pCaller, LPCWSTR szURL, DWORD dwReserved, LPBINDSTATUSCALLBACK lpfnCB) { - FIXME("(%p, %s, 0x%x, %p): stub\n", pCaller, debugstr_w(szURL), dwReserved, + HRESULT hr; + ProxyBindStatusCallback async_bsc; + IStream *pStream; + + TRACE("(%p, %s, 0x%x, %p)\n", pCaller, debugstr_w(szURL), dwReserved, lpfnCB); - return E_NOTIMPL; + + async_bsc.lpVtbl = &AsyncBindStatusCallbackVtbl; + async_bsc.pBSC = lpfnCB; + + hr = URLStartDownload(szURL, &pStream, (IBindStatusCallback *)&async_bsc); + if (SUCCEEDED(hr) && pStream) + IStream_Release(pStream); + + return hr; }