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