Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2849 lines
82 KiB

/*
Module Name:
faxlog.c
Abstract:
This is the main fax service activity logging implementation.
Author:
Revision History:
--*/
#include "faxsvc.h"
#include <string>
using namespace std;
LOG_STRING_TABLE g_OutboxTable[] =
{
{IDS_JOB_ID, FIELD_TYPE_TEXT, 18, NULL },
{IDS_PARENT_JOB_ID, FIELD_TYPE_TEXT, 18, NULL },
{IDS_SUBMITED, FIELD_TYPE_DATE, 0, NULL },
{IDS_SCHEDULED, FIELD_TYPE_DATE, 0, NULL },
{IDS_STATUS, FIELD_TYPE_TEXT, 255, NULL },
{IDS_ERROR_DESC, FIELD_TYPE_TEXT, 255, NULL },
{IDS_ERROR_CODE, FIELD_TYPE_TEXT, 10, NULL },
{IDS_START_TIME, FIELD_TYPE_DATE, 0, NULL },
{IDS_END_TIME, FIELD_TYPE_DATE, 0, NULL },
{IDS_DEVICE, FIELD_TYPE_TEXT, 255, NULL },
{IDS_DIALED_NUMBER, FIELD_TYPE_TEXT, 255, NULL },
{IDS_CSID, FIELD_TYPE_TEXT, 255, NULL },
{IDS_TSID, FIELD_TYPE_TEXT, 255, NULL },
{IDS_PAGES, FIELD_TYPE_FLOAT, 0, NULL },
{IDS_TOTAL_PAGES, FIELD_TYPE_FLOAT, 0, NULL },
{IDS_FILE_NAME, FIELD_TYPE_TEXT, 255, NULL },
{IDS_DOCUMENT, FIELD_TYPE_TEXT, 255, NULL },
{IDS_FILE_SIZE, FIELD_TYPE_FLOAT, 0, NULL },
{IDS_RETRIES, FIELD_TYPE_FLOAT, 0, NULL },
{IDS_COVER_PAGE, FIELD_TYPE_TEXT, 255, NULL },
{IDS_SUBJECT, FIELD_TYPE_TEXT, 255, NULL },
{IDS_NOTE, FIELD_TYPE_TEXT, 255, NULL },
{IDS_USER_NAME, FIELD_TYPE_TEXT, 255, NULL },
{IDS_SENDER_NAME, FIELD_TYPE_TEXT, 255, NULL },
{IDS_SENDER_FAX_NUMBER, FIELD_TYPE_TEXT, 255, NULL },
{IDS_SENDER_COMPANY, FIELD_TYPE_TEXT, 255, NULL },
{IDS_SENDER_STREET, FIELD_TYPE_TEXT, 255, NULL },
{IDS_SENDER_CITY, FIELD_TYPE_TEXT, 255, NULL },
{IDS_SENDER_ZIP, FIELD_TYPE_TEXT, 255, NULL },
{IDS_SENDER_COUNTRY, FIELD_TYPE_TEXT, 255, NULL },
{IDS_SENDER_TITLE, FIELD_TYPE_TEXT, 255, NULL },
{IDS_SENDER_DEPARTMENT, FIELD_TYPE_TEXT, 255, NULL },
{IDS_SENDER_OFFICE, FIELD_TYPE_TEXT, 255, NULL },
{IDS_SENDER_H_PHONE, FIELD_TYPE_TEXT, 255, NULL },
{IDS_SENDER_O_PHONE, FIELD_TYPE_TEXT, 255, NULL },
{IDS_SENDER_E_MAIL, FIELD_TYPE_TEXT, 255, NULL },
{IDS_RECIPIENT_NAME, FIELD_TYPE_TEXT, 255, NULL },
{IDS_RECIPIENT_FAX_NUMBER, FIELD_TYPE_TEXT, 255, NULL },
{IDS_RECIPIENT_COMPANY, FIELD_TYPE_TEXT, 255, NULL },
{IDS_RECIPIENT_STREET, FIELD_TYPE_TEXT, 255, NULL },
{IDS_RECIPIENT_CITY, FIELD_TYPE_TEXT, 255, NULL },
{IDS_RECIPIENT_ZIP, FIELD_TYPE_TEXT, 255, NULL },
{IDS_RECIPIENT_COUNTRY, FIELD_TYPE_TEXT, 255, NULL },
{IDS_RECIPIENT_TITLE, FIELD_TYPE_TEXT, 255, NULL },
{IDS_RECIPIENT_DEPARTMENT, FIELD_TYPE_TEXT, 255, NULL },
{IDS_RECIPIENT_OFFICE, FIELD_TYPE_TEXT, 255, NULL },
{IDS_RECIPIENT_H_PHONE, FIELD_TYPE_TEXT, 255, NULL },
{IDS_RECIPIENT_O_PHONE, FIELD_TYPE_TEXT, 255, NULL },
{IDS_RECIPIENT_E_MAIL, FIELD_TYPE_TEXT, 255, NULL },
{IDS_BILLING_CODE, FIELD_TYPE_TEXT, 255, NULL }
};
LOG_STRING_TABLE g_InboxTable[] =
{
{IDS_STATUS, FIELD_TYPE_TEXT, 255, NULL },
{IDS_ERROR_DESC, FIELD_TYPE_TEXT, 255, NULL },
{IDS_ERROR_CODE, FIELD_TYPE_TEXT, 10, NULL },
{IDS_START_TIME, FIELD_TYPE_DATE, 0, NULL },
{IDS_END_TIME, FIELD_TYPE_DATE, 0, NULL },
{IDS_DEVICE, FIELD_TYPE_TEXT, 255, NULL },
{IDS_FILE_NAME, FIELD_TYPE_TEXT, 255, NULL },
{IDS_FILE_SIZE, FIELD_TYPE_FLOAT, 0, NULL },
{IDS_CSID, FIELD_TYPE_TEXT, 255, NULL },
{IDS_TSID, FIELD_TYPE_TEXT, 255, NULL },
{IDS_CALLER_ID, FIELD_TYPE_TEXT, 255, NULL },
{IDS_ROUTING_INFO, FIELD_TYPE_TEXT, 255, NULL },
{IDS_PAGES, FIELD_TYPE_FLOAT, 0, NULL }
};
const DWORD gc_dwCountInboxTable = (sizeof(g_InboxTable)/sizeof(g_InboxTable[0]));
const DWORD gc_dwCountOutboxTable = (sizeof(g_OutboxTable)/sizeof(g_OutboxTable[0]));
HANDLE g_hInboxActivityLogFile;
HANDLE g_hOutboxActivityLogFile;
static
wstring
FilteredLogString (LPCWSTR lpcwstrSrc) throw (exception);
static
VOID
GetSchemaFileText(wstring &wstrRes) throw (exception);
static
VOID
GetTableColumnsText(
LPTSTR ptszTableName,
wstring &wstrResult
) throw (exception);
static
BOOL
GetFaxTimeAsString(
SYSTEMTIME* pFaxTime,
wstring &wstrTime
) throw (exception);
static
BOOL
GetInboundCommandText(
PJOB_QUEUE lpJobQueue,
LPCFSPI_JOB_STATUS lpcFaxStatus,
wstring &wstrCommandText
) throw (exception);
static
BOOL
GetOutboundCommandText(
PJOB_QUEUE lpJobQueue,
wstring &wstrCommandText
) throw (exception);
//
// Important!! - Always lock g_CsInboundActivityLogging and then g_CsOutboundActivityLogging
//
CFaxCriticalSection g_CsInboundActivityLogging;
CFaxCriticalSection g_CsOutboundActivityLogging;
BOOL g_fLogStringTableInit;
static DWORD CreateLogFile(DWORD dwFileType, LPCWSTR lpcwstrDBPath, LPHANDLE phFile);
static BOOL LogFileLimitReached(DWORD dwFileToCheck);
static DWORD LogFileLimitReachAction(DWORD dwFileType);
static DWORD DeleteLogActivityFile(DWORD dwFileType);
static DWORD ReplaceLogActivityFile(DWORD dwFileType);
static LPTSTR BuildFullFileName( LPCTSTR strPath,LPCTSTR strFileName );
static BOOL SetFileToCurrentTime(HANDLE hFile);
//*********************************************************************************
//* Name: LogInboundActivity()
//* Author: Oded Sacher
//* Date: Oct 19, 1999
//*********************************************************************************
//* DESCRIPTION:
//* Inserts new record into the Inbox Activity logging table.
//* Must be called inside critical section CsActivityLogging.
//*
//* PARAMETERS:
//* [IN ] PJOB_QUEUE lpJobQueue
//* pointer to the job queue of the inbound job.
//*
//* [IN ] LPCFSPI_JOB_STATUS lpcFaxStatus
//* The status of the recieved job.
//*
//*
//* RETURN VALUE:
//* TRUE
//* If no error occured.
//* FALSE
//* If an error occured.
//*********************************************************************************
BOOL
LogInboundActivity(
PJOB_QUEUE lpJobQueue,
LPCFSPI_JOB_STATUS lpcFaxStatus
)
{
DWORD dwRes = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("LogInboundActivity"));
wstring wstrText;
DWORD dwBytesWritten;
if (!g_ActivityLoggingConfig.bLogIncoming)
{
//
// Inbound activity logging is disabled
//
return TRUE;
}
Assert (g_hInboxActivityLogFile != INVALID_HANDLE_VALUE);
try
{
if (!GetInboundCommandText(lpJobQueue, lpcFaxStatus, wstrText))
{
DebugPrintEx(DEBUG_ERR,
TEXT("GetInboundCommandText failed )"));
dwRes = ERROR_OUTOFMEMORY;
goto exit;
}
}
catch (exception &ex)
{
dwRes = ERROR_OUTOFMEMORY;
DebugPrintEx(
DEBUG_ERR,
TEXT("GetInboundCommandText caused exception (%S)"),
ex.what());
goto exit;
}
if (LogFileLimitReached(ACTIVITY_LOG_INBOX))
{
//
// Time to take action and replace/remove the old log file
//
DebugPrintEx(DEBUG_MSG,
TEXT("Inbox activity log file has reached it's limit. deleting/renaming the old file")
);
dwRes = LogFileLimitReachAction(ACTIVITY_LOG_INBOX);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(DEBUG_ERR,
TEXT("LogFileLimitReachAction for ACTIVITY_LOG_INBOX failed (ec: %ld). Inbound activity logging will halt"),
dwRes
);
//
// May happen if we couldn't create a new log file
// CreateLogFile() disables logging on failure
//
if (!g_ActivityLoggingConfig.bLogIncoming ||
g_hInboxActivityLogFile == INVALID_HANDLE_VALUE)
{
goto exit;
}
//
// try to continue with the old log file
//
dwRes = ERROR_SUCCESS;
}
}
if (!WriteFile( g_hInboxActivityLogFile,
wstrText.c_str(),
wstrText.length() * sizeof(WCHAR),
&dwBytesWritten,
NULL))
{
dwRes = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("WriteFile failed (ec: %ld)"),
dwRes);
goto exit;
}
Assert (ERROR_SUCCESS == dwRes);
exit:
if (ERROR_SUCCESS != dwRes)
{
SetLastError (dwRes);
return FALSE;
}
return TRUE;
} // LogInboundActivity
//*********************************************************************************
//* Name: LogOutboundActivity()
//* Author: Oded Sacher
//* Date: Oct 19, 1999
//*********************************************************************************
//* DESCRIPTION:
//* Inserts new record into the Outbox Activity logging table.
//* Must be called inside critical section CsActivityLogging..
//*
//* PARAMETERS:
//* [IN ] PJOB_QUEUE lpJobQueue
//* pointer to the job queue of the inbound job.
//*
//*
//* RETURN VALUE:
//* TRUE
//* If no error occured.
//* FALSE
//* If an error occured.
//*********************************************************************************
BOOL
LogOutboundActivity(
PJOB_QUEUE lpJobQueue
)
{
DWORD dwRes = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("LogOutboundActivity"));
wstring wstrText;
DWORD dwBytesWritten;
if (!g_ActivityLoggingConfig.bLogOutgoing)
{
//
// Outbound activity logging is disabled
//
return TRUE;
}
Assert (g_hOutboxActivityLogFile != INVALID_HANDLE_VALUE);
try
{
if (!GetOutboundCommandText(lpJobQueue, wstrText))
{
DebugPrintEx(DEBUG_ERR,
TEXT("GetOutboundCommandText failed )"));
dwRes = ERROR_OUTOFMEMORY;
goto exit;
}
}
catch (exception &ex)
{
dwRes = ERROR_OUTOFMEMORY;
DebugPrintEx(
DEBUG_ERR,
TEXT("GetOutboundCommandText caused exception (%S)"),
ex.what());
goto exit;
}
if (LogFileLimitReached(ACTIVITY_LOG_OUTBOX))
{
//
// Time to take action and replace/remove the old log file
//
DebugPrintEx(DEBUG_MSG,
TEXT("Outbox activity log file has reached it's limit. deleting/renaming the old file")
);
dwRes = LogFileLimitReachAction(ACTIVITY_LOG_OUTBOX);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(DEBUG_ERR,
TEXT("LogFileLimitReachAction for ACTIVITY_LOG_OUTBOX failed (ec: %ld)."),
dwRes
);
//
// May happen if we couldn't create a new log file
// CreateLogFile() disables logging on failure
//
if (!g_ActivityLoggingConfig.bLogOutgoing ||
g_hOutboxActivityLogFile == INVALID_HANDLE_VALUE)
{
goto exit;
}
//
// try to continue with the old log file
//
dwRes = ERROR_SUCCESS;
}
}
if (!WriteFile( g_hOutboxActivityLogFile,
wstrText.c_str(),
wstrText.length() * sizeof(WCHAR),
&dwBytesWritten,
NULL))
{
dwRes = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("WriteFile failed (ec: %ld)"),
dwRes);
goto exit;
}
Assert (ERROR_SUCCESS == dwRes);
exit:
if (ERROR_SUCCESS != dwRes)
{
SetLastError (dwRes);
return FALSE;
}
return TRUE;
} // LogOutboundActivity
//*********************************************************************************
//* Name: GetTableColumnsText()
//* Author: Oded Sacher
//* Date: Oct 19, 1999
//*********************************************************************************
//* DESCRIPTION:
//* Retrieves the first row of the log file (column names).
//*
//* PARAMETERS:
//* [IN] LPTSTR TableName
//* Table name, can be Outbox or Inbox.
//*
//* [IN] wstring &wstrResult
//* Output result string
//*
//* RETURN VALUE:
//* None
//*
//* NOTE: The function might throw STL string exceptions.
//*
//*********************************************************************************
static
VOID
GetTableColumnsText(
LPTSTR ptszTableName,
wstring &wstrResult
) throw (exception)
{
DEBUG_FUNCTION_NAME(TEXT("GetTableColumnsText"));
PLOG_STRING_TABLE Table = NULL;
DWORD Count = 0;
if (!_tcscmp(ptszTableName, INBOX_TABLE))
{
Table = g_InboxTable;
Count = gc_dwCountInboxTable;
}
else
{
Table = g_OutboxTable;
Count = gc_dwCountOutboxTable;
}
Assert(Table);
for (DWORD Index = 0; Index < Count; Index++)
{
wstrResult += TEXT("\"");
wstrResult += Table[Index].String;
wstrResult += TEXT("\"");
if (Index < Count - 1)
{
wstrResult += TEXT("\t");
}
}
wstrResult += TEXT("\r\n");
DebugPrintEx(DEBUG_MSG,
TEXT("First row (Columns names): %s"),
wstrResult.c_str());
} // GetTableColumnsText
//*********************************************************************************
//* Name: GetSchemaFileText()
//* Author: Oded Sacher
//* Date: Jul 25, 2000
//*********************************************************************************
//* DESCRIPTION:
//* Retrieves the scema.ini text buffer.
//*
//* PARAMETERS:
//* [IN] wstring &wstrRes
//* Output result string
//*
//* RETURN VALUE:
//* None.
//*
//* NOTE: The function might throw STL string exceptions.
//*
//*********************************************************************************
static
VOID
GetSchemaFileText(wstring &wstrRes) throw (exception)
{
DEBUG_FUNCTION_NAME(TEXT("GetSchemaFileText"));
DWORD Index;
//
// Inbox table
//
wstrRes += TEXT("[");
wstrRes += ACTIVITY_LOG_INBOX_FILE;
wstrRes += TEXT("]\r\n");
wstrRes += TEXT("ColNameHeader=True\r\n");
wstrRes += TEXT("Format=TabDelimited\r\n");
wstrRes += TEXT("CharacterSet=1200\r\n");
for (Index = 0; Index < gc_dwCountInboxTable; Index++)
{
TCHAR tszTemp[MAX_PATH * 2] = {0};
if (0 == wcscmp(g_InboxTable[Index].Type, FIELD_TYPE_TEXT))
{
_snwprintf(tszTemp,
ARR_SIZE(tszTemp)-1,
TEXT("Col%ld=%s %s Width %ld\r\n"),
Index + 1,
g_InboxTable[Index].String,
g_InboxTable[Index].Type,
g_InboxTable[Index].Size);
}
else
{
_snwprintf(tszTemp,
ARR_SIZE(tszTemp)-1,
TEXT("Col%ld=%s %s\r\n"),
Index + 1,
g_InboxTable[Index].String,
g_InboxTable[Index].Type);
}
wstrRes += tszTemp;
}
//
// Outbox table
//
wstrRes += TEXT("[");
wstrRes += ACTIVITY_LOG_OUTBOX_FILE;
wstrRes += TEXT("]\r\n");
wstrRes += TEXT("ColNameHeader=True\r\n");
wstrRes += TEXT("Format=TabDelimited\r\n");
wstrRes += TEXT("CharacterSet=1200\r\n");
for (Index = 0; Index < gc_dwCountOutboxTable; Index++)
{
TCHAR tszTemp[MAX_PATH * 2] = {0};
if (0 == wcscmp(g_OutboxTable[Index].Type, FIELD_TYPE_TEXT))
{
_snwprintf(tszTemp,
ARR_SIZE(tszTemp)-1,
TEXT("Col%ld=%s %s Width %ld\r\n"),
Index + 1,
g_OutboxTable[Index].String,
g_OutboxTable[Index].Type,
g_OutboxTable[Index].Size);
}
else
{
_snwprintf(tszTemp,
ARR_SIZE(tszTemp)-1,
TEXT("Col%ld=%s %s\r\n"),
Index + 1,
g_OutboxTable[Index].String,
g_OutboxTable[Index].Type);
}
wstrRes += tszTemp;
}
} // GetSchemaFileText
//*********************************************************************************
//* Name: CreateLogDB()
//* Author: Oded Sacher
//* Date: Oct 19, 1999
//*********************************************************************************
//* DESCRIPTION:
//* Creates the database files. Creates the Schema.ini file.
//*
//* PARAMETERS:
//* [IN] LPCWSTR lpcwstrDBPath
//* Pointer to a NULL terminated string contains the DB path.
//* [OUT] LPHANDLE phInboxFile
//* Adress of a variable to receive the inbox file handle.
//* [OUT] LPHANDLE phOutboxFile
//* Adress of a variable to receive the outbox file handle.
//*
//* RETURN VALUE:
//* Win32 error Code
//*********************************************************************************
DWORD
CreateLogDB (
LPCWSTR lpcwstrDBPath,
LPHANDLE phInboxFile,
LPHANDLE phOutboxFile
)
{
DEBUG_FUNCTION_NAME(TEXT("CreateLogDB"));
DWORD dwRes = ERROR_SUCCESS;
HANDLE hInboxFile = INVALID_HANDLE_VALUE;
HANDLE hOutboxFile = INVALID_HANDLE_VALUE;
HANDLE hSchemaFile = INVALID_HANDLE_VALUE;
WCHAR wszFileName[MAX_PATH] = {0};
DWORD dwBytesWritten;
DWORD ec = ERROR_SUCCESS; // Used for Schema.ini
wstring wstrSchema;
INT iCount = 0;
Assert (lpcwstrDBPath && phInboxFile && phOutboxFile);
if (FALSE == g_fLogStringTableInit)
{
dwRes = InitializeLoggingStringTables();
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(DEBUG_ERR,
TEXT("Close connection failed (hr: 0x%08x)"),
dwRes);
return dwRes;
}
g_fLogStringTableInit = TRUE;
}
dwRes = IsValidFaxFolder(lpcwstrDBPath);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(DEBUG_ERR,
TEXT("IsValidFaxFolder failed for folder : %s (ec=%lu)."),
lpcwstrDBPath,
dwRes);
return dwRes;
}
//
// Create the logging files
//
dwRes = CreateLogFile(ACTIVITY_LOG_INBOX,lpcwstrDBPath,&hInboxFile);
if ( ERROR_SUCCESS != dwRes)
{
DebugPrintEx( DEBUG_ERR,
TEXT("CreateLogFile() Failed, for Inbox file. (ec=%ld)"),
dwRes
);
goto exit;
}
dwRes = CreateLogFile(ACTIVITY_LOG_OUTBOX,lpcwstrDBPath,&hOutboxFile);
if ( ERROR_SUCCESS != dwRes)
{
DebugPrintEx( DEBUG_ERR,
TEXT("CreateLogFile() Failed, for Outbox file. (ec=%ld)"),
dwRes
);
goto exit;
}
*phInboxFile = hInboxFile;
*phOutboxFile= hOutboxFile;
Assert (ERROR_SUCCESS == dwRes && ERROR_SUCCESS == ec);
//
// Create the Schema.ini file - Function do not fail if not succeeded
//
iCount = _snwprintf (wszFileName,
MAX_PATH - 1,
TEXT("%s\\%s"),
lpcwstrDBPath,
TEXT("schema.ini"));
if (0 > iCount)
{
//
// path and file name exceeds MAX_PATH
//
DebugPrintEx(
DEBUG_ERR,
TEXT("_snwprintf Failed, File name bigger than MAX_PATH"));
ec = ERROR_BUFFER_OVERFLOW;
goto exit;
}
hSchemaFile = SafeCreateFile(
wszFileName, // file name
GENERIC_WRITE, // access mode
0, // share mode
NULL, // SD
CREATE_ALWAYS, // how to create
FILE_ATTRIBUTE_NORMAL, // file attributes
NULL);
if (INVALID_HANDLE_VALUE == hSchemaFile)
{
ec = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("CreateFile failed (ec: %ld)"),
ec);
goto exit;
}
try
{
GetSchemaFileText(wstrSchema);
}
catch (exception &ex)
{
dwRes = ERROR_OUTOFMEMORY;
DebugPrintEx(
DEBUG_ERR,
TEXT("GetSchemaFileText caused exception (%S)"),
ex.what());
goto exit;
}
if (!WriteFile( hSchemaFile,
wstrSchema.c_str(),
wstrSchema.length() * sizeof(WCHAR),
&dwBytesWritten,
NULL))
{
ec = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("WriteFile failed (ec: %ld)"),
ec);
goto exit;
}
Assert (ERROR_SUCCESS == dwRes && ERROR_SUCCESS == ec);
exit:
if (ERROR_SUCCESS != dwRes)
{
if (INVALID_HANDLE_VALUE != hOutboxFile)
{
if (!CloseHandle (hOutboxFile))
{
DebugPrintEx(DEBUG_ERR,
TEXT("CloseHandle failed (ec: %ld)"),
GetLastError());
}
}
if (INVALID_HANDLE_VALUE != hInboxFile)
{
if (!CloseHandle (hInboxFile))
{
DebugPrintEx(DEBUG_ERR,
TEXT("CloseHandle failed (ec: %ld)"),
GetLastError());
}
}
}
if (INVALID_HANDLE_VALUE != hSchemaFile)
{
if (!CloseHandle (hSchemaFile))
{
DebugPrintEx(DEBUG_ERR,
TEXT("CloseHandle failed (ec: %ld)"),
GetLastError());
}
}
if (ERROR_SUCCESS != ec)
{
FaxLog(
FAXLOG_CATEGORY_INIT,
FAXLOG_LEVEL_MED,
2,
MSG_FAX_ACTIVITY_LOG_FAILED_SCHEMA,
wszFileName,
DWORD2DECIMAL(ec)
);
}
return dwRes;
} // CreateLogDB
//*********************************************************************************
//* Name: InitializeLogging()
//* Author: Oded Sacher
//* Date: Jun 26, 2000
//*********************************************************************************
//* DESCRIPTION:
//* Initializes the Activity Logging. Opens the files.
//*
//*
//* PARAMETERS: None
//*
//* RETURN VALUE:
//* Win32 error code.
//*********************************************************************************
DWORD
InitializeLogging(
VOID
)
{
DWORD dwRes = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("InitializeLogging"));
if (!g_ActivityLoggingConfig.lptstrDBPath)
{
//
// Activity logging is off
//
return ERROR_SUCCESS;
}
EnterCriticalSection (&g_CsInboundActivityLogging);
EnterCriticalSection (&g_CsOutboundActivityLogging);
Assert ( (INVALID_HANDLE_VALUE == g_hInboxActivityLogFile) &&
(INVALID_HANDLE_VALUE == g_hOutboxActivityLogFile) );
//
// Create the logging files
//
dwRes = CreateLogDB (g_ActivityLoggingConfig.lptstrDBPath,
&g_hInboxActivityLogFile,
&g_hOutboxActivityLogFile);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(DEBUG_ERR,
TEXT("CreateLogDB failed (hr: 0x%08x)"),
dwRes);
goto exit;
}
Assert (ERROR_SUCCESS == dwRes);
exit:
LeaveCriticalSection (&g_CsOutboundActivityLogging);
LeaveCriticalSection (&g_CsInboundActivityLogging);
return dwRes;
}
//*********************************************************************************
//* Name: GetInboundCommandText()
//* Author: Oded Sacher
//* Date: Oct 19, 1999
//*********************************************************************************
//* DESCRIPTION:
//* Retrieves a buffer with the new inbound record.
//* The function allocates the memory for the string that will contain the record.
//*
//* PARAMETERS:
//* [IN ] PJOB_QUEUE lpJobQueue
//* pointer to the job queue of the inbound job.
//*
//* [IN ] LPCFSPI_JOB_STATUS lpcFaxStatus
//* The status of the recieved job.
//*
//* [OUT] wstring &wstrCommandText
//* String to compose
//*
//* RETURN VALUE:
//* TRUE
//* If no error occured.
//* FALSE
//* If an error occured.
//*
//* NOTE: The function might throw STL string exceptions.
//*
//*********************************************************************************
static
BOOL
GetInboundCommandText(
PJOB_QUEUE lpJobQueue,
LPCFSPI_JOB_STATUS lpcFaxStatus,
wstring &wstrCommandText
) throw (exception)
{
DEBUG_FUNCTION_NAME(TEXT("GetInboundCommandText"));
BOOL bStartTime;
BOOL bEndTime;
SYSTEMTIME tmStart;
SYSTEMTIME tmEnd;
HINSTANCE hLoadInstance = NULL;
Assert (lpJobQueue->JobEntry);
Assert (lpJobQueue->JobEntry->LineInfo);
bStartTime = GetRealFaxTimeAsSystemTime (lpJobQueue->JobEntry, FAX_TIME_TYPE_START, &tmStart);
if (bStartTime == FALSE)
{
DebugPrintEx( DEBUG_ERR,
TEXT("GetRealFaxTimeAsSystemTime (Start time) Failed (ec: %ld)"),
GetLastError());
}
bEndTime = GetRealFaxTimeAsSystemTime (lpJobQueue->JobEntry, FAX_TIME_TYPE_END, &tmEnd);
if (bEndTime == FALSE)
{
DebugPrintEx( DEBUG_ERR,
TEXT("GetRealFaxTimeAsSystemTime (End time) Failed (ec: %ld)"),
GetLastError());
}
//
// Status
//
wstrCommandText += TEXT("\"");
switch (lpcFaxStatus->dwJobStatus)
{
case FSPI_JS_FAILED:
wstrCommandText += FilteredLogString(GetString(IDS_FAILED_RECEIVE));
break;
case FSPI_JS_COMPLETED:
wstrCommandText += FilteredLogString(GetString(FPS_COMPLETED));
break;
case FSPI_JS_ABORTED:
wstrCommandText += FilteredLogString(GetString(IDS_CANCELED));
break;
default:
ASSERT_FALSE;
}
wstrCommandText += TEXT("\"\t\"");
//
// ErrorDesc
//
wstring wstrErr;
if (lstrlen(lpJobQueue->JobEntry->ExStatusString))
{
//
// The FSP provided extended status string
//
wstrErr = lpJobQueue->JobEntry->ExStatusString;
}
else if (lpcFaxStatus->dwExtendedStatus == 0)
{
//
// No extended status
//
wstrErr = TEXT(" ");
}
else
{
//
// Well known extended status
//
LPTSTR ResStr = MapFSPIJobExtendedStatusToString(lpcFaxStatus->dwExtendedStatus);
if (NULL == ResStr)
{
ASSERT_FALSE;
wstrErr = TEXT(" ");
DebugPrintEx(
DEBUG_ERR,
TEXT("Unexpected extended status. Extended Status: %ld, Provider: %s"),
lpcFaxStatus->dwExtendedStatus,
lpJobQueue->JobEntry->LineInfo->Provider->ImageName);
}
else
{
if (FSPI_ES_PARTIALLY_RECEIVED == lpcFaxStatus->dwExtendedStatus && // This is a partially received fax
lstrlen(lpJobQueue->ExStatusString)) // The original extended status string is not empty)
{
//
// copy both the partially received and original extended status strings
//
wstrErr = ResStr;
wstrErr += TEXT(" - ");
wstrErr += lpJobQueue->ExStatusString;
}
else
{
//
// Copy just the extended status string
//
wstrErr = ResStr;
}
}
}
wstrCommandText += FilteredLogString(wstrErr.c_str());
wstrCommandText += TEXT("\"\t\"");
//
// Error Code
//
if (lpcFaxStatus->dwExtendedStatus == 0)
{
wstrErr = TEXT(" ");
}
else
{
TCHAR tszHexNum [40];
swprintf(tszHexNum, TEXT("0x%08x"), lpcFaxStatus->dwExtendedStatus);
wstrErr = tszHexNum;
}
wstrCommandText += wstrErr;
wstrCommandText += TEXT("\"\t");
//
// StartTime
//
if (bStartTime)
{
wstring wstrTime;
if (!GetFaxTimeAsString (&tmStart, wstrTime))
{
DebugPrintEx(
DEBUG_ERR,
TEXT("GetFaxTimeAsString Failed (ec: %ld)"),
GetLastError());
return FALSE;
}
wstrCommandText += FilteredLogString(wstrTime.c_str());
}
wstrCommandText += TEXT("\t");
//
// EndTime
//
if (bEndTime)
{
wstring wstrTime;
if (!GetFaxTimeAsString (&tmEnd, wstrTime))
{
DebugPrintEx(
DEBUG_ERR,
TEXT("GetFaxTimeAsString Failed (ec: %ld)"),
GetLastError());
return FALSE;
}
wstrCommandText += FilteredLogString(wstrTime.c_str());
}
wstrCommandText += TEXT("\t\"");
//
// Device
//
wstrCommandText += FilteredLogString(lpJobQueue->JobEntry->LineInfo->DeviceName);
wstrCommandText += TEXT("\"\t\"");
//
// File name
//
wstrCommandText += FilteredLogString(lpJobQueue->FileName);
wstrCommandText += TEXT("\"\t");
//
// File size
//
TCHAR tszSize[40];
swprintf(tszSize,TEXT("%ld"), lpJobQueue->FileSize);
wstrCommandText += tszSize;
wstrCommandText += TEXT("\t\"");
//
// CSID
//
wstrCommandText += FilteredLogString(lpJobQueue->JobEntry->LineInfo->Csid);
wstrCommandText += TEXT("\"\t\"");
//
// TSID
//
wstrCommandText += FilteredLogString(lpcFaxStatus->lpwstrRemoteStationId);
wstrCommandText += TEXT("\"\t\"");
//
// Caller ID
//
wstrCommandText += FilteredLogString(lpcFaxStatus->lpwstrCallerId);
wstrCommandText += TEXT("\"\t\"");
//
// Routing information
//
wstrCommandText += FilteredLogString(lpcFaxStatus->lpwstrRoutingInfo);
wstrCommandText += TEXT("\"\t");
//
// Pages
//
TCHAR tszPages[40];
swprintf(tszPages,TEXT("%ld"),lpcFaxStatus->dwPageCount);
wstrCommandText += tszPages;
wstrCommandText += TEXT("\r\n");
DebugPrintEx(DEBUG_MSG,
TEXT("Inbound SQL statement: %s"),
wstrCommandText.c_str());
return TRUE;
} // GetInboundCommandText
//*********************************************************************************
//* Name: GetOutboundCommandText()
//* Author: Oded Sacher
//* Date: Oct 19, 1999
//*********************************************************************************
//* DESCRIPTION:
//* Retrieves a buffer that contains the new outbound record.
//* The function allocates the memory for the buffer that will contain the new record.
//*
//* PARAMETERS:
//* [IN ] PJOB_QUEUE lpJobQueue
//* pointer to the job queue of the inbound job.
//*
//* [OUT] wstring &wstrCommandText
//* String to compose
//*
//* RETURN VALUE:
//* TRUE
//* If no error occured.
//* FALSE
//* If an error occured.
//*
//* NOTE: The function might throw STL string exceptions.
//*
//*********************************************************************************
static
BOOL
GetOutboundCommandText(
PJOB_QUEUE lpJobQueue,
wstring &wstrCommandText
) throw (exception)
{
DEBUG_FUNCTION_NAME(TEXT("GetOutboundCommandText"));
BOOL bStartTime;
BOOL bEndTime;
BOOL bOriginalTime;
BOOL bSubmissionTime;
SYSTEMTIME tmStart;
SYSTEMTIME tmEnd;
SYSTEMTIME tmOriginal;
SYSTEMTIME tmSubmission;
HINSTANCE hLoadInstance = NULL;
Assert (lpJobQueue->lpParentJob->SubmissionTime);
Assert (lpJobQueue->lpParentJob->OriginalScheduleTime);
bSubmissionTime = FileTimeToSystemTime ((FILETIME*)&(lpJobQueue->lpParentJob->SubmissionTime), &tmSubmission);
if (bSubmissionTime == FALSE)
{
DebugPrintEx( DEBUG_ERR,
TEXT("FileTimeToSystemTime (Submission time) Failed (ec: %ld)"),
GetLastError());
}
bOriginalTime = FileTimeToSystemTime ((FILETIME*)&(lpJobQueue->lpParentJob->SubmissionTime), &tmOriginal);
if (bOriginalTime == FALSE)
{
DebugPrintEx( DEBUG_ERR,
TEXT("FileTimeToSystemTime (Original schduled time) Failed (ec: %ld)"),
GetLastError());
}
if (NULL != lpJobQueue->JobEntry)
{
bStartTime = GetRealFaxTimeAsSystemTime (lpJobQueue->JobEntry, FAX_TIME_TYPE_START, &tmStart);
if (bStartTime == FALSE)
{
DebugPrintEx( DEBUG_ERR,
TEXT("GetRealFaxTimeAsSystemTime (Start time) Failed (ec: %ld)"),
GetLastError());
}
bEndTime = GetRealFaxTimeAsSystemTime (lpJobQueue->JobEntry, FAX_TIME_TYPE_END, &tmEnd);
if (bEndTime == FALSE)
{
DebugPrintEx( DEBUG_ERR,
TEXT("GetRealFaxTimeAsSystemTime (End time) Failed (ec: %ld)"),
GetLastError());
}
}
//
// JobID
//
TCHAR tszTemp[100];
swprintf(tszTemp,TEXT("0x%016I64x"), lpJobQueue->UniqueId);
wstrCommandText += TEXT("\"");
wstrCommandText += tszTemp;
wstrCommandText += TEXT("\"\t\"");
//
// Parent JobID
//
swprintf(tszTemp,TEXT("0x%016I64x"), lpJobQueue->lpParentJob->UniqueId);
wstrCommandText += tszTemp;
wstrCommandText += TEXT("\"\t");
//
// Submition time
//
if (bSubmissionTime)
{
wstring wstrTime;
if (!GetFaxTimeAsString (&tmSubmission, wstrTime))
{
DebugPrintEx(
DEBUG_ERR,
TEXT("GetFaxTimeAsString Failed (ec: %ld)"),
GetLastError());
return FALSE;
}
wstrCommandText += FilteredLogString(wstrTime.c_str());
}
wstrCommandText += TEXT("\t");
//
// Originaly scheduled time
//
if (bOriginalTime)
{
wstring wstrTime;
if (!GetFaxTimeAsString (&tmOriginal, wstrTime))
{
DebugPrintEx(
DEBUG_ERR,
TEXT("GetFaxTimeAsString Failed (ec: %ld)"),
GetLastError());
return FALSE;
}
wstrCommandText += FilteredLogString(wstrTime.c_str());
}
wstrCommandText += TEXT("\t\"");
//
// Status
//
if (JS_CANCELED == lpJobQueue->JobStatus)
{
wstrCommandText += FilteredLogString(GetString(IDS_CANCELED));
wstrCommandText += TEXT("\"\t\"");
//
// Fill the empty columns with NULL information
//
wstrCommandText += TEXT("\"\t\""); // ErrorDesc
wstrCommandText += TEXT("\"\t"); // Error Code
wstrCommandText += TEXT("\t"); // StartTime
wstrCommandText += TEXT("\t\""); // EndTime
wstrCommandText += TEXT("\"\t\""); // Device
wstrCommandText += TEXT("\"\t\""); // DialedNumber
wstrCommandText += TEXT("\"\t\""); // CSID
wstrCommandText += TEXT("\"\t"); // TSID
wstrCommandText += TEXT("\t"); // Pages
}
else
{
// Completed/Failed/Aborted jobs only
Assert (lpJobQueue->JobEntry);
Assert (lpJobQueue->JobEntry->LineInfo);
switch (lpJobQueue->JobEntry->FSPIJobStatus.dwJobStatus)
{
case FSPI_JS_FAILED:
case FSPI_JS_FAILED_NO_RETRY:
case FSPI_JS_DELETED:
wstrCommandText += FilteredLogString(GetString(IDS_FAILED_SEND));
break;
case FSPI_JS_COMPLETED :
wstrCommandText += FilteredLogString(GetString(FPS_COMPLETED));
break;
case FSPI_JS_ABORTED :
wstrCommandText += FilteredLogString(GetString(IDS_CANCELED));
break;
default:
DebugPrintEx(
DEBUG_ERR,
TEXT("Invalid FSPI_JS status: 0x%08X for JobId: %ld"),
lpJobQueue->JobStatus,
lpJobQueue->JobId);
Assert(FSPI_JS_DELETED == lpJobQueue->JobEntry->FSPIJobStatus.dwJobStatus); // ASSERT_FALSE
}
wstrCommandText += TEXT("\"\t\"");
//
// ErrorDesc
//
wstring wstrErr;
if (lstrlen(lpJobQueue->JobEntry->ExStatusString))
{
//
// The FSP provided extended status string
//
wstrErr = lpJobQueue->JobEntry->ExStatusString;
}
else if (lpJobQueue->JobEntry->FSPIJobStatus.dwExtendedStatus == 0)
{
//
// No extended status
//
wstrErr = TEXT(" ");
}
else
{
//
// Well known extended status
//
LPTSTR ResStr = MapFSPIJobExtendedStatusToString(lpJobQueue->JobEntry->FSPIJobStatus.dwExtendedStatus);
if (NULL == ResStr)
{
ASSERT_FALSE;
wstrErr = TEXT(" ");
DebugPrintEx(
DEBUG_ERR,
TEXT("Unexpected extended status. Extended Status: %ld, Provider: %s"),
lpJobQueue->JobEntry->FSPIJobStatus.dwExtendedStatus,
lpJobQueue->JobEntry->LineInfo->Provider->ImageName);
}
else
{
wstrErr = ResStr;
}
}
wstrCommandText += FilteredLogString(wstrErr.c_str());
wstrCommandText += TEXT("\"\t\"");
//
// Error Code
//
if (lpJobQueue->JobEntry->FSPIJobStatus.dwExtendedStatus == 0)
{
wstrErr = TEXT(" ");
}
else
{
swprintf(tszTemp, TEXT("0x%08x"), lpJobQueue->JobEntry->FSPIJobStatus.dwExtendedStatus);
wstrErr = tszTemp;
}
wstrCommandText += wstrErr;
wstrCommandText += TEXT("\"\t");
//
// StartTime
//
if (bStartTime)
{
wstring wstrTime;
if (!GetFaxTimeAsString (&tmStart, wstrTime))
{
DebugPrintEx(
DEBUG_ERR,
TEXT("GetFaxTimeAsString Failed (ec: %ld)"),
GetLastError());
return FALSE;
}
wstrCommandText += FilteredLogString(wstrTime.c_str());
}
wstrCommandText += TEXT("\t");
//
// EndTime
//
if (bEndTime)
{
wstring wstrTime;
if (!GetFaxTimeAsString (&tmEnd, wstrTime))
{
DebugPrintEx(
DEBUG_ERR,
TEXT("GetFaxTimeAsString Failed (ec: %ld)"),
GetLastError());
return FALSE;
}
wstrCommandText += FilteredLogString(wstrTime.c_str());
}
wstrCommandText += TEXT("\t\"");
//
// Device
//
wstrCommandText += FilteredLogString(lpJobQueue->JobEntry->LineInfo->DeviceName);
wstrCommandText += TEXT("\"\t\"");
//
// DialedNumber
//
if (wcslen (lpJobQueue->JobEntry->DisplayablePhoneNumber))
{
// The canonical number was translated to displayable number
wstrCommandText += FilteredLogString(lpJobQueue->JobEntry->DisplayablePhoneNumber);
}
else
{
// The canonical number was not translated
wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrFaxNumber);
}
wstrCommandText += TEXT("\"\t\"");
//
// CSID
//
wstrCommandText += FilteredLogString(lpJobQueue->JobEntry->FSPIJobStatus.lpwstrRemoteStationId);
wstrCommandText += TEXT("\"\t\"");
//
// TSID
//
wstrCommandText += FilteredLogString(lpJobQueue->JobEntry->LineInfo->Tsid);
wstrCommandText += TEXT("\"\t");
//
// Pages
//
swprintf(tszTemp, TEXT("%ld"),lpJobQueue->JobEntry->FSPIJobStatus.dwPageCount);
wstrCommandText += tszTemp;
wstrCommandText += TEXT("\t");
}
// Common for Canceled and Failed/Completed/Aborted Jobs
//
// Total pages
//
swprintf(tszTemp, TEXT("%ld"),lpJobQueue->lpParentJob->PageCount);
wstrCommandText += tszTemp;
wstrCommandText += TEXT("\t\"");
//
// Queue file name
//
wstrCommandText += FilteredLogString(lpJobQueue->QueueFileName);
wstrCommandText += TEXT("\"\t\"");
//
// Document
//
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->JobParamsEx.lptstrDocumentName);
wstrCommandText += TEXT("\"\t");
//
// File size
//
swprintf(tszTemp, TEXT("%ld"), lpJobQueue->lpParentJob->FileSize);
wstrCommandText += tszTemp;
wstrCommandText += TEXT("\t");
//
// Retries
//
swprintf(tszTemp, TEXT("%d"), lpJobQueue->SendRetries);
wstrCommandText += tszTemp;
wstrCommandText += TEXT("\t\"");
//
// ServerCoverPage
//
if (lpJobQueue->lpParentJob->CoverPageEx.bServerBased == TRUE)
{
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->CoverPageEx.lptstrCoverPageFileName);
}
else
{
wstrCommandText += TEXT(" ");
}
wstrCommandText += TEXT("\"\t\"");
//
// Cover page subject
//
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->CoverPageEx.lptstrSubject);
wstrCommandText += TEXT("\"\t\"");
//
// Cover page note
//
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->CoverPageEx.lptstrNote);
wstrCommandText += TEXT("\"\t\"");
//
// User Name
//
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->UserName);
wstrCommandText += TEXT("\"\t\"");
//
// Sender Name
//
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrName);
wstrCommandText += TEXT("\"\t\"");
//
// Sender FaxNumber
//
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrFaxNumber);
wstrCommandText += TEXT("\"\t\"");
//
// Sender Company
//
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrCompany);
wstrCommandText += TEXT("\"\t\"");
//
// Sender Street
//
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrStreetAddress);
wstrCommandText += TEXT("\"\t\"");
//
// Sender City
//
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrCity);
wstrCommandText += TEXT("\"\t\"");
//
// Sender ZipCode
//
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrZip);
wstrCommandText += TEXT("\"\t\"");
//
// Sender Country
//
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrCountry);
wstrCommandText += TEXT("\"\t\"");
//
// Sender Title
//
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrTitle);
wstrCommandText += TEXT("\"\t\"");
//
// Sender Department
//
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrDepartment);
wstrCommandText += TEXT("\"\t\"");
//
// Sender Office
//
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrOfficeLocation);
wstrCommandText += TEXT("\"\t\"");
//
// Sender HomePhone
//
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrHomePhone);
wstrCommandText += TEXT("\"\t\"");
//
// Sender OfficePhone
//
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrOfficePhone);
wstrCommandText += TEXT("\"\t\"");
//
// Sender EMail
//
wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrEmail);
wstrCommandText += TEXT("\"\t\"");
//
// Recipient Name
//
wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrName);
wstrCommandText += TEXT("\"\t\"");
//
// Recipient FaxNumber
//
wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrFaxNumber);
wstrCommandText += TEXT("\"\t\"");
//
// Recipient Company
//
wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrCompany);
wstrCommandText += TEXT("\"\t\"");
//
// Recipient Street
//
wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrStreetAddress);
wstrCommandText += TEXT("\"\t\"");
//
// Recipient City
//
wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrCity);
wstrCommandText += TEXT("\"\t\"");
//
// Recipient ZipCode
//
wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrZip);
wstrCommandText += TEXT("\"\t\"");
//
// Recipient Country
//
wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrCountry);
wstrCommandText += TEXT("\"\t\"");
//
// Recipient Title
//
wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrTitle);
wstrCommandText += TEXT("\"\t\"");
//
// Recipient Department
//
wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrDepartment);
wstrCommandText += TEXT("\"\t\"");
//
// Recipient Office
//
wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrOfficeLocation);
wstrCommandText += TEXT("\"\t\"");
//
// Recipient HomePhone
//
wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrHomePhone);
wstrCommandText += TEXT("\"\t\"");
//
// Recipient OfficePhone
//
wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrOfficePhone);
wstrCommandText += TEXT("\"\t\"");
//
// Recipient EMail
//
wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrEmail);
wstrCommandText += TEXT("\"\t\"");
//
// BillingCode
//
wstrCommandText += FilteredLogString(lpJobQueue->SenderProfile.lptstrBillingCode);
wstrCommandText += TEXT("\"\r\n");
DebugPrintEx(DEBUG_MSG,
TEXT("Outboun SQL statement: %s"),
wstrCommandText.c_str());
return TRUE;
} // GetOutboundCommandText
//*********************************************************************************
//* Name: InitializeLoggingStringTables()
//* Author: Oded Sacher
//* Date: Oct 19, 1999
//*********************************************************************************
//* DESCRIPTION:
//* Initializes the Activity Logging string tables (Inbox and Outbox)
//*
//*
//* PARAMETERS: None
//*
//* RETURN VALUE:
//* Win32 error code.
//*********************************************************************************
DWORD
InitializeLoggingStringTables(
VOID
)
{
DWORD i;
DWORD err = ERROR_SUCCESS;
HINSTANCE hInstance;
TCHAR Buffer[MAX_PATH];
DEBUG_FUNCTION_NAME(TEXT("InitializeLoggingStringTables"));
hInstance = GetResInstance(NULL);
if(!hInstance)
{
return GetLastError();
}
for (i=0; i<gc_dwCountInboxTable; i++)
{
if (LoadString(hInstance,
g_InboxTable[i].FieldStringResourceId,
Buffer,
sizeof(Buffer)/sizeof(TCHAR)))
{
g_InboxTable[i].String = (LPTSTR) MemAlloc( StringSize( Buffer ) );
if (!g_InboxTable[i].String)
{
DebugPrintEx(DEBUG_ERR,
TEXT("Failed to allocate memory"));
err = ERROR_OUTOFMEMORY;
goto CleanUp;
}
else
{
_tcscpy( g_InboxTable[i].String, Buffer );
}
}
else
{
err = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("LoadString failed, Code:%d"),err);
goto CleanUp;
}
}
for (i=0; i<gc_dwCountOutboxTable; i++)
{
if (LoadString(hInstance,
g_OutboxTable[i].FieldStringResourceId,
Buffer,
sizeof(Buffer)/sizeof(TCHAR)))
{
g_OutboxTable[i].String = (LPTSTR) MemAlloc( StringSize( Buffer ) );
if (!g_OutboxTable[i].String)
{
DebugPrintEx(DEBUG_ERR,
TEXT("Failed to allocate memory"));
err = ERROR_OUTOFMEMORY;
goto CleanUp;
}
else
{
_tcscpy( g_OutboxTable[i].String, Buffer );
}
}
else
{
err = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("LoadString failed, Code:%d"),err);
goto CleanUp;
}
}
Assert (ERROR_SUCCESS == err);
return ERROR_SUCCESS;
CleanUp:
Assert (err != ERROR_SUCCESS);
for (i=0; i<gc_dwCountInboxTable; i++)
{
MemFree (g_InboxTable[i].String);
g_InboxTable[i].String = NULL;
}
for (i=0; i<gc_dwCountOutboxTable; i++)
{
MemFree (g_OutboxTable[i].String);
g_OutboxTable[i].String = NULL;
}
return err;
} // InitializeLoggingStringTables
//*********************************************************************************
//* Name: FilteredLogString
//* Author: Eran Yariv
//* Date: Feb 19, 2002
//*********************************************************************************
//* DESCRIPTION:
//* This function is used to filter strings that go into the log files.
//*
//* PARAMETERS:
//* [IN] LPCWSTR lpcwstrSrc
//* The string to filter
//*
//*
//* RETURN VALUE:
//* Filtered string
//*
//* NOTE: The function might throw STL string exceptions.
//*
//*********************************************************************************
static
wstring
FilteredLogString (LPCWSTR lpcwstrSrc) throw (exception)
{
DEBUG_FUNCTION_NAME(TEXT("FilteredLogString"));
if (!lpcwstrSrc)
{
return EMPTY_LOG_STRING;
}
wstring wstrResult = lpcwstrSrc;
//
// Replace new lines ('\n') with one space (' ')
//
wstring::size_type position;
while (wstring::npos != (position = wstrResult.find (TEXT('\n'))))
{
wstrResult[position] = TEXT(' ');
}
//
// Replace carriage returns ('\r') with one space (' ')
//
while (wstring::npos != (position = wstrResult.find (TEXT('\r'))))
{
wstrResult[position] = TEXT(' ');
}
//
// Replace double quotes ('"') with single quotes ('\'')
//
while (wstring::npos != (position = wstrResult.find (TEXT('"'))))
{
wstrResult[position] = TEXT('\'');
}
//
// Replace tabs ('"') with 4 spaces (" ")
//
while (wstring::npos != (position = wstrResult.find (TEXT('\t'))))
{
wstrResult.replace (position, 1, 4, TEXT(' '));
}
return wstrResult;
} // FilteredLogString
//*********************************************************************************
//* Name: GetFaxTimeAsString
//* Author: Oded Sacher
//* Date: Oct 19, 1999
//*********************************************************************************
//* DESCRIPTION:
//* This function is used to convert a fax time to a string.
//*
//* PARAMETERS:
//* [IN] SYSTEMTIME* UniversalTime
//* Fax time
//*
//* [OUT] wstring &wstrTime
//* The output string.
//*
//*
//* RETURN VALUE:
//* TRUE for success, FALSE otherwise.
//*
//* NOTE: The function might throw STL string exceptions.
//*
//*********************************************************************************
static
BOOL
GetFaxTimeAsString(
SYSTEMTIME* UniversalTime,
wstring &wstrTime) throw (exception)
{
DWORD Res;
SYSTEMTIME LocalTime;
TIME_ZONE_INFORMATION LocalTimeZone;
DEBUG_FUNCTION_NAME(TEXT("GetFaxTimeAsString"));
Res = GetTimeZoneInformation(&LocalTimeZone);
if (Res == TIME_ZONE_ID_INVALID)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Failed to get local time zone info (ec: %ld)"),
GetLastError());
return FALSE;
}
else
{
if (!SystemTimeToTzSpecificLocalTime( &LocalTimeZone, UniversalTime, &LocalTime))
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Failed to convert universal system time to local system time (ec: %ld)"),
GetLastError());
return FALSE;
}
}
TCHAR tszTime[100];
_stprintf(tszTime,
TEXT("%d/%d/%d %02d:%02d:%02d"),
LocalTime.wMonth,
LocalTime.wDay,
LocalTime.wYear,
LocalTime.wHour,
LocalTime.wMinute,
LocalTime.wSecond);
wstrTime = tszTime;
return TRUE;
} // GetFaxTimeAsString
static
DWORD
CreateLogFile(DWORD dwFileType,LPCWSTR lpcwstrDBPath, LPHANDLE phFile)
/*++
Routine name : CreateLogFile
Routine description:
According to the selected dwFileType, this function creates an activity log file
Author:
Caliv Nir (t-nicali), Nov, 2001
Arguments:
dwFileType [in] - the file to create (inbox or outbox)
o ACTIVITY_LOG_INBOX for inbox
o ACTIVITY_LOG_OUTBOX for outbox
lpcwstrDBPath [in] - the path to the activity logging folder
phFile [out] - handle to the created log file
Return Value:
Win32 Error codes
Remarks:
--*/
{
HANDLE hFile = INVALID_HANDLE_VALUE;
WCHAR wszFileName[MAX_PATH] = {0};
LARGE_INTEGER FileSize= {0};
DWORD dwBytesWritten;
DWORD dwFilePointer;
int Count = 0 ;
DWORD dwRes = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("CreateLogFile"));
Assert (phFile);
Assert (lpcwstrDBPath);
Assert ( (dwFileType==ACTIVITY_LOG_INBOX) || (dwFileType==ACTIVITY_LOG_OUTBOX) );
Count = _snwprintf (wszFileName,
MAX_PATH -1,
TEXT("%s\\%s"),
lpcwstrDBPath,
((dwFileType == ACTIVITY_LOG_INBOX) ? ACTIVITY_LOG_INBOX_FILE : ACTIVITY_LOG_OUTBOX_FILE)
);
if (Count < 0)
{
//
// We already checked for max dir path name.
//
DebugPrintEx(
DEBUG_ERR,
TEXT("_snwprintf Failed, File name bigger than MAX_PATH"));
dwRes = ERROR_BUFFER_OVERFLOW;
goto exit;
}
hFile = SafeCreateFile(
wszFileName, // file name
GENERIC_WRITE, // access mode
FILE_SHARE_READ, // share mode
NULL, // SD
OPEN_ALWAYS, // how to create
FILE_ATTRIBUTE_NORMAL, // file attributes
NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
dwRes = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("CreateFile failed (ec: %ld)"),
dwRes);
goto exit;
}
if (!GetFileSizeEx (hFile, &FileSize))
{
dwRes = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("GetFileSizeEx failed (ec: %ld)"),
dwRes);
goto exit;
}
if (0 == FileSize.QuadPart)
{
//
// New file was created, add UNICODE header
//
USHORT UnicodeHeader = 0xfeff;
if (!WriteFile( hFile,
&UnicodeHeader,
sizeof(UnicodeHeader),
&dwBytesWritten,
NULL))
{
dwRes = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("WriteFile failed (ec: %ld)"),
dwRes);
goto exit;
}
//
// Add the first line (Columns name)
//
wstring wstrHeader;
try
{
GetTableColumnsText((dwFileType == ACTIVITY_LOG_INBOX) ? INBOX_TABLE : OUTBOX_TABLE, wstrHeader);
}
catch (exception &ex)
{
dwRes = ERROR_OUTOFMEMORY;
DebugPrintEx(
DEBUG_ERR,
TEXT("GetTableColumnsText caused exception (%S)"),
ex.what());
goto exit;
}
if (!WriteFile( hFile,
wstrHeader.c_str(),
wstrHeader.length() * sizeof(WCHAR),
&dwBytesWritten,
NULL))
{
dwRes = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("WriteFile failed (ec: %ld)"),
dwRes);
goto exit;
}
}
else
{
dwFilePointer = SetFilePointer( hFile, // handle to file
0, // bytes to move pointer
NULL, // bytes to move pointer
FILE_END // starting point
);
if (INVALID_SET_FILE_POINTER == dwFilePointer)
{
dwRes = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("SetFilePointer failed (ec: %ld)"),
dwRes);
goto exit;
}
}
*phFile = hFile;
Assert (ERROR_SUCCESS == dwRes);
exit:
if (ERROR_SUCCESS != dwRes)
{
//
// The activity logging will halt because we couldn't complete CreateLogFile().
//
if (*phFile != INVALID_HANDLE_VALUE)
{
CloseHandle(*phFile);
*phFile = INVALID_HANDLE_VALUE;
}
if (dwFileType == ACTIVITY_LOG_INBOX)
{
g_ActivityLoggingConfig.bLogIncoming = FALSE;
}
else
{
g_ActivityLoggingConfig.bLogOutgoing = FALSE;
}
//
// Post an event log entry
//
FaxLog(
FAXLOG_CATEGORY_INIT,
(dwFileType == ACTIVITY_LOG_INBOX)?FAXLOG_CATEGORY_INBOUND:FAXLOG_CATEGORY_OUTBOUND,
2,
MSG_LOGGING_NOT_INITIALIZED,
g_ActivityLoggingConfig.lptstrDBPath,
DWORD2DECIMAL(dwRes)
);
if (INVALID_HANDLE_VALUE != hFile)
{
if (!CloseHandle (hFile))
{
DebugPrintEx(DEBUG_ERR,
TEXT("CloseHandle failed (ec: %ld)"),
GetLastError());
}
}
}
return dwRes;
} // CreateLogFile
static
BOOL
LogFileLimitReached(DWORD dwFileToCheck)
/*++
Routine name : LogFileLimitReached
Routine description:
According to the selected log limit criteria, this function checks to see wheter Activity log file
have reached it's limit.
Author:
Caliv Nir (t-nicali), Nov, 2001
Arguments:
dwFileToCheck [in] - the file to be checked (inbox or outbox)
o ACTIVITY_LOG_INBOX for inbox
o ACTIVITY_LOG_OUTBOX for outbox
Return Value:
TRUE - if the limit have been reached
Remarks:
Call this function only if activity logging is enabled for checked the log file !
--*/
{
BOOL bActivityLogEnabled = FALSE;
HANDLE hLogFile = INVALID_HANDLE_VALUE;
DEBUG_FUNCTION_NAME(TEXT("LogFileLimitReached"));
Assert ( (dwFileToCheck==ACTIVITY_LOG_INBOX) || (dwFileToCheck==ACTIVITY_LOG_OUTBOX) );
Assert ( g_ActivityLoggingConfig.bLogIncoming || g_ActivityLoggingConfig.bLogOutgoing );
if ( g_ActivityLoggingConfig.dwLogLimitCriteria == ACTIVITY_LOG_LIMIT_CRITERIA_NONE )
{
//
// activity logging limiting is disabled so no limit checking is needed
//
goto Exit;
}
hLogFile = (dwFileToCheck==ACTIVITY_LOG_INBOX)? g_hInboxActivityLogFile : g_hOutboxActivityLogFile;
//
// activity logging is enabled so the handle must be valid
//
Assert (hLogFile != INVALID_HANDLE_VALUE);
if ( g_ActivityLoggingConfig.dwLogLimitCriteria == ACTIVITY_LOG_LIMIT_CRITERIA_SIZE )
{
//
// Checking limit according to file size in Mbytes
//
LARGE_INTEGER FileSize = {0};
//
// Check the file size
//
if( !GetFileSizeEx( hLogFile,&FileSize ) )
{
DebugPrintEx(DEBUG_ERR,
TEXT("GetFileSizeEx failed (ec=%ld))"),
GetLastError()
);
goto Exit;
}
//
// Compare it to limit
//
if (FileSize.QuadPart >= ( g_ActivityLoggingConfig.dwLogSizeLimit * 1I64 * 1024I64 * 1024I64 )) // dwLogSizeLimit is in Mbytes
{
//
// File exceeded the given size limit
//
return TRUE;
}
}
else
if ( g_ActivityLoggingConfig.dwLogLimitCriteria == ACTIVITY_LOG_LIMIT_CRITERIA_AGE)
{
//
// Checking limit according to file age in months
//
FILETIME FileTimeCreationTime;
//
// Check file creation time (the creation time is the first time that something was writen into this file)
//
if ( !GetFileTime( hLogFile, // handle to file
&FileTimeCreationTime, // creation time
NULL, // last access time
NULL // last write time
)
)
{
DebugPrintEx(DEBUG_ERR,
TEXT("GetFileTime failed (ec=%ld))"),
GetLastError()
);
goto Exit;
}
SYSTEMTIME SystemTimeCreationTime = {0};
if ( !FileTimeToSystemTime( &FileTimeCreationTime, // file time to convert
&SystemTimeCreationTime // receives system time
)
)
{
DebugPrintEx(DEBUG_ERR,
TEXT("FileTimeToSystemTime failed (ec=%ld))"),
GetLastError()
);
goto Exit;
}
//
// Find out current time
//
SYSTEMTIME CurrentTime = {0};
GetSystemTime(&CurrentTime);
//
// Calculate monthe diff between current time and the time of the first write to the log file.
//
DWORD dwMonthDiff = (CurrentTime.wYear - SystemTimeCreationTime.wYear) * 12 + CurrentTime.wMonth - SystemTimeCreationTime.wMonth;
if (dwMonthDiff >= g_ActivityLoggingConfig.dwLogAgeLimit)
{
//
// the file reached the age limit
//
return TRUE;
}
}
else
{
//
// Bad parameter in g_ActivityLoggingConfig.dwLogLimitCriteria
//
ASSERT_FALSE;
}
Exit:
return FALSE;
} // LogFileLimitReached
static
DWORD
LogFileLimitReachAction(DWORD dwFileType)
/*++
Routine name : LogFileLimitReachAction
Routine description:
According to the selected log limit reached action criteria, take the action.
Author:
Caliv Nir (t-nicali), Nov, 2001
Arguments:
dwFileType [in] - the file to handle (inbox or outbox)
o ACTIVITY_LOG_INBOX for inbox
o ACTIVITY_LOG_OUTBOX for outbox
Return Value:
TRUE - if the limit have been reached
Remarks:
Call this function only if activity logging is enabled *and* Limiting the activity files is enabled
--*/
{
HANDLE hLogFile = INVALID_HANDLE_VALUE;
DWORD dwRes = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("LogFileLimitReachAction"));
//
// Parameter check (Private function)
//
Assert ( (dwFileType==ACTIVITY_LOG_INBOX) || (dwFileType==ACTIVITY_LOG_OUTBOX) );
Assert ( (dwFileType==ACTIVITY_LOG_INBOX && g_ActivityLoggingConfig.bLogIncoming) ||
(dwFileType==ACTIVITY_LOG_OUTBOX && g_ActivityLoggingConfig.bLogOutgoing) );
Assert ( g_ActivityLoggingConfig.dwLogLimitCriteria != ACTIVITY_LOG_LIMIT_CRITERIA_NONE );
hLogFile = (dwFileType==ACTIVITY_LOG_INBOX)? g_hInboxActivityLogFile : g_hOutboxActivityLogFile;
if (g_ActivityLoggingConfig.dwLimitReachedAction == ACTIVITY_LOG_LIMIT_REACHED_ACTION_DELETE)
{
//
// Delete the log file
//
dwRes = DeleteLogActivityFile(dwFileType);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(DEBUG_ERR,
TEXT("DeleteLogActivityFile failed (ec: %ld)"),
dwRes);
goto exit;
}
}
else
if (g_ActivityLoggingConfig.dwLimitReachedAction == ACTIVITY_LOG_LIMIT_REACHED_ACTION_COPY)
{
//
// Replace the log file with a fresh copy
//
dwRes = ReplaceLogActivityFile(dwFileType);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(DEBUG_ERR,
TEXT("DeleteLogActivityFile failed (ec: %ld)"),
dwRes);
goto exit;
}
}
else
{
//
// Bad parameter in g_ActivityLoggingConfig.dwLimitReachedAction
//
ASSERT_FALSE;
}
Assert(ERROR_SUCCESS == dwRes);
exit:
return dwRes;
} // LogFileLimitReachAction
static
DWORD
DeleteLogActivityFile(DWORD dwFileType)
/*++
Routine name : DeleteLogActivityFile
Routine description:
According to dwFileType delete the proper activity log file and create a new one
Author:
Caliv Nir (t-nicali), Nov, 2001
Arguments:
dwFileType [in] - the file to Delete (inbox or outbox)
o ACTIVITY_LOG_INBOX for inbox
o ACTIVITY_LOG_OUTBOX for outbox
Return Value:
TRUE - if the limit have been reached
Remarks:
Call this function only if activity logging is enabled *and* Limiting the activity files is enabled
--*/
{
LPWSTR strFullFileName = NULL;
LPHANDLE phFile=NULL;
DWORD dwRes = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("DeleteLogActivityFile"));
Assert ( (dwFileType==ACTIVITY_LOG_INBOX) || (dwFileType==ACTIVITY_LOG_OUTBOX) );
Assert ( g_ActivityLoggingConfig.dwLimitReachedAction == ACTIVITY_LOG_LIMIT_REACHED_ACTION_DELETE );
Assert ( (dwFileType==ACTIVITY_LOG_INBOX && g_ActivityLoggingConfig.bLogIncoming) ||
(dwFileType==ACTIVITY_LOG_OUTBOX && g_ActivityLoggingConfig.bLogOutgoing) );
Assert ( g_ActivityLoggingConfig.lptstrDBPath );
strFullFileName = BuildFullFileName(g_ActivityLoggingConfig.lptstrDBPath, ((dwFileType == ACTIVITY_LOG_INBOX)? ACTIVITY_LOG_INBOX_FILE : ACTIVITY_LOG_OUTBOX_FILE) );
if (NULL == strFullFileName)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
DebugPrintEx(DEBUG_ERR,
TEXT("BuildFullFileName() failed.")
);
goto exit;
}
phFile = (dwFileType == ACTIVITY_LOG_INBOX) ? &g_hInboxActivityLogFile : &g_hOutboxActivityLogFile ;
Assert(*phFile);
if (!CloseHandle(*phFile))
{
dwRes = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("CloseHandle failed (ec=%ld)."),
dwRes
);
goto exit;
}
*phFile = INVALID_HANDLE_VALUE;
if (!DeleteFile(strFullFileName))
{
dwRes = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("DeleteFile failed (ec=%ld)."),
dwRes
);
//
// Try to roll back and use the old file
//
}
//
// Create new logging file
//
dwRes = CreateLogFile(dwFileType,g_ActivityLoggingConfig.lptstrDBPath,phFile);
if ( ERROR_SUCCESS != dwRes)
{
DebugPrintEx( DEBUG_ERR,
TEXT("CreateLogFile() Failed. (ec=%ld)"),
dwRes
);
goto exit;
}
//
// Because the creation time of the file is important for log limit
// mechanism, we make sure to update the file creation time that may
// not be updated (Due to file system caching mechanism for example)
//
if (!SetFileToCurrentTime(*phFile))
{
DebugPrintEx( DEBUG_ERR,
TEXT("SetFileToCurrentTime() Failed. (ec=%ld)"),
dwRes
);
}
DebugPrintEx( DEBUG_MSG,
TEXT("Activity log file was deleted and replaced with fresh copy.")
);
Assert(ERROR_SUCCESS == dwRes);
exit:
MemFree(strFullFileName);
return dwRes;
} // DeleteLogActivityFile
static
DWORD
ReplaceLogActivityFile(DWORD dwFileType)
/*++
Routine name : ReplaceLogActivityFile
Routine description:
According to dwFileType copy the proper activity log file and create a new one
Author:
Caliv Nir (t-nicali), Nov, 2001
Arguments:
dwFileType [in] - the file to Replace (inbox or outbox)
o ACTIVITY_LOG_INBOX for inbox
o ACTIVITY_LOG_OUTBOX for outbox
Return Value:
Win32 error code
Remarks:
Call this function only if activity logging is enabled *and* Limiting the activity files is enabled
--*/
{
SYSTEMTIME LogStartTime = {0};
SYSTEMTIME LogEndTime = {0};
FILETIME FirstWriteTime = {0};
FILETIME LastWriteTime= {0};
LPWSTR strOldFileName = NULL;
WCHAR strNewFileName[MAX_PATH] = {0};
LPWSTR strNameTemplate = NULL;
LPWSTR strNewFullFileName = NULL;
LPHANDLE phFile=NULL;
DWORD dwRes = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("ReplaceLogActivityFile"));
Assert ( (dwFileType==ACTIVITY_LOG_INBOX) || (dwFileType==ACTIVITY_LOG_OUTBOX) );
Assert ( g_ActivityLoggingConfig.dwLimitReachedAction == ACTIVITY_LOG_LIMIT_REACHED_ACTION_COPY );
Assert ( (dwFileType==ACTIVITY_LOG_INBOX && g_ActivityLoggingConfig.bLogIncoming) ||
(dwFileType==ACTIVITY_LOG_OUTBOX && g_ActivityLoggingConfig.bLogOutgoing) );
Assert ( g_ActivityLoggingConfig.lptstrDBPath );
phFile = (dwFileType == ACTIVITY_LOG_INBOX) ? &g_hInboxActivityLogFile : &g_hOutboxActivityLogFile;
Assert (INVALID_HANDLE_VALUE != *phFile);
//
// find out the file's first and last write time
//
if (!GetFileTime( *phFile, // handle to file
&FirstWriteTime, // creation time
NULL, // last access time
&LastWriteTime // last write time
)
)
{
dwRes = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("GetFileTime() failed. (ec=%ld)"),
dwRes
);
goto exit;
}
if (!FileTimeToSystemTime( &FirstWriteTime, // file time to convert
&LogStartTime // receives system time
)
)
{
dwRes = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("FileTimeToSystemTime() failed. (ec=%ld)"),
dwRes
);
goto exit;
}
if (!FileTimeToSystemTime( &LastWriteTime, // file time to convert
&LogEndTime // receives system time
)
)
{
dwRes = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("FileTimeToSystemTime() failed. (ec=%ld)"),
dwRes
);
goto exit;
}
//
// build the current log file name
//
strOldFileName = BuildFullFileName(g_ActivityLoggingConfig.lptstrDBPath, ((dwFileType == ACTIVITY_LOG_INBOX)? ACTIVITY_LOG_INBOX_FILE : ACTIVITY_LOG_OUTBOX_FILE) );
if (NULL == strOldFileName)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
DebugPrintEx(DEBUG_ERR,
TEXT("BuildFullFileName() failed.")
);
goto exit;
}
//
// build the copy file name according to the first and last write times
//
strNameTemplate = (dwFileType == ACTIVITY_LOG_INBOX) ? ACTIVITY_LOG_INBOX_FILENAME_TEMPLATE : ACTIVITY_LOG_OUTBOX_FILENAME_TEMPLATE;
_snwprintf ( strNewFileName,
ARR_SIZE(strNewFileName)-1,
strNameTemplate, // TEXT("??boxLOG %04d-%02d-%02d through %04d-%02d-%02d.txt") ?? - is "In" or "Out"
LogStartTime.wYear,
LogStartTime.wMonth,
LogStartTime.wDay,
LogEndTime.wYear,
LogEndTime.wMonth,
LogEndTime.wDay
);
strNewFullFileName = BuildFullFileName(g_ActivityLoggingConfig.lptstrDBPath,strNewFileName);
if (NULL == strNewFullFileName)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
DebugPrintEx(DEBUG_ERR,
TEXT("BuildFullFileName() failed.")
);
goto exit;
}
if ( !CloseHandle(*phFile) )
{
dwRes = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("CloseHandle() failed. (ec=%ld)"),
dwRes
);
goto exit;
}
*phFile = INVALID_HANDLE_VALUE;
if ( !MoveFile ( strOldFileName, // file name
strNewFullFileName // new file name
)
)
{
dwRes = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("MoveFileEx() failed. (ec=%ld)"),
dwRes
);
//
// Try to roll back and use the old file
//
}
//
// Create the logging file that was renamed
//
dwRes = CreateLogFile(dwFileType,g_ActivityLoggingConfig.lptstrDBPath,phFile);
if ( ERROR_SUCCESS != dwRes)
{
DebugPrintEx( DEBUG_ERR,
TEXT("CreateLogFile() Failed. (ec=%ld)"),
dwRes
);
goto exit;
}
//
// Because the creation time of the file is important for log limit
// mechanism, we make sure to update the file creation time that may
// not be updated (Due to file system caching mechanism for example)
//
if (!SetFileToCurrentTime(*phFile))
{
DebugPrintEx( DEBUG_ERR,
TEXT("SetFileToCurrentTime() Failed. (ec=%ld)"),
dwRes
);
}
DebugPrintEx( DEBUG_MSG,
TEXT("Activity log file was copied and replaced with fresh copy.")
);
Assert (ERROR_SUCCESS == dwRes);
exit:
MemFree(strOldFileName);
MemFree(strNewFullFileName);
return dwRes;
} // ReplaceLogActivityFile
static
LPTSTR
BuildFullFileName( LPCWSTR strPath,
LPCWSTR strFileName )
/*++
Routine name : BuildFullFileName
Routine description:
Utility function to concat path and file name. -> strPath\strFileName
Author:
Caliv Nir (t-nicali), Nov, 2001
Arguments:
strPath [in] - file path
strFileName [in] - file name
Return Value:
the full file name string
Remarks:
Caller must MemFree the return string
This function works for UNICODE and ANSI (not for MBCS)
--*/
{
LPWSTR strFullFileName = NULL;
DWORD dwNewNameLen = 0;
DEBUG_FUNCTION_NAME(TEXT("BuildFullFileName"));
Assert (strPath && strFileName);
dwNewNameLen = wcslen(strPath) + wcslen(strFileName) + 2; // sizeof path\fileName and null terminator
strFullFileName = (LPTSTR)MemAlloc(dwNewNameLen * sizeof(TCHAR));
if (NULL == strFullFileName)
{
DebugPrintEx(DEBUG_ERR,
TEXT("MemAlloc failed.")
);
goto exit;
}
strFullFileName[dwNewNameLen-1] = TEXT('\0');
//
// Build the full file name
//
_snwprintf (strFullFileName,
dwNewNameLen-1,
TEXT("%s\\%s"),
strPath,
strFileName);
exit:
return strFullFileName;
} // BuildFullFileName
static
BOOL
SetFileToCurrentTime(HANDLE hFile)
/*++
Routine name : SetFileToCurrentTime
Routine description:
Utility function set the creation time of file into current time
Author:
Caliv Nir (t-nicali), Nov, 2001
Arguments:
hFile [in] - file handle
Return Value:
TRUE if successful, FALSE otherwise
Remarks:
hFile - must be a valid file handle
--*/
{
FILETIME ft={0};
SYSTEMTIME st={0};
BOOL bRet = TRUE;
DWORD dwRes;
DEBUG_FUNCTION_NAME(TEXT("SetFileToCurrentTime"));
Assert (INVALID_HANDLE_VALUE != hFile);
//
// Because the creation time of the file is important for log limit
// mechanism, we make sure to update the file creation time that may
// not be updated (Due to file system caching mechanism for example)
//
GetSystemTime(&st); // gets current time
bRet = SystemTimeToFileTime(&st, &ft);
if (FALSE == bRet) // converts to file time format
{
dwRes = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("SystemTimeToFileTime failed (ec: %ld)"),
dwRes);
goto exit;
}
bRet = SetFileTime( hFile, // sets creation time for file
&ft,
(LPFILETIME) NULL,
(LPFILETIME) NULL);
if (FALSE == bRet)
{
dwRes = GetLastError();
DebugPrintEx(DEBUG_ERR,
TEXT("SetFileTime failed (ec: %ld)"),
dwRes);
goto exit;
}
Assert (TRUE == bRet);
exit:
return bRet;
} // SetFileToCurrentTime