Skip to main content

wslpluginapi_sys/
manual.rs

1use crate::WSLPluginAPIV1;
2use windows_sys::core::HRESULT;
3use windows_sys::Win32::Foundation::{SEVERITY_ERROR, S_OK};
4use windows_sys::Win32::System::Diagnostics::Debug::{FACILITY_CODE, FACILITY_ITF};
5
6#[inline(always)]
7const fn make_hresult(severity: u32, facility: FACILITY_CODE, code: u32) -> HRESULT {
8    ((severity << 31) | (facility << 16) | code) as HRESULT
9}
10
11/// Error code indicating that the WSL version is too low and requires an update for this specific plugin API.
12pub const WSL_E_PLUGIN_REQUIRES_UPDATE: HRESULT =
13    make_hresult(SEVERITY_ERROR, FACILITY_ITF, 0x8004032A);
14
15/// Ensures the WSL Plugin API version meets the minimum required version.
16///
17/// This function compares the version of the API passed as a parameter against the required
18/// version numbers specified (`required_major`, `required_minor`, `required_revision`).
19/// If the API version is lower than required, it returns `WSL_E_PLUGIN_REQUIRES_UPDATE`.
20/// Otherwise, it returns `S_OK`.
21///
22/// # Parameters
23///
24/// - `required_major`: The major version number required by the plugin.
25/// - `required_minor`: The minor version number required by the plugin.
26/// - `required_revision`: The revision number required by the plugin.
27/// - `api`: A raw pointer to a [`WSLPluginAPIV1`] structure, containing the current API version.
28///
29/// # Returns
30///
31/// - [`S_OK`]: If the API version meets or exceeds the required version.
32/// - [`WSL_E_PLUGIN_REQUIRES_UPDATE`]: If the API version is below the required minimum.
33///
34/// # Safety
35///
36/// This function is `unsafe` because it dereferences a raw pointer (`api`). The caller must
37/// ensure that the pointer is valid and points to a properly initialized [`WSLPluginAPIV1`]
38/// structure.
39#[inline(always)]
40pub const unsafe fn require_version(
41    required_major: u32,
42    required_minor: u32,
43    required_revision: u32,
44    api: *const WSLPluginAPIV1,
45) -> HRESULT {
46    let version = &(*api).Version;
47
48    if version.Major < required_major
49        || (version.Major == required_major && version.Minor < required_minor)
50        || (version.Major == required_major
51            && version.Minor == required_minor
52            && version.Revision < required_revision)
53    {
54        WSL_E_PLUGIN_REQUIRES_UPDATE
55    } else {
56        S_OK
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63    use crate::{WSLPluginAPIV1, WSLVersion};
64    use windows_sys::Win32::Foundation::S_OK;
65
66    #[test]
67    fn test_version_exact_match() {
68        let api = WSLPluginAPIV1 {
69            Version: WSLVersion {
70                Major: 1,
71                Minor: 0,
72                Revision: 0,
73            },
74            MountFolder: None,
75            ExecuteBinary: None,
76            PluginError: None,
77            ExecuteBinaryInDistribution: None,
78        };
79
80        assert_eq!(unsafe { require_version(1, 0, 0, &api) }, S_OK);
81    }
82
83    #[test]
84    fn test_version_major_too_low() {
85        let api = WSLPluginAPIV1 {
86            Version: WSLVersion {
87                Major: 0,
88                Minor: 9,
89                Revision: 0,
90            },
91            MountFolder: None,
92            ExecuteBinary: None,
93            PluginError: None,
94            ExecuteBinaryInDistribution: None,
95        };
96
97        assert_eq!(
98            unsafe { require_version(1, 0, 0, &api) },
99            WSL_E_PLUGIN_REQUIRES_UPDATE
100        );
101    }
102
103    #[test]
104    fn test_version_minor_too_low() {
105        let api = WSLPluginAPIV1 {
106            Version: WSLVersion {
107                Major: 1,
108                Minor: 0,
109                Revision: 0,
110            },
111            MountFolder: None,
112            ExecuteBinary: None,
113            PluginError: None,
114            ExecuteBinaryInDistribution: None,
115        };
116
117        assert_eq!(
118            unsafe { require_version(1, 1, 0, &api) },
119            WSL_E_PLUGIN_REQUIRES_UPDATE
120        );
121    }
122
123    #[test]
124    fn test_version_revision_too_low() {
125        let api = WSLPluginAPIV1 {
126            Version: WSLVersion {
127                Major: 1,
128                Minor: 0,
129                Revision: 0,
130            },
131            MountFolder: None,
132            ExecuteBinary: None,
133            PluginError: None,
134            ExecuteBinaryInDistribution: None,
135        };
136
137        assert_eq!(
138            unsafe { require_version(1, 0, 1, &api) },
139            WSL_E_PLUGIN_REQUIRES_UPDATE
140        );
141    }
142
143    #[test]
144    fn test_version_high_enough() {
145        let api = WSLPluginAPIV1 {
146            Version: WSLVersion {
147                Major: 1,
148                Minor: 2,
149                Revision: 3,
150            },
151            MountFolder: None,
152            ExecuteBinary: None,
153            PluginError: None,
154            ExecuteBinaryInDistribution: None,
155        };
156
157        assert_eq!(unsafe { require_version(1, 0, 1, &api) }, S_OK);
158    }
159}