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