VirtualBox

source: vbox/trunk/src/VBox/Main/DVDDriveImpl.cpp@ 3340

Last change on this file since 3340 was 3330, checked in by vboxsync, 18 years ago

Main: Converted DVDDrive and FloppyDrive to the new locking scheme.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/** @file
2 *
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22#include "DVDDriveImpl.h"
23#include "MachineImpl.h"
24#include "VirtualBoxImpl.h"
25#include "Logging.h"
26
27#include <iprt/string.h>
28#include <iprt/cpputils.h>
29
30// constructor / destructor
31////////////////////////////////////////////////////////////////////////////////
32
33DEFINE_EMPTY_CTOR_DTOR (DVDDrive)
34
35HRESULT DVDDrive::FinalConstruct()
36{
37 return S_OK;
38}
39
40void DVDDrive::FinalRelease()
41{
42 uninit();
43}
44
45// public initializer/uninitializer for internal purposes only
46////////////////////////////////////////////////////////////////////////////////
47
48/**
49 * Initializes the DVD drive object.
50 *
51 * @param aParent Handle of our parent object.
52 * @return COM result indicator
53 */
54HRESULT DVDDrive::init (Machine *aParent)
55{
56 LogFlowThisFunc (("aParent=%p\n", aParent));
57
58 ComAssertRet (aParent, E_INVALIDARG);
59
60 /* Enclose the state transition NotReady->InInit->Ready */
61 AutoInitSpan autoInitSpan (this);
62 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
63
64 unconst (mParent) = aParent;
65 /* mPeer is left null */
66
67 mData.allocate();
68
69 /* Confirm a successful initialization */
70 autoInitSpan.setSucceeded();
71
72 return S_OK;
73}
74
75/**
76 * Initializes the DVD drive object given another DVD drive object
77 * (a kind of copy constructor). This object shares data with
78 * the object passed as an argument.
79 *
80 * @note This object must be destroyed before the original object
81 * it shares data with is destroyed.
82 *
83 * @note Locks @a aThat object for reading.
84 */
85HRESULT DVDDrive::init (Machine *aParent, DVDDrive *aThat)
86{
87 LogFlowThisFunc (("aParent=%p, aThat=%p\n", aParent, aThat));
88
89 ComAssertRet (aParent && aThat, E_INVALIDARG);
90
91 /* Enclose the state transition NotReady->InInit->Ready */
92 AutoInitSpan autoInitSpan (this);
93 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
94
95 unconst (mParent) = aParent;
96 unconst (mPeer) = aThat;
97
98 AutoCaller thatCaller (aThat);
99 AssertComRCReturnRC (thatCaller.rc());
100
101 AutoReaderLock thatLock (aThat);
102 mData.share (aThat->mData);
103
104 /* Confirm a successful initialization */
105 autoInitSpan.setSucceeded();
106
107 return S_OK;
108}
109
110/**
111 * Initializes the DVD drive object given another DVD drive object
112 * (a kind of copy constructor). This object makes a private copy of data
113 * of the original object passed as an argument.
114 *
115 * @note Locks @a aThat object for reading.
116 */
117HRESULT DVDDrive::initCopy (Machine *aParent, DVDDrive *aThat)
118{
119 LogFlowThisFunc (("aParent=%p, aThat=%p\n", aParent, aThat));
120
121 ComAssertRet (aParent && aThat, E_INVALIDARG);
122
123 /* Enclose the state transition NotReady->InInit->Ready */
124 AutoInitSpan autoInitSpan (this);
125 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
126
127 unconst (mParent) = aParent;
128 /* mPeer is left null */
129
130 AutoCaller thatCaller (aThat);
131 AssertComRCReturnRC (thatCaller.rc());
132
133 AutoReaderLock thatLock (aThat);
134 mData.attachCopy (aThat->mData);
135
136 /* Confirm a successful initialization */
137 autoInitSpan.setSucceeded();
138
139 return S_OK;
140}
141
142/**
143 * Uninitializes the instance and sets the ready flag to FALSE.
144 * Called either from FinalRelease() or by the parent when it gets destroyed.
145 */
146void DVDDrive::uninit()
147{
148 LogFlowThisFunc (("\n"));
149
150 /* Enclose the state transition Ready->InUninit->NotReady */
151 AutoUninitSpan autoUninitSpan (this);
152 if (autoUninitSpan.uninitDone())
153 return;
154
155 mData.free();
156
157 unconst (mParent).setNull();
158 unconst (mParent).setNull();
159}
160
161// IDVDDrive properties
162////////////////////////////////////////////////////////////////////////////////
163
164STDMETHODIMP DVDDrive::COMGETTER(State) (DriveState_T *aDriveState)
165{
166 if (!aDriveState)
167 return E_POINTER;
168
169 AutoCaller autoCaller (this);
170 CheckComRCReturnRC (autoCaller.rc());
171
172 AutoReaderLock alock (this);
173
174 *aDriveState = mData->mDriveState;
175
176 return S_OK;
177}
178
179STDMETHODIMP DVDDrive::COMGETTER(Passthrough) (BOOL *aPassthrough)
180{
181 if (!aPassthrough)
182 return E_POINTER;
183
184 AutoCaller autoCaller (this);
185 CheckComRCReturnRC (autoCaller.rc());
186
187 AutoReaderLock alock (this);
188
189 *aPassthrough = mData->mPassthrough;
190
191 return S_OK;
192}
193
194STDMETHODIMP DVDDrive::COMSETTER(Passthrough) (BOOL aPassthrough)
195{
196 AutoCaller autoCaller (this);
197 CheckComRCReturnRC (autoCaller.rc());
198
199 /* the machine needs to be mutable */
200 Machine::AutoMutableStateDependency adep (mParent);
201 CheckComRCReturnRC (adep.rc());
202
203 AutoLock alock (this);
204
205 if (mData->mPassthrough != aPassthrough)
206 {
207 mData.backup();
208 mData->mPassthrough = aPassthrough;
209 }
210
211 return S_OK;
212}
213
214// IDVDDrive methods
215////////////////////////////////////////////////////////////////////////////////
216
217STDMETHODIMP DVDDrive::MountImage (INPTR GUIDPARAM aImageId)
218{
219 if (Guid::isEmpty (aImageId))
220 return E_INVALIDARG;
221
222 AutoCaller autoCaller (this);
223 CheckComRCReturnRC (autoCaller.rc());
224
225 /* the machine needs to be mutable */
226 Machine::AutoMutableStateDependency adep (mParent);
227 CheckComRCReturnRC (adep.rc());
228
229 AutoLock alock (this);
230
231 HRESULT rc = E_FAIL;
232
233 /* Our lifetime is bound to mParent's lifetime, so we don't add caller.
234 * We also don't lock mParent since its mParent field is const. */
235
236 ComPtr <IDVDImage> image;
237 rc = mParent->virtualBox()->GetDVDImage (aImageId, image.asOutParam());
238
239 if (SUCCEEDED (rc))
240 {
241 if (mData->mDriveState != DriveState_ImageMounted ||
242 !mData->mDVDImage.equalsTo (image))
243 {
244 mData.backup();
245
246 unmount();
247
248 mData->mDVDImage = image;
249 mData->mDriveState = DriveState_ImageMounted;
250
251 /* leave the lock before informing callbacks*/
252 alock.unlock();
253
254 mParent->onDVDDriveChange();
255 }
256 }
257
258 return rc;
259}
260
261STDMETHODIMP DVDDrive::CaptureHostDrive (IHostDVDDrive *aHostDVDDrive)
262{
263 if (!aHostDVDDrive)
264 return E_INVALIDARG;
265
266 AutoCaller autoCaller (this);
267 CheckComRCReturnRC (autoCaller.rc());
268
269 /* the machine needs to be mutable */
270 Machine::AutoMutableStateDependency adep (mParent);
271 CheckComRCReturnRC (adep.rc());
272
273 AutoLock alock (this);
274
275 if (mData->mDriveState != DriveState_HostDriveCaptured ||
276 !mData->mHostDrive.equalsTo (aHostDVDDrive))
277 {
278 mData.backup();
279
280 unmount();
281
282 mData->mHostDrive = aHostDVDDrive;
283 mData->mDriveState = DriveState_HostDriveCaptured;
284
285 /* leave the lock before informing callbacks*/
286 alock.unlock();
287
288 mParent->onDVDDriveChange();
289 }
290
291 return S_OK;
292}
293
294STDMETHODIMP DVDDrive::Unmount()
295{
296 AutoCaller autoCaller (this);
297 CheckComRCReturnRC (autoCaller.rc());
298
299 /* the machine needs to be mutable */
300 Machine::AutoMutableStateDependency adep (mParent);
301 CheckComRCReturnRC (adep.rc());
302
303 AutoLock alock (this);
304
305 if (mData->mDriveState != DriveState_NotMounted)
306 {
307 mData.backup();
308
309 unmount();
310
311 mData->mDriveState = DriveState_NotMounted;
312
313 /* leave the lock before informing callbacks*/
314 alock.unlock();
315
316 mParent->onDVDDriveChange();
317 }
318
319 return S_OK;
320}
321
322STDMETHODIMP DVDDrive::GetImage (IDVDImage **aDVDImage)
323{
324 if (!aDVDImage)
325 return E_POINTER;
326
327 AutoCaller autoCaller (this);
328 CheckComRCReturnRC (autoCaller.rc());
329
330 AutoReaderLock alock (this);
331
332 mData->mDVDImage.queryInterfaceTo (aDVDImage);
333
334 return S_OK;
335}
336
337STDMETHODIMP DVDDrive::GetHostDrive(IHostDVDDrive **aHostDrive)
338{
339 if (!aHostDrive)
340 return E_POINTER;
341
342 AutoCaller autoCaller (this);
343 CheckComRCReturnRC (autoCaller.rc());
344
345 AutoReaderLock alock (this);
346
347 mData->mHostDrive.queryInterfaceTo (aHostDrive);
348
349 return S_OK;
350}
351
352// public methods only for internal purposes
353////////////////////////////////////////////////////////////////////////////////
354
355/**
356 * @note Locks this object for writing.
357 */
358bool DVDDrive::rollback()
359{
360 /* sanity */
361 AutoCaller autoCaller (this);
362 AssertComRCReturn (autoCaller.rc(), false);
363
364 AutoLock alock (this);
365
366 bool changed = false;
367
368 if (mData.isBackedUp())
369 {
370 /* we need to check all data to see whether anything will be changed
371 * after rollback */
372 changed = mData.hasActualChanges();
373 mData.rollback();
374 }
375
376 return changed;
377}
378
379/**
380 * @note Locks this object for writing, together with the peer object (also
381 * for writing) if there is one.
382 */
383void DVDDrive::commit()
384{
385 /* sanity */
386 AutoCaller autoCaller (this);
387 AssertComRCReturnVoid (autoCaller.rc());
388
389 /* sanity too */
390 AutoCaller thatCaller (mPeer);
391 AssertComRCReturnVoid (thatCaller.rc());
392
393 /* lock both for writing since we modify both */
394 AutoMultiLock <2> alock (this->wlock(), AutoLock::maybeWlock (mPeer));
395
396 if (mData.isBackedUp())
397 {
398 mData.commit();
399 if (mPeer)
400 {
401 /* attach new data to the peer and reshare it */
402 mPeer->mData.attach (mData);
403 }
404 }
405}
406
407/**
408 * @note Locks this object for writing, together with the peer object (locked
409 * for reading) if there is one.
410 */
411void DVDDrive::copyFrom (DVDDrive *aThat)
412{
413 /* sanity */
414 AutoCaller autoCaller (this);
415 AssertComRCReturnVoid (autoCaller.rc());
416
417 /* sanity too */
418 AutoCaller thatCaller (mPeer);
419 AssertComRCReturnVoid (thatCaller.rc());
420
421 /* peer is not modified, lock it for reading */
422 AutoMultiLock <2> alock (this->wlock(), AutoLock::maybeRlock (mPeer));
423
424 /* this will back up current data */
425 mData.assignCopy (aThat->mData);
426}
427
428// private methods
429////////////////////////////////////////////////////////////////////////////////
430
431/**
432 * Helper to unmount a drive.
433 *
434 * @return COM status code
435 *
436 */
437HRESULT DVDDrive::unmount()
438{
439 AssertReturn (isLockedOnCurrentThread(), E_FAIL);
440
441 if (mData->mDVDImage)
442 mData->mDVDImage.setNull();
443 if (mData->mHostDrive)
444 mData->mHostDrive.setNull();
445
446 return S_OK;
447}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette