Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDataObject.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDataObject.cpp	(revision 95835)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDataObject.cpp	(revision 95836)
@@ -33,9 +33,4 @@
 #include "VBoxDnD.h"
 
-#ifdef DEBUG
-  /* Enable the following line to get much more debug output about
-   * (un)known clipboard formats. */
-//# define VBOX_DND_DEBUG_FORMATS
-#endif
 
 /** @todo Implement IDataObjectAsyncCapability interface? */
@@ -51,93 +46,12 @@
     , m_cbData(0)
 {
-
-    /*
-     * Allocate arrays for format related stuff.
-     */
-    /** @todo r=bird: Use an init function */
-    int   rc = VERR_NO_MEMORY;
-    ULONG cFixedFormats = 1;
-    ULONG cAllFormats   = cFormats + cFixedFormats;
-    m_paFormatEtc = (LPFORMATETC)RTMemAllocZ(sizeof(m_paFormatEtc[0]) * cAllFormats);
-    if (m_paFormatEtc)
-    {
-        m_paStgMedium = (LPSTGMEDIUM)RTMemAllocZ(sizeof(m_paStgMedium[0]) * cAllFormats);
-        if (m_EvtDropped)
-        {
-
-            /*
-             * Registration of dynamic formats needed?
-             */
-            LogFlowFunc(("%RU32 dynamic formats\n", cFormats));
-            if (cFormats)
-            {
-                AssertPtr(pFormatEtc);
-                AssertPtr(pStgMed);
-
-                for (ULONG i = 0; i < cFormats; i++)
-                {
-                    LogFlowFunc(("Format %RU32: cfFormat=%RI16, tyMed=%RU32, dwAspect=%RU32\n",
-                                 i, pFormatEtc[i].cfFormat, pFormatEtc[i].tymed, pFormatEtc[i].dwAspect));
-                    m_paFormatEtc[i] = pFormatEtc[i];
-                    m_paStgMedium[i] = pStgMed[i];
-                }
-            }
-
-            rc = RTSemEventCreate(&m_EvtDropped);
-            AssertRCStmt(rc, m_EvtDropped = NIL_RTSEMEVENT);
-
-            /*
-             * Register fixed formats.
-             */
-#if 0
-            /* CF_HDROP. */
-            RegisterFormat(&mpFormatEtc[cFormats], CF_HDROP);
-            mpStgMedium[cFormats++].tymed = TYMED_HGLOBAL;
-
-            /* IStream. */
-            RegisterFormat(&mpFormatEtc[cFormats++],
-                           RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR));
-            RegisterFormat(&mpFormatEtc[cFormats++],
-                           RegisterClipboardFormat(CFSTR_FILECONTENTS),
-                           TYMED_ISTREAM, 0 /* lIndex */);
-
-            /* Required for e.g. Windows Media Player. */
-            RegisterFormat(&mpFormatEtc[cFormats++],
-                           RegisterClipboardFormat(CFSTR_FILENAME));
-            RegisterFormat(&mpFormatEtc[cFormats++],
-                           RegisterClipboardFormat(CFSTR_FILENAMEW));
-            RegisterFormat(&mpFormatEtc[cFormats++],
-                           RegisterClipboardFormat(CFSTR_SHELLIDLIST));
-            RegisterFormat(&mpFormatEtc[cFormats++],
-                           RegisterClipboardFormat(CFSTR_SHELLIDLISTOFFSET));
-#endif
-            m_cFormats  = cFormats;
-            m_enmStatus = Status_Initialized;
-        }
-    }
-    LogFlowFunc(("cFormats=%RU32 - %Rrc!\n", cFormats, rc));
+    int rc2 = Init(pFormatEtc, pStgMed, cFormats);
+    AssertRC(rc2);
 }
 
 VBoxDnDDataObject::~VBoxDnDDataObject(void)
 {
-    if (m_paFormatEtc)
-    {
-        RTMemFree(m_paFormatEtc);
-        m_paFormatEtc = NULL;
-    }
-
-    if (m_paStgMedium)
-    {
-        RTMemFree(m_paStgMedium);
-        m_paStgMedium = NULL;
-    }
-
-    if (m_pvData)
-    {
-        RTMemFree(m_pvData);
-        m_pvData = NULL;
-    }
-
-    LogFlowFunc(("mRefCount=%RI32\n", m_cRefs));
+    int rc2 = Destroy();
+    AssertRC(rc2);
 }
 
@@ -148,4 +62,5 @@
 STDMETHODIMP_(ULONG) VBoxDnDDataObject::AddRef(void)
 {
+    AssertReturn(m_cRefs < 32, m_cRefs); /* Paranoia. */
     return InterlockedIncrement(&m_cRefs);
 }
@@ -153,4 +68,5 @@
 STDMETHODIMP_(ULONG) VBoxDnDDataObject::Release(void)
 {
+    AssertReturn(m_cRefs > 0, 0);
     LONG lCount = InterlockedDecrement(&m_cRefs);
     if (lCount == 0)
@@ -477,4 +393,112 @@
  * Own stuff.
  */
+
+int VBoxDnDDataObject::Init(LPFORMATETC pFormatEtc, LPSTGMEDIUM pStgMed, ULONG cFormats)
+{
+    AssertReturn(m_enmStatus == Status_Uninitialized, VERR_WRONG_ORDER);
+
+    int rc = RTSemEventCreate(&m_EvtDropped);
+    AssertRCReturn(rc, rc);
+
+    /*
+     * Allocate arrays for format related stuff.
+     */
+    ULONG cFixedFormats = 1;
+    ULONG cAllFormats   = cFormats + cFixedFormats;
+    m_paFormatEtc = (LPFORMATETC)RTMemAllocZ(sizeof(m_paFormatEtc[0]) * cAllFormats);
+    if (m_paFormatEtc)
+    {
+        m_paStgMedium = (LPSTGMEDIUM)RTMemAllocZ(sizeof(m_paStgMedium[0]) * cAllFormats);
+        if (m_EvtDropped)
+        {
+            /*
+             * Registration of dynamic formats needed?
+             */
+            LogFlowFunc(("%RU32 dynamic formats\n", cFormats));
+            if (cFormats)
+            {
+                AssertPtr(pFormatEtc);
+                AssertPtr(pStgMed);
+
+                for (ULONG i = 0; i < cFormats; i++)
+                {
+                    LogFlowFunc(("Format %RU32: cfFormat=%RI16, tyMed=%RU32, dwAspect=%RU32\n",
+                                 i, pFormatEtc[i].cfFormat, pFormatEtc[i].tymed, pFormatEtc[i].dwAspect));
+                    m_paFormatEtc[i] = pFormatEtc[i];
+                    m_paStgMedium[i] = pStgMed[i];
+                }
+            }
+
+            /*
+             * Register fixed formats.
+             */
+#if 0
+            /* CF_HDROP. */
+            RegisterFormat(&mpFormatEtc[cFormats], CF_HDROP);
+            mpStgMedium[cFormats++].tymed = TYMED_HGLOBAL;
+
+            /* IStream. */
+            RegisterFormat(&mpFormatEtc[cFormats++],
+                           RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR));
+            RegisterFormat(&mpFormatEtc[cFormats++],
+                           RegisterClipboardFormat(CFSTR_FILECONTENTS),
+                           TYMED_ISTREAM, 0 /* lIndex */);
+
+            /* Required for e.g. Windows Media Player. */
+            RegisterFormat(&mpFormatEtc[cFormats++],
+                           RegisterClipboardFormat(CFSTR_FILENAME));
+            RegisterFormat(&mpFormatEtc[cFormats++],
+                           RegisterClipboardFormat(CFSTR_FILENAMEW));
+            RegisterFormat(&mpFormatEtc[cFormats++],
+                           RegisterClipboardFormat(CFSTR_SHELLIDLIST));
+            RegisterFormat(&mpFormatEtc[cFormats++],
+                           RegisterClipboardFormat(CFSTR_SHELLIDLISTOFFSET));
+#endif
+            m_cFormats  = cFormats;
+            m_enmStatus = Status_Initialized;
+        }
+        else
+            rc = VERR_NO_MEMORY;
+    }
+    else
+        rc = VERR_NO_MEMORY;
+
+    LogFlowFunc(("cFormats=%RU32 - %Rrc\n", cFormats, rc));
+    return rc;
+}
+
+int VBoxDnDDataObject::Destroy(void)
+{
+    if (m_enmStatus == Status_Uninitialized)
+        return VINF_SUCCESS;
+
+    AssertReturn(m_cRefs == 0, VERR_WRONG_ORDER);
+
+    if (m_paFormatEtc)
+    {
+        RTMemFree(m_paFormatEtc);
+        m_paFormatEtc = NULL;
+    }
+
+    if (m_paStgMedium)
+    {
+        RTMemFree(m_paStgMedium);
+        m_paStgMedium = NULL;
+    }
+
+    if (m_pvData)
+    {
+        RTMemFree(m_pvData);
+        m_pvData = NULL;
+    }
+
+    int rc = RTSemEventDestroy(m_EvtDropped);
+    AssertRCReturn(rc, rc);
+    m_EvtDropped = NIL_RTSEMEVENT;
+
+    m_enmStatus = Status_Uninitialized;
+
+    return VINF_SUCCESS;
+}
 
 /**
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDEnumFormat.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDEnumFormat.cpp	(revision 95835)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDEnumFormat.cpp	(revision 95836)
@@ -31,5 +31,5 @@
 
 
-VBoxDnDEnumFormatEtc::VBoxDnDEnumFormatEtc(LPFORMATETC pFormatEtc, ULONG cFormats)
+VBoxDnDEnumFormatEtc::VBoxDnDEnumFormatEtc(LPFORMATETC pFormatEtc, ULONG uIdx, ULONG cToCopy, ULONG cTotal)
     : m_cRefs(1)
     , m_uIdxCur(0)
@@ -38,20 +38,6 @@
 
 {
-    LogFlowFunc(("pFormatEtc=%p, cFormats=%RU32\n", pFormatEtc, cFormats));
-    /** @todo r=bird: Use an init() function! */
-    m_paFormatEtc = (LPFORMATETC)RTMemAllocZ(sizeof(*m_paFormatEtc) * cFormats);
-    if (m_paFormatEtc)
-    {
-        for (ULONG i = 0; i < cFormats; i++)
-        {
-            LogFlowFunc(("Format %RU32: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
-                         i, pFormatEtc[i].cfFormat, VBoxDnDDataObject::ClipboardFormatToString(pFormatEtc[i].cfFormat),
-                         pFormatEtc[i].tymed, pFormatEtc[i].dwAspect));
-            VBoxDnDEnumFormatEtc::CopyFormat(&m_paFormatEtc[i], &pFormatEtc[i]);
-        }
-        m_cFormats = cFormats;
-    }
-    else
-        Log(("Failed to allocate memory for %u formats!\n"));
+    int rc2 = Init(pFormatEtc, uIdx, cToCopy, cTotal);
+    AssertRC(rc2);
 }
 
@@ -74,4 +60,47 @@
 }
 
+/**
+ * Initializes the class by copying the required formats.
+ *
+ * @returns VBox status code.
+ * @param   pFormatEtc          Format Etc to use for initialization.
+ * @param   uIdx                Index (zero-based) of format
+ * @param   cToCopy             Number of formats \a pFormatEtc to copy, starting from \a uIdx.
+ * @param   cTotal              Number of total formats \a pFormatEtc holds.
+ */
+int VBoxDnDEnumFormatEtc::Init(LPFORMATETC pFormatEtc, ULONG uIdx, ULONG cToCopy, ULONG cTotal)
+{
+    AssertPtrReturn(pFormatEtc,            VERR_INVALID_POINTER);
+    AssertReturn(uIdx <= cTotal,           VERR_INVALID_PARAMETER);
+    AssertReturn(uIdx + cToCopy <= cTotal, VERR_INVALID_PARAMETER);
+    /* cFormats can be 0. */
+
+    if (!cToCopy)
+        return VINF_SUCCESS;
+
+    AssertReturn(m_paFormatEtc == NULL && m_cFormats == 0, VERR_WRONG_ORDER);
+
+    int rc = VINF_SUCCESS;
+
+    m_paFormatEtc = (LPFORMATETC)RTMemAllocZ(sizeof(FORMATETC) * cToCopy);
+    if (m_paFormatEtc)
+    {
+        for (ULONG i = 0; i < cToCopy; i++)
+        {
+            LPFORMATETC const pFormatCur = &pFormatEtc[uIdx + i];
+
+            LogFlowFunc(("Format %RU32 (index %RU32): cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
+                         i, uIdx + i, pFormatCur->cfFormat, VBoxDnDDataObject::ClipboardFormatToString(pFormatCur->cfFormat),
+                         pFormatCur->tymed, pFormatCur->dwAspect));
+            VBoxDnDEnumFormatEtc::CopyFormat(&m_paFormatEtc[i], pFormatCur);
+        }
+
+        m_cFormats = cToCopy;
+    }
+    else
+        rc = VERR_NO_MEMORY;
+    return rc;
+}
+
 /*
  * IUnknown methods.
@@ -153,9 +182,16 @@
 }
 
+/**
+ * Copies a format etc from \a pSource to \a aDest (deep copy).
+ *
+ * @returns VBox status code.
+ * @param   pDest               Where to copy \a pSource to.
+ * @param   pSource             Source to copy.
+ */
 /* static */
-void VBoxDnDEnumFormatEtc::CopyFormat(LPFORMATETC pDest, LPFORMATETC pSource)
-{
-    AssertPtrReturnVoid(pDest);
-    AssertPtrReturnVoid(pSource);
+int VBoxDnDEnumFormatEtc::CopyFormat(LPFORMATETC pDest, LPFORMATETC pSource)
+{
+    AssertPtrReturn(pDest  , VERR_INVALID_POINTER);
+    AssertPtrReturn(pSource, VERR_INVALID_POINTER);
 
     *pDest = *pSource;
@@ -164,20 +200,33 @@
     {
         pDest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE));
+        AssertPtrReturn(pDest->ptd, VERR_NO_MEMORY);
         *(pDest->ptd) = *(pSource->ptd);
     }
-}
-
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * Creates an IEnumFormatEtc interface from a given format etc structure.
+ *
+ * @returns HRESULT
+ * @param   nNumFormats         Number of formats to copy from \a pFormatEtc.
+ * @param   pFormatEtc          Format etc to use for creation.
+ * @param   ppEnumFormatEtc     Where to return the created IEnumFormatEtc interface on success.
+ */
 /* static */
 HRESULT VBoxDnDEnumFormatEtc::CreateEnumFormatEtc(UINT nNumFormats, LPFORMATETC pFormatEtc, IEnumFORMATETC **ppEnumFormatEtc)
 {
-    AssertReturn(nNumFormats, E_INVALIDARG);
+    /* cNumFormats can be 0. */
     AssertPtrReturn(pFormatEtc, E_INVALIDARG);
     AssertPtrReturn(ppEnumFormatEtc, E_INVALIDARG);
 
 #ifdef RT_EXCEPTIONS_ENABLED
-    try { *ppEnumFormatEtc = new VBoxDnDEnumFormatEtc(pFormatEtc, nNumFormats); }
+    try { *ppEnumFormatEtc = new VBoxDnDEnumFormatEtc(pFormatEtc,
+                                                      0 /* uIdx */,  nNumFormats /* cToCopy */, nNumFormats /* cTotal */); }
     catch (std::bad_alloc &)
 #else
-    *ppEnumFormatEtc = new VBoxDnDEnumFormatEtc(pFormatEtc, nNumFormats);
+    *ppEnumFormatEtc = new VBoxDnDEnumFormatEtc(pFormatEtc,
+                                                0 /* uIdx */, nNumFormats /* cToCopy */, nNumFormats /* cTotal */);
     if (!*ppEnumFormatEtc)
 #endif
