What I found in everyday practice is that it is best to focus on the OVERLAPPED result, as this will not change. One way you can use it effectively is to do something like the following:
struct CompletionHandler { OVERLAPPED dummy_ovl; };
When you send something to IOCP (via an I / O call or just a message through the Win32 API), you first create a CompletionHandler object that you will use to track the call, and enter the address of this object before OVERLAPPED* .
CompletionHander my_handler; // Fill in whatever you need to in my_handler // Don't forget to keep the original my_handler! // I/O call goes here, and for OVERLAPPED* give: (OVERLAPPED*)&my_handler
That way, when you get the OVERLAPPED result, all you have to do is return it back to CompletionHandler and voila! You have the original context of your call.
OVERLAPPED* from_queued_completion_status;
For more information in the real world, see the ASIO Implementation Guide for Windows ( ver 1.42 here ). There are some details, such as checking the OVERLAPPED pointer that you get from GetQueuedCompletionStatus , but again see the GetQueuedCompletionStatus for a good implementation method.
Brian
source share