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