diff options
Diffstat (limited to 'lib/shadow.cpp')
-rw-r--r-- | lib/shadow.cpp | 131 |
1 files changed, 0 insertions, 131 deletions
diff --git a/lib/shadow.cpp b/lib/shadow.cpp deleted file mode 100644 index d1027f69..00000000 --- a/lib/shadow.cpp +++ /dev/null @@ -1,131 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "shadow.h" -#include <stdexcept> -#include <zen/win.h> //includes "windows.h" -#include <zen/dll.h> -#include <zen/win_ver.h> -#include <zen/assert_static.h> -#include <zen/long_path_prefix.h> -#include <zen/symlink_target.h> -#include "ShadowCopy/shadow.h" -#include <zen/scope_guard.h> - -using namespace zen; -using namespace shadow; - - -namespace -{ -bool runningWOW64() //test if process is running under WOW64 (reference http://msdn.microsoft.com/en-us/library/ms684139(VS.85).aspx) -{ - typedef BOOL (WINAPI* IsWow64ProcessFun)(HANDLE hProcess, PBOOL Wow64Process); - - const SysDllFun<IsWow64ProcessFun> isWow64Process(L"kernel32.dll", "IsWow64Process"); - if (isWow64Process) - { - BOOL isWow64 = FALSE; - if (isWow64Process(::GetCurrentProcess(), &isWow64)) - return isWow64 != FALSE; - } - return false; -} - -const bool wereVistaOrLater = vistaOrLater(); //thread-safety: init at startup -} - -//############################################################################################################# - -class ShadowCopy::ShadowVolume -{ -public: - ShadowVolume(const Zstring& volumeNamePf) : //throw FileError - createShadowCopy (getDllName(), funName_createShadowCopy), - releaseShadowCopy(getDllName(), funName_releaseShadowCopy), - getShadowVolume (getDllName(), funName_getShadowVolume), - getLastError (getDllName(), funName_getLastError), - backupHandle(nullptr) - { - //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 - if (runningWOW64()) - throw FileError(_("Cannot access the Volume Shadow Copy Service."), - _("Please use FreeFileSync 64-bit version to create shadow copies on this system.")); - - //check if shadow copy dll was loaded correctly - if (!createShadowCopy || !releaseShadowCopy || !getShadowVolume || !getLastError) - throw FileError(_("Cannot access the Volume Shadow Copy Service."), - replaceCpy(_("Cannot load file %x."), L"%x", fmtFileName(getDllName()))); - - //--------------------------------------------------------------------------------------------------------- - //start volume shadow copy service: - backupHandle = createShadowCopy(volumeNamePf.c_str()); - if (!backupHandle) - throw FileError(_("Cannot access the Volume Shadow Copy Service."), - getLastError() + std::wstring(L" Volume: ") + fmtFileName(volumeNamePf)); - - shadowVolPf = appendSeparator(getShadowVolume(backupHandle)); //shadowVolName NEVER has a trailing backslash - } - - ~ShadowVolume() { releaseShadowCopy(backupHandle); } //fast! no performance optimization necessary - - Zstring geNamePf() const { return shadowVolPf; } //with trailing path separator - -private: - ShadowVolume(const ShadowVolume&); - ShadowVolume& operator=(const ShadowVolume&); - - const DllFun<FunType_createShadowCopy> createShadowCopy; - const DllFun<FunType_releaseShadowCopy> releaseShadowCopy; - const DllFun<FunType_getShadowVolume> getShadowVolume; - const DllFun<FunType_getLastError> getLastError; - - Zstring shadowVolPf; - ShadowHandle backupHandle; -}; - -//############################################################################################################# - -Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile, const std::function<void(const Zstring&)>& onBeforeMakeVolumeCopy) -{ - Zstring filenameFinal = inputFile; - - //try to resolve symlinks and junctions: - //1. symlinks: we need to retrieve the target path, else we would just return a symlink on a VSS volume while the target outside were still locked! - //2. junctions: C:\Users\<username> is a junction that may link to e.g. D:\Users\<username>, so GetVolumePathName() returns "D:\" => "Volume name %x not part of file name %y." - if (wereVistaOrLater) - filenameFinal = getResolvedFilePath(inputFile); //throw FileError; requires Vista or later! - //-> returns paths with \\?\ prefix! => make sure to avoid duplicate shadow copies for volume paths with/without prefix - - DWORD bufferSize = 10000; - std::vector<wchar_t> volBuffer(bufferSize); - if (!::GetVolumePathName(filenameFinal.c_str(), //__in LPCTSTR lpszFileName, - &volBuffer[0], //__out LPTSTR lpszVolumePathName, - bufferSize)) //__in DWORD cchBufferLength - throw FileError(replaceCpy(_("Cannot determine volume name for %x."), L"%x", fmtFileName(filenameFinal)), formatSystemError(L"GetVolumePathName", ::GetLastError())); - - const Zstring volumeNamePf = appendSeparator(&volBuffer[0]); //msdn: if buffer is 1 char too short, GetVolumePathName() may skip last separator without error! - - //input file is always absolute! directory formatting takes care of this! Therefore volume name can always be found. - const size_t pos = filenameFinal.find(volumeNamePf); //filenameFinal needs NOT to begin with volumeNamePf: consider \\?\ prefix! - if (pos == Zstring::npos) - throw FileError(replaceCpy(replaceCpy(_("Volume name %x is not part of file path %y."), - L"%x", fmtFileName(volumeNamePf)), - L"%y", fmtFileName(filenameFinal))); - - //get or create instance of shadow volume - auto it = shadowVol.find(volumeNamePf); - if (it == shadowVol.end()) - { - onBeforeMakeVolumeCopy(volumeNamePf); //notify client before (potentially) blocking some time - auto newEntry = std::make_shared<ShadowVolume>(volumeNamePf); //throw FileError - it = shadowVol.insert(std::make_pair(volumeNamePf, newEntry)).first; - } - - //return filename alias on shadow copy volume - return it->second->geNamePf() + Zstring(filenameFinal.c_str() + pos + volumeNamePf.length()); -} |