3
* VirtualBox COM class implementation
7
* Copyright (C) 2006-2009 Oracle Corporation
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 (GPL) as published by the Free Software
13
* Foundation, in version 2 as it comes in the "COPYING" file of the
14
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18
#include "MediumAttachmentImpl.h"
19
#include "MachineImpl.h"
20
#include "MediumImpl.h"
23
#include "AutoCaller.h"
26
////////////////////////////////////////////////////////////////////////////////
28
// private member data definition
30
////////////////////////////////////////////////////////////////////////////////
32
struct BackupableMediumAttachmentData
34
BackupableMediumAttachmentData()
37
type(DeviceType_Null),
42
ComObjPtr<Medium> pMedium;
43
/* Since MediumAttachment is not a first class citizen when it
44
* comes to managing settings, having a reference to the storage
45
* controller will not work - when settings are changed it will point
46
* to the old, uninitialized instance. Changing this requires
47
* substantial changes to MediumImpl.cpp. */
48
const Bstr bstrControllerName;
51
const DeviceType_T type;
52
bool fPassthrough : 1;
56
struct MediumAttachment::Data
62
/** Reference to Machine object, for checking mutable state. */
63
Machine * const pMachine;
64
/* later: const ComObjPtr<MediumAttachment> mPeer; */
66
Backupable<BackupableMediumAttachmentData> bd;
69
// constructor / destructor
70
/////////////////////////////////////////////////////////////////////////////
72
HRESULT MediumAttachment::FinalConstruct()
74
LogFlowThisFunc(("\n"));
78
void MediumAttachment::FinalRelease()
80
LogFlowThisFuncEnter();
82
LogFlowThisFuncLeave();
85
// public initializer/uninitializer for internal purposes only
86
/////////////////////////////////////////////////////////////////////////////
89
* Initializes the medium attachment object.
91
* @param aParent Machine object.
92
* @param aMedium Medium object.
93
* @param aController Controller the hard disk is attached to.
94
* @param aPort Port number.
95
* @param aDevice Device number on the port.
96
* @param aPassthrough Wether accesses are directly passed to the host drive.
98
HRESULT MediumAttachment::init(Machine *aParent,
100
const Bstr &aControllerName,
106
LogFlowThisFuncEnter();
107
LogFlowThisFunc(("aParent=%p aMedium=%p aControllerName=%ls aPort=%d aDevice=%d aType=%d aPassthrough=%d\n", aParent, aMedium, aControllerName.raw(), aPort, aDevice, aType, aPassthrough));
109
if (aType == DeviceType_HardDisk)
110
AssertReturn(aMedium, E_INVALIDARG);
112
/* Enclose the state transition NotReady->InInit->Ready */
113
AutoInitSpan autoInitSpan(this);
114
AssertReturn(autoInitSpan.isOk(), E_FAIL);
118
unconst(m->pMachine) = aParent;
121
m->bd->pMedium = aMedium;
122
unconst(m->bd->bstrControllerName) = aControllerName;
123
unconst(m->bd->lPort) = aPort;
124
unconst(m->bd->lDevice) = aDevice;
125
unconst(m->bd->type) = aType;
127
m->bd->fPassthrough = aPassthrough;
128
/* Newly created attachments never have an implicitly created medium
129
* associated with them. Implicit diff image creation happens later. */
130
m->bd->fImplicit = false;
132
/* Confirm a successful initialization when it's the case */
133
autoInitSpan.setSucceeded();
135
/* Construct a short log name for this attachment. */
136
Utf8Str ctlName(aControllerName);
137
const char *psz = strpbrk(ctlName.c_str(), " \t:-");
138
mLogName = Utf8StrFmt("MA%p[%.*s:%u:%u:%s%s]",
140
psz ? psz - ctlName.c_str() : 4, ctlName.c_str(),
141
aPort, aDevice, Global::stringifyDeviceType(aType),
142
m->bd->fImplicit ? ":I" : "");
144
LogFlowThisFunc(("LEAVE - %s\n", getLogName()));
149
* Uninitializes the instance.
150
* Called from FinalRelease().
152
void MediumAttachment::uninit()
154
LogFlowThisFunc(("ENTER - %s\n", getLogName()));
156
/* Enclose the state transition Ready->InUninit->NotReady */
157
AutoUninitSpan autoUninitSpan(this);
158
if (autoUninitSpan.uninitDone())
163
unconst(m->pMachine) = NULL;
168
LogFlowThisFuncLeave();
171
// IHardDiskAttachment properties
172
/////////////////////////////////////////////////////////////////////////////
174
STDMETHODIMP MediumAttachment::COMGETTER(Medium)(IMedium **aHardDisk)
176
LogFlowThisFuncEnter();
178
CheckComArgOutPointerValid(aHardDisk);
180
AutoCaller autoCaller(this);
181
if (FAILED(autoCaller.rc())) return autoCaller.rc();
183
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
185
m->bd->pMedium.queryInterfaceTo(aHardDisk);
187
LogFlowThisFuncLeave();
191
STDMETHODIMP MediumAttachment::COMGETTER(Controller)(BSTR *aController)
193
LogFlowThisFuncEnter();
195
CheckComArgOutPointerValid(aController);
197
AutoCaller autoCaller(this);
198
if (FAILED(autoCaller.rc())) return autoCaller.rc();
200
/* m->controller is constant during life time, no need to lock */
201
m->bd->bstrControllerName.cloneTo(aController);
203
LogFlowThisFuncLeave();
207
STDMETHODIMP MediumAttachment::COMGETTER(Port)(LONG *aPort)
209
LogFlowThisFuncEnter();
211
CheckComArgOutPointerValid(aPort);
213
AutoCaller autoCaller(this);
214
if (FAILED(autoCaller.rc())) return autoCaller.rc();
216
/* m->bd->port is constant during life time, no need to lock */
217
*aPort = m->bd->lPort;
219
LogFlowThisFuncLeave();
223
STDMETHODIMP MediumAttachment::COMGETTER(Device)(LONG *aDevice)
225
LogFlowThisFuncEnter();
227
CheckComArgOutPointerValid(aDevice);
229
AutoCaller autoCaller(this);
230
if (FAILED(autoCaller.rc())) return autoCaller.rc();
232
/* m->bd->device is constant during life time, no need to lock */
233
*aDevice = m->bd->lDevice;
235
LogFlowThisFuncLeave();
239
STDMETHODIMP MediumAttachment::COMGETTER(Type)(DeviceType_T *aType)
241
LogFlowThisFuncEnter();
243
CheckComArgOutPointerValid(aType);
245
AutoCaller autoCaller(this);
246
if (FAILED(autoCaller.rc())) return autoCaller.rc();
248
/* m->bd->type is constant during life time, no need to lock */
249
*aType = m->bd->type;
251
LogFlowThisFuncLeave();
255
STDMETHODIMP MediumAttachment::COMGETTER(Passthrough)(BOOL *aPassthrough)
257
LogFlowThisFuncEnter();
259
CheckComArgOutPointerValid(aPassthrough);
261
AutoCaller autoCaller(this);
262
if (FAILED(autoCaller.rc())) return autoCaller.rc();
264
AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
266
*aPassthrough = m->bd->fPassthrough;
268
LogFlowThisFuncLeave();
273
* @note Locks this object for writing.
275
void MediumAttachment::rollback()
277
LogFlowThisFunc(("ENTER - %s\n", getLogName()));
280
AutoCaller autoCaller(this);
281
AssertComRCReturnVoid(autoCaller.rc());
283
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
287
LogFlowThisFunc(("LEAVE - %s\n", getLogName()));
291
* @note Locks this object for writing.
293
void MediumAttachment::commit()
295
LogFlowThisFuncEnter();
298
AutoCaller autoCaller(this);
299
AssertComRCReturnVoid (autoCaller.rc());
301
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
303
if (m->bd.isBackedUp())
306
LogFlowThisFuncLeave();
309
bool MediumAttachment::isImplicit() const
311
return m->bd->fImplicit;
314
void MediumAttachment::setImplicit(bool aImplicit)
316
m->bd->fImplicit = aImplicit;
319
const ComObjPtr<Medium>& MediumAttachment::getMedium() const
321
return m->bd->pMedium;
324
Bstr MediumAttachment::getControllerName() const
326
return m->bd->bstrControllerName;
329
LONG MediumAttachment::getPort() const
334
LONG MediumAttachment::getDevice() const
336
return m->bd->lDevice;
339
DeviceType_T MediumAttachment::getType() const
344
bool MediumAttachment::getPassthrough() const
346
AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
347
return m->bd->fPassthrough;
350
bool MediumAttachment::matches(CBSTR aControllerName, LONG aPort, LONG aDevice)
352
return ( aControllerName == m->bd->bstrControllerName
353
&& aPort == m->bd->lPort
354
&& aDevice == m->bd->lDevice);
357
/** Must be called from under this object's write lock. */
358
void MediumAttachment::updateMedium(const ComObjPtr<Medium> &aMedium)
360
Assert(isWriteLockOnCurrentThread());
363
m->bd->pMedium = aMedium;
366
/** Must be called from under this object's write lock. */
367
void MediumAttachment::updatePassthrough(bool aPassthrough)
369
Assert(isWriteLockOnCurrentThread());
372
m->bd->fPassthrough = aPassthrough;