ctoolbox/workspace/ipc/platform/
windows.rs1#[cfg(windows)]
2use anyhow::Context;
3
4#[cfg(windows)]
5use windows_sys::Win32::Foundation::{
6 CloseHandle, GetLastError, HANDLE, INVALID_HANDLE_VALUE,
7};
8
9#[cfg(windows)]
10use windows_sys::Win32::System::Memory::{
11 CreateFileMappingW, FILE_MAP_READ, FILE_MAP_WRITE, MapViewOfFile,
12 PAGE_READWRITE, UnmapViewOfFile,
13};
14
15#[cfg(windows)]
16use windows_sys::Win32::System::Threading::{
17 DUPLICATE_SAME_ACCESS, DuplicateHandle, GetCurrentProcess,
18};
19
20#[allow(unsafe_code)]
21#[cfg(windows)]
22fn last_err(msg: &str) -> Error {
23 let code = unsafe { GetLastError() };
24 anyhow::anyhow!("{msg} (GetLastError={code})").into()
25}
26
27#[cfg(windows)]
28fn to_handle(raw: u64) -> Result<HANDLE, Error> {
29 let h = raw as usize;
31 anyhow::ensure!(h as u64 == raw, "HANDLE value does not fit in usize");
32 Ok(h as HANDLE)
33}
34
35#[allow(unsafe_code)]
36#[cfg(windows)]
37pub fn create_file_mapping(size: u64) -> Result<u64, Error> {
38 let high = (size >> 32) as u32;
39 let low = (size & 0xffff_ffff) as u32;
40
41 let handle = unsafe {
43 CreateFileMappingW(
44 INVALID_HANDLE_VALUE,
45 std::ptr::null(),
46 PAGE_READWRITE,
47 high,
48 low,
49 std::ptr::null(),
50 )
51 };
52 if handle == 0 {
53 return Err(last_err("CreateFileMappingW failed"));
54 }
55 Ok(handle as u64)
56}
57
58#[allow(unsafe_code)]
59#[cfg(windows)]
60pub fn duplicate_handle_current(handle: u64) -> Result<u64, Error> {
61 let src = unsafe { GetCurrentProcess() };
62 let h = to_handle(handle)?;
63 let mut out: HANDLE = 0;
64
65 let ok = unsafe {
66 DuplicateHandle(
67 src,
68 h,
69 src,
70 &mut out as *mut HANDLE,
71 0,
72 0,
73 DUPLICATE_SAME_ACCESS,
74 )
75 };
76 if ok == 0 {
77 return Err(last_err("DuplicateHandle failed"));
78 }
79 Ok(out as u64)
80}
81
82#[allow(unsafe_code)]
83#[cfg(windows)]
84pub fn close_handle(handle: u64) -> Result<(), Error> {
85 let h = to_handle(handle)?;
86 let ok = unsafe { CloseHandle(h) };
87 if ok == 0 {
88 return Err(last_err("CloseHandle failed"));
89 }
90 Ok(())
91}
92
93#[cfg(windows)]
94pub struct MappingView {
95 handle: HANDLE,
96 ptr: *mut u8,
97 len: usize,
98}
99
100#[cfg(windows)]
101impl MappingView {
102 pub fn as_ptr(&self) -> *const u8 {
103 self.ptr as *const u8
104 }
105}
106
107#[allow(unsafe_code)]
108#[cfg(windows)]
109impl Drop for MappingView {
110 fn drop(&mut self) {
111 unsafe {
112 if !self.ptr.is_null() {
113 let _ = UnmapViewOfFile(self.ptr as *const _);
114 }
115 if self.handle != 0 {
116 let _ = CloseHandle(self.handle);
117 }
118 }
119 }
120}
121
122#[allow(unsafe_code)]
123#[cfg(windows)]
124pub fn map_view_read(handle: u64, len: usize) -> Result<MappingView, Error> {
125 let dup = duplicate_handle_current(handle)?;
128 let h = to_handle(dup)?;
129
130 let ptr = unsafe { MapViewOfFile(h, FILE_MAP_READ, 0, 0, len) } as *mut u8;
131 if ptr.is_null() {
132 let _ = unsafe { CloseHandle(h) };
134 return Err(last_err("MapViewOfFile(FILE_MAP_READ) failed"));
135 }
136
137 Ok(MappingView {
138 handle: h,
139 ptr,
140 len,
141 })
142}
143
144#[allow(unsafe_code)]
145#[cfg(windows)]
146pub fn write_mapping(handle: u64, data: &[u8]) -> Result<(), Error> {
147 let len = data.len();
148 let dup = duplicate_handle_current(handle)?;
149 let h = to_handle(dup)?;
150
151 let ptr = unsafe { MapViewOfFile(h, FILE_MAP_WRITE, 0, 0, len) } as *mut u8;
152 if ptr.is_null() {
153 let _ = unsafe { CloseHandle(h) };
154 return Err(last_err("MapViewOfFile(FILE_MAP_WRITE) failed"));
155 }
156
157 unsafe {
159 std::ptr::copy_nonoverlapping(data.as_ptr(), ptr, len);
160 let _ = UnmapViewOfFile(ptr as *const _);
161 let _ = CloseHandle(h);
162 }
163
164 Ok(())
165}