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 
48 /* The MTabEntry class is representing a mounted volume,
49  * it associates a volume name with mount paths and a device name
50  */
51 class MTabEntry: public SMARTALLOC {
52 public:
53    WCHAR *volumeName;         // Name of the current volume
54    WCHAR *mountPaths;         // List of mount paths
55    WCHAR *deviceName;
56    WCHAR *shadowCopyName;
57    bool   in_SnapshotSet;
58    bool   can_Snapshot;
59    UINT   driveType;
60    rblink link;
61 
MTabEntry()62    MTabEntry() {
63       mountPaths = NULL;
64       volumeName = NULL;
65       deviceName = NULL;
66       in_SnapshotSet = false;
67       shadowCopyName = NULL;
68       can_Snapshot = false;
69       driveType = 0;
70    };
71 
MTabEntry(WCHAR * DeviceName,WCHAR * VolumeName)72    MTabEntry(WCHAR *DeviceName, WCHAR *VolumeName) {
73       int last = wcslen(VolumeName);
74       if (VolumeName[last - 1] == L'\\') {
75          volumeName = bwcsdup(VolumeName);
76       } else {                         /* \\ + \0 */
77          volumeName = (WCHAR *)bmalloc(last+2*sizeof(WCHAR));
78          wcscpy(volumeName, VolumeName);
79          volumeName[last] = L'\\';
80          volumeName[last+1] = L'\0';
81       }
82       mountPaths = NULL;
83       in_SnapshotSet = false;
84       deviceName = bwcsdup(DeviceName);
85       shadowCopyName = NULL;
86       driveType = 0;
87       can_Snapshot = false;
88       get_paths();
89    };
90 
~MTabEntry()91    ~MTabEntry() {
92       destroy();
93    };
94 
destroy()95    void destroy() {
96       if (mountPaths) {
97          free(mountPaths);
98          mountPaths = NULL;
99       }
100       if (volumeName) {
101          free(volumeName);
102          volumeName = NULL;
103       }
104       if (deviceName) {
105          free(deviceName);
106          deviceName = NULL;
107       }
108       if (shadowCopyName) {
109          free(shadowCopyName);
110          shadowCopyName = NULL;
111       }
112    };
113 
114    /* Return  the drive type (cdrom, fixed, network, ...) */
115    UINT getDriveType();
116 
117    /* Return true if the current volume can be snapshoted (ie not CDROM or fat32) */
118    bool isSuitableForSnapshot();
119 
setInSnapshotSet()120    void setInSnapshotSet() {
121       Dmsg1(050, "Marking %ls for the SnapshotSet\n", mountPaths);
122       in_SnapshotSet = true;
123    }
124 
debug_paths()125    void debug_paths() {
126       WCHAR *p;
127       /*  Display the paths in the list. */
128       if (mountPaths != NULL) {
129          Dmsg2(DT_VOLUME|10, "Device: [%ls], Volume: [%ls]\n", deviceName, volumeName);
130          for ( p = mountPaths;  p[0] != L'\0'; p += wcslen(p) + 1) {
131             Dmsg1(DT_VOLUME|10, "  %ls\n", p);
132          }
133       }
134    };
135 
136    /* Compute the path list assiciated with the current volume */
get_paths()137    bool get_paths() {
138       DWORD  count = MAX_PATH + 1;
139       bool   ret = false;
140 
141       for (;;) {
142          //  Allocate a buffer to hold the paths.
143          mountPaths = (WCHAR*) malloc(count * sizeof(WCHAR));
144 
145          //  Obtain all of the paths
146          //  for this volume.
147          ret = GetVolumePathNamesForVolumeNameW(volumeName, mountPaths,
148                                                 count, &count);
149          if (ret) {
150             break;
151          }
152 
153          if (GetLastError() != ERROR_MORE_DATA) {
154             break;
155          }
156 
157          //  Try again with the
158          //  new suggested size.
159          free(mountPaths);
160          mountPaths = NULL;
161       }
162       debug_paths();
163       return ret;
164    };
165 
166    /* Return the first mount point */
first()167    WCHAR *first() {
168       return mountPaths;
169    };
170 
171    /* Return the next mount point */
next(WCHAR * prev)172    WCHAR *next(WCHAR *prev) {
173       if (prev == NULL || prev[0] == L'\0') {
174          return NULL;
175       }
176 
177       prev += wcslen(prev) + 1;
178 
179       return (prev[0] == L'\0') ? NULL : prev;
180    };
181 };
182 
183 /* Class to handle all volumes of the system, it contains
184  * a list of all current volumes (MTabEntry)
185  */
186 class MTab: public SMARTALLOC {
187 public:
188    DWORD       lasterror;
189    const char *lasterror_str;
190    rblist     *entries;         /* MTabEntry */
191    int         nb_in_SnapshotSet;
192 
MTab()193    MTab() {
194       MTabEntry *elt = NULL;
195       lasterror = ERROR_SUCCESS;
196       lasterror_str = "";
197       nb_in_SnapshotSet = 0;
198       entries = New(rblist(elt, &elt->link));
199    };
200 
~MTab()201    ~MTab() {
202       if (entries) {
203          MTabEntry *elt;
204          foreach_rblist(elt, entries) {
205             elt->destroy();
206          }
207          delete entries;
208       }
209    };
210    /* Get a Volume by name */
211    MTabEntry *search(char *file);
212 
213    /* Try to add a volume to the current snapshotset */
214    bool addInSnapshotSet(char *file);
215 
216    /* Fill the "entries" list will all detected volumes of the system*/
217    bool get();
218 };
219 
220 class VSSClient
221 {
222 public:
223     VSSClient();
224     virtual ~VSSClient();
225 
226     // Backup Process
227     bool InitializeForBackup(JCR *jcr);
228     bool InitializeForRestore(JCR *jcr);
229     virtual bool CreateSnapshots(alist *mount_points) = 0;
230     virtual bool CloseBackup() = 0;
231     virtual bool CloseRestore() = 0;
232     virtual WCHAR *GetMetadata() = 0;
233     virtual const char* GetDriverName() = 0;
234     bool GetShadowPath  (const char* szFilePath, char* szShadowPath, int nBuflen);
235     bool GetShadowPathW (const wchar_t* szFilePath, wchar_t* szShadowPath, int nBuflen); /* nBuflen in characters */
236 
237     const size_t GetWriterCount();
238     const char* GetWriterInfo(int nIndex);
239     const int   GetWriterState(int nIndex);
240     void DestroyWriterInfo();
241     void AppendWriterInfo(int nState, const char* pszInfo);
IsInitialized()242     const bool  IsInitialized() { return m_bBackupIsInitialized; };
GetVssObject()243     IUnknown *GetVssObject() { return m_pVssObject; };
244 
245 private:
246     virtual bool Initialize(DWORD dwContext, bool bDuringRestore = FALSE) = 0;
247     virtual bool WaitAndCheckForAsyncOperation(IVssAsync*  pAsync) = 0;
248     virtual void QuerySnapshotSet(GUID snapshotSetID) = 0;
249 
250 protected:
251     JCR       *m_jcr;
252 
253     DWORD      m_dwContext;
254 
255     IUnknown*  m_pVssObject;
256     GUID       m_uidCurrentSnapshotSet;
257 
258     MTab      *m_VolumeList;
259 
260     alist     *m_pAlistWriterState;
261     alist     *m_pAlistWriterInfoText;
262 
263     bool       m_bCoInitializeCalled;
264     bool       m_bCoInitializeSecurityCalled;
265     bool       m_bDuringRestore;  /* true if we are doing a restore */
266     bool       m_bBackupIsInitialized;
267     bool       m_bWriterStatusCurrent;
268 
269     WCHAR     *m_metadata;
270 
271     void       CreateVSSVolumeList();
272     void       DeleteVSSVolumeList();
273 };
274 
275 class VSSClientXP:public VSSClient
276 {
277 public:
278    VSSClientXP();
279    virtual ~VSSClientXP();
280    virtual bool CreateSnapshots(alist *mount_points);
281    virtual bool CloseBackup();
282    virtual bool CloseRestore();
283    virtual WCHAR *GetMetadata();
284 #ifdef _WIN64
GetDriverName()285    virtual const char* GetDriverName() { return "Win64 VSS"; };
286 #else
GetDriverName()287    virtual const char* GetDriverName() { return "Win32 VSS"; };
288 #endif
289 private:
290    virtual bool Initialize(DWORD dwContext, bool bDuringRestore);
291    virtual bool WaitAndCheckForAsyncOperation(IVssAsync* pAsync);
292    virtual void QuerySnapshotSet(GUID snapshotSetID);
293    bool CheckWriterStatus();
294 };
295 
296 class VSSClient2003:public VSSClient
297 {
298 public:
299    VSSClient2003();
300    virtual ~VSSClient2003();
301    virtual bool CreateSnapshots(alist *mount_points);
302    virtual bool CloseBackup();
303    virtual bool CloseRestore();
304    virtual WCHAR *GetMetadata();
305 #ifdef _WIN64
GetDriverName()306    virtual const char* GetDriverName() { return "Win64 VSS"; };
307 #else
GetDriverName()308    virtual const char* GetDriverName() { return "Win32 VSS"; };
309 #endif
310 private:
311    virtual bool Initialize(DWORD dwContext, bool bDuringRestore);
312    virtual bool WaitAndCheckForAsyncOperation(IVssAsync*  pAsync);
313    virtual void QuerySnapshotSet(GUID snapshotSetID);
314    bool CheckWriterStatus();
315 };
316 
317 class VSSClientVista:public VSSClient
318 {
319 public:
320    VSSClientVista();
321    virtual ~VSSClientVista();
322    virtual bool CreateSnapshots(alist *mount_points);
323    virtual bool CloseBackup();
324    virtual bool CloseRestore();
325    virtual WCHAR *GetMetadata();
326 #ifdef _WIN64
GetDriverName()327    virtual const char* GetDriverName() { return "Win64 VSS"; };
328 #else
GetDriverName()329    virtual const char* GetDriverName() { return "Win32 VSS"; };
330 #endif
331 private:
332    virtual bool Initialize(DWORD dwContext, bool bDuringRestore);
333    virtual bool WaitAndCheckForAsyncOperation(IVssAsync*  pAsync);
334    virtual void QuerySnapshotSet(GUID snapshotSetID);
335    bool CheckWriterStatus();
336 };
337 
338 
339 BOOL VSSPathConvert(const char *szFilePath, char *szShadowPath, int nBuflen);
340 BOOL VSSPathConvertW(const wchar_t *szFilePath, wchar_t *szShadowPath, int nBuflen);
341 
342 #endif /* WIN32_VSS */
343 
344 #endif /* __VSS_H_ */
345