From: Friedemann Kleint Date: Tue, 16 Jun 2009 09:59:32 +0000 (+0200) Subject: Add install/uninstall to qtcdebugger dispatcher. X-Git-Tag: v1.2.0~20 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=cd8af32ed4df10352efd78c493041ad40d591c53;p=qt-creator-jp%2Fqt-creator-jp.git Add install/uninstall to qtcdebugger dispatcher. Acked-by: Daniel Molkentin --- diff --git a/src/tools/qtcdebugger/main.cpp b/src/tools/qtcdebugger/main.cpp index 2f1e648647..80c39de8ed 100644 --- a/src/tools/qtcdebugger/main.cpp +++ b/src/tools/qtcdebugger/main.cpp @@ -51,6 +51,7 @@ enum { debug = 0 }; static const char *titleC = "Qt Creator Debugger"; static const char *organizationC = "Nokia"; +static const char *applicationFileC = "qtcdebugger"; static const WCHAR *debuggerRegistryKeyC = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug"; // Optional @@ -67,7 +68,7 @@ static inline QString wCharToQString(const WCHAR *w) { return QString::fromUtf16 #endif -enum Mode { HelpMode, PromptMode, ForceCreatorMode, ForceDefaultMode }; +enum Mode { HelpMode, InstallMode, UninstallMode, PromptMode, ForceCreatorMode, ForceDefaultMode }; Mode optMode = PromptMode; bool optIsWow = false; @@ -112,6 +113,10 @@ static bool parseArguments(const QStringList &args, QString *errorMessage) optMode = ForceCreatorMode; } else if (arg == QLatin1String("default")) { optMode = ForceDefaultMode; + } else if (arg == QLatin1String("install")) { + optMode = InstallMode; + } else if (arg == QLatin1String("uninstall")) { + optMode = UninstallMode; } else if (arg == QLatin1String("wow")) { optIsWow = true; } else { @@ -134,9 +139,16 @@ static bool parseArguments(const QStringList &args, QString *errorMessage) } } } - if (optMode != HelpMode && argProcessId == 0) { - *errorMessage = QString::fromLatin1("Please specify the process-id."); - return false; + switch (optMode) { + case HelpMode: + case InstallMode: + case UninstallMode: + break; + default: + if (argProcessId == 0) { + *errorMessage = QString::fromLatin1("Please specify the process-id."); + return false; + } } return true; } @@ -154,10 +166,12 @@ static void usage(const QString &binary, const QString &message = QString()) str << "" << message << ""; } str << "
"
-        << "Usage: " << QFileInfo(binary).baseName() << "[-wow] [-help|-?|qtcreator|default] <process-id> <event-id>\n"
+        << "Usage: " << QFileInfo(binary).baseName() << "[-wow] [-help|-?|qtcreator|default|install|uninstall] <process-id> <event-id>\n"
         << "Options: -help, -?   Display this help\n"
         << "         -qtcreator  Launch Qt Creator without prompting\n"
         << "         -default    Launch Default handler without prompting\n"
+        << "         -install    Install itself (requires administrative privileges)\n"
+        << "         -uninstall  Uninstall itself (requires administrative privileges)\n"
         << "         -wow        Indicates Wow32 call\n"
         << "
" << "

To install, modify the registry key HKEY_LOCAL_MACHINE\\" << wCharToQString(debuggerRegistryKeyC) @@ -169,6 +183,8 @@ static void usage(const QString &binary, const QString &message = QString()) << "" << "

On 64-bit systems, do the same for the key HKEY_LOCAL_MACHINE\\" << wCharToQString(debuggerWow32RegistryKeyC) << ", " << "setting the new value to

\"" << QDir::toNativeSeparators(binary) << "\" -wow %ld %ld

" + << "

How to run a command with administrative privileges:

" + << "
runas /env /noprofile /user:Administrator \"command arguments\"
" << ""; QMessageBox msgBox(QMessageBox::Information, QLatin1String(titleC), msg, QMessageBox::Ok); @@ -296,6 +312,18 @@ static inline bool registryReplaceStringKey(HKEY rootHandle, // HKEY_LOCAL_MACHI return rc; } +static inline bool registryDeleteValue(HKEY handle, + const WCHAR *valueName, + QString *errorMessage) +{ + const LONG rc = RegDeleteValue(handle, valueName); + if (rc != ERROR_SUCCESS) { + *errorMessage = msgFunctionFailed("RegDeleteValue", rc); + return false; + } + return true; +} + static QString getProcessBaseName(DWORD pid) { QString rc; @@ -331,7 +359,7 @@ bool startCreatorAsDebugger(const QApplication &a, QString *errorMessage) return true; } -bool startDefaultDebugger(const QApplication &a, QString *errorMessage) +bool startDefaultDebugger(const QApplication & /*a*/, QString *errorMessage) { // Read out default value HKEY handle; @@ -385,6 +413,99 @@ bool chooseDebugger(const QApplication &a, QString *errorMessage) return true; } +// Installation helpers: Format the debugger call with placeholders for PID and event +// '"[path]\qtcdebugger" [-wow] %ld %ld'. + +static QString debuggerCall(const QApplication &a, const QString &additionalOption = QString()) +{ + QString rc; + QTextStream str(&rc); + str << '"' << QDir::toNativeSeparators(a.applicationFilePath()) << '"'; + if (!additionalOption.isEmpty()) + str << ' ' << additionalOption; + str << " %ld %ld"; + return rc; +} + +// Installation helper: Register ourselves in a debugger registry key. +// Make a copy of the old value as "Debugger.Default" and have the +// "Debug" key point to us. + +static bool registerDebuggerKey(const WCHAR *key, + const QString &call, + QString *errorMessage) +{ + HKEY handle = 0; + bool success = false; + do { + if (!openRegistryKey(HKEY_LOCAL_MACHINE, key, true, &handle, errorMessage)) + break; + QString oldDebugger; + if (!registryReadStringKey(handle, debuggerRegistryValueNameC, &oldDebugger, errorMessage)) + break; + if (oldDebugger.contains(QLatin1String(applicationFileC), Qt::CaseInsensitive)) { + *errorMessage = QLatin1String("The program is already installed."); + return false; + } + if (!registryWriteStringKey(handle, debuggerRegistryDefaultValueNameC, oldDebugger, errorMessage)) + break; + if (debug) + qDebug() << "registering self as " << call; + if (!registryWriteStringKey(handle, debuggerRegistryValueNameC, call, errorMessage)) + break; + success = true; + } while (false); + if (handle) + RegCloseKey(handle); + return success; +} + +bool install(const QApplication &a, QString *errorMessage) +{ + if (!registerDebuggerKey(debuggerRegistryKeyC, debuggerCall(a), errorMessage)) + return false; +#ifdef Q_OS_WIN64 + if (!registerDebuggerKey(debuggerWow32RegistryKeyC, debuggerCall(a, QLatin1String("-wow")), errorMessage)) + return false; +#endif + return true; +} + +// Uninstall helper: Restore the original debugger key +static bool unregisterDebuggerKey(const WCHAR *key, QString *errorMessage) +{ + HKEY handle = 0; + bool success = false; + do { + if (!openRegistryKey(HKEY_LOCAL_MACHINE, key, true, &handle, errorMessage)) + break; + QString oldDebugger; + if (!registryReadStringKey(handle, debuggerRegistryDefaultValueNameC, &oldDebugger, errorMessage)) + break; + if (!registryWriteStringKey(handle, debuggerRegistryValueNameC, oldDebugger, errorMessage)) + break; + if (!registryDeleteValue(handle, debuggerRegistryDefaultValueNameC, errorMessage)) + break; + success = true; + } while (false); + if (handle) + RegCloseKey(handle); + return success; +} + + +bool uninstall(const QApplication & /*a*/, QString *errorMessage) +{ + if (!unregisterDebuggerKey(debuggerRegistryKeyC, errorMessage)) + return false; +#ifdef Q_OS_WIN64 + if (!unregisterDebuggerKey(debuggerWow32RegistryKeyC, errorMessage)) + return false; +#endif + return true; +} + + int main(int argc, char *argv[]) { QApplication a(argc, argv); @@ -413,6 +534,12 @@ int main(int argc, char *argv[]) case PromptMode: ex = chooseDebugger(a, &errorMessage) ? 0 : -1; break; + case InstallMode: + ex = install(a, &errorMessage) ? 0 : -1; + break; + case UninstallMode: + ex = uninstall(a, &errorMessage) ? 0 : -1; + break; } if (ex && !errorMessage.isEmpty()) { qWarning("%s\n", qPrintable(errorMessage));