[49947] | 1 | /* $Id: VBoxDnDEnumFormat.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
|
---|
| 2 | /** @file
|
---|
| 3 | * VBoxDnDEnumFormat.cpp - IEnumFORMATETC ("Format et cetera") implementation.
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
[98103] | 7 | * Copyright (C) 2013-2023 Oracle and/or its affiliates.
|
---|
[49947] | 8 | *
|
---|
[96407] | 9 | * This file is part of VirtualBox base platform packages, as
|
---|
| 10 | * available from https://www.virtualbox.org.
|
---|
| 11 | *
|
---|
| 12 | * This program is free software; you can redistribute it and/or
|
---|
| 13 | * modify it under the terms of the GNU General Public License
|
---|
| 14 | * as published by the Free Software Foundation, in version 3 of the
|
---|
| 15 | * License.
|
---|
| 16 | *
|
---|
| 17 | * This program is distributed in the hope that it will be useful, but
|
---|
| 18 | * WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
| 20 | * General Public License for more details.
|
---|
| 21 | *
|
---|
| 22 | * You should have received a copy of the GNU General Public License
|
---|
| 23 | * along with this program; if not, see <https://www.gnu.org/licenses>.
|
---|
| 24 | *
|
---|
| 25 | * SPDX-License-Identifier: GPL-3.0-only
|
---|
[49947] | 26 | */
|
---|
[69361] | 27 |
|
---|
[95960] | 28 |
|
---|
| 29 | /*********************************************************************************************************************************
|
---|
| 30 | * Header Files *
|
---|
| 31 | *********************************************************************************************************************************/
|
---|
[95961] | 32 | #define LOG_GROUP LOG_GROUP_GUEST_DND
|
---|
| 33 | #include <VBox/log.h>
|
---|
| 34 |
|
---|
[62679] | 35 | #include <iprt/win/windows.h>
|
---|
[49947] | 36 | #include <new> /* For bad_alloc. */
|
---|
| 37 |
|
---|
| 38 | #include "VBoxTray.h"
|
---|
| 39 | #include "VBoxHelpers.h"
|
---|
| 40 | #include "VBoxDnD.h"
|
---|
| 41 |
|
---|
| 42 |
|
---|
[95836] | 43 | VBoxDnDEnumFormatEtc::VBoxDnDEnumFormatEtc(LPFORMATETC pFormatEtc, ULONG uIdx, ULONG cToCopy, ULONG cTotal)
|
---|
[95734] | 44 | : m_cRefs(1)
|
---|
| 45 | , m_uIdxCur(0)
|
---|
| 46 | , m_cFormats(0)
|
---|
| 47 | , m_paFormatEtc(NULL)
|
---|
| 48 |
|
---|
[49947] | 49 | {
|
---|
[95836] | 50 | int rc2 = Init(pFormatEtc, uIdx, cToCopy, cTotal);
|
---|
| 51 | AssertRC(rc2);
|
---|
[49947] | 52 | }
|
---|
| 53 |
|
---|
| 54 | VBoxDnDEnumFormatEtc::~VBoxDnDEnumFormatEtc(void)
|
---|
| 55 | {
|
---|
[85694] | 56 | if (m_paFormatEtc)
|
---|
[49947] | 57 | {
|
---|
[85694] | 58 | for (ULONG i = 0; i < m_cFormats; i++)
|
---|
[95734] | 59 | if (m_paFormatEtc[i].ptd)
|
---|
| 60 | {
|
---|
[85694] | 61 | CoTaskMemFree(m_paFormatEtc[i].ptd);
|
---|
[95734] | 62 | m_paFormatEtc[i].ptd = NULL;
|
---|
| 63 | }
|
---|
[49947] | 64 |
|
---|
[95734] | 65 | RTMemFree(m_paFormatEtc);
|
---|
[85694] | 66 | m_paFormatEtc = NULL;
|
---|
[49947] | 67 | }
|
---|
| 68 |
|
---|
[85694] | 69 | LogFlowFunc(("m_lRefCount=%RI32\n", m_cRefs));
|
---|
[49947] | 70 | }
|
---|
| 71 |
|
---|
[95836] | 72 | /**
|
---|
| 73 | * Initializes the class by copying the required formats.
|
---|
| 74 | *
|
---|
| 75 | * @returns VBox status code.
|
---|
| 76 | * @param pFormatEtc Format Etc to use for initialization.
|
---|
| 77 | * @param uIdx Index (zero-based) of format
|
---|
| 78 | * @param cToCopy Number of formats \a pFormatEtc to copy, starting from \a uIdx.
|
---|
| 79 | * @param cTotal Number of total formats \a pFormatEtc holds.
|
---|
| 80 | */
|
---|
| 81 | int VBoxDnDEnumFormatEtc::Init(LPFORMATETC pFormatEtc, ULONG uIdx, ULONG cToCopy, ULONG cTotal)
|
---|
| 82 | {
|
---|
| 83 | AssertPtrReturn(pFormatEtc, VERR_INVALID_POINTER);
|
---|
| 84 | AssertReturn(uIdx <= cTotal, VERR_INVALID_PARAMETER);
|
---|
| 85 | AssertReturn(uIdx + cToCopy <= cTotal, VERR_INVALID_PARAMETER);
|
---|
| 86 | /* cFormats can be 0. */
|
---|
| 87 |
|
---|
| 88 | if (!cToCopy)
|
---|
| 89 | return VINF_SUCCESS;
|
---|
| 90 |
|
---|
| 91 | AssertReturn(m_paFormatEtc == NULL && m_cFormats == 0, VERR_WRONG_ORDER);
|
---|
| 92 |
|
---|
| 93 | int rc = VINF_SUCCESS;
|
---|
| 94 |
|
---|
| 95 | m_paFormatEtc = (LPFORMATETC)RTMemAllocZ(sizeof(FORMATETC) * cToCopy);
|
---|
| 96 | if (m_paFormatEtc)
|
---|
| 97 | {
|
---|
| 98 | for (ULONG i = 0; i < cToCopy; i++)
|
---|
| 99 | {
|
---|
| 100 | LPFORMATETC const pFormatCur = &pFormatEtc[uIdx + i];
|
---|
| 101 |
|
---|
| 102 | LogFlowFunc(("Format %RU32 (index %RU32): cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
|
---|
| 103 | i, uIdx + i, pFormatCur->cfFormat, VBoxDnDDataObject::ClipboardFormatToString(pFormatCur->cfFormat),
|
---|
| 104 | pFormatCur->tymed, pFormatCur->dwAspect));
|
---|
| 105 | VBoxDnDEnumFormatEtc::CopyFormat(&m_paFormatEtc[i], pFormatCur);
|
---|
| 106 | }
|
---|
| 107 |
|
---|
| 108 | m_cFormats = cToCopy;
|
---|
| 109 | }
|
---|
| 110 | else
|
---|
| 111 | rc = VERR_NO_MEMORY;
|
---|
| 112 | return rc;
|
---|
| 113 | }
|
---|
| 114 |
|
---|
[49947] | 115 | /*
|
---|
| 116 | * IUnknown methods.
|
---|
| 117 | */
|
---|
| 118 |
|
---|
| 119 | STDMETHODIMP_(ULONG) VBoxDnDEnumFormatEtc::AddRef(void)
|
---|
| 120 | {
|
---|
[85694] | 121 | return InterlockedIncrement(&m_cRefs);
|
---|
[49947] | 122 | }
|
---|
| 123 |
|
---|
| 124 | STDMETHODIMP_(ULONG) VBoxDnDEnumFormatEtc::Release(void)
|
---|
| 125 | {
|
---|
[85694] | 126 | LONG lCount = InterlockedDecrement(&m_cRefs);
|
---|
[49947] | 127 | if (lCount == 0)
|
---|
| 128 | {
|
---|
| 129 | delete this;
|
---|
| 130 | return 0;
|
---|
| 131 | }
|
---|
| 132 |
|
---|
| 133 | return lCount;
|
---|
| 134 | }
|
---|
| 135 |
|
---|
| 136 | STDMETHODIMP VBoxDnDEnumFormatEtc::QueryInterface(REFIID iid, void **ppvObject)
|
---|
| 137 | {
|
---|
| 138 | if ( iid == IID_IEnumFORMATETC
|
---|
| 139 | || iid == IID_IUnknown)
|
---|
| 140 | {
|
---|
| 141 | AddRef();
|
---|
| 142 | *ppvObject = this;
|
---|
| 143 | return S_OK;
|
---|
| 144 | }
|
---|
| 145 |
|
---|
| 146 | *ppvObject = 0;
|
---|
| 147 | return E_NOINTERFACE;
|
---|
| 148 | }
|
---|
| 149 |
|
---|
[56661] | 150 | STDMETHODIMP VBoxDnDEnumFormatEtc::Next(ULONG cFormats, LPFORMATETC pFormatEtc, ULONG *pcFetched)
|
---|
[49947] | 151 | {
|
---|
| 152 | ULONG ulCopied = 0;
|
---|
| 153 |
|
---|
| 154 | if(cFormats == 0 || pFormatEtc == 0)
|
---|
| 155 | return E_INVALIDARG;
|
---|
| 156 |
|
---|
[85694] | 157 | while ( m_uIdxCur < m_cFormats
|
---|
[49947] | 158 | && ulCopied < cFormats)
|
---|
| 159 | {
|
---|
| 160 | VBoxDnDEnumFormatEtc::CopyFormat(&pFormatEtc[ulCopied],
|
---|
[85694] | 161 | &m_paFormatEtc[m_uIdxCur]);
|
---|
[49947] | 162 | ulCopied++;
|
---|
[85694] | 163 | m_uIdxCur++;
|
---|
[49947] | 164 | }
|
---|
| 165 |
|
---|
| 166 | if (pcFetched)
|
---|
| 167 | *pcFetched = ulCopied;
|
---|
| 168 |
|
---|
| 169 | return (ulCopied == cFormats) ? S_OK : S_FALSE;
|
---|
| 170 | }
|
---|
| 171 |
|
---|
| 172 | STDMETHODIMP VBoxDnDEnumFormatEtc::Skip(ULONG cFormats)
|
---|
| 173 | {
|
---|
[85694] | 174 | m_uIdxCur += cFormats;
|
---|
| 175 | return (m_uIdxCur <= m_cFormats) ? S_OK : S_FALSE;
|
---|
[49947] | 176 | }
|
---|
| 177 |
|
---|
| 178 | STDMETHODIMP VBoxDnDEnumFormatEtc::Reset(void)
|
---|
| 179 | {
|
---|
[85694] | 180 | m_uIdxCur = 0;
|
---|
[49947] | 181 | return S_OK;
|
---|
| 182 | }
|
---|
| 183 |
|
---|
| 184 | STDMETHODIMP VBoxDnDEnumFormatEtc::Clone(IEnumFORMATETC **ppEnumFormatEtc)
|
---|
| 185 | {
|
---|
[95734] | 186 | HRESULT hrc = CreateEnumFormatEtc(m_cFormats, m_paFormatEtc, ppEnumFormatEtc);
|
---|
[49947] | 187 |
|
---|
[95734] | 188 | if (hrc == S_OK)
|
---|
[85694] | 189 | ((VBoxDnDEnumFormatEtc *) *ppEnumFormatEtc)->m_uIdxCur = m_uIdxCur;
|
---|
[49947] | 190 |
|
---|
[95734] | 191 | return hrc;
|
---|
[49947] | 192 | }
|
---|
| 193 |
|
---|
[95836] | 194 | /**
|
---|
| 195 | * Copies a format etc from \a pSource to \a aDest (deep copy).
|
---|
| 196 | *
|
---|
| 197 | * @returns VBox status code.
|
---|
| 198 | * @param pDest Where to copy \a pSource to.
|
---|
| 199 | * @param pSource Source to copy.
|
---|
| 200 | */
|
---|
[49947] | 201 | /* static */
|
---|
[95836] | 202 | int VBoxDnDEnumFormatEtc::CopyFormat(LPFORMATETC pDest, LPFORMATETC pSource)
|
---|
[49947] | 203 | {
|
---|
[95836] | 204 | AssertPtrReturn(pDest , VERR_INVALID_POINTER);
|
---|
| 205 | AssertPtrReturn(pSource, VERR_INVALID_POINTER);
|
---|
[49947] | 206 |
|
---|
| 207 | *pDest = *pSource;
|
---|
| 208 |
|
---|
| 209 | if (pSource->ptd)
|
---|
| 210 | {
|
---|
| 211 | pDest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE));
|
---|
[95836] | 212 | AssertPtrReturn(pDest->ptd, VERR_NO_MEMORY);
|
---|
[49947] | 213 | *(pDest->ptd) = *(pSource->ptd);
|
---|
| 214 | }
|
---|
[95836] | 215 |
|
---|
| 216 | return VINF_SUCCESS;
|
---|
[49947] | 217 | }
|
---|
| 218 |
|
---|
[95836] | 219 | /**
|
---|
| 220 | * Creates an IEnumFormatEtc interface from a given format etc structure.
|
---|
| 221 | *
|
---|
| 222 | * @returns HRESULT
|
---|
| 223 | * @param nNumFormats Number of formats to copy from \a pFormatEtc.
|
---|
| 224 | * @param pFormatEtc Format etc to use for creation.
|
---|
| 225 | * @param ppEnumFormatEtc Where to return the created IEnumFormatEtc interface on success.
|
---|
| 226 | */
|
---|
[49947] | 227 | /* static */
|
---|
[56661] | 228 | HRESULT VBoxDnDEnumFormatEtc::CreateEnumFormatEtc(UINT nNumFormats, LPFORMATETC pFormatEtc, IEnumFORMATETC **ppEnumFormatEtc)
|
---|
[49947] | 229 | {
|
---|
[95836] | 230 | /* cNumFormats can be 0. */
|
---|
[49947] | 231 | AssertPtrReturn(pFormatEtc, E_INVALIDARG);
|
---|
| 232 | AssertPtrReturn(ppEnumFormatEtc, E_INVALIDARG);
|
---|
| 233 |
|
---|
[95734] | 234 | #ifdef RT_EXCEPTIONS_ENABLED
|
---|
[95836] | 235 | try { *ppEnumFormatEtc = new VBoxDnDEnumFormatEtc(pFormatEtc,
|
---|
| 236 | 0 /* uIdx */, nNumFormats /* cToCopy */, nNumFormats /* cTotal */); }
|
---|
[95734] | 237 | catch (std::bad_alloc &)
|
---|
| 238 | #else
|
---|
[95836] | 239 | *ppEnumFormatEtc = new VBoxDnDEnumFormatEtc(pFormatEtc,
|
---|
| 240 | 0 /* uIdx */, nNumFormats /* cToCopy */, nNumFormats /* cTotal */);
|
---|
[95734] | 241 | if (!*ppEnumFormatEtc)
|
---|
| 242 | #endif
|
---|
[49947] | 243 | {
|
---|
[95734] | 244 | return E_OUTOFMEMORY;
|
---|
[49947] | 245 | }
|
---|
| 246 |
|
---|
[95734] | 247 | return S_OK;
|
---|
[49947] | 248 | }
|
---|
| 249 |
|
---|