Search code examples
windowsdelphiwindows-firewalldelphi-12-athenswindows-firewall-api

How to get a list of outbound firewall rule names?


I'm trying to build a function that would return a list of all the firewall outbound rules that I have on my computer, but I'm just not getting the function to work.

This is what I have currently:

function GetOutboundFirewallRuleNames: TStringList;
var
  i: Integer;
begin
  var ruleNames := TStringList.Create;

  // Initialize COM
  CoInitialize(nil);
  try
    try
      // Create an instance of the firewall policy
      var fwPolicy2: OleVariant := CreateOleObject('HNetCfg.FwPolicy2');

      // Loop through all rules to find the outbound rules
      for i := 1 to fwPolicy2.Rules.Count do
      begin
        var rule: OleVariant := fwPolicy2.Rules.Item(i - 1);
        if rule.Direction = 2 then // Outbound direction
        begin
          ruleNames.Add(rule.Name);
        end;
      end;

      Result := ruleNames;
    except
      on E: EOleException do
      begin
        ruleNames.Free;
        raise Exception.CreateFmt('Error accessing firewall rules: %s', [E.Message]);
      end;
      on E: Exception do
      begin
        ruleNames.Free;
        raise;
      end;
    end;
  finally
    // Uninitialize COM
    CoUninitialize;
  end;
end;

The errors I am getting are the following:

Project raised exception class EOleException with message 'The system cannot find the file specified'.

Project raised exception class Exception with message 'Error accessing firewall rules: The system cannot find the file specified'.

And the errors seems to happen on this line of code:

var rule: OleVariant := fwPolicy2.Rules.Item(i - 1);

I am also running the Delphi IDE as an administrator as well as my app as an administrator as well.


Could someone please help in assisting me in terms of what I'm doing wrong or what the correct way is to get a list of firewall outbound rule names? 🙏🏻


Solution

  • You can use the IEnumVARIANT interface for looping over rules. Reworked your example and this works for me:

    procedure GetOutboundFirewallRuleNames(AStrings: TStrings);
    var
      Enum: IEnumVARIANT;
      Value: LongWord;
      FwPolicy2, Rule: OleVariant;
    begin
      // Initialize COM
      CoInitialize(nil);
      try
        try
          // Create an instance of the firewall policy
          FwPolicy2 := CreateOleObject('HNetCfg.FwPolicy2');
          Enum := IUnknown(FwPolicy2.Rules._NewEnum) as IEnumVARIANT;
          // Loop through all rules to find the outbound rules
          while Enum.Next(1, Rule, Value) = 0 do
          begin
            if Rule.Direction = 2 then // Outbound direction
              AStrings.Add(Rule.Name);
          end;
        except
          on E: EOleException do
            raise Exception.CreateFmt('Error accessing firewall rules: %s', [E.Message]);
          on E: Exception do
            raise;
        end;
      finally
        // Uninitialize COM
        CoUninitialize;
      end;
    end;