]> wimlib.net Git - wimlib/blobdiff - src/win32_vss.c
Mark VSS support non-experimental
[wimlib] / src / win32_vss.c
index 914cd9127267a69b215ea0895b8f28e51b4ce82b..2270feeac6814fc63e06c4865cf6f2b998238f00 100644 (file)
@@ -1,10 +1,10 @@
 /*
- * win32_vss.c - Experimental Windows-specific code for creating VSS (Volume
- * Shadow Copy Service) snapshots.
+ * win32_vss.c - Windows-specific code for creating VSS (Volume Shadow Copy
+ * Service) snapshots.
  */
 
 /*
- * Copyright (C) 2015 Eric Biggers
+ * Copyright (C) 2015-2016 Eric Biggers
  *
  * This file is free software; you can redistribute it and/or modify it under
  * the terms of the GNU Lesser General Public License as published by the Free
@@ -131,14 +131,21 @@ struct IVssAsyncVTable {
        void *AddRef;
        ULONG (WINAPI *Release)(IVssAsync *this);
        void *Cancel;
-       HRESULT (WINAPI *Wait)(IVssAsync *this, DWORD dwMilliseconds);
+       union {
+               HRESULT (WINAPI *Wait)(IVssAsync *this, DWORD dwMilliseconds);
+
+               /* Pre-Vista version */
+               HRESULT (WINAPI *OldWait)(IVssAsync *this);
+       };
        void *QueryStatus;
 };
 
 typedef struct IVssBackupComponentsVTable IVssBackupComponentsVTable;
+typedef struct IVssBackupComponentsVTable_old IVssBackupComponentsVTable_old;
 
-typedef struct {
+typedef union {
        IVssBackupComponentsVTable *vtable;
+       IVssBackupComponentsVTable_old *old_vtable;
 } IVssBackupComponents;
 
 struct IVssBackupComponentsVTable {
@@ -196,6 +203,7 @@ struct IVssBackupComponentsVTable {
                                        IVssAsync **ppAsync);
        void *DeleteSnapshots;
        void *ImportSnapshots;
+       /*void *RemountReadWrite;*/     /* Old API only  */
        void *BreakSnapshotSet;
        HRESULT (WINAPI *GetSnapshotProperties)(IVssBackupComponents *this,
                                                VSS_ID SnapshotId,
@@ -210,6 +218,88 @@ struct IVssBackupComponentsVTable {
        void *QueryRevertStatus;
 };
 
+/* Pre-Vista version  */
+struct IVssBackupComponentsVTable_old {
+       void *QueryInterface;
+       void *AddRef;
+       ULONG (WINAPI *Release)(IVssBackupComponents *this);
+       void *GetWriterComponentsCount;
+       void *GetWriterComponents;
+       HRESULT (WINAPI *InitializeForBackup)(IVssBackupComponents *this,
+                                             BSTR bstrXML);
+       HRESULT (WINAPI *SetBackupState)(IVssBackupComponents *this,
+                                        BOOLEAN bSelectComponents,
+                                        BOOLEAN bBackupBootableSystemState,
+                                        VSS_BACKUP_TYPE backupType,
+                                        BOOLEAN bPartialFileSupport);
+       void *InitializeForRestore;
+       /*void *SetRestoreState;*/      /* New API only */
+       HRESULT (WINAPI *GatherWriterMetadata)(IVssBackupComponents *this,
+                                              IVssAsync **ppAsync);
+       void *GetWriterMetadataCount;
+       void *GetWriterMetadata;
+       void *FreeWriterMetadata;
+       void *AddComponent;
+       HRESULT (WINAPI *PrepareForBackup)(IVssBackupComponents *this,
+                                          IVssAsync **ppAsync);
+       void *AbortBackup;
+       void *GatherWriterStatus;
+       void *GetWriterStatusCount;
+       void *FreeWriterStatus;
+       void *GetWriterStatus;
+       void *SetBackupSucceeded;
+       void *SetBackupOptions;
+       void *SetSelectedForRestore;
+       void *SetRestoreOptions;
+       void *SetAdditionalRestores;
+       void *SetPreviousBackupStamp;
+       void *SaveAsXML;
+       void *BackupComplete;
+       void *AddAlternativeLocationMapping;
+       void *AddRestoreSubcomponent;
+       void *SetFileRestoreStatus;
+       /*void *AddNewTarget;*/         /* New API only */
+       /*void *SetRangesFilePath;*/    /* New API only */
+       void *PreRestore;
+       void *PostRestore;
+       HRESULT (WINAPI *SetContext)(IVssBackupComponents *this,
+                                    LONG lContext);
+       HRESULT (WINAPI *StartSnapshotSet)(IVssBackupComponents *this,
+                                          VSS_ID *pSnapshotSetId);
+       HRESULT (WINAPI *AddToSnapshotSet)(IVssBackupComponents *this,
+                                          VSS_PWSZ pwszVolumeName,
+                                          VSS_ID ProviderId,
+                                          VSS_ID *pidSnapshot);
+       HRESULT (WINAPI *DoSnapshotSet)(IVssBackupComponents *this,
+                                       IVssAsync **ppAsync);
+       void *DeleteSnapshots;
+       void *ImportSnapshots;
+       void *RemountReadWrite;
+       void *BreakSnapshotSet;
+       HRESULT (WINAPI *GetSnapshotProperties)(IVssBackupComponents *this,
+                                               VSS_ID SnapshotId,
+                                               VSS_SNAPSHOT_PROP *pprop);
+       void *Query;
+       void *IsVolumeSupported;
+       void *DisableWriterClasses;
+       void *EnableWriterClasses;
+       void *DisableWriterInstances;
+       void *ExposeSnapshot;
+       /*void *RevertToSnapshot;*/     /* New API only */
+       /*void *QueryRevertStatus;*/    /* New API only */
+};
+
+/* Call a method, assuming its signature is identical in the old and new APIs */
+#define CALL_METHOD(obj, method, ...)                                  \
+({                                                                     \
+       HRESULT res;                                                    \
+       if (is_old_api)                                                 \
+               res = (obj)->old_vtable->method((obj), ##__VA_ARGS__);  \
+       else                                                            \
+               res = (obj)->vtable->method((obj), ##__VA_ARGS__);      \
+       res;                                                            \
+})
+
 /*----------------------------------------------------------------------------*
  *                             VSS API initialization                         *
  *----------------------------------------------------------------------------*/
@@ -218,9 +308,10 @@ static bool vss_initialized;
 static pthread_mutex_t vss_initialization_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 /* vssapi.dll  */
+static bool is_old_api;                /* old VSS API (pre-Vista)?  */
 static HANDLE hVssapi;
-static HRESULT (WINAPI *func_CreateVssBackupComponentsInternal)(IVssBackupComponents **ppBackup);
-static void (WINAPI *func_VssFreeSnapshotPropertiesInternal)(VSS_SNAPSHOT_PROP *pProp);
+static HRESULT (WINAPI *func_CreateVssBackupComponents)(IVssBackupComponents **ppBackup);
+static void (WINAPI *func_VssFreeSnapshotProperties)(VSS_SNAPSHOT_PROP *pProp);
 
 /* ole32.dll  */
 static HANDLE hOle32;
@@ -236,18 +327,29 @@ vss_global_init_impl(void)
                goto err;
        }
 
-       func_CreateVssBackupComponentsInternal =
+       func_CreateVssBackupComponents =
                (void *)GetProcAddress(hVssapi, "CreateVssBackupComponentsInternal");
-       if (!func_CreateVssBackupComponentsInternal) {
-               ERROR("CreateVssBackupComponentsInternal() not found in vssapi.dll");
-               goto err_vssapi;
+       if (!func_CreateVssBackupComponents) {
+               func_CreateVssBackupComponents =
+                       (void *)GetProcAddress(hVssapi, "?CreateVssBackupComponents@@YGJPAPAVIVssBackupComponents@@@Z");
+               if (!func_CreateVssBackupComponents) {
+                       ERROR("CreateVssBackupComponents() not found in vssapi.dll");
+                       goto err_vssapi;
+               }
+               is_old_api = true;
+       } else {
+               is_old_api = false;
        }
 
-       func_VssFreeSnapshotPropertiesInternal =
+       func_VssFreeSnapshotProperties =
                (void *)GetProcAddress(hVssapi, "VssFreeSnapshotPropertiesInternal");
-       if (!func_VssFreeSnapshotPropertiesInternal) {
-               ERROR("VssFreeSnapshotPropertiesInternal() not found in vssapi.dll");
-               goto err_vssapi;
+       if (!func_VssFreeSnapshotProperties) {
+               func_VssFreeSnapshotProperties =
+                       (void *)GetProcAddress(hVssapi, "VssFreeSnapshotProperties");
+               if (!func_VssFreeSnapshotProperties) {
+                       ERROR("VssFreeSnapshotProperties() not found in vssapi.dll");
+                       goto err_vssapi;
+               }
        }
 
        hOle32 = LoadLibrary(L"ole32.dll");
@@ -332,16 +434,20 @@ vss_delete_snapshot(struct vss_snapshot *snapshot)
        internal = container_of(snapshot, struct vss_snapshot_internal, base);
 
        if (internal->props.m_pwszSnapshotDeviceObject)
-               (*func_VssFreeSnapshotPropertiesInternal)(&internal->props);
+               (*func_VssFreeSnapshotProperties)(&internal->props);
        if (internal->vss)
-               internal->vss->vtable->Release(internal->vss);
+               CALL_METHOD(internal->vss, Release);
        FREE(internal);
 }
 
 static HRESULT
 wait_and_release(IVssAsync *async)
 {
-       HRESULT res = async->vtable->Wait(async, INFINITE);
+       HRESULT res;
+       if (is_old_api)
+               res = async->vtable->OldWait(async);
+       else
+               res = async->vtable->Wait(async, INFINITE);
        async->vtable->Release(async);
        return res;
 }
@@ -353,37 +459,31 @@ request_vss_snapshot(IVssBackupComponents *vss, wchar_t *volume,
        HRESULT res;
        IVssAsync *async;
 
-       res = vss->vtable->InitializeForBackup(vss, NULL);
+       res = CALL_METHOD(vss, InitializeForBackup, NULL);
        if (FAILED(res)) {
                ERROR("IVssBackupComponents.InitializeForBackup() error: %x", res);
                return false;
        }
 
-       res = vss->vtable->SetContext(vss, VSS_CTX_BACKUP);
-       if (FAILED(res)) {
-               ERROR("IVssBackupComponents.SetContext() error: %x", res);
-               return false;
-       }
-
-       res = vss->vtable->SetBackupState(vss, FALSE, TRUE, VSS_BT_COPY, FALSE);
+       res = CALL_METHOD(vss, SetBackupState, FALSE, TRUE, VSS_BT_COPY, FALSE);
        if (FAILED(res)) {
                ERROR("IVssBackupComponents.SetBackupState() error: %x", res);
                return false;
        }
 
-       res = vss->vtable->StartSnapshotSet(vss, snapshot_id);
+       res = CALL_METHOD(vss, StartSnapshotSet, snapshot_id);
        if (FAILED(res)) {
                ERROR("IVssBackupComponents.StartSnapshotSet() error: %x", res);
                return false;
        }
 
-       res = vss->vtable->AddToSnapshotSet(vss, volume, (GUID){}, snapshot_id);
+       res = CALL_METHOD(vss, AddToSnapshotSet, volume, (GUID){}, snapshot_id);
        if (FAILED(res)) {
                ERROR("IVssBackupComponents.AddToSnapshotSet() error: %x", res);
                return false;
        }
 
-       res = vss->vtable->PrepareForBackup(vss, &async);
+       res = CALL_METHOD(vss, PrepareForBackup, &async);
        if (FAILED(res)) {
                ERROR("IVssBackupComponents.PrepareForBackup() error: %x", res);
                return false;
@@ -394,7 +494,7 @@ request_vss_snapshot(IVssBackupComponents *vss, wchar_t *volume,
                return false;
        }
 
-       res = vss->vtable->DoSnapshotSet(vss, &async);
+       res = CALL_METHOD(vss, DoSnapshotSet, &async);
        if (FAILED(res)) {
                ERROR("IVssBackupComponents.DoSnapshotSet() error: %x", res);
                return false;
@@ -459,7 +559,7 @@ vss_create_snapshot(const wchar_t *source, UNICODE_STRING *vss_path_ret,
        if (!vss_global_init())
                goto vss_err;
 
-       res = (*func_CreateVssBackupComponentsInternal)(&vss);
+       res = (*func_CreateVssBackupComponents)(&vss);
        if (FAILED(res)) {
                ERROR("CreateVssBackupComponents error: %x", res);
                goto vss_err;
@@ -470,7 +570,7 @@ vss_create_snapshot(const wchar_t *source, UNICODE_STRING *vss_path_ret,
        if (!request_vss_snapshot(vss, volume, &snapshot_id))
                goto vss_err;
 
-       res = vss->vtable->GetSnapshotProperties(vss, snapshot_id, &snapshot->props);
+       res = CALL_METHOD(vss, GetSnapshotProperties, snapshot_id, &snapshot->props);
        if (FAILED(res)) {
                ERROR("IVssBackupComponents.GetSnapshotProperties() error: %x", res);
                goto vss_err;