/* Start the COM server (if necessary). */ bool qax_startServer(QAxFactory::ServerType type) { if (qAxIsServer) return true; const QStringList keys = qAxFactory()->featureList(); if (!keys.count()) return false; if (!qAxFactory()->isService()) StartMonitor(); classRegistration = new DWORD[keys.count()]; int object = 0; for (QStringList::ConstIterator key = keys.begin(); key != keys.end(); ++key, ++object) { IUnknown* p = 0; CLSID clsid = qAxFactory()->classID(*key); // Create a QClassFactory (implemented in qaxserverbase.cpp) HRESULT hRes = GetClassObject(clsid, IID_IClassFactory, (void**)&p); if (SUCCEEDED(hRes)) hRes = CoRegisterClassObject(clsid, p, CLSCTX_LOCAL_SERVER, type == QAxFactory::MultipleInstances ? REGCLS_MULTIPLEUSE : REGCLS_SINGLEUSE, classRegistration+object); if (p) p->Release(); } qAxIsServer = true; return true; }
static QByteArray convertTypes(const QByteArray &qtype, bool *ok) { qRegisterMetaType<IDispatch *>("IDispatch*"); qRegisterMetaType<IUnknown *>("IUnknown*"); *ok = false; int i = 0; while (type_map[i][0]) { if (qtype == type_map[i][0] && type_map[i][1]) { *ok = true; return type_map[i][1]; } ++i; } if (enums.contains(qtype)) { *ok = true; return "enum " + qtype; } if (subtypes.contains(qtype)) { *ok = true; } else if (qtype.endsWith('*')) { QByteArray cleanType = qtype.left(qtype.length() - 1); const QMetaObject *mo = qAxFactory()->metaObject(QString::fromLatin1(cleanType.constData())); if (mo) { cleanType = qax_clean_type(QString::fromLatin1(cleanType), mo).toLatin1(); if (subtypes.contains(cleanType)) { *ok = true; return cleanType + '*'; } } } return qtype; }
QT_BEGIN_NAMESPACE QAxBase *qax_create_object_wrapper(QObject *object) { IDispatch *dispatch = 0; QAxObject *wrapper = 0; qAxFactory()->createObjectWrapper(object, &dispatch); if (dispatch) { wrapper = new QAxObject(dispatch, object); wrapper->setObjectName(object->objectName()); dispatch->Release(); } return wrapper; }
/*! Registers the QObject \a object with COM as a running object, and returns true if the registration succeeded, otherwise returns false. The object is unregistered automatically when it is destroyed. This function should only be called if the application has been started by the user (i.e. not by COM to respond to a request), and only for one object, usually the toplevel object of the application's object hierarchy. This function does nothing and returns false if the object's class info for "RegisterObject" is not set to "yes", or if the server is an in-process server. */ bool QAxFactory::registerActiveObject(QObject *object) { if (qstricmp(object->metaObject()->classInfo(object->metaObject()->indexOfClassInfo("RegisterObject")).value(), "yes")) return false; if (!QString::fromWCharArray(qAxModuleFilename).toLower().endsWith(QLatin1String(".exe"))) return false; ActiveObject *active = new ActiveObject(object, qAxFactory()); if (!active->wrapper || !active->cookie) { delete active; return false; } return true; }
/* Stop the COM server (if necessary). */ bool qax_stopServer() { if (!qAxIsServer || !classRegistration) return true; qAxIsServer = false; const QStringList keys = qAxFactory()->featureList(); int object = 0; for (QStringList::ConstIterator key = keys.begin(); key != keys.end(); ++key, ++object) CoRevokeClassObject(classRegistration[object]); delete []classRegistration; classRegistration = 0; Sleep(dwPause); //wait for any threads to finish return true; }
static HRESULT classIDL(QObject *o, const QMetaObject *mo, const QString &className, bool isBindable, QTextStream &out) { int id = 1; int i = 0; if (!mo) return 3; QString topclass = qAxFactory()->exposeToSuperClass(className); if (topclass.isEmpty()) topclass = QLatin1String("QObject"); bool hasStockEvents = qAxFactory()->hasStockEvents(className); const QMetaObject *pmo = mo; do { pmo = pmo->superClass(); } while (pmo && topclass != QString::fromLatin1(pmo->className())); int enumoff = pmo ? pmo->enumeratorOffset() : mo->enumeratorOffset(); int methodoff = pmo ? pmo->methodOffset() : mo->methodOffset(); int propoff = pmo ? pmo->propertyOffset() : mo->propertyOffset(); int qtProps = 0; int qtSlots = 0; bool control = false; if (o && o->isWidgetType()) { qtProps = QWidget::staticMetaObject.propertyCount(); qtSlots = QWidget::staticMetaObject.methodCount(); control = true; } const QString classID = stripCurlyBraces(qAxFactory()->classID(className)); if (classID.isEmpty()) return 4; const QString interfaceID = stripCurlyBraces(qAxFactory()->interfaceID(className)); if (interfaceID.isEmpty()) return 5; const QString eventsID = stripCurlyBraces(qAxFactory()->eventsID(className)); const bool hasEvents = !eventsID.isEmpty(); QString cleanClassName = qax_clean_type(className, mo); QString defProp(QLatin1String(mo->classInfo(mo->indexOfClassInfo("DefaultProperty")).value())); QString defSignal(QLatin1String(mo->classInfo(mo->indexOfClassInfo("DefaultSignal")).value())); for (i = enumoff; i < mo->enumeratorCount(); ++i) { const QMetaEnum enumerator = mo->enumerator(i); if (enums.contains(enumerator.name())) continue; enums.append(enumerator.name()); out << "\tenum " << enumerator.name() << " {" << endl; for (int j = 0; j < enumerator.keyCount(); ++j) { QByteArray key(enumerator.key(j)); while (enumValues.contains(key)) { key += '_'; } enumValues.append(key); const uint value = uint(enumerator.value(j)); key = key.leftJustified(20); out << "\t\t" << key << "\t= "; if (enumerator.isFlag()) out << "0x" << QByteArray::number(value, 16).rightJustified(8, '0'); else out << value; if (j < enumerator.keyCount()-1) out << ", "; out << endl; } out << "\t};" << endl << endl; } // mouse cursor enum for QCursor support if (!enums.contains("MousePointer")) { enums.append("MousePointer"); out << "\tenum MousePointer {" << endl; out << "\t\tArrowCursor = " << Qt::ArrowCursor << ',' << endl; out << "\t\tUpArrowCursor = " << Qt::UpArrowCursor << ',' << endl; out << "\t\tCrossCursor = " << Qt::CrossCursor << ',' << endl; out << "\t\tWaitCursor = " << Qt::WaitCursor << ',' << endl; out << "\t\tIBeamCursor = " << Qt::IBeamCursor << ',' << endl; out << "\t\tSizeVerCursor = " << Qt::SizeVerCursor << ',' << endl; out << "\t\tSizeHorCursor = " << Qt::SizeHorCursor << ',' << endl; out << "\t\tSizeBDiagCursor = " << Qt::SizeBDiagCursor << ',' << endl; out << "\t\tSizeFDiagCursor = " << Qt::SizeFDiagCursor << ',' << endl; out << "\t\tSizeAllCursor = " << Qt::SizeAllCursor << ',' << endl; out << "\t\tBlankCursor = " << Qt::BlankCursor << ',' << endl; out << "\t\tSplitVCursor = " << Qt::SplitVCursor << ',' << endl; out << "\t\tSplitHCursor = " << Qt::SplitHCursor << ',' << endl; out << "\t\tPointingHandCursor = " << Qt::PointingHandCursor << ',' << endl; out << "\t\tForbiddenCursor = " << Qt::ForbiddenCursor << ',' << endl; out << "\t\tWhatsThisCursor = " << Qt::WhatsThisCursor << ',' << endl; out << "\t\tBusyCursor\t= " << Qt::BusyCursor << endl; out << "\t};" << endl << endl; } if (!enums.contains("FocusPolicy")) { enums.append("FocusPolicy"); out << "\tenum FocusPolicy {" << endl; out << "\t\tNoFocus = " << Qt::NoFocus << ',' << endl; out << "\t\tTabFocus = " << Qt::TabFocus << ',' << endl; out << "\t\tClickFocus = " << Qt::ClickFocus << ',' << endl; out << "\t\tStrongFocus = " << Qt::StrongFocus << ',' << endl; out << "\t\tWheelFocus = " << Qt::WheelFocus << endl; out << "\t};" << endl << endl; } out << endl; out << "\t[" << endl; out << "\t\tuuid(" << interfaceID << ")," << endl; out << "\t\thelpstring(\"" << cleanClassName << " Interface\")" << endl; out << "\t]" << endl; out << "\tdispinterface I" << cleanClassName << endl; out << "\t{" << endl; out << "\tproperties:" << endl; for (i = propoff; i < mo->propertyCount(); ++i) { const QMetaProperty property = mo->property(i); /* if (property.testFlags(QMetaProperty::Override)) continue;*/ if (i <= qtProps && ignoreProps(property.name())) continue; if (!property.name() || mo->indexOfProperty(property.name()) > i) continue; bool ok = true; QByteArray type(convertTypes(property.typeName(), &ok)); QByteArray name(replaceKeyword(property.name())); if (!ok) out << "\t/****** Property is of unsupported datatype" << endl; out << "\t\t[id(" << id << ')'; if (!property.isWritable()) out << ", readonly"; if (isBindable && property.isScriptable(o)) out << ", bindable"; if (!property.isDesignable(o)) out << ", nonbrowsable"; if (isBindable) out << ", requestedit"; if (defProp == QLatin1String(name)) out << ", uidefault"; out << "] " << type << ' ' << name << ';' << endl; if (!ok) out << "\t******/" << endl; ++id; } out << endl; out << "\tmethods:" << endl; int numDefArgs = 0; QByteArray outBuffer; for (i = methodoff; i < mo->methodCount(); ++i) { const QMetaMethod slot = mo->method(i); if (slot.access() != QMetaMethod::Public || slot.methodType() == QMetaMethod::Signal) continue; if (slot.attributes() & QMetaMethod::Cloned) { ++numDefArgs; continue; } if (!outBuffer.isEmpty()) { outBuffer = addDefaultArguments(outBuffer, numDefArgs); numDefArgs = 0; out << outBuffer; outBuffer = QByteArray(); } QByteArray signature(slot.methodSignature()); QByteArray name(signature.left(signature.indexOf('('))); if (i <= qtSlots && ignoreSlots(name)) continue; signature.remove(0, name.length() + 1); signature.truncate(signature.length() - 1); name = renameOverloads(replaceKeyword(name)); if (ignoreSlots(name)) continue; QList<QByteArray> parameterTypes(slot.parameterTypes()); QList<QByteArray> parameterNames(slot.parameterNames()); bool ok = true; QByteArray type = slot.typeName(); if (type.isEmpty()) type = "void"; else type = convertTypes(type, &ok); QByteArray ptype(prototype(parameterTypes, parameterNames, &ok)); if (!ok) outBuffer += "\t/****** Slot parameter uses unsupported datatype\n"; outBuffer += "\t\t[id(" + QByteArray::number(id) + ")] " + type + ' ' + name + '(' + ptype + ");\n"; if (!ok) outBuffer += "\t******/\n"; ++id; } if (!outBuffer.isEmpty()) { outBuffer = addDefaultArguments(outBuffer, numDefArgs); numDefArgs = 0; out << outBuffer; outBuffer = QByteArray(); } out << "\t};" << endl << endl; mapping.clear(); id = 1; if (hasEvents) { out << "\t[" << endl; out << "\t\tuuid(" << eventsID << ")," << endl; out << "\t\thelpstring(\"" << cleanClassName << " Events Interface\")" << endl; out << "\t]" << endl; out << "\tdispinterface I" << cleanClassName << "Events" << endl; out << "\t{" << endl; out << "\tproperties:" << endl; out << "\tmethods:" << endl; if (hasStockEvents) { out << "\t/****** Stock events ******/" << endl; out << "\t\t[id(DISPID_CLICK)] void Click();" << endl; out << "\t\t[id(DISPID_DBLCLICK)] void DblClick();" << endl; out << "\t\t[id(DISPID_KEYDOWN)] void KeyDown(short* KeyCode, short Shift);" << endl; out << "\t\t[id(DISPID_KEYPRESS)] void KeyPress(short* KeyAscii);" << endl; out << "\t\t[id(DISPID_KEYUP)] void KeyUp(short* KeyCode, short Shift);" << endl; out << "\t\t[id(DISPID_MOUSEDOWN)] void MouseDown(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl; out << "\t\t[id(DISPID_MOUSEMOVE)] void MouseMove(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl; out << "\t\t[id(DISPID_MOUSEUP)] void MouseUp(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl << endl; } for (i = methodoff; i < mo->methodCount(); ++i) { const QMetaMethod signal = mo->method(i); if (signal.methodType() != QMetaMethod::Signal) continue; QByteArray signature(signal.methodSignature()); QByteArray name(signature.left(signature.indexOf('('))); signature.remove(0, name.length() + 1); signature.truncate(signature.length() - 1); QList<QByteArray> parameterTypes(signal.parameterTypes()); QList<QByteArray> parameterNames(signal.parameterNames()); bool isDefault = defSignal == QLatin1String(name); name = renameOverloads(replaceKeyword(name)); bool ok = true; QByteArray type = signal.typeName(); if (!type.isEmpty() && type != "void") // signals with return value not supported continue; QByteArray ptype(prototype(parameterTypes, parameterNames, &ok)); if (!ok) out << "\t/****** Signal parameter uses unsupported datatype" << endl; out << "\t\t[id(" << id << ')'; if (isDefault) out << ", uidefault"; out << "] void " << name << '(' << ptype << ");" << endl; if (!ok) out << "\t******/" << endl; ++id; } out << "\t};" << endl << endl; } out << "\t[" << endl; if (qstricmp(mo->classInfo(mo->indexOfClassInfo("Aggregatable")).value(), "no")) out << "\t\taggregatable," << endl; if (!qstricmp(mo->classInfo(mo->indexOfClassInfo("RegisterObject")).value(), "yes")) out << "\t\tappobject," << endl; if (mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value()) out << "\t\tlicensed," << endl; const char *helpString = mo->classInfo(mo->indexOfClassInfo("Description")).value(); if (helpString) out << "\t\thelpstring(\"" << helpString << "\")," << endl; else out << "\t\thelpstring(\"" << cleanClassName << " Class\")," << endl; const char *classVersion = mo->classInfo(mo->indexOfClassInfo("Version")).value(); if (classVersion) out << "\t\tversion(" << classVersion << ")," << endl; out << "\t\tuuid(" << classID << ')'; if (control) { out << ", " << endl; out << "\t\tcontrol"; } else if (!o) { out << ", " << endl; out << "\t\tnoncreatable"; } out << endl; out << "\t]" << endl; out << "\tcoclass " << cleanClassName << endl; out << "\t{" << endl; out << "\t\t[default] dispinterface I" << cleanClassName << ';' << endl; if (hasEvents) out << "\t\t[default, source] dispinterface I" << cleanClassName << "Events;" << endl; out << "\t};" << endl; return S_OK; }
// (Un)Register the ActiveX server in the registry. // The QAxFactory implementation provides the information. HRESULT UpdateRegistry(BOOL bRegister) { qAxIsServer = false; const QChar dot(QLatin1Char('.')); const QChar slash(QLatin1Char('/')); QString file = QString::fromWCharArray(qAxModuleFilename); const QString module = QFileInfo(file).baseName(); const QString appId = qAxFactory()->appID().toString().toUpper(); const QString libId = qAxFactory()->typeLibID().toString().toUpper(); const QString libFile = qAxInit(); TLIBATTR *libAttr = 0; if (qAxTypeLibrary) qAxTypeLibrary->GetLibAttr(&libAttr); if (!libAttr) return SELFREG_E_TYPELIB; bool userFallback = false; if (bRegister) { if (RegisterTypeLib(qAxTypeLibrary, reinterpret_cast<wchar_t *>(const_cast<ushort *>(libFile.utf16())), 0) == TYPE_E_REGISTRYACCESS) { #ifndef Q_CC_MINGW // MinGW does not have RegisterTypeLibForUser() implemented so we cannot fallback in this case RegisterTypeLibForUser(qAxTypeLibrary, reinterpret_cast<wchar_t *>(const_cast<ushort *>(libFile.utf16())), 0); userFallback = true; #endif } } else { if (UnRegisterTypeLib(libAttr->guid, libAttr->wMajorVerNum, libAttr->wMinorVerNum, libAttr->lcid, libAttr->syskind) == TYPE_E_REGISTRYACCESS) { #ifndef Q_CC_MINGW // MinGW does not have RegisterTypeLibForUser() implemented so we cannot fallback in this case UnRegisterTypeLibForUser(libAttr->guid, libAttr->wMajorVerNum, libAttr->wMinorVerNum, libAttr->lcid, libAttr->syskind); userFallback = true; #endif } } if (userFallback) qWarning("QAxServer: Falling back to registering as user for %s due to insufficient permission.", qPrintable(module)); qAxTypeLibrary->ReleaseTLibAttr(libAttr); // check whether the user has permission to write to HKLM\Software\Classes // if not, use HKCU\Software\Classes QString keyPath(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes")); QScopedPointer<QSettings> settings(new QSettings(keyPath, QSettings::NativeFormat)); if (userFallback || !settings->isWritable()) { keyPath = QLatin1String("HKEY_CURRENT_USER\\Software\\Classes"); settings.reset(new QSettings(keyPath, QSettings::NativeFormat)); } // we try to create the ActiveX widgets later on... bool delete_qApp = false; if (!qApp) { static int argc = 0; // static lifetime, since it's passed as reference to QApplication, which has a lifetime exceeding the stack frame (void)new QApplication(argc, 0); delete_qApp = true; } if (bRegister) { if (qAxOutProcServer) { settings->setValue(QLatin1String("/AppID/") + appId + QLatin1String("/."), module); settings->setValue(QLatin1String("/AppID/") + module + QLatin1String(".EXE/AppID"), appId); } const QStringList keys = qAxFactory()->featureList(); for (const QString &classNameIn : keys) { QObject *object = qAxFactory()->createObject(classNameIn); const QMetaObject *mo = qAxFactory()->metaObject(classNameIn); const QString classId = qAxFactory()->classID(classNameIn).toString().toUpper(); const QString className = qax_clean_type(classNameIn, mo); if (object) { // don't register subobject classes QString classVersion = mo ? QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("Version")).value()) : QString(); if (classVersion.isNull()) classVersion = QLatin1String("1.0"); bool insertable = mo && !qstricmp(mo->classInfo(mo->indexOfClassInfo("Insertable")).value(), "yes"); bool control = object->isWidgetType(); QString classMajorVersion = classVersion.left(classVersion.indexOf(dot)); uint olemisc = OLEMISC_SETCLIENTSITEFIRST |OLEMISC_ACTIVATEWHENVISIBLE |OLEMISC_INSIDEOUT |OLEMISC_CANTLINKINSIDE |OLEMISC_RECOMPOSEONRESIZE; if (!control) olemisc |= OLEMISC_INVISIBLEATRUNTIME; else if (object->findChild<QMenuBar*>() && !qax_disable_inplaceframe) olemisc |= OLEMISC_WANTSTOMENUMERGE; const QString versionLessProgId = module + dot + className; const QString progId = versionLessProgId + dot + classMajorVersion; QString key = slash + progId; settings->setValue(key + QLatin1String("/."), className + QLatin1String(" Class")); settings->setValue(key + QLatin1String("/CLSID/."), classId); if (insertable) settings->setValue(key + QLatin1String("/Insertable/."), QVariant(QLatin1String(""))); key = slash + module + dot + className; settings->setValue(key + QLatin1String("/."), className + QLatin1String(" Class")); settings->setValue(key + QLatin1String("/CLSID/."), classId); settings->setValue(key + QLatin1String("/CurVer/."), progId); key = QLatin1String("/CLSID/") + classId; settings->setValue(key + QLatin1String("/."), className + QLatin1String(" Class")); if (file.endsWith(QLatin1String("exe"), Qt::CaseInsensitive)) settings->setValue(key + QLatin1String("/AppID"), appId); if (control) settings->setValue(key + QLatin1String("/Control/."), QVariant(QLatin1String(""))); if (insertable) settings->setValue(key + QLatin1String("/Insertable/."), QVariant(QLatin1String(""))); if (file.endsWith(QLatin1String("dll"), Qt::CaseInsensitive)) settings->setValue(key + QLatin1String("/InProcServer32/."), file); else settings->setValue(key + QLatin1String("/LocalServer32/."), QLatin1Char('\"') + file + QLatin1String("\" -activex")); settings->setValue(key + QLatin1String("/MiscStatus/."), control ? QLatin1String("1") : QLatin1String("0")); settings->setValue(key + QLatin1String("/MiscStatus/1/."), QString::number(olemisc)); settings->setValue(key + QLatin1String("/Programmable/."), QVariant(QLatin1String(""))); settings->setValue(key + QLatin1String("/ToolboxBitmap32/."), QLatin1Char('\"') + file + QLatin1String("\", 101")); settings->setValue(key + QLatin1String("/TypeLib/."), libId); settings->setValue(key + QLatin1String("/Version/."), classVersion); settings->setValue(key + QLatin1String("/VersionIndependentProgID/."), versionLessProgId); settings->setValue(key + QLatin1String("/ProgID/."), progId); QString mime = QLatin1String(mo->classInfo(mo->indexOfClassInfo("MIME")).value()); if (!mime.isEmpty()) { QStringList mimeTypes = mime.split(QLatin1Char(';')); for (int m = 0; m < mimeTypes.count(); ++m) { mime = mimeTypes.at(m); if (mime.isEmpty()) continue; QString extension; while (mime.contains(QLatin1Char(':'))) { extension = mime.mid(mime.lastIndexOf(QLatin1Char(':')) + 1); mime.chop(extension.length() + 1); // Prepend '.' before extension, if required. extension = extension.trimmed(); if (!extension.startsWith(dot)) extension.prepend(dot); } if (!extension.isEmpty()) { key = slash + extension; settings->setValue(key + QLatin1String("/."), module + dot + className); settings->setValue(key + QLatin1String("/Content Type"), mime); mime.replace(slash, QLatin1Char('\\')); key = QLatin1String("/MIME/Database/Content Type/") + mime; settings->setValue(key + QLatin1String("/CLSID"), classId); settings->setValue(key + QLatin1String("/Extension"), extension); } } } delete object; qCDebug(lcAxRegistration).nospace().noquote() << "Registered \"" << progId << "\"/" << classId << ", \"" << file << "\" at \"" << keyPath << "\", insertable=" << insertable << ", control=" << control << ", olemisc=" << hex << showbase << olemisc << ", mime=" << mime; } qAxFactory()->registerClass(classNameIn, settings.data()); } } else { if (qAxOutProcServer) { settings->remove(QLatin1String("/AppID/") + appId + QLatin1String("/.")); settings->remove(QLatin1String("/AppID/") + module + QLatin1String(".EXE")); } const QStringList keys = qAxFactory()->featureList(); for (const QString &classNameIn : keys) { const QMetaObject *mo = qAxFactory()->metaObject(classNameIn); const QString classId = qAxFactory()->classID(classNameIn).toString().toUpper(); const QString className = qax_clean_type(classNameIn, mo); QString classVersion = mo ? QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("Version")).value()) : QString(); if (classVersion.isNull()) classVersion = QLatin1String("1.0"); const QString classMajorVersion = classVersion.left(classVersion.indexOf(dot)); qAxFactory()->unregisterClass(classNameIn, settings.data()); const QString progId = module + dot + className + dot + classMajorVersion; QString key = slash + progId; settings->remove(key + QLatin1String("/CLSID/.")); settings->remove(key + QLatin1String("/Insertable/.")); settings->remove(key + QLatin1String("/.")); settings->remove(key); key = slash + module + dot + className; settings->remove(key + QLatin1String("/CLSID/.")); settings->remove(key + QLatin1String("/CurVer/.")); settings->remove(key + QLatin1String("/.")); settings->remove(key); key = QLatin1String("/CLSID/") + classId; settings->remove(key + QLatin1String("/AppID")); settings->remove(key + QLatin1String("/Control/.")); settings->remove(key + QLatin1String("/Insertable/.")); settings->remove(key + QLatin1String("/InProcServer32/.")); settings->remove(key + QLatin1String("/LocalServer32/.")); settings->remove(key + QLatin1String("/MiscStatus/1/.")); settings->remove(key + QLatin1String("/MiscStatus/.")); settings->remove(key + QLatin1String("/Programmable/.")); settings->remove(key + QLatin1String("/ToolboxBitmap32/.")); settings->remove(key + QLatin1String("/TypeLib/.")); settings->remove(key + QLatin1String("/Version/.")); settings->remove(key + QLatin1String("/VersionIndependentProgID/.")); settings->remove(key + QLatin1String("/ProgID/.")); settings->remove(key + QLatin1String("/.")); settings->remove(key); QString mime = QLatin1String(mo->classInfo(mo->indexOfClassInfo("MIME")).value()); if (!mime.isEmpty()) { QStringList mimeTypes = mime.split(QLatin1Char(';')); for (int m = 0; m < mimeTypes.count(); ++m) { mime = mimeTypes.at(m); if (mime.isEmpty()) continue; QString extension; while (mime.contains(QLatin1Char(':'))) { extension = mime.mid(mime.lastIndexOf(QLatin1Char(':')) + 1); mime.chop(extension.length() + 1); // Prepend '.' before extension, if required. extension = extension.trimmed(); if (extension[0] != dot) extension.prepend(dot); } if (!extension.isEmpty()) { key = slash + extension; settings->remove(key + QLatin1String("/Content Type")); settings->remove(key + QLatin1String("/.")); settings->remove(key); mime.replace(slash, QLatin1Char('\\')); key = QLatin1String("/MIME/Database/Content Type/") + mime; settings->remove(key + QLatin1String("/Extension")); settings->remove(key + QLatin1String("/CLSID")); settings->remove(key + QLatin1String("/.")); settings->remove(key); } } } qCDebug(lcAxRegistration).nospace().noquote() << "Unregistered \"" << progId << "\"/" << classId << ", \"" << file << "\" from \"" << keyPath << '"'; } } if (delete_qApp) delete qApp; qAxCleanup(); if (settings->status() == QSettings::NoError) return S_OK; qWarning() << module << ": Error writing to " << keyPath; return SELFREG_E_CLASS; }
extern "C" HRESULT __stdcall DumpIDL(const QString &outfile, const QString &ver) { qAxIsServer = false; QTextStream out; if (outfile.contains(QLatin1String("\\"))) { QString outpath = outfile.left(outfile.lastIndexOf(QLatin1String("\\"))); QDir dir; dir.mkpath(outpath); } QFile file(outfile); file.remove(); QString filebase = QString::fromWCharArray(qAxModuleFilename); filebase.truncate(filebase.lastIndexOf(QLatin1Char('.'))); const QString appID = stripCurlyBraces(qAxFactory()->appID()); if (appID.isEmpty()) return 1; const QString typeLibID = stripCurlyBraces(qAxFactory()->typeLibID()); if (typeLibID.isEmpty()) return 2; QString typelib = filebase.right(filebase.length() - filebase.lastIndexOf(QLatin1String("\\"))-1); if (!file.open(QIODevice::WriteOnly)) return -1; out.setDevice(&file); QString version(ver.unicode(), ver.length()); while (version.count(QLatin1Char('.')) > 1) { int lastdot = version.lastIndexOf(QLatin1Char('.')); version.remove(lastdot, 1); } if (version.isEmpty()) version = QLatin1String("1.0"); const QString idQRect = stripCurlyBraces(QUuid(CLSID_QRect)); const QString idQSize = stripCurlyBraces(QUuid(CLSID_QSize)); const QString idQPoint = stripCurlyBraces(QUuid(CLSID_QPoint)); out << "/****************************************************************************" << endl; out << "** Interface definition generated for ActiveQt project" << endl; out << "**" << endl; out << "** '" << QString::fromWCharArray(qAxModuleFilename) << '\'' << endl; out << "**" << endl; out << "** Created: " << QDateTime::currentDateTime().toString() << endl; out << "**" << endl; out << "** WARNING! All changes made in this file will be lost!" << endl; out << "****************************************************************************/" << endl << endl; out << "import \"ocidl.idl\";" << endl; out << "#include <olectl.h>" << endl << endl; // dummy application to create widgets bool delete_qApp = false; if (!qApp) { static int argc = 0; // static lifetime, since it's passed as reference to QApplication, which has a lifetime exceeding the stack frame (void)new QApplication(argc, 0); delete_qApp = true; } out << '[' << endl; out << "\tuuid(" << typeLibID << ")," << endl; out << "\tversion(" << version << ")," << endl; out << "\thelpstring(\"" << typelib << ' ' << version << " Type Library\")" << endl; out << ']' << endl; out << "library " << typelib << "Lib" << endl; out << '{' << endl; out << "\timportlib(\"stdole32.tlb\");" << endl; out << "\timportlib(\"stdole2.tlb\");" << endl << endl; const QStringList keys = qAxFactory()->featureList(); out << "\t/************************************************************************" << endl; out << "\t** If this causes a compile error in MIDL you need to upgrade the" << endl; out << "\t** Platform SDK you are using. Download the SDK from msdn.microsoft.com" << endl; out << "\t** and make sure that both the system and the Visual Studio environment" << endl; out << "\t** use the correct files." << endl; out << "\t**" << endl; #if __REQUIRED_RPCNDR_H_VERSION__ < Q_REQUIRED_RPCNDR_H_VERSION out << "\t** Required version of MIDL could not be verified. QRect, QSize and QPoint" << endl; out << "\t** support needs an updated Platform SDK to be installed." << endl; out << "\t*************************************************************************" << endl; #else out << "\t************************************************************************/" << endl; #endif out << endl; out << "\t[uuid(" << idQRect << ")]" << endl; out << "\tstruct QRect {" << endl; out << "\t\tint left;" << endl; out << "\t\tint top;" << endl; out << "\t\tint right;" << endl; out << "\t\tint bottom;" << endl; out << "\t};" << endl << endl; out << "\t[uuid(" << idQSize << ")]" << endl; out << "\tstruct QSize {" << endl; out << "\t\tint width;" << endl; out << "\t\tint height;" << endl; out << "\t};" << endl << endl; out << "\t[uuid(" << idQPoint << ")]" << endl; out << "\tstruct QPoint {" << endl; out << "\t\tint x;" << endl; out << "\t\tint y;" << endl; out << "\t};" << endl; #if __REQUIRED_RPCNDR_H_VERSION__ < Q_REQUIRED_RPCNDR_H_VERSION out << "\t*/" << endl; #endif out << endl; out << "\t/* Forward declaration of classes that might be used as parameters */" << endl << endl; int res = S_OK; for (const QString &className : keys) { const QMetaObject *mo = qAxFactory()->metaObject(className); // We have meta object information for this type. Forward declare it. if (mo) { QByteArray cleanType = qax_clean_type(className, mo).toLatin1(); out << "\tcoclass " << cleanType << ';' << endl; subtypes.append(cleanType); if (!QMetaType::type(cleanType)) qRegisterMetaType<void *>(cleanType); cleanType += '*'; subtypes.append(cleanType); if (!QMetaType::type(cleanType)) qRegisterMetaType<void *>(cleanType); } } out << endl; for (const QString &className : keys) { const QMetaObject *mo = qAxFactory()->metaObject(className); // We have meta object information for this type. Define it. if (mo) { QObject *o = qAxFactory()->createObject(className); // It's not a control class, so it is actually a subtype. Define it. if (!o) res = classIDL(0, mo, className, false, out); delete o; } } out << endl; if (res != S_OK) goto ErrorInClass; for (const QString &className : keys) { QObject *o = qAxFactory()->createObject(className); if (!o) continue; const QMetaObject *mo = o->metaObject(); QAxBindable *bind = static_cast<QAxBindable *>(o->qt_metacast("QAxBindable")); bool isBindable = bind != 0; const QByteArray cleanType = qax_clean_type(className, mo).toLatin1(); subtypes.append(cleanType); subtypes.append(cleanType + '*'); res = classIDL(o, mo, className, isBindable, out); delete o; if (res != S_OK) break; } out << "};" << endl; out.flush(); ErrorInClass: if (delete_qApp) delete qApp; if (res != S_OK) { file.close(); file.remove(); } return res; }