Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwindowsole.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qwindowsole.h"
8\
9#include<QtGui/qevent.h>
10#include <QtGui/qwindow.h>
11#include <QtGui/qpainter.h>
12#include <QtGui/qcursor.h>
13#include <QtGui/qguiapplication.h>
14
15#include <QtCore/qmimedata.h>
16#include <QtCore/qdebug.h>
17
18#include <shlobj.h>
19
21
22/*!
23 \class QWindowsOleDataObject
24 \brief OLE data container
25
26 The following methods are NOT supported for data transfer using the
27 clipboard or drag-drop:
28 \list
29 \li IDataObject::SetData -- return E_NOTIMPL
30 \li IDataObject::DAdvise -- return OLE_E_ADVISENOTSUPPORTED
31 \li ::DUnadvise
32 \li ::EnumDAdvise
33 \li IDataObject::GetCanonicalFormatEtc -- return E_NOTIMPL
34 (NOTE: must set pformatetcOut->ptd = NULL)
35 \endlist
36
37 \internal
38*/
39
41 data(mimeData),
42 CF_PERFORMEDDROPEFFECT(RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT))
43{
44 qCDebug(lcQpaMime) << __FUNCTION__ << mimeData->formats();
45}
46
48
50{
51 data = nullptr;
52}
53
55{
56 return data.data();
57}
58
60{
61 return performedEffect;
62}
63
65QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) noexcept
66{
67 HRESULT hr = ResultFromScode(DATA_E_FORMATETC);
68
69 if (data) {
71 if (auto converter = mc.converterFromMime(*pformatetc, data))
72 if (converter->convertFromMime(*pformatetc, data, pmedium))
73 hr = ResultFromScode(S_OK);
74 }
75
76 if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled())
77 qCDebug(lcQpaMime) <<__FUNCTION__ << *pformatetc << "returns" << Qt::hex << Qt::showbase << quint64(hr);
78
79 return hr;
80}
81
84{
85 return ResultFromScode(DATA_E_FORMATETC);
86}
87
89QWindowsOleDataObject::QueryGetData(LPFORMATETC pformatetc) noexcept
90{
91 HRESULT hr = ResultFromScode(DATA_E_FORMATETC);
92
94 qCDebug(lcQpaMime) << __FUNCTION__;
95
96 if (data) {
98 hr = mc.converterFromMime(*pformatetc, data) ?
99 ResultFromScode(S_OK) : ResultFromScode(S_FALSE);
100 }
101 if (QWindowsContext::verbose > 1)
102 qCDebug(lcQpaMime) << __FUNCTION__ << " returns 0x" << Qt::hex << int(hr);
103 return hr;
104}
105
107QWindowsOleDataObject::GetCanonicalFormatEtc(LPFORMATETC, LPFORMATETC pformatetcOut) noexcept
108{
109 pformatetcOut->ptd = nullptr;
110 return ResultFromScode(E_NOTIMPL);
111}
112
113STDMETHODIMP
114QWindowsOleDataObject::SetData(LPFORMATETC pFormatetc, STGMEDIUM *pMedium, BOOL fRelease) noexcept
115{
117 qCDebug(lcQpaMime) << __FUNCTION__;
118
119 HRESULT hr = ResultFromScode(E_NOTIMPL);
120
121 if (pFormatetc->cfFormat == CF_PERFORMEDDROPEFFECT && pMedium->tymed == TYMED_HGLOBAL) {
122 if (GlobalSize(pMedium->hGlobal) >= sizeof(DWORD)) {
123 if (const auto *val = static_cast<const DWORD *>(GlobalLock(pMedium->hGlobal))) {
124 performedEffect = *val;
125 GlobalUnlock(pMedium->hGlobal);
126 }
127 }
128 if (fRelease)
129 ReleaseStgMedium(pMedium);
130 hr = ResultFromScode(S_OK);
131 }
132 if (QWindowsContext::verbose > 1)
133 qCDebug(lcQpaMime) << __FUNCTION__ << " returns 0x" << Qt::hex << int(hr);
134 return hr;
135}
136
137
139QWindowsOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc) noexcept
140{
142 qCDebug(lcQpaMime) << __FUNCTION__ << "dwDirection=" << dwDirection;
143
144 if (!data)
145 return ResultFromScode(DATA_E_FORMATETC);
146
147 SCODE sc = S_OK;
148
149 QList<FORMATETC> fmtetcs;
150 if (dwDirection == DATADIR_GET) {
152 fmtetcs = mc.allFormatsForMime(data);
153 } else {
154 FORMATETC formatetc;
155 formatetc.cfFormat = CLIPFORMAT(CF_PERFORMEDDROPEFFECT);
156 formatetc.dwAspect = DVASPECT_CONTENT;
157 formatetc.lindex = -1;
158 formatetc.ptd = nullptr;
159 formatetc.tymed = TYMED_HGLOBAL;
160 fmtetcs.append(formatetc);
161 }
162
163 auto *enumFmtEtc = new QWindowsOleEnumFmtEtc(fmtetcs);
164 *ppenumFormatEtc = enumFmtEtc;
165 if (enumFmtEtc->isNull()) {
166 delete enumFmtEtc;
167 *ppenumFormatEtc = nullptr;
168 sc = E_OUTOFMEMORY;
169 }
170
171 return ResultFromScode(sc);
172}
173
175QWindowsOleDataObject::DAdvise(FORMATETC FAR*, DWORD,
176 LPADVISESINK, DWORD FAR*) noexcept
177{
178 return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
179}
180
181
184{
185 return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
186}
187
189QWindowsOleDataObject::EnumDAdvise(LPENUMSTATDATA FAR*) noexcept
190{
191 return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
192}
193
194/*!
195 \class QWindowsOleEnumFmtEtc
196 \brief Enumerates the FORMATETC structures supported by QWindowsOleDataObject.
197 \internal
198*/
199
200QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QList<FORMATETC> &fmtetcs)
201{
203 qCDebug(lcQpaMime) << __FUNCTION__ << fmtetcs;
204 m_lpfmtetcs.reserve(fmtetcs.count());
205 for (int idx = 0; idx < fmtetcs.count(); ++idx) {
206 auto destetc = new FORMATETC();
207 if (copyFormatEtc(destetc, &(fmtetcs.at(idx)))) {
208 m_lpfmtetcs.append(destetc);
209 } else {
210 m_isNull = true;
211 delete destetc;
212 break;
213 }
214 }
215}
216
217QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QList<LPFORMATETC> &lpfmtetcs)
218{
220 qCDebug(lcQpaMime) << __FUNCTION__;
221 m_lpfmtetcs.reserve(lpfmtetcs.count());
222 for (int idx = 0; idx < lpfmtetcs.count(); ++idx) {
223 LPFORMATETC srcetc = lpfmtetcs.at(idx);
224 auto destetc = new FORMATETC();
225 if (copyFormatEtc(destetc, srcetc)) {
226 m_lpfmtetcs.append(destetc);
227 } else {
228 m_isNull = true;
229 delete destetc;
230 break;
231 }
232 }
233}
234
236{
237 LPMALLOC pmalloc;
238
239 if (CoGetMalloc(MEMCTX_TASK, &pmalloc) == NOERROR) {
240 for (int idx = 0; idx < m_lpfmtetcs.count(); ++idx) {
241 LPFORMATETC tmpetc = m_lpfmtetcs.at(idx);
242 if (tmpetc->ptd)
243 pmalloc->Free(tmpetc->ptd);
244 delete tmpetc;
245 }
246
247 pmalloc->Release();
248 }
249 m_lpfmtetcs.clear();
250}
251
253{
254 return m_isNull;
255}
256
257// IEnumFORMATETC methods
259QWindowsOleEnumFmtEtc::Next(ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetched) noexcept
260{
261 ULONG i=0;
262 ULONG nOffset;
263
264 if (rgelt == nullptr)
265 return ResultFromScode(E_INVALIDARG);
266
267 while (i < celt) {
268 nOffset = m_nIndex + i;
269
270 if (nOffset < ULONG(m_lpfmtetcs.count())) {
271 if (!copyFormatEtc(rgelt + i, m_lpfmtetcs.at(int(nOffset)))) {
272 m_nIndex += i;
273 if (pceltFetched != nullptr)
274 *pceltFetched = i;
275 return ResultFromScode(E_OUTOFMEMORY);
276 }
277 i++;
278 } else {
279 break;
280 }
281 }
282
283 m_nIndex += i;
284
285 if (pceltFetched != nullptr)
286 *pceltFetched = i;
287
288 if (i != celt)
289 return ResultFromScode(S_FALSE);
290
291 return NOERROR;
292}
293
295QWindowsOleEnumFmtEtc::Skip(ULONG celt) noexcept
296{
297 ULONG i=0;
298 ULONG nOffset;
299
300 while (i < celt) {
301 nOffset = m_nIndex + i;
302
303 if (nOffset < ULONG(m_lpfmtetcs.count())) {
304 i++;
305 } else {
306 break;
307 }
308 }
309
310 m_nIndex += i;
311
312 if (i != celt)
313 return ResultFromScode(S_FALSE);
314
315 return NOERROR;
316}
317
320{
321 m_nIndex = 0;
322 return NOERROR;
323}
324
326QWindowsOleEnumFmtEtc::Clone(LPENUMFORMATETC FAR* newEnum) noexcept
327{
328 if (newEnum == nullptr)
329 return ResultFromScode(E_INVALIDARG);
330
331 auto *result = new QWindowsOleEnumFmtEtc(m_lpfmtetcs);
332 result->m_nIndex = m_nIndex;
333
334 if (result->isNull()) {
335 delete result;
336 return ResultFromScode(E_OUTOFMEMORY);
337 }
338
339 *newEnum = result;
340 return NOERROR;
341}
342
343bool QWindowsOleEnumFmtEtc::copyFormatEtc(LPFORMATETC dest, const FORMATETC *src) const
344{
345 if (dest == nullptr || src == nullptr)
346 return false;
347
348 *dest = *src;
349
350 if (src->ptd) {
351 if (src->ptd->tdSize < sizeof(DVTARGETDEVICE)) {
352 dest->ptd = nullptr;
353 return false;
354 }
355
356 LPMALLOC pmalloc;
357 if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) {
358 dest->ptd = nullptr;
359 return false;
360 }
361
362 dest->ptd = static_cast<DVTARGETDEVICE *>(pmalloc->Alloc(src->ptd->tdSize));
363 if (!dest->ptd) {
364 pmalloc->Release();
365 return false;
366 }
367 memcpy(dest->ptd, src->ptd, size_t(src->ptd->tdSize));
368 pmalloc->Release();
369 }
370
371 return true;
372}
373
374QT_END_NAMESPACE
\inmodule QtCore
Definition qmimedata.h:17
Singleton container for all relevant information.
QWindowsMimeRegistry & mimeConverter() const
static QWindowsContext * instance()
Manages the list of QWindowsMimeConverter instances.
OLE data container.
Definition qwindowsole.h:23
STDMETHOD GetDataHere(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) noexcept override
~QWindowsOleDataObject() override
FORMATETC FAR * pFormatetc
Definition qwindowsole.h:40
STDMETHOD QueryGetData(LPFORMATETC pformatetc) noexcept override
STDMETHOD DUnadvise(DWORD dwConnection) noexcept override
QMimeData * mimeData() const
STDMETHOD EnumDAdvise(LPENUMSTATDATA FAR *ppenumAdvise) noexcept override
STDMETHOD EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR *ppenumFormatEtc) noexcept override
DWORD reportedPerformedEffect() const
STDMETHOD GetCanonicalFormatEtc(LPFORMATETC pformatetc, LPFORMATETC pformatetcOut) noexcept override
STDMETHOD GetData(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium) noexcept override
Enumerates the FORMATETC structures supported by QWindowsOleDataObject.
Definition qwindowsole.h:52
~QWindowsOleEnumFmtEtc() override
STDMETHOD Skip(ULONG celt) noexcept override
STDMETHOD Reset(void) noexcept override
STDMETHOD Next(ULONG celt, LPFORMATETC rgelt, ULONG FAR *pceltFetched) noexcept override
STDMETHOD Clone(LPENUMFORMATETC FAR *newEnum) noexcept override
QWindowsOleEnumFmtEtc(const QList< FORMATETC > &fmtetcs)
Combined button and popup list for selecting options.