Use the windows crate facade consistently (#15737)
The initial motivation for this change was that we were using both the `windows`, the `window_sys` and the `windows_core` crate in various places. These crates have slightly unconventional versioning scheme where there is a large workspace with the same version in general, but only some crates get breaking releases when a new breaking release happens, the others stay on the previous breaking version. The `windows` crate is a shim for all three of them, with a single version. This simplifies handling the versions. Using `windows` over `windows_sys` has the advantage of a higher level error interface, we now get a `Result` for all windows API calls instead of C-style int-returns and get-last-error calls. This makes the uv-keyring crate more resilient. We keep using the `windows_registry` crate, which provides a higher level interface to windows registry access.
This commit is contained in:
@@ -12,13 +12,10 @@ use thiserror::Error;
|
||||
use tracing::debug;
|
||||
use uv_platform::Arch;
|
||||
use uv_warnings::{warn_user, warn_user_once};
|
||||
use windows::Win32::Foundation::ERROR_FILE_NOT_FOUND;
|
||||
use windows::Win32::System::Registry::{KEY_WOW64_32KEY, KEY_WOW64_64KEY};
|
||||
use windows::core::HRESULT;
|
||||
use windows_registry::{CURRENT_USER, HSTRING, Key, LOCAL_MACHINE, Value};
|
||||
use windows_result::HRESULT;
|
||||
use windows_sys::Win32::Foundation::ERROR_FILE_NOT_FOUND;
|
||||
use windows_sys::Win32::System::Registry::{KEY_WOW64_32KEY, KEY_WOW64_64KEY};
|
||||
|
||||
/// Code returned when the registry key doesn't exist.
|
||||
const ERROR_NOT_FOUND: HRESULT = HRESULT::from_win32(ERROR_FILE_NOT_FOUND);
|
||||
|
||||
/// A Python interpreter found in the Windows registry through PEP 514 or from a known Microsoft
|
||||
/// Store path.
|
||||
@@ -32,7 +29,7 @@ pub(crate) struct WindowsPython {
|
||||
}
|
||||
|
||||
/// Find all Pythons registered in the Windows registry following PEP 514.
|
||||
pub(crate) fn registry_pythons() -> Result<Vec<WindowsPython>, windows_result::Error> {
|
||||
pub(crate) fn registry_pythons() -> Result<Vec<WindowsPython>, windows::core::Error> {
|
||||
let mut registry_pythons = Vec::new();
|
||||
// Prefer `HKEY_CURRENT_USER` over `HKEY_LOCAL_MACHINE`.
|
||||
// By default, a 64-bit program does not see a 32-bit global (HKLM) installation of Python in
|
||||
@@ -47,7 +44,7 @@ pub(crate) fn registry_pythons() -> Result<Vec<WindowsPython>, windows_result::E
|
||||
let mut open_options = root_key.options();
|
||||
open_options.read();
|
||||
if let Some(access_modifier) = access_modifier {
|
||||
open_options.access(access_modifier);
|
||||
open_options.access(access_modifier.0);
|
||||
}
|
||||
let Ok(key_python) = open_options.open(r"Software\Python") else {
|
||||
continue;
|
||||
@@ -131,7 +128,7 @@ pub enum ManagedPep514Error {
|
||||
#[error("Windows has an unknown pointer width for arch: `{_0}`")]
|
||||
InvalidPointerSize(Arch),
|
||||
#[error("Failed to write registry entry: {0}")]
|
||||
WriteError(#[from] windows_result::Error),
|
||||
WriteError(#[from] windows::core::Error),
|
||||
}
|
||||
|
||||
/// Register a managed Python installation in the Windows registry following PEP 514.
|
||||
@@ -216,7 +213,7 @@ pub fn remove_registry_entry<'a>(
|
||||
if all {
|
||||
debug!("Removing registry key HKCU:\\{}", astral_key);
|
||||
if let Err(err) = CURRENT_USER.remove_tree(&astral_key) {
|
||||
if err.code() == ERROR_NOT_FOUND {
|
||||
if err.code() == HRESULT::from(ERROR_FILE_NOT_FOUND) {
|
||||
debug!("No registry entries to remove, no registry key {astral_key}");
|
||||
} else {
|
||||
warn_user!("Failed to clear registry entries under {astral_key}: {err}");
|
||||
@@ -230,7 +227,7 @@ pub fn remove_registry_entry<'a>(
|
||||
let python_entry = format!("{astral_key}\\{python_tag}");
|
||||
debug!("Removing registry key HKCU:\\{}", python_entry);
|
||||
if let Err(err) = CURRENT_USER.remove_tree(&python_entry) {
|
||||
if err.code() == ERROR_NOT_FOUND {
|
||||
if err.code() == HRESULT::from(ERROR_FILE_NOT_FOUND) {
|
||||
debug!(
|
||||
"No registry entries to remove for {}, no registry key {}",
|
||||
installation.key(),
|
||||
@@ -256,7 +253,7 @@ pub fn remove_orphan_registry_entries(installations: &[ManagedPythonInstallation
|
||||
let astral_key = format!("Software\\Python\\{COMPANY_KEY}");
|
||||
let key = match CURRENT_USER.open(&astral_key) {
|
||||
Ok(subkeys) => subkeys,
|
||||
Err(err) if err.code() == ERROR_NOT_FOUND => {
|
||||
Err(err) if err.code() == HRESULT::from(ERROR_FILE_NOT_FOUND) => {
|
||||
return;
|
||||
}
|
||||
Err(err) => {
|
||||
@@ -268,7 +265,7 @@ pub fn remove_orphan_registry_entries(installations: &[ManagedPythonInstallation
|
||||
// Separate assignment since `keys()` creates a borrow.
|
||||
let subkeys = match key.keys() {
|
||||
Ok(subkeys) => subkeys,
|
||||
Err(err) if err.code() == ERROR_NOT_FOUND => {
|
||||
Err(err) if err.code() == HRESULT::from(ERROR_FILE_NOT_FOUND) => {
|
||||
return;
|
||||
}
|
||||
Err(err) => {
|
||||
@@ -284,7 +281,7 @@ pub fn remove_orphan_registry_entries(installations: &[ManagedPythonInstallation
|
||||
let python_entry = format!("{astral_key}\\{subkey}");
|
||||
debug!("Removing orphan registry key HKCU:\\{}", python_entry);
|
||||
if let Err(err) = CURRENT_USER.remove_tree(&python_entry) {
|
||||
if err.code() == ERROR_NOT_FOUND {
|
||||
if err.code() == HRESULT::from(ERROR_FILE_NOT_FOUND) {
|
||||
continue;
|
||||
}
|
||||
// TODO(konsti): We don't have an installation key here.
|
||||
|
||||
Reference in New Issue
Block a user