The WM_DDE_REQUEST Message

A client posts a WM_DDE_REQUEST message to a server when it wants data that is associated with a particular item. This is the type of transaction known as the cold link. The server responds by posting a WM_DDE_DATA message to the client with the data or a WM_DDE_ACK message if it cannot satisfy the request. Let's look at how ServerProc handles the WM_DDE_REQUEST message.

As is usual with DDE messages, the wParam parameter accompanying WM_DDE- REQUEST is the handle to the window posting the message, in this case the client. The low word of the lParam parameter is a requested data format. The high word of lParam is an atom identifying the requested data item.

The formats of DDE data are the same as clipboard formats, so this low word of lParam will most commonly be one of the identifiers beginning with the CF prefix. A client may send multiple WM_DDE_REQUEST messages to a server for the same item but with different formats. The server should respond with a WM_DDE_DATA message for only the formats it supports. Far and away the most common format for DDE data is CF_TEXT, and this is the only format that DDEPOP supports.

So, when processing the WM_DDE_REQUEST message, ServerProc first checks if the requested format is CF_TEXT. ServerProc then calls the GlobalGetAtomName function to get the character string associated with the atom passed in the high word of lParam. If the client knows what it's doing, this will be a two-character string identifying the state. A for loop goes through the states and attempts to match this with the szState field of the pop structure. If there's a match, ServerProc deletes the atom by calling GlobalDeleteAtom and then calls PostDataMessage (a function towards the end of DDEPOP that posts the WM_DDE_DATA message and which I'll describe shortly). ServerProc then returns.

If the requested format is not CF_TEXT, or if there was no match between the item atom and one of the state names, then ServerProc posts a negative WM_DDE_ACK message indicating that the data was not available. It does this by setting the fAck field of a DDEACK structure (defined in DDE.H) to FALSE. The DDEACK structure is converted to a word, which forms the low word of lParam. The high word of lParam is the atom for the requested item. PostMessage posts the WM_DDE_ACK message to the client.

Notice how the atom is handled here. The documentation for WM_DDE_REQUEST states: ”When responding with either a WM_DDE_DATA or WM_DDE_ACK message, reuse the aItem atom or delete it and create a new one.“ What this means is that the state of the global atom table should not be altered by the server—that is, the reference count for the item atom should not be incremented or decremented.

There are three cases here:

If the requested format is CF_TEXT and the atom matches one of the state names, then ServerProc calls GlobalDeleteAtom before calling the function in DDEPOP.C named PostDataMessage. This PostDataMessage function (as we'll see shortly) re-creates the atom when posting a WM_DDE_DATA message to the client.

If the requested format is not CF_TEXT or if the atom does not match one of the state names, then ServerProc calls PostMessage to deliver a negative WM_DDE_ACK message to the client. The atom is simply reused in this message.

However, if this PostMessage call fails (perhaps indicating that the client has been unexpectedly terminated), then ServerProc deletes the atom because the client cannot.

We are not yet finished with the WM_DDE_REQUEST message because we have not yet examined how DDEPOP's PostDataMessage responds with the WM_DDE_DATA message. That's next.