source: trunk/src/tools/idc/main.cpp@ 187

Last change on this file since 187 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 13.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the tools applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <QFile>
43#include <QSysInfo>
44#include <QProcess>
45#include <QLibraryInfo>
46#include <qt_windows.h>
47#include <io.h>
48
49QT_BEGIN_NAMESPACE
50
51static QString quotePath(const QString &s)
52{
53 if (!s.startsWith(QLatin1String("\"")) && s.contains(QLatin1Char(' ')))
54 return QLatin1String("\"") + s + QLatin1String("\"");
55 return s;
56}
57
58
59static bool runWithQtInEnvironment(const QString &cmd)
60{
61 QProcess proc;
62
63 // prepend the qt binary directory to the path
64 QStringList env = QProcess::systemEnvironment();
65 for (int i=0; i<env.count(); ++i) {
66 QString var = env.at(i);
67 int setidx = var.indexOf(QLatin1Char('='));
68 if (setidx != -1) {
69 QString varname = var.left(setidx).trimmed().toUpper();
70 if (varname == QLatin1String("PATH")) {
71 var = var.mid(setidx + 1);
72 var = QLatin1String("PATH=") +
73 QLibraryInfo::location(QLibraryInfo::BinariesPath) +
74 QLatin1Char(';') + var;
75 env[i] = var;
76 break;
77 }
78 }
79 }
80
81 proc.setEnvironment(env);
82 proc.start(cmd);
83 proc.waitForFinished(-1);
84
85 return (proc.exitCode() == 0);
86}
87
88static bool attachTypeLibrary(const QString &applicationName, int resource, const QByteArray &data, QString *errorMessage)
89{
90 HANDLE hExe = 0;
91 QT_WA({
92 TCHAR *resourceName = MAKEINTRESOURCEW(resource);
93 hExe = BeginUpdateResourceW((TCHAR*)applicationName.utf16(), false);
94 if (hExe == 0) {
95 if (errorMessage)
96 *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not open file.").arg(applicationName);
97 return false;
98 }
99 if (!UpdateResourceW(hExe,L"TYPELIB",resourceName,0,(void*)data.data(),data.count())) {
100 EndUpdateResource(hExe, true);
101 if (errorMessage)
102 *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not update file.").arg(applicationName);
103 return false;
104 }
105 }, {
106 char *resourceName = MAKEINTRESOURCEA(resource);
107 hExe = BeginUpdateResourceA(applicationName.toLocal8Bit(), false);
108 if (hExe == 0) {
109 if (errorMessage)
110 *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not open file.").arg(applicationName);
111 return false;
112 }
113 if (!UpdateResourceA(hExe,"TYPELIB",resourceName,0,(void*)data.data(),data.count())) {
114 EndUpdateResource(hExe, true);
115 if (errorMessage)
116 *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not update file.").arg(applicationName);
117 return false;
118 }
119 });
120
121 if (!EndUpdateResource(hExe,false)) {
122 if (errorMessage)
123 *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not write file.").arg(applicationName);
124 return false;
125 }
126
127 if (errorMessage)
128 *errorMessage = QString::fromLatin1("Type library attached to %1.").arg(applicationName);
129 return true;
130}
131
132static bool registerServer(const QString &input)
133{
134 bool ok = false;
135 if (input.endsWith(QLatin1String(".exe"))) {
136 ok = runWithQtInEnvironment(quotePath(input) + QLatin1String(" -regserver"));
137 } else {
138 HMODULE hdll = 0;
139 QT_WA({
140 hdll = LoadLibraryW((TCHAR*)input.utf16());
141 }, {
142 hdll = LoadLibraryA(input.toLocal8Bit());
143 });
144 if (!hdll) {
145 fprintf(stderr, "Couldn't load library file %s\n", (const char*)input.toLocal8Bit().data());
146 return false;
147 }
148 typedef HRESULT(__stdcall* RegServerProc)();
149 RegServerProc DllRegisterServer = (RegServerProc)GetProcAddress(hdll, "DllRegisterServer");
150 if (!DllRegisterServer) {
151 fprintf(stderr, "Library file %s doesn't appear to be a COM library\n", (const char*)input.toLocal8Bit().data());
152 return false;
153 }
154 ok = DllRegisterServer() == S_OK;
155 }
156 return ok;
157}
158
159static bool unregisterServer(const QString &input)
160{
161 bool ok = false;
162 if (input.endsWith(QLatin1String(".exe"))) {
163 ok = runWithQtInEnvironment(quotePath(input) + QLatin1String(" -unregserver"));
164 } else {
165 HMODULE hdll = 0;
166 QT_WA({
167 hdll = LoadLibraryW((TCHAR*)input.utf16());
168 }, {
169 hdll = LoadLibraryA(input.toLocal8Bit());
170 });
171 if (!hdll) {
172 fprintf(stderr, "Couldn't load library file %s\n", (const char*)input.toLocal8Bit().data());
173 return false;
174 }
175 typedef HRESULT(__stdcall* RegServerProc)();
176 RegServerProc DllUnregisterServer = (RegServerProc)GetProcAddress(hdll, "DllUnregisterServer");
177 if (!DllUnregisterServer) {
178 fprintf(stderr, "Library file %s doesn't appear to be a COM library\n", (const char*)input.toLocal8Bit().data());
179 return false;
180 }
181 ok = DllUnregisterServer() == S_OK;
182 }
183 return ok;
184}
185
186static HRESULT dumpIdl(const QString &input, const QString &idlfile, const QString &version)
187{
188 HRESULT res = E_FAIL;
189
190 if (input.endsWith(QLatin1String(".exe"))) {
191 if (runWithQtInEnvironment(quotePath(input) + QLatin1String(" -dumpidl ") + idlfile + QLatin1String(" -version ") + version))
192 res = S_OK;
193 } else {
194 HMODULE hdll = 0;
195 QT_WA({
196 hdll = LoadLibraryW((TCHAR*)input.utf16());
197 }, {
198 hdll = LoadLibraryA(input.toLocal8Bit());
199 });
200 if (!hdll) {
201 fprintf(stderr, "Couldn't load library file %s\n", (const char*)input.toLocal8Bit().data());
202 return 3;
203 }
204 typedef HRESULT(__stdcall* DumpIDLProc)(const QString&, const QString&);
205 DumpIDLProc DumpIDL = (DumpIDLProc)GetProcAddress(hdll, "DumpIDL");
206 if (!DumpIDL) {
207 fprintf(stderr, "Couldn't resolve 'DumpIDL' symbol in %s\n", (const char*)input.toLocal8Bit().data());
208 return 3;
209 }
210 res = DumpIDL(idlfile, version);
211 FreeLibrary(hdll);
212 }
213
214 return res;
215}
216
217static void slashify(QString &s)
218{
219 if (!s.contains(QLatin1Char('/')))
220 return;
221
222 int i = 0;
223 while (i < (int)s.length()) {
224 if (s[i] == QLatin1Char('/'))
225 s[i] = QLatin1Char('\\');
226 ++i;
227 }
228}
229
230int runIdc(int argc, char **argv)
231{
232 QString error;
233 QString tlbfile;
234 QString idlfile;
235 QString input;
236 QString version = QLatin1String("1.0");
237
238 int i = 1;
239 while (i < argc) {
240 QString p = QString::fromLocal8Bit(argv[i]).toLower();
241
242 if (p == QLatin1String("/idl") || p == QLatin1String("-idl")) {
243 ++i;
244 if (i > argc) {
245 error = QLatin1String("Missing name for interface definition file!");
246 break;
247 }
248 idlfile = QLatin1String(argv[i]);
249 idlfile = idlfile.trimmed().toLower();
250 } else if (p == QLatin1String("/version") || p == QLatin1String("-version")) {
251 ++i;
252 if (i > argc)
253 version = QLatin1String("1.0");
254 else
255 version = QLatin1String(argv[i]);
256 } else if (p == QLatin1String("/tlb") || p == QLatin1String("-tlb")) {
257 if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)
258 fprintf(stderr, "IDC requires Windows NT/2000/XP!\n");
259
260 ++i;
261 if (i > argc) {
262 error = QLatin1String("Missing name for type library file!");
263 break;
264 }
265 tlbfile = QLatin1String(argv[i]);
266 tlbfile = tlbfile.trimmed().toLower();
267 } else if (p == QLatin1String("/v") || p == QLatin1String("-v")) {
268 fprintf(stdout, "Qt Interface Definition Compiler version 1.0\n");
269 return 0;
270 } else if (p == QLatin1String("/regserver") || p == QLatin1String("-regserver")) {
271 if (!registerServer(input)) {
272 fprintf(stderr, "Failed to register server!\n");
273 return 1;
274 }
275 fprintf(stderr, "Server registered successfully!\n");
276 return 0;
277 } else if (p == QLatin1String("/unregserver") || p == QLatin1String("-unregserver")) {
278 if (!unregisterServer(input)) {
279 fprintf(stderr, "Failed to unregister server!\n");
280 return 1;
281 }
282 fprintf(stderr, "Server unregistered successfully!\n");
283 return 0;
284 } else if (p[0] == QLatin1Char('/') || p[0] == QLatin1Char('-')) {
285 error = QLatin1String("Unknown option \"") + p + QLatin1String("\"");
286 break;
287 } else {
288 input = QLatin1String(argv[i]);
289 input = input.trimmed().toLower();
290 }
291 i++;
292 }
293 if (!error.isEmpty()) {
294 fprintf(stderr, "%s", error.toLatin1().data());
295 fprintf(stderr, "\n");
296 return 5;
297 }
298 if (input.isEmpty()) {
299 fprintf(stderr, "No input file specified!\n");
300 return 1;
301 }
302 if (input.endsWith(QLatin1String(".exe")) && tlbfile.isEmpty() && idlfile.isEmpty()) {
303 fprintf(stderr, "No type output file specified!\n");
304 return 2;
305 }
306 if (input.endsWith(QLatin1String(".dll")) && idlfile.isEmpty() && tlbfile.isEmpty()) {
307 fprintf(stderr, "No interface definition file and no type library file specified!\n");
308 return 3;
309 }
310 slashify(input);
311 if (!tlbfile.isEmpty()) {
312 slashify(tlbfile);
313 QFile file(tlbfile);
314 if (!file.open(QIODevice::ReadOnly)) {
315 fprintf(stderr, "Couldn't open %s for read\n", (const char*)tlbfile.toLocal8Bit().data());
316 return 4;
317 }
318 QByteArray data = file.readAll();
319 QString error;
320 bool ok = attachTypeLibrary(input, 1, data, &error);
321 fprintf(stderr, "%s", error.toLatin1().data());
322 fprintf(stderr, "\n");
323 return ok ? 0 : 4;
324 } else if (!idlfile.isEmpty()) {
325 slashify(idlfile);
326 idlfile = quotePath(idlfile);
327 fprintf(stderr, "\n\n%s\n\n", (const char*)idlfile.toLocal8Bit().data());
328 quotePath(input);
329 HRESULT res = dumpIdl(input, idlfile, version);
330
331 switch(res) {
332 case S_OK:
333 break;
334 case -1:
335 fprintf(stderr, "Couldn't open %s for writing!\n", (const char*)idlfile.toLocal8Bit().data());
336 return res;
337 case 1:
338 fprintf(stderr, "Malformed appID value in %s!\n", (const char*)input.toLocal8Bit().data());
339 return res;
340 case 2:
341 fprintf(stderr, "Malformed typeLibID value in %s!\n", (const char*)input.toLocal8Bit().data());
342 return res;
343 case 3:
344 fprintf(stderr, "Class has no metaobject information (error in %s)!\n", (const char*)input.toLocal8Bit().data());
345 return res;
346 case 4:
347 fprintf(stderr, "Malformed classID value in %s!\n", (const char*)input.toLocal8Bit().data());
348 return res;
349 case 5:
350 fprintf(stderr, "Malformed interfaceID value in %s!\n", (const char*)input.toLocal8Bit().data());
351 return res;
352 case 6:
353 fprintf(stderr, "Malformed eventsID value in %s!\n", (const char*)input.toLocal8Bit().data());
354 return res;
355
356 default:
357 fprintf(stderr, "Unknown error writing IDL from %s\n", (const char*)input.toLocal8Bit().data());
358 return 7;
359 }
360 }
361 return 0;
362}
363
364QT_END_NAMESPACE
365
366int main(int argc, char **argv)
367{
368 return QT_PREPEND_NAMESPACE(runIdc)(argc, argv);
369}
Note: See TracBrowser for help on using the repository browser.