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