Search code examples
pointerswinapimemorycallbackdangling-pointer

In Windows API application-defined callback functions, what is the lifetime of pointer parameter data? Does it persist after the callback returns?


As an example, let's look at EnumWindowStations(), which requires the caller to pass an EnumWindowStationsProc() callback function. The callback function will be invoked once for every window station in the current terminal session. Let's look at the signature of the callback function:

BOOL CALLBACK EnumWindowStationProc(
    _In_ LPTSTR lpszWindowStation,
    _In_ LPARAM lParam
);

The first parameter is a pointer to string data. Was that string buffer allocated explicitly for the callback invocation, and will it be freed immediately after the callback returns, or perhaps immediately before the enumeration function returns? Or, does the pointer point to some kind of persistent memory, such that the string buffer will remain allocated and usable afterward?

This is an important point, because if it is not persistent, then it would be incorrect to, for example, store the raw pointer in a global container to be accessed after the callback and full enumeration process have finished. Instead, it would be necessary to copy the underlying string data to a buffer controlled by the application, before the callback returns.

The official documentation does not seem to make clear what the lifetime of the string data is. There's only one line in the description of the parameter:

lpszWindowStation [in]

    The name of the window station.

And nowhere on the documentation page does it talk about the lifetime of the string data. Nor can I recall ever finding an MSDN page that answers this question "once and for all", i.e. for all uses of the callback idiom in the Windows API.

At the moment I am most interested in the EnumWindowStations()/EnumWindowStationsProc() case, but it would be best if answerers would address the general case, i.e. what to assume for all Windows API callback functions.


Solution

  • Generally if the memory is allocated by the system you can rely on it being valid for the duration of the callback and no more. That is the case for lpszWindowStation in your example. You would need to access and copy the string inside your callback function and must not refer to the system supplied data outside your callback.

    You can deduce this with a little thought experiment. If this string could be accessed after the callback returned when would it become invalid? When would it be deallocated? You'd have to tell the system that you were done with it. Since there is no API indicated to do that the only conclusion is that stated above.

    Things are different for lParam. That value was supplied by you when you called EnumWindowStations and so you manage the lifetime of whatever it points to, if indeed you are using it as a pointer.