00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "stdafx.h"
00033
00034 #include "QAFDebug.h"
00035
00036 #include <malloc.h>
00037 #include <shlobj.h>
00038
00039
00040 #ifndef QAF_DISABLED
00041
00042
00043
00044
00045
00046
00047 const DWORD QDEBUG_SHMEMSIZE = sizeof(DWORD);
00048
00049
00050 const DWORD QAFDEBUG_FMT_HRESULT_LEN = 20;
00051
00052
00053 const LPCTSTR QAFDEBUG_FMT_HRESULT = _T("FAILED(0x%08X)");
00054
00055
00056 const DWORD QAFDEBUG_FMT_ERROR_SUCCESS_LEN = 30;
00057
00058
00059 const LPCTSTR QAFDEBUG_FMT_ERROR_SUCCESS = _T("(ERROR_SUCCESS != 0x%08X)");
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 const size_t MAX_BUF_SIZE = 2048;
00078
00079
00080
00081 #define QAFDEBUG_FMT_SPOS _T("%.250s(%d) : %.600s")
00082
00083
00084 #define QAFDEBUG_FMT_PREFIX _T("\r\n\t")
00085
00086
00087
00088 #define QAFDEBUG_FMT_DATE QAFDEBUG_FMT_PREFIX _T("time: ") _T("%04d-%02d-%02d %02d:%02d:%02d:%03d")
00089
00090
00091
00092 #define QAFDEBUG_FMT_PROC QAFDEBUG_FMT_PREFIX _T("process: ") _T("0x%08X")
00093
00094
00095
00096 #define QAFDEBUG_FMT_THRE QAFDEBUG_FMT_PREFIX _T("thread: ") _T("0x%08X")
00097
00098
00099
00100 #define QAFDEBUG_FMT_APPL QAFDEBUG_FMT_PREFIX _T("application: ") _T("%.250s")
00101
00102
00103
00104 #define QAFDEBUG_FMT_MODU QAFDEBUG_FMT_PREFIX _T("module: ") _T("%.250s")
00105
00106
00107
00108 #define QAFDEBUG_FMT_LERR QAFDEBUG_FMT_PREFIX _T("last error: ") _T("%.250s")
00109
00110
00111
00112 #define QAFDEBUG_FMT_EXPR QAFDEBUG_FMT_PREFIX _T("expression: ") _T("%.250s")
00113
00114
00115
00116 #define QAFDEBUG_STD_FORMAT \
00117 QAFDEBUG_FMT_SPOS \
00118 QAFDEBUG_FMT_DATE \
00119 QAFDEBUG_FMT_PROC \
00120 QAFDEBUG_FMT_THRE \
00121 QAFDEBUG_FMT_APPL \
00122 QAFDEBUG_FMT_MODU \
00123 QAFDEBUG_FMT_LERR \
00124 QAFDEBUG_FMT_EXPR
00125
00126
00127 #define QAFDEBUG_ERROR_MUTEX_CREATE QAFDEBUG_ERROR_PREFIX _T("Mutex is not created\r\n")
00128 #define QAFDEBUG_ERROR_MAP_FILE_CREATE QAFDEBUG_ERROR_PREFIX _T("Mapped-memory file is not created\r\n")
00129 #define QAFDEBUG_ERROR_LOG_FILE_PATH QAFDEBUG_ERROR_PREFIX _T("Path to the error log file cannot be retrieved\r\n")
00130 #define QAFDEBUG_ERROR_POINTER_NOT_MAPPED QAFDEBUG_ERROR_PREFIX _T("Memory pointer is not mapped to the Mapped-memory file\r\n")
00131 #define QAFDEBUG_ERROR_NULL QAFDEBUG_ERROR_PREFIX _T("qafOutputDebugString() got an empty error message.\r\n")
00132 #define QAFDEBUG_ERROR_STD_NULL QAFDEBUG_ERROR_PREFIX _T("QAFDebug::std pointer is not initialized.\r\n")
00133 #define QAFDEBUG_ERROR_OPEN_LOG_FILE QAFDEBUG_ERROR_PREFIX _T("Debug log file cannot be opened.\r\n")
00134 #define QAFDEBUG_ERROR_ALLOCATE_BUFFER QAFDEBUG_ERROR_PREFIX _T("Cannot allocate memory for formatting the error message.\r\n")
00135 #define QAFDEBUG_ERROR_NULL_ARGS QAFDEBUG_ERROR_PREFIX _T("NULL input parameters for formatting the error message.\r\n")
00136 #define QAFDEBUG_ERROR_FORMAT QAFDEBUG_ERROR_PREFIX _T("Cannot format the error message.\r\n")
00137 #define QAFDEBUG_ERROR_CLOSE_FILE QAFDEBUG_ERROR_PREFIX _T("Cannot close the debug log file\r\n")
00138 #define QAFDEBUG_ERROR_BACKUP QAFDEBUG_ERROR_PREFIX _T("Cannot create a backup copy of the debug log file\r\n")
00139
00140
00141
00142
00143
00144 #pragma warning( push )
00145 #pragma warning( disable : 4100 ) // (possibly) unreferenced formal parameter
00146
00147
00148
00149
00150
00151 inline void ODS( LPCTSTR szMessage )
00152 {
00153 #ifndef QAF_OUTPUTDEBUGSTRING_DISABLED
00154 OutputDebugString( szMessage );
00155 #endif
00156 }
00157
00158 #pragma warning( pop )
00159
00160
00161
00162
00163
00164
00165
00166 class CSync
00167 {
00168 public:
00169
00170
00171 enum CSOP { CS_NOP = 0, CS_CREATE = 1, CS_DESTROY = 2 };
00172
00173
00174 CSync( CRITICAL_SECTION * pcs, const CSOP csop = CS_NOP )
00175 {
00176 m_pcs = pcs;
00177 m_csop = csop;
00178 if( CS_CREATE == m_csop )
00179 InitializeCriticalSection( m_pcs );
00180 EnterCriticalSection( m_pcs );
00181 }
00182
00183
00184 ~CSync()
00185 {
00186 LeaveCriticalSection( m_pcs );
00187 if( CS_DESTROY == m_csop )
00188 DeleteCriticalSection( m_pcs );
00189 }
00190
00191 private:
00192
00193
00194 CRITICAL_SECTION * m_pcs;
00195
00196
00197 CSOP m_csop;
00198
00199 };
00200
00201
00202
00203
00204
00205 class CQAFDebug
00206 {
00207 private:
00208
00209 #ifndef QAF_UNITTEST_DISABLED
00210
00211 HANDLE m_hMutex;
00212
00213
00214 LPVOID m_pMem;
00215
00216
00217 HANDLE m_hMapObject;
00218 #endif
00219
00220
00221 #ifndef QAF_LOGFILE_DISABLED
00222 TCHAR m_szLogFileName[MAX_PATH];
00223 #endif
00224
00225
00226 CRITICAL_SECTION m_cs;
00227
00228
00229 TCHAR m_szApplicationName[MAX_PATH];
00230
00231 protected:
00232
00233 #ifndef QAF_UNITTEST_DISABLED
00234
00235 bool SetSharedFlag( const DWORD dwFlag )
00236 {
00237 if( ! tryLock() )
00238 return false;
00239
00240 memcpy( m_pMem, &dwFlag, sizeof(dwFlag) );
00241
00242 unLock();
00243
00244 return true;
00245 }
00246
00247
00248 void CQAFDebug::GetSharedFlag( const LPDWORD pdwFlag )
00249 {
00250 if( (NULL != pdwFlag) && tryLock() )
00251 {
00252 memcpy( pdwFlag, m_pMem, sizeof(*pdwFlag) );
00253 unLock();
00254 }
00255 }
00256
00257
00258 bool tryLock()
00259 {
00260 return (WaitForSingleObject( m_hMutex, 50 ) == WAIT_OBJECT_0);
00261 }
00262
00263
00264 void unLock()
00265 {
00266 ReleaseMutex( m_hMutex );
00267 }
00268 #endif
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 static DWORD qafGetLogFileName( LPTSTR szFilenameBuf, const DWORD dwMaxLen );
00280
00281
00282 static CQAFDebug & instance( void )
00283 {
00284
00285 static CQAFDebug std_err;
00286
00287 return std_err;
00288 }
00289
00290 public:
00291
00292
00293 CQAFDebug()
00294 #ifndef QAF_UNITTEST_DISABLED
00295 : m_hMutex(NULL), m_hMapObject(NULL), m_pMem(NULL)
00296 #endif
00297 {
00298 CSync sync( &m_cs, CSync::CS_CREATE );
00299
00300 if( 0 == SetLogModule( NULL, m_szApplicationName, MAX_PATH ) )
00301 m_szApplicationName[0] = 0;
00302
00303 #ifndef QAF_LOGFILE_DISABLED
00304
00305 if( 0 == qafGetLogFileName( m_szLogFileName, MAX_PATH ) )
00306 m_szLogFileName[0] = 0;
00307 #endif
00308
00309 #ifndef QAF_UNITTEST_DISABLED
00310 m_hMutex = CreateMutex( NULL, false, QAFDEBUG_SILENCE_MUTEX );
00311 if( NULL == m_hMutex )
00312 ODS( QAFDEBUG_ERROR_MUTEX_CREATE );
00313
00314 m_hMapObject = CreateFileMapping(
00315 INVALID_HANDLE_VALUE,
00316 NULL,
00317 PAGE_READWRITE,
00318 0,
00319 QDEBUG_SHMEMSIZE,
00320 QDEBUG_SHMEMFILE );
00321 if( NULL == m_hMapObject )
00322 ODS( QAFDEBUG_ERROR_MAP_FILE_CREATE );
00323
00324
00325 bool fInit = (GetLastError() != ERROR_ALREADY_EXISTS);
00326
00327
00328 m_pMem = MapViewOfFile(
00329 m_hMapObject,
00330 FILE_MAP_WRITE,
00331 0,
00332 0,
00333 0 );
00334 if( NULL == m_pMem )
00335 ODS( QAFDEBUG_ERROR_POINTER_NOT_MAPPED );
00336
00337 if( fInit )
00338 SetSharedFlag( TRUE );
00339 #endif
00340 }
00341
00342
00343 ~CQAFDebug()
00344 {
00345 CSync sync( &m_cs, CSync::CS_DESTROY );
00346
00347 #ifndef QAF_UNITTEST_DISABLED
00348 unLock();
00349 #endif
00350
00351 #ifndef QAF_LOGFILE_DISABLED
00352 m_szLogFileName[0] = 0;
00353 #endif
00354
00355 #ifndef QAF_UNITTEST_DISABLED
00356 if( NULL != m_pMem )
00357 {
00358 UnmapViewOfFile( m_pMem );
00359 m_pMem = NULL;
00360 }
00361
00362 if( NULL != m_hMapObject )
00363 {
00364 CloseHandle( m_hMapObject );
00365 m_hMapObject = NULL;
00366 }
00367
00368 if( NULL != m_hMutex )
00369 {
00370 CloseHandle( m_hMutex );
00371 m_hMutex = NULL;
00372 }
00373 #endif
00374 }
00375
00376 #ifndef QAF_LOGFILE_DISABLED
00377
00378 static HANDLE tryOpenLogFile( void )
00379 {
00380 CSync sync( &instance().m_cs );
00381 LPTSTR szFilename = instance().m_szLogFileName;
00382 bool bAlreadyTried = false;
00383 HANDLE h = INVALID_HANDLE_VALUE;
00384 while( true )
00385 {
00386 h = CreateFile( szFilename, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL );
00387 if( INVALID_HANDLE_VALUE == h )
00388 {
00389 ODS( QAFDEBUG_ERROR_OPEN_LOG_FILE );
00390 return INVALID_HANDLE_VALUE;
00391 }
00392 if( bAlreadyTried || ((QAFDEBUG_LOG_FILE_MAX_SIZE / 2) > GetFileSize( h, NULL )) )
00393 break;
00394 if( ! CloseHandle(h) )
00395 {
00396 ODS( QAFDEBUG_ERROR_CLOSE_FILE );
00397 return INVALID_HANDLE_VALUE;
00398 }
00399 TCHAR szCopyFilename[MAX_PATH] = { 0 };
00400 _tcscpy( szCopyFilename, szFilename );
00401 LPTSTR szPos = _tcsrchr( szCopyFilename, _T('\\') );
00402 szPos[1] = 0;
00403 _tcscat( szPos, QAFDEBUG_LOG_OLD_FILE_NAME );
00404 DeleteFile( szCopyFilename );
00405 if( !MoveFile( szFilename, szCopyFilename ) )
00406 {
00407 ODS( QAFDEBUG_ERROR_BACKUP );
00408 }
00409 bAlreadyTried = true;
00410 }
00411 return h;
00412 }
00413 #endif
00414
00415
00416 static bool tryEnable( void )
00417 {
00418 #ifdef QAF_UNITTEST_DISABLED
00419 return true;
00420 #else
00421 CSync sync( &instance().m_cs );
00422 return instance().SetSharedFlag( TRUE );
00423 #endif
00424 }
00425
00426
00427 static bool tryDisable( void )
00428 {
00429 #ifdef QAF_UNITTEST_DISABLED
00430 return true;
00431 #else
00432 CSync sync( &instance().m_cs );
00433 return instance().SetSharedFlag( FALSE );
00434 #endif
00435 }
00436
00437
00438 static bool isEnabled( void )
00439 {
00440 #ifdef QAF_UNITTEST_DISABLED
00441 return true;
00442 #else
00443 CSync sync( &instance().m_cs );
00444 DWORD dwTemp = FALSE;
00445 instance().GetSharedFlag( &dwTemp );
00446 return (dwTemp == TRUE);
00447 #endif
00448 }
00449
00450
00451 static LPCTSTR GetApplication()
00452 {
00453 return instance().m_szApplicationName;
00454 }
00455
00456
00457
00458
00459
00460 static DWORD SetLogModule( HMODULE hModule, LPTSTR szOutputBuffer, DWORD dwBufSize )
00461 {
00462 if( (NULL == szOutputBuffer) || (dwBufSize < 2) )
00463 return 0;
00464 szOutputBuffer[0] = 0;
00465 DWORD dwRet = GetModuleFileName( hModule, szOutputBuffer, dwBufSize - 1 );
00466 if( (0 == dwRet) || (dwRet > (dwBufSize - 2)) )
00467 return 0;
00468 DWORD dwModuleFileNameLen = dwRet;
00469 DWORD dwReserved = 0;
00470 dwRet = GetFileVersionInfoSize( szOutputBuffer, &dwReserved );
00471 if( 0 == dwRet )
00472 return dwModuleFileNameLen;
00473 void * pVerInfo = malloc( dwRet );
00474 if( NULL == pVerInfo )
00475 return dwModuleFileNameLen;
00476 memset( pVerInfo, 0, dwRet );
00477 BOOL bRet = GetFileVersionInfo( szOutputBuffer, dwReserved, dwRet, pVerInfo );
00478 if( !bRet )
00479 {
00480 free( pVerInfo );
00481 return dwModuleFileNameLen;
00482 }
00483 UINT uiSize = 0;
00484 VS_FIXEDFILEINFO * pFixedVerInfo = NULL;
00485 bRet = VerQueryValue( pVerInfo, _T("\\"), (LPVOID *)(&pFixedVerInfo), &uiSize );
00486 if( !bRet || (NULL == pFixedVerInfo) || (sizeof(VS_FIXEDFILEINFO) != uiSize) )
00487 {
00488 free( pVerInfo );
00489 return dwModuleFileNameLen;
00490 }
00491 const int MAX_TEMP_BUF = 26;
00492 TCHAR szBuf[MAX_TEMP_BUF] = { 0 };
00493 _sntprintf( szBuf, 25, _T(" <%d.%d.%d.%d>"),
00494 HIWORD(pFixedVerInfo->dwFileVersionMS), LOWORD(pFixedVerInfo->dwFileVersionMS),
00495 HIWORD(pFixedVerInfo->dwFileVersionLS), LOWORD(pFixedVerInfo->dwFileVersionLS) );
00496 szBuf[MAX_TEMP_BUF - 1] = 0;
00497 free( pVerInfo );
00498 if( (dwModuleFileNameLen + MAX_TEMP_BUF + 1) < dwBufSize )
00499 {
00500 _tcscpy( szOutputBuffer + dwModuleFileNameLen, szBuf );
00501 dwModuleFileNameLen += _tcslen( szBuf );
00502 }
00503 return dwModuleFileNameLen;
00504 }
00505
00506 };
00507
00508
00509
00510
00511
00512
00513 #if !defined(INVALID_FILE_ATTRIBUTES)
00514 const DWORD INVALID_FILE_ATTRIBUTES = 0xFFFFFFFF;
00515 #endif
00516
00517
00518 bool DirExists0( LPCTSTR dirName )
00519 {
00520 DWORD dwAttr = GetFileAttributes( dirName );
00521
00522 if( dwAttr == INVALID_FILE_ATTRIBUTES )
00523 return false;
00524
00525 return ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) != 0);
00526 }
00527
00528
00529
00530 bool CreateSubFolders0( LPCTSTR szFolderName )
00531 {
00532
00533 DWORD dwLen = _tcslen(szFolderName);
00534 if( dwLen <= 0 )
00535 return false;
00536
00537 LPTSTR szTemp = (LPTSTR) malloc( (dwLen + 1) * sizeof(TCHAR) );
00538 if( NULL == szTemp )
00539 return false;
00540 _tcscpy( szTemp, szFolderName );
00541 if( szTemp[dwLen - 1] == _T('\\') )
00542 dwLen--;
00543 szTemp[dwLen] = _T('\0');
00544
00545 bool bRet = DirExists0( szTemp );
00546
00547 if( ! bRet )
00548 {
00549 LPTSTR szPos = _tcsrchr( szTemp, _T('\\') );
00550 if( NULL != szPos )
00551 {
00552 (*szPos) = _T('\0');
00553
00554 if( CreateSubFolders0( szTemp ) )
00555 {
00556
00557 (*szPos) = _T('\\');
00558 bRet = (TRUE == CreateDirectory( szTemp, NULL ));
00559 }
00560 }
00561 }
00562 free( szTemp );
00563 return bRet;
00564 }
00565
00566
00567 #if !defined(CSIDL_COMMON_APPDATA)
00568
00569 #define CSIDL_COMMON_APPDATA 0x0023
00570 #endif
00571 #if !defined(CSIDL_FLAG_CREATE)
00572
00573 #define CSIDL_FLAG_CREATE 0x8000
00574 #endif
00575
00576
00577 #ifndef _WIN32_WCE
00578
00579
00580 const int LIBRARY_COUNT = 2;
00581
00582
00583 const LPCTSTR LIBRARY_DLL[LIBRARY_COUNT] = { _T("shell32.dll"), _T("shfolder.dll") };
00584
00585
00586 #ifdef _UNICODE
00587 const LPCSTR SHGetFolderPathFuncName = "SHGetFolderPathW";
00588 #else
00589 const LPCSTR SHGetFolderPathFuncName = "SHGetFolderPathA";
00590 #endif
00591
00592
00593 typedef HRESULT (__stdcall* PSHGetFolderPath)
00594 ( HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPTSTR szPath );
00595
00596
00597 HRESULT SHGetSpecialFolderPathCustom( HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPTSTR szPath )
00598 {
00599 HRESULT hr = E_FAIL;
00600 for( int i = 0; i < LIBRARY_COUNT; i++ )
00601 {
00602 HMODULE hModule = LoadLibrary( LIBRARY_DLL[i] );
00603 if( NULL != hModule )
00604 {
00605 PSHGetFolderPath pFunc = (PSHGetFolderPath) GetProcAddress( hModule, SHGetFolderPathFuncName );
00606 if( NULL != pFunc )
00607 hr = pFunc( hwndOwner, nFolder, hToken, dwFlags, szPath );
00608 FreeLibrary( hModule );
00609 }
00610 if( S_OK == hr )
00611 break;
00612 }
00613 return hr;
00614 }
00615
00616 #endif // This part is excluded for Windows CE
00617
00618
00619
00620 typedef enum {
00621 Q_SHGFP_TYPE_CURRENT = 0,
00622 Q_SHGFP_TYPE_DEFAULT = 1,
00623 } Q_SHGFP_TYPE;
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 DWORD CQAFDebug::qafGetLogFileName( LPTSTR szFilenameBuf, const DWORD dwMaxLen )
00635 {
00636 DWORD dwRet = QAFDebug::GetLogDir( szFilenameBuf, dwMaxLen );
00637 if( 0 == dwRet )
00638 return 0;
00639
00640 _tcscat( szFilenameBuf, QAFDEBUG_LOG_FILE_NAME );
00641 return _tcslen(szFilenameBuf);
00642 }
00643
00644
00645
00646
00647
00648 class CPreserveLastError
00649 {
00650 public:
00651
00652
00653
00654 CPreserveLastError( const LPDWORD pdwLastError )
00655 {
00656 m_bPreserveLastError = (NULL == pdwLastError);
00657 if( m_bPreserveLastError )
00658 m_dwLastError = GetLastError();
00659 else
00660 m_dwLastError = (*pdwLastError);
00661 }
00662
00663
00664 ~CPreserveLastError()
00665 {
00666 if( m_bPreserveLastError && (GetLastError() != m_dwLastError) )
00667 SetLastError( m_dwLastError );
00668 }
00669
00670
00671 DWORD GetSavedLastError( void )
00672 {
00673 return m_dwLastError;
00674 }
00675
00676
00677 operator LPDWORD()
00678 {
00679 return &m_dwLastError;
00680 }
00681
00682 private:
00683
00684
00685 DWORD m_dwLastError;
00686
00687
00688 bool m_bPreserveLastError;
00689
00690 };
00691
00692
00693
00694
00695
00696
00697 TCHAR szCurrentModuleName[MAX_PATH] = { 0 };
00698
00699
00700 void QAFDebug::SetModule( LPCTSTR szModuleName )
00701 {
00702 szCurrentModuleName[0] = 0;
00703 if( (NULL != szModuleName) && (0 != szModuleName[0]) )
00704 {
00705 HMODULE hModule = GetModuleHandle( szModuleName );
00706 if( NULL == hModule )
00707 return;
00708 CQAFDebug::SetLogModule( hModule, szCurrentModuleName, MAX_PATH );
00709 }
00710 }
00711
00712 bool QAFDebug::tryEnable(void)
00713 {
00714 return CQAFDebug::tryEnable();
00715 }
00716
00717 bool QAFDebug::tryDisable(void)
00718 {
00719 return CQAFDebug::tryDisable();
00720 }
00721
00722
00723 inline bool isRN( const TCHAR ch )
00724 {
00725 return (_T('\r') == ch) || (_T('\n') == ch);
00726 }
00727
00728 #pragma warning( push )
00729 #pragma warning( disable : 4189 ) // local variable is initialized but not referenced
00730
00731 void QAFDebug::OutputDebugStringEx( LPCTSTR szFilename, const int iLine,
00732 LPCTSTR szExpression, LPCTSTR szErrorMessage, const LPDWORD pdwLastError )
00733 {
00734
00735 CPreserveLastError LastError( pdwLastError );
00736
00737
00738 if( !CQAFDebug::isEnabled() )
00739 return;
00740
00741
00742 if( NULL == szFilename )
00743 szFilename = _T("");
00744 if( NULL == szExpression )
00745 szExpression = _T("");
00746 if( NULL == szErrorMessage )
00747 szErrorMessage = _T("");
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759 SYSTEMTIME st;
00760 GetLocalTime( &st );
00761 DWORD dwProcess = GetCurrentProcessId(), dwThread = GetCurrentThreadId();
00762
00763
00764 TCHAR szLastError[MAX_PATH] = _T("0");
00765 if( 0 != LastError.GetSavedLastError() )
00766 {
00767 _itot( LastError.GetSavedLastError(), szLastError, 10 );
00768 LPTSTR szPos = szLastError + _tcslen( szLastError );
00769 _tcscpy( szPos, _T(", ") );
00770 szPos += 2;
00771 DWORD dwRet = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
00772 NULL, LastError.GetSavedLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00773 szPos, MAX_PATH - (szPos - szLastError), NULL );
00774 szPos[dwRet] = 0;
00775 while( dwRet-- && _tcschr( _T("\n\r"), szPos[dwRet] ) )
00776 szPos[dwRet] = 0;
00777 }
00778
00779 LPTSTR szFmtStr = QAFDEBUG_STD_FORMAT;
00780 size_t nBufSize = _tcslen( szFmtStr ) + _tcslen( szFilename ) + _tcslen( szExpression )
00781 + _tcslen( szErrorMessage ) + _tcslen( szLastError )
00782 + _tcslen( CQAFDebug::GetApplication() ) + _tcslen( szCurrentModuleName );
00783 if( nBufSize > MAX_BUF_SIZE )
00784 nBufSize = MAX_BUF_SIZE;
00785 LPTSTR szBuffer = (LPTSTR) malloc( nBufSize * sizeof(TCHAR) );
00786 if( NULL == szBuffer )
00787 {
00788 ODS( QAFDEBUG_ERROR_ALLOCATE_BUFFER );
00789 return;
00790 }
00791
00792
00793 int iRes = _sntprintf( szBuffer, nBufSize, szFmtStr,
00794 szFilename, iLine, szErrorMessage,
00795 st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
00796 dwProcess,
00797 dwThread,
00798 CQAFDebug::GetApplication(),
00799 szCurrentModuleName,
00800 szLastError,
00801 szExpression );
00802 DWORD dw = GetLastError();
00803 if( 0 > iRes )
00804 {
00805 ODS( QAFDEBUG_ERROR_FORMAT );
00806 free( szBuffer );
00807 return;
00808 }
00809
00810
00811 if( (0 != szBuffer[0]) && (0 != szBuffer[1]) )
00812 {
00813 for( TCHAR * szPos = szBuffer; 0 != szPos[2]; ++szPos )
00814 {
00815 if( isRN( szPos[0] ) && isRN( szPos[2] ) )
00816 szPos[0] = _T(' ');
00817 }
00818 }
00819
00820
00821 DWORD dwBufferSize = _tcslen( szBuffer );
00822 if( (szBuffer[dwBufferSize - 1] != _T('\r')) && (szBuffer[dwBufferSize - 1] != _T('\n')) )
00823 {
00824 _tcscat( szBuffer, _T("\r\n") );
00825 dwBufferSize += 2;
00826 }
00827
00828
00829 ODS( szBuffer );
00830
00831
00832 #ifndef QAF_LOGFILE_DISABLED
00833
00834
00835 _tcscat( szBuffer, _T("\r\n") );
00836 dwBufferSize += 2;
00837
00838
00839 #ifdef QAF_SAVE_UNICODE_AS_UTF8
00840 DWORD dwUtf8BufSize = (dwBufferSize + 1) * sizeof(TCHAR);
00841 LPSTR szUTF8 = (LPSTR) malloc( dwUtf8BufSize );
00842 if( NULL != szUTF8 )
00843 {
00844 int nRet = WideCharToMultiByte( CP_UTF8, 0, szBuffer, dwBufferSize, szUTF8,
00845 dwUtf8BufSize, NULL, NULL );
00846 if( nRet > 0 )
00847 {
00848 free( szBuffer );
00849 szBuffer = (LPTSTR) szUTF8;
00850 dwBufferSize = nRet;
00851
00852
00853 }
00854 }
00855 #else
00856 dwBufferSize *= sizeof(TCHAR);
00857 #endif
00858
00859
00860
00861 HANDLE h = INVALID_HANDLE_VALUE;
00862 for( int i = 0; i < 5; i++ )
00863 {
00864 h = CQAFDebug::tryOpenLogFile();
00865 #ifdef _DEBUG
00866 DWORD dw = GetLastError();
00867 #endif
00868 if( h != INVALID_HANDLE_VALUE )
00869 {
00870 SetFilePointer( h, 0, NULL, FILE_END );
00871 #ifdef _DEBUG
00872 dw = GetLastError();
00873 #endif
00874 if( ! WriteFile( h, szBuffer, dwBufferSize, &dwBufferSize, NULL ) )
00875 #ifdef _DEBUG
00876 dw = GetLastError();
00877 #else
00878 dw = 0;
00879 #endif
00880
00881 CloseHandle( h );
00882
00883 break;
00884 }
00885 Sleep( 40 );
00886 }
00887
00888
00889 #endif
00890
00891 free( szBuffer );
00892 }
00893
00894 #pragma warning( pop )
00895
00896 HRESULT QAFDebug::qafReportComError( HRESULT hrStatus, LPCTSTR szFile, const int iLine )
00897 {
00898 if( SUCCEEDED(hrStatus) )
00899 return hrStatus;
00900
00901 CPreserveLastError LastError( NULL );
00902
00903 if( FACILITY_WINDOWS == HRESULT_FACILITY(hrStatus) )
00904 hrStatus = HRESULT_CODE(hrStatus);
00905
00906 LPTSTR szErrMsg = NULL;
00907 int iFreeErrMsg = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
00908 NULL, hrStatus, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), (LPTSTR)&szErrMsg, 0, NULL );
00909 if( (0 == iFreeErrMsg) || (NULL == szErrMsg) )
00910 szErrMsg = QAFDEBUG_ERROR_NO_MESSAGE;
00911
00912 TCHAR szBuf[QAFDEBUG_FMT_HRESULT_LEN];
00913 if( 0 >= wsprintf( szBuf, QAFDEBUG_FMT_HRESULT, hrStatus ) )
00914 szBuf[0] = 0;
00915
00916 QAFDebug::OutputDebugStringEx( szFile, iLine, szBuf, szErrMsg, static_cast<LPDWORD>(LastError) );
00917
00918 if( iFreeErrMsg != 0 )
00919 LocalFree( szErrMsg );
00920
00921 return hrStatus;
00922 }
00923
00924 DWORD QAFDebug::ReportWinError( const DWORD dwError, LPCTSTR szFile, const int iLine )
00925 {
00926 if( ERROR_SUCCESS == dwError )
00927 return dwError;
00928
00929 CPreserveLastError LastError( NULL );
00930
00931 LPTSTR szErrMsg = NULL;
00932 int iFreeErrMsg = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
00933 NULL, dwError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), (LPTSTR)&szErrMsg, 0, NULL );
00934 if( (0 == iFreeErrMsg) || (NULL == szErrMsg) )
00935 szErrMsg = QAFDEBUG_ERROR_NO_MESSAGE;
00936
00937 TCHAR szBuf[QAFDEBUG_FMT_ERROR_SUCCESS_LEN];
00938 if( 0 >= wsprintf( szBuf, QAFDEBUG_FMT_ERROR_SUCCESS, dwError ) )
00939 szBuf[0] = 0;
00940
00941 QAFDebug::OutputDebugStringEx( szFile, iLine, szBuf, szErrMsg, static_cast<LPDWORD>(LastError) );
00942
00943 if( iFreeErrMsg != 0 )
00944 LocalFree( szErrMsg );
00945
00946 return dwError;
00947 }
00948
00949 DWORD QAFDebug::GetLogDir( LPTSTR szDirBuf, const DWORD dwMaxLen )
00950 {
00951
00952
00953 #ifndef _WIN32_WCE
00954
00955
00956
00957 for( int i = 1; i <= 3; i++ )
00958 {
00959 if( 1 == i )
00960 {
00961
00962 DWORD dwRet = GetEnvironmentVariable( QAFDEBUG_LOG_ENV_VAR, szDirBuf, dwMaxLen );
00963 if( (dwRet <= 0) || (dwRet >= dwMaxLen) )
00964 continue;
00965 }
00966 else
00967 {
00968 if( 2 == i )
00969 {
00970
00971 if( S_OK != SHGetSpecialFolderPathCustom( NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, Q_SHGFP_TYPE_CURRENT, szDirBuf ) )
00972 continue;
00973 }
00974 else
00975 {
00976
00977 if( S_OK != SHGetSpecialFolderPathCustom( NULL, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, NULL, Q_SHGFP_TYPE_CURRENT, szDirBuf ) )
00978 return 0;
00979 }
00980
00981 DWORD dwSize = _tcslen(szDirBuf);
00982 if( dwSize > 0 )
00983 {
00984 if( szDirBuf[dwSize - 1] != _T('\\') )
00985 _tcscat( szDirBuf, _T("\\") );
00986 _tcscat( szDirBuf, QAFDEBUG_LOG_SUBFOLDER );
00987 }
00988 }
00989
00990 DWORD dwSizeBuf = _tcslen(szDirBuf);
00991 if( 0 == dwSizeBuf )
00992 continue;
00993
00994
00995 if( szDirBuf[dwSizeBuf - 1] != _T('\\') )
00996 _tcscat( szDirBuf, _T("\\") );
00997
00998 if( ! CreateSubFolders0(szDirBuf) )
00999 continue;
01000
01001 return _tcslen(szDirBuf);
01002 }
01003
01004 #else // This part is specific for Windows CE
01005
01006
01007 SHGetSpecialFolderPath(NULL, szDirBuf, CSIDL_PERSONAL, FALSE);
01008
01009 DWORD dwSize = _tcslen(szDirBuf);
01010 if( dwSize > 0 )
01011 {
01012 if( szDirBuf[dwSize - 1] != _T('\\') )
01013 _tcscat( szDirBuf, _T("\\") );
01014 _tcscat( szDirBuf, QAFDEBUG_LOG_SUBFOLDER );
01015 }
01016
01017 DWORD dwSizeBuf = _tcslen(szDirBuf);
01018 if( 0 == dwSizeBuf )
01019 return 0;
01020
01021
01022 if( szDirBuf[dwSizeBuf - 1] != _T('\\') )
01023 _tcscat( szDirBuf, _T("\\") );
01024
01025 if( ! CreateSubFolders0(szDirBuf) )
01026 return 0;
01027
01028
01029 return _tcslen(szDirBuf);
01030
01031 #endif // This part is specific for Windows CE
01032
01033
01034 return 0;
01035 }
01036
01037
01038
01039
01040 #endif
01041