lib: remove usage of winreg crate

This pulls in a whole library just for what is morally 3 function calls
and can be done easily in the Windows API. Remove it.

This uses `unsafe`; the usage of `windows-rs` might be more preferrable
since we already (and will likely always) depend on it, but it would
probably remain unsafe...

Signed-off-by: Austin Seipp <aseipp@pobox.com>
This commit is contained in:
Austin Seipp 2025-04-07 20:30:23 -05:00
parent af4f7a7811
commit 2c76f79b57
5 changed files with 84 additions and 20 deletions

11
Cargo.lock generated
View File

@ -2396,7 +2396,6 @@ dependencies = [
"tracing",
"version_check",
"watchman_client",
"winreg",
]
[[package]]
@ -4798,16 +4797,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "winreg"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5"
dependencies = [
"cfg-if",
"windows-sys 0.48.0",
]
[[package]]
name = "wit-bindgen-rt"
version = "0.39.0"

View File

@ -122,7 +122,6 @@ unicode-width = "0.2.0"
version_check = "0.9.5"
watchman_client = { version = "0.9.0" }
whoami = "1.6.0"
winreg = "0.52"
# put all inter-workspace libraries, i.e. those that use 'path = ...' here in
# their own (alphabetically sorted) block

View File

@ -79,7 +79,6 @@ watchman_client = { workspace = true, optional = true }
rustix = { workspace = true }
[target.'cfg(windows)'.dependencies]
winreg = { workspace = true }
[dev-dependencies]
assert_matches = { workspace = true }

View File

@ -180,20 +180,97 @@ mod platform {
#[cfg(windows)]
mod platform {
use std::ffi::c_void;
use std::io;
use std::mem;
use std::os::windows::fs::symlink_file;
use std::path::Path;
use std::ptr;
use winreg::enums::HKEY_LOCAL_MACHINE;
use winreg::RegKey;
type HKEY = *mut c_void;
type LSTATUS = i32;
type DWORD = u32;
type REGSAM = u32;
const HKEY_LOCAL_MACHINE: HKEY = 0x80000002 as HKEY;
const KEY_READ: REGSAM = 0x20019;
const REG_DWORD: DWORD = 4;
const ERROR_SUCCESS: LSTATUS = 0;
#[link(name = "advapi32")]
extern "system" {
fn RegOpenKeyExA(
hKey: HKEY,
lpSubKey: *const u8,
ulOptions: DWORD,
samDesired: REGSAM,
phkResult: *mut HKEY,
) -> LSTATUS;
fn RegQueryValueExA(
hKey: HKEY,
lpValueName: *const u8,
lpReserved: *mut DWORD,
lpType: *mut DWORD,
lpData: *mut u8,
lpcbData: *mut DWORD,
) -> LSTATUS;
fn RegCloseKey(hKey: HKEY) -> LSTATUS;
}
/// Symlinks may or may not be enabled on Windows. They require the
/// Developer Mode setting, which is stored in the registry key below.
pub fn check_symlink_support() -> io::Result<bool> {
let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
let sideloading =
hklm.open_subkey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppModelUnlock")?;
let developer_mode: u32 = sideloading.get_value("AllowDevelopmentWithoutDevLicense")?;
// Registry subkey containing the developer mode setting
let subkey = b"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppModelUnlock\0";
// Value name for developer mode setting
let value_name = b"AllowDevelopmentWithoutDevLicense\0";
// Return value from registry operations
let mut key_handle: HKEY = ptr::null_mut();
let mut developer_mode: DWORD = 0;
let mut value_type: DWORD = 0;
let mut data_size: DWORD = mem::size_of::<DWORD>() as DWORD;
#[allow(unsafe_code)]
unsafe {
// Open the registry key
let result = RegOpenKeyExA(
HKEY_LOCAL_MACHINE,
subkey.as_ptr(),
0,
KEY_READ,
&mut key_handle,
);
if result != ERROR_SUCCESS {
return Err(io::Error::from_raw_os_error(result));
}
let result = RegQueryValueExA(
key_handle,
value_name.as_ptr(),
ptr::null_mut(),
&mut value_type,
&mut developer_mode as *mut DWORD as *mut u8,
&mut data_size,
);
RegCloseKey(key_handle);
if result != ERROR_SUCCESS {
return Err(io::Error::from_raw_os_error(result));
}
if value_type != REG_DWORD {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"Registry value is not a DWORD",
));
}
}
Ok(developer_mode == 1)
}

View File

@ -16,7 +16,7 @@
#![warn(missing_docs)]
#![deny(unused_must_use)]
#![forbid(unsafe_code)]
#![deny(unsafe_code)]
// Needed so that proc macros can be used inside jj_lib and by external crates
// that depend on it.