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