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.
683 lines
22 KiB
683 lines
22 KiB
/*++
|
|
|
|
Module Name:
|
|
|
|
psslog.c
|
|
|
|
Abstract:
|
|
|
|
Implementation of the fax service provider PSS log.
|
|
|
|
Author:
|
|
|
|
Jonathan Barner (t-jonb) Feb, 2001
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "prep.h"
|
|
#include "faxreg.h"
|
|
#include "t30gl.h" // for T30CritSection
|
|
#include <time.h>
|
|
|
|
#include "psslog.h"
|
|
|
|
|
|
/*++
|
|
Routine Description:
|
|
Prints the log file header. It assumes that the log file is already open. On any
|
|
unrecoverable error, the function closes the log file and falls back to no logging.
|
|
|
|
Arguments:
|
|
pTG
|
|
szDeviceName - pointer to device name to be included in the header
|
|
|
|
Return Value:
|
|
None
|
|
--*/
|
|
#define LOG_HEADER_LINE_LEN 256
|
|
#define LOG_MAX_DATE 256
|
|
|
|
void PrintPSSLogHeader(PThrdGlbl pTG, LPSTR szDeviceName)
|
|
{
|
|
TCHAR szHeader[LOG_HEADER_LINE_LEN*6] = {'\0'}; // Room for 6 lines
|
|
TCHAR szDate[LOG_MAX_DATE] = {'\0'};
|
|
int iDateRet = 0;
|
|
LPSTR lpszUnimodemKeyEnd = NULL;
|
|
DWORD dwCharIndex = 0;
|
|
DWORD dwNumCharsWritten = 0;
|
|
TCHAR szTimeBuff[10] = {'\0'}; // _tstrtime requires 9 chars
|
|
BOOL fRet = FALSE;
|
|
DEBUG_FUNCTION_NAME(_T("PrintPSSLogHeader"));
|
|
|
|
iDateRet = GetY2KCompliantDate (LOCALE_USER_DEFAULT,
|
|
0,
|
|
NULL,
|
|
szDate,
|
|
LOG_MAX_DATE);
|
|
if (0 == iDateRet)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, "GetY2KCompliantDate failed, LastError = %d, date will not be logged", GetLastError());
|
|
szDate[0] = '\0'; // We continue with a blank date
|
|
}
|
|
|
|
dwCharIndex += _stprintf(&szHeader[dwCharIndex],
|
|
TEXT("[%s %-8s]\r\n"), szDate, _tstrtime(szTimeBuff));
|
|
dwCharIndex += _stprintf(&szHeader[dwCharIndex],
|
|
TEXT("Device name: %s\r\n"), szDeviceName);
|
|
dwCharIndex += _stprintf(&szHeader[dwCharIndex],
|
|
TEXT("Permanent TAPI line ID: %8X\r\n"), pTG->dwPermanentLineID);
|
|
|
|
lpszUnimodemKeyEnd = _tcsrchr(pTG->lpszUnimodemKey, _TEXT('\\'));
|
|
if (NULL == lpszUnimodemKeyEnd)
|
|
{
|
|
lpszUnimodemKeyEnd = _TEXT("");
|
|
}
|
|
else
|
|
{
|
|
lpszUnimodemKeyEnd++; // skip the actual '\'
|
|
}
|
|
dwCharIndex += _stprintf(&szHeader[dwCharIndex],
|
|
TEXT("Unimodem registry key: %s\r\n"), lpszUnimodemKeyEnd);
|
|
|
|
dwCharIndex += _stprintf(&szHeader[dwCharIndex],
|
|
TEXT("Job type: %s\r\n"), (pTG->Operation==T30_TX) ? TEXT("Send") : TEXT("Receive") );
|
|
|
|
// blank line after header
|
|
dwCharIndex += _stprintf(&szHeader[dwCharIndex],
|
|
TEXT("\r\n"));
|
|
|
|
fRet = WriteFile(pTG->hPSSLogFile,
|
|
szHeader,
|
|
dwCharIndex * sizeof(szHeader[0]),
|
|
&dwNumCharsWritten,
|
|
NULL);
|
|
if (FALSE == fRet)
|
|
{
|
|
DebugPrintEx(DEBUG_WRN,"Can't write log header, LastError = %d", GetLastError());
|
|
}
|
|
else
|
|
{
|
|
pTG->dwCurrentFileSize += dwNumCharsWritten;
|
|
// Not checking for size here - I assume that MaxLogFileSize is enough for the header!
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
Routine Description:
|
|
Reads from the registry whether logging should be enabled. If it should, determines
|
|
the logging folder, creates it if it doesn't exist, creates a temporary filename for
|
|
the log file, and creates the file. On any unrecoverable error, falls back to no
|
|
logging.
|
|
Upon exit, if pTG->dwLoggingEnabled==0, there will be no logging.
|
|
|
|
Arguments:
|
|
pTG
|
|
szDeviceName [in] - Pointer to device name to be included in the header
|
|
note: this value is never saved in ThreadGlobal, which
|
|
is why it is passed as a parameter.
|
|
Return Value:
|
|
None
|
|
--*/
|
|
void OpenPSSLogFile(PThrdGlbl pTG, LPSTR szDeviceName)
|
|
{
|
|
HKEY hKey = NULL;
|
|
BOOL fEnteredCriticalSection = FALSE;
|
|
LPTSTR lpszLoggingFolder = NULL; // Logging folder, read from the registry and expanded
|
|
// Another thread can call PSSLogEntry while this function is running
|
|
// So, use a private flag for LoggingEnabled, and set pTG->dwLoggingEnabled
|
|
// Only after pTG->hPSSLogFile is valid.
|
|
DWORD dwLoggingEnabled = PSSLOG_NONE;
|
|
|
|
DEBUG_FUNCTION_NAME(_T("OpenPSSLogFile"));
|
|
|
|
_ASSERT(NULL==pTG->hPSSLogFile && PSSLOG_NONE==pTG->LoggingEnabled);
|
|
|
|
hKey=OpenRegistryKey(HKEY_LOCAL_MACHINE,
|
|
REGKEY_DEVICE_PROVIDER_KEY TEXT("\\") REGVAL_T30_PROVIDER_GUID_STRING,
|
|
FALSE,
|
|
KEY_READ | KEY_WRITE);
|
|
if (!hKey)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, "OpenRegistryKey failed, ec=%d", GetLastError());
|
|
goto exit;
|
|
}
|
|
|
|
// Using T30CritSection to ensure atomic read and write of the registry
|
|
// also for creating the logging folder and choosing a temp filename
|
|
EnterCriticalSection(&T30CritSection);
|
|
fEnteredCriticalSection = TRUE;
|
|
|
|
if (!GetRegistryDwordDefault(hKey, REGVAL_LOGGINGENABLED, &dwLoggingEnabled, PSSLOG_FAILED_ONLY))
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, "GetRegistryDwordDefault failed, LastError = %d", GetLastError());
|
|
dwLoggingEnabled = PSSLOG_NONE;
|
|
goto exit;
|
|
}
|
|
|
|
if (dwLoggingEnabled != PSSLOG_NONE)
|
|
{
|
|
if (!GetRegistryDwordDefault(hKey, REGVAL_MAXLOGFILESIZE, &(pTG->dwMaxLogFileSize), DEFAULT_MAXLOGFILESIZE))
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, "GetRegistryDwordDefault failed, LastError = %d", GetLastError());
|
|
dwLoggingEnabled = PSSLOG_NONE;
|
|
goto exit;
|
|
}
|
|
|
|
lpszLoggingFolder = GetRegistryStringExpand(hKey, (pTG->Operation==T30_TX) ? REGVAL_LOGGINGFOLDER_OUTGOING : REGVAL_LOGGINGFOLDER_INCOMING, NULL);
|
|
if (!lpszLoggingFolder)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, "GetRegistryStringExpand failed");
|
|
dwLoggingEnabled = PSSLOG_NONE;
|
|
goto exit;
|
|
}
|
|
|
|
|
|
// Generate a temporary filename for the log file
|
|
if (!GetTempFileName(lpszLoggingFolder, TEXT("FSP"), 0, pTG->szLogFileName))
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, "GetTempFileName(%s) failed, ec=%d", lpszLoggingFolder, GetLastError());
|
|
dwLoggingEnabled = PSSLOG_NONE;
|
|
goto exit;
|
|
}
|
|
|
|
DebugPrintEx(DEBUG_MSG, "Creating log file %s, MaxLogFileSize=%d", pTG->szLogFileName, pTG->dwMaxLogFileSize);
|
|
|
|
// Create the file
|
|
pTG->hPSSLogFile = CreateFile(pTG->szLogFileName,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
if (INVALID_HANDLE_VALUE == pTG->hPSSLogFile)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, "Can't create log file, LastError = %d", GetLastError());
|
|
dwLoggingEnabled = PSSLOG_NONE;
|
|
pTG->hPSSLogFile = NULL;
|
|
goto exit;
|
|
}
|
|
|
|
pTG->dwLoggingEnabled = dwLoggingEnabled;
|
|
pTG->dwCurrentFileSize = 0;
|
|
}
|
|
|
|
exit:
|
|
if (fEnteredCriticalSection)
|
|
{
|
|
LeaveCriticalSection(&T30CritSection);
|
|
fEnteredCriticalSection = FALSE;
|
|
}
|
|
|
|
if (lpszLoggingFolder)
|
|
{
|
|
MemFree(lpszLoggingFolder);
|
|
lpszLoggingFolder = NULL;
|
|
}
|
|
|
|
if (NULL != hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
hKey = NULL;
|
|
}
|
|
|
|
if (PSSLOG_NONE != pTG->dwLoggingEnabled)
|
|
{
|
|
PrintPSSLogHeader(pTG, szDeviceName);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
Routine Description:
|
|
Closes the log file. If the file needs to be kept, reads LogFileNumber, advances
|
|
it, generates a permanent name, and renames the temp log file to the permanent name.
|
|
|
|
Arguments:
|
|
pTG
|
|
RetCode [in] - Whether the call succeeded or failed. This is used when determining
|
|
whether to keep the log or delete it.
|
|
|
|
Return Value:
|
|
None
|
|
--*/
|
|
void ClosePSSLogFile(PThrdGlbl pTG, BOOL RetCode)
|
|
{
|
|
LONG lError=0;
|
|
HKEY hKey = NULL;
|
|
LPCSTR lpszRegValLogFileNumber = NULL;
|
|
|
|
DWORD dwLoggingEnabled = pTG->dwLoggingEnabled;
|
|
DWORD dwMaxLogFileCount=0;
|
|
DWORD dwLogFileNumber=0;
|
|
DWORD dwNextLogFileNumber=0;
|
|
TCHAR szFinalLogFileName[MAX_PATH]={TEXT('\0')};
|
|
BOOL fKeepFile = FALSE;
|
|
|
|
DEBUG_FUNCTION_NAME(_T("ClosePSSLogFile"));
|
|
|
|
if (PSSLOG_NONE == pTG->dwLoggingEnabled)
|
|
{
|
|
// There was no log - nothing to do!
|
|
return;
|
|
}
|
|
|
|
pTG->dwLoggingEnabled = PSSLOG_NONE;
|
|
CloseHandle(pTG->hPSSLogFile);
|
|
pTG->hPSSLogFile = NULL;
|
|
|
|
switch (dwLoggingEnabled)
|
|
{
|
|
case PSSLOG_ALL: DebugPrintEx(DEBUG_MSG, "LoggingEnabled=1, keeping file");
|
|
fKeepFile = TRUE;
|
|
break;
|
|
case PSSLOG_FAILED_ONLY:
|
|
default:
|
|
fKeepFile = ((!RetCode) && (pTG->fReceivedHDLCflags));
|
|
DebugPrintEx(DEBUG_MSG, "LoggingEnabled=2, RetCode=%d, fReceivedHDLCflags=%d, %s file",
|
|
RetCode, pTG->fReceivedHDLCflags, fKeepFile ? "keeping" : "deleting");
|
|
break;
|
|
}
|
|
|
|
if (fKeepFile)
|
|
{
|
|
hKey=OpenRegistryKey(HKEY_LOCAL_MACHINE,
|
|
REGKEY_DEVICE_PROVIDER_KEY TEXT("\\") REGVAL_T30_PROVIDER_GUID_STRING,
|
|
FALSE,
|
|
0);
|
|
if (!hKey)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, "OpenRegistryKey failed, ec=%d", GetLastError());
|
|
goto exit;
|
|
}
|
|
|
|
// Using T30CritSection to ensure atomic read and write of the registry
|
|
EnterCriticalSection(&T30CritSection);
|
|
|
|
// Read MaxLogFileCount, with SKU-dependant default
|
|
if (!GetRegistryDwordDefault(hKey, REGVAL_MAXLOGFILECOUNT, &dwMaxLogFileCount,
|
|
IsDesktopSKU() ? DEFAULT_MAXLOGFILECOUNT_CLIENT : DEFAULT_MAXLOGFILECOUNT_SERVER))
|
|
{
|
|
DebugPrintEx(DEBUG_WRN, "GetRegistryDwordDefault(%s) failed, ec=%d",
|
|
REGVAL_MAXLOGFILECOUNT, GetLastError());
|
|
LeaveCriticalSection(&T30CritSection);
|
|
goto exit;
|
|
}
|
|
|
|
// Decide whether to use LogFileNumberOutgoing or LogFileNumberIncoming
|
|
lpszRegValLogFileNumber = (pTG->Operation==T30_TX) ? REGVAL_LOGFILENUMBEROUTGOING : REGVAL_LOGFILENUMBERINCOMING;
|
|
|
|
if (!GetRegistryDwordDefault(hKey, lpszRegValLogFileNumber, &dwLogFileNumber, 0))
|
|
{
|
|
DebugPrintEx(DEBUG_WRN, "GetRegistryDwordDefault(%s) failed, ec=%d",
|
|
lpszRegValLogFileNumber, GetLastError());
|
|
LeaveCriticalSection(&T30CritSection);
|
|
goto exit;
|
|
}
|
|
|
|
// Advance LogFileNumber to the next number, with rollover
|
|
dwNextLogFileNumber = dwLogFileNumber+1;
|
|
if (dwNextLogFileNumber >= dwMaxLogFileCount)
|
|
{
|
|
dwNextLogFileNumber = 0;
|
|
}
|
|
|
|
lError = RegSetValueEx(hKey,
|
|
lpszRegValLogFileNumber,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&dwNextLogFileNumber,
|
|
sizeof(DWORD));
|
|
if (lError != ERROR_SUCCESS)
|
|
{
|
|
DebugPrintEx(DEBUG_WRN, "Failed to set registry value %s, lError=%d",
|
|
lpszRegValLogFileNumber, lError);
|
|
LeaveCriticalSection(&T30CritSection);
|
|
goto exit;
|
|
}
|
|
|
|
LeaveCriticalSection(&T30CritSection);
|
|
|
|
// Create final filename
|
|
{
|
|
TCHAR drive[_MAX_DRIVE];
|
|
TCHAR dir[_MAX_DIR];
|
|
TCHAR fname[_MAX_FNAME] = {0};
|
|
TCHAR ext[_MAX_EXT];
|
|
|
|
_splitpath(pTG->szLogFileName, drive, dir, fname, ext);
|
|
_sntprintf(fname,
|
|
ARR_SIZE(fname)-1,
|
|
TEXT("FSP%c%04d"),
|
|
(pTG->Operation==T30_TX) ? TEXT('S') : TEXT('R'),
|
|
dwLogFileNumber);
|
|
_makepath(szFinalLogFileName, drive, dir, fname, TEXT("log"));
|
|
}
|
|
DebugPrintEx(DEBUG_MSG, "Final log filename is %s", szFinalLogFileName);
|
|
|
|
if (!MoveFileEx(pTG->szLogFileName, szFinalLogFileName, MOVEFILE_REPLACE_EXISTING))
|
|
{
|
|
DebugPrintEx(DEBUG_WRN, "MoveFileEx failed, ec=%d", GetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!DeleteFile(pTG->szLogFileName))
|
|
{
|
|
DebugPrintEx(DEBUG_WRN, "Failed to delete %s, le=%d", pTG->szLogFileName, GetLastError());
|
|
}
|
|
}
|
|
|
|
exit:
|
|
if (NULL != hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
hKey = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/*++
|
|
Routine Description:
|
|
Delete all '\n' and '\r' from a string.
|
|
Arguments:
|
|
szDest - [out] pointer to output string
|
|
szSource - [in] pointer to input string
|
|
Return Value:
|
|
Length of new string, in TCHARs
|
|
Note: szDest and szSource can be the same string.
|
|
--*/
|
|
int CopyStrNoNewLines(LPSTR szDest, LPCSTR szSource)
|
|
{
|
|
int iCharRead = 0, iCharWrite = 0;
|
|
while (szSource[iCharRead] != '\0')
|
|
{
|
|
if (szSource[iCharRead]!='\n' && szSource[iCharRead]!='\r')
|
|
{
|
|
szDest[iCharWrite] = szSource[iCharRead];
|
|
iCharWrite++;
|
|
}
|
|
iCharRead++;
|
|
}
|
|
szDest[iCharWrite] = '\0';
|
|
return iCharWrite;
|
|
}
|
|
|
|
|
|
#define MAX_LOG_FILE_SIZE_MESSAGE TEXT("-------- Maximum log file size reached --------\r\n")
|
|
|
|
#define MAX_MESSAGE_LEN 2048
|
|
#define INDENT_LEN 12
|
|
#define HEADER_LEN 38
|
|
/*++
|
|
Routine Description:
|
|
Add an entry to the log, if logging is enabled. If disabled, do nothing.
|
|
|
|
Arguments:
|
|
pTG
|
|
nMessageType - message type (PSS_MSG_ERR, PSS_MSG_WRN, PSS_MSG_MSG)
|
|
dwFileID - File ID, as set in the beginning of every file by #define FILE_ID
|
|
dwLine - Line number
|
|
dwIndent - Indent level in "tabs" (0 - leftmost)
|
|
pcszFormat - Message text, with any format specifiers
|
|
... - Arguments for message format
|
|
Return Value:
|
|
None
|
|
--*/
|
|
void PSSLogEntry(
|
|
PThrdGlbl pTG,
|
|
PSS_MESSAGE_TYPE const nMessageType,
|
|
DWORD const dwFileID,
|
|
DWORD const dwLine,
|
|
DWORD dwIndent,
|
|
LPCTSTR pcszFormat,
|
|
... )
|
|
{
|
|
TCHAR pcszMessage[MAX_MESSAGE_LEN] = {'\0'};
|
|
va_list arg_ptr = NULL;
|
|
LPTSTR lptstrMsgPrefix = NULL;
|
|
TCHAR szTimeBuff[10] = {'\0'};
|
|
int iHeaderIndex = 0;
|
|
int iMessageIndex = 0;
|
|
DWORD dwBytesWritten = 0;
|
|
BOOL fRet = FALSE;
|
|
|
|
// DEBUG_FUNCTION_NAME(_T("PSSLogEntry"));
|
|
// hack: Want only one line in T30DebugLogFile
|
|
#ifdef ENABLE_LOGGING
|
|
LPCTSTR faxDbgFunction=_T("PSSLogEntry");
|
|
#endif // ENABLE_LOGGING
|
|
|
|
switch (nMessageType)
|
|
{
|
|
case PSS_MSG_MSG:
|
|
lptstrMsgPrefix=TEXT(" ");
|
|
break;
|
|
case PSS_WRN_MSG:
|
|
lptstrMsgPrefix=TEXT("WRN");
|
|
break;
|
|
case PSS_ERR_MSG:
|
|
lptstrMsgPrefix=TEXT("ERR");
|
|
break;
|
|
default:
|
|
_ASSERT(FALSE);
|
|
lptstrMsgPrefix=TEXT(" ");
|
|
break;
|
|
}
|
|
|
|
iHeaderIndex = _sntprintf(pcszMessage,
|
|
MAX_MESSAGE_LEN-1,
|
|
TEXT("[%-8s][%09d][%4d%04d][%3s] %*c"),
|
|
_tstrtime(szTimeBuff),
|
|
GetTickCount(),
|
|
dwFileID,
|
|
dwLine % 10000,
|
|
lptstrMsgPrefix,
|
|
dwIndent * INDENT_LEN,
|
|
TEXT(' '));
|
|
if (iHeaderIndex<0)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, "Message header too long, it will not be logged");
|
|
return;
|
|
}
|
|
|
|
// Now comes the actual message
|
|
va_start(arg_ptr, pcszFormat);
|
|
iMessageIndex = _vsntprintf(
|
|
&pcszMessage[iHeaderIndex],
|
|
MAX_MESSAGE_LEN - (iHeaderIndex + 3), // +3 - room for "\r\n\0"
|
|
pcszFormat,
|
|
arg_ptr);
|
|
if (iMessageIndex<0)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, "Message too long, it will not be logged");
|
|
return;
|
|
}
|
|
// Kill all newline chars
|
|
iMessageIndex = CopyStrNoNewLines(&pcszMessage[iHeaderIndex], &pcszMessage[iHeaderIndex]);
|
|
|
|
DebugPrintEx(DEBUG_MSG, "PSSLog: %s", &pcszMessage[iHeaderIndex]);
|
|
|
|
if (PSSLOG_NONE == pTG->dwLoggingEnabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// End of line
|
|
iMessageIndex += iHeaderIndex;
|
|
iMessageIndex += _stprintf( &pcszMessage[iMessageIndex],TEXT("\r\n"));
|
|
|
|
pTG->dwCurrentFileSize += iMessageIndex * sizeof(pcszMessage[0]);
|
|
// Check if not exceeding MaxLogFileSize
|
|
if ((pTG->dwMaxLogFileSize!=0) && (pTG->dwCurrentFileSize > pTG->dwMaxLogFileSize))
|
|
{
|
|
fRet = WriteFile(pTG->hPSSLogFile,
|
|
MAX_LOG_FILE_SIZE_MESSAGE,
|
|
_tcslen(MAX_LOG_FILE_SIZE_MESSAGE) * sizeof(TCHAR),
|
|
&dwBytesWritten,
|
|
NULL);
|
|
if (FALSE == fRet)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, "Writefile failed, LE=%d", GetLastError());
|
|
}
|
|
ClosePSSLogFile(pTG, FALSE); // Always want to keep oversized logs
|
|
}
|
|
else
|
|
{
|
|
fRet = WriteFile(pTG->hPSSLogFile,
|
|
pcszMessage,
|
|
iMessageIndex * sizeof(pcszMessage[0]),
|
|
&dwBytesWritten,
|
|
NULL);
|
|
if (FALSE == fRet)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, "Writefile failed, LE=%d", GetLastError());
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*++
|
|
Routine Description:
|
|
Add an entry to the log, including a binary dump.
|
|
Arguments:
|
|
pTG
|
|
nMessageType - message type (PSS_MSG_ERR, PSS_MSG_WRN, PSS_MSG_MSG)
|
|
dwFileID - File ID, as set in the beginning of every file by #define FILE_ID
|
|
dwLine - Line number
|
|
pcszFormat - Message text, no format specifiers allowed
|
|
lpb - byte buffer to dump
|
|
dwSize - number of bytes to dump
|
|
Return Value:
|
|
None
|
|
--*/
|
|
|
|
void PSSLogEntryHex(
|
|
PThrdGlbl pTG,
|
|
PSS_MESSAGE_TYPE const nMessageType,
|
|
DWORD const dwFileID,
|
|
DWORD const dwLine,
|
|
DWORD dwIndent,
|
|
|
|
LPB const lpb,
|
|
DWORD const dwSize,
|
|
|
|
LPCTSTR pcszFormat,
|
|
... )
|
|
{
|
|
TCHAR pcszMessage[MAX_MESSAGE_LEN] = {'\0'};
|
|
va_list arg_ptr = NULL;
|
|
DWORD dwByte = 0;
|
|
int iMessageIndex = 0;
|
|
|
|
// DEBUG_FUNCTION_NAME(_T("PSSLogEntryHex"));
|
|
// hack: Want only one line in T30DebugLogFile
|
|
#ifdef ENABLE_LOGGING
|
|
LPCTSTR faxDbgFunction=_T("PSSLogEntryHex");
|
|
#endif // ENABLE_LOGGING
|
|
|
|
// Now comes the actual message
|
|
va_start(arg_ptr, pcszFormat);
|
|
iMessageIndex = _vsntprintf(
|
|
pcszMessage,
|
|
(sizeof(pcszMessage)/sizeof(pcszMessage[0]) -1),
|
|
pcszFormat,
|
|
arg_ptr);
|
|
|
|
if (iMessageIndex<0)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, "Message too long, it will not be logged");
|
|
return;
|
|
}
|
|
|
|
for (dwByte=0; dwByte<dwSize; dwByte++)
|
|
{
|
|
iMessageIndex += _stprintf( &pcszMessage[iMessageIndex],TEXT(" %02x"), lpb[dwByte]);
|
|
// -4 - room for "...", -3 - room for "\r\n\0"
|
|
if (iMessageIndex > (int)(MAX_MESSAGE_LEN - HEADER_LEN - dwIndent*INDENT_LEN - 4 - 3))
|
|
{
|
|
iMessageIndex += _stprintf( &pcszMessage[iMessageIndex],TEXT("..."));
|
|
break;
|
|
}
|
|
}
|
|
|
|
PSSLogEntry(pTG, nMessageType, dwFileID, dwLine, dwIndent, pcszMessage);
|
|
}
|
|
|
|
|
|
/*++
|
|
Routine Description:
|
|
Add an entry to the log, including a list of strings.
|
|
Arguments:
|
|
pTG
|
|
nMessageType - message type (PSS_MSG_ERR, PSS_MSG_WRN, PSS_MSG_MSG)
|
|
dwFileID - File ID, as set in the beginning of every file by #define FILE_ID
|
|
dwLine - Line number
|
|
pcszFormat - Message text, no format specifiers allowed
|
|
lplpszStrings - pointer to array of strings to log
|
|
dwStringNum - number of strings
|
|
Return Value:
|
|
None
|
|
--*/
|
|
|
|
void PSSLogEntryStrings(
|
|
PThrdGlbl pTG,
|
|
PSS_MESSAGE_TYPE const nMessageType,
|
|
DWORD const dwFileID,
|
|
DWORD const dwLine,
|
|
DWORD dwIndent,
|
|
|
|
LPCTSTR const *lplpszStrings,
|
|
DWORD const dwStringNum,
|
|
|
|
LPCTSTR pcszFormat,
|
|
... )
|
|
{
|
|
TCHAR pcszMessage[MAX_MESSAGE_LEN] = {'\0'};
|
|
va_list arg_ptr = NULL;
|
|
DWORD dwString = 0;
|
|
int iMessageIndex = 0;
|
|
int iResult = 0;
|
|
|
|
// DEBUG_FUNCTION_NAME(_T("PSSLogEntryStrings"));
|
|
// hack: Want only one line in T30DebugLogFile
|
|
#ifdef ENABLE_LOGGING
|
|
LPCTSTR faxDbgFunction=_T("PSSLogEntryStrings");
|
|
#endif // ENABLE_LOGGING
|
|
|
|
// Now comes the actual message
|
|
va_start(arg_ptr, pcszFormat);
|
|
iMessageIndex = _vsntprintf(
|
|
pcszMessage,
|
|
(sizeof(pcszMessage)/sizeof(pcszMessage[0]) -1),
|
|
pcszFormat,
|
|
arg_ptr);
|
|
|
|
if (iMessageIndex<0)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, "Message too long, it will not be logged");
|
|
return;
|
|
}
|
|
|
|
for (dwString=0; dwString<dwStringNum; dwString++)
|
|
{
|
|
iResult = _sntprintf( &pcszMessage[iMessageIndex],
|
|
MAX_MESSAGE_LEN - iMessageIndex,
|
|
(dwString==0) ? TEXT("%s") : TEXT(", %s"),
|
|
lplpszStrings[dwString]);
|
|
if (iResult < 0)
|
|
{
|
|
break;
|
|
}
|
|
iMessageIndex += iResult;
|
|
}
|
|
|
|
PSSLogEntry(pTG, nMessageType, dwFileID, dwLine, dwIndent, pcszMessage);
|
|
}
|
|
|