From 92caf841f1e0dbb9dec2896a2ee86349f747c84a Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Wed, 11 May 2022 12:18:57 +0200 Subject: [PATCH] Free implementation in alloc if querying fails --- crates/libs/implement/src/lib.rs | 11 ++++++++--- crates/tests/nightly_implement/tests/com.rs | 1 - 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/libs/implement/src/lib.rs b/crates/libs/implement/src/lib.rs index 9aed2215d5..33c95ee52d 100644 --- a/crates/libs/implement/src/lib.rs +++ b/crates/libs/implement/src/lib.rs @@ -144,13 +144,18 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro: } } impl <#constraints> #original_ident::<#(#generics,)*> { - fn alloc(self) -> ::windows::core::Result { + fn alloc(self) -> ::windows::core::Result { let this = #impl_ident::<#(#generics,)*>::new(self); let boxed = ::core::mem::ManuallyDrop::new(::std::boxed::Box::new(this)); let mut result = None; - unsafe { - <#impl_ident::<#(#generics,)*> as ::windows::core::IUnknownImpl>::QueryInterface(&*boxed, &ResultType::IID, &mut result as *mut _ as _).and_some(result) + let result = unsafe { + <#impl_ident::<#(#generics,)*> as ::windows::core::IUnknownImpl>::QueryInterface(&*boxed, &I::IID, &mut result as *mut _ as _).and_some(result) + }; + // If querying for the supplied interface fails, we must free the underlying implementation, otherwise that memory will be leaked + if result.is_err() { + let _ = ::core::mem::ManuallyDrop::into_inner(boxed); } + result } } impl <#constraints> ::windows::core::Compose for #original_ident::<#(#generics,)*> { diff --git a/crates/tests/nightly_implement/tests/com.rs b/crates/tests/nightly_implement/tests/com.rs index 8d85f4c6af..8e993d3d21 100644 --- a/crates/tests/nightly_implement/tests/com.rs +++ b/crates/tests/nightly_implement/tests/com.rs @@ -52,6 +52,5 @@ fn mix() -> Result<()> { let f: IStringable = Mix.alloc()?; assert!(f.ToString()? == "Mix"); - Ok(()) }