//------------------------------------------------------------------------------------------------- // // 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. // //------------------------------------------------------------------------------------------------- #include #include #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(this); } else if (::IsEqualIID(IID_IUnknown, riid)) { *ppvObject = static_cast(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; };