Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / browser_watcher / exit_code_watcher_win.cc
blob0e2318472f455a2c9f40b4b2b12622aa9eca7e68
1 // Copyright (c) 2014 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.
5 #include "components/browser_watcher/exit_code_watcher_win.h"
7 #include "base/logging.h"
8 #include "base/process/kill.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/win/registry.h"
12 namespace browser_watcher {
14 namespace {
16 base::string16 GetValueName(const base::Time creation_time,
17 base::ProcessId pid) {
18 // Convert the PID and creation time to a string value unique to this
19 // process instance.
20 return base::StringPrintf(L"%d-%lld", pid, creation_time.ToInternalValue());
23 } // namespace
25 ExitCodeWatcher::ExitCodeWatcher(const base::char16* registry_path) :
26 registry_path_(registry_path), exit_code_(STILL_ACTIVE) {
29 ExitCodeWatcher::~ExitCodeWatcher() {
32 bool ExitCodeWatcher::Initialize(base::Process process) {
33 if (!process.IsValid()) {
34 LOG(ERROR) << "Invalid parent handle, can't get parent process ID.";
35 return false;
38 DWORD process_pid = process.Pid();
39 if (process_pid == 0) {
40 LOG(ERROR) << "Invalid parent handle, can't get parent process ID.";
41 return false;
44 FILETIME creation_time = {};
45 FILETIME dummy = {};
46 if (!::GetProcessTimes(process.Handle(), &creation_time, &dummy, &dummy,
47 &dummy)) {
48 PLOG(ERROR) << "Invalid parent handle, can't get parent process times.";
49 return false;
52 // Success, take ownership of the process.
53 process_ = process.Pass();
54 process_creation_time_ = base::Time::FromFileTime(creation_time);
56 // Start by writing the value STILL_ACTIVE to registry, to allow detection
57 // of the case where the watcher itself is somehow terminated before it can
58 // write the process' actual exit code.
59 return WriteProcessExitCode(STILL_ACTIVE);
62 void ExitCodeWatcher::WaitForExit() {
63 if (!process_.WaitForExit(&exit_code_)) {
64 LOG(ERROR) << "Failed to wait for process.";
65 return;
68 WriteProcessExitCode(exit_code_);
71 bool ExitCodeWatcher::WriteProcessExitCode(int exit_code) {
72 base::win::RegKey key(HKEY_CURRENT_USER,
73 registry_path_.c_str(),
74 KEY_WRITE);
75 base::string16 value_name(
76 GetValueName(process_creation_time_, process_.Pid()));
78 ULONG result = key.WriteValue(value_name.c_str(), exit_code);
79 if (result != ERROR_SUCCESS) {
80 LOG(ERROR) << "Unable to write to registry, error " << result;
81 return false;
84 return true;
87 } // namespace browser_watcher