OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 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. |
| 4 |
| 5 #include "chrome/browser/operation_output_win.h" |
| 6 |
| 7 #include <string> |
| 8 #include "base/command_line.h" |
| 9 #include "base/logging.h" |
| 10 #include "base/string_number_conversions.h" |
| 11 #include "chrome/common/chrome_switches.h" |
| 12 |
| 13 namespace { |
| 14 |
| 15 bool DoWrite(HANDLE pipe, const char* data, unsigned int length) { |
| 16 DWORD written = 0; |
| 17 BOOL success = TRUE; |
| 18 |
| 19 do { |
| 20 written = 0; |
| 21 success = ::WriteFile(pipe, data, length, &written, NULL); |
| 22 data += written; |
| 23 length -= written; |
| 24 } while (success && written > 0 && length > 0); |
| 25 |
| 26 return length == 0; |
| 27 } |
| 28 |
| 29 } // namespace |
| 30 |
| 31 // static |
| 32 scoped_ptr<OperationOutput> OperationOutput::Create( |
| 33 const CommandLine& command_line) { |
| 34 DWORD process_id = 0; |
| 35 HANDLE remote_output_handle = NULL; |
| 36 HANDLE remote_exit_code_handle = NULL; |
| 37 base::win::ScopedHandle local_output_handle; |
| 38 base::win::ScopedHandle local_exit_code_handle; |
| 39 |
| 40 std::string process_id_string = command_line.GetSwitchValueASCII( |
| 41 switches::kTaskRemoteProcessId); |
| 42 std::string remote_output_handle_string = command_line.GetSwitchValueASCII( |
| 43 switches::kTaskOutputHandle); |
| 44 std::string remote_exit_code_handle_string = command_line.GetSwitchValueASCII( |
| 45 switches::kTaskResultHandle); |
| 46 |
| 47 if (process_id_string.empty() != remote_output_handle_string.empty() || |
| 48 process_id_string.empty() != remote_exit_code_handle_string.empty()) { |
| 49 LOG(WARNING) << switches::kTaskRemoteProcessId << ", " |
| 50 << switches::kTaskOutputHandle << ", and " |
| 51 << switches::kTaskResultHandle |
| 52 << " must either be all present or all absent."; |
| 53 return scoped_ptr<OperationOutput>(); |
| 54 } |
| 55 |
| 56 if (!base::StringToUint(process_id_string, |
| 57 reinterpret_cast<unsigned*>(&process_id)) || |
| 58 !base::StringToUint(remote_output_handle_string, |
| 59 reinterpret_cast<unsigned*>(&remote_output_handle)) || |
| 60 !base::StringToUint(remote_exit_code_handle_string, |
| 61 reinterpret_cast<unsigned*>( |
| 62 &remote_exit_code_handle))) { |
| 63 LOG(WARNING) << "Invalid task output arguments."; |
| 64 return scoped_ptr<OperationOutput>(); |
| 65 } |
| 66 |
| 67 // A pseudo-handle that must not be closed. |
| 68 HANDLE current_process = ::GetCurrentProcess(); |
| 69 base::win::ScopedHandle remote_process_handle( |
| 70 ::OpenProcess(PROCESS_DUP_HANDLE, false, process_id)); |
| 71 if (!remote_process_handle) { |
| 72 PLOG(WARNING) << "OpenProcess failed. " |
| 73 << "Cannot establish operation output channel."; |
| 74 return scoped_ptr<OperationOutput>(); |
| 75 } |
| 76 if (!::DuplicateHandle(remote_process_handle, remote_output_handle, |
| 77 current_process, local_output_handle.Receive(), |
| 78 GENERIC_WRITE | SYNCHRONIZE, FALSE, 0) || |
| 79 !::DuplicateHandle(remote_process_handle, remote_exit_code_handle, |
| 80 current_process, local_exit_code_handle.Receive(), |
| 81 GENERIC_WRITE | SYNCHRONIZE, FALSE, 0)) { |
| 82 PLOG(WARNING) << "Duplicate Handle failed. " |
| 83 << "Cannot establish operation output channel."; |
| 84 return scoped_ptr<OperationOutput>(); |
| 85 } |
| 86 return scoped_ptr<OperationOutput>(new OperationOutputWin( |
| 87 local_output_handle.Pass(), local_exit_code_handle.Pass())); |
| 88 } |
| 89 |
| 90 OperationOutputWin::OperationOutputWin(base::win::ScopedHandle output_pipe, |
| 91 base::win::ScopedHandle exit_code_pipe) { |
| 92 output_pipe_ = output_pipe.Pass(); |
| 93 exit_code_pipe_ = exit_code_pipe.Pass(); |
| 94 } |
| 95 |
| 96 bool OperationOutputWin::Write(const char* data, unsigned int length) { |
| 97 bool success = DoWrite(output_pipe_, data, length); |
| 98 DLOG_IF(ERROR, !success) << "Failed to write operation output."; |
| 99 return success; |
| 100 } |
| 101 |
| 102 bool OperationOutputWin::SetExitCode(unsigned int exit_code) { |
| 103 bool success = DoWrite(exit_code_pipe_, |
| 104 reinterpret_cast<char*>(&exit_code), |
| 105 sizeof(exit_code)); |
| 106 DLOG_IF(ERROR, !success) << "Failed to write operation exit code."; |
| 107 return success; |
| 108 } |
OLD | NEW |