src/activeqt/control/qaxserver.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the ActiveQt framework of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:BSD$
       
    10 ** You may use this file under the terms of the BSD license as follows:
       
    11 **
       
    12 ** "Redistribution and use in source and binary forms, with or without
       
    13 ** modification, are permitted provided that the following conditions are
       
    14 ** met:
       
    15 **   * Redistributions of source code must retain the above copyright
       
    16 **     notice, this list of conditions and the following disclaimer.
       
    17 **   * Redistributions in binary form must reproduce the above copyright
       
    18 **     notice, this list of conditions and the following disclaimer in
       
    19 **     the documentation and/or other materials provided with the
       
    20 **     distribution.
       
    21 **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
       
    22 **     the names of its contributors may be used to endorse or promote
       
    23 **     products derived from this software without specific prior written
       
    24 **     permission.
       
    25 **
       
    26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
    27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
    28 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
    29 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
       
    30 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    31 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
    32 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    33 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    34 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    35 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    36 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
       
    37 ** $QT_END_LICENSE$
       
    38 **
       
    39 ****************************************************************************/
       
    40 
       
    41 #include "qaxbindable.h"
       
    42 #include "qaxfactory.h"
       
    43 
       
    44 #ifndef QT_NO_WIN_ACTIVEQT
       
    45 
       
    46 #include <qapplication.h>
       
    47 #include <qdatetime.h>
       
    48 #include <qdir.h>
       
    49 #include <qmap.h>
       
    50 #include <qmenubar.h>
       
    51 #include <qmetaobject.h>
       
    52 #include <qsettings.h>
       
    53 #include <qvariant.h>
       
    54 #include <qtextstream.h>
       
    55 
       
    56 #include <qt_windows.h>
       
    57 #include <olectl.h>
       
    58 
       
    59 QT_BEGIN_NAMESPACE
       
    60 
       
    61 #define Q_REQUIRED_RPCNDR_H_VERSION 475
       
    62 
       
    63 // Some global variables to store module information
       
    64 bool qAxIsServer = false;
       
    65 HANDLE qAxInstance = 0;
       
    66 ITypeLib *qAxTypeLibrary = 0;
       
    67 wchar_t qAxModuleFilename[MAX_PATH];
       
    68 bool qAxOutProcServer = false;
       
    69 
       
    70 // The QAxFactory instance
       
    71 static QAxFactory* qax_factory = 0;
       
    72 extern CLSID CLSID_QRect;
       
    73 extern CLSID CLSID_QSize;
       
    74 extern CLSID CLSID_QPoint;
       
    75 extern void qax_shutDown();
       
    76 extern bool qax_ownQApp;
       
    77 
       
    78 
       
    79 extern QAxFactory *qax_instantiate();
       
    80 
       
    81 QAxFactory *qAxFactory()
       
    82 {
       
    83     if (!qax_factory) {
       
    84         bool hadQApp = qApp != 0;
       
    85         qax_factory = qax_instantiate();
       
    86         // QAxFactory created a QApplication
       
    87         if (!hadQApp && qApp)
       
    88             qax_ownQApp = true;
       
    89 
       
    90         // register all types with metatype system as pointers
       
    91         QStringList keys(qax_factory->featureList());
       
    92         for (int i = 0; i < keys.count(); ++i) {
       
    93             QString key(keys.at(i));
       
    94             qRegisterMetaType((key + QLatin1Char('*')).toLatin1(), (void**)0);
       
    95         }
       
    96     }
       
    97     return qax_factory;
       
    98 }
       
    99 
       
   100 // Some local variables to handle module lifetime
       
   101 static unsigned long qAxModuleRef = 0;
       
   102 static CRITICAL_SECTION qAxModuleSection;
       
   103 
       
   104 
       
   105 /////////////////////////////////////////////////////////////////////////////
       
   106 // Server control
       
   107 /////////////////////////////////////////////////////////////////////////////
       
   108 
       
   109 static int initCount = 0;
       
   110 
       
   111 QString qAxInit()
       
   112 {
       
   113     static QString libFile;
       
   114 
       
   115     if (initCount++)
       
   116         return libFile;
       
   117     
       
   118     InitializeCriticalSection(&qAxModuleSection);
       
   119     
       
   120     libFile = QString::fromWCharArray(qAxModuleFilename);
       
   121     libFile = libFile.toLower();
       
   122     if (LoadTypeLibEx((wchar_t*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK)
       
   123         return libFile;
       
   124 
       
   125     int lastDot = libFile.lastIndexOf(QLatin1Char('.'));
       
   126     libFile = libFile.left(lastDot) + QLatin1String(".tlb");
       
   127     if (LoadTypeLibEx((wchar_t*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK)
       
   128         return libFile;
       
   129 
       
   130     lastDot = libFile.lastIndexOf(QLatin1Char('.'));
       
   131     libFile = libFile.left(lastDot) + QLatin1String(".olb");
       
   132     if (LoadTypeLibEx((wchar_t*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK)
       
   133         return libFile;
       
   134 
       
   135     libFile = QString();
       
   136     return libFile;
       
   137 }
       
   138 
       
   139 void qAxCleanup()
       
   140 {
       
   141     if (!initCount)
       
   142         qWarning("qAxInit/qAxCleanup mismatch");
       
   143     
       
   144     if (--initCount)
       
   145         return;
       
   146 
       
   147     delete qax_factory;
       
   148     qax_factory = 0;
       
   149     
       
   150     if (qAxTypeLibrary) {
       
   151         qAxTypeLibrary->Release();
       
   152         qAxTypeLibrary = 0;
       
   153     }
       
   154     
       
   155     DeleteCriticalSection(&qAxModuleSection);
       
   156 }
       
   157 
       
   158 unsigned long qAxLock()
       
   159 {
       
   160     EnterCriticalSection(&qAxModuleSection);
       
   161     unsigned long ref = ++qAxModuleRef;
       
   162     LeaveCriticalSection(&qAxModuleSection);
       
   163     return ref;
       
   164 }
       
   165 
       
   166 unsigned long qAxUnlock()
       
   167 {
       
   168     if (!initCount) // cleaned up already
       
   169         return 0;
       
   170 
       
   171     EnterCriticalSection(&qAxModuleSection);
       
   172     unsigned long ref = --qAxModuleRef;
       
   173     LeaveCriticalSection(&qAxModuleSection);
       
   174     
       
   175     if (!ref)
       
   176         qax_shutDown();
       
   177     return ref;
       
   178 }
       
   179 
       
   180 unsigned long qAxLockCount()
       
   181 {
       
   182     return qAxModuleRef;
       
   183 }
       
   184 
       
   185 /////////////////////////////////////////////////////////////////////////////
       
   186 // Registry
       
   187 /////////////////////////////////////////////////////////////////////////////
       
   188 
       
   189 extern bool qax_disable_inplaceframe;
       
   190 
       
   191 QString qax_clean_type(const QString &type, const QMetaObject *mo)
       
   192 {
       
   193     if (mo) {
       
   194         int classInfoIdx = mo->indexOfClassInfo("CoClassAlias");
       
   195         if (classInfoIdx != -1) {
       
   196             const QMetaClassInfo classInfo = mo->classInfo(classInfoIdx);
       
   197             return QLatin1String(classInfo.value());
       
   198         }
       
   199     }
       
   200 
       
   201     QString alias(type);
       
   202     alias.remove(QLatin1String("::"));
       
   203     return alias;
       
   204 }
       
   205 
       
   206 // (Un)Register the ActiveX server in the registry.
       
   207 // The QAxFactory implementation provides the information.
       
   208 HRESULT UpdateRegistry(BOOL bRegister)
       
   209 {
       
   210     qAxIsServer = false;
       
   211     QString file = QString::fromWCharArray(qAxModuleFilename);
       
   212     QString path = file.left(file.lastIndexOf(QLatin1Char('\\'))+1);
       
   213     QString module = file.right(file.length() - path.length());
       
   214     module = module.left(module.lastIndexOf(QLatin1Char('.')));
       
   215     
       
   216     const QString appId = qAxFactory()->appID().toString().toUpper();
       
   217     const QString libId = qAxFactory()->typeLibID().toString().toUpper();
       
   218     
       
   219     QString libFile = qAxInit();
       
   220     QString typeLibVersion;
       
   221 
       
   222     TLIBATTR *libAttr = 0;
       
   223     if (qAxTypeLibrary)
       
   224         qAxTypeLibrary->GetLibAttr(&libAttr);
       
   225     if (!libAttr)
       
   226         return SELFREG_E_TYPELIB;
       
   227 
       
   228     DWORD major = libAttr->wMajorVerNum;
       
   229     DWORD minor = libAttr->wMinorVerNum;
       
   230     typeLibVersion = QString::number((uint)major) + QLatin1Char('.') + QString::number((uint)minor);
       
   231 
       
   232     if (bRegister)
       
   233         RegisterTypeLib(qAxTypeLibrary, (wchar_t*)libFile.utf16(), 0);
       
   234     else
       
   235         UnRegisterTypeLib(libAttr->guid, libAttr->wMajorVerNum, libAttr->wMinorVerNum, libAttr->lcid, libAttr->syskind);
       
   236 
       
   237     qAxTypeLibrary->ReleaseTLibAttr(libAttr);
       
   238 
       
   239     if (typeLibVersion.isEmpty())
       
   240         typeLibVersion = QLatin1String("1.0");
       
   241 
       
   242     // check whether the user has permission to write to HKLM\Software\Classes
       
   243     // if not, use HKCU\Software\Classes
       
   244     QString keyPath(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes"));
       
   245     QSettings test(keyPath, QSettings::NativeFormat);
       
   246     if (!test.isWritable())
       
   247         keyPath = QLatin1String("HKEY_CURRENT_USER\\Software\\Classes");
       
   248 
       
   249     QSettings settings(keyPath, QSettings::NativeFormat);
       
   250     
       
   251     // we try to create the ActiveX widgets later on...
       
   252     bool delete_qApp = false;
       
   253     if (!qApp) {
       
   254         int argc = 0;
       
   255         (void)new QApplication(argc, 0);
       
   256         delete_qApp = true;
       
   257     }
       
   258     
       
   259     if (bRegister) {
       
   260         if (qAxOutProcServer) {
       
   261             settings.setValue(QLatin1String("/AppID/") + appId + QLatin1String("/."), module);
       
   262             settings.setValue(QLatin1String("/AppID/") + module + QLatin1String(".EXE/AppID"), appId);
       
   263         }
       
   264 
       
   265         QStringList keys = qAxFactory()->featureList();
       
   266         for (QStringList::Iterator key = keys.begin(); key != keys.end(); ++key) {
       
   267             QString className = *key;
       
   268             QObject *object = qAxFactory()->createObject(className);
       
   269             const QMetaObject *mo = qAxFactory()->metaObject(className);
       
   270             const QString classId = qAxFactory()->classID(className).toString().toUpper();
       
   271 
       
   272             className = qax_clean_type(className, mo);
       
   273 
       
   274             if (object) { // don't register subobject classes
       
   275                 QString classVersion = mo ? QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("Version")).value()) : QString();
       
   276                 if (classVersion.isNull())
       
   277                     classVersion = QLatin1String("1.0");
       
   278                 bool insertable = mo && !qstricmp(mo->classInfo(mo->indexOfClassInfo("Insertable")).value(), "yes");
       
   279                 bool control = object->isWidgetType();
       
   280                 const QString classMajorVersion = classVersion.left(classVersion.indexOf(QLatin1Char('.')));
       
   281                 uint olemisc = OLEMISC_SETCLIENTSITEFIRST
       
   282                     |OLEMISC_ACTIVATEWHENVISIBLE
       
   283                     |OLEMISC_INSIDEOUT
       
   284                     |OLEMISC_CANTLINKINSIDE
       
   285                     |OLEMISC_RECOMPOSEONRESIZE;
       
   286                 if (!control)
       
   287                     olemisc |= OLEMISC_INVISIBLEATRUNTIME;
       
   288                 else if (qFindChild<QMenuBar*>(object) && !qax_disable_inplaceframe)
       
   289                     olemisc |= OLEMISC_WANTSTOMENUMERGE;
       
   290                 
       
   291                 settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/."), className + QLatin1String(" Class"));
       
   292                 settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/CLSID/."), classId);
       
   293                 if (insertable)
       
   294                     settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/Insertable/."), QVariant(QLatin1String("")));
       
   295                 
       
   296                 settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/."), className + QLatin1String(" Class"));
       
   297                 settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/CLSID/."), classId);
       
   298                 settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/CurVer/."), module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion);
       
   299                 
       
   300                 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/."), className + QLatin1String(" Class"));
       
   301                 if (file.endsWith(QLatin1String("exe"), Qt::CaseInsensitive))
       
   302                     settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/AppID"), appId);
       
   303                 if (control)
       
   304                     settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Control/."), QVariant(QLatin1String("")));
       
   305                 if (insertable)
       
   306                     settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Insertable/."), QVariant(QLatin1String("")));
       
   307                 if (file.right(3).toLower() == QLatin1String("dll"))
       
   308                     settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/InProcServer32/."), file);
       
   309                 else
       
   310                     settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/LocalServer32/."),
       
   311                                       QLatin1Char('\"') + file + QLatin1String("\" -activex"));
       
   312                 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/."), control ? QLatin1String("1") : QLatin1String("0"));
       
   313                 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/1/."), QString::number(olemisc));
       
   314                 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Programmable/."), QVariant(QLatin1String("")));
       
   315                 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/ToolboxBitmap32/."), QLatin1Char('\"') +
       
   316                                   file + QLatin1String("\", 101"));
       
   317                 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/TypeLib/."), libId); settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Version/."), classVersion);
       
   318                 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/VersionIndependentProgID/."), module + QLatin1Char('.') + className);
       
   319                 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/ProgID/."), module + QLatin1Char('.') + className + QLatin1Char('.') + classVersion.left(classVersion.indexOf(QLatin1Char('.'))));
       
   320 
       
   321                 QString mime = QLatin1String(mo->classInfo(mo->indexOfClassInfo("MIME")).value());
       
   322                 if (!mime.isEmpty()) {
       
   323                     QStringList mimeTypes = mime.split(QLatin1Char(';'));
       
   324                     for (int m = 0; m < mimeTypes.count(); ++m) {
       
   325                         mime = mimeTypes.at(m);
       
   326                         if (mime.isEmpty())
       
   327                             continue;
       
   328                         QString extension;
       
   329                         while (mime.contains(QLatin1Char(':'))) {
       
   330                             extension = mime.mid(mime.lastIndexOf(QLatin1Char(':')) + 1);
       
   331                             mime = mime.left(mime.length() - extension.length() - 1);
       
   332                             // Prepend '.' before extension, if required.
       
   333                             extension = extension.trimmed();
       
   334                             if (extension[0] != QLatin1Char('.'))
       
   335                                 extension = QLatin1Char('.') + extension;
       
   336                         }
       
   337 
       
   338                         if (!extension.isEmpty()) {
       
   339                             settings.setValue(QLatin1Char('/') + extension + QLatin1String("/."), module + QLatin1Char('.') + className);
       
   340                             settings.setValue(QLatin1Char('/') + extension + QLatin1String("/Content Type"), mime);
       
   341 
       
   342                             mime = mime.replace(QLatin1Char('/'), QLatin1Char('\\'));
       
   343                             settings.setValue(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/CLSID"), classId);
       
   344                             settings.setValue(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/Extension"), extension);
       
   345                         }
       
   346                     }
       
   347                 }
       
   348 
       
   349                 delete object;
       
   350             }
       
   351 
       
   352             qAxFactory()->registerClass(*key, &settings);
       
   353         }
       
   354     } else {
       
   355         if (qAxOutProcServer) {
       
   356             settings.remove(QLatin1String("/AppID/") + appId + QLatin1String("/."));
       
   357             settings.remove(QLatin1String("/AppID/") + module + QLatin1String(".EXE"));
       
   358         }
       
   359         QStringList keys = qAxFactory()->featureList();
       
   360         for (QStringList::Iterator key = keys.begin(); key != keys.end(); ++key) {
       
   361             QString className = *key;
       
   362             const QMetaObject *mo = qAxFactory()->metaObject(className);
       
   363             const QString classId = qAxFactory()->classID(className).toString().toUpper();
       
   364             className = qax_clean_type(className, mo);
       
   365             
       
   366             QString classVersion = mo ? QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("Version")).value()) : QString();
       
   367             if (classVersion.isNull())
       
   368                 classVersion = QLatin1String("1.0");
       
   369             const QString classMajorVersion = classVersion.left(classVersion.indexOf(QLatin1Char('.')));
       
   370             
       
   371             qAxFactory()->unregisterClass(*key, &settings);
       
   372             
       
   373             settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/CLSID/."));
       
   374             settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/Insertable/."));
       
   375             settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/."));
       
   376             settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion);
       
   377             
       
   378             settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/CLSID/."));
       
   379             settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/CurVer/."));
       
   380             settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/."));
       
   381             settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className);
       
   382             
       
   383             settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/AppID"));
       
   384             settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/Control/."));
       
   385             settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/Insertable/."));
       
   386             settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/InProcServer32/."));
       
   387             settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/LocalServer32/."));
       
   388             settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/1/."));
       
   389             settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/."));	    
       
   390             settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/Programmable/."));
       
   391             settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/ToolboxBitmap32/."));
       
   392             settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/TypeLib/."));
       
   393             settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/Version/."));
       
   394             settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/VersionIndependentProgID/."));
       
   395             settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/ProgID/."));
       
   396             settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/."));
       
   397             settings.remove(QLatin1String("/CLSID/") + classId);
       
   398 
       
   399             QString mime = QLatin1String(mo->classInfo(mo->indexOfClassInfo("MIME")).value());
       
   400             if (!mime.isEmpty()) {
       
   401                 QStringList mimeTypes = mime.split(QLatin1Char(';'));
       
   402                 for (int m = 0; m < mimeTypes.count(); ++m) {
       
   403                     mime = mimeTypes.at(m);
       
   404                     if (mime.isEmpty())
       
   405                         continue;
       
   406                     QString extension;
       
   407                     while (mime.contains(QLatin1Char(':'))) {
       
   408                         extension = mime.mid(mime.lastIndexOf(QLatin1Char(':')) + 1);
       
   409                         mime = mime.left(mime.length() - extension.length() - 1);
       
   410                         // Prepend '.' before extension, if required.
       
   411                         extension = extension.trimmed();
       
   412                         if (extension[0] != QLatin1Char('.'))
       
   413                             extension.prepend(QLatin1Char('.'));
       
   414                     }
       
   415                     if (!extension.isEmpty()) {
       
   416                         settings.remove(QLatin1Char('/') + extension + QLatin1String("/Content Type"));
       
   417                         settings.remove(QLatin1Char('/') + extension + QLatin1String("/."));
       
   418                         settings.remove(QLatin1Char('/') + extension);
       
   419                         mime.replace(QLatin1Char('/'), QLatin1Char('\\'));
       
   420                         settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/Extension"));
       
   421                         settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/CLSID"));
       
   422                         settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/."));
       
   423                         settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime);
       
   424                     }
       
   425                 }
       
   426             }
       
   427         }
       
   428     }
       
   429     
       
   430     if (delete_qApp)
       
   431         delete qApp;
       
   432 
       
   433     qAxCleanup();
       
   434     if (settings.status() == QSettings::NoError)
       
   435         return S_OK;
       
   436     return SELFREG_E_CLASS;
       
   437 }
       
   438 
       
   439 /////////////////////////////////////////////////////////////////////////////
       
   440 // IDL generator
       
   441 /////////////////////////////////////////////////////////////////////////////
       
   442 
       
   443 static QList<QByteArray> enums;
       
   444 static QList<QByteArray> enumValues;
       
   445 static QList<QByteArray> subtypes;
       
   446 
       
   447 static const char* const type_map[][2] =
       
   448 {
       
   449     // QVariant/Qt Value data types
       
   450     { "QString",	"BSTR" },
       
   451     { "QCString",	"BSTR" },
       
   452     { "bool",		"VARIANT_BOOL" },
       
   453     { "int",		"int" },
       
   454     { "uint",		"unsigned int" },
       
   455     { "double",		"double" }, 
       
   456     { "QColor",		"OLE_COLOR" },
       
   457     { "QDate",		"DATE" },
       
   458     { "QTime",		"DATE" },
       
   459     { "QDateTime",	"DATE" },
       
   460     { "QFont",		"IFontDisp*" },
       
   461     { "QPixmap",	"IPictureDisp*" },
       
   462     { "QVariant",	"VARIANT" },
       
   463     { "QVariantList",	 "SAFEARRAY(VARIANT)" },
       
   464     { "QList<QVariant>", "SAFEARRAY(VARIANT)" },
       
   465     { "quint64",	"CY" },
       
   466     { "qint64",	        "CY" },
       
   467     { "qulonglong",	"CY" },
       
   468     { "qlonglong",	"CY" },
       
   469     { "QByteArray",	"SAFEARRAY(BYTE)" },
       
   470     { "QStringList",	"SAFEARRAY(BSTR)" },
       
   471     // Userdefined Qt datatypes - some not on Borland though
       
   472     { "QCursor",         "enum MousePointer" },
       
   473     { "Qt::FocusPolicy", "enum FocusPolicy" },
       
   474 #ifndef Q_CC_BOR
       
   475 # if __REQUIRED_RPCNDR_H_VERSION__ >= Q_REQUIRED_RPCNDR_H_VERSION
       
   476     { "QRect",		"struct QRect" },
       
   477     { "QSize",		"struct QSize" },
       
   478     { "QPoint",		"struct QPoint" },
       
   479 # endif
       
   480 #endif
       
   481     // And we support COM data types
       
   482     { "BOOL",		"BOOL" },
       
   483     { "BSTR",		"BSTR" },
       
   484     { "OLE_COLOR",	"OLE_COLOR" },
       
   485     { "DATE",		"DATE" },
       
   486     { "VARIANT",	"VARIANT" },
       
   487     { "IDispatch",	"IDispatch*" },
       
   488     { "IUnknown",	"IUnknown*" },
       
   489     { "IDispatch*",	"IDispatch*" },
       
   490     { "IUnknown*",	"IUnknown*" },
       
   491     { 0,		0 }
       
   492 };
       
   493 
       
   494 static QByteArray convertTypes(const QByteArray &qtype, bool *ok)
       
   495 {
       
   496     qRegisterMetaType("IDispatch*", (void**)0);
       
   497     qRegisterMetaType("IUnknown*", (void**)0);
       
   498 
       
   499     *ok = false;
       
   500     
       
   501     int i = 0;
       
   502     while (type_map[i][0]) {
       
   503         if (qtype == type_map[i][0] && type_map[i][1]) {
       
   504             *ok = true;
       
   505             return type_map[i][1];	    
       
   506         }
       
   507         ++i;
       
   508     }
       
   509     if (enums.contains(qtype)) {
       
   510         *ok = true;
       
   511         return "enum " + qtype;
       
   512     }
       
   513     if (subtypes.contains(qtype)) {
       
   514         *ok = true;
       
   515     } else if (qtype.endsWith('*')) {
       
   516         QByteArray cleanType = qtype.left(qtype.length() - 1);
       
   517         const QMetaObject *mo = qAxFactory()->metaObject(QString::fromLatin1(cleanType.constData()));
       
   518         if (mo) {
       
   519             cleanType = qax_clean_type(QString::fromLatin1(cleanType), mo).toLatin1();
       
   520             if (subtypes.contains(cleanType)) {
       
   521                 *ok = true;
       
   522                 return cleanType + '*';
       
   523             }
       
   524         }
       
   525     }
       
   526     return qtype;
       
   527 }
       
   528 
       
   529 static const char* const keyword_map[][2] =
       
   530 {
       
   531     { "aggregatable",	"aggregating"	    },
       
   532     { "allocate",	"alloc"		    },
       
   533     { "appobject",	"appObject"	    },
       
   534     { "arrays",		"array"		    },
       
   535     { "async",		"asynchronous"	    },
       
   536     { "bindable",	"binding"	    },
       
   537     { "Boolean",	"boolval"	    },
       
   538     { "boolean",	"boolval"	    },
       
   539     { "broadcast",	"broadCast"	    },
       
   540     { "callback",	"callBack"	    },
       
   541     { "decode",		"deCode"	    },
       
   542     { "default",	"defaulted"	    },
       
   543     { "defaultbind",	"defaultBind"	    },
       
   544     { "defaultvalue",	"defaultValue"	    },
       
   545     { "encode"		"enCode"	    },
       
   546     { "endpoint",	"endPoint"	    },
       
   547     { "hidden",		"isHidden"	    },
       
   548     { "ignore",		"ignore_"	    },
       
   549     { "local",		"local_"	    },
       
   550     { "notify",		"notify_"	    },
       
   551     { "object",		"object_"	    },
       
   552     { "optimize",	"optimize_"	    },
       
   553     { "optional",	"optional_"	    },
       
   554     { "out",		"out_"		    },
       
   555     { "pipe",		"pipe_"		    },
       
   556     { "proxy",		"proxy_"	    },
       
   557     { "ptr",		"pointer"	    },
       
   558     { "readonly",	"readOnly"	    },
       
   559     { "small",		"small_"	    },
       
   560     { "source",		"source_"	    },
       
   561     { "string",		"string_"	    },
       
   562     { "uuid",		"uuid_"		    },
       
   563     { 0,		0		    }
       
   564 };
       
   565 
       
   566 static QByteArray replaceKeyword(const QByteArray &name)
       
   567 {
       
   568     int i = 0;
       
   569     while (keyword_map[i][0]) {
       
   570         if (name == keyword_map[i][0] && keyword_map[i][1])
       
   571             return keyword_map[i][1];
       
   572         ++i;
       
   573     }
       
   574     return name;
       
   575 }
       
   576 
       
   577 static QMap<QByteArray, int> mapping;
       
   578 
       
   579 static QByteArray renameOverloads(const QByteArray &name)
       
   580 {
       
   581     QByteArray newName = name;
       
   582     
       
   583     int n = mapping.value(name);
       
   584     if (mapping.contains(name)) {
       
   585         int n = mapping.value(name);
       
   586         newName = name + '_' + QByteArray::number(n);
       
   587         mapping.insert(name, n+1);
       
   588     } else {
       
   589         mapping.insert(name, 1);
       
   590     }
       
   591     
       
   592     return newName;
       
   593 }
       
   594 
       
   595 // filter out some properties
       
   596 static const char* const ignore_props[] =
       
   597 {
       
   598     "name",
       
   599     "objectName",
       
   600     "isTopLevel",
       
   601     "isDialog",
       
   602     "isModal",
       
   603     "isPopup",
       
   604     "isDesktop",
       
   605     "geometry",
       
   606     "pos",
       
   607     "frameSize",
       
   608     "frameGeometry",
       
   609     "size",
       
   610     "sizeHint",
       
   611     "minimumSizeHint",
       
   612     "microFocusHint",
       
   613     "rect",
       
   614     "childrenRect",
       
   615     "childrenRegion",
       
   616     "minimumSize",
       
   617     "maximumSize",
       
   618     "sizeIncrement",
       
   619     "baseSize",
       
   620     "ownPalette",
       
   621     "ownFont",
       
   622     "ownCursor",
       
   623     "visibleRect",
       
   624     "isActiveWindow",
       
   625     "underMouse",
       
   626     "visible",
       
   627     "hidden",
       
   628     "minimized",
       
   629     "focus",
       
   630     "focusEnabled",
       
   631     "customWhatsThis",
       
   632     "shown",
       
   633     "windowOpacity",
       
   634     0
       
   635 };
       
   636 
       
   637 // filter out some slots
       
   638 static const char* const ignore_slots[] =
       
   639 {
       
   640     "deleteLater",
       
   641     "setMouseTracking",
       
   642     "update",
       
   643     "repaint",
       
   644     "iconify",
       
   645     "showMinimized",
       
   646     "showMaximized",
       
   647     "showFullScreen",
       
   648     "showNormal",
       
   649     "polish",
       
   650     "constPolish",
       
   651     "stackUnder",
       
   652     "setShown",
       
   653     "setHidden",
       
   654     "move_1",
       
   655     "resize_1",
       
   656     "setGeometry_1",
       
   657     0
       
   658 };
       
   659 
       
   660 static bool ignore(const char *test, const char *const *table)
       
   661 {
       
   662     if (!test)
       
   663         return true;
       
   664     int i = 0;
       
   665     while (table[i]) {
       
   666         if (!strcmp(test, table[i]))
       
   667             return true;
       
   668         ++i;
       
   669     }
       
   670     return false;
       
   671 }
       
   672 
       
   673 bool ignoreSlots(const char *test)
       
   674 {
       
   675     return ignore(test, ignore_slots);
       
   676 }
       
   677 
       
   678 bool ignoreProps(const char *test)
       
   679 {
       
   680     return ignore(test, ignore_props);
       
   681 }
       
   682 
       
   683 #define STRIPCB(x) x = x.mid(1, x.length()-2)
       
   684 
       
   685 static QByteArray prototype(const QList<QByteArray> &parameterTypes, const QList<QByteArray> &parameterNames, bool *ok)
       
   686 {
       
   687     QByteArray prototype;
       
   688     
       
   689     for (int p = 0; p < parameterTypes.count() && *ok; ++p) {
       
   690         bool out = false;
       
   691         QByteArray type(parameterTypes.at(p));
       
   692         QByteArray name(parameterNames.at(p));
       
   693         
       
   694         if (type.endsWith('&')) {
       
   695             out = true;
       
   696             type.truncate(type.length() - 1);
       
   697         } else if (type.endsWith("**")) {
       
   698             out = true;
       
   699             type.truncate(type.length() - 1);
       
   700         } else if (type.endsWith('*') && !subtypes.contains(type)) {
       
   701             type.truncate(type.length() - 1);
       
   702         }
       
   703         if (type.isEmpty()) {
       
   704             *ok = false;
       
   705             break;
       
   706         }
       
   707         type = convertTypes(type, ok);
       
   708         if (!out)
       
   709             prototype += "[in] " + type + ' ';
       
   710         else
       
   711             prototype += "[in,out] " + type + ' ';
       
   712         
       
   713         if (out)
       
   714             prototype += '*';
       
   715         if (name.isEmpty())
       
   716             prototype += 'p' + QByteArray::number(p);
       
   717         else
       
   718             prototype += "p_" + replaceKeyword(name);
       
   719         
       
   720         if (p < parameterTypes.count() - 1)
       
   721             prototype += ", ";
       
   722     }
       
   723     
       
   724     return prototype;
       
   725 }
       
   726 
       
   727 static QByteArray addDefaultArguments(const QByteArray &prototype, int numDefArgs)
       
   728 {
       
   729     // nothing to do, or unsupported anyway
       
   730     if (!numDefArgs || prototype.contains("/**"))
       
   731         return prototype;
       
   732 
       
   733     QByteArray ptype(prototype);
       
   734     int in = -1;
       
   735     while (numDefArgs) {
       
   736         in = ptype.lastIndexOf(']', in);
       
   737         ptype.replace(in, 1, ",optional]");
       
   738         in = ptype.indexOf(' ', in) + 1;
       
   739         QByteArray type = ptype.mid(in, ptype.indexOf(' ', in) - in);
       
   740         if (type == "enum")
       
   741             type += ' ' + ptype.mid(in + 5, ptype.indexOf(' ', in + 5) - in - 5);
       
   742         ptype.replace(in, type.length(), QByteArray("VARIANT /*was: ") + type + "*/");
       
   743         --numDefArgs;
       
   744     }
       
   745 
       
   746     return ptype;
       
   747 }
       
   748 
       
   749 static HRESULT classIDL(QObject *o, const QMetaObject *mo, const QString &className, bool isBindable, QTextStream &out)
       
   750 {
       
   751     int id = 1;
       
   752     int i = 0;
       
   753     if (!mo)
       
   754         return 3;
       
   755     
       
   756     QString topclass = qAxFactory()->exposeToSuperClass(className);
       
   757     if (topclass.isEmpty())
       
   758         topclass = QLatin1String("QObject");
       
   759     bool hasStockEvents = qAxFactory()->hasStockEvents(className);
       
   760     
       
   761     const QMetaObject *pmo = mo;
       
   762     do {
       
   763         pmo = pmo->superClass();
       
   764     } while (pmo && topclass != QString::fromLatin1(pmo->className()));
       
   765     
       
   766     int enumoff = pmo ? pmo->enumeratorOffset() : mo->enumeratorOffset();
       
   767     int methodoff = pmo ? pmo->methodOffset() : mo->methodOffset();
       
   768     int propoff = pmo ? pmo->propertyOffset() : mo->propertyOffset();
       
   769     
       
   770     int qtProps = 0;
       
   771     int qtSlots = 0;
       
   772 
       
   773     bool control = false;
       
   774     
       
   775     if (o && o->isWidgetType()) {
       
   776         qtProps = QWidget::staticMetaObject.propertyCount();
       
   777         qtSlots = QWidget::staticMetaObject.methodCount();
       
   778         control = true;
       
   779     }
       
   780     
       
   781     QString classID = qAxFactory()->classID(className).toString().toUpper();
       
   782     if (QUuid(classID).isNull())
       
   783         return 4;
       
   784     STRIPCB(classID);
       
   785     QString interfaceID = qAxFactory()->interfaceID(className).toString().toUpper();
       
   786     if (QUuid(interfaceID).isNull())
       
   787         return 5;
       
   788     STRIPCB(interfaceID);
       
   789     QString eventsID = qAxFactory()->eventsID(className).toString().toUpper();
       
   790     bool hasEvents = !QUuid(eventsID).isNull();
       
   791     STRIPCB(eventsID);
       
   792     
       
   793     QString cleanClassName = qax_clean_type(className, mo);
       
   794     QString defProp(QLatin1String(mo->classInfo(mo->indexOfClassInfo("DefaultProperty")).value()));
       
   795     QString defSignal(QLatin1String(mo->classInfo(mo->indexOfClassInfo("DefaultSignal")).value()));
       
   796     
       
   797     for (i = enumoff; i < mo->enumeratorCount(); ++i) {
       
   798         const QMetaEnum enumerator = mo->enumerator(i);
       
   799         if (enums.contains(enumerator.name()))
       
   800             continue;
       
   801         
       
   802         enums.append(enumerator.name());
       
   803         
       
   804         out << "\tenum " << enumerator.name() << " {" << endl;
       
   805         
       
   806         for (int j = 0; j < enumerator.keyCount(); ++j) {
       
   807             QByteArray key(enumerator.key(j));
       
   808             while (enumValues.contains(key)) {
       
   809                 key += '_';
       
   810             }
       
   811             enumValues.append(key);
       
   812             uint value = (uint)enumerator.value(j);
       
   813             key = key.leftJustified(20);
       
   814             out << "\t\t" << key << "\t= ";
       
   815             if (enumerator.isFlag())
       
   816                 out << "0x" << QByteArray::number(value, 16).rightJustified(8, '0');
       
   817             else
       
   818                 out << value;
       
   819             if (j < enumerator.keyCount()-1)
       
   820                 out << ", ";
       
   821             out << endl;
       
   822         }
       
   823         out << "\t};" << endl << endl;
       
   824     }
       
   825 
       
   826     // mouse cursor enum for QCursor support
       
   827     if (!enums.contains("MousePointer")) {
       
   828         enums.append("MousePointer");
       
   829         out << "\tenum MousePointer {" << endl;
       
   830         out << "\t\tArrowCursor             = " << Qt::ArrowCursor << ',' << endl;
       
   831         out << "\t\tUpArrowCursor           = " << Qt::UpArrowCursor << ',' << endl;
       
   832         out << "\t\tCrossCursor             = " << Qt::CrossCursor << ',' << endl;
       
   833         out << "\t\tWaitCursor              = " << Qt::WaitCursor << ',' << endl;
       
   834         out << "\t\tIBeamCursor             = " << Qt::IBeamCursor << ',' << endl;
       
   835         out << "\t\tSizeVerCursor           = " << Qt::SizeVerCursor << ',' << endl;
       
   836         out << "\t\tSizeHorCursor           = " << Qt::SizeHorCursor << ',' << endl;
       
   837         out << "\t\tSizeBDiagCursor         = " << Qt::SizeBDiagCursor << ',' << endl;
       
   838         out << "\t\tSizeFDiagCursor         = " << Qt::SizeFDiagCursor << ',' << endl;
       
   839         out << "\t\tSizeAllCursor           = " << Qt::SizeAllCursor << ',' << endl;
       
   840         out << "\t\tBlankCursor             = " << Qt::BlankCursor << ',' << endl;
       
   841         out << "\t\tSplitVCursor            = " << Qt::SplitVCursor << ',' << endl;
       
   842         out << "\t\tSplitHCursor            = " << Qt::SplitHCursor << ',' << endl;
       
   843         out << "\t\tPointingHandCursor      = " << Qt::PointingHandCursor << ',' << endl;
       
   844         out << "\t\tForbiddenCursor         = " << Qt::ForbiddenCursor << ',' << endl;
       
   845         out << "\t\tWhatsThisCursor         = " << Qt::WhatsThisCursor << ',' << endl;
       
   846         out << "\t\tBusyCursor\t= " << Qt::BusyCursor << endl;
       
   847         out << "\t};" << endl << endl;
       
   848     }
       
   849     if (!enums.contains("FocusPolicy")) {
       
   850         enums.append("FocusPolicy");
       
   851         out << "\tenum FocusPolicy {" << endl;
       
   852         out << "\t\tNoFocus             = " << Qt::NoFocus << ',' << endl;
       
   853         out << "\t\tTabFocus            = " << Qt::TabFocus << ',' << endl;
       
   854         out << "\t\tClickFocus          = " << Qt::ClickFocus << ',' << endl;
       
   855         out << "\t\tStrongFocus         = " << Qt::StrongFocus << ',' << endl;
       
   856         out << "\t\tWheelFocus          = " << Qt::WheelFocus << endl;
       
   857         out << "\t};" << endl << endl;
       
   858     }
       
   859 
       
   860     out << endl;
       
   861     out << "\t[" << endl;
       
   862     out << "\t\tuuid(" << interfaceID << ")," << endl;
       
   863     out << "\t\thelpstring(\"" << cleanClassName << " Interface\")" << endl;
       
   864     out << "\t]" << endl;
       
   865     out << "\tdispinterface I" << cleanClassName  << endl;
       
   866     out << "\t{" << endl;
       
   867     
       
   868     out << "\tproperties:" << endl;
       
   869     for (i = propoff; i < mo->propertyCount(); ++i) {
       
   870         const QMetaProperty property = mo->property(i);
       
   871         /*	if (property.testFlags(QMetaProperty::Override))
       
   872         continue;*/
       
   873         if (i <= qtProps && ignoreProps(property.name()))
       
   874             continue;
       
   875         if (!property.name() || mo->indexOfProperty(property.name()) > i)
       
   876             continue;
       
   877         
       
   878         bool ok = true;
       
   879         QByteArray type(convertTypes(property.typeName(), &ok));
       
   880         QByteArray name(replaceKeyword(property.name()));
       
   881         
       
   882         if (!ok)
       
   883             out << "\t/****** Property is of unsupported datatype" << endl;
       
   884         
       
   885         out << "\t\t[id(" << id << ')';
       
   886         if (!property.isWritable())
       
   887             out << ", readonly";
       
   888         if (isBindable && property.isScriptable(o))
       
   889             out << ", bindable";
       
   890         if (!property.isDesignable(o))
       
   891             out << ", nonbrowsable";
       
   892         if (isBindable)
       
   893             out << ", requestedit";
       
   894         if (defProp == QLatin1String(name))
       
   895             out << ", uidefault";
       
   896         out << "] " << type << ' ' << name << ';' << endl;
       
   897         
       
   898         if (!ok)
       
   899             out << "\t******/" << endl;
       
   900         ++id;
       
   901     }
       
   902     out << endl;
       
   903     out << "\tmethods:" << endl;
       
   904     int numDefArgs = 0;
       
   905     QByteArray outBuffer;
       
   906     for (i = methodoff; i < mo->methodCount(); ++i) {
       
   907         const QMetaMethod slot = mo->method(i);
       
   908         if (slot.access() != QMetaMethod::Public || slot.methodType() == QMetaMethod::Signal)
       
   909             continue;
       
   910 
       
   911         if (slot.attributes() & QMetaMethod::Cloned) {
       
   912             ++numDefArgs;
       
   913             continue;
       
   914         }
       
   915         if (!outBuffer.isEmpty()) {
       
   916             outBuffer = addDefaultArguments(outBuffer, numDefArgs);
       
   917             numDefArgs = 0;
       
   918             out << outBuffer;
       
   919             outBuffer = QByteArray();
       
   920         }
       
   921         
       
   922         QByteArray signature(slot.signature());
       
   923         QByteArray name(signature.left(signature.indexOf('(')));
       
   924         if (i <= qtSlots && ignoreSlots(name))
       
   925             continue;
       
   926 
       
   927         signature = signature.mid(name.length() + 1);
       
   928         signature.truncate(signature.length() - 1);
       
   929         name = renameOverloads(replaceKeyword(name));
       
   930         if (ignoreSlots(name))
       
   931             continue;
       
   932 
       
   933         QList<QByteArray> parameterTypes(slot.parameterTypes());
       
   934         QList<QByteArray> parameterNames(slot.parameterNames());
       
   935         
       
   936         bool ok = true;
       
   937         QByteArray type = slot.typeName();
       
   938         if (type.isEmpty())
       
   939             type = "void";
       
   940         else
       
   941             type = convertTypes(type, &ok);
       
   942         
       
   943         QByteArray ptype(prototype(parameterTypes, parameterNames, &ok));
       
   944         if (!ok)
       
   945             outBuffer += "\t/****** Slot parameter uses unsupported datatype\n";
       
   946         
       
   947         outBuffer += "\t\t[id(" + QString::number(id).toLatin1() + ")] " + type + ' ' + name + '(' + ptype + ");\n";
       
   948         
       
   949         if (!ok)
       
   950             outBuffer += "\t******/\n";
       
   951         ++id;
       
   952     }
       
   953     if (!outBuffer.isEmpty()) {
       
   954         outBuffer = addDefaultArguments(outBuffer, numDefArgs);
       
   955         numDefArgs = 0;
       
   956         out << outBuffer;
       
   957         outBuffer = QByteArray();
       
   958     }
       
   959     out << "\t};" << endl << endl;
       
   960 
       
   961     mapping.clear();
       
   962     id = 1;
       
   963     
       
   964     if (hasEvents) {
       
   965         out << "\t[" << endl;
       
   966         out << "\t\tuuid(" << eventsID << ")," << endl;
       
   967         out << "\t\thelpstring(\"" << cleanClassName << " Events Interface\")" << endl;
       
   968         out << "\t]" << endl;
       
   969         out << "\tdispinterface I" << cleanClassName << "Events" << endl;
       
   970         out << "\t{" << endl;
       
   971         out << "\tproperties:" << endl;
       
   972         out << "\tmethods:" << endl;
       
   973         
       
   974         if (hasStockEvents) {
       
   975             out << "\t/****** Stock events ******/" << endl;
       
   976             out << "\t\t[id(DISPID_CLICK)] void Click();" << endl;
       
   977             out << "\t\t[id(DISPID_DBLCLICK)] void DblClick();" << endl;
       
   978             out << "\t\t[id(DISPID_KEYDOWN)] void KeyDown(short* KeyCode, short Shift);" << endl;
       
   979             out << "\t\t[id(DISPID_KEYPRESS)] void KeyPress(short* KeyAscii);" << endl;
       
   980             out << "\t\t[id(DISPID_KEYUP)] void KeyUp(short* KeyCode, short Shift);" << endl;
       
   981             out << "\t\t[id(DISPID_MOUSEDOWN)] void MouseDown(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl;
       
   982             out << "\t\t[id(DISPID_MOUSEMOVE)] void MouseMove(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl;
       
   983             out << "\t\t[id(DISPID_MOUSEUP)] void MouseUp(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl << endl;
       
   984         }
       
   985         
       
   986         for (i = methodoff; i < mo->methodCount(); ++i) {
       
   987             const QMetaMethod signal = mo->method(i);
       
   988             if (signal.methodType() != QMetaMethod::Signal)
       
   989                 continue;
       
   990             
       
   991             QByteArray signature(signal.signature());
       
   992             QByteArray name(signature.left(signature.indexOf('(')));
       
   993             signature = signature.mid(name.length() + 1);
       
   994             signature.truncate(signature.length() - 1);
       
   995 
       
   996             QList<QByteArray> parameterTypes(signal.parameterTypes());
       
   997             QList<QByteArray> parameterNames(signal.parameterNames());
       
   998             
       
   999             bool isDefault = defSignal == QLatin1String(name);
       
  1000             name = renameOverloads(replaceKeyword(name));
       
  1001             bool ok = true;
       
  1002             
       
  1003             QByteArray type = signal.typeName();
       
  1004             if (!type.isEmpty()) // signals with return value not supported
       
  1005                 continue;
       
  1006             
       
  1007             QByteArray ptype(prototype(parameterTypes, parameterNames, &ok));
       
  1008             if (!ok)
       
  1009                 out << "\t/****** Signal parameter uses unsupported datatype" << endl;
       
  1010             
       
  1011             out << "\t\t[id(" << id << ')';
       
  1012             if (isDefault)
       
  1013                 out << ", uidefault";
       
  1014             out << "] void " << name << '(' << ptype << ");" << endl;
       
  1015             
       
  1016             if (!ok)
       
  1017                 out << "\t******/" << endl;
       
  1018             ++id;
       
  1019         }
       
  1020         out << "\t};" << endl << endl;
       
  1021     }
       
  1022     
       
  1023     out << "\t[" << endl;
       
  1024     
       
  1025     if (qstricmp(mo->classInfo(mo->indexOfClassInfo("Aggregatable")).value(), "no"))
       
  1026         out << "\t\taggregatable," << endl;
       
  1027     if (!qstricmp(mo->classInfo(mo->indexOfClassInfo("RegisterObject")).value(), "yes"))
       
  1028         out << "\t\tappobject," << endl;
       
  1029     if (mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value())
       
  1030         out << "\t\tlicensed," << endl;
       
  1031     const char *helpString = mo->classInfo(mo->indexOfClassInfo("Description")).value();
       
  1032     if (helpString)
       
  1033         out << "\t\thelpstring(\"" << helpString << "\")," << endl;
       
  1034     else
       
  1035         out << "\t\thelpstring(\"" << cleanClassName << " Class\")," << endl;
       
  1036     const char *classVersion = mo->classInfo(mo->indexOfClassInfo("Version")).value();
       
  1037     if (classVersion)
       
  1038         out << "\t\tversion(" << classVersion << ")," << endl;
       
  1039     out << "\t\tuuid(" << classID << ')';
       
  1040     if (control) {
       
  1041         out << ", " << endl;
       
  1042         out << "\t\tcontrol";
       
  1043     } else if (!o) {
       
  1044         out << ", " << endl;
       
  1045         out << "\t\tnoncreatable";
       
  1046     }
       
  1047     out << endl;
       
  1048     out << "\t]" << endl;
       
  1049     out << "\tcoclass " << cleanClassName << endl;
       
  1050     out << "\t{" << endl;
       
  1051     out << "\t\t[default] dispinterface I" << cleanClassName << ';' << endl;
       
  1052     if (hasEvents)
       
  1053         out << "\t\t[default, source] dispinterface I" << cleanClassName << "Events;" << endl;
       
  1054     out << "\t};" << endl;
       
  1055     
       
  1056     return S_OK;
       
  1057 }
       
  1058 
       
  1059 #if defined(Q_CC_BOR)
       
  1060 extern "C" __stdcall HRESULT DumpIDL(const QString &outfile, const QString &ver)
       
  1061 #else
       
  1062 extern "C" HRESULT __stdcall DumpIDL(const QString &outfile, const QString &ver)
       
  1063 #endif
       
  1064 {
       
  1065     qAxIsServer = false;
       
  1066     QTextStream out;
       
  1067     if (outfile.contains(QLatin1String("\\"))) {
       
  1068         QString outpath = outfile.left(outfile.lastIndexOf(QLatin1String("\\")));
       
  1069         QDir dir;
       
  1070         dir.mkpath(outpath);
       
  1071     }
       
  1072     QFile file(outfile);
       
  1073     file.remove();
       
  1074     
       
  1075     QString filebase = QString::fromWCharArray(qAxModuleFilename);
       
  1076     filebase = filebase.left(filebase.lastIndexOf(QLatin1Char('.')));
       
  1077     
       
  1078     QString appID = qAxFactory()->appID().toString().toUpper();
       
  1079     if (QUuid(appID).isNull())
       
  1080         return 1;
       
  1081     STRIPCB(appID);
       
  1082     QString typeLibID = qAxFactory()->typeLibID().toString().toUpper();
       
  1083     if (QUuid(typeLibID).isNull())
       
  1084         return 2;
       
  1085     STRIPCB(typeLibID);
       
  1086     QString typelib = filebase.right(filebase.length() - filebase.lastIndexOf(QLatin1String("\\"))-1);
       
  1087     
       
  1088     if (!file.open(QIODevice::WriteOnly))
       
  1089         return -1;
       
  1090     
       
  1091     out.setDevice(&file);
       
  1092     
       
  1093     QString version(ver.unicode(), ver.length());
       
  1094     while (version.count(QLatin1Char('.')) > 1) {
       
  1095         int lastdot = version.lastIndexOf(QLatin1Char('.'));
       
  1096         version = version.left(lastdot) + version.right(version.length() - lastdot - 1);
       
  1097     }
       
  1098     if (version.isEmpty())
       
  1099         version = QLatin1String("1.0");
       
  1100     
       
  1101     QString idQRect(QUuid(CLSID_QRect).toString());
       
  1102     STRIPCB(idQRect);
       
  1103     QString idQSize(QUuid(CLSID_QSize).toString());
       
  1104     STRIPCB(idQSize);
       
  1105     QString idQPoint(QUuid(CLSID_QPoint).toString());
       
  1106     STRIPCB(idQPoint);
       
  1107     
       
  1108     out << "/****************************************************************************" << endl;
       
  1109     out << "** Interface definition generated for ActiveQt project" << endl;
       
  1110     out << "**" << endl;
       
  1111     out << "**     '" << QString::fromWCharArray(qAxModuleFilename) << '\'' << endl;
       
  1112     out << "**" << endl;
       
  1113     out << "** Created:  " << QDateTime::currentDateTime().toString() << endl;
       
  1114     out << "**" << endl;
       
  1115     out << "** WARNING! All changes made in this file will be lost!" << endl;
       
  1116     out << "****************************************************************************/" << endl << endl;
       
  1117     
       
  1118     out << "import \"ocidl.idl\";" << endl;
       
  1119     out << "#include <olectl.h>" << endl << endl;
       
  1120     
       
  1121     // dummy application to create widgets
       
  1122     bool delete_qApp = false;
       
  1123     if (!qApp) {
       
  1124         int argc;
       
  1125         (void)new QApplication(argc, 0);
       
  1126         delete_qApp = true;
       
  1127     }
       
  1128     
       
  1129     out << '[' << endl;
       
  1130     out << "\tuuid(" << typeLibID << ")," << endl;
       
  1131     out << "\tversion(" << version << ")," << endl;
       
  1132     out << "\thelpstring(\"" << typelib << ' ' << version << " Type Library\")" << endl;
       
  1133     out << ']' << endl;
       
  1134     out << "library " << typelib << "Lib" << endl;
       
  1135     out << '{' << endl;
       
  1136     out << "\timportlib(\"stdole32.tlb\");" << endl;
       
  1137     out << "\timportlib(\"stdole2.tlb\");" << endl << endl;
       
  1138     
       
  1139     QStringList keys = qAxFactory()->featureList();
       
  1140     QStringList::ConstIterator key;
       
  1141     
       
  1142     out << "\t/************************************************************************" << endl;
       
  1143     out << "\t** If this causes a compile error in MIDL you need to upgrade the" << endl;
       
  1144     out << "\t** Platform SDK you are using. Download the SDK from msdn.microsoft.com" << endl;
       
  1145     out << "\t** and make sure that both the system and the Visual Studio environment" << endl;
       
  1146     out << "\t** use the correct files." << endl;
       
  1147     out << "\t**" << endl;
       
  1148     
       
  1149 #ifndef Q_CC_BOR
       
  1150 #if __REQUIRED_RPCNDR_H_VERSION__ < Q_REQUIRED_RPCNDR_H_VERSION
       
  1151     out << "\t** Required version of MIDL could not be verified. QRect, QSize and QPoint" << endl;
       
  1152     out << "\t** support needs an updated Platform SDK to be installed." << endl;
       
  1153     out << "\t*************************************************************************" << endl;
       
  1154 #else
       
  1155     out << "\t************************************************************************/" << endl;
       
  1156 #endif
       
  1157     
       
  1158     out << endl;
       
  1159     out << "\t[uuid(" << idQRect << ")]" << endl;
       
  1160     out << "\tstruct QRect {" << endl;
       
  1161     out << "\t\tint left;" << endl;
       
  1162     out << "\t\tint top;" << endl;
       
  1163     out << "\t\tint right;" << endl;
       
  1164     out << "\t\tint bottom;" << endl;
       
  1165     out << "\t};" << endl << endl;
       
  1166     
       
  1167     out << "\t[uuid(" << idQSize << ")]" << endl;
       
  1168     out << "\tstruct QSize {" << endl;
       
  1169     out << "\t\tint width;" << endl;
       
  1170     out << "\t\tint height;" << endl;
       
  1171     out << "\t};" << endl << endl;
       
  1172     
       
  1173     out << "\t[uuid(" << idQPoint << ")]" << endl;
       
  1174     out << "\tstruct QPoint {" << endl;
       
  1175     out << "\t\tint x;" << endl;
       
  1176     out << "\t\tint y;" << endl;
       
  1177     out << "\t};" << endl;
       
  1178 #if __REQUIRED_RPCNDR_H_VERSION__ < Q_REQUIRED_RPCNDR_H_VERSION
       
  1179     out << "\t*/" << endl;
       
  1180 #endif
       
  1181 #else
       
  1182     out << "\t** Custom data types not supported with Borland." << endl;
       
  1183     out << "\t*************************************************************************" << endl;
       
  1184 #endif
       
  1185     out << endl;
       
  1186     
       
  1187     out << "\t/* Forward declaration of classes that might be used as parameters */" << endl << endl;
       
  1188     
       
  1189     int res = S_OK;
       
  1190     for (key = keys.begin(); key != keys.end(); ++key) {
       
  1191         QByteArray className = (*key).toLatin1();
       
  1192         const QMetaObject *mo = qAxFactory()->metaObject(QString::fromLatin1(className.constData()));
       
  1193         // We have meta object information for this type. Forward declare it.
       
  1194         if (mo) {
       
  1195             QByteArray cleanType = qax_clean_type(*key, mo).toLatin1();
       
  1196             out << "\tcoclass " << cleanType << ';' << endl;
       
  1197             subtypes.append(cleanType);
       
  1198             qRegisterMetaType(cleanType, (void**)0);
       
  1199             cleanType += '*';
       
  1200             subtypes.append(cleanType);
       
  1201             qRegisterMetaType(cleanType, (void**)0);
       
  1202         }
       
  1203     }
       
  1204     out << endl;
       
  1205 
       
  1206     for (key = keys.begin(); key != keys.end(); ++key) {
       
  1207         QByteArray className = (*key).toLatin1();
       
  1208         const QMetaObject *mo = qAxFactory()->metaObject(QString::fromLatin1(className.constData()));
       
  1209         // We have meta object information for this type. Define it.
       
  1210         if (mo) {
       
  1211             QObject *o = qAxFactory()->createObject(QString::fromLatin1(className.constData()));
       
  1212             // It's not a control class, so it is actually a subtype. Define it.
       
  1213             if (!o)
       
  1214                 res = classIDL(0, mo, QString::fromLatin1(className), false, out);
       
  1215             delete o;
       
  1216         }
       
  1217     }
       
  1218 
       
  1219     out << endl;
       
  1220     if (res != S_OK)
       
  1221         goto ErrorInClass;
       
  1222     
       
  1223     for (key = keys.begin(); key != keys.end(); ++key) {
       
  1224         QByteArray className = (*key).toLatin1();
       
  1225         QObject *o = qAxFactory()->createObject(QString::fromLatin1(className.constData()));
       
  1226         if (!o)
       
  1227             continue;
       
  1228         const QMetaObject *mo = o->metaObject();
       
  1229         QAxBindable *bind = (QAxBindable*)o->qt_metacast("QAxBindable");
       
  1230         bool isBindable =  bind != 0;
       
  1231 
       
  1232         QByteArray cleanType = qax_clean_type(*key, mo).toLatin1();
       
  1233         subtypes.append(cleanType);
       
  1234         subtypes.append(cleanType + '*');
       
  1235         res = classIDL(o, mo, QString::fromLatin1(className.constData()), isBindable, out);
       
  1236         delete o;
       
  1237         if (res != S_OK)
       
  1238             break;
       
  1239     }
       
  1240     
       
  1241     out << "};" << endl;
       
  1242     out.flush();
       
  1243     
       
  1244 ErrorInClass:
       
  1245     if (delete_qApp)
       
  1246         delete qApp;
       
  1247 
       
  1248     if (res != S_OK) {
       
  1249         file.close();
       
  1250         file.remove();
       
  1251     }
       
  1252     
       
  1253     return res;
       
  1254 }
       
  1255 
       
  1256 QT_END_NAMESPACE
       
  1257 #endif // QT_NO_WIN_ACTIVEQT