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