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.
289 lines
6.8 KiB
289 lines
6.8 KiB
#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;
|
|
}
|
|
|