src/activeqt/control/qaxservermain.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 <qstringlist.h>
       
    42 #include <qvector.h>
       
    43 
       
    44 #include "qaxfactory.h"
       
    45 
       
    46 #ifndef QT_NO_WIN_ACTIVEQT
       
    47 
       
    48 #include <qt_windows.h>
       
    49 
       
    50 QT_BEGIN_NAMESPACE
       
    51 
       
    52 static DWORD *classRegistration = 0;
       
    53 static DWORD dwThreadID;
       
    54 static bool qAxActivity = false;
       
    55 static HANDLE hEventShutdown;
       
    56 
       
    57 #ifdef QT_DEBUG
       
    58 QT_STATIC_CONST DWORD dwTimeOut = 1000;
       
    59 QT_STATIC_CONST DWORD dwPause = 500;
       
    60 #else
       
    61 QT_STATIC_CONST DWORD dwTimeOut = 5000; // time for EXE to be idle before shutting down
       
    62 QT_STATIC_CONST DWORD dwPause = 1000; // time to wait for threads to finish up
       
    63 #endif
       
    64 
       
    65 extern HANDLE hEventShutdown;
       
    66 extern bool qAxActivity;
       
    67 extern HANDLE qAxInstance;
       
    68 extern bool qAxIsServer;
       
    69 extern bool qAxOutProcServer;
       
    70 extern wchar_t qAxModuleFilename[MAX_PATH];
       
    71 extern QString qAxInit();
       
    72 extern void qAxCleanup();
       
    73 extern HRESULT UpdateRegistry(BOOL bRegister);
       
    74 extern HRESULT GetClassObject(const GUID &clsid, const GUID &iid, void **ppUnk);
       
    75 extern ulong qAxLockCount();
       
    76 extern bool qax_winEventFilter(void *message);
       
    77 
       
    78 #if defined(Q_CC_BOR)
       
    79 extern "C" __stdcall HRESULT DumpIDL(const QString &outfile, const QString &ver);
       
    80 #else
       
    81 STDAPI DumpIDL(const QString &outfile, const QString &ver);
       
    82 #endif
       
    83 
       
    84 // Monitors the shutdown event
       
    85 static DWORD WINAPI MonitorProc(void* pv)
       
    86 {
       
    87     while (1) {
       
    88         WaitForSingleObject(hEventShutdown, INFINITE);
       
    89         DWORD dwWait=0;
       
    90         do {
       
    91             qAxActivity = false;
       
    92             dwWait = WaitForSingleObject(hEventShutdown, dwTimeOut);
       
    93         } while (dwWait == WAIT_OBJECT_0);
       
    94         // timed out
       
    95         if (!qAxActivity && !qAxLockCount()) // if no activity let's really bail
       
    96             break;
       
    97     }
       
    98     CloseHandle(hEventShutdown);
       
    99     PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
       
   100     PostQuitMessage(0);
       
   101     
       
   102     return 0;
       
   103 }
       
   104 
       
   105 // Starts the monitoring thread
       
   106 static bool StartMonitor()
       
   107 {
       
   108     dwThreadID = GetCurrentThreadId();
       
   109     hEventShutdown = CreateEvent(0, false, false, 0);
       
   110     if (hEventShutdown == 0)
       
   111         return false;
       
   112     DWORD dwThreadID;
       
   113     HANDLE h = CreateThread(0, 0, MonitorProc, 0, 0, &dwThreadID);
       
   114     return (h != NULL);
       
   115 }
       
   116 
       
   117 void qax_shutDown()
       
   118 {
       
   119     qAxActivity = true;
       
   120     if (hEventShutdown)
       
   121         SetEvent(hEventShutdown); // tell monitor that we transitioned to zero
       
   122 }
       
   123 
       
   124 /*
       
   125     Start the COM server (if necessary).
       
   126 */
       
   127 bool qax_startServer(QAxFactory::ServerType type)
       
   128 {
       
   129     if (qAxIsServer)
       
   130         return true;
       
   131     
       
   132     const QStringList keys = qAxFactory()->featureList();
       
   133     if (!keys.count())
       
   134         return false;
       
   135     
       
   136     if (!qAxFactory()->isService())
       
   137         StartMonitor();
       
   138     
       
   139     classRegistration = new DWORD[keys.count()];
       
   140     int object = 0;
       
   141     for (QStringList::ConstIterator key = keys.begin(); key != keys.end(); ++key, ++object) {
       
   142         IUnknown* p = 0;
       
   143         CLSID clsid = qAxFactory()->classID(*key);
       
   144         
       
   145         // Create a QClassFactory (implemented in qaxserverbase.cpp)
       
   146         HRESULT hRes = GetClassObject(clsid, IID_IClassFactory, (void**)&p);
       
   147         if (SUCCEEDED(hRes))
       
   148             hRes = CoRegisterClassObject(clsid, p, CLSCTX_LOCAL_SERVER,
       
   149                 type == QAxFactory::MultipleInstances ? REGCLS_MULTIPLEUSE : REGCLS_SINGLEUSE,
       
   150                 classRegistration+object);
       
   151         if (p)
       
   152             p->Release();
       
   153     }
       
   154 
       
   155     qAxIsServer = true;
       
   156     return true;
       
   157 }
       
   158 
       
   159 /*
       
   160     Stop the COM server (if necessary).
       
   161 */
       
   162 bool qax_stopServer()
       
   163 {
       
   164     if (!qAxIsServer || !classRegistration)
       
   165         return true;
       
   166     
       
   167     qAxIsServer = false;
       
   168     
       
   169     const QStringList keys = qAxFactory()->featureList();
       
   170     int object = 0;
       
   171     for (QStringList::ConstIterator key = keys.begin(); key != keys.end(); ++key, ++object)
       
   172         CoRevokeClassObject(classRegistration[object]);
       
   173     
       
   174     delete []classRegistration;
       
   175     classRegistration = 0;
       
   176     
       
   177     Sleep(dwPause); //wait for any threads to finish
       
   178     
       
   179     return true;
       
   180 }
       
   181 
       
   182 #if defined(Q_OS_WINCE)
       
   183 extern void __cdecl qWinMain(HINSTANCE, HINSTANCE, LPSTR, int, int &, QVector<char *> &);
       
   184 #else
       
   185 extern void qWinMain(HINSTANCE, HINSTANCE, LPSTR, int, int &, QVector<char *> &);
       
   186 #endif
       
   187 
       
   188 QT_END_NAMESPACE
       
   189 
       
   190 #if defined(QT_NEEDS_QMAIN)
       
   191 int qMain(int, char **);
       
   192 #define main qMain
       
   193 #else
       
   194 #if defined(Q_OS_WINCE)
       
   195 extern "C" int __cdecl main(int, char **);
       
   196 #else
       
   197 extern "C" int main(int, char **);
       
   198 #endif
       
   199 #endif
       
   200 
       
   201 
       
   202 EXTERN_C int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR, int nShowCmd)
       
   203 {
       
   204     QT_USE_NAMESPACE 
       
   205 
       
   206     qAxOutProcServer = true;
       
   207     GetModuleFileName(0, qAxModuleFilename, MAX_PATH);
       
   208     qAxInstance = hInstance;
       
   209 
       
   210     QByteArray cmdParam = QString::fromWCharArray(GetCommandLine()).toLocal8Bit();
       
   211     QList<QByteArray> cmds = cmdParam.split(' ');
       
   212     QByteArray unprocessed;
       
   213 
       
   214     int nRet = 0;
       
   215     bool run = true;
       
   216     bool runServer = false;
       
   217     for (int i = 0; i < cmds.count(); ++i) {
       
   218         QByteArray cmd = cmds.at(i).toLower();
       
   219         if (cmd == "-activex" || cmd == "/activex" || cmd == "-embedding" || cmd == "/embedding") {
       
   220             runServer = true;
       
   221         } else if (cmd == "-unregserver" || cmd == "/unregserver") {
       
   222             nRet = UpdateRegistry(false);
       
   223             run = false;
       
   224             break;
       
   225         } else if (cmd == "-regserver" || cmd == "/regserver") {
       
   226             nRet = UpdateRegistry(true);
       
   227             run = false;
       
   228             break;
       
   229         } else if (cmd == "-dumpidl" || cmd == "/dumpidl") {
       
   230             ++i;
       
   231             if (i < cmds.count()) {
       
   232                 QByteArray outfile = cmds.at(i);
       
   233                 ++i;
       
   234                 QByteArray version;
       
   235                 if (i < cmds.count() && (cmds.at(i) == "-version" || cmds.at(i) == "/version")) {
       
   236                     ++i;
       
   237                     if (i < cmds.count())
       
   238                         version = cmds.at(i);
       
   239                     else
       
   240                         version = "1.0";
       
   241                 }
       
   242                 
       
   243                 nRet = DumpIDL(QString::fromLatin1(outfile.constData()), QString::fromLatin1(version.constData()));
       
   244             } else {
       
   245                 qWarning("Wrong commandline syntax: <app> -dumpidl <idl file> [-version <x.y.z>]");
       
   246             }
       
   247             run = false;
       
   248             break;
       
   249         } else {
       
   250             unprocessed += cmds.at(i) + ' ';
       
   251         }
       
   252     }
       
   253     
       
   254     if (run) {
       
   255         HRESULT hRes = CoInitialize(0);
       
   256 
       
   257         int argc;
       
   258         QVector<char*> argv(8);
       
   259         qWinMain(hInstance, hPrevInstance, unprocessed.data(), nShowCmd, argc, argv);
       
   260         qAxInit();
       
   261         if (runServer)
       
   262             QAxFactory::startServer();
       
   263         nRet = ::main(argc, argv.data());
       
   264         QAxFactory::stopServer();
       
   265         qAxCleanup();
       
   266         CoUninitialize();
       
   267         
       
   268     }
       
   269     
       
   270     return nRet;
       
   271 }
       
   272 
       
   273 #endif // QT_NO_WIN_ACTIVEQT