AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Type-Deklaration PF_INTERFACE_STATS (MSDN-PlattformSDK: RAS)
Thema durchsuchen
Ansicht
Themen-Optionen

Type-Deklaration PF_INTERFACE_STATS (MSDN-PlattformSDK: RAS)

Ein Thema von x000x · begonnen am 19. Jun 2005 · letzter Beitrag vom 19. Jun 2005
Antwort Antwort
Benutzerbild von x000x
x000x

Registriert seit: 21. Jan 2004
Ort: Bei Hamburg
308 Beiträge
 
Delphi XE2 Professional
 
#1

Type-Deklaration PF_INTERFACE_STATS (MSDN-PlattformSDK: RAS)

  Alt 19. Jun 2005, 15:02
Hallo,

ich "spiele" etwas mit Packetfiltern (IPHLPAPI.DLL) herum und habe jetzt ein evtl. kleineres Problem.
Erstmal die Vorgeschichte:
Es gibt in der IPHLPAPI.DLL die function "PfGetInterfaceStatistics"
Delphi-Quellcode:
function PfGetInterfaceStatistics(
           pInterface: INTERFACE_HANDLE;
           ppfStats: PPF_INTERFACE_STATS;
           pdwBufferSize: PDWORD;
           fResetCounters: BOOL): DWORD;
           stdcall; external IPHLPAPI name '_PfGetInterfaceStatistics@16';
die mir einen Zeiger auf ein Struktur "PF_INTERFACE_STATS" liefert. Laut MSDN ist diese so deklariert:
Delphi-Quellcode:
  ...
typedef struct _PF_INTERFACE_STATS {
  PVOID pvDriverContext;
  DWORD dwFlags;
  DWORD dwInDrops;
  DWORD dwOutDrops;
  PFFORWARD_ACTION eaInAction;
  PFFORWARD_ACTION eaOutAction;
  DWORD dwNumInFilters;
  DWORD dwNumOutFilters;
  DWORD dwFrag;
  DWORD dwSpoof;
  DWORD dwReserved1;
  DWORD dwReserved2;
  LARGE_INTEGER liSYN;
  LARGE_INTEGER liTotalLogged;
  DWORD dwLostLogEntries;
  PF_FILTER_STATS FilterInfo[1];
}
 PF_INTERFACE_STATS,
*PPF_INTERFACE_STATS;
  ...
Das ganze sollte in Delphi wohl so aussehen:
Delphi-Quellcode:
  ...
type
  _PF_FILTER_DESCRIPTOR = packed record
     dwFilterFlags: DWORD;
     dwRule: DWORD;
     pfatType: PFADDRESSTYPE;
     SrcAddr: PByteArray;
     SrcMask: PByteArray;
     DstAddr: PByteArray;
     DstMask: PByteArray;
     dwProtocol: DWORD;
     fLateBound: DWORD;
     wSrcPort: Word;
     wDstPort: Word;
     wSrcPortHighRange: Word;
     wDstPortHighRange: Word;
  end;
  PF_FILTER_DESCRIPTOR = _PF_FILTER_DESCRIPTOR;
  PPF_FILTER_DESCRIPTOR = ^PF_FILTER_DESCRIPTOR;

type
  _PF_FILTER_STATS = packed record
     dwNumPacketsFiltered:DWORD;
     info: PF_FILTER_DESCRIPTOR;
  end;
  PF_FILTER_STATS = _PF_FILTER_STATS;
  PPF_FILTER_STATS = ^PF_FILTER_STATS;

type
  _PF_INTERFACE_STATS = packed record
     pvDriverContext: Pointer;
     dwFlags: DWORD;
     dwInDrops: DWORD;
     dwOutDrops: DWORD;
     eaInAction: PFFORWARD_ACTION;
     eaOutAction: PFFORWARD_ACTION;
     dwNumInFilters: DWORD;
     dwNumOutFilters: DWORD;
     dwFrag: DWORD;
     dwSpoof: DWORD;
     dwReserved1: DWORD;
     dwReserved2: DWORD;
     liSyn: LARGE_INTEGER;
     liTotalLogged: LARGE_INTEGER;
     dwLostLogEntries: DWORD;
     // hier liegt mein Problem...
     FilterInfo: Array[0..0] of PF_FILTER_STATS;
  end;
  PF_INTERFACE_STATS = _PF_INTERFACE_STATS;
  PPF_INTERFACE_STATS = ^PF_INTERFACE_STATS;
  ...
Die Funktion (PfGetInterfaceStatistics) ansicht tut auch das was sie soll, wenn ich z.B. die Anzahl der Output Filter
für ein Interface haben will, bekomme ich sie über:
Delphi-Quellcode:
...
var PStats : PPF_INTERFACE_STATS;
    ...
begin
    ...
    // Output Filter
    ShowMessage('dwNumOutFilter: ' + IntToStr(Stats^.dwNumOutFilters));
    // Hier liegt mein Problem
    ShowMessage('SrcPort: ' + IntToStr(Stats^.FilterInfo[0].info.wSrcPort));
end;
Der Code oben funktioniert, nur bekomme ich in FilterInfo nur die Infos über den ersten Filter, es sind aber mehrere
vorhanden!
Laut MSDN gibt es in Stats^.FilterInfo für jeden Filter ein Element. Wenn ich aber z.B. Stats^.FilterInfo[1].info.wSrcPort
abfrage, bekomme ich nur Müll. Ich vermute mal, dass es an der Deklaration des Typs liegt, denn wenn ich einfach
Delphi-Quellcode:
     ...
     dwLostLogEntries: DWORD;
     // hier liegt mein Problem...
     // FilterInfo: Array[0..0] of PF_FILTER_STATS;
     FilterInfo: Array[0..15] of PF_FILTER_STATS;
  end;
  PF_INTERFACE_STATS = _PF_INTERFACE_STATS;
  ...
definiere, stehen in Stats^.FilterInfo[1].*** die Informationen zum 2. Filter, in
.FilterInfo[2]
zum 3. usw.

Jetzt meine Frage:
Wie muss ich nun den Type deklarieren, um zur Laufzeit die Infos zu n Filter abzufragen?
Ein FilterInfo: Array[0..15] of PF_FILTER_STATS; würde mir ja auch nur die Infos der
ersten 16 Filter bringen, der User könnte aber mehr Filter anlegen.

Also schonmal vielen Dank für Eure Antwort(en) ...
Peter
-= Gruss Peter =-
-= alias x000x =-
  Mit Zitat antworten Zitat
scp

Registriert seit: 31. Okt 2003
1.120 Beiträge
 
Delphi 7 Personal
 
#2

Re: Type-Deklaration PF_INTERFACE_STATS (MSDN-PlattformSDK:

  Alt 19. Jun 2005, 15:10
Die ursprüngliche Deklaration ist schon OK. Du solltest nur dynamisch mehr Speicher zuweisen, etwa so:
Delphi-Quellcode:
var
  THE_INTERFACE_STATS: PPF_INTERFACE_STATS;
begin
  GetMem(THE_INTERFACE_STATS, SizeOf(PF_INTERFACE_STATS) + 15*SizeOf(PF_FILTER_STATS));
  //...
  FreeMem(THE_INTERFACE_STATS);
end;
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#3

Re: Type-Deklaration PF_INTERFACE_STATS (MSDN-PlattformSDK:

  Alt 19. Jun 2005, 16:34
Die Speicherzuordnung sollte zweistufig erfolgen. Beim ersten Aufruf wird BufferSize mit SizeOf(PF_INTERFACE_STATS) initialisiert. Das Ergebnis des Aufrufs ist eine korrekte Initialisierung von Buffersize für den zweiten Aufruf. Der Zugriff auf die einzelnen Filter erfolgt dann einfach über Zeiger-Arithmetik.

Grüße vom marabu
  Mit Zitat antworten Zitat
Benutzerbild von x000x
x000x

Registriert seit: 21. Jan 2004
Ort: Bei Hamburg
308 Beiträge
 
Delphi XE2 Professional
 
#4

Re: Type-Deklaration PF_INTERFACE_STATS (MSDN-PlattformSDK:

  Alt 19. Jun 2005, 19:07
Zitat von marabu:
Die Speicherzuordnung sollte zweistufig erfolgen. Beim einem ersten Aufruf wird BufferSize mit SizeOf(PF_INTERFACE_STATS) initialisiert. Das Ergebnis des Aufrufs ist eine korrekte Initialisierung von Buffersize für den zweiten Aufruf.
Ok, dass hatte ich auch so verstanden. Trotzdem danke
Delphi-Quellcode:
procedure FltStats;
Type
   TFilter = Array[0..15] of PF_FILTER_STATS;
   PFilter = ^TFilter;
var bufSize : DWord;
    dwResult : DWord;
    ppfStats : PPF_INTERFACE_STATS;
    i : Integer;
    Filter : PFilter;
begin
   bufSize := SizeOf(PF_INTERFACE_STATS);
   GetMem(ppfStats, bufSize);
   try
      dwResult := PfGetInterfaceStatistics(hIf, ppfStats, @bufSize, false);
      case dwResult of
         ERROR_INSUFFICIENT_BUFFER :
            begin
               FreeMem(ppfStats);
               GetMem(ppfStats, bufSize);
               dwResult := PfGetInterfaceStatistics(hIf, ppfStats, @bufSize, false);
               if dwResult <> NO_ERROR then
                  Exit;
            end;
         ERROR_INVALID_HANDLE : Exit;
      end;
      Filter := @ppfStats^.filterinfo;
      for i:= 0 to Length(Filter^)-1 do
         ShowMessage( 'Filter (' + IntToStr(Succ(i)) + ')'#13#10 +
                      ' SourcePort: ' + IntToStr(Filter[i].info.wSrcPort) + #13#10+
                      ' DestinationPort: ' + IntToStr(Filter[i].info.wDstPort));
   finally
      FreeMem(ppfStats);
   end;
end;
Hier hab ich eigentlich nichts anderes gemacht, als wie im 1. Posting von mir. Die MessageBox
gibt mir jedenfalls für die Filter die auch existieren, die Korrekten Infos. Mein Problem ist
anscheinend genau das:
Zitat von marabu:
Der Zugriff auf die einzelnen Filter erfolgt dann einfach über Zeiger-Arithmetik.
Hat jemand dafür eventuell ein Beispiel? Es reicht eine Zeile, z.B. wie komme ich an die Infos für den 2. Filter?
(Das muss doch auch irgendwie dynamisch gehen, also OHNE das ich vorher ein array mit fester länge definiere?!)
Peter
-= Gruss Peter =-
-= alias x000x =-
  Mit Zitat antworten Zitat
Robert Marquardt
(Gast)

n/a Beiträge
 
#5

Re: Type-Deklaration PF_INTERFACE_STATS (MSDN-PlattformSDK:

  Alt 19. Jun 2005, 19:20
Das ist ein bischen tricky. In C kann man am Ende eines Record ein Array der Laenge Null deklarieren.
Das nimmt dann keinen Platz im Record ein, sondern benennt den Bereich hinter dem Record.
In C liefert dann auch noch der Name eines Arrays den Zeiger auf das erste Element des Arrays.
InterfaceStats.FilterInfo ist also in C ein Zeiger hinter InterfaceStats.
Zeiger in C sind direkt mit dem Arrayindex zu benutzen. Da es keine Checks fuer Arrayzugriffe erfolgen,
kann man einfach die Elemente des FilterInfo-Arrays zugreifen. Wie viele es sind steht im Record.

Microsoft verwendet die Laenge 1 was keinerlei praktische Auswirkungen hat. Es erklaert nur das erste Element des FilterInfo-Arrays zum Teil des Records.

Wenn FilterInfo als array [0..0] deklariert ist, kann man auch in Delphi auf die FilteRInfo-Elemente zugreifen.
Man muss nur den Check der Arraygrenzen abschalten.
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#6

Re: Type-Deklaration PF_INTERFACE_STATS (MSDN-PlattformSDK:

  Alt 19. Jun 2005, 19:34
iMaxFilter musst du dir ausrechnen: Angeforderte Gesamtgröße - Größe der Struktur bis zum FilterInfo. Wenn du über Zeigerarithmetik zugreifst, dann spielen die Array-Grenzen keine Rolle.
Delphi-Quellcode:
var
  pf: ^PF_FILTER_INFO;
begin
  for i := 0 to iMaxFilter do begin
    ...
    Inc(pf);
  end;
end;
marabu
  Mit Zitat antworten Zitat
Benutzerbild von x000x
x000x

Registriert seit: 21. Jan 2004
Ort: Bei Hamburg
308 Beiträge
 
Delphi XE2 Professional
 
#7

Re: Type-Deklaration PF_INTERFACE_STATS (MSDN-PlattformSDK:

  Alt 19. Jun 2005, 20:42
Ok,
dank dem Code-Schnippsel von marabu und der ausführlichen Erklärung von Robert habe ich folgende Lösung:
Delphi-Quellcode:
procedure FltStats;
var bufSize : DWord;
    dwResult : DWord;
    ppfStats : PPF_INTERFACE_STATS;
    i : Integer;
    Filter : ^PF_FILTER_STATS;
begin
   bufSize := SizeOf(PF_INTERFACE_STATS);
   GetMem(ppfStats, bufSize);
   try
      dwResult := PfGetInterfaceStatistics(hIf, ppfStats, @bufSize, false);
      case dwResult of
         ERROR_INSUFFICIENT_BUFFER :
            begin
               FreeMem(ppfStats);
               GetMem(ppfStats, bufSize);
               dwResult := PfGetInterfaceStatistics(hIf, ppfStats, @bufSize, false);
               if dwResult <> NO_ERROR then
                  Exit;
            end;
         ERROR_INVALID_HANDLE : Exit;
      end;
      Filter := @ppfStats^.filterinfo;
      for i := 0 to (ppfStats^.dwNumInFilters + ppfStats^.dwNumOutFilters) -1 do begin
         ShowMessage( 'Filter (' + IntToStr(Succ(i)) + ')'#13#10 +
                      ' SourcePort: ' + IntToStr(Integer(Filter^.info.wSrcPort)) + #13#10+
                      ' DestinationPort: ' + IntToStr(Filter^.info.wDstPort));
         Inc(Filter);
      end;
   finally
      FreeMem(ppfStats);
   end;
end;
Sollte oben doch noch was nicht so wirklich OK sein, wäre ich für Hinweise dankbar

Meine Frage wurde perfekt beantwortet und ich habe mal wieder ein Stück dazugelernt...

Thx..
Peter
-= Gruss Peter =-
-= alias x000x =-
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:20 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz