VirtualBox

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

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