Delphi-PRAXiS
Seite 3 von 4     123 4      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Prozesse oder Anwendungen ermitteln, die eine Datei benutzen (https://www.delphipraxis.net/79705-prozesse-oder-anwendungen-ermitteln-die-eine-datei-benutzen.html)

Olli 17. Mai 2007 11:05

Re: Prozesse oder Anwendungen ermitteln, die eine Datei benu
 
Interessant, daß du genau den Code übersetzt hast, dessen Funktionalität ich kritisiert hatte. Ich versuche es nochmal metaphorisch.

Du (Thread) kaufst dir bei IKEA (System) einen Sessel (Öffnen einer Datei) und bekommst ihn (Handle) ins Haus (Prozeß) geliefert. Da ich als Dieb zufällig Superheldenfähigkeiten habe, ziehe ich dir den gelieferten Sessel in dem Moment unterm Popöchen weg (Schließen des Handles), als du dich hinsetzen möchtest (irgendeine Operation an der Datei). Unglücklicherweise ist dahinter eine Tischkante, auf die du mit dem Hinterkopf fällst und du bist tot (Thread crasht, da es der einzige war, nimmt er den Prozeß mit).

BTW: In den meisten Fällen wird es, bspw. beim Aufruf von Win32-Dateifunktionen, zu keinem Absturz kommen, weil das Handle einfach nicht mehr gültig ist. Leider kann es aber so sein, daß die Logik des Programms es normalerweise nicht erlauben würde, daß eine Operation an einer bereits erfolgreich geöffneten Datei fehlschlägt. Was dann?

Viel Spaß noch :zwinker:

daPimP 17. Mai 2007 17:25

Re: Prozesse oder Anwendungen ermitteln, die eine Datei benu
 
@Olli: Ich hatte noch überlegt in meinen vorhergehenden Eintrag reinzuschreiben, KEIN Sarkassmus oder Poesie - aber ich dachte das Wort KONSTRUKTIV würde reichen!

Da ich schon einige Beiträge von dir gelesen habe, hätte ich mir eigentlich etwas "Hilfe" erwartet, anstatt den Lehrerfinger. :zwinker:

NOCHMAL: Meine Absicht ist es, alle Handles aufzulisten. Das über das killen von Handles die Systemstabilität beieinträchtigt werden KÖNNTE, ist kein Geheimnis.

@Apollonius: Da C++ nicht meine Muttersprache ist, kann sich beim Übersetzen schon mal ein Fehler eingeschlichen haben. Schau ich nochmal drauf.

Anhand der Klicks auf diesen Beitrag, scheint im Allgemeinen ein hohes Interesse daran zu bestehen.

Olli 17. Mai 2007 20:37

Re: Prozesse oder Anwendungen ermitteln, die eine Datei benu
 
Zitat:

Zitat von daPimP
Da ich schon einige Beiträge von dir gelesen habe, hätte ich mir eigentlich etwas "Hilfe" erwartet, anstatt den Lehrerfinger. :zwinker:

Hättest du auch bekommen, aber nicht für eine Funktion CloseRemoteHandle() :zwinker:

Zitat:

Zitat von daPimP
NOCHMAL: Meine Absicht ist es, alle Handles aufzulisten.

http://jedi-apilib.sourceforge.net/ntapi_current.zip und dann http://www.openrce.org/forums/posts/46 oder "Windows NT/2000 Native API Reference" ("Listing Open Handles of a Process").

Zitat:

Zitat von daPimP
Das über das killen von Handles die Systemstabilität beieinträchtigt werden KÖNNTE, ist kein Geheimnis.

Na dann ist ja alles in bester Ordnung, solange man es weiß.

daPimP 21. Mai 2007 08:47

Re: Prozesse oder Anwendungen ermitteln, die eine Datei benu
 
@Olli: Genau das hab ich gesucht. :P

Es fehlt nur noch die endgültige Umsetzung.
1) Wenn der erste Teil bis //-------------- richtig ist
2) Wie kann ich alle Werte korrekt anzeigen, irgendwie steh ich auf dem Schlauch :wall:

Delphi-Quellcode:
implementation

uses JwaNative;
...

function SHOWHANDLE(const lv: TListView): BOOL;
const
  BUF_SIZE = $15000;
var
  HANDLEListBuffer: PChar;
  HANDLEInfo: jwanative.PSYSTEM_HANDLE_INFORMATION;

  BufSize: Cardinal;
  Status: Integer;
   i: integer;
  li: TListItem;
begin
  Result := false;
  lv.Items.BeginUpdate;
  lv.Items.Clear;

//  capture Liste
  BufSize := BUF_SIZE;
  repeat
    GetMem(HANDLEListBuffer, BufSize);
    if HANDLEListBuffer = nil then
    begin
      lv.Items.EndUpdate;
      Exit;
    end;

    Status := jwanative.NtQuerySystemInformation(SystemHandleInformation ,
                                       HANDLEListBuffer,
                                       BufSize,
                                       nil);

    if Status <> NO_ERROR then
    begin
      // Buffer zu klein, vergrößern
      FreeMem(HANDLEListBuffer);
      Inc(BufSize, BUF_SIZE);
    end
    else if Status < 0 then  // irgendein Fehler...
    begin
      lv.Items.EndUpdate;
      Exit;
    end;
  until Status >= 0;

  // AB HIER STECK ICH FEST ---------------------------------------
 for i:= 1 to 6 do begin //zur probe nur mal die ersten 6 Werte...
   HANDLEInfo := PSYSTEM_HANDLE_INFORMATION(HANDLEListBuffer);
   HANDLEInfo := PSYSTEM_HANDLE_INFORMATION(Cardinal(HANDLEInfo));
 
          li := lv.Items.Add;
   li.Caption:= HANDLEInfo^.ProcessId;
   li.SubItems.Add(IntToStr(HANDLEInfo^.Handle));
 end;

  Result := true;
  FreeMem(HANDLEListBuffer);
  lv.Items.EndUpdate;
end;

Olli 21. Mai 2007 09:37

Re: Prozesse oder Anwendungen ermitteln, die eine Datei benu
 
Einige Anmerkungen.
  • NO_ERROR ist kein geeigneter Vergleichswert. Benutze die Funktion (in C ein Makro) NT_SUCCESS() aus JwaWinType!
  • Vergleiche mit dem Wert den du finden willst (IMO ist das STATUS_BUFFER_TOO_SMALL aus JwaNtStatus) und andernfalls NT_SUCCESS() - bei dir mußt du das der Reihe nach machen. Also wenn STATUS_BUFFER_TOO_SMALL dann Puffer freigeben und mit neuer Größe allozieren - sonst, wenn NT_SUCCESS nicht True zurückgibt, Fehler ausgeben und raus aus der Routine.
  • SYSTEM_HANDLE_INFORMATION hat eine feste Größe, daher benutzt du hier einfach nur sizeof() um die Größe des Typs zum aktuellen Pointerwert zu addieren und so den Pointer zum nächsten Record zu bekommen (Stichwort: Pointerarithmetik!).
  • Am Ende wirst du irgendwo bei SYSTEM_OBJECT_INFORMATION landen. Dort benutzt du statt sizeof() den Wert von NextEntryOffset aus dem aktuellen Record und addierst ihn zum Offset des aktuellen Records um das Offset zum nächsten Record zu bekommen. Das Prinzip ist also gleich. Das kommt daher, daß SYSTEM_OBJECT_INFORMATION eine variable Länge hat (hier ein String).

Beachte auch, daß die Abfrage der Informationen eines Handles (und ultimativ des entsprechenden Objektes) bei Pipes und Mailslots blockieren kann. Nico kann dir ein Lied davon singen.

daPimP 21. Mai 2007 19:42

Re: Prozesse oder Anwendungen ermitteln, die eine Datei benu
 
Danke für die Tips. Zur Umsetzung:

Zitat:

Vergleiche mit dem Wert den du finden willst (IMO ist das STATUS_BUFFER_TOO_SMALL aus JwaNtStatus) und andernfalls NT_SUCCESS() - bei dir mußt du das der Reihe nach machen. Also wenn STATUS_BUFFER_TOO_SMALL dann Puffer freigeben und mit neuer Größe allozieren - sonst, wenn NT_SUCCESS nicht True zurückgibt, Fehler ausgeben und raus aus der Routine.
Delphi-Quellcode:
  status:= jwanative.NTQuerySystemInformation(jwanative.SystemHandleInformation,
                                              @HANDLEInfo,
                                              sizeof(jwanative.PSYSTEM_HANDLE_INFORMATION),
                                              0);

 if status = jwantstatus.STATUS_BUFFER_TOO_SMALL then
  begin
    form1.Memo1.Lines.Add('STATUS_BUFFER_TOO_SMALL: '+IntToStr(status)); //info
  end else
    if JwaWinType.NT_SUCCESS(Status)= false then begin
      form1.Memo1.Lines.Add('NT_SUCCESS: fehler');          //hier schmeißt er mich raus
      Exit;                                           //worin liegt der fehler?
    end else
      form1.Memo1.Lines.Add('NT_SUCCESS: ok');
Zitat:

SYSTEM_HANDLE_INFORMATION hat eine feste Größe, daher benutzt du hier einfach nur sizeof()
Wenn richtig verstanden, dann so wie oben.

Anschließend..

Zitat:

Pointerwert zu addieren und so den Pointer zum nächsten Record zu bekommen (Stichwort: Pointerarithmetik!).
Am Ende wirst du irgendwo bei SYSTEM_OBJECT_INFORMATION landen.
so was "in der Art"

Delphi-Quellcode:
 
var
  HANDLEListBuffer: PChar;
               obj: PSystem_Object_Information;
            offset: cardinal;
...
 obj := PSYSTEM_OBJECT_INFORMATION(handleListBuffer);
  repeat
    obj := PSYSTEM_OBJECT_INFORMATION(Cardinal(obj) + Offset);
    Offset := obj^.NextEntryOffset;
...
  until Offset = 0;
...
  FreeMem(HANDLEListBuffer);

Olli 21. Mai 2007 20:43

Re: Prozesse oder Anwendungen ermitteln, die eine Datei benu
 
Zitat:

Zitat von daPimP
//worin liegt der fehler?

Meine Kristallkugel ist im Urlaub, wenn du so lieb wärst mir derweil den Statuscode zu nennen, kann ich vielleicht mehr sagen.

NicoDE 21. Mai 2007 22:03

Re: Prozesse oder Anwendungen ermitteln, die eine Datei benu
 
Kleiner Hinweis am Rande: Unter Windows XP Professional x64 Edition gibt es Probleme mit dem Aufruf von NtQuerySystemInformation(SystemHandleInformation) durch eine 32-Bit Anwendung. Die Funktion meldet einen Erfolg, aber nur der erste Eintrag im Array ist gültig (der Rest wird vom WOW64-Wrapper nicht kopiert). Zudem kann es vorkommen (insbesondere unter einem mit /3GB gestartetem Windows), dass der Kernel nicht genug Speicher hat, um die komplette Liste zu liefern.

ps: der Ausgabepuffer sollte übrigens an einer ausgerichteten Adresse liegen.

Zitat:

Zitat von Olli
Beachte auch, daß die Abfrage der Informationen eines Handles (und ultimativ des entsprechenden Objektes) bei Pipes und Mailslots blockieren kann. Nico kann dir ein Lied davon singen.

Nicht nur das... es gibt auch Probleme mit Software, die sich darauf verlässt, dass ihr ReadFile (auf eine Pipe) immer Daten liefert (was nicht der Fall ist, wenn man den Namen des Objekts abfragt *g*). In solchen Fällen neigen diese Programme zu äußerst unschönem Fehlverhalten (Abstürze sind wenigestens Fehler die man 'sehen' kann).

daPimP 29. Mai 2007 20:44

Re: Prozesse oder Anwendungen ermitteln, die eine Datei benu
 
Habe den kompletten Source noch mal über den Haufen geworfen.
Mein neuer Code funktioniert.

Kann die Handles eines Prozesses auslesen und auch den ObjectType bestimmen.

Delphi-Quellcode:
  _SYSTEM_HANDLE_INFORMATION = record // Information Class 16
    ProcessId: ULONG;                                  
    ObjectTypeNumber: UCHAR;
    Flags: UCHAR; // 0x01 = PROTECT_FROM_CLOSE, 0x02 = INHERIT
    Handle: USHORT;                                        
    Object_: PVOID;
    GrantedAccess: ACCESS_MASK;                            
  end;
Aber wie kann ich nun Object_: PVOID auslesen(PVOID ist ein Pointer), bzw. wie funktioniert dies. Was liefert mir der Wert zurück?

NicoDE 30. Mai 2007 10:14

Re: Prozesse oder Anwendungen ermitteln, die eine Datei benu
 
Zitat:

Zitat von daPimP
Aber wie kann ich nun Object_: PVOID auslesen(PVOID ist ein Pointer), bzw. wie funktioniert dies. Was liefert mir der Wert zurück?

Der Pointer ist nur für den KernelMode interessant (du müsstest also einen KM-Treiber schreiben um den Inhalt des Pointers auszuwerten).
Wie bereits erwähnt, bekommst du unter WOW64 keinen 64-Bit-Zeiger (den du aber benötigen würdest).

Für UserMode-Prozesse sind nur die anderen Felder interessant (insbes. ProcessId/Handle).


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:32 Uhr.
Seite 3 von 4     123 4      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz