| Index: mojo/edk/embedder/named_platform_channel_pair_win.cc
|
| diff --git a/mojo/edk/embedder/named_platform_channel_pair_win.cc b/mojo/edk/embedder/named_platform_channel_pair_win.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f7f16ae1ac26987cbb0a50ca6fa3e20bcf3ba17a
|
| --- /dev/null
|
| +++ b/mojo/edk/embedder/named_platform_channel_pair_win.cc
|
| @@ -0,0 +1,131 @@
|
| +// 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 "mojo/edk/embedder/named_platform_channel_pair.h"
|
| +
|
| +#include <sddl.h>
|
| +#include <windows.h>
|
| +
|
| +#include <memory>
|
| +#include <string>
|
| +#include <utility>
|
| +
|
| +#include "base/command_line.h"
|
| +#include "base/logging.h"
|
| +#include "base/rand_util.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "base/strings/stringprintf.h"
|
| +#include "base/win/windows_version.h"
|
| +#include "mojo/edk/embedder/platform_handle.h"
|
| +
|
| +namespace mojo {
|
| +namespace edk {
|
| +
|
| +namespace {
|
| +
|
| +const char kMojoNamedPlatformChannelPipeSwitch[] =
|
| + "mojo-named-platform-channel-pipe";
|
| +
|
| +std::wstring GeneratePipeName() {
|
| + return base::StringPrintf(L"\\\\.\\pipe\\mojo.%u.%u.%I64u",
|
| + GetCurrentProcessId(), GetCurrentThreadId(),
|
| + base::RandUint64());
|
| +
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +NamedPlatformChannelPair::NamedPlatformChannelPair() {
|
| + pipe_name_ = GeneratePipeName();
|
| +
|
| + PSECURITY_DESCRIPTOR security_desc = nullptr;
|
| + ULONG security_desc_len = 0;
|
| + // Create a DACL to grant:
|
| + // GA = Generic All
|
| + // access to:
|
| + // SY = LOCAL_SYSTEM
|
| + // BA = BUILTIN_ADMINISTRATORS
|
| + // OW = OWNER_RIGHTS
|
| + PCHECK(ConvertStringSecurityDescriptorToSecurityDescriptor(
|
| + L"D:(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;OW)",
|
| + SDDL_REVISION_1, &security_desc, &security_desc_len));
|
| + std::unique_ptr<void, decltype(::LocalFree)*> p(security_desc, ::LocalFree);
|
| + SECURITY_ATTRIBUTES security_attributes = {
|
| + sizeof(SECURITY_ATTRIBUTES), security_desc, FALSE };
|
| +
|
| + const DWORD kOpenMode =
|
| + PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE;
|
| + const DWORD kPipeMode =
|
| + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_REJECT_REMOTE_CLIENTS;
|
| + PlatformHandle handle(
|
| + CreateNamedPipeW(pipe_name_.c_str(), kOpenMode, kPipeMode,
|
| + 1, // Max instances.
|
| + 4096, // Out buffer size.
|
| + 4096, // In buffer size.
|
| + 5000, // Timeout in milliseconds.
|
| + &security_attributes));
|
| + handle.needs_connection = true;
|
| + server_handle_.reset(handle);
|
| + PCHECK(server_handle_.is_valid());
|
| +}
|
| +
|
| +NamedPlatformChannelPair::~NamedPlatformChannelPair() {}
|
| +
|
| +ScopedPlatformHandle NamedPlatformChannelPair::PassServerHandle() {
|
| + return std::move(server_handle_);
|
| +}
|
| +
|
| +// static
|
| +ScopedPlatformHandle
|
| +NamedPlatformChannelPair::PassClientHandleFromParentProcess(
|
| + const base::CommandLine& command_line) {
|
| + std::wstring client_handle_string =
|
| + command_line.GetSwitchValueNative(kMojoNamedPlatformChannelPipeSwitch);
|
| +
|
| + if (client_handle_string.empty())
|
| + return ScopedPlatformHandle();
|
| +
|
| + // Note: This may block.
|
| + BOOL ok = WaitNamedPipeW(client_handle_string.c_str(),
|
| + NMPWAIT_USE_DEFAULT_WAIT);
|
| + if (!ok)
|
| + return ScopedPlatformHandle();
|
| +
|
| + // In order to support passing the pipe name on the command line, the pipe
|
| + // handle is lazily created from the pipe name when requested.
|
| + const DWORD kDesiredAccess = GENERIC_READ | GENERIC_WRITE;
|
| + // The SECURITY_ANONYMOUS flag means that the server side cannot impersonate
|
| + // the client.
|
| + const DWORD kFlags =
|
| + SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS | FILE_FLAG_OVERLAPPED;
|
| + ScopedPlatformHandle handle(
|
| + PlatformHandle(CreateFileW(client_handle_string.c_str(), kDesiredAccess,
|
| + 0, // No sharing.
|
| + nullptr, OPEN_EXISTING, kFlags,
|
| + nullptr))); // No template file.
|
| + PCHECK(handle.is_valid());
|
| + return handle;
|
| +}
|
| +
|
| +void NamedPlatformChannelPair::PrepareToPassClientHandleToChildProcess(
|
| + base::CommandLine* command_line) const {
|
| + DCHECK(command_line);
|
| +
|
| + // Log a warning if the command line already has the switch, but "clobber" it
|
| + // anyway, since it's reasonably likely that all the switches were just copied
|
| + // from the parent.
|
| + LOG_IF(WARNING,
|
| + command_line->HasSwitch(kMojoNamedPlatformChannelPipeSwitch))
|
| + << "Child command line already has switch --"
|
| + << kMojoNamedPlatformChannelPipeSwitch << "="
|
| + << command_line->GetSwitchValueNative(
|
| + kMojoNamedPlatformChannelPipeSwitch);
|
| + // (Any existing switch won't actually be removed from the command line, but
|
| + // the last one appended takes precedence.)
|
| + command_line->AppendSwitchNative(
|
| + kMojoNamedPlatformChannelPipeSwitch, pipe_name_);
|
| +}
|
| +
|
| +} // namespace edk
|
| +} // namespace mojo
|
|
|