diff options
Diffstat (limited to 'lib/ShadowCopy')
-rw-r--r-- | lib/ShadowCopy/Shadow_Server2003.vcxproj (renamed from lib/ShadowCopy/Shadow_2003.vcxproj) | 0 | ||||
-rw-r--r-- | lib/ShadowCopy/Shadow_Windows7.vcxproj | 241 | ||||
-rw-r--r-- | lib/ShadowCopy/shadow.cpp | 196 | ||||
-rw-r--r-- | lib/ShadowCopy/shadow.h | 68 |
4 files changed, 361 insertions, 144 deletions
diff --git a/lib/ShadowCopy/Shadow_2003.vcxproj b/lib/ShadowCopy/Shadow_Server2003.vcxproj index a893a389..a893a389 100644 --- a/lib/ShadowCopy/Shadow_2003.vcxproj +++ b/lib/ShadowCopy/Shadow_Server2003.vcxproj diff --git a/lib/ShadowCopy/Shadow_Windows7.vcxproj b/lib/ShadowCopy/Shadow_Windows7.vcxproj new file mode 100644 index 00000000..2392fa99 --- /dev/null +++ b/lib/ShadowCopy/Shadow_Windows7.vcxproj @@ -0,0 +1,241 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectName>Windows7</ProjectName> + <ProjectGuid>{7E217D76-90A5-4B03-A6F8-E7C3ADD22901}</ProjectGuid> + <RootNamespace>ShadowDll</RootNamespace> + <Keyword>Win32Proj</Keyword> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <CharacterSet>Unicode</CharacterSet> + <WholeProgramOptimization>true</WholeProgramOptimization> + <UseOfAtl>false</UseOfAtl> + <PlatformToolset>Windows7.1SDK</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>Windows7.1SDK</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <CharacterSet>Unicode</CharacterSet> + <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>Windows7.1SDK</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>Windows7.1SDK</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup> + <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">OBJ\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">OBJ\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Shadow_$(ProjectName)_$(Platform)</TargetName> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Shadow_$(ProjectName)_$(Platform)</TargetName> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Shadow_$(ProjectName)_$(Platform)</TargetName> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Shadow_$(ProjectName)_$(Platform)</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <BuildLog> + <Path>$(IntDir)Build.html</Path> + </BuildLog> + <ClCompile> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;SHADOWDLL_EXPORTS;USE_SHADOW_WINDOWS7;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MinimalRebuild>true</MinimalRebuild> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level4</WarningLevel> + <SuppressStartupBanner>true</SuppressStartupBanner> + <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> + <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <SuppressStartupBanner>true</SuppressStartupBanner> + <GenerateDebugInformation>true</GenerateDebugInformation> + <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> + <SubSystem>Windows</SubSystem> + <ProfileGuidedDatabase> + </ProfileGuidedDatabase> + <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> + <TargetMachine>MachineX86</TargetMachine> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <BuildLog> + <Path>$(IntDir)Build.html</Path> + </BuildLog> + <Midl> + <TargetEnvironment>X64</TargetEnvironment> + </Midl> + <ClCompile> + <Optimization>Disabled</Optimization> + <MinimalRebuild>true</MinimalRebuild> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level4</WarningLevel> + <SuppressStartupBanner>true</SuppressStartupBanner> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> + <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> + <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;SHADOWDLL_EXPORTS;USE_SHADOW_WINDOWS7;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <SuppressStartupBanner>true</SuppressStartupBanner> + <GenerateDebugInformation>true</GenerateDebugInformation> + <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> + <SubSystem>Windows</SubSystem> + <ProfileGuidedDatabase> + </ProfileGuidedDatabase> + <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> + <TargetMachine>MachineX64</TargetMachine> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <BuildLog> + <Path>$(IntDir)Build.html</Path> + </BuildLog> + <ClCompile> + <Optimization>MaxSpeed</Optimization> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;SHADOWDLL_EXPORTS;USE_SHADOW_WINDOWS7;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <FunctionLevelLinking>true</FunctionLevelLinking> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level4</WarningLevel> + <SuppressStartupBanner>true</SuppressStartupBanner> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> + <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> + <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <SuppressStartupBanner>true</SuppressStartupBanner> + <GenerateDebugInformation>false</GenerateDebugInformation> + <SubSystem>Windows</SubSystem> + <OptimizeReferences>true</OptimizeReferences> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration> + <ProfileGuidedDatabase> + </ProfileGuidedDatabase> + <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> + <TargetMachine>MachineX86</TargetMachine> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <BuildLog> + <Path>$(IntDir)Build.html</Path> + </BuildLog> + <Midl> + <TargetEnvironment>X64</TargetEnvironment> + </Midl> + <ClCompile> + <Optimization>MaxSpeed</Optimization> + <IntrinsicFunctions>true</IntrinsicFunctions> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <FunctionLevelLinking>true</FunctionLevelLinking> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level4</WarningLevel> + <SuppressStartupBanner>true</SuppressStartupBanner> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> + <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> + <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> + <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;SHADOWDLL_EXPORTS;USE_SHADOW_WINDOWS7;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <SuppressStartupBanner>true</SuppressStartupBanner> + <GenerateDebugInformation>false</GenerateDebugInformation> + <SubSystem>Windows</SubSystem> + <OptimizeReferences>true</OptimizeReferences> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration> + <ProfileGuidedDatabase> + </ProfileGuidedDatabase> + <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> + <TargetMachine>MachineX64</TargetMachine> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="dll_main.cpp"> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + </PrecompiledHeader> + <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + </PrecompiledHeader> + <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + </PrecompiledHeader> + <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + </PrecompiledHeader> + <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged> + </ClCompile> + <ClCompile Include="shadow.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="shadow.h" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/lib/ShadowCopy/shadow.cpp b/lib/ShadowCopy/shadow.cpp index 12e9fa60..5047a698 100644 --- a/lib/ShadowCopy/shadow.cpp +++ b/lib/ShadowCopy/shadow.cpp @@ -7,12 +7,9 @@ #include "shadow.h" #include <algorithm> #include <string> -#include <comdef.h> #include <zen/com_ptr.h> #include <zen/com_error.h> - -#define WIN32_LEAN_AND_MEAN -#include "windows.h" +#include <zen/scope_guard.h> #ifdef USE_SHADOW_XP #include "xp/inc/vss.h" @@ -23,13 +20,30 @@ #include "Server 2003/inc/vss.h" #include "Server 2003/inc/vswriter.h" #include "Server 2003/inc/vsbackup.h" + +#elif defined USE_SHADOW_WINDOWS7 +#include <vss.h> // +#include <vswriter.h> //part of Windows SDK for Windows 7 +#include <vsbackup.h> // +#pragma comment(lib, "VssApi.lib") + #else -adapt! +#error adapt! #endif using namespace zen; +struct shadow::ShadowData +{ + ShadowData(const ComPtr<IVssBackupComponents>& backupComp, + const std::wstring& shadowVolume) : backupComp_(backupComp), shadowVolume_(shadowVolume) {} + + ComPtr<IVssBackupComponents> backupComp_; + std::wstring shadowVolume_; +}; + + namespace { inline @@ -45,143 +59,99 @@ void copyString(const std::wstring& input, wchar_t* buffer, size_t bufferSize) } } -inline -void writeErrorMsg(const wchar_t* input, HRESULT hr, wchar_t* output, unsigned int outputLen) -{ - copyString(generateErrorMsg(input, hr), output, outputLen); -} -} - -bool shadow::createShadowCopy(const wchar_t* volumeName, - wchar_t* shadowVolName, - unsigned int shadowBufferLen, - ShadowHandle* handle, - wchar_t* errorMessage, - unsigned int errorBufferLen) +shadow::ShadowData createShadowCopy(const wchar_t* volumeName) //throw ComError { - //MessageBox(0, L"backup err", L"", 0); */ - *handle = 0; - HRESULT hr = NULL; - ComPtr<IVssBackupComponents> backupComp; - if (FAILED(hr = CreateVssBackupComponents(backupComp.init()))) { - 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; + HRESULT hr = ::CreateVssBackupComponents(backupComp.init()); + if (FAILED(hr)) + { + if (hr == E_ACCESSDENIED) + throw ComError(L"The caller does not have sufficient backup privileges or is not an administrator.", hr); + throw ComError(L"Error calling \"CreateVssBackupComponents\".", hr); + } } - if (FAILED(hr = backupComp->InitializeForBackup())) - { - writeErrorMsg(L"Error calling \"InitializeForBackup\".", hr, errorMessage, errorBufferLen); - return false; - } + ZEN_CHECK_COM(backupComp->InitializeForBackup()); //throw ComError + ZEN_CHECK_COM(backupComp->SetBackupState(false, false, VSS_BT_FULL)); //throw ComError - if (FAILED(hr = backupComp->SetBackupState(false, false, VSS_BT_FULL))) + auto waitForComFuture = [](IVssAsync& fut) { - writeErrorMsg(L"Error calling \"SetBackupState\".", hr, errorMessage, errorBufferLen); - return false; - } + ZEN_CHECK_COM(fut.Wait()); - ComPtr<IVssAsync> vssWriters; - if (FAILED(hr = backupComp->GatherWriterMetadata(vssWriters.init()))) - { - //this can happen if XP-version of VSS is used on Windows Vista (which needs at least VSS-Server2003 build) - writeErrorMsg(L"Error calling \"GatherWriterMetadata\".", hr, errorMessage, errorBufferLen); - return false; - } + HRESULT hr = S_OK; + ZEN_CHECK_COM(fut.QueryStatus(&hr, NULL)); //check if the async operation succeeded... + if (FAILED(hr)) + throw ComError(L"Error calling \"fut->QueryStatus\".", hr); + }; - //wait for shadow copy writers to complete - if (FAILED(hr = vssWriters->Wait())) - { - writeErrorMsg(L"Error calling \"vssWriters->Wait\".", hr, errorMessage, errorBufferLen); - return false; - } + ComPtr<IVssAsync> gatherAsync; + ZEN_CHECK_COM(backupComp->GatherWriterMetadata(gatherAsync.init())); + waitForComFuture(*gatherAsync); //failure can happen if XP-version of VSS is used on Windows Vista (which needs at least VSS-Server2003 build) - vssWriters->QueryStatus(&hr, NULL); //check if the async operation succeeded... - if (FAILED(hr)) - { - writeErrorMsg(L"Error calling \"vssWriters->QueryStatus\".", hr, errorMessage, errorBufferLen); - return false; - } + VSS_ID snapshotSetId = {}; + ZEN_CHECK_COM(backupComp->StartSnapshotSet(&snapshotSetId)); + ScopeGuard guardSnapShot = makeGuard([&]() { backupComp->AbortBackup(); }); + //Quote: "This method must be called if a backup operation terminates after the creation of a + //shadow copy set with "StartSnapshotSet" and before "DoSnapshotSet" returns." - VSS_ID snapshotSetId = {0}; - if (FAILED(hr = backupComp->StartSnapshotSet(&snapshotSetId))) + VSS_ID SnapShotId = {}; { - writeErrorMsg(L"Error calling \"StartSnapshotSet\".", hr, errorMessage, errorBufferLen); - return false; + HRESULT hr = backupComp->AddToSnapshotSet(const_cast<wchar_t*>(volumeName), GUID_NULL, &SnapShotId); + if (FAILED(hr)) + { + if (hr == VSS_E_VOLUME_NOT_SUPPORTED) + throw ComError(L"Volume Shadow Copy Service is not supported on this volume!"); + throw ComError(L"Error calling \"backupComp->AddToSnapshotSet\".", hr); + } } - VSS_ID SnapShotId = {0}; - if (FAILED(hr = backupComp->AddToSnapshotSet(const_cast<wchar_t*>(volumeName), GUID_NULL, &SnapShotId))) - { - writeErrorMsg(L"Error calling \"AddToSnapshotSet\".", hr, errorMessage, errorBufferLen); - return false; - } + ComPtr<IVssAsync> prepareAsync; + ZEN_CHECK_COM(backupComp->PrepareForBackup(prepareAsync.init())); + waitForComFuture(*prepareAsync); - ComPtr<IVssAsync> vssPrepare; - if (FAILED(hr = backupComp->PrepareForBackup(vssPrepare.init()))) - { - writeErrorMsg(L"Error calling \"PrepareForBackup\".", hr, errorMessage, errorBufferLen); - return false; - } + ComPtr<IVssAsync> snapshotAsync; + ZEN_CHECK_COM(backupComp->DoSnapshotSet(snapshotAsync.init())); + guardSnapShot.dismiss(); + waitForComFuture(*snapshotAsync); - if (FAILED(hr = vssPrepare->Wait())) - { - writeErrorMsg(L"Error calling \"vssPrepare->Wait\".", hr, errorMessage, errorBufferLen); - return false; - } + VSS_SNAPSHOT_PROP props = {}; + ZEN_CHECK_COM(backupComp->GetSnapshotProperties(SnapShotId, &props)); + ZEN_ON_BLOCK_EXIT(::VssFreeSnapshotProperties(&props)); - vssPrepare->QueryStatus(&hr, NULL); //check if the async operation succeeded... - if (FAILED(hr)) - { - writeErrorMsg(L"Error calling \"vssPrepare->QueryStatus\".", hr, errorMessage, errorBufferLen); - return false; - } - - ComPtr<IVssAsync> vssDoShadowCopy; - if (FAILED(hr = backupComp->DoSnapshotSet(vssDoShadowCopy.init()))) - { - writeErrorMsg(L"Error calling \"DoSnapshotSet\".", hr, errorMessage, errorBufferLen); - return false; - } + //finally: write volume name of newly created shadow copy + return shadow::ShadowData(backupComp, props.m_pwszSnapshotDeviceObject); +} +} - if (FAILED(hr = vssDoShadowCopy->Wait())) - { - writeErrorMsg(L"Error calling \"vssDoShadowCopy->Wait\".", hr, errorMessage, errorBufferLen); - return false; - } - vssDoShadowCopy->QueryStatus(&hr, NULL); //check if the async operation succeeded... - if (FAILED(hr)) +shadow::ShadowHandle shadow::createShadowCopy(const wchar_t* volumeName, + wchar_t* errorMessage, + unsigned int errorBufferLen) +{ + try { - writeErrorMsg(L"Error calling \"vssDoShadowCopy->QueryStatus\".", hr, errorMessage, errorBufferLen); - return false; + ShadowData result = ::createShadowCopy(volumeName); //shadow handle owned by caller! throw ComError + return new ShadowData(result); } - - VSS_SNAPSHOT_PROP props; - if (FAILED(hr = backupComp->GetSnapshotProperties(SnapShotId, &props))) + catch (const zen::ComError& e) { - writeErrorMsg(L"Error calling \"GetSnapshotProperties\".", hr, errorMessage, errorBufferLen); - return false; + copyString(e.toString(), errorMessage, errorBufferLen); + return nullptr; } +} - //finally: write volume name of newly created shadow copy - copyString(props.m_pwszSnapshotDeviceObject, shadowVolName, shadowBufferLen); - - VssFreeSnapshotProperties(&props); - - *handle = backupComp.release(); - return true; +void shadow::getShadowVolume(shadow::ShadowHandle handle, + wchar_t* buffer, + unsigned int bufferLen) +{ + copyString(handle->shadowVolume_, buffer, bufferLen); } void shadow::releaseShadowCopy(ShadowHandle handle) { - if (handle) - handle->Release(); + delete handle; } diff --git a/lib/ShadowCopy/shadow.h b/lib/ShadowCopy/shadow.h index 0dfd39a9..68b7141f 100644 --- a/lib/ShadowCopy/shadow.h +++ b/lib/ShadowCopy/shadow.h @@ -26,23 +26,23 @@ namespace shadow --------------*/ //COM needs to be initialized before calling any of these functions! CoInitializeEx/CoUninitialize +struct ShadowData; +typedef ShadowData* ShadowHandle; -typedef IVssBackupComponents* ShadowHandle; - -//volumeName must end with "\", while shadowVolName does not end with "\" +//volumeName *must* end with "\" SHADOWDLL_API -bool createShadowCopy(const wchar_t* volumeName, // in - wchar_t* shadowVolName, // out - unsigned int shadowBufferLen, // in - ShadowHandle* handle, // out - wchar_t* errorMessage, // out - unsigned int errorBufferLen); // in - +ShadowHandle createShadowCopy(const wchar_t* volumeName, // in Returns nullptr on failure! + wchar_t* errorMessage, // out + unsigned int errorBufferLen); // in //don't forget to release the backupHandle after shadow copy is not needed anymore! SHADOWDLL_API void releaseShadowCopy(ShadowHandle handle); +SHADOWDLL_API +void getShadowVolume(ShadowHandle handle, //shadowVolName does *not* end with "\" + wchar_t* buffer, + unsigned int bufferLen); //########################################################################################## @@ -50,21 +50,24 @@ void releaseShadowCopy(ShadowHandle handle); /*---------- |typedefs| ----------*/ -typedef bool (*CreateShadowCopyFct)(const wchar_t* volumeName, - wchar_t* shadowVolName, - unsigned int shadowBufferLen, - ShadowHandle* handle, - wchar_t* errorMessage, - unsigned int errorBufferLen); +typedef ShadowHandle (*CreateShadowCopyFct)(const wchar_t* volumeName, + wchar_t* errorMessage, + unsigned int errorBufferLen); typedef void (*ReleaseShadowCopyFct)(ShadowHandle handle); +typedef void (*GetShadowVolumeFct)(ShadowHandle handle, + wchar_t* buffer, + unsigned int bufferLen); + + /*-------------- |symbol names| --------------*/ //(use const pointers to ensure internal linkage) -const char createShadowCopyFctName[] = "createShadowCopy"; +const char createShadowCopyFctName [] = "createShadowCopy"; const char releaseShadowCopyFctName[] = "releaseShadowCopy"; +const char getShadowVolumeFctName [] = "getShadowVolume"; /*--------------- |library names| @@ -73,21 +76,24 @@ const char releaseShadowCopyFctName[] = "releaseShadowCopy"; inline const wchar_t* getDllName() { - /* - 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 - */ - return zen::winServer2003orLater() ? - (zen::is64BitBuild ? - L"Shadow_Server2003_x64.dll" : - L"Shadow_Server2003_Win32.dll") : - - (zen::is64BitBuild ? - L"Shadow_XP_x64.dll" : - L"Shadow_XP_Win32.dll"); + // distinguish a bunch of VSS builds: we use XP, Server 2003 and Server 2008 R2 implementations... + // VSS version and compatibility overview: http://msdn.microsoft.com/en-us/library/aa384627(VS.85).aspx + + if (zen::win7OrLater()) //Windows Server 2008 R2 or Windows 7 + return zen::is64BitBuild ? + L"Shadow_Windows7_x64.dll" : + L"Shadow_Windows7_Win32.dll"; + //else if (vistaOrLater()) -> skip Windows Server 2008 and Windows Vista + // ; + else if (zen::winServer2003orLater()) //Windows Server 2003 and Windows Server 2003 R2 + return zen::is64BitBuild ? + L"Shadow_Server2003_x64.dll" : + L"Shadow_Server2003_Win32.dll"; + else //Windows XP + return zen::is64BitBuild ? + L"Shadow_XP_x64.dll" : + L"Shadow_XP_Win32.dll"; } } - - #endif //SHADOWCOPY_H |