@@ -428,28 +428,53 @@ impl WindowsTerminal {
428428 let original_output_mode = output. get_mode ( ) ?;
429429 let original_input_cp = input. get_code_page ( ) ?;
430430 let original_output_cp = output. get_code_page ( ) ?;
431- if mode == InputReaderMode :: Vte {
432- input. set_code_page ( CP_UTF8 ) ?;
433- output. set_code_page ( CP_UTF8 ) ?;
434- }
435431
436- // Enable VT processing for the output handle.
437- let desired_output_mode = original_output_mode
438- | Console :: ENABLE_VIRTUAL_TERMINAL_PROCESSING
439- | Console :: DISABLE_NEWLINE_AUTO_RETURN ;
440- if output. set_mode ( desired_output_mode) . is_err ( ) {
441- bail ! ( "virtual terminal processing could not be enabled for the output handle" ) ;
442- }
432+ // Switch the console to UTF-8 + VT modes. Each step mutates global console state, and a
433+ // later step can fail. Because there is no `WindowsTerminal` yet, `Drop` won't run, so on
434+ // any failure we must roll back to the original values here.
435+ let reader = match ( || -> io:: Result < EventReader > {
436+ if mode == InputReaderMode :: Vte {
437+ input. set_code_page ( CP_UTF8 ) ?;
438+ output. set_code_page ( CP_UTF8 ) ?;
439+ }
443440
444- if mode == InputReaderMode :: Vte {
445- // And now the input handle too.
446- let desired_input_mode = original_input_mode | Console :: ENABLE_VIRTUAL_TERMINAL_INPUT ;
447- if input. set_mode ( desired_input_mode) . is_err ( ) {
448- bail ! ( "virtual terminal processing could not be enabled for the input handle" ) ;
441+ // Enable VT processing for the output handle.
442+ let desired_output_mode = original_output_mode
443+ | Console :: ENABLE_VIRTUAL_TERMINAL_PROCESSING
444+ | Console :: DISABLE_NEWLINE_AUTO_RETURN ;
445+ output. set_mode ( desired_output_mode) . map_err ( |_| {
446+ io:: Error :: new (
447+ io:: ErrorKind :: Other ,
448+ "virtual terminal processing could not be enabled for the output handle" ,
449+ )
450+ } ) ?;
451+
452+ if mode == InputReaderMode :: Vte {
453+ // And now the input handle too.
454+ let desired_input_mode =
455+ original_input_mode | Console :: ENABLE_VIRTUAL_TERMINAL_INPUT ;
456+ input. set_mode ( desired_input_mode) . map_err ( |_| {
457+ io:: Error :: new (
458+ io:: ErrorKind :: Other ,
459+ "virtual terminal processing could not be enabled for the input handle" ,
460+ )
461+ } ) ?;
449462 }
450- }
451463
452- let reader = EventReader :: new ( WindowsEventSource :: new ( input. try_clone ( ) ?, mode) ?) ;
464+ Ok ( EventReader :: new ( WindowsEventSource :: new (
465+ input. try_clone ( ) ?,
466+ mode,
467+ ) ?) )
468+ } ) ( ) {
469+ Ok ( reader) => reader,
470+ Err ( err) => {
471+ let _ = input. set_code_page ( original_input_cp) ;
472+ let _ = output. set_code_page ( original_output_cp) ;
473+ let _ = input. set_mode ( original_input_mode) ;
474+ let _ = output. set_mode ( original_output_mode) ;
475+ return Err ( err) ;
476+ }
477+ } ;
453478
454479 Ok ( Self {
455480 input,
0 commit comments