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 13b39297aeSTomoki Sekiyama #include <stdio.h> 14b39297aeSTomoki Sekiyama #include "vss-common.h" 15b39297aeSTomoki Sekiyama #include "inc/win2003/vscoordint.h" 16b39297aeSTomoki Sekiyama #include "inc/win2003/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 { 281b39297aeSTomoki Sekiyama return E_NOTIMPL; 282b39297aeSTomoki Sekiyama } 283b39297aeSTomoki Sekiyama 284b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::BeginPrepareSnapshot( 285b39297aeSTomoki Sekiyama VSS_ID SnapshotSetId, VSS_ID SnapshotId, 286b39297aeSTomoki Sekiyama VSS_PWSZ pwszVolumeName, LONG lNewContext) 287b39297aeSTomoki Sekiyama { 288b39297aeSTomoki Sekiyama return S_OK; 289b39297aeSTomoki Sekiyama } 290b39297aeSTomoki Sekiyama 291b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::IsVolumeSupported( 292b39297aeSTomoki Sekiyama VSS_PWSZ pwszVolumeName, BOOL *pbSupportedByThisProvider) 293b39297aeSTomoki Sekiyama { 294*ff8adbcfSTomoki Sekiyama HANDLE hEventFrozen; 295b39297aeSTomoki Sekiyama 296*ff8adbcfSTomoki Sekiyama /* Check if a requester is qemu-ga by whether an event is created */ 297*ff8adbcfSTomoki Sekiyama hEventFrozen = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_FROZEN); 298*ff8adbcfSTomoki Sekiyama if (!hEventFrozen) { 299*ff8adbcfSTomoki Sekiyama *pbSupportedByThisProvider = FALSE; 300*ff8adbcfSTomoki Sekiyama return S_OK; 301*ff8adbcfSTomoki Sekiyama } 302*ff8adbcfSTomoki Sekiyama CloseHandle(hEventFrozen); 303*ff8adbcfSTomoki Sekiyama 304*ff8adbcfSTomoki Sekiyama *pbSupportedByThisProvider = TRUE; 305b39297aeSTomoki Sekiyama return S_OK; 306b39297aeSTomoki Sekiyama } 307b39297aeSTomoki Sekiyama 308b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::IsVolumeSnapshotted(VSS_PWSZ pwszVolumeName, 309b39297aeSTomoki Sekiyama BOOL *pbSnapshotsPresent, LONG *plSnapshotCompatibility) 310b39297aeSTomoki Sekiyama { 311b39297aeSTomoki Sekiyama *pbSnapshotsPresent = FALSE; 312b39297aeSTomoki Sekiyama *plSnapshotCompatibility = 0; 313b39297aeSTomoki Sekiyama return S_OK; 314b39297aeSTomoki Sekiyama } 315b39297aeSTomoki Sekiyama 316b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::SetSnapshotProperty(VSS_ID SnapshotId, 317b39297aeSTomoki Sekiyama VSS_SNAPSHOT_PROPERTY_ID eSnapshotPropertyId, VARIANT vProperty) 318b39297aeSTomoki Sekiyama { 319b39297aeSTomoki Sekiyama return E_NOTIMPL; 320b39297aeSTomoki Sekiyama } 321b39297aeSTomoki Sekiyama 322b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::RevertToSnapshot(VSS_ID SnapshotId) 323b39297aeSTomoki Sekiyama { 324b39297aeSTomoki Sekiyama return E_NOTIMPL; 325b39297aeSTomoki Sekiyama } 326b39297aeSTomoki Sekiyama 327b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::QueryRevertStatus( 328b39297aeSTomoki Sekiyama VSS_PWSZ pwszVolume, IVssAsync **ppAsync) 329b39297aeSTomoki Sekiyama { 330b39297aeSTomoki Sekiyama return E_NOTIMPL; 331b39297aeSTomoki Sekiyama } 332b39297aeSTomoki Sekiyama 333b39297aeSTomoki Sekiyama 334b39297aeSTomoki Sekiyama /* 335b39297aeSTomoki Sekiyama * IVssProviderCreateSnapshotSet methods 336b39297aeSTomoki Sekiyama */ 337b39297aeSTomoki Sekiyama 338b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::EndPrepareSnapshots(VSS_ID SnapshotSetId) 339b39297aeSTomoki Sekiyama { 340b39297aeSTomoki Sekiyama return S_OK; 341b39297aeSTomoki Sekiyama } 342b39297aeSTomoki Sekiyama 343b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::PreCommitSnapshots(VSS_ID SnapshotSetId) 344b39297aeSTomoki Sekiyama { 345b39297aeSTomoki Sekiyama return S_OK; 346b39297aeSTomoki Sekiyama } 347b39297aeSTomoki Sekiyama 348b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::CommitSnapshots(VSS_ID SnapshotSetId) 349b39297aeSTomoki Sekiyama { 350b39297aeSTomoki Sekiyama HRESULT hr = S_OK; 351b39297aeSTomoki Sekiyama HANDLE hEventFrozen, hEventThaw, hEventTimeout; 352b39297aeSTomoki Sekiyama 353b39297aeSTomoki Sekiyama hEventFrozen = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_FROZEN); 3544c1b8f1eSTomoki Sekiyama if (!hEventFrozen) { 355b39297aeSTomoki Sekiyama return E_FAIL; 356b39297aeSTomoki Sekiyama } 357b39297aeSTomoki Sekiyama 358b39297aeSTomoki Sekiyama hEventThaw = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_THAW); 3594c1b8f1eSTomoki Sekiyama if (!hEventThaw) { 360b39297aeSTomoki Sekiyama CloseHandle(hEventFrozen); 361b39297aeSTomoki Sekiyama return E_FAIL; 362b39297aeSTomoki Sekiyama } 363b39297aeSTomoki Sekiyama 364b39297aeSTomoki Sekiyama hEventTimeout = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_TIMEOUT); 3654c1b8f1eSTomoki Sekiyama if (!hEventTimeout) { 366b39297aeSTomoki Sekiyama CloseHandle(hEventFrozen); 367b39297aeSTomoki Sekiyama CloseHandle(hEventThaw); 368b39297aeSTomoki Sekiyama return E_FAIL; 369b39297aeSTomoki Sekiyama } 370b39297aeSTomoki Sekiyama 371b39297aeSTomoki Sekiyama /* Send event to qemu-ga to notify filesystem is frozen */ 372b39297aeSTomoki Sekiyama SetEvent(hEventFrozen); 373b39297aeSTomoki Sekiyama 374b39297aeSTomoki Sekiyama /* Wait until the snapshot is taken by the host. */ 375b39297aeSTomoki Sekiyama if (WaitForSingleObject(hEventThaw, VSS_TIMEOUT_MSEC) != WAIT_OBJECT_0) { 376b39297aeSTomoki Sekiyama /* Send event to qemu-ga to notify the provider is timed out */ 377b39297aeSTomoki Sekiyama SetEvent(hEventTimeout); 378b39297aeSTomoki Sekiyama hr = E_ABORT; 379b39297aeSTomoki Sekiyama } 380b39297aeSTomoki Sekiyama 381b39297aeSTomoki Sekiyama CloseHandle(hEventThaw); 382b39297aeSTomoki Sekiyama CloseHandle(hEventFrozen); 383b39297aeSTomoki Sekiyama CloseHandle(hEventTimeout); 384b39297aeSTomoki Sekiyama return hr; 385b39297aeSTomoki Sekiyama } 386b39297aeSTomoki Sekiyama 387b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::PostCommitSnapshots( 388b39297aeSTomoki Sekiyama VSS_ID SnapshotSetId, LONG lSnapshotsCount) 389b39297aeSTomoki Sekiyama { 390b39297aeSTomoki Sekiyama return S_OK; 391b39297aeSTomoki Sekiyama } 392b39297aeSTomoki Sekiyama 393b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::PreFinalCommitSnapshots(VSS_ID SnapshotSetId) 394b39297aeSTomoki Sekiyama { 395b39297aeSTomoki Sekiyama return S_OK; 396b39297aeSTomoki Sekiyama } 397b39297aeSTomoki Sekiyama 398b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::PostFinalCommitSnapshots(VSS_ID SnapshotSetId) 399b39297aeSTomoki Sekiyama { 400b39297aeSTomoki Sekiyama return S_OK; 401b39297aeSTomoki Sekiyama } 402b39297aeSTomoki Sekiyama 403b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::AbortSnapshots(VSS_ID SnapshotSetId) 404b39297aeSTomoki Sekiyama { 405b39297aeSTomoki Sekiyama return S_OK; 406b39297aeSTomoki Sekiyama } 407b39297aeSTomoki Sekiyama 408b39297aeSTomoki Sekiyama /* 409b39297aeSTomoki Sekiyama * IVssProviderNotifications methods 410b39297aeSTomoki Sekiyama */ 411b39297aeSTomoki Sekiyama 412b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::OnLoad(IUnknown *pCallback) 413b39297aeSTomoki Sekiyama { 414b39297aeSTomoki Sekiyama return S_OK; 415b39297aeSTomoki Sekiyama } 416b39297aeSTomoki Sekiyama 417b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProvider::OnUnload(BOOL bForceUnload) 418b39297aeSTomoki Sekiyama { 419b39297aeSTomoki Sekiyama return S_OK; 420b39297aeSTomoki Sekiyama } 421b39297aeSTomoki Sekiyama 422b39297aeSTomoki Sekiyama 423b39297aeSTomoki Sekiyama /* 424b39297aeSTomoki Sekiyama * CQGAVssProviderFactory class 425b39297aeSTomoki Sekiyama */ 426b39297aeSTomoki Sekiyama 427b39297aeSTomoki Sekiyama class CQGAVssProviderFactory : public IClassFactory 428b39297aeSTomoki Sekiyama { 429b39297aeSTomoki Sekiyama public: 430b39297aeSTomoki Sekiyama STDMETHODIMP QueryInterface(REFIID riid, void **ppv); 431b39297aeSTomoki Sekiyama STDMETHODIMP_(ULONG) AddRef(); 432b39297aeSTomoki Sekiyama STDMETHODIMP_(ULONG) Release(); 433b39297aeSTomoki Sekiyama STDMETHODIMP CreateInstance( 434b39297aeSTomoki Sekiyama IUnknown *pUnknownOuter, REFIID iid, void **ppv); 435b39297aeSTomoki Sekiyama STDMETHODIMP LockServer(BOOL lock) { return E_NOTIMPL; } 436b39297aeSTomoki Sekiyama 437b39297aeSTomoki Sekiyama CQGAVssProviderFactory(); 438b39297aeSTomoki Sekiyama ~CQGAVssProviderFactory(); 439b39297aeSTomoki Sekiyama 440b39297aeSTomoki Sekiyama private: 441b39297aeSTomoki Sekiyama long m_nRefCount; 442b39297aeSTomoki Sekiyama }; 443b39297aeSTomoki Sekiyama 444b39297aeSTomoki Sekiyama CQGAVssProviderFactory::CQGAVssProviderFactory() 445b39297aeSTomoki Sekiyama { 446b39297aeSTomoki Sekiyama m_nRefCount = 0; 447b39297aeSTomoki Sekiyama LockModule(TRUE); 448b39297aeSTomoki Sekiyama } 449b39297aeSTomoki Sekiyama 450b39297aeSTomoki Sekiyama CQGAVssProviderFactory::~CQGAVssProviderFactory() 451b39297aeSTomoki Sekiyama { 452b39297aeSTomoki Sekiyama LockModule(FALSE); 453b39297aeSTomoki Sekiyama } 454b39297aeSTomoki Sekiyama 455b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProviderFactory::QueryInterface(REFIID riid, void **ppv) 456b39297aeSTomoki Sekiyama { 457b39297aeSTomoki Sekiyama if (riid == IID_IUnknown || riid == IID_IClassFactory) { 458b39297aeSTomoki Sekiyama *ppv = static_cast<void*>(this); 459b39297aeSTomoki Sekiyama AddRef(); 460b39297aeSTomoki Sekiyama return S_OK; 461b39297aeSTomoki Sekiyama } 462b39297aeSTomoki Sekiyama *ppv = NULL; 463b39297aeSTomoki Sekiyama return E_NOINTERFACE; 464b39297aeSTomoki Sekiyama } 465b39297aeSTomoki Sekiyama 466b39297aeSTomoki Sekiyama STDMETHODIMP_(ULONG) CQGAVssProviderFactory::AddRef() 467b39297aeSTomoki Sekiyama { 468b39297aeSTomoki Sekiyama return InterlockedIncrement(&m_nRefCount); 469b39297aeSTomoki Sekiyama } 470b39297aeSTomoki Sekiyama 471b39297aeSTomoki Sekiyama STDMETHODIMP_(ULONG) CQGAVssProviderFactory::Release() 472b39297aeSTomoki Sekiyama { 473b39297aeSTomoki Sekiyama long nRefCount = InterlockedDecrement(&m_nRefCount); 474b39297aeSTomoki Sekiyama if (m_nRefCount == 0) { 475b39297aeSTomoki Sekiyama delete this; 476b39297aeSTomoki Sekiyama } 477b39297aeSTomoki Sekiyama return nRefCount; 478b39297aeSTomoki Sekiyama } 479b39297aeSTomoki Sekiyama 480b39297aeSTomoki Sekiyama STDMETHODIMP CQGAVssProviderFactory::CreateInstance( 481b39297aeSTomoki Sekiyama IUnknown *pUnknownOuter, REFIID iid, void **ppv) 482b39297aeSTomoki Sekiyama { 483b39297aeSTomoki Sekiyama CQGAVssProvider *pObj; 484b39297aeSTomoki Sekiyama 485b39297aeSTomoki Sekiyama if (pUnknownOuter) { 486b39297aeSTomoki Sekiyama return CLASS_E_NOAGGREGATION; 487b39297aeSTomoki Sekiyama } 488b39297aeSTomoki Sekiyama try { 489b39297aeSTomoki Sekiyama pObj = new CQGAVssProvider; 490b39297aeSTomoki Sekiyama } catch (...) { 491b39297aeSTomoki Sekiyama return E_OUTOFMEMORY; 492b39297aeSTomoki Sekiyama } 493b39297aeSTomoki Sekiyama HRESULT hr = pObj->QueryInterface(iid, ppv); 494b39297aeSTomoki Sekiyama if (FAILED(hr)) { 495b39297aeSTomoki Sekiyama delete pObj; 496b39297aeSTomoki Sekiyama } 497b39297aeSTomoki Sekiyama return hr; 498b39297aeSTomoki Sekiyama } 499b39297aeSTomoki Sekiyama 500b39297aeSTomoki Sekiyama 501b39297aeSTomoki Sekiyama /* 502b39297aeSTomoki Sekiyama * DLL functions 503b39297aeSTomoki Sekiyama */ 504b39297aeSTomoki Sekiyama 505b39297aeSTomoki Sekiyama STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) 506b39297aeSTomoki Sekiyama { 507b39297aeSTomoki Sekiyama CQGAVssProviderFactory *factory; 508b39297aeSTomoki Sekiyama try { 509b39297aeSTomoki Sekiyama factory = new CQGAVssProviderFactory; 510b39297aeSTomoki Sekiyama } catch (...) { 511b39297aeSTomoki Sekiyama return E_OUTOFMEMORY; 512b39297aeSTomoki Sekiyama } 513b39297aeSTomoki Sekiyama factory->AddRef(); 514b39297aeSTomoki Sekiyama HRESULT hr = factory->QueryInterface(riid, ppv); 515b39297aeSTomoki Sekiyama factory->Release(); 516b39297aeSTomoki Sekiyama return hr; 517b39297aeSTomoki Sekiyama } 518b39297aeSTomoki Sekiyama 519b39297aeSTomoki Sekiyama STDAPI DllCanUnloadNow() 520b39297aeSTomoki Sekiyama { 521b39297aeSTomoki Sekiyama return g_nComObjsInUse == 0 ? S_OK : S_FALSE; 522b39297aeSTomoki Sekiyama } 523b39297aeSTomoki Sekiyama 524b39297aeSTomoki Sekiyama EXTERN_C 525b39297aeSTomoki Sekiyama BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved) 526b39297aeSTomoki Sekiyama { 527b39297aeSTomoki Sekiyama if (dwReason == DLL_PROCESS_ATTACH) { 528b39297aeSTomoki Sekiyama g_hinstDll = hinstDll; 529b39297aeSTomoki Sekiyama DisableThreadLibraryCalls(hinstDll); 530b39297aeSTomoki Sekiyama } 531b39297aeSTomoki Sekiyama return TRUE; 532b39297aeSTomoki Sekiyama } 533