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