Fix UserSessionManager::Shutdown ordering.
[chromium-blink-merge.git] / ipc / attachment_broker_privileged_win.cc
blobc8cc1d0aaf903b5926f20e954e0a823883ca4dfa
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 Sender* sender = GetSenderWithProcessId(dest);
79 if (!sender) {
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 sender->Send(new AttachmentBrokerMsg_WinHandleHasBeenDuplicated(wire_format));
91 AttachmentBrokerPrivilegedWin::HandleWireFormat
92 AttachmentBrokerPrivilegedWin::DuplicateWinHandle(
93 const HandleWireFormat& wire_format,
94 base::ProcessId source_pid) {
95 HandleWireFormat new_wire_format;
96 new_wire_format.destination_process = wire_format.destination_process;
97 new_wire_format.attachment_id = wire_format.attachment_id;
98 new_wire_format.permissions = wire_format.permissions;
99 new_wire_format.handle = 0;
101 HANDLE original_handle = LongToHandle(wire_format.handle);
103 base::Process source_process =
104 base::Process::OpenWithExtraPrivileges(source_pid);
105 base::Process dest_process =
106 base::Process::OpenWithExtraPrivileges(wire_format.destination_process);
107 if (source_process.Handle() && dest_process.Handle()) {
108 DWORD desired_access = 0;
109 DWORD options = 0;
110 switch (wire_format.permissions) {
111 case HandleWin::INVALID:
112 LOG(ERROR) << "Received invalid permissions for duplication.";
113 return new_wire_format;
114 case HandleWin::DUPLICATE:
115 options = DUPLICATE_SAME_ACCESS;
116 break;
117 case HandleWin::FILE_READ_WRITE:
118 desired_access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
119 break;
122 HANDLE new_handle;
123 DWORD result = ::DuplicateHandle(source_process.Handle(), original_handle,
124 dest_process.Handle(), &new_handle,
125 desired_access, FALSE, options);
127 new_wire_format.handle = (result != 0) ? HandleToLong(new_handle) : 0;
130 return new_wire_format;
133 } // namespace IPC