#include "qaxbindable.h"
#include "qaxfactory.h"
#ifndef QT_NO_WIN_ACTIVEQT
#include <qapplication.h>
#include <qdatetime.h>
#include <qdir.h>
#include <qmap.h>
#include <qmenubar.h>
#include <qmetaobject.h>
#include <qsettings.h>
#include <qvariant.h>
#include <qtextstream.h>
#include <qt_windows.h>
#include <olectl.h>
QT_BEGIN_NAMESPACE
#define Q_REQUIRED_RPCNDR_H_VERSION 475
// Some global variables to store module information
bool qAxIsServer = false;
HANDLE qAxInstance = 0;
ITypeLib *qAxTypeLibrary = 0;
wchar_t qAxModuleFilename[MAX_PATH];
bool qAxOutProcServer = false;
// The QAxFactory instance
static QAxFactory* qax_factory = 0;
extern CLSID CLSID_QRect;
extern CLSID CLSID_QSize;
extern CLSID CLSID_QPoint;
extern void qax_shutDown();
extern bool qax_ownQApp;
extern QAxFactory *qax_instantiate();
QAxFactory *qAxFactory()
{
if (!qax_factory) {
bool hadQApp = qApp != 0;
qax_factory = qax_instantiate();
// QAxFactory created a QApplication
if (!hadQApp && qApp)
qax_ownQApp = true;
// register all types with metatype system as pointers
QStringList keys(qax_factory->featureList());
for (int i = 0; i < keys.count(); ++i) {
QString key(keys.at(i));
qRegisterMetaType((key + QLatin1Char('*')).toLatin1(), (void**)0);
}
}
return qax_factory;
}
// Some local variables to handle module lifetime
static unsigned long qAxModuleRef = 0;
static CRITICAL_SECTION qAxModuleSection;
/////////////////////////////////////////////////////////////////////////////
// Server control
/////////////////////////////////////////////////////////////////////////////
static int initCount = 0;
QString qAxInit()
{
static QString libFile;
if (initCount++)
return libFile;
InitializeCriticalSection(&qAxModuleSection);
libFile = QString::fromWCharArray(qAxModuleFilename);
libFile = libFile.toLower();
if (LoadTypeLibEx((wchar_t*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK)
return libFile;
int lastDot = libFile.lastIndexOf(QLatin1Char('.'));
libFile = libFile.left(lastDot) + QLatin1String(".tlb");
if (LoadTypeLibEx((wchar_t*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK)
return libFile;
lastDot = libFile.lastIndexOf(QLatin1Char('.'));
libFile = libFile.left(lastDot) + QLatin1String(".olb");
if (LoadTypeLibEx((wchar_t*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK)
return libFile;
libFile = QString();
return libFile;
}
void qAxCleanup()
{
if (!initCount)
qWarning("qAxInit/qAxCleanup mismatch");
if (--initCount)
return;
delete qax_factory;
qax_factory = 0;
if (qAxTypeLibrary) {
qAxTypeLibrary->Release();
qAxTypeLibrary = 0;
}
DeleteCriticalSection(&qAxModuleSection);
}
unsigned long qAxLock()
{
EnterCriticalSection(&qAxModuleSection);
unsigned long ref = ++qAxModuleRef;
LeaveCriticalSection(&qAxModuleSection);
return ref;
}
unsigned long qAxUnlock()
{
if (!initCount) // cleaned up already
return 0;
EnterCriticalSection(&qAxModuleSection);
unsigned long ref = --qAxModuleRef;
LeaveCriticalSection(&qAxModuleSection);
if (!ref)
qax_shutDown();
return ref;
}
unsigned long qAxLockCount()
{
return qAxModuleRef;
}
/////////////////////////////////////////////////////////////////////////////
// Registry
/////////////////////////////////////////////////////////////////////////////
extern bool qax_disable_inplaceframe;
QString qax_clean_type(const QString &type, const QMetaObject *mo)
{
if (mo) {
int classInfoIdx = mo->indexOfClassInfo("CoClassAlias");
if (classInfoIdx != -1) {
const QMetaClassInfo classInfo = mo->classInfo(classInfoIdx);
return QLatin1String(classInfo.value());
}
}
QString alias(type);
alias.remove(QLatin1String("::"));
return alias;
}
// (Un)Register the ActiveX server in the registry.
// The QAxFactory implementation provides the information.
HRESULT UpdateRegistry(BOOL bRegister)
{
qAxIsServer = false;
QString file = QString::fromWCharArray(qAxModuleFilename);
QString path = file.left(file.lastIndexOf(QLatin1Char('\\'))+1);
QString module = file.right(file.length() - path.length());
module = module.left(module.lastIndexOf(QLatin1Char('.')));
const QString appId = qAxFactory()->appID().toString().toUpper();
const QString libId = qAxFactory()->typeLibID().toString().toUpper();
QString libFile = qAxInit();
QString typeLibVersion;
TLIBATTR *libAttr = 0;
if (qAxTypeLibrary)
qAxTypeLibrary->GetLibAttr(&libAttr);
if (!libAttr)
return SELFREG_E_TYPELIB;
DWORD major = libAttr->wMajorVerNum;
DWORD minor = libAttr->wMinorVerNum;
typeLibVersion = QString::number((uint)major) + QLatin1Char('.') + QString::number((uint)minor);
if (bRegister)
RegisterTypeLib(qAxTypeLibrary, (wchar_t*)libFile.utf16(), 0);
else
UnRegisterTypeLib(libAttr->guid, libAttr->wMajorVerNum, libAttr->wMinorVerNum, libAttr->lcid, libAttr->syskind);
qAxTypeLibrary->ReleaseTLibAttr(libAttr);
if (typeLibVersion.isEmpty())
typeLibVersion = QLatin1String("1.0");
// 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"));
QSettings test(keyPath, QSettings::NativeFormat);
if (!test.isWritable())
keyPath = QLatin1String("HKEY_CURRENT_USER\\Software\\Classes");
QSettings settings(keyPath, QSettings::NativeFormat);
// we try to create the ActiveX widgets later on...
bool delete_qApp = false;
if (!qApp) {
int argc = 0;
(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);
}
QStringList keys = qAxFactory()->featureList();
for (QStringList::Iterator key = keys.begin(); key != keys.end(); ++key) {
QString className = *key;
QObject *object = qAxFactory()->createObject(className);
const QMetaObject *mo = qAxFactory()->metaObject(className);
const QString classId = qAxFactory()->classID(className).toString().toUpper();
className = qax_clean_type(className, 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();
const QString classMajorVersion = classVersion.left(classVersion.indexOf(QLatin1Char('.')));
uint olemisc = OLEMISC_SETCLIENTSITEFIRST
|OLEMISC_ACTIVATEWHENVISIBLE
|OLEMISC_INSIDEOUT
|OLEMISC_CANTLINKINSIDE
|OLEMISC_RECOMPOSEONRESIZE;
if (!control)
olemisc |= OLEMISC_INVISIBLEATRUNTIME;
else if (qFindChild<QMenuBar*>(object) && !qax_disable_inplaceframe)
olemisc |= OLEMISC_WANTSTOMENUMERGE;
settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/."), className + QLatin1String(" Class"));
评论0