// ************************************************************************** // * 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) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** #include "shadow.h" #include #include #include #include #include #define WIN32_LEAN_AND_MEAN #include "windows.h" #ifdef USE_SHADOW_XP #include "xp/inc/vss.h" #include "xp/inc/vswriter.h" #include "xp/inc/vsbackup.h" #elif defined USE_SHADOW_2003 #include "Server 2003/inc/vss.h" #include "Server 2003/inc/vswriter.h" #include "Server 2003/inc/vsbackup.h" #else adapt! #endif using namespace zen; namespace { inline void copyString(const std::wstring& input, wchar_t* buffer, size_t bufferSize) { if (bufferSize > 0) { //size_t endPos = input.copy(buffer, bufferSize - 1); //buffer[endPos] = 0; const size_t maxSize = std::min(input.length(), bufferSize - 1); std::copy(input.begin(), input.begin() + maxSize, buffer); buffer[maxSize] = 0; } } 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) { //MessageBox(0, L"backup err", L"", 0); */ *handle = 0; HRESULT hr = NULL; ComPtr 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; } if (FAILED(hr = backupComp->InitializeForBackup())) { writeErrorMsg(L"Error calling \"InitializeForBackup\".", hr, errorMessage, errorBufferLen); return false; } if (FAILED(hr = backupComp->SetBackupState(false, false, VSS_BT_FULL))) { writeErrorMsg(L"Error calling \"SetBackupState\".", hr, errorMessage, errorBufferLen); return false; } ComPtr 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; } //wait for shadow copy writers to complete if (FAILED(hr = vssWriters->Wait())) { writeErrorMsg(L"Error calling \"vssWriters->Wait\".", hr, errorMessage, errorBufferLen); return false; } 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 = {0}; if (FAILED(hr = backupComp->StartSnapshotSet(&snapshotSetId))) { writeErrorMsg(L"Error calling \"StartSnapshotSet\".", hr, errorMessage, errorBufferLen); return false; } VSS_ID SnapShotId = {0}; if (FAILED(hr = backupComp->AddToSnapshotSet(const_cast(volumeName), GUID_NULL, &SnapShotId))) { writeErrorMsg(L"Error calling \"AddToSnapshotSet\".", hr, errorMessage, errorBufferLen); return false; } ComPtr vssPrepare; if (FAILED(hr = backupComp->PrepareForBackup(vssPrepare.init()))) { writeErrorMsg(L"Error calling \"PrepareForBackup\".", hr, errorMessage, errorBufferLen); return false; } if (FAILED(hr = vssPrepare->Wait())) { writeErrorMsg(L"Error calling \"vssPrepare->Wait\".", hr, errorMessage, errorBufferLen); return false; } 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 vssDoShadowCopy; if (FAILED(hr = backupComp->DoSnapshotSet(vssDoShadowCopy.init()))) { writeErrorMsg(L"Error calling \"DoSnapshotSet\".", hr, errorMessage, errorBufferLen); return false; } 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)) { writeErrorMsg(L"Error calling \"vssDoShadowCopy->QueryStatus\".", hr, errorMessage, errorBufferLen); return false; } VSS_SNAPSHOT_PROP props; if (FAILED(hr = backupComp->GetSnapshotProperties(SnapShotId, &props))) { writeErrorMsg(L"Error calling \"GetSnapshotProperties\".", hr, errorMessage, errorBufferLen); return false; } //finally: write volume name of newly created shadow copy copyString(props.m_pwszSnapshotDeviceObject, shadowVolName, shadowBufferLen); VssFreeSnapshotProperties(&props); *handle = backupComp.release(); return true; } void shadow::releaseShadowCopy(ShadowHandle handle) { if (handle) handle->Release(); }