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