Filter Library Camera Interface Physics

QAFDebug.h

Go to the documentation of this file.
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

Camera Filter Library documentation © 2004-2007 by Leiden Probe Microscopy