rustclr/utils/mod.rs
1use alloc::{string::String, vec::Vec};
2use windows_sys::Win32::{
3 Foundation::{
4 SysAllocString,
5 SysStringLen,
6 },
7};
8
9/// Module related to safearray creation
10mod safearray;
11pub use safearray::*;
12
13/// Module used to validate that the file corresponds to what is expected
14pub(crate) mod file;
15
16/// The `WinStr` trait provides methods for working with BSTRs (Binary String),
17/// a format commonly used in Windows API. BSTRs are wide strings (UTF-16)
18/// with specific memory layouts, used for interoperation with COM
19/// (Component Object Model) and other Windows-based APIs.
20pub trait WinStr {
21 /// Converts a Rust string into a BSTR.
22 ///
23 /// # Returns
24 ///
25 /// * `*const u16` - A pointer to the UTF-16 encoded BSTR.
26 ///
27 /// This method is implemented for `&str` and `String`, converting
28 /// them into BSTRs, and for `*const u16` as a passthrough.
29 ///
30 /// # Example
31 ///
32 /// ```
33 /// use rustclr::WinStr;
34 ///
35 /// let rust_str = "Hello, World!";
36 /// let bstr_ptr = rust_str.to_bstr();
37 ///
38 /// // Use the BSTR pointer in a COM function...
39 /// ```
40 fn to_bstr(&self) -> *const u16;
41
42 /// Converts a BSTR (pointer `*const u16`) back to a Rust `String`.
43 ///
44 /// # Returns
45 ///
46 /// * `String` - A `String` containing the text from the BSTR if the trait
47 /// is implemented for `*const u16`. For other types, returns an empty `String`.
48 ///
49 /// # Example
50 ///
51 /// ```
52 /// use rustclr::WinStr;
53 ///
54 /// let bstr: *const u16 = /* assume a BSTR from COM */;
55 /// let rust_string = bstr.to_string();
56 /// ```
57 fn to_string(&self) -> String {
58 String::new()
59 }
60}
61
62impl WinStr for &str {
63 /// Converts a `&str` to a BSTR.
64 ///
65 /// # Returns
66 ///
67 /// * `*const u16` - A pointer to the UTF-16 encoded BSTR.
68 fn to_bstr(&self) -> *const u16 {
69 let utf16_str = self.encode_utf16().chain(Some(0)).collect::<Vec<u16>>();
70 unsafe { SysAllocString(utf16_str.as_ptr()) }
71 }
72}
73
74impl WinStr for String {
75 /// Converts a `String` to a BSTR.
76 ///
77 /// # Returns
78 ///
79 /// * `*const u16` - A pointer to the UTF-16 encoded BSTR.
80 fn to_bstr(&self) -> *const u16 {
81 let utf16_str = self.encode_utf16().chain(Some(0)).collect::<Vec<u16>>();
82 unsafe { SysAllocString(utf16_str.as_ptr()) }
83 }
84}
85
86impl WinStr for *const u16 {
87 /// Passes through the BSTR pointer without modification.
88 ///
89 /// # Returns
90 ///
91 /// * `*const u16` - The original BSTR pointer.
92 fn to_bstr(&self) -> *const u16 {
93 *self
94 }
95
96 /// Converts a `*const u16` BSTR to a `String`.
97 ///
98 /// # Returns
99 ///
100 /// * `String` - A `String` containing the UTF-16 encoded text from the BSTR.
101 fn to_string(&self) -> String {
102 let len = unsafe { SysStringLen(*self) };
103 if len == 0 {
104 return String::new();
105 }
106
107 let slice = unsafe { core::slice::from_raw_parts(*self, len as usize) };
108 String::from_utf16_lossy(slice)
109 }
110}
111
112/// Generates a uuid used to create the AppDomain
113pub(crate) fn uuid() -> uuid::Uuid {
114 let mut buf = [0u8; 16];
115
116 for i in 0..4 {
117 let ticks = unsafe { core::arch::x86_64::_rdtsc() };
118 buf[i * 4 + 0] = (ticks >> 0) as u8;
119 buf[i * 4 + 1] = (ticks >> 8) as u8;
120 buf[i * 4 + 2] = (ticks >> 16) as u8;
121 buf[i * 4 + 3] = (ticks >> 24) as u8;
122 }
123
124 uuid::Uuid::from_bytes(buf)
125}
126
127/// Specifies the invocation type for a method, indicating if it is static or instance-based.
128pub enum Invocation {
129 /// Indicates that the method to invoke is static.
130 Static,
131
132 /// Indicates that the method to invoke is an instance method.
133 Instance,
134}