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