inline HRESULT GetFailureLogString()

in include/wil/result_macros.h [1078:1201]


    inline HRESULT GetFailureLogString(_Out_writes_(cchDest) _Always_(_Post_z_) PWSTR pszDest, _Pre_satisfies_(cchDest > 0) _In_ size_t cchDest, _In_ FailureInfo const &failure) WI_NOEXCEPT
    {
        // This function was lenient to empty strings at one point and some callers became dependent on this beahvior
        if ((cchDest == 0) || (pszDest == nullptr))
        {
            return S_OK;
        }

        pszDest[0] = L'\0';

        // Call the logging callback (if present) to allow them to generate the debug string that will be pushed to the console
        // or the platform exception object if the caller desires it.
        if ((g_pfnResultLoggingCallback != nullptr) && details::g_resultMessageCallbackSet)
        {
            // older-form callback was a non-const FailureInfo*; conceptually this is const as callers should not be modifying
            g_pfnResultLoggingCallback(const_cast<FailureInfo*>(&failure), pszDest, cchDest);
        }

        // The callback only optionally needs to supply the debug string -- if the callback didn't populate it, yet we still want
        // it for OutputDebugString or exception message, then generate the default string.
        if (pszDest[0] == L'\0')
        {
            PCSTR pszType = "";
            switch (failure.type)
            {
            case FailureType::Exception:
                pszType = "Exception";
                break;
            case FailureType::Return:
                if (WI_IsFlagSet(failure.flags, FailureFlags::NtStatus))
                {
                    pszType = "ReturnNt";
                }
                else
                {
                    pszType = "ReturnHr";
                }
                break;
            case FailureType::Log:
                if (WI_IsFlagSet(failure.flags, FailureFlags::NtStatus))
                {
                    pszType = "LogNt";
                }
                else
                {
                    pszType = "LogHr";
                }
                break;
            case FailureType::FailFast:
                pszType = "FailFast";
                break;
            }

            wchar_t szErrorText[256];
            szErrorText[0] = L'\0';
            LONG errorCode = 0;

            if (WI_IsFlagSet(failure.flags, FailureFlags::NtStatus))
            {
                errorCode = failure.status;
                if (wil::details::g_pfnFormatNtStatusMsg)
                {
                    wil::details::g_pfnFormatNtStatusMsg(failure.status, szErrorText, ARRAYSIZE(szErrorText));
                }
            }
            else
            {
                errorCode = failure.hr;
                FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, failure.hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), szErrorText, ARRAYSIZE(szErrorText), nullptr);
            }

            // %FILENAME(%LINE): %TYPE(%count) tid(%threadid) %HRESULT %SystemMessage
            //     %Caller_MSG [%CODE(%FUNCTION)]

            PWSTR dest = pszDest;
            PCWSTR destEnd = (pszDest + cchDest);

            if (failure.pszFile != nullptr)
            {
                dest = details::LogStringPrintf(dest, destEnd, L"%hs(%u)\\%hs!%p: ", failure.pszFile, failure.uLineNumber, failure.pszModule, failure.returnAddress);
            }
            else
            {
                dest = details::LogStringPrintf(dest, destEnd, L"%hs!%p: ", failure.pszModule, failure.returnAddress);
            }

            if (failure.callerReturnAddress != nullptr)
            {
                dest = details::LogStringPrintf(dest, destEnd, L"(caller: %p) ", failure.callerReturnAddress);
            }

            dest = details::LogStringPrintf(dest, destEnd, L"%hs(%d) tid(%x) %08X %ws", pszType, failure.cFailureCount, ::GetCurrentThreadId(), errorCode, szErrorText);

            if ((failure.pszMessage != nullptr) || (failure.pszCallContext != nullptr) || (failure.pszFunction != nullptr))
            {
                dest = details::LogStringPrintf(dest, destEnd, L"    ");
                if (failure.pszMessage != nullptr)
                {
                    dest = details::LogStringPrintf(dest, destEnd, L"Msg:[%ws] ", failure.pszMessage);
                }
                if (failure.pszCallContext != nullptr)
                {
                    dest = details::LogStringPrintf(dest, destEnd, L"CallContext:[%hs] ", failure.pszCallContext);
                }

                if (failure.pszCode != nullptr)
                {
                    dest = details::LogStringPrintf(dest, destEnd, L"[%hs(%hs)]\n", failure.pszFunction, failure.pszCode);
                }
                else if (failure.pszFunction != nullptr)
                {
                    dest = details::LogStringPrintf(dest, destEnd, L"[%hs]\n", failure.pszFunction);
                }
                else
                {
                    dest = details::LogStringPrintf(dest, destEnd, L"\n");
                }
            }
        }

        // Explicitly choosing to return success in the event of truncation... Current callers
        // depend upon it or it would be eliminated.
        return S_OK;
    }