Roll src/third_party/skia fdb788c:028205b
[chromium-blink-merge.git] / ipc / attachment_broker_privileged_win.cc
blob5344e20b82650dddd5bf2027467d9c32cbd5a19d
1 // Copyright 2015 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.
5 #include "ipc/attachment_broker_privileged_win.h"
7 #include <windows.h>
9 #include "base/process/process.h"
10 #include "ipc/attachment_broker_messages.h"
11 #include "ipc/brokerable_attachment.h"
12 #include "ipc/handle_attachment_win.h"
13 #include "ipc/ipc_channel.h"
15 namespace IPC {
17 AttachmentBrokerPrivilegedWin::AttachmentBrokerPrivilegedWin() {}
19 AttachmentBrokerPrivilegedWin::~AttachmentBrokerPrivilegedWin() {}
21 bool AttachmentBrokerPrivilegedWin::SendAttachmentToProcess(
22 const BrokerableAttachment* attachment,
23 base::ProcessId destination_process) {
24 switch (attachment->GetBrokerableType()) {
25 case BrokerableAttachment::WIN_HANDLE:
26 const internal::HandleAttachmentWin* handle_attachment =
27 static_cast<const internal::HandleAttachmentWin*>(attachment);
28 HandleWireFormat wire_format =
29 handle_attachment->GetWireFormat(destination_process);
30 HandleWireFormat new_wire_format =
31 DuplicateWinHandle(wire_format, base::Process::Current().Pid());
32 if (new_wire_format.handle == 0)
33 return false;
34 RouteDuplicatedHandle(new_wire_format);
35 return true;
37 return false;
40 bool AttachmentBrokerPrivilegedWin::OnMessageReceived(const Message& msg) {
41 bool handled = true;
42 switch (msg.type()) {
43 IPC_MESSAGE_HANDLER_GENERIC(AttachmentBrokerMsg_DuplicateWinHandle,
44 OnDuplicateWinHandle(msg))
45 IPC_MESSAGE_UNHANDLED(handled = false)
47 return handled;
50 void AttachmentBrokerPrivilegedWin::OnDuplicateWinHandle(
51 const IPC::Message& message) {
52 AttachmentBrokerMsg_DuplicateWinHandle::Param param;
53 if (!AttachmentBrokerMsg_DuplicateWinHandle::Read(&message, &param))
54 return;
55 IPC::internal::HandleAttachmentWin::WireFormat wire_format =
56 base::get<0>(param);
58 if (wire_format.destination_process == base::kNullProcessId)
59 return;
61 HandleWireFormat new_wire_format =
62 DuplicateWinHandle(wire_format, message.get_sender_pid());
63 RouteDuplicatedHandle(new_wire_format);
66 void AttachmentBrokerPrivilegedWin::RouteDuplicatedHandle(
67 const HandleWireFormat& wire_format) {
68 // This process is the destination.
69 if (wire_format.destination_process == base::Process::Current().Pid()) {
70 scoped_refptr<BrokerableAttachment> attachment(
71 new internal::HandleAttachmentWin(wire_format));
72 HandleReceivedAttachment(attachment);
73 return;
76 // Another process is the destination.
77 base::ProcessId dest = wire_format.destination_process;
78 Channel* channel = GetChannelWithProcessId(dest);
79 if (!channel) {
80 // Assuming that this message was not sent from a malicious process, the
81 // channel endpoint that would have received this message will block
82 // forever.
83 LOG(ERROR) << "Failed to deliver brokerable attachment to process with id: "
84 << dest;
85 return;
88 channel->Send(
89 new AttachmentBrokerMsg_WinHandleHasBeenDuplicated(wire_format));
92 AttachmentBrokerPrivilegedWin::HandleWireFormat
93 AttachmentBrokerPrivilegedWin::DuplicateWinHandle(
94 const HandleWireFormat& wire_format,
95 base::ProcessId source_pid) {
96 HandleWireFormat new_wire_format;
97 new_wire_format.destination_process = wire_format.destination_process;
98 new_wire_format.attachment_id = wire_format.attachment_id;
100 HANDLE original_handle = LongToHandle(wire_format.handle);
102 base::Process source_process =
103 base::Process::OpenWithExtraPrivileges(source_pid);
104 base::Process dest_process =
105 base::Process::OpenWithExtraPrivileges(wire_format.destination_process);
106 if (source_process.Handle() && dest_process.Handle()) {
107 HANDLE new_handle;
108 DWORD result = ::DuplicateHandle(source_process.Handle(), original_handle,
109 dest_process.Handle(), &new_handle, 0,
110 FALSE, DUPLICATE_SAME_ACCESS);
112 new_wire_format.handle = (result != 0) ? HandleToLong(new_handle) : 0;
113 } else {
114 new_wire_format.handle = 0;
116 return new_wire_format;
119 } // namespace IPC