summaryrefslogtreecommitdiff
path: root/NSCmpts/BackupActions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'NSCmpts/BackupActions.cpp')
-rw-r--r--NSCmpts/BackupActions.cpp293
1 files changed, 293 insertions, 0 deletions
diff --git a/NSCmpts/BackupActions.cpp b/NSCmpts/BackupActions.cpp
new file mode 100644
index 0000000..0dff71e
--- /dev/null
+++ b/NSCmpts/BackupActions.cpp
@@ -0,0 +1,293 @@
+// BackupActions.cpp: implementation of the CBackupActions class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "BackupActions.h"
+
+#include "resource.h"
+#include <appmisc.h>
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+bool CBackupActions::ArchivePrepare::Do(CActionEngine* pEngine,
+ HWND hwndUpdates)
+{
+ // Some Checks
+ ASSERT(pEngine != NULL);
+
+ if(!m_dest.valid())
+ throw CActionError(E_INVALIDARG, IDS_BACKUP_ERR_DEST, m_dest);
+
+ // Create destination folder
+ HRESULT hr = m_dest.create();
+ if(FAILED(hr))
+ throw CActionError(hr, IDS_BACKUP_ERR_CREATE_DEST, m_dest);
+
+ // This could take a while so message
+ Update(hwndUpdates, _T("Listing files to backup..."), NULL);
+
+ // Iterate through source folders
+ string_array::const_iterator iterSrc;
+ for(iterSrc = m_src.begin(); iterSrc != m_src.end(); iterSrc++)
+ {
+ Update(hwndUpdates, NULL, (LPCTSTR)*iterSrc);
+
+ // Variables Used below
+ file_path srcPath = *iterSrc;
+ file_path srcFile;
+ file_path destFile;
+
+ file_iterator fileIter(srcPath.files_begin(file_iterator::sub_folders));
+ file_iterator end;
+
+ for( ; fileIter != end; fileIter++)
+ {
+ // Check if it has the ARCHIVE attribute set
+ if(!(fileIter->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE))
+ continue;
+
+ if(fileIter->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ continue;
+
+ // Make File Paths
+ srcFile = *iterSrc;
+
+ // Destination is root destination + same folder structure as
+ // original folder
+ destFile = m_dest;
+
+ if(srcFile.attributes() & FILE_ATTRIBUTE_DIRECTORY)
+ destFile += *(srcFile.end(false) - 1);
+
+ destFile += fileIter->cFileName;
+
+ srcFile = srcFile.folder() + fileIter->cFileName;
+
+
+ // Make sure extension is not in list
+ if(m_asIgnore.find(srcFile.ext().make_lower()) == m_asIgnore.end())
+ {
+ // Add the file
+ ArchiveCopy* pCopy = new ArchiveCopy(srcFile, destFile);
+ pEngine->Add(pCopy);
+ }
+ }
+
+ // Error from file_iterator (listing folders)
+ if(fileIter.state() != ERROR_SUCCESS)
+ throw CActionError(HRESULT_FROM_WIN32(fileIter.state()), IDS_BACKUP_ERR_LIST, (file_path)*iterSrc);
+ }
+
+ return false;
+}
+
+HRESULT CBackupActions::BasePrepare::Initialize(const CPropertyBag& data)
+{
+ m_dest = data.GetString(NS_BACKUP_REG_DEST, _T(""));
+ data.GetStringSet(NS_BACKUP_REG_SOURCE, m_src);
+
+ string_array asTemp;
+ data.GetStringSet(NS_IGNORE_REG_EXT, asTemp);
+
+ // Make them all lower
+ for_each(asTemp.begin(), asTemp.end(), Lower);
+
+ // And copy them to the set (removes doubles)
+ copy(asTemp.begin(), asTemp.end(), inserter(m_asIgnore, m_asIgnore.begin()));
+
+ // Remove any blanks from ignore
+ m_asIgnore.erase(_T(""));
+
+ if(!m_dest.valid())
+ return E_INVALIDARG;
+
+ return S_OK;
+}
+
+#define FILETIME_TO_64(ft) \
+ ((__int64) (ft.dwLowDateTime | ((__int64)(ft.dwHighDateTime << 32))))
+
+
+bool CBackupActions::DatePrepare::Do(CActionEngine* pEngine,
+ HWND hwndUpdates)
+{
+ // Some Checks
+ ASSERT(pEngine != NULL);
+
+ if(!m_dest.valid())
+ throw CActionError(E_INVALIDARG, IDS_BACKUP_ERR_DEST, m_dest);
+
+ // Create destination folder
+ HRESULT hr = m_dest.create();
+ if(FAILED(hr))
+ throw CActionError(hr, IDS_BACKUP_ERR_CREATE_DEST, m_dest);
+
+ // This could take a while so message
+ Update(hwndUpdates, _T("Comparing dates on backup files..."), NULL);
+
+ HANDLE hFile;
+ FILETIME ftModify;
+
+ // Iterate through source folders
+ string_array::const_iterator iterSrc;
+ for(iterSrc = m_src.begin(); iterSrc != m_src.end(); iterSrc++)
+ {
+ Update(hwndUpdates, NULL, (LPCTSTR)*iterSrc);
+
+ // Variables Used below
+ file_path srcPath = *iterSrc;
+ file_path srcFile;
+ file_path destFile;
+
+ file_iterator fileIter(srcPath.files_begin(file_iterator::sub_folders));
+ file_iterator end;
+
+ for( ; fileIter != end; fileIter++)
+ {
+ if(fileIter->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ continue;
+
+ // Make File Paths
+ srcFile = *iterSrc;
+
+ // Destination is root destination + same folder structure as
+ // original folder
+ destFile = m_dest;
+
+ if(srcFile.attributes() & FILE_ATTRIBUTE_DIRECTORY)
+ destFile += *(srcFile.end(false) - 1);
+
+ destFile += fileIter->cFileName;
+
+ srcFile = srcFile.folder() + fileIter->cFileName;
+
+
+ // Make sure extension is not in list
+ if(m_asIgnore.find(srcFile.ext().make_lower()) != m_asIgnore.end())
+ continue;
+
+ // Open the file
+ hFile = CreateFile(destFile, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, 0, NULL);
+
+ // Check return Value
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ // If no file then Backup
+ switch(::GetLastError())
+ {
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ break;
+ default:
+ throw CActionError(HRESULT_FROM_WIN32(::GetLastError()), IDS_BACKUP_ERR_FILE, m_dest);
+ }
+ }
+ else
+ {
+ // Get the filetime
+ ftModify.dwHighDateTime = 0;
+ ftModify.dwLowDateTime = 0;
+
+ if(!GetFileTime(hFile, NULL, NULL, &ftModify))
+ throw CActionError(HRESULT_FROM_WIN32(::GetLastError()), IDS_BACKUP_ERR_FILE, destFile);
+
+ CloseHandle(hFile);
+
+ // Are we newer?
+ if(FILETIME_TO_64(fileIter->ftLastWriteTime) <= FILETIME_TO_64(ftModify))
+ continue;
+ }
+
+ // Add the file
+ ArchiveCopy* pCopy = new ArchiveCopy(srcFile, destFile);
+ pEngine->Add(pCopy);
+
+ }
+
+ // Error from file_iterator (listing folders)
+ if(fileIter.state() != ERROR_SUCCESS)
+ throw CActionError(HRESULT_FROM_WIN32(fileIter.state()), IDS_BACKUP_ERR_LIST, (file_path)*iterSrc);
+ }
+
+ return false;
+}
+
+bool CBackupActions::ArchiveCopy::Do(CActionEngine* pEngine,
+ HWND hwndUpdates)
+{
+start:
+ try
+ {
+ // Update any monitors
+ Update(hwndUpdates, _T("Copying..."), m_src);
+
+ // Create the folder this file is in
+ HRESULT hr = m_dest.folder().create();
+ if(FAILED(hr))
+ throw CActionError(hr, IDS_BACKUP_ERR_CREATE_DEST, m_dest.folder());
+
+ // SetAttributes of the file to make sure it's not read-only
+ // when read-only CopyFile fails (CopyFile copies attributes)
+ ::SetFileAttributes(m_dest, FILE_ATTRIBUTE_NORMAL);
+
+ // Copy. Don't worry about overwriting old files
+ if(!CopyFile(m_src, m_dest, FALSE))
+ throw CActionError(HRESULT_FROM_WIN32(::GetLastError()), IDS_BACKUP_ERR_COPY, m_src);
+
+ // Remove the Archive Attribute of the file
+ SetFileAttributes(m_src, m_src.attributes() ^ FILE_ATTRIBUTE_ARCHIVE);
+
+ return false;
+ }
+ catch(CActionError& err)
+ {
+ switch(err.m_hRes)
+ {
+ case ERROR_HANDLE_DISK_FULL:
+ case ERROR_DISK_FULL:
+ case ERROR_DESTINATION_ELEMENT_FULL:
+ case STG_E_MEDIUMFULL:
+ {
+ string sTemp;
+ sTemp.format(IDS_BACKUP_ERR_DISKFULL, (LPCTSTR)m_src.root());
+
+ if(IDYES == MessageBoxTimeout(hwndUpdates, sTemp, _T("Secure Shutdown"), MB_OKCANCEL | MB_ICONQUESTION, 15000, 5000))
+ break;
+ }
+ default:
+ throw;
+ }
+
+ }
+
+ goto start;
+}
+
+bool CBackupActions::DateCopy::Do(CActionEngine* pEngine,
+ HWND hwndUpdates)
+{
+ // Update any monitors
+ Update(hwndUpdates, _T("Copying..."), m_src);
+
+ // Create the folder this file is in
+ HRESULT hr = m_dest.folder().create();
+ if(FAILED(hr))
+ throw CActionError(hr, IDS_BACKUP_ERR_CREATE_DEST, m_dest.folder());
+
+ // SetAttributes of the file to make sure it's not read-only
+ // when read-only CopyFile fails (CopyFile copies attributes)
+ ::SetFileAttributes(m_dest, FILE_ATTRIBUTE_NORMAL);
+
+ // Copy. Don't worry about overwriting old files
+ if(!CopyFile(m_src, m_dest, FALSE))
+ throw CActionError(HRESULT_FROM_WIN32(::GetLastError()), IDS_BACKUP_ERR_COPY, m_src);
+
+ return false;
+
+ // We don't try to catch disk full errors (and prompt for another disk)
+ // because that doesn't make any sense in a date based backup
+}