diff options
Diffstat (limited to 'src/activeqt/control/qaxservermain.cpp')
-rw-r--r-- | src/activeqt/control/qaxservermain.cpp | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/src/activeqt/control/qaxservermain.cpp b/src/activeqt/control/qaxservermain.cpp new file mode 100644 index 0000000..a50fef0 --- /dev/null +++ b/src/activeqt/control/qaxservermain.cpp @@ -0,0 +1,279 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the ActiveQt framework of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qstringlist.h> +#include <qvector.h> + +#include "qaxfactory.h" + +#ifndef QT_NO_WIN_ACTIVEQT + +#include <qt_windows.h> + +QT_BEGIN_NAMESPACE + +static DWORD *classRegistration = 0; +static DWORD dwThreadID; +static bool qAxActivity = false; +static HANDLE hEventShutdown; + +#ifdef QT_DEBUG +QT_STATIC_CONST DWORD dwTimeOut = 1000; +QT_STATIC_CONST DWORD dwPause = 500; +#else +QT_STATIC_CONST DWORD dwTimeOut = 5000; // time for EXE to be idle before shutting down +QT_STATIC_CONST DWORD dwPause = 1000; // time to wait for threads to finish up +#endif + +extern HANDLE hEventShutdown; +extern bool qAxActivity; +extern HANDLE qAxInstance; +extern bool qAxIsServer; +extern bool qAxOutProcServer; +extern char qAxModuleFilename[MAX_PATH]; +extern QString qAxInit(); +extern void qAxCleanup(); +extern HRESULT UpdateRegistry(BOOL bRegister); +extern HRESULT GetClassObject(const GUID &clsid, const GUID &iid, void **ppUnk); +extern ulong qAxLockCount(); +extern bool qax_winEventFilter(void *message); + +#if defined(Q_CC_BOR) +extern "C" __stdcall HRESULT DumpIDL(const QString &outfile, const QString &ver); +#else +STDAPI DumpIDL(const QString &outfile, const QString &ver); +#endif + +// Monitors the shutdown event +static DWORD WINAPI MonitorProc(void* pv) +{ + while (1) { + WaitForSingleObject(hEventShutdown, INFINITE); + DWORD dwWait=0; + do { + qAxActivity = false; + dwWait = WaitForSingleObject(hEventShutdown, dwTimeOut); + } while (dwWait == WAIT_OBJECT_0); + // timed out + if (!qAxActivity && !qAxLockCount()) // if no activity let's really bail + break; + } + CloseHandle(hEventShutdown); + PostThreadMessage(dwThreadID, WM_QUIT, 0, 0); + PostQuitMessage(0); + + return 0; +} + +// Starts the monitoring thread +static bool StartMonitor() +{ + dwThreadID = GetCurrentThreadId(); + hEventShutdown = CreateEventA(0, false, false, 0); + if (hEventShutdown == 0) + return false; + DWORD dwThreadID; + HANDLE h = CreateThread(0, 0, MonitorProc, 0, 0, &dwThreadID); + return (h != NULL); +} + +void qax_shutDown() +{ + qAxActivity = true; + if (hEventShutdown) + SetEvent(hEventShutdown); // tell monitor that we transitioned to zero +} + +/* + Start the COM server (if necessary). +*/ +bool qax_startServer(QAxFactory::ServerType type) +{ + if (qAxIsServer) + return true; + + const QStringList keys = qAxFactory()->featureList(); + if (!keys.count()) + return false; + + if (!qAxFactory()->isService()) + StartMonitor(); + + classRegistration = new DWORD[keys.count()]; + int object = 0; + for (QStringList::ConstIterator key = keys.begin(); key != keys.end(); ++key, ++object) { + IUnknown* p = 0; + CLSID clsid = qAxFactory()->classID(*key); + + // Create a QClassFactory (implemented in qaxserverbase.cpp) + HRESULT hRes = GetClassObject(clsid, IID_IClassFactory, (void**)&p); + if (SUCCEEDED(hRes)) + hRes = CoRegisterClassObject(clsid, p, CLSCTX_LOCAL_SERVER, + type == QAxFactory::MultipleInstances ? REGCLS_MULTIPLEUSE : REGCLS_SINGLEUSE, + classRegistration+object); + if (p) + p->Release(); + } + + qAxIsServer = true; + return true; +} + +/* + Stop the COM server (if necessary). +*/ +bool qax_stopServer() +{ + if (!qAxIsServer || !classRegistration) + return true; + + qAxIsServer = false; + + const QStringList keys = qAxFactory()->featureList(); + int object = 0; + for (QStringList::ConstIterator key = keys.begin(); key != keys.end(); ++key, ++object) + CoRevokeClassObject(classRegistration[object]); + + delete []classRegistration; + classRegistration = 0; + + Sleep(dwPause); //wait for any threads to finish + + return true; +} + +#if defined(Q_OS_WINCE) +extern void __cdecl qWinMain(HINSTANCE, HINSTANCE, LPSTR, int, int &, QVector<char *> &); +#else +extern void qWinMain(HINSTANCE, HINSTANCE, LPSTR, int, int &, QVector<char *> &); +#endif + +QT_END_NAMESPACE + +#if defined(QT_NEEDS_QMAIN) +int qMain(int, char **); +#define main qMain +#else +#if defined(Q_OS_WINCE) +extern "C" int __cdecl main(int, char **); +#else +extern "C" int main(int, char **); +#endif +#endif + + +EXTERN_C int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR, int nShowCmd) +{ + QT_USE_NAMESPACE + + qAxOutProcServer = true; + GetModuleFileNameA(0, qAxModuleFilename, MAX_PATH-1); + qAxInstance = hInstance; + + QByteArray cmdParam; + QT_WA({ + LPTSTR cmdline = GetCommandLineW(); + cmdParam = QString::fromUtf16((const ushort *)cmdline).toLocal8Bit(); + }, { + cmdParam = GetCommandLineA(); + }); + + QList<QByteArray> cmds = cmdParam.split(' '); + QByteArray unprocessed; + + int nRet = 0; + bool run = true; + bool runServer = false; + for (int i = 0; i < cmds.count(); ++i) { + QByteArray cmd = cmds.at(i).toLower(); + if (cmd == "-activex" || cmd == "/activex" || cmd == "-embedding" || cmd == "/embedding") { + runServer = true; + } else if (cmd == "-unregserver" || cmd == "/unregserver") { + nRet = UpdateRegistry(false); + run = false; + break; + } else if (cmd == "-regserver" || cmd == "/regserver") { + nRet = UpdateRegistry(true); + run = false; + break; + } else if (cmd == "-dumpidl" || cmd == "/dumpidl") { + ++i; + if (i < cmds.count()) { + QByteArray outfile = cmds.at(i); + ++i; + QByteArray version; + if (i < cmds.count() && (cmds.at(i) == "-version" || cmds.at(i) == "/version")) { + ++i; + if (i < cmds.count()) + version = cmds.at(i); + else + version = "1.0"; + } + + nRet = DumpIDL(QString::fromLatin1(outfile.constData()), QString::fromLatin1(version.constData())); + } else { + qWarning("Wrong commandline syntax: <app> -dumpidl <idl file> [-version <x.y.z>]"); + } + run = false; + break; + } else { + unprocessed += cmds.at(i) + " "; + } + } + + if (run) { + HRESULT hRes = CoInitialize(0); + + int argc; + QVector<char*> argv(8); + qWinMain(hInstance, hPrevInstance, unprocessed.data(), nShowCmd, argc, argv); + qAxInit(); + if (runServer) + QAxFactory::startServer(); + nRet = ::main(argc, argv.data()); + QAxFactory::stopServer(); + qAxCleanup(); + CoUninitialize(); + + } + + return nRet; +} + +#endif // QT_NO_WIN_ACTIVEQT |