Всем привет! Выпало чуток свободного времени, бесплатно напишу софт по вашему ТЗ/помогу скомпилить/исправить существующий софт. Все исходники будут выкладываться в теме.
enum DriveType {
SSD,
HDD,
}
struct PhysicalDrive {
partitions: Vec<LogicalDrive>,
_type: DriveType,
}
struct LogicalDrive {
mount: PathBuf
}
fn physical_drives() -> Vec<PhysicalDrive> {
todo!()
}
Возьмусь, скинь пример результата.Функция по получению списка физических дисков (PhysicalDrive) Windows.
Структура диска должна содержать тип диска и его разделы (LogicalDrive).
Знаю, что раздел и LogicalDrive не одно и тоже, но в данном контексте можно пренебречь этой неточностью.
Код:enum DriveType { SSD, HDD, } struct PhysicalDrive { partitions: Vec<LogicalDrive>, _type: DriveType, } struct LogicalDrive { mount: PathBuf } fn physical_drives() -> Vec<PhysicalDrive> { todo!() }
Не надеюсь, что ты будешь этим заниматься, если честно)
[
PhysicalDrive {
partitions: [
LogicalDrive {
mount: "C:/",
},
LogicalDrive {
mount: "D:/",
},
],
_type: SSD,
},
PhysicalDrive {
partitions: [
LogicalDrive {
mount: "E:/",
},
],
_type: HDD,
},
]
Вроде как нужно получить все логические диски (GetLogicalDrives()/GetLogicalDrivesStringsW(...)), получить хэндл \\.\{disk_letter}: (с правами админа) и далее DeviceIoControl(...) - но не пойму какие control codes нужны для получения инфы о разделах?Что-то такого плана:
Код:[ PhysicalDrive { partitions: [ LogicalDrive { mount: "C:/", }, LogicalDrive { mount: "D:/", }, ], _type: SSD, }, PhysicalDrive { partitions: [ LogicalDrive { mount: "E:/", }, ], _type: HDD, }, ]
То есть нужно понять какие в системе есть физические диски и какие разделы к ним привязанны.
Вроде как нужно получить все логические диски (GetLogicalDrives()/GetLogicalDrivesStringsW(...)), получить хэндл \\.\{disk_letter}: (с правами админа) и далее DeviceIoControl(...) - но не пойму какие control codes нужны для получения инфы о разделах?
use windows_sys::Win32::Devices::DeviceAndDriverInstallation::{
DIGCF_DEVICEINTERFACE, DIGCF_PRESENT, SP_DEVICE_INTERFACE_DATA,
SP_DEVICE_INTERFACE_DETAIL_DATA_W, SetupDiGetClassDevsW,
SetupDiEnumDeviceInterfaces, SetupDiGetDeviceInterfaceDetailW
};
use windows_sys::Win32::Foundation::{
FALSE, INVALID_HANDLE_VALUE, ERROR_INSUFFICIENT_BUFFER,
GENERIC_READ, BOOL, HANDLE, CloseHandle
};
use windows_sys::Win32::System::Ioctl::{
GUID_DEVINTERFACE_DISK, IOCTL_STORAGE_GET_DEVICE_NUMBER,
STORAGE_DEVICE_NUMBER, IOCTL_DISK_GET_DRIVE_LAYOUT_EX
};
use windows_sys::Win32::System::IO::DeviceIoControl;
use windows_sys::Win32::Storage::FileSystem::{
FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_SHARE_WRITE,
OPEN_EXISTING, CreateFileW
};
use std::path::PathBuf;
use std::ptr;
use std::mem;
use std::io;
pub struct PhysicalDrive {
partitions: Vec<LogicalDrive>
}
pub struct LogicalDrive {
mount: Option<PathBuf>
}
pub fn local() -> io::Result<Vec<PhysicalDrive>> {
let disk_class_devices = unsafe {
SetupDiGetClassDevsW(
&GUID_DEVINTERFACE_DISK,
ptr::null(),
0,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
)
};
if disk_class_devices == INVALID_HANDLE_VALUE {
return Err(io::Error::last_os_error())
}
let mut device_iface_data = SP_DEVICE_INTERFACE_DATA {
cbSize: mem::size_of::<SP_DEVICE_INTERFACE_DATA>() as u32,
..unsafe { mem::zeroed() }
};
for device_index in 0.. {
if cvt(unsafe {
SetupDiEnumDeviceInterfaces(
disk_class_devices,
ptr::null(),
&GUID_DEVINTERFACE_DISK,
device_index,
&mut device_iface_data
)
}).is_err() {
break
}
let mut required_size = 0;
if let Err(e) = cvt(unsafe {
SetupDiGetDeviceInterfaceDetailW(
disk_class_devices,
&device_iface_data,
ptr::null_mut(),
0,
&mut required_size,
ptr::null_mut(),
)
}) {
let err = e.raw_os_error()
.map(|raw| raw as u32 != ERROR_INSUFFICIENT_BUFFER)
.unwrap_or(false);
if err {
return Err(e);
}
}
let align = mem::align_of::<SP_DEVICE_INTERFACE_DETAIL_DATA_W>();
let buf_size = required_size as usize + align - 1;
let mut buf = Vec::<u8>::with_capacity(buf_size);
let offset = buf.as_mut_ptr().align_offset(align);
let device_iface_detail = unsafe {
&mut *(buf.as_mut_ptr().offset(offset as isize)
as *mut mem::MaybeUninit<SP_DEVICE_INTERFACE_DETAIL_DATA_W>)
};
device_iface_detail.write(
SP_DEVICE_INTERFACE_DETAIL_DATA_W {
cbSize: mem::size_of::<SP_DEVICE_INTERFACE_DETAIL_DATA_W>() as u32,
DevicePath: [0],
}
);
cvt(unsafe {
SetupDiGetDeviceInterfaceDetailW(
disk_class_devices,
&device_iface_data,
device_iface_detail.as_mut_ptr(),
required_size,
ptr::null_mut(),
ptr::null_mut()
)
})?;
let path = ptr::addr_of! (
unsafe { device_iface_detail.assume_init_ref() }.DevicePath[0]
);
let storage = Handle::new(unsafe {
CreateFileW(
path,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
ptr::null(),
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0
)
})?;
let mut number = unsafe {
mem::zeroed::<STORAGE_DEVICE_NUMBER>()
};
let mut bytes_returned = 0;
cvt(unsafe {
DeviceIoControl(
storage.raw(),
IOCTL_STORAGE_GET_DEVICE_NUMBER,
ptr::null(),
0,
&mut number as *const _ as _,
mem::size_of::<STORAGE_DEVICE_NUMBER>() as u32,
&mut bytes_returned,
ptr::null_mut()
)
})?;
dbg!(number.DeviceNumber);
}
todo!()
}
struct Handle(HANDLE);
impl Handle {
fn new(handle: HANDLE) -> io::Result<Self> {
if handle == INVALID_HANDLE_VALUE {
Err(io::Error::last_os_error())
} else {
Ok(Handle(handle))
}
}
fn raw(&self) -> HANDLE {
self.0
}
}
impl Drop for Handle {
fn drop(&mut self) {
unsafe { CloseHandle(self.0) };
}
}
fn cvt(status: BOOL) -> io::Result<BOOL> {
if status == FALSE {
Err(io::Error::last_os_error())
} else {
Ok(status)
}
}
Это полезно, спасибо. Вы случайно не знаете, как можно определить программный/аппаратный рейд?Тип диска HDD/SSD безошибочно (и с малой кровью) можно получить несколькоми способами
"IOCTL_STORAGE_QUERY_PROPERTY" с флагом PropertyId =0 (StorageDeviceProperty).как можно определить программный/аппаратный рейд?
;// http://msdn.microsoft.com/en-us/library/aa363465(VS.85).aspx
;// Константы "STORAGE_BUS_TYPE" ===============================
;//=============================================================
BusTypeUnknown = 0
BusTypeScsi = 1
BusTypeAtapi = 2
BusTypeAta = 3
BusType1394 = 4
BusTypeSsa = 5
BusTypeFibre = 6
BusTypeUsb = 7
BusTypeRAID = 8
BusTypeiSCSI = 9
BusTypeSas = 10
BusTypeSata = 11
BusTypeSd = 12
BusTypeMmc = 13
BusTypeVirtual = 14
BusTypeSpaces = 16
BusTypeNvme = 17
BusTypeSCM = 18
BusTypeUfs = 19
BusTypeMaxReserved = 127
У меня нет дисков SSD, а потому проверить варианты не могу.Это полезно, спасибо.
У меня нет дисков SSD, а потому проверить варианты не могу.
Если у вас сработает хоть какой-то из способов определения SSD/RAID, то просьба отписаться.
Ты язык Solidity помимо Rust, понимаешь? В плане смарт-контрактов и ботов.Да, можешь скинуть код, гляну.
Нет, только раст. С Solidity не было опыта.Ты язык Solidity помимо Rust, понимаешь? В плане смарт-контрактов и ботов.
Жалко.Нет, только раст. С Solidity не было опыта.
Напишу - поддержка каких систем нужна? Какие-либо пожелания по функционалу?Блин интересно как ты напишешь утилиту которая делает скриншот и сохраняет его в данное пользывателем из команднай строки месте.
учти утилита должна не откревать акошка или как либо показываться ползевателю
планиревал для 10ки можно и 11 а там посмотрим.Напишу - поддержка каких систем нужна? Какие-либо пожелания по функционалу?
Не уверен, что это реализуемо. Если только копировать бинарник к пользователю, добавлять там в авторан, который отработает при входе юзера (планировщик, например).- имперсанацу пользывателя делала (чтобе админ мог скриншотить других пользыватели на компе).
build.bat. В архиве есть скомпилированная версия. Usage: win-screen.exe [options]
-h - print help (this message)
-o "%USERPROFILE%\AppData\some_solder" - output folder for saving screens
-i 5000 - screen interval in milliseconds
-f jpg|jpeg|png|gif|bmp - screen format
-u user_name:user_password - run win-screen.exe on other user // unimplemented
~/xss.pro