В Delphi, как получить перечислитель из LocalPolicy.CurrentProfile.GloballyOpenPorts в API брандмауэра - PullRequest
2 голосов
/ 17 сентября 2008

Я пишу некоторый код, чтобы увидеть, есть ли в списке исключений брандмауэра дыра для WinXP и Vista для определенного порта, используемого нашим клиентским программным обеспечением.

Я вижу, что могу использовать NetFwMgr.LocalPolicy.CurrentProfile.GloballyOpenPorts, чтобы получить список текущих исключений открытого порта. Но я не могу понять, как включить этот перечислимый список во что-то, что я могу использовать в моей программе 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 ]

1 голос
/ 20 сентября 2008

ОК, я думаю, что понял.

Мне пришлось создать файл библиотеки типов файла hnetcfg.dll. Я сделал это, когда только начал, но с тех пор многое узнал об объектах брандмауэра. Это не сработало тогда, но работает сейчас. Вы можете создать свой собственный файл из Component | Import Component. А затем следуйте за волшебником.

Оберточный код использует исключения, которые я обычно не люблю делать, но я не знаю, как определить, действительно ли интерфейс, возвращающий интерфейс, возвращает данные, с которыми я могу работать было бы лучше, если бы кто-то мог указать мне правильное направление.

А теперь к коду, с благодарностью Джиму за его ответ.

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 голос
/ 23 октября 2009

Вы можете просмотреть перечисление следующим образом:

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;
0 голосов
/ 17 сентября 2008

Без настройки приложения для тестирования я предложу следующее. Дайте мне знать, если это работает.

Я посмотрел C # пример здесь , и похоже, что вам нужно сделать что-то вроде следующего:

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 и Current - это элементы, которые вы хотите использовать.

...