source: trunk/src/activeqt/control/qaxserver.cpp@ 1168

Last change on this file since 1168 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 47.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the ActiveQt framework of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:BSD$
10** You may use this file under the terms of the BSD license as follows:
11**
12** "Redistribution and use in source and binary forms, with or without
13** modification, are permitted provided that the following conditions are
14** met:
15** * Redistributions of source code must retain the above copyright
16** notice, this list of conditions and the following disclaimer.
17** * Redistributions in binary form must reproduce the above copyright
18** notice, this list of conditions and the following disclaimer in
19** the documentation and/or other materials provided with the
20** distribution.
21** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
22** the names of its contributors may be used to endorse or promote
23** products derived from this software without specific prior written
24** permission.
25**
26** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#include "qaxbindable.h"
42#include "qaxfactory.h"
43
44#ifndef QT_NO_WIN_ACTIVEQT
45
46#include <qapplication.h>
47#include <qdatetime.h>
48#include <qdir.h>
49#include <qmap.h>
50#include <qmenubar.h>
51#include <qmetaobject.h>
52#include <qsettings.h>
53#include <qvariant.h>
54#include <qtextstream.h>
55
56#include <qt_windows.h>
57#include <olectl.h>
58
59QT_BEGIN_NAMESPACE
60
61#define Q_REQUIRED_RPCNDR_H_VERSION 475
62
63// Some global variables to store module information
64bool qAxIsServer = false;
65HANDLE qAxInstance = 0;
66ITypeLib *qAxTypeLibrary = 0;
67wchar_t qAxModuleFilename[MAX_PATH];
68bool qAxOutProcServer = false;
69
70// The QAxFactory instance
71static QAxFactory* qax_factory = 0;
72extern CLSID CLSID_QRect;
73extern CLSID CLSID_QSize;
74extern CLSID CLSID_QPoint;
75extern void qax_shutDown();
76extern bool qax_ownQApp;
77
78
79extern QAxFactory *qax_instantiate();
80
81QAxFactory *qAxFactory()
82{
83 if (!qax_factory) {
84 bool hadQApp = qApp != 0;
85 qax_factory = qax_instantiate();
86 // QAxFactory created a QApplication
87 if (!hadQApp && qApp)
88 qax_ownQApp = true;
89
90 // register all types with metatype system as pointers
91 QStringList keys(qax_factory->featureList());
92 for (int i = 0; i < keys.count(); ++i) {
93 QString key(keys.at(i));
94 qRegisterMetaType((key + QLatin1Char('*')).toLatin1(), (void**)0);
95 }
96 }
97 return qax_factory;
98}
99
100// Some local variables to handle module lifetime
101static unsigned long qAxModuleRef = 0;
102static CRITICAL_SECTION qAxModuleSection;
103
104
105/////////////////////////////////////////////////////////////////////////////
106// Server control
107/////////////////////////////////////////////////////////////////////////////
108
109static int initCount = 0;
110
111QString qAxInit()
112{
113 static QString libFile;
114
115 if (initCount++)
116 return libFile;
117
118 InitializeCriticalSection(&qAxModuleSection);
119
120 libFile = QString::fromWCharArray(qAxModuleFilename);
121 libFile = libFile.toLower();
122 if (LoadTypeLibEx((wchar_t*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK)
123 return libFile;
124
125 int lastDot = libFile.lastIndexOf(QLatin1Char('.'));
126 libFile = libFile.left(lastDot) + QLatin1String(".tlb");
127 if (LoadTypeLibEx((wchar_t*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK)
128 return libFile;
129
130 lastDot = libFile.lastIndexOf(QLatin1Char('.'));
131 libFile = libFile.left(lastDot) + QLatin1String(".olb");
132 if (LoadTypeLibEx((wchar_t*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK)
133 return libFile;
134
135 libFile = QString();
136 return libFile;
137}
138
139void qAxCleanup()
140{
141 if (!initCount)
142 qWarning("qAxInit/qAxCleanup mismatch");
143
144 if (--initCount)
145 return;
146
147 delete qax_factory;
148 qax_factory = 0;
149
150 if (qAxTypeLibrary) {
151 qAxTypeLibrary->Release();
152 qAxTypeLibrary = 0;
153 }
154
155 DeleteCriticalSection(&qAxModuleSection);
156}
157
158unsigned long qAxLock()
159{
160 EnterCriticalSection(&qAxModuleSection);
161 unsigned long ref = ++qAxModuleRef;
162 LeaveCriticalSection(&qAxModuleSection);
163 return ref;
164}
165
166unsigned long qAxUnlock()
167{
168 if (!initCount) // cleaned up already
169 return 0;
170
171 EnterCriticalSection(&qAxModuleSection);
172 unsigned long ref = --qAxModuleRef;
173 LeaveCriticalSection(&qAxModuleSection);
174
175 if (!ref)
176 qax_shutDown();
177 return ref;
178}
179
180unsigned long qAxLockCount()
181{
182 return qAxModuleRef;
183}
184
185/////////////////////////////////////////////////////////////////////////////
186// Registry
187/////////////////////////////////////////////////////////////////////////////
188
189extern bool qax_disable_inplaceframe;
190
191QString qax_clean_type(const QString &type, const QMetaObject *mo)
192{
193 if (mo) {
194 int classInfoIdx = mo->indexOfClassInfo("CoClassAlias");
195 if (classInfoIdx != -1) {
196 const QMetaClassInfo classInfo = mo->classInfo(classInfoIdx);
197 return QLatin1String(classInfo.value());
198 }
199 }
200
201 QString alias(type);
202 alias.remove(QLatin1String("::"));
203 return alias;
204}
205
206// (Un)Register the ActiveX server in the registry.
207// The QAxFactory implementation provides the information.
208HRESULT UpdateRegistry(BOOL bRegister)
209{
210 qAxIsServer = false;
211 QString file = QString::fromWCharArray(qAxModuleFilename);
212 QString path = file.left(file.lastIndexOf(QLatin1Char('\\'))+1);
213 QString module = file.right(file.length() - path.length());
214 module = module.left(module.lastIndexOf(QLatin1Char('.')));
215
216 const QString appId = qAxFactory()->appID().toString().toUpper();
217 const QString libId = qAxFactory()->typeLibID().toString().toUpper();
218
219 QString libFile = qAxInit();
220 QString typeLibVersion;
221
222 TLIBATTR *libAttr = 0;
223 if (qAxTypeLibrary)
224 qAxTypeLibrary->GetLibAttr(&libAttr);
225 if (!libAttr)
226 return SELFREG_E_TYPELIB;
227
228 DWORD major = libAttr->wMajorVerNum;
229 DWORD minor = libAttr->wMinorVerNum;
230 typeLibVersion = QString::number((uint)major) + QLatin1Char('.') + QString::number((uint)minor);
231
232 if (bRegister)
233 RegisterTypeLib(qAxTypeLibrary, (wchar_t*)libFile.utf16(), 0);
234 else
235 UnRegisterTypeLib(libAttr->guid, libAttr->wMajorVerNum, libAttr->wMinorVerNum, libAttr->lcid, libAttr->syskind);
236
237 qAxTypeLibrary->ReleaseTLibAttr(libAttr);
238
239 if (typeLibVersion.isEmpty())
240 typeLibVersion = QLatin1String("1.0");
241
242 // check whether the user has permission to write to HKLM\Software\Classes
243 // if not, use HKCU\Software\Classes
244 QString keyPath(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes"));
245 QSettings test(keyPath, QSettings::NativeFormat);
246 if (!test.isWritable())
247 keyPath = QLatin1String("HKEY_CURRENT_USER\\Software\\Classes");
248
249 QSettings settings(keyPath, QSettings::NativeFormat);
250
251 // we try to create the ActiveX widgets later on...
252 bool delete_qApp = false;
253 if (!qApp) {
254 int argc = 0;
255 (void)new QApplication(argc, 0);
256 delete_qApp = true;
257 }
258
259 if (bRegister) {
260 if (qAxOutProcServer) {
261 settings.setValue(QLatin1String("/AppID/") + appId + QLatin1String("/."), module);
262 settings.setValue(QLatin1String("/AppID/") + module + QLatin1String(".EXE/AppID"), appId);
263 }
264
265 QStringList keys = qAxFactory()->featureList();
266 for (QStringList::Iterator key = keys.begin(); key != keys.end(); ++key) {
267 QString className = *key;
268 QObject *object = qAxFactory()->createObject(className);
269 const QMetaObject *mo = qAxFactory()->metaObject(className);
270 const QString classId = qAxFactory()->classID(className).toString().toUpper();
271
272 className = qax_clean_type(className, mo);
273
274 if (object) { // don't register subobject classes
275 QString classVersion = mo ? QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("Version")).value()) : QString();
276 if (classVersion.isNull())
277 classVersion = QLatin1String("1.0");
278 bool insertable = mo && !qstricmp(mo->classInfo(mo->indexOfClassInfo("Insertable")).value(), "yes");
279 bool control = object->isWidgetType();
280 const QString classMajorVersion = classVersion.left(classVersion.indexOf(QLatin1Char('.')));
281 uint olemisc = OLEMISC_SETCLIENTSITEFIRST
282 |OLEMISC_ACTIVATEWHENVISIBLE
283 |OLEMISC_INSIDEOUT
284 |OLEMISC_CANTLINKINSIDE
285 |OLEMISC_RECOMPOSEONRESIZE;
286 if (!control)
287 olemisc |= OLEMISC_INVISIBLEATRUNTIME;
288 else if (qFindChild<QMenuBar*>(object) && !qax_disable_inplaceframe)
289 olemisc |= OLEMISC_WANTSTOMENUMERGE;
290
291 settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/."), className + QLatin1String(" Class"));
292 settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/CLSID/."), classId);
293 if (insertable)
294 settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/Insertable/."), QVariant(QLatin1String("")));
295
296 settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/."), className + QLatin1String(" Class"));
297 settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/CLSID/."), classId);
298 settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/CurVer/."), module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion);
299
300 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/."), className + QLatin1String(" Class"));
301 if (file.endsWith(QLatin1String("exe"), Qt::CaseInsensitive))
302 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/AppID"), appId);
303 if (control)
304 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Control/."), QVariant(QLatin1String("")));
305 if (insertable)
306 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Insertable/."), QVariant(QLatin1String("")));
307 if (file.right(3).toLower() == QLatin1String("dll"))
308 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/InProcServer32/."), file);
309 else
310 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/LocalServer32/."),
311 QLatin1Char('\"') + file + QLatin1String("\" -activex"));
312 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/."), control ? QLatin1String("1") : QLatin1String("0"));
313 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/1/."), QString::number(olemisc));
314 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Programmable/."), QVariant(QLatin1String("")));
315 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/ToolboxBitmap32/."), QLatin1Char('\"') +
316 file + QLatin1String("\", 101"));
317 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/TypeLib/."), libId); settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Version/."), classVersion);
318 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/VersionIndependentProgID/."), module + QLatin1Char('.') + className);
319 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/ProgID/."), module + QLatin1Char('.') + className + QLatin1Char('.') + classVersion.left(classVersion.indexOf(QLatin1Char('.'))));
320
321 QString mime = QLatin1String(mo->classInfo(mo->indexOfClassInfo("MIME")).value());
322 if (!mime.isEmpty()) {
323 QStringList mimeTypes = mime.split(QLatin1Char(';'));
324 for (int m = 0; m < mimeTypes.count(); ++m) {
325 mime = mimeTypes.at(m);
326 if (mime.isEmpty())
327 continue;
328 QString extension;
329 while (mime.contains(QLatin1Char(':'))) {
330 extension = mime.mid(mime.lastIndexOf(QLatin1Char(':')) + 1);
331 mime = mime.left(mime.length() - extension.length() - 1);
332 // Prepend '.' before extension, if required.
333 extension = extension.trimmed();
334 if (extension[0] != QLatin1Char('.'))
335 extension = QLatin1Char('.') + extension;
336 }
337
338 if (!extension.isEmpty()) {
339 settings.setValue(QLatin1Char('/') + extension + QLatin1String("/."), module + QLatin1Char('.') + className);
340 settings.setValue(QLatin1Char('/') + extension + QLatin1String("/Content Type"), mime);
341
342 mime = mime.replace(QLatin1Char('/'), QLatin1Char('\\'));
343 settings.setValue(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/CLSID"), classId);
344 settings.setValue(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/Extension"), extension);
345 }
346 }
347 }
348
349 delete object;
350 }
351
352 qAxFactory()->registerClass(*key, &settings);
353 }
354 } else {
355 if (qAxOutProcServer) {
356 settings.remove(QLatin1String("/AppID/") + appId + QLatin1String("/."));
357 settings.remove(QLatin1String("/AppID/") + module + QLatin1String(".EXE"));
358 }
359 QStringList keys = qAxFactory()->featureList();
360 for (QStringList::Iterator key = keys.begin(); key != keys.end(); ++key) {
361 QString className = *key;
362 const QMetaObject *mo = qAxFactory()->metaObject(className);
363 const QString classId = qAxFactory()->classID(className).toString().toUpper();
364 className = qax_clean_type(className, mo);
365
366 QString classVersion = mo ? QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("Version")).value()) : QString();
367 if (classVersion.isNull())
368 classVersion = QLatin1String("1.0");
369 const QString classMajorVersion = classVersion.left(classVersion.indexOf(QLatin1Char('.')));
370
371 qAxFactory()->unregisterClass(*key, &settings);
372
373 settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/CLSID/."));
374 settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/Insertable/."));
375 settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/."));
376 settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion);
377
378 settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/CLSID/."));
379 settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/CurVer/."));
380 settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/."));
381 settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className);
382
383 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/AppID"));
384 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/Control/."));
385 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/Insertable/."));
386 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/InProcServer32/."));
387 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/LocalServer32/."));
388 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/1/."));
389 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/."));
390 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/Programmable/."));
391 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/ToolboxBitmap32/."));
392 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/TypeLib/."));
393 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/Version/."));
394 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/VersionIndependentProgID/."));
395 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/ProgID/."));
396 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/."));
397 settings.remove(QLatin1String("/CLSID/") + classId);
398
399 QString mime = QLatin1String(mo->classInfo(mo->indexOfClassInfo("MIME")).value());
400 if (!mime.isEmpty()) {
401 QStringList mimeTypes = mime.split(QLatin1Char(';'));
402 for (int m = 0; m < mimeTypes.count(); ++m) {
403 mime = mimeTypes.at(m);
404 if (mime.isEmpty())
405 continue;
406 QString extension;
407 while (mime.contains(QLatin1Char(':'))) {
408 extension = mime.mid(mime.lastIndexOf(QLatin1Char(':')) + 1);
409 mime = mime.left(mime.length() - extension.length() - 1);
410 // Prepend '.' before extension, if required.
411 extension = extension.trimmed();
412 if (extension[0] != QLatin1Char('.'))
413 extension.prepend(QLatin1Char('.'));
414 }
415 if (!extension.isEmpty()) {
416 settings.remove(QLatin1Char('/') + extension + QLatin1String("/Content Type"));
417 settings.remove(QLatin1Char('/') + extension + QLatin1String("/."));
418 settings.remove(QLatin1Char('/') + extension);
419 mime.replace(QLatin1Char('/'), QLatin1Char('\\'));
420 settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/Extension"));
421 settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/CLSID"));
422 settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/."));
423 settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime);
424 }
425 }
426 }
427 }
428 }
429
430 if (delete_qApp)
431 delete qApp;
432
433 qAxCleanup();
434 if (settings.status() == QSettings::NoError)
435 return S_OK;
436 return SELFREG_E_CLASS;
437}
438
439/////////////////////////////////////////////////////////////////////////////
440// IDL generator
441/////////////////////////////////////////////////////////////////////////////
442
443static QList<QByteArray> enums;
444static QList<QByteArray> enumValues;
445static QList<QByteArray> subtypes;
446
447static const char* const type_map[][2] =
448{
449 // QVariant/Qt Value data types
450 { "QString", "BSTR" },
451 { "QCString", "BSTR" },
452 { "bool", "VARIANT_BOOL" },
453 { "int", "int" },
454 { "uint", "unsigned int" },
455 { "double", "double" },
456 { "QColor", "OLE_COLOR" },
457 { "QDate", "DATE" },
458 { "QTime", "DATE" },
459 { "QDateTime", "DATE" },
460 { "QFont", "IFontDisp*" },
461 { "QPixmap", "IPictureDisp*" },
462 { "QVariant", "VARIANT" },
463 { "QVariantList", "SAFEARRAY(VARIANT)" },
464 { "QList<QVariant>", "SAFEARRAY(VARIANT)" },
465 { "quint64", "CY" },
466 { "qint64", "CY" },
467 { "qulonglong", "CY" },
468 { "qlonglong", "CY" },
469 { "QByteArray", "SAFEARRAY(BYTE)" },
470 { "QStringList", "SAFEARRAY(BSTR)" },
471 // Userdefined Qt datatypes - some not on Borland though
472 { "QCursor", "enum MousePointer" },
473 { "Qt::FocusPolicy", "enum FocusPolicy" },
474#ifndef Q_CC_BOR
475# if __REQUIRED_RPCNDR_H_VERSION__ >= Q_REQUIRED_RPCNDR_H_VERSION
476 { "QRect", "struct QRect" },
477 { "QSize", "struct QSize" },
478 { "QPoint", "struct QPoint" },
479# endif
480#endif
481 // And we support COM data types
482 { "BOOL", "BOOL" },
483 { "BSTR", "BSTR" },
484 { "OLE_COLOR", "OLE_COLOR" },
485 { "DATE", "DATE" },
486 { "VARIANT", "VARIANT" },
487 { "IDispatch", "IDispatch*" },
488 { "IUnknown", "IUnknown*" },
489 { "IDispatch*", "IDispatch*" },
490 { "IUnknown*", "IUnknown*" },
491 { 0, 0 }
492};
493
494static QByteArray convertTypes(const QByteArray &qtype, bool *ok)
495{
496 qRegisterMetaType("IDispatch*", (void**)0);
497 qRegisterMetaType("IUnknown*", (void**)0);
498
499 *ok = false;
500
501 int i = 0;
502 while (type_map[i][0]) {
503 if (qtype == type_map[i][0] && type_map[i][1]) {
504 *ok = true;
505 return type_map[i][1];
506 }
507 ++i;
508 }
509 if (enums.contains(qtype)) {
510 *ok = true;
511 return "enum " + qtype;
512 }
513 if (subtypes.contains(qtype)) {
514 *ok = true;
515 } else if (qtype.endsWith('*')) {
516 QByteArray cleanType = qtype.left(qtype.length() - 1);
517 const QMetaObject *mo = qAxFactory()->metaObject(QString::fromLatin1(cleanType.constData()));
518 if (mo) {
519 cleanType = qax_clean_type(QString::fromLatin1(cleanType), mo).toLatin1();
520 if (subtypes.contains(cleanType)) {
521 *ok = true;
522 return cleanType + '*';
523 }
524 }
525 }
526 return qtype;
527}
528
529static const char* const keyword_map[][2] =
530{
531 { "aggregatable", "aggregating" },
532 { "allocate", "alloc" },
533 { "appobject", "appObject" },
534 { "arrays", "array" },
535 { "async", "asynchronous" },
536 { "bindable", "binding" },
537 { "Boolean", "boolval" },
538 { "boolean", "boolval" },
539 { "broadcast", "broadCast" },
540 { "callback", "callBack" },
541 { "decode", "deCode" },
542 { "default", "defaulted" },
543 { "defaultbind", "defaultBind" },
544 { "defaultvalue", "defaultValue" },
545 { "encode" "enCode" },
546 { "endpoint", "endPoint" },
547 { "hidden", "isHidden" },
548 { "ignore", "ignore_" },
549 { "local", "local_" },
550 { "notify", "notify_" },
551 { "object", "object_" },
552 { "optimize", "optimize_" },
553 { "optional", "optional_" },
554 { "out", "out_" },
555 { "pipe", "pipe_" },
556 { "proxy", "proxy_" },
557 { "ptr", "pointer" },
558 { "readonly", "readOnly" },
559 { "small", "small_" },
560 { "source", "source_" },
561 { "string", "string_" },
562 { "uuid", "uuid_" },
563 { 0, 0 }
564};
565
566static QByteArray replaceKeyword(const QByteArray &name)
567{
568 int i = 0;
569 while (keyword_map[i][0]) {
570 if (name == keyword_map[i][0] && keyword_map[i][1])
571 return keyword_map[i][1];
572 ++i;
573 }
574 return name;
575}
576
577static QMap<QByteArray, int> mapping;
578
579static QByteArray renameOverloads(const QByteArray &name)
580{
581 QByteArray newName = name;
582
583 int n = mapping.value(name);
584 if (mapping.contains(name)) {
585 int n = mapping.value(name);
586 newName = name + '_' + QByteArray::number(n);
587 mapping.insert(name, n+1);
588 } else {
589 mapping.insert(name, 1);
590 }
591
592 return newName;
593}
594
595// filter out some properties
596static const char* const ignore_props[] =
597{
598 "name",
599 "objectName",
600 "isTopLevel",
601 "isDialog",
602 "isModal",
603 "isPopup",
604 "isDesktop",
605 "geometry",
606 "pos",
607 "frameSize",
608 "frameGeometry",
609 "size",
610 "sizeHint",
611 "minimumSizeHint",
612 "microFocusHint",
613 "rect",
614 "childrenRect",
615 "childrenRegion",
616 "minimumSize",
617 "maximumSize",
618 "sizeIncrement",
619 "baseSize",
620 "ownPalette",
621 "ownFont",
622 "ownCursor",
623 "visibleRect",
624 "isActiveWindow",
625 "underMouse",
626 "visible",
627 "hidden",
628 "minimized",
629 "focus",
630 "focusEnabled",
631 "customWhatsThis",
632 "shown",
633 "windowOpacity",
634 0
635};
636
637// filter out some slots
638static const char* const ignore_slots[] =
639{
640 "deleteLater",
641 "setMouseTracking",
642 "update",
643 "repaint",
644 "iconify",
645 "showMinimized",
646 "showMaximized",
647 "showFullScreen",
648 "showNormal",
649 "polish",
650 "constPolish",
651 "stackUnder",
652 "setShown",
653 "setHidden",
654 "move_1",
655 "resize_1",
656 "setGeometry_1",
657 0
658};
659
660static bool ignore(const char *test, const char *const *table)
661{
662 if (!test)
663 return true;
664 int i = 0;
665 while (table[i]) {
666 if (!strcmp(test, table[i]))
667 return true;
668 ++i;
669 }
670 return false;
671}
672
673bool ignoreSlots(const char *test)
674{
675 return ignore(test, ignore_slots);
676}
677
678bool ignoreProps(const char *test)
679{
680 return ignore(test, ignore_props);
681}
682
683#define STRIPCB(x) x = x.mid(1, x.length()-2)
684
685static QByteArray prototype(const QList<QByteArray> &parameterTypes, const QList<QByteArray> &parameterNames, bool *ok)
686{
687 QByteArray prototype;
688
689 for (int p = 0; p < parameterTypes.count() && *ok; ++p) {
690 bool out = false;
691 QByteArray type(parameterTypes.at(p));
692 QByteArray name(parameterNames.at(p));
693
694 if (type.endsWith('&')) {
695 out = true;
696 type.truncate(type.length() - 1);
697 } else if (type.endsWith("**")) {
698 out = true;
699 type.truncate(type.length() - 1);
700 } else if (type.endsWith('*') && !subtypes.contains(type)) {
701 type.truncate(type.length() - 1);
702 }
703 if (type.isEmpty()) {
704 *ok = false;
705 break;
706 }
707 type = convertTypes(type, ok);
708 if (!out)
709 prototype += "[in] " + type + ' ';
710 else
711 prototype += "[in,out] " + type + ' ';
712
713 if (out)
714 prototype += '*';
715 if (name.isEmpty())
716 prototype += 'p' + QByteArray::number(p);
717 else
718 prototype += "p_" + replaceKeyword(name);
719
720 if (p < parameterTypes.count() - 1)
721 prototype += ", ";
722 }
723
724 return prototype;
725}
726
727static QByteArray addDefaultArguments(const QByteArray &prototype, int numDefArgs)
728{
729 // nothing to do, or unsupported anyway
730 if (!numDefArgs || prototype.contains("/**"))
731 return prototype;
732
733 QByteArray ptype(prototype);
734 int in = -1;
735 while (numDefArgs) {
736 in = ptype.lastIndexOf(']', in);
737 ptype.replace(in, 1, ",optional]");
738 in = ptype.indexOf(' ', in) + 1;
739 QByteArray type = ptype.mid(in, ptype.indexOf(' ', in) - in);
740 if (type == "enum")
741 type += ' ' + ptype.mid(in + 5, ptype.indexOf(' ', in + 5) - in - 5);
742 ptype.replace(in, type.length(), QByteArray("VARIANT /*was: ") + type + "*/");
743 --numDefArgs;
744 }
745
746 return ptype;
747}
748
749static HRESULT classIDL(QObject *o, const QMetaObject *mo, const QString &className, bool isBindable, QTextStream &out)
750{
751 int id = 1;
752 int i = 0;
753 if (!mo)
754 return 3;
755
756 QString topclass = qAxFactory()->exposeToSuperClass(className);
757 if (topclass.isEmpty())
758 topclass = QLatin1String("QObject");
759 bool hasStockEvents = qAxFactory()->hasStockEvents(className);
760
761 const QMetaObject *pmo = mo;
762 do {
763 pmo = pmo->superClass();
764 } while (pmo && topclass != QString::fromLatin1(pmo->className()));
765
766 int enumoff = pmo ? pmo->enumeratorOffset() : mo->enumeratorOffset();
767 int methodoff = pmo ? pmo->methodOffset() : mo->methodOffset();
768 int propoff = pmo ? pmo->propertyOffset() : mo->propertyOffset();
769
770 int qtProps = 0;
771 int qtSlots = 0;
772
773 bool control = false;
774
775 if (o && o->isWidgetType()) {
776 qtProps = QWidget::staticMetaObject.propertyCount();
777 qtSlots = QWidget::staticMetaObject.methodCount();
778 control = true;
779 }
780
781 QString classID = qAxFactory()->classID(className).toString().toUpper();
782 if (QUuid(classID).isNull())
783 return 4;
784 STRIPCB(classID);
785 QString interfaceID = qAxFactory()->interfaceID(className).toString().toUpper();
786 if (QUuid(interfaceID).isNull())
787 return 5;
788 STRIPCB(interfaceID);
789 QString eventsID = qAxFactory()->eventsID(className).toString().toUpper();
790 bool hasEvents = !QUuid(eventsID).isNull();
791 STRIPCB(eventsID);
792
793 QString cleanClassName = qax_clean_type(className, mo);
794 QString defProp(QLatin1String(mo->classInfo(mo->indexOfClassInfo("DefaultProperty")).value()));
795 QString defSignal(QLatin1String(mo->classInfo(mo->indexOfClassInfo("DefaultSignal")).value()));
796
797 for (i = enumoff; i < mo->enumeratorCount(); ++i) {
798 const QMetaEnum enumerator = mo->enumerator(i);
799 if (enums.contains(enumerator.name()))
800 continue;
801
802 enums.append(enumerator.name());
803
804 out << "\tenum " << enumerator.name() << " {" << endl;
805
806 for (int j = 0; j < enumerator.keyCount(); ++j) {
807 QByteArray key(enumerator.key(j));
808 while (enumValues.contains(key)) {
809 key += '_';
810 }
811 enumValues.append(key);
812 uint value = (uint)enumerator.value(j);
813 key = key.leftJustified(20);
814 out << "\t\t" << key << "\t= ";
815 if (enumerator.isFlag())
816 out << "0x" << QByteArray::number(value, 16).rightJustified(8, '0');
817 else
818 out << value;
819 if (j < enumerator.keyCount()-1)
820 out << ", ";
821 out << endl;
822 }
823 out << "\t};" << endl << endl;
824 }
825
826 // mouse cursor enum for QCursor support
827 if (!enums.contains("MousePointer")) {
828 enums.append("MousePointer");
829 out << "\tenum MousePointer {" << endl;
830 out << "\t\tArrowCursor = " << Qt::ArrowCursor << ',' << endl;
831 out << "\t\tUpArrowCursor = " << Qt::UpArrowCursor << ',' << endl;
832 out << "\t\tCrossCursor = " << Qt::CrossCursor << ',' << endl;
833 out << "\t\tWaitCursor = " << Qt::WaitCursor << ',' << endl;
834 out << "\t\tIBeamCursor = " << Qt::IBeamCursor << ',' << endl;
835 out << "\t\tSizeVerCursor = " << Qt::SizeVerCursor << ',' << endl;
836 out << "\t\tSizeHorCursor = " << Qt::SizeHorCursor << ',' << endl;
837 out << "\t\tSizeBDiagCursor = " << Qt::SizeBDiagCursor << ',' << endl;
838 out << "\t\tSizeFDiagCursor = " << Qt::SizeFDiagCursor << ',' << endl;
839 out << "\t\tSizeAllCursor = " << Qt::SizeAllCursor << ',' << endl;
840 out << "\t\tBlankCursor = " << Qt::BlankCursor << ',' << endl;
841 out << "\t\tSplitVCursor = " << Qt::SplitVCursor << ',' << endl;
842 out << "\t\tSplitHCursor = " << Qt::SplitHCursor << ',' << endl;
843 out << "\t\tPointingHandCursor = " << Qt::PointingHandCursor << ',' << endl;
844 out << "\t\tForbiddenCursor = " << Qt::ForbiddenCursor << ',' << endl;
845 out << "\t\tWhatsThisCursor = " << Qt::WhatsThisCursor << ',' << endl;
846 out << "\t\tBusyCursor\t= " << Qt::BusyCursor << endl;
847 out << "\t};" << endl << endl;
848 }
849 if (!enums.contains("FocusPolicy")) {
850 enums.append("FocusPolicy");
851 out << "\tenum FocusPolicy {" << endl;
852 out << "\t\tNoFocus = " << Qt::NoFocus << ',' << endl;
853 out << "\t\tTabFocus = " << Qt::TabFocus << ',' << endl;
854 out << "\t\tClickFocus = " << Qt::ClickFocus << ',' << endl;
855 out << "\t\tStrongFocus = " << Qt::StrongFocus << ',' << endl;
856 out << "\t\tWheelFocus = " << Qt::WheelFocus << endl;
857 out << "\t};" << endl << endl;
858 }
859
860 out << endl;
861 out << "\t[" << endl;
862 out << "\t\tuuid(" << interfaceID << ")," << endl;
863 out << "\t\thelpstring(\"" << cleanClassName << " Interface\")" << endl;
864 out << "\t]" << endl;
865 out << "\tdispinterface I" << cleanClassName << endl;
866 out << "\t{" << endl;
867
868 out << "\tproperties:" << endl;
869 for (i = propoff; i < mo->propertyCount(); ++i) {
870 const QMetaProperty property = mo->property(i);
871 /* if (property.testFlags(QMetaProperty::Override))
872 continue;*/
873 if (i <= qtProps && ignoreProps(property.name()))
874 continue;
875 if (!property.name() || mo->indexOfProperty(property.name()) > i)
876 continue;
877
878 bool ok = true;
879 QByteArray type(convertTypes(property.typeName(), &ok));
880 QByteArray name(replaceKeyword(property.name()));
881
882 if (!ok)
883 out << "\t/****** Property is of unsupported datatype" << endl;
884
885 out << "\t\t[id(" << id << ')';
886 if (!property.isWritable())
887 out << ", readonly";
888 if (isBindable && property.isScriptable(o))
889 out << ", bindable";
890 if (!property.isDesignable(o))
891 out << ", nonbrowsable";
892 if (isBindable)
893 out << ", requestedit";
894 if (defProp == QLatin1String(name))
895 out << ", uidefault";
896 out << "] " << type << ' ' << name << ';' << endl;
897
898 if (!ok)
899 out << "\t******/" << endl;
900 ++id;
901 }
902 out << endl;
903 out << "\tmethods:" << endl;
904 int numDefArgs = 0;
905 QByteArray outBuffer;
906 for (i = methodoff; i < mo->methodCount(); ++i) {
907 const QMetaMethod slot = mo->method(i);
908 if (slot.access() != QMetaMethod::Public || slot.methodType() == QMetaMethod::Signal)
909 continue;
910
911 if (slot.attributes() & QMetaMethod::Cloned) {
912 ++numDefArgs;
913 continue;
914 }
915 if (!outBuffer.isEmpty()) {
916 outBuffer = addDefaultArguments(outBuffer, numDefArgs);
917 numDefArgs = 0;
918 out << outBuffer;
919 outBuffer = QByteArray();
920 }
921
922 QByteArray signature(slot.signature());
923 QByteArray name(signature.left(signature.indexOf('(')));
924 if (i <= qtSlots && ignoreSlots(name))
925 continue;
926
927 signature = signature.mid(name.length() + 1);
928 signature.truncate(signature.length() - 1);
929 name = renameOverloads(replaceKeyword(name));
930 if (ignoreSlots(name))
931 continue;
932
933 QList<QByteArray> parameterTypes(slot.parameterTypes());
934 QList<QByteArray> parameterNames(slot.parameterNames());
935
936 bool ok = true;
937 QByteArray type = slot.typeName();
938 if (type.isEmpty())
939 type = "void";
940 else
941 type = convertTypes(type, &ok);
942
943 QByteArray ptype(prototype(parameterTypes, parameterNames, &ok));
944 if (!ok)
945 outBuffer += "\t/****** Slot parameter uses unsupported datatype\n";
946
947 outBuffer += "\t\t[id(" + QString::number(id).toLatin1() + ")] " + type + ' ' + name + '(' + ptype + ");\n";
948
949 if (!ok)
950 outBuffer += "\t******/\n";
951 ++id;
952 }
953 if (!outBuffer.isEmpty()) {
954 outBuffer = addDefaultArguments(outBuffer, numDefArgs);
955 numDefArgs = 0;
956 out << outBuffer;
957 outBuffer = QByteArray();
958 }
959 out << "\t};" << endl << endl;
960
961 mapping.clear();
962 id = 1;
963
964 if (hasEvents) {
965 out << "\t[" << endl;
966 out << "\t\tuuid(" << eventsID << ")," << endl;
967 out << "\t\thelpstring(\"" << cleanClassName << " Events Interface\")" << endl;
968 out << "\t]" << endl;
969 out << "\tdispinterface I" << cleanClassName << "Events" << endl;
970 out << "\t{" << endl;
971 out << "\tproperties:" << endl;
972 out << "\tmethods:" << endl;
973
974 if (hasStockEvents) {
975 out << "\t/****** Stock events ******/" << endl;
976 out << "\t\t[id(DISPID_CLICK)] void Click();" << endl;
977 out << "\t\t[id(DISPID_DBLCLICK)] void DblClick();" << endl;
978 out << "\t\t[id(DISPID_KEYDOWN)] void KeyDown(short* KeyCode, short Shift);" << endl;
979 out << "\t\t[id(DISPID_KEYPRESS)] void KeyPress(short* KeyAscii);" << endl;
980 out << "\t\t[id(DISPID_KEYUP)] void KeyUp(short* KeyCode, short Shift);" << endl;
981 out << "\t\t[id(DISPID_MOUSEDOWN)] void MouseDown(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl;
982 out << "\t\t[id(DISPID_MOUSEMOVE)] void MouseMove(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl;
983 out << "\t\t[id(DISPID_MOUSEUP)] void MouseUp(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl << endl;
984 }
985
986 for (i = methodoff; i < mo->methodCount(); ++i) {
987 const QMetaMethod signal = mo->method(i);
988 if (signal.methodType() != QMetaMethod::Signal)
989 continue;
990
991 QByteArray signature(signal.signature());
992 QByteArray name(signature.left(signature.indexOf('(')));
993 signature = signature.mid(name.length() + 1);
994 signature.truncate(signature.length() - 1);
995
996 QList<QByteArray> parameterTypes(signal.parameterTypes());
997 QList<QByteArray> parameterNames(signal.parameterNames());
998
999 bool isDefault = defSignal == QLatin1String(name);
1000 name = renameOverloads(replaceKeyword(name));
1001 bool ok = true;
1002
1003 QByteArray type = signal.typeName();
1004 if (!type.isEmpty()) // signals with return value not supported
1005 continue;
1006
1007 QByteArray ptype(prototype(parameterTypes, parameterNames, &ok));
1008 if (!ok)
1009 out << "\t/****** Signal parameter uses unsupported datatype" << endl;
1010
1011 out << "\t\t[id(" << id << ')';
1012 if (isDefault)
1013 out << ", uidefault";
1014 out << "] void " << name << '(' << ptype << ");" << endl;
1015
1016 if (!ok)
1017 out << "\t******/" << endl;
1018 ++id;
1019 }
1020 out << "\t};" << endl << endl;
1021 }
1022
1023 out << "\t[" << endl;
1024
1025 if (qstricmp(mo->classInfo(mo->indexOfClassInfo("Aggregatable")).value(), "no"))
1026 out << "\t\taggregatable," << endl;
1027 if (!qstricmp(mo->classInfo(mo->indexOfClassInfo("RegisterObject")).value(), "yes"))
1028 out << "\t\tappobject," << endl;
1029 if (mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value())
1030 out << "\t\tlicensed," << endl;
1031 const char *helpString = mo->classInfo(mo->indexOfClassInfo("Description")).value();
1032 if (helpString)
1033 out << "\t\thelpstring(\"" << helpString << "\")," << endl;
1034 else
1035 out << "\t\thelpstring(\"" << cleanClassName << " Class\")," << endl;
1036 const char *classVersion = mo->classInfo(mo->indexOfClassInfo("Version")).value();
1037 if (classVersion)
1038 out << "\t\tversion(" << classVersion << ")," << endl;
1039 out << "\t\tuuid(" << classID << ')';
1040 if (control) {
1041 out << ", " << endl;
1042 out << "\t\tcontrol";
1043 } else if (!o) {
1044 out << ", " << endl;
1045 out << "\t\tnoncreatable";
1046 }
1047 out << endl;
1048 out << "\t]" << endl;
1049 out << "\tcoclass " << cleanClassName << endl;
1050 out << "\t{" << endl;
1051 out << "\t\t[default] dispinterface I" << cleanClassName << ';' << endl;
1052 if (hasEvents)
1053 out << "\t\t[default, source] dispinterface I" << cleanClassName << "Events;" << endl;
1054 out << "\t};" << endl;
1055
1056 return S_OK;
1057}
1058
1059#if defined(Q_CC_BOR)
1060extern "C" __stdcall HRESULT DumpIDL(const QString &outfile, const QString &ver)
1061#else
1062extern "C" HRESULT __stdcall DumpIDL(const QString &outfile, const QString &ver)
1063#endif
1064{
1065 qAxIsServer = false;
1066 QTextStream out;
1067 if (outfile.contains(QLatin1String("\\"))) {
1068 QString outpath = outfile.left(outfile.lastIndexOf(QLatin1String("\\")));
1069 QDir dir;
1070 dir.mkpath(outpath);
1071 }
1072 QFile file(outfile);
1073 file.remove();
1074
1075 QString filebase = QString::fromWCharArray(qAxModuleFilename);
1076 filebase = filebase.left(filebase.lastIndexOf(QLatin1Char('.')));
1077
1078 QString appID = qAxFactory()->appID().toString().toUpper();
1079 if (QUuid(appID).isNull())
1080 return 1;
1081 STRIPCB(appID);
1082 QString typeLibID = qAxFactory()->typeLibID().toString().toUpper();
1083 if (QUuid(typeLibID).isNull())
1084 return 2;
1085 STRIPCB(typeLibID);
1086 QString typelib = filebase.right(filebase.length() - filebase.lastIndexOf(QLatin1String("\\"))-1);
1087
1088 if (!file.open(QIODevice::WriteOnly))
1089 return -1;
1090
1091 out.setDevice(&file);
1092
1093 QString version(ver.unicode(), ver.length());
1094 while (version.count(QLatin1Char('.')) > 1) {
1095 int lastdot = version.lastIndexOf(QLatin1Char('.'));
1096 version = version.left(lastdot) + version.right(version.length() - lastdot - 1);
1097 }
1098 if (version.isEmpty())
1099 version = QLatin1String("1.0");
1100
1101 QString idQRect(QUuid(CLSID_QRect).toString());
1102 STRIPCB(idQRect);
1103 QString idQSize(QUuid(CLSID_QSize).toString());
1104 STRIPCB(idQSize);
1105 QString idQPoint(QUuid(CLSID_QPoint).toString());
1106 STRIPCB(idQPoint);
1107
1108 out << "/****************************************************************************" << endl;
1109 out << "** Interface definition generated for ActiveQt project" << endl;
1110 out << "**" << endl;
1111 out << "** '" << QString::fromWCharArray(qAxModuleFilename) << '\'' << endl;
1112 out << "**" << endl;
1113 out << "** Created: " << QDateTime::currentDateTime().toString() << endl;
1114 out << "**" << endl;
1115 out << "** WARNING! All changes made in this file will be lost!" << endl;
1116 out << "****************************************************************************/" << endl << endl;
1117
1118 out << "import \"ocidl.idl\";" << endl;
1119 out << "#include <olectl.h>" << endl << endl;
1120
1121 // dummy application to create widgets
1122 bool delete_qApp = false;
1123 if (!qApp) {
1124 int argc;
1125 (void)new QApplication(argc, 0);
1126 delete_qApp = true;
1127 }
1128
1129 out << '[' << endl;
1130 out << "\tuuid(" << typeLibID << ")," << endl;
1131 out << "\tversion(" << version << ")," << endl;
1132 out << "\thelpstring(\"" << typelib << ' ' << version << " Type Library\")" << endl;
1133 out << ']' << endl;
1134 out << "library " << typelib << "Lib" << endl;
1135 out << '{' << endl;
1136 out << "\timportlib(\"stdole32.tlb\");" << endl;
1137 out << "\timportlib(\"stdole2.tlb\");" << endl << endl;
1138
1139 QStringList keys = qAxFactory()->featureList();
1140 QStringList::ConstIterator key;
1141
1142 out << "\t/************************************************************************" << endl;
1143 out << "\t** If this causes a compile error in MIDL you need to upgrade the" << endl;
1144 out << "\t** Platform SDK you are using. Download the SDK from msdn.microsoft.com" << endl;
1145 out << "\t** and make sure that both the system and the Visual Studio environment" << endl;
1146 out << "\t** use the correct files." << endl;
1147 out << "\t**" << endl;
1148
1149#ifndef Q_CC_BOR
1150#if __REQUIRED_RPCNDR_H_VERSION__ < Q_REQUIRED_RPCNDR_H_VERSION
1151 out << "\t** Required version of MIDL could not be verified. QRect, QSize and QPoint" << endl;
1152 out << "\t** support needs an updated Platform SDK to be installed." << endl;
1153 out << "\t*************************************************************************" << endl;
1154#else
1155 out << "\t************************************************************************/" << endl;
1156#endif
1157
1158 out << endl;
1159 out << "\t[uuid(" << idQRect << ")]" << endl;
1160 out << "\tstruct QRect {" << endl;
1161 out << "\t\tint left;" << endl;
1162 out << "\t\tint top;" << endl;
1163 out << "\t\tint right;" << endl;
1164 out << "\t\tint bottom;" << endl;
1165 out << "\t};" << endl << endl;
1166
1167 out << "\t[uuid(" << idQSize << ")]" << endl;
1168 out << "\tstruct QSize {" << endl;
1169 out << "\t\tint width;" << endl;
1170 out << "\t\tint height;" << endl;
1171 out << "\t};" << endl << endl;
1172
1173 out << "\t[uuid(" << idQPoint << ")]" << endl;
1174 out << "\tstruct QPoint {" << endl;
1175 out << "\t\tint x;" << endl;
1176 out << "\t\tint y;" << endl;
1177 out << "\t};" << endl;
1178#if __REQUIRED_RPCNDR_H_VERSION__ < Q_REQUIRED_RPCNDR_H_VERSION
1179 out << "\t*/" << endl;
1180#endif
1181#else
1182 out << "\t** Custom data types not supported with Borland." << endl;
1183 out << "\t*************************************************************************" << endl;
1184#endif
1185 out << endl;
1186
1187 out << "\t/* Forward declaration of classes that might be used as parameters */" << endl << endl;
1188
1189 int res = S_OK;
1190 for (key = keys.begin(); key != keys.end(); ++key) {
1191 QByteArray className = (*key).toLatin1();
1192 const QMetaObject *mo = qAxFactory()->metaObject(QString::fromLatin1(className.constData()));
1193 // We have meta object information for this type. Forward declare it.
1194 if (mo) {
1195 QByteArray cleanType = qax_clean_type(*key, mo).toLatin1();
1196 out << "\tcoclass " << cleanType << ';' << endl;
1197 subtypes.append(cleanType);
1198 qRegisterMetaType(cleanType, (void**)0);
1199 cleanType += '*';
1200 subtypes.append(cleanType);
1201 qRegisterMetaType(cleanType, (void**)0);
1202 }
1203 }
1204 out << endl;
1205
1206 for (key = keys.begin(); key != keys.end(); ++key) {
1207 QByteArray className = (*key).toLatin1();
1208 const QMetaObject *mo = qAxFactory()->metaObject(QString::fromLatin1(className.constData()));
1209 // We have meta object information for this type. Define it.
1210 if (mo) {
1211 QObject *o = qAxFactory()->createObject(QString::fromLatin1(className.constData()));
1212 // It's not a control class, so it is actually a subtype. Define it.
1213 if (!o)
1214 res = classIDL(0, mo, QString::fromLatin1(className), false, out);
1215 delete o;
1216 }
1217 }
1218
1219 out << endl;
1220 if (res != S_OK)
1221 goto ErrorInClass;
1222
1223 for (key = keys.begin(); key != keys.end(); ++key) {
1224 QByteArray className = (*key).toLatin1();
1225 QObject *o = qAxFactory()->createObject(QString::fromLatin1(className.constData()));
1226 if (!o)
1227 continue;
1228 const QMetaObject *mo = o->metaObject();
1229 QAxBindable *bind = (QAxBindable*)o->qt_metacast("QAxBindable");
1230 bool isBindable = bind != 0;
1231
1232 QByteArray cleanType = qax_clean_type(*key, mo).toLatin1();
1233 subtypes.append(cleanType);
1234 subtypes.append(cleanType + '*');
1235 res = classIDL(o, mo, QString::fromLatin1(className.constData()), isBindable, out);
1236 delete o;
1237 if (res != S_OK)
1238 break;
1239 }
1240
1241 out << "};" << endl;
1242 out.flush();
1243
1244ErrorInClass:
1245 if (delete_qApp)
1246 delete qApp;
1247
1248 if (res != S_OK) {
1249 file.close();
1250 file.remove();
1251 }
1252
1253 return res;
1254}
1255
1256QT_END_NAMESPACE
1257#endif // QT_NO_WIN_ACTIVEQT
Note: See TracBrowser for help on using the repository browser.