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