Index: remoting/host/win/host_service.cc |
diff --git a/remoting/host/win/host_service.cc b/remoting/host/win/host_service.cc |
index 0c6ccb504cae1cfef86f769853ac447fefc9cae4..4c82f575e5d997d99778eaf6c9bd8cb064c7a252 100644 |
--- a/remoting/host/win/host_service.cc |
+++ b/remoting/host/win/host_service.cc |
@@ -8,11 +8,12 @@ |
#include "remoting/host/win/host_service.h" |
#include <windows.h> |
+#include <shellapi.h> |
#include <wtsapi32.h> |
-#include <stdio.h> |
#include "base/at_exit.h" |
#include "base/base_paths.h" |
+#include "base/base_switches.h" |
#include "base/bind.h" |
#include "base/command_line.h" |
#include "base/file_path.h" |
@@ -53,35 +54,41 @@ const char kIoThreadName[] = "I/O thread"; |
const wchar_t kSessionNotificationWindowClass[] = |
L"Chromoting_SessionNotificationWindow"; |
-// Command line actions and switches: |
-// "run" sumply runs the service as usual. |
-const wchar_t kRunActionName[] = L"run"; |
+// Command line switches: |
// "--console" runs the service interactively for debugging purposes. |
const char kConsoleSwitchName[] = "console"; |
+// "--elevate=<binary>" requests <binary> to be launched elevated presenting UAC |
+// promt if required. |
+const char kElevateSwitchName[] = "elevate"; |
+ |
// "--help" or "--?" prints the usage message. |
const char kHelpSwitchName[] = "help"; |
const char kQuestionSwitchName[] = "?"; |
-const char kUsageMessage[] = |
- "\n" |
- "Usage: %s [action] [options]\n" |
- "\n" |
- "Actions:\n" |
- " run - Run the service (default if no action was specified).\n" |
- "\n" |
- "Options:\n" |
- " --console - Run the service interactively for debugging purposes.\n" |
- " --help, --? - Print this message.\n"; |
+const wchar_t kUsageMessage[] = |
+ L"\n" |
+ L"Usage: %ls [options]\n" |
+ L"\n" |
+ L"Options:\n" |
+ L" --console - Run the service interactively for debugging purposes.\n" |
+ L" --elevate=<...> - Run <...> elevated.\n" |
+ L" --help, --? - Print this message.\n"; |
+ |
+// The command line parameters that should be copied from the service's command |
+// line when launching an elevated child. |
+const char* kCopiedSwitchNames[] = { |
+ "auth-config", "host-config", switches::kV, switches::kVModule }; |
// Exit codes: |
const int kSuccessExitCode = 0; |
const int kUsageExitCode = 1; |
const int kErrorExitCode = 2; |
-void usage(const char* program_name) { |
- fprintf(stderr, kUsageMessage, program_name); |
+void usage(const FilePath& program_name) { |
+ LOG(INFO) << StringPrintf(kUsageMessage, |
+ UTF16ToWide(program_name.value()).c_str()); |
} |
} // namespace |
@@ -164,17 +171,15 @@ HostService* HostService::GetInstance() { |
bool HostService::InitWithCommandLine(const CommandLine* command_line) { |
CommandLine::StringVector args = command_line->GetArgs(); |
- // Choose the action to perform. |
+ // Perform elevation is requested. |
+ if (command_line->HasSwitch(kElevateSwitchName)) { |
+ run_routine_ = &HostService::Elevate; |
+ return true; |
+ } |
+ |
if (!args.empty()) { |
- if (args.size() > 1) { |
- LOG(ERROR) << "Invalid command line: more than one action requested."; |
- return false; |
- } |
- if (args[0] != kRunActionName) { |
- LOG(ERROR) << "Invalid command line: invalid action specified: " |
- << args[0]; |
- return false; |
- } |
+ LOG(ERROR) << "No positional parameters expected."; |
+ return false; |
} |
// Run interactively if needed. |
@@ -225,6 +230,35 @@ void HostService::RunMessageLoop(MessageLoop* message_loop) { |
stopped_event_.Signal(); |
} |
+int HostService::Elevate() { |
+ // Get the name of the binary to launch. |
+ FilePath binary = |
+ CommandLine::ForCurrentProcess()->GetSwitchValuePath(kElevateSwitchName); |
+ |
+ // Create the child process command line by copying known switches from our |
+ // command line. |
+ CommandLine command_line(CommandLine::NO_PROGRAM); |
+ command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(), |
+ kCopiedSwitchNames, |
+ _countof(kCopiedSwitchNames)); |
+ CommandLine::StringType parameters = command_line.GetCommandLineString(); |
+ |
+ // Launch the child process requesting elevation. |
+ SHELLEXECUTEINFO info; |
+ memset(&info, 0, sizeof(info)); |
+ info.cbSize = sizeof(info); |
+ info.lpVerb = L"runas"; |
+ info.lpFile = binary.value().c_str(); |
+ info.lpParameters = parameters.c_str(); |
+ info.nShow = SW_SHOWNORMAL; |
+ |
+ if (!ShellExecuteEx(&info)) { |
+ return GetLastError(); |
+ } |
+ |
+ return kSuccessExitCode; |
+} |
+ |
int HostService::RunAsService() { |
SERVICE_TABLE_ENTRYW dispatch_table[] = { |
{ const_cast<LPWSTR>(kWindowsServiceName), &HostService::ServiceMain }, |
@@ -409,14 +443,19 @@ LRESULT CALLBACK HostService::SessionChangeNotificationProc(HWND hwnd, |
} // namespace remoting |
-int main(int argc, char** argv) { |
+int CALLBACK WinMain(HINSTANCE /* instance */, |
rvargas (doing something else)
2012/08/13 18:54:12
nit: why not just leave the variable name without
alexeypa (please no reviews)
2012/08/13 20:02:23
Done.
|
+ HINSTANCE /* previous_instance */, |
+ LPSTR /* command_line */, |
+ int /* show_command */) { |
#ifdef OFFICIAL_BUILD |
if (remoting::IsUsageStatsAllowed()) { |
remoting::InitializeCrashReporting(); |
} |
#endif // OFFICIAL_BUILD |
- CommandLine::Init(argc, argv); |
+ // CommandLine::Init() ignores the passed |argc| and |argv| on Windows getting |
+ // the command line from GetCommandLineW(), so we can safely pass NULL here. |
+ CommandLine::Init(0, NULL); |
// This object instance is required by Chrome code (for example, |
// FilePath, LazyInstance, MessageLoop). |
@@ -432,16 +471,15 @@ int main(int argc, char** argv) { |
logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS); |
const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
- |
if (command_line->HasSwitch(kHelpSwitchName) || |
command_line->HasSwitch(kQuestionSwitchName)) { |
- usage(argv[0]); |
+ usage(command_line->GetProgram()); |
return kSuccessExitCode; |
} |
remoting::HostService* service = remoting::HostService::GetInstance(); |
if (!service->InitWithCommandLine(command_line)) { |
- usage(argv[0]); |
+ usage(command_line->GetProgram()); |
return kUsageExitCode; |
} |