File size: 5,433 Bytes
afa0cbf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
use std::ffi::OsString;
use std::fs::OpenOptions;
use std::io;
use std::os::windows::ffi::OsStrExt;
use std::os::windows::ffi::OsStringExt;
use std::os::windows::fs::OpenOptionsExt;
use std::os::windows::io::AsRawHandle;
use std::path::Path;
use std::path::PathBuf;
use std::ptr;

use codex_git_utils::get_git_repo_root;
use os_info::Version;
use windows_sys::Win32::Foundation::ERROR_INVALID_PARAMETER;
use windows_sys::Win32::Storage::FileSystem::FILE_FLAG_BACKUP_SEMANTICS;
use windows_sys::Win32::Storage::FileSystem::FILE_READ_ATTRIBUTES;
use windows_sys::Win32::Storage::FileSystem::FILE_SHARE_READ;
use windows_sys::Win32::Storage::FileSystem::FILE_SHARE_WRITE;
use windows_sys::Win32::Storage::FileSystem::GetDriveTypeW;
use windows_sys::Win32::Storage::FileSystem::GetVolumePathNameW;
use windows_sys::Win32::System::IO::DeviceIoControl;
use windows_sys::Win32::System::WindowsProgramming::DRIVE_FIXED;
use windows_sys::Win32::System::WindowsProgramming::DRIVE_NO_ROOT_DIR;
use windows_sys::Win32::System::WindowsProgramming::DRIVE_UNKNOWN;

use super::CheckStatus;
use super::DoctorCheck;

const ID: &str = "git.worktree.dev_drive";
const DEV_VOLUME: u32 = 0x0000_2000;
const TRUSTED_VOLUME: u32 = 0x0000_4000;
const QUERY_PERSISTENT_VOLUME_STATE: u32 = 0x0009_023c;

#[repr(C)]
struct PersistentVolumeState {
    flags: u32,
    mask: u32,
    version: u32,
    reserved: u32,
}

pub(super) fn check(cwd: &Path) -> DoctorCheck {
    let Some(worktree) = get_git_repo_root(cwd) else {
        return DoctorCheck::new(ID, "git", CheckStatus::Ok, "no Git worktree is active");
    };
    if matches!(
        os_info::get().version(),
        Version::Semantic(_, _, build) if *build < 22_621
    ) {
        return DoctorCheck::new(
            ID,
            "git",
            CheckStatus::Ok,
            "Windows Dev Drives are unavailable on this Windows version",
        );
    }

    match volume_flags(&worktree) {
        Ok(flags) if flags & DEV_VOLUME == 0 => DoctorCheck::new(
            ID,
            "git",
            CheckStatus::Warning,
            "this worktree is not on a Windows Dev Drive; moving it to a trusted Dev Drive can significantly improve repository and filesystem performance",
        )
        .remediation(
            "create a trusted Windows Dev Drive for source repositories: https://learn.microsoft.com/en-us/windows/dev-drive/",
        ),
        Ok(flags) if flags & TRUSTED_VOLUME == 0 => DoctorCheck::new(
            ID,
            "git",
            CheckStatus::Warning,
            "the active Git worktree is on an untrusted Windows Dev Drive",
        )
        .remediation(
            "ask your administrator to trust the Windows Dev Drive: https://learn.microsoft.com/en-us/windows/dev-drive/#how-do-i-designate-a-dev-drive-as-trusted",
        ),
        Ok(_) => DoctorCheck::new(
            ID,
            "git",
            CheckStatus::Ok,
            "the active Git worktree is on a trusted Windows Dev Drive",
        ),
        Err(error) => DoctorCheck::new(
            ID,
            "git",
            CheckStatus::Warning,
            "the active Git worktree's Windows Dev Drive state could not be inspected",
        )
        .detail(format!("filesystem error: {:?}", error.kind()))
        .remediation("check access to the Git worktree and its Windows storage volume"),
    }
}

fn volume_flags(path: &Path) -> io::Result<u32> {
    let path = path
        .as_os_str()
        .encode_wide()
        .chain(std::iter::once(0))
        .collect::<Vec<_>>();
    let mut volume = vec![0_u16; path.len().max(261)];
    if unsafe { GetVolumePathNameW(path.as_ptr(), volume.as_mut_ptr(), volume.len() as u32) } == 0 {
        return Err(io::Error::last_os_error());
    }
    match unsafe { GetDriveTypeW(volume.as_ptr()) } {
        DRIVE_UNKNOWN | DRIVE_NO_ROOT_DIR => {
            return Err(io::Error::new(
                io::ErrorKind::NotFound,
                "the Windows storage volume could not be determined",
            ));
        }
        DRIVE_FIXED => {}
        _ => return Ok(0),
    }

    let length = volume
        .iter()
        .position(|character| *character == 0)
        .unwrap_or(volume.len());
    let root = PathBuf::from(OsString::from_wide(&volume[..length]));
    let handle = OpenOptions::new()
        .access_mode(FILE_READ_ATTRIBUTES)
        .share_mode(FILE_SHARE_READ | FILE_SHARE_WRITE)
        .custom_flags(FILE_FLAG_BACKUP_SEMANTICS)
        .open(root)?;
    let mut state = PersistentVolumeState {
        flags: 0,
        mask: DEV_VOLUME | TRUSTED_VOLUME,
        version: 1,
        reserved: 0,
    };
    let state_size = std::mem::size_of::<PersistentVolumeState>() as u32;
    let state_ptr = ptr::from_mut(&mut state);
    let mut bytes_returned = 0;
    if unsafe {
        DeviceIoControl(
            handle.as_raw_handle() as isize,
            QUERY_PERSISTENT_VOLUME_STATE,
            state_ptr.cast_const().cast(),
            state_size,
            state_ptr.cast(),
            state_size,
            &mut bytes_returned,
            ptr::null_mut(),
        )
    } == 0
    {
        let error = io::Error::last_os_error();
        return if error.raw_os_error() == Some(ERROR_INVALID_PARAMETER as i32) {
            Ok(0)
        } else {
            Err(error)
        };
    }

    Ok(state.flags)
}

#[cfg(test)]
#[path = "windows_dev_drive_tests.rs"]
mod tests;