diff options
Diffstat (limited to 'shared/shadow.cpp')
-rw-r--r-- | shared/shadow.cpp | 112 |
1 files changed, 83 insertions, 29 deletions
diff --git a/shared/shadow.cpp b/shared/shadow.cpp index da7cfd99..29eec53b 100644 --- a/shared/shadow.cpp +++ b/shared/shadow.cpp @@ -6,7 +6,43 @@ using FreeFileSync::ShadowCopy; -class ShadowlDllHandler //dynamically load windows API functions +bool newerThanXP() +{ + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + //symbolic links are supported starting with Vista + if (GetVersionEx(&osvi)) + return osvi.dwMajorVersion > 5 || + (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion > 1) ; + //XP has majorVersion == 5, minorVersion == 1 + //Server 2003 has majorVersion == 5, minorVersion == 2 + //version overview: http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx + return false; +} + + +bool runningWOW64() //test if process is running under WOW64 (reference http://msdn.microsoft.com/en-us/library/ms684139(VS.85).aspx) +{ + typedef BOOL (WINAPI *IsWow64ProcessFunc)( + HANDLE hProcess, + PBOOL Wow64Process); + + const IsWow64ProcessFunc isWow64Process = reinterpret_cast<IsWow64ProcessFunc>( + ::GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process")); + if (isWow64Process != NULL) + { + BOOL isWow64 = FALSE; + if ((*isWow64Process)(::GetCurrentProcess(), &isWow64)) + return isWow64 == TRUE; + } + + return false; +} + + +class ShadowCopy::ShadowlDllHandler //dynamically load windows API functions { typedef bool (*CreateShadowCopyFct)( //volumeName must end with "\", while shadowVolName does not end with "\" const wchar_t* volumeName, @@ -19,23 +55,33 @@ class ShadowlDllHandler //dynamically load windows API functions typedef void (*ReleaseShadowCopyFct)(void* backupHandle); public: - static const ShadowlDllHandler& getInstance() + static const wxString& getShadowDllName() { - static ShadowlDllHandler instance; - return instance; + /* + 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 + */ +#if defined _WIN64 //note: _WIN32 is defined for 64-bit compilations, too, while _WIN64 only for 64-bit + static const wxString filename(newerThanXP() ? + wxT("Shadow_Server2003_x64.dll") : + wxT("Shadow_XP_x64.dll")); +#elif defined(_WIN32) + static const wxString filename(newerThanXP() ? + wxT("Shadow_Server2003_win32.dll") : + wxT("Shadow_XP_win32.dll")); +#else + Are we at 128 bit already? +#endif + return filename; } - CreateShadowCopyFct createShadowCopy; - ReleaseShadowCopyFct releaseShadowCopy; - -private: ShadowlDllHandler() : createShadowCopy(NULL), releaseShadowCopy(NULL), hShadow(NULL) { //get a handle to the DLL module containing the required functionality - hShadow = ::LoadLibrary(L"Shadow.dll"); + hShadow = ::LoadLibrary(getShadowDllName().c_str()); if (hShadow) { createShadowCopy = reinterpret_cast<CreateShadowCopyFct>(::GetProcAddress(hShadow, "createShadowCopy")); @@ -48,41 +94,56 @@ private: if (hShadow) ::FreeLibrary(hShadow); } + CreateShadowCopyFct createShadowCopy; + ReleaseShadowCopyFct releaseShadowCopy; + +private: HINSTANCE hShadow; }; +//############################################################################################################# ShadowCopy::ShadowCopy() : - backupHandle(NULL) {} + backupHandle(NULL) +{ + shadowDll = new ShadowlDllHandler; +} ShadowCopy::~ShadowCopy() { if (backupHandle != NULL) - ShadowlDllHandler::getInstance().releaseShadowCopy(backupHandle); -} - + shadowDll->releaseShadowCopy(backupHandle); -bool ShadowCopy::isOkay() -{ - //check that all functions could be loaded - return ShadowlDllHandler::getInstance().createShadowCopy != NULL && - ShadowlDllHandler::getInstance().releaseShadowCopy != NULL; + delete shadowDll; } Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile) { //check if shadow copy dll was loaded correctly - if (!isOkay()) + if ( shadowDll->createShadowCopy == NULL || + shadowDll->releaseShadowCopy == NULL) { 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") + - _("Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature.")); + _("Could not load a required DLL:") + wxT(" \"") + ShadowlDllHandler::getShadowDllName() + 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) + { + 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.")); } +//--------------------------------------------------------------------------------------------------------- wchar_t volumeNameRaw[1000]; if (!GetVolumePathName(inputFile.c_str(), //__in LPCTSTR lpszFileName, @@ -103,7 +164,7 @@ Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile) //release old shadow copy if (backupHandle != NULL) { - ShadowlDllHandler::getInstance().releaseShadowCopy(backupHandle); + shadowDll->releaseShadowCopy(backupHandle); backupHandle = NULL; } realVolumeLast.clear(); //...if next call fails... @@ -114,7 +175,7 @@ Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile) void* backupHandleTmp = NULL; wchar_t errorMessage[1000]; - if (!ShadowlDllHandler::getInstance().createShadowCopy( + if (!shadowDll->createShadowCopy( volumeNameFormatted.c_str(), shadowVolName, 1000, @@ -149,10 +210,3 @@ Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile) } - - - - - - - |