// Berkeley Open Infrastructure for Network Computing // http://boinc.berkeley.edu // Copyright (C) 2005 University of California // // This is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; // either version 2.1 of the License, or (at your option) any later version. // // This software is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU Lesser General Public License for more details. // // To view the GNU Lesser General Public License visit // http://www.gnu.org/copyleft/lesser.html // or write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // #include "stdafx.h" #include "boinccas.h" ///////////////////////////////////////////////////////////////////// // // Function: BOINCCABase::BOINCCABase // // Description: Initialize the Custom Action infrastructure. // ///////////////////////////////////////////////////////////////////// BOINCCABase::BOINCCABase( MSIHANDLE hMSIHandle, const tstring strActionName, const tstring strProgressTitle ) { // Store the parameters for later use m_hMSIHandle = hMSIHandle; m_strActionName = strActionName; m_strProgressTitle = strProgressTitle; // Initialize all other values to zero or null m_phActionStartRec = NULL; m_phActionDataRec = NULL; m_phProgressRec = NULL; m_phLogInfoRec = NULL; } ///////////////////////////////////////////////////////////////////// // // Function: BOINCCABase::~BOINCCABase // // Description: Cleanup up allocation resources. // ///////////////////////////////////////////////////////////////////// BOINCCABase::~BOINCCABase() { if (m_phActionStartRec) { MsiCloseHandle(m_phActionStartRec); m_phActionStartRec = NULL; } if (m_phActionDataRec) { MsiCloseHandle(m_phActionDataRec); m_phActionDataRec = NULL; } if (m_phProgressRec) { MsiCloseHandle(m_phProgressRec); m_phProgressRec = NULL; } if (m_phLogInfoRec) { MsiCloseHandle(m_phLogInfoRec); m_phLogInfoRec = NULL; } m_strActionName.clear(); m_strProgressTitle.clear(); } ///////////////////////////////////////////////////////////////////// // // Function: Execute // // Description: // ///////////////////////////////////////////////////////////////////// UINT BOINCCABase::Execute() { UINT uiReturnValue = 0; OnInitialize(); if ( TRUE == MsiGetMode( m_hMSIHandle, MSIRUNMODE_SCHEDULED ) ) { uiReturnValue = OnInstall(); } else if ( TRUE == MsiGetMode( m_hMSIHandle, MSIRUNMODE_COMMIT ) ) { uiReturnValue = OnCommit(); } else if ( TRUE == MsiGetMode( m_hMSIHandle, MSIRUNMODE_ROLLBACK ) ) { uiReturnValue = OnRollback(); } else { uiReturnValue = OnExecution(); } OnCleanup(); return uiReturnValue; } static BOOL IsVersionNewer(const tstring v1, const tstring v2) { int v1_maj=0, v1_min=0, v1_rel=0; int v2_maj=0, v2_min=0, v2_rel=0; _stscanf(v1.c_str(), _T("%d.%d.%d"), &v1_maj, &v1_min, &v1_rel); _stscanf(v2.c_str(), _T("%d.%d.%d"), &v2_maj, &v2_min, &v2_rel); if (v1_maj > v2_maj) return TRUE; if (v1_maj < v2_maj) return FALSE; if (v1_min > v2_min) return TRUE; if (v1_min < v2_min) return FALSE; if (v1_rel > v2_rel) return TRUE; return FALSE; } ///////////////////////////////////////////////////////////////////// // // Function: SetUpgradeParameters // // Description: // ///////////////////////////////////////////////////////////////////// UINT BOINCCABase::SetUpgradeParameters() { tstring strCurrentProductVersion; UINT uiReturnValue = 0; uiReturnValue = GetProperty( _T("ProductVersion"), strCurrentProductVersion ); if ( uiReturnValue ) return uiReturnValue; uiReturnValue = SetRegistryValue( _T("UpgradingTo"), strCurrentProductVersion ); if ( uiReturnValue ) return uiReturnValue; return ERROR_SUCCESS; } ///////////////////////////////////////////////////////////////////// // // Function: IsUpgrading // // Description: // ///////////////////////////////////////////////////////////////////// BOOL BOINCCABase::IsUpgrading() { tstring strCurrentProductVersion; tstring strRegistryProductVersion; UINT uiReturnValue = 0; uiReturnValue = GetProperty( _T("ProductVersion"), strCurrentProductVersion ); if ( uiReturnValue ) return FALSE; uiReturnValue = GetRegistryValue( _T("UpgradingTo"), strRegistryProductVersion ); if ( uiReturnValue ) return FALSE; return IsVersionNewer(strRegistryProductVersion, strCurrentProductVersion); } ///////////////////////////////////////////////////////////////////// // // Function: OnInitialize // // Description: // ///////////////////////////////////////////////////////////////////// UINT BOINCCABase::OnInitialize() { UINT uiReturnValue = 0; m_phActionStartRec = MsiCreateRecord(3); assert(NULL != m_phActionStartRec); MsiRecordSetString(m_phActionStartRec, 1, m_strActionName.c_str()); MsiRecordSetString(m_phActionStartRec, 2, m_strProgressTitle.c_str()); MsiRecordSetString(m_phActionStartRec, 3, _T("[1]")); uiReturnValue = MsiProcessMessage(m_hMSIHandle, INSTALLMESSAGE_ACTIONSTART, m_phActionStartRec); if ((uiReturnValue == IDCANCEL)) return ERROR_INSTALL_USEREXIT; // Give the UI a chance to refresh. Sleep(0); m_phActionDataRec = MsiCreateRecord(3); assert(NULL != m_phActionDataRec); m_phProgressRec = MsiCreateRecord(3); assert(NULL != m_phProgressRec); MsiRecordSetInteger(m_phProgressRec, 1, 1); MsiRecordSetInteger(m_phProgressRec, 2, 1); MsiRecordSetInteger(m_phProgressRec, 3, 0); uiReturnValue = MsiProcessMessage(m_hMSIHandle, INSTALLMESSAGE_PROGRESS, m_phProgressRec); if ((uiReturnValue == IDCANCEL)) return ERROR_INSTALL_USEREXIT; m_phLogInfoRec = MsiCreateRecord(3); assert(NULL != m_phLogInfoRec); MsiRecordSetString (m_phLogInfoRec, 0, _T("Custom Message : Action Name: [1] Description: [2] Error Code: [3] ")); MsiRecordSetString (m_phLogInfoRec, 1, m_strActionName.c_str()); LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, NULL, _T("Starting Custom Action") ); return ERROR_SUCCESS; } ///////////////////////////////////////////////////////////////////// // // Function: OnCleanup // // Description: // ///////////////////////////////////////////////////////////////////// UINT BOINCCABase::OnCleanup() { return ERROR_SUCCESS; } ///////////////////////////////////////////////////////////////////// // // Function: OnInstall // // Description: // ///////////////////////////////////////////////////////////////////// UINT BOINCCABase::OnInstall() { return ERROR_SUCCESS; } ///////////////////////////////////////////////////////////////////// // // Function: OnRollback // // Description: // ///////////////////////////////////////////////////////////////////// UINT BOINCCABase::OnRollback() { return ERROR_SUCCESS; } ///////////////////////////////////////////////////////////////////// // // Function: OnCommit // // Description: // ///////////////////////////////////////////////////////////////////// UINT BOINCCABase::OnCommit() { return ERROR_SUCCESS; } ///////////////////////////////////////////////////////////////////// // // Function: OnExecution // // Description: // ///////////////////////////////////////////////////////////////////// UINT BOINCCABase::OnExecution() { return ERROR_SUCCESS; } ///////////////////////////////////////////////////////////////////// // // Function: GetRegistryValue // // Description: // ///////////////////////////////////////////////////////////////////// UINT BOINCCABase::GetRegistryValue( const tstring strName, tstring& strValue, bool bDisplayValue ) { LONG lReturnValue; HKEY hkSetupHive; DWORD dwSize = 0; LPTSTR lpszRegistryValue = NULL; tstring strMessage; lReturnValue = RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Space Sciences Laboratory, U.C. Berkeley\\BOINC Setup"), 0, KEY_READ, &hkSetupHive ); if (lReturnValue != ERROR_SUCCESS) return ERROR_INSTALL_FAILURE; // How large does our buffer need to be? RegQueryValueEx( hkSetupHive, strName.c_str(), NULL, NULL, NULL, &dwSize ); // Allocate the buffer space. lpszRegistryValue = (LPTSTR) malloc(dwSize); (*lpszRegistryValue) = NULL; // Now get the data lReturnValue = RegQueryValueEx( hkSetupHive, strName.c_str(), NULL, NULL, (LPBYTE)lpszRegistryValue, &dwSize ); // Send up the returned value. if (lReturnValue == ERROR_SUCCESS) strValue = lpszRegistryValue; // Cleanup RegCloseKey(hkSetupHive); free(lpszRegistryValue); // One last check to make sure everything is on the up and up. if (lReturnValue != ERROR_SUCCESS) return ERROR_INSTALL_FAILURE; strMessage = _T("Successfully retrieved registry value '") + strName; strMessage += _T("' with a value of '"); if (bDisplayValue) strMessage += strValue; else strMessage += _T("