|
|
//+---------------------------------------------------------------------------
//
// 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) ¶m );
// 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; }
|