From 4b07540a24463471d87444ea639eb7b94ab4ebed Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 31 Aug 2022 13:01:16 -0700 Subject: [PATCH] Make `BOOL`, `BOOLEAN`, and `NTSTATUS` extensions rather than replacements (#1995) --- .github/workflows/build.yml | 2 +- .github/workflows/test.yml | 2 +- .../{replacements => extensions}/bool32.rs | 53 +----- crates/libs/bindgen/src/extensions/boolean.rs | 74 ++++++++ crates/libs/bindgen/src/extensions/mod.rs | 6 + .../{replacements => extensions}/ntstatus.rs | 22 --- crates/libs/bindgen/src/handles.rs | 1 + crates/libs/bindgen/src/replacements/mod.rs | 4 - crates/libs/metadata/src/reader/type_name.rs | 1 + .../src/Windows/Win32/Foundation/mod.rs | 169 +++++++++++++----- crates/tests/error/tests/test.rs | 4 +- .../tests/{ntstatus => extensions}/Cargo.toml | 2 +- .../tests/{ntstatus => extensions}/src/lib.rs | 0 crates/tests/extensions/tests/bool32.rs | 23 +++ crates/tests/extensions/tests/boolean.rs | 23 +++ .../tests/ntstatus.rs | 0 16 files changed, 258 insertions(+), 128 deletions(-) rename crates/libs/bindgen/src/{replacements => extensions}/bool32.rs (65%) create mode 100644 crates/libs/bindgen/src/extensions/boolean.rs rename crates/libs/bindgen/src/{replacements => extensions}/ntstatus.rs (60%) rename crates/tests/{ntstatus => extensions}/Cargo.toml (88%) rename crates/tests/{ntstatus => extensions}/src/lib.rs (100%) create mode 100644 crates/tests/extensions/tests/bool32.rs create mode 100644 crates/tests/extensions/tests/boolean.rs rename crates/tests/{ntstatus => extensions}/tests/ntstatus.rs (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 04f1bfa49b..5945cde060 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -155,6 +155,7 @@ jobs: cargo clippy -p test_enums && cargo clippy -p test_error && cargo clippy -p test_event && + cargo clippy -p test_extensions && cargo clippy -p test_handles && cargo clippy -p test_helpers && cargo clippy -p test_identity && @@ -169,7 +170,6 @@ jobs: cargo clippy -p test_metadata && cargo clippy -p test_no_use && cargo clippy -p test_not_dll && - cargo clippy -p test_ntstatus && cargo clippy -p test_properties && cargo clippy -p test_query_signature && cargo clippy -p test_return_struct && diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e3dcc655be..af47ba18ac 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -139,6 +139,7 @@ jobs: cargo test --target ${{ matrix.target }} -p test_enums && cargo test --target ${{ matrix.target }} -p test_error && cargo test --target ${{ matrix.target }} -p test_event && + cargo test --target ${{ matrix.target }} -p test_extensions && cargo test --target ${{ matrix.target }} -p test_handles && cargo test --target ${{ matrix.target }} -p test_helpers && cargo test --target ${{ matrix.target }} -p test_identity && @@ -153,7 +154,6 @@ jobs: cargo test --target ${{ matrix.target }} -p test_metadata && cargo test --target ${{ matrix.target }} -p test_no_use && cargo test --target ${{ matrix.target }} -p test_not_dll && - cargo test --target ${{ matrix.target }} -p test_ntstatus && cargo test --target ${{ matrix.target }} -p test_properties && cargo test --target ${{ matrix.target }} -p test_query_signature && cargo test --target ${{ matrix.target }} -p test_return_struct && diff --git a/crates/libs/bindgen/src/replacements/bool32.rs b/crates/libs/bindgen/src/extensions/bool32.rs similarity index 65% rename from crates/libs/bindgen/src/replacements/bool32.rs rename to crates/libs/bindgen/src/extensions/bool32.rs index e18f5bed96..f4a3b95af4 100644 --- a/crates/libs/bindgen/src/replacements/bool32.rs +++ b/crates/libs/bindgen/src/extensions/bool32.rs @@ -2,15 +2,11 @@ use super::*; pub fn gen() -> TokenStream { quote! { - #[repr(transparent)] - pub struct BOOL(pub i32); - impl BOOL { #[inline] pub fn as_bool(self) -> bool { self.0 != 0 } - #[inline] pub fn ok(self) -> ::windows::core::Result<()> { if self.as_bool() { @@ -19,101 +15,60 @@ pub fn gen() -> TokenStream { Err(::windows::core::Error::from_win32()) } } - #[inline] #[track_caller] pub fn unwrap(self) { self.ok().unwrap(); } - #[inline] #[track_caller] pub fn expect(self, msg: &str) { self.ok().expect(msg); } } - - impl ::core::default::Default for BOOL { - fn default() -> Self { - Self(0) - } - } - - impl ::core::clone::Clone for BOOL { - fn clone(&self) -> Self { - *self - } - } - - impl ::core::marker::Copy for BOOL {} - - impl ::core::cmp::PartialEq for BOOL { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } - } - - impl ::core::cmp::Eq for BOOL {} - - impl ::core::fmt::Debug for BOOL { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - f.debug_tuple("BOOL").field(&self.0).finish() - } - } - impl ::core::convert::From for bool { fn from(value: BOOL) -> Self { value.as_bool() } } - impl ::core::convert::From<&BOOL> for bool { fn from(value: &BOOL) -> Self { value.as_bool() } } - impl ::core::convert::From for BOOL { fn from(value: bool) -> Self { if value { - BOOL(1) + Self(1) } else { - BOOL(0) + Self(0) } } } - impl ::core::convert::From<&bool> for BOOL { fn from(value: &bool) -> Self { (*value).into() } } - impl ::core::cmp::PartialEq for BOOL { fn eq(&self, other: &bool) -> bool { self.as_bool() == *other } } - impl ::core::cmp::PartialEq for bool { fn eq(&self, other: &BOOL) -> bool { *self == other.as_bool() } } - impl ::core::ops::Not for BOOL { type Output = Self; fn not(self) -> Self::Output { if self.as_bool() { - BOOL(0) + Self(0) } else { - BOOL(1) + Self(1) } } } - - unsafe impl ::windows::core::Abi for BOOL { - type Abi = Self; - } } } diff --git a/crates/libs/bindgen/src/extensions/boolean.rs b/crates/libs/bindgen/src/extensions/boolean.rs new file mode 100644 index 0000000000..daf9683782 --- /dev/null +++ b/crates/libs/bindgen/src/extensions/boolean.rs @@ -0,0 +1,74 @@ +use super::*; + +pub fn gen() -> TokenStream { + quote! { + impl BOOLEAN { + #[inline] + pub fn as_bool(self) -> bool { + self.0 != 0 + } + #[inline] + pub fn ok(self) -> ::windows::core::Result<()> { + if self.as_bool() { + Ok(()) + } else { + Err(::windows::core::Error::from_win32()) + } + } + #[inline] + #[track_caller] + pub fn unwrap(self) { + self.ok().unwrap(); + } + #[inline] + #[track_caller] + pub fn expect(self, msg: &str) { + self.ok().expect(msg); + } + } + impl ::core::convert::From for bool { + fn from(value: BOOLEAN) -> Self { + value.as_bool() + } + } + impl ::core::convert::From<&BOOLEAN> for bool { + fn from(value: &BOOLEAN) -> Self { + value.as_bool() + } + } + impl ::core::convert::From for BOOLEAN { + fn from(value: bool) -> Self { + if value { + Self(1) + } else { + Self(0) + } + } + } + impl ::core::convert::From<&bool> for BOOLEAN { + fn from(value: &bool) -> Self { + (*value).into() + } + } + impl ::core::cmp::PartialEq for BOOLEAN { + fn eq(&self, other: &bool) -> bool { + self.as_bool() == *other + } + } + impl ::core::cmp::PartialEq for bool { + fn eq(&self, other: &BOOLEAN) -> bool { + *self == other.as_bool() + } + } + impl ::core::ops::Not for BOOLEAN { + type Output = Self; + fn not(self) -> Self::Output { + if self.as_bool() { + Self(0) + } else { + Self(1) + } + } + } + } +} diff --git a/crates/libs/bindgen/src/extensions/mod.rs b/crates/libs/bindgen/src/extensions/mod.rs index fccfed298d..7011206451 100644 --- a/crates/libs/bindgen/src/extensions/mod.rs +++ b/crates/libs/bindgen/src/extensions/mod.rs @@ -1,8 +1,11 @@ use super::*; +mod bool32; +mod boolean; mod in6_addr; mod in_addr; mod matrix3x2; mod matrix4x4; +mod ntstatus; mod sockaddr_in; mod sockaddr_in6; mod sockaddr_inet; @@ -14,10 +17,13 @@ mod win32_error; pub fn gen(type_name: TypeName) -> TokenStream { match type_name { + TypeName::BOOL => bool32::gen(), + TypeName::BOOLEAN => boolean::gen(), TypeName::IN_ADDR => in_addr::gen(), TypeName::IN6_ADDR => in6_addr::gen(), TypeName::Matrix3x2 => matrix3x2::gen(), TypeName::Matrix4x4 => matrix4x4::gen(), + TypeName::NTSTATUS => ntstatus::gen(), TypeName::SOCKADDR_IN => sockaddr_in::gen(), TypeName::SOCKADDR_IN6 => sockaddr_in6::gen(), TypeName::SOCKADDR_INET => sockaddr_inet::gen(), diff --git a/crates/libs/bindgen/src/replacements/ntstatus.rs b/crates/libs/bindgen/src/extensions/ntstatus.rs similarity index 60% rename from crates/libs/bindgen/src/replacements/ntstatus.rs rename to crates/libs/bindgen/src/extensions/ntstatus.rs index 2899ce25be..5c578bf16e 100644 --- a/crates/libs/bindgen/src/replacements/ntstatus.rs +++ b/crates/libs/bindgen/src/extensions/ntstatus.rs @@ -2,9 +2,6 @@ use super::*; pub fn gen() -> TokenStream { quote! { - #[repr(transparent)] - #[derive(::core::cmp::PartialEq, ::core::cmp::Eq)] - pub struct NTSTATUS(pub i32); impl NTSTATUS { #[inline] pub const fn is_ok(self) -> bool { @@ -37,24 +34,5 @@ pub fn gen() -> TokenStream { Self{ code: value.to_hresult(), info: None } } } - impl ::core::default::Default for NTSTATUS { - fn default() -> Self { - Self(0) - } - } - impl ::core::clone::Clone for NTSTATUS { - fn clone(&self) -> Self { - *self - } - } - impl ::core::marker::Copy for NTSTATUS {} - impl ::core::fmt::Debug for NTSTATUS { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - f.write_fmt(format_args!("NTSTATUS(0x{:08X})", self.0)) - } - } - unsafe impl ::windows::core::Abi for NTSTATUS { - type Abi = Self; - } } } diff --git a/crates/libs/bindgen/src/handles.rs b/crates/libs/bindgen/src/handles.rs index 183bae0fdd..31689d8ac7 100644 --- a/crates/libs/bindgen/src/handles.rs +++ b/crates/libs/bindgen/src/handles.rs @@ -101,5 +101,6 @@ pub fn gen_win_handle(gen: &Gen, def: TypeDef) -> TokenStream { }); } + tokens.combine(&extensions::gen(gen.reader.type_def_type_name(def))); tokens } diff --git a/crates/libs/bindgen/src/replacements/mod.rs b/crates/libs/bindgen/src/replacements/mod.rs index 961859dad9..00c7968dc4 100644 --- a/crates/libs/bindgen/src/replacements/mod.rs +++ b/crates/libs/bindgen/src/replacements/mod.rs @@ -1,13 +1,9 @@ use super::*; -mod bool32; mod bstr; -mod ntstatus; pub fn gen(type_name: TypeName) -> Option { match type_name { - TypeName::BOOL => Some(bool32::gen()), TypeName::BSTR => Some(bstr::gen()), - TypeName::NTSTATUS => Some(ntstatus::gen()), _ => None, } } diff --git a/crates/libs/metadata/src/reader/type_name.rs b/crates/libs/metadata/src/reader/type_name.rs index c035b3c8bf..3f5bc29962 100644 --- a/crates/libs/metadata/src/reader/type_name.rs +++ b/crates/libs/metadata/src/reader/type_name.rs @@ -37,6 +37,7 @@ impl<'a> TypeName<'a> { pub const WIN32_ERROR: Self = Self::from_const("Windows.Win32.Foundation", "WIN32_ERROR"); pub const NTSTATUS: Self = Self::from_const("Windows.Win32.Foundation", "NTSTATUS"); pub const BOOL: Self = Self::from_const("Windows.Win32.Foundation", "BOOL"); + pub const BOOLEAN: Self = Self::from_const("Windows.Win32.Foundation", "BOOLEAN"); pub const PWSTR: Self = Self::from_const("Windows.Win32.Foundation", "PWSTR"); pub const PSTR: Self = Self::from_const("Windows.Win32.Foundation", "PSTR"); pub const BSTR: Self = Self::from_const("Windows.Win32.Foundation", "BSTR"); diff --git a/crates/libs/windows/src/Windows/Win32/Foundation/mod.rs b/crates/libs/windows/src/Windows/Win32/Foundation/mod.rs index 07215c2b9b..ff8e637888 100644 --- a/crates/libs/windows/src/Windows/Win32/Foundation/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/Foundation/mod.rs @@ -97,7 +97,32 @@ impl ::core::default::Default for APP_LOCAL_DEVICE_ID { #[doc = "*Required features: `\"Win32_Foundation\"`*"] pub const APP_LOCAL_DEVICE_ID_SIZE: u32 = 32u32; #[repr(transparent)] +#[derive(::core::cmp::PartialEq, ::core::cmp::Eq)] pub struct BOOL(pub i32); +impl ::core::default::Default for BOOL { + fn default() -> Self { + unsafe { ::core::mem::zeroed() } + } +} +impl ::core::clone::Clone for BOOL { + fn clone(&self) -> Self { + *self + } +} +impl ::core::marker::Copy for BOOL {} +impl ::core::fmt::Debug for BOOL { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple("BOOL").field(&self.0).finish() + } +} +impl ::core::convert::From<::core::option::Option> for BOOL { + fn from(optional: ::core::option::Option) -> BOOL { + optional.unwrap_or_default() + } +} +unsafe impl ::windows::core::Abi for BOOL { + type Abi = Self; +} impl BOOL { #[inline] pub fn as_bool(self) -> bool { @@ -122,28 +147,6 @@ impl BOOL { self.ok().expect(msg); } } -impl ::core::default::Default for BOOL { - fn default() -> Self { - Self(0) - } -} -impl ::core::clone::Clone for BOOL { - fn clone(&self) -> Self { - *self - } -} -impl ::core::marker::Copy for BOOL {} -impl ::core::cmp::PartialEq for BOOL { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} -impl ::core::cmp::Eq for BOOL {} -impl ::core::fmt::Debug for BOOL { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - f.debug_tuple("BOOL").field(&self.0).finish() - } -} impl ::core::convert::From for bool { fn from(value: BOOL) -> Self { value.as_bool() @@ -157,9 +160,9 @@ impl ::core::convert::From<&BOOL> for bool { impl ::core::convert::From for BOOL { fn from(value: bool) -> Self { if value { - BOOL(1) + Self(1) } else { - BOOL(0) + Self(0) } } } @@ -182,15 +185,12 @@ impl ::core::ops::Not for BOOL { type Output = Self; fn not(self) -> Self::Output { if self.as_bool() { - BOOL(0) + Self(0) } else { - BOOL(1) + Self(1) } } } -unsafe impl ::windows::core::Abi for BOOL { - type Abi = Self; -} #[repr(transparent)] #[derive(::core::cmp::PartialEq, ::core::cmp::Eq)] pub struct BOOLEAN(pub u8); @@ -218,6 +218,74 @@ impl ::core::convert::From<::core::option::Option> for BOOLEAN { unsafe impl ::windows::core::Abi for BOOLEAN { type Abi = Self; } +impl BOOLEAN { + #[inline] + pub fn as_bool(self) -> bool { + self.0 != 0 + } + #[inline] + pub fn ok(self) -> ::windows::core::Result<()> { + if self.as_bool() { + Ok(()) + } else { + Err(::windows::core::Error::from_win32()) + } + } + #[inline] + #[track_caller] + pub fn unwrap(self) { + self.ok().unwrap(); + } + #[inline] + #[track_caller] + pub fn expect(self, msg: &str) { + self.ok().expect(msg); + } +} +impl ::core::convert::From for bool { + fn from(value: BOOLEAN) -> Self { + value.as_bool() + } +} +impl ::core::convert::From<&BOOLEAN> for bool { + fn from(value: &BOOLEAN) -> Self { + value.as_bool() + } +} +impl ::core::convert::From for BOOLEAN { + fn from(value: bool) -> Self { + if value { + Self(1) + } else { + Self(0) + } + } +} +impl ::core::convert::From<&bool> for BOOLEAN { + fn from(value: &bool) -> Self { + (*value).into() + } +} +impl ::core::cmp::PartialEq for BOOLEAN { + fn eq(&self, other: &bool) -> bool { + self.as_bool() == *other + } +} +impl ::core::cmp::PartialEq for bool { + fn eq(&self, other: &BOOLEAN) -> bool { + *self == other.as_bool() + } +} +impl ::core::ops::Not for BOOLEAN { + type Output = Self; + fn not(self) -> Self::Output { + if self.as_bool() { + Self(0) + } else { + Self(1) + } + } +} #[repr(transparent)] pub struct BSTR(*const u16); impl BSTR { @@ -5027,6 +5095,30 @@ pub const NTE_VALIDATION_FAILED: ::windows::core::HRESULT = ::windows::core::HRE #[repr(transparent)] #[derive(::core::cmp::PartialEq, ::core::cmp::Eq)] pub struct NTSTATUS(pub i32); +impl ::core::default::Default for NTSTATUS { + fn default() -> Self { + unsafe { ::core::mem::zeroed() } + } +} +impl ::core::clone::Clone for NTSTATUS { + fn clone(&self) -> Self { + *self + } +} +impl ::core::marker::Copy for NTSTATUS {} +impl ::core::fmt::Debug for NTSTATUS { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple("NTSTATUS").field(&self.0).finish() + } +} +impl ::core::convert::From<::core::option::Option> for NTSTATUS { + fn from(optional: ::core::option::Option) -> NTSTATUS { + optional.unwrap_or_default() + } +} +unsafe impl ::windows::core::Abi for NTSTATUS { + type Abi = Self; +} impl NTSTATUS { #[inline] pub const fn is_ok(self) -> bool { @@ -5059,25 +5151,6 @@ impl ::core::convert::From for ::windows::core::Error { Self { code: value.to_hresult(), info: None } } } -impl ::core::default::Default for NTSTATUS { - fn default() -> Self { - Self(0) - } -} -impl ::core::clone::Clone for NTSTATUS { - fn clone(&self) -> Self { - *self - } -} -impl ::core::marker::Copy for NTSTATUS {} -impl ::core::fmt::Debug for NTSTATUS { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - f.write_fmt(format_args!("NTSTATUS(0x{:08X})", self.0)) - } -} -unsafe impl ::windows::core::Abi for NTSTATUS { - type Abi = Self; -} #[doc = "*Required features: `\"Win32_Foundation\"`*"] #[repr(transparent)] #[derive(::core::cmp::PartialEq, ::core::cmp::Eq)] diff --git a/crates/tests/error/tests/test.rs b/crates/tests/error/tests/test.rs index d4aa09326d..9831bb321b 100644 --- a/crates/tests/error/tests/test.rs +++ b/crates/tests/error/tests/test.rs @@ -51,8 +51,8 @@ fn ntstatus() -> Result<()> { assert_eq!(STATUS_SUCCESS.is_ok(), true); assert_eq!(STATUS_SUCCESS.is_err(), false); - assert_eq!(format!("{:?}", STATUS_SUCCESS), "NTSTATUS(0x00000000)"); - assert_eq!(format!("{:?}", STATUS_NOT_FOUND), "NTSTATUS(0xC0000225)"); + assert_eq!(format!("{:?}", STATUS_SUCCESS), "NTSTATUS(0)"); + assert_eq!(format!("{:?}", STATUS_NOT_FOUND), "NTSTATUS(-1073741275)"); STATUS_SUCCESS.ok() } diff --git a/crates/tests/ntstatus/Cargo.toml b/crates/tests/extensions/Cargo.toml similarity index 88% rename from crates/tests/ntstatus/Cargo.toml rename to crates/tests/extensions/Cargo.toml index d25b937b69..022f5356ee 100644 --- a/crates/tests/ntstatus/Cargo.toml +++ b/crates/tests/extensions/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "test_ntstatus" +name = "test_extensions" version = "0.0.0" authors = ["Microsoft"] edition = "2018" diff --git a/crates/tests/ntstatus/src/lib.rs b/crates/tests/extensions/src/lib.rs similarity index 100% rename from crates/tests/ntstatus/src/lib.rs rename to crates/tests/extensions/src/lib.rs diff --git a/crates/tests/extensions/tests/bool32.rs b/crates/tests/extensions/tests/bool32.rs new file mode 100644 index 0000000000..e8cb7aec75 --- /dev/null +++ b/crates/tests/extensions/tests/bool32.rs @@ -0,0 +1,23 @@ +use windows::Win32::Foundation::*; + +#[test] +fn test() { + let status = BOOL::default(); + assert_eq!(status.0, 0); + + let status = BOOL(1); + assert_eq!(status.0, 1); + assert_eq!(status.as_bool(), true); + assert_eq!(status.ok().is_ok(), true); + + unsafe { + SetLastError(ERROR_ACCESS_DENIED); + } + let status = BOOL(0); + assert_eq!(status.0, 0); + assert_eq!(status.as_bool(), false); + let result = status.ok(); + assert_eq!(result.is_ok(), false); + let error = result.unwrap_err(); + assert_eq!(error.code(), E_ACCESSDENIED); +} diff --git a/crates/tests/extensions/tests/boolean.rs b/crates/tests/extensions/tests/boolean.rs new file mode 100644 index 0000000000..6b51866b72 --- /dev/null +++ b/crates/tests/extensions/tests/boolean.rs @@ -0,0 +1,23 @@ +use windows::Win32::Foundation::*; + +#[test] +fn test() { + let status = BOOLEAN::default(); + assert_eq!(status.0, 0); + + let status = BOOLEAN(1); + assert_eq!(status.0, 1); + assert_eq!(status.as_bool(), true); + assert_eq!(status.ok().is_ok(), true); + + unsafe { + SetLastError(ERROR_ACCESS_DENIED); + } + let status = BOOLEAN(0); + assert_eq!(status.0, 0); + assert_eq!(status.as_bool(), false); + let result = status.ok(); + assert_eq!(result.is_ok(), false); + let error = result.unwrap_err(); + assert_eq!(error.code(), E_ACCESSDENIED); +} diff --git a/crates/tests/ntstatus/tests/ntstatus.rs b/crates/tests/extensions/tests/ntstatus.rs similarity index 100% rename from crates/tests/ntstatus/tests/ntstatus.rs rename to crates/tests/extensions/tests/ntstatus.rs