Index: chrome/browser/operation_output_win.cc |
diff --git a/chrome/browser/operation_output_win.cc b/chrome/browser/operation_output_win.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c0273f20b54099e2c27f60ca0f908142107225b1 |
--- /dev/null |
+++ b/chrome/browser/operation_output_win.cc |
@@ -0,0 +1,108 @@ |
+// Copyright (c) 2013 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 "chrome/browser/operation_output_win.h" |
+ |
+#include <string> |
+#include "base/command_line.h" |
+#include "base/logging.h" |
+#include "base/string_number_conversions.h" |
+#include "chrome/common/chrome_switches.h" |
+ |
+namespace { |
+ |
+bool DoWrite(HANDLE pipe, const char* data, unsigned int length) { |
+ DWORD written = 0; |
+ BOOL success = TRUE; |
+ |
+ do { |
+ written = 0; |
+ success = ::WriteFile(pipe, data, length, &written, NULL); |
+ data += written; |
+ length -= written; |
+ } while (success && written > 0 && length > 0); |
+ |
+ return length == 0; |
+} |
+ |
+} // namespace |
+ |
+// static |
+scoped_ptr<OperationOutput> OperationOutput::Create( |
+ const CommandLine& command_line) { |
+ DWORD process_id = 0; |
+ HANDLE remote_output_handle = NULL; |
+ HANDLE remote_exit_code_handle = NULL; |
+ base::win::ScopedHandle local_output_handle; |
+ base::win::ScopedHandle local_exit_code_handle; |
+ |
+ std::string process_id_string = command_line.GetSwitchValueASCII( |
+ switches::kTaskRemoteProcessId); |
+ std::string remote_output_handle_string = command_line.GetSwitchValueASCII( |
+ switches::kTaskOutputHandle); |
+ std::string remote_exit_code_handle_string = command_line.GetSwitchValueASCII( |
+ switches::kTaskResultHandle); |
+ |
+ if (process_id_string.empty() != remote_output_handle_string.empty() || |
+ process_id_string.empty() != remote_exit_code_handle_string.empty()) { |
+ LOG(WARNING) << switches::kTaskRemoteProcessId << ", " |
+ << switches::kTaskOutputHandle << ", and " |
+ << switches::kTaskResultHandle |
+ << " must either be all present or all absent."; |
+ return scoped_ptr<OperationOutput>(); |
+ } |
+ |
+ if (!base::StringToUint(process_id_string, |
+ reinterpret_cast<unsigned*>(&process_id)) || |
+ !base::StringToUint(remote_output_handle_string, |
+ reinterpret_cast<unsigned*>(&remote_output_handle)) || |
+ !base::StringToUint(remote_exit_code_handle_string, |
+ reinterpret_cast<unsigned*>( |
+ &remote_exit_code_handle))) { |
+ LOG(WARNING) << "Invalid task output arguments."; |
+ return scoped_ptr<OperationOutput>(); |
+ } |
+ |
+ // A pseudo-handle that must not be closed. |
+ HANDLE current_process = ::GetCurrentProcess(); |
+ base::win::ScopedHandle remote_process_handle( |
+ ::OpenProcess(PROCESS_DUP_HANDLE, false, process_id)); |
+ if (!remote_process_handle) { |
+ PLOG(WARNING) << "OpenProcess failed. " |
+ << "Cannot establish operation output channel."; |
+ return scoped_ptr<OperationOutput>(); |
+ } |
+ if (!::DuplicateHandle(remote_process_handle, remote_output_handle, |
+ current_process, local_output_handle.Receive(), |
+ GENERIC_WRITE | SYNCHRONIZE, FALSE, 0) || |
+ !::DuplicateHandle(remote_process_handle, remote_exit_code_handle, |
+ current_process, local_exit_code_handle.Receive(), |
+ GENERIC_WRITE | SYNCHRONIZE, FALSE, 0)) { |
+ PLOG(WARNING) << "Duplicate Handle failed. " |
+ << "Cannot establish operation output channel."; |
+ return scoped_ptr<OperationOutput>(); |
+ } |
+ return scoped_ptr<OperationOutput>(new OperationOutputWin( |
+ local_output_handle.Pass(), local_exit_code_handle.Pass())); |
+} |
+ |
+OperationOutputWin::OperationOutputWin(base::win::ScopedHandle output_pipe, |
+ base::win::ScopedHandle exit_code_pipe) { |
+ output_pipe_ = output_pipe.Pass(); |
+ exit_code_pipe_ = exit_code_pipe.Pass(); |
+} |
+ |
+bool OperationOutputWin::Write(const char* data, unsigned int length) { |
+ bool success = DoWrite(output_pipe_, data, length); |
+ DLOG_IF(ERROR, !success) << "Failed to write operation output."; |
+ return success; |
+} |
+ |
+bool OperationOutputWin::SetExitCode(unsigned int exit_code) { |
+ bool success = DoWrite(exit_code_pipe_, |
+ reinterpret_cast<char*>(&exit_code), |
+ sizeof(exit_code)); |
+ DLOG_IF(ERROR, !success) << "Failed to write operation exit code."; |
+ return success; |
+} |