Skip to content

fix(agent): add OEM code page transcoding in Devolutions Agent#1780

Open
Vladyslav Nikonov (vnikonov-devolutions) wants to merge 1 commit into
masterfrom
fix/agent-io-encodings
Open

fix(agent): add OEM code page transcoding in Devolutions Agent#1780
Vladyslav Nikonov (vnikonov-devolutions) wants to merge 1 commit into
masterfrom
fix/agent-io-encodings

Conversation

@vnikonov-devolutions
Copy link
Copy Markdown
Contributor

This PR adds redirected IO text transcoding to/from OEM code page.

By default all windows command shells (cmd, PowerShell5 & PowerShell7) use OEM code page for console input/output. In RDM we expect UTF-8, and prior to Devolutions/now-proto#62 wire format for now proto was not specified. This PR changes this ad implements OEM <-> UTF8 transcoding.

Additionally, UNICODE_CONSOLE flag was implemented, enabling explicit switching to UTF-8 stdio mode in cmd, ps, pwsh by injecting encoding change command to script file. That means, not only OEM encoding is now handled correctly, but any unicode text can be correctly transfered to/from exec session and displayed in RDM.

Merge blocked by Devolutions/now-proto#62 (crate release)

PS D:\now-proto\dotnet\Devolutions.NowClient.Cli\bin\x64\Debug\net10.0> .\Devolutions.NowClient.Cli.exe --pipe now-proto-GLOBAL
Connecting to the NowProto DVC...
Pipe transport has been connected via now-proto-GLOBAL
Negotiated NowProto client version: NowProtoVersion { Major = 1, Minor = 6 }

Operation: cmd
Batch command: echo деволюшнс
Executing batch command: echo деволюшнс
--- STDOUT Output (20 bytes) ---
деволюшнс
Exit code: 0
Execution time: 0,06 seconds

Operation: +unicode
UNICODE_CONSOLE flag ENABLED

Operation: cmd
Batch command: echo привіт
Executing batch command: echo привіт
--- STDOUT Output (14 bytes) ---
привіт
Exit code: 0
Execution time: 0,05 seconds

Issue: DGW-370

@github-actions
Copy link
Copy Markdown

Let maintainers know that an action is required on their side

  • Add the label release-required Please cut a new release (Devolutions Gateway, Devolutions Agent, Jetsocat, PowerShell module) when you request a maintainer to cut a new release (Devolutions Gateway, Devolutions Agent, Jetsocat, PowerShell module)

  • Add the label release-blocker Follow-up is required before cutting a new release if a follow-up is required before cutting a new release

  • Add the label publish-required Please publish libraries (`Devolutions.Gateway.Utils`, OpenAPI clients, etc) when you request a maintainer to publish libraries (Devolutions.Gateway.Utils, OpenAPI clients, etc.)

  • Add the label publish-blocker Follow-up is required before publishing libraries if a follow-up is required before publishing libraries

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Windows console/OEM code page handling for exec session IO redirection in devolutions-session, enabling correct UTF-8 behavior over NowProto (including a new UNICODE_CONSOLE mode that switches shells to UTF-8).

Changes:

  • Introduces a Windows codepage transcoding module (DataEncoding, InputEncoder, OutputDecoder) to convert stdout/stderr to UTF-8 and stdin from UTF-8 when appropriate.
  • Wires per-session/process encoding selection into exec styles (process, batch, Windows PowerShell, PowerShell 7+), including UTF-8 console injection for UNICODE_CONSOLE.
  • Extends temp file helpers to write scripts in specific encodings (OEM-transcoded, UTF-8 with BOM).

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
devolutions-session/src/dvc/task.rs Selects IO/script encodings per exec operation; adds UNICODE_CONSOLE support and encoding-aware process builder usage.
devolutions-session/src/dvc/process.rs Adds encoding to process context and performs streaming stdin/stdout/stderr transcoding (including flush on EOF).
devolutions-session/src/dvc/mod.rs Exposes the new encoding module.
devolutions-session/src/dvc/fs.rs Adds temp file write helpers for encoded content and UTF-8 BOM scripts.
devolutions-session/src/dvc/encoding.rs New transcoding implementation using Win32 codepage APIs + unit tests.
devolutions-session/Cargo.toml Adds Win32_Globalization Windows feature; modifies now-proto-pdu dependency config (currently broken).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 45 to 49
[dependencies.now-proto-pdu]
optional = true
version = "0.4.2"
# TODO: wait for merge and release https://github.com/Devolutions/now-proto/pull/62
features = ["std"]

Comment on lines +196 to +209
let valid_end = find_valid_utf8_end(&input);

if valid_end == 0 {
// All bytes are part of an incomplete sequence.
self.leftover = input.into_owned();
return Cow::Owned(Vec::new());
}

// Save any trailing incomplete UTF-8 bytes.
if valid_end < input.len() {
self.leftover = input[valid_end..].to_vec();
}

let utf8_str = match std::str::from_utf8(&input[..valid_end]) {
Comment on lines +266 to +274
/// Returns `Err` if the input contains an incomplete multi-byte character.
fn convert_to_utf8(codepage: u32, data: &[u8]) -> Result<Vec<u8>, ()> {
if data.is_empty() {
return Ok(Vec::new());
}

// First pass: get required buffer size for UTF-16 conversion.
// Using MB_ERR_INVALID_CHARS to detect incomplete sequences.
// SAFETY: `data` is a valid byte slice.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants