1use super::{Channel, SendableWinHandle};
2
3use std::{io, mem, ptr, process};
4use std::time::Duration;
5use std::os::windows::prelude::*;
6use std::ffi::{OsString, OsStr};
7
8use uuid::Uuid;
9use serde::{Serializer, Deserializer};
10use tokio::io::{AsyncRead, AsyncWrite};
11use tokio::reactor::{PollEvented, Handle as TokioHandle};
12use futures::{Poll};
13use platform::mio_named_pipes::NamedPipe as MioNamedPipe;
14use winapi::shared::minwindef::{DWORD, ULONG, BOOL, TRUE, FALSE};
15use winapi::shared::ntdef::{HANDLE};
16use winapi::shared::winerror::{ERROR_IO_PENDING};
17use winapi::um::minwinbase::{OVERLAPPED, SECURITY_ATTRIBUTES};
18use winapi::um::winbase::{PIPE_TYPE_MESSAGE, PIPE_READMODE_MESSAGE, PIPE_REJECT_REMOTE_CLIENTS, PIPE_ACCESS_DUPLEX, FILE_FLAG_OVERLAPPED, INFINITE};
19use winapi::um::winbase::{GetNamedPipeClientProcessId, GetNamedPipeServerProcessId};
20use winapi::um::winnt::{PROCESS_DUP_HANDLE, GENERIC_READ, GENERIC_WRITE, PSECURITY_DESCRIPTOR, PACL};
21use winapi::um::errhandlingapi::{GetLastError};
22use winapi::um::processthreadsapi::{GetCurrentProcess, GetCurrentProcessId, GetProcessId, OpenProcess};
23use winapi::um::namedpipeapi::{ConnectNamedPipe, WaitNamedPipeW, CreateNamedPipeW};
24use winapi::um::fileapi::{OPEN_EXISTING, CreateFileW};
25use winapi::um::ioapiset::{GetOverlappedResultEx};
26use winhandle::*;
27use widestring::WideCString;
28
29#[derive(Debug)]
30pub(crate) struct MessageChannel {
31 pipe: PollEvented<MioNamedPipe>,
32 server: bool,
33 target: HandleTarget,
34}
35
36#[derive(Debug)]
37pub(crate) enum HandleTarget<H = ProcessHandle> {
38 #[allow(dead_code)]
39 None,
40 CurrentProcess,
41 RemoteProcess(H),
42}
43
44impl MessageChannel {
45 pub fn pair(tokio_loop: &TokioHandle) -> io::Result<(MessageChannel, MessageChannel)> {
46 let (server_pipe, client_pipe) = raw_pipe_pair(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_REJECT_REMOTE_CLIENTS)?;
47
48 Ok((
49 MessageChannel {
50 pipe: PollEvented::new_with_handle(unsafe { MioNamedPipe::from_raw_handle(server_pipe.into_raw()) }, tokio_loop)?,
51 server: true,
52 target: HandleTarget::CurrentProcess,
53 },
54 MessageChannel {
55 pipe: PollEvented::new_with_handle(unsafe { MioNamedPipe::from_raw_handle(client_pipe.into_raw()) }, tokio_loop)?,
56 server: false,
57 target: HandleTarget::CurrentProcess,
58 },
59 ))
60 }
61
62 pub fn establish_with_child<F>(command: &mut process::Command, tokio_loop: &TokioHandle, transmit_and_launch: F) -> io::Result<(Self, process::Child)> where
63 F: FnOnce(&mut process::Command, ChildMessageChannel) -> io::Result<process::Child>
64 {
65 Self::establish_with_child_custom(tokio_loop, |to_be_sent| {
66 let child = transmit_and_launch(command, to_be_sent)?;
67 Ok((::ProcessHandle::from_windows_handle(&child)?.0, child))
68 })
69 }
70
71 pub fn establish_with_child_custom<F, T>(tokio_loop: &TokioHandle, transmit_and_launch: F) -> io::Result<(Self, T)> where
72 F: FnOnce(ChildMessageChannel) -> io::Result<(ProcessHandle, T)>,
73 {
74 let (server_pipe, client_pipe) = raw_pipe_pair(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_REJECT_REMOTE_CLIENTS)?;
75 let inheritable_process_handle = WinHandle::from_raw(unsafe { GetCurrentProcess() }).unwrap().clone_ex(true, ClonedHandleAccess::Explicit(PROCESS_DUP_HANDLE))?;
76 let to_be_sent = ChildMessageChannel {
77 channel_handle: client_pipe.modify(true, ClonedHandleAccess::Same)?,
78 remote_process_handle: Some(inheritable_process_handle),
79 remote_process_id: unsafe { GetCurrentProcessId() },
80 };
81
82 let (child_handle, t) = transmit_and_launch(to_be_sent)?;
83 let channel = MessageChannel {
84 pipe: PollEvented::new_with_handle(unsafe { MioNamedPipe::from_raw_handle(server_pipe.into_raw()) }, tokio_loop)?,
85 server: true,
86 target: HandleTarget::RemoteProcess(child_handle),
87 };
88
89 Ok((channel, t))
90 }
91}
92
93impl Channel for MessageChannel {
94 fn handle_target(&self) -> HandleTarget<&ProcessHandle> {
95 match self.target {
96 HandleTarget::None => HandleTarget::None,
97 HandleTarget::CurrentProcess => HandleTarget::CurrentProcess,
98 HandleTarget::RemoteProcess(ref p) => HandleTarget::RemoteProcess(p),
99 }
100 }
101}
102
103#[derive(Debug, Serialize, Deserialize)]
104pub(crate) struct ChildMessageChannel {
105 #[serde(with = "inheritable_channel_serialize")]
106 channel_handle: WinHandle,
107 #[serde(with = "inheritable_channel_serialize_opt")]
108 remote_process_handle: Option<WinHandle>,
109 remote_process_id: DWORD,
110}
111
112mod inheritable_channel_serialize {
113 use super::*;
114
115 use serde::{Serialize, Deserialize};
116
117 pub fn serialize<S>(handle: &WinHandle, serializer: S) -> Result<S::Ok, S::Error> where
118 S: Serializer,
119 {
120 usize::serialize(&(handle.get() as usize), serializer)
121 }
122
123 pub fn deserialize<'de, D>(deserializer: D) -> Result<WinHandle, D::Error> where
124 D: Deserializer<'de>,
125 {
126 use serde::de::Error;
127
128 let handle = usize::deserialize(deserializer)?;
129 WinHandle::from_raw(handle as HANDLE)
130 .ok_or_else(|| D::Error::custom(io::Error::new(io::ErrorKind::InvalidData, "received invalid inherited handle")))
131 }
132}
133
134mod inheritable_channel_serialize_opt {
135 use super::*;
136
137 use serde::{Serialize, Deserialize};
138
139 pub fn serialize<S>(handle: &Option<WinHandle>, serializer: S) -> Result<S::Ok, S::Error> where
140 S: Serializer,
141 {
142 Option::<usize>::serialize(&handle.as_ref().map(|handle|(handle.get() as usize)), serializer)
143 }
144
145 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<WinHandle>, D::Error> where
146 D: Deserializer<'de>,
147 {
148 use serde::de::Error;
149
150 if let Some(handle) = Option::<usize>::deserialize(deserializer)? {
151 Ok(Some(WinHandle::from_raw(handle as HANDLE)
152 .ok_or_else(|| D::Error::custom(io::Error::new(io::ErrorKind::InvalidData, "received invalid inherited handle")))?
153 ))
154 } else {
155 Ok(None)
156 }
157 }
158}
159
160impl ChildMessageChannel {
161 pub fn into_channel(self, tokio: &TokioHandle) -> io::Result<MessageChannel> {
162 Ok(
163 MessageChannel {
164 pipe: PollEvented::new_with_handle(unsafe { MioNamedPipe::from_raw_handle(self.channel_handle.into_raw()) }, tokio)?,
165 server: false,
166 target: if let Some(handle) = self.remote_process_handle {
167 HandleTarget::RemoteProcess(ProcessHandle {
168 handle: SendableWinHandle(handle),
169 id: self.remote_process_id,
170 })
171 } else {
172 HandleTarget::None
173 },
174 }
175 )
176 }
177}
178
179pub trait ChildRawMessageChannelExt {
180 fn handles(&self) -> ChildMessageChannelHandles;
181}
182
183impl ChildRawMessageChannelExt for ::ChildRawMessageChannel {
184 fn handles(&self) -> ChildMessageChannelHandles {
185 ChildMessageChannelHandles { channel_handle: &self.0, index: 0 }
186 }
187}
188
189pub trait ChildMessageChannelExt {
190 fn handles(&self) -> ChildMessageChannelHandles;
191}
192
193impl ChildMessageChannelExt for ::ChildMessageChannel {
194 fn handles(&self) -> ChildMessageChannelHandles {
195 ChildMessageChannelHandles { channel_handle: &self.inner, index: 0 }
196 }
197}
198
199pub struct ChildMessageChannelHandles<'a> {
200 channel_handle: &'a ChildMessageChannel,
201 index: usize,
202}
203
204impl<'a> Iterator for ChildMessageChannelHandles<'a> {
205 type Item = HANDLE;
206
207 fn next(&mut self) -> Option<HANDLE> {
208 let handle = match self.index {
209 0 => Some(self.channel_handle.channel_handle.get()),
210 1 => self.channel_handle.remote_process_handle.as_ref().map(|x| x.get()),
211 _ => return None,
212 };
213 self.index += 1;
214 handle
215 }
216}
217
218#[derive(Serialize, Deserialize, Debug)]
219pub(crate) struct PreMessageChannel {
220 pipe: SendableWinHandle,
221 server: bool,
222}
223
224impl PreMessageChannel {
225 pub fn pair() -> io::Result<(Self, Self)> {
226 let (server_pipe, client_pipe) = raw_pipe_pair(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_REJECT_REMOTE_CLIENTS)?;
227
228 Ok((
229 PreMessageChannel { pipe: SendableWinHandle(server_pipe), server: true },
230 PreMessageChannel { pipe: SendableWinHandle(client_pipe), server: false },
231 ))
232 }
233
234 pub fn into_channel(self, process_handle: ProcessHandle, tokio_loop: &TokioHandle) -> io::Result<MessageChannel> {
235 Ok(MessageChannel {
236 pipe: PollEvented::new_with_handle(unsafe { MioNamedPipe::from_raw_handle(self.pipe.0.into_raw()) }, tokio_loop)?,
237 server: self.server,
238 target: HandleTarget::RemoteProcess(process_handle),
239 })
240 }
241
242 pub fn into_sealed_channel(self, tokio_loop: &TokioHandle) -> io::Result<MessageChannel> {
243 Ok(MessageChannel {
244 pipe: PollEvented::new_with_handle(unsafe { MioNamedPipe::from_raw_handle(self.pipe.0.into_raw()) }, tokio_loop)?,
245 server: self.server,
246 target: HandleTarget::None,
247 })
248 }
249}
250
251#[derive(Serialize, Deserialize, Debug)]
252pub(crate) struct ProcessHandle {
253 pub(crate) handle: SendableWinHandle,
254 pub(crate) id: DWORD,
255}
256
257impl ProcessHandle {
258 pub fn current() -> io::Result<Self> {
259 let handle = WinHandle::from_raw(unsafe { GetCurrentProcess() }).unwrap()
260 .clone_ex(false, ClonedHandleAccess::Explicit(PROCESS_DUP_HANDLE))?;
261 let id = unsafe { GetCurrentProcessId() };
262 Ok(ProcessHandle {
263 handle: SendableWinHandle(handle),
264 id,
265 })
266 }
267
268 pub fn clone(&self) -> io::Result<Self> {
269 Ok(ProcessHandle {
270 handle: SendableWinHandle(self.handle.0.clone()?),
271 id: self.id,
272 })
273 }
274
275 pub fn from_child(child: &process::Child) -> io::Result<Self> {
276 Ok(ProcessHandle {
277 handle: SendableWinHandle(WinHandle::clone_from_ex(child, false, ClonedHandleAccess::Explicit(PROCESS_DUP_HANDLE))?),
278 id: child.id(),
279 })
280 }
281}
282
283pub trait ProcessHandleExt: Sized {
284 fn from_windows_handle<H>(handle: &H) -> io::Result<Self> where H: AsRawHandle;
285 unsafe fn from_windows_handle_raw(handle: HANDLE) -> io::Result<Self>;
286}
287
288impl ProcessHandleExt for ::ProcessHandle {
289 fn from_windows_handle<H>(handle: &H) -> io::Result<Self> where H: AsRawHandle {
294 unsafe { Self::from_windows_handle_raw(handle.as_raw_handle()) }
295 }
296
297 unsafe fn from_windows_handle_raw(handle: HANDLE) -> io::Result<Self> {
302 let id = GetProcessId(handle);
303 if id == 0 {
304 return Err(io::Error::last_os_error());
305 }
306 Ok(::ProcessHandle(ProcessHandle {
307 handle: SendableWinHandle(WinHandle::clone_from_raw_ex(handle, false, ClonedHandleAccess::Explicit(PROCESS_DUP_HANDLE))?),
308 id,
309 }))
310 }
311}
312
313pub(crate) struct NamedMessageChannel {
314 name: OsString,
315 server_pipe: WinHandle,
316 overlapped: Box<OVERLAPPED>,
317 tokio_loop: TokioHandle,
318}
319
320impl NamedMessageChannel {
321 pub fn new(tokio: &TokioHandle) -> io::Result<Self> {
322 let pipe_name = format!(r#"\\.\pipe\{}"#, Uuid::new_v4());
323
324 unsafe {
325 let server_pipe = winapi_handle_call! { CreateNamedPipeW(
326 WideCString::from_str(&pipe_name).unwrap().as_ptr(),
327 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
328 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_REJECT_REMOTE_CLIENTS,
329 1,
330 0, 0,
331 0,
332 ptr::null_mut()
333 )}?;
334
335 let mut overlapped: Box<OVERLAPPED> = Box::new(mem::zeroed());
337
338 if ConnectNamedPipe(
339 server_pipe.get(),
340 &mut *overlapped
341 ) != 0 {
342 return Err(io::Error::last_os_error());
343 }
344
345 if GetLastError() != ERROR_IO_PENDING {
346 return Err(io::Error::last_os_error());
347 }
348
349 Ok(NamedMessageChannel {
350 name: OsString::from(pipe_name),
351 server_pipe,
352 overlapped,
353 tokio_loop: tokio.clone(),
354 })
355 }
356 }
357
358 pub fn name(&self) -> &OsStr {
359 &self.name
360 }
361
362 pub fn accept(mut self, timeout: Option<Duration>) -> io::Result<MessageChannel> {
363 unsafe {
364 let timeout = if let Some(duration) = timeout {
365 (duration.as_secs() * 1000 + (duration.subsec_nanos() as u64 / (1000 * 1000))) as ULONG
366 } else {
367 INFINITE
368 };
369 let mut bytes: DWORD = 0;
370 winapi_bool_call!(GetOverlappedResultEx(
371 self.server_pipe.get(),
372 &mut *self.overlapped,
373 &mut bytes,
374 timeout,
375 TRUE
376 ))?;
377
378 let mut process_id: ULONG = 0;
379 winapi_bool_call!(GetNamedPipeClientProcessId(
380 self.server_pipe.get(),
381 &mut process_id,
382 ))?;
383
384 let remote_process_handle = winapi_handle_call!(OpenProcess(
385 PROCESS_DUP_HANDLE,
386 FALSE,
387 process_id,
388 ))?;
389
390 let remote_process_handle = ProcessHandle {
391 handle: SendableWinHandle(remote_process_handle),
392 id: process_id as DWORD,
393 };
394
395 Ok(MessageChannel {
396 pipe: PollEvented::new_with_handle(MioNamedPipe::from_raw_handle(self.server_pipe.into_raw()), &self.tokio_loop)?,
397 server: true,
398 target: HandleTarget::RemoteProcess(remote_process_handle),
399 })
400 }
401 }
402
403 pub fn connect<N>(name: N, timeout: Option<Duration>, tokio_loop: &TokioHandle) -> io::Result<MessageChannel> where
404 N: AsRef<OsStr>,
405 {
406 unsafe {
407 let name = WideCString::from_str(name.as_ref())
408 .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid name for named pipe"))?;
409
410 let timeout = if let Some(duration) = timeout {
411 (duration.as_secs() * 1000 + (duration.subsec_nanos() as u64 / (1000 * 1000))) as DWORD
412 } else {
413 NMPWAIT_WAIT_FOREVER
414 };
415
416 winapi_bool_call!(WaitNamedPipeW(
417 name.as_ptr(),
418 timeout,
419 ))?;
420
421 let client_pipe = winapi_handle_call! { CreateFileW(
422 name.as_ptr(),
423 GENERIC_READ | GENERIC_WRITE,
424 0,
425 ptr::null_mut(),
426 OPEN_EXISTING,
427 SECURITY_IDENTIFICATION | FILE_FLAG_OVERLAPPED,
428 ptr::null_mut()
429 )}?;
430
431 let mut process_id: ULONG = 0;
432 winapi_bool_call!(GetNamedPipeServerProcessId(
433 client_pipe.get(),
434 &mut process_id,
435 ))?;
436
437 let remote_process_handle = winapi_handle_call!(OpenProcess(
438 PROCESS_DUP_HANDLE,
439 FALSE,
440 process_id,
441 ))?;
442
443 let remote_process_handle = ProcessHandle {
444 handle: SendableWinHandle(remote_process_handle),
445 id: process_id,
446 };
447
448 Ok(MessageChannel {
449 pipe: PollEvented::new_with_handle(MioNamedPipe::from_raw_handle(client_pipe.into_raw()), tokio_loop)?,
450 server: false,
451 target: HandleTarget::RemoteProcess(remote_process_handle),
452 })
453 }
454 }
455}
456
457impl io::Write for MessageChannel {
458 fn write(&mut self, buffer: &[u8]) -> io::Result<usize> {
459 self.pipe.write(buffer)
460 }
461
462 fn flush(&mut self) -> io::Result<()> {
463 self.pipe.flush()
464 }
465}
466
467impl AsyncWrite for MessageChannel {
468 fn shutdown(&mut self) -> Poll<(), io::Error> {
469 self.pipe.shutdown()
470 }
471}
472
473impl io::Read for MessageChannel {
474 fn read(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
475 self.pipe.read(buffer)
476 }
477}
478
479impl AsyncRead for MessageChannel {
480
481}
482
483fn raw_pipe_pair(pipe_type: DWORD) -> io::Result<(WinHandle, WinHandle)> {
484 unsafe {
485 let pipe_name = OsString::from(format!(r#"\\.\pipe\{}"#, Uuid::new_v4()));
486
487 let mut security_descriptor: [u8; 256] = mem::zeroed(); winapi_bool_call!(log: InitializeSecurityDescriptor(security_descriptor.as_mut_ptr() as _, 1))?;
490 winapi_bool_call!(log: SetSecurityDescriptorDacl(security_descriptor.as_mut_ptr() as _, TRUE, ptr::null_mut(), FALSE))?;
491
492 let mut security_attributes = SECURITY_ATTRIBUTES {
493 nLength: mem::size_of::<SECURITY_ATTRIBUTES>() as DWORD,
494 lpSecurityDescriptor: security_descriptor.as_mut_ptr() as _,
495 bInheritHandle: FALSE,
496 };
497
498 debug!("creating named pipe pair {:?}", pipe_name);
499 let server_pipe = winapi_handle_call! { CreateNamedPipeW(
500 WideCString::from_str(&pipe_name).unwrap().as_ptr(),
501 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
502 pipe_type,
503 1,
504 0, 0,
505 0,
506 &mut security_attributes,
507 )}?;
508
509 let mut overlapped: OVERLAPPED = mem::zeroed();
511
512 if ConnectNamedPipe(
514 server_pipe.get(),
515 &mut overlapped
516 ) != 0 {
517 return Err(io::Error::last_os_error());
518 }
519
520 if GetLastError() != ERROR_IO_PENDING {
521 return Err(io::Error::last_os_error());
522 }
523
524
525 let client_pipe = winapi_handle_call!(log: CreateFileW(
526 WideCString::from_str(&pipe_name).unwrap().as_ptr(),
527 GENERIC_READ | GENERIC_WRITE,
528 0,
529 &mut security_attributes,
530 OPEN_EXISTING,
531 SECURITY_IDENTIFICATION | FILE_FLAG_OVERLAPPED,
532 ptr::null_mut()
533 ))?;
534
535 let mut bytes: DWORD = 0;
536 winapi_bool_call!(log: GetOverlappedResultEx(
537 server_pipe.get(),
538 &mut overlapped,
539 &mut bytes,
540 1000,
541 TRUE
542 ))?;
543
544 Ok((server_pipe, client_pipe))
545 }
546}
547
548const SECURITY_IDENTIFICATION: DWORD = 65536;
549const NMPWAIT_WAIT_FOREVER: DWORD = 0xFFFFFFFF;
550
551extern "system" {
552 fn InitializeSecurityDescriptor(desc: PSECURITY_DESCRIPTOR, revision: DWORD) -> BOOL;
553 fn SetSecurityDescriptorDacl(desc: PSECURITY_DESCRIPTOR, bDaclPresent: BOOL, pDacl: PACL, bDaclDefaulted: BOOL) -> BOOL;
554}