1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <windows.h>
6#include <stdlib.h>
7
8#include "base/at_exit.h"
9#include "base/command_line.h"
10#include "base/win/scoped_handle.h"
11#include "remoting/host/logging.h"
12
13namespace {
14
15// "--help" or "--?" prints the usage message.
16const char kHelpSwitchName[] = "help";
17const char kQuestionSwitchName[] = "?";
18
19const char kUsageMessage[] =
20  "\n"
21  "Usage: %s <pid>\n"
22  "\n"
23  "  pid  - PID of the process to be crashed.\n";
24
25// Exit codes:
26const int kSuccessExitCode = 0;
27const int kUsageExitCode = 1;
28const int kErrorExitCode = 2;
29
30void usage(const char* program_name) {
31  fprintf(stderr, kUsageMessage, program_name);
32}
33
34}  // namespace
35
36int main(int argc, char** argv) {
37  base::CommandLine::Init(argc, argv);
38
39  base::AtExitManager exit_manager;
40
41  remoting::InitHostLogging();
42
43  const base::CommandLine* command_line =
44      base::CommandLine::ForCurrentProcess();
45  if (command_line->HasSwitch(kHelpSwitchName) ||
46      command_line->HasSwitch(kQuestionSwitchName)) {
47    usage(argv[0]);
48    return kSuccessExitCode;
49  }
50
51  base::CommandLine::StringVector args = command_line->GetArgs();
52  if (args.size() != 1) {
53    usage(argv[0]);
54    return kUsageExitCode;
55  }
56
57  int pid = _wtoi(args[0].c_str());
58  if (pid == 0) {
59    LOG(ERROR) << "Invalid process PID: " << args[0];
60    return kErrorExitCode;
61  }
62
63  DWORD desired_access = PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
64      PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ;
65  base::win::ScopedHandle process;
66  process.Set(OpenProcess(desired_access, FALSE, pid));
67  if (!process.IsValid()) {
68    PLOG(ERROR) << "Failed to open the process " << pid;
69    return kErrorExitCode;
70  }
71
72  DWORD thread_id;
73  base::win::ScopedHandle thread;
74  thread.Set(CreateRemoteThread(process.Get(), NULL, 0, NULL, NULL, 0,
75                                &thread_id));
76  if (!thread.IsValid()) {
77    PLOG(ERROR) << "Failed to create a remote thread in " << pid;
78    return kErrorExitCode;
79  }
80
81  return kSuccessExitCode;
82}
83