source: trunk/src/activeqt/control/qaxfactory.cpp@ 122

Last change on this file since 122 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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