]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/win32/filed/vss_generic.cpp
Tweak: cross-tools + VSS
[bacula/bacula] / bacula / src / win32 / filed / vss_generic.cpp
index a61830ab03acf3c964ee18448fa15b99c181f324..034113e42f680f775560443ecfd6ecc33978606c 100644 (file)
@@ -1,29 +1,43 @@
+/*
+   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
 
@@ -38,6 +52,18 @@ using namespace std;
 #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
@@ -54,41 +80,42 @@ BOOL VSSPathConvertW(const wchar_t *szFilePath, wchar_t *szShadowPath, int nBufl
 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"
 
@@ -173,13 +200,20 @@ inline const wchar_t* GetStringFromWriterStatus(VSS_WRITER_STATE eWriterStatus)
 
 // 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");      
    } 
@@ -195,19 +229,22 @@ VSSClientGeneric::~VSSClientGeneric()
 }
 
 // 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;
    }
@@ -227,13 +264,14 @@ BOOL VSSClientGeneric::Initialize(DWORD dwContext, BOOL bDuringRestore)
          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();
@@ -242,47 +280,53 @@ BOOL VSSClientGeneric::Initialize(DWORD dwContext, BOOL bDuringRestore)
 
    // 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;
@@ -290,11 +334,11 @@ BOOL VSSClientGeneric::Initialize(DWORD dwContext, BOOL 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.
@@ -321,32 +365,31 @@ BOOL VSSClientGeneric::WaitAndCheckForAsyncOperation(IVssAsync* pAsync)
    } 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 */
@@ -354,7 +397,7 @@ BOOL VSSClientGeneric::CreateSnapshots(char* szDriveLetters)
    
    if (!m_pVssObject || m_bBackupIsInitialized) {
       errno = ENOSYS;
-      return FALSE;  
+      return false;  
    }
 
    m_uidCurrentSnapshotSet = GUID_NULL;
@@ -381,17 +424,17 @@ BOOL VSSClientGeneric::CreateSnapshots(char* szDriveLetters)
       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
@@ -399,12 +442,14 @@ BOOL VSSClientGeneric::CreateSnapshots(char* szDriveLetters)
 
    /* 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
@@ -417,12 +462,12 @@ BOOL VSSClientGeneric::CreateSnapshots(char* szDriveLetters)
 
    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 {
@@ -436,7 +481,7 @@ BOOL VSSClientGeneric::CloseBackup()
       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();
@@ -452,7 +497,7 @@ BOOL VSSClientGeneric::CloseBackup()
          pVss->DeleteSnapshots(
             m_uidCurrentSnapshotSet, 
             VSS_OBJECT_SNAPSHOT_SET,
-            FALSE,
+            false,
             &lSnapshots,
             &idNonDeletedSnapshotID);
 
@@ -517,9 +562,9 @@ void VSSClientGeneric::QuerySnapshotSet(GUID snapshotSetID)
 
       // 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;
             }
          }
@@ -530,7 +575,7 @@ void VSSClientGeneric::QuerySnapshotSet(GUID snapshotSetID)
 }
 
 // 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
@@ -544,7 +589,7 @@ BOOL VSSClientGeneric::CheckWriterStatus()
     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
@@ -555,7 +600,7 @@ BOOL VSSClientGeneric::CheckWriterStatus()
     hr = pVss->GetWriterStatusCount(&cWriters);
     if (FAILED(hr)) {
        errno = b_errno_win32;
-       return FALSE;
+       return false;
     }
 
     int nState;
@@ -590,7 +635,7 @@ BOOL VSSClientGeneric::CheckWriterStatus()
             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 */                
@@ -605,16 +650,16 @@ BOOL VSSClientGeneric::CheckWriterStatus()
         /* 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);     
     }
@@ -623,11 +668,11 @@ BOOL VSSClientGeneric::CheckWriterStatus()
 
     if (FAILED(hr)) {
         errno = b_errno_win32;
-        return FALSE;
+        return false;
     } 
 
     errno = 0;
-    return TRUE;
+    return true;
 }
 
 #endif /* WIN32_VSS */