Qt 4.8
qaxservermain.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the ActiveQt framework of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 ** * Redistributions of source code must retain the above copyright
15 ** notice, this list of conditions and the following disclaimer.
16 ** * Redistributions in binary form must reproduce the above copyright
17 ** notice, this list of conditions and the following disclaimer in
18 ** the documentation and/or other materials provided with the
19 ** distribution.
20 ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
21 ** of its contributors may be used to endorse or promote products derived
22 ** from this software without specific prior written permission.
23 **
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
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 
51 
52 static DWORD *classRegistration = 0;
53 static DWORD dwThreadID;
54 static bool qAxActivity = false;
56 
57 #ifdef QT_DEBUG
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 
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 */
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 */
163 {
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 
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 {
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)
263  nRet = ::main(argc, argv.data());
265  qAxCleanup();
266  CoUninitialize();
267 
268  }
269 
270  return nRet;
271 }
272 
273 #endif // QT_NO_WIN_ACTIVEQT
static QString fromWCharArray(const wchar_t *, int size=-1)
Returns a copy of the string, where the encoding of string depends on the size of wchar...
Definition: qstring.cpp:1019
ulong qAxLockCount()
Definition: qaxserver.cpp:180
void qAxCleanup()
Definition: qaxserver.cpp:139
int type
Definition: qmetatype.cpp:239
STDAPI DumpIDL(const QString &outfile, const QString &ver)
Definition: qaxserver.cpp:1062
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
Definition: quuid.h:52
QAxFactory * qAxFactory()
Definition: qaxserver.cpp:81
static bool stopServer()
Stops the COM server and returns true if successful, otherwise returns false.
Definition: qaxfactory.h:123
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
bool qAxIsServer
Definition: qaxserver.cpp:64
bool qax_startServer(QAxFactory::ServerType type)
iterator begin()
Returns an STL-style iterator pointing to the first item in the list.
Definition: qlist.h:267
void qax_shutDown()
QByteArray toLower() const
Returns a lowercase copy of the byte array.
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define WAIT_OBJECT_0
The QVector class is a template class that provides a dynamic array.
Definition: qdatastream.h:64
#define CoInitialize(x)
virtual QStringList featureList() const =0
Reimplement this function to return a list of the widgets (class names) supported by this factory...
void __cdecl qWinMain(HINSTANCE, HINSTANCE, LPSTR, int, int &, QVector< char *> &)
QStringList keys
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QObject * object
HRESULT GetClassObject(const GUID &clsid, const GUID &iid, void **ppUnk)
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:270
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
Q_CORE_EXPORT void qWarning(const char *,...)
QString qAxInit()
Definition: qaxserver.cpp:111
wchar_t qAxModuleFilename[MAX_PATH]
Definition: qaxserver.cpp:67
void * HANDLE
Definition: qnamespace.h:1671
unsigned long ulong
Definition: qglobal.h:997
#define QT_STATIC_CONST
Definition: qglobal.h:1040
QByteArray toLocal8Bit() const Q_REQUIRED_RESULT
Returns the local 8-bit representation of the string as a QByteArray.
Definition: qstring.cpp:4049
virtual bool isService() const
Reimplement this function to return true if the server is running as a persistent service (e...
Definition: qaxfactory.cpp:410
QT_STATIC_CONST DWORD dwTimeOut
bool qAxOutProcServer
Definition: qaxserver.cpp:68
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
QList< QByteArray > split(char sep) const
Splits the byte array into subarrays wherever sep occurs, and returns the list of those arrays...
long HRESULT
bool qax_stopServer()
static DWORD dwThreadID
static bool qAxActivity
static bool startServer(ServerType type=MultipleInstances)
Starts the COM server with type and returns true if successful, otherwise returns false...
Definition: qaxfactory.h:115
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
ServerType
This enum specifies the different types of servers that can be started with startServer.
Definition: qaxfactory.h:93
const_iterator ConstIterator
Qt-style synonym for QList::const_iterator.
Definition: qlist.h:279
int key
#define QT_USE_NAMESPACE
This macro expands to using QT_NAMESPACE if QT_NAMESPACE is defined and nothing otherwise.
Definition: qglobal.h:88
QFuture< T > run(Function function,...)
static HANDLE hEventShutdown
EXTERN_C int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR, int nShowCmd)
HANDLE qAxInstance
Definition: qaxserver.cpp:65
T * data()
Returns a pointer to the data stored in the vector.
Definition: qvector.h:152
int __cdecl main(int, char **)
Definition: qaxmain.cpp:46
static DWORD WINAPI MonitorProc(void *pv)
HRESULT UpdateRegistry(BOOL bRegister)
Definition: qaxserver.cpp:208
QT_STATIC_CONST DWORD dwPause
static bool StartMonitor()
virtual QUuid classID(const QString &key) const
Reimplement this function to return the class identifier for each key returned by the featureList() i...
Definition: qaxfactory.cpp:191
static DWORD * classRegistration
bool qax_winEventFilter(void *message)