Index: /trunk/include/VBox/log.h
===================================================================
--- /trunk/include/VBox/log.h	(revision 74760)
+++ /trunk/include/VBox/log.h	(revision 74761)
@@ -378,4 +378,6 @@
     /** Main group, IDataModel. */
     LOG_GROUP_MAIN_DATAMODEL,
+    /** Main group, IDataStream. */
+    LOG_GROUP_MAIN_DATASTREAM,
     /** Main group, IDHCPServer. */
     LOG_GROUP_MAIN_DHCPSERVER,
@@ -1010,4 +1012,5 @@
     "MAIN_CURSORPOSITIONCHANGEDEVENT", \
     "MAIN_DATAMODEL", \
+    "MAIN_DATASTREASTREAM", \
     "MAIN_DHCPSERVER", \
     "MAIN_DIRECTORY", \
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 74760)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 74761)
@@ -444,4 +444,10 @@
     <desc>
       Guest Control reported an error from the guest side.
+    </desc>
+  </result>
+
+  <result name="VBOX_E_TIMEOUT" value="0x80BB0010">
+    <desc>
+      The operation ran into an explicitly requested timeout.
     </desc>
   </result>
@@ -2621,9 +2627,9 @@
       </param>
       <param name="forceNewUuid" type="boolean" dir="in">
-         <desc>Allows the caller to request a completely new medium UUID for
-           the image which is to be opened. Useful if one intends to open an exact
-           copy of a previously opened image, as this would normally fail due to
-           the duplicate UUID.</desc>
-         </param>
+        <desc>Allows the caller to request a completely new medium UUID for
+          the image which is to be opened. Useful if one intends to open an exact
+          copy of a previously opened image, as this would normally fail due to
+          the duplicate UUID.</desc>
+        </param>
       <param name="medium" type="IMedium" dir="return">
         <desc>Opened medium object.</desc>
@@ -2884,8 +2890,8 @@
     </method>
 
-     <!--
+    <!--
           Returns the NATNetwork by name, e.g. for adding port forward rule or deletion.
-      -->
-     <method name="findNATNetworkByName">
+    -->
+    <method name="findNATNetworkByName">
       <param name="networkName" type="wstring" dir="in"/>
       <param name="network" type="INATNetwork" dir="return"/>
@@ -2893,7 +2899,7 @@
     <!--
         Deletes given NAT network.
-     -->
+    -->
     <method name="removeNATNetwork">
-       <param name="network" type="INATNetwork" dir="in"/>
+      <param name="network" type="INATNetwork" dir="in"/>
     </method>
 
@@ -5464,5 +5470,5 @@
         set by one of <link to="#takeSnapshot" />, <link to="#deleteSnapshot" />
         or <link to="#restoreSnapshot" />, depending on which was called last.
-       See <link to="ISnapshot"/> for details.
+        See <link to="ISnapshot"/> for details.
       </desc>
     </attribute>
@@ -6511,5 +6517,5 @@
       </result>
 
-       </desc>
+      </desc>
       <param name="name" type="wstring" dir="in">
       <desc>Name of the storage controller.</desc>
@@ -10250,21 +10256,21 @@
     <attribute name="proxyURL" type="wstring" readonly="no">
       <desc>
-       Proxy server URL for the <link to="ProxyMode::Manual" /> proxy mode.
-
-       The format is: [{type}"://"][{userid}[@{password}]:]{server}[":"{port}]
-
-       Valid types are: http (default), https, socks4, socks4a, socks5, socks5h and direct.
-       Please note that these are proxy types defining how the proxy operates rather than
-       how to proxy any similarly named protocol (i.e. don't confuse a http-proxy with
-       proxying the http protocol, as a http-proxy usually can proxy https and other protocols too).
-
-       The port number defaults to 80 for http, 443 for https and 1080 for the socks ones.
-
-       <note>The password is currently stored as plain text!  Use the <link to="ProxyMode::System" />
-       mode if you consider the proxy password to be sensitive.</note>
-
-       An empty string will cause the behavior to be identical to <link to="ProxyMode::System" />.
-       For compatibility with libproxy, an URL starting with "direct://" will cause
-       <link to="ProxyMode::NoProxy" /> behavior.
+        Proxy server URL for the <link to="ProxyMode::Manual" /> proxy mode.
+
+        The format is: [{type}"://"][{userid}[@{password}]:]{server}[":"{port}]
+
+        Valid types are: http (default), https, socks4, socks4a, socks5, socks5h and direct.
+        Please note that these are proxy types defining how the proxy operates rather than
+        how to proxy any similarly named protocol (i.e. don't confuse a http-proxy with
+        proxying the http protocol, as a http-proxy usually can proxy https and other protocols too).
+
+        The port number defaults to 80 for http, 443 for https and 1080 for the socks ones.
+
+        <note>The password is currently stored as plain text!  Use the <link to="ProxyMode::System" />
+        mode if you consider the proxy password to be sensitive.</note>
+
+        An empty string will cause the behavior to be identical to <link to="ProxyMode::System" />.
+        For compatibility with libproxy, an URL starting with "direct://" will cause
+        <link to="ProxyMode::NoProxy" /> behavior.
       </desc>
     </attribute>
@@ -11378,5 +11384,5 @@
       <desc>Process terminated abnormally.</desc>
     </const>
-     <const name="TimedOutKilled"       value="512">
+    <const name="TimedOutKilled"       value="512">
       <desc>Process timed out and was killed.</desc>
     </const>
@@ -11680,5 +11686,5 @@
     <attribute name="protocolVersion" type="unsigned long" readonly="yes">
       <desc>Returns the protocol version which is used to communicate
-       with the guest.</desc>
+        with the guest.</desc>
     </attribute>
 
@@ -12174,5 +12180,5 @@
               <td>Update</td>
               <td>Only copy when the source file is newer than the destination
-               file or when the destination file is missing.</td>
+                file or when the destination file is missing.</td>
             </tr>
           </table>
@@ -12229,5 +12235,5 @@
               <td>Update</td>
               <td>Only copy when the source file is newer than the destination
-               file or when the destination file is missing.</td>
+                file or when the destination file is missing.</td>
             </tr>
           </table>
@@ -12406,5 +12412,5 @@
           If @c false, a symbolic link in the final component will make the
           method return @c false (because a symlink isn't a directory).
-         </desc>
+        </desc>
       </param>
       <param name="exists" type="boolean" dir="return">
@@ -12483,5 +12489,5 @@
         <desc>Zero or more <link to="DirectoryRemoveRecFlag"/> flags.
           <note>WARNING! SPECIFYING <link to="DirectoryRemoveRecFlag_ContentAndDir"/> IS
-             MANDATORY AT THE MOMENT!!</note>
+            MANDATORY AT THE MOMENT!!</note>
         </desc>
       </param>
@@ -12670,5 +12676,5 @@
           characters in the template will be replaced by a random
           alphanumeric string to produce a unique name.
-         </desc>
+        </desc>
       </param>
       <param name="mode" type="unsigned long" dir="in">
@@ -12718,5 +12724,5 @@
           If @c false, a symbolic link in the final component will make the
           method return @c false (because a symlink isn't a regular file).
-         </desc>
+        </desc>
       </param>
       <param name="exists" type="boolean" dir="return">
@@ -12827,9 +12833,9 @@
       <param name="followSymlinks" type="boolean" dir="in">
         <desc>
-           It @c true, symbolic links in the final path component will be
-           followed to their target, and the size of the target is returned.
-           If @c false, symbolic links in the final path component will make
-           the method call fail (symblink is not a regular file).
-         </desc>
+          It @c true, symbolic links in the final path component will be
+          followed to their target, and the size of the target is returned.
+          If @c false, symbolic links in the final path component will make
+          the method call fail (symblink is not a regular file).
+        </desc>
       </param>
       <param name="size" type="long long" dir="return">
@@ -12855,9 +12861,9 @@
       <param name="followSymlinks" type="boolean" dir="in">
         <desc>
-           If @c true, symbolic links in the final component will be followed
-           and the method will instead check if the target exists.
-           If @c false, symbolic links in the final component will satisfy the
-           method and it will return @c true in @a exists.
-         </desc>
+          If @c true, symbolic links in the final component will be followed
+          and the method will instead check if the target exists.
+          If @c false, symbolic links in the final component will satisfy the
+          method and it will return @c true in @a exists.
+        </desc>
       </param>
       <param name="exists" type="boolean" dir="return">
@@ -12884,8 +12890,8 @@
       <param name="followSymlinks" type="boolean" dir="in">
         <desc>
-           Information about symbolic links is returned if @c false.  Otherwise,
-           symbolic links are followed and the returned information concerns
-           itself with the symlink target if @c true.
-         </desc>
+          Information about symbolic links is returned if @c false.  Otherwise,
+          symbolic links are followed and the returned information concerns
+          itself with the symlink target if @c true.
+        </desc>
       </param>
       <param name="info" type="IGuestFsObjInfo" dir="return">
@@ -12987,5 +12993,5 @@
           otherwise, if @c false, the method will work directly on a symbolic
           link in the final component.
-         </desc>
+        </desc>
       </param>
       <param name="acl" type="wstring" dir="in">
@@ -16394,6 +16400,6 @@
       </desc>
       <param name="writable" type="boolean" dir="in">
-       <desc>Set this to open the medium for both reading and writing.  When
-             not set the medium is opened readonly.</desc>
+      <desc>Set this to open the medium for both reading and writing.  When
+        not set the medium is opened readonly.</desc>
       </param>
       <param name="password" type="wstring" dir="in">
@@ -16639,4 +16645,50 @@
 
   <!--
+  // IDataStream
+  /////////////////////////////////////////////////////////////////////////
+  -->
+
+  <interface
+    name="IDataStream" extends="$unknown"
+    uuid="a338ed20-58d9-43ae-8b03-c1fd7088ef15"
+    wsmap="managed"
+    reservedMethods="4" reservedAttributes="8"
+    >
+    <desc>
+      The IDataStream interface is used to retrieve a data stream. It is
+      returned by <link to="IMedium::convertToStream"/>.
+    </desc>
+
+    <attribute name="readSize" type="unsigned long" readonly="yes">
+      <desc>Recommended size of a read. Requesting a larger read may be
+        possible in certain situations, but it is not guaranteed.</desc>
+    </attribute>
+
+    <method name="read">
+      <desc>
+        Read data from the stream.
+        <result name="VBOX_E_TIMEOUT">
+          Waiting time has expired.
+        </result>
+      </desc>
+      <param name="size" type="unsigned long" dir="in">
+        <desc>How many bytes to try read.</desc>
+      </param>
+      <param name="timeoutMS" type="unsigned long" dir="in">
+        <desc>
+          Timeout (in ms) for limiting the wait time for data to be available.
+          Pass 0 for an infinite timeout.
+        </desc>
+      </param>
+      <param name="data" type="octet" dir="return" safearray="yes">
+        <desc>Array of data read. This may be shorter than the specified size.
+          Returning a zero-sized array indicates the end of the stream, if the
+          status is successful.</desc>
+      </param>
+    </method>
+
+  </interface>
+
+  <!--
   // IMediumIO
   /////////////////////////////////////////////////////////////////////////
@@ -16658,5 +16710,5 @@
   <interface
     name="IMediumIO" extends="$unknown"
-    uuid="43b03a91-ea1a-4bdb-506f-8c418b72d6a3"
+    uuid="e4b301a9-5f86-4d65-ad1b-87ca284fb1c8"
     wsmap="managed"
     reservedMethods="4" reservedAttributes="8"
@@ -16749,7 +16801,41 @@
       <param name="wholeDiskInOneEntry" type="boolean" dir="in">
         <desc>
-           When @c true a partition table entry for the whole disk is created.
-           Otherwise the partition table is empty.
-        </desc>
+          When @c true a partition table entry for the whole disk is created.
+          Otherwise the partition table is empty.
+        </desc>
+      </param>
+    </method>
+
+    <method name="convertToStream">
+      <desc>
+        Converts the currently opened image into a stream of the specified
+        image type/variant. It is sufficient to open the image in read-only
+        mode. Only few types and variants are supported due to the inherent
+        restrictions of the output style.
+        <result name="VBOX_E_NOT_SUPPORTED">
+          The requested format/variant combination cannot handle stream output.
+        </result>
+        <result name="VBOX_E_FILE_ERROR">
+          An error occurred during the conversion.
+        </result>
+      </desc>
+      <param name="format" type="wstring" dir="in">
+        <desc>Identifier of the storage format to use for output.</desc>
+      </param>
+      <param name="variant" type="MediumVariant" safearray="yes" dir="in">
+        <desc>The partition table format.</desc>
+      </param>
+      <param name="bufferSize" type="unsigned long" dir="in">
+        <desc>
+          Requested buffer size (in bytes) for efficient conversion. Sizes
+          which are too small or too large are silently truncated to suitable
+          values. Tens to hundreds of Megabytes are a good choice.
+        </desc>
+      </param>
+      <param name="stream" type="IDataStream" dir="out">
+        <desc>Data stream object for reading the target image.</desc>
+      </param>
+      <param name="progress" type="IProgress" dir="return">
+        <desc>Progress object to track the operation completion.</desc>
       </param>
     </method>
@@ -18020,5 +18106,5 @@
     <method name="querySourceBitmap" wsmap="suppress">
       <desc>
-         Obtains the guest screen bitmap parameters.
+        Obtains the guest screen bitmap parameters.
       </desc>
       <param name="screenId" type="unsigned long" dir="in"/>
@@ -18028,5 +18114,5 @@
     <method name="notifyScaleFactorChange">
       <desc>
-         Notify OpenGL HGCM host service about graphics content scaling factor change.
+        Notify OpenGL HGCM host service about graphics content scaling factor change.
       </desc>
       <param name="screenId" type="unsigned long" dir="in"/>
@@ -18037,5 +18123,5 @@
     <method name="notifyHiDPIOutputPolicyChange">
       <desc>
-         Notify OpenGL HGCM host service about HiDPI monitor scaling policy change.
+        Notify OpenGL HGCM host service about HiDPI monitor scaling policy change.
       </desc>
       <param name="fUnscaledHiDPI" type="boolean" dir="in"/>
@@ -18539,5 +18625,5 @@
         PortMode_HostPipe, the host serial device name when
         <link to="ISerialPort::hostMode"/> is PortMode_HostDevice or the TCP
-       <b>port</b> (server) or <b>hostname:port</b> (client) when
+        <b>port</b> (server) or <b>hostname:port</b> (client) when
         <link to="ISerialPort::hostMode"/> is PortMode_TCP.
         For those cases, setting a @c null or empty string as the attribute's
@@ -22202,6 +22288,6 @@
   -->
   <enum
-     name="BandwidthGroupType"
-     uuid="1d92b67d-dc69-4be9-ad4c-93a01e1e0c8e">
+    name="BandwidthGroupType"
+    uuid="1d92b67d-dc69-4be9-ad4c-93a01e1e0c8e">
 
     <desc>
Index: /trunk/src/VBox/Main/include/DataStreamImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/DataStreamImpl.h	(revision 74761)
+++ /trunk/src/VBox/Main/include/DataStreamImpl.h	(revision 74761)
@@ -0,0 +1,54 @@
+/* $Id$ */
+/** @file
+ * VirtualBox COM class implementation
+ */
+
+/*
+ * Copyright (C) 2018 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+#ifndef ____H_DATASTREAMIMPL
+#define ____H_DATASTREAMIMPL
+
+#include "DataStreamWrap.h"
+
+
+class ATL_NO_VTABLE DataStream
+    : public DataStreamWrap
+{
+public:
+    DECLARE_EMPTY_CTOR_DTOR(DataStream)
+
+    HRESULT FinalConstruct();
+    void FinalRelease();
+
+    HRESULT init(unsigned long aBufferSize);
+    void uninit();
+
+    /// Feed data into the stream, used by the stream source.
+    /// Blocks if the internal buffer cannot take anything, otherwise
+    /// as much as the internal buffer can hold is taken (if smaller
+    /// than @a cbWrite). Modeled after RTStrmWriteEx.
+    int i_write(const void *pvBuf, size_t cbWrite, size_t *pcbWritten);
+
+private:
+    // wrapped IDataStream attributes and methods
+    HRESULT getReadSize(ULONG *aReadSize);
+    HRESULT read(ULONG aSize, ULONG aTimeoutMS, std::vector<BYTE> &aData);
+
+private:
+    std::vector<BYTE> m_aBuffer;
+};
+
+#endif // !____H_DATASTREAMIMPL
+
+/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Index: /trunk/src/VBox/Main/include/MediumIOImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MediumIOImpl.h	(revision 74760)
+++ /trunk/src/VBox/Main/include/MediumIOImpl.h	(revision 74761)
@@ -52,4 +52,9 @@
     HRESULT formatFAT(BOOL a_fQuick);
     HRESULT initializePartitionTable(PartitionTableType_T a_enmFormat, BOOL a_fWholeDiskInOneEntry);
+    HRESULT convertToStream(const com::Utf8Str &aFormat,
+                            const std::vector<MediumVariant_T> &aVariant,
+                            ULONG aBufferSize,
+                            ComPtr<IDataStream> &aStream,
+                            ComPtr<IProgress> &aProgress);
     HRESULT close();
     /** @} */
Index: /trunk/src/VBox/Main/src-server/MediumIOImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/MediumIOImpl.cpp	(revision 74760)
+++ /trunk/src/VBox/Main/src-server/MediumIOImpl.cpp	(revision 74761)
@@ -394,4 +394,13 @@
 }
 
+HRESULT MediumIO::convertToStream(const com::Utf8Str &aFormat,
+                                  const std::vector<MediumVariant_T> &aVariant,
+                                  ULONG aBufferSize,
+                                  ComPtr<IDataStream> &aStream,
+                                  ComPtr<IProgress> &aProgress)
+{
+    return E_NOTIMPL;
+}
+
 HRESULT MediumIO::close()
 {
