You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4467 lines
129 KiB
4467 lines
129 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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;
|
|
}
|
|
|