Windows2003-3790/inetcore/urlmon/trans/cbinding.cxx
2020-09-30 16:53:55 +02:00

4468 lines
129 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995.
//
// File: cbinding.cxx
//
// Contents:
//
// Classes:
//
// Functions:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
//----------------------------------------------------------------------------
#include <trans.h>
#include "oinet.hxx"
#include "cdl.h" // defined in urlmon\download\
// from helpers.cxx
HRESULT IsMimeHandled(LPCWSTR pwszMimeType);
// From shlwapip.h
LWSTDAPI_(HRESULT) CLSIDFromStringWrap(LPOLESTR lpsz, LPCLSID pclsid);
PerfDbgTag(tagCBinding, "Urlmon", "Log CBinding", DEB_BINDING);
DbgTag(tagCBindingErr, "Urlmon", "Log CBinding Errors", DEB_BINDING|DEB_ERROR);
extern DWORD g_dwSettings;
#define MAX_PROTOCOL_LEN 32 // protocl string length in ASCII BUGBUG is there a standard?
#define PROTOCOL_DELIMITER ':'
#define REG_PROTOCOL_HANDLER L"ProtocolHandler"
WCHAR *rglpProto[] =
{
L"https",
L"http",
L"ftp",
L"gopher",
L"file",
L"local",
L"mk",
NULL,
};
HRESULT GetTransactionObjects(LPBC pBndCtx, LPCWSTR wzUrl, IUnknown *pUnkOuter, IUnknown **ppUnk, IOInetProtocol **ppCTrans, DWORD dwOption, CTransData **pCTransData);
BOOL PDFNeedProgressiveDownload();
EXTERN_C const GUID CLSID_MsHtml;
EXTERN_C const GUID IID_ITransactionData;
//+---------------------------------------------------------------------------
//
// Function: CreateURLBinding
//
// Synopsis:
//
// Arguments: [lpszUrl] --
// [pbc] --
// [ppBdg] --
//
// Returns:
//
// History: 12-04-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CreateURLBinding(LPWSTR lpszUrl, IBindCtx *pbc, IBinding **ppBdg)
{
DEBUG_ENTER_API((DBG_BINDING,
Hresult,
"CreateURLBinding",
"%.80wq, %#x, %#x",
lpszUrl, pbc, ppBdg
));
PerfDbgLog(tagCBinding, NULL, "+CreateURLBinding");
HRESULT hr = NOERROR;
PerfDbgLog1(tagCBinding, NULL, "-CreateURLBinding (IBinding:%lx)", *ppBdg);
DEBUG_LEAVE_API(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::Create
//
// Synopsis:
//
// Arguments: [pUnkOuter] --
// [LPBC] --
// [pbc] --
//
// Returns:
//
// History: 12-06-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CBinding::Create(IUnknown *pUnkOuter, LPCWSTR szUrl, LPBC pbc, REFIID riid, BOOL fBindToObject, CBinding **ppCBdg)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::Create",
"%#x, %.80wq, %#x, %#x, %B, %#x",
pUnkOuter, szUrl, pbc, &riid, fBindToObject, ppCBdg
));
PerfDbgLog1(tagCBinding, NULL, "+CBinding::Create (szUrl:%ws)", szUrl);
HRESULT hr = NOERROR;
CBinding *pCBdg;
UrlMkAssert((ppCBdg != NULL));
// Create and initialize the cbinding object
pCBdg = new CBinding(NULL);
if (pCBdg == NULL)
{
hr = E_OUTOFMEMORY;
}
*ppCBdg = pCBdg;
PerfDbgLog2(tagCBinding, NULL, "-CBinding::Create (hr:%lx,IBinding:%lx)", hr, pCBdg);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::Initialize
//
// Synopsis:
//
// Arguments: [szUrl] --
// [pbc] --
//
// Returns:
//
// History: 12-04-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CBinding::Initialize(LPCWSTR szUrl, IBindCtx *pbc, DWORD grfBindF, REFIID riid, BOOL fBindToObject)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::Initialize",
"this=%#x, %.80wq, %#x, %#x, %#x, %B",
this, szUrl, pbc, grfBindF, &riid, fBindToObject
));
HRESULT hr = NOERROR;
PerfDbgLog(tagCBinding, this, "+CBinding::Initialize");
_fBindToObject = fBindToObject;
if (fBindToObject)
{
// Get the bind options from the bind context
_bindopts.cbStruct = sizeof(BIND_OPTS);
hr = pbc->GetBindOptions(&_bindopts);
if (FAILED(hr))
{
goto End;
}
}
hr = CBindCtx::Create(&_pBndCtx, pbc);
if ((hr == NOERROR) && szUrl)
{
TransAssert((_pBndCtx));
int cchWideChar;
cchWideChar = wcslen(szUrl) + 2;
_lpwszUrl = (LPWSTR) new WCHAR [cchWideChar];
if( !_lpwszUrl )
{
hr = E_OUTOFMEMORY;
goto End;
}
wcscpy(_lpwszUrl, szUrl);
// Try to get an IBindStatusCallback pointer from the bind context
hr = GetObjectParam(pbc, REG_BSCB_HOLDER, IID_IBindStatusCallback, (IUnknown**)&_pBSCB);
UrlMkAssert(( (hr == NOERROR) && _pBSCB ));
PerfDbgLog2(tagCBinding, this, "=== CBinding::Initialize (pbc:%lx -> _pBSCB:%lx)", pbc, _pBSCB);
hr = GetTransactionObjects(_pBndCtx, _lpwszUrl, NULL, NULL, &_pOInetBdg,OIBDG_APARTMENTTHREADED, &_pCTransData);
if (hr == S_OK)
{
TransAssert((!_pCTransData));
// create the transaction data object
// Note: the transdat object has a refcount
// and must be released when done
hr = CTransData::Create(_lpwszUrl, grfBindF, riid, _pBndCtx, _fBindToObject, &_pCTransData);
if (FAILED(hr))
{
//goto End;
}
else
{
UrlMkAssert((_pCTransData != NULL && "CTransData invalid"));
_pBndCtx->SetTransData(_pCTransData);
}
}
else if (hr == S_FALSE)
{
UrlMkAssert((_pCTransData != NULL && "CTransData invalid"));
if (fBindToObject)
_grfInternalFlags |= BDGFLAGS_BTS_BTO;
else
_grfInternalFlags |= BDGFLAGS_ATTACHED;
hr = _pCTransData->Initialize(_lpwszUrl, grfBindF, riid, _pBndCtx);
}
else
{
hr = E_OUTOFMEMORY;
}
if (_fBindToObject)
{
_piidRes = (IID *) &riid;
}
}
else
{
hr = E_OUTOFMEMORY;
}
End:
PerfDbgLog1(tagCBinding, this, "-CBinding::Initialize (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::CBinding
//
// Synopsis:
//
// Arguments: [pUnk] --
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
CBinding::CBinding(IUnknown *pUnk) : _CRefs()
{
DEBUG_ENTER((DBG_BINDING,
None,
"CBinding::CBinding",
"this=%#x, %#x",
this, pUnk
));
_pUnk = pUnk;
if (_pUnk)
{
_pUnk->AddRef();
}
_dwThreadId = GetCurrentThreadId();
_pBSCB = 0;
_nPriority = THREAD_PRIORITY_NORMAL;
_dwState = 0;
_OperationState = OPS_Initialized;
_hwndNotify = 0;
_grfBINDF = 0;
_dwLastSize = 0;
_lpwszUrl = 0;
_pOInetBdg = 0;
_fSentLastNotification = 0;
_fSentFirstNotification = 0;
_fCreateStgMed = 0;
_fCompleteDownloadHere = FALSE;
_fForceBindToObjFail = FALSE;
_fAcceptRanges = FALSE;
_fClsidFromProt = FALSE;
_pMnk = NULL;
_pBndCtx = NULL;
_piidRes = (IID*)&IID_IUnknown; // NULL;
_pUnkObject = NULL;
_pBasicAuth = NULL;
_hrBindResult = NOERROR;
_hrInstantiate = NOERROR;
_dwBindError = 0;
_grfInternalFlags = BDGFLAGS_NOTIFICATIONS;
_pwzRedirectUrl = 0;
_pwzResult = 0;
_pBindInfo = 0;
_clsidIn = CLSID_NULL;
_fCanGetIWinInetInfo = FALSE;
_fCanGetIWinInetHttpInfo = FALSE;
_fBTS_BTO = FALSE;
DEBUG_LEAVE(0);
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::~CBinding
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
CBinding::~CBinding()
{
DEBUG_ENTER((DBG_BINDING,
None,
"CBinding::~CBinding",
"this=%#x",
this
));
PerfDbgLog(tagCBinding, this, "+CBinding::~CBinding");
if (_pBindInfo)
{
_pBindInfo->Release();
}
if (_pUnk)
{
DbgLog(tagCBinding, this, "CBinding::~CBinding Release on _pUnk");
_pUnk->Release();
}
if (_pBasicAuth)
{
DbgLog1(tagCBinding, this, "CBinding::~CBinding Release on _pBasicAuth (%lx)", _pBasicAuth);
_pBasicAuth->Release();
}
if (_pBSCB)
{
DbgLog1(tagCBinding, this, "CBinding::~CBinding Release on IBSCB (%lx)", _pBSCB);
_pBSCB->Release();
}
if (_pOInetBdg)
{
_pOInetBdg->Release();
}
if (_pMnk)
{
_pMnk->Release();
}
if (_pBndCtx)
{
_pBndCtx->Release();
}
if (_pCTransData)
{
DbgLog1(tagCBinding, this, "CBinding::~CBinding Release TransData (%lx)", _pCTransData);
_pCTransData->Release();
}
if (_pUnkObject)
{
_pUnkObject->Release();
}
if (_lpwszUrl)
{
delete [] _lpwszUrl;
}
if (_pwzRedirectUrl)
{
delete [] _pwzRedirectUrl;
}
if (_pwzResult)
{
delete [] _pwzResult;
}
ReleaseBindInfo(&_BndInfo);
PerfDbgLog(tagCBinding, this, "-CBinding::~CBinding");
DEBUG_LEAVE(0);
}
LPWSTR CBinding::GetFileName()
{
DEBUG_ENTER((DBG_BINDING,
String,
"CBinding::GetFileName",
"this=%#x",
this
));
LPWSTR wzFilename = _pCTransData->GetFileName();
DEBUG_LEAVE(wzFilename);
return wzFilename;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::QueryInterface
//
// Synopsis:
//
// Arguments: [riid] --
// [ppv] --
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::QueryInterface( REFIID riid, void **ppv )
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::IUnknown::QueryInterface",
"this=%#x, %#x, %#x",
this, &riid, ppv
));
PerfDbgLog2(tagCBinding, this, "+CBinding::QueryInterface (%lx, %lx)", riid, ppv);
HRESULT hr = NOERROR;
*ppv = NULL;
//UrlMkAssert(( !IsEqualIID(GetProtocolClassID(),CLSID_NULL) ));
if ( IsEqualIID(riid, IID_IUnknown)
|| IsEqualIID(riid, IID_IBinding) )
{
*ppv = (void FAR *)(IBinding *)this;
AddRef();
}
else if (IsEqualIID(riid, IID_IOInetProtocolSink))
{
*ppv = (void FAR *)(IOInetProtocolSink *)this;
AddRef();
}
else if (IsEqualIID(riid, IID_IOInetBindInfo))
{
*ppv = (void FAR *)(IOInetBindInfo *)this;
AddRef();
}
else if (IsEqualIID(riid, IID_IServiceProvider))
{
*ppv = (void FAR *)(IServiceProvider *)this;
AddRef();
}
else if (IsEqualIID(riid, IID_IWinInetInfo))
{
if (_pOInetBdg)
{
IWinInetInfo *pIWinInetInfo;
hr = _pOInetBdg->QueryInterface(riid, (void **)&pIWinInetInfo);
if (S_FALSE == hr)
hr = E_NOINTERFACE;//see bug 99754
//dont keep the reference..release it immdly.
if (SUCCEEDED(hr))
{
pIWinInetInfo->Release();
_fCanGetIWinInetInfo = TRUE;
*ppv = (void FAR *) (IWinInetInfo *)this;
AddRef();
}
}
else
{
hr = E_NOINTERFACE;
}
}
else if (IsEqualIID(riid, IID_IWinInetHttpInfo))
{
if (_pOInetBdg)
{
IWinInetHttpInfo *pIWinInetHttpInfo;
hr = _pOInetBdg->QueryInterface(riid, (void **)&pIWinInetHttpInfo);
if (S_FALSE == hr)
hr = E_NOINTERFACE;//see bug 99754
if (SUCCEEDED(hr))
{
pIWinInetHttpInfo->Release();
_fCanGetIWinInetHttpInfo = TRUE;
*ppv = (void FAR *) (IWinInetHttpInfo *)this;
AddRef();
}
}
else
{
hr = E_NOINTERFACE;
}
}
else
{
*ppv = NULL;
hr = E_NOINTERFACE;
#if DBG==1
//LPSTR lpszName = GetInterfaceName(riid);
//DbgLog3(tagCBinding, this, "CBinding::QI(pUnkObj) >%s< hr:%lx [%lx]", lpszName, hr, *ppv));
#endif // DBG==1
}
PerfDbgLog2(tagCBinding, this, "-CBinding::QueryInterface (%lx)[%lx]", hr, *ppv);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::AddRef
//
// Synopsis:
//
// Arguments: [void] --
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CBinding::AddRef( void )
{
DEBUG_ENTER((DBG_BINDING,
Dword,
"CBinding::IUnknown::AddRef",
"this=%#x",
this
));
LONG lRet = ++_CRefs;
PerfDbgLog1(tagCBinding, this, "CBinding::AddRef (%ld)", lRet);
DEBUG_LEAVE(lRet);
return lRet;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::Release
//
// Synopsis:
//
// Arguments: [void] --
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CBinding::Release( void )
{
DEBUG_ENTER((DBG_BINDING,
Dword,
"CBinding::IUnknown::Release",
"this=%#x",
this
));
PerfDbgLog(tagCBinding, this, "+CBinding::Release");
LONG lRet = --_CRefs;
if (_CRefs == 0)
{
delete this;
}
PerfDbgLog1(tagCBinding, this, "-CBinding::Release (%ld)", lRet);
DEBUG_LEAVE(lRet);
return lRet;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::Abort
//
// Synopsis:
//
// Arguments: [void] --
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::Abort( void )
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::IBinding::Abort",
"this=%#x",
this
));
PerfDbgLog(tagCBinding, this, "+CBinding::Abort");
HRESULT hr = NOERROR;
// AddRef - Release pair to guard this function since it may
// call OnStopBinding() and client will re-enter this
// Object with a Release() call.
AddRef();
if ( (GetOperationState() < OPS_Abort)
&& (GetOperationState() > OPS_Initialized))
{
DbgLog(tagCBindingErr, this, ">>> CBinding::Abort");
// Abort will call OnStopBinding
TransAssert((_pOInetBdg));
hr = _pOInetBdg->Abort(E_ABORT, 0);
if( hr != INET_E_RESULT_DISPATCHED )
{
//
// only set state to OPS_Abort if the the ReportResult
// has not been dispatched already
//
DbgLog(tagCBindingErr, this, ">>> Result already dispatched");
SetOperationState(OPS_Abort);
}
}
else
{
UrlMkAssert(( ( (GetOperationState() < OPS_Stopped)
&& (GetOperationState() > OPS_Initialized)) ));
hr = E_FAIL;
}
PerfDbgLog1(tagCBinding, this, "-CBinding::Abort (hr:%lx)", hr);
// release
Release();
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::Suspend
//
// Synopsis:
//
// Arguments: [void] --
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::Suspend( void )
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::IBinding::Suspend",
"this=%#x",
this
));
PerfDbgLog(tagCBinding, this, "+CBinding::Suspend");
HRESULT hr = E_FAIL;
#ifdef SUSPEND_WORKING
if ( (GetOperationState() < OPS_Stopped)
&& (GetOperationState() > OPS_Initialized))
{
SetOperationState(OPS_Suspend);
}
else
{
UrlMkAssert(( ( (GetOperationState() < OPS_Stopped)
&& (GetOperationState() > OPS_Initialized)) ));
}
#endif //SUSPEND_WORKING
hr = _pOInetBdg->Suspend();
#ifdef UNUSED
UrlMkAssert((_dwState == OPS_Downloading));
_dwState = OPS_Suspend;
if (_pOInetBdg)
{
_pOInetBdg->SetOperationState(OPS_Suspend);
}
#endif //UNUSED
PerfDbgLog1(tagCBinding, this, "-CBinding::Suspend (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::Resume
//
// Synopsis:
//
// Arguments: [void] --
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::Resume( void )
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::IBinding::Resume",
"this=%#x",
this
));
PerfDbgLog(tagCBinding, this, "+CBinding::Resume");
HRESULT hr = NOERROR;
if (GetOperationState() == OPS_Suspend)
{
SetOperationState(OPS_Downloading);
}
else
{
UrlMkAssert(( GetOperationState() == OPS_Suspend ));
}
hr = _pOInetBdg->Resume();
PerfDbgLog1(tagCBinding, this, "-CBinding::Resume (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::SetPriority
//
// Synopsis:
//
// Arguments: [nPriority] --
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::SetPriority(LONG nPriority)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::IBinding::SetPriority",
"this=%#x, %d",
this, nPriority
));
PerfDbgLog1(tagCBinding, this, "+CBinding::SetPriority (%ld)", nPriority);
HRESULT hr = NOERROR;
_nPriority = nPriority;
PerfDbgLog1(tagCBinding, this, "-CBinding::SetPriority (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::GetPriority
//
// Synopsis:
//
// Arguments: [pnPriority] --
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::GetPriority(LONG *pnPriority)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::IBinding::GetPriority",
"this=%#x, %#x",
this, pnPriority
));
PerfDbgLog(tagCBinding, this, "+CBinding::GetPriority");
HRESULT hr = NOERROR;
if (!pnPriority)
{
hr = E_INVALIDARG;
}
else
{
*pnPriority = _nPriority;
}
PerfDbgLog1(tagCBinding, this, "-CBinding::GetPriority (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::GetBindResult
//
// Synopsis:
//
// Arguments: [pnPriority] --
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::GetBindResult(CLSID *pclsidProtocol, DWORD *pdwResult, LPWSTR *pszResult,DWORD *pdwReserved)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::IBinding::GetBindResult",
"this=%#x, %#x, %#x, %#x, %#x",
this, pclsidProtocol, pdwResult, pszResult, pdwReserved
));
PerfDbgLog(tagCBinding, this, "+CBinding::GetBindResult");
HRESULT hr = NOERROR;
if (!pdwResult || !pszResult || pdwReserved)
{
hr = E_INVALIDARG;
}
else
{
HRESULT hrRet = NOERROR;
*pdwResult = 0;
*pszResult = 0;
*pclsidProtocol = CLSID_NULL;
if ((hrRet = GetInstantiateHresult()) != NOERROR)
{
*pdwResult = (DWORD) hrRet;
TransAssert (( (_hrBindResult == INET_E_CANNOT_INSTANTIATE_OBJECT)
|| (_hrBindResult == INET_E_CANNOT_LOAD_DATA) ));
}
else if (_hrBindResult != NOERROR)
{
*pclsidProtocol = _clsidProtocol;
*pszResult = OLESTRDuplicate(_pwzResult);
UrlMkAssert(( (_dwBindError != 0) || (_hrBindResult != NOERROR) ));
if (_dwBindError == 0)
{
_dwBindError = _hrBindResult;
}
*pdwResult = _dwBindError;
}
}
PerfDbgLog3(tagCBinding, this, "-CBinding::GetBindResult (hr:%lx,_hrBindResult;%lx, pdwResult:%lx)", hr, _hrBindResult, *pdwResult);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::QueryOption
//
// Synopsis: Calls QueryOptions on
//
// Arguments: [dwOption] --
// [pBuffer] --
// [pcbBuf] --
//
// Returns:
//
// History: 4-10-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::QueryOption(DWORD dwOption, LPVOID pBuffer, DWORD *pcbBuf)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::IWinInetHttpInfo::QueryOption",
"this=%#x, %#x, %#x, %#x",
this, dwOption, pBuffer, pcbBuf
));
HRESULT hr = NOERROR;
PerfDbgLog(tagCBinding, this, "+CBinding::QueryOption");
VDATEPTROUT(pcbBuf, DWORD*);
if ( (GetOperationState() < OPS_Stopped)
&& (GetOperationState() > OPS_Initialized))
{
TransAssert((_fCanGetIWinInetInfo || _fCanGetIWinInetHttpInfo));
if (_fCanGetIWinInetInfo)
{
IWinInetInfo *pIWinInetInfo;
hr = _pOInetBdg->QueryInterface(IID_IWinInetInfo, (void **)&pIWinInetInfo);
if (S_FALSE == hr)
hr = E_NOINTERFACE;//see bug 99754
if (SUCCEEDED(hr))
{
hr = pIWinInetInfo->QueryOption(dwOption, pBuffer, pcbBuf);
//dont keep the reference..release it immdly.
pIWinInetInfo->Release();
}
}
else if (_fCanGetIWinInetHttpInfo)
{
IWinInetHttpInfo *pIWinInetHttpInfo;
hr = _pOInetBdg->QueryInterface(IID_IWinInetHttpInfo, (void **)&pIWinInetHttpInfo);
if (S_FALSE == hr)
hr = E_NOINTERFACE;//see bug 99754
if (SUCCEEDED(hr))
{
hr = pIWinInetHttpInfo->QueryOption(dwOption, pBuffer, pcbBuf);
//dont keep the reference..release it immdly.
pIWinInetHttpInfo->Release();
}
}
}
else
{
hr = E_FAIL;
}
PerfDbgLog1(tagCBinding, this, "-CBinding::QueryOption (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::QueryInfo
//
// Synopsis: Calls QueryInfos on
//
// Arguments: [dwOption] --
// [pBuffer] --
// [pcbBuf] --
// [pdwFlags] --
// [pdwReserved] --
//
// Returns:
//
// History: 4-10-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::QueryInfo(DWORD dwOption, LPVOID pBuffer, DWORD *pcbBuf, DWORD *pdwFlags, DWORD *pdwReserved)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::IWinInetHttpInfo::QueryInfo",
"this=%#x, %#x, %#x, %#x, %#x, %#x",
this, dwOption, pBuffer, pcbBuf, pdwFlags, pdwReserved
));
HRESULT hr = NOERROR;
PerfDbgLog(tagCBinding, this, "+CBinding::QueryInfo");
VDATEPTROUT(pcbBuf, DWORD*);
if ( (GetOperationState() < OPS_Stopped)
&& (GetOperationState() > OPS_Initialized))
{
TransAssert((_fCanGetIWinInetHttpInfo));
IWinInetHttpInfo *pIWinInetHttpInfo;
hr = _pOInetBdg->QueryInterface(IID_IWinInetHttpInfo, (void **)&pIWinInetHttpInfo);
if (S_FALSE == hr)
hr = E_NOINTERFACE;//see bug 99754
if (SUCCEEDED(hr))
{
hr = pIWinInetHttpInfo->QueryInfo(dwOption, pBuffer, pcbBuf, pdwFlags, pdwReserved);
//dont keep the reference..release it immdly.
pIWinInetHttpInfo->Release();
}
}
else
{
hr = E_FAIL;
}
PerfDbgLog1(tagCBinding, this, "-CBinding::QueryInfo (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
// IServiceProvider methods
//+---------------------------------------------------------------------------
//
// Method: CBinding::QueryService
//
// Synopsis: Calls QueryInfos on
//
// Arguments: [rsid] --
// [riid] --
// [ppvObj] --
//
// Returns:
//
// History: 4-10-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT IUnknown_QueryService(IUnknown* punk, REFGUID rsid, REFIID riid, void ** ppvObj)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"IUnknown_QueryService",
"%#x, %#x, %#x, %#x",
punk, &rsid, &riid, ppvObj
));
HRESULT hr = E_NOINTERFACE;
*ppvObj = 0;
if (punk)
{
IServiceProvider *pSrvPrv;
hr = punk->QueryInterface(IID_IServiceProvider, (void **) &pSrvPrv);
if (hr == NOERROR)
{
hr = pSrvPrv->QueryService(rsid,riid, ppvObj);
pSrvPrv->Release();
}
}
DEBUG_LEAVE(hr);
return hr;
}
HRESULT CBinding::QueryService(REFGUID rsid, REFIID riid, void ** ppvObj)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::IServiceProvider::QueryService",
"this=%#x, %#x, %#x, %#x",
this, &rsid, &riid, ppvObj
));
PerfDbgLog(tagCBinding, this, "+CBinding::QueryService");
HRESULT hr = E_NOINTERFACE;
VDATETHIS(this);
UrlMkAssert((ppvObj));
hr = IUnknown_QueryService(_pBSCB, rsid, riid, ppvObj);
PerfDbgLog1(tagCBinding, this, "-CBinding::QueryService (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//IOInetBindInfo methods
//+---------------------------------------------------------------------------
//
// Method: CBinding::GetBindInfo
//
// Synopsis:
//
// Arguments: [pdwBINDF] --
// [pbindinfo] --
//
// Returns:
//
// History: 11-07-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CBinding::GetBindInfo(DWORD *pdwBINDF, BINDINFO *pbindinfo)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::IInternetBindInfo::GetBindInfo",
"this=%#x, %#x, %#x",
this, pdwBINDF, pbindinfo
));
PerfDbgLog(tagCBinding, this, "+CBinding::GetBindInfo");
HRESULT hr = NOERROR;
TransAssert((pdwBINDF && pbindinfo));
*pdwBINDF = _grfBINDF;
hr = CopyBindInfo(&_BndInfo, pbindinfo ); // Src->Dest
//for IE6 bug 1898.
//For hglobals, copybindinfo allocates new handle and copies over the source data,
//but uses the source as pUnkForRelease and AddRefs it.. but the source has no reference
//to the new handle to free.
//So free the addrefed pUnkForRelease and NULL it, so that ReleaseStgMedium() calls
//GlobalFree().
//There is also a bug in ReleaseBindInfo(), where we always call ReleaseStgMedium(),
//irrespective of the pUnkForRelease member - this fix doesn't depend on that behavior,
//but it does need the receiver of the stgmed in this bindinfo to ReleaseStgMedium() either
//indirectly through ReleaseBindInfo() or directly.
if (SUCCEEDED(hr))
{
STGMEDIUM* pStgmed = &(pbindinfo->stgmedData);
if ( (pStgmed->tymed == TYMED_HGLOBAL) &&
(pStgmed->hGlobal) &&
(pStgmed->pUnkForRelease) )
{
pStgmed->pUnkForRelease->Release();
pStgmed->pUnkForRelease = NULL;
}
}
PerfDbgLog1(tagCBinding, this, "-CBinding::GetBindInfo (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::GetBindString
//
// Synopsis:
//
// Arguments: [ulStringType] --
// [ppwzStr] --
// [cEl] --
// [pcElFetched] --
//
// Returns:
//
// History: 11-07-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CBinding::GetBindString(ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::IInternetBindInfo::GetBindString",
"this=%#x, %#x, %#x, %#x, %#x",
this, ulStringType, ppwzStr, cEl, pcElFetched
));
PerfDbgLog(tagCBinding, this, "+CTransaction::GetBindString");
HRESULT hr = INET_E_USE_DEFAULT_SETTING;
switch (ulStringType)
{
case BINDSTRING_HEADERS :
break;
case BINDSTRING_ACCEPT_MIMES:
hr = _pCTransData->GetAcceptMimes(ppwzStr,cEl, pcElFetched);
break;
case BINDSTRING_EXTRA_URL :
break;
case BINDSTRING_LANGUAGE :
break;
case BINDSTRING_USERNAME :
break;
case BINDSTRING_PASSWORD :
break;
case BINDSTRING_ACCEPT_ENCODINGS:
break;
case BINDSTRING_URL:
if( _lpwszUrl )
{
LPWSTR pwzURL = NULL;
pwzURL = OLESTRDuplicate(_lpwszUrl);
if( pwzURL )
{
*ppwzStr = pwzURL,
*pcElFetched = 1;
hr = NOERROR;
}
else
{
hr = E_OUTOFMEMORY;
*pcElFetched = 0;
}
}
break;
case BINDSTRING_USER_AGENT :
case BINDSTRING_POST_COOKIE :
case BINDSTRING_POST_DATA_MIME:
{
hr = NOERROR;
// QI on IBSC for interface
if (_pBindInfo == NULL)
{
hr = LocalQueryInterface(IID_IInternetBindInfo, (void **)&_pBindInfo);
}
if ( (hr == NOERROR) && _pBindInfo)
{
hr = _pBindInfo->GetBindString(ulStringType, ppwzStr, cEl, pcElFetched);
}
}
break;
case BINDSTRING_IID:
TransAssert(_piidRes);
if (_piidRes)
{
hr = StringFromCLSID(*_piidRes, ppwzStr);
if (pcElFetched)
{
*pcElFetched = (SUCCEEDED(hr)) ? (1) : (0);
}
}
else
{
hr = E_UNEXPECTED;
*pcElFetched = 0;
}
break;
case BINDSTRING_FLAG_BIND_TO_OBJECT:
*ppwzStr = new WCHAR[FLAG_BTO_STR_LENGTH];
if (*ppwzStr)
{
if (_fBindToObject)
{
StrCpyNW(*ppwzStr, FLAG_BTO_STR_TRUE,
lstrlenW(FLAG_BTO_STR_TRUE) + 1);
}
else
{
StrCpyNW(*ppwzStr, FLAG_BTO_STR_FALSE,
lstrlenW(FLAG_BTO_STR_FALSE) + 1);
}
*pcElFetched = 1;
hr = S_OK;
}
else
{
*pcElFetched = 0;
hr = E_OUTOFMEMORY;
}
break;
case BINDSTRING_PTR_BIND_CONTEXT:
if (!_pBndCtx) {
hr = E_UNEXPECTED;
*pcElFetched = 0;
}
else {
*ppwzStr = new WCHAR[MAX_DWORD_DIGITS + 1];
if (*ppwzStr)
{
wnsprintfW(*ppwzStr, MAX_DWORD_DIGITS,
#ifdef _WIN64
L"%I64d",
#else
L"%ld",
#endif
(DWORD_PTR)_pBndCtx);
*pcElFetched = 1;
_pBndCtx->AddRef();
hr = S_OK;
}
else
{
*pcElFetched = 0;
hr = E_OUTOFMEMORY;
}
}
break;
default:
TransAssert((FALSE));
}
PerfDbgLog1(tagCBinding, this, "-CBinding::GetBindString (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBindProtocol::CBindProtocol
//
// Synopsis:
//
// Arguments: [pUnk] --
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
CBindProtocol::CBindProtocol() : _CRefs()
{
DEBUG_ENTER((DBG_BINDING,
None,
"CBindProtocol::CBindProtocol",
"this=%#x",
this
));
_pUnk = NULL;
DEBUG_LEAVE(0);
}
//+---------------------------------------------------------------------------
//
// Method: CBindProtocol::~CBindProtocol
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
CBindProtocol::~CBindProtocol()
{
DEBUG_ENTER((DBG_BINDING,
None,
"CBindProtocol::~CBindProtocol",
"this=%#x",
this
));
DEBUG_LEAVE(0);
}
//+---------------------------------------------------------------------------
//
// Method: CBindProtocol::QueryInterface
//
// Synopsis:
//
// Arguments: [riid] --
// [ppv] --
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBindProtocol::QueryInterface( REFIID riid, void **ppv )
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBindProtocol::IUnknown::QueryInterface",
"this=%#x, %#x, %#x",
this, &riid, ppv
));
HRESULT hr = NOERROR;
PerfDbgLog2(tagCBinding, this, "+CBindProtocol::QueryInterface (%lx, %lx)", riid, ppv);
if ( IsEqualIID(riid, IID_IUnknown)
|| IsEqualIID(riid, IID_IBindProtocol) )
{
*ppv = (void FAR *)this;
AddRef();
}
else
{
*ppv = NULL;
hr = E_NOINTERFACE;
#if DBG==1
//LPSTR lpszName = GetInterfaceName(riid);
//DbgLog3(tagCBinding, this, "CBindProtocol::QI(pUnkObj) >%s< hr:%lx [%lx]", lpszName, hr, *ppv);
#endif // DBG==1
}
PerfDbgLog2(tagCBinding, this, "-CBindProtocol::QueryInterface (%lx)[%lx]", hr, *ppv);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBindProtocol::AddRef
//
// Synopsis:
//
// Arguments: [void] --
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CBindProtocol::AddRef( void )
{
DEBUG_ENTER((DBG_BINDING,
Dword,
"CBindProtocol::IUnknown::AddRef",
"this=%#x",
this
));
LONG lRet = _CRefs++;
PerfDbgLog1(tagCBinding, this, "CBindProtocol::AddRef (%ld)", lRet);
DEBUG_LEAVE(lRet);
return lRet;
}
//+---------------------------------------------------------------------------
//
// Method: CBindProtocol::Release
//
// Synopsis:
//
// Arguments: [void] --
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CBindProtocol::Release( void )
{
DEBUG_ENTER((DBG_BINDING,
Dword,
"CBindProtocol::IUnknown::Release",
"this=%#x",
this
));
PerfDbgLog(tagCBinding, this, "+CBindProtocol::Release");
LONG lRet = --_CRefs;
if (_CRefs == 0)
{
if (_pUnk)
{
PerfDbgLog(tagCBinding, this, "+CBindProtocol::Release _pUnk");
_pUnk->Release();
_pUnk = NULL;
PerfDbgLog(tagCBinding, this, "-CBindProtocol::Release _pUnk");
}
delete this;
}
PerfDbgLog1(tagCBinding, this, "-CBindProtocol::Release (%ld)", lRet);
DEBUG_LEAVE(lRet);
return lRet;
}
//+---------------------------------------------------------------------------
//
// Method: CBindProtocol::CreateBinding
//
// Synopsis:
//
// Arguments: [url] --
// [pBCtx] --
// [ppBdg] --
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBindProtocol::CreateBinding(LPCWSTR szUrl, IBindCtx *pBCtx, IBinding **ppBdg)
{
DEBUG_ENTER((DBG_BINDING,
Dword,
"CBindProtocol::IBindProtocol::CreateBinding",
"this=%#x, %.80wq, %#x, %#x",
this, szUrl, pBCtx, ppBdg
));
PerfDbgLog(tagCBinding, this, "+CBindProtocol::CreateBinding");
HRESULT hr = NOERROR;
BIND_OPTS bindopts;
CBinding *pCBdg = NULL;
VDATEPTROUT(ppBdg, LPVOID);
VDATEIFACE(pBCtx);
*ppBdg = NULL;
// Get the bind options from the bind context
bindopts.cbStruct = sizeof(BIND_OPTS);
hr = pBCtx->GetBindOptions(&bindopts);
ChkHResult(hr);
hr = CBinding::Create(NULL, szUrl, pBCtx, IID_IStream, FALSE, &pCBdg );
if (hr != NOERROR)
{
DEBUG_LEAVE(hr);
return hr;
}
// Start the download transaction
{
LPWSTR pwzExtra = NULL;
hr = pCBdg->StartBinding(szUrl, pBCtx, IID_IStream, FALSE, &pwzExtra, NULL);
}
if (FAILED(hr))
{
// the transaction could not be started
goto End;
}
// if the caller doesn't support IBindStatusCallback
if ( pCBdg->IsAsyncBinding() )
{
// Async case: interface is passed on in OnDataAvailable
*ppBdg = pCBdg;
}
End:
if (pCBdg)
{
pCBdg->Release();
}
PerfDbgLog1(tagCBinding, this, "-CBindProtocol::CreateBinding (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: GetObjectParam
//
// Synopsis:
//
// Arguments: [pbc] --
// [pszKey] --
// [riid] --
// [ppUnk] --
//
// Returns:
//
// History: 12-04-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT GetObjectParam(IBindCtx *pbc, LPOLESTR pszKey, REFIID riid, IUnknown **ppUnk)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"GetObjectParam",
"%#x, %#x, %#x, %#x",
pbc, pszKey, &riid, ppUnk
));
PerfDbgLog1(tagCBinding, NULL, "+GetObjectParam (IBindCtx:%lx)", pbc);
HRESULT hr = E_FAIL;
IUnknown *pUnk;
// Try to get an IUnknown pointer from the bind context
if (pbc)
{
hr = pbc->GetObjectParam(pszKey, &pUnk);
}
if (FAILED(hr))
{
*ppUnk = NULL;
}
else
{
// Query for riid
hr = pUnk->QueryInterface(riid, (void **)ppUnk);
pUnk->Release();
if (FAILED(hr))
{
*ppUnk = NULL;
DumpIID(riid);
}
}
PerfDbgLog2(tagCBinding, NULL, "-GetObjectParam (IBindCtx:%lx, hr:%lx)", pbc, hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::StartBinding
//
// Synopsis:
//
// Arguments: [fBindToObject] --
//
// Returns:
//
// History: 12-04-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CBinding::StartBinding(LPCWSTR szUrl, IBindCtx *pbc, REFIID riid, BOOL fBindToObject, LPWSTR *ppwzExtra, LPVOID *ppv )
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::StartBinding",
"this=%#x, %.80wq, %#x, %#x, %B, %#x, %#x",
this, szUrl, pbc, &riid, fBindToObject, ppwzExtra, ppv
));
PerfDbgLog(tagCBinding, this, "+CBinding::StartTransaction");
//DbgLog1(tagCBindingErr, this, ">>> CBinding::Start(url=%ws)", szUrl);
HRESULT hr;
BOOL fBindingStarted = FALSE;
UrlMkAssert((ppwzExtra));
UrlMkAssert((_pBSCB == NULL));
do
{
// Try to get an IBindStatusCallback pointer from the bind context
hr = GetObjectParam(pbc, REG_BSCB_HOLDER, IID_IBindStatusCallback, (IUnknown**)&_pBSCB);
if (FAILED(hr))
{
break;
}
UrlMkAssert(( (hr == NOERROR) && _pBSCB ));
if (_pBSCB == NULL)
{
hr = E_INVALIDARG;
break;
}
_fBindToObject = fBindToObject;
if (_fBindToObject)
{
_grfInternalFlags |= BDGFLAGS_PARTIAL;
_piidRes = (IID *) &riid;
// Get the bind options from the bind context
_bindopts.cbStruct = sizeof(BIND_OPTS);
hr = pbc->GetBindOptions(&_bindopts);
if (FAILED(hr))
{
break;
}
}
hr = CBindCtx::Create(&_pBndCtx, pbc);
if (FAILED(hr))
{
hr = E_OUTOFMEMORY;
break;
}
{
int cchWideChar;
cchWideChar = wcslen(szUrl) + 2;
_lpwszUrl = (LPWSTR) new WCHAR [cchWideChar];
if( !_lpwszUrl )
{
hr = E_OUTOFMEMORY;
break;
}
wcscpy(_lpwszUrl, szUrl);
}
// call GetBindInfo
_BndInfo.cbSize = sizeof(BINDINFO);
#if DBG==1
if (_BndInfo.stgmedData.tymed != TYMED_NULL)
{
PerfDbgLog1(tagCBinding, this, "CBinding::StartTransaction ReleaseStgMedium (%lx)", _BndInfo.stgmedData);
}
#endif // DBG==1
// Make sure the BINDINFO is released and empty
ReleaseBindInfo(&_BndInfo);
_grfBINDF = 0;
// call IBSC::GetBindInfo
TransAssert((_BndInfo.stgmedData.tymed == TYMED_NULL));
hr = CallGetBindInfo(&_grfBINDF, &_BndInfo);
if( hr == NOERROR && !IsAsyncTransaction() )
{
// we need to turn off BINDF_ASYNCSTORAGE for sync binding
_grfBINDF &= ~BINDF_ASYNCSTORAGE;
}
// this call should not fail
if (FAILED(hr))
{
break;
}
// turn on direct read - not documented yet for APPs
if (g_dwSettings & 0x20000000)
{
_grfBINDF |= BINDF_DIRECT_READ;
}
// check for extend binding (rosebud)
// get the bind option for extend binding (low bits)
// the highest 16 bits is used for additional flags (e.g. wininet flag)
DWORD dwExtBindOption = _BndInfo.dwOptions & 0x0000ffff;
if( dwExtBindOption && !fBindToObject)
{
// extend binding (rosebud)
COInetSession* pSession = NULL;
IOInetProtocol* pProt = NULL;
hr = GetCOInetSession(0, &pSession, 0);
if( hr != NOERROR )
{
break;
}
CLSID clsid = CLSID_NULL;
DWORD dwLocation = 0;
hr = pSession->CreateFirstProtocol(
_lpwszUrl, NULL, NULL, &pProt, &clsid, &dwLocation, dwExtBindOption);
pSession->Release();
if( hr != NOERROR )
{
break;
}
StartParam param;
param.iid = riid;
param.pIBindCtx = pbc;
param.pItf = NULL;
// the interface ptr is returned via param.pItf
hr = pProt->Start(_lpwszUrl, NULL, NULL, 0, (DWORD_PTR) &param );
// release the pluggable protocol
pProt->Release();
if( hr == NOERROR && param.pItf )
{
// we are done, return the pointer
*ppv = param.pItf;
hr = INET_E_USE_EXTEND_BINDING;
break;
}
else
if( hr != INET_E_USE_DEFAULT_PROTOCOLHANDLER )
{
break;
}
// continue with the normal binding process...
}
{
// check for iid (only for BindToStorage)
if( !fBindToObject && (IsRequestedIIDValid(riid) == FALSE) )
{
hr = E_INVALIDARG;
break;
}
if (!IsOInetProtocol(pbc, szUrl))
{
hr = INET_E_UNKNOWN_PROTOCOL;
break;
}
DWORD dwObjectsFlags = OIBDG_APARTMENTTHREADED;
if (_fBindToObject)
{
dwObjectsFlags |= BDGFLAGS_PARTIAL;
}
hr = GetTransactionObjects(_pBndCtx, _lpwszUrl, NULL, NULL, &_pOInetBdg, dwObjectsFlags, &_pCTransData);
}
if (hr == S_OK)
{
TransAssert((!_pCTransData));
// create the transaction data object
// Note: the transdat object has a refcount
// and must be released when done
hr = CTransData::Create(_lpwszUrl, _grfBINDF, riid, _pBndCtx, _fBindToObject, &_pCTransData);
if (SUCCEEDED(hr))
{
UrlMkAssert((_pCTransData != NULL && "CTransData invalid"));
_pBndCtx->SetTransData(_pCTransData);
}
}
else if (hr == S_FALSE)
{
// found an existing transaction
UrlMkAssert((_pCTransData != NULL && "CTransData invalid"));
if (fBindToObject)
_grfInternalFlags |= BDGFLAGS_BTS_BTO;
else
_grfInternalFlags |= BDGFLAGS_ATTACHED;
hr = _pCTransData->Initialize(_lpwszUrl, _grfBINDF, riid, _pBndCtx, fBindToObject);
}
else
{
hr = E_OUTOFMEMORY;
}
if (FAILED(hr))
{
break;
}
// hand back to pointer to of extra info
// to update the url
*ppwzExtra = (_BndInfo.szExtraInfo) ? _BndInfo.szExtraInfo : NULL;
if (_pCTransData->SetDataSink(_grfBINDF) == DataSink_Unknown)
{
hr = E_INVALIDARG;
}
if ( (_pCTransData->IsFileRequired())
|| (IsKnownProtocol(_lpwszUrl) == DLD_PROTOCOL_NONE) )
{
PerfDbgLog(tagCBinding, this, "---TURN ON NEEDFILE!---");
// turn on flag to request file from protocol
_grfBINDF |= BINDF_NEEDFILE;
}
if (SUCCEEDED(hr))
{
PerfDbgLog(tagCBinding, this, "---BINDF_FROMURLMON---");
// turn on flag indicating the binding is from urlmon
_grfBINDF |= BINDF_FROMURLMON;
if( _fBindToObject )
{
_BndInfo.dwOptions |= BINDINFO_OPTIONS_BINDTOOBJECT;
}
}
if (FAILED(hr))
{
break;
}
// send the OnStartBinding notification
hr = CallOnStartBinding(NULL, this);
fBindingStarted = TRUE;
// check if the user did abort
if (SUCCEEDED(hr))
{
OperationState opSt = GetOperationState();
UrlMkAssert((opSt > OPS_Initialized));
if (opSt == OPS_Abort)
{
hr = E_ABORT;
}
}
BOOL fIsSync = (IsAsyncTransaction() == FALSE);
if ( SUCCEEDED(hr))
{
// Note: check if url got redirected
// and report redirection url
if (_pwzRedirectUrl)
{
PerfDbgLog1(tagCBinding, this, "StartTransaction OnProgress REDIRECTING _pBSCP(%lx)", _pBSCB);
hr = CallOnProgress( 0, 0, BINDSTATUS_REDIRECTING,_pwzRedirectUrl );
PerfDbgLog1(tagCBinding, this, "StartTransaction OnProgress REDIRECTING _pBSCP(%lx)", _pBSCB);
}
}
if ( SUCCEEDED(hr))
{
DWORD dwBindFlags = OIBDG_APARTMENTTHREADED | PI_MIMEVERIFICATION | PI_DOCFILECLSIDLOOKUP;
if (fIsSync)
{
dwBindFlags |= PI_SYNCHRONOUS;
}
if(_grfBINDF & BINDF_PREFERDEFAULTHANDLER)
{
dwBindFlags |= BINDF_PREFERDEFAULTHANDLER;
}
if (_grfBINDF & BINDF_FREE_THREADED)
{
dwBindFlags &= ~OIBDG_APARTMENTTHREADED;
}
if (_fBindToObject)
{
dwBindFlags |= BDGFLAGS_PARTIAL | PI_CLASSINSTALL;
}
if (_grfInternalFlags & BDGFLAGS_BTS_BTO)
{
dwBindFlags |= BDGFLAGS_BTS_BTO;
}
if (_grfInternalFlags & BDGFLAGS_ATTACHED)
{
dwBindFlags |= BDGFLAGS_ATTACHED;
}
if (_pOInetBdg)
{
// Just before starting the transaction give it the priority.
IOInetPriority * pOInetPriority = NULL;
if (_pOInetBdg->QueryInterface(IID_IOInetPriority, (void **) &pOInetPriority) == S_OK)
{
pOInetPriority->SetPriority(_nPriority);
pOInetPriority->Release();
}
}
if ( _pCTransData->InProgress() != S_FALSE
|| !_pCTransData->IsRemoteObjectReady() )
{
// guard the transaction object
// the operation might complete synchronous
_pOInetBdg->AddRef();
hr = _pCTransData->OnStart(_pOInetBdg);
TransAssert((hr == NOERROR));
if (hr == NOERROR)
{
hr = _pOInetBdg->Start(_lpwszUrl, (IOInetProtocolSink *) this, (IOInetBindInfo *) this, dwBindFlags, 0);
}
_pOInetBdg->Release();
}
else
{
// call OnProgress for mime type and filename
//
DWORD dwSize = _pCTransData->GetDataSize();
if (_pCTransData->GetMimeType())
{
OnTransNotification(BINDSTATUS_MIMETYPEAVAILABLE, dwSize, dwSize, (LPWSTR)_pCTransData->GetMimeType(), NOERROR);
}
if (_pCTransData->GetFileName())
{
OnTransNotification(BINDSTATUS_CACHEFILENAMEAVAILABLE, dwSize, dwSize, _pCTransData->GetFileName(), NOERROR );
}
// report data - will call OnStopBinding
OnTransNotification(BINDSTATUS_ENDDOWNLOADDATA, dwSize, dwSize,0 , NOERROR);
}
}
break;
} while (TRUE);
if ( FAILED(hr))
{
// call OnStopBinding in case of error
HRESULT hr1 = NOERROR;
if ((_pBSCB != NULL) && fBindingStarted)
{
_hrBindResult = hr;
hr1 = CallOnStopBinding(hr, NULL);
}
if (_pOInetBdg)
{
_pOInetBdg->Terminate(0);
_pOInetBdg->Release();
_pOInetBdg = NULL;
}
}
PerfDbgLog(tagCBinding, this, "-CBinding::StartTransaction");
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::CompleteTransaction
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 12-22-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::CompleteTransaction()
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::CompleteTransaction",
"this=%#x",
this
));
HRESULT hr = NOERROR;
PerfDbgLog(tagCBinding, this, "+CBinding::CompleteTransaction");
if (_hrBindResult != NOERROR)
{
hr = _hrBindResult;
}
PerfDbgLog1(tagCBinding, this, "-CBinding::CompleteTransaction (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::OnTransNotification
//
// Synopsis:
//
// Arguments: [pCTP] --
//
// Returns:
//
// History: 12-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP_(BOOL) CBinding::OnTransNotification(BINDSTATUS NotMsg, DWORD dwCurrentSize, DWORD dwTotalSize,
LPWSTR pwzStr, HRESULT hrINet)
{
DEBUG_ENTER((DBG_BINDING,
Bool,
"CBinding::OnTransNotification",
"this=%#x, %#x, %#x, %#x, %.80wq, %#x",
this, NotMsg, dwCurrentSize, dwTotalSize, pwzStr, hrINet
));
PerfDbgLog(tagCBinding, this, "+CBinding::OnTransNotification");
BOOL fRelease = FALSE;
HRESULT hr = NOERROR;
UrlMkAssert((_dwThreadId));
if ( ( (_dwThreadId == GetCurrentThreadId())
|| (_grfBINDF & BINDF_FREE_THREADED))
&& (_grfInternalFlags & BDGFLAGS_NOTIFICATIONS)
&& (_pBSCB != NULL))
{
switch (NotMsg)
{
case BINDSTATUS_PROTOCOLCLASSID:
UrlMkAssert((pwzStr));
CLSIDFromString(pwzStr, &_clsidProtocol);
break;
case BINDSTATUS_MIMETYPEAVAILABLE:
UrlMkAssert((pwzStr));
_pCTransData->SetMimeType(pwzStr);
CallOnProgress(0,0,BINDSTATUS_MIMETYPEAVAILABLE, pwzStr);
break;
case BINDSTATUS_CLASSIDAVAILABLE:
UrlMkAssert((pwzStr));
CLSIDFromString(pwzStr, &_clsidIn);
break;
case BINDSTATUS_IUNKNOWNAVAILABLE:
if( _fBindToObject )
{
IUnknown *pUnk = NULL;
_fClsidFromProt = TRUE;
// the object should be instantiated now
if (SUCCEEDED(hr))
{
hr = _pBndCtx->GetObjectParam(SZ_IUNKNOWN_PTR, &pUnk);
}
if (SUCCEEDED(hr))
{
// The following four lines of code are a fix for bug#89397.
// There are only a couple of clients who are already using
// this notification, so we can ensure this state change doesn't
// affect their protocols.
OperationState opSt = GetOperationState();
if (opSt >= OPS_StartBinding && opSt < OPS_Downloading)
{
SetOperationState(OPS_Downloading);
}
hr = CallOnObjectAvailable(*_piidRes, pUnk);
pUnk->Release();
}
if (hr != NOERROR)
{
SetInstantiateHresult(hr);
}
// return the download result in case if no error
if (hr == NOERROR || GetHResult() != NOERROR)
{
hr = GetHResult();
}
_hrBindResult = hr;
hr = CallOnStopBinding(hr, NULL);
fRelease = TRUE;
}
break;
case BINDSTATUS_CLSIDCANINSTANTIATE:
if(IsEqualGUID(_clsidIn, CLSID_NULL) && pwzStr)
{
CLSIDFromString(pwzStr, &_clsidIn);
}
if( _fBindToObject )
{
_fClsidFromProt = TRUE;
// the object should be instantiated now
hr = OnObjectAvailable(0,dwCurrentSize,dwTotalSize,TRUE);
if (hr != NOERROR)
{
SetInstantiateHresult(hr);
}
// return the download result in case if no error
if (hr == NOERROR || GetHResult() != NOERROR)
{
hr = GetHResult();
}
_hrBindResult = hr;
hr = CallOnStopBinding(hr, NULL);
fRelease = TRUE;
}
break;
case BINDSTATUS_PROXYDETECTING :
// indicate resolving proxyserver
if (hrINet == NOERROR)
{
hr = CallOnProgress(0,0,BINDSTATUS_PROXYDETECTING,NULL );
}
break;
case BINDSTATUS_CACHEFILENAMEAVAILABLE :
UrlMkAssert((pwzStr));
_pCTransData->SetFileName(pwzStr);
break;
case BINDSTATUS_FINDINGRESOURCE :
// indicate resolving name - pass on server/proxy name
if (hrINet == NOERROR)
{
hr = CallOnProgress(0,0,BINDSTATUS_FINDINGRESOURCE,pwzStr );
PerfDbgLog1(tagCBinding, this, "OnTransNotification done on OnProgress _pBSCP(%lx)", _pBSCB);
}
break;
case BINDSTATUS_SENDINGREQUEST :
// indicate resolving name - pass on server/proxy name
if (hrINet == NOERROR)
{
hr = CallOnProgress(0,0,BINDSTATUS_SENDINGREQUEST,pwzStr );
PerfDbgLog1(tagCBinding, this, "OnTransNotification done on OnProgress _pBSCP(%lx)", _pBSCB);
}
break;
case BINDSTATUS_CONNECTING :
// inidicate progress connecting - pass on address
if (hrINet == NOERROR)
{
hr = CallOnProgress(0,0,BINDSTATUS_CONNECTING, pwzStr);
PerfDbgLog1(tagCBinding, this, "OnTransNotification done on OnProgress _pBSCP(%lx)", _pBSCB);
}
break;
case BINDSTATUS_REDIRECTING :
if (hrINet == NOERROR)
{
TransAssert((pwzStr));
PerfDbgLog1(tagCBinding, this, "OnTransNotification calling OnProgress _pBSCP(%lx)", _pBSCB);
hr = CallOnProgress(
dwCurrentSize, // ulProgress
dwTotalSize, // ulProgressMax
BINDSTATUS_REDIRECTING,
pwzStr // new url
);
PerfDbgLog1(tagCBinding, this, "OnTransNotification done on OnProgress _pBSCP(%lx)", _pBSCB);
TransAssert((_lpwszUrl));
{
DWORD dwLenOld = wcslen(_lpwszUrl);
DWORD dwLenNew = wcslen(pwzStr);
if (dwLenOld < dwLenNew)
{
delete _lpwszUrl;
_lpwszUrl = (LPWSTR) new WCHAR [dwLenNew + 1];
}
if (_lpwszUrl && pwzStr)
{
wcscpy(_lpwszUrl, pwzStr);
}
}
_pCTransData->SetRedirectUrl(pwzStr);
}
break;
case BINDSTATUS_ENDDOWNLOADDATA:
PerfDbgLog(tagCBinding, this, "CBinding::OnTransNotification Notify_Done");
// more work here for data notification
//UrlMkAssert((errCode == INLERR_OK && "Notify_Done with Error"));
if (hrINet == NOERROR)
{
PerfDbgLog1(tagCBinding, this, "OnTransNotification calling OnProgress _pBSCP(%lx)", _pBSCB);
if (!_fSentFirstNotification)
{
hr = CallOnProgress(dwCurrentSize, dwTotalSize,
BINDSTATUS_BEGINDOWNLOADDATA, _lpwszUrl);
LPCWSTR pwzFilename = _pCTransData->GetFileName();
// a filename is not always available
if (pwzFilename)
{
hr = CallOnProgress(dwCurrentSize, dwTotalSize,
BINDSTATUS_CACHEFILENAMEAVAILABLE, pwzFilename);
}
}
hr = CallOnProgress(dwCurrentSize,dwTotalSize,
BINDSTATUS_ENDDOWNLOADDATA,_lpwszUrl);
PerfDbgLog1(tagCBinding, this, "OnTransNotification done on OnProgress _pBSCP(%lx)", _pBSCB);
// In some cases (e.g. data is in cache or progress notifications
// are disbled) we may not get progress notifications
// We might directly get the DONE notitification
// In anycase we do not want to send data notification if it is a
if (!_fBindToObject)
{
hr = OnDataNotification(0,dwCurrentSize,dwTotalSize, TRUE);
}
else
{
// the object should be instanciate now
hr = OnObjectAvailable(0,dwCurrentSize,dwTotalSize,TRUE);
if (hr != NOERROR)
{
SetInstantiateHresult(hr);
}
}
}
if (_fBTS_BTO)
{
//special Trident BTS->BTO scenario.
//Trident needs to get back the INET_E_TERMINATED_BIND error message to
//realize we understand this is where we don't double-bind
hr = INET_E_TERMINATED_BIND;
}
// return the download result in case if no error
else if (hr == NOERROR || GetHResult() != NOERROR)
{
hr = GetHResult();
}
PerfDbgLog2(tagCBinding, this, "OnTransNotification calling OnStopBinding _pBSCP(%lx) HR:%lx", _pBSCB, hr);
_hrBindResult = hr;
hr = CallOnStopBinding(hr, NULL);
fRelease = TRUE;
PerfDbgLog1(tagCBinding, this, "OnTransNotification done on OnStopBinding _pBSCP(%lx)", _pBSCB);
break;
case BINDSTATUS_BEGINDOWNLOADDATA:
case BINDSTATUS_DOWNLOADINGDATA:
PerfDbgLog(tagCBinding, this, "CBinding::OnTransNotification Notify_Update");
// Call OnProgress once if data are from cache
if (!_fSentFirstNotification)
{
if (_pCTransData->IsFromCache())
{
hr = CallOnProgress(0,0,BINDSTATUS_USINGCACHEDCOPY, NULL);
}
}
hr = CallOnProgress(dwCurrentSize, dwTotalSize,
(!_fSentFirstNotification) ? BINDSTATUS_BEGINDOWNLOADDATA : BINDSTATUS_DOWNLOADINGDATA,
_lpwszUrl);
if (!_fSentFirstNotification)
{
LPCWSTR pwzFilename = _pCTransData->GetFileName();
// a filename is not always available
if (pwzFilename)
{
hr = CallOnProgress(dwCurrentSize, dwTotalSize,
BINDSTATUS_CACHEFILENAMEAVAILABLE, pwzFilename);
}
}
PerfDbgLog1(tagCBinding, this, "OnTransNotification done on OnProgress _pBSCP(%lx)", _pBSCB);
if (!_fBindToObject)
{
OnDataNotification(0,dwCurrentSize,dwTotalSize, FALSE);
if (_fBTS_BTO)
{
//special Trident BTS->BTO scenario.
//Trident needs to get back the INET_E_TERMINATED_BIND error message to
//realize we understand this is where we don't double-bind
_hrBindResult = INET_E_TERMINATED_BIND;
hr = CallOnStopBinding(INET_E_TERMINATED_BIND, NULL);
fRelease = TRUE;
}
}
else
{
//
// here is the hack for ms-its:
// if they are sending dwCurrent==dwTotal, we need to flip
// the FALSE to TRUE in order to make word/excel doc host
// working under IE5 (IE5 #71203)
//
BOOL fFullData = FALSE;
if( dwCurrentSize == dwTotalSize &&
dwCurrentSize &&
_lpwszUrl &&
wcslen(_lpwszUrl) > 7 &&
!StrCmpNIW(_lpwszUrl, L"ms-its:", 7) )
{
fFullData = TRUE;
}
// check here if the object can be create already
//hr = OnObjectAvailable(pCTP, FALSE);
hr = OnObjectAvailable(0,dwCurrentSize,dwTotalSize, fFullData);
// mark the transobject for completion
if (hr == S_OK)
{
hr = CallOnStopBinding(NOERROR, NULL);
fRelease = TRUE;
}
else if ((hr != S_OK ) && (hr != S_FALSE))
{
_hrBindResult = hr;
hr = CallOnStopBinding(hr, NULL);
fRelease = TRUE;
}
}
break;
case BINDSTATUS_ERROR:
PerfDbgLog2(tagCBinding, this, "CBinding::OnTransNotification Notify_Error[hr%lx, dwResutl;%lx]", _hrBindResult, _dwBindError);
// call StopBinding witht error code
UrlMkAssert(( (_hrBindResult != NOERROR) && (_dwBindError != 0) ));
hr = CallOnStopBinding(_hrBindResult, NULL);
fRelease = TRUE;
break;
case BINDSTATUS_RESULT:
PerfDbgLog2(tagCBinding, this, "CBinding::OnTransNotification Notify_Error[hr%lx, dwResutl;%lx]", _hrBindResult, _dwBindError);
if( _hrBindResult == INET_E_REDIRECT_TO_DIR )
{
hr = CallOnStopBinding(_hrBindResult, _pwzResult);
}
else
{
hr = CallOnStopBinding(_hrBindResult, NULL);
}
fRelease = TRUE;
break;
case BINDSTATUS_DECODING:
hr = CallOnProgress(0,0,BINDSTATUS_DECODING,pwzStr );
break;
case BINDSTATUS_LOADINGMIMEHANDLER:
hr = CallOnProgress(0,0,BINDSTATUS_LOADINGMIMEHANDLER,pwzStr);
break;
case BINDSTATUS_INTERNAL:
case BINDSTATUS_INTERNALASYNC:
break;
case BINDSTATUS_CONTENTDISPOSITIONATTACH:
_fForceBindToObjFail = TRUE;
hr = CallOnProgress(0,0,BINDSTATUS_CONTENTDISPOSITIONATTACH, pwzStr);
break;
case BINDSTATUS_ACCEPTRANGES:
_fAcceptRanges= TRUE;
break;
case BINDSTATUS_COOKIE_SENT:
case BINDSTATUS_COMPACT_POLICY_RECEIVED:
case BINDSTATUS_COOKIE_SUPPRESSED:
case BINDSTATUS_COOKIE_STATE_UNKNOWN:
case BINDSTATUS_COOKIE_STATE_ACCEPT:
case BINDSTATUS_COOKIE_STATE_REJECT:
case BINDSTATUS_COOKIE_STATE_LEASH:
case BINDSTATUS_COOKIE_STATE_DOWNGRADE:
case BINDSTATUS_COOKIE_STATE_PROMPT:
case BINDSTATUS_POLICY_HREF:
case BINDSTATUS_P3P_HEADER:
case BINDSTATUS_SESSION_COOKIE_RECEIVED:
case BINDSTATUS_PERSISTENT_COOKIE_RECEIVED:
case BINDSTATUS_SESSION_COOKIES_ALLOWED:
hr = CallOnProgress(0,0,NotMsg, pwzStr);
break;
default:
DbgLog1(tagCBindingErr, this, "CBinding::OnTransNotification Unknown (NMsg:%lx)", NotMsg);
UrlMkAssert((FALSE));
break;
}
}
PerfDbgLog(tagCBinding, this, "-CBinding::OnTransNotification");
DEBUG_LEAVE(fRelease);
return fRelease;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::OnDataNotification
//
// Synopsis:
//
// Arguments: [pCTP] --
// [fLastNotification] --
//
// Returns:
//
// History: 12-22-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::OnDataNotification(DWORD grfBSCF, DWORD dwCurrentSize, DWORD dwTotalSize, BOOL fLastNotification)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::OnDataNotification",
"this=%#x, %#x, %#x, %#x, %B",
this, grfBSCF, dwCurrentSize, dwTotalSize, fLastNotification
));
HRESULT hr = NOERROR;
PerfDbgLog3(tagCBinding, this, "+CBinding::OnDataNotification (dwLastSize:%ld, dwCurrentSize:%ld, dwTotalSize:%ld)",
_dwLastSize, dwCurrentSize, dwTotalSize);
STGMEDIUM *pStgMed = 0;
FORMATETC *pFmtETC = 0;
// We shouldn't have less data than last time
#if 0
UrlMkAssert(( (dwTotalSize == 0)
|| (dwTotalSize != 0 && dwCurrentSize > _dwLastSize)
|| (dwTotalSize == dwCurrentSize && dwCurrentSize == _dwLastSize)
));
#endif // 0
// must be BindToStorage scenario
UrlMkAssert((!_fBindToObject));
// should never end up here after the last data notification
//UrlMkAssert((!_fSentLastNotification));
if ( ((dwCurrentSize > 0) || fLastNotification)
&& (!_fSentLastNotification))
{
grfBSCF = 0;
// Check if this will be the first data notification
if (!_fSentFirstNotification)
{
grfBSCF |= BSCF_FIRSTDATANOTIFICATION;
_fSentFirstNotification = TRUE;
}
if (fLastNotification)
{
// Check if this will be the last data notification
grfBSCF |= BSCF_LASTDATANOTIFICATION;
_fSentLastNotification = TRUE;
}
// all other notifications are intermediate
if (grfBSCF == 0)
{
grfBSCF |= BSCF_INTERMEDIATEDATANOTIFICATION;
}
// get the stgmed for this
if (_fCreateStgMed == FALSE)
{
hr = _pCTransData->GetData(&pFmtETC, &pStgMed, grfBSCF);
if (hr == S_OK)
{
// BUGBUG: Looks like _fCreateStgMed is always going to be false.
// Either the following line can be de-commented out
// or _fCreateStgMed can be eliminated:
//_fCreateStgMed = TRUE;
TransAssert((pStgMed));
//
// hold on to the stream or storage
//
if ( (_pUnkObject == NULL)
&& ( pStgMed->tymed == TYMED_ISTREAM
|| pStgMed->tymed == TYMED_ISTORAGE))
{
_pUnkObject = pStgMed->pstm;
_pUnkObject->AddRef();
}
}
}
if ( hr == S_OK && fLastNotification )
{
_pCTransData->OnEndofData();
}
if (hr == S_OK)
{
PerfDbgLog5(tagCBinding, this,
">>> %lx::OnDataNotification (Options:%ld,Size:%ld,FmtEtc:%lx,StgMed:%lx)",
_pBSCB, grfBSCF, dwCurrentSize, pFmtETC, pStgMed);
UrlMkAssert((grfBSCF != 0));
hr = CallOnDataAvailable(grfBSCF, dwCurrentSize, pFmtETC, pStgMed);
if (pStgMed)
{
DEBUG_ENTER((DBG_BINDING,
None,
"EXTERNAL::ReleaseStgMedium",
"%#x",
pStgMed
));
ReleaseStgMedium(pStgMed);
DEBUG_LEAVE(0);
//NOTES: if tymed was TYMED_FILE, lpszFilename ZEROED out,
// else if tymed == TYMED_STREAM, pstm NOT ZEROED out.
// We DEPEND on this behavior in CTransDat::GetData()
//
// Ideally, we should just do this->
// memset( pStgMed, 0, sizeof(STGMEDIUM) );
// and save state in the transDat object.
}
}
}
_dwLastSize = dwCurrentSize;
PerfDbgLog2(tagCBinding, this, "-CBinding::OnDataNotification (hr:%lx, dwLastSize:%ld)", hr, _dwLastSize);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::OnObjectAvailable
//
// Synopsis:
//
// Arguments: [pCTP] --
// [fLastNotification] --
//
// Returns:
//
// History: 12-22-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::OnObjectAvailable(DWORD grfBSCF, DWORD dwCurrentSize, DWORD dwTotalSize, BOOL fLastNotification)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::OnObjectAvailable",
"this=%#x, %#x, %#x, %#x, %B",
this, grfBSCF, dwCurrentSize, dwTotalSize, fLastNotification
));
HRESULT hr = NOERROR;
PerfDbgLog3(tagCBinding, this, "+CBinding::OnObjectAvailable (dwCurrentSize:%ld, dwTotalSize:%ld, LastNotification:%d)",
dwCurrentSize, dwTotalSize, fLastNotification);
CLSID clsid = CLSID_NULL;
// We shouldn't have less data than last time
UrlMkAssert(( (dwTotalSize == 0)
|| (dwTotalSize != 0 && dwCurrentSize != 0)
));
// must be BindToObject scenario
UrlMkAssert((_fBindToObject));
if (!fLastNotification && !_fSentFirstNotification)
{
// check if we've instantiated the object yet
if (_pUnkObject == NULL)
{
hr = _pCTransData->GetClassID(_clsidIn, &clsid);
if (FAILED(hr)) {
hr = InstallIEFeature();
if (SUCCEEDED(hr))
hr = _pCTransData->GetClassID(_clsidIn, &clsid);
}
if( _fForceBindToObjFail )
{
hr = REGDB_E_CLASSNOTREG;
}
if (hr == S_OK)
{
// instantiate the object now and call pass it on in OnDataAvailable
hr = InstantiateObject(&clsid, *_piidRes, &_pUnkObject, FALSE);
if (hr == S_FALSE)
{
// switch to datasink file
_pCTransData->SwitchDataSink(DataSink_File);
if( _pCTransData->IsEOFOnSwitchSink() )
{
hr = ObjectPersistMnkLoad(_pUnkObject, _fLocal, TRUE);
if (hr != NOERROR && hr != E_ABORT)
{
hr = ObjectPersistFileLoad(_pUnkObject);
}
}
}
// Don't send notifications after the 'last' one.
if ((hr == S_OK) && (_pUnkObject != NULL))
{
hr = CallOnObjectAvailable(*_piidRes,_pUnkObject);
// release the object in case transaction is async
// the object is passed back via *ppvObj in sync case
if (IsAsyncTransaction())
{
_pUnkObject->Release();
_pUnkObject = NULL;
}
UrlMkAssert((SUCCEEDED(hr)));
hr = S_OK;
}
// keep the object until all data here
}
else if (hr == S_FALSE)
{
//
// switch the datasink to file
//
_pCTransData->SwitchDataSink(DataSink_File);
}
else
{
hr = REGDB_E_CLASSNOTREG;
}
}
else
{
// we got the object loaded but have to wait until all data
// are available
hr = S_FALSE;
}
if (!_fSentFirstNotification)
{
_fSentFirstNotification = TRUE;
}
}
else if (fLastNotification)
{
UrlMkAssert((!_fSentLastNotification));
DWORD grfBSCF = 0;
// Check if this will be the first data notification
// Check if this will be the last data notification
if (fLastNotification)
{
grfBSCF |= BSCF_LASTDATANOTIFICATION;
}
if (_pUnkObject == NULL)
{
if( _fClsidFromProt && !IsEqualGUID(_clsidIn, CLSID_NULL) )
{
clsid = _clsidIn;
hr = NOERROR;
}
else
{
hr = _pCTransData->GetClassID(_clsidIn, &clsid);
}
if (FAILED(hr)) {
hr = InstallIEFeature();
if (SUCCEEDED(hr))
hr = _pCTransData->GetClassID(_clsidIn, &clsid);
}
if( _fForceBindToObjFail )
{
hr = REGDB_E_CLASSNOTREG;
}
if (FAILED(hr))
{
hr = REGDB_E_CLASSNOTREG;
}
else
{
// instanciate the object now and call pass it on in OnDataAvailable
if( _fClsidFromProt )
{
hr = CreateObject(&clsid, *_piidRes, &_pUnkObject);
}
else
{
hr = InstantiateObject(&clsid, *_piidRes,
&_pUnkObject, TRUE);
}
}
}
else
{
CallOnProgress( 0, 0, BINDSTATUS_BEGINSYNCOPERATION, 0 );
hr = ObjectPersistMnkLoad(_pUnkObject,_fLocal,TRUE);
if (hr != NOERROR && hr != E_ABORT)
{
// if all bits are available
hr = ObjectPersistFileLoad(_pUnkObject);
}
CallOnProgress( 0, 0, BINDSTATUS_ENDSYNCOPERATION, 0 );
}
// Don't send notifications after the 'last' one.
if ( SUCCEEDED(hr)
&& (_pUnkObject != NULL)
&& !_fSentLastNotification)
{
BOOL bRegisteredTransactionData = FALSE;
// Note: register the transaction object only
// in case we are asked to transfer it to the
// new process/thread where no new download
// should be started
if (_grfBINDF & BINDF_COMPLETEDOWNLOAD)
{
hr = _pBndCtx->RegisterObjectParam(SZ_TRANSACTIONDATA, (ITransactionData *)_pCTransData);
if (SUCCEEDED(hr))
{
bRegisteredTransactionData = TRUE;
}
PerfDbgLog2(tagCBinding, this, "=== CBinding::OnObjectAvailable RegisterObjectParam SZ_TRANSACTIONDATA: pbndctx:%lx, hr:%lx)", _pBndCtx, hr);
}
TransAssert((hr == NOERROR));
hr = CallOnObjectAvailable(*_piidRes,_pUnkObject);
if (bRegisteredTransactionData)
{
_pBndCtx->RevokeObjectParam(SZ_TRANSACTIONDATA);
}
// release the object
if (IsAsyncTransaction())
{
_pUnkObject->Release();
_pUnkObject = NULL;
}
UrlMkAssert((SUCCEEDED(hr)));
}
else
{
// why did it fail
}
if (grfBSCF & BSCF_LASTDATANOTIFICATION)
{
_fSentLastNotification = TRUE;
}
}
else
{
hr = S_FALSE;
}
_dwLastSize = dwCurrentSize;
PerfDbgLog1(tagCBinding, this, "-CBinding::OnObjectAvailable (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::InstallIEFeature
//
// Synopsis:
// called when you can't by comventional registry lookup means
// find a clsid for a given mime type
// This code then checks to see if this is an IE feature
// and if so installs it by calling the IE JIT API.
//
// Arguments:
//
// Returns:
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::InstallIEFeature()
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::InstallIEFeature",
"this=%#x",
this
));
PerfDbgLog(tagCBinding, this, "+CBinding::InstallIEFeature");
HRESULT hr = INET_E_CANNOT_INSTANTIATE_OBJECT;
uCLSSPEC classpec;
IWindowForBindingUI *pWindowForBindingUI = NULL;
HWND hWnd = NULL;
REFGUID rguidReason = IID_ICodeInstall;
LPCWSTR pwszMimeType = _pCTransData->GetMimeType();
DWORD dwJITFlags;
// BUGBUG: Cannot extern vwzApplicationCDF from datasnif.cxx
// For some reason, vwzApplicationCDF contains bogus data in some scenarios!
static WCHAR vwzAppCDF[] = L"application/x-cdf";
if (!pwszMimeType) {
DEBUG_LEAVE(hr);
return hr;
}
if (SUCCEEDED(IsMimeHandled(pwszMimeType))) {
// if the mime has been handled by an EXE out of proc
// then fail to instantiate the obj. shdocvw will call
// shellexecute on this url which will succeed.
// we assume here that we enter InstallIEfeature only
// after a conversion MimeToClsid has failed!
hr = INET_E_CANNOT_INSTANTIATE_OBJECT;
DEBUG_LEAVE(hr);
return hr;
}
CallOnProgress( 0, 0, BINDSTATUS_BEGINSYNCOPERATION, 0 );
// Get IWindowForBindingUI ptr
hr = _pBSCB->QueryInterface(IID_IWindowForBindingUI,
(LPVOID *)&pWindowForBindingUI);
if (FAILED(hr)) {
IServiceProvider *pServProv;
hr = _pBSCB->QueryInterface(IID_IServiceProvider,
(LPVOID *)&pServProv);
if (hr == NOERROR) {
pServProv->QueryService(IID_IWindowForBindingUI,IID_IWindowForBindingUI,
(LPVOID *)&pWindowForBindingUI);
pServProv->Release();
}
}
hr = INET_E_CANNOT_INSTANTIATE_OBJECT; // init to fail
// get hWnd
if (pWindowForBindingUI) {
pWindowForBindingUI->GetWindow(rguidReason, &hWnd);
pWindowForBindingUI->Release();
QUERYCONTEXT qc;
memset(&qc, 0, sizeof(qc));
// fill in the minimum version number of the component you need
//qc.dwVersionHi =
//qc.dwVersionLo =
classpec.tyspec=TYSPEC_MIMETYPE;
classpec.tagged_union.pMimeType=(LPWSTR)pwszMimeType;
if (pwszMimeType) {
dwJITFlags = (!StrCmpIW(pwszMimeType, vwzAppCDF)) ?
(FIEF_FLAG_FORCE_JITUI) : (0);
}
else {
dwJITFlags = 0;
}
hr = FaultInIEFeature(hWnd, &classpec, &qc, dwJITFlags);
}
CallOnProgress( 0, 0, BINDSTATUS_ENDSYNCOPERATION, 0 );
PerfDbgLog1(tagCBinding, this, "-CBinding::InstallIEFeature (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::InstantiateObject
//
// Synopsis:
//
// Arguments: [pclsid] --
// [riidResult] --
// [ppUnk] --
//
// Returns:
//
// History: 1-12-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::InstantiateObject(CLSID *pclsid, REFIID riidResult, IUnknown **ppUnk,BOOL fFullyAvailable)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::InstantiateObject",
"this=%#x, %#x, %#x, %#x, %B",
this, pclsid, &riidResult, ppUnk, fFullyAvailable
));
PerfDbgLog(tagCBinding, this, "+CBinding::InstantiateObject");
HRESULT hr;
IUnknown *pUnk = NULL;
LPOLESTR pszStr = NULL;
BOOL fLocal = FALSE;
//call OnProgress with CLASSID_AVAILABLE
hr = StringFromCLSID(*pclsid, &pszStr);
if (hr == NOERROR)
{
PerfDbgLog1(tagCBinding, this, "CBinding::InstantiateObject (Class ID:%ws)", pszStr);
hr = CallOnProgress( 0, 0, BINDSTATUS_CLASSIDAVAILABLE, pszStr );
if(hr == E_ABORT)
SetOperationState(OPS_Abort);
else
UrlMkAssert((hr == NOERROR));
}
if (GetOperationState() == OPS_Abort)
{
// stop now - the client aborted the operation
hr = E_ABORT;
}
else
{
DumpIID(riidResult);
CallOnProgress( 0, 0, BINDSTATUS_BEGINSYNCOPERATION, 0 );
// If CLSID_MsHtml object had to be created to honor scripting access
// before OnObjectAvailable, BINDSTATUS_CLASSIDAVAILABLE OnProgress
// message is signal to register such an object in bind context
hr = _pBndCtx->GetObjectParam(L"__PrecreatedObject", &pUnk);
if (FAILED(hr))
{
// call OleAutoConvert
{
CLSID clsidIn = *pclsid;
CLSID clsidOut;
hr = OleGetAutoConvert(clsidIn, &clsidOut);
if (hr == S_OK)
{
*pclsid = clsidOut;
}
}
if (_grfBINDF & BINDF_GETCLASSOBJECT)
{
// Just want the class object
DEBUG_ENTER((DBG_BINDING,
Hresult,
"EXTERNAL::CoGetClassObject",
"%#x, CLSCTX_INPROC_SERVER, NULL, %#x, %#x",
pclsid, &riidResult, &pUnk
));
hr = CoGetClassObject(*pclsid, CLSCTX_INPROC_SERVER,
NULL, riidResult, (void **)&pUnk);
DEBUG_LEAVE(hr);
if (FAILED(hr))
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"EXTERNAL::CoGetClassObject",
"%#x, CLSCTX_LOCAL_SERVER, NULL, %#x, %#x",
pclsid, &riidResult, &pUnk
));
hr = CoGetClassObject(
*pclsid, CLSCTX_LOCAL_SERVER,
NULL, riidResult, (void **)&pUnk);
DEBUG_LEAVE(hr);
if (FAILED(hr))
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"EXTERNAL::CoGetClassObject",
"%#x, CLSCTX_INPROC_HANDLER, NULL, %#x, %#x",
pclsid, &riidResult, &pUnk
));
hr = CoGetClassObject(
*pclsid, CLSCTX_INPROC_HANDLER,
NULL, riidResult, (void **)&pUnk);
DEBUG_LEAVE(hr);
}
}
}
else
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"EXTERNAL::CoCreateInstance",
"%#x, CLSCTX_INPROC_SERVER, NULL, %#x, %#x",
pclsid, &riidResult, &pUnk
));
hr = CoCreateInstance(*pclsid, NULL, CLSCTX_INPROC_SERVER,
riidResult, (void**)&pUnk);
DEBUG_LEAVE(hr);
if (FAILED(hr))
{
DbgLog1(tagCBindingErr, this, "=== CBinding::InstantiateObject InProcServer (hr:%lx)", hr);
DEBUG_ENTER((DBG_BINDING,
Hresult,
"EXTERNAL::CoCreateInstance",
"%#x, CLSCTX_LOCAL_SERVER, NULL, %#x, %#x",
pclsid, &riidResult, &pUnk
));
hr = CoCreateInstance(*pclsid, NULL, CLSCTX_LOCAL_SERVER,
riidResult, (void**)&pUnk);
DEBUG_LEAVE(hr);
_fLocal = fLocal = TRUE;
if (FAILED(hr))
{
DumpIID(*pclsid);
DbgLog1(tagCBindingErr, this, "=== CBinding::InstantiateObject LocalServer (hr:%lx)", hr);
DEBUG_ENTER((DBG_BINDING,
Hresult,
"EXTERNAL::CoCreateInstance",
"%#x, CLSCTX_INPROC_HANDLER, NULL, %#x, %#x",
pclsid, &riidResult, &pUnk
));
hr = CoCreateInstance(*pclsid, NULL, CLSCTX_INPROC_HANDLER, riidResult, (void**)&pUnk);
DEBUG_LEAVE(hr);
_fLocal = fLocal = FALSE;
if( FAILED(hr))
{
DbgLog1(tagCBindingErr, this, "=== CBinding::InstantiateObject InProcHandler (hr:%lx)", hr);
}
}
}
}
}
if (SUCCEEDED(hr))
{
*ppUnk = pUnk;
if ( _grfBINDF & BINDF_COMPLETEDOWNLOAD
&& IsEqualGUID(*pclsid, CLSID_MsHtml)
&& fFullyAvailable == FALSE)
{
hr = S_FALSE;
}
else
{
// S_FALSE means try later when all data are available
hr = ObjectPersistMnkLoad(pUnk,_fLocal,fFullyAvailable, pclsid);
if (hr == E_NOINTERFACE)
{
if (fFullyAvailable)
{
hr = ObjectPersistFileLoad(_pUnkObject);
}
else
{
// call PersistFile::Load later
hr = S_FALSE;
}
}
else if (hr == S_FALSE)
{
// lock the request
_pOInetBdg->LockRequest(0);
_fCompleteDownloadHere = TRUE;
}
else if (hr != NOERROR && hr != E_ABORT)
{
//
// your last chance of being loaded...
// this was not needed for IE4 since wininet
// ALWAYS return async, start from IE5, wininet
// will return SYNC if the file is in cache
//
if (fFullyAvailable)
{
HRESULT hr2 = ObjectPersistFileLoad(_pUnkObject);
if( hr2 == NOERROR )
{
// if we succeeded here, needs to return NOERROR
hr = hr2;
}
}
}
// else pass back error
}
}
else
{
SetInstantiateHresult(hr);
hr = INET_E_CANNOT_INSTANTIATE_OBJECT;
}
CallOnProgress( 0, 0, BINDSTATUS_ENDSYNCOPERATION, 0 );
}
if (pszStr)
{
delete pszStr;
}
PerfDbgLog1(tagCBinding, this, "-CBinding::InstantiateObject (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::ObjectPersistMnkLoad
//
// Synopsis:
//
// Arguments: [pUnk] --
//
// Returns:
//
// History: 2-07-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::ObjectPersistMnkLoad(IUnknown *pUnk, BOOL fLocal, BOOL fFullyAvailable, CLSID *pclsid)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::ObjectPersistMnkLoad",
"this=%#x, %#x, %B, %B",
this, pUnk, fLocal, fFullyAvailable
));
PerfDbgLog(tagCBinding, this, "+CBinding::ObjectPersistMnkLoad");
HRESULT hr;
IPersistMoniker *pPersistMk = NULL;
BIND_OPTS bindopts;
BOOL bRegisteredTransactionData = FALSE;
if (_grfBINDF & BINDF_GETCLASSOBJECT)
{
// GetClassObj, which means there is no need to PersistMnkLoad
PerfDbgLog(tagCBinding, this, " ObjectPersistMnkLoad : GETCLASSOBJ");
hr = NOERROR;
goto exit;
}
DEBUG_ENTER((DBG_BINDING,
Hresult,
"EXTERNAL::IUnknown::QueryInterface",
"this=%#x, IID_IPersistMoniker, %#x",
pUnk, &pPersistMk
));
hr = pUnk->QueryInterface(IID_IPersistMoniker, (void**)&pPersistMk);
DEBUG_LEAVE(hr);
if (hr == NOERROR)
{
TransAssert((pPersistMk != NULL));
if (!fLocal)
{
hr = _pBndCtx->RegisterObjectParam(SZ_BINDING, (IBinding *)this);
}
IUnknown *pUnk = 0;
// remove the current bindstatuscallback
hr = _pBndCtx->GetObjectParam(REG_BSCB_HOLDER, &pUnk);
TransAssert((hr == NOERROR));
hr = _pBndCtx->RevokeObjectParam(REG_BSCB_HOLDER);
TransAssert((hr == NOERROR));
bindopts = _bindopts;
TransAssert(( bindopts.grfMode & (STGM_READWRITE | STGM_SHARE_EXCLUSIVE) ));
if ( !(bindopts.grfMode & (STGM_READWRITE | STGM_SHARE_EXCLUSIVE)) )
{
bindopts.grfMode |= (STGM_READWRITE | STGM_SHARE_EXCLUSIVE);
}
// Note:
// switch of flag do not receive notifications on this cbinding
// BindToStorage synchronous might be called
_grfInternalFlags &= ~BDGFLAGS_NOTIFICATIONS;
if ( (fFullyAvailable)
&& ( ( !(_grfBINDF & BINDF_COMPLETEDOWNLOAD)
&& _fCompleteDownloadHere )
||
(_fLocal)
)
)
{
_grfBINDF |= BINDF_COMPLETEDOWNLOAD;
hr = _pBndCtx->RegisterObjectParam(SZ_TRANSACTIONDATA, (ITransactionData *)_pCTransData);
if (SUCCEEDED(hr))
{
bRegisteredTransactionData = TRUE;
}
PerfDbgLog2(tagCBinding, this, "=== CBinding::OnObjectAvailable RegisterObjectParam SZ_TRANSACTIONDATA: pbndctx:%lx, hr:%lx)", _pBndCtx, hr);
// swtich the _ds back to StreamOnFile so that the BindToStorage
// can get the IStream from pbc (inproc server only)
if( !_fLocal )
{
_pCTransData->SetFileAsStmFile();
}
}
LPCWSTR pwszMimeType = _pCTransData->GetMimeType();
// Now, we try to shove the mimetype down the throat of pPersistMk
IMonikerProp *pmkp = NULL;
DEBUG_ENTER((DBG_BINDING,
Hresult,
"EXTERNAL::IUnknown::QueryInterface",
"this=%#x, IID_IMonikerProp, %#x (mimetype = %.80wq)",
pPersistMk, &pmkp, pwszMimeType
));
if (SUCCEEDED(pPersistMk->QueryInterface(IID_IMonikerProp, (void **)&pmkp)))
{
DEBUG_LEAVE(NOERROR);
pmkp->PutProperty(MIMETYPEPROP, pwszMimeType);
}
else
DEBUG_LEAVE(E_FAIL);
if( !fFullyAvailable &&
pwszMimeType &&
!StrCmpNIW( pwszMimeType, L"application/pdf", 15) )
{
// let's find out we are dealing with Acrobat 3.02 and above
if( _fAcceptRanges && PDFNeedProgressiveDownload() )
{
if(pmkp)
{
pmkp->PutProperty(USE_SRC_URL, L"1");
}
// this is 3.02 and above, go ahead call PMK::Load
hr = pPersistMk->Load(
fFullyAvailable, GetMoniker(), _pBndCtx, bindopts.grfMode);
}
else
{
//
// this is 3.0 and 3.01,
// or we are dealing with server does not support Range
// don't call PMK::Load until fully available
//
hr = S_FALSE;
}
}
else
{
if( pclsid &&
!fFullyAvailable &&
IsEqualGUID(*pclsid, CLSID_PluginHost))
{
hr = S_FALSE;
}
else
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"EXTERNAL::IPersistMoniker::Load",
"this=%#x, %B, %#x, %#x, %#x",
pPersistMk, fFullyAvailable, GetMoniker(), _pBndCtx, bindopts.grfMode
));
hr = pPersistMk->Load(fFullyAvailable, GetMoniker(), _pBndCtx, bindopts.grfMode);
DEBUG_LEAVE(hr);
}
}
if (bRegisteredTransactionData)
{
_pBndCtx->RevokeObjectParam(SZ_TRANSACTIONDATA);
}
if (FAILED(hr))
{
if (hr == E_FAIL)
{
hr = CO_E_SERVER_EXEC_FAILURE;
}
}
// Note: OnStopBinding is still called even
// even the download finished due sync BindToStorage
// turn the flag back on
_grfInternalFlags |= BDGFLAGS_NOTIFICATIONS;
if (!fLocal)
{
_pBndCtx->RevokeObjectParam(SZ_BINDING);
}
if (pUnk)
{
_pBndCtx->RegisterObjectParam(REG_BSCB_HOLDER, pUnk);
pUnk->Release();
}
pPersistMk->Release();
if(pmkp)
pmkp->Release();
}
exit:
PerfDbgLog1(tagCBinding, this, "-CBinding::ObjectPersistMnkLoad (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::ObjectPersistFileLoad
//
// Synopsis:
//
// Arguments: [pUnk] --
//
// Returns:
//
// History: 2-07-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::ObjectPersistFileLoad(IUnknown *pUnk)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::ObjectPersistFileLoad",
"this=%#x, %#x",
this, pUnk
));
HRESULT hr;
PerfDbgLog1(tagCBinding, this, "+CBinding::ObjectPersistFileLoad (filename:%ws)", GetFileName());
IPersistFile *pPersistFile = NULL;
DEBUG_ENTER((DBG_BINDING,
Hresult,
"EXTERNAL::IUnknown::QueryInterface",
"this=%#x, IID_IPersistFile, %#x",
pUnk, &pPersistFile
));
hr = pUnk->QueryInterface(IID_IPersistFile, (void**)&pPersistFile);
DEBUG_LEAVE(hr);
if (hr == NOERROR)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"EXTERNAL::IPersistFile::Load",
"this=%#x, %#x, %#x",
pPersistFile, GetFileName(), 0
));
hr = pPersistFile->Load(GetFileName(), 0);
DEBUG_LEAVE(hr);
if (hr != NOERROR)
{
SetInstantiateHresult(hr);
hr = INET_E_CANNOT_LOAD_DATA;
}
PerfDbgLog1(tagCBinding, this, "=== CBinding::ObjectPersistFileLoad (Load returned:%lx)", hr);
pPersistFile->Release();
}
PerfDbgLog1(tagCBinding, this, "-CBinding::ObjectPersistFileLoad (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::CallGetBindInfo
//
// Synopsis:
//
// Arguments: [grfBINDINFOF] --
// [pBdInfo] --
//
// Returns:
//
// History: 2-07-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::CallGetBindInfo(DWORD *grfBINDINFOF, BINDINFO *pBdInfo)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::CallGetBindInfo",
"this=%#x, %#x, %#x",
this, grfBINDINFOF, pBdInfo
));
HRESULT hr = E_FAIL;
UrlMkAssert((grfBINDINFOF != NULL));
PerfDbgLog1(tagCBinding, this, "+CBinding::CallGetBindInfo (grfBINDINFOF:%ld)", *grfBINDINFOF);
if (GetOperationState() == OPS_Initialized)
{
hr = _pBSCB->GetBindInfo(grfBINDINFOF, pBdInfo);
SetOperationState(OPS_GetBindInfo);
}
else
{
UrlMkAssert((GetOperationState() == OPS_Initialized));
}
if ( (*grfBINDINFOF & BINDF_ASYNCSTORAGE)
&& (*grfBINDINFOF & BINDF_PULLDATA) )
{
PerfDbgLog2(tagCBinding, this, "=== grfBINDINFOF:%lx, (%s)", *grfBINDINFOF, "BINDF_ASYNCSTORAGE | BINDF_PULLDATA");
}
PerfDbgLog2(tagCBinding, this, "-CBinding::CallGetBindInfo (grfBINDINFOF:%lx, hr:%lx)", *grfBINDINFOF, hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::CallOnStartBinding
//
// Synopsis:
//
// Arguments: [grfBINDINFOF] --
// [pib] --
//
// Returns:
//
// History: 2-07-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::CallOnStartBinding(DWORD grfBINDINFOF, IBinding * pib)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::CallOnStartBinding",
"this=%#x, %#x, %#x",
this, grfBINDINFOF, pib
));
HRESULT hr = E_FAIL;
PerfDbgLog1(tagCBinding, this, "+CBinding::CallOnStartBinding (grfBINDINFOF:%lx)", grfBINDINFOF);
if (GetOperationState() == OPS_GetBindInfo)
{
hr = _pBSCB->OnStartBinding(NULL, this);
SetOperationState(OPS_StartBinding);
}
else
{
UrlMkAssert((GetOperationState() == OPS_GetBindInfo));
}
PerfDbgLog1(tagCBinding, this, "-CBinding::CallOnStartBinding (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::CallOnProgress
//
// Synopsis:
//
// Arguments: [ulProgress] --
// [ulProgressMax] --
// [ulStatusCode] --
// [szStatusText] --
//
// Returns:
//
// History: 2-14-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::CallOnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::CallOnProgress",
"this=%#x, %#x, %#x, %#x, %.80wq",
this, ulProgress, ulProgressMax, ulStatusCode, szStatusText
));
HRESULT hr = NOERROR;
PerfDbgLog(tagCBinding, this, "+CBinding::CallOnProgress");
if ( GetOperationState() == OPS_StartBinding)
{
SetOperationState(OPS_Downloading);
}
if (GetOperationState() == OPS_Downloading)
{
hr = _pBSCB->OnProgress(ulProgress, ulProgressMax, ulStatusCode, szStatusText);
}
PerfDbgLog1(tagCBinding, this, "-CBinding::CallOnProgress hr:%lx", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::CallOnStopBinding
//
// Synopsis:
//
// Arguments: [LPCWSTR] --
// [szError] --
//
// Returns:
//
// History: 2-14-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::CallOnStopBinding(HRESULT hrRet,LPCWSTR szError)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::CallOnStopBinding",
"this=%#x, %#x, %.80wq",
this, hrRet, szError
));
HRESULT hr = E_FAIL;
PerfDbgLog1(tagCBinding, this, "+CBinding::CallOnStopBinding ->hrRet:%lx", hrRet);
if ( (GetOperationState() < OPS_Stopped)
&& (GetOperationState() > OPS_Initialized))
{
UrlMkAssert(( (hrRet != S_FALSE && hrRet != E_FAIL) ));
if (hrRet == E_FAIL)
{
hrRet = INET_E_DOWNLOAD_FAILURE;
}
TransAssert(( ((hr == NOERROR) && _fSentLastNotification)
|| (hr != NOERROR) ));
//if( _fBindToObject )
// DbgLog(tagCBindingErr, this, ">>> OnStopBinding (BindToObject)");
//else
// DbgLog(tagCBindingErr, this, ">>> OnStopBinding (BindToStorage)");
hr = _pBSCB->OnStopBinding(hrRet, NULL);
SetOperationState(OPS_Stopped);
}
TransAssert((_pBndCtx));
//TRIDENT BTS->BTO
//Save the transaction objects for BTO
if (!_fBTS_BTO) //(hrRet != INET_E_TERMINATED_BIND)
_pBndCtx->SetTransactionObjects(NULL,NULL);
PerfDbgLog1(tagCBinding, this, "-CBinding::CallOnStopBinding (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::CallOnLowResource
//
// Synopsis:
//
// Arguments: [reserved] --
//
// Returns:
//
// History: 2-14-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::CallOnLowResource (DWORD reserved)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::CallOnLowResource",
"this=%#x, %#x",
this, reserved
));
HRESULT hr = E_FAIL;
PerfDbgLog(tagCBinding, this, "+CBinding::CallOnLowResource");
PerfDbgLog1(tagCBinding, this, "-CBinding::CallOnLowResource (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::CallGetPriority
//
// Synopsis:
//
// Arguments: [pnPriority] --
//
// Returns:
//
// History: 2-14-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::CallGetPriority (LONG * pnPriority)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::CallGetPriority",
"this=%#x, %#x",
this, pnPriority
));
HRESULT hr = E_FAIL;
PerfDbgLog(tagCBinding, this, "+CBinding::CallGetPriority");
PerfDbgLog1(tagCBinding, this, "-CBinding::CallGetPriority (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::CallOnDataAvailable
//
// Synopsis:
//
// Arguments: [DWORD] --
// [FORMATETC] --
// [STGMEDIUM] --
// [pStgMed] --
//
// Returns:
//
// History: 2-14-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::CallOnDataAvailable(DWORD grfBSC,DWORD dwSize,FORMATETC *pFmtETC,STGMEDIUM *pStgMed)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::CallOnDataAvailable",
"this=%#x, %#x, %#x, %#x, %#x",
this, grfBSC, dwSize, pFmtETC, pStgMed
));
HRESULT hr = E_FAIL;
PerfDbgLog(tagCBinding, this, "+CBinding::CallOnDataAvailable");
if (GetOperationState() == OPS_Downloading)
{
//DbgLog2(tagCBindingErr, this, ">>> OnDataAvailable (BSC=%lx size=%d)",
// grfBSC, dwSize);
hr = _pBSCB->OnDataAvailable(grfBSC, dwSize, pFmtETC, pStgMed);
if (hr == INET_E_TERMINATED_BIND)
{
_fBTS_BTO = TRUE;
hr = NOERROR; //restore back to value which was previous value being returned
}
}
else if (GetOperationState() == OPS_Abort)
{
hr = E_ABORT;
}
PerfDbgLog1(tagCBinding, this, "-CBinding::CallOnDataAvailable (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::CallOnObjectAvailable
//
// Synopsis:
//
// Arguments: [IUnknown] --
// [punk] --
//
// Returns:
//
// History: 2-14-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::CallOnObjectAvailable (REFIID riid,IUnknown *punk)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::CallOnObjectAvailable",
"this=%#x, %#x, %#x",
this, &riid, punk
));
HRESULT hr = E_FAIL;
PerfDbgLog(tagCBinding, this, "+CBinding::CallOnObjectAvailable");
if (GetOperationState() == OPS_Downloading || _grfBINDF & BINDF_GETCLASSOBJECT)
{
hr = _pBSCB->OnObjectAvailable(riid, punk);
SetOperationState(OPS_ObjectAvailable);
}
else
{
UrlMkAssert((GetOperationState() == OPS_Downloading));
}
PerfDbgLog1(tagCBinding, this, "-CBinding::CallOnObjectAvailable (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::GetRequestedObject
//
// Synopsis:
//
// Arguments: [pbc] --
// [ppUnk] --
//
// Returns:
//
// History: 7-04-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::GetRequestedObject(IBindCtx *pbc, IUnknown **ppUnk)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::GetRequestedObject",
"this=%#x, %#x, %#x",
this, pbc, ppUnk
));
HRESULT hr = NOERROR;
PerfDbgLog(tagCBinding, this, "+CBinding::GetRequestedObject");
UrlMkAssert((ppUnk));
*ppUnk = NULL;
if (_pUnkObject)
{
*ppUnk = _pUnkObject;
_pUnkObject->AddRef();
}
else if ( IsAsyncTransaction() )
{
//object is not available yet
hr = MK_S_ASYNCHRONOUS;
}
else
{
// BUGBUG: JohanP - this is bogus for the case of returning a filename in stgmed; either we return a new success code or
// the punk of the punkforrelease of the stgmed
hr = NOERROR;
}
PerfDbgLog1(tagCBinding, this, "-CBinding::GetRequestedObject (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::CallAuthenticate
//
// Synopsis:
//
// Arguments: [phwnd] --
// [LPWSTR] --
// [pszPassword] --
//
// Returns:
//
// History: 2-08-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CBinding::CallAuthenticate(HWND* phwnd, LPWSTR *pszUsername,LPWSTR *pszPassword)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::CallAuthenticate",
"this=%#x, %#x, %#x, %#x",
this, phwnd, pszUsername, pszPassword
));
PerfDbgLog(tagCBinding, this, "+CBinding::CallAuthenticate");
HRESULT hr = NOERROR;
if (_pBasicAuth == NULL)
{
hr = LocalQueryInterface(IID_IAuthenticate, (void **) &_pBasicAuth);
}
if ((hr == NOERROR) && _pBasicAuth)
{
hr = _pBasicAuth->Authenticate(phwnd, pszUsername,pszPassword);
}
else
{
UrlMkAssert((_pBasicAuth == NULL));
*phwnd = 0;
*pszUsername = 0;
*pszPassword = 0;
}
PerfDbgLog4(tagCBinding, this, "-CBinding::CallAuthenticate (hr:%lx, hwnd:%lx, username:%ws, password:%ws)",
hr, *phwnd, *pszUsername?*pszUsername:L"", *pszPassword?*pszPassword:L"");
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::LocalQueryInterface
//
// Synopsis:
//
// Arguments: [iid] --
// [ppvObj] --
//
// Returns:
//
// History: 4-09-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::LocalQueryInterface(REFIID riid, void **ppvObj)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::LocalQueryInterface",
"this=%#x, %#x, %#x",
this, &riid, ppvObj
));
PerfDbgLog2(tagCBinding, this, "+CBinding::LocalQueryInterface (%lx, %lx)", riid, ppvObj);
HRESULT hr = E_NOINTERFACE;
*ppvObj = 0;
if (_pBSCB)
{
IServiceProvider *pSrvPrv;
hr = _pBSCB->QueryInterface(IID_IServiceProvider, (void **) &pSrvPrv);
if (hr == NOERROR)
{
hr = pSrvPrv->QueryService(riid,riid, ppvObj);
pSrvPrv->Release();
}
else
{
hr = E_NOINTERFACE;
*ppvObj = 0;
}
}
PerfDbgLog2(tagCBinding, this, "-CBinding::LocalQueryInterface (%lx)[%lx]", hr, *ppvObj);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::Switch
//
// Synopsis:
//
// Arguments: [pStateInfo] --
//
// Returns:
//
// History: 4-10-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::Switch(PROTOCOLDATA *pStateInfo)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::IInternetProtocolSink::Switch",
"this=%#x, %#x",
this, pStateInfo
));
PerfDbgLog(tagCBinding, this, "+CBinding::Switch");
HRESULT hr = E_FAIL;
TransAssert((FALSE));
PerfDbgLog1(tagCBinding, this, "-CBinding::Switch (%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::ReportProgress
//
// Synopsis:
//
// Arguments: [ulStatusCode] --
// [szStatusText] --
//
// Returns:
//
// History: 4-10-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::ReportProgress(ULONG ulStatusCode, LPCWSTR szStatusText)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::IInternetProtocolSink::ReportProgress",
"this=%#x, %#x, %.80wq",
this, ulStatusCode, szStatusText
));
PerfDbgLog(tagCBinding, this, "+CBinding::ReportProgress");
HRESULT hr = NOERROR;
if ( (ulStatusCode == BINDSTATUS_BEGINDOWNLOADDATA)
|| (ulStatusCode == BINDSTATUS_DOWNLOADINGDATA)
|| (ulStatusCode == BINDSTATUS_ENDDOWNLOADDATA) )
{
}
else
{
BOOL fRet = OnTransNotification(
(BINDSTATUS) ulStatusCode //BINDSTATUS NotMsg,
,0 //ulProgress //DWORD dwCurrentSize,
,0 //ulProgressMax //DWORD dwTotalSize,
,( LPWSTR)szStatusText //LPWSTR pwzStr,
,NOERROR //HRESULT hrINet
);
}
PerfDbgLog1(tagCBinding, this, "-CBinding::ReportProgress (%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::ReportData
//
// Synopsis:
//
// Arguments: [grfBSCF] --
// [ulProgress] --
// [ulProgressMax] --
//
// Returns:
//
// History: 4-10-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::ReportData(DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::IInternetProtocolSink::ReportData",
"this=%#x, %#x, %#x, %#x",
this, grfBSCF, ulProgress, ulProgressMax
));
PerfDbgLog(tagCBinding, this, "+CBinding::ReportData");
HRESULT hr = NOERROR;
BOOL fLastNotification = (grfBSCF & BSCF_LASTDATANOTIFICATION) ? TRUE : FALSE;
ULONG ulStatusCode = BINDSTATUS_DOWNLOADINGDATA;
ULONG dwNew;
AddRef();
if (grfBSCF & BSCF_LASTDATANOTIFICATION)
{
ulStatusCode = BINDSTATUS_ENDDOWNLOADDATA;
}
else if (grfBSCF & BSCF_FIRSTDATANOTIFICATION)
{
ulStatusCode = BINDSTATUS_BEGINDOWNLOADDATA;
}
HRESULT hr1 = _pCTransData->OnDataReceived(grfBSCF, ulProgress, ulProgressMax,&dwNew);
ulProgress = dwNew;
if (hr1 == S_FALSE)
{
// end of data
ulStatusCode = BINDSTATUS_ENDDOWNLOADDATA;
}
else if ( (hr1 != S_NEEDMOREDATA)
&& (hr1 != E_PENDING)
&& (hr1 != NOERROR))
{
ulStatusCode = BINDSTATUS_ERROR;
}
if (hr1 != S_NEEDMOREDATA)
{
BOOL fRet = OnTransNotification(
(BINDSTATUS) ulStatusCode //BINDSTATUS NotMsg,
,ulProgress //DWORD dwCurrentSize,
,ulProgressMax //DWORD dwTotalSize,
,NULL //LPWSTR pwzStr,
,NOERROR //HRESULT hrINet
);
if (fRet == TRUE)
{
_pCTransData->OnTerminate();
if (_fBindToObject)
{
hr = S_FALSE;
TransAssert((_grfInternalFlags | ~BDGFLAGS_ATTACHED));
TransAssert((_grfInternalFlags & BDGFLAGS_PARTIAL));
_pOInetBdg->Terminate(BDGFLAGS_PARTIAL);
}
else if(_fBTS_BTO)
{
_pOInetBdg->Terminate(BDGFLAGS_BTS_BTO);
}
}
}
//TRIDENT BTS->BTO
//used to return only NOERROR and S_FALSE(only for certain BTO sitns.-not returned for BTS)
//Return INET_E_TERMINATED_BIND to let the Trans object know about the transfer.
if (_fBTS_BTO)
hr = INET_E_TERMINATED_BIND;
Release();
PerfDbgLog1(tagCBinding, this, "-CBinding::ReportData (%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CBinding::ReportResult
//
// Synopsis:
//
// Arguments: [hrResult] --
// [dwError] --
// [pwzResult] --
//
// Returns:
//
// History: 4-10-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CBinding::ReportResult(HRESULT hrResult, DWORD dwError, LPCWSTR pwzResult)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::IInternetProtocolSink::ReportResult",
"this=%#x, %#x, %#x, %.80wq",
this, hrResult, dwError, pwzResult
));
PerfDbgLog(tagCBinding, this, "+CBinding::ReportResult");
HRESULT hr = NOERROR;
AddRef();
_dwBindError = dwError;
_hrBindResult = hrResult;
if (pwzResult)
{
if (_pwzResult)
{
delete [] _pwzResult;
}
_pwzResult = OLESTRDuplicate((LPWSTR)pwzResult);
}
BOOL fRet = OnTransNotification(
BINDSTATUS_RESULT //BINDSTATUS NotMsg,
,0 //ulProgress //DWORD dwCurrentSize,
,0 //ulProgressMax //DWORD dwTotalSize,
,(LPWSTR)pwzResult //LPWSTR pwzStr,
,hrResult //HRESULT hrINet
);
if (fRet == TRUE)
{
hr = S_FALSE;
DWORD dwFlags = (_fBindToObject) ? BDGFLAGS_PARTIAL : 0;
_pCTransData->OnTerminate();
_pOInetBdg->Terminate(dwFlags);
}
Release();
PerfDbgLog1(tagCBinding, this, "-CBinding::ReportResult (%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
STDMETHODIMP CBinding::CreateObject(CLSID *pclsid, REFIID riidResult, IUnknown **ppUnk)
{
DEBUG_ENTER((DBG_BINDING,
Hresult,
"CBinding::CreateObject",
"this=%#x, %#x, %#x, %#x",
this, pclsid, &riidResult, ppUnk
));
PerfDbgLog(tagCBinding, this, "+CBinding::CreateObj");
HRESULT hr;
IUnknown *pUnk = NULL;
if (GetOperationState() == OPS_Abort)
{
// stop now - the client aborted the operation
hr = E_ABORT;
}
else
{
DumpIID(riidResult);
// call OleAutoConvert
{
CLSID clsidIn = *pclsid;
CLSID clsidOut;
hr = OleGetAutoConvert(clsidIn, &clsidOut);
if (hr == S_OK)
{
*pclsid = clsidOut;
}
}
if (_grfBINDF & BINDF_GETCLASSOBJECT)
{
// Just want the class object
hr = CoGetClassObject(*pclsid, CLSCTX_INPROC_SERVER,
NULL, riidResult, (void **)&pUnk);
if (FAILED(hr))
{
hr = CoGetClassObject(*pclsid, CLSCTX_LOCAL_SERVER,
NULL, riidResult, (void **)&pUnk);
if (FAILED(hr))
{
hr = CoGetClassObject(*pclsid, CLSCTX_INPROC_HANDLER,
NULL, riidResult, (void **)&pUnk);
}
}
}
else
{
hr = CoCreateInstance(*pclsid, NULL, CLSCTX_INPROC_SERVER,
riidResult, (void**)&pUnk);
if (FAILED(hr))
{
hr = CoCreateInstance(*pclsid, NULL, CLSCTX_LOCAL_SERVER,
riidResult, (void**)&pUnk);
if (FAILED(hr))
{
hr = CoCreateInstance(*pclsid, NULL, CLSCTX_INPROC_HANDLER,
riidResult, (void**)&pUnk);
}
}
}
if (SUCCEEDED(hr))
{
*ppUnk = pUnk;
}
else
{
SetInstantiateHresult(hr);
hr = INET_E_CANNOT_INSTANTIATE_OBJECT;
}
CallOnProgress( 0, 0, BINDSTATUS_ENDSYNCOPERATION, 0 );
}
PerfDbgLog1(tagCBinding, this, "-CBinding::CreateObject (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}