774 lines
17 KiB
C++
774 lines
17 KiB
C++
|
|
/*++
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
stilog.cpp
|
|
|
|
Abstract:
|
|
|
|
Class to handle file based logging
|
|
|
|
Author:
|
|
|
|
Vlad Sadovsky (VladS) 01-Sep-1997
|
|
|
|
History:
|
|
|
|
|
|
--*/
|
|
|
|
|
|
//
|
|
// Include Headers
|
|
//
|
|
|
|
#include "cplusinc.h"
|
|
#include "sticomm.h"
|
|
|
|
//
|
|
// Static definitions and variables
|
|
//
|
|
static const TCHAR szDefaultName[] = TEXT("Sti_Trace.log");
|
|
static const TCHAR szDefaultTracerName[] = TEXT("STI");
|
|
static const TCHAR szMutexNamePrefix[] = TEXT("StiTraceMutex");
|
|
static const TCHAR szColumns[] = TEXT("Severity TracerName [Process::ThreadId] Time MessageText\r\n\r\n");
|
|
static const TCHAR szOpenedLog[] = TEXT("\n****** Opened file log at %s %s .Tracer (%s) , called from [%#s::%#lx]\n");
|
|
static const TCHAR szClosedLog[] = TEXT("\n******Closed trace log on %s %s Tracer (%s) , called from [%#s::%#lx]\n");
|
|
|
|
//
|
|
// Functions
|
|
//
|
|
//
|
|
inline BOOL
|
|
FormatStdTime(
|
|
IN const SYSTEMTIME * pstNow,
|
|
IN OUT TCHAR * pchBuffer,
|
|
IN int cbBuffer
|
|
)
|
|
{
|
|
return ( GetTimeFormat( LOCALE_SYSTEM_DEFAULT,
|
|
( LOCALE_NOUSEROVERRIDE | TIME_FORCE24HOURFORMAT|
|
|
TIME_NOTIMEMARKER),
|
|
pstNow, NULL, pchBuffer, cbBuffer)
|
|
!= 0);
|
|
|
|
} // FormatStdTime()
|
|
|
|
|
|
inline BOOL
|
|
FormatStdDate( IN const SYSTEMTIME * pstNow,
|
|
IN OUT TCHAR * pchBuffer,
|
|
IN int cbBuffer)
|
|
{
|
|
return ( GetDateFormat( LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE,
|
|
pstNow, NULL, pchBuffer, cbBuffer)
|
|
!= 0);
|
|
} // FormatStdDate()
|
|
|
|
|
|
inline TCHAR
|
|
TraceFlagToLetter(
|
|
IN DWORD dwType
|
|
)
|
|
{
|
|
if (dwType & STI_TRACE_ERROR) {
|
|
return TEXT('e');
|
|
}
|
|
else if (dwType & STI_TRACE_WARNING) {
|
|
return TEXT('w');
|
|
}
|
|
else if (dwType & STI_TRACE_INFORMATION) {
|
|
return TEXT('i');
|
|
}
|
|
else {
|
|
return TEXT('t');
|
|
}
|
|
}
|
|
|
|
STI_FILE_LOG::STI_FILE_LOG(
|
|
IN LPCTSTR lpszTracerName,
|
|
IN LPCTSTR lpszLogName,
|
|
IN DWORD dwFlags, // = 0
|
|
IN HMODULE hMessageModule // =NULL
|
|
) :
|
|
m_hMutex(INVALID_HANDLE_VALUE)
|
|
|
|
/*++
|
|
|
|
Description
|
|
|
|
Constructor function for given log object.
|
|
|
|
Arguments:
|
|
|
|
lpszSource: file name for log. Relative to Windows directory
|
|
|
|
Note:
|
|
|
|
--*/
|
|
{
|
|
LPCTSTR lpActualLogName;
|
|
TCHAR szTempName[MAX_PATH];
|
|
LPTSTR pszFilePart;
|
|
|
|
DWORD dwError;
|
|
DWORD cbName;
|
|
DWORD dwLevel;
|
|
DWORD dwMode;
|
|
|
|
BOOL fTruncate = FALSE;
|
|
|
|
m_dwSignature = SIGNATURE_FILE_LOG;
|
|
|
|
lpActualLogName = szDefaultName;
|
|
|
|
m_hLogWindow = NULL;
|
|
m_lWrittenHeader = FALSE;
|
|
m_hDefaultMessageModule = hMessageModule ? hMessageModule : GetModuleHandle(NULL);
|
|
|
|
dwLevel = STI_TRACE_ERROR;
|
|
dwMode = STI_TRACE_ADD_TIME | STI_TRACE_ADD_THREAD;
|
|
|
|
m_hLogFile = INVALID_HANDLE_VALUE;
|
|
*m_szLogFilePath = TEXT('\0');
|
|
m_dwMaxSize = STI_MAX_LOG_SIZE;
|
|
|
|
ReportError(NO_ERROR);
|
|
|
|
//
|
|
// Read global settings from the registry
|
|
//
|
|
RegEntry re(REGSTR_PATH_STICONTROL REGSTR_PATH_LOGGING,HKEY_LOCAL_MACHINE);
|
|
|
|
if (re.IsValid()) {
|
|
|
|
m_dwMaxSize = re.GetNumber(REGSTR_VAL_LOG_MAXSIZE,STI_MAX_LOG_SIZE);
|
|
|
|
//
|
|
// If we need to check append flag, read it from the registry
|
|
//
|
|
if (dwFlags & STIFILELOG_CHECK_TRUNCATE_ON_BOOT) {
|
|
fTruncate = re.GetNumber(REGSTR_VAL_LOG_TRUNCATE_ON_BOOT,FALSE);
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Open file for logging
|
|
//
|
|
if (lpszLogName && *lpszLogName ) {
|
|
lpActualLogName = lpszLogName;
|
|
}
|
|
|
|
//
|
|
// lpszTracerName is ANSI.
|
|
//
|
|
|
|
if (lpszTracerName && *lpszTracerName ) {
|
|
lstrcpyn(m_szTracerName,lpszTracerName,sizeof(m_szTracerName) / sizeof(m_szTracerName[0]));
|
|
m_szTracerName[sizeof(m_szTracerName) / sizeof(m_szTracerName[0]) -1] = TEXT('\0');
|
|
}
|
|
else {
|
|
lstrcpy(m_szTracerName,szDefaultTracerName);
|
|
}
|
|
|
|
//
|
|
// Approximate process name with name of the executable binary used to create process
|
|
//
|
|
*szTempName = TEXT('\0');
|
|
::GetModuleFileName(NULL,szTempName,sizeof(szTempName) / sizeof(szTempName[0]));
|
|
|
|
pszFilePart = _tcsrchr(szTempName,TEXT('\\'));
|
|
|
|
pszFilePart = (pszFilePart && *pszFilePart) ? ::CharNext(pszFilePart) : szTempName;
|
|
|
|
lstrcpyn(m_szProcessName,pszFilePart,sizeof(m_szProcessName)/sizeof(TCHAR));
|
|
m_szProcessName[sizeof(m_szProcessName)/sizeof(TCHAR) - 1] = TEXT('\0');
|
|
|
|
//
|
|
// Read flags for this logger
|
|
//
|
|
re.MoveToSubKey(lpszTracerName);
|
|
|
|
if (re.IsValid()) {
|
|
dwLevel = re.GetNumber(REGSTR_VAL_LOG_LEVEL,STI_TRACE_ERROR)
|
|
& STI_TRACE_MESSAGE_TYPE_MASK;
|
|
|
|
dwMode = re.GetNumber(REGSTR_VAL_LOG_MODE,STI_TRACE_ADD_THREAD)
|
|
& STI_TRACE_MESSAGE_FLAGS_MASK;
|
|
}
|
|
|
|
m_dwReportMode = dwLevel | dwMode;
|
|
|
|
//
|
|
// Open log file
|
|
//
|
|
cbName = ::GetWindowsDirectory(m_szLogFilePath,sizeof(m_szLogFilePath)/sizeof(m_szLogFilePath[0]));
|
|
if (( cbName == 0) || !*m_szLogFilePath ) {
|
|
ReportError(::GetLastError());
|
|
return;
|
|
}
|
|
|
|
lstrcat(lstrcat(m_szLogFilePath,TEXT("\\")),lpActualLogName);
|
|
|
|
m_hLogFile = ::CreateFile(m_szLogFilePath,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
NULL, // security attributes
|
|
OPEN_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL); // template file handle
|
|
|
|
// if ( m_hLogFile!= INVALID_HANDLE_VALUE) {
|
|
if (IS_VALID_HANDLE(m_hLogFile)) {
|
|
|
|
if(fTruncate) {
|
|
::SetFilePointer( m_hLogFile, 0, NULL, FILE_BEGIN );
|
|
::SetEndOfFile( m_hLogFile );
|
|
}
|
|
|
|
::SetFilePointer( m_hLogFile, 0, NULL, FILE_END);
|
|
|
|
lstrcpy(szTempName,szMutexNamePrefix);
|
|
lstrcat(szTempName,lpActualLogName);
|
|
|
|
m_hMutex = ::CreateMutex(NULL,
|
|
FALSE,
|
|
szTempName
|
|
);
|
|
|
|
if ( !IS_VALID_HANDLE(m_hMutex ) ) {
|
|
// ASSERT
|
|
}
|
|
}
|
|
|
|
if (!IS_VALID_HANDLE(m_hLogFile) || !IS_VALID_HANDLE(m_hMutex )) {
|
|
ReportError(::GetLastError());
|
|
}
|
|
else {
|
|
//
|
|
// Success
|
|
//
|
|
}
|
|
|
|
|
|
} /* STI_FILE_LOG::STI_FILE_LOG() */
|
|
|
|
|
|
STI_FILE_LOG::~STI_FILE_LOG( VOID)
|
|
/*++
|
|
|
|
Description:
|
|
|
|
Destructor function for given STI_FILE_LOG object.
|
|
|
|
--*/
|
|
{
|
|
|
|
SYSTEMTIME stCurrentTime;
|
|
TCHAR szFmtDate[20];
|
|
TCHAR szFmtTime[32];
|
|
TCHAR szTextBuffer[128];
|
|
|
|
if(m_lWrittenHeader) {
|
|
|
|
GetLocalTime(&stCurrentTime);
|
|
FormatStdDate( &stCurrentTime, szFmtDate, 15);
|
|
FormatStdTime( &stCurrentTime, szFmtTime, sizeof(szFmtTime) / sizeof(szFmtTime[0]));
|
|
|
|
::wsprintf(szTextBuffer,szClosedLog,
|
|
szFmtDate,szFmtTime,
|
|
m_szTracerName,
|
|
m_szProcessName,
|
|
::GetCurrentThreadId()
|
|
);
|
|
|
|
WriteStringToLog(szTextBuffer);
|
|
|
|
}
|
|
|
|
if (IS_VALID_HANDLE(m_hMutex)) {
|
|
::CloseHandle(m_hMutex);
|
|
m_hMutex = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
if (IS_VALID_HANDLE(m_hLogFile)) {
|
|
::FlushFileBuffers( m_hLogFile);
|
|
::CloseHandle(m_hLogFile);
|
|
m_hLogFile = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
m_dwSignature = SIGNATURE_FILE_LOG_FREE;
|
|
|
|
} /* STI_FILE_LOG::~STI_FILE_LOG() */
|
|
|
|
//
|
|
// IUnknown methods. Used only for reference counting
|
|
//
|
|
STDMETHODIMP
|
|
STI_FILE_LOG::QueryInterface( REFIID riid, LPVOID * ppvObj)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
STI_FILE_LOG::AddRef( void)
|
|
{
|
|
::InterlockedIncrement(&m_cRef);
|
|
return m_cRef;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
STI_FILE_LOG::Release( void)
|
|
{
|
|
LONG cNew;
|
|
|
|
if(!(cNew = ::InterlockedDecrement(&m_cRef))) {
|
|
delete this;
|
|
}
|
|
|
|
return cNew;
|
|
}
|
|
|
|
void
|
|
STI_FILE_LOG::
|
|
WriteLogSessionHeader(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Description
|
|
|
|
|
|
Arguments:
|
|
|
|
Note:
|
|
|
|
--*/
|
|
{
|
|
SYSTEMTIME stCurrentTime;
|
|
TCHAR szFmtDate[32];
|
|
TCHAR szFmtTime[32];
|
|
TCHAR szTextBuffer[128];
|
|
|
|
GetLocalTime(&stCurrentTime);
|
|
FormatStdDate( &stCurrentTime, szFmtDate, sizeof(szFmtDate) / sizeof(szFmtDate[0]));
|
|
FormatStdTime( &stCurrentTime, szFmtTime, sizeof(szFmtTime) / sizeof(szFmtTime[0]));
|
|
|
|
::wsprintf(szTextBuffer,szOpenedLog,
|
|
szFmtDate,szFmtTime,
|
|
m_szTracerName,
|
|
m_szProcessName,
|
|
::GetCurrentThreadId()
|
|
);
|
|
|
|
WriteStringToLog(szTextBuffer);
|
|
WriteStringToLog(szColumns);
|
|
}
|
|
|
|
void
|
|
STI_FILE_LOG::
|
|
ReportMessage(
|
|
DWORD dwType,
|
|
LPCTSTR pszMsg,
|
|
...
|
|
)
|
|
/*++
|
|
|
|
Description
|
|
|
|
|
|
Arguments:
|
|
|
|
Note:
|
|
|
|
--*/
|
|
{
|
|
va_list list;
|
|
TCHAR *pchBuff = NULL;
|
|
DWORD cch;
|
|
|
|
va_start (list, pszMsg);
|
|
|
|
pchBuff = NULL;
|
|
|
|
cch = ::FormatMessage(FORMAT_MESSAGE_MAX_WIDTH_MASK |
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_STRING,
|
|
pszMsg,
|
|
0,
|
|
0,
|
|
(LPTSTR) &pchBuff,
|
|
1024,
|
|
&list
|
|
);
|
|
|
|
vReportMessage(dwType,pszMsg,list);
|
|
|
|
va_end(list);
|
|
}
|
|
|
|
void
|
|
STI_FILE_LOG::
|
|
ReportMessage(
|
|
DWORD dwType,
|
|
DWORD idMessage,
|
|
...
|
|
)
|
|
/*++
|
|
|
|
Description
|
|
|
|
|
|
Arguments:
|
|
|
|
Note:
|
|
|
|
--*/
|
|
{
|
|
va_list list;
|
|
TCHAR *pchBuff = NULL;
|
|
DWORD cch;
|
|
|
|
va_start (list, idMessage);
|
|
|
|
//
|
|
// Read message and add inserts
|
|
//
|
|
pchBuff = NULL;
|
|
|
|
cch = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_MAX_WIDTH_MASK |
|
|
FORMAT_MESSAGE_FROM_HMODULE,
|
|
m_hDefaultMessageModule ,
|
|
idMessage,
|
|
0,
|
|
(LPTSTR) &pchBuff,
|
|
1024,
|
|
&list
|
|
);
|
|
|
|
if (pchBuff && cch) {
|
|
vReportMessage(dwType,pchBuff,list);
|
|
LocalFree(pchBuff);
|
|
}
|
|
|
|
va_end(list);
|
|
|
|
}
|
|
|
|
void
|
|
STI_FILE_LOG::
|
|
vReportMessage(
|
|
DWORD dwType,
|
|
LPCTSTR pszMsg,
|
|
va_list arglist
|
|
)
|
|
/*++
|
|
|
|
Description
|
|
|
|
|
|
Arguments:
|
|
|
|
Note:
|
|
|
|
--*/
|
|
{
|
|
TCHAR achTextBuffer[1024];
|
|
DWORD dwReportMode;
|
|
|
|
|
|
if ((QueryError() != NOERROR) ||
|
|
(!m_hLogFile || m_hLogFile == INVALID_HANDLE_VALUE)) {
|
|
return;
|
|
}
|
|
|
|
// Do we need to display this message ?
|
|
if (!((dwType & m_dwReportMode) & STI_TRACE_MESSAGE_TYPE_MASK)) {
|
|
return;
|
|
}
|
|
|
|
// Start message with type
|
|
*achTextBuffer = TraceFlagToLetter(dwType);
|
|
*(achTextBuffer+1) = TEXT(' ');
|
|
*(achTextBuffer+2) = TEXT('\0');
|
|
|
|
// Add name of tracer source
|
|
lstrcat(lstrcat(achTextBuffer,m_szTracerName),TEXT(" "));;
|
|
|
|
dwReportMode = m_dwReportMode | (dwType & STI_TRACE_MESSAGE_FLAGS_MASK);
|
|
|
|
//
|
|
// Prepare header if needed
|
|
//
|
|
if (dwReportMode & STI_TRACE_MESSAGE_FLAGS_MASK ) {
|
|
|
|
if (dwReportMode & STI_TRACE_ADD_THREAD ) {
|
|
//
|
|
// Add process::thread ID
|
|
//
|
|
TCHAR szThreadId[40];
|
|
|
|
::wsprintf(szThreadId,TEXT("[%#s::%#lx] "),m_szProcessName,::GetCurrentThreadId());
|
|
::lstrcat(::lstrcat(achTextBuffer,szThreadId),TEXT(" "));
|
|
}
|
|
|
|
if (dwReportMode & STI_TRACE_ADD_TIME ) {
|
|
// Add current time
|
|
SYSTEMTIME stCurrentTime;
|
|
TCHAR szFmtTime[32];
|
|
|
|
*szFmtTime = TEXT('\0');
|
|
|
|
::GetLocalTime(&stCurrentTime);
|
|
FormatStdTime( &stCurrentTime, szFmtTime, 15);
|
|
|
|
lstrcat(lstrcat(achTextBuffer,szFmtTime),TEXT(" "));;
|
|
}
|
|
}
|
|
|
|
lstrcat(achTextBuffer,TEXT("\t"));
|
|
|
|
//
|
|
// Now add message text itself
|
|
//
|
|
::wvsprintf(achTextBuffer+::lstrlen(achTextBuffer), pszMsg, arglist);
|
|
::lstrcat(achTextBuffer , TEXT("\r\n"));
|
|
|
|
//
|
|
// Write to the file, flushing buffers if message type is ERROR
|
|
//
|
|
WriteStringToLog(achTextBuffer,(dwType & STI_TRACE_MESSAGE_TYPE_MASK) & STI_TRACE_ERROR);
|
|
|
|
}
|
|
|
|
VOID
|
|
STI_FILE_LOG::
|
|
WriteStringToLog(
|
|
LPCTSTR pszTextBuffer,
|
|
BOOL fFlush // = FALSE
|
|
)
|
|
{
|
|
|
|
DWORD dwcbWritten;
|
|
LONG lHeaderWrittenFlag;
|
|
|
|
//
|
|
// Integrity check. Make sure the mutex and file handles are valid - if not,
|
|
// then bail.
|
|
//
|
|
if (!(IS_VALID_HANDLE(m_hMutex) && IS_VALID_HANDLE(m_hLogFile))) {
|
|
#ifdef DEBUG
|
|
//OutputDebugString(TEXT("STILOG File or Mutex handle is invalid. "));
|
|
#endif
|
|
return ;
|
|
}
|
|
|
|
//
|
|
// If had not done yet, write session header here. Note this is recursive call
|
|
// and flag marking header should be set first.
|
|
//
|
|
lHeaderWrittenFlag = InterlockedExchange(&m_lWrittenHeader,1L);
|
|
|
|
if (!lHeaderWrittenFlag) {
|
|
WriteLogSessionHeader();
|
|
}
|
|
|
|
TAKE_MUTEX t(m_hMutex);
|
|
|
|
//
|
|
// Check that log file size is not exceeding the limit. Assuming log file size is set to fit
|
|
// into 32bit field, so we don't bother looking at high dword.
|
|
//
|
|
// Nb: We are not saving backup copy of the log, expecting that it never grows that large
|
|
//
|
|
|
|
BY_HANDLE_FILE_INFORMATION fi;
|
|
|
|
if (!GetFileInformationByHandle(m_hLogFile,&fi)) {
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("STILOG could not get file size for log file. "));
|
|
#endif
|
|
return ;
|
|
}
|
|
|
|
if ( fi.nFileSizeHigh !=0 || (fi.nFileSizeLow > m_dwMaxSize) ){
|
|
|
|
::SetFilePointer( m_hLogFile, 0, NULL, FILE_BEGIN );
|
|
::SetEndOfFile( m_hLogFile );
|
|
|
|
::GetFileInformationByHandle(m_hLogFile,&fi);
|
|
}
|
|
|
|
#ifdef USE_FILE_LOCK
|
|
::LockFile(m_hLogFile,fi.nFileSizeLow,fi.nFileSizeHigh,4096,0);
|
|
#endif
|
|
|
|
::SetFilePointer( m_hLogFile, 0, NULL, FILE_END);
|
|
|
|
#ifdef _UNICODE
|
|
UINT len = lstrlen(pszTextBuffer);
|
|
CHAR *ansiBuffer = (CHAR *)alloca(len + 2);
|
|
|
|
if(ansiBuffer) {
|
|
::WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
pszTextBuffer,
|
|
-1,
|
|
ansiBuffer,
|
|
len + 1,
|
|
NULL,
|
|
NULL);
|
|
::WriteFile(m_hLogFile,
|
|
ansiBuffer,
|
|
len,
|
|
&dwcbWritten,
|
|
NULL);
|
|
}
|
|
|
|
#else
|
|
::WriteFile(m_hLogFile,
|
|
pszTextBuffer,
|
|
lstrlen(pszTextBuffer),
|
|
&dwcbWritten,
|
|
NULL);
|
|
#endif
|
|
#ifdef USE_FILE_LOCK
|
|
::UnlockFile(m_hLogFile,fi.nFileSizeLow,fi.nFileSizeHigh,4096,0);
|
|
#endif
|
|
|
|
if (fFlush) {
|
|
// Flush buffers to disk
|
|
FlushFileBuffers(m_hLogFile);
|
|
}
|
|
|
|
if(QueryReportMode() & STI_TRACE_LOG_TOUI) {
|
|
|
|
ULONG_PTR dwResult;
|
|
|
|
|
|
SendMessageTimeout(m_hLogWindow,
|
|
STIMON_MSG_LOG_MESSAGE,
|
|
0,
|
|
(LPARAM)pszTextBuffer,
|
|
0,
|
|
100,
|
|
&dwResult
|
|
);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
::OutputDebugString(pszTextBuffer);
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// C-APIs
|
|
//
|
|
HANDLE
|
|
WINAPI
|
|
CreateStiFileLog(
|
|
IN LPCTSTR lpszTracerName,
|
|
IN LPCTSTR lpszLogName,
|
|
IN DWORD dwReportMode
|
|
)
|
|
/*++
|
|
|
|
Description
|
|
|
|
|
|
Arguments:
|
|
|
|
Note:
|
|
|
|
--*/
|
|
{
|
|
|
|
HANDLE hRet = INVALID_HANDLE_VALUE;
|
|
STI_FILE_LOG* pStiFileLog = NULL;
|
|
|
|
pStiFileLog = new STI_FILE_LOG(lpszTracerName,lpszLogName);
|
|
|
|
if(pStiFileLog){
|
|
if (pStiFileLog->IsValid()) {
|
|
hRet = static_cast<HANDLE>(pStiFileLog);
|
|
pStiFileLog->SetReportMode(pStiFileLog->QueryReportMode() | dwReportMode);
|
|
} else {
|
|
|
|
//
|
|
// Notice that we delete this object rather than calling
|
|
// CloseStiFileLog. We do this because it the filelog is
|
|
// not valid (maybe it had an internal creation error),
|
|
// CloseStiFileLog won't try to delete it, hence we delete
|
|
// it here.
|
|
//
|
|
delete pStiFileLog;
|
|
|
|
pStiFileLog = NULL;
|
|
hRet = INVALID_HANDLE_VALUE;
|
|
}
|
|
} else {
|
|
::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
return hRet;
|
|
}
|
|
|
|
DWORD
|
|
WINAPI
|
|
CloseStiFileLog(
|
|
IN HANDLE hFileLog
|
|
)
|
|
{
|
|
STI_FILE_LOG* pStiFileLog = NULL;
|
|
|
|
pStiFileLog = static_cast<STI_FILE_LOG*>(hFileLog);
|
|
|
|
if (IsBadWritePtr(pStiFileLog,sizeof(STI_FILE_LOG)) ||
|
|
!pStiFileLog->IsValid()) {
|
|
::SetLastError(ERROR_INVALID_HANDLE);
|
|
return ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
delete pStiFileLog;
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
DWORD
|
|
WINAPI
|
|
ReportStiLogMessage(
|
|
IN HANDLE hFileLog,
|
|
IN DWORD dwType,
|
|
IN LPCTSTR psz,
|
|
...
|
|
)
|
|
{
|
|
STI_FILE_LOG* pStiFileLog = NULL;
|
|
|
|
pStiFileLog = static_cast<STI_FILE_LOG*>(hFileLog);
|
|
|
|
if (IsBadWritePtr(pStiFileLog,sizeof(STI_FILE_LOG)) ||
|
|
!pStiFileLog->IsValid()) {
|
|
::SetLastError(ERROR_INVALID_HANDLE);
|
|
return ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
va_list list;
|
|
|
|
va_start (list, psz);
|
|
|
|
pStiFileLog->vReportMessage(dwType,psz,list);
|
|
|
|
va_end(list);
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
/********************************* End of File ***************************/
|
|
|