aboutsummaryrefslogtreecommitdiffstats
path: root/share
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@nokia.com>2009-06-04 19:39:48 +0200
committerOswald Buddenhagen <oswald.buddenhagen@nokia.com>2009-06-08 15:55:41 +0200
commit71ff4913ea5b0bb2aaf3c22dd764daf623cbacc8 (patch)
treee6bf83298ff541991e7203c5a11794ed7f02c3c8 /share
parent289d6f8596e307372a10e3b3851ea44f6be6fddb (diff)
move the qtcdebugger tool to an appropriate place
Diffstat (limited to 'share')
-rw-r--r--share/qtcreator/qtcdebugger/main.cpp422
-rw-r--r--share/qtcreator/qtcdebugger/qtcdebugger.pro12
-rw-r--r--share/share.pro4
3 files changed, 0 insertions, 438 deletions
diff --git a/share/qtcreator/qtcdebugger/main.cpp b/share/qtcreator/qtcdebugger/main.cpp
deleted file mode 100644
index 2f1e648647a..00000000000
--- a/share/qtcreator/qtcdebugger/main.cpp
+++ /dev/null
@@ -1,422 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** Commercial Usage
-**
-** Licensees holding valid Qt Commercial licenses may use this file in
-** accordance with the Qt Commercial License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Nokia.
-**
-** 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.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-**
-**************************************************************************/
-
-/* A debug dispatcher for Windows that can be registered for calls with crashed
- * processes. It offers debugging using either Qt Creator or
- * the previously registered default debugger.
- * See usage() on how to install/use.
- * Installs itself in the bin directory of Qt Creator. */
-
-#include <QtGui/QApplication>
-#include <QtGui/QMessageBox>
-#include <QtCore/QDebug>
-#include <QtCore/QTextStream>
-#include <QtCore/QFileInfo>
-#include <QtCore/QByteArray>
-#include <QtCore/QString>
-#include <QtCore/QDir>
-#include <QtCore/QProcess>
-#include <QtGui/QPushButton>
-
-#include <windows.h>
-#include <psapi.h>
-
-enum { debug = 0 };
-
-static const char *titleC = "Qt Creator Debugger";
-static const char *organizationC = "Nokia";
-
-static const WCHAR *debuggerRegistryKeyC = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug";
-// Optional
-static const WCHAR *debuggerWow32RegistryKeyC = L"Software\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug";
-
-static const WCHAR *debuggerRegistryValueNameC = L"Debugger";
-static const WCHAR *debuggerRegistryDefaultValueNameC = L"Debugger.Default";
-
-static const char *linkC = "http://msdn.microsoft.com/en-us/library/cc266343.aspx";
-
-static inline QString wCharToQString(const WCHAR *w) { return QString::fromUtf16(reinterpret_cast<const ushort *>(w)); }
-#ifdef __GNUC__
-#define RRF_RT_ANY 0x0000ffff // no type restriction
-#endif
-
-
-enum Mode { HelpMode, PromptMode, ForceCreatorMode, ForceDefaultMode };
-
-Mode optMode = PromptMode;
-bool optIsWow = false;
-unsigned long argProcessId = 0;
-quint64 argWinCrashEvent = 0;
-
-static QString winErrorMessage(unsigned long error)
-{
- QString rc = QString::fromLatin1("#%1: ").arg(error);
- ushort *lpMsgBuf;
-
- const int len = FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, error, 0, (LPTSTR)&lpMsgBuf, 0, NULL);
- if (len) {
- rc = QString::fromUtf16(lpMsgBuf, len);
- LocalFree(lpMsgBuf);
- } else {
- rc += QString::fromLatin1("<unknown error>");
- }
- return rc;
-}
-
-static inline QString msgFunctionFailed(const char *f, unsigned long error)
-{
- return QString::fromLatin1("'%1' failed: %2").arg(QLatin1String(f), winErrorMessage(error));
-}
-
-static bool parseArguments(const QStringList &args, QString *errorMessage)
-{
- int argNumber = 0;
- const int count = args.size();
- const QChar dash = QLatin1Char('-');
- const QChar slash = QLatin1Char('/');
- for (int i = 1; i < count; i++) {
- QString arg = args.at(i);
- if (arg.startsWith(dash) || arg.startsWith(slash)) { // option
- arg.remove(0, 1);
- if (arg == QLatin1String("help") || arg == QLatin1String("?")) {
- optMode = HelpMode;
- } else if (arg == QLatin1String("qtcreator")) {
- optMode = ForceCreatorMode;
- } else if (arg == QLatin1String("default")) {
- optMode = ForceDefaultMode;
- } else if (arg == QLatin1String("wow")) {
- optIsWow = true;
- } else {
- *errorMessage = QString::fromLatin1("Unexpected option: %1").arg(arg);
- return false;
- }
- } else { // argument
- bool ok = false;
- switch (argNumber++) {
- case 0:
- argProcessId = arg.toULong(&ok);
- break;
- case 1:
- argWinCrashEvent = arg.toULongLong(&ok);
- break;
- }
- if (!ok) {
- *errorMessage = QString::fromLatin1("Invalid argument: %1").arg(arg);
- return false;
- }
- }
- }
- if (optMode != HelpMode && argProcessId == 0) {
- *errorMessage = QString::fromLatin1("Please specify the process-id.");
- return false;
- }
- return true;
-}
-
-static void usage(const QString &binary, const QString &message = QString())
-{
- QString msg;
- QTextStream str(&msg);
- str << "<html><body>";
- if (message.isEmpty()) {
- str << "<h1>" << titleC << "</h1>"
- << "<p>Dispatcher that launches the desired debugger for a crashed process"
- " according to <a href=\"" << linkC << "\">Enabling Postmortem Debugging</a>.</p>";
- } else {
- str << "<b>" << message << "</b>";
- }
- str << "<pre>"
- << "Usage: " << QFileInfo(binary).baseName() << "[-wow] [-help|-?|qtcreator|default] &lt;process-id> &lt;event-id>\n"
- << "Options: -help, -? Display this help\n"
- << " -qtcreator Launch Qt Creator without prompting\n"
- << " -default Launch Default handler without prompting\n"
- << " -wow Indicates Wow32 call\n"
- << "</pre>"
- << "<p>To install, modify the registry key <i>HKEY_LOCAL_MACHINE\\" << wCharToQString(debuggerRegistryKeyC)
- << "</i>:</p><ul>"
- << "<li>Create a copy of the string value <i>" << wCharToQString(debuggerRegistryValueNameC)
- << "</i> as <i>" << wCharToQString(debuggerRegistryDefaultValueNameC) << "</i>"
- << "<li>Change the value of <i>" << wCharToQString(debuggerRegistryValueNameC) << "</i> to "
- << "<pre>\"" << QDir::toNativeSeparators(binary) << "\" %ld %ld</pre>"
- << "</ul>"
- << "<p>On 64-bit systems, do the same for the key <i>HKEY_LOCAL_MACHINE\\" << wCharToQString(debuggerWow32RegistryKeyC) << "</i>, "
- << "setting the new value to <pre>\"" << QDir::toNativeSeparators(binary) << "\" -wow %ld %ld</pre></p>"
- << "</body></html>";
-
- QMessageBox msgBox(QMessageBox::Information, QLatin1String(titleC), msg, QMessageBox::Ok);
- msgBox.exec();
-}
-
-// ------- Registry helpers
-
-static bool openRegistryKey(HKEY category, // HKEY_LOCAL_MACHINE, etc.
- const WCHAR *key,
- bool readWrite,
- HKEY *keyHandle,
- QString *errorMessage)
-{
-
- REGSAM accessRights = KEY_READ;
- if (readWrite)
- accessRights |= KEY_SET_VALUE;
- const LONG rc = RegOpenKeyEx(category, key, 0, accessRights, keyHandle);
- if (rc != ERROR_SUCCESS) {
- *errorMessage = msgFunctionFailed("RegOpenKeyEx", rc);
- return false;
- }
- return true;
-}
-
-static inline QString msgRegistryOperationFailed(const char *op, const WCHAR *valueName, const QString &why)
-{
- QString rc = QLatin1String("Registry ");
- rc += QLatin1String(op);
- rc += QLatin1String(" of ");
- rc += wCharToQString(valueName);
- rc += QLatin1String(" failed: ");
- rc += why;
- return rc;
-}
-
-static bool registryReadBinaryKey(HKEY handle, // HKEY_LOCAL_MACHINE, etc.
- const WCHAR *valueName,
- QByteArray *data,
- QString *errorMessage)
-{
- data->clear();
- DWORD type;
- DWORD size;
- // get size and retrieve
- LONG rc = RegQueryValueEx(handle, valueName, 0, &type, 0, &size);
- if (rc != ERROR_SUCCESS) {
- *errorMessage = msgRegistryOperationFailed("read", valueName, msgFunctionFailed("RegQueryValueEx1", rc));
- return false;
- }
- BYTE *dataC = new BYTE[size + 1];
- // Will be Utf16 in case of a string
- rc = RegQueryValueEx(handle, valueName, 0, &type, dataC, &size);
- if (rc != ERROR_SUCCESS) {
- *errorMessage = msgRegistryOperationFailed("read", valueName, msgFunctionFailed("RegQueryValueEx2", rc));
- return false;
- }
- *data = QByteArray(reinterpret_cast<const char*>(dataC), size);
- delete [] dataC;
- return true;
-}
-
-static bool registryReadStringKey(HKEY handle, // HKEY_LOCAL_MACHINE, etc.
- const WCHAR *valueName,
- QString *s,
- QString *errorMessage)
-{
- QByteArray data;
- if (!registryReadBinaryKey(handle, valueName, &data, errorMessage))
- return false;
- data += '\0';
- data += '\0';
- *s = QString::fromUtf16(reinterpret_cast<const unsigned short*>(data.data()));
- return true;
-}
-
-static inline bool registryWriteBinaryKey(HKEY handle,
- const WCHAR *valueName,
- DWORD type,
- const BYTE *data,
- DWORD size,
- QString *errorMessage)
-{
- const LONG rc = RegSetValueEx(handle, valueName, 0, type, data, size);
- if (rc != ERROR_SUCCESS) {
- *errorMessage = msgRegistryOperationFailed("write", valueName, msgFunctionFailed("RegSetValueEx", rc));
- return false;
- }
- return true;
-}
-
-static inline bool registryWriteStringKey(HKEY handle, // HKEY_LOCAL_MACHINE, etc.
- const WCHAR *key,
- const QString &s,
- QString *errorMessage)
-{
- const BYTE *data = reinterpret_cast<const BYTE *>(s.utf16());
- const DWORD size = 2 * s.size(); // excluding 0
- return registryWriteBinaryKey(handle, key, REG_SZ, data, size, errorMessage);
-}
-
-static inline bool registryReplaceStringKey(HKEY rootHandle, // HKEY_LOCAL_MACHINE, etc.
- const WCHAR *key,
- const WCHAR *valueName,
- const QString &newValue,
- QString *oldValue,
- QString *errorMessage)
-{
- HKEY handle = 0;
- bool rc = false;
- do {
- if (!openRegistryKey(rootHandle, key, true, &handle, errorMessage))
- break;
- if (!registryReadStringKey(handle, valueName, oldValue, errorMessage))
- break;
- if (*oldValue != newValue) {
- if (!registryWriteStringKey(handle, valueName, newValue, errorMessage))
- break;
- }
- rc = true;
- } while(false);
- if (handle)
- RegCloseKey(handle);
- return rc;
-}
-
-static QString getProcessBaseName(DWORD pid)
-{
- QString rc;
- const HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
- if (handle != NULL) {
- WCHAR buffer[MAX_PATH];
- if (GetModuleBaseName(handle, 0, buffer, MAX_PATH))
- rc = wCharToQString(buffer);
- CloseHandle(handle);
- }
- return rc;
-}
-
-// ------- main modes
-
-bool startCreatorAsDebugger(const QApplication &a, QString *errorMessage)
-{
- const QString dir = a.applicationDirPath();
- const QString binary = dir + QLatin1String("/qtcreator.exe");
- QStringList args;
- args << QLatin1String("-debug") << QString::number(argProcessId)
- << QLatin1String("-wincrashevent") << QString::number(argWinCrashEvent);
- if (debug)
- qDebug() << binary << args;
- QProcess p;
- p.setWorkingDirectory(dir);
- p.start(binary, args, QIODevice::NotOpen);
- if (!p.waitForStarted()) {
- *errorMessage = QString::fromLatin1("Unable to start %1!").arg(binary);
- return false;
- }
- p.waitForFinished(-1);
- return true;
-}
-
-bool startDefaultDebugger(const QApplication &a, QString *errorMessage)
-{
- // Read out default value
- HKEY handle;
- if (!openRegistryKey(HKEY_LOCAL_MACHINE, optIsWow ? debuggerWow32RegistryKeyC : debuggerRegistryKeyC,
- false, &handle, errorMessage))
- return false;
- QString defaultDebugger;
- if (!registryReadStringKey(handle, debuggerRegistryDefaultValueNameC, &defaultDebugger, errorMessage)) {
- RegCloseKey(handle);
- return false;
- }
- RegCloseKey(handle);
- // binary, replace placeholders by pid/event id
- if (debug)
- qDebug() << "Default" << defaultDebugger;
- const QString placeHolder = QLatin1String("%ld");
- const int pidPlaceHolderPos = defaultDebugger.indexOf(placeHolder);
- if (pidPlaceHolderPos == -1)
- return true; // was empty or sth
- defaultDebugger.replace(pidPlaceHolderPos, placeHolder.size(), QString::number(argProcessId));
- const int evtPlaceHolderPos = defaultDebugger.indexOf(placeHolder);
- if (evtPlaceHolderPos != -1)
- defaultDebugger.replace(evtPlaceHolderPos, placeHolder.size(), QString::number(argWinCrashEvent));
- if (debug)
- qDebug() << "Default" << defaultDebugger;
- QProcess p;
- p.start(defaultDebugger, QIODevice::NotOpen);
- if (!p.waitForStarted()) {
- *errorMessage = QString::fromLatin1("Unable to start %1!").arg(defaultDebugger);
- return false;
- }
- p.waitForFinished(-1);
- return true;
-}
-
-bool chooseDebugger(const QApplication &a, QString *errorMessage)
-{
- const QString msg = QString::fromLatin1("The application \"%1\" (process id %2) crashed. Would you like to debug it?").arg(getProcessBaseName(argProcessId)).arg(argProcessId);
- QMessageBox msgBox(QMessageBox::Information, QLatin1String(titleC), msg, QMessageBox::Cancel);
- QPushButton *creatorButton = msgBox.addButton(QLatin1String("Debug with Qt Creator"), QMessageBox::AcceptRole);
- QPushButton *defaultButton = msgBox.addButton(QLatin1String("Debug with default debugger"), QMessageBox::AcceptRole);
- msgBox.exec();
- if (msgBox.clickedButton() == creatorButton) {
- // Just in case, default to standard
- if (startCreatorAsDebugger(a, errorMessage))
- return true;
- return startDefaultDebugger(a, errorMessage);
- }
- if (msgBox.clickedButton() == defaultButton)
- return startDefaultDebugger(a, errorMessage);
- return true;
-}
-
-int main(int argc, char *argv[])
-{
- QApplication a(argc, argv);
- a.setApplicationName(QLatin1String(titleC));
- a.setOrganizationName(QLatin1String(organizationC));
- QString errorMessage;
-
- if (!parseArguments(a.arguments(), &errorMessage)) {
- qWarning("%s\n", qPrintable(errorMessage));
- usage(QCoreApplication::applicationFilePath(), errorMessage);
- return -1;
- }
- if (debug)
- qDebug() << "Mode=" << optMode << " PID=" << argProcessId << " Evt=" << argWinCrashEvent;
- bool ex = 0;
- switch (optMode) {
- case HelpMode:
- usage(QCoreApplication::applicationFilePath(), errorMessage);
- break;
- case ForceCreatorMode:
- ex = startCreatorAsDebugger(a, &errorMessage) ? 0 : -1;
- break;
- case ForceDefaultMode:
- ex = startDefaultDebugger(a, &errorMessage) ? 0 : -1;
- break;
- case PromptMode:
- ex = chooseDebugger(a, &errorMessage) ? 0 : -1;
- break;
- }
- if (ex && !errorMessage.isEmpty()) {
- qWarning("%s\n", qPrintable(errorMessage));
- QMessageBox::warning(0, QLatin1String(titleC), errorMessage, QMessageBox::Ok);
- }
- return ex;
-}
diff --git a/share/qtcreator/qtcdebugger/qtcdebugger.pro b/share/qtcreator/qtcdebugger/qtcdebugger.pro
deleted file mode 100644
index f336112edc6..00000000000
--- a/share/qtcreator/qtcdebugger/qtcdebugger.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-TARGET = qtcdebugger
-TEMPLATE = app
-CONFIG += console
-SOURCES += main.cpp
-
-LIBS *= -lpsapi
-# PS API and registry functions
-contains(QMAKE_CXX, cl) {
- LIBS *= -ladvapi32
-}
-
-DESTDIR=..\..\..\bin
diff --git a/share/share.pro b/share/share.pro
index 3bea274ee33..bbf224f2042 100644
--- a/share/share.pro
+++ b/share/share.pro
@@ -1,6 +1,2 @@
TEMPLATE = subdirs
SUBDIRS = qtcreator/static.pro qtcreator/translations
-
-win32 {
- SUBDIRS += qtcreator/qtcdebugger
-}