11use std:: env:: consts:: EXE_SUFFIX ;
2+ use std:: ffi:: { OsStr , OsString } ;
3+ use std:: os:: windows:: ffi:: { OsStrExt , OsStringExt } ;
24use std:: path:: Path ;
35use std:: process:: Command ;
46
@@ -10,6 +12,9 @@ use crate::process;
1012use crate :: utils:: utils;
1113use crate :: utils:: Notification ;
1214
15+ use winreg:: enums:: { RegType , HKEY_CURRENT_USER , KEY_READ , KEY_WRITE } ;
16+ use winreg:: { RegKey , RegValue } ;
17+
1318pub fn ensure_prompt ( ) -> Result < ( ) > {
1419 writeln ! ( process( ) . stdout( ) , ) ?;
1520 writeln ! ( process( ) . stdout( ) , "Press the Enter key to continue." ) ?;
@@ -42,7 +47,6 @@ pub fn do_msvc_check(opts: &InstallOpts<'_>) -> Result<bool> {
4247
4348/// Run by rustup-gc-$num.exe to delete CARGO_HOME
4449pub fn complete_windows_uninstall ( ) -> Result < utils:: ExitCode > {
45- use std:: ffi:: OsStr ;
4650 use std:: process:: Stdio ;
4751
4852 wait_for_parent ( ) ?;
@@ -150,8 +154,6 @@ fn _apply_new_path(new_path: Option<Vec<u16>>) -> Result<()> {
150154 use winapi:: um:: winuser:: {
151155 SendMessageTimeoutA , HWND_BROADCAST , SMTO_ABORTIFHUNG , WM_SETTINGCHANGE ,
152156 } ;
153- use winreg:: enums:: { RegType , HKEY_CURRENT_USER , KEY_READ , KEY_WRITE } ;
154- use winreg:: { RegKey , RegValue } ;
155157
156158 let new_path = match new_path {
157159 Some ( new_path) => new_path,
@@ -198,8 +200,6 @@ fn _apply_new_path(new_path: Option<Vec<u16>>) -> Result<()> {
198200// should not mess with it.
199201fn get_windows_path_var ( ) -> Result < Option < Vec < u16 > > > {
200202 use std:: io;
201- use winreg:: enums:: { HKEY_CURRENT_USER , KEY_READ , KEY_WRITE } ;
202- use winreg:: RegKey ;
203203
204204 let root = RegKey :: predef ( HKEY_CURRENT_USER ) ;
205205 let environment = root
@@ -270,9 +270,6 @@ fn _with_path_cargo_home_bin<F>(f: F) -> Result<Option<Vec<u16>>>
270270where
271271 F : FnOnce ( Vec < u16 > , Vec < u16 > ) -> Option < Vec < u16 > > ,
272272{
273- use std:: ffi:: OsString ;
274- use std:: os:: windows:: ffi:: OsStrExt ;
275-
276273 let windows_path = get_windows_path_var ( ) ?;
277274 let mut path_str = utils:: cargo_home ( ) ?;
278275 path_str. push ( "bin" ) ;
@@ -285,6 +282,55 @@ pub fn do_remove_from_path() -> Result<()> {
285282 _apply_new_path ( new_path)
286283}
287284
285+ const RUSTUP_UNINSTALL_ENTRY : & str = r"Software\Microsoft\Windows\CurrentVersion\Uninstall\Rustup" ;
286+
287+ pub fn do_add_to_programs ( ) -> Result < ( ) > {
288+ use std:: path:: PathBuf ;
289+
290+ let key = RegKey :: predef ( HKEY_CURRENT_USER )
291+ . create_subkey ( RUSTUP_UNINSTALL_ENTRY )
292+ . chain_err ( || ErrorKind :: PermissionDenied ) ?
293+ . 0 ;
294+
295+ // Don't overwrite registry if Rustup is already installed
296+ let prev = key
297+ . get_raw_value ( "UninstallString" )
298+ . map ( |val| from_winreg_value ( & val) ) ;
299+ if let Ok ( Some ( s) ) = prev {
300+ let mut path = PathBuf :: from ( OsString :: from_wide ( & s) ) ;
301+ path. pop ( ) ;
302+ if path. exists ( ) {
303+ return Ok ( ( ) ) ;
304+ }
305+ }
306+
307+ let mut path = utils:: cargo_home ( ) ?;
308+ path. push ( "bin\r ustup.exe" ) ;
309+ let mut uninstall_cmd = OsString :: from ( "\" " ) ;
310+ uninstall_cmd. push ( path) ;
311+ uninstall_cmd. push ( "\" self uninstall" ) ;
312+
313+ let reg_value = RegValue {
314+ bytes : to_winreg_bytes ( uninstall_cmd. encode_wide ( ) . collect ( ) ) ,
315+ vtype : RegType :: REG_SZ ,
316+ } ;
317+
318+ key. set_raw_value ( "UninstallString" , & reg_value)
319+ . chain_err ( || ErrorKind :: PermissionDenied ) ?;
320+ key. set_value ( "DisplayName" , & "Rustup: the Rust toolchain installer" )
321+ . chain_err ( || ErrorKind :: PermissionDenied ) ?;
322+
323+ Ok ( ( ) )
324+ }
325+
326+ pub fn do_remove_from_programs ( ) -> Result < ( ) > {
327+ match RegKey :: predef ( HKEY_CURRENT_USER ) . delete_subkey_all ( RUSTUP_UNINSTALL_ENTRY ) {
328+ Ok ( ( ) ) => Ok ( ( ) ) ,
329+ Err ( ref e) if e. kind ( ) == std:: io:: ErrorKind :: NotFound => Ok ( ( ) ) ,
330+ Err ( e) => Err ( e) . chain_err ( || ErrorKind :: PermissionDenied ) ,
331+ }
332+ }
333+
288334/// Convert a vector UCS-2 chars to a null-terminated UCS-2 string in bytes
289335pub fn to_winreg_bytes ( mut v : Vec < u16 > ) -> Vec < u8 > {
290336 v. push ( 0 ) ;
@@ -296,7 +342,6 @@ pub fn to_winreg_bytes(mut v: Vec<u16>) -> Vec<u8> {
296342/// does a lossy unicode conversion.
297343pub fn from_winreg_value ( val : & winreg:: RegValue ) -> Option < Vec < u16 > > {
298344 use std:: slice;
299- use winreg:: enums:: RegType ;
300345
301346 match val. vtype {
302347 RegType :: REG_SZ | RegType :: REG_EXPAND_SZ => {
@@ -364,7 +409,6 @@ pub fn self_replace() -> Result<utils::ExitCode> {
364409pub fn delete_rustup_and_cargo_home ( ) -> Result < ( ) > {
365410 use std:: io;
366411 use std:: mem;
367- use std:: os:: windows:: ffi:: OsStrExt ;
368412 use std:: ptr;
369413 use std:: thread;
370414 use std:: time:: Duration ;
0 commit comments