|
|
#include "Status.h"
#include "..\\inc\\urlmon.hxx"
#define TIMEOUT 600000 // 10 minutes
/******************************************************************************
Constructor and destructor and helper functions
******************************************************************************/
CSilentCodeDLSink::CSilentCodeDLSink() { m_cRef = 1; m_pBinding = NULL; m_hOnStopBindingEvt = CreateEvent(NULL, TRUE, FALSE, NULL); m_fAbort = FALSE; }
CSilentCodeDLSink::~CSilentCodeDLSink() { if(m_hOnStopBindingEvt) CloseHandle(m_hOnStopBindingEvt); }
VOID CSilentCodeDLSink::Abort() { m_fAbort = TRUE; }
HRESULT CSilentCodeDLSink::WaitTillNotified() { if (m_hOnStopBindingEvt == NULL) return E_FAIL;
HRESULT hr = E_FAIL; DWORD dwResult = 0; const DWORD MORE_INPUT = WAIT_OBJECT_0 + 1; MSG msg;
// Test state of event
dwResult = WaitForSingleObject(m_hOnStopBindingEvt, 0); if (dwResult == WAIT_FAILED) return HRESULT_FROM_WIN32(GetLastError());
// Note that MsgWaitForMultipleObjects doesn't return
// if there was previously unread input of the specified
// type in the queue. It only wakes up when input arrives.
for (dwResult = MORE_INPUT; dwResult == MORE_INPUT; ) { if (dwResult == MORE_INPUT) { // more input in queue
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } else if (dwResult == WAIT_OBJECT_0) { // event has been signaled
hr = S_OK; } else if (dwResult == 0xFFFFFFFF) { // error has occurred
hr = HRESULT_FROM_WIN32(GetLastError()); } else { // timeout or wait abondaned
hr = E_FAIL; } dwResult = MsgWaitForMultipleObjects( 1, &m_hOnStopBindingEvt, FALSE, TIMEOUT, QS_ALLINPUT); }
if (FAILED(hr)) Abort();
return hr; }
/******************************************************************************
IUnknown Methods
******************************************************************************/
STDMETHODIMP CSilentCodeDLSink::QueryInterface(REFIID riid, void **ppv) { *ppv = NULL;
if (riid == IID_IUnknown || riid == IID_IBindStatusCallback) { *ppv = (IBindStatusCallback*)this; } else if (riid == IID_ICodeInstall) { *ppv = (ICodeInstall*)this; } else if (riid == IID_IWindowForBindingUI) { *ppv = (IWindowForBindingUI*)this; }
if (*ppv != NULL) { ((IUnknown*)*ppv)->AddRef(); return S_OK; }
return E_NOINTERFACE; }
STDMETHODIMP_(ULONG) CSilentCodeDLSink::AddRef() { return ++m_cRef; }
STDMETHODIMP_(ULONG) CSilentCodeDLSink::Release() { if (--m_cRef) return m_cRef;
delete this; return 0; }
/******************************************************************************
IBindStatusCallback Methods
******************************************************************************/
STDMETHODIMP CSilentCodeDLSink::OnStartBinding(DWORD grfBSCOption, IBinding *pib) { if (m_pBinding != NULL) m_pBinding->Release();
m_pBinding = pib; if (m_pBinding != NULL) m_pBinding->AddRef();
if (m_fAbort) m_pBinding->Abort();
return S_OK; }
STDMETHODIMP CSilentCodeDLSink::GetPriority(LONG *pnPriority) { if (m_fAbort) m_pBinding->Abort();
return S_OK; }
STDMETHODIMP CSilentCodeDLSink::OnLowResource(DWORD reserved) { if (m_fAbort) m_pBinding->Abort();
return S_OK; }
STDMETHODIMP CSilentCodeDLSink::OnProgress( ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) { if (m_fAbort) m_pBinding->Abort();
return S_OK; }
STDMETHODIMP CSilentCodeDLSink::OnStopBinding( HRESULT hresult, LPCWSTR szError) { if (m_pBinding) { m_pBinding->Release(); m_pBinding = NULL; }
if(m_hOnStopBindingEvt) SetEvent(m_hOnStopBindingEvt);
return S_OK; }
STDMETHODIMP CSilentCodeDLSink::GetBindInfo( DWORD* pgrfBINDF, BINDINFO* pbindInfo) { if (!pgrfBINDF || !pbindInfo || !pbindInfo->cbSize) return E_INVALIDARG;
*pgrfBINDF = BINDF_ASYNCHRONOUS|BINDF_SILENTOPERATION;
// clear BINDINFO but keep its size
DWORD cbSize = pbindInfo->cbSize; ZeroMemory( pbindInfo, cbSize ); pbindInfo->cbSize = cbSize;
return S_OK; }
STDMETHODIMP CSilentCodeDLSink::OnDataAvailable( DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed) { if (m_fAbort) m_pBinding->Abort();
return S_OK; }
STDMETHODIMP CSilentCodeDLSink::OnObjectAvailable( REFIID riid, IUnknown *punk) { return S_OK; }
/******************************************************************************
ICodeInstall Methods
******************************************************************************/
STDMETHODIMP CSilentCodeDLSink::GetWindow( REFGUID rguidReason, HWND *phwnd) { *phwnd = (HWND)INVALID_HANDLE_VALUE;
if (m_fAbort) m_pBinding->Abort();
return S_FALSE; }
STDMETHODIMP CSilentCodeDLSink::OnCodeInstallProblem( ULONG ulStatusCode, LPCWSTR szDestination, LPCWSTR szSource, DWORD dwReserved) { switch (ulStatusCode) { case CIP_ACCESS_DENIED: case CIP_DISK_FULL: return E_ABORT;
case CIP_OLDER_VERSION_EXISTS: return S_OK; // always update
case CIP_NEWER_VERSION_EXISTS: return S_FALSE; // don't update
case CIP_NAME_CONFLICT: return E_ABORT;
case CIP_EXE_SELF_REGISTERATION_TIMEOUT: return S_OK;
case CIP_TRUST_VERIFICATION_COMPONENT_MISSING: return E_ABORT;
case CIP_UNSAFE_TO_ABORT: return S_OK;
default: return E_ABORT; }
return S_OK; }
|