| 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;
|
| +}
|
|
|