Skip to Content

Hacking the Windows Clipboard: CF_HTML vs CF_RTF

A deep dive into the payload structures of the Windows Clipboard and how I built the 'Paste as Rich Text' feature for PowerToys.

Table of contents

No titles in the blog post

This is Part 2 of the PowerToys Experience series. Read Part 1 here.

I was trying to build an orchestration flow for the Windows Clipboard when I realized most developers treat it like a magical black box. It is not. The Windows Clipboard is a brutal, complex data structure that holds multiple distinct payloads simultaneously. When you hit Ctrl+V, the receiving application arbitrarily decides which payload it prefers.


The Clipboard Payload Battle โš”๏ธ

CF_RTF: Microsoft's ancient, rock-solid standard. Used by legacy apps like WordPad. Extremely complex to generate.
CF_HTML: The modern standard. Required by Google Docs, Slack, Notion, and heavily preferred by modern Word and Outlook.


Building "Paste as Rich Text"

My goal was to allow users to copy raw Markdown and paste it as fully-formatted Rich Text. Instead of trying to generate archaic RTF bytes from scratchโ€”a massive architectural vulnerabilityโ€”I leveraged the existing Markdig dependency in the PowerToys repository to compile the Markdown into semantic HTML.

// 1. Compile raw Markdown into Semantic HTML using Markdig
var pipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build();
string htmlContent = Markdown.ToHtml(rawMarkdown, pipeline);

Then came the critical structural bypass: You can't just shove raw HTML into the clipboard. You have to format it using the native HtmlFormatHelper, which wraps the HTML string in a highly specific header containing exact byte offsets so the receiving application knows where the payload starts and ends.

// 2. Wrap the HTML in the CF_HTML byte-offset header
string clipboardHtml = HtmlFormatHelper.CreateHtmlFormat(htmlContent);

// 3. Inject into the Windows Clipboard as CF_HTML
Clipboard.SetText(clipboardHtml, TextDataFormat.Html);

While CF_HTML works flawlessly for 95% of modern apps, true universal support requires generating BOTH CF_HTML and CF_RTF simultaneously. This is the exact architectural debate currently happening on the open-source PR thread.

In the final part of this series, I'll dive into the brutal reality of open-source CI pipelines, how I got a PR rejected, and how I had to rip out 35 seconds of thread delays to save the automated UI tests.

Continue reading the series:
Part 3: The Brutal Reality of Open Source CI Pipelines โž”

Want to try the tool? Download Microsoft PowerToys from the Microsoft Store.

Archive

Comments

Sign in to leave a comment
Stop Paying for Clicks. Start Building Automation.
Marketing brings leads to the front door, but a broken paper intake process turns them away. Here is how CDTA automated the entire customer journey.