VirtualBox

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

Last change on this file since 76558 was 76558, checked in by vboxsync, 6 years ago

include/VBox: Use VBOX_INCLUDED_ rather than _vbox_ as header guard prefix, letting scm enforce this (thereby avoiding copy&paste errors like NativeEventQueue.h).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.9 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-2019 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 GlueHandleComErrorProgress(ComPtr<IProgress> progress, const char *pcszContext, HRESULT rc,
54 const char *pcszSourceFile, uint32_t uLine);
55
56/**
57 * Extended macro that implements all the other CHECK_ERROR2XXX macros.
58 *
59 * Calls the method of the given interface and checks the return status code.
60 * If the status indicates failure, as much information as possible is reported
61 * about the error, including current source file and line.
62 *
63 * After reporting an error, the statement |stmtError| is executed.
64 *
65 * This macro family is intended for command line tools like VBoxManage, but
66 * could also be handy for debugging.
67 *
68 * @param type For defining @a hrc locally inside the the macro
69 * expansion, pass |HRESULT| otherwise |RT_NOTHING|.
70 * @param hrc Name of the HRESULT variable to assign the result of the
71 * method call to.
72 * @param iface The interface pointer (can be a smart pointer object).
73 * @param method The method to invoke together with the parameters.
74 * @param stmtError Statement to be executed after reporting failures. This
75 * can be a |break| or |return| statement, if so desired.
76 *
77 * @remarks Unlike CHECK_ERROR, CHECK_ERROR_RET and family, this macro family
78 * does not presuppose a |rc| variable but instead either let the user
79 * specify the variable to use or employs a local variable |hrcCheck|
80 * within its own scope.
81 *
82 * @sa CHECK_ERROR2, CHECK_ERROR2I, CHECK_ERROR2_STMT, CHECK_ERROR2I_STMT,
83 * CHECK_ERROR2_BREAK, CHECK_ERROR2I_BREAK, CHECK_ERROR2_RET,
84 * CHECK_ERROR2I_RET
85 */
86#define CHECK_ERROR2_EX(type, hrc, iface, method, stmtError) \
87 if (1) { \
88 type hrc = iface->method; \
89 if (SUCCEEDED(hrc)) \
90 { /*likely*/ } \
91 else \
92 { \
93 com::GlueHandleComError(iface, #method, (hrc), __FILE__, __LINE__); \
94 stmtError; \
95 } \
96 } else do { /* nothing */ } while (0)
97
98
99/**
100 * Calls the given method of the given interface and then checks if the return
101 * value (COM result code) indicates a failure. If so, prints the failed
102 * function/line/file, the description of the result code and attempts to
103 * query the extended error information on the current thread (using
104 * com::ErrorInfo) if the interface reports that it supports error information.
105 *
106 * Used by command line tools or for debugging and assumes the |HRESULT rc|
107 * variable is accessible for assigning in the current scope.
108 * @sa CHECK_ERROR2, CHECK_ERROR2I
109 */
110#define CHECK_ERROR(iface, method) \
111 do { \
112 rc = iface->method; \
113 if (FAILED(rc)) \
114 com::GlueHandleComError(iface, #method, rc, __FILE__, __LINE__); \
115 } while (0)
116/**
117 * Simplified version of CHECK_ERROR2_EX, no error statement or type necessary.
118 *
119 * @param hrc Name of the HRESULT variable to assign the result of the
120 * method call to.
121 * @param iface The interface pointer (can be a smart pointer object).
122 * @param method The method to invoke together with the parameters.
123 * @sa CHECK_ERROR2I, CHECK_ERROR2_EX
124 */
125#define CHECK_ERROR2(hrc, iface, method) CHECK_ERROR2_EX(RT_NOTHING, hrc, iface, method, (void)1)
126/**
127 * Simplified version of CHECK_ERROR2_EX that uses an internal variable
128 * |hrcCheck| for holding the result and have no error statement.
129 *
130 * @param iface The interface pointer (can be a smart pointer object).
131 * @param method The method to invoke together with the parameters.
132 * @sa CHECK_ERROR2, CHECK_ERROR2_EX
133 */
134#define CHECK_ERROR2I(iface, method) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, (void)1)
135
136
137/**
138 * Same as CHECK_ERROR except that it also executes the statement |stmt| on
139 * failure.
140 * @sa CHECK_ERROR2_STMT, CHECK_ERROR2I_STMT
141 */
142#define CHECK_ERROR_STMT(iface, method, stmt) \
143 do { \
144 rc = iface->method; \
145 if (FAILED(rc)) \
146 { \
147 com::GlueHandleComError(iface, #method, rc, __FILE__, __LINE__); \
148 stmt; \
149 } \
150 } while (0)
151/**
152 * Simplified version of CHECK_ERROR2_EX (no @a hrc type).
153 *
154 * @param hrc Name of the HRESULT variable to assign the result of the
155 * method call to.
156 * @param iface The interface pointer (can be a smart pointer object).
157 * @param method The method to invoke together with the parameters.
158 * @param stmt Statement to be executed after reporting failures.
159 * @sa CHECK_ERROR2I_STMT, CHECK_ERROR2_EX
160 */
161#define CHECK_ERROR2_STMT(hrc, iface, method, stmt) CHECK_ERROR2_EX(RT_NOTHING, hrc, iface, method, stmt)
162/**
163 * Simplified version of CHECK_ERROR2_EX that uses an internal variable
164 * |hrcCheck| for holding the result.
165 *
166 * @param iface The interface pointer (can be a smart pointer object).
167 * @param method The method to invoke together with the parameters.
168 * @param stmt Statement to be executed after reporting failures.
169 * @sa CHECK_ERROR2_STMT, CHECK_ERROR2_EX
170 */
171#define CHECK_ERROR2I_STMT(iface, method, stmt) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, stmt)
172
173
174/**
175 * Does the same as CHECK_ERROR(), but executes the |break| statement on
176 * failure.
177 * @sa CHECK_ERROR2_BREAK, CHECK_ERROR2I_BREAK
178 */
179#ifdef __GNUC__
180# define CHECK_ERROR_BREAK(iface, method) \
181 __extension__ \
182 ({ \
183 rc = iface->method; \
184 if (FAILED(rc)) \
185 { \
186 com::GlueHandleComError(iface, #method, rc, __FILE__, __LINE__); \
187 break; \
188 } \
189 })
190#else
191# define CHECK_ERROR_BREAK(iface, method) \
192 if (1) \
193 { \
194 rc = iface->method; \
195 if (FAILED(rc)) \
196 { \
197 com::GlueHandleComError(iface, #method, rc, __FILE__, __LINE__); \
198 break; \
199 } \
200 } \
201 else do {} while (0)
202#endif
203/**
204 * Simplified version of CHECK_ERROR2_EX that executes the |break| statement
205 * after error reporting (no @a hrc type).
206 *
207 * @param hrc The result variable (type HRESULT).
208 * @param iface The interface pointer (can be a smart pointer object).
209 * @param method The method to invoke together with the parameters.
210 * @sa CHECK_ERROR2I_BREAK, CHECK_ERROR2_EX
211 */
212#define CHECK_ERROR2_BREAK(hrc, iface, method) CHECK_ERROR2_EX(RT_NOTHING, hrc, iface, method, break)
213/**
214 * Simplified version of CHECK_ERROR2_EX that executes the |break| statement
215 * after error reporting and that uses an internal variable |hrcCheck| for
216 * holding the result.
217 *
218 * @param iface The interface pointer (can be a smart pointer object).
219 * @param method The method to invoke together with the parameters.
220 * @sa CHECK_ERROR2_BREAK, CHECK_ERROR2_EX
221 */
222#define CHECK_ERROR2I_BREAK(iface, method) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, break)
223/**
224 * Simplified version of CHECK_ERROR2_EX that executes the |stmt;break|
225 * statements after error reporting and that uses an internal variable
226 * |hrcCheck| for holding the result.
227 *
228 * @param iface The interface pointer (can be a smart pointer object).
229 * @param method The method to invoke together with the parameters.
230 * @param stmt Statement to be executed after reporting failures.
231 * @sa CHECK_ERROR2_BREAK, CHECK_ERROR2_EX
232 */
233#define CHECK_ERROR2I_BREAK_STMT(iface, method, stmt) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, stmt; break)
234
235
236/**
237 * Does the same as CHECK_ERROR(), but executes the |return ret| statement on
238 * failure.
239 * @sa CHECK_ERROR2_RET, CHECK_ERROR2I_RET
240 */
241#define CHECK_ERROR_RET(iface, method, ret) \
242 do { \
243 rc = iface->method; \
244 if (FAILED(rc)) \
245 { \
246 com::GlueHandleComError(iface, #method, rc, __FILE__, __LINE__); \
247 return (ret); \
248 } \
249 } while (0)
250/**
251 * Simplified version of CHECK_ERROR2_EX that executes the |return (rcRet)|
252 * statement after error reporting.
253 *
254 * @param hrc The result variable (type HRESULT).
255 * @param iface The interface pointer (can be a smart pointer object).
256 * @param method The method to invoke together with the parameters.
257 * @param rcRet What to return on failure.
258 */
259#define CHECK_ERROR2_RET(hrc, iface, method, rcRet) CHECK_ERROR2_EX(RT_NOTHING, hrc, iface, method, return (rcRet))
260/**
261 * Simplified version of CHECK_ERROR2_EX that executes the |return (rcRet)|
262 * statement after error reporting and that uses an internal variable |hrcCheck|
263 * for holding the result.
264 *
265 * @param iface The interface pointer (can be a smart pointer object).
266 * @param method The method to invoke together with the parameters.
267 * @param rcRet What to return on failure. Use |hrcCheck| to return
268 * the status code of the method call.
269 */
270#define CHECK_ERROR2I_RET(iface, method, rcRet) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, return (rcRet))
271
272
273/**
274 * Check the progress object for an error and if there is one print out the
275 * extended error information.
276 * @remarks Requires HRESULT variable named @a rc.
277 */
278#define CHECK_PROGRESS_ERROR(progress, msg) \
279 do { \
280 LONG iRc; \
281 rc = progress->COMGETTER(ResultCode)(&iRc); \
282 if (FAILED(rc) || FAILED(iRc)) \
283 { \
284 if (SUCCEEDED(rc)) rc = iRc; else iRc = rc; \
285 RTMsgError msg; \
286 com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, iRc, __FILE__, __LINE__); \
287 } \
288 } while (0)
289
290/**
291 * Does the same as CHECK_PROGRESS_ERROR(), but executes the |break| statement
292 * on failure.
293 * @remarks Requires HRESULT variable named @a rc.
294 */
295#ifdef __GNUC__
296# define CHECK_PROGRESS_ERROR_BREAK(progress, msg) \
297 __extension__ \
298 ({ \
299 LONG iRc; \
300 rc = progress->COMGETTER(ResultCode)(&iRc); \
301 if (FAILED(rc) || FAILED(iRc)) \
302 { \
303 if (SUCCEEDED(rc)) rc = iRc; else iRc = rc; \
304 RTMsgError msg; \
305 com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, iRc, __FILE__, __LINE__); \
306 break; \
307 } \
308 })
309#else
310# define CHECK_PROGRESS_ERROR_BREAK(progress, msg) \
311 if (1) \
312 { \
313 LONG iRc; \
314 rc = progress->COMGETTER(ResultCode)(&iRc); \
315 if (FAILED(rc) || FAILED(iRc)) \
316 { \
317 if (SUCCEEDED(rc)) rc = iRc; else iRc = rc; \
318 RTMsgError msg; \
319 com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, iRc, __FILE__, __LINE__); \
320 break; \
321 } \
322 } \
323 else do {} while (0)
324#endif
325
326/**
327 * Does the same as CHECK_PROGRESS_ERROR(), but executes the |return ret|
328 * statement on failure.
329 */
330#define CHECK_PROGRESS_ERROR_RET(progress, msg, ret) \
331 do { \
332 LONG iRc; \
333 HRESULT hrcCheck = progress->COMGETTER(ResultCode)(&iRc); \
334 if (SUCCEEDED(hrcCheck) && SUCCEEDED(iRc)) \
335 { /* likely */ } \
336 else \
337 { \
338 RTMsgError msg; \
339 com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, \
340 SUCCEEDED(hrcCheck) ? iRc : hrcCheck, __FILE__, __LINE__); \
341 return (ret); \
342 } \
343 } while (0)
344
345/**
346 * Asserts the given expression is true. When the expression is false, prints
347 * a line containing the failed function/line/file; otherwise does nothing.
348 */
349#define ASSERT(expr) \
350 do { \
351 if (!(expr)) \
352 { \
353 RTPrintf ("[!] ASSERTION FAILED at line %d: %s\n", __LINE__, #expr); \
354 Log (("[!] ASSERTION FAILED at line %d: %s\n", __LINE__, #expr)); \
355 } \
356 } while (0)
357
358
359/**
360 * Does the same as ASSERT(), but executes the |return ret| statement if the
361 * expression to assert is false;
362 * @remarks WARNING! @a expr is evalutated TWICE!
363 */
364#define ASSERT_RET(expr, ret) \
365 do { ASSERT(expr); if (!(expr)) return (ret); } while (0)
366
367/**
368 * Does the same as ASSERT(), but executes the |break| statement if the
369 * expression to assert is false;
370 * @remarks WARNING! @a expr is evalutated TWICE!
371 */
372#define ASSERT_BREAK(expr, ret) \
373 if (1) { ASSERT(expr); if (!(expr)) break; } else do {} while (0)
374
375} /* namespace com */
376
377
378/** @} */
379
380#endif
381
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