Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(473)

Unified Diff: remoting/host/win/launch_native_messaging_host_process.cc

Issue 2152953002: Refactoring Native Messaging Host process launching code into its own file. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: bugfix and cleanup Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: remoting/host/win/launch_native_messaging_host_process.cc
diff --git a/remoting/host/win/launch_native_messaging_host_process.cc b/remoting/host/win/launch_native_messaging_host_process.cc
new file mode 100644
index 0000000000000000000000000000000000000000..86de11240098f47460c2de240ce2ec1e824023d3
--- /dev/null
+++ b/remoting/host/win/launch_native_messaging_host_process.cc
@@ -0,0 +1,188 @@
+// Copyright 2016 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 "remoting/host/win/launch_native_messaging_host_process.h"
+
+#include <windows.h>
+#include <shellapi.h>
+
+#include <cstdint>
+#include <string>
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/win/win_util.h"
+#include "ipc/ipc_channel.h"
+#include "remoting/host/switches.h"
+#include "remoting/host/win/security_descriptor.h"
+
+namespace {
+
+// Windows will use default buffer size when 0 is passed to CreateNamedPipeW().
+const uint32_t kBufferSize = 0;
+const int kTimeOutMilliseconds = 2000;
+const char kChromePipeNamePrefix[] = "\\\\.\\pipe\\chrome_remote_desktop.";
+
+const uint32_t kProcessLaunched = 0;
+const uint32_t kSecurityDescriptorCreationFailed = 1;
Sergey Ulanov 2016/07/28 23:57:15 This special error code is not mentioned in the he
joedow 2016/07/29 03:32:56 Done.
+
+uint32_t CreateNamedPipe(const std::string& pipe_name,
+ const remoting::ScopedSd& security_descriptor,
+ uint32_t open_mode,
+ base::win::ScopedHandle* file_handle) {
+ DCHECK(file_handle);
+
+ SECURITY_ATTRIBUTES security_attributes = {0};
+ security_attributes.nLength = sizeof(security_attributes);
+ security_attributes.lpSecurityDescriptor = security_descriptor.get();
+ security_attributes.bInheritHandle = FALSE;
+
+ base::win::ScopedHandle temp_handle(::CreateNamedPipe(
+ base::ASCIIToUTF16(pipe_name).c_str(),
+ open_mode,
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_REJECT_REMOTE_CLIENTS,
+ 1,
+ kBufferSize,
+ kBufferSize,
+ kTimeOutMilliseconds,
+ &security_attributes));
+
+ if (!temp_handle.IsValid()) {
+ uint32_t error = GetLastError();
+ PLOG(ERROR) << "Failed to create named pipe '" << pipe_name << "'";
+ return error;
+ }
+
+ file_handle->Set(temp_handle.Take());
+ return 0;
+}
+
+} // namespace
+
+namespace remoting {
+
+uint32_t LaunchNativeMessagingHostProcess(
+ const base::FilePath& binary_path,
+ intptr_t parent_window_handle,
+ bool elevate_process,
+ base::win::ScopedHandle* read_handle,
+ base::win::ScopedHandle* write_handle) {
+ DCHECK(read_handle);
+ DCHECK(write_handle);
+
+ // presubmit: allow wstring
+ std::wstring user_sid;
+ if (!base::win::GetUserSidString(&user_sid)) {
+ LOG(ERROR) << "Failed to query the current user SID.";
+ return kSecurityDescriptorCreationFailed;
+ }
+
+ // Create a security descriptor that gives full access to the caller and
+ // BUILTIN_ADMINISTRATORS and denies access by anyone else.
+ // Local admins need access because the privileged host process will run
+ // as a local admin which may not be the same user as the current user.
+ std::string user_sid_ascii = base::UTF16ToASCII(user_sid);
+ std::string security_descriptor = base::StringPrintf(
+ "O:%sG:%sD:(A;;GA;;;%s)(A;;GA;;;BA)", user_sid_ascii.c_str(),
+ user_sid_ascii.c_str(), user_sid_ascii.c_str());
+
+ ScopedSd sd = ConvertSddlToSd(security_descriptor);
+ if (!sd) {
+ PLOG(ERROR) << "Failed to create a security descriptor.";
+ return kSecurityDescriptorCreationFailed;
+ }
+
+ uint32_t result;
+ std::string input_pipe_name(kChromePipeNamePrefix);
+ input_pipe_name.append(IPC::Channel::GenerateUniqueRandomChannelID());
+ base::win::ScopedHandle temp_write_handle;
+ result = CreateNamedPipe(input_pipe_name, sd, PIPE_ACCESS_OUTBOUND,
+ &temp_write_handle);
+ if (!temp_write_handle.IsValid()) {
+ return result;
+ }
+
+ std::string output_pipe_name(kChromePipeNamePrefix);
+ output_pipe_name.append(IPC::Channel::GenerateUniqueRandomChannelID());
+ base::win::ScopedHandle temp_read_handle;
+ result = CreateNamedPipe(output_pipe_name, sd, PIPE_ACCESS_INBOUND,
+ &temp_read_handle);
+ if (!temp_read_handle.IsValid()) {
+ return result;
+ }
+
+ const base::CommandLine* current_command_line =
+ base::CommandLine::ForCurrentProcess();
+ const base::CommandLine::SwitchMap& switches =
+ current_command_line->GetSwitches();
+ base::CommandLine::StringVector args = current_command_line->GetArgs();
+
+ // Create the child process command line by copying switches from the current
+ // command line.
+ base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
+
+ if (elevate_process) {
+ DCHECK(!current_command_line->HasSwitch(kElevateSwitchName));
+ command_line.AppendSwitch(kElevateSwitchName);
+ }
+ command_line.AppendSwitchASCII(kInputSwitchName, input_pipe_name);
+ command_line.AppendSwitchASCII(kOutputSwitchName, output_pipe_name);
+
+ for (base::CommandLine::SwitchMap::const_iterator i = switches.begin();
+ i != switches.end(); ++i) {
+ command_line.AppendSwitchNative(i->first, i->second);
+ }
+ for (base::CommandLine::StringVector::const_iterator i = args.begin();
Sergey Ulanov 2016/07/28 23:57:15 for (const auto& arg : args) ...
joedow 2016/07/29 03:32:56 Good call.
+ i != args.end(); ++i) {
+ command_line.AppendArgNative(*i);
+ }
+
+ // Get the parameters for the binary to launch.
+ base::CommandLine::StringType params = command_line.GetCommandLineString();
+
+ // Launch the child process, requesting elevation if needed.
+ SHELLEXECUTEINFO info;
+ memset(&info, 0, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.hwnd = reinterpret_cast<HWND>(parent_window_handle);
+ info.lpFile = binary_path.value().c_str();
+ info.lpParameters = params.c_str();
+ info.nShow = SW_HIDE;
+
+ if (elevate_process) {
+ info.lpVerb = L"runas";
+ }
+
+ if (!ShellExecuteEx(&info)) {
+ uint32_t error = GetLastError();
+ PLOG(ERROR) << "Unable to launch '" << binary_path.value() << "'";
+ return error;
+ }
+
+ if (!ConnectNamedPipe(temp_write_handle.Get(), nullptr)) {
+ uint32_t error = GetLastError();
+ if (error != ERROR_PIPE_CONNECTED) {
+ PLOG(ERROR) << "Unable to connect '" << output_pipe_name << "'";
+ return error;
+ }
+ }
+
+ if (!ConnectNamedPipe(temp_read_handle.Get(), nullptr)) {
+ uint32_t error = GetLastError();
+ if (error != ERROR_PIPE_CONNECTED) {
+ PLOG(ERROR) << "Unable to connect '" << input_pipe_name << "'";
+ return error;
+ }
+ }
+
+ read_handle->Set(temp_read_handle.Take());
+ write_handle->Set(temp_write_handle.Take());
+ return kProcessLaunched;
+}
+
+} // namespace remoting

Powered by Google App Engine
This is Rietveld 408576698