VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDEnumFormat.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.1 KB
Line 
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/*
7 * Copyright (C) 2013-2023 Oracle and/or its affiliates.
8 *
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
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_GUEST_DND
33#include <VBox/log.h>
34
35#include <iprt/win/windows.h>
36#include <new> /* For bad_alloc. */
37
38#include "VBoxTray.h"
39#include "VBoxHelpers.h"
40#include "VBoxDnD.h"
41
42
43VBoxDnDEnumFormatEtc::VBoxDnDEnumFormatEtc(LPFORMATETC pFormatEtc, ULONG uIdx, ULONG cToCopy, ULONG cTotal)
44 : m_cRefs(1)
45 , m_uIdxCur(0)
46 , m_cFormats(0)
47 , m_paFormatEtc(NULL)
48
49{
50 int rc2 = Init(pFormatEtc, uIdx, cToCopy, cTotal);
51 AssertRC(rc2);
52}
53
54VBoxDnDEnumFormatEtc::~VBoxDnDEnumFormatEtc(void)
55{
56 if (m_paFormatEtc)
57 {
58 for (ULONG i = 0; i < m_cFormats; i++)
59 if (m_paFormatEtc[i].ptd)
60 {
61 CoTaskMemFree(m_paFormatEtc[i].ptd);
62 m_paFormatEtc[i].ptd = NULL;
63 }
64
65 RTMemFree(m_paFormatEtc);
66 m_paFormatEtc = NULL;
67 }
68
69 LogFlowFunc(("m_lRefCount=%RI32\n", m_cRefs));
70}
71
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 */
81int 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
115/*
116 * IUnknown methods.
117 */
118
119STDMETHODIMP_(ULONG) VBoxDnDEnumFormatEtc::AddRef(void)
120{
121 return InterlockedIncrement(&m_cRefs);
122}
123
124STDMETHODIMP_(ULONG) VBoxDnDEnumFormatEtc::Release(void)
125{
126 LONG lCount = InterlockedDecrement(&m_cRefs);
127 if (lCount == 0)
128 {
129 delete this;
130 return 0;
131 }
132
133 return lCount;
134}
135
136STDMETHODIMP 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
150STDMETHODIMP VBoxDnDEnumFormatEtc::Next(ULONG cFormats, LPFORMATETC pFormatEtc, ULONG *pcFetched)
151{
152 ULONG ulCopied = 0;
153
154 if(cFormats == 0 || pFormatEtc == 0)
155 return E_INVALIDARG;
156
157 while ( m_uIdxCur < m_cFormats
158 && ulCopied < cFormats)
159 {
160 VBoxDnDEnumFormatEtc::CopyFormat(&pFormatEtc[ulCopied],
161 &m_paFormatEtc[m_uIdxCur]);
162 ulCopied++;
163 m_uIdxCur++;
164 }
165
166 if (pcFetched)
167 *pcFetched = ulCopied;
168
169 return (ulCopied == cFormats) ? S_OK : S_FALSE;
170}
171
172STDMETHODIMP VBoxDnDEnumFormatEtc::Skip(ULONG cFormats)
173{
174 m_uIdxCur += cFormats;
175 return (m_uIdxCur <= m_cFormats) ? S_OK : S_FALSE;
176}
177
178STDMETHODIMP VBoxDnDEnumFormatEtc::Reset(void)
179{
180 m_uIdxCur = 0;
181 return S_OK;
182}
183
184STDMETHODIMP VBoxDnDEnumFormatEtc::Clone(IEnumFORMATETC **ppEnumFormatEtc)
185{
186 HRESULT hrc = CreateEnumFormatEtc(m_cFormats, m_paFormatEtc, ppEnumFormatEtc);
187
188 if (hrc == S_OK)
189 ((VBoxDnDEnumFormatEtc *) *ppEnumFormatEtc)->m_uIdxCur = m_uIdxCur;
190
191 return hrc;
192}
193
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 */
201/* static */
202int VBoxDnDEnumFormatEtc::CopyFormat(LPFORMATETC pDest, LPFORMATETC pSource)
203{
204 AssertPtrReturn(pDest , VERR_INVALID_POINTER);
205 AssertPtrReturn(pSource, VERR_INVALID_POINTER);
206
207 *pDest = *pSource;
208
209 if (pSource->ptd)
210 {
211 pDest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE));
212 AssertPtrReturn(pDest->ptd, VERR_NO_MEMORY);
213 *(pDest->ptd) = *(pSource->ptd);
214 }
215
216 return VINF_SUCCESS;
217}
218
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 */
227/* static */
228HRESULT VBoxDnDEnumFormatEtc::CreateEnumFormatEtc(UINT nNumFormats, LPFORMATETC pFormatEtc, IEnumFORMATETC **ppEnumFormatEtc)
229{
230 /* cNumFormats can be 0. */
231 AssertPtrReturn(pFormatEtc, E_INVALIDARG);
232 AssertPtrReturn(ppEnumFormatEtc, E_INVALIDARG);
233
234#ifdef RT_EXCEPTIONS_ENABLED
235 try { *ppEnumFormatEtc = new VBoxDnDEnumFormatEtc(pFormatEtc,
236 0 /* uIdx */, nNumFormats /* cToCopy */, nNumFormats /* cTotal */); }
237 catch (std::bad_alloc &)
238#else
239 *ppEnumFormatEtc = new VBoxDnDEnumFormatEtc(pFormatEtc,
240 0 /* uIdx */, nNumFormats /* cToCopy */, nNumFormats /* cTotal */);
241 if (!*ppEnumFormatEtc)
242#endif
243 {
244 return E_OUTOFMEMORY;
245 }
246
247 return S_OK;
248}
249
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use