1#![windows_subsystem = "windows"]
2
3#[cfg(debug_assertions)]
9mod dbg;
10
11mod server;
12
13extern crate asdf_overlay_vulkan_layer;
14
15use anyhow::Context;
16use asdf_overlay::{
17 backend::{Backends, window::ListenInputFlags},
18 event_sink::OverlayEventSink,
19 initialize,
20};
21use asdf_overlay_common::{
22 ipc::create_ipc_addr,
23 request::{Request, WindowRequest},
24};
25use asdf_overlay_event::{OverlayEvent, WindowEvent};
26use core::time::Duration;
27use scopeguard::defer;
28use std::{ffi::OsStr, thread};
29use tokio::{
30 net::windows::named_pipe::{NamedPipeServer, ServerOptions},
31 runtime::Runtime,
32 time::sleep,
33};
34use tracing::{debug, error, trace, warn};
35use windows::{
36 Win32::{
37 Foundation::{GENERIC_READ, GENERIC_WRITE, HINSTANCE},
38 Security::{
39 ACL, AllocateAndInitializeSid,
40 Authorization::{
41 EXPLICIT_ACCESS_A, SET_ACCESS, SetEntriesInAclA, TRUSTEE_A, TRUSTEE_IS_SID,
42 TRUSTEE_IS_USER,
43 },
44 FreeSid, InitializeSecurityDescriptor, NO_INHERITANCE, PSECURITY_DESCRIPTOR, PSID,
45 SECURITY_ATTRIBUTES, SECURITY_DESCRIPTOR, SECURITY_WORLD_SID_AUTHORITY,
46 SetSecurityDescriptorDacl,
47 },
48 System::{
49 SystemServices::{
50 DLL_PROCESS_ATTACH, SECURITY_DESCRIPTOR_REVISION, SECURITY_WORLD_RID,
51 },
52 Threading::GetCurrentProcessId,
53 },
54 },
55 core::{BOOL, PSTR},
56};
57
58use crate::server::IpcServerConn;
59
60#[tracing::instrument(skip(server))]
62async fn run(server: NamedPipeServer) -> anyhow::Result<()> {
63 fn handle_window_event(hwnd: u32, req: WindowRequest) -> anyhow::Result<bool> {
64 let res = Backends::with_backend(hwnd, |backend| {
65 match req {
66 WindowRequest::SetPosition(position) => {
67 backend.update_layout(|layout| {
68 layout.position = (position.x, position.y);
69 });
70 }
71
72 WindowRequest::SetAnchor(anchor) => {
73 backend.update_layout(|layout| {
74 layout.anchor = (anchor.x, anchor.y);
75 });
76 }
77
78 WindowRequest::SetMargin(margin) => {
79 backend.update_layout(|layout| {
80 layout.margin = (margin.top, margin.right, margin.bottom, margin.left);
81 });
82 }
83
84 WindowRequest::ListenInput(cmd) => {
85 let mut flags = ListenInputFlags::empty();
86 flags.set(ListenInputFlags::CURSOR, cmd.cursor);
87 flags.set(ListenInputFlags::KEYBOARD, cmd.keyboard);
88
89 backend.listen_input(flags);
90 }
91
92 WindowRequest::BlockInput(cmd) => {
93 backend.block_input(cmd.block);
94 }
95
96 WindowRequest::SetBlockingCursor(cmd) => {
97 backend.set_blocking_cursor(cmd.cursor);
98 }
99
100 WindowRequest::UpdateSharedHandle(shared) => {
101 if let Err(err) = backend.update_surface(shared.handle) {
102 error!("failed to open shared surface. err: {:?}", err);
103 return false;
104 }
105 }
106 }
107
108 true
109 });
110
111 Ok(res.unwrap_or(false))
112 }
113
114 let mut conn = IpcServerConn::new(server).await?;
115 let emitter = conn.create_emitter();
116 {
117 debug!("sending initial data");
118 for backend in Backends::iter() {
120 let render = backend.render.lock();
121 let gpu_id = render.interop.gpu_id();
122 let size = render.window_size;
123 _ = emitter.emit(OverlayEvent::Window {
124 id: *backend.key() as _,
125 event: WindowEvent::Added {
126 width: size.0,
127 height: size.1,
128 gpu_id,
129 },
130 });
131 }
132 }
133
134 OverlayEventSink::set(move |event| _ = emitter.emit(event));
135 defer!({
136 debug!("cleanup start");
137 OverlayEventSink::clear();
138 Backends::cleanup_backends();
139 });
140
141 while let Ok((req_id, req)) = conn.recv().await {
142 trace!("recv id: {req_id} req: {req:?}");
143
144 match req {
145 Request::Window { id, request } => {
146 conn.reply(req_id, handle_window_event(id, request)?)?;
147 }
148 }
149 }
150 Ok(())
151}
152
153#[tracing::instrument(skip(create_server))]
155async fn run_server(
156 mut server: NamedPipeServer,
157 mut create_server: impl FnMut() -> anyhow::Result<NamedPipeServer>,
158) {
159 loop {
160 debug!("waiting ipc client...");
161 match server.connect().await {
162 Ok(_) => {
163 if let Err(err) = run(server).await {
164 warn!("client connection ended unexpectedly. err: {:?}", err);
165 }
166 }
167 Err(err) => {
168 error!("failed to connect to client. err: {err:?}");
169 }
170 }
171
172 server = loop {
173 match create_server() {
174 Ok(server) => break server,
175 Err(err) => {
176 error!("failed to create server. retrying after 5 seconds. err: {err:?}");
177 sleep(Duration::from_secs(5)).await;
178 }
179 }
180 };
181 }
182}
183
184#[unsafe(no_mangle)]
189#[allow(non_snake_case, unused_variables)]
190pub unsafe extern "system" fn DllMain(dll_module: HINSTANCE, fdw_reason: u32, _: *mut ()) -> bool {
191 #[cfg(debug_assertions)]
192 fn setup_tracing() {
193 use tracing::level_filters::LevelFilter;
194
195 use crate::dbg::WinDbgMakeWriter;
196
197 tracing_subscriber::fmt::fmt()
198 .with_ansi(false)
199 .with_thread_ids(true)
200 .with_max_level(LevelFilter::TRACE)
201 .with_writer(WinDbgMakeWriter::new())
202 .init();
203 }
204
205 if fdw_reason != DLL_PROCESS_ATTACH {
206 return true;
207 }
208
209 #[cfg(debug_assertions)]
211 setup_tracing();
212
213 let Ok(rt) = Runtime::new() else {
215 error!("cannot create tokio runtime");
216 return false;
217 };
218 let _guard = rt.enter();
219
220 let pid = unsafe { GetCurrentProcessId() };
221 let module_handle = dll_module.0 as usize;
222 let server = match create_ipc_server(create_ipc_addr(pid, module_handle as u32), true) {
224 Ok(server) => server,
225 Err(err) => {
226 error!("cannot open ipc server. err: {err:?}");
227 return false;
228 }
229 };
230 let create_server =
231 move || create_ipc_server(create_ipc_addr(pid, module_handle as u32), false);
232
233 thread::spawn(move || {
234 initialize(module_handle as _).expect("initialization failed");
236 debug!("hook installed");
237
238 rt.block_on(run_server(server, create_server))
239 });
240 true
241}
242
243fn create_ipc_server(addr: impl AsRef<OsStr>, first: bool) -> anyhow::Result<NamedPipeServer> {
245 Ok(unsafe {
246 ServerOptions::new()
247 .first_pipe_instance(first)
248 .create_with_security_attributes_raw(
249 addr,
250 &mut SECURITY_ATTRIBUTES {
251 nLength: 1,
252 lpSecurityDescriptor: &mut create_everyone_security_desc()
253 .context("failed to create Everyone security desc")?
254 as *mut _ as _,
255 bInheritHandle: BOOL(0),
256 } as *mut _ as _,
257 )?
258 })
259}
260
261fn create_everyone_security_desc() -> anyhow::Result<SECURITY_DESCRIPTOR> {
263 let mut everyone_sid = PSID::default();
264 unsafe {
265 AllocateAndInitializeSid(
266 &SECURITY_WORLD_SID_AUTHORITY,
267 1,
268 SECURITY_WORLD_RID as _,
269 0,
270 0,
271 0,
272 0,
273 0,
274 0,
275 0,
276 &mut everyone_sid,
277 )?;
278 }
279 defer!(unsafe {
280 FreeSid(everyone_sid);
281 });
282
283 let access = EXPLICIT_ACCESS_A {
284 grfAccessPermissions: GENERIC_READ.0 | GENERIC_WRITE.0,
285 grfAccessMode: SET_ACCESS,
286 grfInheritance: NO_INHERITANCE,
287 Trustee: TRUSTEE_A {
288 TrusteeForm: TRUSTEE_IS_SID,
289 TrusteeType: TRUSTEE_IS_USER,
290 ptstrName: PSTR(everyone_sid.0.cast()),
291 ..Default::default()
292 },
293 };
294
295 let mut pacl: *mut ACL = 0 as _;
296 unsafe {
297 SetEntriesInAclA(Some(&[access]), None, &mut pacl).ok()?;
298 }
299
300 let mut security_desc = SECURITY_DESCRIPTOR::default();
301 unsafe {
302 InitializeSecurityDescriptor(
303 PSECURITY_DESCRIPTOR(&mut security_desc as *mut _ as _),
304 SECURITY_DESCRIPTOR_REVISION,
305 )?;
306
307 SetSecurityDescriptorDacl(
308 PSECURITY_DESCRIPTOR(&mut security_desc as *mut _ as _),
309 true,
310 Some(pacl),
311 false,
312 )?;
313 }
314
315 Ok(security_desc)
316}