1b39297aeSTomoki Sekiyama /* 2b39297aeSTomoki Sekiyama * QEMU Guest Agent win32 VSS Provider 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 13e55eb806SMichael Roth #include "qemu/osdep.h" 14b39297aeSTomoki Sekiyama #include "vss-common.h" 15*872b69e6SMarc-André Lureau #ifdef HAVE_VSS_SDK 1661fb0bd1SMarc-André Lureau #include <vscoordint.h> 17*872b69e6SMarc-André Lureau #else 18*872b69e6SMarc-André Lureau #include <vsadmin.h> 19*872b69e6SMarc-André Lureau #endif 2061fb0bd1SMarc-André Lureau #include <vsprov.h> 21b39297aeSTomoki Sekiyama 22b39297aeSTomoki Sekiyama #define VSS_TIMEOUT_MSEC (60*1000) 23b39297aeSTomoki Sekiyama 24b39297aeSTomoki Sekiyama static long g_nComObjsInUse; 25b39297aeSTomoki Sekiyama HINSTANCE g_hinstDll; 26b39297aeSTomoki Sekiyama 27b39297aeSTomoki Sekiyama /* VSS common GUID's */ 28b39297aeSTomoki Sekiyama 29b39297aeSTomoki Sekiyama const CLSID CLSID_VSSCoordinator = { 0xE579AB5F, 0x1CC4, 0x44b4, 30b39297aeSTomoki Sekiyama {0xBE, 0xD9, 0xDE, 0x09, 0x91, 0xFF, 0x06, 0x23} }; 31b39297aeSTomoki Sekiyama const IID IID_IVssAdmin = { 0x77ED5996, 0x2F63, 0x11d3, 32b39297aeSTomoki Sekiyama {0x8A, 0x39, 0x00, 0xC0, 0x4F, 0x72, 0xD8, 0xE3} }; 33b39297aeSTomoki Sekiyama 34b39297aeSTomoki Sekiyama const IID IID_IVssHardwareSnapshotProvider = { 0x9593A157, 0x44E9, 0x4344, 35b39297aeSTomoki Sekiyama {0xBB, 0xEB, 0x44, 0xFB, 0xF9, 0xB0, 0x6B, 0x10} }; 36b39297aeSTomoki Sekiyama const IID IID_IVssSoftwareSnapshotProvider = { 0x609e123e, 0x2c5a, 0x44d3, 37b39297aeSTomoki Sekiyama {0x8f, 0x01, 0x0b, 0x1d, 0x9a, 0x47, 0xd1, 0xff} }; 38b39297aeSTomoki Sekiyama const IID IID_IVssProviderCreateSnapshotSet = { 0x5F894E5B, 0x1E39, 0x4778, 39b39297aeSTomoki Sekiyama {0x8E, 0x23, 0x9A, 0xBA, 0xD9, 0xF0, 0xE0, 0x8C} }; 40b39297aeSTomoki Sekiyama const IID IID_IVssProviderNotifications = { 0xE561901F, 0x03A5, 0x4afe, 41b39297aeSTomoki Sekiyama {0x86, 0xD0, 0x72, 0xBA, 0xEE, 0xCE, 0x70, 0x04} }; 42b39297aeSTomoki Sekiyama 43b39297aeSTomoki Sekiyama const IID IID_IVssEnumObject = { 0xAE1C7110, 0x2F60, 0x11d3, 44b39297aeSTomoki Sekiyama {0x8A, 0x39, 0x00, 0xC0, 0x4F, 0x72, 0xD8, 0xE3} }; 45b39297aeSTomoki Sekiyama 46b39297aeSTomoki Sekiyama 47b39297aeSTomoki Sekiyama void LockModule(BOOL lock) 48b39297aeSTomoki Sekiyama { 49b39297aeSTomoki Sekiyama if (lock) { 50b39297aeSTomoki Sekiyama InterlockedIncrement(&g_nComObjsInUse); 51b39297aeSTomoki Sekiyama } else { 52b39297aeSTomoki Sekiyama InterlockedDecrement(&g_nComObjsInUse); 53b39297aeSTomoki Sekiyama } 54b39297aeSTomoki Sekiyama } 55b39297aeSTomoki Sekiyama 56b39297aeSTomoki Sekiyama /* Empty enumerator for VssObject */ 57b39297aeSTomoki Sekiyama 58b39297aeSTomoki Sekiyama class CQGAVSSEnumObject : public IVssEnumObject 59b39297aeSTomoki Sekiyama { 60b39297aeSTomoki Sekiyama public: 61b39297aeSTomoki Sekiyama STDMETHODIMP QueryInterface(REFIID riid, void **ppObj); 62b39297aeSTomoki Sekiyama STDMETHODIMP_(ULONG) AddRef(); 63b39297aeSTomoki Sekiyama STDMETHODIMP_(ULONG) Release(); 64b39297aeSTomoki Sekiyama 65b39297aeSTomoki Sekiyama /* IVssEnumObject Methods */ 66b39297aeSTomoki Sekiyama STDMETHODIMP Next( 67b39297aeSTomoki Sekiyama ULONG celt, VSS_OBJECT_PROP *rgelt, ULONG *pceltFetched); 68b39297aeSTomoki Sekiyama STDMETHODIMP Skip(ULONG celt); 69b39297aeSTomoki Sekiyama STDMETHODIMP Reset(void); 70b39297aeSTomoki Sekiyama STDMETHODIMP Clone(IVssEnumObject **ppenum); 71b39297aeSTomoki Sekiyama 72b39297aeSTomoki Sekiyama /* CQGAVSSEnumObject Methods */ 73b39297aeSTomoki Sekiyama CQGAVSSEnumObject(); 74b39297aeSTomoki Sekiyama ~CQGAVSSEnumObject(); 75b39297aeSTomoki Sekiyama 76b39297aeSTomoki Sekiyama private: 77b39297aeSTomoki Sekiyama long m_nRefCount; 78b39297aeSTomoki Sekiyama }; 79b39297aeSTomoki Sekiyama 80b39297aeSTomoki Sekiyama CQGAVSSEnumObject::CQGAVSSEnumObject() 81b39297aeSTomoki Sekiyama { 82b39297aeSTomoki Sekiyama m_nRefCount = 0; 83b39297aeSTomoki Sekiyama LockModule(TRUE); 84b39297aeSTomoki Sekiyama } 85b39297aeSTomoki Sekiyama 86b39297aeSTomoki Sekiyama CQGAVSSEnumObject::~CQGAVSSEnumObject() 87b39297aeSTomoki Sekiyama { 88b39297aeSTomoki Sekiyama LockModule(FALSE); 89b39297aeSTomoki Sekiyama } 90b39297aeSTomoki Sekiyama 91b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVSSEnumObject::QueryInterface(REFIID riid, void **ppObj) 92b39297aeSTomoki Sekiyama { 93b39297aeSTomoki Sekiyama if (riid == IID_IUnknown || riid == IID_IVssEnumObject) { 94b39297aeSTomoki Sekiyama *ppObj = static_cast<void*>(static_cast<IVssEnumObject*>(this)); 95b39297aeSTomoki Sekiyama AddRef(); 96b39297aeSTomoki Sekiyama return S_OK; 97b39297aeSTomoki Sekiyama } 98b39297aeSTomoki Sekiyama *ppObj = NULL; 99b39297aeSTomoki Sekiyama return E_NOINTERFACE; 100b39297aeSTomoki Sekiyama } 101b39297aeSTomoki Sekiyama 102b39297aeSTomoki Sekiyama STDMETHODIMP_(ULONG) CQGAVSSEnumObject::AddRef() 103b39297aeSTomoki Sekiyama { 104b39297aeSTomoki Sekiyama return InterlockedIncrement(&m_nRefCount); 105b39297aeSTomoki Sekiyama } 106b39297aeSTomoki Sekiyama 107b39297aeSTomoki Sekiyama STDMETHODIMP_(ULONG) CQGAVSSEnumObject::Release() 108b39297aeSTomoki Sekiyama { 109b39297aeSTomoki Sekiyama long nRefCount = InterlockedDecrement(&m_nRefCount); 110b39297aeSTomoki Sekiyama if (m_nRefCount == 0) { 111b39297aeSTomoki Sekiyama delete this; 112b39297aeSTomoki Sekiyama } 113b39297aeSTomoki Sekiyama return nRefCount; 114b39297aeSTomoki Sekiyama } 115b39297aeSTomoki Sekiyama 116b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVSSEnumObject::Next( 117b39297aeSTomoki Sekiyama ULONG celt, VSS_OBJECT_PROP *rgelt, ULONG *pceltFetched) 118b39297aeSTomoki Sekiyama { 119b39297aeSTomoki Sekiyama *pceltFetched = 0; 120b39297aeSTomoki Sekiyama return S_FALSE; 121b39297aeSTomoki Sekiyama } 122b39297aeSTomoki Sekiyama 123b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVSSEnumObject::Skip(ULONG celt) 124b39297aeSTomoki Sekiyama { 125b39297aeSTomoki Sekiyama return S_FALSE; 126b39297aeSTomoki Sekiyama } 127b39297aeSTomoki Sekiyama 128b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVSSEnumObject::Reset(void) 129b39297aeSTomoki Sekiyama { 130b39297aeSTomoki Sekiyama return S_OK; 131b39297aeSTomoki Sekiyama } 132b39297aeSTomoki Sekiyama 133b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVSSEnumObject::Clone(IVssEnumObject **ppenum) 134b39297aeSTomoki Sekiyama { 135b39297aeSTomoki Sekiyama return E_NOTIMPL; 136b39297aeSTomoki Sekiyama } 137b39297aeSTomoki Sekiyama 138b39297aeSTomoki Sekiyama 139b39297aeSTomoki Sekiyama /* QGAVssProvider */ 140b39297aeSTomoki Sekiyama 141b39297aeSTomoki Sekiyama class CQGAVssProvider : 142b39297aeSTomoki Sekiyama public IVssSoftwareSnapshotProvider, 143b39297aeSTomoki Sekiyama public IVssProviderCreateSnapshotSet, 144b39297aeSTomoki Sekiyama public IVssProviderNotifications 145b39297aeSTomoki Sekiyama { 146b39297aeSTomoki Sekiyama public: 147b39297aeSTomoki Sekiyama STDMETHODIMP QueryInterface(REFIID riid, void **ppObj); 148b39297aeSTomoki Sekiyama STDMETHODIMP_(ULONG) AddRef(); 149b39297aeSTomoki Sekiyama STDMETHODIMP_(ULONG) Release(); 150b39297aeSTomoki Sekiyama 151b39297aeSTomoki Sekiyama /* IVssSoftwareSnapshotProvider Methods */ 152b39297aeSTomoki Sekiyama STDMETHODIMP SetContext(LONG lContext); 153b39297aeSTomoki Sekiyama STDMETHODIMP GetSnapshotProperties( 154b39297aeSTomoki Sekiyama VSS_ID SnapshotId, VSS_SNAPSHOT_PROP *pProp); 155b39297aeSTomoki Sekiyama STDMETHODIMP Query( 156b39297aeSTomoki Sekiyama VSS_ID QueriedObjectId, VSS_OBJECT_TYPE eQueriedObjectType, 157b39297aeSTomoki Sekiyama VSS_OBJECT_TYPE eReturnedObjectsType, IVssEnumObject **ppEnum); 158b39297aeSTomoki Sekiyama STDMETHODIMP DeleteSnapshots( 159b39297aeSTomoki Sekiyama VSS_ID SourceObjectId, VSS_OBJECT_TYPE eSourceObjectType, 160b39297aeSTomoki Sekiyama BOOL bForceDelete, LONG *plDeletedSnapshots, 161b39297aeSTomoki Sekiyama VSS_ID *pNondeletedSnapshotID); 162b39297aeSTomoki Sekiyama STDMETHODIMP BeginPrepareSnapshot( 163b39297aeSTomoki Sekiyama VSS_ID SnapshotSetId, VSS_ID SnapshotId, 164b39297aeSTomoki Sekiyama VSS_PWSZ pwszVolumeName, LONG lNewContext); 165b39297aeSTomoki Sekiyama STDMETHODIMP IsVolumeSupported( 166b39297aeSTomoki Sekiyama VSS_PWSZ pwszVolumeName, BOOL *pbSupportedByThisProvider); 167b39297aeSTomoki Sekiyama STDMETHODIMP IsVolumeSnapshotted( 168b39297aeSTomoki Sekiyama VSS_PWSZ pwszVolumeName, BOOL *pbSnapshotsPresent, 169b39297aeSTomoki Sekiyama LONG *plSnapshotCompatibility); 170b39297aeSTomoki Sekiyama STDMETHODIMP SetSnapshotProperty( 171b39297aeSTomoki Sekiyama VSS_ID SnapshotId, VSS_SNAPSHOT_PROPERTY_ID eSnapshotPropertyId, 172b39297aeSTomoki Sekiyama VARIANT vProperty); 173b39297aeSTomoki Sekiyama STDMETHODIMP RevertToSnapshot(VSS_ID SnapshotId); 174b39297aeSTomoki Sekiyama STDMETHODIMP QueryRevertStatus(VSS_PWSZ pwszVolume, IVssAsync **ppAsync); 175b39297aeSTomoki Sekiyama 176b39297aeSTomoki Sekiyama /* IVssProviderCreateSnapshotSet Methods */ 177b39297aeSTomoki Sekiyama STDMETHODIMP EndPrepareSnapshots(VSS_ID SnapshotSetId); 178b39297aeSTomoki Sekiyama STDMETHODIMP PreCommitSnapshots(VSS_ID SnapshotSetId); 179b39297aeSTomoki Sekiyama STDMETHODIMP CommitSnapshots(VSS_ID SnapshotSetId); 180b39297aeSTomoki Sekiyama STDMETHODIMP PostCommitSnapshots( 181b39297aeSTomoki Sekiyama VSS_ID SnapshotSetId, LONG lSnapshotsCount); 182b39297aeSTomoki Sekiyama STDMETHODIMP PreFinalCommitSnapshots(VSS_ID SnapshotSetId); 183b39297aeSTomoki Sekiyama STDMETHODIMP PostFinalCommitSnapshots(VSS_ID SnapshotSetId); 184b39297aeSTomoki Sekiyama STDMETHODIMP AbortSnapshots(VSS_ID SnapshotSetId); 185b39297aeSTomoki Sekiyama 186b39297aeSTomoki Sekiyama /* IVssProviderNotifications Methods */ 187b39297aeSTomoki Sekiyama STDMETHODIMP OnLoad(IUnknown *pCallback); 188b39297aeSTomoki Sekiyama STDMETHODIMP OnUnload(BOOL bForceUnload); 189b39297aeSTomoki Sekiyama 190b39297aeSTomoki Sekiyama /* CQGAVssProvider Methods */ 191b39297aeSTomoki Sekiyama CQGAVssProvider(); 192b39297aeSTomoki Sekiyama ~CQGAVssProvider(); 193b39297aeSTomoki Sekiyama 194b39297aeSTomoki Sekiyama private: 195b39297aeSTomoki Sekiyama long m_nRefCount; 196b39297aeSTomoki Sekiyama }; 197b39297aeSTomoki Sekiyama 198b39297aeSTomoki Sekiyama CQGAVssProvider::CQGAVssProvider() 199b39297aeSTomoki Sekiyama { 200b39297aeSTomoki Sekiyama m_nRefCount = 0; 201b39297aeSTomoki Sekiyama LockModule(TRUE); 202b39297aeSTomoki Sekiyama } 203b39297aeSTomoki Sekiyama 204b39297aeSTomoki Sekiyama CQGAVssProvider::~CQGAVssProvider() 205b39297aeSTomoki Sekiyama { 206b39297aeSTomoki Sekiyama LockModule(FALSE); 207b39297aeSTomoki Sekiyama } 208b39297aeSTomoki Sekiyama 209b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::QueryInterface(REFIID riid, void **ppObj) 210b39297aeSTomoki Sekiyama { 211b39297aeSTomoki Sekiyama if (riid == IID_IUnknown) { 212b39297aeSTomoki Sekiyama *ppObj = static_cast<void*>(this); 213b39297aeSTomoki Sekiyama AddRef(); 214b39297aeSTomoki Sekiyama return S_OK; 215b39297aeSTomoki Sekiyama } 216b39297aeSTomoki Sekiyama if (riid == IID_IVssSoftwareSnapshotProvider) { 217b39297aeSTomoki Sekiyama *ppObj = static_cast<void*>( 218b39297aeSTomoki Sekiyama static_cast<IVssSoftwareSnapshotProvider*>(this)); 219b39297aeSTomoki Sekiyama AddRef(); 220b39297aeSTomoki Sekiyama return S_OK; 221b39297aeSTomoki Sekiyama } 222b39297aeSTomoki Sekiyama if (riid == IID_IVssProviderCreateSnapshotSet) { 223b39297aeSTomoki Sekiyama *ppObj = static_cast<void*>( 224b39297aeSTomoki Sekiyama static_cast<IVssProviderCreateSnapshotSet*>(this)); 225b39297aeSTomoki Sekiyama AddRef(); 226b39297aeSTomoki Sekiyama return S_OK; 227b39297aeSTomoki Sekiyama } 228b39297aeSTomoki Sekiyama if (riid == IID_IVssProviderNotifications) { 229b39297aeSTomoki Sekiyama *ppObj = static_cast<void*>( 230b39297aeSTomoki Sekiyama static_cast<IVssProviderNotifications*>(this)); 231b39297aeSTomoki Sekiyama AddRef(); 232b39297aeSTomoki Sekiyama return S_OK; 233b39297aeSTomoki Sekiyama } 234b39297aeSTomoki Sekiyama *ppObj = NULL; 235b39297aeSTomoki Sekiyama return E_NOINTERFACE; 236b39297aeSTomoki Sekiyama } 237b39297aeSTomoki Sekiyama 238b39297aeSTomoki Sekiyama STDMETHODIMP_(ULONG) CQGAVssProvider::AddRef() 239b39297aeSTomoki Sekiyama { 240b39297aeSTomoki Sekiyama return InterlockedIncrement(&m_nRefCount); 241b39297aeSTomoki Sekiyama } 242b39297aeSTomoki Sekiyama 243b39297aeSTomoki Sekiyama STDMETHODIMP_(ULONG) CQGAVssProvider::Release() 244b39297aeSTomoki Sekiyama { 245b39297aeSTomoki Sekiyama long nRefCount = InterlockedDecrement(&m_nRefCount); 246b39297aeSTomoki Sekiyama if (m_nRefCount == 0) { 247b39297aeSTomoki Sekiyama delete this; 248b39297aeSTomoki Sekiyama } 249b39297aeSTomoki Sekiyama return nRefCount; 250b39297aeSTomoki Sekiyama } 251b39297aeSTomoki Sekiyama 252b39297aeSTomoki Sekiyama 253b39297aeSTomoki Sekiyama /* 254b39297aeSTomoki Sekiyama * IVssSoftwareSnapshotProvider methods 255b39297aeSTomoki Sekiyama */ 256b39297aeSTomoki Sekiyama 257b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::SetContext(LONG lContext) 258b39297aeSTomoki Sekiyama { 259b39297aeSTomoki Sekiyama return S_OK; 260b39297aeSTomoki Sekiyama } 261b39297aeSTomoki Sekiyama 262b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::GetSnapshotProperties( 263b39297aeSTomoki Sekiyama VSS_ID SnapshotId, VSS_SNAPSHOT_PROP *pProp) 264b39297aeSTomoki Sekiyama { 265b39297aeSTomoki Sekiyama return VSS_E_OBJECT_NOT_FOUND; 266b39297aeSTomoki Sekiyama } 267b39297aeSTomoki Sekiyama 268b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::Query( 269b39297aeSTomoki Sekiyama VSS_ID QueriedObjectId, VSS_OBJECT_TYPE eQueriedObjectType, 270b39297aeSTomoki Sekiyama VSS_OBJECT_TYPE eReturnedObjectsType, IVssEnumObject **ppEnum) 271b39297aeSTomoki Sekiyama { 272b39297aeSTomoki Sekiyama try { 273b39297aeSTomoki Sekiyama *ppEnum = new CQGAVSSEnumObject; 274b39297aeSTomoki Sekiyama } catch (...) { 275b39297aeSTomoki Sekiyama return E_OUTOFMEMORY; 276b39297aeSTomoki Sekiyama } 277b39297aeSTomoki Sekiyama (*ppEnum)->AddRef(); 278b39297aeSTomoki Sekiyama return S_OK; 279b39297aeSTomoki Sekiyama } 280b39297aeSTomoki Sekiyama 281b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::DeleteSnapshots( 282b39297aeSTomoki Sekiyama VSS_ID SourceObjectId, VSS_OBJECT_TYPE eSourceObjectType, 283b39297aeSTomoki Sekiyama BOOL bForceDelete, LONG *plDeletedSnapshots, VSS_ID *pNondeletedSnapshotID) 284b39297aeSTomoki Sekiyama { 285d9e1f574STomoki Sekiyama *plDeletedSnapshots = 0; 286d9e1f574STomoki Sekiyama *pNondeletedSnapshotID = SourceObjectId; 287d9e1f574STomoki Sekiyama return S_OK; 288b39297aeSTomoki Sekiyama } 289b39297aeSTomoki Sekiyama 290b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::BeginPrepareSnapshot( 291b39297aeSTomoki Sekiyama VSS_ID SnapshotSetId, VSS_ID SnapshotId, 292b39297aeSTomoki Sekiyama VSS_PWSZ pwszVolumeName, LONG lNewContext) 293b39297aeSTomoki Sekiyama { 294b39297aeSTomoki Sekiyama return S_OK; 295b39297aeSTomoki Sekiyama } 296b39297aeSTomoki Sekiyama 297b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::IsVolumeSupported( 298b39297aeSTomoki Sekiyama VSS_PWSZ pwszVolumeName, BOOL *pbSupportedByThisProvider) 299b39297aeSTomoki Sekiyama { 300ff8adbcfSTomoki Sekiyama HANDLE hEventFrozen; 301b39297aeSTomoki Sekiyama 302ff8adbcfSTomoki Sekiyama /* Check if a requester is qemu-ga by whether an event is created */ 303ff8adbcfSTomoki Sekiyama hEventFrozen = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_FROZEN); 304ff8adbcfSTomoki Sekiyama if (!hEventFrozen) { 305ff8adbcfSTomoki Sekiyama *pbSupportedByThisProvider = FALSE; 306ff8adbcfSTomoki Sekiyama return S_OK; 307ff8adbcfSTomoki Sekiyama } 308ff8adbcfSTomoki Sekiyama CloseHandle(hEventFrozen); 309ff8adbcfSTomoki Sekiyama 310ff8adbcfSTomoki Sekiyama *pbSupportedByThisProvider = TRUE; 311b39297aeSTomoki Sekiyama return S_OK; 312b39297aeSTomoki Sekiyama } 313b39297aeSTomoki Sekiyama 314b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::IsVolumeSnapshotted(VSS_PWSZ pwszVolumeName, 315b39297aeSTomoki Sekiyama BOOL *pbSnapshotsPresent, LONG *plSnapshotCompatibility) 316b39297aeSTomoki Sekiyama { 317b39297aeSTomoki Sekiyama *pbSnapshotsPresent = FALSE; 318b39297aeSTomoki Sekiyama *plSnapshotCompatibility = 0; 319b39297aeSTomoki Sekiyama return S_OK; 320b39297aeSTomoki Sekiyama } 321b39297aeSTomoki Sekiyama 322b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::SetSnapshotProperty(VSS_ID SnapshotId, 323b39297aeSTomoki Sekiyama VSS_SNAPSHOT_PROPERTY_ID eSnapshotPropertyId, VARIANT vProperty) 324b39297aeSTomoki Sekiyama { 325b39297aeSTomoki Sekiyama return E_NOTIMPL; 326b39297aeSTomoki Sekiyama } 327b39297aeSTomoki Sekiyama 328b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::RevertToSnapshot(VSS_ID SnapshotId) 329b39297aeSTomoki Sekiyama { 330b39297aeSTomoki Sekiyama return E_NOTIMPL; 331b39297aeSTomoki Sekiyama } 332b39297aeSTomoki Sekiyama 333b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::QueryRevertStatus( 334b39297aeSTomoki Sekiyama VSS_PWSZ pwszVolume, IVssAsync **ppAsync) 335b39297aeSTomoki Sekiyama { 336b39297aeSTomoki Sekiyama return E_NOTIMPL; 337b39297aeSTomoki Sekiyama } 338b39297aeSTomoki Sekiyama 339b39297aeSTomoki Sekiyama 340b39297aeSTomoki Sekiyama /* 341b39297aeSTomoki Sekiyama * IVssProviderCreateSnapshotSet methods 342b39297aeSTomoki Sekiyama */ 343b39297aeSTomoki Sekiyama 344b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::EndPrepareSnapshots(VSS_ID SnapshotSetId) 345b39297aeSTomoki Sekiyama { 346b39297aeSTomoki Sekiyama return S_OK; 347b39297aeSTomoki Sekiyama } 348b39297aeSTomoki Sekiyama 349b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::PreCommitSnapshots(VSS_ID SnapshotSetId) 350b39297aeSTomoki Sekiyama { 351b39297aeSTomoki Sekiyama return S_OK; 352b39297aeSTomoki Sekiyama } 353b39297aeSTomoki Sekiyama 354b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::CommitSnapshots(VSS_ID SnapshotSetId) 355b39297aeSTomoki Sekiyama { 356b39297aeSTomoki Sekiyama HRESULT hr = S_OK; 357b39297aeSTomoki Sekiyama HANDLE hEventFrozen, hEventThaw, hEventTimeout; 358b39297aeSTomoki Sekiyama 359b39297aeSTomoki Sekiyama hEventFrozen = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_FROZEN); 3604c1b8f1eSTomoki Sekiyama if (!hEventFrozen) { 361b39297aeSTomoki Sekiyama return E_FAIL; 362b39297aeSTomoki Sekiyama } 363b39297aeSTomoki Sekiyama 364b39297aeSTomoki Sekiyama hEventThaw = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_THAW); 3654c1b8f1eSTomoki Sekiyama if (!hEventThaw) { 366b39297aeSTomoki Sekiyama CloseHandle(hEventFrozen); 367b39297aeSTomoki Sekiyama return E_FAIL; 368b39297aeSTomoki Sekiyama } 369b39297aeSTomoki Sekiyama 370b39297aeSTomoki Sekiyama hEventTimeout = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_TIMEOUT); 3714c1b8f1eSTomoki Sekiyama if (!hEventTimeout) { 372b39297aeSTomoki Sekiyama CloseHandle(hEventFrozen); 373b39297aeSTomoki Sekiyama CloseHandle(hEventThaw); 374b39297aeSTomoki Sekiyama return E_FAIL; 375b39297aeSTomoki Sekiyama } 376b39297aeSTomoki Sekiyama 377b39297aeSTomoki Sekiyama /* Send event to qemu-ga to notify filesystem is frozen */ 378b39297aeSTomoki Sekiyama SetEvent(hEventFrozen); 379b39297aeSTomoki Sekiyama 380b39297aeSTomoki Sekiyama /* Wait until the snapshot is taken by the host. */ 381b39297aeSTomoki Sekiyama if (WaitForSingleObject(hEventThaw, VSS_TIMEOUT_MSEC) != WAIT_OBJECT_0) { 382b39297aeSTomoki Sekiyama /* Send event to qemu-ga to notify the provider is timed out */ 383b39297aeSTomoki Sekiyama SetEvent(hEventTimeout); 384b39297aeSTomoki Sekiyama } 385b39297aeSTomoki Sekiyama 386b39297aeSTomoki Sekiyama CloseHandle(hEventThaw); 387b39297aeSTomoki Sekiyama CloseHandle(hEventFrozen); 388b39297aeSTomoki Sekiyama CloseHandle(hEventTimeout); 389b39297aeSTomoki Sekiyama return hr; 390b39297aeSTomoki Sekiyama } 391b39297aeSTomoki Sekiyama 392b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::PostCommitSnapshots( 393b39297aeSTomoki Sekiyama VSS_ID SnapshotSetId, LONG lSnapshotsCount) 394b39297aeSTomoki Sekiyama { 395b39297aeSTomoki Sekiyama return S_OK; 396b39297aeSTomoki Sekiyama } 397b39297aeSTomoki Sekiyama 398b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::PreFinalCommitSnapshots(VSS_ID SnapshotSetId) 399b39297aeSTomoki Sekiyama { 400b39297aeSTomoki Sekiyama return S_OK; 401b39297aeSTomoki Sekiyama } 402b39297aeSTomoki Sekiyama 403b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::PostFinalCommitSnapshots(VSS_ID SnapshotSetId) 404b39297aeSTomoki Sekiyama { 405b39297aeSTomoki Sekiyama return S_OK; 406b39297aeSTomoki Sekiyama } 407b39297aeSTomoki Sekiyama 408b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::AbortSnapshots(VSS_ID SnapshotSetId) 409b39297aeSTomoki Sekiyama { 410b39297aeSTomoki Sekiyama return S_OK; 411b39297aeSTomoki Sekiyama } 412b39297aeSTomoki Sekiyama 413b39297aeSTomoki Sekiyama /* 414b39297aeSTomoki Sekiyama * IVssProviderNotifications methods 415b39297aeSTomoki Sekiyama */ 416b39297aeSTomoki Sekiyama 417b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::OnLoad(IUnknown *pCallback) 418b39297aeSTomoki Sekiyama { 419b39297aeSTomoki Sekiyama return S_OK; 420b39297aeSTomoki Sekiyama } 421b39297aeSTomoki Sekiyama 422b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::OnUnload(BOOL bForceUnload) 423b39297aeSTomoki Sekiyama { 424b39297aeSTomoki Sekiyama return S_OK; 425b39297aeSTomoki Sekiyama } 426b39297aeSTomoki Sekiyama 427b39297aeSTomoki Sekiyama 428b39297aeSTomoki Sekiyama /* 429b39297aeSTomoki Sekiyama * CQGAVssProviderFactory class 430b39297aeSTomoki Sekiyama */ 431b39297aeSTomoki Sekiyama 432b39297aeSTomoki Sekiyama class CQGAVssProviderFactory : public IClassFactory 433b39297aeSTomoki Sekiyama { 434b39297aeSTomoki Sekiyama public: 435b39297aeSTomoki Sekiyama STDMETHODIMP QueryInterface(REFIID riid, void **ppv); 436b39297aeSTomoki Sekiyama STDMETHODIMP_(ULONG) AddRef(); 437b39297aeSTomoki Sekiyama STDMETHODIMP_(ULONG) Release(); 438b39297aeSTomoki Sekiyama STDMETHODIMP CreateInstance( 439b39297aeSTomoki Sekiyama IUnknown *pUnknownOuter, REFIID iid, void **ppv); 440b39297aeSTomoki Sekiyama STDMETHODIMP LockServer(BOOL lock) { return E_NOTIMPL; } 441b39297aeSTomoki Sekiyama 442b39297aeSTomoki Sekiyama CQGAVssProviderFactory(); 443b39297aeSTomoki Sekiyama ~CQGAVssProviderFactory(); 444b39297aeSTomoki Sekiyama 445b39297aeSTomoki Sekiyama private: 446b39297aeSTomoki Sekiyama long m_nRefCount; 447b39297aeSTomoki Sekiyama }; 448b39297aeSTomoki Sekiyama 449b39297aeSTomoki Sekiyama CQGAVssProviderFactory::CQGAVssProviderFactory() 450b39297aeSTomoki Sekiyama { 451b39297aeSTomoki Sekiyama m_nRefCount = 0; 452b39297aeSTomoki Sekiyama LockModule(TRUE); 453b39297aeSTomoki Sekiyama } 454b39297aeSTomoki Sekiyama 455b39297aeSTomoki Sekiyama CQGAVssProviderFactory::~CQGAVssProviderFactory() 456b39297aeSTomoki Sekiyama { 457b39297aeSTomoki Sekiyama LockModule(FALSE); 458b39297aeSTomoki Sekiyama } 459b39297aeSTomoki Sekiyama 460b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProviderFactory::QueryInterface(REFIID riid, void **ppv) 461b39297aeSTomoki Sekiyama { 462b39297aeSTomoki Sekiyama if (riid == IID_IUnknown || riid == IID_IClassFactory) { 463b39297aeSTomoki Sekiyama *ppv = static_cast<void*>(this); 464b39297aeSTomoki Sekiyama AddRef(); 465b39297aeSTomoki Sekiyama return S_OK; 466b39297aeSTomoki Sekiyama } 467b39297aeSTomoki Sekiyama *ppv = NULL; 468b39297aeSTomoki Sekiyama return E_NOINTERFACE; 469b39297aeSTomoki Sekiyama } 470b39297aeSTomoki Sekiyama 471b39297aeSTomoki Sekiyama STDMETHODIMP_(ULONG) CQGAVssProviderFactory::AddRef() 472b39297aeSTomoki Sekiyama { 473b39297aeSTomoki Sekiyama return InterlockedIncrement(&m_nRefCount); 474b39297aeSTomoki Sekiyama } 475b39297aeSTomoki Sekiyama 476b39297aeSTomoki Sekiyama STDMETHODIMP_(ULONG) CQGAVssProviderFactory::Release() 477b39297aeSTomoki Sekiyama { 478b39297aeSTomoki Sekiyama long nRefCount = InterlockedDecrement(&m_nRefCount); 479b39297aeSTomoki Sekiyama if (m_nRefCount == 0) { 480b39297aeSTomoki Sekiyama delete this; 481b39297aeSTomoki Sekiyama } 482b39297aeSTomoki Sekiyama return nRefCount; 483b39297aeSTomoki Sekiyama } 484b39297aeSTomoki Sekiyama 485b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProviderFactory::CreateInstance( 486b39297aeSTomoki Sekiyama IUnknown *pUnknownOuter, REFIID iid, void **ppv) 487b39297aeSTomoki Sekiyama { 488b39297aeSTomoki Sekiyama CQGAVssProvider *pObj; 489b39297aeSTomoki Sekiyama 490b39297aeSTomoki Sekiyama if (pUnknownOuter) { 491b39297aeSTomoki Sekiyama return CLASS_E_NOAGGREGATION; 492b39297aeSTomoki Sekiyama } 493b39297aeSTomoki Sekiyama try { 494b39297aeSTomoki Sekiyama pObj = new CQGAVssProvider; 495b39297aeSTomoki Sekiyama } catch (...) { 496b39297aeSTomoki Sekiyama return E_OUTOFMEMORY; 497b39297aeSTomoki Sekiyama } 498b39297aeSTomoki Sekiyama HRESULT hr = pObj->QueryInterface(iid, ppv); 499b39297aeSTomoki Sekiyama if (FAILED(hr)) { 500b39297aeSTomoki Sekiyama delete pObj; 501b39297aeSTomoki Sekiyama } 502b39297aeSTomoki Sekiyama return hr; 503b39297aeSTomoki Sekiyama } 504b39297aeSTomoki Sekiyama 505b39297aeSTomoki Sekiyama 506b39297aeSTomoki Sekiyama /* 507b39297aeSTomoki Sekiyama * DLL functions 508b39297aeSTomoki Sekiyama */ 509b39297aeSTomoki Sekiyama 510b39297aeSTomoki Sekiyama STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) 511b39297aeSTomoki Sekiyama { 512b39297aeSTomoki Sekiyama CQGAVssProviderFactory *factory; 513b39297aeSTomoki Sekiyama try { 514b39297aeSTomoki Sekiyama factory = new CQGAVssProviderFactory; 515b39297aeSTomoki Sekiyama } catch (...) { 516b39297aeSTomoki Sekiyama return E_OUTOFMEMORY; 517b39297aeSTomoki Sekiyama } 518b39297aeSTomoki Sekiyama factory->AddRef(); 519b39297aeSTomoki Sekiyama HRESULT hr = factory->QueryInterface(riid, ppv); 520b39297aeSTomoki Sekiyama factory->Release(); 521b39297aeSTomoki Sekiyama return hr; 522b39297aeSTomoki Sekiyama } 523b39297aeSTomoki Sekiyama 524b39297aeSTomoki Sekiyama STDAPI DllCanUnloadNow() 525b39297aeSTomoki Sekiyama { 526b39297aeSTomoki Sekiyama return g_nComObjsInUse == 0 ? S_OK : S_FALSE; 527b39297aeSTomoki Sekiyama } 528b39297aeSTomoki Sekiyama 529b39297aeSTomoki Sekiyama EXTERN_C 530b39297aeSTomoki Sekiyama BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved) 531b39297aeSTomoki Sekiyama { 532b39297aeSTomoki Sekiyama if (dwReason == DLL_PROCESS_ATTACH) { 533b39297aeSTomoki Sekiyama g_hinstDll = hinstDll; 534b39297aeSTomoki Sekiyama DisableThreadLibraryCalls(hinstDll); 535b39297aeSTomoki Sekiyama } 536b39297aeSTomoki Sekiyama return TRUE; 537b39297aeSTomoki Sekiyama } 538