1 /*
2    Bacula(R) - The Network Backup Solution
3 
4    Copyright (C) 2000-2020 Kern Sibbald
5 
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8 
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13 
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16 
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*                               -*- Mode: C -*-
20  * vss.h --
21  */
22 //
23 // Copyright transferred from MATRIX-Computer GmbH to
24 //   Kern Sibbald by express permission.
25 /*
26  *
27  * Author          : Thorsten Engel
28  * Created On      : Fri May 06 21:44:00 2006
29  */
30 
31 #ifndef __VSS_H_
32 #define __VSS_H_
33 
34 #ifndef b_errno_win32
35 #define b_errno_win32 (1<<29)
36 #endif
37 
38 #ifdef WIN32_VSS
39 
40 #define VSS_INIT_RESTORE_AFTER_INIT   1
41 #define VSS_INIT_RESTORE_AFTER_GATHER 2
42 
43 // some forward declarations
44 struct IVssAsync;
45 
46 #define bwcsdup(str) wcscpy((WCHAR *)bmalloc((wcslen(str)+1)*sizeof(WCHAR)),(str))
47 #define safe_bfree(buf) if (buf) { bfree(buf); buf = NULL; }
48 
49 /* The MTabEntry class is representing a mounted volume,
50  * it associates a volume name with mount paths and a device name
51  */
52 class MTabEntry: public SMARTALLOC {
53 public:
54    WCHAR *volumeName;         // Name of the current volume
55    WCHAR *mountPaths;         // List of mount paths
56    WCHAR *deviceName;
57    WCHAR *shadowCopyName;
58    bool   in_SnapshotSet;
59    bool   can_Snapshot;
60    UINT   driveType;
61    rblink link;
62 
MTabEntry()63    MTabEntry() {
64       mountPaths = NULL;
65       volumeName = NULL;
66       deviceName = NULL;
67       in_SnapshotSet = false;
68       shadowCopyName = NULL;
69       can_Snapshot = false;
70       driveType = 0;
71    };
72 
MTabEntry(WCHAR * DeviceName,WCHAR * VolumeName)73    MTabEntry(WCHAR *DeviceName, WCHAR *VolumeName) {
74       int last = wcslen(VolumeName);
75       if (VolumeName[last - 1] == L'\\') {
76          volumeName = bwcsdup(VolumeName);
77       } else {                         /* \\ + \0 */
78          volumeName = (WCHAR *)bmalloc((last+1)*sizeof(WCHAR));
79          wcscpy(volumeName, VolumeName);
80          volumeName[last] = L'\\';
81          volumeName[last+1] = L'\0';
82       }
83       mountPaths = NULL;
84       in_SnapshotSet = false;
85       deviceName = bwcsdup(DeviceName);
86       shadowCopyName = NULL;
87       driveType = 0;
88       can_Snapshot = false;
89       get_paths();
90    };
91 
~MTabEntry()92    ~MTabEntry() {
93       destroy();
94    };
95 
destroy()96    void destroy() {
97       safe_bfree(mountPaths);
98       safe_bfree(volumeName);
99       safe_bfree(deviceName);
100       safe_bfree(shadowCopyName);
101    };
102 
103    /* Return  the drive type (cdrom, fixed, network, ...) */
104    UINT getDriveType();
105 
106    /* Return true if the current volume can be snapshoted (ie not CDROM or fat32) */
107    bool isSuitableForSnapshot();
108 
setInSnapshotSet()109    void setInSnapshotSet() {
110       Dmsg1(050, "Marking %ls for the SnapshotSet\n", mountPaths);
111       in_SnapshotSet = true;
112    }
113 
debug_paths()114    void debug_paths() {
115       WCHAR *p;
116       /*  Display the paths in the list. */
117       if (mountPaths != NULL) {
118          Dmsg2(DT_VOLUME|10, "Device: [%ls], Volume: [%ls]\n", deviceName, volumeName);
119          for ( p = mountPaths;  p[0] != L'\0'; p += wcslen(p) + 1) {
120             Dmsg1(DT_VOLUME|10, "  %ls\n", p);
121          }
122       }
123    };
124 
125    /* Compute the path list assiciated with the current volume */
get_paths()126    bool get_paths() {
127       DWORD  count = MAX_PATH + 1;
128       bool   ret = false;
129 
130       for (;;) {
131          //  Allocate a buffer to hold the paths.
132          mountPaths = (WCHAR*) malloc(count * sizeof(WCHAR));
133 
134          //  Obtain all of the paths
135          //  for this volume.
136          ret = GetVolumePathNamesForVolumeNameW(volumeName, mountPaths,
137                                                 count, &count);
138          if (ret) {
139             break;
140          }
141 
142          if (GetLastError() != ERROR_MORE_DATA) {
143             break;
144          }
145 
146          //  Try again with the
147          //  new suggested size.
148          free(mountPaths);
149          mountPaths = NULL;
150       }
151       debug_paths();
152       return ret;
153    };
154 
155    /* Return the first mount point */
first()156    WCHAR *first() {
157       return mountPaths;
158    };
159 
160    /* Return the next mount point */
next(WCHAR * prev)161    WCHAR *next(WCHAR *prev) {
162       if (prev == NULL || prev[0] == L'\0') {
163          return NULL;
164       }
165 
166       prev += wcslen(prev) + 1;
167 
168       return (prev[0] == L'\0') ? NULL : prev;
169    };
170 };
171 
172 /* Class to handle all volumes of the system, it contains
173  * a list of all current volumes (MTabEntry)
174  */
175 class MTab: public SMARTALLOC {
176 public:
177    DWORD       lasterror;
178    const char *lasterror_str;
179    rblist     *entries;         /* MTabEntry */
180    int         nb_in_SnapshotSet;
181 
MTab()182    MTab() {
183       MTabEntry *elt = NULL;
184       lasterror = ERROR_SUCCESS;
185       lasterror_str = "";
186       nb_in_SnapshotSet = 0;
187       entries = New(rblist(elt, &elt->link));
188    };
189 
~MTab()190    ~MTab() {
191       if (entries) {
192          MTabEntry *elt;
193          foreach_rblist(elt, entries) {
194             elt->destroy();
195          }
196          delete entries;
197       }
198    };
199    /* Get a Volume by name */
200    MTabEntry *search(char *file);
201 
202    /* Try to add a volume to the current snapshotset */
203    bool addInSnapshotSet(char *file);
204 
205    /* Fill the "entries" list will all detected volumes of the system*/
206    bool get();
207 };
208 
209 class VSSClient
210 {
211 public:
212     VSSClient();
213     virtual ~VSSClient();
214 
215     // Backup Process
216     bool InitializeForBackup(JCR *jcr);
217     bool InitializeForRestore(JCR *jcr);
218     virtual bool CreateSnapshots(alist *mount_points) = 0;
219     virtual bool CloseBackup() = 0;
220     virtual bool CloseRestore() = 0;
221     virtual WCHAR *GetMetadata() = 0;
222     virtual const char* GetDriverName() = 0;
223     bool GetShadowPath  (const char* szFilePath, char* szShadowPath, int nBuflen);
224     bool GetShadowPathW (const wchar_t* szFilePath, wchar_t* szShadowPath, int nBuflen); /* nBuflen in characters */
225 
226     const size_t GetWriterCount();
227     const char* GetWriterInfo(int nIndex);
228     const int   GetWriterState(int nIndex);
229     void DestroyWriterInfo();
230     void AppendWriterInfo(int nState, const char* pszInfo);
IsInitialized()231     const bool  IsInitialized() { return m_bBackupIsInitialized; };
GetVssObject()232     IUnknown *GetVssObject() { return m_pVssObject; };
233 
234 private:
235     virtual bool Initialize(DWORD dwContext, bool bDuringRestore = FALSE) = 0;
236     virtual bool WaitAndCheckForAsyncOperation(IVssAsync*  pAsync) = 0;
237     virtual void QuerySnapshotSet(GUID snapshotSetID) = 0;
238 
239 protected:
240     JCR       *m_jcr;
241 
242     DWORD      m_dwContext;
243 
244     IUnknown*  m_pVssObject;
245     GUID       m_uidCurrentSnapshotSet;
246 
247     MTab      *m_VolumeList;
248 
249     alist     *m_pAlistWriterState;
250     alist     *m_pAlistWriterInfoText;
251 
252     bool       m_bCoInitializeCalled;
253     bool       m_bCoInitializeSecurityCalled;
254     bool       m_bDuringRestore;  /* true if we are doing a restore */
255     bool       m_bBackupIsInitialized;
256     bool       m_bWriterStatusCurrent;
257 
258     WCHAR     *m_metadata;
259 
260     void       CreateVSSVolumeList();
261     void       DeleteVSSVolumeList();
262 };
263 
264 class VSSClientXP:public VSSClient
265 {
266 public:
267    VSSClientXP();
268    virtual ~VSSClientXP();
269    virtual bool CreateSnapshots(alist *mount_points);
270    virtual bool CloseBackup();
271    virtual bool CloseRestore();
272    virtual WCHAR *GetMetadata();
273 #ifdef _WIN64
GetDriverName()274    virtual const char* GetDriverName() { return "Win64 VSS"; };
275 #else
GetDriverName()276    virtual const char* GetDriverName() { return "Win32 VSS"; };
277 #endif
278 private:
279    virtual bool Initialize(DWORD dwContext, bool bDuringRestore);
280    virtual bool WaitAndCheckForAsyncOperation(IVssAsync* pAsync);
281    virtual void QuerySnapshotSet(GUID snapshotSetID);
282    bool CheckWriterStatus();
283 };
284 
285 class VSSClient2003:public VSSClient
286 {
287 public:
288    VSSClient2003();
289    virtual ~VSSClient2003();
290    virtual bool CreateSnapshots(alist *mount_points);
291    virtual bool CloseBackup();
292    virtual bool CloseRestore();
293    virtual WCHAR *GetMetadata();
294 #ifdef _WIN64
GetDriverName()295    virtual const char* GetDriverName() { return "Win64 VSS"; };
296 #else
GetDriverName()297    virtual const char* GetDriverName() { return "Win32 VSS"; };
298 #endif
299 private:
300    virtual bool Initialize(DWORD dwContext, bool bDuringRestore);
301    virtual bool WaitAndCheckForAsyncOperation(IVssAsync*  pAsync);
302    virtual void QuerySnapshotSet(GUID snapshotSetID);
303    bool CheckWriterStatus();
304 };
305 
306 class VSSClientVista:public VSSClient
307 {
308 public:
309    VSSClientVista();
310    virtual ~VSSClientVista();
311    virtual bool CreateSnapshots(alist *mount_points);
312    virtual bool CloseBackup();
313    virtual bool CloseRestore();
314    virtual WCHAR *GetMetadata();
315 #ifdef _WIN64
GetDriverName()316    virtual const char* GetDriverName() { return "Win64 VSS"; };
317 #else
GetDriverName()318    virtual const char* GetDriverName() { return "Win32 VSS"; };
319 #endif
320 private:
321    virtual bool Initialize(DWORD dwContext, bool bDuringRestore);
322    virtual bool WaitAndCheckForAsyncOperation(IVssAsync*  pAsync);
323    virtual void QuerySnapshotSet(GUID snapshotSetID);
324    bool CheckWriterStatus();
325 };
326 
327 
328 BOOL VSSPathConvert(const char *szFilePath, char *szShadowPath, int nBuflen);
329 BOOL VSSPathConvertW(const wchar_t *szFilePath, wchar_t *szShadowPath, int nBuflen);
330 
331 #endif /* WIN32_VSS */
332 
333 #endif /* __VSS_H_ */
334