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