boinc/win_build/installerv2/redist/Windows/src/boinccas/CAMigrateBOINCData.cpp

1125 lines
36 KiB
C++

// 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"
#include "CAMigrateBOINCData.h"
#include "dirops.h"
#define CUSTOMACTION_NAME _T("CAMigrateBOINCData")
#define CUSTOMACTION_PROGRESSTITLE _T("Migrate application data to the data directory.")
/////////////////////////////////////////////////////////////////////
//
// Function:
//
// Description:
//
/////////////////////////////////////////////////////////////////////
CAMigrateBOINCData::CAMigrateBOINCData(MSIHANDLE hMSIHandle) :
BOINCCABase(hMSIHandle, CUSTOMACTION_NAME, CUSTOMACTION_PROGRESSTITLE)
{}
/////////////////////////////////////////////////////////////////////
//
// Function:
//
// Description:
//
/////////////////////////////////////////////////////////////////////
CAMigrateBOINCData::~CAMigrateBOINCData()
{
BOINCCABase::~BOINCCABase();
}
/////////////////////////////////////////////////////////////////////
//
// Function:
//
// Description:
//
/////////////////////////////////////////////////////////////////////
UINT CAMigrateBOINCData::OnInstall()
{
tstring strCustomActionData;
tstring strMigratingDirectory;
tstring strInstallDirectory;
tstring strDataDirectory;
tstring strMessage;
ULONGLONG ullFileSize = 0;
ULONGLONG ullDirectorySize = 0;
ULONGLONG ullBytesTransfered = 0;
UINT uiReturnValue = -1;
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("CAMigrateBOINCData::OnInstall -- Function Begin")
);
// CustomActionData is a pipe seperated string which contains whether
// this interation of the installer is migrating the BOINC data, the
// installer directory, and the data directory.
//
// Ex: <MigrationStatus>|<InstallDirectory>|<DataDrectory>
//
uiReturnValue = GetProperty( _T("CustomActionData"), strCustomActionData );
if ( uiReturnValue ) return uiReturnValue;
strMigratingDirectory =
strCustomActionData.substr(0, strCustomActionData.find(_T("|")));
strMessage = _T("CAMigrateBOINCData::OnInstall -- strMigratingDirectory: '");
strMessage += strMigratingDirectory;
strMessage += _T("'");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
strMessage.c_str()
);
strInstallDirectory =
strCustomActionData.substr(
strCustomActionData.find(_T("|")) + 1,
strCustomActionData.find(_T("|"), (strCustomActionData.find(_T("|")) + 1)) - 5
);
strMessage = _T("CAMigrateBOINCData::OnInstall -- strInstallDirectory: '");
strMessage += strInstallDirectory;
strMessage += _T("'");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
strMessage.c_str()
);
strDataDirectory =
strCustomActionData.substr(strCustomActionData.rfind(_T("|")) + 1, strCustomActionData.length() - strCustomActionData.rfind(_T("|")) - 1);
strMessage = _T("CAMigrateBOINCData::OnInstall -- strDataDirectory: '");
strMessage += strDataDirectory;
strMessage += _T("'");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
strMessage.c_str()
);
// Are we migrating data?
if ( _T("TRUE") == strMigratingDirectory )
{
// Determine how we should setup the progress bar.
GetFileDirectorySizes( strInstallDirectory, ullFileSize, ullDirectorySize );
// Reset the progress bar
MsiRecordSetInteger(m_phProgressRec, 1, 0);
MsiRecordSetInteger(m_phProgressRec, 2, (INT)((ullDirectorySize/1024)/1024));
MsiRecordSetInteger(m_phProgressRec, 3, 0);
MsiProcessMessage(m_hMSIHandle, INSTALLMESSAGE_PROGRESS, m_phProgressRec);
// Tell the installer to use explicit progress messages.
MsiRecordSetInteger(m_phProgressRec, 1, 1);
MsiRecordSetInteger(m_phProgressRec, 2, 1);
MsiRecordSetInteger(m_phProgressRec, 3, 0);
MsiProcessMessage(m_hMSIHandle, INSTALLMESSAGE_PROGRESS, m_phProgressRec);
// Migrate the data files
if (!MoveFiles( strInstallDirectory, strDataDirectory, ullBytesTransfered ))
{
LogMessage(
INSTALLMESSAGE_FATALEXIT,
NULL,
NULL,
NULL,
NULL,
_T("Failed to migrate BOINC data files to the data directory.")
);
return ERROR_INSTALL_FAILURE;
}
}
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("CAMigrateBOINCData::OnInstall -- Function End")
);
return ERROR_SUCCESS;
}
/////////////////////////////////////////////////////////////////////
//
// Function:
//
// Description:
//
/////////////////////////////////////////////////////////////////////
UINT CAMigrateBOINCData::OnRollback()
{
tstring strCustomActionData;
tstring strMigratingDirectory;
tstring strInstallDirectory;
tstring strDataDirectory;
tstring strMessage;
ULONGLONG ullFileSize = 0;
ULONGLONG ullDirectorySize = 0;
ULONGLONG ullBytesTransfered = 0;
UINT uiReturnValue = -1;
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("CAMigrateBOINCData::OnRollback -- Function Begin")
);
// CustomActionData is a pipe seperated string which contains whether
// this interation of the installer is migrating the BOINC data, the
// installer directory, and the data directory.
//
// Ex: <MigrationStatus>|<InstallDirectory>|<DataDrectory>
//
uiReturnValue = GetProperty( _T("CustomActionData"), strCustomActionData );
if ( uiReturnValue ) return uiReturnValue;
strMigratingDirectory =
strCustomActionData.substr(0, strCustomActionData.find(_T("|")));
strMessage = _T("CAMigrateBOINCData::OnRollback -- strMigratingDirectory: '");
strMessage += strMigratingDirectory;
strMessage += _T("'");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
strMessage.c_str()
);
strInstallDirectory =
strCustomActionData.substr(
strCustomActionData.find(_T("|")) + 1,
strCustomActionData.find(_T("|"), (strCustomActionData.find(_T("|")) + 1)) - 5
);
strMessage = _T("CAMigrateBOINCData::OnRollback -- strInstallDirectory: '");
strMessage += strInstallDirectory;
strMessage += _T("'");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
strMessage.c_str()
);
strDataDirectory =
strCustomActionData.substr(strCustomActionData.rfind(_T("|")) + 1, strCustomActionData.length() - strCustomActionData.rfind(_T("|")) - 1);
strMessage = _T("CAMigrateBOINCData::OnRollback -- strDataDirectory: '");
strMessage += strDataDirectory;
strMessage += _T("'");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
strMessage.c_str()
);
// Are we migrating data?
if ( _T("TRUE") == strMigratingDirectory )
{
// Determine how we should setup the progress bar.
GetFileDirectorySizes( strInstallDirectory, ullFileSize, ullDirectorySize );
// Reset the progress bar
MsiRecordSetInteger(m_phProgressRec, 1, 0);
MsiRecordSetInteger(m_phProgressRec, 2, (INT)((ullDirectorySize/1024)/1024));
MsiRecordSetInteger(m_phProgressRec, 3, 0);
MsiProcessMessage(m_hMSIHandle, INSTALLMESSAGE_PROGRESS, m_phProgressRec);
// Tell the installer to use explicit progress messages.
MsiRecordSetInteger(m_phProgressRec, 1, 1);
MsiRecordSetInteger(m_phProgressRec, 2, 1);
MsiRecordSetInteger(m_phProgressRec, 3, 0);
MsiProcessMessage(m_hMSIHandle, INSTALLMESSAGE_PROGRESS, m_phProgressRec);
// Migrate the data files back to the original location
MoveFiles( strDataDirectory, strInstallDirectory, ullBytesTransfered );
}
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("CAMigrateBOINCData::OnRollback -- Function End")
);
return ERROR_SUCCESS;
}
/////////////////////////////////////////////////////////////////////
//
// Function:
//
// Description:
//
/////////////////////////////////////////////////////////////////////
UINT CAMigrateBOINCData::OnExecution()
{
tstring strCustomActionData;
tstring strCurrentInstallDirectory;
tstring strFutureInstallDirectory;
tstring strCurrentDataDirectory;
tstring strFutureDataDirectory;
tstring strMigration;
tstring strMigrationVersion;
tstring strMigrationDirectory;
tstring strDestinationClientStateFile;
tstring strRemove;
tstring strProductVersion;
tstring strWindowsDirectory;
tstring strWindowsSystemDirectory;
tstring strProgramFilesDirectory;
tstring strSystemDrive;
tstring strVersionWindows64;
struct _stat buf;
ULONGLONG ullFileSize = 0;
ULONGLONG ullDirectorySize = 0;
ULONGLONG ullFreeDiskSpace = 0;
UINT uiReturnValue = -1;
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("CAMigrateBOINCData::OnExecution -- Function Begin")
);
GetRegistryValue( _T("INSTALLDIR"), strCurrentInstallDirectory );
uiReturnValue = GetProperty( _T("INSTALLDIR"), strFutureInstallDirectory );
if ( uiReturnValue ) return uiReturnValue;
uiReturnValue = GetProperty( _T("DATADIR"), strFutureDataDirectory );
if ( uiReturnValue ) return uiReturnValue;
uiReturnValue = GetRegistryValue( _T("MIGRATION"), strMigration );
uiReturnValue = GetRegistryValue( _T("MIGRATIONVERSION"), strMigrationVersion );
uiReturnValue = GetRegistryValue( _T("MIGRATIONDIR"), strMigrationDirectory );
uiReturnValue = GetProperty( _T("REMOVE"), strRemove );
if ( uiReturnValue ) return uiReturnValue;
uiReturnValue = GetProperty( _T("ProductVersion"), strProductVersion );
if ( uiReturnValue ) return uiReturnValue;
uiReturnValue = GetProperty( _T("VersionNT64"), strVersionWindows64 );
if ( uiReturnValue ) return uiReturnValue;
uiReturnValue = GetProperty( _T("WindowsFolder"), strWindowsDirectory );
if ( uiReturnValue ) return uiReturnValue;
uiReturnValue = GetProperty( _T("WindowsVolume"), strSystemDrive );
if ( uiReturnValue ) return uiReturnValue;
if (strVersionWindows64.length() > 0)
{
uiReturnValue = GetProperty( _T("System64Folder"), strWindowsSystemDirectory );
if ( uiReturnValue ) return uiReturnValue;
uiReturnValue = GetProperty( _T("ProgramFiles64Folder"), strProgramFilesDirectory );
if ( uiReturnValue ) return uiReturnValue;
}
else
{
uiReturnValue = GetProperty( _T("SystemFolder"), strWindowsSystemDirectory );
if ( uiReturnValue ) return uiReturnValue;
uiReturnValue = GetProperty( _T("ProgramFilesFolder"), strProgramFilesDirectory );
if ( uiReturnValue ) return uiReturnValue;
}
// If the REMOVE property is specified, then we are uninstalling BOINC
if (strRemove.length())
{
// If we successfully migrated, and the user is now uninstalling, they
// are probably going back to a 6.x client, so don't migrate the
// data back to the 5.x location.
//
strMigration = _T("FALSE");
strCustomActionData += strMigration + _T("|");
strCustomActionData += strMigrationDirectory + _T("|");
strCustomActionData += strFutureDataDirectory;
}
else
{
strDestinationClientStateFile = strFutureDataDirectory + _T("\\client_state.xml");
// Perform some basic sanity tests to see if we need to migrate
// anything.
BOOL bClientStateExists =
(BOOL)(0 == _stat(strDestinationClientStateFile.c_str(), &buf));
BOOL bInstallDataSameDirectory =
(BOOL)(strFutureInstallDirectory == strFutureDataDirectory);
BOOL bDataDirExistsWithinInstallDir =
(BOOL)(tstring::npos != strFutureDataDirectory.find(strFutureInstallDirectory));
BOOL bInstallDirWindowsDirSame =
(BOOL)(strFutureInstallDirectory == strWindowsDirectory);
BOOL bDataDirWindowsDirSame =
(BOOL)(strFutureDataDirectory == strWindowsDirectory);
BOOL bInstallDirSystemDriveSame =
(BOOL)(strFutureInstallDirectory == strSystemDrive);
BOOL bDataDirSystemDriveSame =
(BOOL)(strFutureDataDirectory == strSystemDrive);
BOOL bInstallDirWindowsSystemDirSame =
(BOOL)(strFutureInstallDirectory == strWindowsSystemDirectory);
BOOL bDataDirWindowsSystemDirSame =
(BOOL)(strFutureDataDirectory == strWindowsSystemDirectory);
BOOL bInstallDirProgramFilesDirSame =
(BOOL)(strFutureInstallDirectory == strProgramFilesDirectory);
BOOL bDataDirProgramFilesDirSame =
(BOOL)(strFutureDataDirectory == strProgramFilesDirectory);
if ( bClientStateExists )
{
strMigration = _T("FALSE");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("Data files already exists, skipping migration.")
);
}
else if ( bInstallDataSameDirectory )
{
strMigration = _T("FALSE");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("Install directory and data directory are the same, skipping migration.")
);
}
else if ( bDataDirExistsWithinInstallDir )
{
strMigration = _T("FALSE");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("Data drectory exists within the install directory, skipping migration.")
);
}
else if ( bInstallDirWindowsDirSame )
{
strMigration = _T("FALSE");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("Install directory is the same as the Windows directory, skipping migration.")
);
}
else if ( bDataDirWindowsDirSame )
{
strMigration = _T("FALSE");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("Data directory is the same as the Windows directory, skipping migration.")
);
}
else if ( bInstallDirSystemDriveSame )
{
strMigration = _T("FALSE");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("Install directory is the same as the system drive, skipping migration.")
);
}
else if ( bDataDirSystemDriveSame )
{
strMigration = _T("FALSE");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("Data directory is the same as the system drive, skipping migration.")
);
}
else if ( bInstallDirWindowsSystemDirSame )
{
strMigration = _T("FALSE");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("Install directory is the same as the Windows system directory, skipping migration.")
);
}
else if ( bDataDirWindowsSystemDirSame )
{
strMigration = _T("FALSE");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("Data directory is the same as the Windows system directory, skipping migration.")
);
}
else if ( bInstallDirProgramFilesDirSame )
{
strMigration = _T("FALSE");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("Install directory is the same as the program files directory, skipping migration.")
);
}
else if ( bDataDirProgramFilesDirSame )
{
strMigration = _T("FALSE");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("Data directory is the same as the program files directory, skipping migration.")
);
}
else
{
strMigration = _T("TRUE");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("Data files do NOT exist, performing migration.")
);
strMigrationDirectory = strCurrentInstallDirectory + _T("\\client_state.xml");
if (0 == _stat(strMigrationDirectory.c_str(), &buf)) {
strMigrationDirectory = strCurrentInstallDirectory;
} else {
strMigrationDirectory = strFutureInstallDirectory;
}
if ( GetFileDirectorySizes( strMigrationDirectory, ullFileSize, ullDirectorySize ) )
{
// The total amount of disk space required depends on whether or not
// the files in the original location are on the same volume as the
// destination. So do a quick check to see if we have enough disk
// space.
if (!GetFreeDiskSpace(strFutureDataDirectory, ullFreeDiskSpace))
{
// If the destination directory doesn't exist, try the parent
// directory
tstring strBuffer = tstring(strFutureDataDirectory + _T("..\\"));
if (!GetFreeDiskSpace(strBuffer, ullFreeDiskSpace))
{
// If the parent directory doesn't exist, just choose
// the default volume. Something is better than nothing
GetFreeDiskSpace(tstring(""), ullFreeDiskSpace);
}
}
// Are we on the same volume?
if (strMigrationDirectory.substr(0, 2) == strFutureDataDirectory.substr(0, 2))
{
// We only need the amount of free space as the largest file
// that is going to be transfered.
if (ullFileSize > ullFreeDiskSpace)
{
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("Not enough free disk space is available to migrate BOINC's data files to\n"
"the new data directory. Please free up some disk space or migrate the files\n"
"manually. (ullFileSize > ullFreeDiskSpace)")
);
return ERROR_INSTALL_FAILURE;
}
}
else
{
// We only need the amount of free space of the directory
// that is going to be transfered.
if (ullDirectorySize > ullFreeDiskSpace)
{
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("Not enough free disk space is available to migrate BOINC's data files to\n"
"the new data directory. Please free up some disk space or migrate the files\n"
"manually. (ullDirectorySize > ullFreeDiskSpace)")
);
return ERROR_INSTALL_FAILURE;
}
}
}
}
// Contruct a '|' delimited string to pass along to the install script
// and rollback script parts of this custom action.
strCustomActionData += strMigration + _T("|");
strCustomActionData += strMigrationDirectory + _T("|");
strCustomActionData += strFutureDataDirectory;
}
SetRegistryValue( _T("MIGRATION"), strMigration );
SetRegistryValue( _T("MIGRATIONDIR"), strMigrationDirectory );
SetProperty( _T("CAMigrateBOINCDataInstall"), strCustomActionData );
SetProperty( _T("CAMigrateBOINCDataRollback"), strCustomActionData );
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("CAMigrateBOINCData::OnExecution -- Function End")
);
return ERROR_SUCCESS;
}
/////////////////////////////////////////////////////////////////////
//
// Function:
//
// Description:
//
/////////////////////////////////////////////////////////////////////
BOOL CAMigrateBOINCData::GetFileDirectorySizes( tstring strDirectory, ULONGLONG& ullFileSize, ULONGLONG& ullDirectorySize )
{
WIN32_FIND_DATA ffData;
HANDLE hFind;
tstring csPathMask;
tstring csFullPath;
tstring csNewFullPath;
if ( _T("\\") != strDirectory.substr(strDirectory.length() - 1, 1) )
{
strDirectory += _T("\\");
}
csPathMask = strDirectory + _T("*.*");
hFind = FindFirstFile(csPathMask.c_str(), &ffData);
if (hFind == INVALID_HANDLE_VALUE){
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("CAMigrateBOINCData::GetFileDirectorySizes -- Invalid handle")
);
return FALSE;
}
// Calculating Sizes
while (hFind && FindNextFile(hFind, &ffData))
{
if( !(ffData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
{
csFullPath = strDirectory;
csFullPath += ffData.cFileName;
// Add current file size to the overall directory size
ullDirectorySize += ((ffData.nFileSizeHigh * MAXDWORD) + ffData.nFileSizeLow);
// If this file size is bigger than the one we know about, store it
// for later use.
if (ullFileSize < ((ffData.nFileSizeHigh * MAXDWORD) + ffData.nFileSizeLow)) {
ullFileSize = ((ffData.nFileSizeHigh * MAXDWORD) + ffData.nFileSizeLow);
}
}
else // it is a directory
{
csNewFullPath = strDirectory;
csNewFullPath += ffData.cFileName;
csNewFullPath += _T("\\");
if( (_tcscmp(ffData.cFileName, _T(".")) != 0) &&
(_tcscmp(ffData.cFileName, _T("..")) != 0) )
{
GetFileDirectorySizes(csNewFullPath, ullFileSize, ullDirectorySize);
}
}
}
FindClose(hFind);
return TRUE;
}
/////////////////////////////////////////////////////////////////////
//
// Function:
//
// Description:
//
/////////////////////////////////////////////////////////////////////
typedef BOOL (CALLBACK* MyGetDiskFreeSpaceEx)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
BOOL CAMigrateBOINCData::GetFreeDiskSpace( tstring strDirectory, ULONGLONG& ullFreeSpace )
{
ULARGE_INTEGER TotalNumberOfFreeBytes;
ULARGE_INTEGER TotalNumberOfBytes;
ULARGE_INTEGER TotalNumberOfBytesFreeToCaller;
DWORD dwSectPerClust = NULL;
DWORD dwBytesPerSect = NULL;
DWORD dwFreeClusters = NULL;
DWORD dwTotalClusters = NULL;
BOOL bReturnValue = FALSE;
MyGetDiskFreeSpaceEx pGetDiskFreeSpaceEx = NULL;
TCHAR szMessage[2048];
#ifdef _UNICODE
pGetDiskFreeSpaceEx = (MyGetDiskFreeSpaceEx)GetProcAddress(
GetModuleHandle("kernel32.dll"), "GetDiskFreeSpaceExW"
);
#else
pGetDiskFreeSpaceEx = (MyGetDiskFreeSpaceEx)GetProcAddress(
GetModuleHandle("kernel32.dll"), "GetDiskFreeSpaceExA"
);
#endif
_sntprintf(
szMessage,
sizeof(szMessage),
_T("GetFreeDiskSpace Directory Location: '%s'"),
strDirectory.c_str()
);
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
szMessage
);
if (pGetDiskFreeSpaceEx) {
if (0 == strDirectory.length())
{
bReturnValue = pGetDiskFreeSpaceEx(
NULL,
&TotalNumberOfBytesFreeToCaller,
&TotalNumberOfBytes,
&TotalNumberOfFreeBytes
);
}
else
{
bReturnValue = pGetDiskFreeSpaceEx(
strDirectory.c_str(),
&TotalNumberOfBytesFreeToCaller,
&TotalNumberOfBytes,
&TotalNumberOfFreeBytes
);
}
_sntprintf(
szMessage,
sizeof(szMessage),
_T("GetDiskFreeSpaceEx Return Value: '%d'"),
bReturnValue
);
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
szMessage
);
_sntprintf(
szMessage,
sizeof(szMessage),
_T("GetDiskFreeSpaceEx GetLastError: '%d'"),
GetLastError()
);
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
szMessage
);
_sntprintf(
szMessage,
sizeof(szMessage),
_T("TotalNumberOfFreeBytes: '%I64u'"),
TotalNumberOfFreeBytes.QuadPart
);
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
szMessage
);
ullFreeSpace = TotalNumberOfFreeBytes.QuadPart;
}
else
{
if (0 == strDirectory.length())
{
bReturnValue = GetDiskFreeSpace(
NULL,
&dwSectPerClust,
&dwBytesPerSect,
&dwFreeClusters,
&dwTotalClusters
);
}
else
{
bReturnValue = GetDiskFreeSpace(
strDirectory.c_str(),
&dwSectPerClust,
&dwBytesPerSect,
&dwFreeClusters,
&dwTotalClusters
);
}
_sntprintf(
szMessage,
sizeof(szMessage),
_T("GetDiskFreeSpace Return Value: '%d'"),
bReturnValue
);
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
szMessage
);
_sntprintf(
szMessage,
sizeof(szMessage),
_T("GetDiskFreeSpace GetLastError: '%d'"),
GetLastError()
);
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
szMessage
);
ullFreeSpace = dwFreeClusters * dwSectPerClust * dwBytesPerSect;
}
return bReturnValue;
}
/////////////////////////////////////////////////////////////////////
//
// Function:
//
// Description:
//
/////////////////////////////////////////////////////////////////////
BOOL CAMigrateBOINCData::MoveFiles( tstring strSourceDirectory, tstring strDestinationDirectory, ULONGLONG& ullBytesTransfered )
{
BOOL bRet = TRUE;
WIN32_FIND_DATA ffData;
HANDLE hFind;
tstring csPathMask;
tstring csFullPath;
tstring csNewFullPath;
tstring strMessage;
strMessage = _T("CAMigrateBOINCData::MoveFiles -- Directory: '");
strMessage += strSourceDirectory;
strMessage += _T("'");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
strMessage.c_str()
);
// Create the destination cirectory if needed.
//
CreateDirectory(strDestinationDirectory.c_str(), NULL);
if ( _T("\\") != strSourceDirectory.substr(strSourceDirectory.length() - 1, 1) )
{
strSourceDirectory += _T("\\");
}
if ( _T("\\") != strDestinationDirectory.substr(strDestinationDirectory.length() - 1, 1) )
{
strDestinationDirectory += _T("\\");
}
csPathMask = strSourceDirectory + _T("*.*");
hFind = FindFirstFile(csPathMask.c_str(), &ffData);
if (hFind == INVALID_HANDLE_VALUE){
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("CAMigrateBOINCData::MoveFiles -- Invalid handle")
);
return FALSE;
}
// Copying all the files
while (hFind && FindNextFile(hFind, &ffData))
{
csFullPath = strSourceDirectory + ffData.cFileName;
csNewFullPath = strDestinationDirectory + ffData.cFileName;
RemoveReadOnly(csFullPath);
RemoveReadOnly(csNewFullPath);
if( !(ffData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
{
strMessage = _T("CAMigrateBOINCData::MoveFiles -- Copy File: '");
strMessage += csFullPath.c_str();
strMessage += _T("' to '");
strMessage += csNewFullPath.c_str();
strMessage += _T("'");
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
strMessage.c_str()
);
if( !CopyFile(csFullPath.c_str(), csNewFullPath.c_str(), FALSE) )
{
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
GetLastError(),
_T("CAMigrateBOINCData::MoveFiles -- Failed to copy original file")
);
bRet = FALSE;
}
else
{
ullBytesTransfered += ((ffData.nFileSizeHigh * MAXDWORD) + ffData.nFileSizeLow);
// Specify that an update of the progress bar's position in
// this case means to move it forward by one increment.
MsiRecordSetInteger(m_phProgressRec, 1, 2);
MsiRecordSetInteger(m_phProgressRec, 2, (INT)((ullBytesTransfered/1024)/1024));
MsiRecordSetInteger(m_phProgressRec, 3, 0);
MsiProcessMessage(m_hMSIHandle, INSTALLMESSAGE_PROGRESS, m_phProgressRec);
Sleep(0);
// Delete the original file when it has been successfully
// copied
if( !DeleteFile(csFullPath.c_str()) )
{
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
GetLastError(),
_T("CAMigrateBOINCData::MoveFiles -- Failed to delete original file")
);
}
}
}
else // it is a directory -> Copying recursivly
{
if( (_tcscmp(ffData.cFileName, _T(".")) != 0) &&
(_tcscmp(ffData.cFileName, _T("..")) != 0) &&
(!IsDirectoryExcluded(tstring(ffData.cFileName))))
{
if( !MoveFiles(csFullPath, csNewFullPath, ullBytesTransfered) )
{
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
_T("CAMigrateBOINCData::MoveFiles -- Failed to copy drectory")
);
LogMessage(
INSTALLMESSAGE_INFO,
NULL,
NULL,
NULL,
NULL,
csNewFullPath.c_str()
);
bRet = FALSE;
}
}
}
}
FindClose(hFind);
RemoveReadOnly(strSourceDirectory);
RemoveDirectory(strSourceDirectory.c_str());
return bRet;
}
/////////////////////////////////////////////////////////////////////
//
// Function:
//
// Description:
//
/////////////////////////////////////////////////////////////////////
BOOL CAMigrateBOINCData::IsDirectoryExcluded( tstring strTargetDirectory )
{
DowncaseString(strTargetDirectory);
if (StartsWith(strTargetDirectory, tstring("locale"))) return TRUE;
if (StartsWith(strTargetDirectory, tstring("skins"))) return TRUE;
return FALSE;
}
/////////////////////////////////////////////////////////////////////
//
// Function: MigrateBOINCData
//
// Description:
//
/////////////////////////////////////////////////////////////////////
UINT __stdcall MigrateBOINCData(MSIHANDLE hInstall)
{
UINT uiReturnValue = 0;
CAMigrateBOINCData* pCA = new CAMigrateBOINCData(hInstall);
uiReturnValue = pCA->Execute();
delete pCA;
return uiReturnValue;
}
const char *BOINC_RCSID_8dca879ada="$Id: CAMigrateBOINCData.cpp 11773 2007-01-05 08:49:02Z rwalton $";