(…because the clipboard is a shared system resource)
A few years back we came across a bug where a customer was unable to copy data from a remote session to the local session using the TS shared clipboard. They had a script in the remote session that was doing something like:
CopyDataToClipboard(...)
//
// Do something...
//
CopyDataToClipboard(...)
The second copy did not always succeed. This was proving to be quite frustrating. After some debugging we discovered the cause…
The Windows system clipboard can only be opened by one application at a time. When it is opened by Application A, attempts by Application B to open it will fail. Hence, B cannot copy any data to the clipboard while A has it open (A might have it open for a valid reason, such as enumerating through the data which is available).
Enter the TS shared clipboard. In order to be notified of when the clipboard has been changed, the TS client (which runs in the local session) and RDPCLIP (which runs in the remote session) register to be part of the clipboard viewer chain associated with their session. When the clipboard is updated, they will be notified of the change. Part of responding to that notification requires opening the clipboard and enumerating through the list of available data types (such as text, graphics or files) and then sending them to the peer component (for example, the TS client will send the list of new data types to RDPCLIP).
Now if you look carefully you can see the race condition which exists in the customer bug. The following time line of events explains it:
1. Script in the remote session opens the clipboard.
2. Script in the remote session copies data to the clipboard.
3. Script in the remote session closes the clipboard.
4. RDPCLIP is notified that the clipboard has been updated.
5. RDPCLIP opens the clipboard to enumerate through the data types.
6. RDPCLIP begins to enumerate through the data types.
7. Script in the remote session tries to open the clipboard.
8. RDPCLIP finishes enumerating through the data types.
9. Script in the remote session fails to open the clipboard.
10. RDPCLIP closes the clipboard.
So, what is the solution? Well, in this case we just made the script retry updating the clipboard a few times, sleeping a bit in between each attempt.
However, for Windows Vista (and Longhorn Server) we worked with our friends in the USER32 team and added a new mechanism which allows us to get the list of data types on the clipboard without opening the clipboard. This means that when the clipboard is updated, RDPCLIP (or the TS client) never needs to hold the clipboard open to enumerate the available data types, effectively blowing away this race condition. Another reason to upgrade to the best Windows version ever!