JNIEXPORT jobject JNICALL Java_org_racob_com_TypeInfo_getContainingTypeLib (JNIEnv *env, jobject obj, jint pointer) { ITypeInfo *typeInfo = (ITypeInfo *) pointer; ITypeLib* typeLib = NULL; unsigned int index = 0; HRESULT hr = typeInfo->GetContainingTypeLib(&typeLib, &index); if (!SUCCEEDED(hr)) { ThrowComFail(env, "GetContainingTypeLib failed", hr); return NULL; } int typeCount = typeLib->GetTypeInfoCount(); if (typeCount == E_NOTIMPL) { ThrowComFail(env, "GetContainingTypeLib failed to get count", hr); return NULL; } TLIBATTR *libAttr = NULL; hr = typeLib->GetLibAttr(&libAttr); if (!SUCCEEDED(hr)) { ThrowComFail(env, "Automation.loadTypeLibEx failed", hr); return NULL; } jstring guid = makeGUIDString(env, libAttr->guid); jclass autoClass = env->FindClass("org/racob/com/TypeLib"); jmethodID autoCons = env->GetMethodID(autoClass, "<init>", "(IILjava/lang/String;IIII)V"); jobject newAuto = env->NewObject(autoClass, autoCons, (jint) typeLib, index, guid, typeCount, libAttr->wLibFlags, libAttr->wMajorVerNum, libAttr->wMinorVerNum); typeLib->ReleaseTLibAttr(libAttr); return newAuto; }
CJSProxyObj::CJSProxyObj(CJSExtender* _pJSExtender, IDispatch *pDisp, const GUID iid, CString strPrefix) : m_dwCookie(0xFEFEFEFE), m_pDisp(pDisp), m_EventIID(iid) { m_pEventObj = nullptr; ITypeInfo* pTypeInfo = nullptr; m_pJSExtender = _pJSExtender; if (theApp.m_pEventProxy) { m_pEventObj = theApp.m_pEventProxy; theApp.m_pEventProxy = nullptr; } else { pDisp->GetTypeInfo(0, GetUserDefaultLCID(), &pTypeInfo); if (pTypeInfo) { CComPtr<ITypeLib> pTypeLib; UINT nIndex = 0; pTypeInfo->GetContainingTypeLib(&pTypeLib, &nIndex); pTypeLib->GetTypeInfoOfGuid(iid, &m_pTypeInfo); pTypeInfo->Release(); } } CString strName = strPrefix; auto it = m_pJSExtender->m_mapCloudJSObject.find(strName); if (it != m_pJSExtender->m_mapCloudJSObject.end()) { int nSize = m_pJSExtender->m_mapCloudJSObject.size(); CString s = _T(""); s.Format(_T("%s_%d_"), strName, nSize); strName = s; } m_bstrPrefix = CComBSTR(strName); SetEventNames(); m_pJSExtender->m_mapCloudJSObject[strName] = this; HRESULT hr = AtlAdvise(m_pDisp, this, m_EventIID, &m_dwCookie); }
ITypeInfo *tCOMUtil::GetCoClassTypeInfo(IDispatch* pdisp, CLSID clsid) { CHECKPARAM(pdisp); ITypeInfo* typeinfo = NULL; ITypeLib* typelib = NULL; HRESULT hr = S_OK; { unsigned int typeinfocount = 0; hr = pdisp->GetTypeInfoCount(&typeinfocount); if(FAILED(hr) || typeinfocount == 0) return NULL; } hr = pdisp->GetTypeInfo(0, 0, &typeinfo); if(FAILED(hr)) return NULL; { unsigned int dumb_index = -1; hr = typeinfo->GetContainingTypeLib(&typelib, &dumb_index); COM_RELEASE(typeinfo); } if(FAILED(hr)) return NULL; ITypeInfo* coclasstypeinfo = tCOMUtil::GetCoClassTypeInfo(typelib, clsid); typelib->Release(); return coclasstypeinfo; }
PyObject *PyITypeInfo::GetContainingTypeLib() { // BUGBUG?? // Note that since we do not check to see if there is already a Python // object corresponding to the returned typelib, we could theoretically // end up with multiple Python objects pointing to the same OLE objects // Maybe we should to keep a global mapping of C/C++/OLE objects by // their memory address onto Python objects (by their memory address). ITypeInfo *pMyTypeInfo = GetI(this); if (pMyTypeInfo==NULL) return NULL; ITypeLib *ptlib; unsigned index; PY_INTERFACE_PRECALL; SCODE sc = pMyTypeInfo->GetContainingTypeLib(&ptlib, &index); PY_INTERFACE_POSTCALL; if (FAILED(sc)) return PyCom_BuildPyException(sc, pMyTypeInfo, IID_ITypeInfo); PyObject *ret = PyTuple_New(2); PyTuple_SetItem(ret, 0, PyCom_PyObjectFromIUnknown(ptlib, IID_ITypeLib)); PyTuple_SetItem(ret, 1, PyInt_FromLong(index)); return ret; }
ITypeInfo *tCOMUtil::GetDispatchTypeInfo(IDispatch* pdisp) { ITypeInfo* typeinfo = NULL; HRESULT hr = pdisp->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, &typeinfo); if(FAILED(hr)) return NULL; TYPEATTR *ptypeattr = NULL; typeinfo->GetTypeAttr(&ptypeattr); TYPEKIND typekind = ptypeattr->typekind; if(typekind == TKIND_DISPATCH) { typeinfo->ReleaseTypeAttr(ptypeattr); return typeinfo; } // tries to find another description of the same // interface in the typelib with TKIND_DISPATCH ITypeLib *ptypelib = NULL; unsigned int dumb = 0; IID iid = ptypeattr->guid; hr = typeinfo->GetContainingTypeLib(&ptypelib, &dumb); typeinfo->ReleaseTypeAttr(ptypeattr); // if there's no containing type lib, we have to // trust this one is the right type info if(FAILED(hr)) return typeinfo; // obtem a typeinfo do iid fornecido // caso haja uma implementacao dispinterface, // esta' e' que sera' retornada (segundo // documentacao do ActiveX ITypeInfo* typeinfo_guid = NULL; hr = ptypelib->GetTypeInfoOfGuid(iid, &typeinfo_guid); if(FAILED(hr)) { ptypelib->Release(); return typeinfo; } // verifica se e' dispinterface TYPEATTR *ptypeattr_iface = NULL; hr = typeinfo_guid->GetTypeAttr(&ptypeattr_iface); TYPEKIND typekind_iface = ptypeattr_iface->typekind; typeinfo_guid->ReleaseTypeAttr(ptypeattr_iface); if(typekind_iface == TKIND_DISPATCH) { // releases original type information COM_RELEASE(typeinfo); return typeinfo_guid; } else { COM_RELEASE(typeinfo_guid); // returns original type info return typeinfo; } }
QString qax_generateDocumentation(QAxBase *that) { that->metaObject(); if (that->isNull()) return QString(); ITypeInfo *typeInfo = 0; IDispatch *dispatch = 0; that->queryInterface(IID_IDispatch, (void**)&dispatch); if (dispatch) dispatch->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, &typeInfo); QString docu; QTextStream stream(&docu, QIODevice::WriteOnly); const QMetaObject *mo = that->metaObject(); QString coClass = QLatin1String(mo->classInfo(mo->indexOfClassInfo("CoClass")).value()); stream << "<h1 align=center>" << coClass << " Reference</h1>" << endl; stream << "<p>The " << coClass << " COM object is a " << that->qObject()->metaObject()->className(); stream << " with the CLSID " << that->control() << ".</p>" << endl; stream << "<h3>Interfaces</h3>" << endl; stream << "<ul>" << endl; const char *inter = 0; int interCount = 1; while ((inter = mo->classInfo(mo->indexOfClassInfo("Interface " + QByteArray::number(interCount))).value())) { stream << "<li>" << inter << endl; interCount++; } stream << "</ul>" << endl; stream << "<h3>Event Interfaces</h3>" << endl; stream << "<ul>" << endl; interCount = 1; while ((inter = mo->classInfo(mo->indexOfClassInfo("Event Interface " + QByteArray::number(interCount))).value())) { stream << "<li>" << inter << endl; interCount++; } stream << "</ul>" << endl; QList<QString> methodDetails, propDetails; const int slotCount = mo->methodCount(); if (slotCount) { stream << "<h2>Public Slots:</h2>" << endl; stream << "<ul>" << endl; int defArgCount = 0; for (int islot = mo->methodOffset(); islot < slotCount; ++islot) { const QMetaMethod slot = mo->method(islot); if (slot.methodType() != QMetaMethod::Slot) continue; if (slot.attributes() & QMetaMethod::Cloned) { ++defArgCount; continue; } QByteArray returntype(slot.typeName()); if (returntype.isEmpty()) returntype = "void"; QByteArray prototype = namedPrototype(slot.parameterTypes(), slot.parameterNames(), defArgCount); QByteArray signature = slot.methodSignature(); QByteArray name = signature.left(signature.indexOf('(')); stream << "<li>" << returntype << " <a href=\"#" << name << "\"><b>" << name << "</b></a>" << prototype << ";</li>" << endl; prototype = namedPrototype(slot.parameterTypes(), slot.parameterNames()); QString detail = QString::fromLatin1("<h3><a name=") + QString::fromLatin1(name.constData()) + QLatin1String("></a>") + QLatin1String(returntype.constData()) + QLatin1Char(' ') + QLatin1String(name.constData()) + QLatin1Char(' ') + QString::fromLatin1(prototype.constData()) + QLatin1String("<tt> [slot]</tt></h3>\n"); prototype = namedPrototype(slot.parameterTypes(), QList<QByteArray>()); detail += docuFromName(typeInfo, QString::fromLatin1(name.constData())); detail += QLatin1String("<p>Connect a signal to this slot:<pre>\n"); detail += QString::fromLatin1("\tQObject::connect(sender, SIGNAL(someSignal") + QString::fromLatin1(prototype.constData()) + QLatin1String("), object, SLOT(") + QString::fromLatin1(name.constData()) + QString::fromLatin1(prototype.constData()) + QLatin1String("));"); detail += QLatin1String("</pre>\n"); if (1) { detail += QLatin1String("<p>Or call the function directly:<pre>\n"); bool hasParams = slot.parameterTypes().count() != 0; if (hasParams) detail += QLatin1String("\tQVariantList params = ...\n"); detail += QLatin1String("\t"); QByteArray functionToCall = "dynamicCall"; if (returntype == "IDispatch*" || returntype == "IUnknown*") { functionToCall = "querySubObject"; returntype = "QAxObject *"; } if (returntype != "void") detail += QLatin1String(returntype.constData()) + QLatin1String(" result = "); detail += QLatin1String("object->") + QLatin1String(functionToCall.constData()) + QLatin1String("(\"" + name + prototype + '\"'); if (hasParams) detail += QLatin1String(", params"); detail += QLatin1Char(')'); if (returntype != "void" && returntype != "QAxObject *" && returntype != "QVariant") detail += QLatin1Char('.') + QLatin1String(toType(returntype)); detail += QLatin1String(";</pre>\n"); } else { detail += QLatin1String("<p>This function has parameters of unsupported types and cannot be called directly."); } methodDetails << detail; defArgCount = 0; } stream << "</ul>" << endl; } int signalCount = mo->methodCount(); if (signalCount) { ITypeLib *typeLib = 0; if (typeInfo) { UINT index = 0; typeInfo->GetContainingTypeLib(&typeLib, &index); typeInfo->Release(); } typeInfo = 0; stream << "<h2>Signals:</h2>" << endl; stream << "<ul>" << endl; for (int isignal = mo->methodOffset(); isignal < signalCount; ++isignal) { const QMetaMethod signal(mo->method(isignal)); if (signal.methodType() != QMetaMethod::Signal) continue; QByteArray prototype = namedPrototype(signal.parameterTypes(), signal.parameterNames()); QByteArray signature = signal.methodSignature(); QByteArray name = signature.left(signature.indexOf('(')); stream << "<li>void <a href=\"#" << name << "\"><b>" << name << "</b></a>" << prototype << ";</li>" << endl; QString detail = QLatin1String("<h3><a name=") + QLatin1String(name.constData()) + QLatin1String("></a>void ") + QLatin1String(name.constData()) + QLatin1Char(' ') + QLatin1String(prototype.constData()) + QLatin1String("<tt> [signal]</tt></h3>\n"); if (typeLib) { interCount = 0; do { if (typeInfo) typeInfo->Release(); typeInfo = 0; typeLib->GetTypeInfo(++interCount, &typeInfo); QString typeLibDocu = docuFromName(typeInfo, QString::fromLatin1(name.constData())); if (!typeLibDocu.isEmpty()) { detail += typeLibDocu; break; } } while (typeInfo); } prototype = namedPrototype(signal.parameterTypes(), QList<QByteArray>()); detail += QLatin1String("<p>Connect a slot to this signal:<pre>\n"); detail += QLatin1String("\tQObject::connect(object, SIGNAL(") + QString::fromLatin1(name.constData()) + QString::fromLatin1(prototype.constData()) + QLatin1String("), receiver, SLOT(someSlot") + QString::fromLatin1(prototype.constData()) + QLatin1String("));"); detail += QLatin1String("</pre>\n"); methodDetails << detail; if (typeInfo) typeInfo->Release(); typeInfo = 0; } stream << "</ul>" << endl; if (typeLib) typeLib->Release(); } const int propCount = mo->propertyCount(); if (propCount) { if (dispatch) dispatch->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, &typeInfo); stream << "<h2>Properties:</h2>" << endl; stream << "<ul>" << endl; for (int iprop = 0; iprop < propCount; ++iprop) { const QMetaProperty prop = mo->property(iprop); QByteArray name(prop.name()); QByteArray type(prop.typeName()); stream << "<li>" << type << " <a href=\"#" << name << "\"><b>" << name << "</b></a>;</li>" << endl; QString detail = QLatin1String("<h3><a name=") + QString::fromLatin1(name.constData()) + QLatin1String("></a>") + QLatin1String(type.constData()) + QLatin1Char(' ') + QLatin1String(name.constData()) + QLatin1String("</h3>\n"); detail += docuFromName(typeInfo, QString::fromLatin1(name)); QVariant::Type vartype = QVariant::nameToType(type); if (!prop.isReadable()) continue; if (prop.isEnumType()) vartype = QVariant::Int; if (vartype != QVariant::Invalid) { detail += QLatin1String("<p>Read this property's value using QObject::property:<pre>\n"); if (prop.isEnumType()) detail += QLatin1String("\tint val = "); else detail += QLatin1Char('\t') + QLatin1String(type.constData()) + QLatin1String(" val = "); detail += QLatin1String("object->property(\"") + QLatin1String(name.constData()) + QLatin1String("\").") + QLatin1String(toType(type).constData()) + QLatin1String(";\n"); detail += QLatin1String("</pre>\n"); } else if (type == "IDispatch*" || type == "IUnknown*") { detail += QLatin1String("<p>Get the subobject using querySubObject:<pre>\n"); detail += QLatin1String("\tQAxObject *") + QLatin1String(name.constData()) + QLatin1String(" = object->querySubObject(\"") + QLatin1String(name.constData()) + QLatin1String("\");\n"); detail += QLatin1String("</pre>\n"); } else { detail += QLatin1String("<p>This property is of an unsupported type.\n"); } if (prop.isWritable()) { detail += QLatin1String("Set this property' value using QObject::setProperty:<pre>\n"); if (prop.isEnumType()) { detail += QLatin1String("\tint newValue = ... // string representation of values also supported\n"); } else { detail += QLatin1String("\t") + QString::fromLatin1(type.constData()) + QLatin1String(" newValue = ...\n"); } detail += QLatin1String("\tobject->setProperty(\"") + QString::fromLatin1(name) + QLatin1String("\", newValue);\n"); detail += QLatin1String("</pre>\n"); detail += QLatin1String("Or using the "); QByteArray setterSlot; if (isupper(name.at(0))) { setterSlot = "Set" + name; } else { QByteArray nameUp = name; nameUp[0] = toupper(nameUp.at(0)); setterSlot = "set" + nameUp; } detail += QLatin1String("<a href=\"#") + QString::fromLatin1(setterSlot) + QLatin1String("\">") + QString::fromLatin1(setterSlot.constData()) + QLatin1String("</a> slot.\n"); } if (prop.isEnumType()) { detail += QLatin1String("<p>See also <a href=\"#") + QString::fromLatin1(type) + QLatin1String("\">") + QString::fromLatin1(type) + QLatin1String("</a>.\n"); } propDetails << detail; } stream << "</ul>" << endl; } const int enumCount = mo->enumeratorCount(); if (enumCount) { stream << "<hr><h2>Member Type Documentation</h2>" << endl; for (int i = 0; i < enumCount; ++i) { const QMetaEnum enumdata = mo->enumerator(i); stream << "<h3><a name=" << enumdata.name() << "></a>" << enumdata.name() << "</h3>" << endl; stream << "<ul>" << endl; for (int e = 0; e < enumdata.keyCount(); ++e) { stream << "<li>" << enumdata.key(e) << "\t=" << enumdata.value(e) << "</li>" << endl; } stream << "</ul>" << endl; } } if (methodDetails.count()) { stream << "<hr><h2>Member Function Documentation</h2>" << endl; for (int i = 0; i < methodDetails.count(); ++i) stream << methodDetails.at(i) << endl; } if (propDetails.count()) { stream << "<hr><h2>Property Documentation</h2>" << endl; for (int i = 0; i < propDetails.count(); ++i) stream << propDetails.at(i) << endl; } if (typeInfo) typeInfo->Release(); if (dispatch) dispatch->Release(); return docu; }