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