xref: /qemu/qga/vss-win32/provider.cpp (revision b39297aedfabe9b2c426cd540413be991500da25)
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