在Delphi中,如何从Firewall API中的LocalPolicy.CurrentProfile.GloballyOpenPorts获取枚举器

时间:2008-09-16 22:21:38

标签: delphi firewall

我正在编写一些代码,以查看我们的客户端软件使用的特定端口的 WinXP Vista 的防火墙例外列表中是否存在漏洞。

我可以看到我可以使用NetFwMgr.LocalPolicy.CurrentProfile.GloballyOpenPorts获取当前Open端口异常的列表。但我无法弄清楚如何将枚举列表添加到我可以在我的Delphi程序中使用的内容中。

我的最新尝试列在下面。当我使用port_list.Item时,它会给我一个访问冲突。我知道这是错的,这主要是我一厢情愿的想法。任何帮助将不胜感激。

function TFirewallUtility.IsPortInExceptionList(iPortNumber: integer): boolean;
var
  i, h: integer;
  port_list, port: OleVariant;
begin
  Result := False;
  port_list := mxFirewallManager.LocalPolicy.CurrentProfile.GloballyOpenPorts;
  for i := 0 to port_list.Count - 1 do
  begin
    port := port_list.Item[i];
    if (port.PortNumber = iPortNumber) then
    begin
      Result := True;
      break;
    end;
  end;
end;

3 个答案:

答案 0 :(得分:1)

好的,我认为我已经弄清楚了。

我必须创建一个hnetcfg.dll的类型库文件。我刚开始的时候就这样做了,但从那以后我就学到了很多关于防火墙对象的知识。它当时没有用,但它现在正在工作。您可以从Component | Import Component创建自己的文件。然后按照向导进行操作。

包装代码使用我通常不喜欢的异常,但我不知道如何判断返回接口的接口是否实际上返回了我可以处理的数据......所以如果有人能指出我正确的方向,那将是一种进步。

现在到代码中,感谢Jim的回应。

constructor TFirewallUtility.Create;
begin
  inherited Create;
  CoInitialize(nil);
  mxCurrentFirewallProfile := INetFwMgr(CreateOLEObject('HNetCfg.FwMgr')).LocalPolicy.CurrentProfile;
end;

function TFirewallUtility.IsPortInExceptionList(iPortNumber: integer): boolean;
begin
  try
    Result := mxCurrentFirewallProfile.GloballyOpenPorts.Item(iPortNumber, NET_FW_IP_PROTOCOL_TCP).Port = iPortNumber;
  except
    Result := False;
  end;
end;

function TFirewallUtility.IsPortEnabled(iPortNumber: integer): boolean;
begin
  try
    Result := mxCurrentFirewallProfile.GloballyOpenPorts.Item(iPortNumber, NET_FW_IP_PROTOCOL_TCP).Enabled;
  except
    Result := False;
  end;
end;

procedure TFirewallUtility.SetPortEnabled(iPortNumber: integer; sPortName: string; xProtocol: TFirewallPortProtocol);
begin
  try
   mxCurrentFirewallProfile.GloballyOpenPorts.Item(iPortNumber, CFirewallPortProtocalConsts[xProtocol]).Enabled := True;
  except
    HaltIf(True, 'xFirewallManager.TFirewallUtility.IsPortEnabled: Port not in exception list.');
  end;
end;

procedure TFirewallUtility.AddPortToFirewall(sPortName: string; iPortNumber: Cardinal; xProtocol: TFirewallPortProtocol);
var
  port: INetFwOpenPort;
begin
  port := INetFwOpenPort(CreateOLEObject('HNetCfg.FWOpenPort'));
  port.Name := sPortName;
  port.Protocol := CFirewallPortProtocalConsts[xProtocol];
  port.Port := iPortNumber;
  port.Scope := NET_FW_SCOPE_ALL;
  port.Enabled := true;
  mxCurrentFirewallProfile.GloballyOpenPorts.Add(port);
end;

答案 1 :(得分:1)

你可以像这样循环枚举:

type
  IEnumVariant = interface(IUnknown)
  ['{00020404-0000-0000-C000-000000000046}']
    function Next(celt: LongWord; var rgvar : OleVariant;
                 pceltFetched: PLongWord): HResult; stdcall;
    function Skip(celt: LongWord): HResult; stdcall;
    function Reset: HResult; stdcall;
    function Clone(out Enum : IEnumVariant) : HResult; stdcall;
  end;

var
  Enum : IEnumVariant;
  Port : OleVariant;
  Count : Integer;
...
Count := 1;
IUnknown (Profile.GloballyOpenPorts._NewEnum).QueryInterface (IEnumVariant, Enum);
Enum.Reset;
while (Enum.Next (1, FirewallPort, @Count) = S_OK) do
  begin
  if (FirewallPort.Port = Port) then
    Exit (True)
  end;

答案 2 :(得分:0)

如果没有设置要测试的应用程序,我会建议以下内容。如果有效,请告诉我。

我查看了C# example here,看起来您需要执行以下操作:

Result := False;
port_enum := mxFirewallManager.LocalPolicy.CurrentProfile.GloballyOpenPorts._NewEnum;
while port_enum.MoveNext <> Null do // try assigned if that doesn't work
begin
  port = e.Current as INetFwOpenPort;
  if (port.PortNumber = iPortNumber) then
  begin
    Result := True;
    break;
  end;
end;

不确定是否会编译,但 _NewEnum MoveNext 当前是您要使用的成员。