Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Определение размера диска


Автор: Riply 5.6.2007, 05:44
Здравствуйте !
Допустим, мы берем диск ( например CD ) и тремя способами пробуем получить его "размер".
DeviceIoControl(..., IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, ...., PDISK_GEOMETRY_EX,.....
Size_Ex := PDISK_GEOMETRY_EX.DiskSize.QuadPart; // первый вариант
with PDISK_GEOMETRY_EX.Geometry do
 Size_Calc := Cylinders.QuadPart * TracksPerCylinder * SectorsPerTrack * BytesPerSector; // второй вариант
и
 GetDiskFreeSpaceEx(PChar('\\.\CdRom0\), ..., Size_Total, ...) // третий вариант
Сравниваем результаты:
Size_Calc = 725 614 592
Size_Total = 728 975 360
Size_Ex = 729 282 560
Объясните мне, пожалуйста, почему они различаются и что каждый из них под собой подразумевает ?
Почему отличается результат, полученный GetDiskFreeSpaceEx, еще, худо-бедно, 
предположить можно (служебная информация и все такое),
но почему различаются Size_Ex и Size_Calc, мне совсем непонятно :(
P.S. 
CD-диск взят как пример.
Для дискеты:
Size_Calc = 1 474 560
Size_Total = 1 457 664
Size_Ex = получить не удается из-за EX-кода.
Для флешки:
Size_Calc = 123 379 200
Size_Total = 124 559 360
Size_Ex = 125 829 120

Автор: Rennigth 7.6.2007, 17:09
Riply, 
Ну ты бы могла хоть структурки с константами описать... :( Ну это так, лирика, очень уж лениво было. smile

А так по сути топа,
накатал примерчик:
Код

const
  IOCTL_DISK_GET_DRIVE_GEOMETRY_EX = $000700A0;
type

  MEDIA_TYPE = (Unknown, F5_1Pt2_512, F3_1Pt44_512, F3_2Pt88_512, F3_20Pt8_512,
    F3_720_512, F5_360_512, F5_320_512, F5_320_1024, F5_180_512, F5_160_512,
    RemovableMedia, FixedMedia, F3_120M_512, F3_640_512, F5_640_512, F5_720_512,
    F3_1Pt2_512, F3_1Pt23_1024, F5_1Pt23_1024, F3_128Mb_512, F3_230Mb_512,
    F8_256_128, F3_200Mb_512, F3_240M_512, F3_32M_512);

  PDISK_GEOMETRY = ^DISK_GEOMETRY;
  DISK_GEOMETRY = record
    Cylinders: LARGE_INTEGER;
    MediaType: MEDIA_TYPE;
    TracksPerCylinder: DWORD;
    SectorsPerTrack: DWORD;
    BytesPerSector: DWORD;
  end;

  PDISK_GEOMETRY_EX = ^DISK_GEOMETRY_EX;
  DISK_GEOMETRY_EX = record
    Geometry: DISK_GEOMETRY;
    DiskSize: LARGE_INTEGER;
    Data: array [0..0] of Byte;
  end;

var
  hDrive: DWORD;
  pDiskGeometry: PDISK_GEOMETRY_EX;
  pOvrlppd: POVERLAPPED;
  nOutBufferSize: DWORD;
  lpBytesReturned: DWORD;
  lSize: Int64;
  lTotalFreeSize, lTotalSize, lAVSize: LARGE_INTEGER;
begin
  {$R-}
//  hDrive := CreateFile ('\\.\\PhysicalDrive0', GENERIC_READ,
  hDrive := CreateFile ('\\.\CdRom0', GENERIC_READ,
    FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
  if hDrive <> INVALID_HANDLE_VALUE then
  begin
    DeviceIoControl(hDrive, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, nil, 0,
      nil, 0, lpBytesReturned, nil); (* Get Size *)

    if (GetLastError = ERROR_INSUFFICIENT_BUFFER)then
    begin
      nOutBufferSize := lpBytesReturned;
      pDiskGeometry := GetMemory(nOutBufferSize);
      ZeroMemory(pDiskGeometry, nOutBufferSize);
      if DeviceIoControl(hDrive, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, nil, 0,
        pDiskGeometry, nOutBufferSize, lpBytesReturned, nil) then
      begin
        (* Вариант 1*)
        lSize := pDiskGeometry^.DiskSize.QuadPart;
        lstSizes.Items.Add(IntToStr(lSize));
        (* Вариант 2*)
        lSize := pDiskGeometry^.Geometry.Cylinders.QuadPart *
          pDiskGeometry^.Geometry.TracksPerCylinder *
          pDiskGeometry^.Geometry.SectorsPerTrack *
          pDiskGeometry^.Geometry.BytesPerSector;
        lstSizes.Items.Add(IntToStr(lSize));
        FreeMemory(pDiskGeometry);
      end else
      begin
        FreeMemory(pDiskGeometry);
        RaiseLastOSError;
      end;
  end else
    RaiseLastOSError;
  end;


  (* Вариант 3 *)
  if not Windows.GetDiskFreeSpaceEx(PChar('\\.\CdRom0\'), lAVSize, lTotalSize, @lTotalFreeSize) then
    RaiseLastOSError;
  lstSizes.Items.Add(IntToStr(lTotalSize.QuadPart));
end;


1й и 3й вариант у меня одинаковы. Почему отличается 2й будем думать... p.s. уже завтра.  smile  smile

Добавлено через 6 минут и 4 секунды
PSS: Пример не совсем удачный, непинайте если что  smile 

Автор: Rouse_ 7.6.2007, 23:40
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX для флопиков не перекрыт в драйвере. Ну а остальное очень хорошо описано в DDK в том-же месте откуда взяты сами константы DeviceIoControl запросов.

Автор: Riply 8.6.2007, 08:06
Цитата(Rennigth @  7.6.2007,  17:09 Найти цитируемый пост)
Ну ты бы могла хоть структурки с константами описать... 

Sorry.
Думала, если кто-то заинтересуется вопросом, то приведу.

Цитата(Rennigth @  7.6.2007,  17:09 Найти цитируемый пост)
1й и 3й вариант у меня одинаковы.

У меня на некоторых CD дисках, тоже совпадают, но не на всех. 

Цитата(Rouse_ @  7.6.2007,  23:40 Найти цитируемый пост)
Ну а остальное очень хорошо описано в DDK в том-же месте откуда взяты сами константы DeviceIoControl запросов. 

У мненя не получилось найти там пояснения, что подразумевается под "размером диска" smile 
 
И еще вопрос. Наблюдается такой эффект:
Иногда DeviceIoControl на Floppy (в основном на нем ставлю эксперименты) начинает выдавать 
ошибку: ERROR_MEDIA_CHANGED ( Media in drive may have changed. ) при любом Io - коде.
Лечится открыванием флоппика в Explorer-е. В чем может быть дело ?
P.S. Открываю с доступом только на чтение(ну и читаю, разумеется). 
Используемые команды в DeviceIoControl:
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
IOCTL_DISK_GET_PARTITION_INFO_EX, IOCTL_STORAGE_QUERY_PROPERTY, 
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS.



Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)