1use windows::{
2 core::{PCWSTR},
3 Win32::{
4 System::{
5 Com::{CoCreateInstance, CLSCTX_INPROC_SERVER}
6 },
7 UI::{
8 Shell::{ICustomDestinationList, IShellLinkW, Common::{IObjectCollection, IObjectArray}, DestinationList, EnumerableObjectCollection, ShellLink, PropertiesSystem::{IPropertyStore, InitPropVariantFromStringVector}}
9 },
10 }
11};
12use windows::core::ComInterface;
13use windows::Win32::Storage::EnhancedStorage::PKEY_Title;
14
15
16#[inline]
20fn string_to_pwstr(str: &str) -> PCWSTR {
21 let mut encoded = str.encode_utf16().chain([0u16]).collect::<Vec<u16>>();
22 PCWSTR(encoded.as_mut_ptr())
23}
24
25pub struct UserTask<'a> {
26 pub title: &'a str,
27 pub description: &'a str,
28 pub arguments: &'a str,
29 pub icon_path: &'a str,
30 pub icon_index: i32,
31 pub program: &'a str,
32}
33
34pub fn set_tasks(tasks: Vec<UserTask>) -> Result<(), windows::core::Error> {
35 let cdl: ICustomDestinationList = unsafe {
36 CoCreateInstance(&DestinationList, None, CLSCTX_INPROC_SERVER)?
37 };
38
39 let collection: IObjectCollection = unsafe {
40 CoCreateInstance(&EnumerableObjectCollection, None, CLSCTX_INPROC_SERVER)?
41 };
42
43 unsafe {
44 for task in tasks {
45 let shell_link: IShellLinkW = CoCreateInstance(&ShellLink, None, CLSCTX_INPROC_SERVER)?;
46
47 shell_link.SetDescription(string_to_pwstr(task.description))?;
48 shell_link.SetArguments(string_to_pwstr(task.arguments))?;
49 shell_link.SetIconLocation(string_to_pwstr(task.icon_path), task.icon_index)?;
50 shell_link.SetPath(string_to_pwstr(task.program) )?;
51
52 let prop_store: IPropertyStore = shell_link.cast()?;
53 let pkey = PKEY_Title;
54
55 let mut title: Vec<u16> = task.title.encode_utf16().collect();
56 title.push(0x00);
57 let pv = InitPropVariantFromStringVector(Some(&[windows::core::PCWSTR(title.as_mut_ptr())]))?;
58
59 prop_store.SetValue(&pkey, &pv)?;
60 prop_store.Commit()?;
61
62 collection.AddObject(&shell_link)?;
63 }
64
65 let mut slots_visible: u32 = 0;
66 let _removed: IObjectArray = cdl.BeginList(&mut slots_visible as *mut u32)?;
67
68 cdl.AddUserTasks(&collection)?;
69 cdl.CommitList()?;
70 }
71
72 Ok(())
73}