@@ -51,65 +51,27 @@ pub fn enable_autostart(app_handle: &AppHandle) -> Result<(), String> {
5151 Data4 : [ 0xC0 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x46 ] ,
5252 } ;
5353
54- // RAII wrapper for IShellLinkW
55- struct ShellLinkGuard ( * mut IShellLinkW ) ;
56-
57- impl ShellLinkGuard {
58- unsafe fn as_ref ( & self ) -> Option < & IShellLinkW > {
59- if self . 0 . is_null ( ) {
60- None
61- } else {
62- // SAFETY: We've checked that the pointer is not null
63- unsafe { Some ( & * self . 0 ) }
64- }
65- }
66- }
67-
68- impl Drop for ShellLinkGuard {
69- fn drop ( & mut self ) {
70- unsafe {
71- if !self . 0 . is_null ( ) {
72- ( * self . 0 ) . Release ( ) ;
73- }
74- }
75- }
76- }
77-
78- // RAII wrapper for IPersistFile
79- struct PersistFileGuard ( * mut IPersistFile ) ;
80-
81- impl PersistFileGuard {
82- /// Execute a closure with the raw IPersistFile pointer if it is non-null.
83- ///
84- /// Returns an error if the pointer is null.
85- unsafe fn with < F , R > ( & self , f : F ) -> Result < R , String >
86- where
87- F : FnOnce ( * mut IPersistFile ) -> R ,
88- {
89- if self . 0 . is_null ( ) {
90- Err ( "Persist file pointer is null" . to_string ( ) )
91- } else {
92- // SAFETY: We've checked that the pointer is not null, and we
93- // only pass the pointer into the provided closure without
94- // extending its lifetime beyond this call.
95- Ok ( f ( self . 0 ) )
96- }
97- }
98- }
99-
100- impl Drop for PersistFileGuard {
101- fn drop ( & mut self ) {
102- unsafe {
103- if !self . 0 . is_null ( ) {
104- ( * self . 0 ) . Release ( ) ;
105- }
106- }
107- }
108- }
54+ // Precompute wide strings outside unsafe to avoid early returns inside COM section
55+ let wide_exe_path: Vec < u16 > = executable_path
56+ . to_str ( )
57+ . ok_or ( "Failed to convert path to string" ) ?
58+ . encode_utf16 ( )
59+ . chain ( std:: iter:: once ( 0 ) )
60+ . collect ( ) ;
61+
62+ let wide_shortcut_path: Vec < u16 > = shortcut_path
63+ . to_str ( )
64+ . ok_or ( "Failed to convert shortcut path to string" ) ?
65+ . encode_utf16 ( )
66+ . chain ( std:: iter:: once ( 0 ) )
67+ . collect ( ) ;
10968
11069 unsafe {
11170 // Initialize COM
112- CoInitializeEx ( ptr:: null_mut ( ) , COINIT_APARTMENTTHREADED ) ;
71+ let hr_init = CoInitializeEx ( ptr:: null_mut ( ) , COINIT_APARTMENTTHREADED ) ;
72+ if !SUCCEEDED ( hr_init) {
73+ return Err ( format ! ( "Failed to initialize COM: {hr_init:#x}" ) ) ;
74+ }
11375
11476 // Create shell link object
11577 let mut shell_link: * mut IShellLinkW = ptr:: null_mut ( ) ;
@@ -121,75 +83,49 @@ pub fn enable_autostart(app_handle: &AppHandle) -> Result<(), String> {
12183 & mut shell_link as * mut _ as * mut _ ,
12284 ) ;
12385
124- if SUCCEEDED ( hr) && !shell_link. is_null ( ) {
125- let shell_link_guard = ShellLinkGuard ( shell_link) ;
126- let shell_link_ref = shell_link_guard
127- . as_ref ( )
128- . ok_or ( "Shell link pointer is null" . to_string ( ) ) ?;
129-
130- // Set the path to the executable
131- let wide_path: Vec < u16 > = match executable_path. to_str ( ) {
132- Some ( path) => path. encode_utf16 ( ) . chain ( std:: iter:: once ( 0 ) ) . collect ( ) ,
133- None => {
134- CoUninitialize ( ) ;
135- return Err ( "Failed to convert path to string" . to_string ( ) ) ;
136- }
137- } ;
138-
139- let hr_set_path = shell_link_ref. SetPath ( wide_path. as_ptr ( ) ) ;
140- if !SUCCEEDED ( hr_set_path) {
141- CoUninitialize ( ) ;
142- return Err ( format ! ( "Failed to set shortcut path: {hr_set_path:#x}" ) ) ;
143- }
144-
145- let hr_set_show = shell_link_ref. SetShowCmd ( SW_SHOW ) ;
146- if !SUCCEEDED ( hr_set_show) {
147- CoUninitialize ( ) ;
148- return Err ( format ! ( "Failed to set show command: {hr_set_show:#x}" ) ) ;
149- }
150-
151- // Get the IPersistFile interface
152- let mut persist_file: * mut IPersistFile = ptr:: null_mut ( ) ;
153- let hr_query = shell_link_ref. QueryInterface (
154- & IPersistFile :: uuidof ( ) ,
155- & mut persist_file as * mut _ as * mut _ ,
156- ) ;
157-
158- if !SUCCEEDED ( hr_query) {
159- CoUninitialize ( ) ;
160- return Err ( format ! (
161- "Failed to get IPersistFile interface: {hr_query:#x}"
162- ) ) ;
163- }
164-
165- // Convert shortcut path to wide string before using persist_file
166- let wide_shortcut_path: Vec < u16 > = match shortcut_path. to_str ( ) {
167- Some ( path) => path. encode_utf16 ( ) . chain ( std:: iter:: once ( 0 ) ) . collect ( ) ,
168- None => {
169- CoUninitialize ( ) ;
170- return Err ( "Failed to convert shortcut path to string" . to_string ( ) ) ;
171- }
172- } ;
173-
174- if !persist_file. is_null ( ) {
175- let persist_file_guard = PersistFileGuard ( persist_file) ;
176-
177- // Save the shortcut
178- let hr_save = {
179- persist_file_guard. with ( |pf| ( * pf) . Save ( wide_shortcut_path. as_ptr ( ) , 1 ) ) ?
180- } ;
181-
182- if !SUCCEEDED ( hr_save) {
183- CoUninitialize ( ) ;
184- return Err ( format ! ( "Failed to save shortcut: {hr_save:#x}" ) ) ;
185- }
186- }
187- } else {
86+ if !SUCCEEDED ( hr) || shell_link. is_null ( ) {
18887 CoUninitialize ( ) ;
18988 return Err ( format ! ( "Failed to create shell link: {hr:#x}" ) ) ;
19089 }
19190
192- // Uninitialize COM
91+ let hr_set_path = ( * shell_link) . SetPath ( wide_exe_path. as_ptr ( ) ) ;
92+ if !SUCCEEDED ( hr_set_path) {
93+ ( * shell_link) . Release ( ) ;
94+ CoUninitialize ( ) ;
95+ return Err ( format ! ( "Failed to set shortcut path: {hr_set_path:#x}" ) ) ;
96+ }
97+
98+ let hr_set_show = ( * shell_link) . SetShowCmd ( SW_SHOW ) ;
99+ if !SUCCEEDED ( hr_set_show) {
100+ ( * shell_link) . Release ( ) ;
101+ CoUninitialize ( ) ;
102+ return Err ( format ! ( "Failed to set show command: {hr_set_show:#x}" ) ) ;
103+ }
104+
105+ let mut persist_file: * mut IPersistFile = ptr:: null_mut ( ) ;
106+ let hr_query = ( * shell_link) . QueryInterface (
107+ & IPersistFile :: uuidof ( ) ,
108+ & mut persist_file as * mut _ as * mut _ ,
109+ ) ;
110+
111+ if !SUCCEEDED ( hr_query) || persist_file. is_null ( ) {
112+ ( * shell_link) . Release ( ) ;
113+ CoUninitialize ( ) ;
114+ return Err ( format ! (
115+ "Failed to get IPersistFile interface: {hr_query:#x}"
116+ ) ) ;
117+ }
118+
119+ let hr_save = ( * persist_file) . Save ( wide_shortcut_path. as_ptr ( ) , 1 ) ;
120+ if !SUCCEEDED ( hr_save) {
121+ ( * persist_file) . Release ( ) ;
122+ ( * shell_link) . Release ( ) ;
123+ CoUninitialize ( ) ;
124+ return Err ( format ! ( "Failed to save shortcut: {hr_save:#x}" ) ) ;
125+ }
126+
127+ ( * persist_file) . Release ( ) ;
128+ ( * shell_link) . Release ( ) ;
193129 CoUninitialize ( ) ;
194130 }
195131
0 commit comments