Index: /trunk/include/VBox/settings.h
===================================================================
--- /trunk/include/VBox/settings.h	(revision 31614)
+++ /trunk/include/VBox/settings.h	(revision 31615)
@@ -131,4 +131,8 @@
 
 /**
+ * A media registry. Starting with VirtualBox 3.3, this can appear in both the
+ * VirtualBox.xml file as well as machine XML files with settings version 1.11
+ * or higher, so these lists are now in ConfigFileBase.
+ *
  * NOTE: If you add any fields in here, you must update a) the constructor and b)
  * the operator== which is used by MachineConfigFile::operator==(), or otherwise
@@ -917,4 +921,6 @@
     bool operator==(const MachineConfigFile &m) const;
 
+    bool canHaveOwnMediaRegistry() const;
+
     void importMachineXML(const xml::ElementNode &elmMachine);
 
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp	(revision 31614)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp	(revision 31615)
@@ -661,7 +661,5 @@
                     if (hardDisk)
                     {
-                        Bstr uuid;
-                        hardDisk->COMGETTER(Id)(uuid.asOutParam());
-                        CHECK_ERROR(machine, AttachDevice(bstrController, u1, u2, DeviceType_HardDisk, uuid));
+                        CHECK_ERROR(machine, AttachDevice(bstrController, u1, u2, DeviceType_HardDisk, hardDisk));
                     }
                     else
@@ -757,12 +755,10 @@
                     if (hardDisk)
                     {
-                        Bstr uuid;
-                        hardDisk->COMGETTER(Id)(uuid.asOutParam());
-                        rc = machine->AttachDevice(Bstr("LsiLogic"), GetOptState.uIndex, 0, DeviceType_HardDisk, uuid);
+                        rc = machine->AttachDevice(Bstr("LsiLogic"), GetOptState.uIndex, 0, DeviceType_HardDisk, hardDisk);
                         if (FAILED(rc))
                             CHECK_ERROR(machine,
                                          AttachDevice(Bstr("BusLogic"),
                                                       GetOptState.uIndex, 0,
-                                                      DeviceType_HardDisk, uuid));
+                                                      DeviceType_HardDisk, hardDisk));
                     }
                     else
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageStorageController.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageStorageController.cpp	(revision 31614)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageStorageController.cpp	(revision 31615)
@@ -287,5 +287,5 @@
             /* attach a empty floppy/dvd drive after removing previous attachment */
             machine->DetachDevice(Bstr(pszCtl), port, device);
-            CHECK_ERROR(machine, AttachDevice(Bstr(pszCtl), port, device, deviceType, Bstr("")));
+            CHECK_ERROR(machine, AttachDevice(Bstr(pszCtl), port, device, deviceType, NULL));
         }
     }
@@ -411,10 +411,10 @@
                     {
                         machine->DetachDevice(Bstr(pszCtl), port, device);
-                        rc = machine->AttachDevice(Bstr(pszCtl), port, device, DeviceType_DVD, Bstr(""));
+                        rc = machine->AttachDevice(Bstr(pszCtl), port, device, DeviceType_DVD, NULL);
                     }
                 }
                 else
                 {
-                    rc = machine->AttachDevice(Bstr(pszCtl), port, device, DeviceType_DVD, Bstr(""));
+                    rc = machine->AttachDevice(Bstr(pszCtl), port, device, DeviceType_DVD, NULL);
                 }
             }
@@ -501,7 +501,5 @@
             if (hardDisk)
             {
-                Bstr uuid;
-                hardDisk->COMGETTER(Id)(uuid.asOutParam());
-                CHECK_ERROR(machine, AttachDevice(Bstr(pszCtl), port, device, DeviceType_HardDisk, uuid));
+                CHECK_ERROR(machine, AttachDevice(Bstr(pszCtl), port, device, DeviceType_HardDisk, hardDisk));
             }
             else
@@ -520,5 +518,5 @@
             if (   !fRunTime
                 && !floppyAttachment)
-                CHECK_ERROR(machine, AttachDevice(Bstr(pszCtl), port, device, DeviceType_Floppy, Bstr("")));
+                CHECK_ERROR(machine, AttachDevice(Bstr(pszCtl), port, device, DeviceType_Floppy, NULL));
 
             /* host drive? */
Index: /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp	(revision 31614)
+++ /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp	(revision 31615)
@@ -1426,7 +1426,5 @@
              * Go and attach it!
              */
-            Bstr uuidHD;
             Bstr storageCtlName;
-            hardDisk->COMGETTER(Id)(uuidHD.asOutParam());
 
             /* get the first IDE controller to attach the harddisk to
@@ -1463,5 +1461,5 @@
             }
 
-            gMachine->AttachDevice(storageCtlName, 0, 0, DeviceType_HardDisk, uuidHD);
+            gMachine->AttachDevice(storageCtlName, 0, 0, DeviceType_HardDisk, hardDisk);
             /// @todo why is this attachment saved?
         }
Index: /trunk/src/VBox/Frontends/VirtualBox/src/settings/vm/VBoxVMSettingsHD.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/settings/vm/VBoxVMSettingsHD.cpp	(revision 31614)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/settings/vm/VBoxVMSettingsHD.cpp	(revision 31615)
@@ -1856,5 +1856,8 @@
             QString attMediumId = mStorageModel->data (attIndex, StorageModel::R_AttMediumId).toString();
             QString attMediumLocation = mStorageModel->data (attIndex, StorageModel::R_AttLocation).toString();
-            mMachine.AttachDevice (ctrName, attStorageSlot.port, attStorageSlot.device, attDeviceType, attMediumId);
+
+            VBoxMedium vmedium = vboxGlobal().findMedium(attMediumId);
+            CMedium medium = vmedium.medium();              // @todo r=dj can this be cached somewhere?
+            mMachine.AttachDevice(ctrName, attStorageSlot.port, attStorageSlot.device, attDeviceType, medium);
             if (mMachine.isOk())
             {
Index: /trunk/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UINewVMWzd.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UINewVMWzd.cpp	(revision 31614)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UINewVMWzd.cpp	(revision 31615)
@@ -754,8 +754,11 @@
             CMachine m = session.GetMachine();
 
+            QString strId = field("hardDiskId").toString();
             /* Boot hard disk */
-            if (!field("hardDiskId").toString().isNull())
+            if (!strId.isNull())
             {
-                m.AttachDevice(ctrHdName, 0, 0, KDeviceType_HardDisk, field("hardDiskId").toString());
+                VBoxMedium vmedium = vboxGlobal().findMedium(strId);
+                CMedium medium = vmedium.medium();              // @todo r=dj can this be cached somewhere?
+                m.AttachDevice(ctrHdName, 0, 0, KDeviceType_HardDisk, medium);
                 if (!m.isOk())
                     vboxProblem().cannotAttachDevice(this, m, VBoxDefs::MediumType_HardDisk,
@@ -764,5 +767,5 @@
 
             /* Attach empty CD/DVD ROM Device */
-            m.AttachDevice(ctrDvdName, 1, 0, KDeviceType_DVD, QString(""));
+            m.AttachDevice(ctrDvdName, 1, 0, KDeviceType_DVD, CMedium());
             if (!m.isOk())
                 vboxProblem().cannotAttachDevice(this, m, VBoxDefs::MediumType_DVD, QString(), ctrDvdBus, 1, 0);
Index: /trunk/src/VBox/Main/ApplianceImplExport.cpp
===================================================================
--- /trunk/src/VBox/Main/ApplianceImplExport.cpp	(revision 31614)
+++ /trunk/src/VBox/Main/ApplianceImplExport.cpp	(revision 31615)
@@ -1504,5 +1504,7 @@
             // create a new hard disk interface for the destination disk image
             Log(("Creating target disk \"%s\"\n", strTargetFilePath.c_str()));
-            rc = mVirtualBox->CreateHardDisk(bstrSrcFormat, Bstr(strTargetFilePath), pTargetDisk.asOutParam());
+            rc = mVirtualBox->CreateHardDisk(bstrSrcFormat,
+                                             Bstr(strTargetFilePath),
+                                             pTargetDisk.asOutParam());
             if (FAILED(rc)) throw rc;
 
Index: /trunk/src/VBox/Main/ApplianceImplImport.cpp
===================================================================
--- /trunk/src/VBox/Main/ApplianceImplImport.cpp	(revision 31614)
+++ /trunk/src/VBox/Main/ApplianceImplImport.cpp	(revision 31615)
@@ -1316,5 +1316,7 @@
                 srcFormat = L"VMDK";
             // create an empty hard disk
-            rc = mVirtualBox->CreateHardDisk(srcFormat, Bstr(strTargetPath), pTargetHD.asOutParam());
+            rc = mVirtualBox->CreateHardDisk(srcFormat,
+                                             Bstr(strTargetPath),
+                                             pTargetHD.asOutParam());
             if (FAILED(rc)) DebugBreakThrow(rc);
 
@@ -1354,5 +1356,7 @@
             if (FAILED(rc)) DebugBreakThrow(rc);
             /* Create a new hard disk interface for the destination disk image */
-            rc = mVirtualBox->CreateHardDisk(srcFormat, Bstr(strTargetPath), pTargetHD.asOutParam());
+            rc = mVirtualBox->CreateHardDisk(srcFormat,
+                                             Bstr(strTargetPath),
+                                             pTargetHD.asOutParam());
             if (FAILED(rc)) DebugBreakThrow(rc);
             /* Clone the source disk image */
@@ -1707,5 +1711,6 @@
     rc = pNewMachine->COMGETTER(Id)(bstrNewMachineId.asOutParam());
     if (FAILED(rc)) DebugBreakThrow(rc);
-    m->llGuidsMachinesCreated.push_back(Guid(bstrNewMachineId));
+    Guid uuidNewMachine(bstrNewMachineId);
+    m->llGuidsMachinesCreated.push_back(uuidNewMachine);
 
     // Add floppies and CD-ROMs to the appropriate controllers.
@@ -1874,7 +1879,4 @@
                 rc = stack.pSession->COMGETTER(Machine)(sMachine.asOutParam());
                 if (FAILED(rc)) DebugBreakThrow(rc);
-                Bstr hdId;
-                rc = pTargetHD->COMGETTER(Id)(hdId.asOutParam());
-                if (FAILED(rc)) DebugBreakThrow(rc);
 
                 // find the hard disk controller to which we should attach
@@ -1897,5 +1899,5 @@
                                             mhda.lDevice,           // long device
                                             DeviceType_HardDisk,    // DeviceType_T type
-                                            hdId);                  // uuid id
+                                            pTargetHD);
                 if (FAILED(rc)) DebugBreakThrow(rc);
 
Index: /trunk/src/VBox/Main/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/MachineImpl.cpp	(revision 31614)
+++ /trunk/src/VBox/Main/MachineImpl.cpp	(revision 31615)
@@ -3097,8 +3097,8 @@
                                    LONG aDevice,
                                    DeviceType_T aType,
-                                   IN_BSTR aId)
+                                   IMedium *aMedium)
 {
     LogFlowThisFunc(("aControllerName=\"%ls\" aControllerPort=%d aDevice=%d aType=%d aId=\"%ls\"\n",
-                     aControllerName, aControllerPort, aDevice, aType, aId));
+                     aControllerName, aControllerPort, aDevice, aType, aMedium));
 
     CheckComArgStrNotEmptyOrNull(aControllerName);
@@ -3109,5 +3109,5 @@
     // if this becomes true then we need to call saveSettings in the end
     // @todo r=dj there is no error handling so far...
-    bool fNeedsSaveSettings = false;
+    bool fNeedsGlobalSaveSettings = false;
 
     // request the host lock first, since might be calling Host methods for getting host drives;
@@ -3165,26 +3165,7 @@
     }
 
-    Guid uuid(aId);
-
-    ComObjPtr<Medium> medium;
-
-    switch (aType)
-    {
-        case DeviceType_HardDisk:
-            /* find a hard disk by UUID */
-            rc = mParent->findHardDisk(&uuid, Utf8Str::Empty, true /* aSetError */, &medium);
-            if (FAILED(rc)) return rc;
-            break;
-
-        case DeviceType_DVD:
-        case DeviceType_Floppy:
-            rc = mParent->findRemoveableMedium(aType, uuid, true /* fRefresh */, medium);
-        break;
-
-        default:
-            return setError(E_INVALIDARG,
-                            tr("The device type %d is not recognized"),
-                            (int)aType);
-    }
+    ComObjPtr<Medium> medium = static_cast<Medium*>(aMedium);
+    if (aMedium && medium.isNull())
+        return setError(E_INVALIDARG, "The given medium pointer is invalid");
 
     AutoCaller mediumCaller(medium);
@@ -3223,5 +3204,5 @@
                 {
                     /* the simplest case: restore the whole attachment
-                    * and return, nothing else to do */
+                     * and return, nothing else to do */
                     mMediaData->mAttachments.push_back(pAttachTemp);
                     return S_OK;
@@ -3229,5 +3210,5 @@
 
                 /* bus/channel/device differ; we need a new attachment object,
-                    * but don't try to associate it again */
+                 * but don't try to associate it again */
                 associate = false;
                 break;
@@ -3394,5 +3375,6 @@
                         medium->getPreferredDiffFormat(),
                         Utf8Str(mUserData->m_strSnapshotFolderFull).append(RTPATH_SLASH_STR),
-                        &fNeedsSaveSettings);
+                        medium->getRegistryMachineId(),         // store this diff in the same registry as the parent
+                        &fNeedsGlobalSaveSettings);
         if (FAILED(rc)) return rc;
 
@@ -3426,5 +3408,5 @@
                                                NULL /* aProgress */,
                                                true /* aWait */,
-                                               &fNeedsSaveSettings);
+                                               &fNeedsGlobalSaveSettings);
 
                 alock.enter();
@@ -3463,9 +3445,14 @@
     if (associate && !medium.isNull())
     {
-        /* as the last step, associate the medium to the VM */
+        // as the last step, associate the medium to the VM
         rc = medium->addBackReference(mData->mUuid);
-        /* here we can fail because of Deleting, or being in process of
-         * creating a Diff */
+        // here we can fail because of Deleting, or being in process of creating a Diff
         if (FAILED(rc)) return rc;
+
+        // and decide which medium registry to use now that the medium is attached:
+        if (mData->pMachineConfigFile->canHaveOwnMediaRegistry())
+            medium->setRegistryIdIfFirst(getId());        // machine UUID
+        else
+            medium->setRegistryIdIfFirst(mParent->getGlobalRegistryId()); // VirtualBox global registry UUID
     }
 
@@ -3475,5 +3462,5 @@
     mMediaData->mAttachments.push_back(attachment);
 
-    if (fNeedsSaveSettings)
+    if (fNeedsGlobalSaveSettings)
     {
         // save the global settings; for that we should hold only the VirtualBox lock
@@ -3953,8 +3940,11 @@
                                  ComSafeArrayOut(IMedium*, aMedia))
 {
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+    // use AutoLimitedCaller because this call is valid on inaccessible machines as well
+    AutoLimitedCaller autoCaller(this);
+    AssertComRCReturnRC(autoCaller.rc());
 
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    Guid id(getId());
 
     if (mData->mSession.mState != SessionState_Unlocked)
@@ -3962,4 +3952,24 @@
                         tr("Cannot unregister the machine '%s' while it is locked"),
                         mUserData->s.strName.c_str());
+
+    // wait for state dependants to drop to zero
+    ensureNoStateDependencies();
+
+    if (!mData->mAccessible)
+    {
+        // inaccessible maschines can only be unregistered; uninitialize ourselves
+        // here because currently there may be no unregistered that are inaccessible
+        // (this state combination is not supported). Note releasing the caller and
+        // leaving the lock before alling uninit()
+        alock.leave();
+        autoCaller.release();
+
+        uninit();
+
+        mParent->unregisterMachine(this, id);
+            // calls VirtualBox::saveSettings()
+
+        return S_OK;
+    }
 
     HRESULT rc = S_OK;
@@ -4055,5 +4065,5 @@
     sfaMedia.detachTo(ComSafeArrayOutArg(aMedia));
 
-    mParent->unregisterMachine(this);
+    mParent->unregisterMachine(this, id);
             // calls VirtualBox::saveSettings()
 
@@ -6681,4 +6691,12 @@
     mUserData.commitCopy();
 
+    // machine registry, if present (must be loaded before snapshots)
+    if (config.canHaveOwnMediaRegistry())
+    {
+        rc = mParent->initMedia(getId(),         // media registry ID == machine UUID
+                                config.mediaRegistry);
+        if (FAILED(rc)) return rc;
+    }
+
     /* Snapshot node (optional) */
     size_t cRootSnapshots;
@@ -6696,9 +6714,9 @@
     }
 
-    /* Hardware node (required) */
+    // hardware data
     rc = loadHardware(config.hardwareMachine);
     if (FAILED(rc)) return rc;
 
-    /* Load storage controllers */
+    // load storage controllers
     rc = loadStorageControllers(config.storageMachine);
     if (FAILED(rc)) return rc;
@@ -7779,4 +7797,10 @@
     if (FAILED(rc)) throw rc;
 
+    // save machine's media registry if this is VirtualBox 3.3 or later
+    if (config.canHaveOwnMediaRegistry())
+        mParent->saveMediaRegistry(config.mediaRegistry,
+                                   getId());            // only media with registry ID == machine UUID
+            // this throws HRESULT
+
     // save snapshots
     rc = saveAllSnapshots(config);
@@ -8357,4 +8381,5 @@
                             pMedium->getPreferredDiffFormat(),
                             Utf8Str(mUserData->m_strSnapshotFolderFull).append(RTPATH_SLASH_STR),
+                            pMedium->getRegistryMachineId(),        // store the diff in the same registry as the parent
                             pfNeedsSaveSettings);
             if (FAILED(rc)) throw rc;
Index: /trunk/src/VBox/Main/MediumImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/MediumImpl.cpp	(revision 31614)
+++ /trunk/src/VBox/Main/MediumImpl.cpp	(revision 31615)
@@ -191,5 +191,5 @@
     Task(Medium *aMedium, Progress *aProgress)
         : mVDOperationIfaces(NULL),
-          m_pfNeedsSaveSettings(NULL),
+          m_pfNeedsGlobalSaveSettings(NULL),
           mMedium(aMedium),
           mMediumCaller(aMedium),
@@ -234,5 +234,5 @@
     // the task function returns. Only used in synchronous (wait) mode;
     // otherwise the task will save the settings itself.
-    bool *m_pfNeedsSaveSettings;
+    bool *m_pfNeedsGlobalSaveSettings;
 
     const ComObjPtr<Medium> mMedium;
@@ -728,5 +728,11 @@
  * storage unit.
  *
- * This gets called by VirtualBox::CreateHardDisk().
+ * This gets called by VirtualBox::CreateHardDisk() in which case uuidMachineRegistry
+ * is empty since starting with VirtualBox 3.3, we no longer add opened media to a
+ * registry automatically (this is deferred until the medium is attached to a machine).
+ *
+ * This also gets called when VirtualBox creates diff images; in this case uuidMachineRegistry
+ * is set to the registry of the parent image to make sure they all end up in the same
+ * file.
  *
  * For hard disks that don't have the VD_CAP_CREATE_FIXED or
@@ -736,6 +742,8 @@
  *
  * @param aVirtualBox   VirtualBox object.
+ * @param aFormat
  * @param aLocation     Storage unit location.
- * @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
+ * @param uuidMachineRegistry The registry to which this medium should be added (global registry UUI or medium UUID or empty if none).
+ * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
  *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
  */
@@ -743,5 +751,6 @@
                      const Utf8Str &aFormat,
                      const Utf8Str &aLocation,
-                     bool *pfNeedsSaveSettings)
+                     const Guid &uuidMachineRegistry,
+                     bool *pfNeedsGlobalSaveSettings)
 {
     AssertReturn(aVirtualBox != NULL, E_FAIL);
@@ -754,6 +763,6 @@
     HRESULT rc = S_OK;
 
-    /* share VirtualBox weakly (parent remains NULL so far) */
     unconst(m->pVirtualBox) = aVirtualBox;
+    m->uuidRegistryMachine = uuidMachineRegistry;
 
     /* no storage yet */
@@ -791,5 +800,5 @@
 
         AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
-        rc = m->pVirtualBox->registerHardDisk(this, pfNeedsSaveSettings);
+        rc = m->pVirtualBox->registerHardDisk(this, pfNeedsGlobalSaveSettings);
     }
 
@@ -809,4 +818,8 @@
  * Machine::AttachDevice() and createImplicitDiffs() when new diff
  * images are created.
+ *
+ * There is no registry for this case since starting with VirtualBox 3.3, we
+ * no longer add opened media to a registry automatically (this is deferred
+ * until the medium is attached to a machine).
  *
  * For hard disks, the UUID, format and the parent of this medium will be
@@ -835,5 +848,4 @@
     HRESULT rc = S_OK;
 
-    /* share VirtualBox weakly (parent remains NULL so far) */
     unconst(m->pVirtualBox) = aVirtualBox;
 
@@ -893,7 +905,12 @@
  * node. In this mode, the medium will always be opened read/write.
  *
+ * In this case, since we're loading from a registry, uuidMachineRegistry is
+ * always set: it's either the global registry UUID or a machine UUID when
+ * loading from a per-machine registry.
+ *
  * @param aVirtualBox   VirtualBox object.
  * @param aParent       Parent medium disk or NULL for a root (base) medium.
  * @param aDeviceType   Device type of the medium.
+ * @param uuidMachineRegistry The registry to which this medium should be added (global registry UUI or medium UUID).
  * @param aNode         Configuration settings.
  *
@@ -903,4 +920,5 @@
                      Medium *aParent,
                      DeviceType_T aDeviceType,
+                     const Guid &uuidMachineRegistry,
                      const settings::Medium &data)
 {
@@ -915,6 +933,6 @@
     HRESULT rc = S_OK;
 
-    /* share VirtualBox and parent weakly */
     unconst(m->pVirtualBox) = aVirtualBox;
+    m->uuidRegistryMachine = uuidMachineRegistry;
 
     /* register with VirtualBox/parent early, since uninit() will
@@ -1020,8 +1038,9 @@
                        this,            // parent
                        aDeviceType,
+                       uuidMachineRegistry,
                        med);              // child data
         if (FAILED(rc)) break;
 
-        rc = m->pVirtualBox->registerHardDisk(pHD, NULL /*pfNeedsSaveSettings*/);
+        rc = m->pVirtualBox->registerHardDisk(pHD, NULL /*pfNeedsGlobalSaveSettings*/);
         if (FAILED(rc)) break;
     }
@@ -1037,4 +1056,6 @@
  * Initializes the medium object by providing the host drive information.
  * Not used for anything but the host floppy/host DVD case.
+ *
+ * There is no registry for this case.
  *
  * @param aVirtualBox   VirtualBox object.
@@ -1057,5 +1078,4 @@
     AssertReturn(autoInitSpan.isOk(), E_FAIL);
 
-    /* share VirtualBox weakly (parent remains NULL so far) */
     unconst(m->pVirtualBox) = aVirtualBox;
 
@@ -1962,8 +1982,8 @@
     ComObjPtr<VirtualBox> pVirtualBox(m->pVirtualBox);
 
-    bool fNeedsSaveSettings = false;
-    HRESULT rc = close(&fNeedsSaveSettings, autoCaller);
-
-    if (fNeedsSaveSettings)
+    bool fNeedsGlobalSaveSettings = false;
+    HRESULT rc = close(&fNeedsGlobalSaveSettings, autoCaller);
+
+    if (fNeedsGlobalSaveSettings)
     {
         AutoWriteLock vboxlock(pVirtualBox COMMA_LOCKVAL_SRC_POS);
@@ -2180,11 +2200,11 @@
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
-    bool fNeedsSaveSettings = false;
+    bool fNeedsGlobalSaveSettings = false;
     ComObjPtr<Progress> pProgress;
 
     HRESULT rc = deleteStorage(&pProgress,
                                false /* aWait */,
-                               &fNeedsSaveSettings);
-    if (fNeedsSaveSettings)
+                               &fNeedsGlobalSaveSettings);
+    if (fNeedsGlobalSaveSettings)
     {
         AutoWriteLock vboxlock(m->pVirtualBox COMMA_LOCKVAL_SRC_POS);
@@ -2236,5 +2256,5 @@
 
     rc = createDiffStorage(diff, aVariant, pMediumLockList, &pProgress,
-                           false /* aWait */, NULL /* pfNeedsSaveSettings*/);
+                           false /* aWait */, NULL /* pfNeedsGlobalSaveSettings*/);
     if (FAILED(rc))
         delete pMediumLockList;
@@ -2271,5 +2291,5 @@
     rc = mergeTo(pTarget, fMergeForward, pParentForTarget, childrenToReparent,
                  pMediumLockList, &pProgress, false /* aWait */,
-                 NULL /* pfNeedsSaveSettings */);
+                 NULL /* pfNeedsGlobalSaveSettings */);
     if (FAILED(rc))
         cancelMergeTo(childrenToReparent, pMediumLockList);
@@ -3265,4 +3285,26 @@
     Utf8Str name = RTPathFilename(m->strLocationFull.c_str());
     return name;
+}
+
+/**
+ * This sets the UUID of the machine in whose registry this medium should
+ * be registered, or the UUID of the global VirtualBox.xml registry, but
+ * only if no registry ID had been previously set.
+ * @param id
+ */
+void Medium::setRegistryIdIfFirst(const Guid& id)
+{
+    if (m->uuidRegistryMachine.isEmpty())
+        m->uuidRegistryMachine = id;
+}
+
+/**
+ * Returns the UUID of the machine in whose registry this medium is registered,
+ * or the UUID of the global VirtualBox.xml registry.
+ * @return
+ */
+const Guid& Medium::getRegistryId() const
+{
+    return m->uuidRegistryMachine;
 }
 
@@ -3851,5 +3893,5 @@
  * the object is no longer usable ("not ready" state).
  *
- * @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
+ * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
  *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
  *                This only works in "wait" mode; otherwise saveSettings gets called automatically by the thread that was created,
@@ -3859,5 +3901,5 @@
  * @return
  */
-HRESULT Medium::close(bool *pfNeedsSaveSettings, AutoCaller &autoCaller)
+HRESULT Medium::close(bool *pfNeedsGlobalSaveSettings, AutoCaller &autoCaller)
 {
     // we're accessing parent/child and backrefs, so lock the tree first, then ourselves
@@ -3896,5 +3938,5 @@
         // uninitialization (to keep the media registry consistent on
         // failure to do so)
-        rc = unregisterWithVirtualBox(pfNeedsSaveSettings);
+        rc = unregisterWithVirtualBox(pfNeedsGlobalSaveSettings);
         if (FAILED(rc)) return rc;
     }
@@ -3930,5 +3972,5 @@
  * @param aWait         @c true if this method should block instead of creating
  *                      an asynchronous thread.
- * @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
+ * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
  *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
  *                This only works in "wait" mode; otherwise saveSettings gets called automatically by the thread that was created,
@@ -3940,5 +3982,5 @@
 HRESULT Medium::deleteStorage(ComObjPtr<Progress> *aProgress,
                               bool aWait,
-                              bool *pfNeedsSaveSettings)
+                              bool *pfNeedsGlobalSaveSettings)
 {
     AssertReturn(aProgress != NULL || aWait == true, E_FAIL);
@@ -4042,5 +4084,5 @@
          * which would have been broken if unregisterWithVirtualBox() failed
          * after we successfully deleted the storage) */
-        rc = unregisterWithVirtualBox(pfNeedsSaveSettings);
+        rc = unregisterWithVirtualBox(pfNeedsGlobalSaveSettings);
         if (FAILED(rc))
             throw rc;
@@ -4078,5 +4120,5 @@
     {
         if (aWait)
-            rc = runNow(pTask, NULL /* pfNeedsSaveSettings*/);
+            rc = runNow(pTask, NULL /* pfNeedsGlobalSaveSettings*/);
         else
             rc = startThread(pTask);
@@ -4201,5 +4243,5 @@
  * @param aWait             @c true if this method should block instead of
  *                          creating an asynchronous thread.
- * @param pfNeedsSaveSettings Optional pointer to a bool that must have been
+ * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been
  *                          initialized to false and that will be set to true
  *                          by this function if the caller should invoke
@@ -4217,5 +4259,5 @@
                                   ComObjPtr<Progress> *aProgress,
                                   bool aWait,
-                                  bool *pfNeedsSaveSettings)
+                                  bool *pfNeedsGlobalSaveSettings)
 {
     AssertReturn(!aTarget.isNull(), E_FAIL);
@@ -4307,5 +4349,5 @@
     {
         if (aWait)
-            rc = runNow(pTask, pfNeedsSaveSettings);
+            rc = runNow(pTask, pfNeedsGlobalSaveSettings);
         else
             rc = startThread(pTask);
@@ -4685,5 +4727,5 @@
  * @param aWait         @c true if this method should block instead of creating
  *                      an asynchronous thread.
- * @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
+ * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
  *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
  *                This only works in "wait" mode; otherwise saveSettings gets called automatically by the thread that was created,
@@ -4700,5 +4742,5 @@
                         ComObjPtr <Progress> *aProgress,
                         bool aWait,
-                        bool *pfNeedsSaveSettings)
+                        bool *pfNeedsGlobalSaveSettings)
 {
     AssertReturn(pTarget != NULL, E_FAIL);
@@ -4762,5 +4804,5 @@
     {
         if (aWait)
-            rc = runNow(pTask, pfNeedsSaveSettings);
+            rc = runNow(pTask, pfNeedsGlobalSaveSettings);
         else
             rc = startThread(pTask);
@@ -4863,10 +4905,10 @@
  * on the device type of this medium.
  *
- * @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
+ * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
  *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
  *
  * @note Caller must have locked the media tree lock for writing!
  */
-HRESULT Medium::unregisterWithVirtualBox(bool *pfNeedsSaveSettings)
+HRESULT Medium::unregisterWithVirtualBox(bool *pfNeedsGlobalSaveSettings)
 {
     /* Note that we need to de-associate ourselves from the parent to let
@@ -4885,13 +4927,13 @@
     {
         case DeviceType_DVD:
-            rc = m->pVirtualBox->unregisterImage(this, DeviceType_DVD, pfNeedsSaveSettings);
+            rc = m->pVirtualBox->unregisterImage(this, DeviceType_DVD, pfNeedsGlobalSaveSettings);
         break;
 
         case DeviceType_Floppy:
-            rc = m->pVirtualBox->unregisterImage(this, DeviceType_Floppy, pfNeedsSaveSettings);
+            rc = m->pVirtualBox->unregisterImage(this, DeviceType_Floppy, pfNeedsGlobalSaveSettings);
         break;
 
         case DeviceType_HardDisk:
-            rc = m->pVirtualBox->unregisterHardDisk(this, pfNeedsSaveSettings);
+            rc = m->pVirtualBox->unregisterHardDisk(this, pfNeedsGlobalSaveSettings);
         break;
 
@@ -5320,5 +5362,5 @@
  */
 HRESULT Medium::runNow(Medium::Task *pTask,
-                       bool *pfNeedsSaveSettings)
+                       bool *pfNeedsGlobalSaveSettings)
 {
 #ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
@@ -5330,5 +5372,5 @@
 #endif
 
-    pTask->m_pfNeedsSaveSettings = pfNeedsSaveSettings;
+    pTask->m_pfNeedsGlobalSaveSettings = pfNeedsGlobalSaveSettings;
 
     /* NIL_RTTHREAD indicates synchronous call. */
@@ -5428,10 +5470,10 @@
          * Created state only on success (leaving an orphan file is
          * better than breaking media registry consistency) */
-        bool fNeedsSaveSettings = false;
+        bool fNeedsGlobalSaveSettings = false;
         AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
-        rc = m->pVirtualBox->registerHardDisk(this, &fNeedsSaveSettings);
+        rc = m->pVirtualBox->registerHardDisk(this, &fNeedsGlobalSaveSettings);
         treeLock.release();
 
-        if (fNeedsSaveSettings)
+        if (fNeedsGlobalSaveSettings)
         {
             AutoWriteLock vboxlock(m->pVirtualBox COMMA_LOCKVAL_SRC_POS);
@@ -5470,5 +5512,5 @@
  * synchronously or asynchronously depending on the "wait" parameter passed to
  * that function. If we run synchronously, the caller expects the bool
- * *pfNeedsSaveSettings to be set before returning; otherwise (in asynchronous
+ * *pfNeedsGlobalSaveSettings to be set before returning; otherwise (in asynchronous
  * mode), we save the settings ourselves.
  *
@@ -5480,5 +5522,5 @@
     HRESULT rc = S_OK;
 
-    bool fNeedsSaveSettings = false;
+    bool fNeedsGlobalSaveSettings = false;
 
     const ComObjPtr<Medium> &pTarget = task.mTarget;
@@ -5609,5 +5651,5 @@
          * Created state only on success (leaving an orphan file is
          * better than breaking media registry consistency) */
-        rc = m->pVirtualBox->registerHardDisk(pTarget, &fNeedsSaveSettings);
+        rc = m->pVirtualBox->registerHardDisk(pTarget, &fNeedsGlobalSaveSettings);
 
         if (FAILED(rc))
@@ -5644,5 +5686,5 @@
     if (task.isAsync())
     {
-        if (fNeedsSaveSettings)
+        if (fNeedsGlobalSaveSettings)
         {
             // save the global settings; for that we should hold only the VirtualBox lock
@@ -5654,6 +5696,6 @@
     else
         // synchronous mode: report save settings result to caller
-        if (task.m_pfNeedsSaveSettings)
-            *task.m_pfNeedsSaveSettings = fNeedsSaveSettings;
+        if (task.m_pfNeedsGlobalSaveSettings)
+            *task.m_pfNeedsGlobalSaveSettings = fNeedsGlobalSaveSettings;
 
     /* Note that in sync mode, it's the caller's responsibility to
@@ -5669,5 +5711,5 @@
  * synchronously or asynchrously depending on the "wait" parameter passed to
  * that function. If we run synchronously, the caller expects the bool
- * *pfNeedsSaveSettings to be set before returning; otherwise (in asynchronous
+ * *pfNeedsGlobalSaveSettings to be set before returning; otherwise (in asynchronous
  * mode), we save the settings ourselves.
  *
@@ -5831,5 +5873,5 @@
             /* first, unregister the target since it may become a base
              * medium which needs re-registration */
-            rc2 = m->pVirtualBox->unregisterHardDisk(pTarget, NULL /*&fNeedsSaveSettings*/);
+            rc2 = m->pVirtualBox->unregisterHardDisk(pTarget, NULL /*&fNeedsGlobalSaveSettings*/);
             AssertComRC(rc2);
 
@@ -5845,5 +5887,5 @@
 
             /* then, register again */
-            rc2 = m->pVirtualBox->registerHardDisk(pTarget, NULL /*&fNeedsSaveSettings*/);
+            rc2 = m->pVirtualBox->registerHardDisk(pTarget, NULL /*&fNeedsGlobalSaveSettings*/);
             AssertComRC(rc2);
         }
@@ -5899,5 +5941,5 @@
 
             rc2 = pMedium->m->pVirtualBox->unregisterHardDisk(pMedium,
-                                                              NULL /*pfNeedsSaveSettings*/);
+                                                              NULL /*pfNeedsGlobalSaveSettings*/);
             AssertComRC(rc2);
 
@@ -5941,6 +5983,6 @@
     else
         // synchronous mode: report save settings result to caller
-        if (task.m_pfNeedsSaveSettings)
-            *task.m_pfNeedsSaveSettings = true;
+        if (task.m_pfNeedsGlobalSaveSettings)
+            *task.m_pfNeedsGlobalSaveSettings = true;
 
     if (FAILED(rc))
@@ -6160,5 +6202,5 @@
              * Created state only on success (leaving an orphan file is
              * better than breaking media registry consistency) */
-            rc = pParent->m->pVirtualBox->registerHardDisk(pTarget, NULL /* pfNeedsSaveSettings */);
+            rc = pParent->m->pVirtualBox->registerHardDisk(pTarget, NULL /* pfNeedsGlobalSaveSettings */);
 
             if (FAILED(rc))
@@ -6169,5 +6211,5 @@
         {
             /* just register  */
-            rc = m->pVirtualBox->registerHardDisk(pTarget, NULL /* pfNeedsSaveSettings */);
+            rc = m->pVirtualBox->registerHardDisk(pTarget, NULL /* pfNeedsGlobalSaveSettings */);
         }
     }
Index: /trunk/src/VBox/Main/SnapshotImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/SnapshotImpl.cpp	(revision 31614)
+++ /trunk/src/VBox/Main/SnapshotImpl.cpp	(revision 31615)
@@ -1357,5 +1357,5 @@
 
     // if this becomes true, we need to call VirtualBox::saveSettings() in the end
-    bool fNeedsSaveSettings = false;
+    bool fNeedsGlobalSaveSettings = false;
 
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -1440,5 +1440,5 @@
                                  1,            // operation weight; must be the same as in Console::TakeSnapshot()
                                  !!fTakingSnapshotOnline,
-                                 &fNeedsSaveSettings);
+                                 &fNeedsGlobalSaveSettings);
         if (FAILED(rc))
             throw rc;
@@ -1501,5 +1501,5 @@
         *aStateFilePath = NULL;
 
-    // @todo r=dj normally we would need to save the settings if fNeedsSaveSettings was set to true,
+    // @todo r=dj normally we would need to save the settings if fNeedsGlobalSaveSettings was set to true,
     // but since we have no error handling that cleans up the diff image that might have gotten created,
     // there's no point in saving the disk registry at this point either... this needs fixing.
@@ -2320,5 +2320,5 @@
 
     bool fMachineSettingsChanged = false;       // Machine
-    bool fNeedsSaveSettings = false;            // VirtualBox.xml
+    bool fNeedsGlobalSaveSettings = false;            // VirtualBox.xml
 
     Guid snapshotId;
@@ -2564,5 +2564,5 @@
                                                 true /* aWait */,
                                                 &fNeedsSave);
-                    fNeedsSaveSettings |= fNeedsSave;
+                    fNeedsGlobalSaveSettings |= fNeedsSave;
                     if (FAILED(rc))
                         throw rc;
@@ -2607,5 +2607,5 @@
                                                &fNeedsSave);
                 }
-                fNeedsSaveSettings |= fNeedsSave;
+                fNeedsGlobalSaveSettings |= fNeedsSave;
 
                 // If the merge failed, we need to do our best to have a usable
@@ -2754,5 +2754,5 @@
         updateMachineStateOnClient();
 
-        if (fMachineSettingsChanged || fNeedsSaveSettings)
+        if (fMachineSettingsChanged || fNeedsGlobalSaveSettings)
         {
             if (fMachineSettingsChanged)
@@ -2765,8 +2765,8 @@
                 // then, as it avoids a rather costly config equality check
                 // when we know that it is changed.
-                saveSettings(&fNeedsSaveSettings, SaveS_Force | SaveS_InformCallbacksAnyway);
+                saveSettings(&fNeedsGlobalSaveSettings, SaveS_Force | SaveS_InformCallbacksAnyway);
             }
 
-            if (fNeedsSaveSettings)
+            if (fNeedsGlobalSaveSettings)
             {
                 AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
@@ -3137,5 +3137,5 @@
  *                      return NULL if no real merge is necessary).
  * @param aProgress     Progress indicator.
- * @param pfNeedsSaveSettings Whether the VM settings need to be saved (out).
+ * @param pfNeedsMachineSaveSettings Whether the VM settings need to be saved (out).
  */
 HRESULT SessionMachine::onlineMergeMedium(const ComObjPtr<MediumAttachment> &aMediumAttachment,
@@ -3147,5 +3147,5 @@
                                           MediumLockList *aMediumLockList,
                                           ComObjPtr<Progress> &aProgress,
-                                          bool *pfNeedsSaveSettings)
+                                          bool *pfNeedsMachineSaveSettings)
 {
     AssertReturn(aSource != NULL, E_FAIL);
@@ -3225,6 +3225,6 @@
     // The callback mentioned above takes care of update the medium state
 
-    if (pfNeedsSaveSettings)
-        *pfNeedsSaveSettings = true;
+    if (pfNeedsMachineSaveSettings)
+        *pfNeedsMachineSaveSettings = true;
 
     return rc;
@@ -3260,7 +3260,9 @@
     if (aMergeForward)
     {
+        Guid uuidRegistry = pTarget->getRegistryId();
+
         // first, unregister the target since it may become a base
         // hard disk which needs re-registration
-        rc = mParent->unregisterHardDisk(pTarget, NULL /*&fNeedsSaveSettings*/);
+        rc = mParent->unregisterHardDisk(pTarget, NULL /*&fNeedsGlobalSaveSettings*/);
         AssertComRC(rc);
 
@@ -3273,5 +3275,5 @@
 
         // then, register again
-        rc = mParent->registerHardDisk(pTarget, NULL /*&fNeedsSaveSettings*/);
+        rc = mParent->registerHardDisk(pTarget, NULL /*&fNeedsGlobalSaveSettings*/);
         AssertComRC(rc);
     }
@@ -3344,5 +3346,5 @@
         {
             rc = mParent->unregisterHardDisk(pMedium,
-                                             NULL /*pfNeedsSaveSettings*/);
+                                             NULL /*pfNeedsGlobalSaveSettings*/);
             AssertComRC(rc);
 
Index: /trunk/src/VBox/Main/VirtualBoxImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/VirtualBoxImpl.cpp	(revision 31614)
+++ /trunk/src/VBox/Main/VirtualBoxImpl.cpp	(revision 31615)
@@ -240,5 +240,7 @@
           threadAsyncEvent(NIL_RTTHREAD),
           pAsyncEventQ(NULL)
-    {}
+    {
+        unconst(uuidMediaRegistry).create();
+    }
 
     ~Data()
@@ -257,4 +259,7 @@
     const Utf8Str                       strSettingsFilePath;
     settings::MainConfigFile            *pMainConfigFile;
+
+    // pseudo machine ID for global media registry (recreated on every startup)
+    const Guid                          uuidMediaRegistry;
 
     // const objects not requiring locking
@@ -465,5 +470,6 @@
 
         /* all registered media, needed by machines */
-        if (FAILED(rc = initMedia()))
+        if (FAILED(rc = initMedia(m->uuidMediaRegistry,
+                                  m->pMainConfigFile->mediaRegistry)))
             throw rc;
 
@@ -593,12 +599,37 @@
 }
 
-HRESULT VirtualBox::initMedia()
-{
+/**
+ * Loads a media registry from XML and adds the media contained therein to
+ * the global lists of known media.
+ *
+ * This now (3.3) gets called from two locations:
+ *
+ *  --  VirtualBox::init(), to load the global media registry from VirtualBox.xml;
+ *
+ *  --  Machine::loadMachineDataFromSettings(), to load the per-machine registry
+ *      from machine XML, for machines created with VirtualBox 3.3 or later.
+ *
+ * In both cases, the media found are added to the global lists so the
+ * global arrays of media (including the GUI's virtual media manager)
+ * continue to work as before.
+ *
+ * @param uuidMachineRegistry The UUID of the media registry. This is either the
+ *       transient UUID created at VirtualBox startup for the global registry or
+ *       a machine ID.
+ * @param mediaRegistry The XML settings structure to load, either from VirtualBox.xml
+ *       or a machine XML.
+ * @return
+ */
+HRESULT VirtualBox::initMedia(const Guid &uuidRegistry,
+                              const settings::MediaRegistry mediaRegistry)
+{
+    LogFlow(("VirtualBox::initMedia ENTERING, uuidRegistry=%s\n", uuidRegistry.toString().c_str()));
+
     AutoWriteLock treeLock(getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
 
     HRESULT rc = S_OK;
     settings::MediaList::const_iterator it;
-    for (it = m->pMainConfigFile->mediaRegistry.llHardDisks.begin();
-         it != m->pMainConfigFile->mediaRegistry.llHardDisks.end();
+    for (it = mediaRegistry.llHardDisks.begin();
+         it != mediaRegistry.llHardDisks.end();
          ++it)
     {
@@ -608,15 +639,17 @@
         if (SUCCEEDED(rc = pHardDisk.createObject()))
             rc = pHardDisk->init(this,
-                                 NULL,           // parent
+                                 NULL,          // parent
                                  DeviceType_HardDisk,
-                                 xmlHD);         // XML data; this recurses to processes the children
+                                 uuidRegistry,
+                                 xmlHD);        // XML data; this recurses to processes the children
         if (FAILED(rc)) return rc;
 
-        rc = registerHardDisk(pHardDisk, NULL /*pfNeedsSaveSettings*/ );
+        rc = registerHardDisk(pHardDisk,
+                              NULL /*pfNeedsGlobalSaveSettings*/ );
         if (FAILED(rc)) return rc;
     }
 
-    for (it = m->pMainConfigFile->mediaRegistry.llDvdImages.begin();
-         it != m->pMainConfigFile->mediaRegistry.llDvdImages.end();
+    for (it = mediaRegistry.llDvdImages.begin();
+         it != mediaRegistry.llDvdImages.end();
          ++it)
     {
@@ -625,13 +658,19 @@
         ComObjPtr<Medium> pImage;
         if (SUCCEEDED(pImage.createObject()))
-            rc = pImage->init(this, NULL, DeviceType_DVD, xmlDvd);
+            rc = pImage->init(this,
+                              NULL,
+                              DeviceType_DVD,
+                              uuidRegistry,
+                              xmlDvd);
         if (FAILED(rc)) return rc;
 
-        rc = registerImage(pImage, DeviceType_DVD, NULL /*pfNeedsSaveSettings*/ );
+        rc = registerImage(pImage,
+                           DeviceType_DVD,
+                           NULL /*pfNeedsGlobalSaveSettings*/ );
         if (FAILED(rc)) return rc;
     }
 
-    for (it = m->pMainConfigFile->mediaRegistry.llFloppyImages.begin();
-         it != m->pMainConfigFile->mediaRegistry.llFloppyImages.end();
+    for (it = mediaRegistry.llFloppyImages.begin();
+         it != mediaRegistry.llFloppyImages.end();
          ++it)
     {
@@ -640,10 +679,18 @@
         ComObjPtr<Medium> pImage;
         if (SUCCEEDED(pImage.createObject()))
-            rc = pImage->init(this, NULL, DeviceType_Floppy, xmlFloppy);
+            rc = pImage->init(this,
+                              NULL,
+                              DeviceType_Floppy,
+                              uuidRegistry,
+                              xmlFloppy);
         if (FAILED(rc)) return rc;
 
-        rc = registerImage(pImage, DeviceType_Floppy, NULL /*pfNeedsSaveSettings*/ );
+        rc = registerImage(pImage,
+                           DeviceType_Floppy,
+                           NULL /*pfNeedsGlobalSaveSettings*/ );
         if (FAILED(rc)) return rc;
     }
+
+    LogFlow(("VirtualBox::initMedia LEAVING\n"));
 
     return S_OK;
@@ -1328,19 +1375,18 @@
         getDefaultHardDiskFormat(format);
 
-    HRESULT rc = E_FAIL;
-
-    bool fNeedsSaveSettings = false;
+    bool fNeedsGlobalSaveSettings = false;
 
     ComObjPtr<Medium> hardDisk;
     hardDisk.createObject();
-    rc = hardDisk->init(this,
-                        format,
-                        aLocation,
-                        &fNeedsSaveSettings);
+    HRESULT rc = hardDisk->init(this,
+                                format,
+                                aLocation,
+                                Guid::Empty,        // media registry
+                                &fNeedsGlobalSaveSettings);
 
     if (SUCCEEDED(rc))
         hardDisk.queryInterfaceTo(aHardDisk);
 
-    if (fNeedsSaveSettings)
+    if (fNeedsGlobalSaveSettings)
     {
         AutoWriteLock vboxlock(this COMMA_LOCKVAL_SRC_POS);
@@ -1362,6 +1408,8 @@
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
+    bool fNeedsGlobalSaveSettings = false;
+    ComObjPtr<Medium> pMedium;
+
     /* we don't access non-const data members so no need to lock */
-    HRESULT rc = E_FAIL;
 
     switch (deviceType)
@@ -1379,15 +1427,12 @@
     }
 
-    ComObjPtr<Medium> pMedium;
     pMedium.createObject();
-    rc = pMedium->init(this,
-                       aLocation,
-                       (accessMode == AccessMode_ReadWrite) ? Medium::OpenReadWrite : Medium::OpenReadOnly,
-                       deviceType);
+    HRESULT rc = pMedium->init(this,
+                               aLocation,
+                               (accessMode == AccessMode_ReadWrite) ? Medium::OpenReadWrite : Medium::OpenReadOnly,
+                               deviceType);
 
     if (SUCCEEDED(rc))
     {
-        bool fNeedsGlobalSaveSettings = false;
-
         AutoWriteLock treeLock(getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
 
@@ -1395,10 +1440,13 @@
         {
             case DeviceType_HardDisk:
-                rc = registerHardDisk(pMedium, &fNeedsGlobalSaveSettings);
+                rc = registerHardDisk(pMedium,
+                                      &fNeedsGlobalSaveSettings);
             break;
 
             case DeviceType_DVD:
             case DeviceType_Floppy:
-                rc = registerImage(pMedium, deviceType, &fNeedsGlobalSaveSettings);
+                rc = registerImage(pMedium,
+                                   deviceType,
+                                   &fNeedsGlobalSaveSettings);
             break;
         }
@@ -1410,14 +1458,15 @@
          * with the parent and this association needs to be broken. */
 
-        if (SUCCEEDED(rc))
-            pMedium.queryInterfaceTo(aMedium);
-        else
+        if (FAILED(rc))
             pMedium->uninit();
-
-        if (fNeedsGlobalSaveSettings)
-        {
-            AutoWriteLock vboxlock(this COMMA_LOCKVAL_SRC_POS);
-            saveSettings();
-        }
+    }
+
+    if (SUCCEEDED(rc))
+        pMedium.queryInterfaceTo(aMedium);
+
+    if (fNeedsGlobalSaveSettings)
+    {
+        AutoWriteLock vboxlock(this COMMA_LOCKVAL_SRC_POS);
+        saveSettings();
     }
 
@@ -2749,4 +2798,23 @@
 }
 
+/**
+ * Returns the pseudo-machine UUID that is created on each VirtualBox startup
+ * and that is used to identify the global media registry.
+ *
+ * Starting with VirtualBox 3.3 each medium remembers in its instance data
+ * in which media registry it is saved (if any): this can either be a machine
+ * UUID, if it's in a per-machine media registry, or this global ID.
+ *
+ * This UUID is only used to identify the VirtualBox object while VirtualBox
+ * is running. It is not saved anywhere and thus gets recreated with every
+ * VirtualBox startup.
+ *
+ * @return
+ */
+const Guid& VirtualBox::getGlobalRegistryId() const
+{
+    return m->uuidMediaRegistry;
+}
+
 const ComObjPtr<Host>& VirtualBox::host() const
 {
@@ -2857,4 +2925,18 @@
 // private methods
 /////////////////////////////////////////////////////////////////////////////
+
+Utf8Str VirtualBox::getRegistryPath(Medium *pMedium)
+{
+    const Guid &rid = pMedium->getRegistryId();
+
+    if (!rid.isEmpty())
+    {
+        if (rid == getGlobalRegistryId())
+            return settingsFilePath();
+
+        return rid.toString();
+    }
+    return "[null]";
+}
 
 /**
@@ -2957,4 +3039,85 @@
 
 /**
+ * Goes through all known media (hard disks, floppies and DVDs) and saves
+ * those into the given settings::MediaRegistry structures whose registry
+ * ID match the given UUID.
+ *
+ * This gets called from two contexts:
+ *
+ *  -- VirtualBox::saveSettings() with the UUID of the global registry
+ *     (VirtualBox::Data.uuidRegistry); this will save those media
+ *     which had been loaded from the global registry or have been
+ *     attached to a "legacy" machine which can't save its own registry;
+ *
+ *  -- Machine::saveSettings() with the UUID of a machine, if a medium
+ *     has been attached to a machine created with VirtualBox 3.3 or later.
+ *
+ * Media which have only been temporarily opened without having been
+ * attached to a machine have a NULL registry UUID and therefore don't
+ * get saved.
+ *
+ * This throws HRESULT on errors!
+ *
+ * @param mediaRegistry
+ * @param uuidRegistry
+ * @return
+ */
+void VirtualBox::saveMediaRegistry(settings::MediaRegistry &mediaRegistry,
+                                   const Guid &uuidRegistry)
+{
+    HRESULT rc;
+    // hard disks
+    mediaRegistry.llHardDisks.clear();
+    for (MediaList::const_iterator it = m->allHardDisks.begin();
+         it != m->allHardDisks.end();
+         ++it)
+    {
+        Medium *pMedium = *it;
+        // is medium in global registry:?
+        if (pMedium->getRegistryId() == uuidRegistry)
+        {
+            settings::Medium med;
+            rc = pMedium->saveSettings(med);     // this recurses into its children
+            if (FAILED(rc)) throw rc;
+            mediaRegistry.llHardDisks.push_back(med);
+        }
+    }
+
+    // CD/DVD images
+    mediaRegistry.llDvdImages.clear();
+    for (MediaList::const_iterator it = m->allDVDImages.begin();
+         it != m->allDVDImages.end();
+         ++it)
+    {
+        Medium *pMedium = *it;
+        // is medium in global registry:?
+        if (pMedium->getRegistryId() == uuidRegistry)
+        {
+            settings::Medium med;
+            rc = pMedium->saveSettings(med);
+            if (FAILED(rc)) throw rc;
+            mediaRegistry.llDvdImages.push_back(med);
+        }
+    }
+
+    // floppy images
+    mediaRegistry.llFloppyImages.clear();
+    for (MediaList::const_iterator it = m->allFloppyImages.begin();
+         it != m->allFloppyImages.end();
+         ++it)
+    {
+        Medium *pMedium = *it;
+        // is medium in global registry:?
+        if (pMedium->getRegistryId() == uuidRegistry)
+        {
+            settings::Medium med;
+            rc = pMedium->saveSettings(med);
+            if (FAILED(rc)) throw rc;
+            mediaRegistry.llFloppyImages.push_back(med);
+        }
+    }
+}
+
+/**
  *  Helper function which actually writes out VirtualBox.xml, the main configuration file.
  *  Gets called from the public VirtualBox::SaveSettings() as well as from various other
@@ -3019,7 +3182,11 @@
                      ++it2)
                 {
-                    const Data::PendingMachineRename &pmr = *it2;
-                    pMedium->updatePath(pmr.strConfigDirOld,
-                                        pmr.strConfigDirNew);
+                    // is medium in global registry:?
+                    if (pMedium->getRegistryId() == m->uuidMediaRegistry)
+                    {
+                        const Data::PendingMachineRename &pmr = *it2;
+                        pMedium->updatePath(pmr.strConfigDirOld,
+                                            pmr.strConfigDirNew);
+                    }
                 }
             }
@@ -3028,39 +3195,6 @@
         }
 
-        // hard disks
-        m->pMainConfigFile->mediaRegistry.llHardDisks.clear();
-        for (MediaList::const_iterator it = m->allHardDisks.begin();
-             it != m->allHardDisks.end();
-             ++it)
-        {
-            settings::Medium med;
-            rc = (*it)->saveSettings(med);     // this recurses into its children
-            if (FAILED(rc)) throw rc;
-            m->pMainConfigFile->mediaRegistry.llHardDisks.push_back(med);
-        }
-
-        /* CD/DVD images */
-        m->pMainConfigFile->mediaRegistry.llDvdImages.clear();
-        for (MediaList::const_iterator it = m->allDVDImages.begin();
-             it != m->allDVDImages.end();
-             ++it)
-        {
-            settings::Medium med;
-            rc = (*it)->saveSettings(med);
-            if (FAILED(rc)) throw rc;
-            m->pMainConfigFile->mediaRegistry.llDvdImages.push_back(med);
-        }
-
-        /* floppy images */
-        m->pMainConfigFile->mediaRegistry.llFloppyImages.clear();
-        for (MediaList::const_iterator it = m->allFloppyImages.begin();
-             it != m->allFloppyImages.end();
-             ++it)
-        {
-            settings::Medium med;
-            rc = (*it)->saveSettings(med);
-            if (FAILED(rc)) throw rc;
-            m->pMainConfigFile->mediaRegistry.llFloppyImages.push_back(med);
-        }
+        saveMediaRegistry(m->pMainConfigFile->mediaRegistry,
+                          m->uuidMediaRegistry);
 
         mediaLock.release();
@@ -3169,21 +3303,24 @@
 
 /**
- * Remembers the given hard disk by storing it in the hard disk registry.
- *
- * @param aHardDisk     Hard disk object to remember.
- * @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
+ * Remembers the given hard disk by storing it in either the global hard disk registry
+ * or a machine one.
+ *
+ * @note Caller must hold the media tree lock for writing; in addition, this locks @a aHardDisk for reading
+ *
+ * @param aHardDisk Hard disk object to remember.
+ * @param uuidMachineRegistry UUID of machine whose registry should be used, or a NULL UUID for the global registry.
+ * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
  *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
- *
- * @note Caller must hold the media tree lock for writing; in addition, this locks @a aHardDisk for reading
- */
-HRESULT VirtualBox::registerHardDisk(Medium *aHardDisk,
-                                     bool *pfNeedsSaveSettings)
-{
-    AssertReturn(aHardDisk != NULL, E_INVALIDARG);
+ * @return
+ */
+HRESULT VirtualBox::registerHardDisk(Medium *pMedium,
+                                     bool *pfNeedsGlobalSaveSettings)
+{
+    AssertReturn(pMedium != NULL, E_INVALIDARG);
 
     AutoCaller autoCaller(this);
     AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
 
-    AutoCaller hardDiskCaller(aHardDisk);
+    AutoCaller hardDiskCaller(pMedium);
     AssertComRCReturn(hardDiskCaller.rc(), hardDiskCaller.rc());
 
@@ -3195,8 +3332,8 @@
     ComObjPtr<Medium> pParent;
     {
-        AutoReadLock hardDiskLock(aHardDisk COMMA_LOCKVAL_SRC_POS);
-        id = aHardDisk->getId();
-        strLocationFull = aHardDisk->getLocationFull();
-        pParent = aHardDisk->getParent();
+        AutoReadLock hardDiskLock(pMedium COMMA_LOCKVAL_SRC_POS);
+        id = pMedium->getId();
+        strLocationFull = pMedium->getLocationFull();
+        pParent = pMedium->getParent();
     }
 
@@ -3210,21 +3347,25 @@
 
     if (strConflict.length())
+    {
         return setError(E_INVALIDARG,
-                        tr("Cannot register the hard disk '%s' with UUID {%RTuuid} because a %s already exists in the media registry ('%s')"),
+                        tr("Cannot register the hard disk '%s' {%RTuuid} because a %s already exists"),
                         strLocationFull.c_str(),
                         id.raw(),
                         strConflict.c_str(),
                         m->strSettingsFilePath.c_str());
+    }
 
     // store base (root) hard disks in the list
     if (pParent.isNull())
-        m->allHardDisks.getList().push_back(aHardDisk);
+        m->allHardDisks.getList().push_back(pMedium);
                 // access the list directly because we already locked the list above
 
     // store all hard disks (even differencing images) in the map
-    m->mapHardDisks[id] = aHardDisk;
-
-    if (pfNeedsSaveSettings)
-        *pfNeedsSaveSettings = true;
+    m->mapHardDisks[id] = pMedium;
+
+    if (pfNeedsGlobalSaveSettings)
+        // global settings need saving only if the medium is to be saved in the global registry
+        if (pMedium->getRegistryId() == m->uuidMediaRegistry)
+            *pfNeedsGlobalSaveSettings = true;
 
     return rc;
@@ -3235,5 +3376,5 @@
  *
  * @param aHardDisk     Hard disk object to remove.
- * @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
+ * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
  *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
  *
@@ -3241,5 +3382,5 @@
  */
 HRESULT VirtualBox::unregisterHardDisk(Medium *aHardDisk,
-                                       bool *pfNeedsSaveSettings)
+                                       bool *pfNeedsGlobalSaveSettings)
 {
     AssertReturn(aHardDisk != NULL, E_INVALIDARG);
@@ -3272,6 +3413,8 @@
     NOREF(cnt);
 
-    if (pfNeedsSaveSettings)
-        *pfNeedsSaveSettings = true;
+    if (pfNeedsGlobalSaveSettings)
+        // global settings need saving only if the medium is to be saved in the global registry
+        if (aHardDisk->getRegistryId() == m->uuidMediaRegistry)
+            *pfNeedsGlobalSaveSettings = true;
 
     return S_OK;
@@ -3283,19 +3426,20 @@
  * @param argImage      Image object to remember.
  * @param argType       Either DeviceType_DVD or DeviceType_Floppy.
- * @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
+ * @param uuidMachineRegistry UUID of machine whose registry should be used, or a NULL UUID for the global registry.
+ * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
  *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
  *
  * @note Caller must hold the media tree lock for writing; in addition, this locks @a argImage for reading
  */
-HRESULT VirtualBox::registerImage(Medium *argImage,
+HRESULT VirtualBox::registerImage(Medium *pMedium,
                                   DeviceType_T argType,
-                                  bool *pfNeedsSaveSettings)
-{
-    AssertReturn(argImage != NULL, E_INVALIDARG);
+                                  bool *pfNeedsGlobalSaveSettings)
+{
+    AssertReturn(pMedium != NULL, E_INVALIDARG);
 
     AutoCaller autoCaller(this);
     AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
 
-    AutoCaller imageCaller(argImage);
+    AutoCaller imageCaller(pMedium);
     AssertComRCReturn(imageCaller.rc(), imageCaller.rc());
 
@@ -3307,8 +3451,8 @@
     ComObjPtr<Medium> pParent;
     {
-        AutoReadLock al(argImage COMMA_LOCKVAL_SRC_POS);
-        id = argImage->getId();
-        strLocationFull = argImage->getLocationFull();
-        pParent = argImage->getParent();
+        AutoReadLock al(pMedium COMMA_LOCKVAL_SRC_POS);
+        id = pMedium->getId();
+        strLocationFull = pMedium->getLocationFull();
+        pParent = pMedium->getParent();
     }
 
@@ -3322,22 +3466,24 @@
     Utf8Str strConflict;
     rc = checkMediaForConflicts2(id,
-                                    strLocationFull,
-                                    strConflict);
+                                 strLocationFull,
+                                 strConflict);
     if (FAILED(rc)) return rc;
 
     if (strConflict.length())
         return setError(VBOX_E_INVALID_OBJECT_STATE,
-                        tr("Cannot register the image '%s' with UUID {%RTuuid} because a %s already exists in the media registry ('%s')"),
+                        tr("Cannot register the image '%s' with UUID {%RTuuid} from '%s' because a %s already exists"),
                         strLocationFull.c_str(),
                         id.raw(),
-                        strConflict.c_str(),
-                        m->strSettingsFilePath.c_str());
+                        getRegistryPath(pMedium).c_str(),
+                        strConflict.c_str());
 
     // add to the collection
-    all.getList().push_back(argImage);
+    all.getList().push_back(pMedium);
             // access the list directly because we already locked the list above
 
-    if (pfNeedsSaveSettings)
-        *pfNeedsSaveSettings = true;
+    if (pfNeedsGlobalSaveSettings)
+        // global settings need saving only if the medium is to be saved in the global registry
+        if (pMedium->getRegistryId() == m->uuidMediaRegistry)
+            *pfNeedsGlobalSaveSettings = true;
 
     return rc;
@@ -3349,5 +3495,5 @@
  * @param argImage        Image object to remove.
  * @param argType         Either DeviceType_DVD or DeviceType_Floppy.
- * @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
+ * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
  *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
  *
@@ -3356,5 +3502,5 @@
 HRESULT VirtualBox::unregisterImage(Medium *argImage,
                                     DeviceType_T argType,
-                                    bool *pfNeedsSaveSettings)
+                                    bool *pfNeedsGlobalSaveSettings)
 {
     AssertReturn(argImage != NULL, E_INVALIDARG);
@@ -3385,6 +3531,8 @@
     HRESULT rc = S_OK;
 
-    if (pfNeedsSaveSettings)
-        *pfNeedsSaveSettings = true;
+    if (pfNeedsGlobalSaveSettings)
+        // global settings need saving only if the medium is to be saved in the global registry
+        if (argImage->getRegistryId() == m->uuidMediaRegistry)
+            *pfNeedsGlobalSaveSettings = true;
 
     return rc;
@@ -3395,10 +3543,10 @@
  * Called from Machine::Unregister().
  * @param pMachine
+ * @param id  UUID of the machine. Must be passed by caller because machine may be dead by this time.
  * @return
  */
-HRESULT VirtualBox::unregisterMachine(Machine *pMachine)
-{
-    const Guid &id = pMachine->getId();
-
+HRESULT VirtualBox::unregisterMachine(Machine *pMachine,
+                                      const Guid &id)
+{
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 31614)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 31615)
@@ -1437,5 +1437,5 @@
     <attribute name="DVDImages" type="IMedium" readonly="yes" safearray="yes">
       <desc>
-        Array of CD/DVD image objects registered with this VirtualBox instance.
+        Array of CD/DVD image objects currently in use by this VirtualBox instance.
       </desc>
     </attribute>
@@ -1443,5 +1443,5 @@
     <attribute name="floppyImages" type="IMedium" readonly="yes" safearray="yes">
       <desc>
-        Array of floppy image objects registered with this VirtualBox instance.
+        Array of floppy image objects currently in use by this VirtualBox instance.
       </desc>
     </attribute>
@@ -1705,9 +1705,7 @@
         created by one of the above methods.
 
-        After the storage unit is successfully created, the medium gets
-        remembered by this VirtualBox installation and will be accessible
-        through the <link to="#findMedium"/> method. Remembered base medium
-        are also returned as part of the <link to="#hardDisks"/> array.
-        See <link to="IMedium" /> for more details.
+        After the storage unit is successfully created, it will be
+        accessible through the <link to="#findMedium"/> method and can
+        be found in the <link to="#hardDisks"/> array.
 
         The list of all storage formats supported by this VirtualBox
@@ -1749,12 +1747,6 @@
         Opens a medium from an existing storage location.
 
-        Once a medium has been opened, VirtualBox saves the medium in a media
-        registry. Prior to VirtualBox 3.3, this registry had to be the global
-        media registry in the VirtualBox.xml file, which was shared between
-        all machines and made transporting machines from one host to another
-        difficult. Now you can optionally specify an <link to="IMachine" />
-        instance, in which case the medium will be remembered in that machine's
-        registry. This is the recommended procedure for machines created with
-        VirtualBox 3.3 or later. <i>(not yet implemented)</i>
+        Once a medium has been opened, it can be passed to other VirtualBox
+        methods, in particular to <link to="IMachine::AttachDevice" />.
 
         Depending on the given device type, the file at the storage location
@@ -1806,4 +1798,16 @@
         <link to="IMedium::location"/>, IMedium and
         <link to="ISystemProperties::defaultHardDiskFolder"/> for more details.
+
+        Prior to VirtualBox 3.3, opening a medium added it to a global media
+        registry in the VirtualBox.xml file, which was shared between
+        all machines and made transporting machines and their media from one
+        host to another difficult.
+
+        Starting with VirtualBox 3.3, media are only added to a registry when
+        they are attached to a machine. Machines created with VirtualBox 3.3
+        or later can have their own media registry. As a result, a medium attached
+        to such a machine will be remembered in that machine's XML settings file.
+        Media attached to older machines will continue to be added to the global
+        registry.
 
         <result name="VBOX_E_FILE_ERROR">
@@ -2751,5 +2755,4 @@
         hard disk image. This means that on import the image will be copied and converted from the
         "ovf" location to the "vbox" location; on export, this will be handled the other way round.
-        On import, the target image will also be registered with VirtualBox.
 
         The matching item in the @a aExtraConfigValues[] array must contain a string of the following
@@ -4225,42 +4228,17 @@
         This method is intended for managing storage devices in general while a
         machine is powered off. It can be used to attach and detach fixed
-        and removeable media.
-
-        Starting with VirtualBox 3.3, media no longer have to be globally
-        registered before they can be attached to a virtual machine. For
-        compatibility with machines created by older versions of VirtualBox
-        and for greater flexibility with managing removable media, media
-        can still be registered globally. As a result, there are now
-        several variants of attaching media:
+        and removeable media. The following kind of media can be attached
+        to a machine:
 
         <ul>
-          <li>To directly attach a medium without first registering it
-            globally, simply pass the file name of its storage unit in the
-            @a medium string parameter. This works for all media formats
-            supported by the <li to="VirtualBox::openMedium" /> method.
-            The difference is that the medium will not be saved in the
-            global media registry, but only with the machine settings
-            XML file. For better portability of the machine as a whole,
-            it is recommended to place the storage unit in the machine's
-            folder as well.
+          <li>For fixed and removable media, you can pass in a medium that was
+            previously opened using <link to="VirtualBox::openMedium" />.
           </li>
 
-          <li>To attach a medium that has been globally registered using
-            <li to="VirtualBox::openMedium" />, call that method with the
-            full path of a storage unit. Then, retrieve the UUID of that
-            medium from its <link to="IMedium::id" /> attribute and pass
-            that UUID into this method. This way, the medium will be
-            saved in the global media registry in the VirtualBox.xml
-            settings file. This is still the recommended way to manage
-            removable media such as ISO and RAW files if they are to be
-            used by several virtual machines and the storage unit is not
-            located in the machine's directory.
-          </li>
-
           <li>Only for storage devices supporting removable media (such as
-            DVDs and floppies), you can also specify an empty string to
-            indicate an empty drive or the UUID of a host DVD or floppy
-            drive; those UUIDs can be obtained from <link to="IHost::DVDDrives" />
-            and <link to="IHost::floppyDrives"/>.
+            DVDs and floppies), you can also specify a null pointer to
+            indicate an empty drive or one of the medium objects listed
+            in the <link to="IHost::DVDDrives" /> and <link to="IHost::floppyDrives"/>
+            arrays to indicate a host drive.
             For removeable devices, you can also use <link to="IMachine::mountMedium"/>
             to change the media while the machine is running.
@@ -4326,9 +4304,10 @@
       </param>
       <param name="type" type="DeviceType" dir="in">
-        <desc>Device type of the attached device.</desc>
-      </param>
-      <param name="medium" type="wstring" dir="in">
-        <desc>Path of the storage unit or UUID of the medium or the UUID of a
-          host drive to mount, or an empty string for an empty drive.</desc>
+        <desc>Device type of the attached device. For media opened by
+        <link to="IVirtualBox::openMedium" />, this must match the device type
+        specified there.</desc>
+      </param>
+      <param name="medium" type="IMedium" dir="in">
+        <desc>Medium to mount or NULL for an empty drive.</desc>
       </param>
     </method>
Index: /trunk/src/VBox/Main/include/MachineImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MachineImpl.h	(revision 31614)
+++ /trunk/src/VBox/Main/include/MachineImpl.h	(revision 31615)
@@ -452,5 +452,5 @@
     STDMETHOD(GetBootOrder)(ULONG aPosition, DeviceType_T *aDevice);
     STDMETHOD(AttachDevice)(IN_BSTR aControllerName, LONG aControllerPort,
-                            LONG aDevice, DeviceType_T aType, IN_BSTR aId);
+                            LONG aDevice, DeviceType_T aType, IMedium *aMedium);
     STDMETHOD(DetachDevice)(IN_BSTR aControllerName, LONG aControllerPort, LONG aDevice);
     STDMETHOD(PassthroughDevice)(IN_BSTR aControllerName, LONG aControllerPort, LONG aDevice, BOOL aPassthrough);
@@ -1018,5 +1018,5 @@
                               MediumLockList *aMediumLockList,
                               ComObjPtr<Progress> &aProgress,
-                              bool *pfNeedsSaveSettings);
+                              bool *pfNeedsMachineSaveSettings);
 
     HRESULT lockMedia();
Index: /trunk/src/VBox/Main/include/MediumImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MediumImpl.h	(revision 31614)
+++ /trunk/src/VBox/Main/include/MediumImpl.h	(revision 31615)
@@ -72,8 +72,9 @@
                  const Utf8Str &aFormat,
                  const Utf8Str &aLocation,
-                 bool *pfNeedsSaveSettings);
+                 const Guid &uuidMachineRegistry,
+                 bool *pfNeedsGlobalSaveSettings);
 
     // initializer for opening existing media
-    // (VirtualBox::OpenHardDisk/DVD(); Machine::AttachDevice())
+    // (VirtualBox::OpenMedium(); Machine::AttachDevice())
     HRESULT init(VirtualBox *aVirtualBox,
                  const Utf8Str &aLocation,
@@ -85,4 +86,5 @@
                  Medium *aParent,
                  DeviceType_T aDeviceType,
+                 const Guid &uuidMachineRegistry,
                  const settings::Medium &data);
 
@@ -176,4 +178,7 @@
     Utf8Str getName();
 
+    void setRegistryIdIfFirst(const Guid& id);
+    const Guid& getRegistryId() const;
+
     HRESULT addBackReference(const Guid &aMachineId,
                              const Guid &aSnapshotId = Guid::Empty);
@@ -208,8 +213,8 @@
                               ComObjPtr<Progress> *aProgress,
                               bool aWait,
-                              bool *pfNeedsSaveSettings);
-
-    HRESULT close(bool *pfNeedsSaveSettings, AutoCaller &autoCaller);
-    HRESULT deleteStorage(ComObjPtr<Progress> *aProgress, bool aWait, bool *pfNeedsSaveSettings);
+                              bool *pfNeedsGlobalSaveSettings);
+
+    HRESULT close(bool *pfNeedsGlobalSaveSettings, AutoCaller &autoCaller);
+    HRESULT deleteStorage(ComObjPtr<Progress> *aProgress, bool aWait, bool *pfNeedsGlobalSaveSettings);
     HRESULT markForDeletion();
     HRESULT unmarkForDeletion();
@@ -232,5 +237,5 @@
                     ComObjPtr<Progress> *aProgress,
                     bool aWait,
-                    bool *pfNeedsSaveSettings);
+                    bool *pfNeedsGlobalSaveSettings);
     void cancelMergeTo(const MediaList &aChildrenToReparent,
                        MediumLockList *aMediumLockList);
@@ -246,5 +251,5 @@
 
     HRESULT canClose();
-    HRESULT unregisterWithVirtualBox(bool *pfNeedsSaveSettings);
+    HRESULT unregisterWithVirtualBox(bool *pfNeedsGlobalSaveSettings);
 
     HRESULT setStateError();
@@ -297,5 +302,5 @@
 
     HRESULT startThread(Medium::Task *pTask);
-    HRESULT runNow(Medium::Task *pTask, bool *pfNeedsSaveSettings);
+    HRESULT runNow(Medium::Task *pTask, bool *pfNeedsGlobalSaveSettings);
 
     HRESULT taskCreateBaseHandler(Medium::CreateBaseTask &task);
Index: /trunk/src/VBox/Main/include/VirtualBoxImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/VirtualBoxImpl.h	(revision 31614)
+++ /trunk/src/VBox/Main/include/VirtualBoxImpl.h	(revision 31615)
@@ -54,4 +54,5 @@
 {
     class MainConfigFile;
+    class MediaRegistry;
 }
 
@@ -96,5 +97,6 @@
     HRESULT init();
     HRESULT initMachines();
-    HRESULT initMedia();
+    HRESULT initMedia(const Guid &uuidMachineRegistry,
+                      const settings::MediaRegistry mediaRegistry);
     void uninit();
 
@@ -127,6 +129,7 @@
     STDMETHOD(CreateAppliance) (IAppliance **anAppliance);
 
-    STDMETHOD(CreateHardDisk)(IN_BSTR aFormat, IN_BSTR aLocation,
-                               IMedium **aHardDisk);
+    STDMETHOD(CreateHardDisk)(IN_BSTR aFormat,
+                              IN_BSTR aLocation,
+                              IMedium **aHardDisk);
     STDMETHOD(OpenMedium)(IN_BSTR aLocation,
                           DeviceType_T deviceType,
@@ -204,8 +207,8 @@
                            InternalControlList *aControls = NULL);
 
-    HRESULT findMachine (const Guid &aId,
-                         bool fPermitInaccessible,
-                         bool aSetError,
-                         ComObjPtr<Machine> *machine = NULL);
+    HRESULT findMachine(const Guid &aId,
+                        bool fPermitInaccessible,
+                        bool aSetError,
+                        ComObjPtr<Machine> *machine = NULL);
 
     HRESULT findHardDisk(const Guid *aId,
@@ -226,4 +229,6 @@
                             GuestOSType*& pGuestOSType);
 
+    const Guid& getGlobalRegistryId() const;
+
     const ComObjPtr<Host>& host() const;
     SystemProperties* getSystemProperties() const;
@@ -242,15 +247,17 @@
     void copyPathRelativeToConfig(const Utf8Str &strSource, Utf8Str &strTarget);
 
-    HRESULT registerHardDisk(Medium *aHardDisk, bool *pfNeedsSaveSettings);
-    HRESULT unregisterHardDisk(Medium *aHardDisk, bool *pfNeedsSaveSettings);
-
-    HRESULT registerImage(Medium *aImage, DeviceType_T argType, bool *pfNeedsSaveSettings);
-    HRESULT unregisterImage(Medium *aImage, DeviceType_T argType, bool *pfNeedsSaveSettings);
-
-    HRESULT unregisterMachine(Machine *pMachine);
+    HRESULT registerHardDisk(Medium *aHardDisk, bool *pfNeedsGlobalSaveSettings);
+    HRESULT unregisterHardDisk(Medium *aHardDisk, bool *pfNeedsGlobalSaveSettings);
+
+    HRESULT registerImage(Medium *aImage, DeviceType_T argType, bool *pfNeedsGlobalSaveSettings);
+    HRESULT unregisterImage(Medium *aImage, DeviceType_T argType, bool *pfNeedsGlobalSaveSettings);
+
+    HRESULT unregisterMachine(Machine *pMachine, const Guid &id);
 
     void rememberMachineNameChangeForMedia(const Utf8Str &strOldConfigDir,
                                            const Utf8Str &strNewConfigDir);
 
+    void saveMediaRegistry(settings::MediaRegistry &mediaRegistry,
+                           const Guid &uuidRegistry);
     HRESULT saveSettings();
 
@@ -271,4 +278,6 @@
     }
 
+    Utf8Str getRegistryPath(Medium *pMedium);
+
     HRESULT checkMediaForConflicts2(const Guid &aId, const Utf8Str &aLocation,
                                     Utf8Str &aConflictType);
Index: /trunk/src/VBox/Main/testcase/tstVBoxAPILinux.cpp
===================================================================
--- /trunk/src/VBox/Main/testcase/tstVBoxAPILinux.cpp	(revision 31614)
+++ /trunk/src/VBox/Main/testcase/tstVBoxAPILinux.cpp	(revision 31615)
@@ -330,15 +330,11 @@
             {
                 /*
-                 * Now that it's created, we can assign it to the VM. This is done
-                 * by UUID, so query that one fist. The UUID has been assigned automatically
-                 * when we've created the image.
+                 * Now that it's created, we can assign it to the VM.
                  */
-                nsXPIDLString vdiUUID;
-                hardDisk->GetId(getter_Copies(vdiUUID));
                 rc = machine->AttachDevice(NS_LITERAL_STRING("IDE Controller").get(), // controller identifier
                                            0,                              // channel number on the controller
                                            0,                              // device number on the controller
                                            DeviceType_HardDisk,
-                                           vdiUUID);
+                                           hardDisk);
                 if (NS_FAILED(rc))
                 {
Index: /trunk/src/VBox/Main/xml/Settings.cpp
===================================================================
--- /trunk/src/VBox/Main/xml/Settings.cpp	(revision 31614)
+++ /trunk/src/VBox/Main/xml/Settings.cpp	(revision 31615)
@@ -1742,4 +1742,15 @@
 
 /**
+ * Public routine which returns true if this machine config file can have its
+ * own media registry (which is true for settings version v1.11 and higher,
+ * i.e. files created by VirtualBox 3.3 and higher).
+ * @return
+ */
+bool MachineConfigFile::canHaveOwnMediaRegistry() const
+{
+    return (m->sv >= SettingsVersion_v1_11);
+}
+
+/**
  * Public routine which allows for importing machine XML from an external DOM tree.
  * Use this after having called the constructor with a NULL argument.
@@ -3097,4 +3108,6 @@
                 pelmMachineChild->getAttributeValue("password", machineUserData.strTeleporterPassword);
             }
+            else if (pelmMachineChild->nameEquals("MediaRegistry"))
+                readMediaRegistry(*pelmMachineChild, mediaRegistry);
         }
 
@@ -3998,4 +4011,9 @@
     }
 
+    if (    (fl & BuildMachineXML_MediaRegistry)
+         && (m->sv >= SettingsVersion_v1_11)
+       )
+        buildMediaRegistry(elmMachine, mediaRegistry);
+
     buildExtraData(elmMachine, mapExtraDataItems);
 
@@ -4009,9 +4027,4 @@
                                !!(fl & BuildMachineXML_SkipRemovableMedia),
                                pllElementsWithUuidAttributes);
-
-    if (    (fl & BuildMachineXML_MediaRegistry)
-         && (m->sv >= SettingsVersion_v1_11)
-       )
-        buildMediaRegistry(elmMachine, mediaRegistry);
 }
 
