From 52352c091cb079d0727c22b019df06b851ae2293 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 1 May 2024 06:34:14 -0500 Subject: [PATCH] Add support for freeing handles automatically (#3013) --- crates/libs/bindgen/src/rust/handles.rs | 58 ++++++++++++++++++- crates/libs/core/src/handles.rs | 45 ++++++++++++++ crates/libs/core/src/lib.rs | 2 + .../Windows/Wdk/System/OfflineRegistry/mod.rs | 7 +++ .../Windows/Win32/Devices/Bluetooth/mod.rs | 14 +++++ .../DeviceAndDriverInstallation/mod.rs | 7 +++ .../src/Windows/Win32/Devices/Display/mod.rs | 7 +++ .../src/Windows/Win32/Devices/Usb/mod.rs | 7 +++ .../src/Windows/Win32/Foundation/mod.rs | 35 +++++++++++ .../src/Windows/Win32/Graphics/Gdi/mod.rs | 56 ++++++++++++++++++ .../src/Windows/Win32/Graphics/OpenGL/mod.rs | 7 +++ .../Security/Authentication/Identity/mod.rs | 7 +++ .../Win32/Security/Cryptography/mod.rs | 56 ++++++++++++++++++ .../Storage/InstallableFileSystems/mod.rs | 14 +++++ .../mod.rs | 7 +++ .../src/Windows/Win32/System/Console/mod.rs | 7 +++ .../Win32/System/Diagnostics/Etw/mod.rs | 7 +++ .../Win32/System/ErrorReporting/mod.rs | 14 +++++ .../src/Windows/Win32/System/EventLog/mod.rs | 7 +++ .../Win32/System/HostComputeSystem/mod.rs | 21 +++++++ .../Windows/Win32/System/Hypervisor/mod.rs | 7 +++ .../src/Windows/Win32/System/Power/mod.rs | 7 +++ .../src/Windows/Win32/System/Registry/mod.rs | 7 +++ .../Win32/System/StationsAndDesktops/mod.rs | 14 +++++ .../src/Windows/Win32/UI/Accessibility/mod.rs | 7 +++ .../src/Windows/Win32/UI/ColorSystem/mod.rs | 7 +++ .../src/Windows/Win32/UI/Controls/mod.rs | 21 +++++++ .../Win32/UI/WindowsAndMessaging/mod.rs | 42 ++++++++++++++ .../samples/windows/kernel_event/src/main.rs | 10 ++-- crates/samples/windows/overlapped/src/main.rs | 10 ++-- crates/samples/windows/privileges/src/main.rs | 3 +- crates/tests/bcrypt/tests/win.rs | 31 +++++----- 32 files changed, 520 insertions(+), 31 deletions(-) create mode 100644 crates/libs/core/src/handles.rs diff --git a/crates/libs/bindgen/src/rust/handles.rs b/crates/libs/bindgen/src/rust/handles.rs index cd04b20448..1964b85e4b 100644 --- a/crates/libs/bindgen/src/rust/handles.rs +++ b/crates/libs/bindgen/src/rust/handles.rs @@ -30,7 +30,7 @@ pub fn gen_win_handle(writer: &Writer, def: metadata::TypeDef) -> TokenStream { let ident = to_ident(name); let underlying_type = def.underlying_type(); let signature = writer.type_default_name(&underlying_type); - let check = if underlying_type.is_pointer() { + let is_invalid = if underlying_type.is_pointer() { quote! { impl #ident { pub fn is_invalid(&self) -> bool { @@ -63,12 +63,47 @@ pub fn gen_win_handle(writer: &Writer, def: metadata::TypeDef) -> TokenStream { } }; + let free = if let Some(function) = free_function(def) { + if is_invalid.is_empty() { + // TODO: https://github.com/microsoft/win32metadata/issues/1891 + quote! {} + } else { + let name = to_ident(function.name()); + let signature = metadata::method_def_signature(def.namespace(), function, &[]); + + // BCryptCloseAlgorithmProvider has an unused trailing parameter. + let tail = if signature.params.len() > 1 { + quote! { , 0 } + } else { + quote! {} + }; + + let result = if signature.return_type == metadata::Type::Void { + quote! {} + } else { + quote! { _ = } + }; + + quote! { + impl windows_core::Free for #ident { + unsafe fn free(&mut self) { + if !self.is_invalid() { + #result #name(*self #tail); + } + } + } + } + } + } else { + quote! {} + }; + let mut tokens = quote! { #[repr(transparent)] - // Unfortunately, Rust requires these to be derived to allow constant patterns. #[derive(PartialEq, Eq)] pub struct #ident(pub #signature); - #check + #is_invalid + #free impl Default for #ident { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -116,3 +151,20 @@ fn type_def_usable_for(row: metadata::TypeDef) -> Option { } None } + +fn free_function(def: metadata::TypeDef) -> Option { + if let Some(attribute) = def.find_attribute("RAIIFreeAttribute") { + // TODO: https://github.com/microsoft/win32metadata/issues/1892 + if matches!(def.name(), "COMPRESSOR_HANDLE" | "WSAEVENT") { + return None; + } + + if let Some((_, metadata::Value::String(name))) = attribute.args().first() { + if let Some((method, _)) = def.reader().get_method_def(def.namespace(), name.as_str()).next() { + return Some(method); + } + } + } + + None +} diff --git a/crates/libs/core/src/handles.rs b/crates/libs/core/src/handles.rs new file mode 100644 index 0000000000..415e13a802 --- /dev/null +++ b/crates/libs/core/src/handles.rs @@ -0,0 +1,45 @@ +/// Custom code to free a handle. +/// +/// This is similar to the `Drop` trait, and may be used to implement `Drop`, but allows handles +/// to be dropped depending on context. +pub trait Free { + /// Calls the handle's free function. + /// + /// # Safety + /// The handle must be owned by the caller and safe to free. + unsafe fn free(&mut self); +} + +/// A wrapper to provide ownership for handles to automatically drop via the handle's `Free` trait. +#[repr(transparent)] +#[derive(Clone, PartialEq, Eq, Default, Debug)] +pub struct Owned(T); + +impl Owned { + /// Takes ownership of the handle. + /// + /// # Safety + /// The handle must be owned by the caller and safe to free. + pub unsafe fn new(x: T) -> Self { + Self(x) + } +} + +impl Drop for Owned { + fn drop(&mut self) { + unsafe { self.0.free() }; + } +} + +impl std::ops::Deref for Owned { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::ops::DerefMut for Owned { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} diff --git a/crates/libs/core/src/lib.rs b/crates/libs/core/src/lib.rs index e5ad41ee83..1e36f0d7d9 100644 --- a/crates/libs/core/src/lib.rs +++ b/crates/libs/core/src/lib.rs @@ -16,6 +16,7 @@ mod array; mod as_impl; mod event; mod guid; +mod handles; mod inspectable; mod interface; mod param; @@ -33,6 +34,7 @@ pub use array::*; pub use as_impl::*; pub use event::*; pub use guid::*; +pub use handles::*; pub use inspectable::*; pub use interface::*; pub use param::*; diff --git a/crates/libs/windows/src/Windows/Wdk/System/OfflineRegistry/mod.rs b/crates/libs/windows/src/Windows/Wdk/System/OfflineRegistry/mod.rs index b532178147..67ecd5609c 100644 --- a/crates/libs/windows/src/Windows/Wdk/System/OfflineRegistry/mod.rs +++ b/crates/libs/windows/src/Windows/Wdk/System/OfflineRegistry/mod.rs @@ -210,6 +210,13 @@ impl ORHKEY { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for ORHKEY { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = ORCloseKey(*self); + } + } +} impl Default for ORHKEY { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/Devices/Bluetooth/mod.rs b/crates/libs/windows/src/Windows/Win32/Devices/Bluetooth/mod.rs index 2219e903e6..827850c936 100644 --- a/crates/libs/windows/src/Windows/Win32/Devices/Bluetooth/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/Devices/Bluetooth/mod.rs @@ -2465,6 +2465,13 @@ impl HBLUETOOTH_DEVICE_FIND { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HBLUETOOTH_DEVICE_FIND { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = BluetoothFindDeviceClose(*self); + } + } +} impl Default for HBLUETOOTH_DEVICE_FIND { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -2492,6 +2499,13 @@ impl HBLUETOOTH_RADIO_FIND { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HBLUETOOTH_RADIO_FIND { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = BluetoothFindRadioClose(*self); + } + } +} impl Default for HBLUETOOTH_RADIO_FIND { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/Devices/DeviceAndDriverInstallation/mod.rs b/crates/libs/windows/src/Windows/Win32/Devices/DeviceAndDriverInstallation/mod.rs index 8e7a320cbd..21481fdfcd 100644 --- a/crates/libs/windows/src/Windows/Win32/Devices/DeviceAndDriverInstallation/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/Devices/DeviceAndDriverInstallation/mod.rs @@ -8392,6 +8392,13 @@ impl HDEVINFO { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HDEVINFO { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = SetupDiDestroyDeviceInfoList(*self); + } + } +} impl Default for HDEVINFO { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/Devices/Display/mod.rs b/crates/libs/windows/src/Windows/Win32/Devices/Display/mod.rs index e85f4141d5..d00cb49e3d 100644 --- a/crates/libs/windows/src/Windows/Win32/Devices/Display/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/Devices/Display/mod.rs @@ -6245,6 +6245,13 @@ impl HSEMAPHORE { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HSEMAPHORE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + EngDeleteSemaphore(*self); + } + } +} impl Default for HSEMAPHORE { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/Devices/Usb/mod.rs b/crates/libs/windows/src/Windows/Win32/Devices/Usb/mod.rs index 68b9798dce..34cd2bd4ad 100644 --- a/crates/libs/windows/src/Windows/Win32/Devices/Usb/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/Devices/Usb/mod.rs @@ -5968,6 +5968,13 @@ impl WINUSB_INTERFACE_HANDLE { self.0 == 0 } } +impl windows_core::Free for WINUSB_INTERFACE_HANDLE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = WinUsb_Free(*self); + } + } +} impl Default for WINUSB_INTERFACE_HANDLE { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/Foundation/mod.rs b/crates/libs/windows/src/Windows/Win32/Foundation/mod.rs index f7eb01194e..f6725f65bc 100644 --- a/crates/libs/windows/src/Windows/Win32/Foundation/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/Foundation/mod.rs @@ -10785,6 +10785,13 @@ impl HANDLE { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HANDLE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = CloseHandle(*self); + } + } +} impl Default for HANDLE { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -10834,6 +10841,13 @@ impl HGLOBAL { self.0.is_null() } } +impl windows_core::Free for HGLOBAL { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = GlobalFree(*self); + } + } +} impl Default for HGLOBAL { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -10861,6 +10875,13 @@ impl HINSTANCE { self.0 == 0 } } +impl windows_core::Free for HINSTANCE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = FreeLibrary(*self); + } + } +} impl Default for HINSTANCE { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -10894,6 +10915,13 @@ impl HLOCAL { self.0.is_null() } } +impl windows_core::Free for HLOCAL { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = LocalFree(*self); + } + } +} impl Default for HLOCAL { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -10943,6 +10971,13 @@ impl HMODULE { self.0 == 0 } } +impl windows_core::Free for HMODULE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = FreeLibrary(*self); + } + } +} impl Default for HMODULE { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/Graphics/Gdi/mod.rs b/crates/libs/windows/src/Windows/Win32/Graphics/Gdi/mod.rs index 0577da6ad0..9a77b4ea4a 100644 --- a/crates/libs/windows/src/Windows/Win32/Graphics/Gdi/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/Graphics/Gdi/mod.rs @@ -10668,6 +10668,13 @@ impl HBITMAP { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HBITMAP { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = DeleteObject(*self); + } + } +} impl Default for HBITMAP { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -10701,6 +10708,13 @@ impl HBRUSH { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HBRUSH { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = DeleteObject(*self); + } + } +} impl Default for HBRUSH { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -10761,6 +10775,13 @@ impl HENHMETAFILE { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HENHMETAFILE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = DeleteEnhMetaFile(*self); + } + } +} impl Default for HENHMETAFILE { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -10788,6 +10809,13 @@ impl HFONT { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HFONT { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = DeleteObject(*self); + } + } +} impl Default for HFONT { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -10848,6 +10876,13 @@ impl HMETAFILE { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HMETAFILE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = DeleteMetaFile(*self); + } + } +} impl Default for HMETAFILE { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -10902,6 +10937,13 @@ impl HPALETTE { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HPALETTE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = DeleteObject(*self); + } + } +} impl Default for HPALETTE { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -10935,6 +10977,13 @@ impl HPEN { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HPEN { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = DeleteObject(*self); + } + } +} impl Default for HPEN { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -10968,6 +11017,13 @@ impl HRGN { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HRGN { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = DeleteObject(*self); + } + } +} impl Default for HRGN { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/Graphics/OpenGL/mod.rs b/crates/libs/windows/src/Windows/Win32/Graphics/OpenGL/mod.rs index ae6e9461a5..e1792205b4 100644 --- a/crates/libs/windows/src/Windows/Win32/Graphics/OpenGL/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/Graphics/OpenGL/mod.rs @@ -3087,6 +3087,13 @@ impl HGLRC { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HGLRC { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = wglDeleteContext(*self); + } + } +} impl Default for HGLRC { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/Security/Authentication/Identity/mod.rs b/crates/libs/windows/src/Windows/Win32/Security/Authentication/Identity/mod.rs index b7e3871205..b937ad2349 100644 --- a/crates/libs/windows/src/Windows/Win32/Security/Authentication/Identity/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/Security/Authentication/Identity/mod.rs @@ -7805,6 +7805,13 @@ impl LSA_HANDLE { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for LSA_HANDLE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = LsaClose(*self); + } + } +} impl Default for LSA_HANDLE { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/Security/Cryptography/mod.rs b/crates/libs/windows/src/Windows/Win32/Security/Cryptography/mod.rs index 217819c1f7..be8890829e 100644 --- a/crates/libs/windows/src/Windows/Win32/Security/Cryptography/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/Security/Cryptography/mod.rs @@ -8799,6 +8799,13 @@ impl BCRYPT_ALG_HANDLE { self.0.is_null() } } +impl windows_core::Free for BCRYPT_ALG_HANDLE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = BCryptCloseAlgorithmProvider(*self, 0); + } + } +} impl Default for BCRYPT_ALG_HANDLE { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -9209,6 +9216,13 @@ impl BCRYPT_HASH_HANDLE { self.0.is_null() } } +impl windows_core::Free for BCRYPT_HASH_HANDLE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = BCryptDestroyHash(*self); + } + } +} impl Default for BCRYPT_HASH_HANDLE { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -9332,6 +9346,13 @@ impl BCRYPT_KEY_HANDLE { self.0.is_null() } } +impl windows_core::Free for BCRYPT_KEY_HANDLE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = BCryptDestroyKey(*self); + } + } +} impl Default for BCRYPT_KEY_HANDLE { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -9671,6 +9692,13 @@ impl BCRYPT_SECRET_HANDLE { self.0.is_null() } } +impl windows_core::Free for BCRYPT_SECRET_HANDLE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = BCryptDestroySecret(*self); + } + } +} impl Default for BCRYPT_SECRET_HANDLE { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -19101,6 +19129,13 @@ impl HCERTCHAINENGINE { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HCERTCHAINENGINE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + CertFreeCertificateChainEngine(*self); + } + } +} impl Default for HCERTCHAINENGINE { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -19182,6 +19217,13 @@ impl HCRYPTASYNC { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HCRYPTASYNC { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = CryptCloseAsyncHandle(*self); + } + } +} impl Default for HCRYPTASYNC { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -19828,6 +19870,13 @@ impl NCRYPT_KEY_HANDLE { self.0 == 0 } } +impl windows_core::Free for NCRYPT_KEY_HANDLE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = NCryptFreeObject(*self); + } + } +} impl Default for NCRYPT_KEY_HANDLE { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -20068,6 +20117,13 @@ impl NCRYPT_PROV_HANDLE { self.0 == 0 } } +impl windows_core::Free for NCRYPT_PROV_HANDLE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = NCryptFreeObject(*self); + } + } +} impl Default for NCRYPT_PROV_HANDLE { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/Storage/InstallableFileSystems/mod.rs b/crates/libs/windows/src/Windows/Win32/Storage/InstallableFileSystems/mod.rs index 6eecfd8109..6528b87902 100644 --- a/crates/libs/windows/src/Windows/Win32/Storage/InstallableFileSystems/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/Storage/InstallableFileSystems/mod.rs @@ -775,6 +775,13 @@ impl HFILTER { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HFILTER { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = FilterClose(*self); + } + } +} impl Default for HFILTER { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -802,6 +809,13 @@ impl HFILTER_INSTANCE { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HFILTER_INSTANCE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = FilterInstanceClose(*self); + } + } +} impl Default for HFILTER_INSTANCE { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/System/ApplicationInstallationAndServicing/mod.rs b/crates/libs/windows/src/Windows/Win32/System/ApplicationInstallationAndServicing/mod.rs index 38a1356593..12d18ec578 100644 --- a/crates/libs/windows/src/Windows/Win32/System/ApplicationInstallationAndServicing/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/System/ApplicationInstallationAndServicing/mod.rs @@ -8004,6 +8004,13 @@ impl MSIHANDLE { self.0 == -1 as _ || self.0 == 0 } } +impl windows_core::Free for MSIHANDLE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = MsiCloseHandle(*self); + } + } +} impl Default for MSIHANDLE { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/System/Console/mod.rs b/crates/libs/windows/src/Windows/Win32/System/Console/mod.rs index 2715e55954..f087fc680a 100644 --- a/crates/libs/windows/src/Windows/Win32/System/Console/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/System/Console/mod.rs @@ -1413,6 +1413,13 @@ impl HPCON { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HPCON { + unsafe fn free(&mut self) { + if !self.is_invalid() { + ClosePseudoConsole(*self); + } + } +} impl Default for HPCON { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/System/Diagnostics/Etw/mod.rs b/crates/libs/windows/src/Windows/Win32/System/Diagnostics/Etw/mod.rs index da3735ccb8..653768f781 100644 --- a/crates/libs/windows/src/Windows/Win32/System/Diagnostics/Etw/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/System/Diagnostics/Etw/mod.rs @@ -4538,6 +4538,13 @@ impl TDH_HANDLE { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for TDH_HANDLE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = TdhCloseDecodingHandle(*self); + } + } +} impl Default for TDH_HANDLE { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/System/ErrorReporting/mod.rs b/crates/libs/windows/src/Windows/Win32/System/ErrorReporting/mod.rs index 9d0b912421..53617c476d 100644 --- a/crates/libs/windows/src/Windows/Win32/System/ErrorReporting/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/System/ErrorReporting/mod.rs @@ -689,6 +689,13 @@ impl HREPORT { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HREPORT { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = WerReportCloseHandle(*self); + } + } +} impl Default for HREPORT { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -716,6 +723,13 @@ impl HREPORTSTORE { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HREPORTSTORE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + WerStoreClose(*self); + } + } +} impl Default for HREPORTSTORE { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/System/EventLog/mod.rs b/crates/libs/windows/src/Windows/Win32/System/EventLog/mod.rs index 6a94fd0a96..c6c070f53c 100644 --- a/crates/libs/windows/src/Windows/Win32/System/EventLog/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/System/EventLog/mod.rs @@ -1080,6 +1080,13 @@ impl EVT_HANDLE { self.0 == 0 } } +impl windows_core::Free for EVT_HANDLE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = EvtClose(*self); + } + } +} impl Default for EVT_HANDLE { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/System/HostComputeSystem/mod.rs b/crates/libs/windows/src/Windows/Win32/System/HostComputeSystem/mod.rs index 2e5d671feb..da478f8a3e 100644 --- a/crates/libs/windows/src/Windows/Win32/System/HostComputeSystem/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/System/HostComputeSystem/mod.rs @@ -880,6 +880,13 @@ impl HCS_OPERATION { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HCS_OPERATION { + unsafe fn free(&mut self) { + if !self.is_invalid() { + HcsCloseOperation(*self); + } + } +} impl Default for HCS_OPERATION { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -907,6 +914,13 @@ impl HCS_PROCESS { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HCS_PROCESS { + unsafe fn free(&mut self) { + if !self.is_invalid() { + HcsCloseProcess(*self); + } + } +} impl Default for HCS_PROCESS { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -967,6 +981,13 @@ impl HCS_SYSTEM { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HCS_SYSTEM { + unsafe fn free(&mut self) { + if !self.is_invalid() { + HcsCloseComputeSystem(*self); + } + } +} impl Default for HCS_SYSTEM { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/System/Hypervisor/mod.rs b/crates/libs/windows/src/Windows/Win32/System/Hypervisor/mod.rs index d08e94d089..a741097e40 100644 --- a/crates/libs/windows/src/Windows/Win32/System/Hypervisor/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/System/Hypervisor/mod.rs @@ -3862,6 +3862,13 @@ impl WHV_PARTITION_HANDLE { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for WHV_PARTITION_HANDLE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = WHvDeletePartition(*self); + } + } +} impl Default for WHV_PARTITION_HANDLE { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/System/Power/mod.rs b/crates/libs/windows/src/Windows/Win32/System/Power/mod.rs index 6f5c7e5689..a4df6f01e8 100644 --- a/crates/libs/windows/src/Windows/Win32/System/Power/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/System/Power/mod.rs @@ -2372,6 +2372,13 @@ impl HPOWERNOTIFY { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HPOWERNOTIFY { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = UnregisterPowerSettingNotification(*self); + } + } +} impl Default for HPOWERNOTIFY { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/System/Registry/mod.rs b/crates/libs/windows/src/Windows/Win32/System/Registry/mod.rs index a0a14b2d08..49607573c7 100644 --- a/crates/libs/windows/src/Windows/Win32/System/Registry/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/System/Registry/mod.rs @@ -1997,6 +1997,13 @@ impl HKEY { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HKEY { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = RegCloseKey(*self); + } + } +} impl Default for HKEY { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/System/StationsAndDesktops/mod.rs b/crates/libs/windows/src/Windows/Win32/System/StationsAndDesktops/mod.rs index b952daf6b0..3de9c9d630 100644 --- a/crates/libs/windows/src/Windows/Win32/System/StationsAndDesktops/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/System/StationsAndDesktops/mod.rs @@ -471,6 +471,13 @@ impl HDESK { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HDESK { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = CloseDesktop(*self); + } + } +} impl Default for HDESK { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -498,6 +505,13 @@ impl HWINSTA { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HWINSTA { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = CloseWindowStation(*self); + } + } +} impl Default for HWINSTA { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/UI/Accessibility/mod.rs b/crates/libs/windows/src/Windows/Win32/UI/Accessibility/mod.rs index 372d1d343c..e5e7c3f18e 100644 --- a/crates/libs/windows/src/Windows/Win32/UI/Accessibility/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/UI/Accessibility/mod.rs @@ -9767,6 +9767,13 @@ impl HWINEVENTHOOK { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HWINEVENTHOOK { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = UnhookWinEvent(*self); + } + } +} impl Default for HWINEVENTHOOK { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/UI/ColorSystem/mod.rs b/crates/libs/windows/src/Windows/Win32/UI/ColorSystem/mod.rs index a30fe2f0ce..aab42fe2a3 100644 --- a/crates/libs/windows/src/Windows/Win32/UI/ColorSystem/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/UI/ColorSystem/mod.rs @@ -1901,6 +1901,13 @@ impl HCOLORSPACE { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HCOLORSPACE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = DeleteColorSpace(*self); + } + } +} impl Default for HCOLORSPACE { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/UI/Controls/mod.rs b/crates/libs/windows/src/Windows/Win32/UI/Controls/mod.rs index cf818f36a7..9121ef8976 100644 --- a/crates/libs/windows/src/Windows/Win32/UI/Controls/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/UI/Controls/mod.rs @@ -12586,6 +12586,13 @@ impl HIMAGELIST { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HIMAGELIST { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = ImageList_Destroy(*self); + } + } +} impl Default for HIMAGELIST { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -12613,6 +12620,13 @@ impl HPROPSHEETPAGE { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HPROPSHEETPAGE { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = DestroyPropertySheetPage(*self); + } + } +} impl Default for HPROPSHEETPAGE { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -12667,6 +12681,13 @@ impl HTHEME { self.0 == 0 } } +impl windows_core::Free for HTHEME { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = CloseThemeData(*self); + } + } +} impl Default for HTHEME { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/libs/windows/src/Windows/Win32/UI/WindowsAndMessaging/mod.rs b/crates/libs/windows/src/Windows/Win32/UI/WindowsAndMessaging/mod.rs index dfbdf0b8ec..c68fdcfdd8 100644 --- a/crates/libs/windows/src/Windows/Win32/UI/WindowsAndMessaging/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/UI/WindowsAndMessaging/mod.rs @@ -8812,6 +8812,13 @@ impl HACCEL { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HACCEL { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = DestroyAcceleratorTable(*self); + } + } +} impl Default for HACCEL { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -8871,6 +8878,13 @@ impl HCURSOR { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HCURSOR { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = DestroyCursor(*self); + } + } +} impl Default for HCURSOR { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -8904,6 +8918,13 @@ impl HDEVNOTIFY { self.0.is_null() } } +impl windows_core::Free for HDEVNOTIFY { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = UnregisterDeviceNotification(*self); + } + } +} impl Default for HDEVNOTIFY { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -8958,6 +8979,13 @@ impl HHOOK { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HHOOK { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = UnhookWindowsHookEx(*self); + } + } +} impl Default for HHOOK { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -8985,6 +9013,13 @@ impl HICON { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HICON { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = DestroyIcon(*self); + } + } +} impl Default for HICON { fn default() -> Self { unsafe { core::mem::zeroed() } @@ -9012,6 +9047,13 @@ impl HMENU { self.0 == -1 || self.0 == 0 } } +impl windows_core::Free for HMENU { + unsafe fn free(&mut self) { + if !self.is_invalid() { + _ = DestroyMenu(*self); + } + } +} impl Default for HMENU { fn default() -> Self { unsafe { core::mem::zeroed() } diff --git a/crates/samples/windows/kernel_event/src/main.rs b/crates/samples/windows/kernel_event/src/main.rs index 0a818e0f2f..b08d9e5666 100644 --- a/crates/samples/windows/kernel_event/src/main.rs +++ b/crates/samples/windows/kernel_event/src/main.rs @@ -1,13 +1,13 @@ use windows::{ - Win32::Foundation::CloseHandle, + core::Owned, Win32::System::Threading::{CreateEventW, SetEvent, WaitForSingleObject}, }; fn main() -> windows::core::Result<()> { unsafe { - let event = CreateEventW(None, true, false, None)?; - SetEvent(event)?; - WaitForSingleObject(event, 0); - CloseHandle(event) + let event = Owned::new(CreateEventW(None, true, false, None)?); + SetEvent(*event)?; + WaitForSingleObject(*event, 0); } + Ok(()) } diff --git a/crates/samples/windows/overlapped/src/main.rs b/crates/samples/windows/overlapped/src/main.rs index 630a5a64ee..93879acccd 100644 --- a/crates/samples/windows/overlapped/src/main.rs +++ b/crates/samples/windows/overlapped/src/main.rs @@ -10,7 +10,7 @@ fn main() -> Result<()> { let mut string = filename.as_path().to_str().unwrap().to_owned(); string.push('\0'); - let file = CreateFileA( + let file = Owned::new(CreateFileA( PCSTR(string.as_ptr()), // See: https://github.com/microsoft/win32metadata/issues/1457 FILE_GENERIC_READ.0, @@ -19,7 +19,7 @@ fn main() -> Result<()> { OPEN_EXISTING, FILE_FLAG_OVERLAPPED, None, - )?; + )?); let mut overlapped = OVERLAPPED { Anonymous: OVERLAPPED_0 { @@ -35,18 +35,16 @@ fn main() -> Result<()> { let mut buffer: [u8; 12] = Default::default(); - if let Err(error) = ReadFile(file, Some(&mut buffer), None, Some(&mut overlapped)) { + if let Err(error) = ReadFile(*file, Some(&mut buffer), None, Some(&mut overlapped)) { assert_eq!(error.code(), ERROR_IO_PENDING.into()); } WaitForSingleObject(overlapped.hEvent, 2000); let mut bytes_copied = 0; - GetOverlappedResult(file, &overlapped, &mut bytes_copied, false)?; + GetOverlappedResult(*file, &overlapped, &mut bytes_copied, false)?; assert!(bytes_copied == 12); - CloseHandle(file)?; - println!("{}", String::from_utf8_lossy(&buffer)); } diff --git a/crates/samples/windows/privileges/src/main.rs b/crates/samples/windows/privileges/src/main.rs index 4ba4c753bf..b09952d9ed 100644 --- a/crates/samples/windows/privileges/src/main.rs +++ b/crates/samples/windows/privileges/src/main.rs @@ -11,7 +11,7 @@ fn main() -> Result<()> { let mut bytes_required = 0; _ = GetTokenInformation(token, TokenPrivileges, None, 0, &mut bytes_required); - let buffer = LocalAlloc(LPTR, bytes_required as usize)?; + let buffer = Owned::new(LocalAlloc(LPTR, bytes_required as usize)?); GetTokenInformation( token, @@ -37,7 +37,6 @@ fn main() -> Result<()> { println!("{}", name.display()) } - LocalFree(buffer); Ok(()) } } diff --git a/crates/tests/bcrypt/tests/win.rs b/crates/tests/bcrypt/tests/win.rs index 038f7a2fec..832cc11672 100644 --- a/crates/tests/bcrypt/tests/win.rs +++ b/crates/tests/bcrypt/tests/win.rs @@ -3,18 +3,18 @@ use windows::{core::*, Win32::Security::Cryptography::*}; #[test] fn test() -> Result<()> { unsafe { - let mut rng = Default::default(); - BCryptOpenAlgorithmProvider(&mut rng, BCRYPT_RNG_ALGORITHM, None, Default::default()) + let mut rng = Owned::default(); + BCryptOpenAlgorithmProvider(&mut *rng, BCRYPT_RNG_ALGORITHM, None, Default::default()) .ok()?; - let mut des = Default::default(); - BCryptOpenAlgorithmProvider(&mut des, BCRYPT_3DES_ALGORITHM, None, Default::default()) + let mut des = Owned::default(); + BCryptOpenAlgorithmProvider(&mut *des, BCRYPT_3DES_ALGORITHM, None, Default::default()) .ok()?; let mut object_len = [0; 4]; let mut bytes_copied = 0; BCryptGetProperty( - des, + *des, BCRYPT_OBJECT_LENGTH, Some(&mut object_len), &mut bytes_copied, @@ -24,14 +24,14 @@ fn test() -> Result<()> { let object_len = u32::from_le_bytes(object_len); let mut shared_secret = vec![0; object_len as usize]; - BCryptGenRandom(rng, &mut shared_secret, Default::default()).ok()?; + BCryptGenRandom(*rng, &mut shared_secret, Default::default()).ok()?; - let mut encrypt_key = Default::default(); - BCryptGenerateSymmetricKey(des, &mut encrypt_key, None, &shared_secret, 0).ok()?; + let mut encrypt_key = Owned::default(); + BCryptGenerateSymmetricKey(*des, &mut *encrypt_key, None, &shared_secret, 0).ok()?; let mut block_len = [0; 4]; BCryptGetProperty( - des, + *des, BCRYPT_BLOCK_LENGTH, Some(&mut block_len), &mut bytes_copied, @@ -47,7 +47,7 @@ fn test() -> Result<()> { let mut encrypted_len = 0; BCryptEncrypt( - encrypt_key, + *encrypt_key, Some(&send_buffer), None, None, @@ -59,7 +59,7 @@ fn test() -> Result<()> { let mut encrypted = vec![0; encrypted_len as usize]; BCryptEncrypt( - encrypt_key, + *encrypt_key, Some(&send_buffer), None, None, @@ -69,12 +69,12 @@ fn test() -> Result<()> { ) .ok()?; - let mut decrypt_key = Default::default(); - BCryptGenerateSymmetricKey(des, &mut decrypt_key, None, &shared_secret, 0).ok()?; + let mut decrypt_key = Owned::default(); + BCryptGenerateSymmetricKey(*des, &mut *decrypt_key, None, &shared_secret, 0).ok()?; let mut decrypted_len = 0; BCryptDecrypt( - decrypt_key, + *decrypt_key, Some(&encrypted), None, None, @@ -86,7 +86,7 @@ fn test() -> Result<()> { let mut decrypted = vec![0; decrypted_len as usize]; BCryptDecrypt( - decrypt_key, + *decrypt_key, Some(&encrypted), None, None, @@ -100,6 +100,7 @@ fn test() -> Result<()> { std::str::from_utf8(trim_null_end(&decrypted)).expect("Not a valid message"); assert_eq!(send_message, receive_message); } + Ok(()) }