diff options
Diffstat (limited to 'shared/shadow.cpp')
-rw-r--r-- | shared/shadow.cpp | 204 |
1 files changed, 103 insertions, 101 deletions
diff --git a/shared/shadow.cpp b/shared/shadow.cpp index 3909c37b..b38103de 100644 --- a/shared/shadow.cpp +++ b/shared/shadow.cpp @@ -7,16 +7,21 @@ #include "shadow.h" #include <wx/msw/wrapwin.h> //includes "windows.h" #include <wx/intl.h> -#include "systemConstants.h" -#include "dllLoader.h" +#include "system_constants.h" +#include "dll_loader.h" #include <stdexcept> -#include "staticAssert.h" -#include "buildInfo.h" +#include "assert_static.h" +#include "build_info.h" #include "ShadowCopy\shadow.h" +#include "string_conv.h" -using FreeFileSync::ShadowCopy; +using shadow::ShadowCopy; +using shadow::WaitingForShadow; +using ffs3::FileError; +namespace +{ bool newerThanXP() { OSVERSIONINFO osvi; @@ -41,7 +46,7 @@ bool runningWOW64() //test if process is running under WOW64 (reference http://m PBOOL Wow64Process); static const IsWow64ProcessFunc isWow64Process = - Utility::loadDllFunction<IsWow64ProcessFunc>(L"kernel32.dll", "IsWow64Process"); + util::loadDllFunction<IsWow64ProcessFunc>(L"kernel32.dll", "IsWow64Process"); if (isWow64Process) { @@ -54,148 +59,145 @@ bool runningWOW64() //test if process is running under WOW64 (reference http://m } -const wxString& getShadowDllName() +const std::wstring& getShadowDllName() { /* distinguish a bunch of VSS builds: we use XP and Server 2003 implementations... VSS version and compatibility overview: http://msdn.microsoft.com/en-us/library/aa384627(VS.85).aspx */ - static const wxString filename( + assert_static(util::is32BitBuild || util::is64BitBuild); + + static const std::wstring filename( newerThanXP() ? - (Utility::is64BitBuild ? - wxT("Shadow_Server2003_x64.dll") : - wxT("Shadow_Server2003_Win32.dll")) : + (util::is64BitBuild ? + L"Shadow_Server2003_x64.dll" : + L"Shadow_Server2003_Win32.dll") : - (Utility::is64BitBuild ? - wxT("Shadow_XP_x64.dll") : - wxT("Shadow_XP_Win32.dll"))); + (util::is64BitBuild ? + L"Shadow_XP_x64.dll" : + L"Shadow_XP_Win32.dll")); - assert_static(Utility::is32BitBuild || Utility::is64BitBuild); return filename; } - +} //############################################################################################################# -ShadowCopy::ShadowCopy() : - backupHandle(NULL) {} +ShadowCopy::ShadowCopy(WaitingForShadow* callback) : callback_(callback) {} +ShadowCopy::~ShadowCopy() {} //std::auto_ptr: keep non-inline +//############################################################################################################# -ShadowCopy::~ShadowCopy() +class ShadowCopy::ShadowVolume { - if (backupHandle != NULL) +public: + ShadowVolume(const Zstring& volumeNameFormatted) : //throw(FileError) + realVol(volumeNameFormatted), + backupHandle(NULL) { - using namespace Shadow; + using namespace shadow; - static const ReleaseShadowCopyFct releaseShadowCopy = - Utility::loadDllFunction<ReleaseShadowCopyFct>(getShadowDllName().c_str(), releaseShadowCopyFctName); + if (!createShadowCopy) + createShadowCopy = util::loadDllFunction<CreateShadowCopyFct>(getShadowDllName(), createShadowCopyFctName); - if (releaseShadowCopy == NULL) - throw std::logic_error("Could not load \"releaseShadowCopy\"!"); //shouldn't arrive here! + if (!releaseShadowCopy) + releaseShadowCopy = util::loadDllFunction<ReleaseShadowCopyFct>(getShadowDllName(), releaseShadowCopyFctName); - releaseShadowCopy(backupHandle); - } -} + //check if shadow copy dll was loaded correctly + if ( createShadowCopy == NULL || + releaseShadowCopy == NULL) + throw FileError(wxString(_("Error starting Volume Shadow Copy Service!")) + wxT("\n") + + _("Could not load a required DLL:") + wxT(" \"") + getShadowDllName().c_str() + wxT("\"")); + //VSS does not support running under WOW64 except for Windows XP and Windows Server 2003 + //(Reference: http://msdn.microsoft.com/en-us/library/aa384627(VS.85).aspx) + static const bool wow64Active = runningWOW64(); + if (wow64Active) + throw FileError(wxString(_("Error starting Volume Shadow Copy Service!")) + wxT("\n") + + _("Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.")); -Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile) -{ - using namespace Shadow; +//--------------------------------------------------------------------------------------------------------- + //start shadow volume copy service: + wchar_t shadowVolName[1000]; + wchar_t errorMessage[1000]; + + if (!createShadowCopy( + volumeNameFormatted.c_str(), + shadowVolName, + 1000, + &backupHandle, + errorMessage, + 1000)) + throw FileError(wxString(_("Error starting Volume Shadow Copy Service!")) + wxT("\n") + + wxT("(") + errorMessage + wxT(" Volume: \"") + volumeNameFormatted.c_str() + wxT("\")")); - static const CreateShadowCopyFct createShadowCopy = - Utility::loadDllFunction<CreateShadowCopyFct>(getShadowDllName().c_str(), createShadowCopyFctName); + shadowVol = Zstring(shadowVolName) + common::FILE_NAME_SEPARATOR; //shadowVolName NEVER has a trailing backslash + } - static const ReleaseShadowCopyFct releaseShadowCopy = - Utility::loadDllFunction<ReleaseShadowCopyFct>(getShadowDllName().c_str(), releaseShadowCopyFctName); + ~ShadowVolume() + { + releaseShadowCopy(backupHandle); + } - //check if shadow copy dll was loaded correctly - if ( createShadowCopy == NULL || - releaseShadowCopy == NULL) + Zstring getShadowVolume() const //trailing path separator { - wxString errorMsg = _("Error copying locked file %x!"); - errorMsg.Replace(wxT("%x"), wxString(wxT("\"")) + inputFile.c_str() + wxT("\"")); - throw FileError(errorMsg + wxT("\n\n") + _("Error starting Volume Shadow Copy Service!") + wxT("\n") + - _("Could not load a required DLL:") + wxT(" \"") + getShadowDllName() + wxT("\"")); + return shadowVol; } - //VSS does not support running under WOW64 except for Windows XP and Windows Server 2003 - //(Reference: http://msdn.microsoft.com/en-us/library/aa384627(VS.85).aspx) - static const bool wow64Active = runningWOW64(); - if (wow64Active) + Zstring getRealVolume() const //trailing path separator { - wxString errorMsg = _("Error copying locked file %x!"); - errorMsg.Replace(wxT("%x"), wxString(wxT("\"")) + inputFile.c_str() + wxT("\"")); - throw FileError(errorMsg + wxT("\n\n") + _("Error starting Volume Shadow Copy Service!") + wxT("\n") + - _("Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.")); + return realVol; } +private: + ShadowVolume(const ShadowVolume&); + ShadowVolume& operator=(const ShadowVolume&); + + static shadow::CreateShadowCopyFct createShadowCopy; + static shadow::ReleaseShadowCopyFct releaseShadowCopy; + + Zstring shadowVol; + const Zstring realVol; + + void* backupHandle; +}; + + +shadow::CreateShadowCopyFct ShadowCopy::ShadowVolume::createShadowCopy; +shadow::ReleaseShadowCopyFct ShadowCopy::ShadowVolume::releaseShadowCopy; +//############################################################################################################# + + +Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile) +{ + using namespace ffs3; -//--------------------------------------------------------------------------------------------------------- wchar_t volumeNameRaw[1000]; if (!::GetVolumePathName(inputFile.c_str(), //__in LPCTSTR lpszFileName, volumeNameRaw, //__out LPTSTR lpszVolumePathName, 1000)) //__in DWORD cchBufferLength - { - wxString errorMsg = _("Error copying locked file %x!"); - errorMsg.Replace(wxT("%x"), wxString(wxT("\"")) + inputFile.c_str() + wxT("\"")); - throw FileError(errorMsg + wxT("\n\n") + _("Could not determine volume name for file:") + wxT("\n\"") + inputFile.c_str() + wxT("\"")); - } + throw FileError(wxString(_("Could not determine volume name for file:")) + wxT("\n\"") + zToWx(inputFile) + wxT("\"")); Zstring volumeNameFormatted = volumeNameRaw; - if (!volumeNameFormatted.EndsWith(globalFunctions::FILE_NAME_SEPARATOR)) - volumeNameFormatted += globalFunctions::FILE_NAME_SEPARATOR; - - if (volumeNameFormatted != realVolumeLast) - { - //release old shadow copy - if (backupHandle != NULL) - { - releaseShadowCopy(backupHandle); - backupHandle = NULL; - } - realVolumeLast.clear(); //...if next call fails... - shadowVolumeLast.clear(); //...if next call fails... - - //start shadow volume copy service: - wchar_t shadowVolName[1000]; - void* backupHandleTmp = NULL; - wchar_t errorMessage[1000]; - - if (!createShadowCopy( - volumeNameFormatted.c_str(), - shadowVolName, - 1000, - &backupHandleTmp, - errorMessage, - 1000)) - { - wxString errorMsg = _("Error copying locked file %x!"); - errorMsg.Replace(wxT("%x"), Zstring(wxT("\"")) + inputFile + wxT("\"")); - throw FileError(errorMsg + wxT("\n\n") + _("Error starting Volume Shadow Copy Service!") + wxT("\n") + - wxT("(") + errorMessage + wxT(" Volume: \"") + volumeNameFormatted.c_str() + wxT("\")")); - } - - realVolumeLast = volumeNameFormatted; - shadowVolumeLast = Zstring(shadowVolName) + globalFunctions::FILE_NAME_SEPARATOR; //shadowVolName NEVER has a trailing backslash - backupHandle = backupHandleTmp; - } + if (!volumeNameFormatted.EndsWith(common::FILE_NAME_SEPARATOR)) + volumeNameFormatted += common::FILE_NAME_SEPARATOR; //input file is always absolute! directory formatting takes care of this! Therefore volume name can always be found. const size_t pos = inputFile.find(volumeNameFormatted); //inputFile needs NOT to begin with volumeNameFormatted: consider for example \\?\ prefix! if (pos == Zstring::npos) { - wxString errorMsg = _("Error copying locked file %x!"); - errorMsg.Replace(wxT("%x"), Zstring(wxT("\"")) + inputFile + wxT("\"")); - wxString msg = _("Volume name %x not part of filename %y!"); - msg.Replace(wxT("%x"), wxString(wxT("\"")) + volumeNameFormatted.c_str() + wxT("\""), false); - msg.Replace(wxT("%y"), wxString(wxT("\"")) + inputFile.c_str() + wxT("\""), false); - throw FileError(errorMsg + wxT("\n\n") + msg); + msg.Replace(wxT("%x"), wxString(wxT("\"")) + zToWx(volumeNameFormatted) + wxT("\""), false); + msg.Replace(wxT("%y"), wxString(wxT("\"")) + zToWx(inputFile) + wxT("\""), false); + throw FileError(msg); } + + if (!shadowVol.get() || shadowVol->getRealVolume() != volumeNameFormatted) + shadowVol.reset(new ShadowVolume(volumeNameFormatted)); //throw (FileError) + //return filename alias on shadow copy volume - return shadowVolumeLast + Zstring(inputFile.c_str() + pos + volumeNameFormatted.length()); + return shadowVol->getShadowVolume() + Zstring(inputFile.c_str() + pos + volumeNameFormatted.length()); } - |