Einzelnen Beitrag anzeigen

Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#12

AW: Vollständigen Datei- oder Verzeichnisnamen über das Handle ermitteln

  Alt 26. Apr 2012, 14:22
... allerdings habe ich dies nicht weiter getestet.
Eben, ich wollte nämlich schon gerade fragen: hast Du den Code jemals selbst erfolgreich getestet ?
Selbstverständlich funktioniert er mit validen File Handles unter XE2 wunderbar, sonst hätte ich den Code kaum gepostet.

Eindeutig wohl eher aber nur per "Copy & Paste" von irgendwoher ungeprüft übernommen..
Denn "Dein" Code funktioniert weder unter Delphi 7 noch unter Delphi XE.
Es grenzt schon stark an Unverschämtheit mit sowas (noch dazu ohne Beweise) zu unterstellen. Lediglich die Funktion zum Ermitteln der korrekten Partitionsbuchstaben habe ich aus einer vorhandenen C-Source portiert. Ich bin so freundlich und teile bestimmte Funktionen, die für andere Leute nützlich sein könnten und du kommst mit deinem jämmerlichen Halbwissen daher, posaunst falsche Tatsachen und machst meine Arbeit schlecht.

Erste Stolperstelle: Der Status bei folgendem Call
Code:
Status := NtQueryObject(hFile, ObjectNameInformation, ObjectInformation, ReturnLength, @ReturnLength);
ist "nicht erfolgreich".
Genau und das liegt nicht etwa an meinem Code, sondern daran, dass du vergessen hast Aligned Records per Compilerdirektive zu aktivieren, bzw. UNICODE_STRING sogar noch (fälschlicherweise) absichtlich als packed record deklarierst.

Im eigentlichen Code sind nämlich massenweise Fehler,
z.B. ist in der Funktionsbeschreibung von NtQueryObject() der letzte Parameter nicht als OUT- bzw. VAR-Parameter deklariert. Das aber ist zwingend erforderlich, weil genau dieser Wert anschließend Parameter für den Zugriff auf die Daten der OBJECT_INFORMATION_CLASS ist.
Dann sind wohl in den Jedi Native API Headers "massenweise Fehler", denn genau von dort habe ich die Funktionsdeklaration kopiert. Des weiteren solltest du, deinem Namen nach zu schließen, wissen, dass OUT oder VAR intern (auf Assembler-Ebene) 1 zu 1 wie ein Pointer behandelt wird.

Zweitens, die (lokale) Deklaration
Code:
var ObjectInformation: PUNICODE_STRING
ist völliger Unsinn.
ObjectInformation muss vielmehr ein Record vom Typ OBJECT_NAME_INFORMATION sein; entsprechend muss ein pObjectInformation:=@OBJECT_NAME_INFORMATION eingeführt werden, weil der Zugriff über den Pointer läuft. Dadurch ändern sich natürlich zwingend eine Anzahl Anweisungen. Man erhält dann mit der Abfrage auf pObjectInformation^.Name.Buffer den korrekten DeviceNamen zum Filehandle.
Dann schau dir mal ganz genau die Deklaration von OBJECT_NAME_INFORMATION an. Oh Wunder: Es befindet sich ein einzelnes Feld vom Typ UNICODE_STRING darin. Also auch hier: Kein Fehler!

Letztens (das Letzte i.e.S.):
Und diesen DeviceNamen nun mit DeviceNameToFilePath() in den logischen WindowsFilepath konvertieren zu wollen, ist ein völlig falscher Ansatz; das ergibt als Ergebnis einfach nur einen leeren String;
In diesem Falle stimme ich zu. Hier ist es wohl sinnvoller bei Fehlschlag den unkonvertierten Namen anstelle eines leeren Ergebnisses zurückzuliefern.

Ansonsten: Danke dir für deinen wirklich fundierten und hilfreichen Beitrag!

Achja ...:
Noch ein sehr wichtiger, ergänzender Hinweis als Nachtrag zu meinem Code:

In der Compileroption (Menu: Optionen >> Compiler-Tab >> Codeerzeugung) muss unbedingt die Optimierung deaktiviert werden, was ohnehin grundsätzlich immer dringend zu empfehlen ist.

Der Compiler verhaspelt sich sonst in FileHandleToFilePath() bei der Ermittlung der benötigten Größe des Ausgabepuffers im ersten Aufruf von NtQueryObject(). Irgendetwas geht da unverständlicherweise intern mit der Zuweisung der Speichergröße an den entsprechenden Pointer schief. Folge: weil dann nicht auf den Ausgabepuffer zugegriffen werden kann, kann somit daraus auch nicht der Devicename zum Filehandle ausgelesen werden und somit natürlich auch nicht der Win32Filepath ermittelt.
Vollkommener Blödsinn. Der Code Funktioniert auch mit Compileroptimierung wunderbar. Und unverständlich ist an dem von dir beschriebenen Verhalten auch rein gar nichts. Die meisten (nativen) APIs erwarten Aligned Structs und 4 Byte Enum Typen. Dies kann durch die Compilerdirektiven {$A+} und {$Z4} erzwungen werden.
Dass du UNICODE_STRING sogar noch explizit als "packed record" (also nicht aligned) deklariert hast, zeigt nochmal, dass du absolut keine Ahnung hast, was du da überhaupt machst.

Edit:
1) (korrekte) Typendeklarationen ergänzt
2): Standardrückgabewert geändert
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)

Geändert von Zacherl (26. Apr 2012 um 16:55 Uhr)
  Mit Zitat antworten Zitat