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 GetVolumePathNamesForVolume (https://www.delphipraxis.net/74385-getvolumepathnamesforvolume.html)

himitsu 2. Aug 2006 13:10


GetVolumePathNamesForVolume
 
hab hier mal 'nen WorkAround für GetVolumePathNamesForVolumeNameW, welches ja erst seit WinXP vorhanden ist,
ist nicht perfekt und das Ergebnis is och nich ganz zu 100% identisch mit dem Original, aber es müßte zumindestens "voll" kompatibel sein. :)


Wie die meisten unktionen aus diesem Bereich des VolumeManagements ist(sollte) dieses ab Windows 2000 Professional lauffähig.

Delphi-Quellcode:
  Function _GetVolumePathNamesForVolumeNameW(VolumeName, VolumePathNames: PWideChar; BufferLength: LongWord; ReturnLength: PLongWord): LongBool; StdCall;
    Var LogicalDriveStrings, SearchBuffer, ResultS: WideString;
      ResultBuffer: Array[0..MAX_VOLUMENAME-1] of WideChar;

    Procedure SearchRecursiv(Const SearchBuffer2: WideString);
      Var SearchHandle: THandle;
        SearchBuffer3: WideString;

      Begin
        SearchHandle := FindFirstVolumeMountPointW(@ResultBuffer, @ResultBuffer, MAX_VOLUMENAME);
        If SearchHandle = INVALID_HANDLE_VALUE Then Exit;
        Repeat
          SearchBuffer3 := SearchBuffer2 + ResultBuffer;
          If GetVolumeNameForVolumeMountPointW(PWideChar(SearchBuffer3), @ResultBuffer, MAX_VOLUMENAME) Then Begin
            If CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, VolumeName, -1, @ResultBuffer, -1) = 2 Then
              ResultS := ResultS + Copy(SearchBuffer3, 5, MAX_PATH) + #0;
            SearchRecursiv(SearchBuffer3);
          End;
        Until not FindNextVolumeMountPointW(SearchHandle, @ResultBuffer, MAX_VOLUMENAME);
        FindVolumeMountPointClose(SearchHandle);
      End;

    Begin
      ResultS := '';
      SetLength(LogicalDriveStrings, GetLogicalDriveStringsW(0, nil));
      GetLogicalDriveStringsW(255, @LogicalDriveStrings[1]);
      LogicalDriveStrings := Trim(LogicalDriveStrings);
      While LogicalDriveStrings <> '' do Begin
        SearchBuffer := '\\.\' + PWideChar(LogicalDriveStrings);
        Delete(LogicalDriveStrings, 1, Length(SearchBuffer) - 4);
        LogicalDriveStrings := TrimLeft(LogicalDriveStrings);
        If (SearchBuffer[5] <= 'B') and (SearchBuffer[6] = ':') Then Continue;
        If GetVolumeNameForVolumeMountPointW(PWideChar(SearchBuffer), @ResultBuffer, MAX_VOLUMENAME) Then Begin
          If CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, VolumeName, -1, @ResultBuffer, -1) = 2 Then
            ResultS := ResultS + Copy(SearchBuffer, 5, MAX_PATH) + #0;
          SearchRecursiv(SearchBuffer);
        End;
      End;
      ResultS := ResultS + #0;
      If (BufferLength >= LongWord(Length(ResultS))) and (VolumePathNames <> nil) Then Begin
        Move(ResultS[1], VolumePathNames^, 2*Length(ResultS));
        If ReturnLength <> nil Then ReturnLength^ := Length(ResultS);
        Result := True;
      End Else If (BufferLength = 0) and (VolumePathNames = nil) Then Begin
        If ReturnLength <> nil Then ReturnLength^ := Length(ResultS);
        Result := True;
      End Else Begin
        If VolumePathNames <> nil Then VolumePathNames^ := #0;
        If ReturnLength <> nil Then ReturnLength^ := 1;
        Result := False;
      End;
    End;

Dieses If (SearchBuffer[5] <= 'B') and (SearchBuffer[6] = ':') Then Continue; müßte eigentlich raus, aber dann fragt GetVolumeNameForVolumeMountPointW immer nach 'ner Diskette, wenn grad keine im Laufwerk ist.

Wer Verbesserungsvorschläge hat, oder Fehler im Code findet, sollte sich bitte mal melden ._.


Eingebunden hab ich es so,
Delphi-Quellcode:
Var GetVolumePathNamesForVolumeNameW: Function(VolumeName, VolumePathNames: PWideChar;
  BufferLength: LongWord; ReturnLength: PLongWord): LongBool; StdCall;
statt GetVolumePathNamesForVolumeName direkt aus der API aufrurufen:
Delphi-Quellcode:
Function GetVolumePathNamesForVolumeNameW(VolumeName, VolumePathNames: PWideChar;
  BufferLength: LongWord; ReturnLength: PLongWord): LongBool; StdCall;
  External 'kernel32.dll' Name 'GetVolumePathNamesForVolumeNameW';
Und dann natürlich noch die passende Initialization:
(ab WinXP wird ja das Original gefunden und initialisiert ... davor (Win2000 Pro) kann wird halt meine Funktion verwendet.
Delphi-Quellcode:
Initialization
  GetVolumePathNamesForVolumeNameW := GetProcAddress(GetModuleHandle('kernel32.dll'), 'GetVolumePathNamesForVolumeNameW');
  If @GetVolumePathNamesForVolumeNameW = nil Then
    GetVolumePathNamesForVolumeNameW := @_GetVolumePathNamesForVolumeNameW;

End.
Die kernel32.dll ist meist eh schon geladen, also man braucht sich nur das passende Handle mit GetModuleHandle zubesorgen.
Und Freigeben braucht man somit dann auch nichts. :mrgreen:



PS: für eine AnsiVersion braucht man halt nur die ganzen "Wide" durch "Ansi" und die "W(" durch "A(" zu ersetzen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:01 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz