You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
237 lines
5.5 KiB
237 lines
5.5 KiB
// ClientCaps.cpp : Implementation of CClientCaps
|
|
#include "headers.h"
|
|
|
|
#pragma MARK_DATA(__FILE__)
|
|
#pragma MARK_CODE(__FILE__)
|
|
#pragma MARK_CONST(__FILE__)
|
|
#include "iextag.h"
|
|
|
|
#include "utils.hxx"
|
|
|
|
#include "download.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CDownload
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
CDownload::~CDownload()
|
|
{
|
|
ReleaseInterface (_pdispCallback);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT
|
|
CDownload::Download(
|
|
BSTR bstrURL,
|
|
IDispatch * pdispCallback,
|
|
IUnknown * pUnkContainer)
|
|
{
|
|
HRESULT hr;
|
|
CComObject<CDownload> * pDownload;
|
|
|
|
hr = CComObject<CDownload>::CreateInstance(&pDownload);
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
pDownload->_pdispCallback = pdispCallback;
|
|
pdispCallback->AddRef();
|
|
|
|
pDownload->StartAsyncDownload(NULL, NULL, bstrURL, pUnkContainer, TRUE);
|
|
// hr can now be S_OK, S_ASYNC, or failure
|
|
|
|
// ignore hr
|
|
#if 0
|
|
if (FAILED(hr))
|
|
{
|
|
hr = InvokeCallback(NULL, pdispCallback);
|
|
}
|
|
#endif
|
|
|
|
Cleanup:
|
|
return hr;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// the implementation is similar to CBindStatusCallback::OnDataAvailable,
|
|
// except it waits for the last chunk of data and only then calls OnFinalDataAvailable
|
|
|
|
HRESULT
|
|
CDownload::OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwActuallyRead;
|
|
BYTE * pBytes = NULL;
|
|
CComPtr<IStream> pStream;
|
|
|
|
ATLTRACE(_T("CBindStatusCallback::OnDataAvailable\n"));
|
|
|
|
if (!(BSCF_LASTDATANOTIFICATION & grfBSCF))
|
|
goto Cleanup;
|
|
|
|
ATLTRACE(_T("CBindStatusCallback::OnDataAvailable FINAL\n"));
|
|
|
|
if (pstgmed->tymed != TYMED_ISTREAM)
|
|
goto Cleanup;
|
|
|
|
pStream = pstgmed->pstm;
|
|
if (!pStream)
|
|
goto Cleanup;
|
|
|
|
pBytes = new BYTE[dwSize + 1];
|
|
if (pBytes == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = pStream->Read(pBytes, dwSize, &dwActuallyRead);
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
pBytes[dwActuallyRead] = 0;
|
|
if (0 < dwActuallyRead)
|
|
{
|
|
OnFinalDataAvailable(pBytes, dwActuallyRead);
|
|
}
|
|
|
|
Cleanup:
|
|
delete[] pBytes;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void
|
|
CDownload::OnFinalDataAvailable (BYTE * pBytes, DWORD dwSize)
|
|
{
|
|
LPTSTR pchString = NULL;
|
|
ULONG cchString;
|
|
|
|
//
|
|
// get unicode string
|
|
//
|
|
|
|
// get length
|
|
cchString = MultiByteToWideChar(CP_ACP, 0, (LPSTR) pBytes, dwSize, NULL, 0);
|
|
if (!cchString)
|
|
goto Cleanup;
|
|
|
|
pchString = new TCHAR[cchString + 1];
|
|
if (!pchString)
|
|
goto Cleanup;
|
|
|
|
// convert now
|
|
MultiByteToWideChar(CP_ACP, 0, (LPSTR) pBytes, dwSize, pchString, cchString);
|
|
pchString[cchString] = 0;
|
|
|
|
//
|
|
// invoke the callback function
|
|
//
|
|
|
|
InvokeCallback(pchString, _pdispCallback);
|
|
|
|
Cleanup:
|
|
ClearInterface (&_pdispCallback);
|
|
|
|
delete pchString;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT
|
|
CDownload::InvokeCallback(LPTSTR pchString, IDispatch * pdispCallback)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (pdispCallback)
|
|
{
|
|
VARIANT varArg;
|
|
DISPPARAMS dispparams = {&varArg, NULL, 1, 0};
|
|
EXCEPINFO excepinfo;
|
|
UINT nArgErr;
|
|
|
|
if (pchString)
|
|
{
|
|
V_VT(&varArg) = VT_BSTR;
|
|
V_BSTR(&varArg) = SysAllocString(pchString);
|
|
if (!V_BSTR(&varArg))
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
V_VT(&varArg) = VT_NULL;
|
|
}
|
|
|
|
hr = pdispCallback->Invoke(
|
|
DISPID_VALUE, IID_NULL, LOCALE_SYSTEM_DEFAULT,
|
|
DISPATCH_METHOD, &dispparams, NULL, &excepinfo, &nArgErr);
|
|
SysFreeString(V_BSTR(&varArg));
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CDownloadBehavior
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
CDownloadBehavior::CDownloadBehavior()
|
|
{
|
|
memset (this, 0, sizeof(*this));
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
CDownloadBehavior::~CDownloadBehavior()
|
|
{
|
|
ReleaseInterface(_pSite);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT
|
|
CDownloadBehavior::Init(IElementBehaviorSite *pSite)
|
|
{
|
|
if (!pSite)
|
|
return E_INVALIDARG;
|
|
|
|
_pSite = pSite;
|
|
_pSite->AddRef();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT
|
|
CDownloadBehavior::Notify(LONG lEvent, VARIANT * pVarNotify)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT
|
|
CDownloadBehavior::startDownload(BSTR bstrUrl, IDispatch * pdispCallback)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (!bstrUrl || !pdispCallback)
|
|
return E_INVALIDARG;
|
|
|
|
if (!AccessAllowed(bstrUrl, _pSite))
|
|
return E_ACCESSDENIED;
|
|
|
|
hr = CDownload::Download(bstrUrl, pdispCallback, _pSite);
|
|
|
|
return hr;
|
|
}
|