/******************************************************************************** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).** All rights reserved.** Contact: Nokia Corporation (qt-info@nokia.com)**** This file is part of the tools applications of the Qt Toolkit.**** $QT_BEGIN_LICENSE:LGPL$** No Commercial Usage** This file contains pre-release code and may not be distributed.** You may use this file in accordance with the terms and conditions** contained in the Technology Preview License Agreement accompanying** this package.**** GNU Lesser General Public License Usage** Alternatively, this file may be used under the terms of the GNU Lesser** General Public License version 2.1 as published by the Free Software** Foundation and appearing in the file LICENSE.LGPL included in the** packaging of this file. Please review the following information to** ensure the GNU Lesser General Public License version 2.1 requirements** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.**** In addition, as a special exception, Nokia gives you certain additional** rights. These rights are described in the Nokia Qt LGPL Exception** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.**** If you have questions regarding the use of this file, please contact** Nokia at qt-info@nokia.com.****************** $QT_END_LICENSE$******************************************************************************/#include <QFile>#include <QProcess>#include <QLibraryInfo>#include <qt_windows.h>#include <io.h>QT_BEGIN_NAMESPACEstatic QString quotePath(const QString &s){ if (!s.startsWith(QLatin1Char('\"')) && s.contains(QLatin1Char(' '))) return QLatin1Char('\"') + s + QLatin1Char('\"'); return s;}static bool runWithQtInEnvironment(const QString &cmd){ QProcess proc; // prepend the qt binary directory to the path QStringList env = QProcess::systemEnvironment(); for (int i=0; i<env.count(); ++i) { QString var = env.at(i); int setidx = var.indexOf(QLatin1Char('=')); if (setidx != -1) { QString varname = var.left(setidx).trimmed().toUpper(); if (varname == QLatin1String("PATH")) { var = var.mid(setidx + 1); var = QLatin1String("PATH=") + QLibraryInfo::location(QLibraryInfo::BinariesPath) + QLatin1Char(';') + var; env[i] = var; break; } } } proc.setEnvironment(env); proc.start(cmd); proc.waitForFinished(-1); return (proc.exitCode() == 0);}static bool attachTypeLibrary(const QString &applicationName, int resource, const QByteArray &data, QString *errorMessage){ HANDLE hExe = BeginUpdateResource((const wchar_t *)applicationName.utf16(), false); if (hExe == 0) { if (errorMessage) *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not open file.").arg(applicationName); return false; } if (!UpdateResource(hExe, L"TYPELIB", MAKEINTRESOURCE(resource), 0, (void*)data.data(), data.count())) { EndUpdateResource(hExe, true); if (errorMessage) *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not update file.").arg(applicationName); return false; } if (!EndUpdateResource(hExe,false)) { if (errorMessage) *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not write file.").arg(applicationName); return false; } if (errorMessage) *errorMessage = QString::fromLatin1("Type library attached to %1.").arg(applicationName); return true;}static bool registerServer(const QString &input){ bool ok = false; if (input.endsWith(QLatin1String(".exe"))) { ok = runWithQtInEnvironment(quotePath(input) + QLatin1String(" -regserver")); } else { HMODULE hdll = LoadLibrary((const wchar_t *)input.utf16()); if (!hdll) { fprintf(stderr, "Couldn't load library file %s\n", (const char*)input.toLocal8Bit().data()); return false; } typedef HRESULT(__stdcall* RegServerProc)(); RegServerProc DllRegisterServer = (RegServerProc)GetProcAddress(hdll, "DllRegisterServer"); if (!DllRegisterServer) { fprintf(stderr, "Library file %s doesn't appear to be a COM library\n", (const char*)input.toLocal8Bit().data()); return false; } ok = DllRegisterServer() == S_OK; } return ok;}static bool unregisterServer(const QString &input){ bool ok = false; if (input.endsWith(QLatin1String(".exe"))) { ok = runWithQtInEnvironment(quotePath(input) + QLatin1String(" -unregserver")); } else { HMODULE hdll = LoadLibrary((const wchar_t *)input.utf16()); if (!hdll) { fprintf(stderr, "Couldn't load library file %s\n", (const char*)input.toLocal8Bit().data()); return false; } typedef HRESULT(__stdcall* RegServerProc)(); RegServerProc DllUnregisterServer = (RegServerProc)GetProcAddress(hdll, "DllUnregisterServer"); if (!DllUnregisterServer) { fprintf(stderr, "Library file %s doesn't appear to be a COM library\n", (const char*)input.toLocal8Bit().data()); return false; } ok = DllUnregisterServer() == S_OK; } return ok;}static HRESULT dumpIdl(const QString &input, const QString &idlfile, const QString &version){ HRESULT res = E_FAIL; if (input.endsWith(QLatin1String(".exe"))) { if (runWithQtInEnvironment(quotePath(input) + QLatin1String(" -dumpidl ") + idlfile + QLatin1String(" -version ") + version)) res = S_OK; } else { HMODULE hdll = LoadLibrary((const wchar_t *)input.utf16()); if (!hdll) { fprintf(stderr, "Couldn't load library file %s\n", (const char*)input.toLocal8Bit().data()); return 3; } typedef HRESULT(__stdcall* DumpIDLProc)(const QString&, const QString&); DumpIDLProc DumpIDL = (DumpIDLProc)GetProcAddress(hdll, "DumpIDL"); if (!DumpIDL) { fprintf(stderr, "Couldn't resolve 'DumpIDL' symbol in %s\n", (const char*)input.toLocal8Bit().data()); return 3; } res = DumpIDL(idlfile, version); FreeLibrary(hdll); } return res;}static void slashify(QString &s){ if (!s.contains(QLatin1Char('/'))) return; int i = 0; while (i < (int)s.length()) { if (s[i] == QLatin1Char('/')) s[i] = QLatin1Char('\\'); ++i; }}int runIdc(int argc, char **argv){ QString error; QString tlbfile; QString idlfile; QString input; QString version = QLatin1String("1.0"); int i = 1; while (i < argc) { QString p = QString::fromLocal8Bit(argv[i]).toLower(); if (p == QLatin1String("/idl") || p == QLatin1String("-idl")) { ++i; if (i > argc) { error = QLatin1String("Missing name for interface definition file!"); break; } idlfile = QLatin1String(argv[i]); idlfile = idlfile.trimmed().toLower(); } else if (p == QLatin1String("/version") || p == QLatin1String("-version")) { ++i; if (i > argc) version = QLatin1String("1.0"); else version = QLatin1String(argv[i]); } else if (p == QLatin1String("/tlb") || p == QLatin1String("-tlb")) { ++i; if (i > argc) { error = QLatin1String("Missing name for type library file!"); break; } tlbfile = QLatin1String(argv[i]); tlbfile = tlbfile.trimmed().toLower(); } else if (p == QLatin1String("/v") || p == QLatin1String("-v")) { fprintf(stdout, "Qt Interface Definition Compiler version 1.0\n"); return 0; } else if (p == QLatin1String("/regserver") || p == QLatin1String("-regserver")) { if (!registerServer(input)) { fprintf(stderr, "Failed to register server!\n"); return 1; } fprintf(stderr, "Server registered successfully!\n"); return 0; } else if (p == QLatin1String("/unregserver") || p == QLatin1String("-unregserver")) { if (!unregisterServer(input)) { fprintf(stderr, "Failed to unregister server!\n"); return 1; } fprintf(stderr, "Server unregistered successfully!\n"); return 0; } else if (p[0] == QLatin1Char('/') || p[0] == QLatin1Char('-')) { error = QLatin1String("Unknown option \"") + p + QLatin1Char('\"'); break; } else { input = QLatin1String(argv[i]); input = input.trimmed().toLower(); } i++; } if (!error.isEmpty()) { fprintf(stderr, "%s", error.toLatin1().data()); fprintf(stderr, "\n"); return 5; } if (input.isEmpty()) { fprintf(stderr, "No input file specified!\n"); return 1; } if (input.endsWith(QLatin1String(".exe")) && tlbfile.isEmpty() && idlfile.isEmpty()) { fprintf(stderr, "No type output file specified!\n"); return 2; } if (input.endsWith(QLatin1String(".dll")) && idlfile.isEmpty() && tlbfile.isEmpty()) { fprintf(stderr, "No interface definition file and no type library file specified!\n"); return 3; } slashify(input); if (!tlbfile.isEmpty()) { slashify(tlbfile); QFile file(tlbfile); if (!file.open(QIODevice::ReadOnly)) { fprintf(stderr, "Couldn't open %s for read\n", (const char*)tlbfile.toLocal8Bit().data()); return 4; } QByteArray data = file.readAll(); QString error; bool ok = attachTypeLibrary(input, 1, data, &error); fprintf(stderr, "%s", error.toLatin1().data()); fprintf(stderr, "\n"); return ok ? 0 : 4; } else if (!idlfile.isEmpty()) { slashify(idlfile); idlfile = quotePath(idlfile); fprintf(stderr, "\n\n%s\n\n", (const char*)idlfile.toLocal8Bit().data()); quotePath(input); HRESULT res = dumpIdl(input, idlfile, version); switch(res) { case S_OK: break; case E_FAIL: fprintf(stderr, "IDL generation failed trying to run program %s!\n", (const char*)input.toLocal8Bit().data()); return res; case -1: fprintf(stderr, "Couldn't open %s for writing!\n", (const char*)idlfile.toLocal8Bit().data()); return res; case 1: fprintf(stderr, "Malformed appID value in %s!\n", (const char*)input.toLocal8Bit().data()); return res; case 2: fprintf(stderr, "Malformed typeLibID value in %s!\n", (const char*)input.toLocal8Bit().data()); return res; case 3: fprintf(stderr, "Class has no metaobject information (error in %s)!\n", (const char*)input.toLocal8Bit().data()); return res; case 4: fprintf(stderr, "Malformed classID value in %s!\n", (const char*)input.toLocal8Bit().data()); return res; case 5: fprintf(stderr, "Malformed interfaceID value in %s!\n", (const char*)input.toLocal8Bit().data()); return res; case 6: fprintf(stderr, "Malformed eventsID value in %s!\n", (const char*)input.toLocal8Bit().data()); return res; default: fprintf(stderr, "Unknown error writing IDL from %s\n", (const char*)input.toLocal8Bit().data()); return 7; } } return 0;}QT_END_NAMESPACEint main(int argc, char **argv){ return QT_PREPEND_NAMESPACE(runIdc)(argc, argv);}