November 14th, 2025
0 reactions

I can use WM_COPYDATA to send a block of data to another window, but how does it send data back?

The WM_COPY­DATA message can be used to send a blob of data from one window to another. The window manager does the work of copying the data from the sending process to the receiving process, but how does the receiving process send data back?

If the only information that needs to come back is a success/failure, the recipient can return TRUE on success or FALSE on failure.

But if you need to return more information, then you have a few choices.

One is to have the receiving window send the results back to the sending window by sending the WM_COPY­DATA message back to the sending window. (The sending window passes its handle in the wParam.) The data blob can contain a transaction ID or some other way to distinguish which WM_COPY­DATA the recipient is responding to.

Another way is for the sending window to create a shared memory block, duplicate the shared handle into the receiving window’s process,¹ and then pass the duplicated handle in the WM_COPY­DATA payload. The receiving window can use Map­View­Of­File to access the shared memory block and write its results there. Of course, if you’re going to do it this way, then you don’t really need WM_COPY­DATA; you can just use a custom message and pass the handle in, say, the wParam.

A customer said that if they created a shared memory block with Create­File­Mapping, they were worried because memory would become visible to all other processes, not just the two processes trying to talk to each other.

Maybe they were thinking about named shared memory blocks, which are accessible to anybody who knows (or can guess) the name, and for whom access is granted by the shared memory block’s access control list.

So don’t use a named shared memory block. Use an anonymous one. The only way to get access to an anonymous shared memory block is to get access to its handle.

So your exposure is not to all processes but just processes which have “duplicate handle” permission. And somebody has “duplicate handle” permission on your process, then they already pwn your process: They can duplicate the GetCurrentProcess() handle out of your process, and that gives them a handle with full access to your process. Your exposure is only to people who are already on the other side of the airtight hatchway.

¹ This assumes that the sending process is running at equal or higher integrity level than the recipient. If the roles are reversed, with a low integrity process sending to a high integrity process, you can delegate the duplication to the recipient. The low integrity sending process allocates the shared memory and puts the handle into the WM_COPY­DATA memory block. The recipient can then call Duplicate­Handle function to duplicate the handle out of the sending process, using Get­Window­Thread­Process­Id to get the sender’s process ID. You can include information in the WM_COPY­DATA memory block to indicate that you are in this reverse case.

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

0 comments