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
use crate::Result;
use nom::bytes::complete::take;
use nom::number::complete::{le_u16, le_u8};

#[derive(Clone, Debug, Default, PartialEq)]
pub struct Version {
    pub major: u8,
    pub minor: u8,
    pub build: u16,
    pub revision: u8,
}

impl Version {
    pub fn new(major: u8, minor: u8, build: u16, revision: u8) -> Self {
        return Self {
            major,
            minor,
            build,
            revision,
        };
    }

    /// Creates a Windows 7 version with the given build.
    pub fn windows7(build: u16) -> Self {
        return Self::new(6, 1, build, 15);
    }

    /// Creates a Windows 7 version with the build 7601.
    pub fn windows7_7601() -> Self {
        return Self::windows7(7601);
    }

    /// Return the Operating Systems names that match with the version.
    pub fn os_names(&self) -> Vec<&'static str> {
        match (self.major, self.minor) {
            (10, 0) => {
                vec!["Windows 10", "Windows Server 2019", "Windows Server 2016"]
            }
            (6, 3) => vec!["Windows 8.1", "Windows Server 2012 R2"],
            (6, 2) => vec!["Windows 8", "Windows Server 2012"],
            (6, 1) => vec!["Windows 7", "Windows Server 2008 R2"],
            (6, 0) => vec!["Windows Vista", "Windows Server 2008"],
            (5, 2) => vec![
                "Windows XP 64-Bit",
                "Windows Server 2003",
                "Windows Server 2003 R2",
            ],
            (5, 1) => vec!["Windows XP"],
            (5, 0) => vec!["Windows 2000"],
            _ => Vec::new(),
        }
    }

    /// Create the raw representation in bytes to be transmitted over the
    /// network.
    pub fn build(&self) -> Vec<u8> {
        let mut bytes = vec![self.major, self.minor];
        bytes.extend(&self.build.to_le_bytes());

        // reserved bytes and revision
        bytes.extend(&[0, 0, 0, self.revision]);

        return bytes;
    }

    /// Parse raw version bytes.
    pub fn parse(raw: &[u8]) -> Result<(&[u8], Self)> {
        let (raw, major) = le_u8(raw)?;
        let (raw, minor) = le_u8(raw)?;
        let (raw, build) = le_u16(raw)?;
        let (raw, _) = take(3usize)(raw)?;
        let (raw, revision) = le_u8(raw)?;

        return Ok((raw, Self {
            major,
            minor,
            build,
            revision,
        }));
    }
}