Skip to main content

ib_shell_item/string/
mod.rs

1use std::{mem, ptr};
2
3use widestring::U16CStr;
4use windows::{
5    Win32::{
6        System::Com::{CoTaskMemAlloc, CoTaskMemFree, CoTaskMemRealloc},
7        UI::Shell::Common::{STRRET, STRRET_WSTR},
8    },
9    core::PWSTR,
10};
11
12pub mod bar;
13
14#[allow(unused)]
15pub fn strret_free(s: STRRET) {
16    if s.uType == STRRET_WSTR.0 as u32 {
17        unsafe { CoTaskMemFree(Some(s.Anonymous.pOleStr.0 as *mut _)) };
18    }
19}
20
21/// Converts a `&str` to a `PWSTR` by allocating memory using `CoTaskMemAlloc`.
22#[allow(unused)]
23pub fn str_to_co_task(s: &str) -> PWSTR {
24    let len = s.encode_utf16().count() + 1;
25
26    let ptr = unsafe { CoTaskMemAlloc(len * mem::size_of::<u16>()) };
27    if ptr.is_null() {
28        return PWSTR(ptr::null_mut());
29    }
30
31    let ptr = ptr as *mut u16;
32    unsafe {
33        for (i, ch) in s.encode_utf16().enumerate() {
34            ptr.add(i).write(ch);
35        }
36        ptr.add(len - 1).write(0);
37    }
38
39    PWSTR(ptr)
40}
41
42/// Prepends a prefix to a name slice and writes to ptr using CoTaskMemRealloc.
43/// The name slice includes the original name with its null terminator.
44pub(crate) fn prefix_u16cstr_ptr(name: &U16CStr, prefix: &[u16]) -> PWSTR {
45    let ptr = unsafe {
46        CoTaskMemRealloc(
47            Some(name.as_ptr().cast()),
48            (prefix.len() + name.len() + 1) * size_of::<u16>(),
49        )
50    } as *mut u16;
51
52    if ptr.is_null() {
53        return PWSTR(name.as_ptr() as _);
54    }
55
56    unsafe {
57        ptr::copy_nonoverlapping(prefix.as_ptr(), ptr, prefix.len());
58        ptr::copy_nonoverlapping(name.as_ptr(), ptr.add(prefix.len()), name.len() + 1);
59    }
60
61    PWSTR(ptr)
62}
63
64/// Appends a suffix to a name slice and writes to ptr using [`CoTaskMemRealloc`].
65#[allow(dead_code)]
66pub(crate) fn suffix_u16cstr_ptr(s: &U16CStr, suffix: &[u16]) -> PWSTR {
67    let ptr = unsafe {
68        CoTaskMemRealloc(
69            Some(s.as_ptr().cast()),
70            (s.len() + suffix.len() + 1) * size_of::<u16>(),
71        )
72    } as *mut u16;
73
74    if ptr.is_null() {
75        return PWSTR(s.as_ptr() as _);
76    }
77
78    unsafe {
79        ptr::copy_nonoverlapping(suffix.as_ptr(), ptr.add(s.len()), suffix.len());
80        ptr.add(s.len() + suffix.len()).write(0);
81    }
82
83    PWSTR(ptr)
84}