601 lines
17 KiB
C++
601 lines
17 KiB
C++
//-------------------------------------------------------------------------------------------------
|
|
// <copyright file="BalBaseBootstrapperApplication.h" company="Outercurve Foundation">
|
|
// Copyright (c) 2004, Outercurve Foundation.
|
|
// This software is released under Microsoft Reciprocal License (MS-RL).
|
|
// The license and further copyright text can be found in the file
|
|
// LICENSE.TXT at the root directory of the distribution.
|
|
// </copyright>
|
|
//-------------------------------------------------------------------------------------------------
|
|
|
|
#include <windows.h>
|
|
#include <msiquery.h>
|
|
|
|
#include "IBootstrapperEngine.h"
|
|
#include "IBootstrapperApplication.h"
|
|
|
|
#include "balutil.h"
|
|
#include "balretry.h"
|
|
|
|
class CBalBaseBootstrapperApplication : public IBootstrapperApplication
|
|
{
|
|
public: // IUnknown
|
|
virtual STDMETHODIMP QueryInterface(
|
|
__in REFIID riid,
|
|
__out LPVOID *ppvObject
|
|
)
|
|
{
|
|
if (!ppvObject)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*ppvObject = NULL;
|
|
|
|
if (::IsEqualIID(__uuidof(IBootstrapperApplication), riid))
|
|
{
|
|
*ppvObject = static_cast<IBootstrapperApplication*>(this);
|
|
}
|
|
else if (::IsEqualIID(IID_IUnknown, riid))
|
|
{
|
|
*ppvObject = static_cast<IUnknown*>(this);
|
|
}
|
|
else // no interface for requested iid
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(ULONG) AddRef()
|
|
{
|
|
return ::InterlockedIncrement(&this->m_cReferences);
|
|
}
|
|
|
|
virtual STDMETHODIMP_(ULONG) Release()
|
|
{
|
|
long l = ::InterlockedDecrement(&this->m_cReferences);
|
|
if (0 < l)
|
|
{
|
|
return l;
|
|
}
|
|
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
public: // IBurnUserExperience
|
|
virtual STDMETHODIMP OnStartup()
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnShutdown()
|
|
{
|
|
return IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnSystemShutdown(
|
|
__in DWORD dwEndSession,
|
|
__in int /*nRecommendation*/
|
|
)
|
|
{
|
|
// Allow requests to shut down when critical or not applying.
|
|
if (ENDSESSION_CRITICAL & dwEndSession || !m_fApplying)
|
|
{
|
|
return IDOK;
|
|
}
|
|
|
|
return IDCANCEL;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnDetectBegin(
|
|
__in BOOL /*fInstalled*/,
|
|
__in DWORD /*cPackages*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnDetectForwardCompatibleBundle(
|
|
__in_z LPCWSTR /*wzBundleId*/,
|
|
__in BOOTSTRAPPER_RELATION_TYPE /*relationType*/,
|
|
__in_z LPCWSTR /*wzBundleTag*/,
|
|
__in BOOL /*fPerMachine*/,
|
|
__in DWORD64 /*dw64Version*/,
|
|
__in int nRecommendation
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : nRecommendation;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnDetectUpdateBegin(
|
|
__in_z LPCWSTR /*wzUpdateLocation*/,
|
|
__in int nRecommendation
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : nRecommendation;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(void) OnDetectUpdateComplete(
|
|
__in HRESULT /*hrStatus*/,
|
|
__in_z_opt LPCWSTR /*wzUpdateLocation*/
|
|
)
|
|
{
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnDetectPriorBundle(
|
|
__in_z LPCWSTR /*wzBundleId*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnDetectPackageBegin(
|
|
__in_z LPCWSTR /*wzPackageId*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnDetectRelatedBundle(
|
|
__in_z LPCWSTR /*wzBundleId*/,
|
|
__in BOOTSTRAPPER_RELATION_TYPE /*relationType*/,
|
|
__in_z LPCWSTR /*wzBundleTag*/,
|
|
__in BOOL /*fPerMachine*/,
|
|
__in DWORD64 /*dw64Version*/,
|
|
__in BOOTSTRAPPER_RELATED_OPERATION /*operation*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnDetectRelatedMsiPackage(
|
|
__in_z LPCWSTR /*wzPackageId*/,
|
|
__in_z LPCWSTR /*wzProductCode*/,
|
|
__in BOOL /*fPerMachine*/,
|
|
__in DWORD64 /*dw64Version*/,
|
|
__in BOOTSTRAPPER_RELATED_OPERATION /*operation*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnDetectTargetMsiPackage(
|
|
__in_z LPCWSTR /*wzPackageId*/,
|
|
__in_z LPCWSTR /*wzProductCode*/,
|
|
__in BOOTSTRAPPER_PACKAGE_STATE /*patchState*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnDetectMsiFeature(
|
|
__in_z LPCWSTR /*wzPackageId*/,
|
|
__in_z LPCWSTR /*wzFeatureId*/,
|
|
__in BOOTSTRAPPER_FEATURE_STATE /*state*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(void) OnDetectPackageComplete(
|
|
__in_z LPCWSTR /*wzPackageId*/,
|
|
__in HRESULT /*hrStatus*/,
|
|
__in BOOTSTRAPPER_PACKAGE_STATE /*state*/
|
|
)
|
|
{
|
|
}
|
|
|
|
virtual STDMETHODIMP_(void) OnDetectComplete(
|
|
__in HRESULT /*hrStatus*/
|
|
)
|
|
{
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnPlanBegin(
|
|
__in DWORD /*cPackages*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnPlanRelatedBundle(
|
|
__in_z LPCWSTR /*wzBundleId*/,
|
|
__inout BOOTSTRAPPER_REQUEST_STATE* /*pRequestedState*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnPlanPackageBegin(
|
|
__in_z LPCWSTR /*wzPackageId*/,
|
|
__inout BOOTSTRAPPER_REQUEST_STATE* /*pRequestState*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnPlanTargetMsiPackage(
|
|
__in_z LPCWSTR /*wzPackageId*/,
|
|
__in_z LPCWSTR /*wzProductCode*/,
|
|
__inout BOOTSTRAPPER_REQUEST_STATE* /*pRequestedState*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnPlanMsiFeature(
|
|
__in_z LPCWSTR /*wzPackageId*/,
|
|
__in_z LPCWSTR /*wzFeatureId*/,
|
|
__inout BOOTSTRAPPER_FEATURE_STATE* /*pRequestedState*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(void) OnPlanPackageComplete(
|
|
__in_z LPCWSTR /*wzPackageId*/,
|
|
__in HRESULT /*hrStatus*/,
|
|
__in BOOTSTRAPPER_PACKAGE_STATE /*state*/,
|
|
__in BOOTSTRAPPER_REQUEST_STATE /*requested*/,
|
|
__in BOOTSTRAPPER_ACTION_STATE /*execute*/,
|
|
__in BOOTSTRAPPER_ACTION_STATE /*rollback*/
|
|
)
|
|
{
|
|
}
|
|
|
|
virtual STDMETHODIMP_(void) OnPlanComplete(
|
|
__in HRESULT /*hrStatus*/
|
|
)
|
|
{
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnApplyBegin()
|
|
{
|
|
m_fApplying = TRUE;
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnElevate()
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnRegisterBegin()
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(void) OnRegisterComplete(
|
|
__in HRESULT /*hrStatus*/
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(void) OnUnregisterBegin()
|
|
{
|
|
return;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(void) OnUnregisterComplete(
|
|
__in HRESULT /*hrStatus*/
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnApplyComplete(
|
|
__in HRESULT /*hrStatus*/,
|
|
__in BOOTSTRAPPER_APPLY_RESTART restart
|
|
)
|
|
{
|
|
m_fApplying = FALSE;
|
|
return BOOTSTRAPPER_APPLY_RESTART_REQUIRED == restart ? IDRESTART : CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnCacheBegin()
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnCachePackageBegin(
|
|
__in_z LPCWSTR /*wzPackageId*/,
|
|
__in DWORD /*cCachePayloads*/,
|
|
__in DWORD64 /*dw64PackageCacheSize*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnCacheAcquireBegin(
|
|
__in_z LPCWSTR wzPackageOrContainerId,
|
|
__in_z_opt LPCWSTR wzPayloadId,
|
|
__in BOOTSTRAPPER_CACHE_OPERATION /*operation*/,
|
|
__in_z LPCWSTR /*wzSource*/
|
|
)
|
|
{
|
|
BalRetryStartPackage(BALRETRY_TYPE_CACHE, wzPackageOrContainerId, wzPayloadId);
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnCacheAcquireProgress(
|
|
__in_z LPCWSTR /*wzPackageOrContainerId*/,
|
|
__in_z_opt LPCWSTR /*wzPayloadId*/,
|
|
__in DWORD64 /*dw64Progress*/,
|
|
__in DWORD64 /*dw64Total*/,
|
|
__in DWORD /*dwOverallPercentage*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnCacheAcquireComplete(
|
|
__in_z LPCWSTR wzPackageOrContainerId,
|
|
__in_z_opt LPCWSTR wzPayloadId,
|
|
__in HRESULT hrStatus,
|
|
__in int nRecommendation
|
|
)
|
|
{
|
|
int nResult = CheckCanceled() ? IDCANCEL : BalRetryEndPackage(BALRETRY_TYPE_CACHE, wzPackageOrContainerId, wzPayloadId, hrStatus);
|
|
return IDNOACTION == nResult ? nRecommendation : nResult;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnCacheVerifyBegin(
|
|
__in_z LPCWSTR /*wzPackageId*/,
|
|
__in_z LPCWSTR /*wzPayloadId*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnCacheVerifyComplete(
|
|
__in_z LPCWSTR /*wzPackageId*/,
|
|
__in_z LPCWSTR /*wzPayloadId*/,
|
|
__in HRESULT /*hrStatus*/,
|
|
__in int nRecommendation
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : nRecommendation;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnCachePackageComplete(
|
|
__in_z LPCWSTR /*wzPackageId*/,
|
|
__in HRESULT /*hrStatus*/,
|
|
__in int nRecommendation
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : nRecommendation;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(void) OnCacheComplete(
|
|
__in HRESULT /*hrStatus*/
|
|
)
|
|
{
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnExecuteBegin(
|
|
__in DWORD /*cExecutingPackages*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnExecutePackageBegin(
|
|
__in_z LPCWSTR wzPackageId,
|
|
__in BOOL fExecute
|
|
)
|
|
{
|
|
// Only track retry on execution (not rollback).
|
|
if (fExecute)
|
|
{
|
|
BalRetryStartPackage(BALRETRY_TYPE_EXECUTE, wzPackageId, NULL);
|
|
}
|
|
|
|
m_fRollingBack = !fExecute;
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnExecutePatchTarget(
|
|
__in_z LPCWSTR /*wzPackageId*/,
|
|
__in_z LPCWSTR /*wzTargetProductCode*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnError(
|
|
__in BOOTSTRAPPER_ERROR_TYPE errorType,
|
|
__in_z LPCWSTR wzPackageId,
|
|
__in DWORD dwCode,
|
|
__in_z LPCWSTR /*wzError*/,
|
|
__in DWORD /*dwUIHint*/,
|
|
__in DWORD /*cData*/,
|
|
__in_ecount_z_opt(cData) LPCWSTR* /*rgwzData*/,
|
|
__in int nRecommendation
|
|
)
|
|
{
|
|
BalRetryErrorOccurred(wzPackageId, dwCode);
|
|
|
|
if (BOOTSTRAPPER_DISPLAY_FULL == m_display)
|
|
{
|
|
if (BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_SERVER == errorType ||BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_PROXY == errorType)
|
|
{
|
|
nRecommendation = IDTRYAGAIN;
|
|
}
|
|
}
|
|
|
|
return CheckCanceled() ? IDCANCEL : nRecommendation;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnProgress(
|
|
__in DWORD /*dwProgressPercentage*/,
|
|
__in DWORD /*dwOverallProgressPercentage*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnDownloadPayloadBegin(
|
|
__in_z LPCWSTR /*wzPayloadId*/,
|
|
__in_z LPCWSTR /*wzPayloadFileName*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnDownloadPayloadComplete(
|
|
__in_z LPCWSTR /*wzPayloadId*/,
|
|
__in_z LPCWSTR /*wzPayloadFileName*/,
|
|
__in HRESULT /*hrStatus*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnExecuteProgress(
|
|
__in_z LPCWSTR /*wzPackageId*/,
|
|
__in DWORD /*dwProgressPercentage*/,
|
|
__in DWORD /*dwOverallProgressPercentage*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnExecuteMsiMessage(
|
|
__in_z LPCWSTR /*wzPackageId*/,
|
|
__in INSTALLMESSAGE /*mt*/,
|
|
__in UINT /*uiFlags*/,
|
|
__in_z LPCWSTR /*wzMessage*/,
|
|
__in DWORD /*cData*/,
|
|
__in_ecount_z_opt(cData) LPCWSTR* /*rgwzData*/,
|
|
__in int nRecommendation
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : nRecommendation;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnExecuteFilesInUse(
|
|
__in_z LPCWSTR /*wzPackageId*/,
|
|
__in DWORD /*cFiles*/,
|
|
__in_ecount_z(cFiles) LPCWSTR* /*rgwzFiles*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnExecutePackageComplete(
|
|
__in_z LPCWSTR wzPackageId,
|
|
__in HRESULT hrExitCode,
|
|
__in BOOTSTRAPPER_APPLY_RESTART /*restart*/,
|
|
__in int nRecommendation
|
|
)
|
|
{
|
|
int nResult = CheckCanceled() ? IDCANCEL : CheckCanceled() ? IDCANCEL : BalRetryEndPackage(BALRETRY_TYPE_EXECUTE, wzPackageId, NULL, hrExitCode);
|
|
return IDNOACTION == nResult ? nRecommendation : nResult;
|
|
}
|
|
|
|
virtual STDMETHODIMP_(void) OnExecuteComplete(
|
|
__in HRESULT /*hrStatus*/
|
|
)
|
|
{
|
|
}
|
|
|
|
virtual STDMETHODIMP_(int) OnResolveSource(
|
|
__in_z LPCWSTR /*wzPackageOrContainerId*/,
|
|
__in_z_opt LPCWSTR /*wzPayloadId*/,
|
|
__in_z LPCWSTR /*wzLocalSource*/,
|
|
__in_z_opt LPCWSTR /*wzDownloadSource*/
|
|
)
|
|
{
|
|
return CheckCanceled() ? IDCANCEL : IDNOACTION;
|
|
}
|
|
|
|
protected:
|
|
//
|
|
// PromptCancel - prompts the user to close (if not forced).
|
|
//
|
|
virtual BOOL PromptCancel(
|
|
__in HWND hWnd,
|
|
__in BOOL fForceCancel,
|
|
__in_z LPCWSTR wzMessage,
|
|
__in_z LPCWSTR wzCaption
|
|
)
|
|
{
|
|
::EnterCriticalSection(&m_csCanceled);
|
|
|
|
// Only prompt the user to close if we have not canceled already.
|
|
if (!m_fCanceled)
|
|
{
|
|
if (fForceCancel)
|
|
{
|
|
m_fCanceled = TRUE;
|
|
}
|
|
else
|
|
{
|
|
m_fCanceled = (IDYES == ::MessageBoxW(hWnd, wzMessage, wzCaption, MB_YESNO | MB_ICONEXCLAMATION));
|
|
}
|
|
}
|
|
|
|
::LeaveCriticalSection(&m_csCanceled);
|
|
|
|
return m_fCanceled;
|
|
}
|
|
|
|
//
|
|
// CheckCanceled - waits if the cancel dialog is up and checks to see if the user canceled the operation.
|
|
//
|
|
BOOL CheckCanceled()
|
|
{
|
|
::EnterCriticalSection(&m_csCanceled);
|
|
::LeaveCriticalSection(&m_csCanceled);
|
|
return m_fRollingBack ? FALSE : m_fCanceled;
|
|
}
|
|
|
|
BOOL IsRollingBack()
|
|
{
|
|
return m_fRollingBack;
|
|
}
|
|
|
|
BOOL IsCanceled()
|
|
{
|
|
return m_fCanceled;
|
|
}
|
|
|
|
CBalBaseBootstrapperApplication(
|
|
__in IBootstrapperEngine* /*pEngine*/,
|
|
__in const BOOTSTRAPPER_COMMAND* pCommand,
|
|
__in DWORD dwRetryCount = 0,
|
|
__in DWORD dwRetryTimeout = 1000
|
|
)
|
|
{
|
|
m_cReferences = 1;
|
|
m_display = pCommand->display;
|
|
m_restart = pCommand->restart;
|
|
|
|
::InitializeCriticalSection(&m_csCanceled);
|
|
m_fCanceled = FALSE;
|
|
m_fApplying = FALSE;
|
|
m_fRollingBack = FALSE;
|
|
|
|
BalRetryInitialize(dwRetryCount, dwRetryTimeout);
|
|
}
|
|
|
|
virtual ~CBalBaseBootstrapperApplication()
|
|
{
|
|
BalRetryUninitialize();
|
|
::DeleteCriticalSection(&m_csCanceled);
|
|
}
|
|
|
|
private:
|
|
long m_cReferences;
|
|
BOOTSTRAPPER_DISPLAY m_display;
|
|
BOOTSTRAPPER_RESTART m_restart;
|
|
|
|
CRITICAL_SECTION m_csCanceled;
|
|
BOOL m_fCanceled;
|
|
BOOL m_fApplying;
|
|
BOOL m_fRollingBack;
|
|
};
|