15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "mojo/embedder/platform_channel_pair.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <windows.h> 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <string> 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/command_line.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/rand_util.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/stringprintf.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/win/windows_version.h" 1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "mojo/embedder/platform_handle.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace mojo { 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace embedder { 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::wstring GeneratePipeName() { 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return base::StringPrintf(L"\\\\.\\pipe\\mojo.%u.%u.%I64u", 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) GetCurrentProcessId(), 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) GetCurrentThreadId(), 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::RandUint64()); 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PlatformChannelPair::PlatformChannelPair() { 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::wstring pipe_name = GeneratePipeName(); 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const DWORD kOpenMode = 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE; 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const DWORD kPipeMode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE; 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci server_handle_.reset(PlatformHandle( 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CreateNamedPipeW(pipe_name.c_str(), 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci kOpenMode, 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci kPipeMode, 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1, // Max instances. 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4096, // Out buffer size. 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4096, // In buffer size. 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5000, // Timeout in milliseconds. 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci nullptr))); // Default security descriptor. 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PCHECK(server_handle_.is_valid()); 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const DWORD kDesiredAccess = GENERIC_READ | GENERIC_WRITE; 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The SECURITY_ANONYMOUS flag means that the server side cannot impersonate 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the client. 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const DWORD kFlags = 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS | FILE_FLAG_OVERLAPPED; 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Allow the handle to be inherited by child processes. 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SECURITY_ATTRIBUTES security_attributes = {sizeof(SECURITY_ATTRIBUTES), 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci nullptr, TRUE}; 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci client_handle_.reset( 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PlatformHandle(CreateFileW(pipe_name.c_str(), 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci kDesiredAccess, 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0, // No sharing. 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &security_attributes, 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OPEN_EXISTING, 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci kFlags, 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci nullptr))); // No template file. 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PCHECK(client_handle_.is_valid()); 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Since a client has connected, ConnectNamedPipe() should return zero and 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // GetLastError() should return ERROR_PIPE_CONNECTED. 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(!ConnectNamedPipe(server_handle_.get().handle, nullptr)); 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PCHECK(GetLastError() == ERROR_PIPE_CONNECTED); 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ScopedPlatformHandle PlatformChannelPair::PassClientHandleFromParentProcess( 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::CommandLine& command_line) { 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string client_handle_string = 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int client_handle_value = 0; 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (client_handle_string.empty() || 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !base::StringToInt(client_handle_string, &client_handle_value)) { 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch; 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ScopedPlatformHandle(); 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ScopedPlatformHandle( 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PlatformHandle(LongToHandle(client_handle_value))); 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PlatformChannelPair::PrepareToPassClientHandleToChildProcess( 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::CommandLine* command_line, 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::HandlesToInheritVector* handle_passing_info) const { 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(command_line); 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(handle_passing_info); 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(client_handle_.is_valid()); 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK_GE(base::win::GetVersion(), base::win::VERSION_VISTA); 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) handle_passing_info->push_back(client_handle_.get().handle); 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Log a warning if the command line already has the switch, but "clobber" it 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // anyway, since it's reasonably likely that all the switches were just copied 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // from the parent. 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG_IF(WARNING, command_line->HasSwitch(kMojoPlatformChannelHandleSwitch)) 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << "Child command line already has switch --" 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << kMojoPlatformChannelHandleSwitch << "=" 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << command_line->GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // (Any existing switch won't actually be removed from the command line, but 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the last one appended takes precedence.) 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) command_line->AppendSwitchASCII( 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kMojoPlatformChannelHandleSwitch, 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::IntToString(HandleToLong(client_handle_.get().handle))); 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace embedder 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace mojo 118