1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the ActiveQt framework of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 **   * Redistributions of source code must retain the above copyright
15 **     notice, this list of conditions and the following disclaimer.
16 **   * Redistributions in binary form must reproduce the above copyright
17 **     notice, this list of conditions and the following disclaimer in
18 **     the documentation and/or other materials provided with the
19 **     distribution.
20 **   * Neither the name of The Qt Company Ltd nor the names of its
21 **     contributors may be used to endorse or promote products derived
22 **     from this software without specific prior written permission.
23 **
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #include "qaxfactory.h"
42 
43 #ifndef QT_NO_WIN_ACTIVEQT
44 
45 #include <qfile.h>
46 #include <qfileinfo.h>
47 #include <qmetaobject.h>
48 #include <qsettings.h>
49 #include <qwidget.h>
50 #include <qt_windows.h>
51 
52 QT_BEGIN_NAMESPACE
53 
54 extern wchar_t qAxModuleFilename[MAX_PATH];
55 
56 /*!
57     \class QAxFactory
58     \brief The QAxFactory class defines a factory for the creation of COM components.
59 
60     \inmodule QAxServer
61 
62     Implement this factory once in your COM server to provide information
63     about the components the server can create. Subclass QAxFactory and implement
64     the pure virtual functions in any implementation file (e.g. main.cpp), and export
65     the factory using the \c QAXFACTORY_EXPORT() macro.
66 
67     \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 0
68 
69     If you use the \c Q_CLASSINFO() macro to provide the unique
70     identifiers or other attributes for your class you can use the \c
71     QAXFACTORY_BEGIN(), \c QAXCLASS() and \c QAXFACTORY_END() macros to
72     expose one or more classes as COM objects.
73 
74     \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 1
75 
76 
77     If your server supports just a single COM object, you can use
78     a default factory implementation through the \c QAXFACTORY_DEFAULT() macro.
79 
80     \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 2
81 
82     Only one QAxFactory implementation may be instantiated and
83     exported by an ActiveX server application. This instance is accessible
84     through the global qAxFactory() function.
85 
86     A factory can also reimplement the registerClass() and
87     unregisterClass() functions to set additional flags for an ActiveX
88     control in the registry. To limit the number of methods or
89     properties a widget class exposes from its parent classes
90     reimplement exposeToSuperClass().
91 
92     \sa QAxAggregated, QAxBindable, {ActiveQt Framework}
93 */
94 
95 /*!
96     Constructs a QAxFactory object that returns \a libid and \a appid
97     in the implementation of the respective interface functions.
98 */
99 
QAxFactory(const QUuid & libid,const QUuid & appid)100 QAxFactory::QAxFactory(const QUuid &libid, const QUuid &appid)
101 : typelib(libid), app(appid)
102 {
103 }
104 
105 /*!
106     Destroys the QAxFactory object.
107 */
~QAxFactory()108 QAxFactory::~QAxFactory()
109 {
110 }
111 
112 /*!
113     \fn QUuid QAxFactory::typeLibID() const
114 
115     Reimplement this function to return the ActiveX server's type
116     library identifier.
117 */
typeLibID() const118 QUuid QAxFactory::typeLibID() const
119 {
120     return typelib;
121 }
122 
123 /*!
124     \fn QUuid QAxFactory::appID() const
125 
126     Reimplement this function to return the ActiveX server's
127     application identifier.
128 */
appID() const129 QUuid QAxFactory::appID() const
130 {
131     return app;
132 }
133 
134 /*!
135     \fn QStringList QAxFactory::featureList() const
136 
137     Reimplement this function to return a list of the widgets (class
138     names) supported by this factory.
139 */
140 
141 /*!
142     \fn QObject *QAxFactory::createObject(const QString &key)
143 
144     Reimplement this function to return a new object for \a key, or 0 if
145     this factory doesn't support the value of \a key.
146 
147     If the object returned is a QWidget it will be exposed as an ActiveX
148     control, otherwise the returned object will be exposed as a simple COM
149     object.
150 */
151 
152 /*!
153     \fn const QMetaObject *QAxFactory::metaObject(const QString &key) const
154 
155     Reimplement this function to return the QMetaObject corresponding to
156     \a key, or 0 if this factory doesn't support the value of \a key.
157 */
158 
159 /*!
160     \fn bool QAxFactory::createObjectWrapper(QObject *object, IDispatch **wrapper)
161 
162     Reimplement this function to provide the COM object for \a object
163     in \a wrapper. Return true if the function was successful; otherwise
164     return false.
165 
166     The default implementation creates a generic automation wrapper based
167     on the meta object information of \a object.
168 */
169 // implementation in qaxserverbase.cpp
170 
171 /*!
172     Reimplement this function to return the class identifier for each
173     \a key returned by the featureList() implementation, or an empty
174     QUuid if this factory doesn't support the value of \a key.
175 
176     The default implementation interprets \a key as the class name,
177     and returns the value of the Q_CLASSINFO() entry "ClassID".
178 */
classID(const QString & key) const179 QUuid QAxFactory::classID(const QString &key) const
180 {
181     const QMetaObject *mo = metaObject(key);
182     if (!mo)
183         return QUuid();
184     QString id = QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("ClassID")).value());
185 
186     return QUuid(id);
187 }
188 
189 /*!
190     Reimplement this function to return the interface identifier for
191     each \a key returned by the featureList() implementation, or an
192     empty QUuid if this factory doesn't support the value of \a key.
193 
194     The default implementation interprets \a key as the class name,
195     and returns the value of the Q_CLASSINFO() entry "InterfaceID".
196 */
interfaceID(const QString & key) const197 QUuid QAxFactory::interfaceID(const QString &key) const
198 {
199     const QMetaObject *mo = metaObject(key);
200     if (!mo)
201         return QUuid();
202     QString id = QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("InterfaceID")).value());
203 
204     return QUuid(id);
205 }
206 
207 /*!
208     Reimplement this function to return the identifier of the event
209     interface for each \a key returned by the featureList()
210     implementation, or an empty QUuid if this factory doesn't support
211     the value of \a key.
212 
213     The default implementation interprets \a key as the class name,
214     and returns the value of the Q_CLASSINFO() entry "EventsID".
215 */
eventsID(const QString & key) const216 QUuid QAxFactory::eventsID(const QString &key) const
217 {
218     const QMetaObject *mo = metaObject(key);
219     if (!mo)
220         return QUuid();
221     QString id = QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("EventsID")).value());
222 
223     return QUuid(id);
224 }
225 
226 /*!
227     Registers additional values for the class \a key in the system
228     registry using the \a settings object. The standard values have
229     already been registered by the framework, but additional values,
230     e.g. implemented categories, can be added in an implementation of
231     this function.
232 
233     \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 3
234 
235     If you reimplement this function you must also reimplement
236     unregisterClass() to remove the additional registry values.
237 
238     \sa QSettings
239 */
registerClass(const QString & key,QSettings * settings) const240 void QAxFactory::registerClass(const QString &key, QSettings *settings) const
241 {
242     Q_UNUSED(key);
243     Q_UNUSED(settings)
244 }
245 
246 /*!
247     Unregisters any additional values for the class \a key from the
248     system registry using the \a settings object.
249 
250     \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 4
251 
252     \sa registerClass(), QSettings
253 */
unregisterClass(const QString & key,QSettings * settings) const254 void QAxFactory::unregisterClass(const QString &key, QSettings *settings) const
255 {
256     Q_UNUSED(key);
257     Q_UNUSED(settings)
258 }
259 
260 /*!
261     Reimplement this function to return true if \a licenseKey is a valid
262     license for the class \a key, or if the current machine is licensed.
263 
264     The default implementation returns true if the class \a key is
265     not licensed (ie. no \c Q_CLASSINFO() attribute "LicenseKey"), or
266     if  \a licenseKey matches the value of the "LicenseKey"
267     attribute, or if the machine is licensed through a .LIC file with
268     the same filename as this COM server.
269 */
validateLicenseKey(const QString & key,const QString & licenseKey) const270 bool QAxFactory::validateLicenseKey(const QString &key, const QString &licenseKey) const
271 {
272     const QMetaObject *mo = metaObject(key);
273     if (!mo)
274         return true;
275 
276     QString classKey = QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value());
277     if (classKey.isEmpty())
278         return true;
279 
280     if (licenseKey.isEmpty()) {
281         QString licFile(QString::fromWCharArray(qAxModuleFilename));
282         int lastDot = licFile.lastIndexOf(QLatin1Char('.'));
283         licFile = licFile.left(lastDot) + QLatin1String(".lic");
284         if (QFile::exists(licFile))
285             return true;
286         return false;
287     }
288     return licenseKey == classKey;
289 }
290 
291 /*!
292     Reimplement this function to return the name of the super class of
293     \a key up to which methods and properties should be exposed by the
294     ActiveX control.
295 
296     The default implementation interprets \a key as the class name,
297     and returns the value of the \c Q_CLASSINFO() entry
298     "ToSuperClass". If no such value is set the null-string is
299     returned, and the functions  and properties of all the super
300     classes including QWidget will be  exposed.
301 
302     To only expose the functions and properties of the class itself,
303     reimplement this function to return \a key.
304 */
exposeToSuperClass(const QString & key) const305 QString QAxFactory::exposeToSuperClass(const QString &key) const
306 {
307     const QMetaObject *mo = metaObject(key);
308     if (!mo)
309         return QString();
310     return QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("ToSuperClass")).value());
311 }
312 
313 /*!
314     Reimplement this function to return true if the ActiveX control \a key
315     should be a top level window, e.g. a dialog. The default implementation
316     returns false.
317 */
stayTopLevel(const QString & key) const318 bool QAxFactory::stayTopLevel(const QString &key) const
319 {
320     return false;
321 }
322 
323 /*!
324     Reimplement this function to return true if the ActiveX control
325     \a key should support the standard ActiveX events
326     \list
327     \i Click
328     \i DblClick
329     \i KeyDown
330     \i KeyPress
331     \i KeyUp
332     \i MouseDown
333     \i MouseUp
334     \i MouseMove
335     \endlist
336 
337     The default implementation interprets \a key as the class name,
338     and returns true if the value of the \c Q_CLASSINFO() entry
339     "StockEvents" is "yes". Otherwise this function returns false.
340 */
hasStockEvents(const QString & key) const341 bool QAxFactory::hasStockEvents(const QString &key) const
342 {
343     const QMetaObject *mo = metaObject(key);
344     if (!mo)
345         return false;
346     return QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("StockEvents")).value()) == QLatin1String("yes");
347 }
348 
349 
350 extern bool qAxIsServer;
351 
352 /*!
353     Returns true if the application has been started (by COM) as an ActiveX
354     server, otherwise returns false.
355 
356     \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 5
357 */
358 
isServer()359 bool QAxFactory::isServer()
360 {
361     return qAxIsServer;
362 }
363 
364 extern wchar_t qAxModuleFilename[MAX_PATH];
365 
366 /*!
367     Returns the directory that contains the server binary.
368 
369     For out-of-process servers this is the same as
370     QApplication::applicationDirPath(). For in-process servers
371     that function returns the directory that contains the hosting
372     application.
373 */
serverDirPath()374 QString QAxFactory::serverDirPath()
375 {
376     return QFileInfo(QString::fromWCharArray(qAxModuleFilename)).absolutePath();
377 }
378 
379 /*!
380     Returns the file path of the server binary.
381 
382     For out-of-process servers this is the same as
383     QApplication::applicationFilePath(). For in-process servers
384     that function returns the file path of the hosting application.
385 */
serverFilePath()386 QString QAxFactory::serverFilePath()
387 {
388     return QString::fromWCharArray(qAxModuleFilename);
389 }
390 
391 /*!
392     Reimplement this function to return true if the server is
393     running as a persistent service (e.g. an NT service) and should
394     not terminate even when all objects provided have been released.
395 
396     The default implementation returns false.
397 */
isService() const398 bool QAxFactory::isService() const
399 {
400     return false;
401 }
402 
403 /*!
404     \enum QAxFactory::ServerType
405 
406     This enum specifies the different types of servers that can be
407     started with startServer.
408 
409     \value SingleInstance The server process can create only one instance of each
410     exported class. COM starts a new process for each request. This is typically
411     used in servers that export only one creatable class.
412     \value MultipleInstances The server can create multiple instances of
413     each exported class. This is the default. All instances will live in the same
414     thread, and will share static resources.
415 */
416 
417 /*!
418     \fn bool QAxFactory::startServer(ServerType type);
419 
420     Starts the COM server with \a type and returns true if successful,
421     otherwise returns false.
422 
423     Calling this function if the server is already running (or for an
424     in-process server) does nothing and returns true.
425 
426     The server is started automatically with \a type set to \c MultipleInstances
427     if the server executable has been started with the \c -activex
428     command line parameter. To switch to SingleInstance, call
429 
430     \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 6
431 
432     in your own main() entry point function.
433 */
434 
435 /*!
436     \fn bool QAxFactory::stopServer();
437 
438     Stops the COM server and returns true if successful, otherwise
439     returns false.
440 
441     Calling this function if the server is not running (or for an
442     in-process server) does nothing and returns true.
443 
444     Stopping the server will not invalidate existing objects, but no
445     new objects can be created from the existing server process. Usually
446     COM will start a new server process if additional objects are requested.
447 
448     The server is stopped automatically when the main() function returns.
449 */
450 
451 class ActiveObject : public QObject
452 {
453 public:
454     ActiveObject(QObject *parent, QAxFactory *factory);
455     ~ActiveObject();
456 
457     IDispatch *wrapper;
458     DWORD cookie;
459 };
460 
ActiveObject(QObject * parent,QAxFactory * factory)461 ActiveObject::ActiveObject(QObject *parent, QAxFactory *factory)
462 : QObject(parent), wrapper(0), cookie(0)
463 {
464     QLatin1String key(parent->metaObject()->className());
465 
466     factory->createObjectWrapper(parent, &wrapper);
467     if (wrapper)
468         RegisterActiveObject(wrapper, QUuid(factory->classID(key)), ACTIVEOBJECT_STRONG, &cookie);
469 }
470 
~ActiveObject()471 ActiveObject::~ActiveObject()
472 {
473     if (cookie)
474         RevokeActiveObject(cookie, 0);
475     if (wrapper)
476         wrapper->Release();
477 }
478 
479 /*!
480     Registers the QObject \a object with COM as a running object, and returns true if
481     the registration succeeded, otherwise returns false. The object is unregistered
482     automatically when it is destroyed.
483 
484     This function should only be called if the application has been started by the user
485     (i.e. not by COM to respond to a request), and only for one object, usually the
486     toplevel object of the application's object hierarchy.
487 
488     This function does nothing and returns false if the object's class info for
489     "RegisterObject" is not set to "yes", or if the server is an in-process server.
490 */
registerActiveObject(QObject * object)491 bool QAxFactory::registerActiveObject(QObject *object)
492 {
493     if (qstricmp(object->metaObject()->classInfo(object->metaObject()->indexOfClassInfo("RegisterObject")).value(), "yes"))
494         return false;
495 
496     if (!QString::fromWCharArray(qAxModuleFilename).toLower().endsWith(QLatin1String(".exe")))
497 	return false;
498 
499     ActiveObject *active = new ActiveObject(object, qAxFactory());
500     if (!active->wrapper || !active->cookie) {
501         delete active;
502         return false;
503     }
504     return true;
505 }
506 
507 /*!
508     \macro QAXFACTORY_DEFAULT(Class, ClassID, InterfaceID, EventID, LibID, AppID)
509     \relates QAxFactory
510 
511     This macro can be used to export a single QObject subclass \a Class a this
512     COM server through an implicitly declared QAxFactory implementation.
513 
514     This macro exports the class \a Class as a COM coclass with the CLSID \a ClassID.
515     The properties and slots will be declared through a COM interface with the IID
516     \a InterfaceID, and signals will be declared through a COM event interface with
517     the IID \a EventID. All declarations will be in a type library with the id \a LibID,
518     and if the server is an executable server then it will have the application id
519     \a AppID.
520 
521     \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 7
522 
523     \sa QAXFACTORY_EXPORT(), QAXFACTORY_BEGIN()
524 */
525 
526 /*!
527     \macro QAXFACTORY_EXPORT(Class, LibID, AppID)
528     \relates QAxFactory
529 
530     This macro can be used to export a QAxFactory implementation \a Class from
531     a COM server. All declarations will be in a type library with the id \a LibID,
532     and if the server is an executable server then it will have the application id
533     \a AppID.
534 
535     \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 8
536 
537     \sa QAXFACTORY_BEGIN()
538 */
539 
540 /*!
541     \macro QAXFACTORY_BEGIN(IDTypeLib, IDApp)
542     \relates QAxFactory
543 
544     This macro can be used to export multiple QObject classes through an
545     implicitly declared QAxFactory implementation. All QObject classes have to
546     declare the ClassID, InterfaceID and EventsID (if applicable) through the
547     Q_CLASSINFO() macro. All declarations will be in a type library with the id
548     \a IDTypeLib, and if the server is an executable server then it will have the
549     application id \a IDApp.
550 
551     This macro needs to be used together with the QAXCLASS(), QAXTYPE()
552     and QAXFACTORY_END() macros.
553 
554     \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 9
555 */
556 
557 /*!
558     \macro QAXCLASS(Class)
559     \relates QAxFactory
560 
561     This macro adds a creatable COM class \a Class to the QAxFactory declared
562     with the QAXFACTORY_BEGIN() macro.
563 
564     \sa QAXFACTORY_BEGIN(), QAXTYPE(), QAXFACTORY_END(), Q_CLASSINFO()
565 */
566 
567 /*!
568     \macro QAXTYPE(Class)
569     \relates QAxFactory
570 
571     This macro adds a non-creatable COM class \a Class to the QAxFactory
572     declared with the QAXFACTORY_BEGIN(). The class \a Class can be used
573     in APIs of other COM classes exported through QAXTYPE() or QAXCLASS().
574 
575     Instances of type \a Class can only be retrieved using APIs of already
576     instantiated objects.
577 
578     \sa QAXFACTORY_BEGIN(), QAXCLASS(), QAXFACTORY_END(), Q_CLASSINFO()
579 */
580 
581 /*!
582     \macro QAXFACTORY_END()
583     \relates QAxFactory
584 
585     Completes the QAxFactory declaration started with the QAXFACTORY_BEGIN()
586     macro.
587 
588     \sa QAXFACTORY_BEGIN(), QAXCLASS(), QAXTYPE()
589 */
590 
591 QT_END_NAMESPACE
592 #endif // QT_NO_WIN_ACTIVEQT
593