@@ -134,7 +134,11 @@ pub fn wait_for_parent() -> Result<()> {
134134
135135pub fn do_add_to_path ( methods : & [ PathUpdateMethod ] ) -> Result < ( ) > {
136136 assert ! ( methods. len( ) == 1 && methods[ 0 ] == PathUpdateMethod :: Windows ) ;
137+ let new_path = _with_path_cargo_home_bin ( _add_to_path) ?;
138+ _apply_new_path ( new_path)
139+ }
137140
141+ fn _apply_new_path ( new_path : Option < String > ) -> Result < ( ) > {
138142 use std:: ptr;
139143 use winapi:: shared:: minwindef:: * ;
140144 use winapi:: um:: winuser:: {
@@ -143,7 +147,7 @@ pub fn do_add_to_path(methods: &[PathUpdateMethod]) -> Result<()> {
143147 use winreg:: enums:: { RegType , HKEY_CURRENT_USER , KEY_READ , KEY_WRITE } ;
144148 use winreg:: { RegKey , RegValue } ;
145149
146- let new_path = match _with_path_cargo_home_bin ( _add_to_path ) ? {
150+ let new_path = match new_path {
147151 Some ( new_path) => new_path,
148152 None => return Ok ( ( ) ) , // No need to set the path
149153 } ;
@@ -153,14 +157,19 @@ pub fn do_add_to_path(methods: &[PathUpdateMethod]) -> Result<()> {
153157 . open_subkey_with_flags ( "Environment" , KEY_READ | KEY_WRITE )
154158 . chain_err ( || ErrorKind :: PermissionDenied ) ?;
155159
156- let reg_value = RegValue {
157- bytes : utils:: string_to_winreg_bytes ( & new_path) ,
158- vtype : RegType :: REG_EXPAND_SZ ,
159- } ;
160-
161- environment
162- . set_raw_value ( "PATH" , & reg_value)
163- . chain_err ( || ErrorKind :: PermissionDenied ) ?;
160+ if new_path. is_empty ( ) {
161+ environment
162+ . delete_value ( "PATH" )
163+ . chain_err ( || ErrorKind :: PermissionDenied ) ?;
164+ } else {
165+ let reg_value = RegValue {
166+ bytes : utils:: string_to_winreg_bytes ( & new_path) ,
167+ vtype : RegType :: REG_EXPAND_SZ ,
168+ } ;
169+ environment
170+ . set_raw_value ( "PATH" , & reg_value)
171+ . chain_err ( || ErrorKind :: PermissionDenied ) ?;
172+ }
164173
165174 // Tell other processes to update their environment
166175 unsafe {
@@ -258,53 +267,8 @@ where
258267
259268pub fn do_remove_from_path ( methods : & [ PathUpdateMethod ] ) -> Result < ( ) > {
260269 assert ! ( methods. len( ) == 1 && methods[ 0 ] == PathUpdateMethod :: Windows ) ;
261-
262- use std:: ptr;
263- use winapi:: shared:: minwindef:: * ;
264- use winapi:: um:: winuser:: {
265- SendMessageTimeoutA , HWND_BROADCAST , SMTO_ABORTIFHUNG , WM_SETTINGCHANGE ,
266- } ;
267- use winreg:: enums:: { RegType , HKEY_CURRENT_USER , KEY_READ , KEY_WRITE } ;
268- use winreg:: { RegKey , RegValue } ;
269-
270- let new_path = match _with_path_cargo_home_bin ( _remove_from_path) ? {
271- Some ( new_path) => new_path,
272- None => return Ok ( ( ) ) , // No need to set the path
273- } ;
274-
275- let root = RegKey :: predef ( HKEY_CURRENT_USER ) ;
276- let environment = root
277- . open_subkey_with_flags ( "Environment" , KEY_READ | KEY_WRITE )
278- . chain_err ( || ErrorKind :: PermissionDenied ) ?;
279-
280- if new_path. is_empty ( ) {
281- environment
282- . delete_value ( "PATH" )
283- . chain_err ( || ErrorKind :: PermissionDenied ) ?;
284- } else {
285- let reg_value = RegValue {
286- bytes : utils:: string_to_winreg_bytes ( & new_path) ,
287- vtype : RegType :: REG_EXPAND_SZ ,
288- } ;
289- environment
290- . set_raw_value ( "PATH" , & reg_value)
291- . chain_err ( || ErrorKind :: PermissionDenied ) ?;
292- }
293-
294- // Tell other processes to update their environment
295- unsafe {
296- SendMessageTimeoutA (
297- HWND_BROADCAST ,
298- WM_SETTINGCHANGE ,
299- 0 as WPARAM ,
300- "Environment\0 " . as_ptr ( ) as LPARAM ,
301- SMTO_ABORTIFHUNG ,
302- 5000 ,
303- ptr:: null_mut ( ) ,
304- ) ;
305- }
306-
307- Ok ( ( ) )
270+ let new_path = _with_path_cargo_home_bin ( _remove_from_path) ?;
271+ _apply_new_path ( new_path)
308272}
309273
310274pub fn run_update ( setup_path : & Path ) -> Result < utils:: ExitCode > {
@@ -548,6 +512,31 @@ mod tests {
548512 ) ;
549513 }
550514
515+ #[ test]
516+ fn windows_path_regkey_type ( ) {
517+ // per issue #261, setting PATH should use REG_EXPAND_SZ.
518+ let tp = Box :: new ( currentprocess:: TestProcess :: default ( ) ) ;
519+ with_registry_edits ( & || {
520+ currentprocess:: with ( tp. clone ( ) , || {
521+ let root = RegKey :: predef ( HKEY_CURRENT_USER ) ;
522+ let environment = root
523+ . open_subkey_with_flags ( "Environment" , KEY_READ | KEY_WRITE )
524+ . unwrap ( ) ;
525+ environment. delete_value ( "PATH" ) . unwrap ( ) ;
526+
527+ assert_eq ! ( ( ) , super :: _apply_new_path( Some ( "foo" . into( ) ) ) . unwrap( ) ) ;
528+
529+ let root = RegKey :: predef ( HKEY_CURRENT_USER ) ;
530+ let environment = root
531+ . open_subkey_with_flags ( "Environment" , KEY_READ | KEY_WRITE )
532+ . unwrap ( ) ;
533+ let path = environment. get_raw_value ( "PATH" ) . unwrap ( ) ;
534+ assert_eq ! ( path. vtype, RegType :: REG_EXPAND_SZ ) ;
535+ assert_eq ! ( utils:: string_to_winreg_bytes( "foo" ) , & path. bytes[ ..] ) ;
536+ } )
537+ } ) ;
538+ }
539+
551540 #[ test]
552541 fn windows_uninstall_removes_semicolon_from_path_prefix ( ) {
553542 assert_eq ! (
0 commit comments