source: trunk/src/activeqt/control/qaxservermain.cpp@ 618

Last change on this file since 618 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 8.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
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
50QT_BEGIN_NAMESPACE
51
52static DWORD *classRegistration = 0;
53static DWORD dwThreadID;
54static bool qAxActivity = false;
55static HANDLE hEventShutdown;
56
57#ifdef QT_DEBUG
58QT_STATIC_CONST DWORD dwTimeOut = 1000;
59QT_STATIC_CONST DWORD dwPause = 500;
60#else
61QT_STATIC_CONST DWORD dwTimeOut = 5000; // time for EXE to be idle before shutting down
62QT_STATIC_CONST DWORD dwPause = 1000; // time to wait for threads to finish up
63#endif
64
65extern HANDLE hEventShutdown;
66extern bool qAxActivity;
67extern HANDLE qAxInstance;
68extern bool qAxIsServer;
69extern bool qAxOutProcServer;
70extern wchar_t qAxModuleFilename[MAX_PATH];
71extern QString qAxInit();
72extern void qAxCleanup();
73extern HRESULT UpdateRegistry(BOOL bRegister);
74extern HRESULT GetClassObject(const GUID &clsid, const GUID &iid, void **ppUnk);
75extern ulong qAxLockCount();
76extern bool qax_winEventFilter(void *message);
77
78#if defined(Q_CC_BOR)
79extern "C" __stdcall HRESULT DumpIDL(const QString &outfile, const QString &ver);
80#else
81STDAPI DumpIDL(const QString &outfile, const QString &ver);
82#endif
83
84// Monitors the shutdown event
85static 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
106static 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
117void 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*/
127bool 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*/
162bool 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)
183extern void __cdecl qWinMain(HINSTANCE, HINSTANCE, LPSTR, int, int &, QVector<char *> &);
184#else
185extern void qWinMain(HINSTANCE, HINSTANCE, LPSTR, int, int &, QVector<char *> &);
186#endif
187
188QT_END_NAMESPACE
189
190#if defined(QT_NEEDS_QMAIN)
191int qMain(int, char **);
192#define main qMain
193#else
194#if defined(Q_OS_WINCE)
195extern "C" int __cdecl main(int, char **);
196#else
197extern "C" int main(int, char **);
198#endif
199#endif
200
201
202EXTERN_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
Note: See TracBrowser for help on using the repository browser.