+/*
+ Bacula® - The Network Backup Solution
+
+ Copyright (C) 2005-2010 Free Software Foundation Europe e.V.
+
+ The main author of Bacula is Kern Sibbald, with contributions from
+ many others, a complete list can be found in the file AUTHORS.
+ This program is Free Software; you can redistribute it and/or
+ modify it under the terms of version two of the GNU General Public
+ License as published by the Free Software Foundation and included
+ in the file LICENSE.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ Bacula® is a registered trademark of Kern Sibbald.
+ The licensor of Bacula is the Free Software Foundation Europe
+ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+ Switzerland, email:ftf@fsfeurope.org.
+*/
// -*- Mode: C++ -*-
// vss.cpp -- Interface to Volume Shadow Copies (VSS)
//
// Copyright transferred from MATRIX-Computer GmbH to
// Kern Sibbald by express permission.
//
-// Copyright (C) 2005-2006 Kern Sibbald
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// version 2 as amended with additional clauses defined in the
-// file LICENSE in the main source directory.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// the file LICENSE for additional details.
-//
-//
// Author : Thorsten Engel
// Created On : Fri May 06 21:44:00 2005
#ifdef WIN32_VSS
-#include <bacula.h>
+#include "bacula.h"
#undef setlocale
#include "ms_atl.h"
#include <objbase.h>
+/*
+ * Kludges to get Vista code to compile.
+ * KES - June 2007
+ */
+#define __in IN
+#define __out OUT
+#define __RPC_unique_pointer
+#define __RPC_string
+#define __RPC__out_ecount_part(x, y)
+#define __RPC__deref_inout_opt
+#define __RPC__out
+
#if !defined(ENABLE_NLS)
#define setlocale(p, d)
#endif
class IXMLDOMDocument;
#endif
+/* Reduce compiler warnings from Windows vss code */
+#define uuid(x)
+
#ifdef B_VSS_XP
- #pragma message("compile VSS for Windows XP")
#define VSSClientGeneric VSSClientXP
#include "inc/WinXP/vss.h"
#include "inc/WinXP/vswriter.h"
#include "inc/WinXP/vsbackup.h"
-
- /* In VSSAPI.DLL */
- typedef HRESULT (STDAPICALLTYPE* t_CreateVssBackupComponents)(OUT IVssBackupComponents **);
- typedef void (APIENTRY* t_VssFreeSnapshotProperties)(IN VSS_SNAPSHOT_PROP*);
-
- static t_CreateVssBackupComponents p_CreateVssBackupComponents = NULL;
- static t_VssFreeSnapshotProperties p_VssFreeSnapshotProperties = NULL;
- #define VSSVBACK_ENTRY "?CreateVssBackupComponents@@YGJPAPAVIVssBackupComponents@@@Z"
#endif
#ifdef B_VSS_W2K3
- #pragma message("compile VSS for Windows 2003")
#define VSSClientGeneric VSSClient2003
#include "inc/Win2003/vss.h"
#include "inc/Win2003/vswriter.h"
#include "inc/Win2003/vsbackup.h"
+#endif
+
+#ifdef B_VSS_VISTA
+ #define VSSClientGeneric VSSClientVista
+
+ #include "inc/Win2003/vss.h"
+ #include "inc/Win2003/vswriter.h"
+ #include "inc/Win2003/vsbackup.h"
+#endif
- /* In VSSAPI.DLL */
- typedef HRESULT (STDAPICALLTYPE* t_CreateVssBackupComponents)(OUT IVssBackupComponents **);
- typedef void (APIENTRY* t_VssFreeSnapshotProperties)(IN VSS_SNAPSHOT_PROP*);
+/* In VSSAPI.DLL */
+typedef HRESULT (STDAPICALLTYPE* t_CreateVssBackupComponents)(OUT IVssBackupComponents **);
+typedef void (APIENTRY* t_VssFreeSnapshotProperties)(IN VSS_SNAPSHOT_PROP*);
- static t_CreateVssBackupComponents p_CreateVssBackupComponents = NULL;
- static t_VssFreeSnapshotProperties p_VssFreeSnapshotProperties = NULL;
+static t_CreateVssBackupComponents p_CreateVssBackupComponents = NULL;
+static t_VssFreeSnapshotProperties p_VssFreeSnapshotProperties = NULL;
+
- #define VSSVBACK_ENTRY "?CreateVssBackupComponents@@YGJPAPAVIVssBackupComponents@@@Z"
-#endif
#include "vss.h"
// Constructor
+#ifdef HAVE_VSS64
+/* 64 bit entrypoint name */
+#define VSSVBACK_ENTRY "?CreateVssBackupComponents@@YAJPEAPEAVIVssBackupComponents@@@Z"
+#else
+/* 32 bit entrypoint name */
+#define VSSVBACK_ENTRY "?CreateVssBackupComponents@@YGJPAPAVIVssBackupComponents@@@Z"
+#endif
+
VSSClientGeneric::VSSClientGeneric()
{
m_hLib = LoadLibraryA("VSSAPI.DLL");
if (m_hLib) {
p_CreateVssBackupComponents = (t_CreateVssBackupComponents)
GetProcAddress(m_hLib, VSSVBACK_ENTRY);
-
p_VssFreeSnapshotProperties = (t_VssFreeSnapshotProperties)
GetProcAddress(m_hLib, "VssFreeSnapshotProperties");
}
}
// Initialize the COM infrastructure and the internal pointers
-BOOL VSSClientGeneric::Initialize(DWORD dwContext, BOOL bDuringRestore)
+bool VSSClientGeneric::Initialize(DWORD dwContext, bool bDuringRestore)
{
if (!(p_CreateVssBackupComponents && p_VssFreeSnapshotProperties)) {
+ Dmsg2(0, "VSSClientGeneric::Initialize: p_CreateVssBackupComponents = 0x%08X, p_VssFreeSnapshotProperties = 0x%08X\n", p_CreateVssBackupComponents, p_VssFreeSnapshotProperties);
errno = ENOSYS;
- return FALSE;
+ return false;
}
HRESULT hr;
- // Initialize COM
- if (!m_bCoInitializeCalled) {
- if (FAILED(CoInitialize(NULL))) {
+ // Initialize COM
+ if (!m_bCoInitializeCalled) {
+ hr = CoInitialize(NULL);
+ if (FAILED(hr)) {
+ Dmsg1(0, "VSSClientGeneric::Initialize: CoInitialize returned 0x%08X\n", hr);
errno = b_errno_win32;
- return FALSE;
+ return false;
}
m_bCoInitializeCalled = true;
}
NULL // Reserved parameter
);
- if (FAILED(hr)) {
+ if (FAILED(hr)) {
+ Dmsg1(0, "VSSClientGeneric::Initialize: CoInitializeSecurity returned 0x%08X\n", hr);
errno = b_errno_win32;
- return FALSE;
+ return false;
}
- m_bCoInitializeSecurityCalled = true;
+ m_bCoInitializeSecurityCalled = true;
}
-
+
// Release the IVssBackupComponents interface
if (m_pVssObject) {
m_pVssObject->Release();
// Create the internal backup components object
hr = p_CreateVssBackupComponents((IVssBackupComponents**) &m_pVssObject);
- if (FAILED(hr)) {
+ if (FAILED(hr)) {
+ berrno be;
+ Dmsg2(0, "VSSClientGeneric::Initialize: CreateVssBackupComponents returned 0x%08X. ERR=%s\n",
+ hr, be.bstrerror(b_errno_win32));
errno = b_errno_win32;
- return FALSE;
+ return false;
}
-#ifdef B_VSS_W2K3
+#if defined(B_VSS_W2K3) || defined(B_VSS_VISTA)
if (dwContext != VSS_CTX_BACKUP) {
hr = ((IVssBackupComponents*) m_pVssObject)->SetContext(dwContext);
if (FAILED(hr)) {
+ Dmsg1(0, "VSSClientGeneric::Initialize: IVssBackupComponents->SetContext returned 0x%08X\n", hr);
errno = b_errno_win32;
- return FALSE;
+ return false;
}
}
#endif
if (!bDuringRestore) {
- // 1. InitializeForBackup
- hr = ((IVssBackupComponents*) m_pVssObject)->InitializeForBackup();
- if (FAILED(hr)) {
- errno = b_errno_win32;
- return FALSE;
- }
+ // 1. InitializeForBackup
+ hr = ((IVssBackupComponents*) m_pVssObject)->InitializeForBackup();
+ if (FAILED(hr)) {
+ Dmsg1(0, "VSSClientGeneric::Initialize: IVssBackupComponents->InitializeForBackup returned 0x%08X\n", hr);
+ errno = b_errno_win32;
+ return false;
+ }
- // 2. SetBackupState
- hr = ((IVssBackupComponents*) m_pVssObject)->SetBackupState(true, true, VSS_BT_FULL, false);
- if (FAILED(hr)) {
- errno = b_errno_win32;
- return FALSE;
- }
-
- CComPtr<IVssAsync> pAsync1;
- // 3. GatherWriterMetaData
- hr = ((IVssBackupComponents*) m_pVssObject)->GatherWriterMetadata(&pAsync1.p);
- if (FAILED(hr)) {
- errno = b_errno_win32;
- return FALSE;
- }
- // Waits for the async operation to finish and checks the result
- WaitAndCheckForAsyncOperation(pAsync1.p);
- }
+ // 2. SetBackupState
+ hr = ((IVssBackupComponents*) m_pVssObject)->SetBackupState(true, true, VSS_BT_FULL, false);
+ if (FAILED(hr)) {
+ Dmsg1(0, "VSSClientGeneric::Initialize: IVssBackupComponents->SetBackupState returned 0x%08X\n", hr);
+ errno = b_errno_win32;
+ return false;
+ }
+ CComPtr<IVssAsync> pAsync1;
+ // 3. GatherWriterMetaData
+ hr = ((IVssBackupComponents*) m_pVssObject)->GatherWriterMetadata(&pAsync1.p);
+ if (FAILED(hr)) {
+ Dmsg1(0, "VSSClientGeneric::Initialize: IVssBackupComponents->GatherWriterMetadata returned 0x%08X\n", hr);
+ errno = b_errno_win32;
+ return false;
+ }
+ // Waits for the async operation to finish and checks the result
+ WaitAndCheckForAsyncOperation(pAsync1.p);
+ }
// We are during restore now?
m_bDuringRestore = bDuringRestore;
// Keep the context
m_dwContext = dwContext;
- return TRUE;
+ return true;
}
-BOOL VSSClientGeneric::WaitAndCheckForAsyncOperation(IVssAsync* pAsync)
+bool VSSClientGeneric::WaitAndCheckForAsyncOperation(IVssAsync* pAsync)
{
// Wait until the async operation finishes
// unfortunately we can't use a timeout here yet.
} while ((timeout-- > 0) && (hrReturned == VSS_S_ASYNC_PENDING));
if (hrReturned == VSS_S_ASYNC_FINISHED)
- return TRUE;
+ return true;
-#ifdef DEBUG
+#ifdef xDEBUG
// Check if the async operation succeeded...
if(hrReturned != VSS_S_ASYNC_FINISHED) {
wchar_t *pwszBuffer = NULL;
- DWORD dwRet = ::FormatMessageW(
- FORMAT_MESSAGE_ALLOCATE_BUFFER
- | FORMAT_MESSAGE_FROM_SYSTEM
- | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, hrReturned,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPWSTR)&pwszBuffer, 0, NULL);
-
- if (dwRet != 0) {
- LocalFree(pwszBuffer);
- }
+ /* I don't see the usefulness of the following -- KES */
+ FormatMessageW(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, hrReturned,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPWSTR)&pwszBuffer, 0, NULL);
+
+ LocalFree(pwszBuffer);
errno = b_errno_win32;
}
#endif
- return FALSE;
+ return false;
}
-BOOL VSSClientGeneric::CreateSnapshots(char* szDriveLetters)
+bool VSSClientGeneric::CreateSnapshots(char* szDriveLetters)
{
/* szDriveLetters contains all drive letters in uppercase */
/* if a drive can not being added, it's converted to lowercase in szDriveLetters */
if (!m_pVssObject || m_bBackupIsInitialized) {
errno = ENOSYS;
- return FALSE;
+ return false;
}
m_uidCurrentSnapshotSet = GUID_NULL;
szDrive[0] = szDriveLetters[i];
volume = GetUniqueVolumeNameForPath(szDrive);
// store uniquevolumname
- if (SUCCEEDED(pVss->AddToSnapshotSet((LPWSTR)volume.c_str(), GUID_NULL, &pid)))
+ if (SUCCEEDED(pVss->AddToSnapshotSet((LPWSTR)volume.c_str(), GUID_NULL, &pid))) {
wcsncpy (m_wszUniqueVolumeName[szDriveLetters[i]-'A'], (LPWSTR) volume.c_str(), MAX_PATH);
- else
- {
+ } else {
szDriveLetters[i] = tolower (szDriveLetters[i]);
}
}
/* PrepareForBackup */
if (FAILED(pVss->PrepareForBackup(&pAsync1.p))) {
- return FALSE;
+ errno = b_errno_win32;
+ return false;
}
// Waits for the async operation to finish and checks the result
/* get latest info about writer status */
if (!CheckWriterStatus()) {
- return FALSE;
+ errno = b_errno_win32;
+ return false;
}
/* DoSnapShotSet */
if (FAILED(pVss->DoSnapshotSet(&pAsync2.p))) {
- return FALSE;
+ errno = b_errno_win32;
+ return false;
}
// Waits for the async operation to finish and checks the result
m_bBackupIsInitialized = true;
- return TRUE;
+ return true;
}
-BOOL VSSClientGeneric::CloseBackup()
+bool VSSClientGeneric::CloseBackup()
{
- BOOL bRet = FALSE;
+ bool bRet = false;
if (!m_pVssObject)
errno = ENOSYS;
else {
if (SUCCEEDED(pVss->BackupComplete(&pAsync.p))) {
// Waits for the async operation to finish and checks the result
WaitAndCheckForAsyncOperation(pAsync.p);
- bRet = TRUE;
+ bRet = true;
} else {
errno = b_errno_win32;
pVss->AbortBackup();
pVss->DeleteSnapshots(
m_uidCurrentSnapshotSet,
VSS_OBJECT_SNAPSHOT_SET,
- FALSE,
+ false,
&lSnapshots,
&idNonDeletedSnapshotID);
// Print the shadow copy (if not filtered out)
if (Snap.m_SnapshotSetId == snapshotSetID) {
- for (char ch='A'-'A';ch<='Z'-'A';ch++) {
+ for (int ch='A'-'A';ch<='Z'-'A';ch++) {
if (wcscmp(Snap.m_pwszOriginalVolumeName, m_wszUniqueVolumeName[ch]) == 0) {
- wcsncpy (m_szShadowCopyName[ch],Snap.m_pwszSnapshotDeviceObject, MAX_PATH-1);
+ wcsncpy(m_szShadowCopyName[ch],Snap.m_pwszSnapshotDeviceObject, MAX_PATH-1);
break;
}
}
}
// Check the status for all selected writers
-BOOL VSSClientGeneric::CheckWriterStatus()
+bool VSSClientGeneric::CheckWriterStatus()
{
/*
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vss/base/ivssbackupcomponents_startsnapshotset.asp
HRESULT hr = pVss->GatherWriterStatus(&pAsync.p);
if (FAILED(hr)) {
errno = b_errno_win32;
- return FALSE;
+ return false;
}
// Waits for the async operation to finish and checks the result
hr = pVss->GetWriterStatusCount(&cWriters);
if (FAILED(hr)) {
errno = b_errno_win32;
- return FALSE;
+ return false;
}
int nState;
case VSS_WS_FAILED_AT_BACKUP_COMPLETE:
case VSS_WS_FAILED_AT_PRE_RESTORE:
case VSS_WS_FAILED_AT_POST_RESTORE:
- #ifdef B_VSS_W2K3
+ #if defined(B_VSS_W2K3) || defined(B_VSS_VISTA)
case VSS_WS_FAILED_AT_BACKUPSHUTDOWN:
#endif
/* failed */
/* store text info */
char str[1000];
char szBuf[200];
- strcpy(str, "\"");
+ bstrncpy(str, "\"", sizeof(str));
wchar_2_UTF8(szBuf, bstrWriterName.p, sizeof(szBuf));
- strcat(str, szBuf);
- strcat(str, "\", State: 0x");
+ bstrncat(str, szBuf, sizeof(str));
+ bstrncat(str, "\", State: 0x", sizeof(str));
itoa(eWriterStatus, szBuf, sizeof(szBuf));
- strcat(str, szBuf);
- strcat(str, " (");
+ bstrncat(str, szBuf, sizeof(str));
+ bstrncat(str, " (", sizeof(str));
wchar_2_UTF8(szBuf, GetStringFromWriterStatus(eWriterStatus), sizeof(szBuf));
- strcat(str, szBuf);
- strcat(str, ")");
+ bstrncat(str, szBuf, sizeof(str));
+ bstrncat(str, ")", sizeof(str));
AppendWriterInfo(nState, (const char *)str);
}
if (FAILED(hr)) {
errno = b_errno_win32;
- return FALSE;
+ return false;
}
errno = 0;
- return TRUE;
+ return true;
}
#endif /* WIN32_VSS */