/* $Id: errmsgwin.cpp 83984 2020-04-27 00:17:19Z vboxsync $ */ /** @file * IPRT - Status code messages, Windows. */ /* * Copyright (C) 2006-2020 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. * * The contents of this file may alternatively be used under the terms * of the Common Development and Distribution License Version 1.0 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the * VirtualBox OSE distribution, in which case the provisions of the * CDDL are applicable instead of those of the GPL. * * You may elect to license modified versions of this file under the * terms and conditions of either the GPL or the CDDL or both. */ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ #include #include #include #include /********************************************************************************************************************************* * Defined Constants And Macros * *********************************************************************************************************************************/ #if defined(IPRT_ERRMSG_DEFINES_ONLY) || defined(IN_RT_STATIC) /* No message text in static builds to save space. */ # define ENTRY(a_pszMsg, a_pszDefine, a_iCode) \ { a_pszDefine, a_pszDefine, a_iCode } #else # define ENTRY(a_pszMsg, a_pszDefine, a_iCode) \ { a_pszMsg, a_pszDefine, a_iCode } #endif /********************************************************************************************************************************* * Global Variables * *********************************************************************************************************************************/ /** Array of messages. * The data is generated by sed scripts and sorted by errmsgwin-sorter.cpp. */ static const RTWINERRMSG g_aStatusMsgs[] = { #if !defined(IPRT_NO_ERROR_DATA) && !defined(DOXYGEN_RUNNING) # include "errmsgwindata-sorted.h" #else { "Success.", "ERROR_SUCCESS", 0 }, #endif }; /** Temporary buffers to format unknown messages in. * @{ */ static char g_aszUnknownStr[8][64]; static RTWINERRMSG g_aUnknownMsgs[8] = { { &g_aszUnknownStr[0][0], &g_aszUnknownStr[0][0], 0 }, { &g_aszUnknownStr[1][0], &g_aszUnknownStr[1][0], 0 }, { &g_aszUnknownStr[2][0], &g_aszUnknownStr[2][0], 0 }, { &g_aszUnknownStr[3][0], &g_aszUnknownStr[3][0], 0 }, { &g_aszUnknownStr[4][0], &g_aszUnknownStr[4][0], 0 }, { &g_aszUnknownStr[5][0], &g_aszUnknownStr[5][0], 0 }, { &g_aszUnknownStr[6][0], &g_aszUnknownStr[6][0], 0 }, { &g_aszUnknownStr[7][0], &g_aszUnknownStr[7][0], 0 }, }; /** Last used index in g_aUnknownMsgs. */ static volatile uint32_t g_iUnknownMsgs; /** @} */ /** * Get the message corresponding to a given status code. * * @returns Pointer to read-only message description. * @param rc The status code. */ RTDECL(PCRTWINERRMSG) RTErrWinGet(long rc) { /* * Perform binary search (duplicate code in RTErrGet). */ size_t iStart = 0; size_t iEnd = RT_ELEMENTS(g_aStatusMsgs); for (;;) { size_t i = iStart + (iEnd - iStart) / 2; long const iCode = g_aStatusMsgs[i].iCode; if (rc < iCode) { if (iStart < i) iEnd = i; else break; } else if (rc > iCode) { i++; if (i < iEnd) iStart = i; else break; } else return &g_aStatusMsgs[i]; } #ifdef RT_STRICT for (size_t i = 0; i < RT_ELEMENTS(g_aStatusMsgs); i++) Assert(g_aStatusMsgs[i].iCode != rc); #endif /* * If FACILITY_WIN32 kind of status, look up the win32 code. */ if (SCODE_FACILITY(rc) == FACILITY_WIN32) { long const rcWin32 = HRESULT_CODE(rc); iStart = 0; iEnd = RT_ELEMENTS(g_aStatusMsgs); for (;;) { size_t i = iStart + (iEnd - iStart) / 2; long const iCode = g_aStatusMsgs[i].iCode; if (rcWin32 < iCode) { if (iStart < i) iEnd = i; else break; } else if (rcWin32 > iCode) { i++; if (i < iEnd) iStart = i; else break; } else { /* Append the incoming rc, so we know it's not a regular WIN32 status: */ int32_t iMsg = (ASMAtomicIncU32(&g_iUnknownMsgs) - 1) % RT_ELEMENTS(g_aUnknownMsgs); RTStrPrintf(&g_aszUnknownStr[iMsg][0], sizeof(g_aszUnknownStr[iMsg]), "%s/0x%x", g_aStatusMsgs[i].pszDefine, rc); return &g_aUnknownMsgs[iMsg]; } } #ifdef RT_STRICT for (size_t i = 0; i < RT_ELEMENTS(g_aStatusMsgs); i++) Assert(g_aStatusMsgs[i].iCode != rcWin32); #endif } /* * Need to use the temporary stuff. */ int32_t iMsg = (ASMAtomicIncU32(&g_iUnknownMsgs) - 1) % RT_ELEMENTS(g_aUnknownMsgs); RTStrPrintf(&g_aszUnknownStr[iMsg][0], sizeof(g_aszUnknownStr[iMsg]), "Unknown Status 0x%X", rc); return &g_aUnknownMsgs[iMsg]; } RTDECL(PCRTCOMERRMSG) RTErrCOMGet(uint32_t rc) { return RTErrWinGet((long)rc); }