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