Index: /trunk/src/VBox/GuestHost/SharedClipboard/x11-clipboard.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/x11-clipboard.cpp	(revision 61588)
+++ /trunk/src/VBox/GuestHost/SharedClipboard/x11-clipboard.cpp	(revision 61589)
@@ -54,4 +54,5 @@
 #include <VBox/HostServices/VBoxClipboardSvc.h>
 
+class formats;
 static Atom clipGetAtom(CLIPBACKEND *pCtx, const char *pszName);
 
@@ -63,5 +64,6 @@
     TEXT,  /* Treat this as Utf8, but it may really be ascii */
     UTF8,
-    BMP
+    BMP,
+	HTML
 };
 
@@ -88,7 +90,12 @@
     { "TEXT", TEXT, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT },
     { "text/plain", TEXT, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT },
+    { "text/html", HTML, VBOX_SHARED_CLIPBOARD_FMT_HTML },
+    { "text/html;charset=utf-8", HTML,
+      VBOX_SHARED_CLIPBOARD_FMT_HTML },
     { "image/bmp", BMP, VBOX_SHARED_CLIPBOARD_FMT_BITMAP },
     { "image/x-bmp", BMP, VBOX_SHARED_CLIPBOARD_FMT_BITMAP },
-    { "image/x-MS-bmp", BMP, VBOX_SHARED_CLIPBOARD_FMT_BITMAP },
+    { "image/x-MS-bmp", BMP, VBOX_SHARED_CLIPBOARD_FMT_BITMAP }
+   
+	
     /* TODO: Inkscape exports image/png but not bmp... */
 };
@@ -187,4 +194,7 @@
      * table */
     CLIPX11FORMAT X11BitmapFormat;
+    /** The best HTML format X11 has to offer, as an index into the formats
+     * table */
+    CLIPX11FORMAT X11HTMLFormat;
     /** What formats does VBox have on offer? */
     uint32_t vboxFormats;
@@ -327,4 +337,9 @@
     uint32_t u32VBoxFormats = clipVBoxFormatForX11Format(pCtx->X11TextFormat);
     u32VBoxFormats |= clipVBoxFormatForX11Format(pCtx->X11BitmapFormat);
+    u32VBoxFormats |= clipVBoxFormatForX11Format(pCtx->X11HTMLFormat);
+    LogRelFlowFunc(("clipReportFormatsToVBox format: %d\n", u32VBoxFormats));
+    LogRelFlowFunc(("clipReportFormatsToVBox txt: %d, bitm: %d, html:%d, u32VBoxFormats: %d\n", 
+                    pCtx->X11TextFormat, pCtx->X11BitmapFormat, pCtx->X11HTMLFormat, 
+                    u32VBoxFormats ));
     ClipReportX11Formats(pCtx->pFrontend, u32VBoxFormats);
 }
@@ -337,4 +352,5 @@
     pCtx->X11TextFormat = INVALID;
     pCtx->X11BitmapFormat = INVALID;
+    pCtx->X11HTMLFormat = INVALID;
 }
 
@@ -433,4 +449,36 @@
 
 /**
+ * Go through an array of X11 clipboard targets to see if they contain a HTML
+ * format we can support, and if so choose the ones we prefer 
+ * @param  pCtx      the clipboard backend context structure
+ * @param  pTargets  the list of targets
+ * @param  cTargets  the size of the list in @a pTargets
+ */
+static CLIPX11FORMAT clipGetHtmlFormatFromTargets(CLIPBACKEND *pCtx,
+                                                  CLIPX11FORMAT *pTargets,
+                                                  size_t cTargets)
+{
+    CLIPX11FORMAT bestHTMLFormat = NIL_CLIPX11FORMAT;
+    CLIPFORMAT enmBestHtmlTarget = INVALID;
+    AssertPtrReturn(pCtx, NIL_CLIPX11FORMAT);
+    AssertReturn(VALID_PTR(pTargets) || cTargets == 0, NIL_CLIPX11FORMAT);
+    for (unsigned i = 0; i < cTargets; ++i)
+    {
+        CLIPX11FORMAT format = pTargets[i];
+        if (format != NIL_CLIPX11FORMAT)
+        {
+            if (   (clipVBoxFormatForX11Format(format) == VBOX_SHARED_CLIPBOARD_FMT_HTML)
+                    && enmBestHtmlTarget < clipRealFormatForX11Format(format))
+            {
+                enmBestHtmlTarget = clipRealFormatForX11Format(format);
+                bestHTMLFormat = format;
+            }
+        }
+    }
+    return bestHTMLFormat;
+}
+
+
+/**
  * Go through an array of X11 clipboard targets to see if we can support any
  * of them and if relevant to choose the ones we prefer (e.g. we like Utf8
@@ -447,4 +495,5 @@
     CLIPX11FORMAT bestTextFormat;
     CLIPX11FORMAT bestBitmapFormat;
+    CLIPX11FORMAT bestHtmlFormat;
     bestTextFormat = clipGetTextFormatFromTargets(pCtx, pTargets, cTargets);
     if (pCtx->X11TextFormat != bestTextFormat)
@@ -457,4 +506,9 @@
     {
         pCtx->X11BitmapFormat = bestBitmapFormat;
+    }
+    bestHtmlFormat = clipGetHtmlFormatFromTargets(pCtx, pTargets, cTargets);
+    if(pCtx->X11HTMLFormat != bestHtmlFormat)
+    {
+        pCtx->X11HTMLFormat = bestHtmlFormat;
     }
 }
@@ -1120,4 +1174,49 @@
 
 /**
+ * Satisfy a request from X11 to convert the clipboard HTML fragment to Utf-8.  We
+ * return null-terminated text, but can cope with non-null-terminated input.
+ *
+ * @returns iprt status code
+ * @param  pDisplay        an X11 display structure, needed for conversions
+ *                         performed by Xlib
+ * @param  pv              the text to be converted (UTF8 with Windows EOLs)
+ * @param  cb              the length of the text in @cb in bytes
+ * @param  atomTypeReturn  where to store the atom for the type of the data
+ *                         we are returning
+ * @param  pValReturn      where to store the pointer to the data we are
+ *                         returning.  This should be to memory allocated by
+ *                         XtMalloc, which will be freed by the Xt toolkit
+ *                         later.
+ * @param  pcLenReturn     where to store the length of the data we are
+ *                         returning
+ * @param  piFormatReturn  where to store the bit width (8, 16, 32) of the
+ *                         data we are returning
+ */
+static int clipWinHTMLToUtf8ForX11CB(Display *pDisplay, const char* pszSrc,
+                                    size_t cbSrc, Atom *atomTarget,
+                                    Atom *atomTypeReturn,
+                                    XtPointer *pValReturn,
+                                    unsigned long *pcLenReturn,
+                                    int *piFormatReturn)
+{
+    /* This may slightly overestimate the space needed. */
+    LogRelFlowFunc(("source: %s", pszSrc));
+
+    char *pszDest = (char *)XtMalloc(cbSrc);
+    if(pszDest == NULL)
+        return VERR_NO_MEMORY;
+        
+    memcpy(pszDest, pszSrc, cbSrc);
+
+    *atomTypeReturn = *atomTarget;
+    *pValReturn = (XtPointer)pszDest;
+    *pcLenReturn = cbSrc;
+    *piFormatReturn = 8;
+    
+    return VINF_SUCCESS;
+}
+
+
+/**
  * Does this atom correspond to one of the two selection types we support?
  * @param  widget   a valid Xt widget
@@ -1142,5 +1241,5 @@
     AssertPtrReturnVoid(pText);
     AssertPtrReturnVoid(pcText);
-    AssertReturnVoid((format == UTF8) || (format == TEXT));
+    AssertReturnVoid((format == UTF8) || (format == TEXT) || (format == HTML));
     if (((char *)pText)[*pcText - 1] == '\0')
        --(*pcText);
@@ -1200,4 +1299,35 @@
         }
         RTMemFree(pv);
+    }
+    else if ( (format == HTML) 
+            && (pCtx->vboxFormats & VBOX_SHARED_CLIPBOARD_FMT_HTML))
+    {
+        void *pv = NULL;
+        uint32_t cb = 0;
+        rc = clipReadVBoxClipboard(pCtx,
+                                   VBOX_SHARED_CLIPBOARD_FMT_HTML,
+                                   &pv, &cb);
+        if (RT_SUCCESS(rc) && (cb == 0))
+            rc = VERR_NO_DATA;
+        if (RT_SUCCESS(rc))
+        {
+            /* 
+            * The common VBox HTML encoding will be - Utf8 
+            * becuase it more general for HTML formats then UTF16
+            * X11 clipboard returns UTF16, so before sending it we should 
+            * convert it to UTF8
+            * It's very strange but here we get utf16 from x11 clipboard
+            * in same time we send utf8 to x11 clipboard and it's work
+            */
+            rc = clipWinHTMLToUtf8ForX11CB(XtDisplay(pCtx->widget),
+                (const char*)pv, cb, atomTarget,
+                atomTypeReturn, pValReturn,
+                pcLenReturn, piFormatReturn);
+
+
+            if (RT_SUCCESS(rc))
+                clipTrimTrailingNul(*(XtPointer *)pValReturn, pcLenReturn, format);
+            RTMemFree(pv);
+        }
     }
     else
@@ -1467,4 +1597,69 @@
 }
 
+
+/**
+* Convert Utf16 text into UTF8 as Windows expects
+* it and return the result in a RTMemAlloc allocated buffer.
+* @returns  IPRT status code
+* @param  pcSrc      The source text
+* @param  cbSrc      The size of the source in bytes, not counting the
+*                    terminating zero
+* @param  ppwszDest  Where to store the buffer address
+* @param  pcbDest    On success, where to store the number of bytes written.
+*                    Undefined otherwise.  Optional
+*/
+int  clipUTF16ToWinHTML(RTUTF16* buffer, size_t cb, char **output, uint32_t *outsz)
+{
+    Assert(buffer);
+    Assert(cb);
+    Assert(output);
+    Assert(outsz);
+
+    size_t i = 0;
+    RTUTF16* p = buffer;
+    char* result = NULL;
+    size_t resultLen = 0;
+    LogRelFlowFunc(("clipUTF16ToWinHTML src= %ls cb=%d i=%i, %x %x\n", buffer, cb, i, output, outsz));
+    while (i != cb / 2)
+    {
+        /* find  zero symbol (end of string) */
+        for (; i < cb / 2 && buffer[i] != 0; i++);
+        LogRelFlowFunc(("skipped nulls i=%d cb/2=%d\n", i, cb / 2));
+
+        /* convert found string */
+        char* cTmp = NULL;
+        size_t sz = 0;
+        int rc = RTUtf16ToUtf8Ex(p, cb / 2, &cTmp, p - buffer, &sz);
+        LogRelFlowFunc(("utf16toutf8 src= %ls res=%s i=%i\n", p, cTmp, i));
+        if (!RT_SUCCESS(rc))
+            return rc;
+
+        /* append new substring */
+        result = (char*)RTMemRealloc(result, resultLen + sz + 1);
+        if (result == NULL)
+        {
+            RTStrFree(cTmp);
+            cTmp = NULL;
+            return VERR_NO_MEMORY;
+        }
+        memcpy(result + resultLen, cTmp, sz + 1);
+        LogRelFlowFunc(("Temp result res=%s\n", result + resultLen));
+
+        /* remove temporary buffer */
+        RTStrFree(cTmp);
+        resultLen += sz + 1;
+        /* skip zero symbols */
+        for (; i < cb / 2 && buffer[i] == 0; i++);
+        /* remember start of string */
+        p += i;
+    }
+    *output = result;
+    *outsz = resultLen;
+
+    return VINF_SUCCESS;
+}
+
+
+
 /** A structure containing information about where to store a request
  * for the X11 clipboard contents. */
@@ -1477,4 +1672,6 @@
     /** The bitmap format we requested from X11 if we requested bitmap */
     CLIPX11FORMAT mBitmapFormat;
+    /** The HTML format we requested from X11 if we requested HTML */
+    CLIPX11FORMAT mHtmlFormat;
     /** The clipboard context this request is associated with */
     CLIPBACKEND *mCtx;
@@ -1497,7 +1694,7 @@
     CLIPREADX11CBREQ *pReq = (CLIPREADX11CBREQ *) pClientData;
     LogRelFlowFunc(("pReq->mFormat=%02X, pReq->mTextFormat=%u, "
-                "pReq->mBitmapFormat=%u, pReq->mCtx=%p\n",
+                "pReq->mBitmapFormat=%u, pReq->mHtmlFormat=%u, pReq->mCtx=%p\n",
                  pReq->mFormat, pReq->mTextFormat, pReq->mBitmapFormat,
-                 pReq->mCtx));
+                 pReq->mHtmlFormat, pReq->mCtx));
     AssertPtr(pReq->mCtx);
     Assert(pReq->mFormat != 0);  /* sanity */
@@ -1564,4 +1761,31 @@
         }
     }
+    else if(pReq->mFormat == VBOX_SHARED_CLIPBOARD_FMT_HTML)
+    {
+        /* In which format is the clipboard data? */
+        switch (clipRealFormatForX11Format(pReq->mHtmlFormat))
+        {
+            case HTML:
+            {
+                /* The common VBox HTML encoding will be - Utf8 
+                * becuase it more general for HTML formats then UTF16
+                * X11 clipboard returns UTF16, so before sending it we should 
+                * convert it to UTF8 
+                */
+                pvDest = NULL;
+                cbDest = 0;
+                rc = clipUTF16ToWinHTML((RTUTF16*)pvSrc, cbSrc,
+                    (char**)&pvDest, &cbDest);
+                LogRelFlowFunc(("Source unicode %ls, cbSrc = %d\n", pvSrc, cbSrc));
+                LogRelFlowFunc(("converted to win unicode %s, cbDest = %d, rc = %Rrc\n", pvDest, cbDest, rc));
+                rc = VINF_SUCCESS;
+                break;
+            }
+            default:
+            {
+                rc = VERR_INVALID_PARAMETER;
+            }
+        }
+    }
     else
         rc = VERR_NOT_IMPLEMENTED;
@@ -1653,5 +1877,18 @@
             getSelectionValue(pCtx, pCtx->X11BitmapFormat, pReq);
     }
-    else
+    else if(pReq->mFormat == VBOX_SHARED_CLIPBOARD_FMT_HTML)
+    {
+        /* Send out a request for the data to the current clipboard
+             * owner */
+        pReq->mHtmlFormat = pCtx->X11HTMLFormat;
+        if(pReq->mHtmlFormat == INVALID)
+                    /* VBox thinks we have data and we don't */
+            rc = VERR_NO_DATA;
+        else
+            /* Send out a request for the data to the current clipboard
+             * owner */
+            getSelectionValue(pCtx, pCtx->X11HTMLFormat, pReq);
+    }
+    else   
         rc = VERR_NOT_IMPLEMENTED;
     if (RT_FAILURE(rc))
@@ -2545,2 +2782,4 @@
 
 #endif /* SMOKETEST defined */
+
+                    
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard-win.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard-win.cpp	(revision 61588)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard-win.cpp	(revision 61589)
@@ -42,4 +42,10 @@
 typedef FNREMOVECLIPBOARDFORMATLISTENER *PFNREMOVECLIPBOARDFORMATLISTENER;
 
+/*Forward declarations*/
+int ConvertMimeToCFHTML(const char *source, size_t cb, char **output, size_t *pcch);
+int ConvertCFHtmlToMime(const char *source, const uint32_t cch, char **output, size_t *pcch);
+bool IsWindowsHTML(const char *source);
+
+
 #ifndef WM_CLIPBOARDUPDATE
 #define WM_CLIPBOARDUPDATE 0x031D
@@ -96,4 +102,17 @@
         {
             Log(("%s\n", pv));
+            
+            //size_t cb = RTStrNLen(pv, );
+            char* buf = (char*)RTMemAlloc(cb + 1);
+            RT_BZERO(buf, cb);
+            RTStrCopy(buf, cb, (const char*)pv);
+            for (int i = 0; i < cb; ++i)
+            {
+                if (buf[i] == '\n' || buf[i] == '\r')
+                    buf[i] = ' ';
+            }
+            
+            Log(("%s\n", buf));
+            RTMemFree(buf);
         }
         else
@@ -202,5 +221,23 @@
     }
 
-    memcpy (pvDst, pvSrc, cbSrc);
+    if (u32Format == VBOX_SHARED_CLIPBOARD_FMT_HTML &&
+                            IsWindowsHTML((const char*)pvSrc))
+    {
+        char* buffer = NULL;
+        size_t cbuf = 0;
+        ConvertCFHtmlToMime((const char*)pvSrc, cbSrc, (char**)&buffer, &cbuf);
+        if (cbuf > cbDst)
+        {
+            /* Do not copy data. The dst buffer is not enough. */
+            return;
+        }
+        memcpy(pvDst, buffer, cbuf);
+        *pcbActualDst = cbuf;
+        RTMemFree(buffer);
+    }
+    else
+    {
+        memcpy(pvDst, pvSrc, cbSrc);
+    }
 
     vboxClipboardDump(pvDst, cbSrc, u32Format);
@@ -794,4 +831,39 @@
 }
 
+int DumpHtml(char* src, size_t cb)
+{
+    size_t lenght = 0;
+    int rc = RTStrNLenEx(src, cb, &lenght);
+    if (RT_SUCCESS(rc))
+    {
+        char* buf = (char*)RTMemAlloc(cb + 1);
+        if (buf != NULL)
+        {
+            RT_BZERO(buf, cb + 1);
+            rc = RTStrCopy(buf, cb, (const char*)src);
+            if (RT_SUCCESS(rc))
+            {
+                for (int i = 0; i < cb; ++i)
+                {
+                    if (buf[i] == '\n' || buf[i] == '\r')
+                        buf[i] = ' ';
+                }
+            }
+            else
+            {
+                Log(("Error in copying string.\n"));
+            }
+            Log(("Removed \\r\\n: %s\n", buf));
+            RTMemFree(buf);
+        }
+        else
+        {
+            rc = VERR_NO_MEMORY;
+            Log(("Not enough memory to allocate buffer.\n"));
+        }
+    }
+    return rc;
+}
+
 int vboxClipboardReadData (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Format, void *pv, uint32_t cb, uint32_t *pcbActual)
 {
@@ -872,5 +944,6 @@
                         vboxClipboardGetData (VBOX_SHARED_CLIPBOARD_FMT_HTML, lp, GlobalSize (hClip),
                                               pv, cb, pcbActual);
-
+                        LogRelFlowFunc(("Raw HTML clipboard data from host :"));
+                        DumpHtml((char*)pv, cb);
                         GlobalUnlock(hClip);
                     }
@@ -913,11 +986,31 @@
     if (cb > 0)
     {
-        pClient->data.pv = RTMemAlloc (cb);
-
-        if (pClient->data.pv)
-        {
-            memcpy (pClient->data.pv, pv, cb);
-            pClient->data.cb = cb;
-            pClient->data.u32Format = u32Format;
+        char* result = NULL;
+        size_t cch;
+
+        if(u32Format == VBOX_SHARED_CLIPBOARD_FMT_HTML && 
+            !IsWindowsHTML((const char*)pv))
+        {
+            /* check that this is not already CF_HTML */
+            int rc = ConvertMimeToCFHTML((const char*)pv, cb, &result, &cch);
+            if (RT_SUCCESS(rc))
+            {
+                if (result != NULL && cch != 0)
+                {
+                    pClient->data.pv = result;
+                    pClient->data.cb = cch;
+                    pClient->data.u32Format = u32Format;
+                }
+            }
+        }
+        else
+        {
+            pClient->data.pv = RTMemAlloc (cb);
+            if (pClient->data.pv)
+            {
+                memcpy (pClient->data.pv, pv, cb);
+                pClient->data.cb = cb;
+                pClient->data.u32Format = u32Format;
+            }
         }
     }
@@ -925,2 +1018,211 @@
     SetEvent(pClient->pCtx->hRenderEvent);
 }
+
+/*
+@StartHtml - pos before <html>
+@EndHtml - whole size of text excluding ending zero char
+@StartFragment - pos after <!--StartFragment-->
+@EndFragment - pos before <!--EndFragment-->
+@note: all values includes CR\LF inserted into text
+Calculations:
+Header length = format Length + (3*6('digits')) - 2('%s') = format length + 16 (control value - 183)
+EndHtml  = Header length + fragment length
+StartHtml = 105(constant)
+StartFragment = 143(constant)
+EndFragment  = Header length + fragment length - 40(ending length)
+*/
+char strFormatSample[] =
+    "Version:1.0\r\n"
+    "StartHTML:000000101\r\n"
+    "EndHTML:%09d\r\n" // END HTML = Header length + fragment lengh 
+"StartFragment:000000137\r\n"
+"EndFragment:%09d\r\n"
+"<html>\r\n"
+"<body>\r\n"
+"<!--StartFragment-->%s<!--EndFragment-->\r\n"
+"</body>\r\n"
+"</html>\r\n";
+
+/* 
+* Extracts field value from CF_HTML struct
+* @src - source in CF_HTML format
+* @option - name of CF_HTML field
+* @value - extracted value of CF_HTML field
+* returns RC result code
+*/
+int GetHeaderValue(const char *src, const char *option, size_t *value)
+{
+    size_t optionLenght;
+    int rc = VERR_INVALID_PARAMETER;
+
+    Assert(src);
+    Assert(option);
+
+    char* optionValue = RTStrStr(src, option);
+    if (optionValue)
+    {
+        rc = RTStrNLenEx(option, RTSTR_MAX, &optionLenght);
+        Assert(optionLenght);
+        if (RT_SUCCESS(rc))
+        {
+            int32_t tmpValue;
+            rc = RTStrToInt32Ex(optionValue + optionLenght, NULL, 10, &tmpValue);
+            if (RT_SUCCESS(rc))
+            {
+                *value = tmpValue;
+                rc = VINF_SUCCESS;
+            }
+        }
+    }
+    return rc;
+}
+
+/* 
+ * Check that the source string contains CF_HTML struct
+ * returns true if the @source string is in CF_HTML format
+ */
+bool IsWindowsHTML(const char *source)
+{
+    return RTStrStr(source, "Version:") != NULL
+        && RTStrStr(source, "StartHTML:") != NULL;
+}
+
+
+/* 
+* Converts clipboard data from CF_HTML format to mimie clipboard format
+* Returns allocated buffer that contains html converted to text/html mime type
+* return result code
+* parameters - output buffer and size of output buffer
+* It allocates the buffer needed for storing converted fragment 
+* Allocated buffer should be destroyed by RTMemFree after usage
+*/
+int ConvertCFHtmlToMime(const char *source, const uint32_t cch, char **output, size_t *pcch)
+{
+    char* result = NULL;
+
+    Assert(source);
+    Assert(cch);
+    Assert(output);
+    Assert(pcch);
+
+    size_t startOffset, endOffset;
+    int rc = GetHeaderValue(source, "StartFragment:", &startOffset);
+    if (!RT_SUCCESS(rc))
+    {
+        LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected StartFragment. rc = %Rrc.\n", rc));
+        return VERR_INVALID_PARAMETER;
+    }
+    rc = GetHeaderValue(source, "EndFragment:", &endOffset);
+    if (!RT_SUCCESS(rc))
+    {
+        LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc.\n", rc));
+        return VERR_INVALID_PARAMETER;
+    }
+    if (startOffset > 0 && endOffset > 0 && endOffset > startOffset)
+    {
+        size_t substrlen = endOffset - startOffset;
+        result = (char*)RTMemAlloc(substrlen + 1);
+        if (result)
+        {
+            RT_BZERO(result, substrlen + 1);
+            rc = RTStrCopyEx(result, substrlen + 1, source + startOffset, substrlen);
+            if (RT_SUCCESS(rc))
+            {
+                *output = result;
+                *pcch = substrlen + 1;
+            }
+            else
+            {
+                LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc));
+                return rc;
+            }
+        }
+        else
+        {
+            LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment.\n"));
+            return VERR_NO_MEMORY;
+        }
+    }
+
+return VINF_SUCCESS;
+}
+
+
+
+/*
+* Converts source Utf16 mime html clipboard data to Utf8 CF_HTML format
+* It allocates
+* Calculations:
+* Header length = format Length + (2*(10 - 5('%010d'))('digits')) - 2('%s') = format length + 8
+* EndHtml  = Header length + fragment length
+* StartHtml = 105(constant)
+* StartFragment = 141(constant) may vary if the header html content will be extended
+* EndFragment  = Header length + fragment length - 38(ending length)
+* @source: source buffer that contains utf-16 string in mime html format
+* @cb: size of source buffer in bytes
+* @output: allocated output buffer to put converted Utf8 CF_HTML clipboard data. This function allocates memory for this.
+* @pcch: size of allocated result buffer in bytes
+* @note: output buffer should be free using RTMemFree()
+* @note: Everything inside of fragment can be UTF8. Windows allows it. Everything in header should be Latin1.
+*/
+int ConvertMimeToCFHTML(const char *source, size_t cb, char **output, size_t *pcch)
+{
+    Assert(output);
+    Assert(pcch);
+    Assert(source);
+    Assert(cb);
+
+    size_t fragmentLength = 0;
+
+    char* buf = (char*)source;
+    
+    /* construct CF_HTML formatted string */
+    char* result = NULL;
+    int rc = RTStrNLenEx(buf, RTSTR_MAX, &fragmentLength);
+    if (!RT_SUCCESS(rc))
+    {
+        LogRelFlowFunc(("Error: invalid source fragment. rc = %Rrc.\n"));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    /* caluclate parameters of CF_HTML header */
+    size_t headerLength = (sizeof(strFormatSample) - 1) + 8;
+    size_t endHtml = headerLength + fragmentLength;
+    size_t endFragment = headerLength + fragmentLength - 38;
+    result = (char*)RTMemAlloc(endHtml + 1);
+    if (result == NULL)
+    {
+        LogRelFlowFunc(("Error: Cannot allocate memory for result buffer. rc = %Rrc.\n"));
+        return VERR_NO_MEMORY;
+    }
+
+    /* format result CF_HTML string */
+    rc = RTStrPrintf(result, endHtml + 1, strFormatSample, endHtml, endFragment, buf);
+    if (rc == -1)
+    {
+        LogRelFlowFunc(("Error: cannot construct CF_HTML. rc = %Rrc.\n"));
+        return VERR_CANT_CREATE;
+    }
+    Assert(endHtml == rc);
+
+#ifdef DEBUG
+    {
+        /*Control calculations. check consistency.*/
+        const char strStartFragment[] = "<!--StartFragment-->";
+        const char strEndFragment[] = "<!--EndFragment-->";
+
+        /* check 'StartFragment:' value */
+        const char* realStartFragment = RTStrStr(result, strStartFragment);
+        Assert((realStartFragment + sizeof(strStartFragment) - 1) - result == 137);//141);
+
+        /* check 'EndFragment:' value */
+        const char* realEndFragment = RTStrStr(result, strEndFragment);
+        Assert((realEndFragment - result) == endFragment);
+    }
+#endif
+
+    *output = result;
+    *pcch = rc+1;
+
+    return VINF_SUCCESS;
+}
