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