diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 16:59:06 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 16:59:06 +0200 |
commit | 4046be06720932a57a0f49416b0144b2858824d0 (patch) | |
tree | 678c37cab05960f48923a23bb46d9e01be89d35a /library/ShadowCopy | |
parent | 1.19 (diff) | |
download | FreeFileSync-4046be06720932a57a0f49416b0144b2858824d0.tar.gz FreeFileSync-4046be06720932a57a0f49416b0144b2858824d0.tar.bz2 FreeFileSync-4046be06720932a57a0f49416b0144b2858824d0.zip |
2.0
Diffstat (limited to 'library/ShadowCopy')
-rw-r--r-- | library/ShadowCopy/ShadowDll.vcproj | 219 | ||||
-rw-r--r-- | library/ShadowCopy/dllmain.cpp | 22 | ||||
-rw-r--r-- | library/ShadowCopy/shadow.cpp | 178 | ||||
-rw-r--r-- | library/ShadowCopy/shadow.h | 33 |
4 files changed, 452 insertions, 0 deletions
diff --git a/library/ShadowCopy/ShadowDll.vcproj b/library/ShadowCopy/ShadowDll.vcproj new file mode 100644 index 00000000..637aad0c --- /dev/null +++ b/library/ShadowCopy/ShadowDll.vcproj @@ -0,0 +1,219 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="9,00" + Name="ShadowDll" + ProjectGUID="{70394AEF-5897-4911-AFA1-82EAF0581EFA}" + RootNamespace="ShadowDll" + Keyword="Win32Proj" + TargetFrameworkVersion="196613" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="obj\$(SolutionDir)$(ConfigurationName)" + IntermediateDirectory="obj\$(ConfigurationName)" + ConfigurationType="2" + CharacterSet="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SHADOWDLL_EXPORTS" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="0" + WarningLevel="3" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile="Shadow.dll" + LinkIncremental="2" + GenerateDebugInformation="true" + SubSystem="2" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="obj\$(ConfigurationName)" + IntermediateDirectory="obj\$(ConfigurationName)" + ConfigurationType="2" + CharacterSet="1" + WholeProgramOptimization="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + EnableIntrinsicFunctions="true" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SHADOWDLL_EXPORTS" + RuntimeLibrary="2" + EnableFunctionLevelLinking="true" + UsePrecompiledHeader="0" + WarningLevel="3" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile="Shadow.dll" + LinkIncremental="1" + GenerateDebugInformation="true" + SubSystem="2" + OptimizeReferences="2" + EnableCOMDATFolding="2" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Quelldateien" + Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" + > + <File + RelativePath=".\dllmain.cpp" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="0" + CompileAsManaged="0" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="0" + CompileAsManaged="0" + /> + </FileConfiguration> + </File> + <File + RelativePath=".\shadow.cpp" + > + </File> + </Filter> + <Filter + Name="Headerdateien" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" + > + <File + RelativePath=".\shadow.h" + > + </File> + </Filter> + <File + RelativePath=".\lib\vssapi.lib" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/library/ShadowCopy/dllmain.cpp b/library/ShadowCopy/dllmain.cpp new file mode 100644 index 00000000..834b4f88 --- /dev/null +++ b/library/ShadowCopy/dllmain.cpp @@ -0,0 +1,22 @@ +// dllmain.cpp : Definiert den Einstiegspunkt für die DLL-Anwendung. + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/library/ShadowCopy/shadow.cpp b/library/ShadowCopy/shadow.cpp new file mode 100644 index 00000000..e10a4eb8 --- /dev/null +++ b/library/ShadowCopy/shadow.cpp @@ -0,0 +1,178 @@ +#include "shadow.h" + +#define WIN32_LEAN_AND_MEAN +#include "windows.h" +#include "inc/vss.h" +#include "inc/vswriter.h" +#include "inc/vsbackup.h" +#include <algorithm> +#include <string> +#include <cstdio> +#include <comdef.h> + +//typedef GUID VSS_ID; + + +void writeString(const wchar_t* input, wchar_t* output, unsigned int outputBufferLen) +{ + const unsigned int newSize = min(wcslen(input) + 1, outputBufferLen); //including null-termination + memcpy(output, input, newSize * sizeof(wchar_t)); +} + + +std::wstring numberToHexString(const long number) +{ + wchar_t result[100]; + swprintf(result, 100, L"0x%08x", number); + return std::wstring(result); +} + + +void writeErrorMsg(const wchar_t* input, HRESULT hr, wchar_t* output, unsigned int outputBufferLen) +{ + std::wstring formattedMsg(input); + formattedMsg += L" ("; + formattedMsg += numberToHexString(hr); + formattedMsg += L": "; + formattedMsg += _com_error(hr).ErrorMessage(); + formattedMsg += L")"; + + writeString(formattedMsg.c_str(), output, outputBufferLen); +} + + +bool shadow::createShadowCopy(const wchar_t* volumeName, + wchar_t* shadowVolName, + unsigned int shadowBufferLen, + void** backupHandle, + wchar_t* errorMessage, + unsigned int errorBufferLen) +{ + //MessageBox(0, L"backup err", L"", 0); */ + *backupHandle = NULL; + HRESULT hr = NULL; + + IVssBackupComponents* pBackupComponents = NULL; + if (FAILED(hr = CreateVssBackupComponents(&pBackupComponents))) + { + if (hr == E_ACCESSDENIED) + writeErrorMsg(L"The caller does not have sufficient backup privileges or is not an administrator.", hr, errorMessage, errorBufferLen); + else + writeErrorMsg(L"Error calling \"CreateVssBackupComponents\".", hr, errorMessage, errorBufferLen); + return false; + } + + + if (FAILED(hr = pBackupComponents->InitializeForBackup())) + { + releaseShadowCopy(pBackupComponents); + writeErrorMsg(L"Error calling \"InitializeForBackup\".", hr, errorMessage, errorBufferLen); + return false; + } + + + IVssAsync* pWriteMetaData = NULL; + if (FAILED(hr = pBackupComponents->GatherWriterMetadata( &pWriteMetaData ))) + { + releaseShadowCopy(pBackupComponents); + writeErrorMsg(L"\"Shadow.dll\" might be incompatible with this Operating System!\n\ + Error calling \"GatherWriterMetadata\".", hr, errorMessage, errorBufferLen); + return false; + } + + //wait for shadow copy writers to complete + hr = pWriteMetaData->Wait(); + pWriteMetaData->Release(); + if (FAILED(hr)) + { + releaseShadowCopy(pBackupComponents); + writeErrorMsg(L"Error calling \"ppWriteMetaData->Wait\".", hr, errorMessage, errorBufferLen); + return false; + } + + + VSS_ID snapshotSetId = {0}; + if (FAILED(hr = pBackupComponents->StartSnapshotSet( &snapshotSetId ))) + { + releaseShadowCopy(pBackupComponents); + writeErrorMsg(L"Error calling \"StartSnapshotSet\".", hr, errorMessage, errorBufferLen); + return false; + } + + + VSS_ID SnapShotId = {0}; + if (FAILED(hr = pBackupComponents->AddToSnapshotSet(const_cast<wchar_t*>(volumeName), GUID_NULL, &SnapShotId))) + { + releaseShadowCopy(pBackupComponents); + writeErrorMsg(L"Error calling \"AddToSnapshotSet\".", hr, errorMessage, errorBufferLen); + return false; + } + + + if (FAILED(hr = pBackupComponents->SetBackupState( false, false, VSS_BT_FULL ))) + { + releaseShadowCopy(pBackupComponents); + writeErrorMsg(L"Error calling \"SetBackupState\".", hr, errorMessage, errorBufferLen); + return false; + } + + + IVssAsync* pPrepare = NULL; + if (FAILED(hr = pBackupComponents->PrepareForBackup( &pPrepare ))) + { + releaseShadowCopy(pBackupComponents); + writeErrorMsg(L"Error calling \"PrepareForBackup\".", hr, errorMessage, errorBufferLen); + return false; + } + + hr = pPrepare->Wait(); + pPrepare->Release(); + if (FAILED(hr)) + { + releaseShadowCopy(pBackupComponents); + writeErrorMsg(L"Error calling \"pPrepare->Wait\".", hr, errorMessage, errorBufferLen); + return false; + } + + + IVssAsync* pDoShadowCopy = NULL; + if (FAILED(hr = pBackupComponents->DoSnapshotSet( &pDoShadowCopy ))) + { + releaseShadowCopy(pBackupComponents); + writeErrorMsg(L"Error calling \"DoSnapshotSet\".", hr, errorMessage, errorBufferLen); + return false; + } + + hr = pDoShadowCopy->Wait(); + pDoShadowCopy->Release(); + if (FAILED(hr)) + { + releaseShadowCopy(pBackupComponents); + writeErrorMsg(L"Error calling \"pPrepare->Wait\".", hr, errorMessage, errorBufferLen); + return false; + } + + VSS_SNAPSHOT_PROP props; + if (FAILED(hr = pBackupComponents->GetSnapshotProperties( SnapShotId, &props ))) + { + releaseShadowCopy(pBackupComponents); + writeErrorMsg(L"Error calling \"GetSnapshotProperties\".", hr, errorMessage, errorBufferLen); + return false; + } + + //finally: write volume name of newly created shadow copy + writeString(props.m_pwszSnapshotDeviceObject, shadowVolName, shadowBufferLen); + + VssFreeSnapshotProperties(&props); + + *backupHandle = pBackupComponents; + + return true; +} + + +void shadow::releaseShadowCopy(void* backupHandle) +{ + if (backupHandle != NULL) + static_cast<IVssBackupComponents*>(backupHandle)->Release(); +} diff --git a/library/ShadowCopy/shadow.h b/library/ShadowCopy/shadow.h new file mode 100644 index 00000000..e25c6a32 --- /dev/null +++ b/library/ShadowCopy/shadow.h @@ -0,0 +1,33 @@ +#ifndef SHADOWCOPY_H +#define SHADOWCOPY_H + +#ifdef SHADOWDLL_EXPORTS +#define SHADOWDLL_API extern "C" __declspec(dllexport) +#else +#define SHADOWDLL_API extern "C" __declspec(dllimport) +#endif + + +namespace shadow +{ + //COM needs to be initialized before calling any of these functions! CoInitializeEx/CoUninitialize + + + //volumeName must end with "\", while shadowVolName does not end with "\" + SHADOWDLL_API + bool createShadowCopy(const wchar_t* volumeName, + wchar_t* shadowVolName, + unsigned int shadowBufferLen, + void** backupHandle, + wchar_t* errorMessage, + unsigned int errorBufferLen); + + + //don't forget to release the backupHandle after shadow copy is not needed anymore! + SHADOWDLL_API + void releaseShadowCopy(void* backupHandle); +} + + + +#endif //SHADOWCOPY_H |