2 * win32_vss.c - Windows-specific code for creating VSS (Volume Shadow Copy
7 * Copyright (C) 2015-2016 Eric Biggers
9 * This file is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU Lesser General Public License as published by the Free
11 * Software Foundation; either version 3 of the License, or (at your option) any
14 * This file is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this file; if not, see http://www.gnu.org/licenses/.
29 #include "wimlib/win32_common.h"
34 #include "wimlib/error.h"
35 #include "wimlib/util.h"
36 #include "wimlib/win32_vss.h"
38 /*----------------------------------------------------------------------------*
39 * VSS API declarations *
40 *----------------------------------------------------------------------------*/
43 typedef LONGLONG VSS_TIMESTAMP;
44 typedef WCHAR *VSS_PWSZ;
49 VSS_BT_INCREMENTAL = 2,
50 VSS_BT_DIFFERENTIAL = 3,
57 VSS_SS_UNKNOWN = 0x00,
58 VSS_SS_PREPARING = 0x01,
59 VSS_SS_PROCESSING_PREPARE = 0x02,
60 VSS_SS_PREPARED = 0x03,
61 VSS_SS_PROCESSING_PRECOMMIT = 0x04,
62 VSS_SS_PRECOMMITTED = 0x05,
63 VSS_SS_PROCESSING_COMMIT = 0x06,
64 VSS_SS_COMMITTED = 0x07,
65 VSS_SS_PROCESSING_POSTCOMMIT = 0x08,
66 VSS_SS_PROCESSING_PREFINALCOMMIT = 0x09,
67 VSS_SS_PREFINALCOMMITTED = 0x0a,
68 VSS_SS_PROCESSING_POSTFINALCOMMIT = 0x0b,
69 VSS_SS_CREATED = 0x0c,
70 VSS_SS_ABORTED = 0x0d,
71 VSS_SS_DELETED = 0x0e,
72 VSS_SS_POSTCOMMITTED = 0x0f,
77 VSS_VOLSNAP_ATTR_PERSISTENT = 0x00000001,
78 VSS_VOLSNAP_ATTR_NO_AUTORECOVERY = 0x00000002,
79 VSS_VOLSNAP_ATTR_CLIENT_ACCESSIBLE = 0x00000004,
80 VSS_VOLSNAP_ATTR_NO_AUTO_RELEASE = 0x00000008,
81 VSS_VOLSNAP_ATTR_NO_WRITERS = 0x00000010,
82 VSS_VOLSNAP_ATTR_TRANSPORTABLE = 0x00000020,
83 VSS_VOLSNAP_ATTR_NOT_SURFACED = 0x00000040,
84 VSS_VOLSNAP_ATTR_NOT_TRANSACTED = 0x00000080,
85 VSS_VOLSNAP_ATTR_HARDWARE_ASSISTED = 0x00010000,
86 VSS_VOLSNAP_ATTR_DIFFERENTIAL = 0x00020000,
87 VSS_VOLSNAP_ATTR_PLEX = 0x00040000,
88 VSS_VOLSNAP_ATTR_IMPORTED = 0x00080000,
89 VSS_VOLSNAP_ATTR_EXPOSED_LOCALLY = 0x00100000,
90 VSS_VOLSNAP_ATTR_EXPOSED_REMOTELY = 0x00200000,
91 VSS_VOLSNAP_ATTR_AUTORECOVER = 0x00400000,
92 VSS_VOLSNAP_ATTR_ROLLBACK_RECOVERY = 0x00800000,
93 VSS_VOLSNAP_ATTR_DELAYED_POSTSNAPSHOT = 0x01000000,
94 VSS_VOLSNAP_ATTR_TXF_RECOVERY = 0x02000000,
95 } VSS_VOLUME_SNAPSHOT_ATTRIBUTES;
99 VSS_CTX_FILE_SHARE_BACKUP = VSS_VOLSNAP_ATTR_NO_WRITERS,
100 VSS_CTX_NAS_ROLLBACK = ( ( VSS_VOLSNAP_ATTR_PERSISTENT | VSS_VOLSNAP_ATTR_NO_AUTO_RELEASE ) | VSS_VOLSNAP_ATTR_NO_WRITERS ),
101 VSS_CTX_APP_ROLLBACK = ( VSS_VOLSNAP_ATTR_PERSISTENT | VSS_VOLSNAP_ATTR_NO_AUTO_RELEASE ),
102 VSS_CTX_CLIENT_ACCESSIBLE = ( ( ( VSS_VOLSNAP_ATTR_PERSISTENT | VSS_VOLSNAP_ATTR_CLIENT_ACCESSIBLE ) | VSS_VOLSNAP_ATTR_NO_AUTO_RELEASE ) | VSS_VOLSNAP_ATTR_NO_WRITERS ),
103 VSS_CTX_CLIENT_ACCESSIBLE_WRITERS = ( ( VSS_VOLSNAP_ATTR_PERSISTENT | VSS_VOLSNAP_ATTR_CLIENT_ACCESSIBLE ) | VSS_VOLSNAP_ATTR_NO_AUTO_RELEASE ),
104 VSS_CTX_ALL = 0xffffffff,
105 } VSS_SNAPSHOT_CONTEXT;
109 VSS_ID m_SnapshotSetId;
110 LONG m_lSnapshotsCount;
111 VSS_PWSZ m_pwszSnapshotDeviceObject;
112 VSS_PWSZ m_pwszOriginalVolumeName;
113 VSS_PWSZ m_pwszOriginatingMachine;
114 VSS_PWSZ m_pwszServiceMachine;
115 VSS_PWSZ m_pwszExposedName;
116 VSS_PWSZ m_pwszExposedPath;
118 LONG m_lSnapshotAttributes;
119 VSS_TIMESTAMP m_tsCreationTimestamp;
120 VSS_SNAPSHOT_STATE m_eStatus;
123 typedef struct IVssAsyncVTable IVssAsyncVTable;
126 IVssAsyncVTable *vtable;
129 struct IVssAsyncVTable {
130 void *QueryInterface;
132 ULONG (WINAPI *Release)(IVssAsync *this);
135 HRESULT (WINAPI *Wait)(IVssAsync *this, DWORD dwMilliseconds);
137 /* Pre-Vista version */
138 HRESULT (WINAPI *OldWait)(IVssAsync *this);
143 typedef struct IVssBackupComponentsVTable IVssBackupComponentsVTable;
144 typedef struct IVssBackupComponentsVTable_old IVssBackupComponentsVTable_old;
147 IVssBackupComponentsVTable *vtable;
148 IVssBackupComponentsVTable_old *old_vtable;
149 } IVssBackupComponents;
151 struct IVssBackupComponentsVTable {
152 void *QueryInterface;
154 ULONG (WINAPI *Release)(IVssBackupComponents *this);
155 void *GetWriterComponentsCount;
156 void *GetWriterComponents;
157 HRESULT (WINAPI *InitializeForBackup)(IVssBackupComponents *this,
159 HRESULT (WINAPI *SetBackupState)(IVssBackupComponents *this,
160 BOOLEAN bSelectComponents,
161 BOOLEAN bBackupBootableSystemState,
162 VSS_BACKUP_TYPE backupType,
163 BOOLEAN bPartialFileSupport);
164 void *InitializeForRestore;
165 void *SetRestoreState;
166 HRESULT (WINAPI *GatherWriterMetadata)(IVssBackupComponents *this,
167 IVssAsync **ppAsync);
168 void *GetWriterMetadataCount;
169 void *GetWriterMetadata;
170 void *FreeWriterMetadata;
172 HRESULT (WINAPI *PrepareForBackup)(IVssBackupComponents *this,
173 IVssAsync **ppAsync);
175 void *GatherWriterStatus;
176 void *GetWriterStatusCount;
177 void *FreeWriterStatus;
178 void *GetWriterStatus;
179 void *SetBackupSucceeded;
180 void *SetBackupOptions;
181 void *SetSelectedForRestore;
182 void *SetRestoreOptions;
183 void *SetAdditionalRestores;
184 void *SetPreviousBackupStamp;
186 void *BackupComplete;
187 void *AddAlternativeLocationMapping;
188 void *AddRestoreSubcomponent;
189 void *SetFileRestoreStatus;
191 void *SetRangesFilePath;
194 HRESULT (WINAPI *SetContext)(IVssBackupComponents *this,
196 HRESULT (WINAPI *StartSnapshotSet)(IVssBackupComponents *this,
197 VSS_ID *pSnapshotSetId);
198 HRESULT (WINAPI *AddToSnapshotSet)(IVssBackupComponents *this,
199 VSS_PWSZ pwszVolumeName,
201 VSS_ID *pidSnapshot);
202 HRESULT (WINAPI *DoSnapshotSet)(IVssBackupComponents *this,
203 IVssAsync **ppAsync);
204 void *DeleteSnapshots;
205 void *ImportSnapshots;
206 /*void *RemountReadWrite;*/ /* Old API only */
207 void *BreakSnapshotSet;
208 HRESULT (WINAPI *GetSnapshotProperties)(IVssBackupComponents *this,
210 VSS_SNAPSHOT_PROP *pprop);
212 void *IsVolumeSupported;
213 void *DisableWriterClasses;
214 void *EnableWriterClasses;
215 void *DisableWriterInstances;
216 void *ExposeSnapshot;
217 void *RevertToSnapshot;
218 void *QueryRevertStatus;
221 /* Pre-Vista version */
222 struct IVssBackupComponentsVTable_old {
223 void *QueryInterface;
225 ULONG (WINAPI *Release)(IVssBackupComponents *this);
226 void *GetWriterComponentsCount;
227 void *GetWriterComponents;
228 HRESULT (WINAPI *InitializeForBackup)(IVssBackupComponents *this,
230 HRESULT (WINAPI *SetBackupState)(IVssBackupComponents *this,
231 BOOLEAN bSelectComponents,
232 BOOLEAN bBackupBootableSystemState,
233 VSS_BACKUP_TYPE backupType,
234 BOOLEAN bPartialFileSupport);
235 void *InitializeForRestore;
236 /*void *SetRestoreState;*/ /* New API only */
237 HRESULT (WINAPI *GatherWriterMetadata)(IVssBackupComponents *this,
238 IVssAsync **ppAsync);
239 void *GetWriterMetadataCount;
240 void *GetWriterMetadata;
241 void *FreeWriterMetadata;
243 HRESULT (WINAPI *PrepareForBackup)(IVssBackupComponents *this,
244 IVssAsync **ppAsync);
246 void *GatherWriterStatus;
247 void *GetWriterStatusCount;
248 void *FreeWriterStatus;
249 void *GetWriterStatus;
250 void *SetBackupSucceeded;
251 void *SetBackupOptions;
252 void *SetSelectedForRestore;
253 void *SetRestoreOptions;
254 void *SetAdditionalRestores;
255 void *SetPreviousBackupStamp;
257 void *BackupComplete;
258 void *AddAlternativeLocationMapping;
259 void *AddRestoreSubcomponent;
260 void *SetFileRestoreStatus;
261 /*void *AddNewTarget;*/ /* New API only */
262 /*void *SetRangesFilePath;*/ /* New API only */
265 HRESULT (WINAPI *SetContext)(IVssBackupComponents *this,
267 HRESULT (WINAPI *StartSnapshotSet)(IVssBackupComponents *this,
268 VSS_ID *pSnapshotSetId);
269 HRESULT (WINAPI *AddToSnapshotSet)(IVssBackupComponents *this,
270 VSS_PWSZ pwszVolumeName,
272 VSS_ID *pidSnapshot);
273 HRESULT (WINAPI *DoSnapshotSet)(IVssBackupComponents *this,
274 IVssAsync **ppAsync);
275 void *DeleteSnapshots;
276 void *ImportSnapshots;
277 void *RemountReadWrite;
278 void *BreakSnapshotSet;
279 HRESULT (WINAPI *GetSnapshotProperties)(IVssBackupComponents *this,
281 VSS_SNAPSHOT_PROP *pprop);
283 void *IsVolumeSupported;
284 void *DisableWriterClasses;
285 void *EnableWriterClasses;
286 void *DisableWriterInstances;
287 void *ExposeSnapshot;
288 /*void *RevertToSnapshot;*/ /* New API only */
289 /*void *QueryRevertStatus;*/ /* New API only */
292 /* Call a method, assuming its signature is identical in the old and new APIs */
293 #define CALL_METHOD(obj, method, ...) \
297 res = (obj)->old_vtable->method((obj), ##__VA_ARGS__); \
299 res = (obj)->vtable->method((obj), ##__VA_ARGS__); \
303 /*----------------------------------------------------------------------------*
304 * VSS API initialization *
305 *----------------------------------------------------------------------------*/
307 static bool vss_initialized;
308 static pthread_mutex_t vss_initialization_mutex = PTHREAD_MUTEX_INITIALIZER;
311 static bool is_old_api; /* old VSS API (pre-Vista)? */
312 static HANDLE hVssapi;
313 static HRESULT (WINAPI *func_CreateVssBackupComponents)(IVssBackupComponents **ppBackup);
314 static void (WINAPI *func_VssFreeSnapshotProperties)(VSS_SNAPSHOT_PROP *pProp);
317 static HANDLE hOle32;
318 static void (WINAPI *func_CoInitialize)(LPVOID *pvReserved);
319 static void (WINAPI *func_CoUninitialize)(void);
322 vss_global_init_impl(void)
324 hVssapi = LoadLibrary(L"vssapi.dll");
326 ERROR("vssapi.dll not found");
330 func_CreateVssBackupComponents =
331 (void *)GetProcAddress(hVssapi, "CreateVssBackupComponentsInternal");
332 if (!func_CreateVssBackupComponents) {
333 func_CreateVssBackupComponents =
334 (void *)GetProcAddress(hVssapi, "?CreateVssBackupComponents@@YGJPAPAVIVssBackupComponents@@@Z");
335 if (!func_CreateVssBackupComponents) {
336 ERROR("CreateVssBackupComponents() not found in vssapi.dll");
344 func_VssFreeSnapshotProperties =
345 (void *)GetProcAddress(hVssapi, "VssFreeSnapshotPropertiesInternal");
346 if (!func_VssFreeSnapshotProperties) {
347 func_VssFreeSnapshotProperties =
348 (void *)GetProcAddress(hVssapi, "VssFreeSnapshotProperties");
349 if (!func_VssFreeSnapshotProperties) {
350 ERROR("VssFreeSnapshotProperties() not found in vssapi.dll");
355 hOle32 = LoadLibrary(L"ole32.dll");
357 ERROR("ole32.dll not found");
361 func_CoInitialize = (void *)GetProcAddress(hOle32, "CoInitialize");
362 if (!func_CoInitialize) {
363 ERROR("CoInitialize() not found in ole32.dll");
367 func_CoUninitialize = (void *)GetProcAddress(hOle32, "CoUninitialize");
368 if (!func_CoUninitialize) {
369 ERROR("CoUninitialize() not found in ole32.dll");
373 (*func_CoInitialize)(NULL);
379 FreeLibrary(hVssapi);
385 vss_global_init(void)
390 pthread_mutex_lock(&vss_initialization_mutex);
391 if (!vss_initialized)
392 vss_initialized = vss_global_init_impl();
393 pthread_mutex_unlock(&vss_initialization_mutex);
397 ERROR("The Volume Shadow Copy Service (VSS) API could not be "
398 "initialized. Probably it isn't supported on this computer.");
403 vss_global_cleanup(void)
405 if (!vss_initialized)
408 pthread_mutex_lock(&vss_initialization_mutex);
409 if (vss_initialized) {
410 (*func_CoUninitialize)();
412 FreeLibrary(hVssapi);
413 vss_initialized = false;
415 pthread_mutex_unlock(&vss_initialization_mutex);
418 /*----------------------------------------------------------------------------*
419 * VSS implementation *
420 *----------------------------------------------------------------------------*/
422 struct vss_snapshot_internal {
423 struct vss_snapshot base;
424 IVssBackupComponents *vss;
425 VSS_SNAPSHOT_PROP props;
428 /* Delete the specified VSS snapshot. */
430 vss_delete_snapshot(struct vss_snapshot *snapshot)
432 struct vss_snapshot_internal *internal;
434 internal = container_of(snapshot, struct vss_snapshot_internal, base);
436 if (internal->props.m_pwszSnapshotDeviceObject)
437 (*func_VssFreeSnapshotProperties)(&internal->props);
439 CALL_METHOD(internal->vss, Release);
444 wait_and_release(IVssAsync *async)
448 res = async->vtable->OldWait(async);
450 res = async->vtable->Wait(async, INFINITE);
451 async->vtable->Release(async);
456 request_vss_snapshot(IVssBackupComponents *vss, wchar_t *volume,
462 res = CALL_METHOD(vss, InitializeForBackup, NULL);
464 ERROR("IVssBackupComponents.InitializeForBackup() error: %x", res);
468 res = CALL_METHOD(vss, SetBackupState, FALSE, TRUE, VSS_BT_COPY, FALSE);
470 ERROR("IVssBackupComponents.SetBackupState() error: %x", res);
474 res = CALL_METHOD(vss, StartSnapshotSet, snapshot_id);
476 ERROR("IVssBackupComponents.StartSnapshotSet() error: %x", res);
480 res = CALL_METHOD(vss, AddToSnapshotSet, volume, (GUID){}, snapshot_id);
482 ERROR("IVssBackupComponents.AddToSnapshotSet() error: %x", res);
486 res = CALL_METHOD(vss, PrepareForBackup, &async);
488 ERROR("IVssBackupComponents.PrepareForBackup() error: %x", res);
491 res = wait_and_release(async);
493 ERROR("IVssAsync.Wait() error while preparing for backup: %x", res);
497 res = CALL_METHOD(vss, DoSnapshotSet, &async);
499 ERROR("IVssBackupComponents.DoSnapshotSet() error: %x", res);
502 res = wait_and_release(async);
504 ERROR("IVssAsync.Wait() error while doing snapshot set: %x", res);
515 if (sizeof(size_t) == 4)
516 IsWow64Process(GetCurrentProcess(), &wow64);
521 * Create a VSS snapshot of the specified @volume. Return the NT namespace path
522 * to the snapshot root directory in @vss_path_ret and a handle to the snapshot
526 vss_create_snapshot(const wchar_t *source, UNICODE_STRING *vss_path_ret,
527 struct vss_snapshot **snapshot_ret)
529 wchar_t *source_abspath;
532 struct vss_snapshot_internal *snapshot = NULL;
533 IVssBackupComponents *vss;
537 source_abspath = realpath(source, NULL);
538 if (!source_abspath) {
539 ret = WIMLIB_ERR_NOMEM;
543 if (source_abspath[0] == L'\0' || source_abspath[1] != L':' ||
544 source_abspath[2] != L'\\') {
545 ERROR("\"%ls\" (full path \"%ls\"): Path format not recognized",
546 source, source_abspath);
547 ret = WIMLIB_ERR_UNSUPPORTED;
551 wsprintf(volume, L"%lc:\\", source_abspath[0]);
553 snapshot = CALLOC(1, sizeof(*snapshot));
555 ret = WIMLIB_ERR_NOMEM;
559 if (!vss_global_init())
562 res = (*func_CreateVssBackupComponents)(&vss);
564 ERROR("CreateVssBackupComponents error: %x", res);
570 if (!request_vss_snapshot(vss, volume, &snapshot_id))
573 res = CALL_METHOD(vss, GetSnapshotProperties, snapshot_id, &snapshot->props);
575 ERROR("IVssBackupComponents.GetSnapshotProperties() error: %x", res);
579 if (wcsncmp(snapshot->props.m_pwszSnapshotDeviceObject, L"\\\\?\\", 4)) {
580 ERROR("Unexpected volume shadow device path: %ls",
581 snapshot->props.m_pwszSnapshotDeviceObject);
585 vss_path_ret->MaximumLength = sizeof(wchar_t) *
586 (wcslen(snapshot->props.m_pwszSnapshotDeviceObject) +
587 1 + wcslen(&source_abspath[3]) + 1);
588 vss_path_ret->Length = vss_path_ret->MaximumLength - sizeof(wchar_t);
589 vss_path_ret->Buffer = HeapAlloc(GetProcessHeap(), 0,
590 vss_path_ret->MaximumLength);
591 if (!vss_path_ret->Buffer) {
592 ret = WIMLIB_ERR_NOMEM;
596 wsprintf(vss_path_ret->Buffer, L"\\??\\%ls\\%ls",
597 &snapshot->props.m_pwszSnapshotDeviceObject[4],
599 *snapshot_ret = &snapshot->base;
600 snapshot->base.refcnt = 1;
605 ret = WIMLIB_ERR_SNAPSHOT_FAILURE;
607 ERROR("64-bit Windows doesn't allow 32-bit applications to "
608 "create VSS snapshots.\n"
609 " Run the 64-bit version of this application "
612 ERROR("A problem occurred while creating a VSS snapshot of "
614 " Aborting the operation.", volume);
618 vss_delete_snapshot(&snapshot->base);
620 FREE(source_abspath);
624 #endif /* __WIN32__ */