Filter Library | Camera | Interface Physics |
00001 ///////////////////////////////////////////////////////////////////////////////// 00002 // 00003 // QAFDebug critical error log 00004 // 00005 // Copyright (c) 2000-2004 00006 // Andrew Schetinin 00007 // 00008 // This software is provided "as is" without express or implied warranty, 00009 // and with no claim as to its suitability for any purpose. 00010 // 00011 // Permission to use or copy this software for any purpose is hereby granted 00012 // without fee, provided the above notices are retained on all copies. 00013 // Permission to modify the code and to distribute modified code is granted, 00014 // provided the above notices are retained, and a notice that the code was 00015 // modified is included with the above copyright notice. 00016 // 00017 // This software accompanies the article "Code that debugs itself" 00018 // located at http://www.codeproject.com/debug/qafdebug.asp 00019 // 00020 // You are welcomed to report bugs, send comments and post code modifications 00021 // to aschetinin@hotmail.com 00022 // 00023 ///////////////////////////////////////////////////////////////////////////////// 00024 00025 /// 00026 /// @file QAFDebug.h "../Include/QAFDebug.h" 00027 /// @brief Macros for reporting critical errors. 00028 /// 00029 /// This file defines a set of macros that replaces some of 00030 /// standard ATL and C++ macros. It is strongly recommended to use 00031 /// these macros in all functions. <P> 00032 /// 00033 /// The general guideline of using these macros: if you write code 00034 /// that should never fail under normal conditions, use these macros to report 00035 /// the cases when something extra-ordinary happens. <P> 00036 /// 00037 /// For the moment these macros are defined in both RELEASE and DEBUG builds. 00038 /// They use OutputDebugString() and log file to report about errors. <P> 00039 /// 00040 /// You must add QAFDebug.cpp to your project in order to use this header file. 00041 /// 00042 00043 #ifndef _QAFDEBUG_H_ 00044 #define _QAFDEBUG_H_ 00045 00046 #if _MSC_VER > 1000 00047 #pragma once 00048 #endif // _MSC_VER > 1000 00049 00050 /// 00051 /// @def QAF_DISABLED 00052 /// @brief Disable all error log staff, you may define it for release builds if you want. 00053 /// 00054 /// I ENABLE reporting even in RELEASE builds, it makes the program a bit larger (not affecting performance) 00055 /// but instead I get the full diagnostics for all problems. To disable the error reporting in release builds 00056 /// either uncomment these lines or define the QAF_DISABLED conditional define for the release builds. 00057 /// 00058 #ifndef QAF_DISABLED 00059 #define QAF_DISABLED 00060 // If you want to disable the error log in release builds, uncomment this test of _DEBUG 00061 //#ifndef _DEBUG 00062 #undef QAF_DISABLED 00063 //#endif 00064 #endif 00065 00066 /// 00067 /// @def QAF_LOGFILE_DISABLED 00068 /// @brief Disable writing to the error log file, you may define it for release builds if you want. 00069 /// 00070 /// I ENABLE writting to the error log file even in RELEASE builds , it makes the program a bit larger 00071 /// (not affecting performance) but instead I get the full diagnostics for all problems. 00072 /// To disable writting to the error log file in release builds either uncomment these lines or define the 00073 /// QAF_LOGFILE_DISABLED conditional define for the release builds. 00074 /// 00075 #ifndef QAF_LOGFILE_DISABLED 00076 #define QAF_LOGFILE_DISABLED 00077 // If you want to disable the error log in release builds, uncomment this test of _DEBUG 00078 //#ifndef _DEBUG 00079 #undef QAF_LOGFILE_DISABLED 00080 //#endif 00081 #endif 00082 00083 /// 00084 /// @def QAF_OUTPUTDEBUGSTRING_DISABLED 00085 /// @brief Disable calling OutputDebugString(), I recommend you to define it for release builds. 00086 /// 00087 /// I DISABLE reporting using OutputDebugString() in RELEASE builds (since usually nobody will trace it). 00088 /// 00089 #ifndef QAF_OUTPUTDEBUGSTRING_DISABLED 00090 #define QAF_OUTPUTDEBUGSTRING_DISABLED 00091 // This will enable the reporting back for DEBUG build 00092 #ifdef _DEBUG 00093 #undef QAF_OUTPUTDEBUGSTRING_DISABLED 00094 #endif 00095 #endif 00096 00097 /// @def QAF_UNITTEST_DISABLED 00098 /// @brief Disable unit tests related staff, I recommend you to define it for release builds 00099 /// and disable unit tests too. 00100 /// 00101 /// I DISABLE part of the functionality related to the unit tests in RELEASE build to optimize the code. 00102 /// Defining this directive removes all the synchronization and memory mapped file staff from the code. 00103 /// 00104 #ifndef _DEBUG 00105 #define QAF_UNITTEST_DISABLED 00106 #endif 00107 00108 /// @def QAF_SAVE_UNICODE_AS_UTF8 00109 /// @brief Saves UNICODE error messages to the log file in UTF8 charset. 00110 /// 00111 /// When defined, it makes UNICODE error messages to be saved to the log file in UTF8 charset. 00112 /// It improves readability of the error log file when working with both ASCII and UNICODE modules. 00113 /// Minus is that encoding requires to allocate an additional buffer. 00114 /// 00115 #ifdef _UNICODE 00116 #define QAF_SAVE_UNICODE_AS_UTF8 00117 #endif 00118 00119 /////////////////////////////////////////////////////////////////////////////////////////////////////////// 00120 // Includes 00121 /////////////////////////////////////////////////////////////////////////////////////////////////////////// 00122 00123 #include <windows.h> 00124 #include <winerror.h> 00125 #include <tchar.h> 00126 #include <stdio.h> 00127 00128 /////////////////////////////////////////////////////////////////////////////////////////////////////////// 00129 // Macros 00130 /////////////////////////////////////////////////////////////////////////////////////////////////////////// 00131 00132 /// 00133 /// @def Q_ASSERT 00134 /// @brief This macro reports about critical error if @c bCondition evaluates to @c false. 00135 /// @param bCondition Any expression that evaluates to @c bool or @c int 00136 /// @return bool (same as bCondition) 00137 /// @author Andrew Schetinin 00138 /// @date September 26, 2002 00139 /// 00140 /// This macro output a error report string to the error log (file and/or debug console). 00141 /// The string looks like that: 00142 /// @code 00143 /// c:\SharedUnits\Dev\QMSOColl\QMSOColl.cpp(56) : Assertion raised 00144 /// time: 2003-12-08 16:11:34:003 00145 /// process: 0x000006F4 00146 /// thread: 0x00000148 00147 /// application: c:\ErrorLog_demo\Debug\ErrorLog.exe <1.0.0.3> 00148 /// module: c:\SharedUnits\Dev\QMSOColl\Debug\QMSOColl.dll <1.0.0.10> 00149 /// last error: 2, The system cannot find the file specified. 00150 /// expression: false 00151 /// @endcode 00152 /// It is recommended to use this macro in all places where any error 00153 /// means program crash or non-predictable behavior of dependent code. 00154 /// It will help to detect where first the error appeared. 00155 /// Recommended for IFs without ELSE or testing return values of functions. 00156 /// @code 00157 /// if( Q_ASSERT( TRUE == bVarShouldAlwaysBeTRUE ) ) // here it will write to the error log 00158 /// do_something(); 00159 /// @endcode 00160 /// 00161 00162 #ifndef QAF_DISABLED 00163 #define Q_ASSERT( bCondition ) ((bCondition) ? true : (QAFDebug::OutputDebugStringEx( \ 00164 _T(__FILE__), __LINE__, QAF_EXPR(_T(#bCondition)), QAFDEBUG_ERROR_ASSERTION ), false) ) 00165 #else 00166 #define Q_ASSERT( bCondition ) (bCondition) 00167 #endif 00168 00169 /// 00170 /// @def Q_CHECK 00171 /// @brief This macro reports about critical error if @c exprConst != @c exprCheck. 00172 /// @param exprConst Any expression that evaluates to @c bool or @c int 00173 /// @param exprCheck Any expression that evaluates to @c bool or @c int 00174 /// @return bool (same as (exprConst == exprCheck)) 00175 /// @author Andrew Schetinin 00176 /// @date April 10, 2003 00177 /// 00178 /// This macro output a error report string to the error log (file and/or debug console). 00179 /// The important thing about this macro is that it outputs 00180 /// also the actual compared values (error codes, handles, etc.) 00181 /// The string looks like that: 00182 /// @code 00183 /// c:\SharedUnits\Dev\QMSOColl\QMSOColl.cpp(56) : Check error: got 10 (0xA) while expected 0 (0x0) 00184 /// time: 2003-12-08 16:11:34:003 00185 /// process: 0x000006F4 00186 /// thread: 0x00000148 00187 /// application: c:\ErrorLog_demo\Debug\ErrorLog.exe <1.0.0.3> 00188 /// module: c:\SharedUnits\Dev\QMSOColl\Debug\QMSOColl.dll <1.0.0.10> 00189 /// last error: 2, The system cannot find the file specified. 00190 /// expression: ERROR_SUCCESS == ret 00191 /// @endcode 00192 /// It is recommended to use this macro in all places where any error 00193 /// means program crash or non-predictable behavior of dependent code. 00194 /// It will help to detect where first the error appeared. 00195 /// Recommended for IFs without ELSE or testing return values of functions. 00196 /// @code 00197 /// if( Q_CHECK( ERROR_SUCCESS, ret ) ) // here it will write to the error log 00198 /// do_something(); 00199 /// @endcode 00200 /// 00201 00202 #ifndef QAF_DISABLED 00203 #define Q_CHECK( exprConst, exprCheck ) QAFDebug::ReportCheckError( (exprConst), \ 00204 (exprCheck), QAF_EXPR( _T(#exprConst) _T(" == ") _T(#exprCheck) ), _T(__FILE__), __LINE__ ) 00205 #else 00206 #define Q_CHECK( exprConst, exprCheck ) ((exprConst) == (exprCheck)) 00207 #endif 00208 00209 /// 00210 /// @def Q_INVALID 00211 /// @brief This macro reports about critical error if @c bCondition evaluates to @c true. 00212 /// @param bCondition Any expression that evaluates to @c bool or @c int 00213 /// @return bool (same as bCondition) 00214 /// @author Andrew Schetinin 00215 /// @date December 11, 2002 00216 /// 00217 /// This macro output a error report string to the error log (file and/or debug console). 00218 /// The string looks like that: 00219 /// @code 00220 /// c:\SharedUnits\Dev\QMSOColl\QMSOColl.cpp(56) : Assumption failed 00221 /// time: 2003-12-08 16:11:34:003 00222 /// process: 0x000006F4 00223 /// thread: 0x00000148 00224 /// application: c:\ErrorLog_demo\Debug\ErrorLog.exe <1.0.0.3> 00225 /// module: c:\SharedUnits\Dev\QMSOColl\Debug\QMSOColl.dll <1.0.0.10> 00226 /// last error: 2, The system cannot find the file specified. 00227 /// expression: NULL == lpszStringParam 00228 /// @endcode 00229 /// It is recommended to use this macro in all places where any error 00230 /// means program crash or non-predictable behavior of dependent code. 00231 /// It will help to detect where first the error appeared. 00232 /// Recommended for testing input parameters or error conditions. 00233 /// @code 00234 /// if( Q_INVALID( NULL == lpszStringParam ) ) // here it will write to the error log 00235 /// return E_INVALIDARG; 00236 /// @endcode 00237 /// 00238 00239 #ifndef QAF_DISABLED 00240 #define Q_INVALID( bCondition ) ((bCondition) ? (QAFDebug::OutputDebugStringEx( \ 00241 _T(__FILE__), __LINE__, QAF_EXPR(_T(#bCondition)), QAFDEBUG_ERROR_INVALID_ASSUMPTION ), true) : false ) 00242 #else 00243 #define Q_INVALID( bCondition ) (bCondition) 00244 #endif 00245 00246 /// 00247 /// @def Q_SUCCEEDED 00248 /// @brief Add reporting critical errors to the standard SUCCEEDED macro. 00249 /// @param Status HRESULT result code 00250 /// @return bool. @c true means "no error" 00251 /// @author Andrew Schetinin 00252 /// @date September 26, 2002 00253 /// 00254 /// Generic test for success on any status value (non-negative numbers 00255 /// indicate success). <P> 00256 /// 00257 /// This macro output a error report string to the error log (file and/or debug console). 00258 /// The string looks like that: 00259 /// @code 00260 /// c:\SharedUnits\Dev\QMSOColl\QMSOColl.cpp(56) : The component's CLSID is missing or corrupt. 00261 /// time: 2003-12-08 16:11:34:003 00262 /// process: 0x000006F4 00263 /// thread: 0x00000148 00264 /// application: c:\ErrorLog_demo\Debug\ErrorLog.exe <1.0.0.3> 00265 /// module: c:\SharedUnits\Dev\QMSOColl\Debug\QMSOColl.dll <1.0.0.10> 00266 /// last error: 0 00267 /// expression: Q_FAILED(0x800401F3) 00268 /// @endcode 00269 /// It is recommended to use this macro in all places where any error 00270 /// means program crash or non-predictable behavior of dependent code. 00271 /// It will help to detect where first the error appeared. 00272 /// Recommended for testing return HRESULTs that usually always should return S_OK or S_FALSE. 00273 /// Another use for this macro is to report about a critical error in your function 00274 /// that is returned to the calling function. 00275 /// @code 00276 /// if( Q_SUCCEEDED(hr) ) // here it will write to the error log 00277 /// do_something(); 00278 /// @endcode 00279 /// 00280 00281 #ifndef QAF_DISABLED 00282 #define Q_SUCCEEDED(hResultExpr) SUCCEEDED(Q_ERROR(hResultExpr)) 00283 #else 00284 #define Q_SUCCEEDED(hResultExpr) SUCCEEDED(hResultExpr) 00285 #endif 00286 00287 /// 00288 /// @def Q_FAILED 00289 /// @brief Add reporting critical errors to the standard FAILED macro. 00290 /// @param Status HRESULT result code 00291 /// @return bool. @c true means "there is an error!" 00292 /// @author Andrew Schetinin 00293 /// @date September 26, 2002 00294 /// 00295 /// Generic test for failure on any status value. <P> 00296 /// 00297 /// This macro output a error report string to the error log (file and/or debug console). 00298 /// The string looks like that: 00299 /// @code 00300 /// c:\SharedUnits\Dev\QMSOColl\QMSOColl.cpp(56) : The component's CLSID is missing or corrupt. 00301 /// time: 2003-12-08 16:11:34:003 00302 /// process: 0x000006F4 00303 /// thread: 0x00000148 00304 /// application: c:\ErrorLog_demo\Debug\ErrorLog.exe <1.0.0.3> 00305 /// module: c:\SharedUnits\Dev\QMSOColl\Debug\QMSOColl.dll <1.0.0.10> 00306 /// last error: 0 00307 /// expression: Q_FAILED(0x800401F3) 00308 /// @endcode 00309 /// It is recommended to use this macro in all places where any error 00310 /// means program crash or non-predictable behavior of dependent code. 00311 /// It will help to detect where first the error appeared. 00312 /// Recommended for testing return HRESULTs that usually always should return S_OK or S_FALSE. 00313 /// Another use for this macro is to report about the error before returning from your function. 00314 /// @code 00315 /// if( Q_FAILED(hr) ) // here it will write to the error log 00316 /// return hr; 00317 /// @endcode 00318 /// 00319 00320 #ifndef QAF_DISABLED 00321 #define Q_FAILED(hResultExpr) FAILED(Q_ERROR(hResultExpr)) 00322 #else 00323 #define Q_FAILED(hResultExpr) FAILED(hResultExpr) 00324 #endif 00325 00326 /// 00327 /// @def Q_ERROR 00328 /// @brief Reports critical errors returned from your function before returning. 00329 /// @param Status HRESULT result code 00330 /// @return HRESULT (same as Status) 00331 /// @author Andrew Schetinin 00332 /// @date September 26, 2002 00333 /// 00334 /// Generic test for failure on any status value. <P> 00335 /// 00336 /// This macro output a error report string to the error log (file and/or debug console). 00337 /// The string looks like that: 00338 /// @code 00339 /// c:\SharedUnits\Dev\QMSOColl\QMSOColl.cpp(56) : The component's CLSID is missing or corrupt. 00340 /// time: 2003-12-08 16:11:34:003 00341 /// process: 0x000006F4 00342 /// thread: 0x00000148 00343 /// application: c:\ErrorLog_demo\Debug\ErrorLog.exe <1.0.0.3> 00344 /// module: c:\SharedUnits\Dev\QMSOColl\Debug\QMSOColl.dll <1.0.0.10> 00345 /// last error: 0 00346 /// expression: Q_FAILED(0x800401F3) 00347 /// @endcode 00348 /// It is recommended to use this macro in all places where any error 00349 /// means program crash or non-predictable behavior of dependent code. 00350 /// It will help to detect where first the error appeared. 00351 /// Recommended for testing return HRESULTs that usually always should return S_OK or S_FALSE. 00352 /// Another use for this macro is to test return values of generic functions that 00353 /// usually never fail. 00354 /// @code 00355 /// // This will report about the error in the exact place where it first happened. 00356 /// return Q_ERROR( CoCreateInstance( clsid, NULL, dwCtx, IID_IDispatch, (void**)(&this->p) ) ); 00357 /// @endcode 00358 /// 00359 00360 #ifndef QAF_DISABLED 00361 #define Q_ERROR(hResultExpr) (QAFDebug::ReportComError( hResultExpr, _T(__FILE__), __LINE__ )) 00362 #else 00363 #define Q_ERROR(hResultExpr) (hResultExpr) 00364 #endif 00365 00366 /// 00367 /// @def Q_ERROR_SUCCESS 00368 /// @brief Reports critical errors from ERROR_SUCCESS group. 00369 /// @param dwError Error result code. 00370 /// @return bool (dwError == ERROR_SUCCESS) 00371 /// @author Andrew Schetinin 00372 /// @date March 19, 2003 00373 /// 00374 /// Generic test for failure on error code. <P> 00375 /// 00376 /// This macro output a error report string to the error log (file and/or debug console). 00377 /// The string looks like that: 00378 /// @code 00379 /// c:\SharedUnits\Dev\QMSOColl\QMSOColl.cpp(56) : More data is available. 00380 /// time: 2003-12-08 16:11:34:003 00381 /// process: 0x000006F4 00382 /// thread: 0x00000148 00383 /// application: c:\ErrorLog_demo\Debug\ErrorLog.exe <1.0.0.3> 00384 /// module: c:\SharedUnits\Dev\QMSOColl\Debug\QMSOColl.dll <1.0.0.10> 00385 /// last error: 123, More data is available. 00386 /// expression: ERROR_SUCCESS != 123 00387 /// @endcode 00388 /// It is recommended to use this macro in all places where any error 00389 /// means program crash or non-predictable behavior of dependent code. 00390 /// It will help to detect where first the error appeared. 00391 /// Recommended for testing return error codes that usually always should return ERROR_SUCCESS. 00392 /// Another use for this macro is to test return values of generic functions that 00393 /// usually never fail. 00394 /// @code 00395 /// // This will report about the error in the exact place where it first happened. 00396 /// DWORD dwRes = RegQueryValueEx( hKey, _T("Value"), NULL, &dwType, (LPBYTE)szBuf, &dwSize ); 00397 /// if( Q_ERROR_SUCCESS(dwRes) ) 00398 /// /*do something*/; 00399 /// @endcode 00400 /// 00401 00402 #ifndef QAF_DISABLED 00403 #define Q_ERROR_SUCCESS(dwErrorExpr) (ERROR_SUCCESS == QAFDebug::ReportWinError( dwErrorExpr, _T(__FILE__), __LINE__ )) 00404 #else 00405 #define Q_ERROR_SUCCESS(dwErrorExpr) (ERROR_SUCCESS == (dwErrorExpr)) 00406 #endif 00407 00408 /// 00409 /// @def Q_LOG 00410 /// @brief Reports critical errors with a string message. 00411 /// @param lpszMessage LPCTSTR message string 00412 /// @return void 00413 /// @author Andrew Schetinin 00414 /// @date January 28, 2003 00415 /// 00416 /// This is a macro for reporting about critical errors in a user-understandable format. 00417 /// Generally it is preferable to Q_ASSERT(false). <P> 00418 /// 00419 /// This macro output a error report string to the error log (file and/or debug console). 00420 /// The string looks like that: 00421 /// @code 00422 /// c:\SharedUnits\Dev\QMSOColl\QMSOColl.cpp(56) : My custom error message. 00423 /// time: 2003-12-08 16:11:34:003 00424 /// process: 0x000006F4 00425 /// thread: 0x00000148 00426 /// application: c:\ErrorLog_demo\Debug\ErrorLog.exe <1.0.0.3> 00427 /// module: c:\SharedUnits\Dev\QMSOColl\Debug\QMSOColl.dll <1.0.0.10> 00428 /// last error: 0 00429 /// expression: Error message 00430 /// @endcode 00431 /// It is recommended to use this macro in all places where any error 00432 /// means program crash or non-predictable behavior of dependent code. 00433 /// It will help to detect where first the error appeared. 00434 /// Recommended for IFs without ELSE or testing return values of functions. 00435 /// @code 00436 /// catch( ... ) 00437 /// { 00438 /// Q_LOG( _T("Unknown exception catched") ); // here it will report about all exceptions 00439 /// } 00440 /// @endcode 00441 /// 00442 00443 #ifndef QAF_DISABLED 00444 #define Q_LOG(lpszMessage) (QAFDebug::OutputDebugStringEx( _T(__FILE__), __LINE__, QAFDEBUG_ERROR_LOG, lpszMessage )) 00445 #else 00446 #define Q_LOG(lpszMessage) (lpszMessage) 00447 #endif 00448 00449 /// 00450 /// @def Q_MFC_EXCEPTION 00451 /// @brief Reports critical exceptions. 00452 /// @param e CException object instance (MFC-style) 00453 /// @return void 00454 /// @author Andrew Schetinin 00455 /// @date November 18, 2002 00456 /// 00457 /// This is a special macro to report about an MFC-style exception. <P> 00458 /// 00459 /// This macro output a error report string to the error log (file and/or debug console). 00460 /// The string looks like that: 00461 /// @code 00462 /// c:\SharedUnits\Dev\QMSOColl\QMSOColl.cpp(56) : Cannot open file 00463 /// time: 2003-12-08 16:11:34:003 00464 /// process: 0x000006F4 00465 /// thread: 0x00000148 00466 /// application: c:\ErrorLog_demo\Debug\ErrorLog.exe <1.0.0.3> 00467 /// module: c:\SharedUnits\Dev\QMSOColl\Debug\QMSOColl.dll <1.0.0.10> 00468 /// last error: 0 00469 /// expression: e 00470 /// @endcode 00471 /// It is recommended to use this macro in all places where any error 00472 /// means program crash or non-predictable behavior of dependent code. 00473 /// It will help to detect where first the error appeared. 00474 /// Recommended for reporting about exceptions in CATCH clauses. 00475 /// You may define your own exception classes (without MFC support), just define 00476 /// the GetErrorMessage() method and this macro will work. 00477 /// @code 00478 /// catch( CMyException & e ) 00479 /// { 00480 /// Q_MFC_EXCEPTION(e); // here it will write to the error log with the error message 00481 /// } 00482 /// catch( ... ) 00483 /// { 00484 /// Q_LOG( _T("Unknown exception catched") ); // here it will report about any other exception 00485 /// } 00486 /// @endcode 00487 /// 00488 00489 #ifndef QAF_DISABLED 00490 #define Q_MFC_EXCEPTION(e) \ 00491 do { \ 00492 TCHAR szBuf[251] = { 0 }; \ 00493 if( (NULL == e) || (! e->GetErrorMessage( szBuf, 250, NULL )) ) \ 00494 strcpy( szBuf, QAFDEBUG_ERROR_NO_MESSAGE ); \ 00495 QAFDebug::OutputDebugStringEx( _T(__FILE__), __LINE__, QAF_EXPR(_T(#e)), szBuf ); \ 00496 } while( false ) 00497 #else 00498 #define Q_MFC_EXCEPTION(e) (e) 00499 #endif 00500 00501 /// Synonim for Q_MFC_EXCEPTION macro - left for backward compatibility. 00502 #define Q_EXCEPTION(e) Q_MFC_EXCEPTION(e) 00503 00504 /// 00505 /// @def Q_STD_EXCEPTION 00506 /// @brief Reports critical exceptions. 00507 /// @param e std::exception object instance (STL-style) 00508 /// @return void 00509 /// @author Andrew Schetinin 00510 /// @date December 11, 2003 00511 /// 00512 /// This is a special macro to report about an STL exception. <P> 00513 /// 00514 /// This macro output a error report string to the error log (file and/or debug console). 00515 /// The string looks like that: 00516 /// @code 00517 /// c:\SharedUnits\Dev\QMSOColl\QMSOColl.cpp(56) : Cannot open file 00518 /// time: 2003-12-08 16:11:34:003 00519 /// process: 0x000006F4 00520 /// thread: 0x00000148 00521 /// application: c:\ErrorLog_demo\Debug\ErrorLog.exe <1.0.0.3> 00522 /// module: c:\SharedUnits\Dev\QMSOColl\Debug\QMSOColl.dll <1.0.0.10> 00523 /// last error: 0 00524 /// expression: e 00525 /// @endcode 00526 /// It is recommended to use this macro in all places where any error 00527 /// means program crash or non-predictable behavior of dependent code. 00528 /// It will help to detect where first the error appeared. 00529 /// Recommended for reporting about exceptions in CATCH clauses. 00530 /// @code 00531 /// catch( std::exception & e ) 00532 /// { 00533 /// Q_STD_EXCEPTION(e); // here it will write to the error log with the error message 00534 /// } 00535 /// catch( ... ) 00536 /// { 00537 /// Q_LOG( _T("Unknown exception catched") ); // here it will report about any other exception 00538 /// } 00539 /// @endcode 00540 /// 00541 00542 #ifndef QAF_DISABLED 00543 #define Q_STD_EXCEPTION(e) QAFDebug::OutputDebugStringEx( _T(__FILE__), __LINE__, QAF_EXPR(_T(#e)), e.what() ) 00544 #else 00545 #define Q_STD_EXCEPTION(e) (e) 00546 #endif 00547 00548 /// 00549 /// @def Q_MAPI_ERROR 00550 /// @brief Reports critical exceptions. 00551 /// @param hresult (HRESULT) - MAPI error code 00552 /// @param piObjectMAPI (any of MAPI interfaces) 00553 /// @return void 00554 /// @author Andrew Schetinin 00555 /// @date November 18, 2002 00556 /// 00557 /// This is a special macro to report about an MAPI error. <P> 00558 /// 00559 /// This macro output a error report string to the error log (file and/or debug console). 00560 /// The string looks like that: 00561 /// @code 00562 /// c:\SharedUnits\Dev\QMSOColl\QMSOColl.cpp(56) : Cannot login to MAPI storage 00563 /// time: 2003-12-08 16:11:34:003 00564 /// process: 0x000006F4 00565 /// thread: 0x00000148 00566 /// application: c:\ErrorLog_demo\Debug\ErrorLog.exe <1.0.0.3> 00567 /// module: c:\SharedUnits\Dev\QMSOColl\Debug\QMSOColl.dll <1.0.0.10> 00568 /// last error: 0 00569 /// expression: hr 00570 /// @endcode 00571 /// It is recommended to use this macro in all places where any error 00572 /// means program crash or non-predictable behavior of dependent code. 00573 /// It will help to detect where first the error appeared. 00574 /// Recommended for reporting about critical MAPI errors. 00575 /// @code 00576 /// Q_MAPI_ERROR( hresult, piObjectMAPI ); 00577 /// @endcode 00578 /// 00579 00580 #ifndef QAF_DISABLED 00581 // taken from MAPI Inside, they do not use SUCCEEDED 00582 #define Q_MAPI_ERROR( hresult, piObjectMAPI ) \ 00583 do { \ 00584 HRESULT hrtemp39472 = hresult; \ 00585 LPMAPIERROR pErr = NULL; \ 00586 if( Q_ASSERT( NULL != piObjectMAPI ) \ 00587 && Q_ASSERT( S_OK == piObjectMAPI->GetLastError( hrtemp39472, 0, &pErr ) ) \ 00588 && Q_ASSERT( NULL != pErr ) ) \ 00589 { \ 00590 int BUF_SIZE = 128 + _tcslen(pErr->lpszError) + _tcslen(pErr->lpszComponent); \ 00591 LPTSTR szBuf = (LPTSTR)malloc( BUF_SIZE * sizeof(TCHAR) ); \ 00592 if( Q_ASSERT( NULL != szBuf ) ) \ 00593 { \ 00594 _stprintf( szBuf, _T("MAPI Error: %s. Component: %s. Version: %08X. ") \ 00595 _T("LowLevelError: %08X. Context: %08X."), \ 00596 ((NULL != pErr->lpszError) ? pErr->lpszError : _T("")), \ 00597 ((NULL != pErr->lpszComponent) ? pErr->lpszComponent : _T("")), \ 00598 pErr->ulVersion, pErr->ulLowLevelError, pErr->ulContext ); \ 00599 TCHAR szHRBuf[20] = { 0 }; \ 00600 _stprintf( szHRBuf, _T("Q_FAILED(%08X)"), hrtemp39472 ); \ 00601 QAFDebug::OutputDebugStringEx( _T(__FILE__), __LINE__, szHRBuf, szBuf ); \ 00602 free( szBuf ); \ 00603 } \ 00604 } \ 00605 } while( false ) 00606 #else 00607 #define Q_MAPI_ERROR( hresult, piObjectMAPI ) (hresult) 00608 #endif 00609 00610 /// 00611 /// @def Q_RETURN 00612 /// @brief If input HRESULT failed, then macro returns it. 00613 /// @param hr HRESULT 00614 /// @return hr, if 00615 /// @author Andrey Krasnopolsky 00616 /// @date August 05, 2003 00617 /// 00618 /// This macro is for testing HRESULTs. It gets HRESULT as input, tests it and 00619 /// returns the same HRESULT in case of error. 00620 /// Very useful if you need to break function execution in case of error. 00621 /// @code 00622 /// // if the method returns E_XXX, it will exit and return the error code 00623 /// Q_RETURN( CallSomeMethod() ); 00624 /// @endcode 00625 /// 00626 00627 #define Q_RETURN(hr) do { HRESULT hrtmp83457 = hr; if( Q_SUCCEEDED(hrtmp83457) ) ; else return hrtmp83457; } while( false ) 00628 00629 /////////////////////////////////////////////////////////////////////////////////////////////////////////// 00630 // Defines related to the unit tests 00631 /////////////////////////////////////////////////////////////////////////////////////////////////////////// 00632 00633 /// 00634 /// @def Q_ENABLE_DEBUG_LOG 00635 /// @brief Enable the error log in case if it was disabled because of the previous unit test failure. 00636 /// @return void 00637 /// @author Andrew Schetinin 00638 /// @date November 18, 2002 00639 /// 00640 /// This is a special macro for unit test functions. This macro ensures that the 00641 /// reporting is switched on. It is recommended to put it at the beginning of a single 00642 /// tests case (at the beginning of the function). 00643 /// @code 00644 /// void CUnitTest::testCase01( void ) 00645 /// { 00646 /// Q_ENABLE_DEBUG_LOG; // switch the error log on 00647 /// CPPUNIT_ASSERT( Q_SUCCEEDED( QAFGetRegKey( HKCU_C_END, &str ) ) ); // write to the log if it fails 00648 /// ... 00649 /// } 00650 /// @endcode 00651 /// 00652 00653 #define Q_ENABLE_DEBUG_LOG ; 00654 #ifndef QAF_DISABLED 00655 #ifndef QAF_UNITTEST_DISABLED 00656 #undef Q_ENABLE_DEBUG_LOG 00657 #define Q_ENABLE_DEBUG_LOG QAFDebug::tryEnable(); 00658 #endif 00659 #endif 00660 00661 /// 00662 /// @def Q_SILENT 00663 /// @brief Temporary disable the error log and evaluate the expression. 00664 /// @param expr Any expression 00665 /// @return void 00666 /// @author Andrew Schetinin 00667 /// @date November 18, 2002 00668 /// 00669 /// This is a special macro for unit test functions. It is useful for testing the wrong cases 00670 /// (for example, passing wrong parameters and checking that the function fails). 00671 /// For wrong test cases we do not want to report about errors because we want them to happen. 00672 /// @code 00673 /// void CUnitTest::testCase01( void ) 00674 /// { 00675 /// Q_ENABLE_DEBUG_LOG; // switch the error log on 00676 /// CPPUNIT_ASSERT( Q_SUCCEEDED( QAFGetRegKey( HKCU_C_END, &str ) ) ); // write to the log if it fails 00677 /// Q_SILENT( CPPUNIT_ASSERT( Q_FAILED( QAFGetRegKey( NULL, NULL ) ) ) ); // do not write to log 00678 /// ... 00679 /// } 00680 /// @endcode 00681 /// 00682 00683 #define Q_SILENT(expr) expr; 00684 #ifndef QAF_DISABLED 00685 #ifndef QAF_UNITTEST_DISABLED 00686 #undef Q_SILENT 00687 #define Q_SILENT(expr) \ 00688 do { \ 00689 bool bLogDisabled = QAFDebug::tryDisable(); \ 00690 expr; \ 00691 if( bLogDisabled ) \ 00692 QAFDebug::tryEnable(); \ 00693 } while( false ) 00694 #endif 00695 #endif 00696 00697 /////////////////////////////////////////////////////////////////////////////////////////////////////////// 00698 // Conditional defines 00699 /////////////////////////////////////////////////////////////////////////////////////////////////////////// 00700 00701 /// 00702 /// @def Q_SET_MODULE 00703 /// @brief This macro allows setting the module name for additional logging options. 00704 /// @param LPCTSTR, name of the DLL or EXE, 0-terminated, not longer than MAX_PATH characters. 00705 /// @return void 00706 /// @author Andrew Schetinin 00707 /// @date December 7, 2003 00708 /// 00709 /// This will switch on logging of the file name and version number of the current EXE or DLL. 00710 /// It will be logged after the file name and path of the hosting process, 00711 /// only the module file name without path is logged: FILENAME.DLL(1.0.0.1) 00712 /// 00713 #if !defined(QAF_DISABLED) 00714 #define Q_SET_MODULE( szModuleName ) QAFDebug::SetModule( szModuleName ) 00715 #else 00716 #define Q_SET_MODULE( szModuleName ) 00717 #endif 00718 00719 // Only if reporting is not disabled 00720 #ifndef QAF_DISABLED 00721 00722 /// The name of the mutex for synchronizing the unit test support staff. 00723 const LPCTSTR QAFDEBUG_SILENCE_MUTEX = _T("QAFDebugMutex001A"); 00724 00725 /// Subfolder in the application data folder 00726 //const LPCTSTR QAFDEBUG_LOG_SUBFOLDER = _T("MyCompany\\Log\\"); 00727 const LPCTSTR QAFDEBUG_LOG_SUBFOLDER = _T("Camera\\Log\\"); 00728 00729 /// Name of the environment variable that may set the output debug log folder. 00730 //const LPCTSTR QAFDEBUG_LOG_ENV_VAR = _T("QAFERRORLOGPATH"); 00731 const LPCTSTR QAFDEBUG_LOG_ENV_VAR = _T("LPMCAMERALOGDIR"); 00732 00733 /// @brief Maximum log file size 00734 /// 00735 /// Maximum log file size (there are two log files - one current and second previous). 00736 /// When the log file size exceeds half of this limit, it is renamed to the second name 00737 /// (thus both files together cannot take more than this maximum size). 00738 /// The size is in bytes. Usually 1 record takes about 500 characters, so I reserve 00739 /// space for about 2,000 records with 1 Mb limit. 00740 const DWORD QAFDEBUG_LOG_FILE_MAX_SIZE = (1024 * 1024); 00741 00742 /// The current error log file name 00743 const LPCTSTR QAFDEBUG_LOG_FILE_NAME = _T("error.log"); 00744 00745 /// The previous error log file name 00746 const LPCTSTR QAFDEBUG_LOG_OLD_FILE_NAME = _T("error.old.log"); 00747 00748 /// The name of the memory-mapped-file that stores the shared flags 00749 const LPCTSTR QDEBUG_SHMEMFILE = _T("QAFDbgMemFile01"); 00750 00751 /// Errors in the reporting engine 00752 #define QAFDEBUG_ERROR_PREFIX _T("Debug System Error --> ") 00753 00754 /// Fixed error message for assertion raised 00755 #define QAFDEBUG_ERROR_ASSERTION _T("Assertion raised\r\n") 00756 00757 /// Fixed error message for invalid assumption raised 00758 #define QAFDEBUG_ERROR_INVALID_ASSUMPTION _T("Invalid assumption is raised\r\n") 00759 00760 /// Fixed error message for unknown error 00761 #define QAFDEBUG_ERROR_NO_MESSAGE _T("[Could not find any description for the error]\r\n") 00762 00763 /// Fixed expression for the custom error message 00764 #define QAFDEBUG_ERROR_LOG _T("Error Message") 00765 00766 /// 00767 /// @def QAF_EXPR 00768 /// @brief The Expression string is printed to the error log only in DEBUG builds. 00769 /// 00770 /// It makes the binary a bit smaller for the release build. 00771 /// 00772 #ifdef _DEBUG 00773 #define QAF_EXPR(expression) (expression) 00774 #else 00775 #define QAF_EXPR(expression) (NULL) 00776 #endif 00777 00778 #endif 00779 00780 /////////////////////////////////////////////////////////////////////////////////////////////////////////// 00781 // class CQAFDebug - this is a service class - do not use it directly! 00782 /////////////////////////////////////////////////////////////////////////////////////////////////////////// 00783 00784 #ifndef QAF_DISABLED 00785 00786 /// 00787 /// @namespace QAFDebug 00788 /// @brief Namespace QAFDebug hides the debug functions from global scope. 00789 /// 00790 namespace QAFDebug 00791 { 00792 /// 00793 /// @brief Try to enable the error log 00794 /// @return bool true if the log is enabled successfully 00795 /// @author Andrew Schetinin 00796 /// @date November 20, 2002 00797 /// 00798 /// Try to enable the error log. This function is used only in unit tests. 00799 /// Do not use it in your code! 00800 /// 00801 bool tryEnable( void ); 00802 00803 /// 00804 /// @brief Try to disable the error log 00805 /// @return bool true if the log is disabled successfully 00806 /// @author Andrew Schetinin 00807 /// @date November 20, 2002 00808 /// 00809 /// Try to disable the error log. This function is used only in unit tests. 00810 /// Do not use it in your code! 00811 /// 00812 bool tryDisable( void ); 00813 00814 /// 00815 /// @brief Reports about critical errors 00816 /// @param szFilename LPCTSTR - the file name returned by _FILE_ 00817 /// @param iLine const int - the line number returned by _LINE_ 00818 /// @param szExpression LPCTSTR - the expression where the error was detected 00819 /// @param szErrorMessage LPCTSTR - the error message generated 00820 /// @param pdwLastError LPDWORD - the last error code must be restored 00821 /// @author Andrew Schetinin 00822 /// @date November 20, 2002 00823 /// 00824 /// Reports critical errors. 00825 /// This function is used by debug macroses. Do not use it in your code! 00826 /// 00827 void OutputDebugStringEx( LPCTSTR szFilename, const int iLine, LPCTSTR szExpression, 00828 LPCTSTR szErrorMessage, const LPDWORD pdwLastError = NULL ); 00829 00830 /// 00831 /// @brief Reports about critical errors if HRESULT is failed 00832 /// @param hrStatus HRESULT - tested on failure 00833 /// @param szFile LPCTSTR - the file name returned by _FILE_ 00834 /// @param iLine const int - the line number returned by _LINE_ 00835 /// @return HRESULT the same hrStatus that it received 00836 /// @author Andrew Schetinin 00837 /// @date November 20, 2002 00838 /// 00839 /// Reports critical errors if HRESULT is failed. 00840 /// This function is used by debug macroses. Do not use it in your code! 00841 /// 00842 HRESULT qafReportComError( const HRESULT hrStatus, LPCTSTR szFile, const int iLine ); 00843 00844 /// 00845 /// @brief Reports about critical errors if dwError != ERROR_SUCCESS. 00846 /// @param dwError DWORD - tested on failure 00847 /// @param szFile LPCTSTR - the file name returned by _FILE_ 00848 /// @param iLine const int - the line number returned by _LINE_ 00849 /// @return DWORD the same as dwError 00850 /// @author Andrew Schetinin 00851 /// @date March 19, 2003 00852 /// 00853 /// Reports critical errors if dwError != ERROR_SUCCESS. 00854 /// This function is used by debug macroses. Do not use it in your code! 00855 /// 00856 DWORD ReportWinError( const DWORD dwError, LPCTSTR szFile, const int iLine ); 00857 00858 /// 00859 /// @brief Reports about critical errors if HRESULT is failed 00860 /// @param hrStatus HRESULT - tested on failure 00861 /// @param szFile LPCTSTR - the file name returned by _FILE_ 00862 /// @param iLine const int - the line number returned by _LINE_ 00863 /// @return HRESULT the same hrStatus that it received 00864 /// @author Andrew Schetinin 00865 /// @date November 20, 2002 00866 /// 00867 /// Reports critical errors if HRESULT is failed. 00868 /// This function is used by debug macroses. Do not use it in your code! 00869 /// 00870 inline HRESULT ReportComError( const HRESULT hrStatus, LPCTSTR szFile, const int iLine ) 00871 { 00872 if( FAILED(hrStatus) ) 00873 qafReportComError( hrStatus, szFile, iLine ); 00874 return hrStatus; 00875 } 00876 00877 /// 00878 /// @brief Reports about critical errors if ulConstExpr != ulCheckExpr 00879 /// @param ulConstExpr unsigned long - the expected expression 00880 /// @param ulCheckExpr unsigned long - the returned expression 00881 /// @param szExpr LPCTSTR - the expression of ulCheckExpr 00882 /// @param szFile LPCTSTR - the file name returned by _FILE_ 00883 /// @param iLine const int - the line number returned by _LINE_ 00884 /// @return bool the same as (ulConstExpr == ulCheckExpr) 00885 /// @author Andrew Schetinin 00886 /// @date July 2, 2003 00887 /// 00888 /// Reports critical errors if ulConstExpr != ulCheckExpr. 00889 /// This function is used by debug macroses. Do not use it in your code! 00890 /// 00891 inline bool ReportCheckError( const unsigned long ulConstExpr, 00892 const unsigned long ulCheckExpr, LPCTSTR szExpr, LPCTSTR szFile, 00893 const int iLine ) 00894 { 00895 if( ulConstExpr == ulCheckExpr ) 00896 return true; 00897 TCHAR szErrorMessage[100] = { 0 }; 00898 _stprintf( szErrorMessage, _T("Check error: got %d (0x%X) while expected %d (0x%X)"), 00899 ulCheckExpr, ulCheckExpr, ulConstExpr, ulConstExpr ); 00900 OutputDebugStringEx( szFile, iLine, szExpr, szErrorMessage ); 00901 return false; 00902 } 00903 00904 /// 00905 /// @brief Return an accessible directory name for all log files. 00906 /// @param lpszDirBuf LPTSTR buffer for the directory name 00907 /// @param dwMaxLen DWORD size of the buffer in characters (including the trailing zero) 00908 /// @return DWORD length of the returned string or 0 in case of error 00909 /// @author Andrew Schetinin 00910 /// @date February 6, 2003 00911 /// 00912 /// Get the buffer and the buffer length in TCHAR characters including tailing 0x00(00). 00913 /// Returns the length of the written string or 0 if the directory name cannot be generated. 00914 /// The directory name is constructed from the: <p> 00915 /// 1. Try get the folder path from the environment variable QAFDEBUG_LOG_ENV_VAR <p> 00916 /// 2. Try CSIDL_APPDATA (C:\Documents and Settings\username\Application Data) + QAFDEBUG_LOG_SUBFOLDER <p> 00917 /// 3. Try CSIDL_COMMON_APPDATA (C:\Documents and Settings\All Users\Application Data) 00918 /// + QAFDEBUG_LOG_SUBFOLDER <p> 00919 /// 4. Return 0 <p> 00920 /// If the folders are missing on the disk, they are created. 00921 /// 00922 DWORD GetLogDir( LPTSTR lpszDirBuf, const DWORD dwMaxLen ); 00923 00924 /// 00925 /// @brief This function allows setting the module name for additional logging options. 00926 /// @param LPCTSTR, name of the DLL or EXE, 0-terminated, not longer than MAX_PATH characters. 00927 /// @return void 00928 /// @author Andrew Schetinin 00929 /// @date December 7, 2003 00930 /// 00931 /// This will switch on logging of the file name and version number of the current EXE or DLL. 00932 /// It will be logged after the file name and path of the hosting process, 00933 /// only the module file name without path is logged: FILENAME.DLL(1.0.0.1) 00934 /// 00935 void SetModule( LPCTSTR szModuleName ); 00936 00937 } 00938 00939 #endif 00940 00941 00942 /////////////////////////////////////////////// 00943 // END OF FILE 00944 /////////////////////////////////////////////// 00945 #endif