diff --git a/src/activeqt/control/control.pro b/src/activeqt/control/control.pro index b87c30e5b2b897e9834049ecfe5cfbb90f8c76d3..6409112f0eb25e428202e5806b0d3672a6214299 100644 --- a/src/activeqt/control/control.pro +++ b/src/activeqt/control/control.pro @@ -10,6 +10,7 @@ mingw: DEFINES += QT_NEEDS_QMAIN HEADERS = qaxaggregated.h \ qaxbindable.h \ qaxfactory.h \ + qclassfactory_p.h \ ../shared/qaxtypes.h SOURCES = qaxaggregated.cpp \ diff --git a/src/activeqt/control/qaxserverbase.cpp b/src/activeqt/control/qaxserverbase.cpp index 61645fd0406bdaf88406cd9e6988cdc09876f5f0..663edf1f5d490a3eaf6bd894a9bcb0fce7fd85dc 100644 --- a/src/activeqt/control/qaxserverbase.cpp +++ b/src/activeqt/control/qaxserverbase.cpp @@ -65,6 +65,9 @@ #include <qpa/qplatformnativeinterface.h> #include <qabstractnativeeventfilter.h> +#include <qcoreapplication.h> +#include <private/qthread_p.h> + #include "qaxfactory.h" #include "qaxbindable.h" #include "qaxaggregated.h" @@ -72,6 +75,8 @@ #include "../shared/qaxtypes.h" #include "../shared/qaxutils_p.h" +#include "qclassfactory_p.h" + #if defined Q_CC_GNU # include <w32api.h> #endif @@ -831,182 +836,180 @@ Q_GLOBAL_STATIC(QAxWinEventFilter, qax_winEventFilter); // COM Factory class, mapping COM requests to ActiveQt requests. // One instance of this class for each ActiveX the server can provide. -class QClassFactory : public IClassFactory2 +QClassFactory::QClassFactory(CLSID clsid) + : ref(0), licensed(false) { -public: - QClassFactory(CLSID clsid) - : ref(0), licensed(false) - { - InitializeCriticalSection(&refCountSection); - - // COM only knows the CLSID, but QAxFactory is class name based... - QStringList keys = qAxFactory()->featureList(); - foreach (const QString &key, keys) { - if (qAxFactory()->classID(key) == clsid) { - className = key; - break; - } - } + InitializeCriticalSection(&refCountSection); - const QMetaObject *mo = qAxFactory()->metaObject(className); - if (mo) { - classKey = QLatin1String(mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value()); - licensed = !classKey.isEmpty(); + // COM only knows the CLSID, but QAxFactory is class name based... + QStringList keys = qAxFactory()->featureList(); + foreach (const QString &key, keys) { + if (qAxFactory()->classID(key) == clsid) { + className = key; + break; } } - virtual ~QClassFactory() - { - DeleteCriticalSection(&refCountSection); + const QMetaObject *mo = qAxFactory()->metaObject(className); + if (mo) { + classKey = QLatin1String(mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value()); + licensed = !classKey.isEmpty(); } +} - // IUnknown - unsigned long WINAPI AddRef() - { - return InterlockedIncrement(&ref); - } - unsigned long WINAPI Release() - { - LONG refCount = InterlockedDecrement(&ref); - if (!refCount) - delete this; +QClassFactory::~QClassFactory() +{ + DeleteCriticalSection(&refCountSection); +} - return refCount; - } - HRESULT WINAPI QueryInterface(REFIID iid, LPVOID *iface) - { - *iface = 0; - if (iid == IID_IUnknown) - *iface = static_cast<IUnknown *>(this); - else if (iid == IID_IClassFactory) - *iface = static_cast<IClassFactory *>(this); - else if (iid == IID_IClassFactory2 && licensed) - *iface = static_cast<IClassFactory2 *>(this); - else - return E_NOINTERFACE; +// IUnknown +unsigned long QClassFactory::AddRef() +{ + return InterlockedIncrement(&ref); +} - AddRef(); - return S_OK; - } +unsigned long QClassFactory::Release() +{ + LONG refCount = InterlockedDecrement(&ref); + if (!refCount) + delete this; - HRESULT WINAPI CreateInstanceHelper(IUnknown *pUnkOuter, REFIID iid, void **ppObject) - { - if (pUnkOuter) { - if (iid != IID_IUnknown) - return CLASS_E_NOAGGREGATION; - const QMetaObject *mo = qAxFactory()->metaObject(className); - if (mo && !qstricmp(mo->classInfo(mo->indexOfClassInfo("Aggregatable")).value(), "no")) - return CLASS_E_NOAGGREGATION; - } + return refCount; +} - // Make sure a QApplication instance is present (inprocess case) - if (!qApp) { - qax_ownQApp = true; - int argc = 0; - new QApplication(argc, 0); - } - QGuiApplication::setQuitOnLastWindowClosed(false); +HRESULT QClassFactory::QueryInterface(REFIID iid, LPVOID *iface) +{ + *iface = 0; + if (iid == IID_IUnknown) + *iface = static_cast<IUnknown *>(this); + else if (iid == IID_IClassFactory) + *iface = static_cast<IClassFactory *>(this); + else if (iid == IID_IClassFactory2 && licensed) + *iface = static_cast<IClassFactory2 *>(this); + else + return E_NOINTERFACE; - if (qAxOutProcServer) - QAbstractEventDispatcher::instance()->installNativeEventFilter(qax_winEventFilter()); - else - QApplication::instance()->d_func()->in_exec = true; + AddRef(); + return S_OK; +} - // hook into eventloop; this allows a server to create his own QApplication object - if (!qax_hhook && qax_ownQApp) { - qax_hhook = SetWindowsHookEx(WH_GETMESSAGE, axs_FilterProc, 0, GetCurrentThreadId()); - } +HRESULT QClassFactory::CreateInstanceHelper(IUnknown *pUnkOuter, REFIID iid, void **ppObject) +{ + if (pUnkOuter) { + if (iid != IID_IUnknown) + return CLASS_E_NOAGGREGATION; + const QMetaObject *mo = qAxFactory()->metaObject(className); + if (mo && !qstricmp(mo->classInfo(mo->indexOfClassInfo("Aggregatable")).value(), "no")) + return CLASS_E_NOAGGREGATION; + } - // If we created QApplication instance, ensure native event loop starts properly - // by calling processEvents. - if (qax_ownQApp) - QCoreApplication::processEvents(); - - HRESULT res; - // Create the ActiveX wrapper - aggregate if requested - if (pUnkOuter) { - QAxServerAggregate *aggregate = new QAxServerAggregate(className, pUnkOuter); - res = aggregate->QueryInterface(iid, ppObject); - if (FAILED(res)) - delete aggregate; - } else { - QAxServerBase *activeqt = new QAxServerBase(className, pUnkOuter); - res = activeqt->QueryInterface(iid, ppObject); - if (FAILED(res)) - delete activeqt; - else - activeqt->registerActiveObject((IUnknown*)(IDispatch*)activeqt); - } - return res; + // Make sure a QApplication instance is present (inprocess case) + if (!qApp) { + qax_ownQApp = true; + int argc = 0; + new QApplication(argc, 0); } + QGuiApplication::setQuitOnLastWindowClosed(false); - // IClassFactory - HRESULT WINAPI CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppObject) - { - // class is licensed - if (licensed && !qAxFactory()->validateLicenseKey(className, QString())) - return CLASS_E_NOTLICENSED; + if (qAxOutProcServer) + QAbstractEventDispatcher::instance()->installNativeEventFilter(qax_winEventFilter()); + else + QApplication::instance()->d_func()->in_exec = true; - return CreateInstanceHelper(pUnkOuter, iid, ppObject); + // hook into eventloop; this allows a server to create his own QApplication object + if (!qax_hhook && qax_ownQApp) { + qax_hhook = SetWindowsHookEx(WH_GETMESSAGE, axs_FilterProc, 0, GetCurrentThreadId()); } - HRESULT WINAPI LockServer(BOOL fLock) - { - if (fLock) - qAxLock(); - else - qAxUnlock(); - return S_OK; + // If we created QApplication instance, ensure native event loop starts properly + // by calling processEvents. + if (qax_ownQApp) + QCoreApplication::processEvents(); + + HRESULT res; + // Create the ActiveX wrapper - aggregate if requested + if (pUnkOuter) { + QAxServerAggregate *aggregate = new QAxServerAggregate(className, pUnkOuter); + res = aggregate->QueryInterface(iid, ppObject); + if (FAILED(res)) + delete aggregate; + } else { + QAxServerBase *activeqt = new QAxServerBase(className, pUnkOuter); + res = activeqt->QueryInterface(iid, ppObject); + if (FAILED(res)) + delete activeqt; + else + activeqt->registerActiveObject((IUnknown*)(IDispatch*)activeqt); } + return res; +} - // IClassFactory2 - HRESULT WINAPI RequestLicKey(DWORD, BSTR *pKey) - { - if (!pKey) - return E_POINTER; - *pKey = 0; +// IClassFactory +HRESULT QClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppObject) +{ + // class is licensed + if (licensed && !qAxFactory()->validateLicenseKey(className, QString())) + return CLASS_E_NOTLICENSED; - // This of course works only on fully licensed machines - if (!qAxFactory()->validateLicenseKey(className, QString())) - return CLASS_E_NOTLICENSED; + return CreateInstanceHelper(pUnkOuter, iid, ppObject); +} - *pKey = QStringToBSTR(classKey); - return S_OK; - } +HRESULT QClassFactory::LockServer(BOOL fLock) +{ + if (fLock) + qAxLock(); + else + qAxUnlock(); - HRESULT WINAPI GetLicInfo(LICINFO *pLicInfo) - { - if (!pLicInfo) - return E_POINTER; - pLicInfo->cbLicInfo = sizeof(LICINFO); + return S_OK; +} - // class specific license key? - const QMetaObject *mo = qAxFactory()->metaObject(className); - const char *key = mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value(); - pLicInfo->fRuntimeKeyAvail = key && key[0]; +// IClassFactory2 +HRESULT QClassFactory::RequestLicKey(DWORD, BSTR *pKey) +{ + if (!pKey) + return E_POINTER; + *pKey = 0; - // machine fully licensed? - pLicInfo->fLicVerified = qAxFactory()->validateLicenseKey(className, QString()); + // This of course works only on fully licensed machines + if (!qAxFactory()->validateLicenseKey(className, QString())) + return CLASS_E_NOTLICENSED; - return S_OK; - } + *pKey = QStringToBSTR(classKey); + return S_OK; +} - HRESULT WINAPI CreateInstanceLic(IUnknown *pUnkOuter, IUnknown * /* pUnkReserved */, REFIID iid, BSTR bKey, PVOID *ppObject) - { - QString licenseKey = QString::fromWCharArray(bKey); - if (!qAxFactory()->validateLicenseKey(className, licenseKey)) - return CLASS_E_NOTLICENSED; - return CreateInstanceHelper(pUnkOuter, iid, ppObject); - } +HRESULT QClassFactory::GetLicInfo(LICINFO *pLicInfo) +{ + if (!pLicInfo) + return E_POINTER; + pLicInfo->cbLicInfo = sizeof(LICINFO); - QString className; + // class specific license key? + const QMetaObject *mo = qAxFactory()->metaObject(className); + const char *key = mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value(); + pLicInfo->fRuntimeKeyAvail = key && key[0]; + + // machine fully licensed? + pLicInfo->fLicVerified = qAxFactory()->validateLicenseKey(className, QString()); + + return S_OK; +} + +HRESULT QClassFactory::CreateInstanceLic(IUnknown *pUnkOuter, IUnknown * /* pUnkReserved */, REFIID iid, BSTR bKey, PVOID *ppObject) +{ + QString licenseKey = QString::fromWCharArray(bKey); + if (!qAxFactory()->validateLicenseKey(className, licenseKey)) + return CLASS_E_NOTLICENSED; + return CreateInstanceHelper(pUnkOuter, iid, ppObject); +} + +void QClassFactory::cleanupCreatedApplication(QCoreApplication &app) +{ + // Cleanup similar to QCoreApplication::exec() + app.d_func()->execCleanup(); +} -protected: - CRITICAL_SECTION refCountSection; - LONG ref; - bool licensed; - QString classKey; -}; // Create a QClassFactory object for class \a iid HRESULT GetClassObject(REFIID clsid, REFIID iid, void **ppUnk) diff --git a/src/activeqt/control/qaxserverdll.cpp b/src/activeqt/control/qaxserverdll.cpp index 7117cbb051f94b2e7996dd6b185334a11ca67537..b0584d5b09fb119ff9a4bf314f60c0842237c596 100644 --- a/src/activeqt/control/qaxserverdll.cpp +++ b/src/activeqt/control/qaxserverdll.cpp @@ -45,6 +45,8 @@ #include <qt_windows.h> +#include "qclassfactory_p.h" + QT_BEGIN_NAMESPACE bool qax_ownQApp = false; @@ -111,6 +113,7 @@ STDAPI DllCanUnloadNow() if (qax_hhook) UnhookWindowsHookEx(qax_hhook); + QClassFactory::cleanupCreatedApplication(*qApp); delete qApp; qax_ownQApp = false; diff --git a/src/activeqt/control/qclassfactory_p.h b/src/activeqt/control/qclassfactory_p.h new file mode 100644 index 0000000000000000000000000000000000000000..633c6f1a209f2a321ac2eca6cafe17699e26bc03 --- /dev/null +++ b/src/activeqt/control/qclassfactory_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the ActiveQt framework of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLASSFACTORY_P_H +#define QCLASSFACTORY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <qcoreapplication.h> +#include <ocidl.h> + +QT_BEGIN_NAMESPACE + +// COM Factory class, mapping COM requests to ActiveQt requests. +// One instance of this class for each ActiveX the server can provide. +class QClassFactory : public IClassFactory2 +{ +public: + QClassFactory(CLSID clsid); + + virtual ~QClassFactory(); + + // IUnknown + unsigned long WINAPI AddRef(); + unsigned long WINAPI Release(); + HRESULT WINAPI QueryInterface(REFIID iid, LPVOID *iface); + + HRESULT WINAPI CreateInstanceHelper(IUnknown *pUnkOuter, REFIID iid, void **ppObject); + + // IClassFactory + HRESULT WINAPI CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppObject); + + HRESULT WINAPI LockServer(BOOL fLock); + // IClassFactory2 + HRESULT WINAPI RequestLicKey(DWORD, BSTR *pKey); + + HRESULT WINAPI GetLicInfo(LICINFO *pLicInfo); + + HRESULT WINAPI CreateInstanceLic(IUnknown *pUnkOuter, IUnknown * /* pUnkReserved */, REFIID iid, BSTR bKey, PVOID *ppObject); + + static void cleanupCreatedApplication(QCoreApplication &app); + + QString className; + +protected: + CRITICAL_SECTION refCountSection; + LONG ref; + bool licensed; + QString classKey; +}; + +QT_END_NAMESPACE + +#endif // QCLASSFACTORY_P_H