INetFwAuthorizedApplications fails to return _NewEnum and type returned appears incorrect #1317
Open
Description
Actual behavior
Calling the _NewEnum
method on an instance of INetFwAuthorizedApplications
fails with the following exception:
Unhandled exception. System.Runtime.InteropServices.InvalidOleVariantTypeException: Specified OLE variant is invalid.
at System.StubHelpers.ObjectMarshaler.ConvertToManaged(IntPtr pSrcVariant)
at Windows.Win32.NetworkManagement.WindowsFirewall.INetFwAuthorizedApplications.get__NewEnum()
at Fires.Program.Main() in C:\Users\Fots\source\Firewallcs\Program.cs:line 12
The source generated also suggests it returns an object
when I think it should either be IUnknown
(which can be cast to IEnumVARIANT
) or IEnumVARIANT
directly.
This all works perfectly in windows-rs (see below for equivalent code).
Expected behavior
I expect to be able to retrieve the _NewEnum
so I can iterate through the collection.
Repro steps
NativeMethods.txt
content:
INetFwMgr
NetFwMgr
IEnumVARIANT
NetFwAuthorizedApplication
NativeMethods.json
content (if present):
N/A
- Any of your own code that should be shared?
using Windows.Win32.NetworkManagement.WindowsFirewall;
using Windows.Win32.System.Ole;
namespace Firewallcs;
internal class Program
{
static void Main()
{
var fwMgr = (INetFwMgr)new NetFwMgr();
var authorizedApplications = fwMgr.LocalPolicy.CurrentProfile.AuthorizedApplications;
var applicationsEnum = authorizedApplications._NewEnum;
}
}
Here's the equivalent in Rust...
Cargo.toml
[package]
name = "firewall"
version = "0.1.0"
edition = "2021"
[dependencies]
windows-result = "0.2.0"
[dependencies.windows]
version = "0.58.0"
features = [
"Win32_System_Com",
"Win32_System_Ole",
"Win32_NetworkManagement_WindowsFirewall",
]
main.rs
use std::iter;
use windows::{
core::{Interface as _, VARIANT},
Win32::{
NetworkManagement::WindowsFirewall::{INetFwAuthorizedApplication, INetFwMgr, NetFwMgr},
System::{
Com::{CoCreateInstance, CoInitialize, IDispatch, CLSCTX_INPROC_SERVER},
Ole::IEnumVARIANT,
},
},
};
use windows_result::Result;
fn main() -> Result<()> {
unsafe {
CoInitialize(None).ok()?;
let firewall_manager: INetFwMgr = CoCreateInstance(&NetFwMgr, None, CLSCTX_INPROC_SERVER)?;
let current_profile = firewall_manager.LocalPolicy()?.CurrentProfile()?;
let authorized_applications = current_profile.AuthorizedApplications()?;
let applications_enum = authorized_applications._NewEnum()?;
let applications_enum = applications_enum.cast::<IEnumVARIANT>()?;
applications_enum.Reset()?;
let mut variants = iter::repeat(VARIANT::default())
.take(authorized_applications.Count()? as usize)
.collect::<Vec<VARIANT>>();
let mut count = 0;
applications_enum.Next(&mut variants, &mut count).ok()?;
for variant in variants {
let dispatch = IDispatch::try_from(&variant)?;
let app = dispatch.cast::<INetFwAuthorizedApplication>()?;
println!(
"- Name: {}, Enabled: {}, RemoteAddresses: {}",
app.Name()?,
app.Enabled()?.as_bool(),
app.RemoteAddresses()?
);
println!(
" Scope: {:?}, ProcessImageFileName: {}, IpVersion: {:?}",
app.Scope()?,
app.ProcessImageFileName()?,
app.IpVersion()?
);
}
}
Ok(())
}
Context
- CsWin32 version: [e.g.
0.4.422-beta
]: 0.3.106 - Win32Metadata version (if explicitly set by project): N/A
- Target Framework: [e.g.
netstandard2.0
]: net8.0-windows LangVersion
(if explicitly set by project): [e.g.9
]: N/A
Thanks a lot in advance!
Fotis