Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#7

Re: Dateiname zu FileHandle auslesen

  Alt 3. Jan 2008, 03:09
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 )


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
Angehängte Dateien
Dateityp: 7z reopenfile_180.7z (26,8 KB, 28x aufgerufen)
$2B or not $2B
  Mit Zitat antworten Zitat