VirtualBox

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

Last change on this file since 3829 was 3348, checked in by vboxsync, 17 years ago

Main: Converted AudioAdapter and NetworkAdapter 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 the parent object.
52 */
53HRESULT DVDDrive::init (Machine *aParent)
54{
55 LogFlowThisFunc (("aParent=%p\n", aParent));
56
57 ComAssertRet (aParent, E_INVALIDARG);
58
59 /* Enclose the state transition NotReady->InInit->Ready */
60 AutoInitSpan autoInitSpan (this);
61 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
62
63 unconst (mParent) = aParent;
64 /* mPeer is left null */
65
66 mData.allocate();
67
68 /* Confirm a successful initialization */
69 autoInitSpan.setSucceeded();
70
71 return S_OK;
72}
73
74/**
75 * Initializes the DVD drive object given another DVD drive object
76 * (a kind of copy constructor). This object shares data with
77 * the object passed as an argument.
78 *
79 * @note This object must be destroyed before the original object
80 * it shares data with is destroyed.
81 *
82 * @note Locks @a aThat object for reading.
83 */
84HRESULT DVDDrive::init (Machine *aParent, DVDDrive *aThat)
85{
86 LogFlowThisFunc (("aParent=%p, aThat=%p\n", aParent, aThat));
87
88 ComAssertRet (aParent && aThat, E_INVALIDARG);
89
90 /* Enclose the state transition NotReady->InInit->Ready */
91 AutoInitSpan autoInitSpan (this);
92 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
93
94 unconst (mParent) = aParent;
95 unconst (mPeer) = aThat;
96
97 AutoCaller thatCaller (aThat);
98 AssertComRCReturnRC (thatCaller.rc());
99
100 AutoReaderLock thatLock (aThat);
101 mData.share (aThat->mData);
102
103 /* Confirm a successful initialization */
104 autoInitSpan.setSucceeded();
105
106 return S_OK;
107}
108
109/**
110 * Initializes the DVD drive object given another DVD drive object
111 * (a kind of copy constructor). This object makes a private copy of data
112 * of the original object passed as an argument.
113 *
114 * @note Locks @a aThat object for reading.
115 */
116HRESULT DVDDrive::initCopy (Machine *aParent, DVDDrive *aThat)
117{
118 LogFlowThisFunc (("aParent=%p, aThat=%p\n", aParent, aThat));
119
120 ComAssertRet (aParent && aThat, E_INVALIDARG);
121
122 /* Enclose the state transition NotReady->InInit->Ready */
123 AutoInitSpan autoInitSpan (this);
124 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
125
126 unconst (mParent) = aParent;
127 /* mPeer is left null */
128
129 AutoCaller thatCaller (aThat);
130 AssertComRCReturnRC (thatCaller.rc());
131
132 AutoReaderLock thatLock (aThat);
133 mData.attachCopy (aThat->mData);
134
135 /* Confirm a successful initialization */
136 autoInitSpan.setSucceeded();
137
138 return S_OK;
139}
140
141/**
142 * Uninitializes the instance and sets the ready flag to FALSE.
143 * Called either from FinalRelease() or by the parent when it gets destroyed.
144 */
145void DVDDrive::uninit()
146{
147 LogFlowThisFunc (("\n"));
148
149 /* Enclose the state transition Ready->InUninit->NotReady */
150 AutoUninitSpan autoUninitSpan (this);
151 if (autoUninitSpan.uninitDone())
152 return;
153
154 mData.free();
155
156 unconst (mPeer).setNull();
157 unconst (mParent).setNull();
158}
159
160// IDVDDrive properties
161////////////////////////////////////////////////////////////////////////////////
162
163STDMETHODIMP DVDDrive::COMGETTER(State) (DriveState_T *aDriveState)
164{
165 if (!aDriveState)
166 return E_POINTER;
167
168 AutoCaller autoCaller (this);
169 CheckComRCReturnRC (autoCaller.rc());
170
171 AutoReaderLock alock (this);
172
173 *aDriveState = mData->mDriveState;
174
175 return S_OK;
176}
177
178STDMETHODIMP DVDDrive::COMGETTER(Passthrough) (BOOL *aPassthrough)
179{
180 if (!aPassthrough)
181 return E_POINTER;
182
183 AutoCaller autoCaller (this);
184 CheckComRCReturnRC (autoCaller.rc());
185
186 AutoReaderLock alock (this);
187
188 *aPassthrough = mData->mPassthrough;
189
190 return S_OK;
191}
192
193STDMETHODIMP DVDDrive::COMSETTER(Passthrough) (BOOL aPassthrough)
194{
195 AutoCaller autoCaller (this);
196 CheckComRCReturnRC (autoCaller.rc());
197
198 /* the machine needs to be mutable */
199 Machine::AutoMutableStateDependency adep (mParent);
200 CheckComRCReturnRC (adep.rc());
201
202 AutoLock alock (this);
203
204 if (mData->mPassthrough != aPassthrough)
205 {
206 mData.backup();
207 mData->mPassthrough = aPassthrough;
208 }
209
210 return S_OK;
211}
212
213// IDVDDrive methods
214////////////////////////////////////////////////////////////////////////////////
215
216STDMETHODIMP DVDDrive::MountImage (INPTR GUIDPARAM aImageId)
217{
218 if (Guid::isEmpty (aImageId))
219 return E_INVALIDARG;
220
221 AutoCaller autoCaller (this);
222 CheckComRCReturnRC (autoCaller.rc());
223
224 /* the machine needs to be mutable */
225 Machine::AutoMutableStateDependency adep (mParent);
226 CheckComRCReturnRC (adep.rc());
227
228 AutoLock alock (this);
229
230 HRESULT rc = E_FAIL;
231
232 /* Our lifetime is bound to mParent's lifetime, so we don't add caller.
233 * We also don't lock mParent since its mParent field is const. */
234
235 ComPtr <IDVDImage> image;
236 rc = mParent->virtualBox()->GetDVDImage (aImageId, image.asOutParam());
237
238 if (SUCCEEDED (rc))
239 {
240 if (mData->mDriveState != DriveState_ImageMounted ||
241 !mData->mDVDImage.equalsTo (image))
242 {
243 mData.backup();
244
245 unmount();
246
247 mData->mDVDImage = image;
248 mData->mDriveState = DriveState_ImageMounted;
249
250 /* leave the lock before informing callbacks */
251 alock.unlock();
252
253 mParent->onDVDDriveChange();
254 }
255 }
256
257 return rc;
258}
259
260STDMETHODIMP DVDDrive::CaptureHostDrive (IHostDVDDrive *aHostDVDDrive)
261{
262 if (!aHostDVDDrive)
263 return E_INVALIDARG;
264
265 AutoCaller autoCaller (this);
266 CheckComRCReturnRC (autoCaller.rc());
267
268 /* the machine needs to be mutable */
269 Machine::AutoMutableStateDependency adep (mParent);
270 CheckComRCReturnRC (adep.rc());
271
272 AutoLock alock (this);
273
274 if (mData->mDriveState != DriveState_HostDriveCaptured ||
275 !mData->mHostDrive.equalsTo (aHostDVDDrive))
276 {
277 mData.backup();
278
279 unmount();
280
281 mData->mHostDrive = aHostDVDDrive;
282 mData->mDriveState = DriveState_HostDriveCaptured;
283
284 /* leave the lock before informing callbacks */
285 alock.unlock();
286
287 mParent->onDVDDriveChange();
288 }
289
290 return S_OK;
291}
292
293STDMETHODIMP DVDDrive::Unmount()
294{
295 AutoCaller autoCaller (this);
296 CheckComRCReturnRC (autoCaller.rc());
297
298 /* the machine needs to be mutable */
299 Machine::AutoMutableStateDependency adep (mParent);
300 CheckComRCReturnRC (adep.rc());
301
302 AutoLock alock (this);
303
304 if (mData->mDriveState != DriveState_NotMounted)
305 {
306 mData.backup();
307
308 unmount();
309
310 mData->mDriveState = DriveState_NotMounted;
311
312 /* leave the lock before informing callbacks */
313 alock.unlock();
314
315 mParent->onDVDDriveChange();
316 }
317
318 return S_OK;
319}
320
321STDMETHODIMP DVDDrive::GetImage (IDVDImage **aDVDImage)
322{
323 if (!aDVDImage)
324 return E_POINTER;
325
326 AutoCaller autoCaller (this);
327 CheckComRCReturnRC (autoCaller.rc());
328
329 AutoReaderLock alock (this);
330
331 mData->mDVDImage.queryInterfaceTo (aDVDImage);
332
333 return S_OK;
334}
335
336STDMETHODIMP DVDDrive::GetHostDrive(IHostDVDDrive **aHostDrive)
337{
338 if (!aHostDrive)
339 return E_POINTER;
340
341 AutoCaller autoCaller (this);
342 CheckComRCReturnRC (autoCaller.rc());
343
344 AutoReaderLock alock (this);
345
346 mData->mHostDrive.queryInterfaceTo (aHostDrive);
347
348 return S_OK;
349}
350
351// public methods only for internal purposes
352////////////////////////////////////////////////////////////////////////////////
353
354/**
355 * @note Locks this object for writing.
356 */
357bool DVDDrive::rollback()
358{
359 /* sanity */
360 AutoCaller autoCaller (this);
361 AssertComRCReturn (autoCaller.rc(), false);
362
363 AutoLock alock (this);
364
365 bool changed = false;
366
367 if (mData.isBackedUp())
368 {
369 /* we need to check all data to see whether anything will be changed
370 * after rollback */
371 changed = mData.hasActualChanges();
372 mData.rollback();
373 }
374
375 return changed;
376}
377
378/**
379 * @note Locks this object for writing, together with the peer object (also
380 * for writing) if there is one.
381 */
382void DVDDrive::commit()
383{
384 /* sanity */
385 AutoCaller autoCaller (this);
386 AssertComRCReturnVoid (autoCaller.rc());
387
388 /* sanity too */
389 AutoCaller thatCaller (mPeer);
390 AssertComRCReturnVoid (thatCaller.rc());
391
392 /* lock both for writing since we modify both */
393 AutoMultiLock <2> alock (this->wlock(), AutoLock::maybeWlock (mPeer));
394
395 if (mData.isBackedUp())
396 {
397 mData.commit();
398 if (mPeer)
399 {
400 /* attach new data to the peer and reshare it */
401 mPeer->mData.attach (mData);
402 }
403 }
404}
405
406/**
407 * @note Locks this object for writing, together with the peer object
408 * represented by @a aThat (locked for reading).
409 */
410void DVDDrive::copyFrom (DVDDrive *aThat)
411{
412 AssertReturnVoid (aThat != NULL);
413
414 /* sanity */
415 AutoCaller autoCaller (this);
416 AssertComRCReturnVoid (autoCaller.rc());
417
418 /* sanity too */
419 AutoCaller thatCaller (mPeer);
420 AssertComRCReturnVoid (thatCaller.rc());
421
422 /* peer is not modified, lock it for reading */
423 AutoMultiLock <2> alock (this->wlock(), aThat->rlock());
424
425 /* this will back up current data */
426 mData.assignCopy (aThat->mData);
427}
428
429// private methods
430////////////////////////////////////////////////////////////////////////////////
431
432/**
433 * Helper to unmount a drive.
434 *
435 * @return COM status code
436 *
437 */
438HRESULT DVDDrive::unmount()
439{
440 AssertReturn (isLockedOnCurrentThread(), E_FAIL);
441
442 if (mData->mDVDImage)
443 mData->mDVDImage.setNull();
444 if (mData->mHostDrive)
445 mData->mHostDrive.setNull();
446
447 return S_OK;
448}
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