use crate::{
ProcessId,
peer::{Credentials, UserEvidence},
};
use std::io;
use std::os::windows::io::{AsHandle, AsRawHandle, RawHandle};
const NO_CONNECTION_USER: [i32; 2] = [1368, 1347];
fn pipe_credentials(
stream: &impl interprocess::local_socket::traits::StreamCommon,
server_end: Option<RawHandle>,
) -> io::Result<Credentials> {
let pid = stream
.peer_creds()?
.pid()
.and_then(ProcessId::new)
.ok_or_else(|| io::Error::other("named-pipe peer has no PID"))?;
let (same_user, evidence) =
match server_end.map(super::super::windows::pipe_client_runs_as_this_user) {
Some(Ok(same_user)) => (same_user, UserEvidence::Connection),
Some(Err(error))
if !error
.raw_os_error()
.is_some_and(|code| NO_CONNECTION_USER.contains(&code)) =>
{
return Err(error);
}
_ => (
super::super::windows::process_runs_as_this_user(pid)?,
UserEvidence::PidLookup,
),
};
Ok(Credentials::new(Some(pid), same_user).with_user_evidence(evidence))
}
impl super::PeerCredentials for interprocess::local_socket::Stream {
fn credentials(&self) -> io::Result<Credentials> {
let Self::NamedPipe(pipe) = self;
let server_end = pipe
.inner()
.is_server()
.then(|| pipe.as_handle().as_raw_handle());
pipe_credentials(self, server_end)
}
}
#[cfg(feature = "local-async")]
impl super::PeerCredentials for interprocess::local_socket::tokio::Stream {
fn credentials(&self) -> io::Result<Credentials> {
let Self::NamedPipe(pipe) = self;
let server_end = pipe
.inner()
.is_server()
.then(|| pipe.as_handle().as_raw_handle());
pipe_credentials(self, server_end)
}
}