c++mfchtml-help

What is the c++ approach for upgrading these c style casts for HtmlHelp API?


What is the c++ approach for upgrading these c style casts for HtmlHelp API?

void CMeetingScheduleAssistantApp::DisplayHelpTopic(CString strTopic)
{
    CString strURL = _T("https://help-msa.publictalksoftware.co.uk/") + strTopic;

    if (theApp.UseDownloadedHelpDocumentation())
    {
        // CHM files use 3 letter suffix
        strTopic.Replace(_T(".html"), _T(".htm"));
        HtmlHelp((DWORD_PTR)(LPCTSTR)strTopic, HH_DISPLAY_TOPIC);
    }
    else
        ShellExecute(nullptr, nullptr, strURL, nullptr, nullptr, SW_SHOWDEFAULT);
}

Specifically:

HtmlHelp((DWORD_PTR)(LPCTSTR)strTopic, HH_DISPLAY_TOPIC);


In answer to the question in the comments:

enter image description here

It is odd because the official docs for x86 HtmlHelpA / HtmlHelpW do indicate different calls.

It doesn't seem to be listed as part of the CWinApp class in the docs.


Solution

  • reinterpret_cast will always trigger a code analysys warning

    In that case, you could invent your own pointer cast function. A smart compiler will most probably optimize this away:

    #include <cstring>
    
    template<class D, class T>
    D ptr_cast(T* x) {
        D rv;
        static_assert(sizeof rv == sizeof x);
        std::memcpy(&rv, &x, sizeof rv);
        return rv;
    }
    

    Then

    HtmlHelp( ptr_cast<DWORD_PTR>(strTopic.GetString()),
              HH_DISPLAY_TOPIC);
    

    In g++ and clang++, explicitly instantiating the function

    template DWORD_PTR ptr_cast<DWORD_PTR,char>(char*);
    

    makes it into the assembly code

    unsigned long ptr_cast<unsigned long, char>(char*):
            mov     rax, rdi
            ret
    

    When inlined and optimized (as it will be in your code) the function call is gone and only the mov (assignment) to the destination DWORD_PTR is left, which is exactly the trace a reinterpret_cast would leave. In MSVC, inlining it results in the similar:

    lea     rdx, OFFSET FLAT:`string'