diff --git a/crates/gen/src/function.rs b/crates/gen/src/function.rs index a355d5de1c..c1e8293cdc 100644 --- a/crates/gen/src/function.rs +++ b/crates/gen/src/function.rs @@ -5,28 +5,78 @@ use squote::{quote, TokenStream}; pub struct Function { pub name: TypeName, pub method: winmd::MethodDef, + pub params: Vec<(&'static str, Type)>, + pub return_type: Option, } impl Function { pub fn new(name: TypeName, method: &winmd::MethodDef) -> Self { + let mut blob = method.sig(); + + if blob.read_unsigned() & 0x10 != 0 { + blob.read_unsigned(); + } + + let param_count = blob.read_unsigned(); + blob.read_modifiers(); + blob.read_expected(0x10); + + let mut params = Vec::with_capacity(param_count as usize); + + let return_type = if blob.read_expected(0x01) { + None + } else { + Some(Type::from_blob(&mut blob, &[], name.namespace)) + }; + + for param in method.params() { + if return_type.is_none() || param.sequence() != 0 { + blob.read_modifiers(); // const + blob.read_expected(0x10); // ref + params.push(( + param.name(), + Type::from_blob(&mut blob, &[], name.namespace), + )); + } + } + Self { name, method: *method, + params, + return_type, } } pub fn gen(&self) -> TokenStream { let name = format_ident(self.method.name()); + let return_type = if let Some(t) = &self.return_type { + let tokens = t.gen_field(); + quote! { -> #tokens } + } else { + TokenStream::new() + }; + + let params = self.params.iter().map(|(name, t)| { + let name = format_ident(name); + let tokens = t.gen_field(); + quote! { #name: #tokens } + }); + quote! { #[link(name = "onecoreuap")] extern "system" { - pub fn #name(); + pub fn #name(#(#params),*) #return_type; } } } pub fn dependencies(&self) -> Vec { - Vec::new() + self.return_type + .iter() + .chain(self.params.iter().map(|(_, t)| t)) + .flat_map(|t| t.kind.dependencies()) + .collect() } } diff --git a/crates/tests/build.rs b/crates/tests/build.rs index 79df5208b1..d3645b9ac0 100644 --- a/crates/tests/build.rs +++ b/crates/tests/build.rs @@ -33,7 +33,8 @@ fn main() { windows::win32::{ ACCESS_MODE, CHOOSECOLORW, DXGI_ADAPTER_FLAG, DXGI_FORMAT, DXGI_MODE_DESC, DXGI_MODE_SCALING, DXGI_MODE_SCANLINE_ORDER, DXGI_RATIONAL, RECT, WM_KEYUP, ALLJOYN_BIG_ENDIAN, ALLJOYN_CRED_CERT_CHAIN, - D3D12_DEFAULT_BLEND_FACTOR_ALPHA, UIA_ScrollPatternNoScroll, D3DCOMPILER_DLL + D3D12_DEFAULT_BLEND_FACTOR_ALPHA, UIA_ScrollPatternNoScroll, D3DCOMPILER_DLL, + CreateEventW, SetEvent, WaitForSingleObject, CloseHandle } ); } diff --git a/crates/tests/tests/win32.rs b/crates/tests/tests/win32.rs index 92ffbd1d3d..f772d75ee9 100644 --- a/crates/tests/tests/win32.rs +++ b/crates/tests/tests/win32.rs @@ -1,8 +1,8 @@ use tests::windows::win32::{ - UIA_ScrollPatternNoScroll, ACCESS_MODE, ALLJOYN_BIG_ENDIAN, ALLJOYN_CRED_CERT_CHAIN, - CHOOSECOLORW, D3D12_DEFAULT_BLEND_FACTOR_ALPHA, D3DCOMPILER_DLL, DXGI_ADAPTER_FLAG, - DXGI_FORMAT, DXGI_MODE_DESC, DXGI_MODE_SCALING, DXGI_MODE_SCANLINE_ORDER, DXGI_RATIONAL, RECT, - WM_KEYUP, + CloseHandle, CreateEventW, SetEvent, UIA_ScrollPatternNoScroll, WaitForSingleObject, + ACCESS_MODE, ALLJOYN_BIG_ENDIAN, ALLJOYN_CRED_CERT_CHAIN, CHOOSECOLORW, + D3D12_DEFAULT_BLEND_FACTOR_ALPHA, D3DCOMPILER_DLL, DXGI_ADAPTER_FLAG, DXGI_FORMAT, + DXGI_MODE_DESC, DXGI_MODE_SCALING, DXGI_MODE_SCANLINE_ORDER, DXGI_RATIONAL, RECT, WM_KEYUP, }; use winrt::Abi; @@ -96,3 +96,20 @@ fn constant() { assert!(UIA_ScrollPatternNoScroll == -1f64); assert!(D3DCOMPILER_DLL == "d3dcompiler_47.dll"); } + +#[test] +fn function() { + unsafe { + let event = CreateEventW(std::ptr::null_mut(), 1, 0, std::ptr::null_mut()); + assert!(event != 0); + + let result = SetEvent(event); + assert!(result != 0); + + let result = WaitForSingleObject(event, 0); + assert!(result == 0); // https://github.com/microsoft/win32metadata/issues/77 + + let result = CloseHandle(event); + assert!(result != 0); + } +} diff --git a/crates/winmd/src/parsed/param.rs b/crates/winmd/src/parsed/param.rs index c8376608be..e92296cef0 100644 --- a/crates/winmd/src/parsed/param.rs +++ b/crates/winmd/src/parsed/param.rs @@ -16,7 +16,7 @@ impl Param { self.reader.u32(self.row, 1) } - pub fn name(&self) -> &str { + pub fn name(&self) -> &'static str { self.reader.str(self.row, 2) } }