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
4#include "qwindowsole.h"
7\
8#include<QtGui/qevent.h>
9#include <QtGui/qwindow.h>
10#include <QtGui/qpainter.h>
11#include <QtGui/qcursor.h>
12#include <QtGui/qguiapplication.h>
13
14#include <QtCore/qmimedata.h>
15#include <QtCore/qdebug.h>
16
17#include <shlobj.h>
18
20
21/*!
22 \class QWindowsOleDataObject
23 \brief OLE data container
24
25 The following methods are NOT supported for data transfer using the
26 clipboard or drag-drop:
27 \list
28 \li IDataObject::SetData -- return E_NOTIMPL
29 \li IDataObject::DAdvise -- return OLE_E_ADVISENOTSUPPORTED
30 \li ::DUnadvise
31 \li ::EnumDAdvise
32 \li IDataObject::GetCanonicalFormatEtc -- return E_NOTIMPL
33 (NOTE: must set pformatetcOut->ptd = NULL)
34 \endlist
35
36 \internal
37*/
38
40 data(mimeData),
41 CF_PERFORMEDDROPEFFECT(RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT))
42{
43 qCDebug(lcQpaMime) << __FUNCTION__ << mimeData->formats();
44}
45
47
49{
50 data = nullptr;
51}
52
54{
55 return data.data();
56}
57
59{
60 return performedEffect;
61}
62
64QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) noexcept
65{
66 HRESULT hr = ResultFromScode(DATA_E_FORMATETC);
67
68 if (data) {
70 if (auto converter = mc.converterFromMime(*pformatetc, data))
71 if (converter->convertFromMime(*pformatetc, data, pmedium))
72 hr = ResultFromScode(S_OK);
73 }
74
75 if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled())
76 qCDebug(lcQpaMime) <<__FUNCTION__ << *pformatetc << "returns" << Qt::hex << Qt::showbase << quint64(hr);
77
78 return hr;
79}
80
83{
84 return ResultFromScode(DATA_E_FORMATETC);
85}
86
88QWindowsOleDataObject::QueryGetData(LPFORMATETC pformatetc) noexcept
89{
90 HRESULT hr = ResultFromScode(DATA_E_FORMATETC);
91
92 if (QWindowsContext::verbose > 1)
93 qCDebug(lcQpaMime) << __FUNCTION__;
94
95 if (data) {
97 hr = mc.converterFromMime(*pformatetc, data) ?
98 ResultFromScode(S_OK) : ResultFromScode(S_FALSE);
99 }
100 if (QWindowsContext::verbose > 1)
101 qCDebug(lcQpaMime) << __FUNCTION__ << " returns 0x" << Qt::hex << int(hr);
102 return hr;
103}
104
106QWindowsOleDataObject::GetCanonicalFormatEtc(LPFORMATETC, LPFORMATETC pformatetcOut) noexcept
107{
108 pformatetcOut->ptd = nullptr;
109 return ResultFromScode(E_NOTIMPL);
110}
111
112STDMETHODIMP
113QWindowsOleDataObject::SetData(LPFORMATETC pFormatetc, STGMEDIUM *pMedium, BOOL fRelease) noexcept
114{
115 if (QWindowsContext::verbose > 1)
116 qCDebug(lcQpaMime) << __FUNCTION__;
117
118 HRESULT hr = ResultFromScode(E_NOTIMPL);
119
120 if (pFormatetc->cfFormat == CF_PERFORMEDDROPEFFECT && pMedium->tymed == TYMED_HGLOBAL) {
121 auto * val = (DWORD*)GlobalLock(pMedium->hGlobal);
122 performedEffect = *val;
123 GlobalUnlock(pMedium->hGlobal);
124 if (fRelease)
125 ReleaseStgMedium(pMedium);
126 hr = ResultFromScode(S_OK);
127 }
128 if (QWindowsContext::verbose > 1)
129 qCDebug(lcQpaMime) << __FUNCTION__ << " returns 0x" << Qt::hex << int(hr);
130 return hr;
131}
132
133
135QWindowsOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc) noexcept
136{
137 if (QWindowsContext::verbose > 1)
138 qCDebug(lcQpaMime) << __FUNCTION__ << "dwDirection=" << dwDirection;
139
140 if (!data)
141 return ResultFromScode(DATA_E_FORMATETC);
142
143 SCODE sc = S_OK;
144
145 QList<FORMATETC> fmtetcs;
146 if (dwDirection == DATADIR_GET) {
148 fmtetcs = mc.allFormatsForMime(data);
149 } else {
150 FORMATETC formatetc;
151 formatetc.cfFormat = CLIPFORMAT(CF_PERFORMEDDROPEFFECT);
152 formatetc.dwAspect = DVASPECT_CONTENT;
153 formatetc.lindex = -1;
154 formatetc.ptd = nullptr;
155 formatetc.tymed = TYMED_HGLOBAL;
156 fmtetcs.append(formatetc);
157 }
158
159 auto *enumFmtEtc = new QWindowsOleEnumFmtEtc(fmtetcs);
160 *ppenumFormatEtc = enumFmtEtc;
161 if (enumFmtEtc->isNull()) {
162 delete enumFmtEtc;
163 *ppenumFormatEtc = nullptr;
164 sc = E_OUTOFMEMORY;
165 }
166
167 return ResultFromScode(sc);
168}
169
171QWindowsOleDataObject::DAdvise(FORMATETC FAR*, DWORD,
172 LPADVISESINK, DWORD FAR*) noexcept
173{
174 return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
175}
176
177
180{
181 return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
182}
183
185QWindowsOleDataObject::EnumDAdvise(LPENUMSTATDATA FAR*) noexcept
186{
187 return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
188}
189
190/*!
191 \class QWindowsOleEnumFmtEtc
192 \brief Enumerates the FORMATETC structures supported by QWindowsOleDataObject.
193 \internal
194*/
195
196QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QList<FORMATETC> &fmtetcs)
197{
198 if (QWindowsContext::verbose > 1)
199 qCDebug(lcQpaMime) << __FUNCTION__ << fmtetcs;
200 m_lpfmtetcs.reserve(fmtetcs.count());
201 for (int idx = 0; idx < fmtetcs.count(); ++idx) {
202 auto destetc = new FORMATETC();
203 if (copyFormatEtc(destetc, &(fmtetcs.at(idx)))) {
204 m_lpfmtetcs.append(destetc);
205 } else {
206 m_isNull = true;
207 delete destetc;
208 break;
209 }
210 }
211}
212
213QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QList<LPFORMATETC> &lpfmtetcs)
214{
215 if (QWindowsContext::verbose > 1)
216 qCDebug(lcQpaMime) << __FUNCTION__;
217 m_lpfmtetcs.reserve(lpfmtetcs.count());
218 for (int idx = 0; idx < lpfmtetcs.count(); ++idx) {
219 LPFORMATETC srcetc = lpfmtetcs.at(idx);
220 auto destetc = new FORMATETC();
221 if (copyFormatEtc(destetc, srcetc)) {
222 m_lpfmtetcs.append(destetc);
223 } else {
224 m_isNull = true;
225 delete destetc;
226 break;
227 }
228 }
229}
230
232{
233 LPMALLOC pmalloc;
234
235 if (CoGetMalloc(MEMCTX_TASK, &pmalloc) == NOERROR) {
236 for (int idx = 0; idx < m_lpfmtetcs.count(); ++idx) {
237 LPFORMATETC tmpetc = m_lpfmtetcs.at(idx);
238 if (tmpetc->ptd)
239 pmalloc->Free(tmpetc->ptd);
240 delete tmpetc;
241 }
242
243 pmalloc->Release();
244 }
245 m_lpfmtetcs.clear();
246}
247
249{
250 return m_isNull;
251}
252
253// IEnumFORMATETC methods
255QWindowsOleEnumFmtEtc::Next(ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetched) noexcept
256{
257 ULONG i=0;
258 ULONG nOffset;
259
260 if (rgelt == nullptr)
261 return ResultFromScode(E_INVALIDARG);
262
263 while (i < celt) {
264 nOffset = m_nIndex + i;
265
266 if (nOffset < ULONG(m_lpfmtetcs.count())) {
267 copyFormatEtc(rgelt + i, m_lpfmtetcs.at(int(nOffset)));
268 i++;
269 } else {
270 break;
271 }
272 }
273
274 m_nIndex += i;
275
276 if (pceltFetched != nullptr)
277 *pceltFetched = i;
278
279 if (i != celt)
280 return ResultFromScode(S_FALSE);
281
282 return NOERROR;
283}
284
286QWindowsOleEnumFmtEtc::Skip(ULONG celt) noexcept
287{
288 ULONG i=0;
289 ULONG nOffset;
290
291 while (i < celt) {
292 nOffset = m_nIndex + i;
293
294 if (nOffset < ULONG(m_lpfmtetcs.count())) {
295 i++;
296 } else {
297 break;
298 }
299 }
300
301 m_nIndex += i;
302
303 if (i != celt)
304 return ResultFromScode(S_FALSE);
305
306 return NOERROR;
307}
308
311{
312 m_nIndex = 0;
313 return NOERROR;
314}
315
317QWindowsOleEnumFmtEtc::Clone(LPENUMFORMATETC FAR* newEnum) noexcept
318{
319 if (newEnum == nullptr)
320 return ResultFromScode(E_INVALIDARG);
321
322 auto *result = new QWindowsOleEnumFmtEtc(m_lpfmtetcs);
323 result->m_nIndex = m_nIndex;
324
325 if (result->isNull()) {
326 delete result;
327 return ResultFromScode(E_OUTOFMEMORY);
328 }
329
330 *newEnum = result;
331 return NOERROR;
332}
333
334bool QWindowsOleEnumFmtEtc::copyFormatEtc(LPFORMATETC dest, const FORMATETC *src) const
335{
336 if (dest == nullptr || src == nullptr)
337 return false;
338
339 *dest = *src;
340
341 if (src->ptd) {
342 LPMALLOC pmalloc;
343
344 if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR)
345 return false;
346
347 pmalloc->Alloc(src->ptd->tdSize);
348 memcpy(dest->ptd, src->ptd, size_t(src->ptd->tdSize));
349
350 pmalloc->Release();
351 }
352
353 return true;
354}
355
356QT_END_NAMESPACE
\inmodule QtCore
Definition qmimedata.h:16
Singleton container for all relevant information.
QWindowsMimeRegistry & mimeConverter() const
static QWindowsContext * instance()
Manages the list of QWindowsMimeConverter instances.
OLE data container.
Definition qwindowsole.h:22
STDMETHOD GetDataHere(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) noexcept override
~QWindowsOleDataObject() override
FORMATETC FAR * pFormatetc
Definition qwindowsole.h:39
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:51
~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)