falahati / WindowsFirewallHelper

A class library to manage the Windows Firewall as well as adding your program to the Windows Firewall Exception list.
MIT License
276 stars 72 forks source link

Using WindowsFirewallHelper with .NET Core 2.1 #13

Closed brent-williams closed 5 years ago

brent-williams commented 6 years ago

Have had great success with .NET Framework but completely blocked when trying to use with .NET Core. Adding nuget package appears to work but DLL obviously doesn't get added, using WindowsFirewallHelper doesn't resolve. Pulling the source inexplicably has INetFwRule3 undefined in master and v1.3.6543.29360 tag. Any suggestions on getting this to work with .NET Core and/or resolving missing INetFwRule3 in source so I can attempt to build from source under .NET Core?

brent-williams commented 6 years ago

@falahati if I can locate a branch that builds I can probably get it running on .NET Core and report findings. Any quick fixes/hacks/suggestions much appreciated!

icnocop commented 6 years ago

For issues with INetFwRule3, see https://github.com/falahati/WindowsFirewallHelper/issues/14#issuecomment-418541836

falahati commented 6 years ago

You can follow the newly created 'netcore' branch: https://github.com/falahati/WindowsFirewallHelper/tree/netcore

However, there is a problem currently with lack of System.Runtime.InteropServices.CustomMarshalers in netstandard, especially in our case, the EnumeratorToEnumVariantMarshaler class. https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.custommarshalers.enumeratortoenumvariantmarshaler?view=netframework-4.7.2

This can be solved, but with the cost of writing the COM interrupt type (proxy type) by hand.

brent-williams commented 6 years ago

@falahati understood .NET Core port is ongoing thanks.

falahati commented 5 years ago

I am going to leave this one open as a reminder. However, from what one of netcore moderators said, we need to wait for netstandard3 for this to happen.

jjxtra commented 5 years ago

I'm the creator of IPBan (https://github.com/DigitalRuby/IPBan) and I'm using Windows firewall in .net core 2.2, I've gotten rid of the type lib dll and put it all in a custom csharp file.

This error can be worked around by writing the typelib yourself. My csharp file was generated from the typelib dll using reflector, and there has been a hand-editing of the INetFwRules interface to support enumeration of rules.

Here are the relevant bits for rules (full file at https://github.com/DigitalRuby/IPBan/blob/master/Windows/IPBanWindowsFirewallNetFwTypeLibImport.cs)

    [ComImport]
    [TypeLibType(4160)]
    [Guid("98325047-C671-4174-8D81-DEFCD3F03186")]
    public interface INetFwPolicy2
    {
        [DispId(1)]
        int CurrentProfileTypes
        {
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(1)]
            get;
        }

        [DispId(2)]
        bool FirewallEnabled
        {
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(2)]
            get;
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(2)]
            [param: In]
            set;
        }

        [DispId(3)]
        object ExcludedInterfaces
        {
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(3)]
            //[return: MarshalAs(UnmanagedType.Struct)]
            get;
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(3)]
            [param: In]
            //[param: MarshalAs(UnmanagedType.Struct)]
            set;
        }

        [DispId(4)]
        bool BlockAllInboundTraffic
        {
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(4)]
            get;
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(4)]
            [param: In]
            set;
        }

        [DispId(5)]
        bool NotificationsDisabled
        {
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(5)]
            get;
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(5)]
            [param: In]
            set;
        }

        [DispId(6)]
        bool UnicastResponsesToMulticastBroadcastDisabled
        {
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(6)]
            get;
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(6)]
            [param: In]
            set;
        }

        [DispId(7)]
        INetFwRules Rules
        {
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(7)]
            [return: MarshalAs(UnmanagedType.Interface)]
            get;
        }

        [DispId(8)]
        INetFwServiceRestriction ServiceRestriction
        {
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(8)]
            [return: MarshalAs(UnmanagedType.Interface)]
            get;
        }

        [DispId(12)]
        NET_FW_ACTION_ DefaultInboundAction
        {
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(12)]
            get;
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(12)]
            [param: In]
            set;
        }

        [DispId(13)]
        NET_FW_ACTION_ DefaultOutboundAction
        {
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(13)]
            get;
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(13)]
            [param: In]
            set;
        }

        [DispId(14)]
        bool IsRuleGroupCurrentlyEnabled
        {
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(14)]
            get;
        }

        [DispId(15)]
        NET_FW_MODIFY_STATE_ LocalPolicyModifyState
        {
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(15)]
            get;
        }

        [MethodImpl(MethodImplOptions.InternalCall)]
        [DispId(9)]
        void EnableRuleGroup([In] int profileTypesBitmask, [In] [MarshalAs(UnmanagedType.BStr)] string group, [In] bool enable);

        [MethodImpl(MethodImplOptions.InternalCall)]
        [DispId(10)]
        bool IsRuleGroupEnabled([In] int profileTypesBitmask, [In] [MarshalAs(UnmanagedType.BStr)] string group);

        [MethodImpl(MethodImplOptions.InternalCall)]
        [DispId(11)]
        void RestoreLocalFirewallDefaults();
    }

    [ComImport]
    [Guid("9C4C6277-5027-441E-AFAE-CA1F542DA009")]
    [TypeLibType(4160)]
    public interface INetFwRules : IEnumerable
    {
        [DispId(1)]
        int Count
        {
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(1)]
            get;
        }

        [MethodImpl(MethodImplOptions.InternalCall)]
        [DispId(2)]
        void Add([In] [MarshalAs(UnmanagedType.Interface)] INetFwRule rule);

        [MethodImpl(MethodImplOptions.InternalCall)]
        [DispId(3)]
        void Remove([In] [MarshalAs(UnmanagedType.BStr)] string Name);

        [MethodImpl(MethodImplOptions.InternalCall)]
        [DispId(4)]
        [return: MarshalAs(UnmanagedType.Interface)]
        INetFwRule Item([In] [MarshalAs(UnmanagedType.BStr)] string Name);

        [DispId(-4)]
        System.Runtime.InteropServices.ComTypes.IEnumVARIANT GetEnumeratorVariant();

        /*
        [MethodImpl(MethodImplOptions.InternalCall)]
        [DispId(-4)]
        [TypeLibFunc(1)]
        [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "System.Runtime.InteropServices.CustomMarshalers.EnumeratorToEnumVariantMarshaler")]
        new IEnumerator GetEnumerator();
        */
    }

    private const string clsidFwPolicy2 = "{E2B3C97F-6AE1-41AC-817A-F6F92166D7DD}";
    private static readonly INetFwPolicy2 policy = Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid(clsidFwPolicy2))) as INetFwPolicy2;

    private IEnumerable<INetFwRule> EnumerateRulesMatchingPrefix(string prefix)
    {
        var e = policy.Rules.GetEnumeratorVariant();
        object[] results = new object[64];
        IntPtr useless = new IntPtr();
        bool done = false;

        while (!done)
        {
            e.Next(results.Length, results, useless);
            foreach (object o in results)
            {
                if (!(o is INetFwRule rule))
                {
                    done = true;
                    break;
                }
                else if (prefix == "*" || rule.Name.StartsWith(prefix))
                {
                    yield return rule;
                }
            }
            Array.Clear(results, 0, results.Length);
        }
    }
falahati commented 5 years ago

Thank you for @jjxtra for helping me with this issue.

The problem, however, wasn't the possibility of a workaround. The problem was that I didn't want to write the whole Interop interfaces just to change one line of code (literally its 1 line of code in the whole library; ok, maybe 3 for supporting WindowsXP as well).

However, now that you mentioned decompiling the generated code; I should take another look at this to see if dotPeek works as advertised with this library. Had some bad experiences with decompiled codes before so I don't expect much at this point. But thank again for pointing me in the right direction.

Probably going to push some modifications today; if I am happy with the result; might even publish it.

falahati commented 5 years ago

The latest version of this library should be finally compatible with netcore2+. Therefore I am going to close this issue.

If you had any other problem with the library; please open a new issue.