|
|
// ===========================================================================
// File: CDL.CXX
// The main code downloader file.
//
#include <cdlpch.h>
// ---------------------------------------------------------------------------
// %%Function: CClBinding::CClBinding
// CClBinding (For client's IBinding for code download)
// ---------------------------------------------------------------------------
CClBinding::CClBinding( CCodeDownload *pcdl, IBindStatusCallback *pAssClientBSC, IBindCtx *pAssClientBC, REFCLSID rclsid, DWORD dwClsContext, LPVOID pvReserved, REFIID riid, IInternetHostSecurityManager *pHostSecurityManager): m_riid(riid) { DEBUG_ENTER((DBG_DOWNLOAD, None, "CClBinding::CClBinding", "this=%#x, %#x, %#x, %#x, %#x, %#x, %#x, %#x", this, pcdl, pAssClientBSC, pAssClientBC, &rclsid, dwClsContext, pvReserved, &riid, pHostSecurityManager )); m_cRef = 1; //equ of an internal addref
m_dwState = CDL_NoOperation; m_pcdl = pcdl; m_pAssClientBSC = pAssClientBSC; m_pAssClientBC = pAssClientBC; m_pCodeInstall = NULL; m_pWindowForBindingUI = NULL; m_wszClassString = NULL;
m_pHostSecurityManager = pHostSecurityManager; if (m_pHostSecurityManager) m_pHostSecurityManager->AddRef();
m_pBindHost = NULL;
m_hWnd = (HWND)INVALID_HANDLE_VALUE;
m_dwClsContext = dwClsContext; m_pvReserved = pvReserved;
memcpy(&m_clsid, &rclsid, sizeof(GUID));
DEBUG_LEAVE(0); } // CClBinding
// ---------------------------------------------------------------------------
// %%Function: CClBinding::~CClBinding
// ---------------------------------------------------------------------------
CClBinding::~CClBinding() { DEBUG_ENTER((DBG_DOWNLOAD, None, "CClBinding::~CClBinding", "this=%#x", this )); if (m_wszClassString) { delete [] m_wszClassString; }
DEBUG_LEAVE(0); } // ~CClBinding
// ---------------------------------------------------------------------------
// %%Function: CClBinding::ReleaseClient
// ---------------------------------------------------------------------------
HRESULT CClBinding::ReleaseClient() { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "CClBinding::ReleaseClient", "this=%#x", this )); SAFERELEASE(m_pAssClientBSC); SAFERELEASE(m_pAssClientBC); SAFERELEASE(m_pCodeInstall); SAFERELEASE(m_pWindowForBindingUI); SAFERELEASE(m_pBindHost); SAFERELEASE(m_pHostSecurityManager );
DEBUG_LEAVE(S_OK); return S_OK; }
// ---------------------------------------------------------------------------
// %%Function: CClBinding::GetHWnd
// ---------------------------------------------------------------------------
HWND CClBinding::GetHWND(REFGUID rguidReason) { DEBUG_ENTER((DBG_DOWNLOAD, Dword, "CClBinding::GetHWND", "this=%#x, %#x", this, &rguidReason )); m_hWnd = (HWND)INVALID_HANDLE_VALUE; // don't cache hwnd
// this degrades will
// if CSite goes away but
// code download was not
// aborted.
if (m_pcdl->IsSilentMode()) {
DEBUG_LEAVE(m_hWnd); return m_hWnd; }
GetIWindowForBindingUI();
if (m_pWindowForBindingUI) {
m_pWindowForBindingUI->GetWindow(rguidReason, &m_hWnd);
} else {
GetICodeInstall();
if (m_pCodeInstall) HRESULT hr = m_pCodeInstall->GetWindow(rguidReason,&m_hWnd);
}
DEBUG_LEAVE(m_hWnd); return m_hWnd; }
// ---------------------------------------------------------------------------
// %%Function: GetHostSecurityManager
// ---------------------------------------------------------------------------
IInternetHostSecurityManager* GetHostSecurityManager(IBindStatusCallback *pclientbsc) { DEBUG_ENTER((DBG_DOWNLOAD, Pointer, "GetHostSecurityManager", "%#x", pclientbsc )); IInternetHostSecurityManager *pHostSecurityManager = NULL;
// Get IInternetHostSecurityManager ptr
HRESULT hr = pclientbsc->QueryInterface(IID_IInternetHostSecurityManager, (LPVOID *)&pHostSecurityManager);
if (FAILED(hr)) { IServiceProvider *pServProv; hr = pclientbsc->QueryInterface(IID_IServiceProvider, (LPVOID *)&pServProv);
if (hr == NOERROR) { pServProv->QueryService(IID_IInternetHostSecurityManager,IID_IInternetHostSecurityManager, (LPVOID *)&pHostSecurityManager); pServProv->Release(); } }
DEBUG_LEAVE(pHostSecurityManager); return pHostSecurityManager;
}
// ---------------------------------------------------------------------------
// %%Function: CClBinding::GetHostSecurityManager
// ---------------------------------------------------------------------------
IInternetHostSecurityManager* CClBinding::GetHostSecurityManager() { DEBUG_ENTER((DBG_DOWNLOAD, Pointer, "CClBinding::GetHostSecurityManager", "this=%#x", this )); static BOOL fFailedOnce = FALSE;
if (m_pHostSecurityManager) { DEBUG_LEAVE(m_pHostSecurityManager); return m_pHostSecurityManager; } if (fFailedOnce) {
DEBUG_LEAVE(NULL); return NULL; }
Assert(m_pcdl); Assert(m_pcdl->GetClientBSC());
m_pHostSecurityManager = ::GetHostSecurityManager(m_pcdl->GetClientBSC());
if (!m_pHostSecurityManager) fFailedOnce = TRUE;
DEBUG_LEAVE(m_pHostSecurityManager); return m_pHostSecurityManager;
}
// ---------------------------------------------------------------------------
// %%Function: CClBinding::GetBindHost
// ---------------------------------------------------------------------------
IBindHost* CClBinding::GetIBindHost() { DEBUG_ENTER((DBG_DOWNLOAD, Pointer, "CClBinding::GetIBindHost", "this=%#x", this )); static BOOL fFailedOnce = FALSE;
if (m_pBindHost) { DEBUG_LEAVE(m_pBindHost); return m_pBindHost; } if (fFailedOnce) { DEBUG_LEAVE(NULL); return NULL; }
Assert(m_pcdl); Assert(m_pcdl->GetClientBSC());
// Get IBindHost ptr
HRESULT hr = m_pcdl->GetClientBSC()->QueryInterface(IID_IBindHost, (LPVOID *)&m_pBindHost);
if (FAILED(hr)) { IServiceProvider *pServProv; hr = m_pcdl->GetClientBSC()->QueryInterface(IID_IServiceProvider, (LPVOID *)&pServProv);
if (hr == NOERROR) { pServProv->QueryService(IID_IBindHost,IID_IBindHost, (LPVOID *)&m_pBindHost); pServProv->Release(); } }
if (!m_pBindHost) fFailedOnce = TRUE;
DEBUG_LEAVE(m_pBindHost); return m_pBindHost;
}
// ---------------------------------------------------------------------------
// %%Function: CClBinding::GetIWindowForBindingUI
// ---------------------------------------------------------------------------
IWindowForBindingUI* CClBinding::GetIWindowForBindingUI() { DEBUG_ENTER((DBG_DOWNLOAD, Pointer, "CClBinding::GetIWindowForBindingUI", "this=%#x", this ));
if (m_pWindowForBindingUI) { DEBUG_LEAVE(m_pWindowForBindingUI); return m_pWindowForBindingUI; } Assert(m_pcdl); Assert(m_pcdl->GetClientBSC());
// Get IWindowForBindingUI ptr
HRESULT hr = m_pcdl->GetClientBSC()->QueryInterface(IID_IWindowForBindingUI, (LPVOID *)&m_pWindowForBindingUI);
if (FAILED(hr)) { IServiceProvider *pServProv; hr = m_pcdl->GetClientBSC()->QueryInterface(IID_IServiceProvider, (LPVOID *)&pServProv);
if (hr == NOERROR) { pServProv->QueryService(IID_IWindowForBindingUI,IID_IWindowForBindingUI, (LPVOID *)&m_pWindowForBindingUI); pServProv->Release(); } }
if (!m_pWindowForBindingUI) { m_pcdl->CodeDownloadDebugOut(DEB_CODEDL, FALSE, ID_CDLDBG_NO_IWINDOWFORBINDINGUI); } DEBUG_LEAVE(m_pWindowForBindingUI); return m_pWindowForBindingUI;
}
// ---------------------------------------------------------------------------
// %%Function: CClBinding::GetCodeInstall
// ---------------------------------------------------------------------------
ICodeInstall* CClBinding::GetICodeInstall() { DEBUG_ENTER((DBG_DOWNLOAD, Pointer, "CClBinding::GetICodeInstall", "this=%#x", this ));
if (m_pCodeInstall) { DEBUG_LEAVE(m_pCodeInstall); return m_pCodeInstall; } Assert(m_pcdl); Assert(m_pcdl->GetClientBSC());
// Get ICodeInstall ptr
HRESULT hr = m_pcdl->GetClientBSC()->QueryInterface(IID_ICodeInstall, (LPVOID *)&m_pCodeInstall);
if (FAILED(hr)) { IServiceProvider *pServProv; hr = m_pcdl->GetClientBSC()->QueryInterface(IID_IServiceProvider, (LPVOID *)&pServProv);
if (hr == NOERROR) { pServProv->QueryService(IID_ICodeInstall,IID_ICodeInstall, (LPVOID *)&m_pCodeInstall); pServProv->Release(); } }
DEBUG_LEAVE(m_pCodeInstall); return m_pCodeInstall;
}
// ---------------------------------------------------------------------------
// %%Function: CClBinding::AddRef
// ---------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CClBinding::AddRef() { DEBUG_ENTER((DBG_DOWNLOAD, Dword, "CClBinding::IUnknown::AddRef", "this=%#x", this )); ULONG ulRet = m_cRef++;
DEBUG_LEAVE(ulRet); return ulRet; } // ---------------------------------------------------------------------------
// %%Function: CClBinding::Release
// ---------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CClBinding::Release() { DEBUG_ENTER((DBG_DOWNLOAD, Dword, "CClBinding::IUnknown::Release", "this=%#x", this )); if (--m_cRef == 0) { delete this;
DEBUG_LEAVE(0); return 0; }
DEBUG_LEAVE(m_cRef); return m_cRef; }
// ---------------------------------------------------------------------------
// %%Function: CClBinding::QueryInterface
// ---------------------------------------------------------------------------
STDMETHODIMP CClBinding::QueryInterface(REFIID riid, void** ppv) { DEBUG_ENTER((DBG_DOWNLOAD, Pointer, "CClBinding::IUnknown::QueryInterface", "this=%#x, %#x, %#x", this, &riid, ppv )); *ppv = NULL;
if (riid==IID_IUnknown || riid==IID_IBinding) { *ppv = this; AddRef();
DEBUG_LEAVE(S_OK); return S_OK; }
// BUGBUG: what about IWinInetInfo and IWinsock???
DEBUG_LEAVE(E_NOINTERFACE); return E_NOINTERFACE; } // CClBinding::QueryInterface
// ---------------------------------------------------------------------------
// %%Function: CClBinding::Abort( void )
// ---------------------------------------------------------------------------
STDMETHODIMP CClBinding::Abort( void ) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "CClBinding::IBinding::Abort", "this=%#x", this )); Assert(m_pcdl); HRESULT hr = S_OK; CDownload *pdl = NULL;
// BUGBUG: need to understand why this pointer might be null
// nothing to do
if (m_pcdl == NULL) { DEBUG_LEAVE(S_OK); return S_OK; } //BUGBUG: this is hack fix for a stress bug
__try { pdl = m_pcdl->GetDownloadHead(); if (m_pcdl->GetCountClientBindings() > 1) { } pdl->GetDLState();
} __except(EXCEPTION_EXECUTE_HANDLER) { DEBUG_LEAVE(S_OK); return S_OK; } #ifdef unix
__endexcept #endif /* unix */
if (m_pcdl->GetCountClientBindings() > 1) { hr = m_pcdl->AbortBinding(this);// not sure what we should do with
// a failed hr!
if (SUCCEEDED(hr)) { DEBUG_LEAVE(hr); return hr; } //else fall thru to really abort
// we have some bad state inside
}
if (!m_pcdl->SafeToAbort()) {
hr = m_pcdl->HandleUnSafeAbort(); // returns either S_FALSE or error
if (hr == S_FALSE) // chose not to abort
{ DEBUG_LEAVE(hr); return hr; // indicated that we did not abort
} else { DEBUG_LEAVE(S_OK); return S_OK; // means DoSetp will abort
}
}
CUrlMkTls tls(hr); // hr passed by reference!
Assert(SUCCEEDED(hr)); Assert(tls->pCDLPacketMgr);
// to mark that atleast one real URLMON bindign was aborted
// in this case URLMON will post an OnStopBinding for that
// and we will end up aborting all other bindings and the whole
// code download. However if that's not the case then we were probably
// in some post binding processing such as verifytrust cab extraction etc
// and so we need to post a DoSetup() packet with UserCancelled flag set.
// forward the call to all our IBindings
do {
if (!pdl->IsSignalled(m_pcdl)) { // packet processing pending for this state. we will check for
// DLSTATE_ABORT in each packet processing state and if true
// it will call CompleteOne(us), which marks each piece DLSTATE_DONE
hr = pdl->Abort(m_pcdl); DEBUG_LEAVE(hr); return hr;
}
} while ((pdl = pdl->GetNext()) != NULL);
m_pcdl->SetUserCancelled();
DEBUG_LEAVE(hr); return hr; }
STDMETHODIMP CClBinding::Suspend( void ) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "CClBinding::IBinding::Suspend", "this=%#x", this )); CDownload *pdl = m_pcdl->GetDownloadHead();
if (m_dwState != CDL_Suspend) m_dwState = CDL_Suspend; else { DEBUG_LEAVE(S_OK); return S_OK; } // forward the call to all our IBindings
do { if (pdl->GetBSC()->GetBinding()) pdl->GetBSC()->GetBinding()->Suspend(); } while ((pdl = pdl->GetNext()) != NULL);
DEBUG_LEAVE(S_OK); return S_OK; }
STDMETHODIMP CClBinding::Resume( void ) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "CClBinding::IBinding::Resume", "this=%#x", this )); CDownload *pdl = m_pcdl->GetDownloadHead();
if (m_dwState == CDL_Suspend) m_dwState = CDL_Downloading; else { DEBUG_LEAVE(S_OK); return S_OK; } // forward the call to all our IBindings
do { if (pdl->GetBSC()->GetBinding()) pdl->GetBSC()->GetBinding()->Resume(); } while ((pdl = pdl->GetNext()) != NULL);
DEBUG_LEAVE(S_OK); return S_OK; }
STDMETHODIMP CClBinding::SetPriority(LONG nPriority) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "CClBinding::IBinding::SetPriority", "this=%#x, %#x", this, nPriority ));
CDownload *pdl = m_pcdl->GetDownloadHead();
m_nPriority = nPriority; // cache pri
// pass on priorty to our IBindings
do { if (pdl->GetBSC()->GetBinding()) pdl->GetBSC()->GetBinding()->SetPriority(nPriority); } while ((pdl = pdl->GetNext()) != NULL);
DEBUG_LEAVE(S_OK); return S_OK; }
STDMETHODIMP CClBinding::GetPriority(LONG *pnPriority) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "CClBinding::IBinding::GetPriority", "this=%#x, %#x", this, pnPriority ));
*pnPriority = m_nPriority; // don't need to call our IBindings: pri cached
DEBUG_LEAVE(S_OK); return S_OK; }
STDMETHODIMP CClBinding::GetBindResult(CLSID *pclsidProtocol, DWORD *pdwResult, LPWSTR *pszResult,DWORD *pdwReserved) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "CClBinding::IBinding::GetBindResult", "this=%#x, %#x, %#x, %#x, %#x", this, pclsidProtocol, pdwResult, pszResult, pdwReserved )); HRESULT hr = NOERROR;
if (!pdwResult || !pszResult || pdwReserved) { hr = E_INVALIDARG; } else { *pdwResult = NOERROR; *pszResult = NULL; }
DEBUG_LEAVE(hr); return hr; }
// ---------------------------------------------------------------------------
// %%Function: CClBinding::InstantiateObjectAndReport()
// ---------------------------------------------------------------------------
HRESULT CClBinding::InstantiateObjectAndReport(CCodeDownload *pcdl) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "CClBinding::InstantiateObjectAndReport", "this=%#x, %#x", this, pcdl )); HRESULT hr = S_OK;
LPVOID ppv = 0; CLSID myclsid; BOOL bLogGenOk; WCHAR *pwszOSBErrMsg = NULL; char *pszExactErrMsg = NULL; hr = GetClsidFromExtOrMime( m_clsid, myclsid, m_pcdl->GetMainExt(), m_pcdl->GetMainType(), NULL);
if (SUCCEEDED(hr)) hr = CoGetClassObject(myclsid, m_dwClsContext, m_pvReserved, m_riid, &ppv);
if (SUCCEEDED(hr)) { (GetAssBSC())->OnObjectAvailable( m_riid, (IUnknown*) ppv);
Assert(ppv);
// release the IUnkown returned by CoGetClassObject
((IUnknown*)ppv)->Release();
}
if (FAILED(hr)) { bLogGenOk = pcdl->GenerateErrStrings(hr, &pszExactErrMsg, &pwszOSBErrMsg); if (!bLogGenOk) { pwszOSBErrMsg = NULL; pszExactErrMsg = NULL; } }
(GetAssBSC())->OnStopBinding(hr, pwszOSBErrMsg); m_pcdl->CodeDownloadDebugOut(DEB_CODEDL, hr != S_OK, ID_CDLDBG_ONSTOPBINDING_CALLED, hr, (hr == S_OK)?"(SUCCESS)":"", myclsid.Data1, m_pcdl->GetMainURL(), m_pcdl->GetMainType(), m_pcdl->GetMainExt());
SAFEDELETE(pwszOSBErrMsg); SAFEDELETE(pszExactErrMsg);
DEBUG_LEAVE(hr); return hr; }
HRESULT CClBinding::SetClassString(LPCWSTR pszClassString) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "CClBinding::SetClassString", "this=%#x, %.80wq", this, pszClassString )); HRESULT hr = S_OK;
if (m_wszClassString) { delete [] m_wszClassString; }
if (!pszClassString) { m_wszClassString = NULL; } else { m_wszClassString = new WCHAR[lstrlenW(pszClassString) + 1]; if (m_wszClassString) { StrCpyW(m_wszClassString, pszClassString); } else { hr = E_OUTOFMEMORY; } }
DEBUG_LEAVE(hr); return hr; }
const LPWSTR CClBinding::GetClassString() { DEBUG_ENTER((DBG_DOWNLOAD, Pointer, "CClBinding::GetClassString", "this=%#x", this ));
DEBUG_LEAVE(m_wszClassString); return m_wszClassString; }
|