Index: remoting/tools/breakpad_tester_win.cc |
diff --git a/remoting/tools/breakpad_tester_win.cc b/remoting/tools/breakpad_tester_win.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..af1a095cfca2d0806268a9c4f3bbc4c6fe58fcb9 |
--- /dev/null |
+++ b/remoting/tools/breakpad_tester_win.cc |
@@ -0,0 +1,85 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <windows.h> |
+#include <stdlib.h> |
+ |
+#include "base/at_exit.h" |
+#include "base/command_line.h" |
+#include "base/logging.h" |
+#include "base/win/scoped_handle.h" |
+ |
+namespace { |
+ |
+// "--help" or "--?" prints the usage message. |
+const char kHelpSwitchName[] = "help"; |
+const char kQuestionSwitchName[] = "?"; |
+ |
+const char kUsageMessage[] = |
+ "\n" |
+ "Usage: %s <pid>\n" |
+ "\n" |
+ " pid - PID of the process to be crashed.\n"; |
+ |
+// 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); |
+} |
+ |
+} // namespace |
+ |
+int main(int argc, char** argv) { |
+ CommandLine::Init(argc, argv); |
+ |
+ base::AtExitManager exit_manager; |
+ |
+ InitLogging(NULL, |
+ logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG, |
+ logging::DONT_LOCK_LOG_FILE, |
+ logging::APPEND_TO_OLD_LOG_FILE, |
+ 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]); |
+ return kSuccessExitCode; |
+ } |
+ |
+ CommandLine::StringVector args = command_line->GetArgs(); |
+ if (args.size() != 1) { |
+ usage(argv[0]); |
+ return kUsageExitCode; |
+ } |
+ |
+ int pid = _wtoi(args[0].c_str()); |
+ if (pid == 0) { |
+ LOG(ERROR) << "Invalid process PID: " << args[0]; |
+ return kErrorExitCode; |
+ } |
+ |
+ DWORD desired_access = PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | |
+ PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ; |
+ base::win::ScopedHandle process; |
+ process.Set(OpenProcess(desired_access, FALSE, pid)); |
+ if (!process.IsValid()) { |
+ LOG_GETLASTERROR(ERROR) << "Failed to open the process " << pid; |
+ return kErrorExitCode; |
+ } |
+ |
+ DWORD thread_id; |
+ base::win::ScopedHandle thread; |
+ thread.Set(CreateRemoteThread(process.Get(), NULL, 0, NULL, NULL, 0, |
+ &thread_id)); |
+ if (!thread.IsValid()) { |
+ LOG_GETLASTERROR(ERROR) << "Failed to create a remote thread in " << pid; |
+ return kErrorExitCode; |
+ } |
+ |
+ return kSuccessExitCode; |
+} |