Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp	(revision 23927)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp	(revision 23928)
@@ -1012,9 +1012,5 @@
             case MODIFYVM_DVDPASSTHROUGH: // deprecated
             {
-                ComPtr<IMediumAttachment> dvdAttachment;
-                machine->GetMediumAttachment(Bstr("IDE Controller"), 1, 0, dvdAttachment.asOutParam());
-                ASSERT(dvdAttachment);
-
-                CHECK_ERROR (dvdAttachment, COMSETTER(Passthrough)(!strcmp(ValueUnion.psz, "on")));
+                CHECK_ERROR (machine, PassthroughDevice(Bstr("IDE Controller"), 1, 0, !strcmp(ValueUnion.psz, "on")));
                 break;
             }
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageStorageController.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageStorageController.cpp	(revision 23927)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageStorageController.cpp	(revision 23928)
@@ -459,9 +459,9 @@
             if (!RTStrICmp(pszPassThrough, "on"))
             {
-                CHECK_ERROR (mattach, COMSETTER(Passthrough)(true));
+                CHECK_ERROR (machine, PassthroughDevice(Bstr(pszCtl), port, device, TRUE));
             }
             else if (!RTStrICmp(pszPassThrough, "off"))
             {
-                CHECK_ERROR (mattach, COMSETTER(Passthrough)(false));
+                CHECK_ERROR (machine, PassthroughDevice(Bstr(pszCtl), port, device, FALSE));
             }
             else
Index: /trunk/src/VBox/Frontends/VirtualBox/src/VBoxVMSettingsHD.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/VBoxVMSettingsHD.cpp	(revision 23927)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/VBoxVMSettingsHD.cpp	(revision 23928)
@@ -1789,7 +1789,7 @@
                 QString attMediumId = mStorageModel->data (attIndex, StorageModel::R_AttMediumId).toString();
                 mMachine.AttachDevice (ctrName, attStorageSlot.port, attStorageSlot.device, attDeviceType, attMediumId);
-                CMediumAttachment attachment = mMachine.GetMediumAttachment (ctrName, attStorageSlot.port, attStorageSlot.device);
-                attachment.SetPassthrough (mStorageModel->data (attIndex, StorageModel::R_AttIsHostDrive).toBool() &&
-                                           mStorageModel->data (attIndex, StorageModel::R_AttIsPassthrough).toBool());
+                if (attDeviceType == KDeviceType_DVD)
+                    mMachine.PassthroughDevice (ctrName, attStorageSlot.port, attStorageSlot.device,
+                                                mStorageModel->data (attIndex, StorageModel::R_AttIsPassthrough).toBool());
                 maxUsedPort = attStorageSlot.port > maxUsedPort ? attStorageSlot.port : maxUsedPort;
             }
Index: /trunk/src/VBox/Main/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/MachineImpl.cpp	(revision 23927)
+++ /trunk/src/VBox/Main/MachineImpl.cpp	(revision 23928)
@@ -2518,4 +2518,50 @@
      * still refers to the original and is not valid for the copy */
     mMediaData->mAttachments.remove(pAttach);
+
+    return S_OK;
+}
+
+STDMETHODIMP Machine::PassthroughDevice(IN_BSTR aControllerName, LONG aControllerPort,
+                                        LONG aDevice, BOOL aPassthrough)
+{
+    CheckComArgNotNull(aControllerName);
+
+    LogFlowThisFunc(("aControllerName=\"%ls\" aControllerPort=%ld aDevice=%ld aPassthrough=%d\n",
+                     aControllerName, aControllerPort, aDevice, aPassthrough));
+
+    AutoCaller autoCaller(this);
+    CheckComRCReturnRC(autoCaller.rc());
+
+    AutoWriteLock alock(this);
+
+    HRESULT rc = checkStateDependency(MutableStateDep);
+    CheckComRCReturnRC(rc);
+
+    AssertReturn(mData->mMachineState != MachineState_Saved, E_FAIL);
+
+    if (Global::IsOnlineOrTransient(mData->mMachineState))
+        return setError(VBOX_E_INVALID_VM_STATE,
+                        tr("Invalid machine state: %s"),
+                        Global::stringifyMachineState(mData->mMachineState));
+
+    MediumAttachment *pAttach = findAttachment(mMediaData->mAttachments,
+                                               aControllerName,
+                                               aControllerPort,
+                                               aDevice);
+    if (!pAttach)
+        return setError(VBOX_E_OBJECT_NOT_FOUND,
+                        tr("No storage device attached to device slot %d on port %d of controller '%ls'"),
+                        aDevice, aControllerPort, aControllerName);
+
+
+    mMediaData.backup();
+
+    AutoWriteLock attLock(pAttach);
+
+    if (pAttach->type() != DeviceType_DVD)
+        return setError(E_INVALIDARG,
+                        tr("Setting passthrough rejected as the device attached to device slot %d on port %d of controller '%ls' is not a DVD"),
+                        aDevice, aControllerPort, aControllerName);
+    pAttach->updatePassthrough(aPassthrough);
 
     return S_OK;
Index: /trunk/src/VBox/Main/MediumAttachmentImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/MediumAttachmentImpl.cpp	(revision 23927)
+++ /trunk/src/VBox/Main/MediumAttachmentImpl.cpp	(revision 23928)
@@ -247,31 +247,4 @@
 }
 
-STDMETHODIMP MediumAttachment::COMSETTER(Passthrough)(BOOL aPassthrough)
-{
-    LogFlowThisFuncEnter();
-
-    AutoCaller autoCaller(this);
-    CheckComRCReturnRC(autoCaller.rc());
-
-    /** @todo the entire passthrough handling can only be enabled after the
-     *  MediumAttachment handling in Machine is fixed. */
-#if 0
-    /* the machine need to be mutable */
-    Machine::AutoMutableStateDependency adep(mParent);
-    CheckComRCReturnRC(adep.rc());
-
-    AutoWriteLock lock(this);
-
-    if (m->passthrough != !!aPassthrough)
-    {
-        m.backup();
-        m->passthrough = !!aPassthrough;
-    }
-#endif
-
-    LogFlowThisFuncLeave();
-    return S_OK;
-}
-
 STDMETHODIMP MediumAttachment::COMGETTER(Passthrough)(BOOL *aPassthrough)
 {
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 23927)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 23928)
@@ -4060,5 +4060,5 @@
   <interface
      name="IMachine" extends="$unknown"
-     uuid="d867a463-0f78-4ec7-a876-8da001464537"
+     uuid="db35f17a-179f-4332-91b2-a49d5cfb678c"
      wsmap="managed"
      >
@@ -4751,4 +4751,40 @@
     </method>
 
+    <method name="passthroughDevice">
+      <desc>
+        Sets the passthrough mode of an existing DVD device. Changing the
+        setting while the VM is running is forbidden. The setting is only used
+        if at VM start the device is configured as a host DVD drive, in all
+        other cases it is ignored. The device must already exist; see
+        <link to="IMachine::attachDevice"/> for how to attach a new device.
+
+        The @a controllerPort and @a device parameters specify the device slot and
+        have have the same meaning as with <link to="IMachine::attachDevice" />.
+
+        <result name="E_INVALIDARG">
+          SATA device, SATA port, IDE port or IDE slot out of range.
+        </result>
+        <result name="VBOX_E_INVALID_OBJECT_STATE">
+          Attempt to modify an unregistered virtual machine.
+        </result>
+        <result name="VBOX_E_INVALID_VM_STATE">
+          Invalid machine state.
+        </result>
+
+      </desc>
+      <param name="name" type="wstring" dir="in">
+        <desc>Name of the storage controller.</desc>
+      </param>
+      <param name="controllerPort" type="long" dir="in">
+        <desc>Storage controller port.</desc>
+      </param>
+      <param name="device" type="long" dir="in">
+        <desc>Device slot in the given port.</desc>
+      </param>
+      <param name="passthrough" type="boolean" dir="in">
+        <desc>New value for the passthrough setting.</desc>
+      </param>
+    </method>
+
     <method name="mountMedium">
       <desc>
@@ -8363,5 +8399,5 @@
   <interface
     name="IMediumAttachment" extends="$unknown"
-    uuid="ff554585-560a-489d-963c-cf6da6a826de"
+    uuid="7bb6ac41-8c03-4863-9eea-d9c76561b8d1"
     wsmap="struct"
   >
@@ -8400,5 +8436,5 @@
     </attribute>
 
-    <attribute name="passthrough" type="boolean" readonly="no">
+    <attribute name="passthrough" type="boolean" readonly="yes">
       <desc>Pass I/O requests through to a device on the host.</desc>
     </attribute>
Index: /trunk/src/VBox/Main/include/MachineImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MachineImpl.h	(revision 23927)
+++ /trunk/src/VBox/Main/include/MachineImpl.h	(revision 23928)
@@ -577,4 +577,5 @@
                             LONG aDevice, DeviceType_T aType, IN_BSTR aId);
     STDMETHOD(DetachDevice)(IN_BSTR aControllerName, LONG aControllerPort, LONG aDevice);
+    STDMETHOD(PassthroughDevice)(IN_BSTR aControllerName, LONG aControllerPort, LONG aDevice, BOOL aPassthrough);
     STDMETHOD(MountMedium)(IN_BSTR aControllerName, LONG aControllerPort,
                            LONG aDevice, IN_BSTR aId);
Index: /trunk/src/VBox/Main/include/MediumAttachmentImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MediumAttachmentImpl.h	(revision 23927)
+++ /trunk/src/VBox/Main/include/MediumAttachmentImpl.h	(revision 23928)
@@ -74,5 +74,4 @@
     STDMETHOD(COMGETTER(Type))(DeviceType_T *aType);
     STDMETHOD(COMGETTER(Passthrough))(BOOL *aPassthrough);
-    STDMETHOD(COMSETTER(Passthrough))(BOOL aPassthrough);
 
     // unsafe inline public methods for internal purposes only (ensure there is
@@ -102,4 +101,11 @@
         m->medium = aMedium;
         m->implicit = aImplicit;
+    }
+
+    /** Must be called from under this object's write lock. */
+    void updatePassthrough(bool aPassthrough)
+    {
+        m.backup();
+        m->passthrough = aPassthrough;
     }
 
