win-drives 0.1.0

Low-level access to Windows physical drives and harddisk volumes via NT APIs, with no_std support

# Win drivers


[![Build Status](https://github.com/Jozefpodlecki/win-drives/actions/workflows/ci.yml/badge.svg)](https://github.com/Jozefpodlecki/win-drives/actions)
[![Crates.io](https://img.shields.io/crates/v/win-drives.svg)](https://crates.io/crates/win-drives)
[![Rust](https://img.shields.io/badge/rust-1.85.0%2B-blue.svg?maxAge=3600)](https://github.com/Jozefpodlecki/win-drives)

A low-level wrapper around Windows NT APIs for opening and inspecting
**physical drives** and **harddisk volumes** with `NtCreateFile`, `NtDeviceIoControlFile`, and
`NtReadFile`.

> ⚠️ **Administrator privileges required.**
> Opening `\\.\PhysicalDriveN` and `\\.\HarddiskVolumeN` requires the process to run
> **elevated**.
> Without it, `open` returns `DriverError::Permission` and every example
> below will fail.

## Examples


### Enumerate physical drives


```rust
use win_drives::PhysicalDrive;

fn main() {
    for drive in PhysicalDrive::enumerate() {
        println!("{drive:?}");
        println!("{:?}", drive.device_number());
    }
}
```

```rust
use win_drives::PhysicalDrive;

fn main() -> Result<(), win_drives::DriverError> {
    let drive = PhysicalDrive::open(0)?;

    let bps = drive.bytes_per_sector();
    assert!(bps.is_power_of_two());
    assert!(matches!(bps, 512 | 1024 | 2048 | 4096));

    println!("cylinders:          {}", drive.cylinders());
    println!("tracks_per_cylinder: {}", drive.tracks_per_cylinder());
    println!("sectors_per_track:  {}", drive.sectors_per_track());
    println!("bytes_per_sector:   {}", bps);
    println!("size:               {} bytes", drive.size());
    println!("media_type:         {}", drive.media_type());

    Ok(())
}
```

### Read a sector from a volume


```rust
use win_drives::HarddiskVolume;

fn main() -> Result<(), win_drives::DriverError> {
    let mut vol = HarddiskVolume::open(1)?;
    let sector = vol.bytes_per_sector() as usize;

    let mut buf = vec![0u8; sector];
    let n = vol.read_at(0, &mut buf)?;
    assert_eq!(n, sector);

    // NTFS boot sectors carry the OEM ID "NTFS    " at offset 3.
    // FAT32 uses "FAT32   ", exFAT uses "EXFAT   ", etc.
    println!("OEM ID: {:?}", &buf[3..11]);

    Ok(())
}
```