wslpluginapi_sys/
manual.rs

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