From 0b8d0804219b7e2e6179112d663b989d5b749d17 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 17 Aug 2011 15:58:39 +0200 Subject: Add Windows to the Lighthouse. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an initial Lighthouse plugin for the Windows operating system. Change-Id: I6934562266e1aa0ac270bf6107df05a9e56ef82c Reviewed-on: http://codereview.qt.nokia.com/3107 Reviewed-by: Oliver Wolff Reviewed-by: Samuel Rødal --- src/plugins/platforms/windows/qwindowsole.cpp | 476 ++++++++++++++++++++++++++ 1 file changed, 476 insertions(+) create mode 100644 src/plugins/platforms/windows/qwindowsole.cpp (limited to 'src/plugins/platforms/windows/qwindowsole.cpp') diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp new file mode 100644 index 0000000000..864dc3dbb7 --- /dev/null +++ b/src/plugins/platforms/windows/qwindowsole.cpp @@ -0,0 +1,476 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowsole.h" +#include "qwindowsmime.h" +#include "qwindowscontext.h" +\ +#include +#include +#include +#include +#include + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QWindowsOleDataObject + \brief OLE data container + + The following methods are NOT supported for data transfer using the + clipboard or drag-drop: + \list + \o IDataObject::SetData -- return E_NOTIMPL + \o IDataObject::DAdvise -- return OLE_E_ADVISENOTSUPPORTED + \o ::DUnadvise + \o ::EnumDAdvise + \o IDataObject::GetCanonicalFormatEtc -- return E_NOTIMPL + (NOTE: must set pformatetcOut->ptd = NULL) + \endlist + + \ingroup qt-lighthouse-win +*/ + +QWindowsOleDataObject::QWindowsOleDataObject(QMimeData *mimeData) : + m_refs(1), data(mimeData), + CF_PERFORMEDDROPEFFECT(RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT)), + performedEffect(DROPEFFECT_NONE) +{ + if (QWindowsContext::verboseOLE) + qDebug("%s '%s'", __FUNCTION__, qPrintable(mimeData->formats().join(QStringLiteral(", ")))); +} + +QWindowsOleDataObject::~QWindowsOleDataObject() +{ + if (QWindowsContext::verboseOLE) + qDebug("%s", __FUNCTION__); +} + +void QWindowsOleDataObject::releaseQt() +{ + data = 0; +} + +QMimeData *QWindowsOleDataObject::mimeData() const +{ + return data.data(); +} + +DWORD QWindowsOleDataObject::reportedPerformedEffect() const +{ + return performedEffect; +} + +//--------------------------------------------------------------------- +// IUnknown Methods +//--------------------------------------------------------------------- + +STDMETHODIMP +QWindowsOleDataObject::QueryInterface(REFIID iid, void FAR* FAR* ppv) +{ + if (iid == IID_IUnknown || iid == IID_IDataObject) { + *ppv = this; + AddRef(); + return NOERROR; + } + *ppv = NULL; + return ResultFromScode(E_NOINTERFACE); +} + +STDMETHODIMP_(ULONG) +QWindowsOleDataObject::AddRef(void) +{ + return ++m_refs; +} + +STDMETHODIMP_(ULONG) +QWindowsOleDataObject::Release(void) +{ + if (--m_refs == 0) { + releaseQt(); + delete this; + return 0; + } + return m_refs; +} + +STDMETHODIMP +QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) +{ + HRESULT hr = ResultFromScode(DATA_E_FORMATETC); + + if (QWindowsContext::verboseOLE) { + wchar_t buf[256] = {0}; + GetClipboardFormatName(pformatetc->cfFormat, buf, 255); + qDebug("%s CF = %d : %s", __FUNCTION__, pformatetc->cfFormat, qPrintable(QString::fromWCharArray(buf))); + } + + if (data) { + const QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter(); + if (QWindowsMime *converter = mc.converterFromMime(*pformatetc, data)) + if (converter->convertFromMime(*pformatetc, data, pmedium)) + hr = ResultFromScode(S_OK); + } + + if (QWindowsContext::verboseOLE) { + wchar_t buf[256] = {0}; + GetClipboardFormatName(pformatetc->cfFormat, buf, 255); + qDebug("%s CF = %d : %s returns 0x%x", __FUNCTION__, pformatetc->cfFormat, + qPrintable(QString::fromWCharArray(buf)), int(hr)); + } + + return hr; +} + +STDMETHODIMP +QWindowsOleDataObject::GetDataHere(LPFORMATETC, LPSTGMEDIUM) +{ + return ResultFromScode(DATA_E_FORMATETC); +} + +STDMETHODIMP +QWindowsOleDataObject::QueryGetData(LPFORMATETC pformatetc) +{ + HRESULT hr = ResultFromScode(DATA_E_FORMATETC); + + if (QWindowsContext::verboseOLE > 1) + qDebug("%s", __FUNCTION__); + + if (data) { + const QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter(); + hr = mc.converterFromMime(*pformatetc, data) ? + ResultFromScode(S_OK) : ResultFromScode(S_FALSE); + } + if (QWindowsContext::verboseOLE > 1) + qDebug("%s returns 0x%x", __FUNCTION__, int(hr)); + return hr; +} + +STDMETHODIMP +QWindowsOleDataObject::GetCanonicalFormatEtc(LPFORMATETC, LPFORMATETC pformatetcOut) +{ + pformatetcOut->ptd = NULL; + return ResultFromScode(E_NOTIMPL); +} + +STDMETHODIMP +QWindowsOleDataObject::SetData(LPFORMATETC pFormatetc, STGMEDIUM *pMedium, BOOL fRelease) +{ + if (QWindowsContext::verboseOLE > 1) + qDebug("%s", __FUNCTION__); + + HRESULT hr = ResultFromScode(E_NOTIMPL); + + if (pFormatetc->cfFormat == CF_PERFORMEDDROPEFFECT && pMedium->tymed == TYMED_HGLOBAL) { + DWORD * val = (DWORD*)GlobalLock(pMedium->hGlobal); + performedEffect = *val; + GlobalUnlock(pMedium->hGlobal); + if (fRelease) + ReleaseStgMedium(pMedium); + hr = ResultFromScode(S_OK); + } + if (QWindowsContext::verboseOLE > 1) + qDebug("%s returns 0x%x", __FUNCTION__, int(hr)); + return hr; +} + + +STDMETHODIMP +QWindowsOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc) +{ + if (QWindowsContext::verboseOLE > 1) + qDebug("%s", __FUNCTION__); + + if (!data) + return ResultFromScode(DATA_E_FORMATETC); + + SCODE sc = S_OK; + + QVector fmtetcs; + if (dwDirection == DATADIR_GET) { + QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter(); + fmtetcs = mc.allFormatsForMime(data); + } else { + FORMATETC formatetc; + formatetc.cfFormat = CF_PERFORMEDDROPEFFECT; + formatetc.dwAspect = DVASPECT_CONTENT; + formatetc.lindex = -1; + formatetc.ptd = NULL; + formatetc.tymed = TYMED_HGLOBAL; + fmtetcs.append(formatetc); + } + + QWindowsOleEnumFmtEtc *enumFmtEtc = new QWindowsOleEnumFmtEtc(fmtetcs); + *ppenumFormatEtc = enumFmtEtc; + if (enumFmtEtc->isNull()) { + delete enumFmtEtc; + *ppenumFormatEtc = NULL; + sc = E_OUTOFMEMORY; + } + + return ResultFromScode(sc); +} + +STDMETHODIMP +QWindowsOleDataObject::DAdvise(FORMATETC FAR*, DWORD, + LPADVISESINK, DWORD FAR*) +{ + return ResultFromScode(OLE_E_ADVISENOTSUPPORTED); +} + + +STDMETHODIMP +QWindowsOleDataObject::DUnadvise(DWORD) +{ + return ResultFromScode(OLE_E_ADVISENOTSUPPORTED); +} + +STDMETHODIMP +QWindowsOleDataObject::EnumDAdvise(LPENUMSTATDATA FAR*) +{ + return ResultFromScode(OLE_E_ADVISENOTSUPPORTED); +} + +/*! + \class QWindowsOleEnumFmtEtc + \brief Enumerates the FORMATETC structures supported by QWindowsOleDataObject. + \ingroup qt-lighthouse-win +*/ + +QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector &fmtetcs) : + m_dwRefs(1), m_nIndex(0), m_isNull(false) +{ + if (QWindowsContext::verboseOLE > 1) + qDebug("%s", __FUNCTION__); + m_lpfmtetcs.reserve(fmtetcs.count()); + for (int idx = 0; idx < fmtetcs.count(); ++idx) { + LPFORMATETC destetc = new FORMATETC(); + if (copyFormatEtc(destetc, (LPFORMATETC)&(fmtetcs.at(idx)))) { + m_lpfmtetcs.append(destetc); + } else { + m_isNull = true; + delete destetc; + break; + } + } +} + +QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector &lpfmtetcs) : + m_dwRefs(1), m_nIndex(0), m_isNull(false) +{ + if (QWindowsContext::verboseOLE > 1) + qDebug("%s", __FUNCTION__); + m_lpfmtetcs.reserve(lpfmtetcs.count()); + for (int idx = 0; idx < lpfmtetcs.count(); ++idx) { + LPFORMATETC srcetc = lpfmtetcs.at(idx); + LPFORMATETC destetc = new FORMATETC(); + if (copyFormatEtc(destetc, srcetc)) { + m_lpfmtetcs.append(destetc); + } else { + m_isNull = true; + delete destetc; + break; + } + } +} + +QWindowsOleEnumFmtEtc::~QWindowsOleEnumFmtEtc() +{ + LPMALLOC pmalloc; + + if (CoGetMalloc(MEMCTX_TASK, &pmalloc) == NOERROR) { + for (int idx = 0; idx < m_lpfmtetcs.count(); ++idx) { + LPFORMATETC tmpetc = m_lpfmtetcs.at(idx); + if (tmpetc->ptd) + pmalloc->Free(tmpetc->ptd); + delete tmpetc; + } + + pmalloc->Release(); + } + m_lpfmtetcs.clear(); +} + +bool QWindowsOleEnumFmtEtc::isNull() const +{ + return m_isNull; +} + +// IUnknown methods +STDMETHODIMP +QWindowsOleEnumFmtEtc::QueryInterface(REFIID riid, void FAR* FAR* ppvObj) +{ + if (riid == IID_IUnknown || riid == IID_IEnumFORMATETC) { + *ppvObj = this; + AddRef(); + return NOERROR; + } + *ppvObj = NULL; + return ResultFromScode(E_NOINTERFACE); +} + +STDMETHODIMP_(ULONG) +QWindowsOleEnumFmtEtc::AddRef(void) +{ + return ++m_dwRefs; +} + +STDMETHODIMP_(ULONG) +QWindowsOleEnumFmtEtc::Release(void) +{ + if (--m_dwRefs == 0) { + delete this; + return 0; + } + return m_dwRefs; +} + +// IEnumFORMATETC methods +STDMETHODIMP +QWindowsOleEnumFmtEtc::Next(ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetched) +{ + ULONG i=0; + ULONG nOffset; + + if (rgelt == NULL) + return ResultFromScode(E_INVALIDARG); + + while (i < celt) { + nOffset = m_nIndex + i; + + if (nOffset < ULONG(m_lpfmtetcs.count())) { + copyFormatEtc((LPFORMATETC)&(rgelt[i]), m_lpfmtetcs.at(nOffset)); + i++; + } else { + break; + } + } + + m_nIndex += (WORD)i; + + if (pceltFetched != NULL) + *pceltFetched = i; + + if (i != celt) + return ResultFromScode(S_FALSE); + + return NOERROR; +} + +STDMETHODIMP +QWindowsOleEnumFmtEtc::Skip(ULONG celt) +{ + ULONG i=0; + ULONG nOffset; + + while (i < celt) { + nOffset = m_nIndex + i; + + if (nOffset < ULONG(m_lpfmtetcs.count())) { + i++; + } else { + break; + } + } + + m_nIndex += (WORD)i; + + if (i != celt) + return ResultFromScode(S_FALSE); + + return NOERROR; +} + +STDMETHODIMP +QWindowsOleEnumFmtEtc::Reset() +{ + m_nIndex = 0; + return NOERROR; +} + +STDMETHODIMP +QWindowsOleEnumFmtEtc::Clone(LPENUMFORMATETC FAR* newEnum) +{ + if (newEnum == NULL) + return ResultFromScode(E_INVALIDARG); + + QWindowsOleEnumFmtEtc *result = new QWindowsOleEnumFmtEtc(m_lpfmtetcs); + result->m_nIndex = m_nIndex; + + if (result->isNull()) { + delete result; + return ResultFromScode(E_OUTOFMEMORY); + } else { + *newEnum = result; + } + + return NOERROR; +} + +bool QWindowsOleEnumFmtEtc::copyFormatEtc(LPFORMATETC dest, LPFORMATETC src) const +{ + if (dest == NULL || src == NULL) + return false; + + *dest = *src; + + if (src->ptd) { + LPVOID pout; + LPMALLOC pmalloc; + + if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) + return false; + + pout = (LPVOID)pmalloc->Alloc(src->ptd->tdSize); + memcpy(dest->ptd, src->ptd, size_t(src->ptd->tdSize)); + + pmalloc->Release(); + } + + return true; +} + +QT_END_NAMESPACE -- cgit v1.2.3