A customer was trying to write a tool to preload items into the clipboard history. In a way, this is sort of the opposite of history. Instead of looking backward to things that were once on the clipboard in the past, they want to look forward into the future and preload things that they anticipate you are soon going to wish were on the clipboard. Here’s a stripped-down version.
// All error checking elided for expository purposes #include <windows.h> void SetClipboardText(HWND hwnd, PCWSTR text) { OpenClipboard(hwnd); EmptyClipboard(); auto size = sizeof(wchar_t) * (1 + wcslen(text)); auto clipData = GlobalAlloc(GMEM_MOVEABLE, size); auto buffer = (LPWSTR)GlobalLock(clipData); strcpy_s(buffer, size, text); GlobalUnlock(clipData); SetClipboardData(CF_UNICODETEXT, clipData); CloseClipboard(); } // Put these strings in the clipboard history for quick access. static constexpr PCWSTR messages[] = { L"314159", // the bug number we want to edit L"e83c5163316f89bfbde7d9ab23ca2e25604af290", // the commit to link the bug to L"Widget polarity was set incorrectly.", // the comment to add }; int wmain([[maybe_unused]] int argc, [[maybe_unused]] wchar_t* argv[]) { auto tempWindow = CreateWindowExW(0, L"static", nullptr, WS_POPUPWINDOW, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr); for (auto message : messages) { SetClipboardText(tempWindow, message); } DestroyWindow(tempWindow); return 0; }
This program sets three strings onto the clipboard one after the other. But when you run it, only the last string makes it into the clipboard history. What happened to the other two?
The clipboard history service operates asynchronously. It registers for clipboard changes via AddÂClipboardÂFormatÂListener
, and when it receives a change notification, it updates the clipboard history. The listener is notified asynchronous, however, so by the time the listener receives the WM_
message, the clipboard may have changed a second time.
This is different from clipboard viewers, which are notified synchronously when the clipboard changes. The downside is that you might miss out on clipboard changes. The much better upside is that you don’t slow down or hang the clipboard.
In practice, missing every little clipboard change is sort of a feature of the clipboard history service. I can imagine that there are programs that just spam the clipboard with a rapid sequence of clipboard changes. All of the intermediate ones are useless because they are never on the clipboard long enough for the user to paste them. Only the last one really counts from an end-user point of view, so it’s reasonable that the clipboard history service matches what the user sees on the clipboard.
Next time, we’ll see what we can do to repair this program.
Developers who call
without the action being user-initiated should be executed.
The action is user-initiated because the user ran this program, whose stated purpose is emptying the clipboard and replacing its contents! This is just a hard-coded version of clip.exe.
The scenario is “I have a workflow that requires me to paste a lot of long hard-to-remember strings. I can make this easier by writing an app that figures out what strings I need, and then preloads them into the clipboard history, so that I can use Win+V to access them, rather than having to keep switching back and forth between the app that has the strings and the app that I want to paste them into.” This program is presumably being run by the user for this express purpose. I don’t see where encrypted storage enters the picture.
Re 2: it’s the program’s responsibility because prior to preloading, Windows isn’t aware that a program is about to edit the clipboard. But I suspect you have a non-desktop model of security. If the program preloading the history runs in the context of the user, there’s no security boundary to other processes running as the same user (at the same integrity level). Any decryption the program can do, other programs can do for it.
Re 3: It’s clear from the exposition that the user will press Win+V, then click through the three items. The purpose is to make the three things...
First, stated purpose in your article was “to preload items into the clipboard history” — that doesn’t imply erasing current contents.
Second, what guarantee the user has that those clipboard items will be kept in encrypted storage until it’s time to preload them?
Third, if history is enabled shouldn’t you save what’s on the clipboard and add it back after preloading to, you know, preserve history?
Guess: Listen to Windows.ApplicationModel.DataTransfer.Clipboard.HistoryChanged?