Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Dateiname zu FileHandle auslesen (https://www.delphipraxis.net/104370-dateiname-zu-filehandle-auslesen.html)

himitsu 2. Dez 2007 18:42


Dateiname zu FileHandle auslesen
 
mir war zwar so, als wenn's hier mal etwas dazu gab, aber hab irgendwie nichts gefunden -.-''

also, weiß zufällig wer wie ich aus einem FileHandle (CreateFile) den Dateinamen rausbekomm?
über MemoryMapping und GetModuleFilename ging's leider nicht.

ich wollte meinen Programmcode etwas aufräumen und daher
das auskommentierte MSDN-Library durchsuchenReOpenFile (da erst ab Vista) aktivieren und den Ersatzcode weglassen,
aber dafür bräuchte ich eine Möglichkeit um an den Dateinamen ranzukommen
um einen Vor-Vista-Ersatz schreiben zu können:
Code:
Var ReOpenFileW: Function (hOriginalFile: THandle;
  dwDesiredAccess, dwShareMode, dwFlags: LongWord): THandle; StdCall;

Function ReOpenFileW_(hOriginalFile: THandle;
  dwDesiredAccess, dwShareMode, dwFlags: LongWord): THandle; StdCall;

  Var FileName: WideString;
    lpSecurityAttributes: PSecurityAttributes;
    hTemplateFile: THandle;

  Begin
    FileName            := [color=red]FileHandleToFileName[/color](hOriginalFile);
    lpSecurityAttributes := nil; // diese Beiden müssen für mich nicht
    hTemplateFile       := 0;   // unbedingt ausgelesen werden

    CloseHandle(hOriginalFile);
    Result := CreateFileW(PWideChar(FileName), dwDesiredAccess, dwShareMode,
      lpSecurityAttributes, OPEN_EXISTING, dwFlags, hTemplateFile);
  End;

ReOpenFileW := GetProcAddress(GetModuleHandle('kernel32.dll'), 'ReOpenFileW');
If @ReOpenFileW = nil Then ReOpenFileW := @ReOpenFileW_;
Und nein, auch noch CreateFile/CloseHandle zu hooken und die Dateinamen/FileHandles zu speichern kommt nicht in Frage ... da laß ich es doch lieber so wie es jetzt ist.

turboPASCAL 2. Dez 2007 18:54

Re: Dateiname zu FileHandle auslesen
 
:gruebel: http://msdn2.microsoft.com/en-us/library/aa366789.aspx

Hilft dir das ggf. ?

marabu 2. Dez 2007 19:12

Re: Dateiname zu FileHandle auslesen
 
Hallo Frank,

es gibt eine undokumentierte API Funktion namens NTQueryInformationFile() für alle NT-basierten Kernel.

Grüße vom marabu

Wotan89 2. Dez 2007 19:20

Re: Dateiname zu FileHandle auslesen
 
Ich glaub eine Lösung wäre für dich GetModuleFileNameEx. Dazu musst du nur psapi in den uses einbinden.

himitsu 2. Dez 2007 19:54

Re: Dateiname zu FileHandle auslesen
 
Also abgesehn daß ich das mit dem GetMappedFileName noch nicht ganz zum laufen gebracht hatte, ginge es eh nicht, da CreateFileMapping nur mit Dateien funktioniert, welche mindestens über Leserechte verfügen,
aber meine Dateien (wo ich es aktuell bräuchte) sind nur mit Schreibrechten (GENERIC_WRITE) geöffnet/erstellt. :?
Bei GetModuleFileNameEx das Selbe.

Das mit MSDN-Library durchsuchenNTQueryInformationFile probier ich grad.

himitsu 2. Dez 2007 21:27

Re: Dateiname zu FileHandle auslesen
 
könnte bitte mal jemand den Wert für FileNameInformation posten?

laut MSDN irgendwo in wdm.h. Include wdm.h, ntddk.h oder ntifs.h

hab hier leider kein PSDK installiert :cry:


MSDN > ZwQueryInformationFile


so, hab's jetzt einfach durchprobiert und die 9 brachte gleich eine Lösung :stupid:

nur liefert ZwQueryInformationFile leider nur /pfad/datei ohne Laufwerksangabe :cry:

himitsu 3. Jan 2008 02:09

Re: Dateiname zu FileHandle auslesen
 
Liste der Anhänge anzeigen (Anzahl: 1)
So, hab inzwischen eine "Lösung" gefunden.

QueryInformationFile gibt mir Pfad+Dateiname

GetFileInformationByHandle rückt die Partition (VolumeSerialNumber) raus

dann werden noch die (hoffentlich alle nötigen) Laufwerke durchforstes
und die Gewünschten über ihre VolumeSerialNumber ausgewählt.

FileHandleToFileName ist eine eigene Funktion, welche den Dateinamen zurückgibt.
(KO, ein Array mit eventuell Mehreren, da eine Partition mehrfach gemountet sein kann und es auf diese Weise keine eindeutige Zuordnung gibt)

Delphi-Quellcode:
Function _ReOpenFileW(hOriginalFile: THandle; dwDesiredAccess, dwShareMode, dwFlags: LongWord): THandle; StdCall;
  Var ioSB: IO_STATUS_BLOCK;
    FNI: FILE_NAME_INFORMATION;
    BHFI: BY_HANDLE_FILE_INFORMATION;
    FileName, S, S2, S3: WideString;
    FileDrives: Array of WideString;
    lpSecurityAttributes: PSecurityAttributes;
    hTemplateFile: THandle;
    W, W2: LongWord;
    i: Integer;
    Sh: THandle;

  Begin
    Result := hOriginalFile;
    ZeroMemory(@FNI, SizeOf(FNI));
    If QueryInformationFile(hOriginalFile, ioSB, @FNI, SizeOf(FNI),
      FileNameInformation) <> STATUS_SUCCESS Then Exit;
    If not GetFileInformationByHandle(hOriginalFile, BHFI) Then Exit;
    FileName := Copy(FNI.FileName, 1, FNI.FileNameLength div 2);

    FileDrives := nil;
    SetLength(S, 1024); GetLogicalDriveStringsW(255, PChar(S)); S := Trim(S);
    While S <> '' do Begin
      S2 := PWideChar(S); Delete(S, 1, Length(S2)); S := Trim(S);
      If not GetVolumeInformationW(PWideChar(S2), nil, 0, @W, W2, W2, nil, 0)
        or (W <> BHFI.dwVolumeSerialNumber) Then Continue;
      i := Length(FileDrives); SetLength(FileDrives, i + 1); FileDrives[i] := S2;
    End;
    SetLength(S, MAX_PATH - 1); Sh := FindFirstVolumeW(PWideChar(S), MAX_PATH);
    If Sh <> INVALID_HANDLE_VALUE Then
      Repeat
        S := PWideChar(S);
        If not GetVolumeInformationW(PWideChar(S), nil, 0, @W, W2, W2, nil, 0)
          or (W <> BHFI.dwVolumeSerialNumber) Then Continue;
        W := 1024;
        GetVolumePathNamesForVolumeNameW(PWideChar(S), nil, 0, @W);
        SetLength(S2, W);
        If GetVolumePathNamesForVolumeNameW(PWideChar(S), PWideChar(S2), W + 1, @W) Then Begin
          SetLength(S2, W - 2);
          While S2 <> '' do Begin
            S3 := PWideChar(S2); Delete(S2, 1, Length(S3)); S2 := Trim(S2);
            i := Length(FileDrives); SetLength(FileDrives, i + 1); FileDrives[i] := S3;
          End;
        End;
        i := Length(FileDrives); SetLength(FileDrives, i + 1); FileDrives[i] := S;
        SetLength(S, MAX_PATH - 1);
      Until not FindNextVolumeW(Sh, PWideChar(S), MAX_PATH);
    FindVolumeClose(Sh);

    lpSecurityAttributes := nil;
    hTemplateFile       := 0;
    CloseHandle(hOriginalFile);

    Result := INVALID_HANDLE_VALUE;
    For i := 0 to High(FileDrives) do Begin
      Result := CreateFileW(PWideChar(FileDrives[i] + FileName), dwDesiredAccess,
        dwShareMode, lpSecurityAttributes, OPEN_EXISTING, dwFlags, hTemplateFile);
      If Result <> INVALID_HANDLE_VALUE Then Break;
    End;
  End;
im Angang ist 'nen Testprogramm mit
Delphi-Quellcode:
Function ReOpenFileW(hOriginalFile: THandle; dwDesiredAccess,
  dwShareMode, dwFlags: LongWord): THandle; StdCall;

Function FileHandleToFileName(hFile: THandle): TDynWideStringArray;
Infos:
ReOpenFile wurde in Vista eingeführt.
(die Ersatzfunktion funktioniert hoffentlich schon ab Win2Kpro)

FileHandleToFileName gibt den/die vollständigen Dateinamen der Datei (dem Handle) zurück.

GetVolumePathNamesForVolumeName wurde in WinXP eingeführt
(Ersatzfunktion ist also für Win2Kpro mit enthalten ... hab ich glaub'sch schonmal hier irgendwo veröffentlich :gruebel: )


Achtung
lpSecurityAttributes und hTemplateFile wird nicht übernommen,
hab noch nicht rausgefunden wie diese ausgelesen werden,
aber Meistens werden die eh nicht verwendet *duck*

Und dann weiß ich noch nicht ob der Dateizeiger in Vista übernommen wird.

Also wenn das mal bitte wer testen könnte?
Hab derzeit kein Vista installiert -.-''
> Testprogramm starten und auf die Ausgabe achten
(da wird eine Testdatei ausgelesen und die Zeigerpositionen angezeigt)


PS: die CompilerWarnung GetLogicalDriveStringsW+PAnsiChar einfach ignorieren ... ist schon richtig so
> Delphi - Bugreports > GetLogicalDriveStringsW und PAnsiChar


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:28 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