Repository navigation
feat(agent): add clipboard image support - #1877
Merged
Benoît Cortier (CBenoit) merged 1 commit intoSep 4, 2026
Merged
Benoît Cortier (CBenoit) merged 1 commit into
Benoît Cortier (CBenoit) merged 1 commit into
Conversation
Greg Lamberson (glamberson)
temporarily deployed
to
llm-providers
September 2, 2026 01:51 — with
GitHub Actions
Inactive
Contributor
Author
Benoît Cortier (CBenoit)
temporarily deployed
to
llm-providers
September 2, 2026 13:58 — with
GitHub Actions
Inactive
Benoît Cortier (CBenoit)
approved these changes
Sep 2, 2026
Copilot started reviewing on behalf of
Benoît Cortier (CBenoit)
September 2, 2026 15:45
View session
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
RPC size mismatch, stale-response correlation, and concurrent advertisement races can break clipboard operations.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds PNG clipboard image support to the agent daemon and CLI using CLIPRDR DIB conversions.
Changes:
- Adds image clipboard RPC variants and CLI commands.
- Supports DIB/DIBV5 advertisement and conversion.
- Adds wire round-trip and redaction tests.
File summaries
| File | Description |
|---|---|
crates/ironrdp-testsuite-extra/tests/agent.rs |
Extends RPC codec tests. |
crates/ironrdp-rpc/src/wire/mod.rs |
Adds optional byte encoding. |
crates/ironrdp-rpc/src/ipc.rs |
Defines image RPC messages and limits. |
crates/ironrdp-daemon/src/daemon.rs |
Handles image clipboard requests. |
crates/ironrdp-daemon/src/clipboard.rs |
Implements DIB image clipboard behavior. |
crates/ironrdp-daemon/Cargo.toml |
Adds the format-conversion dependency. |
crates/ironrdp-agent/src/help.rs |
Documents image commands. |
crates/ironrdp-agent/src/cli.rs |
Implements image file operations. |
crates/ironrdp-activex/src/rpc.rs |
Marks image operations unavailable. |
Cargo.lock |
Records the dependency update. |
Review details
- Files reviewed: 9/10 changed files
- Comments generated: 6
- Review effort level: Balanced
Benoît Cortier (CBenoit)
temporarily deployed
to
llm-providers
September 3, 2026 12:48 — with
GitHub Actions
Inactive
Extends the daemon clipboard-get/clipboard-set operations added in Devolutions#1863 to images: clipboard-get-image writes the last image received from the remote clipboard to a PNG file, clipboard-set-image reads a PNG file and advertises it to the remote as CF_DIB/CF_DIBV5. The daemon stores images as PNG bytes and converts to/from the wire's DIB byte layout via ironrdp-cliprdr-format's existing png_to_cf_dib(v5) and dib(v5)_to_png. Both DIB variants are advertised when offering an image (DIBV5 is richer but not every peer understands it); on paste, DIBV5 is preferred over DIB, and image is preferred over text when the remote offers both. Replaces ClipboardState's two Option<String> fields with a small ClipboardContent enum (Text/Image) so local and remote clipboard content is a single logical item, matching how each clipboard-set* call replaces whatever was there before. New Request::ClipboardGetImage/ClipboardSetImage and Payload::ClipboardImage wire variants. Adds the two new variants to ironrdp-activex's exhaustive match on Request, same treatment as the existing ClipboardGet/ClipboardSet arm (unavailable through the ActiveX automation surface). Behavior change: clipboard-get now prints (empty) if the last remote copy was an image rather than text, since local/remote content is a single logical item. Previously it always reflected the last text. Review round (CBenoit, Copilot): Seven issues addressed. - MAX_CLIPBOARD_IMAGE_BYTES is now derived from ironrdp-rpc's own transport::MAX_MESSAGE_LEN (16 MiB) minus framing headroom, instead of an unrelated 64 MiB that the RPC transport could never actually carry. - Fixed a real, pre-existing bug in ironrdp-cliprdr-format::bitmap:: decode_png: It requested ALPHA | EXPAND but not STRIP_16, and this png crate version declares a GRAY_TO_RGB transform flag but never implements it, so grayscale and 16-bit-per-channel PNGs decoded to a buffer layout the RGBA-only conversion downstream silently misread. Added STRIP_16, a manual GrayscaleAlpha-to-RGBA expansion, a MAX_BUFFER_SIZE re-check for that expansion, and grayscale/16-bit regression tests. - The CLIPRDR backend now serializes paste requests: on_remote_copy no longer issues a second SendInitiatePaste while one is outstanding (a stale response could otherwise be misinterpreted as the answer to a newer request, since FormatDataResponse carries no correlation ID). A newer copy is queued and issued once the outstanding one resolves, or after a 5-second timeout if the peer never answers. - The daemon now checks a converted remote image against MAX_CLIPBOARD_IMAGE_BYTES before storing it, so a legitimate but oversized image from the remote can't get stuck in a state where clipboard-get-image can never send it back. - clipboard_set/clipboard_set_image now write local and advertise to a connected session as one atomic step under the clipboard mutex, so concurrent IPC callers can't interleave their state write and their advertisement. - clipboard-set-image reads at most MAX_CLIPBOARD_IMAGE_BYTES + 1 bytes via Read::take instead of loading the whole file before checking its size. - Extended the Debug-redaction test to also cover the pre-existing text variants, which the original PR body claimed but the test didn't exercise. cargo xtask check fmt/lints/tests/typos/locks all pass. Not yet verified against a live remote client; that check is still owed before merge.
Greg Lamberson (glamberson)
force-pushed
the
feat/agent-clipboard-image
branch
from
September 3, 2026 17:52
8ce022b to
7f6ffd9
Compare
Greg Lamberson (glamberson)
temporarily deployed
to
llm-providers
September 3, 2026 17:53 — with
GitHub Actions
Inactive
Greg Lamberson (glamberson)
added a commit
to lamco-admin/IronRDP
that referenced
this pull request
Sep 3, 2026
Depends on Devolutions#1877 (clipboard image support), which this branch is stacked on: it introduces the ClipboardContent enum this PR extends with an Html variant. Diff is cumulative against master per the usual stacking note; the image-only diff is Devolutions#1877's own. Extends the daemon clipboard-get/clipboard-set operations to HTML fragments: clipboard-get-html prints the last HTML fragment received from the remote clipboard, clipboard-set-html sets one and advertises it to the remote as the registered HTML Format. Stores the fragment as plain text (not yet CF_HTML-wrapped) and converts at the point of use via ironrdp-cliprdr-format's existing plain_html_to_cf_html/cf_html_to_plain_html, so no new markup handling is needed here, mirroring the image PR's use of the crate's existing bitmap conversions. HTML Format is a registered, not fixed-ID, clipboard format: the offering side picks a private-range ID (0xC000 here) and pairs it with the name; the receiver learns the ID-to-name mapping from the FormatList. When receiving, matches the remote's offer by name and uses whatever ID it assigned, not the locally-chosen one, since those only apply to formats this backend itself offers. Extends the remote-copy priority order to image, then HTML, then text (richest representation first), and the PendingPaste tracking added in Devolutions#1877 with an Html variant so a returned FormatDataResponse is decoded correctly regardless of which of the three was requested. A remote HTML fragment over the same 256 KiB bound is dropped and logged rather than stored, mirroring the oversized-image drop Devolutions#1877 added for the same reason: an unbounded stored value would otherwise fail encoding once handed back to clipboard-get-html over the RPC transport. New Request::ClipboardGetHtml/ClipboardSetHtml and Payload::ClipboardHtml wire variants, bounded at 256 KiB in the CLI parser and on wire decode. Extends ironrdp-activex's exhaustive match on Request with the same treatment as the other clipboard operations. Extends the wire round-trip and Debug-redaction test coverage added in Devolutions#1877 to the two new variants. cargo xtask check fmt/lints/tests/typos/locks all pass. Not yet verified against a live remote client, same as Devolutions#1877.
Benoît Cortier (CBenoit)
temporarily deployed
to
llm-providers
September 4, 2026 01:43 — with
GitHub Actions
Inactive
Benoît Cortier (CBenoit)
approved these changes
Sep 4, 2026
Benoît Cortier (CBenoit)
left a comment
Member
There was a problem hiding this comment.
Thank you, Greg
Greg Lamberson (glamberson)
added a commit
to lamco-admin/IronRDP
that referenced
this pull request
Sep 4, 2026
Depends on Devolutions#1877 (clipboard image support), which this branch is stacked on: it introduces the ClipboardContent enum this PR extends with an Html variant. Diff is cumulative against master per the usual stacking note; the image-only diff is Devolutions#1877's own. Extends the daemon clipboard-get/clipboard-set operations to HTML fragments: clipboard-get-html prints the last HTML fragment received from the remote clipboard, clipboard-set-html sets one and advertises it to the remote as the registered HTML Format. Stores the fragment as plain text (not yet CF_HTML-wrapped) and converts at the point of use via ironrdp-cliprdr-format's existing plain_html_to_cf_html/cf_html_to_plain_html, so no new markup handling is needed here, mirroring the image PR's use of the crate's existing bitmap conversions. HTML Format is a registered, not fixed-ID, clipboard format: the offering side picks a private-range ID (0xC000 here) and pairs it with the name; the receiver learns the ID-to-name mapping from the FormatList. When receiving, matches the remote's offer by name and uses whatever ID it assigned, not the locally-chosen one, since those only apply to formats this backend itself offers. Extends the remote-copy priority order to image, then HTML, then text (richest representation first), and the PendingPaste tracking added in Devolutions#1877 with an Html variant so a returned FormatDataResponse is decoded correctly regardless of which of the three was requested. A remote HTML fragment over the same 256 KiB bound is dropped and logged rather than stored, mirroring the oversized-image drop Devolutions#1877 added for the same reason: an unbounded stored value would otherwise fail encoding once handed back to clipboard-get-html over the RPC transport. New Request::ClipboardGetHtml/ClipboardSetHtml and Payload::ClipboardHtml wire variants, bounded at 256 KiB in the CLI parser and on wire decode. Extends ironrdp-activex's exhaustive match on Request with the same treatment as the other clipboard operations. Extends the wire round-trip and Debug-redaction test coverage added in Devolutions#1877 to the two new variants. cargo xtask check fmt/lints/tests/typos/locks all pass. Not yet verified against a live remote client, same as Devolutions#1877.
Anton Mostovoy (antonmos)
added a commit
to antonmos/IronRDP
that referenced
this pull request
Sep 8, 2026
…nnection-negotiation * upstream/master: (124 commits) feat(server): let an authenticated connection preempt an existing session (Devolutions#1476) ci(pr-automation): recover reviewer stages (Devolutions#1922) ci(pr-automation): report review check diagnostics (Devolutions#1926) ci(pr-automation): recover agent runtime (Devolutions#1921) ci(pr-automation): report reviewer recovery (Devolutions#1920) docs(pr-automation): define review recovery intent (Devolutions#1915) feat(web): expose enable_server_pointer from the WASM module (Devolutions#1914) fix(web): restore default remote cursor rendering (Devolutions#1910) feat(usb)!: support SuperSpeed packet sizes (Devolutions#1883) ci(pr-automation): explain reviewer ineligibility (Devolutions#1906) ci(pr-automation): explain skipped reviews (Devolutions#1907) ci(pr-automation): request JSON mode (Devolutions#1908) ci(pr-automation): repair empty agent responses (Devolutions#1905) ci(pr-automation): diagnose invalid repairs (Devolutions#1904) ci(pr-automation): simplify review findings (Devolutions#1901) fix(server): bound accept_finalize so a wedged client cannot hold the server (Devolutions#1890) ci(pr-automation): improve reviewer diagnostics (Devolutions#1898) ci(pr-automation): redispatch explicit retries (Devolutions#1897) test: focus PR automation workflow coverage (Devolutions#1896) feat(agent): add clipboard image support (Devolutions#1877) ... # Conflicts: # crates/ironrdp-server/src/server.rs
Marc-André Moreau (mamoreau-devolutions)
pushed a commit
that referenced
this pull request
Sep 22, 2026
#1877 (clipboard image support) merged: This PR now rebases cleanly onto master and its own diff is HTML-only. It still depends on the ClipboardContent enum #1877 introduced. Extends the daemon clipboard-get/clipboard-set operations to HTML fragments: clipboard-get-html prints the last HTML fragment received from the remote clipboard, clipboard-set-html sets one and advertises it to the remote as the registered HTML Format. Stores the fragment as plain text (not yet CF_HTML-wrapped) and converts at the point of use via ironrdp-cliprdr-format's existing plain_html_to_cf_html/cf_html_to_plain_html, so no new markup handling is needed here, mirroring the image PR's use of the crate's existing bitmap conversions. HTML Format is a registered, not fixed-ID, clipboard format: The offering side picks a private-range ID (0xC000 here) and pairs it with the name; the receiver learns the ID-to-name mapping from the FormatList. When receiving, matches the remote's offer by name and uses whatever ID it assigned, not the locally-chosen one, since those only apply to formats this backend itself offers. Extends the remote-copy priority order to image, then HTML, then text (richest representation first), and the PendingPaste tracking added in #1877 with an Html variant so a returned FormatDataResponse is decoded correctly regardless of which of the three was requested. A remote HTML fragment over the 256 KiB bound is dropped and logged rather than stored, mirroring the oversized-image drop #1877's review round added, for the same reason: An unbounded stored value would otherwise fail encoding once handed back over the RPC transport. New Request::ClipboardGetHtml/ClipboardSetHtml and Payload::ClipboardHtml wire variants, bounded at 256 KiB in the CLI parser and on wire decode. Extends ironrdp-activex's exhaustive match on Request with the same treatment as the other clipboard operations. Extends the wire round-trip and Debug-redaction test coverage added in #1877 to the two new variants. cargo xtask check fmt/lints/tests/typos/locks all pass. Not yet verified against a live remote client, same as #1877.
Greg Lamberson (glamberson)
added a commit
to lamco-admin/IronRDP
that referenced
this pull request
Sep 22, 2026
Extends the daemon clipboard-get/clipboard-set operations added in Devolutions#1877 to files: clipboard-set-files offers one or more local files to the remote via the CLIPRDR file-list mechanism (FileGroupDescriptorW), clipboard-list-files lists what the remote currently offers (metadata only, matching the delayed-render model MS-RDPECLIP itself uses), and clipboard-get-file fetches one file's full contents by its position in that list. Independent of Devolutions#1878 (HTML support, still open): This branches directly off master rather than off Devolutions#1878, and touches none of its code. Both extend the ClipboardContent enum Devolutions#1877 introduced, so whichever of the two merges first will need the other rebased, same as the earlier Devolutions#1877/Devolutions#1878 rebase. Extends ClipboardContent with a Files variant (wire-shaped metadata, symmetric for what is offered locally and what the remote last advertised); a parallel local_file_paths list on ClipboardState carries the on-disk paths a local offer maps to, since FileDescriptor itself carries no filesystem path and file transfer is a structurally different CLIPRDR mechanism from the FormatDataRequest path text/image/HTML share. Advertises STREAM_FILECLIP_ENABLED and CAN_LOCK_CLIPDATA in client_capabilities. Cliprdr::initiate_file_copy and request_file_contents both hard-error when file transfer was not negotiated, and that error is session-fatal by the time it reaches ironrdp-client's dispatcher, so the daemon tracks the negotiated capabilities from on_process_negotiated_capabilities and checks them before sending either message, failing cleanly at the IPC layer instead. Cliprdr already owns the whole clipboard-lock lifecycle for file transfer (snapshotting the local file list on an incoming LockData, auto-locking when a remote file list arrives, timeout-driven expiry); this backend's on_lock/on_unlock stay informational. on_outgoing_locks_expired is not: It aborts an in-progress clipboard-get-file fetch bound to the expiring lock rather than let it continue issuing requests against a remote clipboard that has since changed underneath it. on_remote_copy clears an in-progress fetch the same way when the remote clipboard changes again mid-fetch, so a clipboard-get-file caller left waiting is told the fetch was interrupted instead of silently blocked until its own timeout. clipboard-get-file drives ironrdp_cliprdr::chunked_fetch::ChunkedFetch to completion inside the daemon, bounded at MAX_CLIPBOARD_FILE_BYTES (derived from the RPC transport's own frame limit, the same reasoning MAX_CLIPBOARD_IMAGE_BYTES already uses) before issuing any wire request, not just before framing the IPC response. The IPC handler and the CLIPRDR backend's on_file_contents_response coordinate through a per-session Notify, the same wait-and-recheck shape rail_wait already uses for RAIL evidence, including re-checking state once more after a timeout races against a same-instant completion rather than assuming a timeout means nothing arrived. Serving a remote's request for a file we offered (on_file_contents_request) reads from the local path clipboard-set-files recorded, seeking to the requested range and capping a single RANGE response at 4 MiB regardless of what the peer's own cbRequested asks for: MS-RDPECLIP defines cbRequested as an upper bound on what a responder may return, not a guarantee, and ChunkedFetch on the requesting side already handles a shorter-than-asked response by issuing another RANGE request for the remainder. This read happens synchronously on the session's own current-thread runtime (Cliprdr callbacks are not async), bounded per response by the same 4 MiB cap: A slow local read stalls that session briefly rather than the whole daemon, but it is a real tradeoff against a fully async read path, disclosed rather than silently accepted. Directory entries are rejected, not silently mishandled: clipboard-set-files refuses a directory path outright rather than support recursive folder copy (out of scope here), and a remote directory entry (real Windows Explorer folder copies advertise one per subfolder, mixed in with the files) is shown as such in clipboard-list-files and refused by clipboard-get-file rather than attempt a byte fetch against it. New Request::ClipboardSetFiles/ClipboardListFiles/ClipboardGetFile and Payload::ClipboardFileList/ClipboardFile wire variants, plus the shared ClipboardFileEntry metadata type, bounded at MAX_CLIPBOARD_FILE_BYTES and MAX_CLIPBOARD_FILE_LIST_ENTRIES on wire decode. Extends ironrdp-activex's exhaustive match on Request with the same treatment as the other clipboard operations. Extends the wire round-trip and Debug-redaction test coverage added in Devolutions#1877 to the three new variants. cargo xtask check fmt/lints/tests/typos/locks all pass. Not yet verified against a live remote client, same as Devolutions#1877/Devolutions#1878.
Marc-André Moreau (mamoreau-devolutions)
pushed a commit
that referenced
this pull request
Sep 28, 2026
Extends the daemon clipboard-get/clipboard-set operations added in #1877 to files: clipboard-set-files offers one or more local files to the remote via the CLIPRDR file-list mechanism (FileGroupDescriptorW), clipboard-list-files lists what the remote currently offers (metadata only, matching the delayed-render model MS-RDPECLIP itself uses), and clipboard-get-file fetches one file's full contents by its position in that list. Rebased onto master after #1878 (HTML support) merged. The two were built in parallel and both extend the ClipboardContent enum from #1877, so this PR now carries both: A remote copy is requested files over image over HTML over text, and the file-transfer IPC tags sit after HTML's (Payload 16 and 17, Request 35 to 37) rather than reusing the numbers HTML took. Extends ClipboardContent with a Files variant (wire-shaped metadata, symmetric for what is offered locally and what the remote last advertised); a parallel local_file_paths list on ClipboardState carries the on-disk paths a local offer maps to, since FileDescriptor itself carries no filesystem path and file transfer is a structurally different CLIPRDR mechanism from the FormatDataRequest path text/image/HTML share. Advertises STREAM_FILECLIP_ENABLED and CAN_LOCK_CLIPDATA in client_capabilities. Cliprdr::initiate_file_copy and request_file_contents both hard-error when file transfer was not negotiated, and that error is session-fatal by the time it reaches ironrdp-client's dispatcher, so the daemon tracks the negotiated capabilities from on_process_negotiated_capabilities and checks them before sending either message, failing cleanly at the IPC layer instead. Cliprdr already owns the whole clipboard-lock lifecycle for file transfer (snapshotting the local file list on an incoming LockData, auto-locking when a remote file list arrives, timeout-driven expiry); this backend's on_lock/on_unlock stay informational. on_outgoing_locks_expired is not: It aborts an in-progress clipboard-get-file fetch bound to the expiring lock rather than let it continue issuing requests against a remote clipboard that has since changed underneath it. on_remote_copy clears an in-progress fetch the same way when the remote clipboard changes again mid-fetch, so a clipboard-get-file caller left waiting is told the fetch was interrupted instead of silently blocked until its own timeout. clipboard-get-file drives ironrdp_cliprdr::chunked_fetch::ChunkedFetch to completion inside the daemon, bounded at MAX_CLIPBOARD_FILE_BYTES (derived from the RPC transport's own frame limit, the same reasoning MAX_CLIPBOARD_IMAGE_BYTES already uses) before issuing any wire request, not just before framing the IPC response. The IPC handler and the CLIPRDR backend's on_file_contents_response coordinate through a per-session Notify, the same wait-and-recheck shape rail_wait already uses for RAIL evidence, including re-checking state once more after a timeout races against a same-instant completion rather than assuming a timeout means nothing arrived. Serving a remote's request for a file we offered (on_file_contents_request) reads from the local path clipboard-set-files recorded, seeking to the requested range and capping a single RANGE response at 4 MiB regardless of what the peer's own cbRequested asks for: MS-RDPECLIP defines cbRequested as an upper bound on what a responder may return, not a guarantee, and ChunkedFetch on the requesting side already handles a shorter-than-asked response by issuing another RANGE request for the remainder. This read happens synchronously on the session's own current-thread runtime (Cliprdr callbacks are not async), bounded per response by the same 4 MiB cap: A slow local read stalls that session briefly rather than the whole daemon, but it is a real tradeoff against a fully async read path, disclosed rather than silently accepted. Directory entries are rejected, not silently mishandled: clipboard-set-files refuses a directory path outright rather than support recursive folder copy (out of scope here), and a remote directory entry (real Windows Explorer folder copies advertise one per subfolder, mixed in with the files) is shown as such in clipboard-list-files and refused by clipboard-get-file rather than attempt a byte fetch against it. New Request::ClipboardSetFiles/ClipboardListFiles/ClipboardGetFile and Payload::ClipboardFileList/ClipboardFile wire variants, plus the shared ClipboardFileEntry metadata type, bounded at MAX_CLIPBOARD_FILE_BYTES and MAX_CLIPBOARD_FILE_LIST_ENTRIES on wire decode. Extends ironrdp-activex's exhaustive match on Request with the same treatment as the other clipboard operations. Extends the wire round-trip and Debug-redaction test coverage added in #1877 to the three new variants. cargo xtask check fmt/lints/tests/typos/locks all pass. Not yet verified against a live remote client, same as #1877/#1878.
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Extends the daemon clipboard-get/clipboard-set operations added in #1863 to
images: clipboard-get-image writes the last image received from the remote
clipboard to a PNG file, clipboard-set-image reads a PNG file and advertises
it to the remote as CF_DIB/CF_DIBV5.
The daemon stores images as PNG bytes and converts to/from the wire's DIB
byte layout via ironrdp-cliprdr-format's existing png_to_cf_dib(v5) and
dib(v5)_to_png, so no new pixel-format code is needed here. Both DIB variants
are advertised when offering an image (DIBV5 is richer but not every peer
understands it); on paste, DIBV5 is preferred over DIB, and image is
preferred over text when the remote offers both.
Replaces ClipboardState's two Option fields with a small
ClipboardContent enum (Text/Image) so local and remote clipboard content is
a single logical item, matching how each clipboard-set* call replaces
whatever was there before. Adds a PendingPaste field to the CLIPRDR backend
to track which format was requested, since FormatDataResponse does not
itself carry the format it answers and MS-RDPECLIP allows only one
outstanding request at a time.
New Request::ClipboardGetImage/ClipboardSetImage and
Payload::ClipboardImage wire variants, bounded at 64 MiB (matching
ironrdp-cliprdr-format's own internal cap) both in the CLI parser and on
wire decode. clipboard_set_image validates the PNG up front by attempting
the DIB conversion, so a bad set fails immediately rather than only once the
remote asks for it.
Adds the two new variants to ironrdp-activex's exhaustive match on Request,
same treatment as the existing ClipboardGet/ClipboardSet arm (unavailable
through the ActiveX automation surface). Adds wire round-trip and
Debug-redaction test coverage for all four clipboard Request/Payload
variants, including the two existing text ones that had none before.
Behavior change: clipboard-get now prints (empty) if the last remote copy
was an image rather than text, since local/remote content is a single
logical item. Previously it always reflected the last text.
Known limitation: FormatDataResponse does not carry a request-correlation
ID, so a stale response to a superseded paste request (a second remote
copy landing before the first paste response arrives) is fed through
whatever PendingPaste variant is current at the time. The failure mode is
graceful: the mismatched conversion (dib_to_png/dibv5_to_png on the wrong
byte layout) returns an error and the response is dropped, not
misinterpreted as valid data.
cargo xtask check fmt/lints/tests/typos/locks all pass, including new wire
round-trip and Debug-redaction coverage for both DIB and DIBV5 paths. Not
yet verified against a live remote client; that check is still owed before
merge.