VirtualBox

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

Last change on this file since 4663 was 4071, checked in by vboxsync, 17 years ago

Biggest check-in ever. New source code headers for all (C) innotek files.

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