VirtualBox

source: vbox/trunk/include/VBox/com/errorprint.h@ 89363

Last change on this file since 89363 was 86141, checked in by vboxsync, 4 years ago

Main/glue: Added GlueHandleComErrorNoCtx() for printing extended error info but no method/file/linx context. bugref:9224

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.0 KB
Line 
1/** @file
2 * MS COM / XPCOM Abstraction Layer - Error Reporting.
3 *
4 * Error printing macros using shared functions defined in shared glue code.
5 * Use these CHECK_* macros for efficient error checking around calling COM
6 * methods.
7 */
8
9/*
10 * Copyright (C) 2009-2020 Oracle Corporation
11 *
12 * This file is part of VirtualBox Open Source Edition (OSE), as
13 * available from http://www.virtualbox.org. This file is free software;
14 * you can redistribute it and/or modify it under the terms of the GNU
15 * General Public License (GPL) as published by the Free Software
16 * Foundation, in version 2 as it comes in the "COPYING" file of the
17 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19 *
20 * The contents of this file may alternatively be used under the terms
21 * of the Common Development and Distribution License Version 1.0
22 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
23 * VirtualBox OSE distribution, in which case the provisions of the
24 * CDDL are applicable instead of those of the GPL.
25 *
26 * You may elect to license modified versions of this file under the
27 * terms and conditions of either the GPL or the CDDL or both.
28 */
29
30#ifndef VBOX_INCLUDED_com_errorprint_h
31#define VBOX_INCLUDED_com_errorprint_h
32#ifndef RT_WITHOUT_PRAGMA_ONCE
33# pragma once
34#endif
35
36#include <VBox/com/ErrorInfo.h>
37
38
39/** @defgroup grp_com_error_reporting Error Reporting
40 * @ingroup grp_com
41 * @{
42 */
43
44namespace com
45{
46
47// shared prototypes; these are defined in shared glue code and are
48// compiled only once for all front-ends
49void GluePrintErrorInfo(const com::ErrorInfo &info);
50void GluePrintErrorContext(const char *pcszContext, const char *pcszSourceFile, uint32_t uLine);
51void GluePrintRCMessage(HRESULT rc);
52void GlueHandleComError(ComPtr<IUnknown> iface, const char *pcszContext, HRESULT rc, const char *pcszSourceFile, uint32_t uLine);
53void GlueHandleComErrorNoCtx(ComPtr<IUnknown> iface, HRESULT rc);
54void GlueHandleComErrorProgress(ComPtr<IProgress> progress, const char *pcszContext, HRESULT rc,
55 const char *pcszSourceFile, uint32_t uLine);
56
57/**
58 * Extended macro that implements all the other CHECK_ERROR2XXX macros.
59 *
60 * Calls the method of the given interface and checks the return status code.
61 * If the status indicates failure, as much information as possible is reported
62 * about the error, including current source file and line.
63 *
64 * After reporting an error, the statement |stmtError| is executed.
65 *
66 * This macro family is intended for command line tools like VBoxManage, but
67 * could also be handy for debugging.
68 *
69 * @param type For defining @a hrc locally inside the the macro
70 * expansion, pass |HRESULT| otherwise |RT_NOTHING|.
71 * @param hrc Name of the HRESULT variable to assign the result of the
72 * method call to.
73 * @param iface The interface pointer (can be a smart pointer object).
74 * @param method The method to invoke together with the parameters.
75 * @param stmtError Statement to be executed after reporting failures. This
76 * can be a |break| or |return| statement, if so desired.
77 *
78 * @remarks Unlike CHECK_ERROR, CHECK_ERROR_RET and family, this macro family
79 * does not presuppose a |rc| variable but instead either let the user
80 * specify the variable to use or employs a local variable |hrcCheck|
81 * within its own scope.
82 *
83 * @sa CHECK_ERROR2, CHECK_ERROR2I, CHECK_ERROR2_STMT, CHECK_ERROR2I_STMT,
84 * CHECK_ERROR2_BREAK, CHECK_ERROR2I_BREAK, CHECK_ERROR2_RET,
85 * CHECK_ERROR2I_RET
86 */
87#define CHECK_ERROR2_EX(type, hrc, iface, method, stmtError) \
88 if (1) { \
89 type hrc = iface->method; \
90 if (SUCCEEDED(hrc)) \
91 { /*likely*/ } \
92 else \
93 { \
94 com::GlueHandleComError(iface, #method, (hrc), __FILE__, __LINE__); \
95 stmtError; \
96 } \
97 } else do { /* nothing */ } while (0)
98
99
100/**
101 * Calls the given method of the given interface and then checks if the return
102 * value (COM result code) indicates a failure. If so, prints the failed
103 * function/line/file, the description of the result code and attempts to
104 * query the extended error information on the current thread (using
105 * com::ErrorInfo) if the interface reports that it supports error information.
106 *
107 * Used by command line tools or for debugging and assumes the |HRESULT rc|
108 * variable is accessible for assigning in the current scope.
109 * @sa CHECK_ERROR2, CHECK_ERROR2I
110 */
111#define CHECK_ERROR(iface, method) \
112 do { \
113 rc = iface->method; \
114 if (FAILED(rc)) \
115 com::GlueHandleComError(iface, #method, rc, __FILE__, __LINE__); \
116 } while (0)
117/**
118 * Simplified version of CHECK_ERROR2_EX, no error statement or type necessary.
119 *
120 * @param hrc Name of the HRESULT variable to assign the result of the
121 * method call to.
122 * @param iface The interface pointer (can be a smart pointer object).
123 * @param method The method to invoke together with the parameters.
124 * @sa CHECK_ERROR2I, CHECK_ERROR2_EX
125 */
126#define CHECK_ERROR2(hrc, iface, method) CHECK_ERROR2_EX(RT_NOTHING, hrc, iface, method, (void)1)
127/**
128 * Simplified version of CHECK_ERROR2_EX that uses an internal variable
129 * |hrcCheck| for holding the result and have no error statement.
130 *
131 * @param iface The interface pointer (can be a smart pointer object).
132 * @param method The method to invoke together with the parameters.
133 * @sa CHECK_ERROR2, CHECK_ERROR2_EX
134 */
135#define CHECK_ERROR2I(iface, method) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, (void)1)
136
137
138/**
139 * Same as CHECK_ERROR except that it also executes the statement |stmt| on
140 * failure.
141 * @sa CHECK_ERROR2_STMT, CHECK_ERROR2I_STMT
142 */
143#define CHECK_ERROR_STMT(iface, method, stmt) \
144 do { \
145 rc = iface->method; \
146 if (FAILED(rc)) \
147 { \
148 com::GlueHandleComError(iface, #method, rc, __FILE__, __LINE__); \
149 stmt; \
150 } \
151 } while (0)
152/**
153 * Simplified version of CHECK_ERROR2_EX (no @a hrc type).
154 *
155 * @param hrc Name of the HRESULT variable to assign the result of the
156 * method call to.
157 * @param iface The interface pointer (can be a smart pointer object).
158 * @param method The method to invoke together with the parameters.
159 * @param stmt Statement to be executed after reporting failures.
160 * @sa CHECK_ERROR2I_STMT, CHECK_ERROR2_EX
161 */
162#define CHECK_ERROR2_STMT(hrc, iface, method, stmt) CHECK_ERROR2_EX(RT_NOTHING, hrc, iface, method, stmt)
163/**
164 * Simplified version of CHECK_ERROR2_EX that uses an internal variable
165 * |hrcCheck| for holding the result.
166 *
167 * @param iface The interface pointer (can be a smart pointer object).
168 * @param method The method to invoke together with the parameters.
169 * @param stmt Statement to be executed after reporting failures.
170 * @sa CHECK_ERROR2_STMT, CHECK_ERROR2_EX
171 */
172#define CHECK_ERROR2I_STMT(iface, method, stmt) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, stmt)
173
174
175/**
176 * Does the same as CHECK_ERROR(), but executes the |break| statement on
177 * failure.
178 * @sa CHECK_ERROR2_BREAK, CHECK_ERROR2I_BREAK
179 */
180#ifdef __GNUC__
181# define CHECK_ERROR_BREAK(iface, method) \
182 __extension__ \
183 ({ \
184 rc = iface->method; \
185 if (FAILED(rc)) \
186 { \
187 com::GlueHandleComError(iface, #method, rc, __FILE__, __LINE__); \
188 break; \
189 } \
190 })
191#else
192# define CHECK_ERROR_BREAK(iface, method) \
193 if (1) \
194 { \
195 rc = iface->method; \
196 if (FAILED(rc)) \
197 { \
198 com::GlueHandleComError(iface, #method, rc, __FILE__, __LINE__); \
199 break; \
200 } \
201 } \
202 else do {} while (0)
203#endif
204/**
205 * Simplified version of CHECK_ERROR2_EX that executes the |break| statement
206 * after error reporting (no @a hrc type).
207 *
208 * @param hrc The result variable (type HRESULT).
209 * @param iface The interface pointer (can be a smart pointer object).
210 * @param method The method to invoke together with the parameters.
211 * @sa CHECK_ERROR2I_BREAK, CHECK_ERROR2_EX
212 */
213#define CHECK_ERROR2_BREAK(hrc, iface, method) CHECK_ERROR2_EX(RT_NOTHING, hrc, iface, method, break)
214/**
215 * Simplified version of CHECK_ERROR2_EX that executes the |break| statement
216 * after error reporting and that uses an internal variable |hrcCheck| for
217 * holding the result.
218 *
219 * @param iface The interface pointer (can be a smart pointer object).
220 * @param method The method to invoke together with the parameters.
221 * @sa CHECK_ERROR2_BREAK, CHECK_ERROR2_EX
222 */
223#define CHECK_ERROR2I_BREAK(iface, method) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, break)
224/**
225 * Simplified version of CHECK_ERROR2_EX that executes the |stmt;break|
226 * statements after error reporting and that uses an internal variable
227 * |hrcCheck| for holding the result.
228 *
229 * @param iface The interface pointer (can be a smart pointer object).
230 * @param method The method to invoke together with the parameters.
231 * @param stmt Statement to be executed after reporting failures.
232 * @sa CHECK_ERROR2_BREAK, CHECK_ERROR2_EX
233 */
234#define CHECK_ERROR2I_BREAK_STMT(iface, method, stmt) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, stmt; break)
235
236
237/**
238 * Does the same as CHECK_ERROR(), but executes the |return ret| statement on
239 * failure.
240 * @sa CHECK_ERROR2_RET, CHECK_ERROR2I_RET
241 */
242#define CHECK_ERROR_RET(iface, method, ret) \
243 do { \
244 rc = iface->method; \
245 if (FAILED(rc)) \
246 { \
247 com::GlueHandleComError(iface, #method, rc, __FILE__, __LINE__); \
248 return (ret); \
249 } \
250 } while (0)
251/**
252 * Simplified version of CHECK_ERROR2_EX that executes the |return (rcRet)|
253 * statement after error reporting.
254 *
255 * @param hrc The result variable (type HRESULT).
256 * @param iface The interface pointer (can be a smart pointer object).
257 * @param method The method to invoke together with the parameters.
258 * @param rcRet What to return on failure.
259 */
260#define CHECK_ERROR2_RET(hrc, iface, method, rcRet) CHECK_ERROR2_EX(RT_NOTHING, hrc, iface, method, return (rcRet))
261/**
262 * Simplified version of CHECK_ERROR2_EX that executes the |return (rcRet)|
263 * statement after error reporting and that uses an internal variable |hrcCheck|
264 * for holding the result.
265 *
266 * @param iface The interface pointer (can be a smart pointer object).
267 * @param method The method to invoke together with the parameters.
268 * @param rcRet What to return on failure. Use |hrcCheck| to return
269 * the status code of the method call.
270 */
271#define CHECK_ERROR2I_RET(iface, method, rcRet) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, return (rcRet))
272
273
274/**
275 * Check the progress object for an error and if there is one print out the
276 * extended error information.
277 * @remarks Requires HRESULT variable named @a rc.
278 */
279#define CHECK_PROGRESS_ERROR(progress, msg) \
280 do { \
281 LONG iRc; \
282 rc = progress->COMGETTER(ResultCode)(&iRc); \
283 if (FAILED(rc) || FAILED(iRc)) \
284 { \
285 if (SUCCEEDED(rc)) rc = iRc; else iRc = rc; \
286 RTMsgError msg; \
287 com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, iRc, __FILE__, __LINE__); \
288 } \
289 } while (0)
290
291/**
292 * Does the same as CHECK_PROGRESS_ERROR(), but executes the |break| statement
293 * on failure.
294 * @remarks Requires HRESULT variable named @a rc.
295 */
296#ifdef __GNUC__
297# define CHECK_PROGRESS_ERROR_BREAK(progress, msg) \
298 __extension__ \
299 ({ \
300 LONG iRc; \
301 rc = progress->COMGETTER(ResultCode)(&iRc); \
302 if (FAILED(rc) || FAILED(iRc)) \
303 { \
304 if (SUCCEEDED(rc)) rc = iRc; else iRc = rc; \
305 RTMsgError msg; \
306 com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, iRc, __FILE__, __LINE__); \
307 break; \
308 } \
309 })
310#else
311# define CHECK_PROGRESS_ERROR_BREAK(progress, msg) \
312 if (1) \
313 { \
314 LONG iRc; \
315 rc = progress->COMGETTER(ResultCode)(&iRc); \
316 if (FAILED(rc) || FAILED(iRc)) \
317 { \
318 if (SUCCEEDED(rc)) rc = iRc; else iRc = rc; \
319 RTMsgError msg; \
320 com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, iRc, __FILE__, __LINE__); \
321 break; \
322 } \
323 } \
324 else do {} while (0)
325#endif
326
327/**
328 * Does the same as CHECK_PROGRESS_ERROR(), but executes the |return ret|
329 * statement on failure.
330 */
331#define CHECK_PROGRESS_ERROR_RET(progress, msg, ret) \
332 do { \
333 LONG iRc; \
334 HRESULT hrcCheck = progress->COMGETTER(ResultCode)(&iRc); \
335 if (SUCCEEDED(hrcCheck) && SUCCEEDED(iRc)) \
336 { /* likely */ } \
337 else \
338 { \
339 RTMsgError msg; \
340 com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, \
341 SUCCEEDED(hrcCheck) ? iRc : hrcCheck, __FILE__, __LINE__); \
342 return (ret); \
343 } \
344 } while (0)
345
346/**
347 * Asserts the given expression is true. When the expression is false, prints
348 * a line containing the failed function/line/file; otherwise does nothing.
349 */
350#define ASSERT(expr) \
351 do { \
352 if (!(expr)) \
353 { \
354 RTPrintf ("[!] ASSERTION FAILED at line %d: %s\n", __LINE__, #expr); \
355 Log (("[!] ASSERTION FAILED at line %d: %s\n", __LINE__, #expr)); \
356 } \
357 } while (0)
358
359
360/**
361 * Does the same as ASSERT(), but executes the |return ret| statement if the
362 * expression to assert is false;
363 * @remarks WARNING! @a expr is evalutated TWICE!
364 */
365#define ASSERT_RET(expr, ret) \
366 do { ASSERT(expr); if (!(expr)) return (ret); } while (0)
367
368/**
369 * Does the same as ASSERT(), but executes the |break| statement if the
370 * expression to assert is false;
371 * @remarks WARNING! @a expr is evalutated TWICE!
372 */
373#define ASSERT_BREAK(expr, ret) \
374 if (1) { ASSERT(expr); if (!(expr)) break; } else do {} while (0)
375
376} /* namespace com */
377
378
379/** @} */
380
381#endif /* !VBOX_INCLUDED_com_errorprint_h */
382
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