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