Repository: microsoft/terminal (language: cpp)

Issue:
Sending unicode character via KEYEVENTF_UNICODE/VK_PACKET in SendInput outputs the wrong characters
### Windows Terminal version

1.12.10982.0

### Windows build number

10.0.19043

### Other Software

Reproducible in:
- cmd.exe
- wsl ubuntu 20.04

powershell just displays `??   `, not sure which behaviour is more incorrect

Uses SendInput:
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendinput

### Steps to reproduce

Via SendInput, send the unicode character 🙁

E.g. in
https://github.com/jtroo/kanata/blob/master/src/oskbd/windows.rs#L168

### Expected Behavior

The correct unicode value gets typed in: 🙁

### Actual Behavior

The characters `翿翿` are typed in instead

### Additional info

When copy-pasting the unicode character, it's rendered correctly (in cmd/wsl). It's just not typed correctly via SendInput.


Discussion / hints:
For reference:
🙁: https://www.compart.com/en/unicode/U+1F641
翿: https://www.compart.com/en/unicode/U+7FFF
the problem still appear.

，： => 翿

![image](https://user-images.githubusercontent.com/35659194/174417340-b56df550-d38b-43f1-aa7f-48c870a5fa16.png)

In conhost (the old terminal) this issue is caused by `COOKED_READ_DATA` and will take a while to fix (and it's outside of the scope of this issue).

In Windows Terminal I've narrowed this down to being caused by the Win32 Input Mode. You can work around this issue by adding `"experimental.input.forceVT": true` in your `settings.json` file (in the global global scope - this setting isn't per profile).

Edit: This is caused by `MAX_PARAMETER_VALUE` clamping the character parameter to 0x7fff.

Fix patch:
diff --git a/src/terminal/parser/stateMachine.cpp b/src/terminal/parser/stateMachine.cpp
index 34fab677423..21ee4a88efb 100644
--- a/src/terminal/parser/stateMachine.cpp
+++ b/src/terminal/parser/stateMachine.cpp
@@ -2014,7 +2014,6 @@ void StateMachine::ResetState() noexcept
 //   into the given size_t. All existing value is moved up by 10.
 // - For example, if your value had 437 and you put in the printable number 2,
 //   this function will update value to 4372.
-// - Clamps to 32767 if it gets too big.
 // Arguments:
 // - wch - Printable character to accumulate into the value (after conversion to number, of course)
 // - value - The value to update with the printable character. See example above.
diff --git a/src/terminal/parser/stateMachine.hpp b/src/terminal/parser/stateMachine.hpp
index 2e3b741d6e6..c3c3936693b 100644
--- a/src/terminal/parser/stateMachine.hpp
+++ b/src/terminal/parser/stateMachine.hpp
@@ -21,11 +21,11 @@ Module Name:
 
 namespace Microsoft::Console::VirtualTerminal
 {
-    // The DEC STD 070 reference recommends supporting up to at least 16384 for
-    // parameter values, so 32767 should be more than enough. At most we might
-    // want to increase this to 65535, since that is what XTerm and VTE support,
-    // but for now 32767 is the safest limit for our existing code base.
-    constexpr VTInt MAX_PARAMETER_VALUE = 32767;
+    // The DEC STD 070 reference recommends supporting up to at least 16384
+    // for parameter values. 65535 is what XTerm and VTE support.
+    // GH#12977: We must use 65535 to properly parse win32-input-mode
+    // sequences, which transmit the UTF-16 character value as a parameter.
+    constexpr VTInt MAX_PARAMETER_VALUE = 65535;
 
     // The DEC STD 070 reference requires that a minimum of 16 parameter values
     // are supported, but most modern terminal emulators will allow around twice
diff --git a/src/terminal/parser/ut_parser/OutputEngineTest.cpp b/src/terminal/parser/ut_parser/OutputEngineTest.cpp
index f7df6498c78..02040fabf94 100644
--- a/src/terminal/parser/ut_parser/OutputEngineTest.cpp
+++ b/src/terminal/parser/ut_parser/OutputEngineTest.cpp
@@ -1589,7 +1589,7 @@ class StateMachineExternalTest final
         }
         else if (uiGiven > MAX_PARAMETER_VALUE)
         {
-            *uiExpected = MAX_PARAMETER_VALUE; // 32767 is our max value.
+            *uiExpected = MAX_PARAMETER_VALUE;
         }
     }
 


Test patch: