windows: credentials implementation (#9385)

Release Notes:

- N/A
This commit is contained in:
Ezekiel Warren 2024-03-18 10:16:29 -07:00 committed by GitHub
parent 64ebbb4afc
commit 4e17ce3b37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 69 additions and 7 deletions

View File

@ -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",

View File

@ -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<Result<()>> {
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<Result<Option<(String, Vec<u8>)>>> {
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<u8> = 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<Result<()>> {
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<anyhow::Result<()>> {

View File

@ -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)
}