mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1445 lines
38 KiB
1445 lines
38 KiB
//+----------------------------------------------------------------------------
|
|
//
|
|
// File: cmlog.cpp
|
|
//
|
|
// Module: CMLOG.LIB
|
|
//
|
|
// Synopsis: Connection Manager Logging File i/o class
|
|
//
|
|
// Copyright (c) 1998-2000 Microsoft Corporation
|
|
//
|
|
// Author: 25-May-2000 SumitC Created
|
|
//
|
|
// Note:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#define CMLOG_IMPLEMENTATION
|
|
#ifndef UNICODE
|
|
#define UNICODE
|
|
#endif
|
|
|
|
#include <windows.h>
|
|
#include <psapi.h>
|
|
#include <tlhelp32.h>
|
|
|
|
#include "cmmaster.h"
|
|
|
|
#include "CmLogStr.h"
|
|
#include "cmlog.h"
|
|
#include "cmlogutil.h"
|
|
|
|
#include "getmodulever.cpp"
|
|
|
|
//
|
|
// Constants
|
|
//
|
|
LPCTSTR c_szSep = TEXT("\\");
|
|
LPCTSTR c_szDotLog = TEXT(".log");
|
|
LPCTSTR c_szNewLine = TEXT("\r\n");
|
|
LPCTSTR c_szEmpty = TEXT("");
|
|
#define CHECKEMPTY(sz) ((sz) ? (sz) : c_szEmpty)
|
|
|
|
LPCTSTR c_szLineOfStars = TEXT("******************************************************************");
|
|
LPCTSTR c_szFieldSeparator = TEXT("\t");
|
|
|
|
//
|
|
// Byte order mark constant, written as the first two bytes to a Unicode file to mark it as such
|
|
//
|
|
const WCHAR c_wchBOM = BYTE_ORDER_MARK;
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
extern HINSTANCE g_hInst;
|
|
|
|
//
|
|
// utility macros
|
|
//
|
|
#define INBETWEEN(x, a, b) ( ( (x) >= (a) ) && ( (x) <= (b) ) )
|
|
|
|
//
|
|
// local function declarations
|
|
//
|
|
LPTSTR GetLogDesc(_CMLOG_ITEM eItem);
|
|
LPTSTR GetLogFormat(_CMLOG_ITEM eItem, BOOL fUnicode);
|
|
|
|
|
|
|
|
typedef struct _CM_LOG_ITEM_DESC
|
|
{
|
|
enum _CMLOG_ITEM eLogItem; // id of the log item (enum is in cmlog.h)
|
|
UINT idDesc; // resource id of the description string
|
|
UINT idFormat; // resource id of the format string used
|
|
}
|
|
CMLOGITEM;
|
|
|
|
//
|
|
//
|
|
// Array with information about each log entry. All logging is driven by this table.
|
|
// See above for column details.
|
|
//
|
|
//
|
|
static CMLOGITEM s_aCmLogItems[] =
|
|
{
|
|
{ LOGGING_ENABLED_EVENT, IDS_LOGDESC_LOGENABLED, 0 },
|
|
{ LOGGING_DISABLED_EVENT, IDS_LOGDESC_LOGDISABLED, 0 },
|
|
{ PREINIT_EVENT, IDS_LOGDESC_PREINIT, IDS_LOGFMT_PREINIT, },
|
|
{ PRECONNECT_EVENT, IDS_LOGDESC_PRECONNECT, IDS_LOGFMT_PRECONNECT },
|
|
{ PREDIAL_EVENT, IDS_LOGDESC_PREDIAL, IDS_LOGFMT_PREDIAL },
|
|
{ PRETUNNEL_EVENT, IDS_LOGDESC_PRETUNNEL, IDS_LOGFMT_PRETUNNEL },
|
|
{ CONNECT_EVENT, IDS_LOGDESC_CONNECT, 0 },
|
|
{ CUSTOMACTIONDLL, IDS_LOGDESC_CUSTOMACTIONDLL, IDS_LOGFMT_CUSTOMACTIONDLL },
|
|
{ CUSTOMACTIONEXE, IDS_LOGDESC_CUSTOMACTIONEXE, IDS_LOGFMT_CUSTOMACTIONEXE },
|
|
{ CUSTOMACTION_NOT_ALLOWED, IDS_LOGDESC_CUSTOMACTION_NOT_ALLOWED, IDS_LOGFMT_CUSTOMACTION_NOT_ALLOWED},
|
|
{ CUSTOMACTION_WONT_RUN, IDS_LOGDESC_CUSTOMACTION_WONT_RUN, IDS_LOGFMT_CUSTOMACTION_WONT_RUN},
|
|
{ DISCONNECT_EVENT, IDS_LOGDESC_DISCONNECT, IDS_LOGFMT_DISCONNECT },
|
|
{ RECONNECT_EVENT, IDS_LOGDESC_RECONNECT, 0 },
|
|
{ RETRY_AUTH_EVENT, IDS_LOGDESC_RETRYAUTH, 0 },
|
|
{ CALLBACK_NUMBER_EVENT, IDS_LOGDESC_CALLBACKNUMBER, IDS_LOGFMT_CALLBACKNUMBER },
|
|
{ PASSWORD_EXPIRED_EVENT, IDS_LOGDESC_PWDEXPIRED, IDS_LOGFMT_PWDEXPIRED },
|
|
{ PASSWORD_RESET_EVENT, IDS_LOGDESC_PWDRESET, IDS_LOGFMT_PWDRESET },
|
|
{ CUSTOM_BUTTON_EVENT, IDS_LOGDESC_CUSTOMBUTTON, 0 },
|
|
{ ONCANCEL_EVENT, IDS_LOGDESC_ONCANCEL, 0 },
|
|
{ ONERROR_EVENT, IDS_LOGDESC_ONERROR, IDS_LOGFMT_ONERROR },
|
|
{ CLEAR_LOG_EVENT, IDS_LOGDESC_CLEARLOG, 0 },
|
|
{ DISCONNECT_EXT, IDS_LOGDESC_EXT_DISCONNECT, 0 },
|
|
{ DISCONNECT_INT_MANUAL, IDS_LOGDESC_INT_DISCONNECT_MANUAL, 0 },
|
|
{ DISCONNECT_INT_AUTO, IDS_LOGDESC_INT_DISCONNECT_AUTO, 0 },
|
|
{ DISCONNECT_EXT_LOST_CONN, IDS_LOGDESC_EXT_DISCONNECT_LOST_CONN, 0 },
|
|
{ PB_DOWNLOAD_SUCCESS, IDS_LOGDESC_PB_DOWNLOAD_SUCCESS, IDS_LOGFMT_PB_DOWNLOAD_SUCCESS },
|
|
{ PB_DOWNLOAD_FAILURE, IDS_LOGDESC_PB_DOWNLOAD_FAILURE, IDS_LOGFMT_PB_DOWNLOAD_FAILURE },
|
|
{ PB_UPDATE_SUCCESS, IDS_LOGDESC_PB_UPDATE_SUCCESSFUL, IDS_LOGFMT_PB_UPDATE_SUCCESSFUL },
|
|
{ PB_UPDATE_FAILURE_PBS, IDS_LOGDESC_PB_UPDATE_FAILED_PBS, IDS_LOGFMT_PB_UPDATE_FAILED_PBS },
|
|
{ PB_UPDATE_FAILURE_CMPBK, IDS_LOGDESC_PB_UPDATE_FAILED_CMPBK, IDS_LOGFMT_PB_UPDATE_FAILED_CMPBK },
|
|
{ PB_ABORTED, IDS_LOGDESC_PB_ABORTED, 0 },
|
|
{ USER_FORMATTED, 0, 0 }
|
|
};
|
|
|
|
int s_cCmLogItems = sizeof(s_aCmLogItems) / sizeof(CMLOGITEM);
|
|
|
|
#define VERIFY_CMLOG_ITEM_OK(x) INBETWEEN(x, 1, s_cCmLogItems)
|
|
|
|
|
|
//
|
|
// Usage Note: Caller/User of logging must:
|
|
// p = new CmLogFile
|
|
// p->Init( instancehandle, fIsItAnAllUserProfile, "name of connectoid" )
|
|
// p->SetParams( ... the params ... )
|
|
// if (p->m_fEnabled)
|
|
// p->Start
|
|
// else
|
|
// p->Stop
|
|
//
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Func: CmLogFile::CmLogFile
|
|
//
|
|
// Desc: constructor
|
|
//
|
|
// Args: none
|
|
//
|
|
// Return: n/a
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 30-Apr-2000 SumitC Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
CmLogFile::CmLogFile()
|
|
{
|
|
m_fInitialized = FALSE;
|
|
|
|
m_hfile = NULL;
|
|
m_dwSize = 0;
|
|
m_pszServiceName = NULL;
|
|
m_szModule[0] = TEXT('\0');
|
|
m_pszLogFile = NULL;
|
|
|
|
m_dwMaxSize = 0;
|
|
m_fEnabled = FALSE;
|
|
m_pszLogFileDir = NULL;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Func: CmLogFile::~CmLogFile
|
|
//
|
|
// Desc: destructor
|
|
//
|
|
// Args: none
|
|
//
|
|
// Return: n/a
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 30-Apr-2000 SumitC Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
CmLogFile::~CmLogFile()
|
|
{
|
|
if (m_fInitialized)
|
|
{
|
|
DeInit();
|
|
}
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Func: CmLogFile::Init
|
|
//
|
|
// Desc: Initializes the CmLogFile object
|
|
//
|
|
// Args: [hInst] -- instance handle
|
|
// [fAllUser] -- is this an all user profile?
|
|
// [pszServiceName] -- long service name
|
|
//
|
|
// Return: HRESULT
|
|
//
|
|
// Notes: There are both Ansi and Unicode versions for this function
|
|
//
|
|
// History: 18-Jul-2000 SumitC Created
|
|
// 11-Apr-2001 SumitC Added Ansi version
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
CmLogFile::Init(HINSTANCE hInst, BOOL fAllUser, LPCSTR pszAnsiServiceName)
|
|
{
|
|
LPWSTR pszServiceName = SzToWzWithAlloc(pszAnsiServiceName);
|
|
|
|
HRESULT hr = pszServiceName ? Init(hInst, fAllUser, pszServiceName) : E_OUTOFMEMORY;
|
|
|
|
CmFree(pszServiceName);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CmLogFile::Init(HINSTANCE hInst, BOOL fAllUser, LPCWSTR pszServiceName)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// if m_fInitialized is already true, assert and exit
|
|
CMASSERTMSG(!m_fInitialized, TEXT("CmLogFile::Init - called twice"));
|
|
if (TRUE == m_fInitialized)
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
CMASSERTMSG(pszServiceName && pszServiceName[0], TEXT("CmLogFile::Init - invalid servicename, investigate"));
|
|
if ((NULL == pszServiceName) || (TEXT('\0') == pszServiceName[0]))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// set the args as member vars
|
|
m_fAllUser = fAllUser;
|
|
|
|
m_pszServiceName = CmStrCpyAlloc(pszServiceName);
|
|
if (NULL == m_pszServiceName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// store away the module name
|
|
//
|
|
if (FALSE == CmGetModuleBaseName(hInst, m_szModule))
|
|
{
|
|
lstrcpyU(m_szModule, TEXT("cm"));
|
|
}
|
|
|
|
// if all is well, set m_fInitialized to true
|
|
m_fInitialized = TRUE;
|
|
|
|
Cleanup:
|
|
CMTRACEHR(TEXT("CmLogFile::Init"), hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Func: CmLogFile::SetParams
|
|
//
|
|
// Desc: Read logging params from the CMS file
|
|
//
|
|
// Args: [fEnabled] -- is logging enabled?
|
|
// [dwMaxFileSize] -- maximum file size, in KB.
|
|
// [pszLogFileDir] -- put logging files in this dir.
|
|
//
|
|
// Return: HRESULT
|
|
//
|
|
// Notes: There are both Ansi and Unicode versions for this function
|
|
//
|
|
// History: 18-Jul-2000 SumitC Created
|
|
// 11-Apr-2001 SumitC Added Ansi version
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
CmLogFile::SetParams(BOOL fEnabled, DWORD dwMaxFileSize, LPCSTR pszAnsiLogFileDir)
|
|
{
|
|
LPWSTR pszLogFileDir = SzToWzWithAlloc(pszAnsiLogFileDir);
|
|
|
|
HRESULT hr = pszLogFileDir ? SetParams(fEnabled, dwMaxFileSize, pszLogFileDir) : E_OUTOFMEMORY;
|
|
|
|
CmFree(pszLogFileDir);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CmLogFile::SetParams(BOOL fEnabled, DWORD dwMaxFileSize, LPCWSTR pszLogFileDir)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPTSTR szUnexpanded = NULL;
|
|
CIni * pIni = NULL;
|
|
|
|
//
|
|
// logging must be stopped for this function to be called
|
|
//
|
|
CMASSERTMSG(NULL == m_hfile, TEXT("CmLogFile::SetParams - m_hfile must be null when this is called"));
|
|
if (m_hfile)
|
|
{
|
|
CMTRACE(TEXT("CmLogFile::SetParams was called during logging - must call Stop first"));
|
|
hr = E_UNEXPECTED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// EnableLogging (BOOL)
|
|
//
|
|
m_fEnabled = fEnabled;
|
|
|
|
//
|
|
// MaxFileSize (DWORD)
|
|
//
|
|
m_dwMaxSize = dwMaxFileSize;
|
|
if (0 == m_dwMaxSize)
|
|
{
|
|
m_dwMaxSize = c_dwMaxFileSize;
|
|
}
|
|
m_dwMaxSize *= 1024; // size was in KB, convert to bytes.
|
|
|
|
//
|
|
// FileDirectory (string)
|
|
//
|
|
if (CmStrStr(pszLogFileDir, TEXT("%")))
|
|
{
|
|
//
|
|
// now expand the string we have
|
|
//
|
|
|
|
LPTSTR sz = NULL;
|
|
DWORD cch = ExpandEnvironmentStringsU(pszLogFileDir, NULL, 0);
|
|
|
|
//
|
|
// if cch is zero, the pszLogFileDir string supplied is essentially bogus,
|
|
// i.e. it contains '%' indicating there's a macro to be expanded, but
|
|
// ExpandEnvironmentStrings can't expand it. Here we let m_pszLogFileDir
|
|
// be set to NULL (the logging code will then use the Temp dir.
|
|
//
|
|
if (cch)
|
|
{
|
|
sz = (LPTSTR) CmMalloc(cch * sizeof(TCHAR));
|
|
if (NULL == sz)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
if (cch != ExpandEnvironmentStringsU(pszLogFileDir, sz, cch))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
CmFree(sz);
|
|
goto Cleanup;
|
|
}
|
|
|
|
// success...
|
|
}
|
|
CmFree(m_pszLogFileDir);
|
|
m_pszLogFileDir = sz;
|
|
}
|
|
else
|
|
{
|
|
CmFree(m_pszLogFileDir);
|
|
if (pszLogFileDir)
|
|
{
|
|
m_pszLogFileDir = CmStrCpyAlloc(pszLogFileDir);
|
|
if (NULL == m_pszLogFileDir)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pszLogFileDir = NULL;
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
CMTRACEHR(TEXT("CmLogFile::SetParams"), hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Func: CmLogFile::Start
|
|
//
|
|
// Desc: Start logging
|
|
//
|
|
// Args: [fBanner] -- write a banner when starting
|
|
//
|
|
// Return: HRESULT
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 18-Jul-2000 SumitC Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
CmLogFile::Start(BOOL fBanner)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// if already started, or already Initialized, or not enabled, exit
|
|
CMASSERTMSG(!m_hfile, TEXT("CmLogFile::Start - already started!"));
|
|
CMASSERTMSG(m_fInitialized, TEXT("CmLogFile::Start - must be initialized"));
|
|
CMASSERTMSG(m_fEnabled, TEXT("CmLogFile::Start - must be enabled"));
|
|
if (NULL != m_hfile || FALSE == m_fInitialized || FALSE == m_fEnabled)
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// open log file
|
|
hr = OpenFile();
|
|
if (S_OK != hr)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
// set m_dwSize while doing so.
|
|
|
|
m_dwSize = GetFileSize(m_hfile, NULL);
|
|
if (DWORD(-1) == m_dwSize)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
m_dwSize = 0;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// no matter what the size of the file, we only clear an 'over the size limit'
|
|
// file at the start of a call. The fBanner param covers this.
|
|
//
|
|
if (fBanner)
|
|
{
|
|
// check file size, if over size Clear the file
|
|
if (m_dwSize > m_dwMaxSize)
|
|
{
|
|
Clear(); // this writes a banner as well
|
|
}
|
|
else
|
|
{
|
|
// log banner
|
|
Banner();
|
|
}
|
|
}
|
|
|
|
CMASSERTMSG(m_hfile, TEXT("CmLogFile::Start - at end of fn, m_hfile must be valid"));
|
|
|
|
Cleanup:
|
|
CMTRACEHR(TEXT("CmLogFile::Start"), hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Func: CmLogFile::Stop
|
|
//
|
|
// Desc: Stops logging
|
|
//
|
|
// Args: none
|
|
//
|
|
// Return: HRESULT
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 18-Jul-2000 SumitC Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
CmLogFile::Stop()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// if initialized is false, assert and exit
|
|
//
|
|
CMASSERTMSG(m_fInitialized, TEXT("CmLogFile::Stop - must be initialized"));
|
|
if (FALSE == m_fInitialized)
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// if already stopped, exit - nothing to do
|
|
//
|
|
if (NULL == m_hfile || FALSE == m_fEnabled)
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// end log and close file
|
|
//
|
|
CloseFile();
|
|
|
|
m_fEnabled = FALSE;
|
|
|
|
CMASSERTMSG(NULL == m_hfile, TEXT("CmLogFile::Stop - at end of fn, m_hfile must be NULL"));
|
|
|
|
Cleanup:
|
|
|
|
CMTRACEHR(TEXT("CmLogFile::Stop"), hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Func: CmLogFile::DeInit
|
|
//
|
|
// Desc: Uninitializes cm logging
|
|
//
|
|
// Args: none
|
|
//
|
|
// Return: HRESULT
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 18-Jul-2000 SumitC Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
CmLogFile::DeInit()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// if initialized is false, assert and exit
|
|
//
|
|
CMASSERTMSG(m_fInitialized, TEXT("CmLogFile::DeInit - must be initialized"));
|
|
if (FALSE == m_fInitialized)
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// end log and close file
|
|
//
|
|
CloseFile();
|
|
|
|
CmFree(m_pszServiceName);
|
|
m_pszServiceName = NULL;
|
|
CmFree(m_pszLogFileDir);
|
|
m_pszLogFileDir = NULL;
|
|
CmFree(m_pszLogFile);
|
|
m_pszLogFile = NULL;
|
|
|
|
m_fInitialized = FALSE;
|
|
|
|
Cleanup:
|
|
|
|
CMTRACEHR(TEXT("CmLogFile::DeInit"), hr);
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Func: CmLogFile::Log
|
|
//
|
|
// Desc: Logs a connection manager or connection point services event
|
|
//
|
|
// Args: [fUnicode] - are the args Unicode or ANSI?
|
|
// [eLogItem] - word containing source, type & description of log item
|
|
// [...] - optional args (depends on log item)
|
|
//
|
|
// Return: void
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 30-Apr-2000 SumitC Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
CmLogFile::Log(_CMLOG_ITEM eLogItem, ...)
|
|
{
|
|
TCHAR sz[2*MAX_PATH]; // REVIEW: Is this big enough? Could we dynamically allocate it?
|
|
LPTSTR pszTmp = NULL;
|
|
|
|
CMASSERTMSG(m_fInitialized, TEXT("CmLogFile::Log - must be initialized"));
|
|
CMASSERTMSG((m_hfile && m_fEnabled) || (!m_hfile && !m_fEnabled), TEXT("CmLogFile::Log - m_hfile and m_fenabled must be in sync"));
|
|
|
|
if (NULL == m_hfile || NULL == m_fEnabled)
|
|
{
|
|
// Start hasn't been called yet, or logging is disabled. Nothing to do.
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Verify that the log item is a valid one
|
|
//
|
|
CMASSERTMSG(VERIFY_CMLOG_ITEM_OK(eLogItem), TEXT("CmLogFile::Log - eItem must represent valid Log item"));
|
|
|
|
#if DBG
|
|
pszTmp = GetLogDesc(eLogItem);
|
|
CMTRACE2(TEXT("Logging item = %d, desc = %s"), eLogItem, CHECKEMPTY(pszTmp));
|
|
CmFree(pszTmp);
|
|
#endif
|
|
|
|
if (VERIFY_CMLOG_ITEM_OK(eLogItem))
|
|
{
|
|
switch (eLogItem)
|
|
{
|
|
case USER_FORMATTED:
|
|
va_list valArgs;
|
|
|
|
va_start(valArgs, eLogItem);
|
|
lstrcpyU(sz, va_arg(valArgs, LPTSTR));
|
|
FormatWrite(eLogItem, sz);
|
|
va_end(valArgs);
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// Format the arguments, and log the result
|
|
//
|
|
lstrcpyU(sz, c_szEmpty);
|
|
|
|
pszTmp = GetLogFormat(eLogItem, TRUE);
|
|
if (pszTmp)
|
|
{
|
|
va_list valArgs;
|
|
|
|
va_start(valArgs, eLogItem);
|
|
wvsprintfU(sz, pszTmp, valArgs);
|
|
CmFree(pszTmp);
|
|
FormatWrite(eLogItem, sz);
|
|
va_end(valArgs);
|
|
}
|
|
else
|
|
{
|
|
FormatWrite(eLogItem, NULL);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CMTRACE2(TEXT("Illegal CmLog entry %d (0x%x)"), eLogItem, eLogItem);
|
|
CMASSERTMSG(FALSE, TEXT("Illegal CmLog type - check trace, then edit code to fix"));
|
|
}
|
|
|
|
Cleanup:
|
|
;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Func: CmLogFile::Write
|
|
//
|
|
// Desc: Actually writes out the logged string (to debug console and logfile)
|
|
//
|
|
// Args: [szLog] - string to log
|
|
//
|
|
// Return: void
|
|
//
|
|
// Notes: *ALL* writes to the log file must be done using this function
|
|
//
|
|
// History: 30-Apr-2000 SumitC Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
CmLogFile::Write(LPTSTR szLog)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD cb = 0;
|
|
DWORD cbActuallyWritten = 0;
|
|
LPSTR szLogAnsi = NULL;
|
|
|
|
CMASSERTMSG(m_hfile, TEXT("CmLogFile::Write - m_hfile must be valid, check code"));
|
|
|
|
if (NULL == m_hfile)
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
#if 0
|
|
//
|
|
// Dump string to debug console as well
|
|
//
|
|
CMTRACE(szLog);
|
|
#endif
|
|
|
|
//
|
|
// Check for max size, open new log file if necessary
|
|
//
|
|
if (OS_NT)
|
|
{
|
|
cb = lstrlenW(szLog) * sizeof(TCHAR);
|
|
}
|
|
else
|
|
{
|
|
szLogAnsi = WzToSzWithAlloc(szLog);
|
|
cb = lstrlenA(szLogAnsi) * sizeof(CHAR);
|
|
}
|
|
|
|
#if 0
|
|
// I'm leaving this here, but for now logging will not terminate a log file
|
|
// during a log even if it goes past the max size.
|
|
//
|
|
if (m_dwSize + cb > m_dwMaxSize)
|
|
{
|
|
Clear();
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Write string to logfile
|
|
//
|
|
|
|
SetFilePointer(m_hfile, 0, NULL, FILE_END);
|
|
if (OS_NT)
|
|
{
|
|
WriteFile(m_hfile, szLog, cb, &cbActuallyWritten, 0);
|
|
}
|
|
else
|
|
{
|
|
WriteFile(m_hfile, szLogAnsi, cb, &cbActuallyWritten, 0);
|
|
}
|
|
|
|
if (cb != cbActuallyWritten)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
CMTRACE(TEXT("CMLOG: incomplete write to logfile"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
m_dwSize += cb;
|
|
|
|
Cleanup:
|
|
|
|
CmFree(szLogAnsi);
|
|
|
|
CMTRACEHR(TEXT("CmLogFile::Write"), hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Func: CmLogFile::FormatWrite
|
|
//
|
|
// Desc: Formats a log message with additional information and call Write fn
|
|
//
|
|
// Args: [eItem] - id of item being logged
|
|
// [szArgs] - string containing all the args.
|
|
//
|
|
// Return: void
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 30-Apr-2000 SumitC Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
CmLogFile::FormatWrite(_CMLOG_ITEM eItem, LPTSTR szArgs)
|
|
{
|
|
TCHAR szLog[2*MAX_PATH]; // REVIEW: Is this big enough? Could we dynamically allocate it?
|
|
TCHAR sz[2*MAX_PATH]; // REVIEW: Is this big enough? Could we dynamically allocate it?
|
|
|
|
CMASSERTMSG(VERIFY_CMLOG_ITEM_OK(eItem), TEXT("CmLogFile::FormatWrite - eItem must represent valid Log item"));
|
|
|
|
lstrcpyU(szLog, TEXT(""));
|
|
|
|
//
|
|
// Thread and Module name
|
|
//
|
|
TCHAR szModuleWithParens[11];
|
|
|
|
wsprintfU(szModuleWithParens, TEXT("[%s]"), m_szModule);
|
|
|
|
wsprintfU(sz, TEXT("%-10s%s"), szModuleWithParens, c_szFieldSeparator);
|
|
lstrcatU(szLog, sz);
|
|
|
|
//
|
|
// Time
|
|
//
|
|
LPTSTR pszTime = NULL;
|
|
|
|
CmGetDateTime(NULL, &pszTime);
|
|
if (pszTime)
|
|
{
|
|
lstrcatU(szLog, pszTime);
|
|
lstrcatU(szLog, c_szFieldSeparator);
|
|
CmFree(pszTime);
|
|
}
|
|
|
|
//
|
|
// Description
|
|
//
|
|
if (USER_FORMATTED == eItem)
|
|
{
|
|
wsprintfU(sz, TEXT("%02d%s%s\r\n"), eItem, c_szFieldSeparator, szArgs);
|
|
}
|
|
else
|
|
{
|
|
LPTSTR pszDesc = GetLogDesc(eItem);
|
|
if (szArgs)
|
|
{
|
|
wsprintfU(sz, TEXT("%02d%s%s%s%s\r\n"),
|
|
eItem, c_szFieldSeparator, CHECKEMPTY(pszDesc), c_szFieldSeparator, szArgs);
|
|
}
|
|
else
|
|
{
|
|
wsprintfU(sz, TEXT("%02d%s%s\r\n"),
|
|
eItem, c_szFieldSeparator, CHECKEMPTY(pszDesc));
|
|
}
|
|
CmFree(pszDesc);
|
|
}
|
|
|
|
lstrcatU(szLog, sz);
|
|
|
|
//
|
|
// Write it out...
|
|
//
|
|
Write(szLog);
|
|
}
|
|
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Func: CmLogFile::OpenFile
|
|
//
|
|
// Desc: Utility function to open the log file
|
|
//
|
|
// Args: none
|
|
//
|
|
// Return: HRESULT (S_OK for success, else error)
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 22-Jul-2000 SumitC Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
CmLogFile::OpenFile()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HANDLE hDir = NULL;
|
|
LPTSTR pszUsers = NULL;
|
|
BOOL fFileOpened = FALSE;
|
|
|
|
CMASSERTMSG(m_pszServiceName, TEXT("CmLogFile::OpenFile - m_pszServiceName must be valid"));
|
|
|
|
if (m_fAllUser)
|
|
{
|
|
// this is the more common case, so no suffix
|
|
pszUsers = CmStrCpyAlloc(TEXT(""));
|
|
}
|
|
else
|
|
{
|
|
LPTSTR pszTmp = CmLoadString(g_hInst, IDS_LOGSTR_SINGLEUSER);
|
|
if (pszTmp)
|
|
{
|
|
pszUsers = (LPTSTR) CmMalloc((lstrlenU(pszTmp) + 4) * sizeof(TCHAR));
|
|
if (pszUsers)
|
|
{
|
|
wsprintfU(pszUsers, TEXT(" (%s)"), pszTmp);
|
|
}
|
|
CmFree(pszTmp);
|
|
}
|
|
}
|
|
|
|
if (NULL == pszUsers)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
CMTRACE1(TEXT("CmLogFile::OpenFile - couldn't get Users strings, hr=%x"), hr);
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// To open a log file, we first try the location provided by the user. If
|
|
// that fails for whatever reason, we try GetTempPath. If that fails, no
|
|
// logging.
|
|
//
|
|
for (int i = 0; (i < 2) && (FALSE == fFileOpened); ++i)
|
|
{
|
|
TCHAR szBuf[2 * MAX_PATH];
|
|
|
|
CMTRACE1(TEXT("CmLogFile::OpenFile, iteration %d."), i + 1);
|
|
|
|
//
|
|
// get the directory name
|
|
//
|
|
switch (i)
|
|
{
|
|
case 0:
|
|
if (m_pszLogFileDir)
|
|
{
|
|
lstrcpyU(szBuf, m_pszLogFileDir);
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
if (0 == GetTempPathU(2 * MAX_PATH, szBuf))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
CMTRACE1(TEXT("GetTempPath failed with error 0x%x"), hr);
|
|
goto Cleanup;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
MYDBGASSERT(0);
|
|
goto Cleanup;
|
|
break;
|
|
}
|
|
|
|
CMTRACE1(TEXT("CmLogFile::OpenFile, directory name is %s"), szBuf);
|
|
|
|
//
|
|
// see if the directory exists, if not try to create it
|
|
//
|
|
DWORD dwAttrib = GetFileAttributesU(szBuf);
|
|
if (-1 == dwAttrib)
|
|
{
|
|
// directory does not exist
|
|
CMTRACE(TEXT("CmLogFile::OpenFile - directory does not exist, trying to create it"));
|
|
if (FALSE == CreateDirectoryU(szBuf, NULL))
|
|
{
|
|
DWORD dw = GetLastError();
|
|
|
|
if (ERROR_ALREADY_EXISTS != dw)
|
|
{
|
|
// real failure
|
|
hr = HRESULT_FROM_WIN32(dw);
|
|
CMTRACE2(TEXT("CmLogFile::OpenFile - Failed to create logging directory (%s), hr=%x"), szBuf, hr);
|
|
continue;
|
|
}
|
|
//
|
|
// On Win95/98, CreateDirectory fails with ERROR_ALREADY_EXISTS
|
|
// if the dir already exists. i.e. we have a dir, so keep going.
|
|
//
|
|
CMTRACE(TEXT("CmLogFile::OpenFile - directory created"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CMTRACE(TEXT("CmLogFile::OpenFile - directory already exists"));
|
|
|
|
if (0 == (FILE_ATTRIBUTE_DIRECTORY & dwAttrib))
|
|
{
|
|
// there is a file of that name
|
|
CMTRACE(TEXT("CmLogFile::OpenFile - there is a file of the same name as requested dir"));
|
|
hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
|
|
continue;
|
|
}
|
|
else if (FILE_ATTRIBUTE_READONLY & dwAttrib)
|
|
{
|
|
// the directory is readonly
|
|
CMTRACE(TEXT("CmLogFile::OpenFile - the directory is readonly"));
|
|
hr = E_ACCESSDENIED;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// the directory exists, try to create/open the logfile
|
|
//
|
|
if (*c_szSep != szBuf[lstrlenU(szBuf) - 1])
|
|
{
|
|
lstrcatU(szBuf, c_szSep);
|
|
}
|
|
lstrcatU(szBuf, m_pszServiceName);
|
|
lstrcatU(szBuf, pszUsers);
|
|
lstrcatU(szBuf, c_szDotLog);
|
|
|
|
m_hfile = CreateFileU(szBuf,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
//
|
|
// Since we asked for open existing, the file may just need to be created
|
|
//
|
|
if (INVALID_HANDLE_VALUE == m_hfile)
|
|
{
|
|
m_hfile = CreateFileU(szBuf,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
CREATE_NEW,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if ((INVALID_HANDLE_VALUE != m_hfile) && OS_NT)
|
|
{
|
|
//
|
|
// Set the Byte order mark on the file
|
|
//
|
|
DWORD cbActuallyWritten = 0;
|
|
|
|
WriteFile(m_hfile, &c_wchBOM, sizeof(c_wchBOM), &cbActuallyWritten, 0);
|
|
|
|
if (sizeof(c_wchBOM) != cbActuallyWritten)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
CMTRACE(TEXT("CMLOG: Unable to set the Byte order mark while opening the file"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
m_dwSize += sizeof(c_wchBOM);
|
|
}
|
|
}
|
|
|
|
if (INVALID_HANDLE_VALUE == m_hfile)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
CMTRACE2(TEXT("CmLogFile::OpenFile - Failed to open log file in dir %s with error 0x%x"), szBuf, hr);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Success!!
|
|
//
|
|
CmFree(m_pszLogFile);
|
|
m_pszLogFile = CmStrCpyAlloc(szBuf);
|
|
if (NULL == m_pszLogFile)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
hr = S_OK;
|
|
fFileOpened = TRUE;
|
|
}
|
|
|
|
#if DBG
|
|
if (S_OK == hr)
|
|
{
|
|
CMASSERTMSG(m_hfile, TEXT("CmLogFile::OpenFile - at end. m_hfile must be valid here"));
|
|
}
|
|
#endif
|
|
|
|
Cleanup:
|
|
|
|
CmFree(pszUsers);
|
|
|
|
CMTRACEHR(TEXT("CmLogFile::OpenFile"), hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Func: CmLogFile::CloseFile
|
|
//
|
|
// Desc: Closes the logging file
|
|
//
|
|
// Args: none
|
|
//
|
|
// Return: HRESULT
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 30-Apr-2000 SumitC Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
CmLogFile::CloseFile()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_hfile)
|
|
{
|
|
//
|
|
// Close the file
|
|
//
|
|
FlushFileBuffers(m_hfile);
|
|
CloseHandle(m_hfile);
|
|
m_hfile = NULL;
|
|
}
|
|
|
|
CMTRACEHR(TEXT("CmLogFile::CloseFile"), hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Func: CmLogFile::Clear
|
|
//
|
|
// Desc: Clears (resets) the logging file
|
|
//
|
|
// Args: [fWriteBannerAfterwards] -- after clearing, write the banner?
|
|
//
|
|
// Return: void
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 17-Jul-2000 SumitC Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
CmLogFile::Clear(BOOL fWriteBannerAfterwards)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL fWasDisabled = FALSE;
|
|
|
|
if (NULL == m_hfile)
|
|
{
|
|
fWasDisabled = TRUE; // if called when logging is disabled, we still clear the log file
|
|
|
|
hr = OpenFile();
|
|
if (S_OK != hr)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
//
|
|
// make sure everything gets written out (ignore errors for this one)
|
|
//
|
|
FlushFileBuffers(m_hfile);
|
|
|
|
//
|
|
// clear the file (set fileptr to the start, then set EOF to that).
|
|
//
|
|
if (INVALID_SET_FILE_POINTER == SetFilePointer(m_hfile, 0, NULL, FILE_BEGIN))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (FALSE == SetEndOfFile(m_hfile))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Cleanup;
|
|
}
|
|
|
|
m_dwSize = 0;
|
|
|
|
CMTRACE(TEXT("CmLogFile::Clear - cleared log file"));
|
|
|
|
//
|
|
// If this is NT and thus a Unicode file, we need to set the Byte order mark
|
|
//
|
|
if (OS_NT)
|
|
{
|
|
if ((INVALID_HANDLE_VALUE != m_hfile) && OS_NT)
|
|
{
|
|
//
|
|
// Set the Byte order mark on the file
|
|
//
|
|
DWORD cbActuallyWritten = 0;
|
|
|
|
WriteFile(m_hfile, &c_wchBOM, sizeof(c_wchBOM), &cbActuallyWritten, 0);
|
|
|
|
if (sizeof(c_wchBOM) != cbActuallyWritten)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
CMTRACE(TEXT("CMLOG: Unable to set the Byte order mark while clearing the file"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
m_dwSize += sizeof(c_wchBOM);
|
|
}
|
|
}
|
|
|
|
if (fWriteBannerAfterwards)
|
|
{
|
|
Banner();
|
|
}
|
|
|
|
if (fWasDisabled)
|
|
{
|
|
CloseFile();
|
|
}
|
|
|
|
Cleanup:
|
|
CMTRACEHR(TEXT("CmLogFile::Clear"), hr);
|
|
return;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Func: CmLogFile::Banner
|
|
//
|
|
// Desc: Logs the banner heading for a Connection Manager log
|
|
//
|
|
// Args: none
|
|
//
|
|
// Return: void
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 30-Apr-2000 SumitC Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
CmLogFile::Banner()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPTSTR psz = NULL;
|
|
|
|
if (NULL == m_hfile)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// System information, Process, Time
|
|
//
|
|
OSVERSIONINFO VersionInfo;
|
|
LPTSTR pszPlatform = TEXT("NT");
|
|
|
|
ZeroMemory(&VersionInfo, sizeof(VersionInfo));
|
|
VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
|
|
GetVersionExU(&VersionInfo);
|
|
|
|
if (VER_PLATFORM_WIN32_WINDOWS == VersionInfo.dwPlatformId)
|
|
{
|
|
pszPlatform = TEXT("9x");
|
|
}
|
|
else if (VER_PLATFORM_WIN32_NT == VersionInfo.dwPlatformId)
|
|
{
|
|
pszPlatform = TEXT("NT");
|
|
}
|
|
else
|
|
{
|
|
CMASSERTMSG(0, TEXT("CmLogFile::Banner - platform ID is not Windows or NT"));
|
|
}
|
|
|
|
//
|
|
// Connection Manager version number (using cmdial32.dll)
|
|
//
|
|
DWORD dwCMVer = 0;
|
|
DWORD dwCMBuild = 0;
|
|
DWORD dwLCID = 0;
|
|
TCHAR szModulePath[MAX_PATH + 1];
|
|
UINT uRet = 0;
|
|
|
|
uRet = GetSystemDirectoryU(szModulePath, MAX_PATH);
|
|
if (0 == uRet)
|
|
{
|
|
CMTRACE1(TEXT("CmLogFile::Banner - GetSystemDirectoryU failed, GLE=%d"), GetLastError());
|
|
}
|
|
else
|
|
{
|
|
const LPTSTR c_pszCmdial32 = TEXT("\\cmdial32.dll");
|
|
|
|
if ((uRet + lstrlenU(c_pszCmdial32) + 1) <= MAX_PATH)
|
|
{
|
|
lstrcatU(szModulePath, c_pszCmdial32);
|
|
|
|
hr = GetModuleVersionAndLCID(szModulePath, &dwCMVer, &dwCMBuild, &dwLCID);
|
|
if (FAILED(hr))
|
|
{
|
|
CMTRACE1(TEXT("CmLogFile::Banner - couldn't get CM version, hr=%x"), hr);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Date & Time
|
|
//
|
|
|
|
LPTSTR pszDate = NULL;
|
|
LPTSTR pszTime = NULL;
|
|
|
|
CmGetDateTime(&pszDate, &pszTime);
|
|
// strings can be NULL, but we handle that when using them (below)
|
|
|
|
LPTSTR pszFmt = CmLoadString(g_hInst, IDS_LOGFMT_BANNER);
|
|
LPTSTR pszUsers = CmLoadString(g_hInst,
|
|
m_fAllUser ? IDS_LOGSTR_ALLUSERS : IDS_LOGSTR_SINGLEUSER);
|
|
|
|
if (pszFmt && pszUsers)
|
|
{
|
|
UINT cch = lstrlenU(pszFmt) +
|
|
1 +
|
|
(3 * lstrlenU(c_szLineOfStars)) + // occurs thrice total
|
|
lstrlenU(pszPlatform) +
|
|
(6 * 10) + // how big can a DWORD get
|
|
lstrlenU(VersionInfo.szCSDVersion) +
|
|
lstrlenU(m_pszServiceName) +
|
|
lstrlenU(pszUsers) +
|
|
(pszDate ? lstrlenU(pszDate) : 0) +
|
|
(pszTime ? lstrlenU(pszTime) : 0) +
|
|
1;
|
|
|
|
psz = (LPTSTR) CmMalloc(cch * sizeof(TCHAR));
|
|
CMASSERTMSG(psz, TEXT("CmLogFile::Banner - couldn't log banner, malloc failed"));
|
|
if (psz)
|
|
{
|
|
//
|
|
// Unicode logfiles are marked as such using a byte order mark, which
|
|
// means that to check for an "empty" file we have to account for the
|
|
// presence of the BOM.
|
|
//
|
|
BOOL fFileIsEmpty = (m_dwSize == (OS_NT ? sizeof(c_wchBOM) : 0));
|
|
|
|
wsprintfU(psz, pszFmt,
|
|
fFileIsEmpty ? c_szEmpty : c_szNewLine, // don't start with a newline if the file is empty
|
|
c_szLineOfStars,
|
|
pszPlatform,
|
|
VersionInfo.dwMajorVersion, VersionInfo.dwMinorVersion, VersionInfo.szCSDVersion,
|
|
HIWORD(dwCMVer), LOWORD(dwCMVer), HIWORD(dwCMBuild), LOWORD(dwCMBuild),
|
|
m_pszServiceName,
|
|
pszUsers,
|
|
(pszDate ? pszDate : TEXT("")),
|
|
(pszTime ? pszTime : TEXT("")),
|
|
c_szLineOfStars,
|
|
c_szLineOfStars);
|
|
|
|
CMTRACE(TEXT("CmLogFile::Banner - wrote banner"));
|
|
}
|
|
}
|
|
|
|
CmFree(pszFmt);
|
|
CmFree(pszUsers);
|
|
CmFree(pszDate);
|
|
CmFree(pszTime);
|
|
|
|
//
|
|
// Write it out...
|
|
//
|
|
if (psz)
|
|
{
|
|
Write(psz);
|
|
CmFree(psz);
|
|
}
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Func: GetLogDesc
|
|
//
|
|
// Desc: Utility function, returns log item friendly name (desc)
|
|
//
|
|
// Args: [eItem] - the log item about which to return information
|
|
//
|
|
// Return: LPTSTR if found, or NULL if not
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 30-Apr-2000 SumitC Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
LPTSTR
|
|
GetLogDesc(_CMLOG_ITEM eItem)
|
|
{
|
|
CMASSERTMSG(VERIFY_CMLOG_ITEM_OK(eItem), TEXT("GetLogDesc - eItem must represent valid Log item"));
|
|
|
|
return CmLoadString(g_hInst, s_aCmLogItems[eItem - 1].idDesc);
|
|
}
|
|
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Func: GetLogFormat
|
|
//
|
|
// Desc: Utility function, returns log item Format
|
|
//
|
|
// Args: [eItem] - the log item about which to return information
|
|
// [fUnicode] - is the caller unicode?
|
|
//
|
|
// Return: LPTSTR if found, or NULL if not
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 30-Apr-2000 SumitC Created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
LPTSTR
|
|
GetLogFormat(_CMLOG_ITEM eItem, BOOL fUnicode)
|
|
{
|
|
CMASSERTMSG(VERIFY_CMLOG_ITEM_OK(eItem), TEXT("GetLogFormat - eItem must represent valid Log item"));
|
|
|
|
CMASSERTMSG(fUnicode, TEXT("GetLogFormat - currently cmlog is only being compiled unicode"));
|
|
|
|
LPTSTR pszFmt = CmLoadString(g_hInst, s_aCmLogItems[eItem - 1].idFormat);
|
|
|
|
if (0 == lstrcmpU(TEXT(""), pszFmt))
|
|
{
|
|
// NOTE: CmLoadString has a rather broken implementation where it decides
|
|
// to return empty strings in case of failure. This is a problem
|
|
// because (a) it makes it impossible to detect an actual failure,
|
|
// as opposed to an empty string, and and (b) it uses an alloc within
|
|
// a return statement, so it can fail anyway. This 'if' block
|
|
// gives me back a NULL so that my code can work the way it should.
|
|
CmFree(pszFmt);
|
|
return NULL;
|
|
}
|
|
else if (pszFmt)
|
|
{
|
|
// If the module is compiled unicode, then fUnicode=false requires conversion.
|
|
// If the module is compiled ANSI, then fUnicode=true requires conversion.
|
|
|
|
#if 0 // since we're compiled Unicode for now
|
|
#ifdef UNICODE
|
|
if (!fUnicode)
|
|
{
|
|
if (FALSE == ConvertFormatString(pszFmt))
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
#else
|
|
if (fUnicode)
|
|
{
|
|
if (FALSE == ConvertFormatString(pszFmt))
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
#endif
|
|
#endif // 0
|
|
return pszFmt;
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
#undef CMLOG_IMPLEMENTATION
|