summaryrefslogtreecommitdiff
path: root/shared/shadow.cpp
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:03:20 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:03:20 +0200
commit528635604eea1d8c679a3d038e2f00030ef72444 (patch)
tree9c3cbec29aa7d3e209939662e040b9342c9e7400 /shared/shadow.cpp
parent3.1 (diff)
downloadFreeFileSync-528635604eea1d8c679a3d038e2f00030ef72444.tar.gz
FreeFileSync-528635604eea1d8c679a3d038e2f00030ef72444.tar.bz2
FreeFileSync-528635604eea1d8c679a3d038e2f00030ef72444.zip
3.2
Diffstat (limited to 'shared/shadow.cpp')
-rw-r--r--shared/shadow.cpp112
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)
}
-
-
-
-
-
-
-
bgstack15