Конференция "WinAPI" » знать PhysicalDrive по имени диска
 
  • DevilDevil © (17.02.13 17:36) [0]
    Есть например логический диск "C" или "E"

    нужно определить номер физического диска, соответствующего этой букве
    спасибо
  • DVM © (17.02.13 18:10) [1]
    DeviceIoControl + IOCTL_STORAGE_GET_DEVICE_NUMBER ?
  • DevilDevil © (17.02.13 18:30) [2]
    > DVM ©   (17.02.13 18:10) [1]

    привет
    приведи пожалуйста более полный код
    я знаю, у тебя дофига опыта работы с внутренностями Windows )
  • brother © (17.02.13 19:09) [3]
    procedure _GetLogicalDrives;
    var
     max: byte;
     ld: DWORD;
     i: integer;
     letter: string;
     hDevice,
     BytesReturned: DWord;
     DeviceInfo: Packed Record
       DeviceType,
       DeviceNumber,
       PartitionNumber: DWord;
     End;
     VolumeName: array [0..MAX_PATH-1] of Char;
     FileSystemName     : array [0..MAX_PATH-1] of Char;
     VolumeSerialNo     : DWord;
     MaxComponentLength : DWord;
     FileSystemFlags    : DWord;
    begin
     SetLength(LogicalDrives, 0);
     ld := GetLogicalDrives;
     for i := 0 to 25 do
       if (ld and (1 shl i)) <> 0 then
       begin
         SetLength(LogicalDrives, High(LogicalDrives)+2);
         letter:= Char(Ord('A') + i) + ':';
         max:= High(LogicalDrives);
         LogicalDrives[max].Letter:= letter[1];

         SplashForm.LoadProgress('Iieo?aai eioi?iaoe? ii aeneo ' + letter);

         //
         ZeroMemory(@DeviceInfo, SizeOf(DeviceInfo));
         hDevice := CreateFile(PChar('\\.\' + letter), GENERIC_READ,
           FILE_SHARE_READ, Nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
         if (hDevice <> INVALID_HANDLE_VALUE) and DeviceIoControl(hDevice,
           IOCTL_STORAGE_GET_DEVICE_NUMBER, Nil, 0, @DeviceInfo,
           SizeOf(DeviceInfo), BytesReturned, Nil) Then
         begin
           LogicalDrives[max].DeviceType:= DeviceInfo.DeviceType;
           LogicalDrives[max].DeviceNumber:= DeviceInfo.DeviceNumber;
           LogicalDrives[max].PartitionNumber:= DeviceInfo.PartitionNumber;
           CloseHandle(hDevice);
         end
         else
         begin
    //        ShowMessage(SysErrorMessage(GetLastError));
           LogicalDrives[max].Error:= True;
         end;

         //
         if not Windows.GetDiskFreeSpaceEx(PChar(letter), LogicalDrives[max].FreeBytesAvailableToCaller,
           LogicalDrives[max].TotalNumberOfBytes, @LogicalDrives[max].TotalNumberOfFreeBytes) then LogicalDrives[max].Error:= True;

         //
         if Windows.GetVolumeInformation(PChar(letter + '\'), VolumeName, MAX_PATH, @VolumeSerialNo, MaxComponentLength,
           FileSystemFlags, FileSystemName, MAX_PATH) then
         begin
          LogicalDrives[max].SerialNo:= IntToHex(Integer(VolumeSerialNo), 8);
          LogicalDrives[max].Name:= VolumeName;
         end
         else
           LogicalDrives[max].Error:= True;

           
       end;
    end;


    выдирай нужное
  • DVM © (17.02.13 19:12) [4]

    > DevilDevil ©   (17.02.13 18:30) [2]

    как то так:


    function GetDeviceNumberByLetter(ALetter: Char): Integer;
    const
     IOCTL_STORAGE_GET_DEVICE_NUMBER = $2D1080;
    type
     TDeviceInfo = packed record
       DeviceType, DeviceNumber, PartitionNumber :dword
     end;
    var
     hDevice: THandle;
     BytesReturned: DWORD;
     DeviceInfo: TDeviceInfo;
    begin
     Result  := -1;
     hDevice := CreateFile(PChar('\\.\' + ALetter + ':'), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
     Win32Check(hDevice <> INVALID_HANDLE_VALUE);
     try
       Win32Check(DeviceIoControl(hDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER, nil, 0, @DeviceInfo, SizeOf(TDeviceInfo), BytesReturned, nil));
       Result := DeviceInfo.DeviceNumber;
     finally
       CloseHandle(hDevice);
     end;
    end;



    Но в обязательном порядке будет требовать запуска под Администратором.
    Для съемных дисков там по другому несколько.
  • brother © (17.02.13 19:14) [5]
    обращаю внимание на
    DeviceInfo.PartitionNumber

  • DevilDevil © (17.02.13 19:26) [6]
    > brother ©   (17.02.13 19:14) [5]

    спасибо !
    а почему DeviceInfo.PartitionNumber ?
  • DevilDevil © (17.02.13 19:26) [7]
    > DVM ©   (17.02.13 19:12) [4]

    я ж говорил, ты профи )
    да, спасибо, работает.
    сейчас возьму именно этот вариант
  • brother © (17.02.13 19:28) [8]
    > а почему DeviceInfo.PartitionNumber ?

    на устройстве может быть несколько партиций, контролируй этот момент...
  • DevilDevil © (17.02.13 19:51) [9]
    > brother ©   (17.02.13 19:28) [8]

    мне надо именно DeviceNumber
    спасиб
  • Pavia © (17.02.13 19:52) [10]
    Кстати одной букве может соответствовать несколько физических дисков.  Правда это редкость.
  • Pavia © (17.02.13 19:57) [11]
    Составной том - это динамический том, состоящий из дискового пространства на нескольких физических дисках.
  • Inovet © (17.02.13 19:59) [12]
    > [11] Pavia ©   (17.02.13 19:57)

    Ну так ещё в папку можно назначить диск.
  • DevilDevil © (17.02.13 20:00) [13]
    > Pavia ©

    прикольно )
  • DVM © (17.02.13 21:37) [14]

    > Pavia ©   (17.02.13 19:57) [11]
    > Составной том - это динамический том, состоящий из дискового
    > пространства на нескольких физических дисках.

    этот составной том, как и raid массив считается одним физическим диском для системы
  • brother © (19.02.13 13:10) [15]
    кстати,
    IOCTL_STORAGE_GET_DEVICE_NUMBER


    не определяет для диска C: (диск занят) ...
  • DVM © (19.02.13 14:10) [16]

    > brother ©   (19.02.13 13:10) [15]

    у меня определяет (Win7), запускай под админом явно.
  • brother © (19.02.13 15:22) [17]
    w7x64 d7 в коде
    ZeroMemory(@DeviceInfo, SizeOf(DeviceInfo));
         hDevice := CreateFile(PChar('\\.\' + letter), GENERIC_READ,
           FILE_SHARE_READ, Nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
         if (hDevice <> INVALID_HANDLE_VALUE) and DeviceIoControl(hDevice,
           IOCTL_STORAGE_GET_DEVICE_NUMBER, Nil, 0, @DeviceInfo,
           SizeOf(DeviceInfo), BytesReturned, Nil) Then
         begin
           LogicalDrives[max].DeviceType:= DeviceInfo.DeviceType;
           LogicalDrives[max].DeviceNumber:= DeviceInfo.DeviceNumber;
           LogicalDrives[max].PartitionNumber:= DeviceInfo.PartitionNumber;
           CloseHandle(hDevice);
         end
         else
         begin
           ShowMessage(SysErrorMessage(GetLastError));
           LogicalDrives[max].Error:= True;
         end;


    ругается: процесс не может получить доступ к файлу, тк этот файл занят другим процессом
    запускаю явно от админа
  • DVM © (19.02.13 17:32) [18]

    > brother ©   (19.02.13 15:22) [17]

    а если FILE_ATTRIBUTE_NORMAL убрать? И после letter двоеточие есть?
  • brother © (19.02.13 18:32) [19]
    > а если FILE_ATTRIBUTE_NORMAL убрать?

    тоже(

    > И после letter двоеточие есть?

    да, остальные диски открываются нормально...
    исходники: http://brotherirk.narod.ru/temp/1.rar
  • igen (07.10.15 14:52) [20]
    Можно через WMI класс Win32_LogicalDiskToPartition (без прав админа!), работает даже на XP, хотя MSDN говорит, что провайдер WMI_Storage для Windows XP не реализован.
    Класс выдаёт инфу в таком виде:

    Antecedent                                                             Dependent                                         EndingAddress  StartingAddress
    \\ST4\root\cimv2:Win32_DiskPartition.DeviceID="Disk #1, Partition #1"  \\ST4\root\cimv2:Win32_LogicalDisk.DeviceID="C:"  86754983935    105906176
    \\ST4\root\cimv2:Win32_DiskPartition.DeviceID="Disk #1, Partition #2"  \\ST4\root\cimv2:Win32_LogicalDisk.DeviceID="D:"  250058113023   86754983936
    \\ST4\root\cimv2:Win32_DiskPartition.DeviceID="Disk #0, Partition #0"  \\ST4\root\cimv2:Win32_LogicalDisk.DeviceID="V:"  80025223167    1048576


    Если пугают дебри WMI можно воспользоваться утилитой для генерации WMI кода https://github.com/RRUZ/wmi-delphi-code-creator или просто распарсить командную строку, введя команду wmic.exe (первый запуск на компе может занимать около минуты), затем
    path Win32_LogicalDiskToPartition

  • DayGaykin © (18.10.15 17:23) [21]
    Я делал так:
    1. GetVolumePathName. Получаем точку монтирования по пути.
    2. GetVolumeNameForVolumeMountPoint. Получаем имя раздела.
    3. GetPhysicalDisk. Получаем номер физического диска.

    Права админа не требовались.


    function FindFirstVolume(lpszVolumeName: PChar; cchBufferLength: DWORD): THandle; stdcall external Kernel32 name 'FindFirstVolumeA';
    function FindNextVolume(hFindVolume:THandle; lpszVolumeName: PChar; cchBufferLength: DWORD): BOOL; stdcall external Kernel32 name 'FindNextVolumeA';
    function FindVolumeClose(hFindVolume:THandle): BOOL; stdcall external Kernel32 name 'FindVolumeClose';
    function FindFirstVolumeMountPoint(lpszRootPathName, lpszVolumeMountPoint: PChar; cchBufferLength: DWORD): THandle; stdcall external Kernel32 name 'FindFirstVolumeMountPointA';
    function FindNextVolumeMountPoint(hFindVolumeMountPoint:THandle; lpszVolumeMountPoint: PChar; cchBufferLength: DWORD): BOOL; stdcall external Kernel32 name 'FindNextVolumeMountPointA';
    function FindVolumeMountPointClose(hFindVolumeMountPoint:THandle): BOOL; stdcall external Kernel32 name 'FindVolumeMountPointClose';
    function GetVolumePathName(lpszFileName:LPCTSTR; lpszVolumePathName:LPTSTR; cchBufferLength:DWORD): BOOL; stdcall external Kernel32 name 'GetVolumePathNameA';
    function GetVolumePathNamesForVolumeName(lpszVolumeName: LPCTSTR;lpszVolumePathNames: LPTSTR;cchBufferLength: DWORD;lpcchReturnLength:PDWORD):BOOL; stdcall external Kernel32 name 'GetVolumePathNamesForVolumeNameA';
    function GetVolumeNameForVolumeMountPoint(lpszVolumeMountPoint: LPCTSTR;lpszVolumeName: LPTSTR;cchBufferLength: DWORD): BOOL; stdcall external Kernel32 name 'GetVolumeNameForVolumeMountPointA';

    function GetPhysicalDisk(Partition: String): Integer;
    type
     _STORAGE_DEVICE_NUMBER = record
       DeviceType: ULONG;
       DeviceNumber: ULONG;
       PartitionNumber: ULONG;
     end;
    const
     IOCTL_STORAGE_GET_DEVICE_NUMBER = $2D1080;
    var
     F: THandle;
     Info: _STORAGE_DEVICE_NUMBER;
     Dummy: DWORD;
    begin
     F := CreateFile(PChar(ExcludeTrailingPathDelimiter(Partition)), 0, FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
     Win32Check(F <> INVALID_HANDLE_VALUE);
     try
       Win32Check(DeviceIoControl(F, IOCTL_STORAGE_GET_DEVICE_NUMBER, nil, 0, @Info, SizeOf(Info), Dummy, nil));
       Result := Info.DeviceNumber;
     finally
       CloseHandle(F);
     end;
    end;
  • brother © (18.10.15 20:52) [22]
    некрофилы) но возможно пригодится
 
Конференция "WinAPI" » знать PhysicalDrive по имени диска
Есть новые Нет новых   [134427   +35][b:0][p:0.004]