-
Есть например логический диск "C" или "E"
нужно определить номер физического диска, соответствующего этой букве спасибо
-
DeviceIoControl + IOCTL_STORAGE_GET_DEVICE_NUMBER ?
-
> DVM © (17.02.13 18:10) [1]
привет приведи пожалуйста более полный код я знаю, у тебя дофига опыта работы с внутренностями Windows )
-
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
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; выдирай нужное
-
> 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;
Но в обязательном порядке будет требовать запуска под Администратором. Для съемных дисков там по другому несколько.
-
обращаю внимание на DeviceInfo.PartitionNumber
-
> brother © (17.02.13 19:14) [5]
спасибо ! а почему DeviceInfo.PartitionNumber ?
-
> DVM © (17.02.13 19:12) [4]
я ж говорил, ты профи ) да, спасибо, работает. сейчас возьму именно этот вариант
-
> а почему DeviceInfo.PartitionNumber ?
на устройстве может быть несколько партиций, контролируй этот момент...
-
> brother © (17.02.13 19:28) [8]
мне надо именно DeviceNumber спасиб
-
Кстати одной букве может соответствовать несколько физических дисков. Правда это редкость.
-
Составной том - это динамический том, состоящий из дискового пространства на нескольких физических дисках.
-
> [11] Pavia © (17.02.13 19:57)
Ну так ещё в папку можно назначить диск.
-
> Pavia ©
прикольно )
-
> Pavia © (17.02.13 19:57) [11] > Составной том - это динамический том, состоящий из дискового > пространства на нескольких физических дисках.
этот составной том, как и raid массив считается одним физическим диском для системы
-
кстати, IOCTL_STORAGE_GET_DEVICE_NUMBER не определяет для диска C: (диск занят) ...
-
> brother © (19.02.13 13:10) [15]
у меня определяет (Win7), запускай под админом явно.
-
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; ругается: процесс не может получить доступ к файлу, тк этот файл занят другим процессом запускаю явно от админа
-
> brother © (19.02.13 15:22) [17]
а если FILE_ATTRIBUTE_NORMAL убрать? И после letter двоеточие есть?
-
-
Можно через 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
-
Я делал так: 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;
-
некрофилы) но возможно пригодится
|