Index: /trunk/src/VBox/Main/VirtualBoxImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/VirtualBoxImpl.cpp	(revision 17871)
+++ /trunk/src/VBox/Main/VirtualBoxImpl.cpp	(revision 17872)
@@ -92,4 +92,5 @@
     "    <MachineRegistry/>"RTFILE_LINEFEED
     "    <MediaRegistry/>"RTFILE_LINEFEED
+    "    <NetserviceRegistry/>"RTFILE_LINEFEED
     "    <USBDeviceFilters/>"RTFILE_LINEFEED
     "    <SystemProperties/>"RTFILE_LINEFEED
@@ -290,4 +291,8 @@
             CheckComRCThrowRC (rc);
 
+            /* net services */
+            rc = loadNetservices(global);
+            CheckComRCThrowRC (rc);
+
             /* check hard disk consistency */
 /// @todo (r=dmik) add IVirtualBox::cleanupHardDisks() instead or similar
@@ -3113,4 +3118,56 @@
 
 /**
+ *  Reads in the network service registration entries from the global settings file
+ *  and creates the relevant objects.
+ *
+ *  @param aGlobal  <Global> node
+ *
+ *  @note Can be called only from #init().
+ *  @note Doesn't lock anything.
+ */
+HRESULT VirtualBox::loadNetservices (const settings::Key &aGlobal)
+{
+    using namespace settings;
+
+    AutoCaller autoCaller (this);
+    AssertReturn (autoCaller.state() == InInit, E_FAIL);
+
+    HRESULT rc = S_OK;
+
+    Key registry = aGlobal.findKey ("NetserviceRegistry");
+    if(registry.isNull())
+        return S_OK;
+
+    const char *kMediaNodes[] = { "DhcpServers" };
+
+    for (size_t n = 0; n < RT_ELEMENTS (kMediaNodes); ++ n)
+    {
+        /* All three media nodes are optional */
+        Key node = registry.findKey (kMediaNodes [n]);
+        if (node.isNull())
+            continue;
+
+        if (n == 0)
+        {
+            Key::List dhcpServers = node.keys ("DhcpServer");
+            for (Key::List::const_iterator it = dhcpServers.begin();
+                 it != dhcpServers.end(); ++ it)
+            {
+                ComObjPtr<DhcpServer> dhcpServer;
+                dhcpServer.createObject();
+                rc = dhcpServer->init (*it);
+                CheckComRCBreakRC (rc);
+
+                rc = registerDhcpServer(dhcpServer, false /* aSaveRegistry */);
+                CheckComRCBreakRC (rc);
+            }
+
+            continue;
+        }
+    }
+   return rc;
+}
+
+/**
  *  Helper function to write out the configuration tree.
  *
@@ -3210,4 +3267,28 @@
                 {
                     rc = (*it)->saveSettings (imagesNode);
+                    CheckComRCThrowRC (rc);
+                }
+            }
+        }
+
+        /* netservices */
+        {
+            /* first, delete the entire netservice registry */
+            Key registryNode = global.findKey ("NetserviceRegistry");
+            if (!registryNode.isNull())
+                registryNode.zap();
+            /* then, recreate it */
+            registryNode = global.createKey ("NetserviceRegistry");
+
+            /* hard disks */
+            {
+                Key dhcpServersNode = registryNode.createKey ("DhcpServers");
+
+                for (DhcpServerList::const_iterator it =
+                        mData.mDhcpServers.begin();
+                     it != mData.mDhcpServers.end();
+                     ++ it)
+                {
+                    rc = (*it)->saveSettings (dhcpServersNode);
                     CheckComRCThrowRC (rc);
                 }
@@ -4592,3 +4673,98 @@
 }
 
+/**
+ * Remembers the given dhcp server by storing it in the hard disk registry.
+ *
+ * @param aDhcpServer     Dhcp Server object to remember.
+ * @param aSaveRegistry @c true to save hard disk registry to disk (default).
+ *
+ * When @a aSaveRegistry is @c true, this operation may fail because of the
+ * failed #saveSettings() method it calls. In this case, the dhcp server object
+ * will not be remembered. It is therefore the responsibility of the caller to
+ * call this method as the last step of some action that requires registration
+ * in order to make sure that only fully functional dhcp server objects get
+ * registered.
+ *
+ * @note Locks this object for writing and @a aDhcpServer for reading.
+ */
+HRESULT VirtualBox::registerDhcpServer(DhcpServer *aDhcpServer,
+                                     bool aSaveRegistry /*= true*/)
+{
+    AssertReturn (aDhcpServer != NULL, E_INVALIDARG);
+
+    AutoCaller autoCaller (this);
+    AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
+
+    AutoWriteLock alock (this);
+
+    AutoCaller dhcpServerCaller (aDhcpServer);
+    AssertComRCReturn (dhcpServerCaller.rc(), dhcpServerCaller.rc());
+
+    AutoReadLock dhcpServerLock (aDhcpServer);
+
+    Bstr name;
+    HRESULT rc;
+    rc = aDhcpServer->COMGETTER(NetworkName) (name.asOutParam());
+    CheckComRCReturnRC (rc);
+
+    ComPtr<IDhcpServer> existing;
+    rc = FindDhcpServerByName(name.mutableRaw(), existing.asOutParam());
+    CheckComRCReturnRC (rc);
+
+    mData.mDhcpServers.push_back (aDhcpServer);
+
+    if (aSaveRegistry)
+    {
+        rc = saveSettings();
+        if (FAILED (rc))
+            unregisterDhcpServer(aDhcpServer, false /* aSaveRegistry */);
+    }
+
+    return rc;
+}
+
+/**
+ * Removes the given hard disk from the hard disk registry.
+ *
+ * @param aHardDisk     Hard disk object to remove.
+ * @param aSaveRegistry @c true to save hard disk registry to disk (default).
+ *
+ * When @a aSaveRegistry is @c true, this operation may fail because of the
+ * failed #saveSettings() method it calls. In this case, the hard disk object
+ * will NOT be removed from the registry when this method returns. It is
+ * therefore the responsibility of the caller to call this method as the first
+ * step of some action that requires unregistration, before calling uninit() on
+ * @a aHardDisk.
+ *
+ * @note Locks this object for writing and @a aHardDisk for reading.
+ */
+HRESULT VirtualBox::unregisterDhcpServer(DhcpServer *aDhcpServer,
+                                       bool aSaveRegistry /*= true*/)
+{
+    AssertReturn (aDhcpServer != NULL, E_INVALIDARG);
+
+    AutoCaller autoCaller (this);
+    AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
+
+    AutoWriteLock alock (this);
+
+    AutoCaller dhcpServerCaller (aDhcpServer);
+    AssertComRCReturn (dhcpServerCaller.rc(), dhcpServerCaller.rc());
+
+    AutoReadLock dhcpServerLock (aDhcpServer);
+
+    mData.mDhcpServers.remove (aDhcpServer);
+
+    HRESULT rc = S_OK;
+
+    if (aSaveRegistry)
+    {
+        rc = saveSettings();
+        if (FAILED (rc))
+            registerDhcpServer(aDhcpServer, false /* aSaveRegistry */);
+    }
+
+    return rc;
+}
+
 /* vi: set tabstop=4 shiftwidth=4 expandtab: */
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 17871)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 17872)
@@ -1219,5 +1219,5 @@
   
   <interface
-    name="IDhcpServer" extends="$dispatched"
+    name="IDhcpServer" extends="$unknown"
     uuid="f6de19f7-f4b5-4d93-b3de-664729267a53"
     wsmap="managed"
Index: /trunk/src/VBox/Main/include/VirtualBoxImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/VirtualBoxImpl.h	(revision 17871)
+++ /trunk/src/VBox/Main/include/VirtualBoxImpl.h	(revision 17872)
@@ -54,4 +54,5 @@
 class Host;
 class SystemProperties;
+class DhcpServer;
 
 #ifdef RT_OS_WINDOWS
@@ -372,4 +373,5 @@
     typedef std::list <ComObjPtr <FloppyImage> > FloppyImageList;
     typedef std::list <ComObjPtr <SharedFolder> > SharedFolderList;
+    typedef std::list <ComObjPtr <DhcpServer> > DhcpServerList;
 
     typedef std::map <Guid, ComObjPtr<HardDisk> > HardDiskMap;
@@ -390,6 +392,12 @@
     HRESULT loadMachines (const settings::Key &aGlobal);
     HRESULT loadMedia (const settings::Key &aGlobal);
+    HRESULT loadNetservices (const settings::Key &aGlobal);
 
     HRESULT registerMachine (Machine *aMachine);
+
+    HRESULT registerDhcpServer(DhcpServer *aDhcpServer,
+                                         bool aSaveRegistry = true);
+    HRESULT unregisterDhcpServer(DhcpServer *aDhcpServer,
+                                         bool aSaveRegistry = true);
 
     HRESULT lockConfig();
@@ -439,4 +447,5 @@
         FloppyImageList mFloppyImages;
         SharedFolderList mSharedFolders;
+        DhcpServerList mDhcpServers;
 
         /// @todo NEWMEDIA do we really need this map? Used only in
Index: /trunk/src/VBox/Main/xml/VirtualBox-settings-common.xsd
===================================================================
--- /trunk/src/VBox/Main/xml/VirtualBox-settings-common.xsd	(revision 17871)
+++ /trunk/src/VBox/Main/xml/VirtualBox-settings-common.xsd	(revision 17872)
@@ -255,4 +255,12 @@
 /////////////////////////////////////////////////////////////////////////
 -->
+<xsd:complexType name="TDhcpServer">
+  <xsd:attribute name="networkName" type="xsd:string"  use="required"/>
+  <xsd:attribute name="lowerIp"     type="xsd:string"  use="optional"/>
+  <xsd:attribute name="upperIp"     type="xsd:string"  use="optional"/>
+  <xsd:attribute name="IPAddress"   type="xsd:string"  use="required"/>
+  <xsd:attribute name="networkMask" type="xsd:string"  use="required"/>
+  <xsd:attribute name="enabled"     type="xsd:boolean" use="required"/>
+</xsd:complexType>
 
 <xsd:complexType name="THardDiskBase">
@@ -396,4 +404,17 @@
       </xsd:complexType>
     </xsd:element>
+    <xsd:element name="NetserviceRegistry" minOccurs="0" maxOccurs="1">
+      <xsd:complexType>
+        <xsd:all>
+          <xsd:element name="DhcpServers" minOccurs="0">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="DhcpServer" type="TDhcpServer" minOccurs="0" maxOccurs="unbounded"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:all>
+      </xsd:complexType>
+    </xsd:element>
     <xsd:element name="USBDeviceFilters">
       <xsd:complexType>
