1b39297aeSTomoki Sekiyama /* 2b39297aeSTomoki Sekiyama * QEMU Guest Agent win32 VSS Requester implementations 3b39297aeSTomoki Sekiyama * 4b39297aeSTomoki Sekiyama * Copyright Hitachi Data Systems Corp. 2013 5b39297aeSTomoki Sekiyama * 6b39297aeSTomoki Sekiyama * Authors: 7b39297aeSTomoki Sekiyama * Tomoki Sekiyama <tomoki.sekiyama@hds.com> 8b39297aeSTomoki Sekiyama * 9b39297aeSTomoki Sekiyama * This work is licensed under the terms of the GNU GPL, version 2 or later. 10b39297aeSTomoki Sekiyama * See the COPYING file in the top-level directory. 11b39297aeSTomoki Sekiyama */ 12b39297aeSTomoki Sekiyama 13b39297aeSTomoki Sekiyama #include <stdio.h> 14b39297aeSTomoki Sekiyama #include "vss-common.h" 15b39297aeSTomoki Sekiyama #include "requester.h" 16b39297aeSTomoki Sekiyama #include "assert.h" 17b39297aeSTomoki Sekiyama #include "inc/win2003/vswriter.h" 18b39297aeSTomoki Sekiyama #include "inc/win2003/vsbackup.h" 19b39297aeSTomoki Sekiyama 20b39297aeSTomoki Sekiyama /* Max wait time for frozen event (VSS can only hold writes for 10 seconds) */ 21b39297aeSTomoki Sekiyama #define VSS_TIMEOUT_FREEZE_MSEC 10000 22b39297aeSTomoki Sekiyama 23b39297aeSTomoki Sekiyama /* Call QueryStatus every 10 ms while waiting for frozen event */ 24b39297aeSTomoki Sekiyama #define VSS_TIMEOUT_EVENT_MSEC 10 25b39297aeSTomoki Sekiyama 26b39297aeSTomoki Sekiyama #define err_set(e, err, fmt, ...) \ 27e7cf59e8SMarkus Armbruster ((e)->error_setg_win32((e)->errp, err, fmt, ## __VA_ARGS__)) 28*08e64640SMarkus Armbruster /* Bad idea, works only when (e)->errp != NULL: */ 29b39297aeSTomoki Sekiyama #define err_is_set(e) ((e)->errp && *(e)->errp) 30*08e64640SMarkus Armbruster /* To lift this restriction, error_propagate(), like we do in QEMU code */ 31b39297aeSTomoki Sekiyama 32b39297aeSTomoki Sekiyama /* Handle to VSSAPI.DLL */ 33b39297aeSTomoki Sekiyama static HMODULE hLib; 34b39297aeSTomoki Sekiyama 35b39297aeSTomoki Sekiyama /* Functions in VSSAPI.DLL */ 36b39297aeSTomoki Sekiyama typedef HRESULT(STDAPICALLTYPE * t_CreateVssBackupComponents)( 37b39297aeSTomoki Sekiyama OUT IVssBackupComponents**); 38b39297aeSTomoki Sekiyama typedef void(APIENTRY * t_VssFreeSnapshotProperties)(IN VSS_SNAPSHOT_PROP*); 39b39297aeSTomoki Sekiyama static t_CreateVssBackupComponents pCreateVssBackupComponents; 40b39297aeSTomoki Sekiyama static t_VssFreeSnapshotProperties pVssFreeSnapshotProperties; 41b39297aeSTomoki Sekiyama 42b39297aeSTomoki Sekiyama /* Variables used while applications and filesystes are frozen by VSS */ 43b39297aeSTomoki Sekiyama static struct QGAVSSContext { 44b39297aeSTomoki Sekiyama IVssBackupComponents *pVssbc; /* VSS requester interface */ 45b39297aeSTomoki Sekiyama IVssAsync *pAsyncSnapshot; /* async info of VSS snapshot operation */ 46b39297aeSTomoki Sekiyama HANDLE hEventFrozen; /* notify fs/writer freeze from provider */ 47b39297aeSTomoki Sekiyama HANDLE hEventThaw; /* request provider to thaw */ 48b39297aeSTomoki Sekiyama HANDLE hEventTimeout; /* notify timeout in provider */ 49b39297aeSTomoki Sekiyama int cFrozenVols; /* number of frozen volumes */ 50b39297aeSTomoki Sekiyama } vss_ctx; 51b39297aeSTomoki Sekiyama 52b39297aeSTomoki Sekiyama STDAPI requester_init(void) 53b39297aeSTomoki Sekiyama { 54b39297aeSTomoki Sekiyama COMInitializer initializer; /* to call CoInitializeSecurity */ 55b39297aeSTomoki Sekiyama HRESULT hr = CoInitializeSecurity( 56b39297aeSTomoki Sekiyama NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, 57b39297aeSTomoki Sekiyama RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL); 58b39297aeSTomoki Sekiyama if (FAILED(hr)) { 59b39297aeSTomoki Sekiyama fprintf(stderr, "failed to CoInitializeSecurity (error %lx)\n", hr); 60b39297aeSTomoki Sekiyama return hr; 61b39297aeSTomoki Sekiyama } 62b39297aeSTomoki Sekiyama 63b39297aeSTomoki Sekiyama hLib = LoadLibraryA("VSSAPI.DLL"); 64b39297aeSTomoki Sekiyama if (!hLib) { 65b39297aeSTomoki Sekiyama fprintf(stderr, "failed to load VSSAPI.DLL\n"); 66b39297aeSTomoki Sekiyama return HRESULT_FROM_WIN32(GetLastError()); 67b39297aeSTomoki Sekiyama } 68b39297aeSTomoki Sekiyama 69b39297aeSTomoki Sekiyama pCreateVssBackupComponents = (t_CreateVssBackupComponents) 70b39297aeSTomoki Sekiyama GetProcAddress(hLib, 71b39297aeSTomoki Sekiyama #ifdef _WIN64 /* 64bit environment */ 72b39297aeSTomoki Sekiyama "?CreateVssBackupComponents@@YAJPEAPEAVIVssBackupComponents@@@Z" 73b39297aeSTomoki Sekiyama #else /* 32bit environment */ 74b39297aeSTomoki Sekiyama "?CreateVssBackupComponents@@YGJPAPAVIVssBackupComponents@@@Z" 75b39297aeSTomoki Sekiyama #endif 76b39297aeSTomoki Sekiyama ); 77b39297aeSTomoki Sekiyama if (!pCreateVssBackupComponents) { 78b39297aeSTomoki Sekiyama fprintf(stderr, "failed to get proc address from VSSAPI.DLL\n"); 79b39297aeSTomoki Sekiyama return HRESULT_FROM_WIN32(GetLastError()); 80b39297aeSTomoki Sekiyama } 81b39297aeSTomoki Sekiyama 82b39297aeSTomoki Sekiyama pVssFreeSnapshotProperties = (t_VssFreeSnapshotProperties) 83b39297aeSTomoki Sekiyama GetProcAddress(hLib, "VssFreeSnapshotProperties"); 84b39297aeSTomoki Sekiyama if (!pVssFreeSnapshotProperties) { 85b39297aeSTomoki Sekiyama fprintf(stderr, "failed to get proc address from VSSAPI.DLL\n"); 86b39297aeSTomoki Sekiyama return HRESULT_FROM_WIN32(GetLastError()); 87b39297aeSTomoki Sekiyama } 88b39297aeSTomoki Sekiyama 89b39297aeSTomoki Sekiyama return S_OK; 90b39297aeSTomoki Sekiyama } 91b39297aeSTomoki Sekiyama 92b39297aeSTomoki Sekiyama static void requester_cleanup(void) 93b39297aeSTomoki Sekiyama { 944c1b8f1eSTomoki Sekiyama if (vss_ctx.hEventFrozen) { 95b39297aeSTomoki Sekiyama CloseHandle(vss_ctx.hEventFrozen); 964c1b8f1eSTomoki Sekiyama vss_ctx.hEventFrozen = NULL; 97b39297aeSTomoki Sekiyama } 984c1b8f1eSTomoki Sekiyama if (vss_ctx.hEventThaw) { 99b39297aeSTomoki Sekiyama CloseHandle(vss_ctx.hEventThaw); 1004c1b8f1eSTomoki Sekiyama vss_ctx.hEventThaw = NULL; 101b39297aeSTomoki Sekiyama } 1024c1b8f1eSTomoki Sekiyama if (vss_ctx.hEventTimeout) { 103b39297aeSTomoki Sekiyama CloseHandle(vss_ctx.hEventTimeout); 1044c1b8f1eSTomoki Sekiyama vss_ctx.hEventTimeout = NULL; 105b39297aeSTomoki Sekiyama } 106b39297aeSTomoki Sekiyama if (vss_ctx.pAsyncSnapshot) { 107b39297aeSTomoki Sekiyama vss_ctx.pAsyncSnapshot->Release(); 108b39297aeSTomoki Sekiyama vss_ctx.pAsyncSnapshot = NULL; 109b39297aeSTomoki Sekiyama } 110b39297aeSTomoki Sekiyama if (vss_ctx.pVssbc) { 111b39297aeSTomoki Sekiyama vss_ctx.pVssbc->Release(); 112b39297aeSTomoki Sekiyama vss_ctx.pVssbc = NULL; 113b39297aeSTomoki Sekiyama } 114b39297aeSTomoki Sekiyama vss_ctx.cFrozenVols = 0; 115b39297aeSTomoki Sekiyama } 116b39297aeSTomoki Sekiyama 117b39297aeSTomoki Sekiyama STDAPI requester_deinit(void) 118b39297aeSTomoki Sekiyama { 119b39297aeSTomoki Sekiyama requester_cleanup(); 120b39297aeSTomoki Sekiyama 121b39297aeSTomoki Sekiyama pCreateVssBackupComponents = NULL; 122b39297aeSTomoki Sekiyama pVssFreeSnapshotProperties = NULL; 123b39297aeSTomoki Sekiyama if (hLib) { 124b39297aeSTomoki Sekiyama FreeLibrary(hLib); 125b39297aeSTomoki Sekiyama hLib = NULL; 126b39297aeSTomoki Sekiyama } 127b39297aeSTomoki Sekiyama 128b39297aeSTomoki Sekiyama return S_OK; 129b39297aeSTomoki Sekiyama } 130b39297aeSTomoki Sekiyama 131b39297aeSTomoki Sekiyama static HRESULT WaitForAsync(IVssAsync *pAsync) 132b39297aeSTomoki Sekiyama { 133b39297aeSTomoki Sekiyama HRESULT ret, hr; 134b39297aeSTomoki Sekiyama 135b39297aeSTomoki Sekiyama do { 136b39297aeSTomoki Sekiyama hr = pAsync->Wait(); 137b39297aeSTomoki Sekiyama if (FAILED(hr)) { 138b39297aeSTomoki Sekiyama ret = hr; 139b39297aeSTomoki Sekiyama break; 140b39297aeSTomoki Sekiyama } 141b39297aeSTomoki Sekiyama hr = pAsync->QueryStatus(&ret, NULL); 142b39297aeSTomoki Sekiyama if (FAILED(hr)) { 143b39297aeSTomoki Sekiyama ret = hr; 144b39297aeSTomoki Sekiyama break; 145b39297aeSTomoki Sekiyama } 146b39297aeSTomoki Sekiyama } while (ret == VSS_S_ASYNC_PENDING); 147b39297aeSTomoki Sekiyama 148b39297aeSTomoki Sekiyama return ret; 149b39297aeSTomoki Sekiyama } 150b39297aeSTomoki Sekiyama 151b39297aeSTomoki Sekiyama static void AddComponents(ErrorSet *errset) 152b39297aeSTomoki Sekiyama { 153b39297aeSTomoki Sekiyama unsigned int cWriters, i; 154b39297aeSTomoki Sekiyama VSS_ID id, idInstance, idWriter; 155b39297aeSTomoki Sekiyama BSTR bstrWriterName = NULL; 156b39297aeSTomoki Sekiyama VSS_USAGE_TYPE usage; 157b39297aeSTomoki Sekiyama VSS_SOURCE_TYPE source; 158b39297aeSTomoki Sekiyama unsigned int cComponents, c1, c2, j; 159b39297aeSTomoki Sekiyama COMPointer<IVssExamineWriterMetadata> pMetadata; 160b39297aeSTomoki Sekiyama COMPointer<IVssWMComponent> pComponent; 161b39297aeSTomoki Sekiyama PVSSCOMPONENTINFO info; 162b39297aeSTomoki Sekiyama HRESULT hr; 163b39297aeSTomoki Sekiyama 164b39297aeSTomoki Sekiyama hr = vss_ctx.pVssbc->GetWriterMetadataCount(&cWriters); 165b39297aeSTomoki Sekiyama if (FAILED(hr)) { 166b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to get writer metadata count"); 167b39297aeSTomoki Sekiyama goto out; 168b39297aeSTomoki Sekiyama } 169b39297aeSTomoki Sekiyama 170b39297aeSTomoki Sekiyama for (i = 0; i < cWriters; i++) { 171b39297aeSTomoki Sekiyama hr = vss_ctx.pVssbc->GetWriterMetadata(i, &id, pMetadata.replace()); 172b39297aeSTomoki Sekiyama if (FAILED(hr)) { 173b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to get writer metadata of %d/%d", 174b39297aeSTomoki Sekiyama i, cWriters); 175b39297aeSTomoki Sekiyama goto out; 176b39297aeSTomoki Sekiyama } 177b39297aeSTomoki Sekiyama 178b39297aeSTomoki Sekiyama hr = pMetadata->GetIdentity(&idInstance, &idWriter, 179b39297aeSTomoki Sekiyama &bstrWriterName, &usage, &source); 180b39297aeSTomoki Sekiyama if (FAILED(hr)) { 181b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to get identity of writer %d/%d", 182b39297aeSTomoki Sekiyama i, cWriters); 183b39297aeSTomoki Sekiyama goto out; 184b39297aeSTomoki Sekiyama } 185b39297aeSTomoki Sekiyama 186b39297aeSTomoki Sekiyama hr = pMetadata->GetFileCounts(&c1, &c2, &cComponents); 187b39297aeSTomoki Sekiyama if (FAILED(hr)) { 188b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to get file counts of %S", 189b39297aeSTomoki Sekiyama bstrWriterName); 190b39297aeSTomoki Sekiyama goto out; 191b39297aeSTomoki Sekiyama } 192b39297aeSTomoki Sekiyama 193b39297aeSTomoki Sekiyama for (j = 0; j < cComponents; j++) { 194b39297aeSTomoki Sekiyama hr = pMetadata->GetComponent(j, pComponent.replace()); 195b39297aeSTomoki Sekiyama if (FAILED(hr)) { 196b39297aeSTomoki Sekiyama err_set(errset, hr, 197b39297aeSTomoki Sekiyama "failed to get component %d/%d of %S", 198b39297aeSTomoki Sekiyama j, cComponents, bstrWriterName); 199b39297aeSTomoki Sekiyama goto out; 200b39297aeSTomoki Sekiyama } 201b39297aeSTomoki Sekiyama 202b39297aeSTomoki Sekiyama hr = pComponent->GetComponentInfo(&info); 203b39297aeSTomoki Sekiyama if (FAILED(hr)) { 204b39297aeSTomoki Sekiyama err_set(errset, hr, 205b39297aeSTomoki Sekiyama "failed to get component info %d/%d of %S", 206b39297aeSTomoki Sekiyama j, cComponents, bstrWriterName); 207b39297aeSTomoki Sekiyama goto out; 208b39297aeSTomoki Sekiyama } 209b39297aeSTomoki Sekiyama 210b39297aeSTomoki Sekiyama if (info->bSelectable) { 211b39297aeSTomoki Sekiyama hr = vss_ctx.pVssbc->AddComponent(idInstance, idWriter, 212b39297aeSTomoki Sekiyama info->type, 213b39297aeSTomoki Sekiyama info->bstrLogicalPath, 214b39297aeSTomoki Sekiyama info->bstrComponentName); 215b39297aeSTomoki Sekiyama if (FAILED(hr)) { 216b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to add component %S(%S)", 217b39297aeSTomoki Sekiyama info->bstrComponentName, bstrWriterName); 218b39297aeSTomoki Sekiyama goto out; 219b39297aeSTomoki Sekiyama } 220b39297aeSTomoki Sekiyama } 221b39297aeSTomoki Sekiyama SysFreeString(bstrWriterName); 222b39297aeSTomoki Sekiyama bstrWriterName = NULL; 223b39297aeSTomoki Sekiyama pComponent->FreeComponentInfo(info); 224b39297aeSTomoki Sekiyama info = NULL; 225b39297aeSTomoki Sekiyama } 226b39297aeSTomoki Sekiyama } 227b39297aeSTomoki Sekiyama out: 228b39297aeSTomoki Sekiyama if (bstrWriterName) { 229b39297aeSTomoki Sekiyama SysFreeString(bstrWriterName); 230b39297aeSTomoki Sekiyama } 231b39297aeSTomoki Sekiyama if (pComponent && info) { 232b39297aeSTomoki Sekiyama pComponent->FreeComponentInfo(info); 233b39297aeSTomoki Sekiyama } 234b39297aeSTomoki Sekiyama } 235b39297aeSTomoki Sekiyama 236b39297aeSTomoki Sekiyama void requester_freeze(int *num_vols, ErrorSet *errset) 237b39297aeSTomoki Sekiyama { 238b39297aeSTomoki Sekiyama COMPointer<IVssAsync> pAsync; 239b39297aeSTomoki Sekiyama HANDLE volume; 240b39297aeSTomoki Sekiyama HRESULT hr; 241b39297aeSTomoki Sekiyama LONG ctx; 242b39297aeSTomoki Sekiyama GUID guidSnapshotSet = GUID_NULL; 243b39297aeSTomoki Sekiyama SECURITY_DESCRIPTOR sd; 244b39297aeSTomoki Sekiyama SECURITY_ATTRIBUTES sa; 245b39297aeSTomoki Sekiyama WCHAR short_volume_name[64], *display_name = short_volume_name; 246b39297aeSTomoki Sekiyama DWORD wait_status; 247b39297aeSTomoki Sekiyama int num_fixed_drives = 0, i; 248b39297aeSTomoki Sekiyama 249b39297aeSTomoki Sekiyama if (vss_ctx.pVssbc) { /* already frozen */ 250b39297aeSTomoki Sekiyama *num_vols = 0; 251b39297aeSTomoki Sekiyama return; 252b39297aeSTomoki Sekiyama } 253b39297aeSTomoki Sekiyama 254b39297aeSTomoki Sekiyama CoInitialize(NULL); 255b39297aeSTomoki Sekiyama 256ff8adbcfSTomoki Sekiyama /* Allow unrestricted access to events */ 257ff8adbcfSTomoki Sekiyama InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); 258ff8adbcfSTomoki Sekiyama SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); 259ff8adbcfSTomoki Sekiyama sa.nLength = sizeof(sa); 260ff8adbcfSTomoki Sekiyama sa.lpSecurityDescriptor = &sd; 261ff8adbcfSTomoki Sekiyama sa.bInheritHandle = FALSE; 262ff8adbcfSTomoki Sekiyama 263ff8adbcfSTomoki Sekiyama vss_ctx.hEventFrozen = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_FROZEN); 264ff8adbcfSTomoki Sekiyama if (!vss_ctx.hEventFrozen) { 265ff8adbcfSTomoki Sekiyama err_set(errset, GetLastError(), "failed to create event %s", 266ff8adbcfSTomoki Sekiyama EVENT_NAME_FROZEN); 267ff8adbcfSTomoki Sekiyama goto out; 268ff8adbcfSTomoki Sekiyama } 269ff8adbcfSTomoki Sekiyama vss_ctx.hEventThaw = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_THAW); 270ff8adbcfSTomoki Sekiyama if (!vss_ctx.hEventThaw) { 271ff8adbcfSTomoki Sekiyama err_set(errset, GetLastError(), "failed to create event %s", 272ff8adbcfSTomoki Sekiyama EVENT_NAME_THAW); 273ff8adbcfSTomoki Sekiyama goto out; 274ff8adbcfSTomoki Sekiyama } 275ff8adbcfSTomoki Sekiyama vss_ctx.hEventTimeout = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_TIMEOUT); 276ff8adbcfSTomoki Sekiyama if (!vss_ctx.hEventTimeout) { 277ff8adbcfSTomoki Sekiyama err_set(errset, GetLastError(), "failed to create event %s", 278ff8adbcfSTomoki Sekiyama EVENT_NAME_TIMEOUT); 279ff8adbcfSTomoki Sekiyama goto out; 280ff8adbcfSTomoki Sekiyama } 281ff8adbcfSTomoki Sekiyama 282b39297aeSTomoki Sekiyama assert(pCreateVssBackupComponents != NULL); 283b39297aeSTomoki Sekiyama hr = pCreateVssBackupComponents(&vss_ctx.pVssbc); 284b39297aeSTomoki Sekiyama if (FAILED(hr)) { 285b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to create VSS backup components"); 286b39297aeSTomoki Sekiyama goto out; 287b39297aeSTomoki Sekiyama } 288b39297aeSTomoki Sekiyama 289b39297aeSTomoki Sekiyama hr = vss_ctx.pVssbc->InitializeForBackup(); 290b39297aeSTomoki Sekiyama if (FAILED(hr)) { 291b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to initialize for backup"); 292b39297aeSTomoki Sekiyama goto out; 293b39297aeSTomoki Sekiyama } 294b39297aeSTomoki Sekiyama 295b39297aeSTomoki Sekiyama hr = vss_ctx.pVssbc->SetBackupState(true, true, VSS_BT_FULL, false); 296b39297aeSTomoki Sekiyama if (FAILED(hr)) { 297b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to set backup state"); 298b39297aeSTomoki Sekiyama goto out; 299b39297aeSTomoki Sekiyama } 300b39297aeSTomoki Sekiyama 301b39297aeSTomoki Sekiyama /* 302b39297aeSTomoki Sekiyama * Currently writable snapshots are not supported. 303b39297aeSTomoki Sekiyama * To prevent the final commit (which requires to write to snapshots), 304b39297aeSTomoki Sekiyama * ATTR_NO_AUTORECOVERY and ATTR_TRANSPORTABLE are specified here. 305b39297aeSTomoki Sekiyama */ 306b39297aeSTomoki Sekiyama ctx = VSS_CTX_APP_ROLLBACK | VSS_VOLSNAP_ATTR_TRANSPORTABLE | 307b39297aeSTomoki Sekiyama VSS_VOLSNAP_ATTR_NO_AUTORECOVERY | VSS_VOLSNAP_ATTR_TXF_RECOVERY; 308b39297aeSTomoki Sekiyama hr = vss_ctx.pVssbc->SetContext(ctx); 309b39297aeSTomoki Sekiyama if (hr == (HRESULT)VSS_E_UNSUPPORTED_CONTEXT) { 310b39297aeSTomoki Sekiyama /* Non-server version of Windows doesn't support ATTR_TRANSPORTABLE */ 311b39297aeSTomoki Sekiyama ctx &= ~VSS_VOLSNAP_ATTR_TRANSPORTABLE; 312b39297aeSTomoki Sekiyama hr = vss_ctx.pVssbc->SetContext(ctx); 313b39297aeSTomoki Sekiyama } 314b39297aeSTomoki Sekiyama if (FAILED(hr)) { 315b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to set backup context"); 316b39297aeSTomoki Sekiyama goto out; 317b39297aeSTomoki Sekiyama } 318b39297aeSTomoki Sekiyama 319b39297aeSTomoki Sekiyama hr = vss_ctx.pVssbc->GatherWriterMetadata(pAsync.replace()); 320b39297aeSTomoki Sekiyama if (SUCCEEDED(hr)) { 321b39297aeSTomoki Sekiyama hr = WaitForAsync(pAsync); 322b39297aeSTomoki Sekiyama } 323b39297aeSTomoki Sekiyama if (FAILED(hr)) { 324b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to gather writer metadata"); 325b39297aeSTomoki Sekiyama goto out; 326b39297aeSTomoki Sekiyama } 327b39297aeSTomoki Sekiyama 328b39297aeSTomoki Sekiyama AddComponents(errset); 329b39297aeSTomoki Sekiyama if (err_is_set(errset)) { 330b39297aeSTomoki Sekiyama goto out; 331b39297aeSTomoki Sekiyama } 332b39297aeSTomoki Sekiyama 333b39297aeSTomoki Sekiyama hr = vss_ctx.pVssbc->StartSnapshotSet(&guidSnapshotSet); 334b39297aeSTomoki Sekiyama if (FAILED(hr)) { 335b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to start snapshot set"); 336b39297aeSTomoki Sekiyama goto out; 337b39297aeSTomoki Sekiyama } 338b39297aeSTomoki Sekiyama 339b39297aeSTomoki Sekiyama volume = FindFirstVolumeW(short_volume_name, sizeof(short_volume_name)); 340b39297aeSTomoki Sekiyama if (volume == INVALID_HANDLE_VALUE) { 341b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to find first volume"); 342b39297aeSTomoki Sekiyama goto out; 343b39297aeSTomoki Sekiyama } 344b39297aeSTomoki Sekiyama for (;;) { 345b39297aeSTomoki Sekiyama if (GetDriveTypeW(short_volume_name) == DRIVE_FIXED) { 346b39297aeSTomoki Sekiyama VSS_ID pid; 347b39297aeSTomoki Sekiyama hr = vss_ctx.pVssbc->AddToSnapshotSet(short_volume_name, 348b39297aeSTomoki Sekiyama g_gProviderId, &pid); 349b39297aeSTomoki Sekiyama if (FAILED(hr)) { 350b39297aeSTomoki Sekiyama WCHAR volume_path_name[PATH_MAX]; 351b39297aeSTomoki Sekiyama if (GetVolumePathNamesForVolumeNameW( 352b39297aeSTomoki Sekiyama short_volume_name, volume_path_name, 353b39297aeSTomoki Sekiyama sizeof(volume_path_name), NULL) && *volume_path_name) { 354b39297aeSTomoki Sekiyama display_name = volume_path_name; 355b39297aeSTomoki Sekiyama } 356b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to add %S to snapshot set", 357b39297aeSTomoki Sekiyama display_name); 358b39297aeSTomoki Sekiyama FindVolumeClose(volume); 359b39297aeSTomoki Sekiyama goto out; 360b39297aeSTomoki Sekiyama } 361b39297aeSTomoki Sekiyama num_fixed_drives++; 362b39297aeSTomoki Sekiyama } 363b39297aeSTomoki Sekiyama if (!FindNextVolumeW(volume, short_volume_name, 364b39297aeSTomoki Sekiyama sizeof(short_volume_name))) { 365b39297aeSTomoki Sekiyama FindVolumeClose(volume); 366b39297aeSTomoki Sekiyama break; 367b39297aeSTomoki Sekiyama } 368b39297aeSTomoki Sekiyama } 369b39297aeSTomoki Sekiyama 370b39297aeSTomoki Sekiyama if (num_fixed_drives == 0) { 371b39297aeSTomoki Sekiyama goto out; /* If there is no fixed drive, just exit. */ 372b39297aeSTomoki Sekiyama } 373b39297aeSTomoki Sekiyama 374b39297aeSTomoki Sekiyama hr = vss_ctx.pVssbc->PrepareForBackup(pAsync.replace()); 375b39297aeSTomoki Sekiyama if (SUCCEEDED(hr)) { 376b39297aeSTomoki Sekiyama hr = WaitForAsync(pAsync); 377b39297aeSTomoki Sekiyama } 378b39297aeSTomoki Sekiyama if (FAILED(hr)) { 379b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to prepare for backup"); 380b39297aeSTomoki Sekiyama goto out; 381b39297aeSTomoki Sekiyama } 382b39297aeSTomoki Sekiyama 383b39297aeSTomoki Sekiyama hr = vss_ctx.pVssbc->GatherWriterStatus(pAsync.replace()); 384b39297aeSTomoki Sekiyama if (SUCCEEDED(hr)) { 385b39297aeSTomoki Sekiyama hr = WaitForAsync(pAsync); 386b39297aeSTomoki Sekiyama } 387b39297aeSTomoki Sekiyama if (FAILED(hr)) { 388b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to gather writer status"); 389b39297aeSTomoki Sekiyama goto out; 390b39297aeSTomoki Sekiyama } 391b39297aeSTomoki Sekiyama 392b39297aeSTomoki Sekiyama /* 393b39297aeSTomoki Sekiyama * Start VSS quiescing operations. 394b39297aeSTomoki Sekiyama * CQGAVssProvider::CommitSnapshots will kick vss_ctx.hEventFrozen 395b39297aeSTomoki Sekiyama * after the applications and filesystems are frozen. 396b39297aeSTomoki Sekiyama */ 397b39297aeSTomoki Sekiyama hr = vss_ctx.pVssbc->DoSnapshotSet(&vss_ctx.pAsyncSnapshot); 398b39297aeSTomoki Sekiyama if (FAILED(hr)) { 399b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to do snapshot set"); 400b39297aeSTomoki Sekiyama goto out; 401b39297aeSTomoki Sekiyama } 402b39297aeSTomoki Sekiyama 403b39297aeSTomoki Sekiyama /* Need to call QueryStatus several times to make VSS provider progress */ 404b39297aeSTomoki Sekiyama for (i = 0; i < VSS_TIMEOUT_FREEZE_MSEC/VSS_TIMEOUT_EVENT_MSEC; i++) { 405b39297aeSTomoki Sekiyama HRESULT hr2 = vss_ctx.pAsyncSnapshot->QueryStatus(&hr, NULL); 406b39297aeSTomoki Sekiyama if (FAILED(hr2)) { 407b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to do snapshot set"); 408b39297aeSTomoki Sekiyama goto out; 409b39297aeSTomoki Sekiyama } 410b39297aeSTomoki Sekiyama if (hr != VSS_S_ASYNC_PENDING) { 411b39297aeSTomoki Sekiyama err_set(errset, E_FAIL, 412b39297aeSTomoki Sekiyama "DoSnapshotSet exited without Frozen event"); 413b39297aeSTomoki Sekiyama goto out; 414b39297aeSTomoki Sekiyama } 415b39297aeSTomoki Sekiyama wait_status = WaitForSingleObject(vss_ctx.hEventFrozen, 416b39297aeSTomoki Sekiyama VSS_TIMEOUT_EVENT_MSEC); 417b39297aeSTomoki Sekiyama if (wait_status != WAIT_TIMEOUT) { 418b39297aeSTomoki Sekiyama break; 419b39297aeSTomoki Sekiyama } 420b39297aeSTomoki Sekiyama } 421b39297aeSTomoki Sekiyama if (wait_status != WAIT_OBJECT_0) { 422b39297aeSTomoki Sekiyama err_set(errset, E_FAIL, 423b39297aeSTomoki Sekiyama "couldn't receive Frozen event from VSS provider"); 424b39297aeSTomoki Sekiyama goto out; 425b39297aeSTomoki Sekiyama } 426b39297aeSTomoki Sekiyama 427b39297aeSTomoki Sekiyama *num_vols = vss_ctx.cFrozenVols = num_fixed_drives; 428b39297aeSTomoki Sekiyama return; 429b39297aeSTomoki Sekiyama 430b39297aeSTomoki Sekiyama out: 431b39297aeSTomoki Sekiyama if (vss_ctx.pVssbc) { 432b39297aeSTomoki Sekiyama vss_ctx.pVssbc->AbortBackup(); 433b39297aeSTomoki Sekiyama } 434b39297aeSTomoki Sekiyama requester_cleanup(); 435b39297aeSTomoki Sekiyama CoUninitialize(); 436b39297aeSTomoki Sekiyama } 437b39297aeSTomoki Sekiyama 438b39297aeSTomoki Sekiyama 439b39297aeSTomoki Sekiyama void requester_thaw(int *num_vols, ErrorSet *errset) 440b39297aeSTomoki Sekiyama { 441b39297aeSTomoki Sekiyama COMPointer<IVssAsync> pAsync; 442b39297aeSTomoki Sekiyama 4434c1b8f1eSTomoki Sekiyama if (!vss_ctx.hEventThaw) { 444b39297aeSTomoki Sekiyama /* 445b39297aeSTomoki Sekiyama * In this case, DoSnapshotSet is aborted or not started, 446b39297aeSTomoki Sekiyama * and no volumes must be frozen. We return without an error. 447b39297aeSTomoki Sekiyama */ 448b39297aeSTomoki Sekiyama *num_vols = 0; 449b39297aeSTomoki Sekiyama return; 450b39297aeSTomoki Sekiyama } 451b39297aeSTomoki Sekiyama 452b39297aeSTomoki Sekiyama /* Tell the provider that the snapshot is finished. */ 453b39297aeSTomoki Sekiyama SetEvent(vss_ctx.hEventThaw); 454b39297aeSTomoki Sekiyama 455b39297aeSTomoki Sekiyama assert(vss_ctx.pVssbc); 456b39297aeSTomoki Sekiyama assert(vss_ctx.pAsyncSnapshot); 457b39297aeSTomoki Sekiyama 458b39297aeSTomoki Sekiyama HRESULT hr = WaitForAsync(vss_ctx.pAsyncSnapshot); 459b39297aeSTomoki Sekiyama switch (hr) { 460b39297aeSTomoki Sekiyama case VSS_S_ASYNC_FINISHED: 461b39297aeSTomoki Sekiyama hr = vss_ctx.pVssbc->BackupComplete(pAsync.replace()); 462b39297aeSTomoki Sekiyama if (SUCCEEDED(hr)) { 463b39297aeSTomoki Sekiyama hr = WaitForAsync(pAsync); 464b39297aeSTomoki Sekiyama } 465b39297aeSTomoki Sekiyama if (FAILED(hr)) { 466b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to complete backup"); 467b39297aeSTomoki Sekiyama } 468b39297aeSTomoki Sekiyama break; 469b39297aeSTomoki Sekiyama 470b39297aeSTomoki Sekiyama case (HRESULT)VSS_E_OBJECT_NOT_FOUND: 471b39297aeSTomoki Sekiyama /* 472b39297aeSTomoki Sekiyama * On Windows earlier than 2008 SP2 which does not support 473b39297aeSTomoki Sekiyama * VSS_VOLSNAP_ATTR_NO_AUTORECOVERY context, the final commit is not 474b39297aeSTomoki Sekiyama * skipped and VSS is aborted by VSS_E_OBJECT_NOT_FOUND. However, as 475b39297aeSTomoki Sekiyama * the system had been frozen until fsfreeze-thaw command was issued, 476b39297aeSTomoki Sekiyama * we ignore this error. 477b39297aeSTomoki Sekiyama */ 478b39297aeSTomoki Sekiyama vss_ctx.pVssbc->AbortBackup(); 479b39297aeSTomoki Sekiyama break; 480b39297aeSTomoki Sekiyama 481b39297aeSTomoki Sekiyama case VSS_E_UNEXPECTED_PROVIDER_ERROR: 482b39297aeSTomoki Sekiyama if (WaitForSingleObject(vss_ctx.hEventTimeout, 0) != WAIT_OBJECT_0) { 483b39297aeSTomoki Sekiyama err_set(errset, hr, "unexpected error in VSS provider"); 484b39297aeSTomoki Sekiyama break; 485b39297aeSTomoki Sekiyama } 486b39297aeSTomoki Sekiyama /* fall through if hEventTimeout is signaled */ 487b39297aeSTomoki Sekiyama 488b39297aeSTomoki Sekiyama case (HRESULT)VSS_E_HOLD_WRITES_TIMEOUT: 489b39297aeSTomoki Sekiyama err_set(errset, hr, "couldn't hold writes: " 490b39297aeSTomoki Sekiyama "fsfreeze is limited up to 10 seconds"); 491b39297aeSTomoki Sekiyama break; 492b39297aeSTomoki Sekiyama 493b39297aeSTomoki Sekiyama default: 494b39297aeSTomoki Sekiyama err_set(errset, hr, "failed to do snapshot set"); 495b39297aeSTomoki Sekiyama } 496b39297aeSTomoki Sekiyama 497b39297aeSTomoki Sekiyama if (err_is_set(errset)) { 498b39297aeSTomoki Sekiyama vss_ctx.pVssbc->AbortBackup(); 499b39297aeSTomoki Sekiyama } 500b39297aeSTomoki Sekiyama *num_vols = vss_ctx.cFrozenVols; 501b39297aeSTomoki Sekiyama requester_cleanup(); 502b39297aeSTomoki Sekiyama 503b39297aeSTomoki Sekiyama CoUninitialize(); 504b39297aeSTomoki Sekiyama } 505