Search code examples
visual-c++castingmfcc-stringspostmessage

Is it safe to use CString::GetString() with CWnd::SendMessage()?


I have this code:

GetParent()->SendMessage(UWM_DELETE_NAME_HISTORY_MSG, (WPARAM)strName.GetBufferSetLength(_MAX_PATH));
strName.ReleaseBuffer();

Is it safe for me to change it like this:

GetParent()->SendMessage(UWM_DELETE_NAME_HISTORY_MSG, (WPARAM)strName.GetString());

Related to this, is it correct to use static_cast<WPARAM>(strName.GetString())?


For completion, this is my custom message handler:

LRESULT CChristianLifeMinistryEditorDlg::OnDeleteNameHistory(WPARAM wParam, LPARAM lParam)
{
    auto szName = (LPCTSTR)wParam;

    m_History.erase(szName);

    for (auto& kv : m_mapWeekendHistData)
        kv.second.erase(szName);

    return 0;
}

Solution

  • SendMessage is a blocking call. Once it returns, it no longer needs access to its arguments. With that in mind

    GetParent()->SendMessage(UWM_DELETE_NAME_HISTORY_MSG, (WPARAM)strName.GetString());
    

    is safe (as far as the SendMessage call is concerned).

    You'd still need to be careful about the implementer of the UWM_DELETE_NAME_HISTORY_MSG message (which, presumably, is a custom message). If the implementation stores a pointer and uses it after the handler has run to completion, then that is an issue that needs to be resolved.

    In general, if you implement a message handler, you should follow the Windows API's core principles. There are ultimately two implementation:

    • Store a copy of client-provided data (such as SetWindowTextW).
    • Return a reference to the previous value in case the API takes ownership of the client-provided data (such as SelectObject).