]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/win32/compat/vss.cpp
small vss improvement (more complete shutdown and startup after each backup instead...
[bacula/bacula] / bacula / src / win32 / compat / vss.cpp
index 6177b06c61a9a7498a0d961148f41ff20ccfbf66..8234aad31794e88bcfc6bf0bcc77eef2c17dc3f5 100644 (file)
@@ -1,28 +1,24 @@
-//                              -*- Mode: C++ -*-
+
 // vss.cpp -- Interface to Volume Shadow Copies (VSS)
 //
 // Copyright transferred from MATRIX-Computer GmbH to
 //   Kern Sibbald by express permission.
 //
-// Copyright (C) 2004-2005 Kern Sibbald
-//
-//   This program is free software; you can redistribute it and/or
-//   modify it under the terms of the GNU General Public License as
-//   published by the Free Software Foundation; either version 2 of
-//   the License, or (at your option) any later version.
+//  Copyright (C) 2005 Kern Sibbald
 //
-//   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.
+//  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.
 //
-//   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., 59 Temple Place - Suite 330, Boston,
-//   MA 02111-1307, USA.
+//  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 2006
+// Created On      : Fri May 06 21:44:00 2005
 
 
 #include <stdio.h>
@@ -65,79 +61,27 @@ using namespace std;
 
 // Used for safe string manipulation
 #include <strsafe.h>
-
-#include "vss/inc/WinXP/vss.h"
-#include "vss/inc/WinXP/vswriter.h"
-#include "vss/inc/WinXP/vsbackup.h"
-
 #include "vss.h"
 
-#pragma comment(lib,"C:/Development/bacula/bacula/src/win32/compat/vss/lib/WinXP/obj/i386/vssapi.lib")
-#pragma comment(lib,"C:/Development/bacula/bacula/src/win32/compat/vss/lib/WinXP/obj/i386/vss_uuid.lib")
-#pragma comment(lib,"atlsd.lib")
-
-
-
-// define global VssClient
-VSSClient g_VSSClient;
-
-/* 
- *
- * some helper functions 
- *
- *
- */
-
-// Append a backslash to the current string 
-inline wstring AppendBackslash(wstring str)
-{
-    if (str.length() == 0)
-        return wstring(L"\\");
-    if (str[str.length() - 1] == L'\\')
-        return str;
-    return str.append(L"\\");
-}
-
-// Get the unique volume name for the given path
-inline wstring GetUniqueVolumeNameForPath(wstring path)
-{
-    _ASSERTE(path.length() > 0);
-
-    // Add the backslash termination, if needed
-    path = AppendBackslash(path);
 
-    // Get the root path of the volume
-    WCHAR volumeRootPath[MAX_PATH];
-    WCHAR volumeName[MAX_PATH];
-    WCHAR volumeUniqueName[MAX_PATH];
-
-    if (!GetVolumePathNameW((LPCWSTR)path.c_str(), volumeRootPath, MAX_PATH))
-      return L'\0';
-    
-    // Get the volume name alias (might be different from the unique volume name in rare cases)
-    if (!GetVolumeNameForVolumeMountPointW(volumeRootPath, volumeName, MAX_PATH))
-       return L'\0';
-    
-    // Get the unique volume name    
-    if (!GetVolumeNameForVolumeMountPointW(volumeName, volumeUniqueName, MAX_PATH))
-       return L'\0';
-    
-    return volumeUniqueName;
-}
+#pragma comment(lib,"atlsd.lib")
 
 
-// we need something like a map
 
 // Constructor
 VSSClient::VSSClient()
 {
     m_bCoInitializeCalled = false;
-    m_dwContext = VSS_CTX_BACKUP;
+    m_bCoInitializeSecurityCalled = false;
+    m_dwContext = 0; // VSS_CTX_BACKUP;
     m_bDuringRestore = false;
     m_bBackupIsInitialized = false;
     m_pVssObject = NULL;
-    memset (m_wszUniqueVolumeName,0,sizeof (m_wszUniqueVolumeName));
-    memset (m_szShadowCopyName,0,sizeof (m_szShadowCopyName));
+    m_pVectorWriterStates = new vector<int>;
+    m_pVectorWriterInfo = new vector<string>;
+    m_uidCurrentSnapshotSet = GUID_NULL;
+    memset(m_wszUniqueVolumeName,0, sizeof(m_wszUniqueVolumeName));
+    memset(m_szShadowCopyName,0, sizeof(m_szShadowCopyName));
 }
 
 // Destructor
@@ -150,6 +94,12 @@ VSSClient::~VSSClient()
       m_pVssObject = NULL;
    }
 
+   if (m_pVectorWriterStates)
+      delete (m_pVectorWriterStates);
+
+   if (m_pVectorWriterInfo)
+      delete (m_pVectorWriterInfo);
+
    // Call CoUninitialize if the CoInitialize was performed sucesfully
    if (m_bCoInitializeCalled)
       CoUninitialize();
@@ -157,252 +107,58 @@ VSSClient::~VSSClient()
 
 BOOL VSSClient::InitializeForBackup()
 {
-    return Initialize (VSS_CTX_BACKUP);
+    //return Initialize (VSS_CTX_BACKUP);
+   return Initialize(0);
 }
 
-// Initialize the COM infrastructure and the internal pointers
-BOOL VSSClient::Initialize(DWORD dwContext, bool bDuringRestore)
-{
-   HRESULT hr;
-   // Initialize COM 
-   if (!m_bCoInitializeCalled)  {
-      if (FAILED(CoInitialize(NULL)))
-         return FALSE;
-
-      m_bCoInitializeCalled = true;
-
-      // Initialize COM security
-      hr =
-         CoInitializeSecurity(
-         NULL,                           //  Allow *all* VSS writers to communicate back!
-         -1,                             //  Default COM authentication service
-         NULL,                           //  Default COM authorization service
-         NULL,                           //  reserved parameter
-         RPC_C_AUTHN_LEVEL_PKT_PRIVACY,  //  Strongest COM authentication level
-         RPC_C_IMP_LEVEL_IDENTIFY,       //  Minimal impersonation abilities 
-         NULL,                           //  Default COM authentication settings
-         EOAC_NONE,                      //  No special options
-         NULL                            //  Reserved parameter
-         );
-
-      if (FAILED(hr))
-         return FALSE;
-   }
-
-   // Release the IVssBackupComponents interface 
-   if (m_pVssObject) {
-      m_pVssObject->Release();
-      m_pVssObject = NULL;
-   }
-
-   // Create the internal backup components object
-   hr = CreateVssBackupComponents(&m_pVssObject);
-   if (FAILED(hr))
-      return FALSE;
-
-   // We are during restore now?
-   m_bDuringRestore = bDuringRestore;
-/*
-   // Call either Initialize for backup or for restore
-   if (m_bDuringRestore)  {
-      hr = m_pVssObject->InitializeForRestore(CComBSTR(L""));
-      if (FAILED(hr))
-         return FALSE;
-   }
-   else
-   {
-      // Initialize for backup
-      hr = m_pVssObject->InitializeForBackup();
-      if (FAILED(hr))
-         return FALSE;
-   }
-
-   
-
-   // Set various properties per backup components instance
-   hr = m_pVssObject->SetBackupState(true, true, VSS_BT_FULL, false);
-   if (FAILED(hr))
-      return FALSE;
-*/
-// Keep the context
-   m_dwContext = dwContext;
-
-   return TRUE;
-}
-
-
-void VSSClient::WaitAndCheckForAsyncOperation(IVssAsync* pAsync)
-{
-     // Wait until the async operation finishes
-    HRESULT hr = pAsync->Wait();
-
-    // Check the result of the asynchronous operation
-    HRESULT hrReturned = S_OK;
-    hr = pAsync->QueryStatus(&hrReturned, NULL);
-
-    // Check if the async operation succeeded...
-    if(FAILED(hrReturned))
-    {
-        throw(hrReturned);
-    }
-}
-
-BOOL VSSClient::CreateSnapshots(char* szDriveLetters)
-{
-   /* szDriveLetters contains all drive letters in uppercase */
-   /* if a drive can not being added, it's converted to lowercase in szDriveLetters */
-   /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vss/base/ivssbackupcomponents_startsnapshotset.asp */
-   
-   if (!m_pVssObject || m_bBackupIsInitialized)
-      return FALSE;      
-
-   m_bBackupIsInitialized = true;
-
-   // 1. InitializeForBackup
-   HRESULT hr = m_pVssObject->InitializeForBackup();
-   if (FAILED(hr))
-      return FALSE;
-   
-   // 2. SetBackupState
-   hr = m_pVssObject->SetBackupState(true, true, VSS_BT_FULL, false);
-   if (FAILED(hr))
-      return FALSE;
-
-   CComPtr<IVssAsync>  pAsync;
-   VSS_ID latestSnapshotSetID;
-   VSS_ID pid;
-
-   // 3. startSnapshotSet
-
-   m_pVssObject->StartSnapshotSet(&latestSnapshotSetID);
-
-   // 4. AddToSnapshotSet
-
-   WCHAR szDrive[3];
-   szDrive[1] = ':';
-   szDrive[2] = 0;
-
-   wstring volume;
-
-   for (size_t i=0; i < strlen (szDriveLetters); i++) {
-      szDrive[0] = szDriveLetters[i];
-      volume = GetUniqueVolumeNameForPath(szDrive);
-      // store uniquevolumname
-      if (SUCCEEDED(m_pVssObject->AddToSnapshotSet((LPWSTR)volume.c_str(), GUID_NULL, &pid)))
-         wcsncpy (m_wszUniqueVolumeName[szDriveLetters[i]-'A'], (LPWSTR) volume.c_str(), MAX_PATH);
-      else
-         szDriveLetters[i] = tolower (szDriveLetters[i]);               
-   }
-
-   // 5. PrepareForBackup
-
-   m_pVssObject->PrepareForBackup(&pAsync);
 
-   // Waits for the async operation to finish and checks the result
-   WaitAndCheckForAsyncOperation(pAsync);
 
 
-   // 6. DoSnapShotSet
-   
-   pAsync = NULL;
-   m_pVssObject->DoSnapshotSet(&pAsync);
-
-   // Waits for the async operation to finish and checks the result
-   WaitAndCheckForAsyncOperation(pAsync); 
-   
-   /* query snapshot info */
-   QuerySnapshotSet(latestSnapshotSetID);
-
-   return TRUE;
-}
-
-BOOL VSSClient::CloseBackup()
+BOOL VSSClient::GetShadowPath(const char *szFilePath, char *szShadowPath, int nBuflen)
 {
-   if (!m_pVssObject || !m_bBackupIsInitialized)
+   if (!m_bBackupIsInitialized)
       return FALSE;
 
-   m_bBackupIsInitialized = false;
-
-   CComPtr<IVssAsync>  pAsync;
-
-   if (SUCCEEDED(m_pVssObject->BackupComplete(&pAsync))) {
-     // Waits for the async operation to finish and checks the result
-     WaitAndCheckForAsyncOperation(pAsync);
-   }
-   else return FALSE;
-   
-   return TRUE;
-}
-
-// Query all the shadow copies in the given set
-void VSSClient::QuerySnapshotSet(GUID snapshotSetID)
-{   
-   memset (m_szShadowCopyName,0,sizeof (m_szShadowCopyName));
-   
-   if (snapshotSetID == GUID_NULL || m_pVssObject == NULL)
-      return;
-            
-   // Get list all shadow copies. 
-   CComPtr<IVssEnumObject> pIEnumSnapshots;
-   HRESULT hr = m_pVssObject->Query( GUID_NULL, 
-         VSS_OBJECT_NONE, 
-         VSS_OBJECT_SNAPSHOT, 
-         &pIEnumSnapshots );    
-
-   // If there are no shadow copies, just return
-   if (hr == S_FALSE) {
-      return;
-   } 
-
-   // Enumerate all shadow copies. 
-   VSS_OBJECT_PROP Prop;
-   VSS_SNAPSHOT_PROP& Snap = Prop.Obj.Snap;
-   
-   while(true)
-   {
-      // Get the next element
-      ULONG ulFetched;
-      hr = pIEnumSnapshots->Next( 1, &Prop, &ulFetched );
-
-      // We reached the end of list
-      if (ulFetched == 0)
-         break;
-
-      // Print the shadow copy (if not filtered out)
-      if (Snap.m_SnapshotSetId == snapshotSetID)  {
-         for (char ch='A'-'A';ch<='Z'-'A';ch++) {
-            if (wcscmp(Snap.m_pwszOriginalVolumeName, m_wszUniqueVolumeName[ch]) == 0) {               
-               WideCharToMultiByte(CP_UTF8,0,Snap.m_pwszSnapshotDeviceObject,-1,m_szShadowCopyName[ch],MAX_PATH*2,NULL,NULL);               
-               break;
-            }
-         }
-      }
-      ::VssFreeSnapshotProperties(&Snap);
-   }
-}
-
-BOOL VSSClient::GetShadowPath (const char* szFilePath, char* szShadowPath, int nBuflen)
-{
    /* check for valid pathname */
    BOOL bIsValidName;
    
-   bIsValidName = strlen (szFilePath) > 3;
+   bIsValidName = strlen(szFilePath) > 3;
    if (bIsValidName)
       bIsValidName &= isalpha (szFilePath[0]) &&
                       szFilePath[1]==':' && 
-                      szFilePath[2]=='\\';
+                      szFilePath[2] == '\\';
 
    if (bIsValidName) {
       int nDriveIndex = toupper(szFilePath[0])-'A';
       if (m_szShadowCopyName[nDriveIndex][0] != 0) {
-         strncpy (szShadowPath, m_szShadowCopyName[nDriveIndex], nBuflen);
-         nBuflen -= (int) strlen (m_szShadowCopyName[nDriveIndex]);
-         strncat (szShadowPath, szFilePath+2,nBuflen);
-
+         strncpy(szShadowPath, m_szShadowCopyName[nDriveIndex], nBuflen);
+         nBuflen -= (int)strlen(m_szShadowCopyName[nDriveIndex]);
+         strncat(szShadowPath, szFilePath+2, nBuflen);
          return TRUE;
       }
    }
    
-   strncpy (szShadowPath,  szFilePath, nBuflen);
+   strncpy(szShadowPath,  szFilePath, nBuflen);
+   errno = EINVAL;
    return FALSE;   
-}
\ No newline at end of file
+}
+
+
+const size_t VSSClient::GetWriterCount()
+{
+   vector<int>* pV = (vector<int>*) m_pVectorWriterStates;
+   return pV->size();
+}
+
+const char* VSSClient::GetWriterInfo(size_t nIndex)
+{
+   vector<string>* pV = (vector<string>*) m_pVectorWriterInfo;   
+   return pV->at(nIndex).c_str();
+}
+
+
+const int VSSClient::GetWriterState(size_t nIndex)
+{
+   vector<int>* pV = (vector<int>*) m_pVectorWriterStates;   
+   return pV->at(nIndex);
+}