]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/win32/filed/vss.cpp
Back port fixes from BEE to fix Windows bug #1892
[bacula/bacula] / bacula / src / win32 / filed / vss.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2005-2010 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 // vss.cpp -- Interface to Volume Shadow Copies (VSS)
29 //
30 // Copyright transferred from MATRIX-Computer GmbH to
31 //   Kern Sibbald by express permission.
32 //
33 // Author          : Thorsten Engel
34 // Created On      : Fri May 06 21:44:00 2005
35
36
37 #ifdef WIN32_VSS
38 #include "bacula.h"
39 #include "compat.h"
40
41 #include "ms_atl.h"
42 #include <objbase.h>
43
44 #include "vss.h"
45
46 VSSClient *g_pVSSClient;
47
48 // {b5946137-7b9f-4925-af80-51abd60b20d5}
49
50 static const GUID VSS_SWPRV_ProviderID =
51    { 0xb5946137, 0x7b9f, 0x4925, { 0xaf, 0x80, 0x51, 0xab, 0xd6, 0x0b, 0x20, 0xd5 } };
52
53 void 
54 VSSCleanup()
55 {
56    if (g_pVSSClient) {
57       delete (g_pVSSClient);
58       g_pVSSClient = NULL;
59    }
60 }
61
62 /*
63  * May be called multiple times 
64  */
65 void VSSInit()
66 {
67    if (g_pVSSClient) {
68       return;                   /* already initialized */
69    }
70    /* decide which vss class to initialize */
71    if (g_MajorVersion == 5) {
72       switch (g_MinorVersion) {
73       case 1: 
74          g_pVSSClient = new VSSClientXP();
75          break;
76       case 2: 
77          g_pVSSClient = new VSSClient2003();
78          break;
79       }
80    /* Vista or Longhorn or later */
81    } else if (g_MajorVersion >= 6) {
82       g_pVSSClient = new VSSClientVista();
83    }
84    if (g_pVSSClient) {
85       atexit(VSSCleanup);
86    }
87 }
88
89 BOOL
90 VSSPathConvert(const char *szFilePath, char *szShadowPath, int nBuflen)
91 {
92    return g_pVSSClient->GetShadowPath(szFilePath, szShadowPath, nBuflen);
93 }
94
95 BOOL
96 VSSPathConvertW(const wchar_t *szFilePath, wchar_t *szShadowPath, int nBuflen)
97 {
98    return g_pVSSClient->GetShadowPathW(szFilePath, szShadowPath, nBuflen);
99 }
100
101 // Constructor
102 VSSClient::VSSClient()
103 {
104     memset(this, 0, sizeof(VSSClient));
105     m_pAlistWriterState = New(alist(10, not_owned_by_alist));
106     m_pAlistWriterInfoText = New(alist(10, owned_by_alist));
107     m_uidCurrentSnapshotSet = GUID_NULL;
108 }
109
110 // Destructor
111 VSSClient::~VSSClient()
112 {
113    // Release the IVssBackupComponents interface 
114    // WARNING: this must be done BEFORE calling CoUninitialize()
115    if (m_pVssObject) {
116 //      m_pVssObject->Release();
117       m_pVssObject = NULL;
118    }
119
120    DestroyWriterInfo();
121    delete m_pAlistWriterState;
122    delete m_pAlistWriterInfoText;
123
124    // Call CoUninitialize if the CoInitialize was performed successfully
125    if (m_bCoInitializeCalled) {
126       CoUninitialize();
127    }
128 }
129
130 bool VSSClient::InitializeForBackup(JCR *jcr)
131 {
132     //return Initialize (VSS_CTX_BACKUP);
133    m_jcr = jcr;
134    return Initialize(0);
135 }
136
137
138 bool VSSClient::InitializeForRestore(JCR *jcr)
139 {
140    m_metadata = NULL;
141    m_jcr = jcr;
142    return Initialize(0, true/*=>Restore*/);
143 }
144
145 bool VSSClient::GetShadowPath(const char *szFilePath, char *szShadowPath, int nBuflen)
146 {
147    if (!m_bBackupIsInitialized)
148       return false;
149
150    /* check for valid pathname */
151    bool bIsValidName;
152    
153    bIsValidName = strlen(szFilePath) > 3;
154    if (bIsValidName)
155       bIsValidName &= isalpha (szFilePath[0]) &&
156                       szFilePath[1]==':' && 
157                       szFilePath[2] == '\\';
158
159    if (bIsValidName) {
160       int nDriveIndex = toupper(szFilePath[0])-'A';
161       if (m_szShadowCopyName[nDriveIndex][0] != 0) {
162
163          if (WideCharToMultiByte(CP_UTF8,0,m_szShadowCopyName[nDriveIndex],-1,szShadowPath,nBuflen-1,NULL,NULL)) {
164             nBuflen -= (int)strlen(szShadowPath);
165             bstrncat(szShadowPath, szFilePath+2, nBuflen);
166             return true;
167          }
168       }
169    }
170    
171    bstrncpy(szShadowPath, szFilePath, nBuflen);
172    errno = EINVAL;
173    return false;   
174 }
175
176 bool VSSClient::GetShadowPathW(const wchar_t *szFilePath, wchar_t *szShadowPath, int nBuflen)
177 {
178    if (!m_bBackupIsInitialized)
179       return false;
180
181    /* check for valid pathname */
182    bool bIsValidName;
183    
184    bIsValidName = wcslen(szFilePath) > 3;
185    if (bIsValidName)
186       bIsValidName &= iswalpha (szFilePath[0]) &&
187                       szFilePath[1]==':' && 
188                       szFilePath[2] == '\\';
189
190    if (bIsValidName) {
191       int nDriveIndex = towupper(szFilePath[0])-'A';
192       if (m_szShadowCopyName[nDriveIndex][0] != 0) {
193          wcsncpy(szShadowPath, m_szShadowCopyName[nDriveIndex], nBuflen);
194          nBuflen -= (int)wcslen(m_szShadowCopyName[nDriveIndex]);
195          wcsncat(szShadowPath, szFilePath+2, nBuflen);
196          return true;
197       }
198    }
199    
200    wcsncpy(szShadowPath, szFilePath, nBuflen);
201    errno = EINVAL;
202    return false;   
203 }
204
205
206 const size_t VSSClient::GetWriterCount()
207 {
208    return m_pAlistWriterInfoText->size();
209 }
210
211 const char* VSSClient::GetWriterInfo(int nIndex)
212 {
213    return (char*)m_pAlistWriterInfoText->get(nIndex);
214 }
215
216
217 const int VSSClient::GetWriterState(int nIndex)
218 {
219    void *item = m_pAlistWriterState->get(nIndex);
220
221 /* Eliminate compiler warnings */
222 #ifdef HAVE_VSS64
223    return (int64_t)(char *)item;
224 #else
225    return (int)(char *)item;
226 #endif
227 }
228
229 void VSSClient::AppendWriterInfo(int nState, const char* pszInfo)
230 {
231    m_pAlistWriterInfoText->push(bstrdup(pszInfo));
232    m_pAlistWriterState->push((void*)nState);   
233 }
234
235 /*
236  * Note, this is called at the end of every job, so release all
237  *  the items in the alists, but do not delete the alist.
238  */
239 void VSSClient::DestroyWriterInfo()
240 {
241    while (!m_pAlistWriterInfoText->empty()) {
242       free(m_pAlistWriterInfoText->pop());
243    }
244
245    while (!m_pAlistWriterState->empty()) {
246       m_pAlistWriterState->pop();      
247    }
248 }
249
250 #endif