From 4e17ce3b37868a78ea16cba7cd44d0dfec7cc80c Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Mon, 18 Mar 2024 10:16:29 -0700 Subject: [PATCH] windows: credentials implementation (#9385) Release Notes: - N/A --- Cargo.toml | 1 + crates/gpui/src/platform/windows/platform.rs | 71 ++++++++++++++++++-- crates/gpui/src/platform/windows/util.rs | 4 ++ 3 files changed, 69 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7e50561ec8..3f5f496776 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -347,6 +347,7 @@ features = [ "Win32_Graphics_Gdi", "Win32_Media", "Win32_Security", + "Win32_Security_Credentials", "Win32_Storage_FileSystem", "Win32_System_Com", "Win32_System_Com_StructuredStorage", diff --git a/crates/gpui/src/platform/windows/platform.rs b/crates/gpui/src/platform/windows/platform.rs index 968537e1fd..663bf0c720 100644 --- a/crates/gpui/src/platform/windows/platform.rs +++ b/crates/gpui/src/platform/windows/platform.rs @@ -4,6 +4,7 @@ use std::{ cell::{Cell, RefCell}, ffi::{c_uint, c_void, OsString}, + iter::once, mem::transmute, os::windows::ffi::{OsStrExt, OsStringExt}, path::{Path, PathBuf}, @@ -28,7 +29,8 @@ use windows::{ Foundation::*, Graphics::Gdi::*, Media::*, - System::{Com::*, LibraryLoader::*, Ole::*, Threading::*, Time::*}, + Security::Credentials::*, + System::{Com::*, LibraryLoader::*, Ole::*, SystemInformation::*, Threading::*, Time::*}, UI::{Input::KeyboardAndMouse::*, Shell::*, WindowsAndMessaging::*}, }, }; @@ -606,19 +608,74 @@ impl Platform for WindowsPlatform { }) } - // todo(windows) fn write_credentials(&self, url: &str, username: &str, password: &[u8]) -> Task> { - Task::Ready(Some(Err(anyhow!("not implemented yet.")))) + let mut password = password.to_vec(); + let mut username = username.encode_utf16().chain(once(0)).collect_vec(); + let mut target_name = windows_credentials_target_name(url) + .encode_utf16() + .chain(once(0)) + .collect_vec(); + self.foreground_executor().spawn(async move { + let credentials = CREDENTIALW { + LastWritten: unsafe { GetSystemTimeAsFileTime() }, + Flags: CRED_FLAGS(0), + Type: CRED_TYPE_GENERIC, + TargetName: PWSTR::from_raw(target_name.as_mut_ptr()), + CredentialBlobSize: password.len() as u32, + CredentialBlob: password.as_ptr() as *mut _, + Persist: CRED_PERSIST_LOCAL_MACHINE, + UserName: PWSTR::from_raw(username.as_mut_ptr()), + ..CREDENTIALW::default() + }; + unsafe { CredWriteW(&credentials, 0) }?; + Ok(()) + }) } - // todo(windows) fn read_credentials(&self, url: &str) -> Task)>>> { - Task::Ready(Some(Err(anyhow!("not implemented yet.")))) + let mut target_name = windows_credentials_target_name(url) + .encode_utf16() + .chain(once(0)) + .collect_vec(); + self.foreground_executor().spawn(async move { + let mut credentials: *mut CREDENTIALW = std::ptr::null_mut(); + unsafe { + CredReadW( + PCWSTR::from_raw(target_name.as_ptr()), + CRED_TYPE_GENERIC, + 0, + &mut credentials, + )? + }; + + if credentials.is_null() { + Ok(None) + } else { + let username: String = unsafe { (*credentials).UserName.to_string()? }; + let credential_blob = unsafe { + std::slice::from_raw_parts( + (*credentials).CredentialBlob, + (*credentials).CredentialBlobSize as usize, + ) + }; + let mut password: Vec = Vec::with_capacity(credential_blob.len()); + password.resize(password.capacity(), 0); + password.clone_from_slice(&credential_blob); + unsafe { CredFree(credentials as *const c_void) }; + Ok(Some((username, password))) + } + }) } - // todo(windows) fn delete_credentials(&self, url: &str) -> Task> { - Task::Ready(Some(Err(anyhow!("not implemented yet.")))) + let mut target_name = windows_credentials_target_name(url) + .encode_utf16() + .chain(once(0)) + .collect_vec(); + self.foreground_executor().spawn(async move { + unsafe { CredDeleteW(PCWSTR::from_raw(target_name.as_ptr()), CRED_TYPE_GENERIC, 0)? }; + Ok(()) + }) } fn register_url_scheme(&self, _: &str) -> Task> { diff --git a/crates/gpui/src/platform/windows/util.rs b/crates/gpui/src/platform/windows/util.rs index 7093f564ca..5fbff4a3ce 100644 --- a/crates/gpui/src/platform/windows/util.rs +++ b/crates/gpui/src/platform/windows/util.rs @@ -68,3 +68,7 @@ pub(crate) unsafe fn set_window_long( SetWindowLongW(hwnd, nindex, dwnewlong as i32) as isize } } + +pub(crate) fn windows_credentials_target_name(url: &str) -> String { + format!("zed:url={}", url) +}