launcher_win.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "platform/win/launcher_win.h"
  8. #include "core/crash_reports.h"
  9. #include "core/update_checker.h"
  10. #include <windows.h>
  11. #include <shellapi.h>
  12. #include <VersionHelpers.h>
  13. namespace Platform {
  14. Launcher::Launcher(int argc, char *argv[])
  15. : Core::Launcher(argc, argv) {
  16. }
  17. std::optional<QStringList> Launcher::readArgumentsHook(
  18. int argc,
  19. char *argv[]) const {
  20. auto count = 0;
  21. if (const auto list = CommandLineToArgvW(GetCommandLine(), &count)) {
  22. const auto guard = gsl::finally([&] { LocalFree(list); });
  23. if (count > 0) {
  24. auto result = QStringList();
  25. result.reserve(count);
  26. for (auto i = 0; i != count; ++i) {
  27. result.push_back(QString::fromWCharArray(list[i]));
  28. }
  29. return result;
  30. }
  31. }
  32. return std::nullopt;
  33. }
  34. bool Launcher::launchUpdater(UpdaterLaunch action) {
  35. if (cExeName().isEmpty()) {
  36. return false;
  37. }
  38. const auto operation = (action == UpdaterLaunch::JustRelaunch)
  39. ? QString()
  40. : (cWriteProtected()
  41. ? u"runas"_q
  42. : QString());
  43. const auto binaryPath = (action == UpdaterLaunch::JustRelaunch)
  44. ? (cExeDir() + cExeName())
  45. : (cWriteProtected()
  46. ? (cWorkingDir() + u"tupdates/temp/Updater.exe"_q)
  47. : (cExeDir() + u"Updater.exe"_q));
  48. auto argumentsList = QStringList();
  49. const auto pushArgument = [&](const QString &argument) {
  50. argumentsList.push_back(argument.trimmed());
  51. };
  52. if (cLaunchMode() == LaunchModeAutoStart) {
  53. pushArgument(u"-autostart"_q);
  54. }
  55. if (Logs::DebugEnabled()) {
  56. pushArgument(u"-debug"_q);
  57. }
  58. if (cStartInTray()) {
  59. pushArgument(u"-startintray"_q);
  60. }
  61. if (customWorkingDir()) {
  62. pushArgument(u"-workdir"_q);
  63. pushArgument('"' + cWorkingDir() + '"');
  64. }
  65. if (cDataFile() != u"data"_q) {
  66. pushArgument(u"-key"_q);
  67. pushArgument('"' + cDataFile() + '"');
  68. }
  69. if (action == UpdaterLaunch::JustRelaunch) {
  70. pushArgument(u"-noupdate"_q);
  71. if (cRestartingToSettings()) {
  72. pushArgument(u"-tosettings"_q);
  73. }
  74. } else {
  75. pushArgument(u"-update"_q);
  76. pushArgument(u"-exename"_q);
  77. pushArgument('"' + cExeName() + '"');
  78. if (cWriteProtected()) {
  79. pushArgument(u"-writeprotected"_q);
  80. pushArgument('"' + cExeDir() + '"');
  81. }
  82. }
  83. return launch(operation, binaryPath, argumentsList);
  84. }
  85. bool Launcher::launch(
  86. const QString &operation,
  87. const QString &binaryPath,
  88. const QStringList &argumentsList) {
  89. const auto convertPath = [](const QString &path) {
  90. return QDir::toNativeSeparators(path).toStdWString();
  91. };
  92. const auto nativeBinaryPath = convertPath(binaryPath);
  93. const auto nativeWorkingDir = convertPath(cWorkingDir());
  94. const auto arguments = argumentsList.join(' ');
  95. DEBUG_LOG(("Application Info: executing %1 %2"
  96. ).arg(binaryPath
  97. ).arg(arguments
  98. ));
  99. Logs::closeMain();
  100. CrashReports::Finish();
  101. const auto hwnd = HWND(0);
  102. const auto result = ShellExecute(
  103. hwnd,
  104. operation.isEmpty() ? nullptr : operation.toStdWString().c_str(),
  105. nativeBinaryPath.c_str(),
  106. arguments.toStdWString().c_str(),
  107. nativeWorkingDir.empty() ? nullptr : nativeWorkingDir.c_str(),
  108. SW_SHOWNORMAL);
  109. if (int64(result) < 32) {
  110. DEBUG_LOG(("Application Error: failed to execute %1, working directory: '%2', result: %3"
  111. ).arg(binaryPath
  112. ).arg(cWorkingDir()
  113. ).arg(int64(result)
  114. ));
  115. return false;
  116. }
  117. return true;
  118. }
  119. } // namespace Platform