VirtualBox

source: vbox/trunk/src/VBox/Main/FloppyDriveImpl.cpp@ 3516

Last change on this file since 3516 was 3348, checked in by vboxsync, 18 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.8 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 "FloppyDriveImpl.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 (FloppyDrive)
34
35HRESULT FloppyDrive::FinalConstruct()
36{
37 return S_OK;
38}
39
40void FloppyDrive::FinalRelease()
41{
42 uninit();
43}
44
45// public initializer/uninitializer for internal purposes only
46/////////////////////////////////////////////////////////////////////////////
47
48/**
49 * Initializes the Floppy drive object.
50 *
51 * @param aParent Handle of the parent object.
52 */
53HRESULT FloppyDrive::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 Floppy drive object given another Floppy 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 FloppyDrive::init (Machine *aParent, FloppyDrive *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 guest object given another guest 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 FloppyDrive::initCopy (Machine *aParent, FloppyDrive *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 FloppyDrive::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// IFloppyDrive properties
161/////////////////////////////////////////////////////////////////////////////
162
163STDMETHODIMP FloppyDrive::COMGETTER(Enabled) (BOOL *aEnabled)
164{
165 if (!aEnabled)
166 return E_POINTER;
167
168 AutoCaller autoCaller (this);
169 CheckComRCReturnRC (autoCaller.rc());
170
171 AutoReaderLock alock (this);
172
173 *aEnabled = mData->mEnabled;
174
175 return S_OK;
176}
177
178STDMETHODIMP FloppyDrive::COMSETTER(Enabled) (BOOL aEnabled)
179{
180 LogFlowThisFunc (("aEnabled=%RTbool\n", aEnabled));
181
182 AutoCaller autoCaller (this);
183 CheckComRCReturnRC (autoCaller.rc());
184
185 /* the machine needs to be mutable */
186 Machine::AutoMutableStateDependency adep (mParent);
187 CheckComRCReturnRC (adep.rc());
188
189 AutoLock alock (this);
190
191 if (mData->mEnabled != aEnabled)
192 {
193 mData.backup();
194 mData->mEnabled = aEnabled;
195
196 /* leave the lock before informing callbacks */
197 alock.unlock();
198
199 mParent->onFloppyDriveChange();
200 }
201
202 return S_OK;
203}
204
205STDMETHODIMP FloppyDrive::COMGETTER(State) (DriveState_T *aDriveState)
206{
207 if (!aDriveState)
208 return E_POINTER;
209
210 AutoCaller autoCaller (this);
211 CheckComRCReturnRC (autoCaller.rc());
212
213 AutoReaderLock alock (this);
214
215 *aDriveState = mData->mDriveState;
216
217 return S_OK;
218}
219
220// IFloppyDrive methods
221/////////////////////////////////////////////////////////////////////////////
222
223STDMETHODIMP FloppyDrive::MountImage (INPTR GUIDPARAM aImageId)
224{
225 if (Guid::isEmpty (aImageId))
226 return E_INVALIDARG;
227
228 AutoCaller autoCaller (this);
229 CheckComRCReturnRC (autoCaller.rc());
230
231 /* the machine needs to be mutable */
232 Machine::AutoMutableStateDependency adep (mParent);
233 CheckComRCReturnRC (adep.rc());
234
235 AutoLock alock (this);
236
237 HRESULT rc = E_FAIL;
238
239 /* Our lifetime is bound to mParent's lifetime, so we don't add caller.
240 * We also don't lock mParent since its mParent field is const. */
241
242 ComPtr <IFloppyImage> image;
243 rc = mParent->virtualBox()->GetFloppyImage (aImageId, image.asOutParam());
244
245 if (SUCCEEDED (rc))
246 {
247 if (mData->mDriveState != DriveState_ImageMounted ||
248 !mData->mFloppyImage.equalsTo (image))
249 {
250 mData.backup();
251
252 unmount();
253
254 mData->mFloppyImage = image;
255 mData->mDriveState = DriveState_ImageMounted;
256
257 /* leave the lock before informing callbacks */
258 alock.unlock();
259
260 mParent->onFloppyDriveChange();
261 }
262 }
263
264 return rc;
265}
266
267STDMETHODIMP FloppyDrive::CaptureHostDrive (IHostFloppyDrive *aHostFloppyDrive)
268{
269 if (!aHostFloppyDrive)
270 return E_INVALIDARG;
271
272 AutoCaller autoCaller (this);
273 CheckComRCReturnRC (autoCaller.rc());
274
275 /* the machine needs to be mutable */
276 Machine::AutoMutableStateDependency adep (mParent);
277 CheckComRCReturnRC (adep.rc());
278
279 AutoLock alock (this);
280
281 if (mData->mDriveState != DriveState_HostDriveCaptured ||
282 !mData->mHostDrive.equalsTo (aHostFloppyDrive))
283 {
284 mData.backup();
285
286 unmount();
287
288 mData->mHostDrive = aHostFloppyDrive;
289 mData->mDriveState = DriveState_HostDriveCaptured;
290
291 /* leave the lock before informing callbacks */
292 alock.unlock();
293
294 mParent->onFloppyDriveChange();
295 }
296
297 return S_OK;
298}
299
300STDMETHODIMP FloppyDrive::Unmount()
301{
302 AutoCaller autoCaller (this);
303 CheckComRCReturnRC (autoCaller.rc());
304
305 /* the machine needs to be mutable */
306 Machine::AutoMutableStateDependency adep (mParent);
307 CheckComRCReturnRC (adep.rc());
308
309 AutoLock alock (this);
310
311 if (mData->mDriveState != DriveState_NotMounted)
312 {
313 mData.backup();
314
315 unmount();
316
317 mData->mDriveState = DriveState_NotMounted;
318
319 /* leave the lock before informing callbacks */
320 alock.unlock();
321
322 mParent->onFloppyDriveChange();
323 }
324
325 return S_OK;
326}
327
328STDMETHODIMP FloppyDrive::GetImage (IFloppyImage **aFloppyImage)
329{
330 if (!aFloppyImage)
331 return E_POINTER;
332
333 AutoCaller autoCaller (this);
334 CheckComRCReturnRC (autoCaller.rc());
335
336 AutoReaderLock alock (this);
337
338 mData->mFloppyImage.queryInterfaceTo (aFloppyImage);
339
340 return S_OK;
341}
342
343STDMETHODIMP FloppyDrive::GetHostDrive (IHostFloppyDrive **aHostDrive)
344{
345 if (!aHostDrive)
346 return E_POINTER;
347
348 AutoCaller autoCaller (this);
349 CheckComRCReturnRC (autoCaller.rc());
350
351 AutoReaderLock alock (this);
352
353 mData->mHostDrive.queryInterfaceTo (aHostDrive);
354
355 return S_OK;
356}
357
358// public methods only for internal purposes
359/////////////////////////////////////////////////////////////////////////////
360
361/**
362 * @note Locks this object for writing.
363 */
364bool FloppyDrive::rollback()
365{
366 /* sanity */
367 AutoCaller autoCaller (this);
368 AssertComRCReturn (autoCaller.rc(), false);
369
370 AutoLock alock (this);
371
372 bool changed = false;
373
374 if (mData.isBackedUp())
375 {
376 /* we need to check all data to see whether anything will be changed
377 * after rollback */
378 changed = mData.hasActualChanges();
379 mData.rollback();
380 }
381
382 return changed;
383}
384
385/**
386 * @note Locks this object for writing, together with the peer object (also
387 * for writing) if there is one.
388 */
389void FloppyDrive::commit()
390{
391 /* sanity */
392 AutoCaller autoCaller (this);
393 AssertComRCReturnVoid (autoCaller.rc());
394
395 /* sanity too */
396 AutoCaller thatCaller (mPeer);
397 AssertComRCReturnVoid (thatCaller.rc());
398
399 /* lock both for writing since we modify both */
400 AutoMultiLock <2> alock (this->wlock(), AutoLock::maybeWlock (mPeer));
401
402 if (mData.isBackedUp())
403 {
404 mData.commit();
405 if (mPeer)
406 {
407 /* attach new data to the peer and reshare it */
408 mPeer->mData.attach (mData);
409 }
410 }
411}
412
413/**
414 * @note Locks this object for writing, together with the peer object (locked
415 * for reading) if there is one.
416 */
417void FloppyDrive::copyFrom (FloppyDrive *aThat)
418{
419 /* sanity */
420 AutoCaller autoCaller (this);
421 AssertComRCReturnVoid (autoCaller.rc());
422
423 /* sanity too */
424 AutoCaller thatCaller (mPeer);
425 AssertComRCReturnVoid (thatCaller.rc());
426
427 /* peer is not modified, lock it for reading */
428 AutoMultiLock <2> alock (this->wlock(), AutoLock::maybeRlock (mPeer));
429
430 /* this will back up current data */
431 mData.assignCopy (aThat->mData);
432}
433
434// private methods
435/////////////////////////////////////////////////////////////////////////////
436
437/**
438 * Helper to unmount a drive.
439 *
440 * @return COM status code
441 */
442HRESULT FloppyDrive::unmount()
443{
444 AssertReturn (isLockedOnCurrentThread(), E_FAIL);
445
446 if (mData->mFloppyImage)
447 mData->mFloppyImage.setNull();
448 if (mData->mHostDrive)
449 mData->mHostDrive.setNull();
450
451 return S_OK;
452}
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