The PostDataMessage function towards the end of DDEPOP.C is responsible for posting a WM_DDE_DATA message to a client. This function is set up to also handle WM- DDE_ADVISE messages (which I'll discuss shortly), so it's a little more complex than if it only had to handle WM_DDE_REQUEST messages.
PostDataMessage has six parameters:
hwndServer—the window handle of the server
hwndClient—the window handle of the client
i—which is the index of the pop array identifying the state for which population data is requested
fDeferUpd—which ServerProc sets to FALSE when responding to WM_DDE_REQUEST messages
fAckReq—which ServerProc also sets to FALSE in this case
fResponse—which ServerProc sets to TRUE to indicate a response from a WM_DDE_REQUEST message
(I'll discuss the fDeferUpd and fAckReq parameters shortly when we get to the WM_DDE_ADVISE message. For now, just ignore all parts of PostDataMessage when either of these two parameters is set to TRUE.)
PostDataMessage begins by calling GlobalAddItem to create an atom for the two-character state name. (You'll recall that ServerProc deleted the atom before calling PostDataMessage.) It then calls wsprintf to convert the population for the state (updated by WndProc within the past 5 seconds) to a character string terminated with a carriage return and line feed.
PostDataMessage then uses GlobalAlloc with the GMEM_DDESHARE option to allocate a block of memory large enough for a DDEDATA structure (defined in DDE.H) with the actual data (the character string szPopulation) appended to the end. In the case of PostDataMessage being used in response to a WM_DDE_REQUEST message, the fields of the DDEDATA structure are set as follows:
The fResponse field of the DDEDATA structure is set to TRUE, indicating that the data is in response to a WM_DDE_DATA message.
The fRelease field is also set to TRUE, indicating that the client should free the global memory block just allocated.
The fAckReq field is set to FALSE, indicating that a WM_DDE_ACK message from the client is not required.
The cfFormat field is set to CF_TEXT, indicating that the data is in a text format.
The szPopulation array is copied into the area of the memory block beginning at the Value field of the structure.
PostDataMessage then uses PostMessage to post a WM_DDE_DATA message to the client. As usual, wParam is the handle of the window sending the message (the server). The low word of lParam is the handle of the memory block containing the DDEDATA structure, and the high word of lParam is the atom identifying the data item (the two-character state name).
If PostMessage is successful, then we're done. The client is responsible for freeing the memory block and deleting the atom. If PostMessage fails (perhaps because the client is no longer with us), PostDataMessage frees the memory block it allocated and deletes the atom.