Qt 4.8
qaxserver.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia Plc and its Subsidiary(-ies) nor the names
21 ** of its 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 "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 
60 
61 #define Q_REQUIRED_RPCNDR_H_VERSION 475
62 
63 // Some global variables to store module information
64 bool qAxIsServer = false;
66 ITypeLib *qAxTypeLibrary = 0;
67 wchar_t qAxModuleFilename[MAX_PATH];
68 bool qAxOutProcServer = false;
69 
70 // The QAxFactory instance
71 static QAxFactory* qax_factory = 0;
72 extern CLSID CLSID_QRect;
73 extern CLSID CLSID_QSize;
74 extern CLSID CLSID_QPoint;
75 extern void qax_shutDown();
76 extern bool qax_ownQApp;
77 
78 
79 extern QAxFactory *qax_instantiate();
80 
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**)(quintptr)-1);
95  }
96  }
97  return qax_factory;
98 }
99 
100 // Some local variables to handle module lifetime
101 static unsigned long qAxModuleRef = 0;
102 static CRITICAL_SECTION qAxModuleSection;
103 
104 
106 // Server control
108 
109 static int initCount = 0;
110 
112 {
113  static QString libFile;
114 
115  if (initCount++)
116  return libFile;
117 
118  InitializeCriticalSection(&qAxModuleSection);
119 
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 
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 
158 unsigned long qAxLock()
159 {
160  EnterCriticalSection(&qAxModuleSection);
161  unsigned long ref = ++qAxModuleRef;
162  LeaveCriticalSection(&qAxModuleSection);
163  return ref;
164 }
165 
166 unsigned 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 
180 unsigned long qAxLockCount()
181 {
182  return qAxModuleRef;
183 }
184 
186 // Registry
188 
189 extern bool qax_disable_inplaceframe;
190 
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.
208 HRESULT UpdateRegistry(BOOL bRegister)
209 {
210  qAxIsServer = false;
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 
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 (object->findChild<QMenuBar*>() && !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  }
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 
440 // IDL generator
442 
446 
447 static 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 
494 static 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 
529 static 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 
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 
578 
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
596 static 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
638 static 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 
660 static 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 
673 bool ignoreSlots(const char *test)
674 {
675  return ignore(test, ignore_slots);
676 }
677 
678 bool 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 
685 static QByteArray prototype(const QList<QByteArray> &parameterTypes, const QList<QByteArray> &parameterNames, bool *ok)
686 {
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 
727 static 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 
749 static 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()) {
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));
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)
1060 extern "C" __stdcall HRESULT DumpIDL(const QString &outfile, const QString &ver)
1061 #else
1062 extern "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 
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 
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) {
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();
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 
1244 ErrorInClass:
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 
1257 #endif // QT_NO_WIN_ACTIVEQT
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qstring.cpp:6448
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
static QString fromWCharArray(const wchar_t *, int size=-1)
Returns a copy of the string, where the encoding of string depends on the size of wchar...
Definition: qstring.cpp:1019
The QDir class provides access to directory structures and their contents.
Definition: qdir.h:58
static HRESULT classIDL(QObject *o, const QMetaObject *mo, const QString &className, bool isBindable, QTextStream &out)
Definition: qaxserver.cpp:749
QBool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.h:904
bool mkpath(const QString &dirPath) const
Creates the directory path dirPath.
Definition: qdir.cpp:1477
virtual QUuid typeLibID() const
Reimplement this function to return the ActiveX server&#39;s type library identifier. ...
Definition: qaxfactory.cpp:124
The QMetaObject class contains meta-information about Qt objects.
Definition: qobjectdefs.h:304
QTextStream & endl(QTextStream &stream)
Writes &#39; &#39; to the stream and flushes the stream.
The QApplication class manages the GUI application&#39;s control flow and main settings.
Definition: qapplication.h:99
void setValue(const QString &key, const QVariant &value)
Sets the value of setting key to value.
Definition: qsettings.cpp:3328
void setDevice(QIODevice *device)
Sets the current device to device.
static CRITICAL_SECTION qAxModuleSection
Definition: qaxserver.cpp:102
int type
Definition: qmetatype.cpp:239
QIntegerForSizeof< void * >::Unsigned quintptr
Definition: qglobal.h:986
The QMetaEnum class provides meta-data about an enumerator.
Definition: qmetaobject.h:147
QAxFactory * qax_instantiate()
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
static const char *const type_map[][2]
Definition: qaxserver.cpp:447
bool ignoreProps(const char *test)
Definition: qaxserver.cpp:678
bool isWritable() const
Returns true if settings can be written using this QSettings object; returns false otherwise...
Definition: qsettings.cpp:3306
The QAxBindable class provides an interface between a QWidget and an ActiveX client.
Definition: qaxbindable.h:60
bool open(OpenMode flags)
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition: qfile.cpp:1064
unsigned long qAxLockCount()
Definition: qaxserver.cpp:180
QString qax_clean_type(const QString &type, const QMetaObject *mo)
Definition: qaxserver.cpp:191
The QSettings class provides persistent platform-independent application settings.
Definition: qsettings.h:73
bool qax_ownQApp
void qAxCleanup()
Definition: qaxserver.cpp:139
QMetaClassInfo classInfo(int index) const
Returns the meta-data for the item of class information with the given index.
QByteArray rightJustified(int width, char fill=' ', bool truncate=false) const
Returns a byte array of size width that contains the fill character followed by this byte array...
QString & replace(int i, int len, QChar after)
Definition: qstring.cpp:2005
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
QString & prepend(QChar c)
Definition: qstring.h:261
QString toUpper() const Q_REQUIRED_RESULT
Returns an uppercase copy of the string.
Definition: qstring.cpp:5483
iterator begin()
Returns an STL-style iterator pointing to the first item in the list.
Definition: qlist.h:267
unsigned long qAxUnlock()
Definition: qaxserver.cpp:166
const char * mime
static bool ignore(const char *test, const char *const *table)
Definition: qaxserver.cpp:660
static const QMetaObject staticMetaObject
This variable stores the meta-object for the class.
Definition: qobject.h:128
The QAxFactory class defines a factory for the creation of COM components.
Definition: qaxfactory.h:64
static QByteArray addDefaultArguments(const QByteArray &prototype, int numDefArgs)
Definition: qaxserver.cpp:727
static QString keyPath(const QString &rKey)
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
static const char *const ignore_slots[]
Definition: qaxserver.cpp:638
const char * key(int index) const
Returns the key with the given index, or 0 if no such key exists.
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
int qRegisterMetaType()
Call this function to register the type T.
Definition: qmetatype.h:234
static const char *const ignore_props[]
Definition: qaxserver.cpp:596
ITypeLib * qAxTypeLibrary
Definition: qaxserver.cpp:66
int enumeratorOffset() const
Returns the enumerator offset for this class; i.e.
int propertyCount() const
Returns the number of properties in this class, including the number of properties provided by each b...
The QString class provides a Unicode character string.
Definition: qstring.h:83
const char * typeName() const
Returns the return type of this method, or an empty string if the return type is void.
static const char *const keyword_map[][2]
Definition: qaxserver.cpp:529
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
const char * value() const
Returns the value of this item.
virtual QStringList featureList() const =0
Reimplement this function to return a list of the widgets (class names) supported by this factory...
int indexOfProperty(const char *name) const
Finds property name and returns its index; otherwise returns -1.
QString toString() const
Returns the string representation of this QUuid.
Definition: quuid.cpp:512
const char * name() const
Returns the name of the enumerator (without the scope).
bool qAxOutProcServer
Definition: qaxserver.cpp:68
QStringList keys
QString toString(Qt::DateFormat f=Qt::TextDate) const
Returns the datetime as a string in the format given.
Definition: qdatetime.cpp:2628
const char * className
Definition: qwizard.cpp:137
bool isNull() const
Returns true if this is the null UUID {00000000-0000-0000-0000-000000000000}; otherwise returns false...
Definition: quuid.cpp:700
iterator Iterator
Qt-style synonym for QList::iterator.
Definition: qlist.h:278
bool qAxIsServer
Definition: qaxserver.cpp:64
virtual QString exposeToSuperClass(const QString &key) const
Reimplement this function to return the name of the super class of key up to which methods and proper...
Definition: qaxfactory.cpp:317
static QString toString(Register *reg, int type, bool *ok=0)
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
CLSID CLSID_QSize
QBool contains(const T &t) const
Returns true if the list contains an occurrence of value; otherwise returns false.
Definition: qlist.h:880
int lastIndexOf(char c, int from=-1) const
Returns the index position of the last occurrence of character ch in the byte array, searching backward from index position from.
Status status() const
Returns a status code indicating the first error that was met by QSettings, or QSettings::NoError if ...
Definition: qsettings.cpp:3041
HRESULT UpdateRegistry(BOOL bRegister)
Definition: qaxserver.cpp:208
QList< QByteArray > parameterNames() const
Returns a list of parameter names.
int methodOffset() const
Returns the method offset for this class; i.e.
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
QString trimmed() const Q_REQUIRED_RESULT
Returns a string that has whitespace removed from the start and the end.
Definition: qstring.cpp:4506
const QChar * unicode() const
Returns a &#39;\0&#39;-terminated Unicode representation of the string.
Definition: qstring.h:706
virtual bool hasStockEvents(const QString &key) const
Reimplement this function to return true if the ActiveX control key should support the standard Activ...
Definition: qaxfactory.cpp:353
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
#define qApp
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:270
const char * name
const T value(const Key &key) const
Returns the value associated with the key key.
Definition: qmap.h:499
wchar_t qAxModuleFilename[MAX_PATH]
Definition: qaxserver.cpp:67
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
static QByteArray replaceKeyword(const QByteArray &name)
Definition: qaxserver.cpp:566
Q_CORE_EXPORT void qWarning(const char *,...)
static QByteArray renameOverloads(const QByteArray &name)
Definition: qaxserver.cpp:579
virtual QUuid appID() const
Reimplement this function to return the ActiveX server&#39;s application identifier.
Definition: qaxfactory.cpp:138
unsigned int uint
Definition: qglobal.h:996
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:2838
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
T findChild(const QString &aName=QString()) const
Returns the child of this object that can be cast into type T and that is called name, or 0 if there is no such object.
Definition: qobject.h:158
virtual QUuid interfaceID(const QString &key) const
Reimplement this function to return the interface identifier for each key returned by the featureList...
Definition: qaxfactory.cpp:209
int enumeratorCount() const
Returns the number of enumerators in this class.
QString right(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n rightmost characters of the string.
Definition: qstring.cpp:3682
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
QByteArray left(int len) const
Returns a byte array that contains the leftmost len bytes of this byte array.
void * HANDLE
Definition: qnamespace.h:1671
const QMetaObject * superClass() const
Returns the meta-object of the superclass, or 0 if there is no such object.
Definition: qobjectdefs.h:494
QByteArray mid(int index, int len=-1) const
Returns a byte array containing len bytes from this byte array, starting at position pos...
virtual QUuid eventsID(const QString &key) const
Reimplement this function to return the identifier of the event interface for each key returned by th...
Definition: qaxfactory.cpp:228
int indexOf(char c, int from=0) const
Returns the index position of the first occurrence of the character ch in the byte array...
int qstricmp(const char *str1, const char *str2)
A safe stricmp() function.
Definition: qbytearray.cpp:279
int keyCount() const
Returns the number of keys.
HANDLE qAxInstance
Definition: qaxserver.cpp:65
#define STRIPCB(x)
Definition: qaxserver.cpp:683
bool ignoreSlots(const char *test)
Definition: qaxserver.cpp:673
int length() const
Same as size().
Definition: qbytearray.h:356
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
MethodType methodType() const
Returns the type of this method (signal, slot, or method).
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition: qstring.h:505
static QByteArray prototype(const QList< QByteArray > &parameterTypes, const QList< QByteArray > &parameterNames, bool *ok)
Definition: qaxserver.cpp:685
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
QList< QByteArray > parameterTypes() const
Returns a list of parameter types.
long HRESULT
bool isWidgetType() const
Returns true if the object is a widget; otherwise returns false.
Definition: qobject.h:146
HRESULT __stdcall DumpIDL(const QString &outfile, const QString &ver)
Definition: qaxserver.cpp:1062
The QMenuBar class provides a horizontal menu bar.
Definition: qmenubar.h:62
static int initCount
Definition: qaxserver.cpp:109
virtual void unregisterClass(const QString &key, QSettings *) const
Unregisters any additional values for the class key from the system registry using the settings objec...
Definition: qaxfactory.cpp:266
QString qAxInit()
Definition: qaxserver.cpp:111
The QFile class provides an interface for reading from and writing to files.
Definition: qfile.h:65
bool isFlag() const
Returns true if this enumerator is used as a flag; otherwise returns false.
void remove(const QString &key)
Removes the setting key and any sub-settings of key.
Definition: qsettings.cpp:3359
static unsigned long qAxModuleRef
Definition: qaxserver.cpp:101
The QTextStream class provides a convenient interface for reading and writing text.
Definition: qtextstream.h:73
The QMetaClassInfo class provides additional information about a class.
Definition: qmetaobject.h:224
int lastIndexOf(QChar c, int from=-1, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:3000
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
iterator insert(const Key &key, const T &value)
Inserts a new item with the key key and a value of value.
Definition: qmap.h:559
static QByteArray convertTypes(const QByteArray &qtype, bool *ok)
Definition: qaxserver.cpp:494
static QMap< QByteArray, int > mapping
Definition: qaxserver.cpp:577
const_iterator ConstIterator
Qt-style synonym for QList::const_iterator.
Definition: qlist.h:279
int key
QString toLower() const Q_REQUIRED_RESULT
Returns a lowercase copy of the string.
Definition: qstring.cpp:5389
const char * className() const
Returns the class name.
Definition: qobjectdefs.h:491
const char * property
Definition: qwizard.cpp:138
static QDateTime currentDateTime()
Returns the current datetime, as reported by the system clock, in the local time zone.
Definition: qdatetime.cpp:3138
bool contains(const Key &key) const
Returns true if the map contains an item with key key; otherwise returns false.
Definition: qmap.h:553
QMetaEnum enumerator(int index) const
Returns the meta-data for the enumerator with the given index.
static QList< QByteArray > enums
Definition: qaxserver.cpp:443
int attributes() const
bool remove()
Removes the file specified by fileName().
Definition: qfile.cpp:715
void flush()
Flushes any buffered data waiting to be written to the device.
bool qax_disable_inplaceframe
QMetaMethod method(int index) const
Returns the meta-data for the method with the given index.
The QMetaProperty class provides meta-data about a property.
Definition: qmetaobject.h:176
QByteArray & replace(int index, int len, const char *s)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QList< QByteArray > enumValues
Definition: qaxserver.cpp:444
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
static QAxFactory * qax_factory
Definition: qaxserver.cpp:71
int propertyOffset() const
Returns the property offset for this class; i.e.
const char * signature() const
Returns the signature of this method (e.g., setValue(double)).
static QList< QByteArray > subtypes
Definition: qaxserver.cpp:445
Access access() const
Returns the access specification of this method (private, protected, or public).
unsigned long qAxLock()
Definition: qaxserver.cpp:158
virtual const QMetaObject * metaObject(const QString &key) const =0
Reimplement this function to return the QMetaObject corresponding to key, or 0 if this factory doesn&#39;...
virtual QObject * createObject(const QString &key)=0
Reimplement this function to return a new object for key, or 0 if this factory doesn&#39;t support the va...
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition: qstring.cpp:3796
CLSID CLSID_QRect
QAxFactory * qAxFactory()
Definition: qaxserver.cpp:81
virtual void close()
Calls QFile::flush() and closes the file.
Definition: qfile.cpp:1680
void qax_shutDown()
int indexOfClassInfo(const char *name) const
Finds class information item name and returns its index; otherwise returns -1.
CLSID CLSID_QPoint
int methodCount() const
Returns the number of methods known to the meta-object system in this class, including the number of ...
static QByteArray number(int, int base=10)
Returns a byte array containing the string equivalent of the number n to base base (10 by default)...
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
The QMetaMethod class provides meta-data about a member function.
Definition: qmetaobject.h:56
void clear()
Removes all items from the map.
Definition: qmap.h:444
virtual const QMetaObject * metaObject() const
Returns a pointer to the meta-object of this object.
The QUuid class stores a Universally Unique Identifier (UUID).
Definition: quuid.h:67
static bool isNull(const QVariant::Private *d)
Definition: qvariant.cpp:300
QMetaProperty property(int index) const
Returns the meta-data for the property with the given index.
virtual QUuid classID(const QString &key) const
Reimplement this function to return the class identifier for each key returned by the featureList() i...
Definition: qaxfactory.cpp:191
bool endsWith(const QByteArray &a) const
Returns true if this byte array ends with byte array ba; otherwise returns false. ...
QBool contains(char c) const
Returns true if the byte array contains the character ch; otherwise returns false.
Definition: qbytearray.h:525
const ushort * utf16() const
Returns the QString as a &#39;\0\&#39;-terminated array of unsigned shorts.
Definition: qstring.cpp:5290
int value(int index) const
Returns the value with the given index; or returns -1 if there is no such value.
virtual void registerClass(const QString &key, QSettings *) const
Registers additional values for the class key in the system registry using the settings object...
Definition: qaxfactory.cpp:252