VirtualBox

source: vbox/trunk/src/VBox/Runtime/win/errmsgwin.cpp@ 90802

Last change on this file since 90802 was 84068, checked in by vboxsync, 5 years ago

IPRT,++: Compress the windows status code info (errmsgwin.cpp) to save space and reduce load time a tiny bit. [test + fix] bugref:9726

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 9.7 KB
Line 
1/* $Id: errmsgwin.cpp 84068 2020-04-28 23:34:42Z vboxsync $ */
2/** @file
3 * IPRT - Status code messages, Windows.
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/win/windows.h>
32
33#include <iprt/errcore.h>
34#include <iprt/asm.h>
35#include <iprt/string.h>
36
37#include <iprt/bldprog-strtab.h>
38
39
40/*********************************************************************************************************************************
41* Defined Constants And Macros *
42*********************************************************************************************************************************/
43#if !defined(IPRT_ERRMSG_DEFINES_ONLY) && defined(IN_RT_STATIC) /* No message text in static builds to save space. */
44# define IPRT_ERRMSG_DEFINES_ONLY
45#endif
46
47#ifdef IPRT_ERRMSG_DEFINES_ONLY
48# define ENTRY(a_pszMsg, a_pszDefine, a_iCode) \
49 { a_pszDefine, a_pszDefine, a_iCode }
50#else
51# define ENTRY(a_pszMsg, a_pszDefine, a_iCode) \
52 { a_pszMsg, a_pszDefine, a_iCode }
53#endif
54
55
56/*********************************************************************************************************************************
57* Global Variables *
58*********************************************************************************************************************************/
59#ifdef IPRT_ERRMSG_DEFINES_ONLY
60/* Cook data just for VINF_SUCCESS so that code below compiles fine. */
61static const char g_achWinStrTabData[] = { "ERROR_SUCCESS" };
62static const RTBLDPROGSTRTAB g_WinMsgStrTab = { g_achWinStrTabData, sizeof(g_achWinStrTabData) - 1, 0, NULL };
63static const struct
64{
65 int16_t iCode;
66 uint8_t offDefine;
67 uint8_t cchDefine;
68 uint8_t offMsgFull;
69 uint8_t cchMsgFull;
70} g_aWinMsgs[] =
71{
72 { 0, 0, 13, 0, 13, },
73};
74#elif defined(IPRT_ERRMSG_DEFINES_ONLY)
75# include "errmsgwindata-only-defines.h"
76#else
77# include "errmsgwindata-all.h"
78#endif
79
80
81/**
82 * Looks up the message table entry for @a rc.
83 *
84 * @returns index into g_aWinMsgs on success, ~(size_t)0 if not found.
85 * @param rc The status code to locate the entry for.
86 */
87static size_t rtErrWinLookup(long rc)
88{
89 /*
90 * Perform binary search (duplicate code in rtErrLookup).
91 */
92 size_t iStart = 0;
93 size_t iEnd = RT_ELEMENTS(g_aWinMsgs);
94 for (;;)
95 {
96 size_t i = iStart + (iEnd - iStart) / 2;
97 long const iCode = g_aWinMsgs[i].iCode;
98 if (rc < iCode)
99 {
100 if (iStart < i)
101 iEnd = i;
102 else
103 break;
104 }
105 else if (rc > iCode)
106 {
107 i++;
108 if (i < iEnd)
109 iStart = i;
110 else
111 break;
112 }
113 else
114 return i;
115 }
116
117#ifdef RT_STRICT
118 for (size_t i = 0; i < RT_ELEMENTS(g_aWinMsgs); i++)
119 Assert(g_aWinMsgs[i].iCode != rc);
120#endif
121
122 return ~(size_t)0;
123}
124
125
126RTDECL(bool) RTErrWinIsKnown(long rc)
127{
128 if (rtErrWinLookup(rc) != ~(size_t)0)
129 return true;
130 if (SCODE_FACILITY(rc) == FACILITY_WIN32)
131 {
132 if (rtErrWinLookup(HRESULT_CODE(rc)) != ~(size_t)0)
133 return true;
134 }
135 return false;
136}
137
138
139RTDECL(ssize_t) RTErrWinQueryDefine(long rc, char *pszBuf, size_t cbBuf, bool fFailIfUnknown)
140{
141 size_t idx = rtErrWinLookup(rc);
142 if (idx != ~(size_t)0)
143 return RTBldProgStrTabQueryString(&g_WinMsgStrTab,
144 g_aWinMsgs[idx].offDefine, g_aWinMsgs[idx].cchDefine,
145 pszBuf, cbBuf);
146
147 /*
148 * If FACILITY_WIN32 kind of status, look up the win32 code.
149 */
150 if ( SCODE_FACILITY(rc) == FACILITY_WIN32
151 && (idx = rtErrWinLookup(HRESULT_CODE(rc))) != ~(size_t)0)
152 {
153 /* Append the incoming rc, so we know it's not a regular WIN32 status: */
154 ssize_t cchRet = RTBldProgStrTabQueryString(&g_WinMsgStrTab,
155 g_aWinMsgs[idx].offDefine, g_aWinMsgs[idx].cchDefine,
156 pszBuf, cbBuf);
157 if (cchRet > 0)
158 {
159 pszBuf[cchRet++] = '/';
160 return RTStrFormatU32(pszBuf + cchRet, cbBuf - cchRet, rc, 16, 0, 0, RTSTR_F_SPECIAL);
161 }
162 return VERR_BUFFER_OVERFLOW;
163 }
164
165 if (fFailIfUnknown)
166 return VERR_NOT_FOUND;
167 return RTStrFormatU32(pszBuf, cbBuf, rc, 16, 0, 0, RTSTR_F_SPECIAL);
168}
169
170
171RTDECL(size_t) RTErrWinFormatDefine(long rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp)
172{
173 RT_NOREF(pszTmp, cbTmp);
174 size_t idx = rtErrWinLookup(rc);
175 if (idx != ~(size_t)0)
176 return RTBldProgStrTabQueryOutput(&g_WinMsgStrTab,
177 g_aWinMsgs[idx].offDefine, g_aWinMsgs[idx].cchDefine,
178 pfnOutput, pvArgOutput);
179
180 /*
181 * If FACILITY_WIN32 kind of status, look up the win32 code.
182 */
183 size_t cchRet = 0;
184 if ( SCODE_FACILITY(rc) == FACILITY_WIN32
185 && (idx = rtErrWinLookup(HRESULT_CODE(rc))) != ~(size_t)0)
186 {
187 /* Append the incoming rc, so we know it's not a regular WIN32 status: */
188 cchRet = RTBldProgStrTabQueryOutput(&g_WinMsgStrTab,
189 g_aWinMsgs[idx].offDefine, g_aWinMsgs[idx].cchDefine,
190 pfnOutput, pvArgOutput);
191 cchRet += pfnOutput(pvArgOutput, RT_STR_TUPLE("/"));
192 }
193
194 ssize_t cchValue = RTStrFormatU32(pszTmp, cbTmp, rc, 16, 0, 0, RTSTR_F_SPECIAL);
195 Assert(cchValue > 0);
196 cchRet += pfnOutput(pvArgOutput, pszTmp, cchValue);
197 return cchRet;
198}
199
200
201RTDECL(size_t) RTErrWinFormatMsg(long rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp)
202{
203#ifdef IPRT_ERRMSG_DEFINES_ONLY
204 return RTErrWinFormatDefine(rc, pfnOutput, pvArgOutput, pszTmp, cbTmp);
205#else
206 size_t idx = rtErrWinLookup(rc);
207 if (idx != ~(size_t)0)
208 return RTBldProgStrTabQueryOutput(&g_WinMsgStrTab,
209 g_aWinMsgs[idx].offMsgFull, g_aWinMsgs[idx].cchMsgFull,
210 pfnOutput, pvArgOutput);
211
212 /*
213 * If FACILITY_WIN32 kind of status, look up the win32 code.
214 */
215 const char *pszTail = NULL;
216 size_t cchRet;
217 if ( SCODE_FACILITY(rc) == FACILITY_WIN32
218 && (idx = rtErrWinLookup(HRESULT_CODE(rc))) != ~(size_t)0)
219 {
220 /* Append the incoming rc, so we know it's not a regular WIN32 status: */
221 cchRet = RTBldProgStrTabQueryOutput(&g_WinMsgStrTab,
222 g_aWinMsgs[idx].offMsgFull, g_aWinMsgs[idx].cchMsgFull,
223 pfnOutput, pvArgOutput);
224 cchRet += pfnOutput(pvArgOutput, RT_STR_TUPLE(" ("));
225 pszTail = ")";
226 }
227 else
228 cchRet = pfnOutput(pvArgOutput, RT_STR_TUPLE("Unknown Status "));
229
230 ssize_t cchValue = RTStrFormatU32(pszTmp, cbTmp, rc, 16, 0, 0, RTSTR_F_SPECIAL);
231 Assert(cchValue > 0);
232 cchRet += pfnOutput(pvArgOutput, pszTmp, cchValue);
233
234 if (pszTail)
235 cchRet += pfnOutput(pvArgOutput, pszTail, 1);
236 return cchRet;
237#endif
238}
239
240
241RTDECL(size_t) RTErrWinFormatMsgAll(long rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp)
242{
243 RT_NOREF(pszTmp, cbTmp);
244 size_t cchRet;
245 size_t idx = rtErrWinLookup(rc);
246 if ( idx != ~(size_t)0
247 || ( SCODE_FACILITY(rc) == FACILITY_WIN32
248 && (idx = rtErrWinLookup(HRESULT_CODE(rc))) != ~(size_t)0))
249 {
250 cchRet = RTBldProgStrTabQueryOutput(&g_WinMsgStrTab,
251 g_aWinMsgs[idx].offDefine, g_aWinMsgs[idx].cchDefine,
252 pfnOutput, pvArgOutput);
253 cchRet += pfnOutput(pvArgOutput, RT_STR_TUPLE(" ("));
254 }
255 else
256 cchRet = pfnOutput(pvArgOutput, RT_STR_TUPLE("Unknown Status "));
257
258 ssize_t cchValue = RTStrFormatU32(pszTmp, cbTmp, rc, 16, 0, 0, RTSTR_F_SPECIAL);
259 Assert(cchValue > 0);
260 cchRet += pfnOutput(pvArgOutput, pszTmp, cchValue);
261
262#ifndef IPRT_ERRMSG_DEFINES_ONLY
263 if (idx != ~(size_t)0)
264 {
265 cchRet += pfnOutput(pvArgOutput, RT_STR_TUPLE(") - "));
266 cchRet += RTBldProgStrTabQueryOutput(&g_WinMsgStrTab,
267 g_aWinMsgs[idx].offMsgFull, g_aWinMsgs[idx].cchMsgFull,
268 pfnOutput, pvArgOutput);
269 }
270#endif
271 return cchRet;
272}
273
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette