Skip to main content

wslplugins_rs/
wsl_session_information.rs

1//! # WSL Session Information
2//!
3//! This module provides a safe abstraction over the `WSLSessionInformation` structure
4//! from the WSL Plugin API, allowing access to session details in an idiomatic Rust interface.
5
6use crate::SessionID;
7use core::hash;
8use std::{fmt, os::windows::raw::HANDLE};
9use wslpluginapi_sys::windows_sys::Win32::Security::PSID;
10
11/// Represents session information for a WSL instance.
12///
13/// This struct wraps the `WSLSessionInformation` provided by the WSL Plugin API and
14/// provides safe, idiomatic access to its fields.
15#[repr(transparent)]
16pub struct WSLSessionInformation(wslpluginapi_sys::WSLSessionInformation);
17
18impl WSLSessionInformation {
19    /// Retrieves the session ID.
20    ///
21    /// # Returns
22    /// The unique session ID as a [`SessionID`].
23    #[must_use]
24    #[inline]
25    pub const fn id(&self) -> SessionID {
26        SessionID(self.0.SessionId)
27    }
28
29    /// Retrieves the user token for the session.
30    ///
31    /// # Returns
32    /// A [HANDLE] representing the user token.
33    /// # Safety
34    /// This function returns a raw handle to the user token.
35    /// The handle should be used only during the life of the session and must not be closed
36    #[must_use]
37    #[inline]
38    pub const unsafe fn user_token(&self) -> HANDLE {
39        self.0.UserToken
40    }
41
42    /// Retrieves the user SID (security identifier) for the session.
43    ///
44    /// # Returns
45    /// A [PSID] representing the user SID.
46    /// # Safety
47    /// This function returns a raw pointer to the user SID.
48    /// This pointer should be used only during the life of the session and must not be freed or modified.
49    #[must_use]
50    #[inline]
51    pub const unsafe fn user_sid(&self) -> PSID {
52        self.0.UserSid
53    }
54}
55
56impl From<wslpluginapi_sys::WSLSessionInformation> for WSLSessionInformation {
57    #[inline]
58    fn from(value: wslpluginapi_sys::WSLSessionInformation) -> Self {
59        Self(value)
60    }
61}
62
63impl From<WSLSessionInformation> for wslpluginapi_sys::WSLSessionInformation {
64    #[inline]
65    fn from(value: WSLSessionInformation) -> Self {
66        value.0
67    }
68}
69
70impl AsRef<WSLSessionInformation> for wslpluginapi_sys::WSLSessionInformation {
71    #[inline]
72    fn as_ref(&self) -> &WSLSessionInformation {
73        // SAFETY: conveting this kind of ref is safe as it is transparent
74        unsafe { &*std::ptr::from_ref::<Self>(self).cast::<WSLSessionInformation>() }
75    }
76}
77
78impl AsRef<wslpluginapi_sys::WSLSessionInformation> for WSLSessionInformation {
79    #[inline]
80    fn as_ref(&self) -> &wslpluginapi_sys::WSLSessionInformation {
81        &self.0
82    }
83}
84
85impl hash::Hash for WSLSessionInformation {
86    /// Computes a hash based on the session ID.
87    ///
88    /// # Arguments
89    /// - `state`: The hasher state to update with the session ID.
90    #[inline]
91    fn hash<H: hash::Hasher>(&self, state: &mut H) {
92        self.0.SessionId.hash(state);
93    }
94}
95
96impl PartialEq for WSLSessionInformation {
97    /// Compares two `WSLSessionInformation` instances for equality based on their session IDs.
98    ///
99    /// # Arguments
100    /// - `other`: The other `WSLSessionInformation` instance to compare.
101    ///
102    /// # Returns
103    /// `true` if the session IDs are equal, `false` otherwise.
104    #[inline]
105    fn eq(&self, other: &Self) -> bool {
106        self.0.SessionId == other.0.SessionId
107    }
108}
109
110// Manually implements Debug for `WSLSessionInformation`.
111impl fmt::Debug for WSLSessionInformation {
112    /// Formats the session information for debugging.
113    ///
114    /// The output includes the session ID, user token, and user SID.
115    #[inline]
116    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117        f.debug_struct("WSLSessionInformation")
118            .field("sessionId", &self.0.SessionId)
119            .field("userToken", &self.0.UserToken)
120            .field("userSid", &self.0.UserSid)
121            .finish()
122    }
123}
124
125#[cfg(test)]
126mod tests {
127    use crate::utils::test_transparence;
128
129    use super::WSLSessionInformation;
130
131    #[test]
132    fn test_layouts() {
133        test_transparence::<wslpluginapi_sys::WSLSessionInformation, WSLSessionInformation>();
134    }
135}