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

Last change on this file since 1056 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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