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
{
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
20 return base::StringPrintf(L
"%d-%lld", pid
, creation_time
.ToInternalValue());
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.";
38 DWORD process_pid
= process
.Pid();
39 if (process_pid
== 0) {
40 LOG(ERROR
) << "Invalid parent handle, can't get parent process ID.";
44 FILETIME creation_time
= {};
46 if (!::GetProcessTimes(process
.Handle(), &creation_time
, &dummy
, &dummy
,
48 PLOG(ERROR
) << "Invalid parent handle, can't get parent process times.";
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.";
68 WriteProcessExitCode(exit_code_
);
71 bool ExitCodeWatcher::WriteProcessExitCode(int exit_code
) {
72 base::win::RegKey
key(HKEY_CURRENT_USER
,
73 registry_path_
.c_str(),
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
;
87 } // namespace browser_watcher