VirtualBox

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

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

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