Einzelnen Beitrag anzeigen

Benutzerbild von Zacherl
Zacherl

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

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

  Alt 24. Apr 2012, 17:58
Hallo zusammen,

folgende Funktion liefert den vollständigen Namen einer Datei oder eines Verzeichnisses anhand eines Handles.
Delphi-Quellcode:
const
  STATUS_SUCCESS = NTSTATUS($00000000);
  STATUS_INVALID_PARAMETER = NTSTATUS($C000000D);
  STATUS_INFO_LENGTH_MISMATCH = NTSTATUS($C0000004);

type
  NTSTATUS = ULONG;
  HANDLE = Winapi.Windows.THandle;
  PWSTR = Winapi.Windows.LPWSTR;

  PUNICODE_STRING = ^UNICODE_STRING;
  _UNICODE_STRING = record
    Length: USHORT;
    MaximumLength: USHORT;
    Buffer: PWSTR;
  end;
  UNICODE_STRING = _UNICODE_STRING;
  PCUNICODE_STRING = ^UNICODE_STRING;
  TUnicodeString = UNICODE_STRING;
  PUnicodeString = PUNICODE_STRING;

function GetFilePathFromHandle(hFile: THandle): String;

function DeviceNameToFilePath(FileName: String): String;
var
  Buffer: array[0..MAX_PATH - 1] of Char;
  BufferSize: DWord;
  LogicalDrives: array of Char;
  I: Integer;
  DeviceName: String;
begin
  Result := FileName;
  BufferSize := GetLogicalDriveStrings(MAX_PATH, @Buffer[0]);
  if (BufferSize = 0) then Exit;
  SetLength(LogicalDrives, (BufferSize - 2 * SizeOf(Char)) div 3);
  for I := Low(LogicalDrives) to High(LogicalDrives) do
  begin
    LogicalDrives[I] := Buffer[I * 4];
  end;
  for I := Low(LogicalDrives) to High(LogicalDrives) do
  begin
    BufferSize := QueryDosDevice(PChar(LogicalDrives[I] + ':'),
      @Buffer[0], MAX_PATH);
    if (BufferSize > 0) then
    begin
      DeviceName := AnsiLowerCase(PWideChar(@Buffer[0]));
      if (AnsiLowerCase(Copy(FileName, 1, Length(DeviceName))) =
        DeviceName) then
      begin
        Result := LogicalDrives[I] + ':' + Copy(FileName,
          Length(DeviceName) + 1, Length(FileName));
        Exit;
      end;
    end;
  end;
end;

const
  ObjectNameInformation = 1;
var
  NtQueryObject: function(ObjectHandle: HANDLE;
    ObjectInformationClass: ULONG; ObjectInformation: PVOID;
    ObjectInformationLength: ULONG; ReturnLength: PULONG): NTSTATUS; stdcall;
var
  ObjectInformation: PUNICODE_STRING;
  ReturnLength: ULONG;
  Status: NTSTATUS;
begin
  Result := '';
  @NtQueryObject := GetProcAddress(LoadLibrary('ntdll.dll'), 'NtQueryObject');
  if not Assigned(@NtQueryObject) then Exit;
  Status := NtQueryObject(hFile, ObjectNameInformation, nil, 0, @ReturnLength);
  if (Status <> STATUS_INFO_LENGTH_MISMATCH) then Exit;
  GetMem(ObjectInformation, ReturnLength);
  try
    Status := NtQueryObject(hFile, ObjectNameInformation, ObjectInformation,
      ReturnLength, @ReturnLength);
    if (Status = STATUS_SUCCESS) then
    begin
      Result := ObjectInformation.Buffer;
      Result := DeviceNameToFilePath(Result);
    end;
  finally
    FreeMem(ObjectInformation);
  end;
end;
Vermutlich können damit auch die Namen anderer Handles ermittelt werden, allerdings habe ich dies nicht weiter getestet.

Viele Grüße
Zacherl
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)

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