Qt 4.8
qaxbase.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 //#define QAX_NO_CLASSINFO
42 
43 #define QT_CHECK_STATE
44 
45 #include "qaxobject.h"
46 
47 #ifndef QT_NO_WIN_ACTIVEQT
48 
49 #include <qfile.h>
50 #include <qwidget.h>
51 
52 #include <quuid.h>
53 #include <qhash.h>
54 #include <qset.h>
55 #include <qpair.h>
56 #include <qmetaobject.h>
57 #include <qsettings.h>
58 
59 #ifndef QT_NO_THREAD
60 # include <qmutex.h>
61 #endif
62 
63 #include <qt_windows.h>
64 #include <ocidl.h>
65 #include <ctype.h>
66 
67 #include "../shared/qaxtypes.h"
68 
70 
71 /*
72  \internal
73  \class QAxMetaObject
74 
75  \brief The QAxMetaObject class stores extended information
76 */
77 struct QAxMetaObject : public QMetaObject
78 {
80  {
81  d.data = 0;
82  d.stringdata = 0;
83  }
85  {
86  delete [] (int*)d.data;
87  delete [] (char*)d.stringdata;
88  }
89 
90  int numParameter(const QByteArray &prototype);
91  QByteArray paramType(const QByteArray &signature, int index, bool *out = 0);
92  QByteArray propertyType(const QByteArray &propertyName);
93  void parsePrototype(const QByteArray &prototype);
94  DISPID dispIDofName(const QByteArray &name, IDispatch *disp);
95 
96 private:
97  friend class MetaObjectGenerator;
98  // save information about QAxEventSink connections, and connect when found in cache
100  // DISPID -> signal name
102  // DISPID -> property changed signal name
104  // DISPID -> property name
106 
107  // Prototype -> member info
110 
111  // DISPID cache
113 };
114 
116 {
117  QByteArray realProto = realPrototype.value(prototype, prototype);
118  QByteArray parameters = realProto.mid(realProto.indexOf('(') + 1);
119  parameters.truncate(parameters.length() - 1);
120 
121  if (parameters.isEmpty()) {
122  memberInfo.insert(prototype, QList<QByteArray>());
123  } else {
124  QList<QByteArray> plist = parameters.split(',');
125  memberInfo.insert(prototype, plist);
126  }
127 }
128 
130 {
131  return realPrototype.value(propertyName);
132 }
133 
135 {
136  if (!memberInfo.contains(prototype))
137  parsePrototype(prototype);
138 
139  return memberInfo.value(prototype).count();
140 }
141 
143 {
144  if (!memberInfo.contains(prototype))
145  parsePrototype(prototype);
146 
147  if (out)
148  *out = false;
149 
150  QList<QByteArray> plist = memberInfo.value(prototype);
151  if (index > plist.count() - 1)
152  return QByteArray();
153 
154  QByteArray param(plist.at(index));
155  if (param.isEmpty())
156  return QByteArray();
157 
158  bool byRef = param.endsWith('&') || param.endsWith("**");
159  if (byRef) {
160  param.truncate(param.length() - 1);
161  if (out)
162  *out = true;
163  }
164 
165  return param;
166 }
167 
168 inline DISPID QAxMetaObject::dispIDofName(const QByteArray &name, IDispatch *disp)
169 {
170  DISPID dispid = dispIDs.value(name, DISPID_UNKNOWN);
171  if (dispid == DISPID_UNKNOWN) {
172  // get the Dispatch ID from the object
173  QString unicodeName = QLatin1String(name);
174  OLECHAR *names = (wchar_t*)unicodeName.utf16();
175  disp->GetIDsOfNames(IID_NULL, &names, 1, LOCALE_USER_DEFAULT, &dispid);
176  if (dispid != DISPID_UNKNOWN)
177  dispIDs.insert(name, dispid);
178  }
179  return dispid;
180 }
181 
182 
185 static int mo_cache_ref = 0;
187 
188 
189 static const char *const type_conversion[][2] =
190 {
191  { "float", "double"},
192  { "short", "int"},
193  { "char", "int"},
194  { "QList<int>", "QVariantList" },
195  { "QList<uint>", "QVariantList" },
196  { "QList<double>", "QVariantList" },
197  { "QList<bool>", "QVariantList" },
198  { "QList<QDateTime>", "QVariantList" },
199  { "QList<qlonglong>", "QVariantList" },
200  { 0, 0 }
201 };
202 
203 /*
204  \internal
205  \class QAxEventSink
206 
207  \brief The QAxEventSink class implements the event sink for all
208  IConnectionPoints implemented in the COM object.
209 */
210 
211 class QAxEventSink : public IDispatch, public IPropertyNotifySink
212 {
213 public:
215  : cpoint(0), ciid(IID_NULL), combase(com), ref(1)
216  {}
217  virtual ~QAxEventSink()
218  {
219  Q_ASSERT(!cpoint);
220  }
221 
223  {
224  return ciid;
225  }
227  {
228  return sigs;
229  }
231  {
232  return props;
233  }
235  {
236  return propsigs;
237  }
238 
239  // add a connection
240  void advise(IConnectionPoint *cp, IID iid)
241  {
242  cpoint = cp;
243  cpoint->AddRef();
244  ciid = iid;
245  cpoint->Advise((IUnknown*)(IDispatch*)this, &cookie);
246  }
247 
248  // disconnect from all connection points
249  void unadvise()
250  {
251  combase = 0;
252  if (cpoint) {
253  cpoint->Unadvise(cookie);
254  cpoint->Release();
255  cpoint = 0;
256  }
257  }
258 
259  void addSignal(DISPID memid, const char *name)
260  {
261  QByteArray signalname = name;
262  int pi = signalname.indexOf('(');
263  int i = 0;
264  while (type_conversion[i][0]) {
265  int ti = pi;
266  int len = int(strlen(type_conversion[i][0]));
267  while ((ti = signalname.indexOf(type_conversion[i][0], ti)) != -1)
268  signalname.replace(ti, len, type_conversion[i][1]);
269  ++i;
270  }
271 
272  sigs.insert(memid, signalname);
274  DISPID id = -1;
275  for (it = propsigs.constBegin(); it!= propsigs.constEnd(); ++it) {
276  if (it.value() == signalname) {
277  id = it.key();
278  break;
279  }
280  }
281  if (id != -1)
282  propsigs.remove(id);
283  }
284  void addProperty(DISPID propid, const char *name, const char *signal)
285  {
286  props.insert(propid, name);
287  propsigs.insert(propid, signal);
288  }
289 
290  // IUnknown
291  unsigned long __stdcall AddRef()
292  {
293  return InterlockedIncrement(&ref);
294  }
295  unsigned long __stdcall Release()
296  {
297  LONG refCount = InterlockedDecrement(&ref);
298  if (!refCount)
299  delete this;
300 
301  return refCount;
302  }
303  HRESULT __stdcall QueryInterface(REFIID riid, void **ppvObject)
304  {
305  *ppvObject = 0;
306  if (riid == IID_IUnknown)
307  *ppvObject = (IUnknown*)(IDispatch*)this;
308  else if (riid == IID_IDispatch)
309  *ppvObject = (IDispatch*)this;
310  else if (riid == IID_IPropertyNotifySink)
311  *ppvObject = (IPropertyNotifySink*)this;
312  else if (ciid == riid)
313  *ppvObject = (IDispatch*)this;
314  else
315  return E_NOINTERFACE;
316 
317  AddRef();
318  return S_OK;
319  }
320 
321  // IDispatch
322  HRESULT __stdcall GetTypeInfoCount(unsigned int *) { return E_NOTIMPL; }
323  HRESULT __stdcall GetTypeInfo(UINT, LCID, ITypeInfo **) { return E_NOTIMPL; }
324  HRESULT __stdcall GetIDsOfNames(const _GUID &, wchar_t **, unsigned int, unsigned long, long *) { return E_NOTIMPL; }
325 
326  HRESULT __stdcall Invoke(DISPID dispIdMember,
327  REFIID riid,
328  LCID,
329  WORD wFlags,
330  DISPPARAMS *pDispParams,
331  VARIANT*,
332  EXCEPINFO*,
333  UINT*)
334  {
335  // verify input
336  if (riid != IID_NULL)
337  return DISP_E_UNKNOWNINTERFACE;
338  if (!(wFlags & DISPATCH_METHOD))
339  return DISP_E_MEMBERNOTFOUND;
340  if (!combase)
341  return E_UNEXPECTED;
342 
343  QByteArray signame = sigs.value(dispIdMember);
344  if (signame.isEmpty())
345  return DISP_E_MEMBERNOTFOUND;
346 
347  QObject *qobject = combase->qObject();
348  if (qobject->signalsBlocked())
349  return S_OK;
350 
351  QAxMetaObject *axmeta = combase->internalMetaObject();
352  const QMetaObject *meta = combase->metaObject();
353 
354  int index = -1;
355  // emit the generic signal "as is"
356  if (signalHasReceivers(qobject, "signal(QString,int,void*)")) {
357  index = meta->indexOfSignal("signal(QString,int,void*)");
358  Q_ASSERT(index != -1);
359 
360  QString nameString = QLatin1String(signame);
361  void *argv[] = {0, &nameString, &pDispParams->cArgs, &pDispParams->rgvarg};
362  combase->qt_metacall(QMetaObject::InvokeMetaMethod, index, argv);
363  }
364 
365  HRESULT hres = S_OK;
366 
367  // get the signal information from the metaobject
368  index = -1;
369  if (signalHasReceivers(qobject, signame)) {
370  index = meta->indexOfSignal(signame);
371  Q_ASSERT(index != -1);
372  const QMetaMethod signal = meta->method(index);
374  Q_ASSERT(signame == signal.signature());
375  // verify parameter count
376  int pcount = axmeta->numParameter(signame);
377  int argcount = pDispParams->cArgs;
378  if (pcount > argcount)
379  return DISP_E_PARAMNOTOPTIONAL;
380  else if (pcount < argcount)
381  return DISP_E_BADPARAMCOUNT;
382 
383  // setup parameters (no return values in signals)
384  bool ok = true;
385  void *static_argv[QAX_NUM_PARAMS + 1];
386  void *static_argv_pointer[QAX_NUM_PARAMS + 1];
387  QVariant static_varp[QAX_NUM_PARAMS + 1];
388 
389  void **argv = 0;
390  void **argv_pointer = 0; // in case we need an additional level of indirection
391  QVariant *varp = 0;
392 
393  if (pcount) {
394  if (pcount <= QAX_NUM_PARAMS) {
395  argv = static_argv;
396  argv_pointer = static_argv_pointer;
397  varp = static_varp;
398  } else {
399  argv = new void*[pcount + 1];
400  argv_pointer = new void*[pcount + 1];
401  varp = new QVariant[pcount + 1];
402  }
403 
404  argv[0] = 0;
405  argv_pointer[0] = 0;
406  }
407 
408  int p;
409  for (p = 0; p < pcount && ok; ++p) {
410  // map the VARIANT to the void*
411  QByteArray ptype = axmeta->paramType(signame, p);
412  varp[p + 1] = VARIANTToQVariant(pDispParams->rgvarg[pcount - p - 1], ptype);
413  argv_pointer[p + 1] = 0;
414  if (varp[p + 1].isValid()) {
415  if (varp[p + 1].type() == QVariant::UserType) {
416  argv[p + 1] = varp[p + 1].data();
417  } else if (ptype == "QVariant") {
418  argv[p + 1] = varp + p + 1;
419  } else {
420  argv[p + 1] = const_cast<void*>(varp[p + 1].constData());
421  if (ptype.endsWith('*')) {
422  argv_pointer[p + 1] = argv[p + 1];
423  argv[p + 1] = argv_pointer + p + 1;
424  }
425  }
426  } else if (ptype == "QVariant") {
427  argv[p + 1] = varp + p + 1;
428  } else {
429  ok = false;
430  }
431  }
432 
433  if (ok) {
434  // emit the generated signal if everything went well
435  combase->qt_metacall(QMetaObject::InvokeMetaMethod, index, argv);
436  // update the VARIANT for references and free memory
437  for (p = 0; p < pcount; ++p) {
438  bool out;
439  QByteArray ptype = axmeta->paramType(signame, p, &out);
440  if (out) {
441  if (!QVariantToVARIANT(varp[p + 1], pDispParams->rgvarg[pcount - p - 1], ptype, out))
442  ok = false;
443  }
444  }
445  }
446 
447  if (argv != static_argv) {
448  delete [] argv;
449  delete [] argv_pointer;
450  delete [] varp;
451  }
452  hres = ok ? S_OK : (ok ? DISP_E_MEMBERNOTFOUND : DISP_E_TYPEMISMATCH);
453  }
454 
455  return hres;
456  }
457 
458  QByteArray findProperty(DISPID dispID);
459 
460  // IPropertyNotifySink
461  HRESULT __stdcall OnChanged(DISPID dispID)
462  {
463  // verify input
464  if (dispID == DISPID_UNKNOWN || !combase)
465  return S_OK;
466 
467  const QMetaObject *meta = combase->metaObject();
468  if (!meta)
469  return S_OK;
470 
471  QByteArray propname(findProperty(dispID));
472  if (propname.isEmpty())
473  return S_OK;
474 
475  QObject *qobject = combase->qObject();
476  if (qobject->signalsBlocked())
477  return S_OK;
478 
479  // emit the generic signal
480  int index = meta->indexOfSignal("propertyChanged(QString)");
481  if (index != -1) {
482  QString propnameString = QString::fromLatin1(propname);
483  void *argv[] = {0, &propnameString};
484  combase->qt_metacall(QMetaObject::InvokeMetaMethod, index, argv);
485  }
486 
487  QByteArray signame = propsigs.value(dispID);
488  if (signame.isEmpty())
489  return S_OK;
490 
491  index = meta->indexOfSignal(signame);
492  if (index == -1) // bindable but not marked as bindable in typelib
493  return S_OK;
494 
495  // get the signal information from the metaobject
496  if (signalHasReceivers(qobject, signame)) {
497  index = meta->indexOfSignal(signame);
498  Q_ASSERT(index != -1);
499  // setup parameters
500  QVariant var = qobject->property(propname);
501  if (!var.isValid())
502  return S_OK;
503 
504  const QMetaProperty metaProp = meta->property(meta->indexOfProperty(propname));
505  void *argv[] = {0, var.data()};
506  if (metaProp.type() == QVariant::LastType)
507  argv[1] = &var;
508 
509  // emit the "changed" signal
510  combase->qt_metacall(QMetaObject::InvokeMetaMethod, index, argv);
511  }
512  return S_OK;
513  }
514  HRESULT __stdcall OnRequestEdit(DISPID dispID)
515  {
516  if (dispID == DISPID_UNKNOWN || !combase)
517  return S_OK;
518 
519  QByteArray propname(findProperty(dispID));
520  if (propname.isEmpty())
521  return S_OK;
522 
523  return combase->propertyWritable(propname) ? S_OK : S_FALSE;
524  }
525 
526  static bool signalHasReceivers(QObject *qobject, const char *signalName)
527  {
528  Q_ASSERT(qobject);
529  return ((QAxObject*)qobject)->receivers(QByteArray::number(QSIGNAL_CODE) + signalName);
530  }
531 
532  IConnectionPoint *cpoint;
533  IID ciid;
534  ULONG cookie;
535 
539 
541  LONG ref;
542 };
543 
544 /*
545  \internal
546  \class QAxBasePrivate
547 */
548 
550 {
551 public:
553  : useEventSink(true), useMetaObject(true), useClassInfo(true),
554  cachedMetaObject(false), initialized(false), tryCache(false),
555  ptr(0), disp(0), metaobj(0)
556  {
557  // protect initialization
558  QMutexLocker locker(&cache_mutex);
559  mo_cache_ref++;
560 
561  qRegisterMetaType<IUnknown*>("IUnknown*", &ptr);
562  qRegisterMetaType<IDispatch*>("IDispatch*", &disp);
563  }
564 
566  {
567  Q_ASSERT(!ptr);
568  Q_ASSERT(!disp);
569 
570  // protect cleanup
571  QMutexLocker locker(&cache_mutex);
572  if (!--mo_cache_ref) {
573  qDeleteAll(mo_cache);
574  mo_cache.clear();
575  }
576 
577  CoFreeUnusedLibraries();
578  }
579 
580  inline IDispatch *dispatch() const
581  {
582  if (disp)
583  return disp;
584 
585  if (ptr)
586  ptr->QueryInterface(IID_IDispatch, (void**)&disp);
587  return disp;
588  }
589 
591 
599 
600  IUnknown *ptr;
601  mutable IDispatch *disp;
602 
604 
606  {
607  if (!metaobj)
608  metaobj = new QAxMetaObject;
609  return metaobj;
610  }
611 
613 
615 };
616 
617 
619 {
620  // look up in cache, and fall back to
621  // type info for precompiled metaobjects
622  QByteArray propname(props.value(dispID));
623 
624  if (!propname.isEmpty())
625  return propname;
626 
627  IDispatch *dispatch = combase->d->dispatch();
628  ITypeInfo *typeinfo = 0;
629  if (dispatch)
630  dispatch->GetTypeInfo(0, LOCALE_USER_DEFAULT, &typeinfo);
631  if (!typeinfo)
632  return propname;
633 
634  BSTR names;
635  UINT cNames;
636  typeinfo->GetNames(dispID, &names, 1, &cNames);
637  if (cNames) {
638  propname = QString::fromWCharArray(names).toLatin1();
639  SysFreeString(names);
640  }
641  typeinfo->Release();
642 
643  QByteArray propsignal(propname + "Changed(");
644  const QMetaObject *mo = combase->metaObject();
645  int index = mo->indexOfProperty(propname);
646  const QMetaProperty prop = mo->property(index);
647  propsignal += prop.typeName();
648  propsignal += ')';
649  addProperty(dispID, propname, propsignal);
650 
651  return propname;
652 }
653 
850 QAxBase::QAxBase(IUnknown *iface)
851 {
852  d = new QAxBasePrivate();
853  d->ptr = iface;
854  if (d->ptr) {
855  d->ptr->AddRef();
856  d->initialized = true;
857  }
858 #if defined(Q_OS_WINCE)
859  CoInitializeEx(0, COINIT_MULTITHREADED);
860 #endif
861 }
862 
869 {
870 #if defined(Q_OS_WINCE)
871  CoUninitialize();
872 #endif
873 
874  clear();
875 
876  delete d;
877  d = 0;
878 }
879 
889 {
890  if (d->ptr)
891  d->ptr->Release();
892 }
893 
903 {
904  if (d->ptr)
905  return;
906 
907  d->ptr = that->d->ptr;
908  if (d->ptr) {
909  d->ptr->AddRef();
910  d->initialized = true;
911  }
912 }
913 
914 
916 {
917  return d->metaObject();
918 }
919 
976 {
977  if (c.toLower() == d->ctrl.toLower())
978  return !d->ctrl.isEmpty();
979 
980  QString search = c;
981  // don't waste time for DCOM requests
982  int dcomIDIndex = search.indexOf(QLatin1String("/{"));
983  if ((dcomIDIndex == -1 || dcomIDIndex != search.length()-39) && !search.endsWith(QLatin1String("}&"))) {
984  QUuid uuid(search);
985  if (uuid.isNull()) {
986  CLSID clsid;
987  HRESULT res = CLSIDFromProgID((wchar_t*)c.utf16(), &clsid);
988  if (res == S_OK)
989  search = QUuid(clsid).toString();
990  else {
991  QSettings controls(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes\\"), QSettings::NativeFormat);
992  search = controls.value(c + QLatin1String("/CLSID/Default")).toString();
993  if (search.isEmpty()) {
994  controls.beginGroup(QLatin1String("/CLSID"));
995  QStringList clsids = controls.childGroups();
996  for (QStringList::Iterator it = clsids.begin(); it != clsids.end(); ++it) {
997  QString clsid = *it;
998  QString name = controls.value(clsid + QLatin1String("/Default")).toString();
999  if (name == c) {
1000  search = clsid;
1001  break;
1002  }
1003  }
1004  controls.endGroup();
1005  }
1006  }
1007  }
1008  if (search.isEmpty())
1009  search = c;
1010  }
1011 
1012  if (search.toLower() == d->ctrl.toLower())
1013  return !d->ctrl.isEmpty();
1014 
1015  clear();
1016  d->ctrl = search;
1017 
1018  d->tryCache = true;
1019  if (!initialize(&d->ptr))
1020  d->initialized = true;
1021  if (isNull()) {
1022  qWarning("QAxBase::setControl: requested control %s could not be instantiated", c.toLatin1().data());
1023  clear();
1024  return false;
1025  }
1026  return true;
1027 }
1028 
1030 {
1031  return d->ctrl;
1032 }
1033 
1048 {
1049  d->useEventSink = false;
1050 }
1051 
1069 {
1070  d->useMetaObject = false;
1071  d->useEventSink = false;
1072  d->useClassInfo = false;
1073 }
1074 
1084 {
1085  d->useClassInfo = false;
1086 }
1087 
1096 {
1097  QHash<QUuid, QAxEventSink*>::Iterator it = d->eventSink.begin();
1098  while (it != d->eventSink.end()) {
1099  QAxEventSink *eventSink = it.value();
1100  ++it;
1101  if (eventSink) {
1102  eventSink->unadvise();
1103  eventSink->Release();
1104  }
1105  }
1106  d->eventSink.clear();
1107  if (d->disp) {
1108  d->disp->Release();
1109  d->disp = 0;
1110  }
1111  if (d->ptr) {
1112  d->ptr->Release();
1113  d->ptr = 0;
1114  d->initialized = false;
1115  }
1116 
1117  d->ctrl.clear();
1118 
1119  if (!d->cachedMetaObject)
1120  delete d->metaobj;
1121  d->metaobj = 0;
1122 }
1123 
1138 {
1139  if (!d->ptr)
1140  return QStringList();
1141 
1142  if (d->verbs.isEmpty()) {
1143  IOleObject *ole = 0;
1144  d->ptr->QueryInterface(IID_IOleObject, (void**)&ole);
1145  if (ole) {
1146  IEnumOLEVERB *enumVerbs = 0;
1147  ole->EnumVerbs(&enumVerbs);
1148  if (enumVerbs) {
1149  enumVerbs->Reset();
1150  ULONG c;
1151  OLEVERB verb;
1152  while (enumVerbs->Next(1, &verb, &c) == S_OK) {
1153  if (!verb.lpszVerbName)
1154  continue;
1155  QString verbName = QString::fromWCharArray(verb.lpszVerbName);
1156  if (!verbName.isEmpty())
1157  d->verbs.insert(verbName, verb.lVerb);
1158  }
1159  enumVerbs->Release();
1160  }
1161  ole->Release();
1162  }
1163  }
1164 
1165  return d->verbs.keys();
1166 }
1167 
1172 long QAxBase::indexOfVerb(const QString &verb) const
1173 {
1174  return d->verbs.value(verb);
1175 }
1176 
1199 bool QAxBase::initialize(IUnknown **ptr)
1200 {
1201  if (*ptr || control().isEmpty())
1202  return false;
1203 
1204  *ptr = 0;
1205 
1206  bool res = false;
1207 
1208  const QString ctrl(d->ctrl);
1209  if (ctrl.contains(QLatin1String("/{"))) // DCOM request
1210  res = initializeRemote(ptr);
1211  else if (ctrl.contains(QLatin1String("}:"))) // licensed control
1212  res = initializeLicensed(ptr);
1213  else if (ctrl.contains(QLatin1String("}&"))) // running object
1214  res = initializeActive(ptr);
1215  else if (QFile::exists(ctrl)) // existing file
1216  res = initializeFromFile(ptr);
1217 
1218  if (!res) { // standard
1219  HRESULT hres = CoCreateInstance(QUuid(ctrl), 0, CLSCTX_SERVER, IID_IUnknown, (void**)ptr);
1220  res = S_OK == hres;
1221 #ifndef QT_NO_DEBUG
1222  if (!res)
1223  qErrnoWarning(hres, "CoCreateInstance failure");
1224 #endif
1225  }
1226 
1227  return *ptr != 0;
1228 }
1229 
1241 {
1242  int at = control().lastIndexOf(QLatin1String("}:"));
1243 
1244  QString clsid(control().left(at));
1245  QString key(control().mid(at+2));
1246 
1247  IClassFactory *factory = 0;
1248  CoGetClassObject(QUuid(clsid), CLSCTX_SERVER, 0, IID_IClassFactory, (void**)&factory);
1249  if (!factory)
1250  return false;
1251  initializeLicensedHelper(factory, key, ptr);
1252  factory->Release();
1253 
1254  return *ptr != 0;
1255 }
1256 
1257 /* \internal
1258  Called by initializeLicensed and initializedRemote to create an object
1259  via IClassFactory2.
1260 */
1261 bool QAxBase::initializeLicensedHelper(void *f, const QString &key, IUnknown **ptr)
1262 {
1263  IClassFactory *factory = (IClassFactory*)f;
1264  IClassFactory2 *factory2 = 0;
1265  factory->QueryInterface(IID_IClassFactory2, (void**)&factory2);
1266  if (factory2) {
1267  BSTR bkey = QStringToBSTR(key);
1268  HRESULT hres = factory2->CreateInstanceLic(0, 0, IID_IUnknown, bkey, (void**)ptr);
1269  SysFreeString(bkey);
1270 #ifdef QT_DEBUG
1271  LICINFO licinfo;
1272  licinfo.cbLicInfo = sizeof(LICINFO);
1273  factory2->GetLicInfo(&licinfo);
1274 
1275  if (hres != S_OK) {
1276  SetLastError(hres);
1277  qErrnoWarning("CreateInstanceLic failed");
1278  if (!licinfo.fLicVerified) {
1279  qWarning("Wrong license key specified, and machine is not fully licensed.");
1280  } else if (licinfo.fRuntimeKeyAvail) {
1281  BSTR licenseKey;
1282  factory2->RequestLicKey(0, &licenseKey);
1283  QString qlicenseKey = QString::fromWCharArray(licenseKey);
1284  SysFreeString(licenseKey);
1285  qWarning("Use license key is '%s' to create object on unlicensed machine.",
1286  qlicenseKey.toLatin1().constData());
1287  }
1288  } else if (licinfo.fLicVerified) {
1289  qWarning("Machine is fully licensed for '%s'", control().toLatin1().constData());
1290  if (licinfo.fRuntimeKeyAvail) {
1291  BSTR licenseKey;
1292  factory2->RequestLicKey(0, &licenseKey);
1293  QString qlicenseKey = QString::fromWCharArray(licenseKey);
1294  SysFreeString(licenseKey);
1295 
1296  if (qlicenseKey != key)
1297  qWarning("Runtime license key is '%s'", qlicenseKey.toLatin1().constData());
1298  }
1299  }
1300 #else
1301  Q_UNUSED(hres);
1302 #endif
1303  factory2->Release();
1304  } else { // give it a shot without license
1305  factory->CreateInstance(0, IID_IUnknown, (void**)ptr);
1306  }
1307  return *ptr != 0;
1308 }
1309 
1310 
1322 {
1323 #if defined(Q_OS_WINCE)
1324  Q_UNUSED(ptr);
1325  return false;
1326 #else
1327  int at = control().lastIndexOf(QLatin1String("}&"));
1328  QString clsid(control().left(at));
1329 
1330  GetActiveObject(QUuid(clsid), 0, ptr);
1331 
1332  return *ptr != 0;
1333 #endif
1334 }
1335 
1336 #ifdef Q_CC_GNU
1337 # ifndef OLEPENDER_NONE
1338 # define OLERENDER_NONE 0
1339 # endif
1340 #endif
1341 
1353 {
1354 #if defined(Q_OS_WINCE)
1355  Q_UNUSED(ptr);
1356  return false;
1357 #else
1358  IStorage *storage = 0;
1359  ILockBytes * bytes = 0;
1360  HRESULT hres = ::CreateILockBytesOnHGlobal(0, TRUE, &bytes);
1361  hres = ::StgCreateDocfileOnILockBytes(bytes, STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &storage);
1362 
1363  hres = OleCreateFromFile(CLSID_NULL, reinterpret_cast<const wchar_t*>(control().utf16()), IID_IUnknown, OLERENDER_NONE, 0, 0, storage, (void**)ptr);
1364 
1365  storage->Release();
1366  bytes->Release();
1367 
1368  return hres == S_OK;
1369 #endif
1370 }
1371 
1372 
1373 // There seams to be a naming problem in mingw headers
1374 #if defined(Q_CC_GNU) && !defined(COAUTHIDENTITY) && !defined(__MINGW64_VERSION_MAJOR)
1375 #define COAUTHIDENTITY AUTH_IDENTITY
1376 #endif
1377 
1378 
1391 {
1392  int at = control().lastIndexOf(QLatin1String("/{"));
1393 
1394  QString server(control().left(at));
1395  QString clsid(control().mid(at+1));
1396 
1397  QString user;
1398  QString domain;
1399  QString passwd;
1400  QString key;
1401 
1402  at = server.indexOf(QChar::fromLatin1('@'));
1403  if (at != -1) {
1404  user = server.left(at);
1405  server = server.mid(at+1);
1406 
1407  at = user.indexOf(QChar::fromLatin1(':'));
1408  if (at != -1) {
1409  passwd = user.mid(at+1);
1410  user = user.left(at);
1411  }
1412  at = user.indexOf(QChar::fromLatin1('/'));
1413  if (at != -1) {
1414  domain = user.left(at);
1415  user = user.mid(at+1);
1416  }
1417  }
1418 
1419  at = clsid.lastIndexOf(QLatin1String("}:"));
1420  if (at != -1) {
1421  key = clsid.mid(at+2);
1422  clsid = clsid.left(at);
1423  }
1424 
1425  d->ctrl = server + QChar::fromLatin1('/') + clsid;
1426  if (!key.isEmpty())
1427  d->ctrl = d->ctrl + QChar::fromLatin1(':') + key;
1428 
1429  COAUTHIDENTITY authIdentity;
1430  authIdentity.UserLength = user.length();
1431  authIdentity.User = authIdentity.UserLength ? (ushort*)user.utf16() : 0;
1432  authIdentity.DomainLength = domain.length();
1433  authIdentity.Domain = authIdentity.DomainLength ? (ushort*)domain.utf16() : 0;
1434  authIdentity.PasswordLength = passwd.length();
1435  authIdentity.Password = authIdentity.PasswordLength ? (ushort*)passwd.utf16() : 0;
1436  authIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1437 
1438  COAUTHINFO authInfo;
1439  authInfo.dwAuthnSvc = RPC_C_AUTHN_WINNT;
1440  authInfo.dwAuthzSvc = RPC_C_AUTHZ_NONE;
1441  authInfo.pwszServerPrincName = 0;
1442  authInfo.dwAuthnLevel = RPC_C_AUTHN_LEVEL_DEFAULT;
1443  authInfo.dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE;
1444  authInfo.pAuthIdentityData = &authIdentity;
1445  authInfo.dwCapabilities = 0;
1446 
1447  COSERVERINFO serverInfo;
1448  serverInfo.dwReserved1 = 0;
1449  serverInfo.dwReserved2 = 0;
1450  serverInfo.pAuthInfo = &authInfo;
1451  serverInfo.pwszName = (wchar_t*)server.utf16();
1452 
1453  IClassFactory *factory = 0;
1454  HRESULT res = CoGetClassObject(QUuid(clsid), CLSCTX_REMOTE_SERVER, &serverInfo, IID_IClassFactory, (void**)&factory);
1455  if (factory) {
1456  if (!key.isEmpty())
1457  initializeLicensedHelper(factory, key, ptr);
1458  else
1459  res = factory->CreateInstance(0, IID_IUnknown, (void**)ptr);
1460  factory->Release();
1461  }
1462 #ifndef QT_NO_DEBUG
1463  if (res != S_OK)
1464  qErrnoWarning(res, "initializeRemote Failed");
1465 #endif
1466 
1467  return res == S_OK;
1468 }
1469 
1479 long QAxBase::queryInterface(const QUuid &uuid, void **iface) const
1480 {
1481  *iface = 0;
1482  if (!d->ptr) {
1483  ((QAxBase*)this)->initialize(&d->ptr);
1484  d->initialized = true;
1485  }
1486 
1487  if (d->ptr && !uuid.isNull())
1488  return d->ptr->QueryInterface(uuid, iface);
1489 
1490  return E_NOTIMPL;
1491 }
1492 
1494 {
1495 public:
1497  MetaObjectGenerator(ITypeLib *typelib, ITypeInfo *typeinfo);
1499 
1500  QMetaObject *metaObject(const QMetaObject *parentObject, const QByteArray &className = QByteArray());
1501 
1502  void readClassInfo();
1503  void readEnumInfo();
1504  void readInterfaceInfo();
1505  void readFuncsInfo(ITypeInfo *typeinfo, ushort nFuncs);
1506  void readVarsInfo(ITypeInfo *typeinfo, ushort nVars);
1507  void readEventInfo();
1508  void readEventInterface(ITypeInfo *eventinfo, IConnectionPoint *cpoint);
1509 
1510  inline void addClassInfo(const char *key, const char *value)
1511  {
1512  classinfo_list.insert(key, value);
1513  }
1514 
1515 private:
1516  void init();
1517 
1518 
1519  QMetaObject *tryCache();
1520 
1521  QByteArray createPrototype(FUNCDESC *funcdesc, ITypeInfo *typeinfo, const QList<QByteArray> &names,
1522  QByteArray &type, QList<QByteArray> &parameters);
1523 
1524  QByteArray usertypeToString(const TYPEDESC &tdesc, ITypeInfo *info, const QByteArray &function);
1525  QByteArray guessTypes(const TYPEDESC &tdesc, ITypeInfo *info, const QByteArray &function);
1526 
1527  // ### from qmetaobject.cpp
1529  Invalid = 0x00000000,
1530  Readable = 0x00000001,
1531  Writable = 0x00000002,
1532  Resettable = 0x00000004,
1533  EnumOrFlag = 0x00000008,
1534  StdCppSet = 0x00000100,
1535 // Override = 0x00000200,
1536  Designable = 0x00001000,
1537  ResolveDesignable = 0x00002000,
1538  Scriptable = 0x00004000,
1539  ResolveScriptable = 0x00008000,
1540  Stored = 0x00010000,
1541  ResolveStored = 0x00020000,
1542  Editable = 0x00040000,
1543  ResolveEditable = 0x00080000,
1544  User = 0x00100000,
1545  ResolveUser = 0x00200000,
1546  // And our own - don't use the upper byte, as it's used for the property type
1547  RequestingEdit = 0x00400000,
1548  Bindable = 0x00800000
1549  };
1554  MemberMethod = 0x00,
1555  MemberSignal = 0x04,
1556  MemberSlot = 0x08,
1557  MemberCompatibility = 0x10,
1558  MemberCloned = 0x20,
1559  MemberScriptable = 0x40,
1560  };
1561 
1563  {
1564  QByteArray prototype(proto);
1565  QByteArray parameters = prototype.mid(prototype.indexOf('(') + 1);
1566  parameters.truncate(parameters.length() - 1);
1567 
1568  QList<QByteArray> plist = parameters.split(',');
1569  return plist;
1570  }
1571 
1572  inline QByteArray replaceType(const QByteArray &type)
1573  {
1574  int i = 0;
1575  while (type_conversion[i][0]) {
1576  int len = int(strlen(type_conversion[i][0]));
1577  int ti;
1578  if ((ti = type.indexOf(type_conversion[i][0])) != -1) {
1579  QByteArray rtype(type);
1580  rtype.replace(ti, len, type_conversion[i][1]);
1581  return rtype;
1582  }
1583  ++i;
1584  }
1585  return type;
1586  }
1587 
1589  {
1590  QByteArray proto(prototype);
1591 
1592  QList<QByteArray> plist = paramList(prototype);
1593  for (int p = 0; p < plist.count(); ++p) {
1594  QByteArray param(plist.at(p));
1595  if (param != replaceType(param)) {
1596  int type = 0;
1597  while (type_conversion[type][0]) {
1598  int paren = proto.indexOf('(');
1599  while ((paren = proto.indexOf(type_conversion[type][0])) != -1) {
1600  proto.replace(paren, qstrlen(type_conversion[type][0]), type_conversion[type][1]);
1601  }
1602  ++type;
1603  }
1604  break;
1605  }
1606  }
1607 
1608  return proto;
1609  }
1610 
1612 
1613  inline bool hasClassInfo(const char *key)
1614  {
1615  return classinfo_list.contains(key);
1616  }
1617 
1618  struct Method {
1619  Method() : flags(0)
1620  {}
1623  int flags;
1625  };
1627  inline void addSignal(const QByteArray &prototype, const QByteArray &parameters)
1628  {
1629  QByteArray proto(replacePrototype(prototype));
1630 
1631  Method &signal = signal_list[proto];
1632  signal.type = 0;
1633  signal.parameters = parameters;
1634  signal.flags = QMetaMethod::Public | MemberSignal;
1635  if (proto != prototype)
1636  signal.realPrototype = prototype;
1637  }
1638 
1639  void addChangedSignal(const QByteArray &function, const QByteArray &type, int memid);
1640 
1641  inline bool hasSignal(const QByteArray &prototype)
1642  {
1643  return signal_list.contains(prototype);
1644  }
1645 
1647  inline void addSlot(const QByteArray &type, const QByteArray &prototype, const QByteArray &parameters, int flags = QMetaMethod::Public)
1648  {
1649  QByteArray proto = replacePrototype(prototype);
1650 
1651  Method &slot = slot_list[proto];
1652  slot.type = replaceType(type);
1653  slot.parameters = parameters;
1654  slot.flags = flags | MemberSlot;
1655  if (proto != prototype)
1656  slot.realPrototype = prototype;
1657  }
1658 
1659  void addSetterSlot(const QByteArray &property);
1660 
1661  inline bool hasSlot(const QByteArray &prototype)
1662  {
1663  return slot_list.contains(prototype);
1664  }
1665 
1666  struct Property {
1667  Property() : typeId(0)
1668  {}
1672  };
1674  void addProperty(const QByteArray &type, const QByteArray &name, uint flags)
1675  {
1676  QByteArray propertyType(type);
1677  if (propertyType.endsWith('&'))
1678  propertyType.chop(1);
1679 
1680  Property &prop = property_list[name];
1681  if (!propertyType.isEmpty() && propertyType != "HRESULT") {
1682  prop.type = replaceType(propertyType);
1683  if (prop.type != propertyType)
1684  prop.realType = propertyType;
1685  }
1686  if (flags & Writable)
1687  flags |= Stored;
1688  prop.typeId |= flags;
1689  QVariant::Type vartype = QVariant::nameToType(prop.type);
1690  switch(vartype) {
1691  case QVariant::Invalid:
1692  case QVariant::UserType:
1693  if (prop.type == "QVariant") {
1694  prop.typeId |= 0xff << 24;
1695  break;
1696  }
1697  if (QMetaType::type(prop.type) == -1)
1698  qWarning("QAxBase: Unsupported property type: %s", prop.type.data());
1699  break;
1700  default:
1701  prop.typeId |= vartype << 24;
1702  break;
1703  }
1704  }
1705 
1706  inline bool hasProperty(const QByteArray &name)
1707  {
1708  return property_list.contains(name);
1709  }
1710 
1712  {
1713  return property_list.value(name).type;
1714  }
1715 
1717  inline void addEnumValue(const QByteArray &enumname, const QByteArray &key, int value)
1718  {
1719  enum_list[enumname].append(QPair<QByteArray, int>(key, value));
1720  }
1721 
1722  inline bool hasEnum(const QByteArray &enumname)
1723  {
1724  return enum_list.contains(enumname);
1725  }
1726 
1729 
1730  IDispatch *disp;
1731  ITypeInfo *dispInfo;
1732  ITypeInfo *classInfo;
1733  ITypeLib *typelib;
1735 
1739 
1741 
1742  friend QMetaObject *qax_readClassInfo(ITypeLib *typeLib, ITypeInfo *classInfo, const QMetaObject *parentObject);
1743 };
1744 
1745 QMetaObject *qax_readEnumInfo(ITypeLib *typeLib, const QMetaObject *parentObject)
1746 {
1747  MetaObjectGenerator generator(typeLib, 0);
1748 
1749  generator.readEnumInfo();
1750  return generator.metaObject(parentObject, "EnumInfo");
1751 }
1752 
1753 QMetaObject *qax_readInterfaceInfo(ITypeLib *typeLib, ITypeInfo *typeInfo, const QMetaObject *parentObject)
1754 {
1755  MetaObjectGenerator generator(typeLib, typeInfo);
1756 
1758  BSTR bstr;
1759  if (S_OK != typeInfo->GetDocumentation(-1, &bstr, 0, 0, 0))
1760  return 0;
1761 
1762  className = QString::fromWCharArray(bstr);
1763  SysFreeString(bstr);
1764 
1765  generator.readEnumInfo();
1766  generator.readFuncsInfo(typeInfo, 0);
1767  generator.readVarsInfo(typeInfo, 0);
1768 
1769  return generator.metaObject(parentObject, className.toLatin1());
1770 }
1771 
1772 QMetaObject *qax_readClassInfo(ITypeLib *typeLib, ITypeInfo *classInfo, const QMetaObject *parentObject)
1773 {
1774  MetaObjectGenerator generator(typeLib, 0);
1775  generator.addSignal("exception(int,QString,QString,QString)", "code,source,disc,help");
1776  generator.addSignal("propertyChanged(QString)", "name");
1777 
1779  BSTR bstr;
1780  if (S_OK != classInfo->GetDocumentation(-1, &bstr, 0, 0, 0))
1781  return 0;
1782 
1783  className = QString::fromWCharArray(bstr);
1784  SysFreeString(bstr);
1785 
1786  generator.readEnumInfo();
1787 
1788  TYPEATTR *typeattr;
1789  classInfo->GetTypeAttr(&typeattr);
1790  if (typeattr) {
1791  int nInterfaces = typeattr->cImplTypes;
1792  classInfo->ReleaseTypeAttr(typeattr);
1793 
1794  for (int index = 0; index < nInterfaces; ++index) {
1795  HREFTYPE refType;
1796  if (S_OK != classInfo->GetRefTypeOfImplType(index, &refType))
1797  continue;
1798 
1799  int flags = 0;
1800  classInfo->GetImplTypeFlags(index, &flags);
1801  if (flags & IMPLTYPEFLAG_FRESTRICTED)
1802  continue;
1803 
1804  ITypeInfo *interfaceInfo = 0;
1805  classInfo->GetRefTypeInfo(refType, &interfaceInfo);
1806  if (!interfaceInfo)
1807  continue;
1808 
1809  interfaceInfo->GetDocumentation(-1, &bstr, 0, 0, 0);
1810  QString interfaceName = QString::fromWCharArray(bstr);
1811  SysFreeString(bstr);
1812  QByteArray key;
1813 
1814  TYPEATTR *typeattr = 0;
1815  interfaceInfo->GetTypeAttr(&typeattr);
1816 
1817  if (flags & IMPLTYPEFLAG_FSOURCE) {
1818  if (typeattr && !(typeattr->wTypeFlags & TYPEFLAG_FHIDDEN))
1819  key = "Event Interface " + QByteArray::number(index);
1820  generator.readEventInterface(interfaceInfo, 0);
1821  } else {
1822  if (typeattr && !(typeattr->wTypeFlags & TYPEFLAG_FHIDDEN))
1823  key = "Interface " + QByteArray::number(index);
1824  generator.readFuncsInfo(interfaceInfo, 0);
1825  generator.readVarsInfo(interfaceInfo, 0);
1826  }
1827  if (!key.isEmpty())
1828  generator.addClassInfo(key.data(), interfaceName.toLatin1());
1829 
1830  if (typeattr)
1831  interfaceInfo->ReleaseTypeAttr(typeattr);
1832  interfaceInfo->Release();
1833  }
1834  }
1835 
1836  return generator.metaObject(parentObject, className.toLatin1());
1837 }
1838 
1840 : that(ax), d(dptr), disp(0), dispInfo(0), classInfo(0), typelib(0),
1841  iidnames(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes"), QSettings::NativeFormat)
1842 {
1843  init();
1844 }
1845 
1846 MetaObjectGenerator::MetaObjectGenerator(ITypeLib *tlib, ITypeInfo *tinfo)
1847 : that(0), d(0), disp(0), dispInfo(tinfo), classInfo(0), typelib(tlib),
1848  iidnames(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes"), QSettings::NativeFormat)
1849 {
1850  init();
1851 
1852  if (dispInfo)
1853  dispInfo->AddRef();
1854  if (typelib) {
1855  typelib->AddRef();
1856  BSTR bstr;
1857  typelib->GetDocumentation(-1, &bstr, 0, 0, 0);
1859  SysFreeString(bstr);
1860  }
1861  readClassInfo();
1862 }
1863 
1865 {
1866  if (d)
1867  disp = d->dispatch();
1868 
1869  iid_propNotifySink = IID_IPropertyNotifySink;
1870 
1871  addSignal("signal(QString,int,void*)", "name,argc,argv");
1872  addSignal("exception(int,QString,QString,QString)", "code,source,disc,help");
1873  addSignal("propertyChanged(QString)", "name");
1874  if (d || dispInfo) {
1876  }
1877 }
1878 
1880 {
1881  if (dispInfo) dispInfo->Release();
1882  if (classInfo) classInfo->Release();
1883  if (typelib) typelib->Release();
1884 }
1885 
1888 
1889 QByteArray MetaObjectGenerator::usertypeToString(const TYPEDESC &tdesc, ITypeInfo *info, const QByteArray &function)
1890 {
1891  HREFTYPE usertype = tdesc.hreftype;
1892  if (tdesc.vt != VT_USERDEFINED)
1893  return 0;
1894 
1896  ITypeInfo *usertypeinfo = 0;
1897  info->GetRefTypeInfo(usertype, &usertypeinfo);
1898  if (usertypeinfo) {
1899  ITypeLib *usertypelib = 0;
1900  UINT index;
1901  usertypeinfo->GetContainingTypeLib(&usertypelib, &index);
1902  if (usertypelib) {
1903  // get type library name
1904  BSTR typelibname = 0;
1905  usertypelib->GetDocumentation(-1, &typelibname, 0, 0, 0);
1906  QByteArray typeLibName = QString::fromWCharArray(typelibname).toLatin1();
1907  SysFreeString(typelibname);
1908 
1909  // get type name
1910  BSTR usertypename = 0;
1911  usertypelib->GetDocumentation(index, &usertypename, 0, 0, 0);
1912  QByteArray userTypeName = QString::fromWCharArray(usertypename).toLatin1();
1913  SysFreeString(usertypename);
1914 
1915  if (hasEnum(userTypeName)) // known enum?
1916  typeName = userTypeName;
1917  else if (userTypeName == "OLE_COLOR" || userTypeName == "VB_OLE_COLOR")
1918  typeName = "QColor";
1919  else if (userTypeName == "IFontDisp" || userTypeName == "IFontDisp*" || userTypeName == "IFont" || userTypeName == "IFont*")
1920  typeName = "QFont";
1921  else if (userTypeName == "Picture" || userTypeName == "Picture*")
1922  typeName = "QPixmap";
1923 
1924  if (typeName.isEmpty()) {
1925  TYPEATTR *typeattr = 0;
1926  usertypeinfo->GetTypeAttr(&typeattr);
1927  if (typeattr) {
1928  switch(typeattr->typekind) {
1929  case TKIND_ALIAS:
1930  userTypeName = guessTypes(typeattr->tdescAlias, usertypeinfo, function);
1931  break;
1932  case TKIND_DISPATCH:
1933  case TKIND_COCLASS:
1935  userTypeName = "IDispatch";
1936  } else {
1937  if (typeLibName != current_typelib)
1938  userTypeName = typeLibName + "::" + userTypeName;
1939  if (!qax_qualified_usertypes.contains(userTypeName))
1940  qax_qualified_usertypes << userTypeName;
1941  }
1942  break;
1943  case TKIND_ENUM:
1944  if (typeLibName != current_typelib)
1945  userTypeName = typeLibName + "::" + userTypeName;
1946  if (!qax_qualified_usertypes.contains("enum " + userTypeName))
1947  qax_qualified_usertypes << "enum " + userTypeName;
1948  break;
1949  case TKIND_INTERFACE:
1950  if (typeLibName != current_typelib)
1951  userTypeName = typeLibName + "::" + userTypeName;
1952  if (!qax_qualified_usertypes.contains(userTypeName))
1953  qax_qualified_usertypes << userTypeName;
1954  break;
1955  case TKIND_RECORD:
1956  if (!qax_qualified_usertypes.contains("struct " + userTypeName))
1957  qax_qualified_usertypes << "struct "+ userTypeName;
1958  break;
1959  default:
1960  break;
1961  }
1962  }
1963 
1964  usertypeinfo->ReleaseTypeAttr(typeattr);
1965  typeName = userTypeName;
1966  }
1967  usertypelib->Release();
1968  }
1969  usertypeinfo->Release();
1970  }
1971 
1972  return typeName;
1973 }
1974 
1975 #define VT_UNHANDLED(x) case VT_##x: qWarning("QAxBase: Unhandled type %s", #x); str = #x; break;
1976 
1977 QByteArray MetaObjectGenerator::guessTypes(const TYPEDESC &tdesc, ITypeInfo *info, const QByteArray &function)
1978 {
1979  QByteArray str;
1980  switch (tdesc.vt) {
1981  case VT_EMPTY:
1982  case VT_VOID:
1983  break;
1984  case VT_LPWSTR:
1985  str = "wchar_t *";
1986  break;
1987  case VT_BSTR:
1988  str = "QString";
1989  break;
1990  case VT_BOOL:
1991  str = "bool";
1992  break;
1993  case VT_I1:
1994  str = "char";
1995  break;
1996  case VT_I2:
1997  str = "short";
1998  break;
1999  case VT_I4:
2000  case VT_INT:
2001  str = "int";
2002  break;
2003  case VT_I8:
2004  str = "qlonglong";
2005  break;
2006  case VT_UI1:
2007  case VT_UI2:
2008  case VT_UI4:
2009  case VT_UINT:
2010  str = "uint";
2011  break;
2012  case VT_UI8:
2013  str = "qulonglong";
2014  break;
2015  case VT_CY:
2016  str = "qlonglong";
2017  break;
2018  case VT_R4:
2019  str = "float";
2020  break;
2021  case VT_R8:
2022  str = "double";
2023  break;
2024  case VT_DATE:
2025  str = "QDateTime";
2026  break;
2027  case VT_DISPATCH:
2028  str = "IDispatch*";
2029  break;
2030  case VT_VARIANT:
2031  str = "QVariant";
2032  break;
2033  case VT_UNKNOWN:
2034  str = "IUnknown*";
2035  break;
2036  case VT_HRESULT:
2037  str = "HRESULT";
2038  break;
2039  case VT_PTR:
2040  str = guessTypes(*tdesc.lptdesc, info, function);
2041  switch(tdesc.lptdesc->vt) {
2042  case VT_VOID:
2043  str = "void*";
2044  break;
2045  case VT_VARIANT:
2046  case VT_BSTR:
2047  case VT_I1:
2048  case VT_I2:
2049  case VT_I4:
2050  case VT_I8:
2051  case VT_UI1:
2052  case VT_UI2:
2053  case VT_UI4:
2054  case VT_UI8:
2055  case VT_BOOL:
2056  case VT_R4:
2057  case VT_R8:
2058  case VT_INT:
2059  case VT_UINT:
2060  case VT_CY:
2061  str += '&';
2062  break;
2063  case VT_PTR:
2064  if (str == "QFont" || str == "QPixmap") {
2065  str += '&';
2066  break;
2067  } else if (str == "void*") {
2068  str = "void **";
2069  break;
2070  }
2071  // FALLTHROUGH
2072  default:
2073  if (str == "QColor")
2074  str += '&';
2075  else if (str == "QDateTime")
2076  str += '&';
2077  else if (str == "QVariantList")
2078  str += '&';
2079  else if (str == "QByteArray")
2080  str += '&';
2081  else if (str == "QStringList")
2082  str += '&';
2083  else if (!str.isEmpty() && hasEnum(str))
2084  str += '&';
2085  else if (!str.isEmpty() && str != "QFont" && str != "QPixmap" && str != "QVariant")
2086  str += '*';
2087  }
2088  break;
2089  case VT_SAFEARRAY:
2090  switch(tdesc.lpadesc->tdescElem.vt) {
2091  // some shortcuts, and generic support for lists of QVariant-supported types
2092  case VT_UI1:
2093  str = "QByteArray";
2094  break;
2095  case VT_BSTR:
2096  str = "QStringList";
2097  break;
2098  case VT_VARIANT:
2099  str = "QVariantList";
2100  break;
2101  default:
2102  str = guessTypes(tdesc.lpadesc->tdescElem, info, function);
2103  if (!str.isEmpty())
2104  str = "QList<" + str + '>';
2105  break;
2106  }
2107  break;
2108  case VT_CARRAY:
2109  str = guessTypes(tdesc.lpadesc->tdescElem, info, function);
2110  if (!str.isEmpty()) {
2111  for (int index = 0; index < tdesc.lpadesc->cDims; ++index)
2112  str += '[' + QByteArray::number((int)tdesc.lpadesc->rgbounds[index].cElements) + ']';
2113  }
2114  break;
2115  case VT_USERDEFINED:
2116  str = usertypeToString(tdesc, info, function);
2117  break;
2118 
2119  VT_UNHANDLED(FILETIME);
2120  VT_UNHANDLED(BLOB);
2122  VT_UNHANDLED(DECIMAL);
2123  VT_UNHANDLED(LPSTR);
2124  default:
2125  break;
2126  }
2127 
2128  if (tdesc.vt & VT_BYREF)
2129  str += '&';
2130 
2131  str.replace("&*", "**");
2132  return str;
2133 }
2134 
2136 {
2137  // Read class information
2138  IProvideClassInfo *provideClassInfo = 0;
2139  if (d)
2140  d->ptr->QueryInterface(IID_IProvideClassInfo, (void**)&provideClassInfo);
2141  if (provideClassInfo) {
2142  provideClassInfo->GetClassInfo(&classInfo);
2143  TYPEATTR *typeattr = 0;
2144  if (classInfo)
2145  classInfo->GetTypeAttr(&typeattr);
2146 
2147  QString coClassID;
2148  if (typeattr) {
2149  QUuid clsid(typeattr->guid);
2150  coClassID = clsid.toString().toUpper();
2151 #ifndef QAX_NO_CLASSINFO
2152  // UUID
2153  if (d->useClassInfo && !hasClassInfo("CoClass")) {
2154  QString coClassIDstr = iidnames.value(QLatin1String("/CLSID/") + coClassID + QLatin1String("/Default"), coClassID).toString();
2155  addClassInfo("CoClass", coClassIDstr.isEmpty() ? coClassID.toLatin1() : coClassIDstr.toLatin1());
2156  QByteArray version = QByteArray::number(typeattr->wMajorVerNum) + '.' + QByteArray::number(typeattr->wMinorVerNum);
2157  if (version != "0.0")
2158  addClassInfo("Version", version);
2159  }
2160 #endif
2161  classInfo->ReleaseTypeAttr(typeattr);
2162  }
2163  provideClassInfo->Release();
2164  provideClassInfo = 0;
2165 
2166  if (d->tryCache && !coClassID.isEmpty())
2167  cacheKey = QString::fromLatin1("%1$%2$%3$%4").arg(coClassID)
2169  }
2170 
2171  UINT index = 0;
2172  if (disp && !dispInfo)
2173  disp->GetTypeInfo(index, LOCALE_USER_DEFAULT, &dispInfo);
2174 
2175  if (dispInfo && !typelib)
2176  dispInfo->GetContainingTypeLib(&typelib, &index);
2177 
2178  if (!typelib) {
2179  QSettings controls(QLatin1String("HKEY_LOCAL_MACHINE\\Software"), QSettings::NativeFormat);
2180  QString tlid = controls.value(QLatin1String("/Classes/CLSID/") + that->control() + QLatin1String("/TypeLib/.")).toString();
2181  QString tlfile;
2182  if (!tlid.isEmpty()) {
2183  controls.beginGroup(QLatin1String("/Classes/TypeLib/") + tlid);
2184  QStringList versions = controls.childGroups();
2185  QStringList::Iterator vit = versions.begin();
2186  while (tlfile.isEmpty() && vit != versions.end()) {
2187  QString version = *vit;
2188  ++vit;
2189  tlfile = controls.value(QLatin1Char('/') + version + QLatin1String("/0/win32/.")).toString();
2190  }
2191  controls.endGroup();
2192  } else {
2193  tlfile = controls.value(QLatin1String("/Classes/CLSID/") + that->control() + QLatin1String("/InprocServer32/.")).toString();
2194  if (tlfile.isEmpty())
2195  tlfile = controls.value(QLatin1String("/Classes/CLSID/") + that->control() + QLatin1String("/LocalServer32/.")).toString();
2196  }
2197  if (!tlfile.isEmpty()) {
2198  LoadTypeLib((OLECHAR*)tlfile.utf16(), &typelib);
2199  if (!typelib) {
2200  tlfile = tlfile.left(tlfile.lastIndexOf(QLatin1Char('.'))) + QLatin1String(".tlb");
2201  LoadTypeLib((OLECHAR*)tlfile.utf16(), &typelib);
2202  }
2203  if (!typelib) {
2204  tlfile = tlfile.left(tlfile.lastIndexOf(QLatin1Char('.'))) + QLatin1String(".olb");
2205  LoadTypeLib((OLECHAR*)tlfile.utf16(), &typelib);
2206  }
2207  }
2208  }
2209 
2210  if (!classInfo && typelib && that)
2211  typelib->GetTypeInfoOfGuid(QUuid(that->control()), &classInfo);
2212 
2213  if (classInfo && !dispInfo) {
2214  TYPEATTR *classAttr;
2215  classInfo->GetTypeAttr(&classAttr);
2216  if (classAttr) {
2217  for (int i = 0; i < classAttr->cImplTypes; ++i) {
2218  int typeFlags = 0;
2219  classInfo->GetImplTypeFlags(i, &typeFlags);
2220  if (typeFlags & IMPLTYPEFLAG_FSOURCE)
2221  continue;
2222 
2223  HREFTYPE hrefType;
2224  if (S_OK == classInfo->GetRefTypeOfImplType(i, &hrefType))
2225  classInfo->GetRefTypeInfo(hrefType, &dispInfo);
2226  if (dispInfo) {
2227  TYPEATTR *ifaceAttr;
2228  dispInfo->GetTypeAttr(&ifaceAttr);
2229  WORD typekind = ifaceAttr->typekind;
2230  dispInfo->ReleaseTypeAttr(ifaceAttr);
2231 
2232  if (typekind & TKIND_DISPATCH) {
2233  break;
2234  } else {
2235  dispInfo->Release();
2236  dispInfo = 0;
2237  }
2238  }
2239  }
2240  classInfo->ReleaseTypeAttr(classAttr);
2241  }
2242  }
2243 
2244  if (!d || !dispInfo || !cacheKey.isEmpty() || !d->tryCache)
2245  return;
2246 
2247  TYPEATTR *typeattr = 0;
2248  dispInfo->GetTypeAttr(&typeattr);
2249 
2250  QString interfaceID;
2251  if (typeattr) {
2252  QUuid iid(typeattr->guid);
2253  interfaceID = iid.toString().toUpper();
2254 
2255  dispInfo->ReleaseTypeAttr(typeattr);
2256  // ### event interfaces!!
2257  if (!interfaceID.isEmpty())
2258  cacheKey = QString::fromLatin1("%1$%2$%3$%4").arg(interfaceID)
2260  }
2261 }
2262 
2264 {
2265  if (!typelib)
2266  return;
2267 
2268  QUuid libUuid;
2269 
2270  if (d && d->tryCache) {
2271  TLIBATTR *libAttr = 0;
2272  typelib->GetLibAttr(&libAttr);
2273  if (libAttr) {
2274  libUuid = QUuid(libAttr->guid);
2275  typelib->ReleaseTLibAttr(libAttr);
2276  enum_list = enum_cache.value(libUuid);
2277  if (!enum_list.isEmpty())
2278  return;
2279  }
2280  }
2281 
2282  int valueindex = 0;
2283  QSet<QString> clashCheck;
2284  int clashIndex = 0;
2285 
2286  int enum_serial = 0;
2287  UINT index = typelib->GetTypeInfoCount();
2288  for (UINT i = 0; i < index; ++i) {
2289  TYPEKIND typekind;
2290  typelib->GetTypeInfoType(i, &typekind);
2291  if (typekind == TKIND_ENUM) {
2292  // Get the type information for the enum
2293  ITypeInfo *enuminfo = 0;
2294  typelib->GetTypeInfo(i, &enuminfo);
2295  if (!enuminfo)
2296  continue;
2297 
2298  // Get the name of the enumeration
2299  BSTR enumname;
2300  QByteArray enumName;
2301  if (typelib->GetDocumentation(i, &enumname, 0, 0, 0) == S_OK) {
2302  enumName = QString::fromWCharArray(enumname).toLatin1();
2303  SysFreeString(enumname);
2304  } else {
2305  enumName = "enum" + QByteArray::number(++enum_serial);
2306  }
2307 
2308  // Get the attributes of the enum type
2309  TYPEATTR *typeattr = 0;
2310  enuminfo->GetTypeAttr(&typeattr);
2311  if (typeattr) {
2312  // Get all values of the enumeration
2313  for (UINT vd = 0; vd < (UINT)typeattr->cVars; ++vd) {
2314  VARDESC *vardesc = 0;
2315  enuminfo->GetVarDesc(vd, &vardesc);
2316  if (vardesc && vardesc->varkind == VAR_CONST) {
2317  int value = vardesc->lpvarValue->lVal;
2318  int memid = vardesc->memid;
2319  // Get the name of the value
2320  BSTR valuename;
2321  QByteArray valueName;
2322  UINT maxNamesOut;
2323  enuminfo->GetNames(memid, &valuename, 1, &maxNamesOut);
2324  if (maxNamesOut) {
2325  valueName = QString::fromWCharArray(valuename).toLatin1();
2326  SysFreeString(valuename);
2327  } else {
2328  valueName = "value" + QByteArray::number(valueindex++);
2329  }
2330 
2331  if (clashCheck.contains(QString::fromLatin1(valueName)))
2332  valueName += QByteArray::number(++clashIndex);
2333 
2334  clashCheck.insert(QString::fromLatin1(valueName));
2335  addEnumValue(enumName, valueName, value);
2336  }
2337  enuminfo->ReleaseVarDesc(vardesc);
2338  }
2339  }
2340  enuminfo->ReleaseTypeAttr(typeattr);
2341  enuminfo->Release();
2342  }
2343  }
2344 
2345  if (!libUuid.isNull())
2346  enum_cache.insert(libUuid, enum_list);
2347 }
2348 
2349 void MetaObjectGenerator::addChangedSignal(const QByteArray &function, const QByteArray &type, int memid)
2350 {
2351  QAxEventSink *eventSink = 0;
2352  if (d) {
2353  eventSink = d->eventSink.value(iid_propNotifySink);
2354  if (!eventSink && d->useEventSink) {
2355  eventSink = new QAxEventSink(that);
2356  d->eventSink.insert(iid_propNotifySink, eventSink);
2357  }
2358  }
2359  // generate changed signal
2360  QByteArray signalName(function);
2361  signalName += "Changed";
2362  QByteArray signalProto = signalName + '(' + replaceType(type) + ')';
2363  if (!hasSignal(signalProto))
2364  addSignal(signalProto, function);
2365  if (eventSink)
2366  eventSink->addProperty(memid, function, signalProto);
2367 }
2368 
2370 {
2371  QByteArray set;
2372  QByteArray prototype(property);
2373  if (isupper(prototype.at(0))) {
2374  set = "Set";
2375  } else {
2376  set = "set";
2377  prototype[0] = toupper(prototype[0]);
2378  }
2379  prototype = set + prototype + '(' + propertyType(property) + ')';
2380  if (!hasSlot(prototype))
2381  addSlot(0, prototype, property);
2382 }
2383 
2384 QByteArray MetaObjectGenerator::createPrototype(FUNCDESC *funcdesc, ITypeInfo *typeinfo, const QList<QByteArray> &names,
2385  QByteArray &type, QList<QByteArray> &parameters)
2386 {
2388  QByteArray function(names.at(0));
2389  const QByteArray hresult("HRESULT");
2390  // get function prototype
2391  type = guessTypes(funcdesc->elemdescFunc.tdesc, typeinfo, function);
2392  if ((type.isEmpty() || type == hresult) && funcdesc->invkind == INVOKE_PROPERTYPUT && funcdesc->lprgelemdescParam) {
2393  type = guessTypes(funcdesc->lprgelemdescParam->tdesc, typeinfo, function);
2394  }
2395 
2396  prototype = function + '(';
2397  if (funcdesc->invkind == INVOKE_FUNC && type == hresult)
2398  type = 0;
2399 
2400  int p;
2401  for (p = 1; p < names.count(); ++p) {
2402  // parameter
2403  QByteArray paramName = names.at(p);
2404  bool optional = p > (funcdesc->cParams - funcdesc->cParamsOpt);
2405  TYPEDESC tdesc = funcdesc->lprgelemdescParam[p-1].tdesc;
2406  PARAMDESC pdesc = funcdesc->lprgelemdescParam[p-1].paramdesc;
2407 
2408  QByteArray ptype = guessTypes(tdesc, typeinfo, function);
2409  if (pdesc.wParamFlags & PARAMFLAG_FRETVAL) {
2410  if (ptype.endsWith('&')) {
2411  ptype.truncate(ptype.length() - 1);
2412  } else if (ptype.endsWith("**")) {
2413  ptype.truncate(ptype.length() - 1);
2414  }
2415  type = ptype;
2416  } else {
2417  prototype += ptype;
2418  if (pdesc.wParamFlags & PARAMFLAG_FOUT && !ptype.endsWith('&') && !ptype.endsWith("**"))
2419  prototype += '&';
2420  if (optional || pdesc.wParamFlags & PARAMFLAG_FOPT)
2421  paramName += "=0";
2422  else if (pdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) {
2423  // ### get the value from pdesc.pparamdescex
2424  paramName += "=0";
2425  }
2426  parameters << paramName;
2427  }
2428  if (p < funcdesc->cParams && !(pdesc.wParamFlags & PARAMFLAG_FRETVAL))
2429  prototype += ',';
2430  }
2431 
2432  if (!prototype.isEmpty()) {
2433  if (prototype.endsWith(',')) {
2434  if (funcdesc->invkind == INVOKE_PROPERTYPUT && p == funcdesc->cParams) {
2435  TYPEDESC tdesc = funcdesc->lprgelemdescParam[p-1].tdesc;
2436  QByteArray ptype = guessTypes(tdesc, typeinfo, function);
2437  prototype += ptype;
2438  prototype += ')';
2439  parameters << "rhs";
2440  } else {
2441  prototype[prototype.length()-1] = ')';
2442  }
2443  } else {
2444  prototype += ')';
2445  }
2446  }
2447 
2448  return prototype;
2449 }
2450 
2451 void MetaObjectGenerator::readFuncsInfo(ITypeInfo *typeinfo, ushort nFuncs)
2452 {
2453  if (!nFuncs) {
2454  TYPEATTR *typeattr = 0;
2455  typeinfo->GetTypeAttr(&typeattr);
2456  if (typeattr) {
2457  nFuncs = typeattr->cFuncs;
2458  typeinfo->ReleaseTypeAttr(typeattr);
2459  }
2460  }
2461 
2462  // get information about all functions
2463  for (ushort fd = 0; fd < nFuncs ; ++fd) {
2464  FUNCDESC *funcdesc = 0;
2465  typeinfo->GetFuncDesc(fd, &funcdesc);
2466  if (!funcdesc)
2467  break;
2468 
2469  QByteArray function;
2470  QByteArray type;
2472  QList<QByteArray> parameters;
2473 
2474  // parse function description
2475  BSTR bstrNames[256];
2476  UINT maxNames = 255;
2477  UINT maxNamesOut;
2478  typeinfo->GetNames(funcdesc->memid, (BSTR*)&bstrNames, maxNames, &maxNamesOut);
2479  QList<QByteArray> names;
2480  int p;
2481  for (p = 0; p < (int)maxNamesOut; ++p) {
2482  names << QString::fromWCharArray(bstrNames[p]).toLatin1();
2483  SysFreeString(bstrNames[p]);
2484  }
2485 
2486  // function name
2487  function = names.at(0);
2488  if ((maxNamesOut == 3 && function == "QueryInterface") ||
2489  (maxNamesOut == 1 && function == "AddRef") ||
2490  (maxNamesOut == 1 && function == "Release") ||
2491  (maxNamesOut == 9 && function == "Invoke") ||
2492  (maxNamesOut == 6 && function == "GetIDsOfNames") ||
2493  (maxNamesOut == 2 && function == "GetTypeInfoCount") ||
2494  (maxNamesOut == 4 && function == "GetTypeInfo")) {
2495  typeinfo->ReleaseFuncDesc(funcdesc);
2496  continue;
2497  }
2498 
2499  prototype = createPrototype(/*in*/ funcdesc, typeinfo, names, /*out*/type, parameters);
2500 
2501  // get type of function
2502  switch(funcdesc->invkind) {
2503  case INVOKE_PROPERTYGET: // property
2504  case INVOKE_PROPERTYPUT:
2505  if (funcdesc->cParams - funcdesc->cParamsOpt <= 1) {
2506  bool dontBreak = false;
2507  // getter with non-default-parameters -> fall through to function handling
2508  if (funcdesc->invkind == INVOKE_PROPERTYGET && parameters.count() && funcdesc->cParams - funcdesc->cParamsOpt) {
2509  dontBreak = true;
2510  } else {
2511  uint flags = Readable;
2512  if (funcdesc->invkind != INVOKE_PROPERTYGET)
2513  flags |= Writable;
2514  if (!(funcdesc->wFuncFlags & (FUNCFLAG_FNONBROWSABLE | FUNCFLAG_FHIDDEN)))
2515  flags |= Designable;
2516  if (!(funcdesc->wFuncFlags & FUNCFLAG_FRESTRICTED))
2517  flags |= Scriptable;
2518  if (funcdesc->wFuncFlags & FUNCFLAG_FREQUESTEDIT)
2519  flags |= RequestingEdit;
2520  if (hasEnum(type))
2521  flags |= EnumOrFlag;
2522 
2523  if (funcdesc->wFuncFlags & FUNCFLAG_FBINDABLE && funcdesc->invkind == INVOKE_PROPERTYGET) {
2524  addChangedSignal(function, type, funcdesc->memid);
2525  flags |= Bindable;
2526  }
2527  // Don't generate code for properties without type
2528  if (type.isEmpty())
2529  break;
2530  addProperty(type, function, flags);
2531 
2532  // more parameters -> function handling
2533  if (funcdesc->invkind == INVOKE_PROPERTYGET && funcdesc->cParams)
2534  dontBreak = true;
2535  }
2536 
2537  if (!funcdesc->cParams) {
2538  // don't generate slots for incomplete properties
2539  if (type.isEmpty())
2540  break;
2541 
2542  // Done for getters
2543  if (funcdesc->invkind == INVOKE_PROPERTYGET)
2544  break;
2545 
2546  // generate setter slot
2547  if (funcdesc->invkind == INVOKE_PROPERTYPUT && hasProperty(function)) {
2548  addSetterSlot(function);
2549  break;
2550  }
2551  } else if (funcdesc->invkind == INVOKE_PROPERTYPUT && hasProperty(function)) {
2552  addSetterSlot(function);
2553  // more parameters -> function handling
2554  if (funcdesc->cParams > 1)
2555  dontBreak = true;
2556  }
2557  if (!dontBreak)
2558  break;
2559  }
2560  if (funcdesc->invkind == INVOKE_PROPERTYPUT) {
2561  // remove the typename guessed for property setters
2562  // its done only for setter's with more than one parameter.
2563  if (funcdesc->cParams - funcdesc->cParamsOpt > 1) {
2564  type.clear();
2565  }
2566  QByteArray set;
2567  if (isupper(prototype.at(0))) {
2568  set = "Set";
2569  } else {
2570  set = "set";
2571  prototype[0] = toupper(prototype[0]);
2572  }
2573 
2574  prototype = set + prototype;
2575  }
2576  // FALL THROUGH to support multi-variat properties
2577  case INVOKE_FUNC: // method
2578  {
2579  bool cloned = false;
2580  bool defargs;
2581  do {
2582  QByteArray pnames;
2583  for (p = 0; p < parameters.count(); ++p) {
2584  pnames += parameters.at(p);
2585  if (p < parameters.count() - 1)
2586  pnames += ',';
2587  }
2588  defargs = pnames.contains("=0");
2589  int flags = QMetaMethod::Public;
2590  if (cloned)
2591  flags |= QMetaMethod::Cloned << 4;
2592  cloned |= defargs;
2593  addSlot(type, prototype, pnames.replace("=0", ""), flags);
2594 
2595  if (defargs) {
2596  parameters.takeLast();
2597  int lastParam = prototype.lastIndexOf(',');
2598  if (lastParam == -1)
2599  lastParam = prototype.indexOf('(') + 1;
2600  prototype.truncate(lastParam);
2601  prototype += ')';
2602  }
2603  } while (defargs);
2604  }
2605  break;
2606 
2607  default:
2608  break;
2609  }
2610 #if 0 // documentation in metaobject would be cool?
2611  // get function documentation
2612  BSTR bstrDocu;
2613  info->GetDocumentation(funcdesc->memid, 0, &bstrDocu, 0, 0);
2614  QString strDocu = QString::fromWCharArray(bstrDocu);
2615  SysFreeString(bstrDocu);
2616  if (!!strDocu)
2617  desc += '[' + strDocu + ']';
2618  desc += '\n';
2619 #endif
2620  typeinfo->ReleaseFuncDesc(funcdesc);
2621  }
2622 }
2623 
2624 void MetaObjectGenerator::readVarsInfo(ITypeInfo *typeinfo, ushort nVars)
2625 {
2626  if (!nVars) {
2627  TYPEATTR *typeattr = 0;
2628  typeinfo->GetTypeAttr(&typeattr);
2629  if (typeattr) {
2630  nVars = typeattr->cVars;
2631  typeinfo->ReleaseTypeAttr(typeattr);
2632  }
2633  }
2634 
2635  // get information about all variables
2636  for (ushort vd = 0; vd < nVars; ++vd) {
2637  VARDESC *vardesc;
2638  typeinfo->GetVarDesc(vd, &vardesc);
2639  if (!vardesc)
2640  break;
2641 
2642  // no use if it's not a dispatched variable
2643  if (vardesc->varkind != VAR_DISPATCH) {
2644  typeinfo->ReleaseVarDesc(vardesc);
2645  continue;
2646  }
2647 
2648  // get variable name
2649  BSTR bstrName;
2650  UINT maxNames = 1;
2651  UINT maxNamesOut;
2652  typeinfo->GetNames(vardesc->memid, &bstrName, maxNames, &maxNamesOut);
2653  if (maxNamesOut != 1 || !bstrName) {
2654  typeinfo->ReleaseVarDesc(vardesc);
2655  continue;
2656  }
2657  QByteArray variableType;
2658  QByteArray variableName;
2659  uint flags = 0;
2660 
2661  variableName = QString::fromWCharArray(bstrName).toLatin1();
2662  SysFreeString(bstrName);
2663 
2664  // get variable type
2665  TYPEDESC typedesc = vardesc->elemdescVar.tdesc;
2666  variableType = guessTypes(typedesc, typeinfo, variableName);
2667 
2668  // generate meta property
2669  if (!hasProperty(variableName)) {
2670  flags = Readable;
2671  if (!(vardesc->wVarFlags & VARFLAG_FREADONLY))
2672  flags |= Writable;
2673  if (!(vardesc->wVarFlags & (VARFLAG_FNONBROWSABLE | VARFLAG_FHIDDEN)))
2674  flags |= Designable;
2675  if (!(vardesc->wVarFlags & VARFLAG_FRESTRICTED))
2676  flags |= Scriptable;
2677  if (vardesc->wVarFlags & VARFLAG_FREQUESTEDIT)
2678  flags |= RequestingEdit;
2679  if (hasEnum(variableType))
2680  flags |= EnumOrFlag;
2681 
2682  if (vardesc->wVarFlags & VARFLAG_FBINDABLE) {
2683  addChangedSignal(variableName, variableType, vardesc->memid);
2684  flags |= Bindable;
2685  }
2686  addProperty(variableType, variableName, flags);
2687  }
2688 
2689  // generate a set slot
2690  if (!(vardesc->wVarFlags & VARFLAG_FREADONLY))
2691  addSetterSlot(variableName);
2692 
2693 #if 0 // documentation in metaobject would be cool?
2694  // get function documentation
2695  BSTR bstrDocu;
2696  info->GetDocumentation(vardesc->memid, 0, &bstrDocu, 0, 0);
2697  QString strDocu = QString::fromWCharArray(bstrDocu);
2698  SysFreeString(bstrDocu);
2699  if (!!strDocu)
2700  desc += '[' + strDocu + ']';
2701  desc += '\n';
2702 #endif
2703  typeinfo->ReleaseVarDesc(vardesc);
2704  }
2705 }
2706 
2708 {
2709  ITypeInfo *typeinfo = dispInfo;
2710  if (!typeinfo)
2711  return;
2712  typeinfo->AddRef();
2713  int interface_serial = 0;
2714  while (typeinfo) {
2715  ushort nFuncs = 0;
2716  ushort nVars = 0;
2717  ushort nImpl = 0;
2718  // get information about type
2719  TYPEATTR *typeattr;
2720  typeinfo->GetTypeAttr(&typeattr);
2721  bool interesting = true;
2722  if (typeattr) {
2723  // get number of functions, variables, and implemented interfaces
2724  nFuncs = typeattr->cFuncs;
2725  nVars = typeattr->cVars;
2726  nImpl = typeattr->cImplTypes;
2727 
2728  if ((typeattr->typekind == TKIND_DISPATCH || typeattr->typekind == TKIND_INTERFACE) &&
2729  (typeattr->guid != IID_IDispatch && typeattr->guid != IID_IUnknown)) {
2730 #ifndef QAX_NO_CLASSINFO
2731  if (d && d->useClassInfo) {
2732  // UUID
2733  QUuid uuid(typeattr->guid);
2734  QString uuidstr = uuid.toString().toUpper();
2735  uuidstr = iidnames.value(QLatin1String("/Interface/") + uuidstr + QLatin1String("/Default"), uuidstr).toString();
2736  addClassInfo("Interface " + QByteArray::number(++interface_serial), uuidstr.toLatin1());
2737  }
2738 #endif
2739  typeinfo->ReleaseTypeAttr(typeattr);
2740  } else {
2741  interesting = false;
2742  typeinfo->ReleaseTypeAttr(typeattr);
2743  }
2744  }
2745 
2746  if (interesting) {
2747  readFuncsInfo(typeinfo, nFuncs);
2748  readVarsInfo(typeinfo, nVars);
2749  }
2750 
2751  if (!nImpl) {
2752  typeinfo->Release();
2753  typeinfo = 0;
2754  break;
2755  }
2756 
2757  // go up one base class
2758  HREFTYPE pRefType;
2759  typeinfo->GetRefTypeOfImplType(0, &pRefType);
2760  ITypeInfo *baseInfo = 0;
2761  typeinfo->GetRefTypeInfo(pRefType, &baseInfo);
2762  typeinfo->Release();
2763  if (typeinfo == baseInfo) { // IUnknown inherits IUnknown ???
2764  baseInfo->Release();
2765  typeinfo = 0;
2766  break;
2767  }
2768  typeinfo = baseInfo;
2769  }
2770 }
2771 
2772 void MetaObjectGenerator::readEventInterface(ITypeInfo *eventinfo, IConnectionPoint *cpoint)
2773 {
2774  TYPEATTR *eventattr;
2775  eventinfo->GetTypeAttr(&eventattr);
2776  if (!eventattr)
2777  return;
2778  if (eventattr->typekind != TKIND_DISPATCH) {
2779  eventinfo->ReleaseTypeAttr(eventattr);
2780  return;
2781  }
2782 
2783  QAxEventSink *eventSink = 0;
2784  if (d) {
2785  IID conniid;
2786  cpoint->GetConnectionInterface(&conniid);
2787  eventSink = d->eventSink.value(QUuid(conniid));
2788  if (!eventSink) {
2789  eventSink = new QAxEventSink(that);
2790  d->eventSink.insert(QUuid(conniid), eventSink);
2791  eventSink->advise(cpoint, conniid);
2792  }
2793  }
2794 
2795  // get information about all event functions
2796  for (UINT fd = 0; fd < (UINT)eventattr->cFuncs; ++fd) {
2797  FUNCDESC *funcdesc;
2798  eventinfo->GetFuncDesc(fd, &funcdesc);
2799  if (!funcdesc)
2800  break;
2801  if (funcdesc->invkind != INVOKE_FUNC ||
2802  funcdesc->funckind != FUNC_DISPATCH) {
2803  eventinfo->ReleaseTypeAttr(eventattr);
2804  eventinfo->ReleaseFuncDesc(funcdesc);
2805  continue;
2806  }
2807 
2808  QByteArray function;
2810  QList<QByteArray> parameters;
2811 
2812  // parse event function description
2813  BSTR bstrNames[256];
2814  UINT maxNames = 255;
2815  UINT maxNamesOut;
2816  eventinfo->GetNames(funcdesc->memid, (BSTR*)&bstrNames, maxNames, &maxNamesOut);
2817  QList<QByteArray> names;
2818  int p;
2819  for (p = 0; p < (int)maxNamesOut; ++p) {
2820  names << QString::fromWCharArray(bstrNames[p]).toLatin1();
2821  SysFreeString(bstrNames[p]);
2822  }
2823 
2824  // get event function prototype
2825  function = names.at(0);
2826  QByteArray type; // dummy - we don't care about return values for signals
2827  prototype = createPrototype(/*in*/ funcdesc, eventinfo, names, /*out*/type, parameters);
2828  if (!hasSignal(prototype)) {
2829  QByteArray pnames;
2830  for (p = 0; p < parameters.count(); ++p) {
2831  pnames += parameters.at(p);
2832  if (p < parameters.count() - 1)
2833  pnames += ',';
2834  }
2835  addSignal(prototype, pnames);
2836  }
2837  if (eventSink)
2838  eventSink->addSignal(funcdesc->memid, prototype);
2839 
2840 #if 0 // documentation in metaobject would be cool?
2841  // get function documentation
2842  BSTR bstrDocu;
2843  eventinfo->GetDocumentation(funcdesc->memid, 0, &bstrDocu, 0, 0);
2844  QString strDocu = QString::fromWCharArray(bstrDocu);
2845  SysFreeString(bstrDocu);
2846  if (!!strDocu)
2847  desc += '[' + strDocu + ']';
2848  desc += '\n';
2849 #endif
2850  eventinfo->ReleaseFuncDesc(funcdesc);
2851  }
2852  eventinfo->ReleaseTypeAttr(eventattr);
2853 }
2854 
2856 {
2857  int event_serial = 0;
2858  IConnectionPointContainer *cpoints = 0;
2859  if (d && d->useEventSink)
2860  d->ptr->QueryInterface(IID_IConnectionPointContainer, (void**)&cpoints);
2861  if (cpoints) {
2862  // Get connection point enumerator
2863  IEnumConnectionPoints *epoints = 0;
2864  cpoints->EnumConnectionPoints(&epoints);
2865  if (epoints) {
2866  ULONG c = 1;
2867  IConnectionPoint *cpoint = 0;
2868  epoints->Reset();
2869  QList<QUuid> cpointlist;
2870  do {
2871  if (cpoint) cpoint->Release();
2872  cpoint = 0;
2873  HRESULT hr = epoints->Next(c, &cpoint, &c);
2874  if (!c || hr != S_OK)
2875  break;
2876 
2877  IID conniid;
2878  cpoint->GetConnectionInterface(&conniid);
2879  // workaround for typelibrary bug of Word.Application
2880  QUuid connuuid(conniid);
2881  if (cpointlist.contains(connuuid))
2882  break;
2883 
2884 #ifndef QAX_NO_CLASSINFO
2885  if (d->useClassInfo) {
2886  QString uuidstr = connuuid.toString().toUpper();
2887  uuidstr = iidnames.value(QLatin1String("/Interface/") + uuidstr + QLatin1String("/Default"), uuidstr).toString();
2888  addClassInfo("Event Interface " + QByteArray::number(++event_serial), uuidstr.toLatin1());
2889  }
2890 #endif
2891 
2892  // get information about type
2893  if (conniid == IID_IPropertyNotifySink) {
2894  // test whether property notify sink has been created already, and advise on it
2896  if (eventSink)
2897  eventSink->advise(cpoint, conniid);
2898  continue;
2899  }
2900 
2901  ITypeInfo *eventinfo = 0;
2902  if (typelib)
2903  typelib->GetTypeInfoOfGuid(conniid, &eventinfo);
2904 
2905  if (eventinfo) {
2906  // avoid recursion (see workaround above)
2907  cpointlist.append(connuuid);
2908 
2909  readEventInterface(eventinfo, cpoint);
2910  eventinfo->Release();
2911  }
2912  } while (c);
2913  if (cpoint) cpoint->Release();
2914  epoints->Release();
2915  } else if (classInfo) { // no enumeration - search source interfaces and ask for those
2916  TYPEATTR *typeattr = 0;
2917  classInfo->GetTypeAttr(&typeattr);
2918  if (typeattr) {
2919  for (int i = 0; i < typeattr->cImplTypes; ++i) {
2920  int flags = 0;
2921  classInfo->GetImplTypeFlags(i, &flags);
2922  if (!(flags & IMPLTYPEFLAG_FSOURCE))
2923  continue;
2924  HREFTYPE reference;
2925  if (S_OK != classInfo->GetRefTypeOfImplType(i, &reference))
2926  continue;
2927  ITypeInfo *eventInfo = 0;
2928  classInfo->GetRefTypeInfo(reference, &eventInfo);
2929  if (!eventInfo)
2930  continue;
2931  TYPEATTR *eventattr = 0;
2932  eventInfo->GetTypeAttr(&eventattr);
2933  if (eventattr) {
2934  IConnectionPoint *cpoint = 0;
2935  cpoints->FindConnectionPoint(eventattr->guid, &cpoint);
2936  if (cpoint) {
2937  if (eventattr->guid == IID_IPropertyNotifySink) {
2938  // test whether property notify sink has been created already, and advise on it
2940  if (eventSink)
2941  eventSink->advise(cpoint, eventattr->guid);
2942  continue;
2943  }
2944 
2945  readEventInterface(eventInfo, cpoint);
2946  cpoint->Release();
2947  }
2948  eventInfo->ReleaseTypeAttr(eventattr);
2949  }
2950  eventInfo->Release();
2951  }
2952  classInfo->ReleaseTypeAttr(typeattr);
2953  }
2954  }
2955  cpoints->Release();
2956  }
2957 }
2958 
2960 {
2961  if (!cacheKey.isEmpty()) {
2962  d->metaobj = mo_cache.value(cacheKey);
2963  if (d->metaobj) {
2964  d->cachedMetaObject = true;
2965 
2966  IConnectionPointContainer *cpoints = 0;
2967  d->ptr->QueryInterface(IID_IConnectionPointContainer, (void**)&cpoints);
2968  if (cpoints) {
2970  while (it != d->metaobj->connectionInterfaces.end()) {
2971  QUuid iid = *it;
2972  ++it;
2973 
2974  IConnectionPoint *cpoint = 0;
2975  cpoints->FindConnectionPoint(iid, &cpoint);
2976  if (cpoint) {
2977  QAxEventSink *sink = new QAxEventSink(that);
2978  sink->advise(cpoint, iid);
2979  d->eventSink.insert(iid, sink);
2980  sink->sigs = d->metaobj->sigs.value(iid);
2981  sink->props = d->metaobj->props.value(iid);
2982  sink->propsigs = d->metaobj->propsigs.value(iid);
2983  cpoint->Release();
2984  }
2985  }
2986  cpoints->Release();
2987  }
2988 
2989  return d->metaobj;
2990  }
2991  }
2992  return 0;
2993 }
2994 
2996 {
2997  if (that) {
2998  readClassInfo();
2999  if (typelib) {
3000  BSTR bstr;
3001  typelib->GetDocumentation(-1, &bstr, 0, 0, 0);
3003  SysFreeString(bstr);
3004  }
3005  if (d->tryCache && tryCache())
3006  return d->metaobj;
3007  readEnumInfo();
3009  readEventInfo();
3010  }
3011 
3013 
3014 #ifndef QAX_NO_CLASSINFO
3015  if (!debugInfo.isEmpty() && d->useClassInfo)
3016  addClassInfo("debugInfo", debugInfo);
3017 #endif
3018 
3019  QAxMetaObject *metaobj = new QAxMetaObject;
3020 
3021  // revision + classname + table + zero terminator
3022  uint int_data_size = 1+1+2+2+2+2+1;
3023 
3024  int_data_size += classinfo_list.count() * 2;
3025  int_data_size += signal_list.count() * 5;
3026  int_data_size += slot_list.count() * 5;
3027  int_data_size += property_list.count() * 3;
3028  int_data_size += enum_list.count() * 4;
3029  for (QMap<QByteArray, QList<QPair<QByteArray, int> > >::ConstIterator it = enum_list.begin();
3030  it != enum_list.end(); ++it) {
3031  int_data_size += (*it).count() * 2;
3032  }
3033 
3034  uint *int_data = new uint[int_data_size];
3035  int_data[0] = 1; // revision number
3036  int_data[1] = 0; // classname index
3037  int_data[2] = classinfo_list.count(); // num_classinfo
3038  int_data[3] = 10; // idx_classinfo
3039  int_data[4] = signal_list.count() + slot_list.count(); // num_methods
3040  int_data[5] = int_data[3] + int_data[2] * 2; // idx_signals
3041  int_data[6] = property_list.count(); // num_properties
3042  int_data[7] = int_data[5] + int_data[4] * 5; // idx_properties
3043  int_data[8] = enum_list.count(); // num_enums
3044  int_data[9] = int_data[7] + int_data[6] * 3; // idx_enums
3045  int_data[int_data_size - 1] = 0; // eod;
3046 
3047  char null('\0');
3048  // data + zero-terminator
3049  QByteArray stringdata = that ? QByteArray(that->className()) : className;
3050  stringdata += null;
3051  stringdata.reserve(8192);
3052 
3053  uint offset = int_data[3]; //idx_classinfo
3054 
3055  // each class info in form key\0value\0
3057  QByteArray key(it.key());
3058  QByteArray value(it.value());
3059  int_data[offset++] = stringdata.length();
3060  stringdata += key;
3061  stringdata += null;
3062  int_data[offset++] = stringdata.length();
3063  stringdata += value;
3064  stringdata += null;
3065  }
3066  Q_ASSERT(offset == int_data[5]);
3067 
3068  // each signal in form prototype\0parameters\0type\0tag\0
3071  QByteArray type(it.value().type);
3072  QByteArray parameters(it.value().parameters);
3073  if (!it.value().realPrototype.isEmpty())
3074  metaobj->realPrototype.insert(prototype, it.value().realPrototype);
3075  QByteArray tag;
3076  int flags = it.value().flags;
3077 
3078  int_data[offset++] = stringdata.length();
3079  stringdata += prototype;
3080  stringdata += null;
3081  int_data[offset++] = stringdata.length();
3082  stringdata += parameters;
3083  stringdata += null;
3084  int_data[offset++] = stringdata.length();
3085  stringdata += type;
3086  stringdata += null;
3087  int_data[offset++] = stringdata.length();
3088  stringdata += tag;
3089  stringdata += null;
3090  int_data[offset++] = flags;
3091  }
3092 
3093  // each slot in form prototype\0parameters\0type\0tag\0
3094  for (QMap<QByteArray, Method>::ConstIterator it = slot_list.begin(); it != slot_list.end(); ++it) {
3096  QByteArray type(it.value().type);
3097  QByteArray parameters(it.value().parameters);
3098  if (!it.value().realPrototype.isEmpty())
3099  metaobj->realPrototype.insert(prototype, it.value().realPrototype);
3100  QByteArray tag;
3101  int flags = it.value().flags;
3102 
3103  int_data[offset++] = stringdata.length();
3104  stringdata += prototype;
3105  stringdata += null;
3106  int_data[offset++] = stringdata.length();
3107  stringdata += parameters;
3108  stringdata += null;
3109  int_data[offset++] = stringdata.length();
3110  stringdata += type;
3111  stringdata += null;
3112  int_data[offset++] = stringdata.length();
3113  stringdata += tag;
3114  stringdata += null;
3115  int_data[offset++] = flags;
3116  }
3117  Q_ASSERT(offset == int_data[7]);
3118 
3119  // each property in form name\0type\0
3121  QByteArray name(it.key());
3122  QByteArray type(it.value().type);
3123  QByteArray realType(it.value().realType);
3124  if (!realType.isEmpty() && realType != type)
3125  metaobj->realPrototype.insert(name, realType);
3126  uint flags = it.value().typeId;
3127 
3128  int_data[offset++] = stringdata.length();
3129  stringdata += name;
3130  stringdata += null;
3131  int_data[offset++] = stringdata.length();
3132  stringdata += type;
3133  stringdata += null;
3134  int_data[offset++] = flags;
3135  }
3136  Q_ASSERT(offset == int_data[9]);
3137 
3138  int value_offset = offset + enum_list.count() * 4;
3139  // each enum in form name\0
3140  for (QMap<QByteArray, QList<QPair<QByteArray, int> > >::ConstIterator it = enum_list.begin(); it != enum_list.end(); ++it) {
3141  QByteArray name(it.key());
3142  int flags = 0x0; // 0x1 for flag?
3143  int count = it.value().count();
3144 
3145  int_data[offset++] = stringdata.length();
3146  stringdata += name;
3147  stringdata += null;
3148  int_data[offset++] = flags;
3149  int_data[offset++] = count;
3150  int_data[offset++] = value_offset;
3151  value_offset += count * 2;
3152  }
3153  Q_ASSERT(offset == int_data[9] + enum_list.count() * 4);
3154 
3155  // each enum value in form key\0
3156  for (QMap<QByteArray, QList<QPair<QByteArray, int> > >::ConstIterator it = enum_list.begin(); it != enum_list.end(); ++it) {
3157  for (QList<QPair<QByteArray,int> >::ConstIterator it2 = it.value().begin(); it2 != it.value().end(); ++it2) {
3158  QByteArray key((*it2).first);
3159  int value = (*it2).second;
3160  int_data[offset++] = stringdata.length();
3161  stringdata += key;
3162  stringdata += null;
3163  int_data[offset++] = value;
3164  }
3165  }
3166  Q_ASSERT(offset == int_data_size-1);
3167 
3168  char *string_data = new char[stringdata.length()];
3169  memcpy(string_data, stringdata, stringdata.length());
3170 
3171  // put the metaobject together
3172  metaobj->d.data = int_data;
3173  metaobj->d.extradata = 0;
3174  metaobj->d.stringdata = string_data;
3175  metaobj->d.superdata = parentObject;
3176 
3177  if (d)
3178  d->metaobj = metaobj;
3179 
3180  if (!cacheKey.isEmpty()) {
3181  mo_cache.insert(cacheKey, d->metaobj);
3182  d->cachedMetaObject = true;
3184  QAxEventSink *sink = it.value();
3185  if (sink) {
3186  QUuid ciid = sink->connectionInterface();
3187 
3189  d->metaobj->sigs.insert(ciid, sink->signalMap());
3190  d->metaobj->props.insert(ciid, sink->propertyMap());
3191  d->metaobj->propsigs.insert(ciid, sink->propSignalMap());
3192  }
3193  }
3194  }
3195 
3196  return metaobj;
3197 }
3198 
3199 static const uint qt_meta_data_QAxBase[] = {
3200 
3201  // content:
3202  1, // revision
3203  0, // classname
3204  0, 0, // classinfo
3205  3, 10, // methods
3206  1, 25, // properties
3207  0, 0, // enums/sets
3208 
3209  // signals: signature, parameters, type, tag, flags
3210  24, 9, 8, 8, 0x05,
3211  55, 50, 8, 8, 0x05,
3212  102, 80, 8, 8, 0x05,
3213 
3214  // properties: name, type, flags
3215  149, 141, 0x0a095103,
3216 
3217  0 // eod
3218 };
3219 
3220 static const char qt_meta_stringdata_QAxBase[] = {
3221  "QAxBase\0\0name,argc,argv\0signal(QString,int,void*)\0name\0"
3222  "propertyChanged(QString)\0code,source,desc,help\0"
3223  "exception(int,QString,QString,QString)\0QString\0control\0"
3224 };
3225 
3229 };
3233 };
3234 
3246 {
3247  if (d->metaobj)
3248  return d->metaobj;
3249  const QMetaObject* parentObject = parentMetaObject();
3250 
3251  if (!d->ptr && !d->initialized) {
3252  ((QAxBase*)this)->initialize(&d->ptr);
3253  d->initialized = true;
3254  }
3255 
3256 #ifndef QT_NO_THREAD
3257  // only one thread at a time can generate meta objects
3258  QMutexLocker locker(&cache_mutex);
3259 #endif
3260 
3261  // return the default meta object if not yet initialized
3262  if (!d->ptr || !d->useMetaObject) {
3263  if (qObject()->isWidgetType())
3266  }
3267  MetaObjectGenerator generator((QAxBase*)this, d);
3268  return generator.metaObject(parentObject);
3269 }
3270 
3283 {
3284  if (d->eventSink.count()) // already listening
3285  return;
3286 
3287  IEnumConnectionPoints *epoints = 0;
3288  if (d->ptr && d->useEventSink) {
3289  IConnectionPointContainer *cpoints = 0;
3290  d->ptr->QueryInterface(IID_IConnectionPointContainer, (void**)&cpoints);
3291  if (!cpoints)
3292  return;
3293 
3294  cpoints->EnumConnectionPoints(&epoints);
3295  cpoints->Release();
3296  }
3297 
3298  if (!epoints)
3299  return;
3300 
3301  UINT index;
3302  IDispatch *disp = d->dispatch();
3303  ITypeInfo *typeinfo = 0;
3304  ITypeLib *typelib = 0;
3305  if (disp)
3306  disp->GetTypeInfo(0, LOCALE_USER_DEFAULT, &typeinfo);
3307  if (typeinfo)
3308  typeinfo->GetContainingTypeLib(&typelib, &index);
3309 
3310  if (!typelib) {
3311  epoints->Release();
3312  return;
3313  }
3314 
3315  MetaObjectGenerator generator(this, d);
3316  bool haveEnumInfo = false;
3317 
3318  ULONG c = 1;
3319  IConnectionPoint *cpoint = 0;
3320  epoints->Reset();
3321  do {
3322  if (cpoint) cpoint->Release();
3323  cpoint = 0;
3324  epoints->Next(c, &cpoint, &c);
3325  if (!c || !cpoint)
3326  break;
3327 
3328  IID conniid;
3329  cpoint->GetConnectionInterface(&conniid);
3330  // workaround for typelibrary bug of Word.Application
3331  QString connuuid(QUuid(conniid).toString());
3332  if (d->eventSink.contains(connuuid))
3333  break;
3334 
3335  // Get ITypeInfo for source-interface, and skip if not supporting IDispatch
3336  ITypeInfo *eventinfo = 0;
3337  typelib->GetTypeInfoOfGuid(conniid, &eventinfo);
3338  if (eventinfo) {
3339  TYPEATTR *eventAttr;
3340  eventinfo->GetTypeAttr(&eventAttr);
3341  if (!eventAttr) {
3342  eventinfo->Release();
3343  break;
3344  }
3345 
3346  TYPEKIND eventKind = eventAttr->typekind;
3347  eventinfo->ReleaseTypeAttr(eventAttr);
3348  if (eventKind != TKIND_DISPATCH) {
3349  eventinfo->Release();
3350  break;
3351  }
3352  }
3353 
3354  // always into the cache to avoid recoursion
3355  QAxEventSink *eventSink = eventinfo ? new QAxEventSink(this) : 0;
3356  d->eventSink.insert(connuuid, eventSink);
3357 
3358  if (!eventinfo)
3359  continue;
3360 
3361  // have to get type info to support signals with enum parameters
3362  if (!haveEnumInfo) {
3363  bool wasTryCache = d->tryCache;
3364  d->tryCache = true;
3365  generator.readClassInfo();
3366  generator.readEnumInfo();
3367  d->tryCache = wasTryCache;
3368  haveEnumInfo = true;
3369  }
3370  generator.readEventInterface(eventinfo, cpoint);
3371  eventSink->advise(cpoint, conniid);
3372 
3373  eventinfo->Release();
3374  } while (c);
3375  if (cpoint) cpoint->Release();
3376  epoints->Release();
3377 
3378  typelib->Release();
3379 
3380  // make sure we don't try again
3381  if (!d->eventSink.count())
3382  d->eventSink.insert(QString(), 0);
3383 }
3384 
3396 static bool checkHRESULT(HRESULT hres, EXCEPINFO *exc, QAxBase *that, const QString &name, uint argerr)
3397 {
3398  switch(hres) {
3399  case S_OK:
3400  return true;
3401  case DISP_E_BADPARAMCOUNT:
3402  qWarning("QAxBase: Error calling IDispatch member %s: Bad parameter count", name.toLatin1().data());
3403  return false;
3404  case DISP_E_BADVARTYPE:
3405  qWarning("QAxBase: Error calling IDispatch member %s: Bad variant type", name.toLatin1().data());
3406  return false;
3407  case DISP_E_EXCEPTION:
3408  {
3409  bool printWarning = true;
3410  unsigned short code = -1;
3411  QString source, desc, help;
3412  const QMetaObject *mo = that->metaObject();
3413  int exceptionSignal = mo->indexOfSignal("exception(int,QString,QString,QString)");
3414  if (exceptionSignal >= 0) {
3415  if (exc->pfnDeferredFillIn)
3416  exc->pfnDeferredFillIn(exc);
3417 
3418  code = exc->wCode ? exc->wCode : exc->scode;
3419  source = QString::fromWCharArray(exc->bstrSource);
3420  desc = QString::fromWCharArray(exc->bstrDescription);
3421  help = QString::fromWCharArray(exc->bstrHelpFile);
3422  uint helpContext = exc->dwHelpContext;
3423 
3424  if (helpContext && !help.isEmpty())
3425  help += QString::fromLatin1(" [%1]").arg(helpContext);
3426 
3427  if (QAxEventSink::signalHasReceivers(that->qObject(), "exception(int,QString,QString,QString)")) {
3428  void *argv[] = {0, &code, &source, &desc, &help};
3429  that->qt_metacall(QMetaObject::InvokeMetaMethod, exceptionSignal, argv);
3430  printWarning = false;
3431  }
3432  }
3433  if (printWarning) {
3434  qWarning("QAxBase: Error calling IDispatch member %s: Exception thrown by server", name.toLatin1().data());
3435  qWarning(" Code : %d", code);
3436  qWarning(" Source : %s", source.toLatin1().data());
3437  qWarning(" Description: %s", desc.toLatin1().data());
3438  qWarning(" Help : %s", help.toLatin1().data());
3439  qWarning(" Connect to the exception(int,QString,QString,QString) signal to catch this exception");
3440  }
3441  }
3442  return false;
3443  case DISP_E_MEMBERNOTFOUND:
3444  qWarning("QAxBase: Error calling IDispatch member %s: Member not found", name.toLatin1().data());
3445  return false;
3446  case DISP_E_NONAMEDARGS:
3447  qWarning("QAxBase: Error calling IDispatch member %s: No named arguments", name.toLatin1().data());
3448  return false;
3449  case DISP_E_OVERFLOW:
3450  qWarning("QAxBase: Error calling IDispatch member %s: Overflow", name.toLatin1().data());
3451  return false;
3452  case DISP_E_PARAMNOTFOUND:
3453  qWarning("QAxBase: Error calling IDispatch member %s: Parameter %d not found", name.toLatin1().data(), argerr);
3454  return false;
3455  case DISP_E_TYPEMISMATCH:
3456  qWarning("QAxBase: Error calling IDispatch member %s: Type mismatch in parameter %d", name.toLatin1().data(), argerr);
3457  return false;
3458  case DISP_E_UNKNOWNINTERFACE:
3459  qWarning("QAxBase: Error calling IDispatch member %s: Unknown interface", name.toLatin1().data());
3460  return false;
3461  case DISP_E_UNKNOWNLCID:
3462  qWarning("QAxBase: Error calling IDispatch member %s: Unknown locale ID", name.toLatin1().data());
3463  return false;
3464  case DISP_E_PARAMNOTOPTIONAL:
3465  qWarning("QAxBase: Error calling IDispatch member %s: Non-optional parameter missing", name.toLatin1().data());
3466  return false;
3467  default:
3468  qWarning("QAxBase: Error calling IDispatch member %s: Unknown error", name.toLatin1().data());
3469  return false;
3470  }
3471 }
3472 
3477 {
3478  const QMetaObject *mo = metaObject();
3479  const QMetaProperty prop = mo->property(index + mo->propertyOffset());
3480  QByteArray propname = prop.name();
3481 
3482  // hardcoded control property
3483  if (propname == "control") {
3484  switch(call) {
3486  *(QString*)*v = control();
3487  break;
3489  setControl(*(QString*)*v);
3490  break;
3492  clear();
3493  break;
3494  default:
3495  break;
3496  }
3497  return index - mo->propertyCount();
3498  }
3499 
3500  // get the IDispatch
3501  if (!d->ptr || !prop.isValid())
3502  return index;
3503  IDispatch *disp = d->dispatch();
3504  if (!disp)
3505  return index;
3506 
3507  DISPID dispid = d->metaObject()->dispIDofName(propname, disp);
3508  if (dispid == DISPID_UNKNOWN)
3509  return index;
3510 
3511  Q_ASSERT(d->metaobj);
3512  // property found, so everthing that goes wrong now should not bother the caller
3513  index -= mo->propertyCount();
3514 
3515  VARIANTARG arg;
3516  VariantInit(&arg);
3517  DISPPARAMS params;
3518  EXCEPINFO excepinfo;
3519  memset(&excepinfo, 0, sizeof(excepinfo));
3520  UINT argerr = 0;
3521  HRESULT hres = E_FAIL;
3522 
3523  QByteArray proptype(prop.typeName());
3524  switch (call) {
3526  {
3527  params.cArgs = 0;
3528  params.cNamedArgs = 0;
3529  params.rgdispidNamedArgs = 0;
3530  params.rgvarg = 0;
3531 
3532  hres = disp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &params, &arg, &excepinfo, 0);
3533 
3534  // map result VARIANTARG to void*
3536  if (!prop.isEnumType())
3537  type = prop.type();
3538  QVariantToVoidStar(VARIANTToQVariant(arg, proptype, type), *v, proptype, type);
3539  if ((arg.vt != VT_DISPATCH && arg.vt != VT_UNKNOWN) || type == QVariant::Pixmap || type == QVariant::Font)
3540  clearVARIANT(&arg);
3541  }
3542  break;
3543 
3545  {
3546  QVariant::Type t = (QVariant::Type)prop.type();
3547 
3548  DISPID dispidNamed = DISPID_PROPERTYPUT;
3549  params.cArgs = 1;
3550  params.cNamedArgs = 1;
3551  params.rgdispidNamedArgs = &dispidNamed;
3552  params.rgvarg = &arg;
3553 
3554  arg.vt = VT_ERROR;
3555  arg.scode = DISP_E_TYPEMISMATCH;
3556 
3557  // map void* to VARIANTARG via QVariant
3558  QVariant qvar;
3559  if (prop.isEnumType()) {
3560  qvar = *(int*)v[0];
3561  proptype = 0;
3562  } else {
3563  if (t == QVariant::LastType) {
3564  qvar = *(QVariant*)v[0];
3565  proptype = 0;
3566  } else if (t == QVariant::UserType) {
3567  qvar = QVariant(qRegisterMetaType<void*>(prop.typeName()), (void**)v[0]);
3568 // qvar.setValue(*(void**)v[0], prop.typeName());
3569  } else {
3570  proptype = d->metaObject()->propertyType(propname);
3571  qvar = QVariant(t, v[0]);
3572  }
3573  }
3574 
3575  QVariantToVARIANT(qvar, arg, proptype);
3576  if (arg.vt == VT_EMPTY || arg.vt == VT_ERROR) {
3577  qWarning("QAxBase::setProperty: Unhandled property type %s", prop.typeName());
3578  break;
3579  }
3580  }
3581  hres = disp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &params, 0, &excepinfo, &argerr);
3582  clearVARIANT(&arg);
3583  break;
3584 
3585  default:
3586  break;
3587  }
3588 
3589  checkHRESULT(hres, &excepinfo, this, QLatin1String(propname), argerr);
3590  return index;
3591 }
3592 
3594 {
3596  Q_UNUSED(call);
3597 
3598  // get the IDispatch
3599  IDispatch *disp = d->dispatch();
3600  if (!disp)
3601  return index;
3602 
3603  const QMetaObject *mo = metaObject();
3604  // get the slot information
3605  const QMetaMethod slot = mo->method(index + mo->methodOffset());
3607 
3608  QByteArray signature(slot.signature());
3609  QByteArray slotname(signature);
3610  slotname.truncate(slotname.indexOf('('));
3611 
3612  // Get the Dispatch ID of the method to be called
3613  bool isProperty = false;
3614  DISPID dispid = d->metaObject()->dispIDofName(slotname, disp);
3615 
3616  Q_ASSERT(d->metaobj);
3617 
3618  if (dispid == DISPID_UNKNOWN && slotname.toLower().startsWith("set")) {
3619  // see if we are calling a property set function as a slot
3620  slotname = slotname.right(slotname.length() - 3);
3621  dispid = d->metaobj->dispIDofName(slotname, disp);
3622  isProperty = true;
3623  }
3624  if (dispid == DISPID_UNKNOWN)
3625  return index;
3626 
3627  // slot found, so everthing that goes wrong now should not bother the caller
3628  index -= mo->methodCount();
3629 
3630  // setup the parameters
3631  DISPPARAMS params;
3632  DISPID dispidNamed = DISPID_PROPERTYPUT;
3633  params.cArgs = d->metaobj->numParameter(signature);
3634  params.cNamedArgs = isProperty ? 1 : 0;
3635  params.rgdispidNamedArgs = isProperty ? &dispidNamed : 0;
3636  params.rgvarg = 0;
3637  VARIANTARG static_rgvarg[QAX_NUM_PARAMS];
3638  if (params.cArgs) {
3639  if (params.cArgs <= QAX_NUM_PARAMS)
3640  params.rgvarg = static_rgvarg;
3641  else
3642  params.rgvarg = new VARIANTARG[params.cArgs];
3643  }
3644 
3645  int p;
3646  for (p = 0; p < (int)params.cArgs; ++p) {
3647  bool out;
3648  QByteArray type = d->metaobj->paramType(signature, p, &out);
3650  QVariant qvar;
3651  if (vt != QVariant::UserType)
3652  qvar = QVariant(vt, v[p + 1]);
3653 
3654  if (!qvar.isValid()) {
3655  if (type == "IDispatch*")
3656  qvar.setValue(*(IDispatch**)v[p+1]);
3657  else if (type == "IUnknown*")
3658  qvar.setValue(*(IUnknown**)v[p+1]);
3659  else if (type == "QVariant")
3660  qvar = *(QVariant*)v[p + 1];
3661  else if (mo->indexOfEnumerator(type) != -1)
3662  qvar = *(int*)v[p + 1];
3663  else
3664  qvar = QVariant(QMetaType::type(type), v[p + 1]);
3665  }
3666 
3667  QVariantToVARIANT(qvar, params.rgvarg[params.cArgs - p - 1], type, out);
3668  }
3669 
3670  // call the method
3671  VARIANT ret;
3672  VariantInit(&ret);
3673  UINT argerr = 0;
3674  HRESULT hres = E_FAIL;
3675  EXCEPINFO excepinfo;
3676  memset(&excepinfo, 0, sizeof(excepinfo));
3677 
3678  WORD wFlags = isProperty ? DISPATCH_PROPERTYPUT : DISPATCH_METHOD | DISPATCH_PROPERTYGET;
3679  hres = disp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, wFlags, &params, &ret, &excepinfo, &argerr);
3680 
3681  // get return value
3682  if (hres == S_OK && ret.vt != VT_EMPTY)
3683  QVariantToVoidStar(VARIANTToQVariant(ret, slot.typeName()), v[0], slot.typeName());
3684 
3685  // update out parameters
3686  for (p = 0; p < (int)params.cArgs; ++p) {
3687  bool out;
3688  QByteArray ptype = d->metaobj->paramType(signature, p, &out);
3689  if (out)
3690  QVariantToVoidStar(VARIANTToQVariant(params.rgvarg[params.cArgs - p - 1], ptype), v[p+1], ptype);
3691  }
3692  // clean up
3693  for (p = 0; p < (int)params.cArgs; ++p)
3694  clearVARIANT(params.rgvarg+p);
3695  if (params.rgvarg != static_rgvarg)
3696  delete [] params.rgvarg;
3697 
3698  checkHRESULT(hres, &excepinfo, this, QString::fromLatin1(slotname), params.cArgs-argerr-1);
3699  return index;
3700 }
3701 
3705 int QAxBase::qt_metacall(QMetaObject::Call call, int id, void **v)
3706 {
3707  const QMetaObject *mo = metaObject();
3708  if (isNull() && mo->property(id + mo->propertyOffset()).name() != QByteArray("control")) {
3709  qWarning("QAxBase::qt_metacall: Object is not initialized, or initialization failed");
3710  return id;
3711  }
3712 
3713  switch(call) {
3715  switch (mo->method(id + mo->methodOffset()).methodType()) {
3716  case QMetaMethod::Signal:
3717  QMetaObject::activate(qObject(), mo, id, v);
3718  id -= mo->methodCount();
3719  break;
3720  case QMetaMethod::Method:
3721  case QMetaMethod::Slot:
3722  id = internalInvoke(call, id, v);
3723  break;
3724  default:
3725  break;
3726  }
3727  break;
3731  id = internalProperty(call, id, v);
3732  break;
3738  id -= mo->propertyCount();
3739  break;
3740  default:
3741  break;
3742  }
3743  Q_ASSERT(id < 0);
3744  return id;
3745 }
3746 
3747 #ifdef QT_CHECK_STATE
3748 static void qax_noSuchFunction(int disptype, const QByteArray &name, const QByteArray &function, const QAxBase *that)
3749 {
3750  const QMetaObject *metaObject = that->metaObject();
3751  const char *coclass = metaObject->classInfo(metaObject->indexOfClassInfo("CoClass")).value();
3752 
3753  if (disptype == DISPATCH_METHOD) {
3754  qWarning("QAxBase::dynamicCallHelper: %s: No such method in %s [%s]", name.data(), that->control().toLatin1().data(), coclass ? coclass: "unknown");
3755  qWarning("\tCandidates are:");
3756  for (int i = 0; i < metaObject->methodCount(); ++i) {
3757  const QMetaMethod slot(metaObject->method(i));
3758  if (slot.methodType() != QMetaMethod::Slot)
3759  continue;
3760  QByteArray signature = slot.signature();
3761  if (signature.toLower().startsWith(function.toLower()))
3762  qWarning("\t\t%s", signature.data());
3763  }
3764  } else {
3765  qWarning("QAxBase::dynamicCallHelper: %s: No such property in %s [%s]", name.data(), that->control().toLatin1().data(), coclass ? coclass: "unknown");
3766  if (!function.isEmpty()) {
3767  qWarning("\tCandidates are:");
3768  char f0 = function.toLower().at(0);
3769  for (int i = metaObject->propertyOffset(); i < metaObject->propertyCount(); ++i) {
3770  QByteArray signature(metaObject->property(i).name());
3771  if (!signature.isEmpty() && signature.toLower().at(0) == f0)
3772  qWarning("\t\t%s", signature.data());
3773  }
3774  }
3775  }
3776 }
3777 #endif
3778 
3784 bool QAxBase::dynamicCallHelper(const char *name, void *inout, QList<QVariant> &vars, QByteArray &type)
3785 {
3786  if (isNull()) {
3787  qWarning("QAxBase::dynamicCallHelper: Object is not initialized, or initialization failed");
3788  return false;
3789  }
3790 
3791  IDispatch *disp = d->dispatch();
3792  if (!disp) {
3793  qWarning("QAxBase::dynamicCallHelper: Object does not support automation");
3794  return false;
3795  }
3796 
3797  const QMetaObject *mo = metaObject();
3798  d->metaObject();
3799  Q_ASSERT(d->metaobj);
3800 
3801  int varc = vars.count();
3802 
3803  QByteArray normFunction = QMetaObject::normalizedSignature(name);
3804  QByteArray function(normFunction);
3805  VARIANT staticarg[QAX_NUM_PARAMS];
3806  VARIANT *arg = 0;
3807  VARIANTARG *res = (VARIANTARG*)inout;
3808 
3809  unsigned short disptype;
3810 
3811  int id = -1;
3812  bool parse = false;
3813 
3814  if (function.contains('(')) {
3815  disptype = DISPATCH_METHOD | DISPATCH_PROPERTYGET;
3816  if (d->useMetaObject)
3817  id = mo->indexOfSlot(function);
3818  if (id >= 0) {
3819  const QMetaMethod slot = mo->method(id);
3821  function = slot.signature();
3822  type = slot.typeName();
3823  }
3824  function.truncate(function.indexOf('('));
3825  parse = !varc && normFunction.length() > function.length() + 2;
3826  if (parse) {
3827  QString args = QLatin1String(normFunction);
3828  args = args.mid(function.length() + 1);
3829  // parse argument string int list of arguments
3830  QString curArg;
3831  const QChar *c = args.unicode();
3832  int index = 0;
3833  bool inString = false;
3834  bool inEscape = false;
3835  while (index < (int)args.length()) {
3836  QChar cc = *c;
3837  ++c;
3838  ++index;
3839  switch(cc.toLatin1()) {
3840  case 'n':
3841  if (inEscape)
3842  cc = QLatin1Char('\n');
3843  break;
3844  case 'r':
3845  if (inEscape)
3846  cc = QLatin1Char('\r');
3847  break;
3848  case 't':
3849  if (inEscape)
3850  cc = QLatin1Char('\t');
3851  break;
3852  case '\\':
3853  if (!inEscape && inString) {
3854  inEscape = true;
3855  continue;
3856  }
3857  break;
3858  case '"':
3859  if (!inEscape) {
3860  inString = !inString;
3861  curArg += cc;
3862  continue;
3863  }
3864  break;
3865  case ' ':
3866  if (!inString && curArg.isEmpty())
3867  continue;
3868  break;
3869  case ',':
3870  case ')':
3871  if (inString)
3872  break;
3873  curArg = curArg.trimmed();
3874  if (curArg.at(0) == QLatin1Char('\"') && curArg.at(curArg.length()-1) == QLatin1Char('\"')) {
3875  vars << curArg.mid(1, curArg.length() - 2);
3876  } else {
3877  bool isNumber = false;
3878  bool isDouble = false;
3879  int number = curArg.toInt(&isNumber);
3880  double dbl = curArg.toDouble(&isDouble);
3881  if (isNumber) {
3882  vars << number;
3883  } else if (isDouble) {
3884  vars << dbl;
3885  } else {
3886  bool isEnum = false;
3887  for (int enumIndex = 0; enumIndex < mo->enumeratorCount(); ++enumIndex) {
3888  QMetaEnum metaEnum =mo->enumerator(enumIndex);
3889  int value = metaEnum.keyToValue(curArg.toLatin1());
3890  if (value != -1 && !QByteArray(metaEnum.valueToKey(value)).isEmpty()) {
3891  vars << value;
3892  isEnum = true;
3893  break;
3894  }
3895  }
3896  if (!isEnum)
3897  vars << curArg;
3898  }
3899  }
3900  curArg.clear();
3901  continue;
3902  default:
3903  break;
3904  }
3905  inEscape = false;
3906  curArg += cc;
3907  }
3908 
3909  varc = vars.count();
3910  }
3911  } else {
3912  if (d->useMetaObject)
3913  id = mo->indexOfProperty(normFunction);
3914 
3915  if (id >= 0) {
3916  const QMetaProperty prop =mo->property(id);
3917  type = prop.typeName();
3918  }
3919  if (varc == 1) {
3920  res = 0;
3921  disptype = DISPATCH_PROPERTYPUT;
3922  } else {
3923  disptype = DISPATCH_PROPERTYGET;
3924  }
3925  }
3926  if (varc) {
3927  varc = qMin(varc, d->metaobj->numParameter(normFunction));
3928  arg = varc <= QAX_NUM_PARAMS ? staticarg : new VARIANT[varc];
3929  for (int i = 0; i < varc; ++i) {
3930  QVariant var(vars.at(i));
3931  VariantInit(arg + (varc - i - 1));
3932  bool out = false;
3934  if (disptype == DISPATCH_PROPERTYPUT)
3935  paramType = type;
3936  else if (parse || disptype == DISPATCH_PROPERTYGET)
3937  paramType = 0;
3938  else
3939  paramType = d->metaobj->paramType(normFunction, i, &out);
3940 
3941  if ((!parse && d->useMetaObject && var.type() == QVariant::String) || var.type() == QVariant::ByteArray) {
3942  int enumIndex =mo->indexOfEnumerator(paramType);
3943  if (enumIndex != -1) {
3944  QMetaEnum metaEnum =mo->enumerator(enumIndex);
3945  QVariantToVARIANT(metaEnum.keyToValue(var.toByteArray()), arg[varc - i - 1], "int", out);
3946  }
3947  }
3948 
3949  if (arg[varc - i - 1].vt == VT_EMPTY)
3950  QVariantToVARIANT(var, arg[varc - i - 1], paramType, out);
3951  }
3952  }
3953 
3954  DISPID dispid = d->metaobj->dispIDofName(function, disp);
3955  if (dispid == DISPID_UNKNOWN && function.toLower().startsWith("set")) {
3956  function = function.mid(3);
3957  dispid = d->metaobj->dispIDofName(function, disp);
3958  disptype = DISPATCH_PROPERTYPUT;
3959  }
3960 
3961  if (dispid == DISPID_UNKNOWN) {
3962 #ifdef QT_CHECK_STATE
3963  qax_noSuchFunction(disptype, normFunction, function, this);
3964 #endif
3965  return false;
3966  }
3967 
3968  DISPPARAMS params;
3969  DISPID dispidNamed = DISPID_PROPERTYPUT;
3970 
3971  params.cArgs = varc;
3972  params.cNamedArgs = (disptype == DISPATCH_PROPERTYPUT) ? 1 : 0;
3973  params.rgdispidNamedArgs = (disptype == DISPATCH_PROPERTYPUT) ? &dispidNamed : 0;
3974  params.rgvarg = arg;
3975  EXCEPINFO excepinfo;
3976  memset(&excepinfo, 0, sizeof(excepinfo));
3977  UINT argerr = 0;
3978 
3979  HRESULT hres = disp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, disptype, &params, res, &excepinfo, &argerr);
3980 
3981  if (disptype == (DISPATCH_METHOD|DISPATCH_PROPERTYGET) && hres == S_OK && varc) {
3982  for (int i = 0; i < varc; ++i)
3983  if (arg[varc-i-1].vt & VT_BYREF) // update out-parameters
3984  vars[i] = VARIANTToQVariant(arg[varc-i-1], vars.at(i).typeName());
3985  }
3986 
3987  // clean up
3988  for (int i = 0; i < varc; ++i)
3989  clearVARIANT(params.rgvarg+i);
3990  if (arg && arg != staticarg)
3991  delete[] arg;
3992 
3993  return checkHRESULT(hres, &excepinfo, this, QLatin1String(function), varc-argerr-1);
3994 }
3995 
3996 
4046 QVariant QAxBase::dynamicCall(const char *function,
4047  const QVariant &var1,
4048  const QVariant &var2,
4049  const QVariant &var3,
4050  const QVariant &var4,
4051  const QVariant &var5,
4052  const QVariant &var6,
4053  const QVariant &var7,
4054  const QVariant &var8)
4055 {
4056  QList<QVariant> vars;
4057  QVariant var = var1;
4058  int argc = 1;
4059  while(var.isValid()) {
4060  vars << var;
4061  switch(++argc) {
4062  case 2: var = var2; break;
4063  case 3: var = var3; break;
4064  case 4: var = var4; break;
4065  case 5: var = var5; break;
4066  case 6: var = var6; break;
4067  case 7: var = var7; break;
4068  case 8: var = var8; break;
4069  default:var = QVariant(); break;
4070  }
4071  }
4072 
4073  return dynamicCall(function, vars);
4074 }
4075 
4091 QVariant QAxBase::dynamicCall(const char *function, QList<QVariant> &vars)
4092 {
4093  VARIANTARG res;
4094  VariantInit(&res);
4095 
4096  QByteArray rettype;
4097  if (!dynamicCallHelper(function, &res, vars, rettype))
4098  return QVariant();
4099 
4100  QVariant qvar = VARIANTToQVariant(res, rettype);
4101  if ((res.vt != VT_DISPATCH && res.vt != VT_UNKNOWN) || qvar.type() == QVariant::Pixmap || qvar.type() == QVariant::Font)
4102  clearVARIANT(&res);
4103 
4104  return qvar;
4105 }
4106 
4131  const QVariant &var1,
4132  const QVariant &var2,
4133  const QVariant &var3,
4134  const QVariant &var4,
4135  const QVariant &var5,
4136  const QVariant &var6,
4137  const QVariant &var7,
4138  const QVariant &var8)
4139 {
4140  QList<QVariant> vars;
4141  QVariant var = var1;
4142  int argc = 1;
4143  while(var.isValid()) {
4144  vars << var;
4145  switch(++argc) {
4146  case 2: var = var2; break;
4147  case 3: var = var3; break;
4148  case 4: var = var4; break;
4149  case 5: var = var5; break;
4150  case 6: var = var6; break;
4151  case 7: var = var7; break;
4152  case 8: var = var8; break;
4153  default:var = QVariant(); break;
4154  }
4155  }
4156 
4157  return querySubObject(name, vars);
4158 }
4159 
4170 {
4171  QAxObject *object = 0;
4172  VARIANTARG res;
4173  VariantInit(&res);
4174 
4175  QByteArray rettype;
4176  if (!dynamicCallHelper(name, &res, vars, rettype))
4177  return 0;
4178 
4179  switch (res.vt) {
4180  case VT_DISPATCH:
4181  if (res.pdispVal) {
4182  if (rettype.isEmpty() || rettype == "IDispatch*" || rettype == "QVariant") {
4183  object = new QAxObject(res.pdispVal, qObject());
4184  } else if (QMetaType::type(rettype)) {
4185  QVariant qvar = VARIANTToQVariant(res, rettype, 0);
4186  object = *(QAxObject**)qvar.constData();
4187 // qVariantGet(qvar, object, rettype);
4188  res.pdispVal->AddRef();
4189  }
4190  if (object)
4191  ((QAxBase*)object)->d->tryCache = true;
4192  }
4193  break;
4194  case VT_UNKNOWN:
4195  if (res.punkVal) {
4196  if (rettype.isEmpty() || rettype == "IUnknown*") {
4197  object = new QAxObject(res.punkVal, qObject());
4198  } else if (QMetaType::type(rettype)) {
4199  QVariant qvar = VARIANTToQVariant(res, rettype, 0);
4200  object = *(QAxObject**)qvar.constData();
4201 // qVariantGet(qvar, object, rettype);
4202  res.punkVal->AddRef();
4203  }
4204  if (object)
4205  ((QAxBase*)object)->d->tryCache = true;
4206  }
4207  break;
4208  case VT_EMPTY:
4209 #ifdef QT_CHECK_STATE
4210  {
4211  const char *coclass = metaObject()->classInfo(metaObject()->indexOfClassInfo("CoClass")).value();
4212  qWarning("QAxBase::querySubObject: %s: Error calling function or property in %s (%s)"
4213  , name, control().toLatin1().data(), coclass ? coclass: "unknown");
4214  }
4215 #endif
4216  break;
4217  default:
4218 #ifdef QT_CHECK_STATE
4219  {
4220  const char *coclass = metaObject()->classInfo(metaObject()->indexOfClassInfo("CoClass")).value();
4221  qWarning("QAxBase::querySubObject: %s: Method or property is not of interface type in %s (%s)"
4222  , name, control().toLatin1().data(), coclass ? coclass: "unknown");
4223  }
4224 #endif
4225  break;
4226  }
4227 
4228  clearVARIANT(&res);
4229  return object;
4230 }
4231 
4232 class QtPropertyBag : public IPropertyBag
4233 {
4234 public:
4235  QtPropertyBag() :ref(0) {}
4236  virtual ~QtPropertyBag() {}
4237 
4238  HRESULT __stdcall QueryInterface(REFIID iid, LPVOID *iface)
4239  {
4240  *iface = 0;
4241  if (iid == IID_IUnknown)
4242  *iface = this;
4243  else if (iid == IID_IPropertyBag)
4244  *iface = this;
4245  else
4246  return E_NOINTERFACE;
4247 
4248  AddRef();
4249  return S_OK;
4250  }
4251  unsigned long __stdcall AddRef()
4252  {
4253  return InterlockedIncrement(&ref);
4254  }
4255  unsigned long __stdcall Release()
4256  {
4257  LONG refCount = InterlockedDecrement(&ref);
4258  if (!refCount)
4259  delete this;
4260 
4261  return refCount;
4262  }
4263 
4264  HRESULT __stdcall Read(LPCOLESTR name, VARIANT *var, IErrorLog *)
4265  {
4266  if (!var)
4267  return E_POINTER;
4268 
4269  QString property = QString::fromWCharArray(name);
4270  QVariant qvar = map.value(property);
4271  QVariantToVARIANT(qvar, *var);
4272  return S_OK;
4273  }
4274  HRESULT __stdcall Write(LPCOLESTR name, VARIANT *var)
4275  {
4276  if (!var)
4277  return E_POINTER;
4278  QString property = QString::fromWCharArray(name);
4279  QVariant qvar = VARIANTToQVariant(*var, 0);
4280  map[property] = qvar;
4281 
4282  return S_OK;
4283  }
4284 
4286 
4287 private:
4288  LONG ref;
4289 };
4290 
4304 {
4305  PropertyBag result;
4306 
4307  if (!d->ptr && !d->initialized) {
4308  ((QAxBase*)this)->initialize(&d->ptr);
4309  d->initialized = true;
4310  }
4311 
4312  if (isNull())
4313  return result;
4314  IPersistPropertyBag *persist = 0;
4315  d->ptr->QueryInterface(IID_IPersistPropertyBag, (void**)&persist);
4316  if (persist) {
4317  QtPropertyBag *pbag = new QtPropertyBag();
4318  pbag->AddRef();
4319  persist->Save(pbag, false, true);
4320  result = pbag->map;
4321  pbag->Release();
4322  persist->Release();
4323  return result;
4324  } else {
4325  const QMetaObject *mo = metaObject();
4326  for (int p = mo->propertyOffset(); p < mo->propertyCount(); ++p) {
4327  const QMetaProperty property = mo->property(p);
4328  QVariant var = qObject()->property(property.name());
4329  result.insert(QLatin1String(property.name()), var);
4330  }
4331  }
4332  return result;
4333 }
4334 
4348 {
4349  if (!d->ptr && !d->initialized) {
4350  initialize(&d->ptr);
4351  d->initialized = true;
4352  }
4353 
4354  if (isNull())
4355  return;
4356  IPersistPropertyBag *persist = 0;
4357  d->ptr->QueryInterface(IID_IPersistPropertyBag, (void**)&persist);
4358  if (persist) {
4359  QtPropertyBag *pbag = new QtPropertyBag();
4360  pbag->map = bag;
4361  pbag->AddRef();
4362  persist->Load(pbag, 0);
4363  pbag->Release();
4364  persist->Release();
4365  } else {
4366  const QMetaObject *mo = metaObject();
4367  for (int p = mo->propertyOffset(); p < mo->propertyCount(); ++p) {
4368  const QMetaProperty property = mo->property(p);
4369  QVariant var = bag.value(QLatin1String(property.name()));
4370  qObject()->setProperty(property.name(), var);
4371  }
4372  }
4373 }
4374 
4385 bool QAxBase::propertyWritable(const char *prop) const
4386 {
4387  return d->propWritable.value(prop, true);
4388 }
4389 
4401 void QAxBase::setPropertyWritable(const char *prop, bool ok)
4402 {
4403  d->propWritable[prop] = ok;
4404 }
4405 
4412 bool QAxBase::isNull() const
4413 {
4414  return !d->ptr;
4415 }
4416 
4422 {
4423  if (!d->ptr && !d->initialized) {
4424  ((QAxBase*)this)->initialize(&d->ptr);
4425  d->initialized = true;
4426  }
4427 
4428  QVariant qvar;
4429  QByteArray cn(className());
4430  if (cn == "QAxObject" || cn == "QAxWidget" || cn == "QAxBase") {
4431  if (d->dispatch())
4432  qvar.setValue(d->dispatch());
4433  else if (d->ptr)
4434  qvar.setValue(d->ptr);
4435  } else {
4436  cn = cn.mid(cn.lastIndexOf(':') + 1);
4437  QObject *object = qObject();
4438  if (QMetaType::type(cn))
4439  qvar = QVariant(qRegisterMetaType<QObject*>(cn + '*'), &object);
4440 // qvar.setValue(qObject(), cn + '*');
4441  }
4442 
4443  return qvar;
4444 }
4445 
4446 // internal function that creates a QAxObject from an iface
4447 // used by type-conversion code (types.cpp)
4448 void *qax_createObjectWrapper(int metaType, IUnknown *iface)
4449 {
4450  if (!iface)
4451  return 0;
4452 
4453  QAxObject *object = (QAxObject*)QMetaType::construct(metaType, 0);
4454  QAxBasePrivate *d = object->d;
4455 
4456  d->ptr = iface;
4457  d->initialized = true;
4458 
4459  // no release, since no addref
4460 
4461  return object;
4462 }
4463 
4513 #endif //QT_NO_WIN_ACTIVEQT
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
QBool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.h:904
bool hasEnum(const QByteArray &enumname)
Definition: qaxbase.cpp:1722
QStringList verbs() const
Returns the list of verbs that the COM object can execute.
Definition: qaxbase.cpp:1137
static QHash< QString, QAxMetaObject * > mo_cache
Definition: qaxbase.cpp:183
QHash< QByteArray, QList< QByteArray > > memberInfo
Definition: qaxbase.cpp:108
The QMetaObject class contains meta-information about Qt objects.
Definition: qobjectdefs.h:304
HRESULT __stdcall GetIDsOfNames(const _GUID &, wchar_t **, unsigned int, unsigned long, long *)
Definition: qaxbase.cpp:324
IUnknown * ptr
Definition: qaxbase.cpp:600
void chop(int n)
Removes n bytes from the end of the byte array.
bool qax_dispatchEqualsIDispatch
Definition: qaxbase.cpp:1886
void * qax_createObjectWrapper(int metaType, IUnknown *iface)
Definition: qaxbase.cpp:4448
void clearVARIANT(VARIANT *var)
Definition: qaxtypes.cpp:1408
void addProperty(const QByteArray &type, const QByteArray &name, uint flags)
Definition: qaxbase.cpp:1674
HRESULT __stdcall Invoke(DISPID dispIdMember, REFIID riid, LCID, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *, EXCEPINFO *, UINT *)
Definition: qaxbase.cpp:326
bool isNull() const
Returns true if there is no COM object loaded by this wrapper; otherwise return false.
Definition: qaxbase.cpp:4412
QMap< QByteArray, QByteArray > realPrototype
Definition: qaxbase.cpp:109
int type
Definition: qmetatype.cpp:239
QAxBasePrivate * d
Definition: qaxbase.cpp:1728
void truncate(int pos)
Truncates the byte array at index position pos.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Returns the value for setting key.
Definition: qsettings.cpp:3460
virtual ~QtPropertyBag()
Definition: qaxbase.cpp:4236
static mach_timebase_info_data_t info
unsigned char c[8]
Definition: qnumeric_p.h:62
The QMetaEnum class provides meta-data about an enumerator.
Definition: qmetaobject.h:147
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
const void * extradata
Definition: qobjectdefs.h:472
virtual ~QAxBase()
Shuts down the COM object and destroys the QAxBase object.
Definition: qaxbase.cpp:868
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
virtual const QMetaObject * metaObject() const
The metaobject is generated on the fly from the information provided by the IDispatch and ITypeInfo i...
Definition: qaxbase.cpp:3245
const Key key(const T &value) const
Returns the first key with value value.
Definition: qmap.h:844
The QMutex class provides access serialization between threads.
Definition: qmutex.h:60
static QByteArray normalizedSignature(const char *method)
Normalizes the signature of the given method.
void clear()
Removes all items from the hash.
Definition: qhash.h:574
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
Definition: quuid.h:52
QVariant dynamicCall(const char *name, const QVariant &v1=QVariant(), const QVariant &v2=QVariant(), const QVariant &v3=QVariant(), const QVariant &v4=QVariant(), const QVariant &v5=QVariant(), const QVariant &v6=QVariant(), const QVariant &v7=QVariant(), const QVariant &v8=QVariant())
Calls the COM object&#39;s method function, passing the parameters var1, var1, var2, var3, var4, var5, var6, var7 and var8, and returns the value returned by the method, or an invalid QVariant if the method does not return a value or when the function call failed.
Definition: qaxbase.cpp:4046
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
QMap< DISPID, QByteArray > sigs
Definition: qaxbase.cpp:536
#define QAX_NUM_PARAMS
Definition: qaxtypes.h:74
QVariant asVariant() const
Returns a QVariant that wraps the COM object.
Definition: qaxbase.cpp:4421
bool initializeActive(IUnknown **ptr)
Connects to an active instance running on the current machine, and returns the IUnknown interface to ...
Definition: qaxbase.cpp:1321
bool dynamicCallHelper(const char *name, void *out, QList< QVariant > &var, QByteArray &type)
Definition: qaxbase.cpp:3784
void initializeFrom(QAxBase *that)
Used by subclasses generated with dumpcpp to implement cast-operators.
Definition: qaxbase.cpp:902
QString control() const
the name of the COM object wrapped by this QAxBase object.
Definition: qaxbase.cpp:1029
int toInt(bool *ok=0, int base=10) const
Returns the string converted to an int using base base, which is 10 by default and must be between 2 ...
Definition: qstring.cpp:6090
#define it(className, varName)
void readEventInterface(ITypeInfo *eventinfo, IConnectionPoint *cpoint)
Definition: qaxbase.cpp:2772
ITypeInfo * classInfo
Definition: qaxbase.cpp:1732
bool initializeRemote(IUnknown **ptr)
Creates the instance on a remote server, and returns the IUnknown interface to the object in ptr...
Definition: qaxbase.cpp:1390
void readInterfaceInfo()
Definition: qaxbase.cpp:2707
QMap< QUuid, QMap< DISPID, QByteArray > > props
Definition: qaxbase.cpp:105
The QSettings class provides persistent platform-independent application settings.
Definition: qsettings.h:73
void endGroup()
Resets the group to what it was before the corresponding beginGroup() call.
Definition: qsettings.cpp:3089
#define VT_UNHANDLED(x)
Definition: qaxbase.cpp:1975
Data * d
Definition: qbytearray.h:386
QList< QByteArray > qax_qualified_usertypes
Definition: qaxbase.cpp:1887
virtual QObject * qObject() const =0
unsigned long __stdcall AddRef()
Definition: qaxbase.cpp:291
QMetaClassInfo classInfo(int index) const
Returns the meta-data for the item of class information with the given index.
QAxMetaObject * metaobj
Definition: qaxbase.cpp:614
#define at(className, varName)
void internalRelease()
Used by subclasses generated with dumpcpp to balance reference count.
Definition: qaxbase.cpp:888
void disableClassInfo()
Disables the class info generation for this ActiveX container.
Definition: qaxbase.cpp:1083
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 toUpper() const Q_REQUIRED_RESULT
Returns an uppercase copy of the string.
Definition: qstring.cpp:5483
void beginGroup(const QString &prefix)
Appends prefix to the current group.
Definition: qsettings.cpp:3073
void advise(IConnectionPoint *cp, IID iid)
Definition: qaxbase.cpp:240
static void qax_noSuchFunction(int disptype, const QByteArray &name, const QByteArray &function, const QAxBase *that)
Definition: qaxbase.cpp:3748
static void clear(QVariant::Private *d)
Definition: qvariant.cpp:197
iterator begin()
Returns an STL-style iterator pointing to the first item in the list.
Definition: qlist.h:267
HRESULT __stdcall OnChanged(DISPID dispID)
Definition: qaxbase.cpp:461
int count(const Key &key) const
Returns the number of items associated with key key.
Definition: qmap.h:539
QString toString() const
Returns the variant as a QString if the variant has type() String , Bool , ByteArray ...
Definition: qvariant.cpp:2270
void setPropertyBag(const PropertyBag &)
Sets the properties of the COM object to the corresponding values in bag.
Definition: qaxbase.cpp:4347
const char * valueToKey(int value) const
Returns the string that is used as the name of the given enumeration value, or 0 if value is not defi...
MetaObjectGenerator(QAxBase *ax, QAxBasePrivate *dptr)
Definition: qaxbase.cpp:1839
static const QMetaObject staticMetaObject
This variable stores the meta-object for the class.
Definition: qobject.h:128
unsigned long __stdcall Release()
Definition: qaxbase.cpp:295
virtual void setPropertyWritable(const char *, bool)
Sets the property prop to writable if ok is true, otherwise sets prop to be read-only.
Definition: qaxbase.cpp:4401
QByteArray toLower() const
Returns a lowercase copy of the byte array.
static bool checkHRESULT(HRESULT hres, EXCEPINFO *exc, QAxBase *that, const QString &name, uint argerr)
Definition: qaxbase.cpp:3396
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
static bool isNumber(char s)
HRESULT __stdcall Read(LPCOLESTR name, VARIANT *var, IErrorLog *)
Definition: qaxbase.cpp:4264
int numParameter(const QByteArray &prototype)
Definition: qaxbase.cpp:134
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
HRESULT __stdcall GetTypeInfo(UINT, LCID, ITypeInfo **)
Definition: qaxbase.cpp:323
bool isValid() const
Returns true if this property is valid (readable); otherwise returns false.
Definition: qmetaobject.h:213
HRESULT __stdcall OnRequestEdit(DISPID dispID)
Definition: qaxbase.cpp:514
T & value() const
Returns a modifiable reference to the current item&#39;s value.
Definition: qhash.h:348
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.
void addClassInfo(const char *key, const char *value)
Definition: qaxbase.cpp:1510
The QHash class is a template class that provides a hash-table-based dictionary.
Definition: qdatastream.h:66
The QAxObject class provides a QObject that wraps a COM object.
Definition: qaxobject.h:54
const char * stringdata
Definition: qobjectdefs.h:470
void setValue(const T &value)
Stores a copy of value.
Definition: qvariant.h:527
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
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.
bool startsWith(const QByteArray &a) const
Returns true if this byte array starts with byte array ba; otherwise returns false.
bool hasProperty(const QByteArray &name)
Definition: qaxbase.cpp:1706
bool hasSlot(const QByteArray &prototype)
Definition: qaxbase.cpp:1661
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
bool contains(const Key &key) const
Returns true if the hash contains an item with the key; otherwise returns false.
Definition: qhash.h:872
QSettings iidnames
Definition: qaxbase.cpp:1736
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
QByteArray guessTypes(const TYPEDESC &tdesc, ITypeInfo *info, const QByteArray &function)
Definition: qaxbase.cpp:1977
static void * construct(int type, const void *copy=0)
Returns a copy of copy, assuming it is of type type.
Definition: qmetatype.cpp:1042
const T value(const Key &key) const
Returns the value associated with the key.
Definition: qhash.h:606
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
void readVarsInfo(ITypeInfo *typeinfo, ushort nVars)
Definition: qaxbase.cpp:2624
QStringList childGroups() const
Returns a list of all key top-level groups that contain keys that can be read using the QSettings obj...
Definition: qsettings.cpp:3288
iterator Iterator
Qt-style synonym for QList::iterator.
Definition: qlist.h:278
static int mo_cache_ref
Definition: qaxbase.cpp:185
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:753
bool exists() const
Returns true if the file specified by fileName() exists; otherwise returns false. ...
Definition: qfile.cpp:626
bool hasClassInfo(const char *key)
Definition: qaxbase.cpp:1613
QHash< QUuid, QAxEventSink * > eventSink
Definition: qaxbase.cpp:592
ULONG cookie
Definition: qaxbase.cpp:534
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
void * data()
Definition: qvariant.cpp:3077
unsigned long __stdcall Release()
Definition: qaxbase.cpp:4255
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QAxObject * querySubObject(const char *name, const QVariant &v1=QVariant(), const QVariant &v2=QVariant(), const QVariant &v3=QVariant(), const QVariant &v4=QVariant(), const QVariant &v5=QVariant(), const QVariant &v6=QVariant(), const QVariant &v7=QVariant(), const QVariant &v8=QVariant())
Returns a pointer to a QAxObject wrapping the COM object provided by the method or property name...
Definition: qaxbase.cpp:4130
QHash< QByteArray, DISPID > dispIDs
Definition: qaxbase.cpp:112
bool isEnumType() const
Returns true if the property&#39;s type is an enumeration value; otherwise returns false.
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.
static bool isEmpty(const char *str)
virtual const char * className() const =0
QByteArray propertyType(const QByteArray &propertyName)
Definition: qaxbase.cpp:129
void addSlot(const QByteArray &type, const QByteArray &prototype, const QByteArray &parameters, int flags=QMetaMethod::Public)
Definition: qaxbase.cpp:1647
unsigned long __stdcall AddRef()
Definition: qaxbase.cpp:4251
int methodOffset() const
Returns the method offset for this class; i.e.
int internalProperty(QMetaObject::Call, int index, void **v)
Definition: qaxbase.cpp:3476
QString ctrl
Definition: qaxbase.cpp:590
int internalInvoke(QMetaObject::Call, int index, void **v)
Definition: qaxbase.cpp:3593
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
QMap< QUuid, QMap< DISPID, QByteArray > > sigs
Definition: qaxbase.cpp:101
const char * typeName
Definition: qmetatype.cpp:239
bool contains(const T &value) const
Definition: qset.h:91
QString trimmed() const Q_REQUIRED_RESULT
Returns a string that has whitespace removed from the start and the end.
Definition: qstring.cpp:4506
static const uint qt_meta_data_QAxBase[]
Definition: qaxbase.cpp:3199
const QChar * unicode() const
Returns a &#39;\0&#39;-terminated Unicode representation of the string.
Definition: qstring.h:706
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
static bool init
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:270
HRESULT __stdcall QueryInterface(REFIID riid, void **ppvObject)
Definition: qaxbase.cpp:303
const char * name
const T value(const Key &key) const
Returns the value associated with the key key.
Definition: qmap.h:499
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
QAxBasePrivate * d
Definition: qaxbase.h:150
virtual int qt_metacall(QMetaObject::Call, int, void **)
Definition: qaxbase.cpp:3705
bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName, bool out)
Definition: qaxtypes.cpp:246
void addProperty(DISPID propid, const char *name, const char *signal)
Definition: qaxbase.cpp:284
Q_CORE_EXPORT void qWarning(const char *,...)
const_iterator insert(const T &value)
Definition: qset.h:179
QMap< QByteArray, QByteArray > classinfo_list
Definition: qaxbase.cpp:1611
IConnectionPoint * cpoint
Definition: qaxbase.cpp:532
void addSignal(DISPID memid, const char *name)
Definition: qaxbase.cpp:259
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:2838
QMetaObject * qax_readEnumInfo(ITypeLib *typeLib, const QMetaObject *parentObject)
Definition: qaxbase.cpp:1745
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
QMetaObject * qax_readClassInfo(ITypeLib *typeLib, ITypeInfo *classInfo, const QMetaObject *parentObject)
Definition: qaxbase.cpp:1772
Type
This enum type defines the types of variable that a QVariant can contain.
Definition: qvariant.h:95
void connectNotify()
Connects to all event interfaces of the object.
Definition: qaxbase.cpp:3282
bool setControl(const QString &)
Definition: qaxbase.cpp:975
static QChar fromLatin1(char c)
Converts the Latin-1 character c to its equivalent QChar.
Definition: qchar.h:378
bool hasSignal(const QByteArray &prototype)
Definition: qaxbase.cpp:1641
int enumeratorCount() const
Returns the number of enumerators in this class.
int indexOfSlot(const char *slot) const
Finds slot and returns its index; otherwise returns -1.
int indexOfSignal(const char *signal) const
Finds signal and returns its index; otherwise returns -1.
uint cachedMetaObject
Definition: qaxbase.cpp:596
const T * ptr(const T &t)
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
static int type(const char *typeName)
Returns a handle to the type called typeName, or 0 if there is no such type.
Definition: qmetatype.cpp:607
void addSignal(const QByteArray &prototype, const QByteArray &parameters)
Definition: qaxbase.cpp:1627
virtual bool propertyWritable(const char *) const
Returns true if the property prop is writable; otherwise returns false.
Definition: qaxbase.cpp:4385
QMetaObject * tryCache()
Definition: qaxbase.cpp:2959
const uint * data
Definition: qobjectdefs.h:471
QByteArray propertyType(const QByteArray &name)
Definition: qaxbase.cpp:1711
QByteArray mid(int index, int len=-1) const
Returns a byte array containing len bytes from this byte array, starting at position pos...
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the map.
Definition: qmap.h:374
const char * typeName() const
Returns the name of the type stored in the variant.
Definition: qvariant.cpp:1984
bool initializeLicensedHelper(void *factory, const QString &key, IUnknown **ptr)
Definition: qaxbase.cpp:1261
int indexOf(char c, int from=0) const
Returns the index position of the first occurrence of the character ch in the byte array...
QByteArray debugInfo
Definition: qaxbase.cpp:1738
QByteArray paramType(const QByteArray &signature, int index, bool *out=0)
Definition: qaxbase.cpp:142
QByteArray usertypeToString(const TYPEDESC &tdesc, ITypeInfo *info, const QByteArray &function)
Definition: qaxbase.cpp:1889
bool initializeFromFile(IUnknown **ptr)
Creates the COM object handling the filename in the control property, and returns the IUnknown interf...
Definition: qaxbase.cpp:1352
void readFuncsInfo(ITypeInfo *typeinfo, ushort nFuncs)
Definition: qaxbase.cpp:2451
void disableMetaObject()
Disables the meta object generation for this ActiveX container.
Definition: qaxbase.cpp:1068
QAxEventSink(QAxBase *com)
Definition: qaxbase.cpp:214
QAxBase * combase
Definition: qaxbase.cpp:540
QAxBase::PropertyBag map
Definition: qaxbase.cpp:4285
uint useEventSink
Definition: qaxbase.cpp:593
iterator begin()
Returns an STL-style iterator pointing to the first item in the map.
Definition: qmap.h:372
#define TRUE
Synonym for true.
Definition: qglobal.h:1018
int length() const
Same as size().
Definition: qbytearray.h:356
bool QVariantToVoidStar(const QVariant &var, void *data, const QByteArray &typeName, uint type)
Copies the data in var into data.
Definition: qaxtypes.cpp:814
uint useClassInfo
Definition: qaxbase.cpp:595
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).
static QByteArray prototype(const QList< QByteArray > &parameterTypes, const QList< QByteArray > &parameterNames, bool *ok)
Definition: qaxserver.cpp:685
int remove(const Key &key)
Removes all the items that have the key key from the map.
Definition: qmap.h:662
QMap< DISPID, QByteArray > signalMap() const
Definition: qaxbase.cpp:226
HRESULT __stdcall QueryInterface(REFIID iid, LPVOID *iface)
Definition: qaxbase.cpp:4238
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
#define QSIGNAL_CODE
Definition: qobjectdefs.h:244
static QMutex cache_mutex
Definition: qaxbase.cpp:186
QList< QByteArray > split(char sep) const
Splits the byte array into subarrays wherever sep occurs, and returns the list of those arrays...
static QAuServer & server()
Definition: qsound.cpp:79
uint qstrlen(const char *str)
Definition: qbytearray.h:79
The QMap::const_iterator class provides an STL-style const iterator for QMap and QMultiMap.
Definition: qmap.h:301
long HRESULT
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the map...
Definition: qmap.h:380
QByteArray findProperty(DISPID dispID)
Definition: qaxbase.cpp:618
void parsePrototype(const QByteArray &prototype)
Definition: qaxbase.cpp:115
QMap< DISPID, QByteArray > propsigs
Definition: qaxbase.cpp:537
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
void addSetterSlot(const QByteArray &property)
Definition: qaxbase.cpp:2369
long indexOfVerb(const QString &verb) const
Definition: qaxbase.cpp:1172
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the hash...
Definition: qhash.h:467
const char * name() const
Returns this property&#39;s name.
QMetaObject * qax_readInterfaceInfo(ITypeLib *typeLib, ITypeInfo *typeInfo, const QMetaObject *parentObject)
Definition: qaxbase.cpp:1753
void clear()
Clears the contents of the string and makes it empty.
Definition: qstring.h:723
unsigned short ushort
Definition: qglobal.h:995
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the map...
Definition: qmap.h:375
static QByteArray paramType(const QByteArray &ptype, bool *out)
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
QAxMetaObject * internalMetaObject() const
Definition: qaxbase.cpp:915
QMap< QByteArray, Method > signal_list
Definition: qaxbase.cpp:1626
Type type() const
Returns the storage type of the value stored in the variant.
Definition: qvariant.cpp:1901
PropertyBag propertyBag() const
Returns a name:value map of all the properties exposed by the COM object.
Definition: qaxbase.cpp:4303
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 void activate(QObject *sender, int signal_index, void **argv)
Definition: qobject.cpp:3690
const void * constData() const
Definition: qvariant.cpp:3065
int key
QString toLower() const Q_REQUIRED_RESULT
Returns a lowercase copy of the string.
Definition: qstring.cpp:5389
static BSTR QStringToBSTR(const QString &str)
Definition: qaxtypes.h:76
static QMetaObject qaxobject_staticMetaObject
Definition: qaxbase.cpp:3226
QByteArray replacePrototype(const QByteArray &prototype)
Definition: qaxbase.cpp:1588
The QHash::iterator class provides an STL-style non-const iterator for QHash and QMultiHash.
Definition: qhash.h:330
bool initializeLicensed(IUnknown **ptr)
Creates an instance of a licensed control, and returns the IUnknown interface to the object in ptr...
Definition: qaxbase.cpp:1240
const QMetaObject * superdata
Definition: qobjectdefs.h:469
double toDouble(bool *ok=0) const
Returns the string converted to a double value.
Definition: qstring.cpp:6227
bool isEmpty() const
Returns true if the map contains no items; otherwise returns false.
Definition: qmap.h:203
QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint type)
Returns arg as a QVariant of type type.
Definition: qaxtypes.cpp:919
uint initialized
Definition: qaxbase.cpp:597
static const char *const type_conversion[][2]
Definition: qaxbase.cpp:189
const char * className() const
Returns the class name.
Definition: qobjectdefs.h:491
const char * property
Definition: qwizard.cpp:138
QByteArray createPrototype(FUNCDESC *funcdesc, ITypeInfo *typeinfo, const QList< QByteArray > &names, QByteArray &type, QList< QByteArray > &parameters)
Definition: qaxbase.cpp:2384
HRESULT __stdcall GetTypeInfoCount(unsigned int *)
Definition: qaxbase.cpp:322
struct QMetaObject::@38 d
QMap< DISPID, QByteArray > propertyMap() const
Definition: qaxbase.cpp:230
QList< QByteArray > paramList(const QByteArray &proto)
Definition: qaxbase.cpp:1562
iterator begin()
Returns an STL-style iterator pointing to the first item in the hash.
Definition: qhash.h:464
QMap< QByteArray, Method > slot_list
Definition: qaxbase.cpp:1646
IDispatch * disp
Definition: qaxbase.cpp:601
QMap< DISPID, QByteArray > propSignalMap() const
Definition: qaxbase.cpp:234
virtual ~QAxEventSink()
Definition: qaxbase.cpp:217
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.
QMap< QByteArray, QList< QPair< QByteArray, int > > > enum_list
Definition: qaxbase.cpp:1716
int keyToValue(const char *key) const
Returns the integer value of the given enumeration key, or -1 if key is not defined.
char toLatin1() const
Returns the Latin-1 character equivalent to the QChar, or 0.
Definition: qchar.h:376
quint16 index
ITypeLib * typelib
Definition: qaxbase.cpp:1733
QVariant property(const char *name) const
Returns the value of the object&#39;s name property.
Definition: qobject.cpp:3807
QByteArray current_typelib
Definition: qaxbase.cpp:1734
void disableEventSink()
Disables the event sink implementation for this ActiveX container.
Definition: qaxbase.cpp:1047
void unadvise()
Definition: qaxbase.cpp:249
static const char qt_meta_stringdata_QAxBase[]
Definition: qaxbase.cpp:3220
static QHash< QUuid, QMap< QByteArray, QList< QPair< QByteArray, int > > > > enum_cache
Definition: qaxbase.cpp:184
T takeLast()
Removes the last item in the list and returns it.
Definition: qlist.h:492
int count(const Key &key) const
Returns the number of items associated with the key.
Definition: qhash.h:719
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...
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
DISPID dispIDofName(const QByteArray &name, IDispatch *disp)
Definition: qaxbase.cpp:168
QUuid connectionInterface() const
Definition: qaxbase.cpp:222
QMap< DISPID, QByteArray > props
Definition: qaxbase.cpp:538
QAxMetaObject * metaObject()
Definition: qaxbase.cpp:605
int propertyOffset() const
Returns the property offset for this class; i.e.
static QMetaObject qaxwidget_staticMetaObject
Definition: qaxbase.cpp:3230
const char * signature() const
Returns the signature of this method (e.g., setValue(double)).
friend class MetaObjectGenerator
Definition: qaxbase.cpp:97
IDispatch * disp
Definition: qaxbase.cpp:1730
bool signalsBlocked() const
Returns true if signals are blocked; otherwise returns false.
Definition: qobject.h:148
int indexOfEnumerator(const char *name) const
Finds enumerator name and returns its index; otherwise returns -1.
char at(int i) const
Returns the character at index position i in the byte array.
Definition: qbytearray.h:413
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
bool isValid() const
Returns true if the storage type of this variant is not QVariant::Invalid; otherwise returns false...
Definition: qvariant.h:485
void reserve(int size)
Attempts to allocate memory for at least size bytes.
Definition: qbytearray.h:449
static Type nameToType(const char *name)
Converts the string representation of the storage type given in name, to its enum representation...
Definition: qvariant.cpp:2026
IDispatch * dispatch() const
Definition: qaxbase.cpp:580
long queryInterface(const QUuid &, void **) const
Requests the interface uuid from the COM object and sets the value of iface to the provided interface...
Definition: qaxbase.cpp:1479
virtual void clear()
Disconnects and destroys the COM object.
Definition: qaxbase.cpp:1095
QMap< QByteArray, bool > propWritable
Definition: qaxbase.cpp:603
QAxBase(IUnknown *iface=0)
Creates a QAxBase object that wraps the COM object iface.
Definition: qaxbase.cpp:850
static bool signalHasReceivers(QObject *qobject, const char *signalName)
Definition: qaxbase.cpp:526
virtual bool initialize(IUnknown **ptr)
This virtual function is called by setControl() and creates the requested COM object.
Definition: qaxbase.cpp:1199
int indexOfClassInfo(const char *name) const
Finds class information item name and returns its index; otherwise returns -1.
void addEnumValue(const QByteArray &enumname, const QByteArray &key, int value)
Definition: qaxbase.cpp:1717
Q_CORE_EXPORT QTextStream & left(QTextStream &s)
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end)
Definition: qalgorithms.h:319
The QAxBase class is an abstract class that provides an API to initialize and access a COM object...
Definition: qaxbase.h:66
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)...
QMap< QString, LONG > verbs
Definition: qaxbase.cpp:612
QMap< QUuid, QMap< DISPID, QByteArray > > propsigs
Definition: qaxbase.cpp:103
const char * typeName() const
Returns the name of this property&#39;s type.
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
QMetaObject * metaObject(const QMetaObject *parentObject, const QByteArray &className=QByteArray())
Definition: qaxbase.cpp:2995
HRESULT __stdcall Write(LPCOLESTR name, VARIANT *var)
Definition: qaxbase.cpp:4274
The QMetaMethod class provides meta-data about a member function.
Definition: qmetaobject.h:56
void clear()
Clears the contents of the byte array and makes it empty.
uint useMetaObject
Definition: qaxbase.cpp:594
The QUuid class stores a Universally Unique Identifier (UUID).
Definition: quuid.h:67
The QMap class is a template class that provides a skip-list-based dictionary.
Definition: qdatastream.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.
void addChangedSignal(const QByteArray &function, const QByteArray &type, int memid)
Definition: qaxbase.cpp:2349
QMap< QByteArray, Property > property_list
Definition: qaxbase.cpp:1673
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
QByteArray replaceType(const QByteArray &type)
Definition: qaxbase.cpp:1572
QList< QUuid > connectionInterfaces
Definition: qaxbase.cpp:99
const ushort * utf16() const
Returns the QString as a &#39;\0\&#39;-terminated array of unsigned shorts.
Definition: qstring.cpp:5290
void qErrnoWarning(const char *msg,...)
Definition: qglobal.cpp:2954
QVariant::Type type() const
Returns this property&#39;s type.
ITypeInfo * dispInfo
Definition: qaxbase.cpp:1731