diff --git a/Cargo.lock b/Cargo.lock index defbf9c14..a9a9b6685 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,6 +163,21 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "assert_cmd" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed72493ac66d5804837f480ab3766c72bdfab91a65e565fc54fa9e42db0073a8" +dependencies = [ + "anstyle", + "bstr", + "doc-comment", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + [[package]] name = "async-broadcast" version = "0.5.1" @@ -1257,6 +1272,12 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + [[package]] name = "diffy" version = "0.3.0" @@ -1314,7 +1335,7 @@ checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1337,7 +1358,7 @@ checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", "redox_users", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1346,6 +1367,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + [[package]] name = "dtoa" version = "1.0.9" @@ -1491,7 +1518,7 @@ checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" dependencies = [ "errno-dragonfly", "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1719,7 +1746,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04412b8935272e3a9bae6f48c7bfff74c2911f60525404edfdd28e49884c3bfb" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2045,7 +2072,7 @@ dependencies = [ "gobject-sys", "libc", "system-deps 6.2.2", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2140,6 +2167,7 @@ dependencies = [ name = "gitbutler-git" version = "0.0.0" dependencies = [ + "assert_cmd", "futures", "gix-path 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.29.0", @@ -2149,8 +2177,7 @@ dependencies = [ "thiserror", "tokio", "uuid", - "winapi 0.3.9", - "windows-named-pipe", + "windows 0.57.0", ] [[package]] @@ -3430,7 +3457,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -3725,16 +3752,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "keyring" version = "2.3.3" @@ -4176,7 +4193,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -4186,7 +4203,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ "overload", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -4599,7 +4616,7 @@ dependencies = [ "libc", "redox_syscall 0.2.16", "smallvec", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -4938,6 +4955,33 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "predicates" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" +dependencies = [ + "anstyle", + "difflib", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" + +[[package]] +name = "predicates-tree" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +dependencies = [ + "predicates-core", + "termtree", +] + [[package]] name = "pretty_assertions" version = "1.4.0" @@ -6050,7 +6094,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -6409,7 +6453,7 @@ dependencies = [ "unicode-segmentation", "uuid", "windows 0.39.0", - "windows-implement", + "windows-implement 0.39.0", "x11-dl", ] @@ -6578,7 +6622,7 @@ dependencies = [ "serde", "tauri", "time", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -6740,6 +6784,12 @@ dependencies = [ "utf-8", ] +[[package]] +name = "termtree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" + [[package]] name = "thin-slice" version = "0.1.1" @@ -7152,7 +7202,7 @@ checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" dependencies = [ "memoffset 0.9.1", "tempfile", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -7297,6 +7347,15 @@ dependencies = [ "libc", ] +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "waker-fn" version = "1.2.0" @@ -7479,7 +7538,7 @@ dependencies = [ "webview2-com-macros", "webview2-com-sys", "windows 0.39.0", - "windows-implement", + "windows-implement 0.39.0", ] [[package]] @@ -7514,12 +7573,6 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - [[package]] name = "winapi" version = "0.3.9" @@ -7530,12 +7583,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -7576,7 +7623,7 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a" dependencies = [ - "windows-implement", + "windows-implement 0.39.0", "windows_aarch64_msvc 0.39.0", "windows_i686_gnu 0.39.0", "windows_i686_msvc 0.39.0", @@ -7599,7 +7646,17 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-core", + "windows-core 0.52.0", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", "windows-targets 0.52.5", ] @@ -7622,6 +7679,18 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement 0.57.0", + "windows-interface", + "windows-result", + "windows-targets 0.52.5", +] + [[package]] name = "windows-implement" version = "0.39.0" @@ -7632,6 +7701,28 @@ dependencies = [ "windows-tokens", ] +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "windows-metadata" version = "0.39.0" @@ -7639,13 +7730,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ee5e275231f07c6e240d14f34e1b635bf1faa1c76c57cfd59a5cdb9848e4278" [[package]] -name = "windows-named-pipe" -version = "0.1.0" +name = "windows-result" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808ba65b3d86cc5465971ad08ee3850e197cc8d5719277611fabb27827c02388" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" dependencies = [ - "kernel32-sys", - "winapi 0.2.8", + "windows-targets 0.52.5", ] [[package]] @@ -8016,7 +8106,7 @@ dependencies = [ "webkit2gtk-sys", "webview2-com", "windows 0.39.0", - "windows-implement", + "windows-implement 0.39.0", ] [[package]] @@ -8110,7 +8200,7 @@ dependencies = [ "static_assertions", "tracing", "uds_windows", - "winapi 0.3.9", + "winapi", "xdg-home", "zbus_macros", "zbus_names", diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index fd7d9c5ac..ab1313ed5 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -202,7 +202,7 @@ This paragraph is about crosscompilation to x86_64-MSVC from ARM Windows, a configuration typical for people with Apple Silicon and Parallels VMs, which only allow ARM Windows to be used. -The `winapi` dependency on `gitbutler-git` doesn't currently compile on ARM, +The `windows` dependency on `gitbutler-git` doesn't currently compile on ARM, which means cross-compilation to x86-64 is required to workaround that. Besides, most users will probably still be on INTEL machines, making this capability a common requirement. diff --git a/crates/gitbutler-git/Cargo.toml b/crates/gitbutler-git/Cargo.toml index 37f10138b..03c63b286 100644 --- a/crates/gitbutler-git/Cargo.toml +++ b/crates/gitbutler-git/Cargo.toml @@ -45,10 +45,21 @@ gix-path = "0.10.7" nix = { version = "0.29.0", features = ["process", "socket", "user"] } [target."cfg(windows)".dependencies] -winapi = { version = "0.3.9", features = ["winbase", "namedpipeapi"] } +windows = { version = "0.57.0", features = [ + "Win32", + "Win32_System", + "Win32_System_Pipes", + "Win32_Storage", + "Win32_Storage_FileSystem", + "Win32_Security", + "Win32_System_IO", + "Win32_System_Threading", +] } tokio = { workspace = true, optional = true, features = ["sync"] } -# synchronous named pipes for the askpass utility -windows-named-pipe = "0.1.0" + +[dev-dependencies] +assert_cmd = "2.0.14" +tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } [lints.clippy] all = "deny" diff --git a/crates/gitbutler-git/src/bin/askpass/windows-pipe.rs b/crates/gitbutler-git/src/bin/askpass/windows-pipe.rs new file mode 100644 index 000000000..6268b5153 --- /dev/null +++ b/crates/gitbutler-git/src/bin/askpass/windows-pipe.rs @@ -0,0 +1,160 @@ +use std::io::{self, Read, Write}; +use std::os::windows::ffi::OsStrExt; +use std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; +use std::path::Path; +use windows::core::PWSTR; +use windows::Win32::Foundation::{ + CloseHandle, DuplicateHandle, BOOL, DUPLICATE_SAME_ACCESS, ERROR_PIPE_NOT_CONNECTED, + GENERIC_READ, GENERIC_WRITE, HANDLE, WIN32_ERROR, +}; +use windows::Win32::Storage::FileSystem::{ + CreateFileW, FlushFileBuffers, ReadFile, WriteFile, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, + FILE_SHARE_WRITE, OPEN_EXISTING, +}; +use windows::Win32::System::Pipes::{WaitNamedPipeW, NMPWAIT_USE_DEFAULT_WAIT}; +use windows::Win32::System::Threading::GetCurrentProcess; + +#[derive(Debug)] +struct Handle { + inner: HANDLE, +} + +unsafe impl Send for Handle {} +unsafe impl Sync for Handle {} + +impl Handle { + fn try_clone(&self) -> io::Result { + let mut new_handle = HANDLE::default(); + let current_ps_handle: HANDLE = unsafe { GetCurrentProcess() }; + let res = unsafe { + DuplicateHandle( + current_ps_handle, + self.inner, + current_ps_handle, + &mut new_handle as *mut HANDLE, + 0, + BOOL(1), + DUPLICATE_SAME_ACCESS, + ) + }; + match res { + Ok(_) => Ok(Handle { inner: new_handle }), + Err(err) => Err(io::Error::from_raw_os_error(err.code().0)), + } + } +} + +impl Drop for Handle { + fn drop(&mut self) { + let _ = unsafe { CloseHandle(self.inner) }; + } +} + +#[derive(Debug)] +pub struct Pipe { + handle: Handle, +} + +impl Pipe { + pub fn connect(path: &Path) -> io::Result { + let mut wide_path: Vec = path + .as_os_str() + .encode_wide() + .chain(std::iter::once(0)) + .collect(); + + let pwstr_path = PWSTR(wide_path.as_mut_ptr()); + let _ = unsafe { WaitNamedPipeW(pwstr_path, NMPWAIT_USE_DEFAULT_WAIT) }; + let handle_res = unsafe { + CreateFileW( + pwstr_path, + GENERIC_READ.0 | GENERIC_WRITE.0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + None, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + None, + ) + }; + + match handle_res { + Ok(handle) => Ok(Pipe { + handle: Handle { inner: handle }, + }), + Err(err) => Err(io::Error::from_raw_os_error(err.code().0)), + } + } + + pub fn get_handle(&self) -> HANDLE { + self.handle.inner + } + + pub fn try_clone(&self) -> io::Result { + let handle = self.handle.try_clone()?; + Ok(Pipe { handle }) + } +} + +impl Drop for Pipe { + fn drop(&mut self) { + let _ = unsafe { FlushFileBuffers(self.handle.inner) }; + } +} + +impl Read for Pipe { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let mut bytes_read = 0u32; + let res = unsafe { ReadFile(self.handle.inner, Some(buf), Some(&mut bytes_read), None) }; + match res { + Ok(_) => Ok(bytes_read as usize), + Err(err) => match WIN32_ERROR::from_error(&err) { + Some(ERROR_PIPE_NOT_CONNECTED) => Ok(0), + _ => Err(io::Error::from_raw_os_error(err.code().0)), + }, + } + } +} + +impl Write for Pipe { + fn write(&mut self, buf: &[u8]) -> io::Result { + let mut bytes_written = 0u32; + + let res = + unsafe { WriteFile(self.handle.inner, Some(buf), Some(&mut bytes_written), None) }; + + match res { + Ok(_) => Ok(bytes_written as usize), + Err(err) => Err(io::Error::from_raw_os_error(err.code().0)), + } + } + + fn flush(&mut self) -> io::Result<()> { + let res = unsafe { FlushFileBuffers(self.handle.inner) }; + + match res { + Ok(_) => Ok(()), + Err(err) => Err(io::Error::from_raw_os_error(err.code().0)), + } + } +} + +impl AsRawHandle for Pipe { + fn as_raw_handle(&self) -> RawHandle { + self.handle.inner.0 as RawHandle + } +} + +impl IntoRawHandle for Pipe { + fn into_raw_handle(self) -> RawHandle { + self.handle.inner.0 as RawHandle + } +} + +impl FromRawHandle for Pipe { + unsafe fn from_raw_handle(handle: RawHandle) -> Self { + let handle = HANDLE(handle as isize); + Pipe { + handle: Handle { inner: handle }, + } + } +} diff --git a/crates/gitbutler-git/src/bin/askpass/windows.rs b/crates/gitbutler-git/src/bin/askpass/windows.rs index fb473f88b..14afb704a 100644 --- a/crates/gitbutler-git/src/bin/askpass/windows.rs +++ b/crates/gitbutler-git/src/bin/askpass/windows.rs @@ -1,12 +1,11 @@ -use std::{ - io, - os::windows::io::{AsRawHandle, FromRawHandle}, - time::Duration, -}; -use windows_named_pipe::PipeStream; +use std::{io, time::Duration}; +use windows::Win32::System::Pipes::SetNamedPipeHandleState; +#[path = "windows-pipe.rs"] +mod windows_pipe; +use windows_pipe::Pipe; -pub fn establish(sock_path: &str) -> PipeStream { - PipeStream::connect(sock_path).unwrap() +pub fn establish(sock_path: &str) -> Pipe { + Pipe::connect(std::path::Path::new(sock_path)).unwrap() } /// There are some methods we need in order to run askpass correctly, @@ -14,15 +13,10 @@ pub fn establish(sock_path: &str) -> PipeStream { /// We stub them using this trait so we don't have to newtype /// the pipestream itself (which would be extensive and un-DRY). pub trait UnixCompatibility: Sized { - fn try_clone(&self) -> Option; fn set_read_timeout(&self, timeout: Option) -> io::Result<()>; } -impl UnixCompatibility for PipeStream { - fn try_clone(&self) -> Option { - Some(unsafe { Self::from_raw_handle(self.as_raw_handle()) }) - } - +impl UnixCompatibility for Pipe { fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { // NOTE(qix-): Technically, this shouldn't work (and probably doesn't). // NOTE(qix-): The documentation states: @@ -32,28 +26,14 @@ impl UnixCompatibility for PipeStream { // NOTE(qix-): // NOTE(qix-): This is indeed the case here, but we try to make it work // NOTE(qix-): anyway. - #[allow(unused_assignments)] - let mut timeout_ms: winapi::shared::minwindef::DWORD = 0; - let timeout_ptr: winapi::shared::minwindef::LPDWORD = if let Some(timeout) = timeout { - timeout_ms = timeout.as_millis() as winapi::shared::minwindef::DWORD; - &mut timeout_ms as *mut _ - } else { - std::ptr::null_mut() - }; + let timeout_ms: Option<*const u32> = + timeout.map(|timeout| timeout.as_millis() as *const u32); - let r = unsafe { - winapi::um::namedpipeapi::SetNamedPipeHandleState( - self.as_raw_handle() as winapi::um::winnt::HANDLE, - std::ptr::null_mut(), - std::ptr::null_mut(), - timeout_ptr, - ) - }; + let r = unsafe { SetNamedPipeHandleState(self.get_handle(), None, None, timeout_ms) }; - if r == 0 { - Err(io::Error::last_os_error()) - } else { - Ok(()) + match r { + Ok(_) => Ok(()), + Err(err) => Err(io::Error::from_raw_os_error(err.code().0)), } } } diff --git a/crates/gitbutler-git/src/executor/tokio/mod.rs b/crates/gitbutler-git/src/executor/tokio/mod.rs index dd0e820ee..86e6c24df 100644 --- a/crates/gitbutler-git/src/executor/tokio/mod.rs +++ b/crates/gitbutler-git/src/executor/tokio/mod.rs @@ -128,3 +128,51 @@ unsafe impl super::GitExecutor for TokioExecutor { } } } +#[cfg(test)] +mod tests { + use super::*; + + use crate::executor::AskpassServer; + use crate::executor::GitExecutor; + use crate::executor::Socket; + use assert_cmd::Command; + use std::time::Duration; + + // cargo test --package gitbutler-git --lib test_askpass + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_askpass() { + let secret = "super-secret-secret"; + let executor = TokioExecutor; + #[allow(unsafe_code)] + let sock_server: TokioAskpassServer = unsafe { executor.create_askpass_server() } + .await + .expect("create_askpass_server():"); + let sock_server_string = sock_server.to_string(); + let handle = tokio::spawn(async move { + let mut cmd = Command::cargo_bin("gitbutler-git-askpass").unwrap(); + let assert = cmd + .env("GITBUTLER_ASKPASS_PIPE", sock_server_string) + .env("GITBUTLER_ASKPASS_SECRET", secret) + .arg("Please enter your password:") + .assert(); + assert.success().stdout("super_secret_password\n"); + }); + + let mut sock = sock_server + .accept(Some(Duration::from_secs(10))) + .await + .expect("accept():"); + + let peer_secret = sock.read_line().await.expect("read_line() peer_secret:"); + + assert_eq!(peer_secret, secret); + + let prompt = sock.read_line().await.expect("read_line() prompt:"); + assert_eq!(prompt.trim(), "Please enter your password:"); + + sock.write_line("super_secret_password") + .await + .expect("write_line() password:"); + handle.await.expect("Askpass command failed"); + } +} diff --git a/crates/gitbutler-git/src/executor/tokio/windows.rs b/crates/gitbutler-git/src/executor/tokio/windows.rs index 60c63686b..27b74d7bd 100644 --- a/crates/gitbutler-git/src/executor/tokio/windows.rs +++ b/crates/gitbutler-git/src/executor/tokio/windows.rs @@ -10,30 +10,25 @@ use tokio::{ net::windows::named_pipe::{NamedPipeServer, ServerOptions}, sync::Mutex, }; +use windows::Win32::{Foundation::HANDLE, System::Pipes::GetNamedPipeClientProcessId}; -const ASKPASS_PIPE_PREFIX: &str = r"\\.\pipe\gitbutler-askpass-"; +// Slashes instead of backslashes to prevent any issues with escaping. +const ASKPASS_PIPE_PREFIX: &str = r"//./pipe/gitbutler-askpass-"; impl Socket for BufStream { type Error = std::io::Error; fn pid(&self) -> Result { let raw_handle = self.get_ref().as_raw_handle(); - let mut out_pid: winapi::shared::minwindef::ULONG = 0; + let handle: HANDLE = HANDLE(raw_handle as isize); + let mut out_pid: u32 = 0; #[allow(unsafe_code)] - let r = unsafe { - winapi::um::winbase::GetNamedPipeClientProcessId( - // We need the `as` here to make rustdoc shut up - // about winapi using different type defs for docs. - raw_handle as winapi::um::winnt::HANDLE, - &mut out_pid, - ) - }; + let r = unsafe { GetNamedPipeClientProcessId(handle, &mut out_pid) }; - if r == 0 { - Err(std::io::Error::last_os_error()) - } else { - Ok(Pid::from(out_pid)) + match r { + Err(err) => Err(std::io::Error::from_raw_os_error(err.code().0)), + Ok(_) => Ok(Pid::from(out_pid)), } } @@ -64,6 +59,7 @@ impl TokioAskpassServer { let server = Mutex::new(RefCell::new( ServerOptions::new() .first_pipe_instance(true) + .max_instances(2) .create(&connection_string)?, ));