Index: /trunk/include/VBox/GuestHost/SharedClipboard-win.h
===================================================================
--- /trunk/include/VBox/GuestHost/SharedClipboard-win.h	(revision 81268)
+++ /trunk/include/VBox/GuestHost/SharedClipboard-win.h	(revision 81269)
@@ -170,6 +170,14 @@
     enum Status
     {
+        /** The object is uninitialized (not ready). */
         Uninitialized = 0,
-        Initialized
+        /** The object is initialized and ready to use. */
+        Initialized,
+        /** The operation has been successfully completed. */
+        Completed,
+        /** The operation has been canceled. */
+        Canceled,
+        /** An (unrecoverable) error occurred. */
+        Error
     };
 
@@ -218,5 +226,5 @@
     static DECLCALLBACK(int) readThread(RTTHREAD ThreadSelf, void *pvUser);
 
-    static const char* ClipboardFormatToString(CLIPFORMAT fmt);
+    static void logFormat(CLIPFORMAT fmt);
 
 protected:
@@ -249,11 +257,18 @@
     typedef std::vector<FSOBJENTRY> FsObjEntryList;
 
+    /** The object's current status. */
     Status                      m_enmStatus;
+    /** The object's current reference count. */
     LONG                        m_lRefCount;
+    /** How many formats have been registered. */
     ULONG                       m_cFormats;
     LPFORMATETC                 m_pFormatEtc;
     LPSTGMEDIUM                 m_pStgMedium;
+    /** Pointer to the associated transfer object being handled. */
     PSHCLTRANSFER               m_pTransfer;
+    /** Current stream object being used. */
     IStream                    *m_pStream;
+    /** Current object index being handled by the data object.
+     *  This is needed to create the next IStream object for e.g. the next upcoming file/dir/++ in the transfer. */
     ULONG                       m_uObjIdx;
     /** List of (cached) file system objects. */
@@ -265,7 +280,12 @@
     /** Event being triggered when the transfer has been completed. */
     RTSEMEVENT                  m_EventTransferComplete;
+    /** Registered format for CFSTR_FILEDESCRIPTORA. */
     UINT                        m_cfFileDescriptorA;
+    /** Registered format for CFSTR_FILEDESCRIPTORW. */
     UINT                        m_cfFileDescriptorW;
+    /** Registered format for CFSTR_FILECONTENTS. */
     UINT                        m_cfFileContents;
+    /** Registered format for CFSTR_PERFORMEDDROPEFFECT. */
+    UINT                        m_cfPerformedDropEffect;
 };
 
Index: /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp	(revision 81268)
+++ /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp	(revision 81269)
@@ -58,5 +58,5 @@
     HRESULT hr;
 
-    ULONG cFixedFormats = 2; /* CFSTR_FILEDESCRIPTORA + CFSTR_FILECONTENTS */
+    ULONG cFixedFormats = 3; /* CFSTR_FILEDESCRIPTORA + CFSTR_FILECONTENTS + CFSTR_PERFORMEDDROPEFFECT */
 #ifdef VBOX_CLIPBOARD_WITH_UNICODE_SUPPORT
     cFixedFormats++; /* CFSTR_FILEDESCRIPTORW */
@@ -92,4 +92,9 @@
         registerFormat(&m_pFormatEtc[uIdx++], m_cfFileContents, TYMED_ISTREAM, 0 /* lIndex */);
 
+        /* We want to know from the target what the outcome of the operation was to react accordingly (e.g. abort a transfer). */
+        LogFlowFunc(("Registering CFSTR_PERFORMEDDROPEFFECT ...\n"));
+        m_cfPerformedDropEffect = RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT);
+        registerFormat(&m_pFormatEtc[uIdx++], m_cfPerformedDropEffect, TYMED_HGLOBAL, -1 /* lIndex */, DVASPECT_CONTENT);
+
         /*
          * Registration of dynamic formats needed?
@@ -403,5 +408,21 @@
                     AssertRC(rc2);
 
-                    LogRel2(("Shared Clipboard: Transfer complete\n"));
+                    switch (pThis->m_enmStatus)
+                    {
+                        case Completed:
+                            LogRel2(("Shared Clipboard: Transfer complete\n"));
+                            break;
+
+                        case Canceled:
+                            LogRel2(("Shared Clipboard: Transfer canceled\n"));
+                            break;
+
+                        case Error:
+                            LogRel2(("Shared Clipboard: Transfer error occurred\n"));
+                            break;
+
+                        default:
+                            break;
+                    }
                 }
                 else
@@ -650,4 +671,17 @@
         }
     }
+    else if (pFormatEtc->cfFormat == m_cfPerformedDropEffect)
+    {
+        HGLOBAL hGlobal = GlobalAlloc(GHND, sizeof(DWORD));
+
+        DWORD* pdwDropEffect = (DWORD*)GlobalLock(hGlobal);
+        *pdwDropEffect = DROPEFFECT_COPY;
+
+        GlobalUnlock(hGlobal);
+
+        pMedium->tymed          = TYMED_HGLOBAL;
+        pMedium->hGlobal        = hGlobal;
+        pMedium->pUnkForRelease = NULL;
+    }
 
     if (   FAILED(hr)
@@ -686,5 +720,5 @@
 {
     LogFlowFunc(("\n"));
-    return (lookupFormatEtc(pFormatEtc, NULL /* puIndex */)) ? S_OK : DV_E_FORMATETC;
+    return lookupFormatEtc(pFormatEtc, NULL /* puIndex */) ? S_OK : DV_E_FORMATETC;
 }
 
@@ -701,6 +735,45 @@
 STDMETHODIMP SharedClipboardWinDataObject::SetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium, BOOL fRelease)
 {
-    RT_NOREF(pFormatEtc, pMedium, fRelease);
-    LogFlowFunc(("\n"));
+    if (   pFormatEtc == NULL
+        || pMedium    == NULL)
+        return E_INVALIDARG;
+
+    if (pFormatEtc->lindex != -1)
+        return DV_E_LINDEX;
+
+    if (pFormatEtc->tymed != TYMED_HGLOBAL)
+        return DV_E_TYMED;
+
+    if (pFormatEtc->dwAspect != DVASPECT_CONTENT)
+        return DV_E_DVASPECT;
+
+    LogFlowFunc(("cfFormat=%RU16, lookupFormatEtc=%RTbool\n",
+                 pFormatEtc->cfFormat, lookupFormatEtc(pFormatEtc, NULL /* puIndex */)));
+
+    /* CFSTR_PERFORMEDDROPEFFECT is used by the drop target (caller of this IDataObject) to communicate
+     * the outcome of the overall operation. */
+    if (   pFormatEtc->cfFormat == m_cfPerformedDropEffect
+        && pMedium->tymed       == TYMED_HGLOBAL)
+    {
+        DWORD dwEffect = *(DWORD *)GlobalLock(pMedium->hGlobal);
+        GlobalUnlock(pMedium->hGlobal);
+
+        LogFlowFunc(("dwEffect=%RI32\n", dwEffect));
+
+        /* Did the user cancel the operation via UI (shell)? This also might happen when overwriting an existing file
+         * and the user doesn't want to allow this. */
+        if (dwEffect == DROPEFFECT_NONE)
+        {
+            LogRel2(("Shared Clipboard: Transfer canceled by user interaction\n"));
+
+            OnTransferCanceled();
+        }
+        /** @todo Detect move / overwrite actions here. */
+
+        if (fRelease)
+            ReleaseStgMedium(pMedium);
+
+        return S_OK;
+    }
 
     return E_NOTIMPL;
@@ -791,20 +864,16 @@
     LogFlowFunc(("m_uObjIdx=%RU32 (total: %zu)\n", m_uObjIdx, m_lstEntries.size()));
 
-    const bool fComplete = m_uObjIdx == m_lstEntries.size() - 1 /* Object index is zero-based */;
-    if (fComplete)
-    {
-        if (m_EventTransferComplete != NIL_RTSEMEVENT)
-        {
-            int rc2 = RTSemEventSignal(m_EventTransferComplete);
-            AssertRC(rc2);
-        }
-    }
-
-    LogFlowFuncLeaveRC(rc);
-}
-
-void SharedClipboardWinDataObject::OnTransferCanceled(void)
-{
-    LogFlowFuncEnter();
+    if (RT_SUCCESS(rc))
+    {
+        const bool fComplete = m_uObjIdx == m_lstEntries.size() - 1 /* Object index is zero-based */;
+        if (fComplete)
+        {
+            m_enmStatus = Completed;
+        }
+        else
+            AssertFailed();
+    }
+    else
+        m_enmStatus = Error;
 
     if (m_EventTransferComplete != NIL_RTSEMEVENT)
@@ -814,88 +883,32 @@
     }
 
+    LogFlowFuncLeaveRC(rc);
+}
+
+void SharedClipboardWinDataObject::OnTransferCanceled(void)
+{
+    LogFlowFuncEnter();
+
+    m_enmStatus = Canceled;
+
+    if (m_EventTransferComplete != NIL_RTSEMEVENT)
+    {
+        int rc2 = RTSemEventSignal(m_EventTransferComplete);
+        AssertRC(rc2);
+    }
+
     LogFlowFuncLeave();
 }
 
 /* static */
-const char* SharedClipboardWinDataObject::ClipboardFormatToString(CLIPFORMAT fmt)
-{
-#if 0
+void SharedClipboardWinDataObject::logFormat(CLIPFORMAT fmt)
+{
     char szFormat[128];
     if (GetClipboardFormatName(fmt, szFormat, sizeof(szFormat)))
-        LogFlowFunc(("wFormat=%RI16, szName=%s\n", fmt, szFormat));
-#endif
-
-    switch (fmt)
-    {
-
-    case 1:
-        return "CF_TEXT";
-    case 2:
-        return "CF_BITMAP";
-    case 3:
-        return "CF_METAFILEPICT";
-    case 4:
-        return "CF_SYLK";
-    case 5:
-        return "CF_DIF";
-    case 6:
-        return "CF_TIFF";
-    case 7:
-        return "CF_OEMTEXT";
-    case 8:
-        return "CF_DIB";
-    case 9:
-        return "CF_PALETTE";
-    case 10:
-        return "CF_PENDATA";
-    case 11:
-        return "CF_RIFF";
-    case 12:
-        return "CF_WAVE";
-    case 13:
-        return "CF_UNICODETEXT";
-    case 14:
-        return "CF_ENHMETAFILE";
-    case 15:
-        return "CF_HDROP";
-    case 16:
-        return "CF_LOCALE";
-    case 17:
-        return "CF_DIBV5";
-    case 18:
-        return "CF_MAX";
-    case 49158:
-        return "FileName";
-    case 49159:
-        return "FileNameW";
-    case 49161:
-        return "DATAOBJECT";
-    case 49171:
-        return "Ole Private Data";
-    case 49314:
-        return "Shell Object Offsets";
-    case 49316:
-        return "File Contents";
-    case 49317:
-        return "File Group Descriptor";
-    case 49323:
-        return "Preferred Drop Effect";
-    case 49380:
-        return "Shell Object Offsets";
-    case 49382:
-        return "FileContents";
-    case 49383:
-        return "FileGroupDescriptor";
-    case 49389:
-        return "Preferred DropEffect";
-    case 49268:
-        return "Shell IDList Array";
-    case 49619:
-        return "RenPrivateFileAttachments";
-    default:
-        break;
-    }
-
-    return "unknown";
+    {
+        LogFlowFunc(("clipFormat=%RI16 -> %s\n", fmt, szFormat));
+    }
+    else
+        LogFlowFunc(("clipFormat=%RI16 is unknown\n", fmt));
 }
 
@@ -912,7 +925,6 @@
             //&& pFormatEtc->dwAspect == m_pFormatEtc[i].dwAspect)
         {
-            LogRel3(("Shared Clipboard: Format found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32, ulIndex=%RU32\n",
-                      pFormatEtc->tymed, pFormatEtc->cfFormat, SharedClipboardWinDataObject::ClipboardFormatToString(m_pFormatEtc[i].cfFormat),
-                      pFormatEtc->dwAspect, i));
+            LogRel2(("Shared Clipboard: Format found: tyMed=%RI32, cfFormat=%RI16, dwAspect=%RI32, ulIndex=%RU32\n",
+                     pFormatEtc->tymed, pFormatEtc->cfFormat, pFormatEtc->dwAspect, i));
             if (puIndex)
                 *puIndex = i;
@@ -921,7 +933,8 @@
     }
 
-    LogRel3(("Shared Clipboard: Format NOT found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32\n",
-             pFormatEtc->tymed, pFormatEtc->cfFormat, SharedClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
-             pFormatEtc->dwAspect));
+    LogRel2(("Shared Clipboard: Format NOT found: tyMed=%RI32, cfFormat=%RI16, dwAspect=%RI32\n",
+             pFormatEtc->tymed, pFormatEtc->cfFormat, pFormatEtc->dwAspect));
+
+    logFormat(pFormatEtc->cfFormat);
 
     return false;
@@ -940,6 +953,7 @@
     pFormatEtc->ptd      = pTargetDevice;
 
-    LogFlowFunc(("Registered format=%ld, sFormat=%s\n",
-                 pFormatEtc->cfFormat, SharedClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat)));
-}
-
+    LogFlowFunc(("Registered format=%ld\n", pFormatEtc->cfFormat));
+
+    logFormat(pFormatEtc->cfFormat);
+}
+
Index: /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardEnumFormatEtcImpl-win.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardEnumFormatEtcImpl-win.cpp	(revision 81268)
+++ /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardEnumFormatEtcImpl-win.cpp	(revision 81269)
@@ -44,7 +44,9 @@
         for (ULONG i = 0; i < cFormats; i++)
         {
-            LogFlowFunc(("Format %RU32: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
-                         i, pFormatEtc[i].cfFormat, SharedClipboardWinDataObject::ClipboardFormatToString(pFormatEtc[i].cfFormat),
-                         pFormatEtc[i].tymed, pFormatEtc[i].dwAspect));
+            LogFlowFunc(("Format %RU32: cfFormat=%RI16, tyMed=%RU32, dwAspect=%RU32\n",
+                         i, pFormatEtc[i].cfFormat, pFormatEtc[i].tymed, pFormatEtc[i].dwAspect));
+
+            SharedClipboardWinDataObject::logFormat(pFormatEtc[i].cfFormat);
+
             SharedClipboardWinEnumFormatEtc::CopyFormat(&m_pFormatEtc[i], &pFormatEtc[i]);
         }
