Конференция "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
 
Конференция "WinAPI" » знать PhysicalDrive по имени диска
Есть новые Нет новых   [134427   +34][b:0][p:0.003]