1691 lines
54 KiB
C++
1691 lines
54 KiB
C++
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Receipts.cpp
|
|
|
|
Abstract:
|
|
|
|
Implementation of the fax DR/NDR mechanism
|
|
|
|
Author:
|
|
|
|
Eran Yariv (EranY) Feb, 2000
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "faxsvc.h"
|
|
#include "lmcons.h" // Required by lmmsg.h
|
|
#include "lmmsg.h" // Exports NetMessageBufferSend
|
|
#include "htmltags.h"
|
|
|
|
//
|
|
// Static functions:
|
|
//
|
|
static
|
|
BOOL
|
|
TimeToString(
|
|
const FILETIME *pft,
|
|
wstring &wstr
|
|
) throw (exception);
|
|
|
|
static
|
|
BOOL
|
|
PrepareReceiptSubject (
|
|
BOOL bPositive,
|
|
BOOL bBroadcast,
|
|
const JOB_QUEUE *lpcJobQueue,
|
|
LPWSTR * pwstrSubject
|
|
);
|
|
|
|
static
|
|
BOOL
|
|
GetNumericResourceValue (
|
|
int iResourceId,
|
|
DWORD &dwValue
|
|
);
|
|
|
|
static
|
|
BOOL
|
|
AddRecipientLine (
|
|
const JOB_QUEUE *lpcJobQueue,
|
|
BOOL bDisplayError,
|
|
wstring &wstrLine,
|
|
wstring &wstrHTMLLine
|
|
) throw (exception);
|
|
|
|
static
|
|
BOOL
|
|
PrepareReceiptBody(
|
|
BOOL bPositive,
|
|
BOOL bBroadcast,
|
|
const JOB_QUEUE * lpcJobQueue,
|
|
LPCWSTR lpcwstrSubject,
|
|
BOOL bAttachment,
|
|
LPWSTR * ppwstrBody,
|
|
LPWSTR * ppestrHTMLBody
|
|
) throw (exception);
|
|
|
|
static
|
|
BOOL
|
|
PrepareReceiptErrorString (
|
|
const JOB_QUEUE *lpcJobQueue,
|
|
wstring &wstrError
|
|
) throw (exception);
|
|
|
|
|
|
//
|
|
// Implementations
|
|
//
|
|
|
|
|
|
BOOL
|
|
TimeToString(
|
|
const FILETIME *pft,
|
|
wstring &wstr
|
|
) throw (exception)
|
|
/*++
|
|
|
|
Routine name : TimeToString
|
|
|
|
Routine description:
|
|
|
|
Converts a FILETIME to a string, according to system's locale.
|
|
|
|
This function may throw STL exceptions in case of string errors.
|
|
|
|
Author:
|
|
|
|
Eran Yariv (EranY), Feb, 2000
|
|
|
|
Arguments:
|
|
|
|
pft [in] - Pointer to FILETIME
|
|
wstr [out] - Reference to output time string.
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE otherwise.
|
|
In case of failure, call GetLastError() to obtain error code.
|
|
|
|
--*/
|
|
{
|
|
DWORD ec = ERROR_SUCCESS;
|
|
DEBUG_FUNCTION_NAME(TEXT("TimeToString"));
|
|
Assert (pft);
|
|
|
|
FILETIME tmLocalTime;
|
|
SYSTEMTIME tmSystemTime;
|
|
LPWSTR lpwstrTime = NULL;
|
|
int iRequiredBufSize;
|
|
|
|
//
|
|
// Convert time from UTC to local time zone
|
|
//
|
|
if (!FileTimeToLocalFileTime( pft, &tmLocalTime ))
|
|
{
|
|
ec=GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("FileTimeToLocalFileTime failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
if (!FileTimeToSystemTime( &tmLocalTime, &tmSystemTime ))
|
|
{
|
|
ec=GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("FileTimeToSystemTime failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
//
|
|
// Find required string size (in TCHARs)
|
|
//
|
|
iRequiredBufSize = FaxTimeFormat(
|
|
LOCALE_SYSTEM_DEFAULT,
|
|
LOCALE_NOUSEROVERRIDE,
|
|
&tmSystemTime,
|
|
NULL,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
Assert (iRequiredBufSize);
|
|
if (0 == iRequiredBufSize)
|
|
{
|
|
ec=GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("FaxTimeFormat failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
//
|
|
// Allocate string buffer
|
|
//
|
|
WCHAR wszTime[256];
|
|
lpwstrTime = wszTime;
|
|
if (iRequiredBufSize > ARR_SIZE (wszTime))
|
|
{
|
|
//
|
|
// The static buffer is not enough, allocate one from the heap
|
|
//
|
|
lpwstrTime = (LPWSTR) MemAlloc (sizeof (TCHAR) * iRequiredBufSize);
|
|
if (!lpwstrTime)
|
|
{
|
|
ec=GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("MemAlloc failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
}
|
|
//
|
|
// Format time into result string
|
|
//
|
|
if (!FaxTimeFormat(
|
|
LOCALE_SYSTEM_DEFAULT,
|
|
LOCALE_NOUSEROVERRIDE,
|
|
&tmSystemTime,
|
|
NULL,
|
|
lpwstrTime,
|
|
iRequiredBufSize
|
|
))
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("FaxTimeFormat failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
|
|
wstr = lpwstrTime;
|
|
Assert (ERROR_SUCCESS == ec);
|
|
|
|
exit:
|
|
if ((lpwstrTime != wszTime) && (NULL != lpwstrTime))
|
|
{
|
|
//
|
|
// Memory successfully allocated from the heap
|
|
//
|
|
MemFree ((LPVOID)lpwstrTime);
|
|
}
|
|
if (ERROR_SUCCESS != ec)
|
|
{
|
|
SetLastError (ec);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
} // TimeToString
|
|
|
|
BOOL
|
|
PrepareReceiptSubject (
|
|
BOOL bPositive,
|
|
BOOL bBroadcast,
|
|
const JOB_QUEUE *lpcJobQueue,
|
|
LPWSTR * pwstrSubject
|
|
)
|
|
/*++
|
|
|
|
Routine name : PrepareReceiptSubject
|
|
|
|
Routine description:
|
|
|
|
Prepares the receipts subject line to be sent out via mail or a message box
|
|
|
|
Author:
|
|
|
|
Eran Yariv (EranY), Feb, 2000
|
|
|
|
Arguments:
|
|
|
|
bPositive [in] - Did the job(s) complete successfully?
|
|
bBroadcast [in] - Is this the a broadcast job?
|
|
lpcJobQueue [in] - Pointer to job (or broadcast parent job)
|
|
pwstrSubject [out] - Pointer to subject line string.
|
|
The string is allocated by this function.
|
|
If the function succeeded, the caller must call LocalFree() to
|
|
deallocate it.
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE otherwise.
|
|
In case of failure, call GetLastError() to obtain error code.
|
|
|
|
--*/
|
|
{
|
|
DWORD ec = ERROR_SUCCESS;
|
|
DEBUG_FUNCTION_NAME(TEXT("PrepareReceiptSubject"));
|
|
|
|
Assert (lpcJobQueue && pwstrSubject);
|
|
|
|
DWORD dwMsgCount;
|
|
LPDWORD MsgPtr[4] = {0};
|
|
int nMsgStrID;
|
|
|
|
try
|
|
{
|
|
wstring wstrSubject = TEXT("");
|
|
wstring wstrError;
|
|
|
|
if (lpcJobQueue->CoverPageEx.lptstrSubject)
|
|
{
|
|
//
|
|
// Job has a subject
|
|
//
|
|
wstrSubject = lpcJobQueue->CoverPageEx.lptstrSubject;
|
|
wstrSubject.append (TEXT(" "));
|
|
}
|
|
else if (lpcJobQueue->lpParentJob && lpcJobQueue->lpParentJob->CoverPageEx.lptstrSubject)
|
|
{
|
|
//
|
|
// Parent job has a subject
|
|
//
|
|
wstrSubject = lpcJobQueue->lpParentJob->CoverPageEx.lptstrSubject;
|
|
wstrSubject.append (TEXT(" "));
|
|
}
|
|
if (!bBroadcast)
|
|
{
|
|
//
|
|
// Compose subject for single recipient job
|
|
//
|
|
MsgPtr[0] = (LPDWORD)(LPCTSTR)wstrSubject.c_str();
|
|
MsgPtr[1] = (LPDWORD)lpcJobQueue->RecipientProfile.lptstrName;
|
|
MsgPtr[2] = (LPDWORD)lpcJobQueue->RecipientProfile.lptstrFaxNumber;
|
|
|
|
if (bPositive)
|
|
{
|
|
//
|
|
// Success line
|
|
// "Fax <subject> was successfully sent to <name> at <number>"
|
|
//
|
|
if (!MsgPtr[1])
|
|
{
|
|
//
|
|
// Name is not mandatory parameter
|
|
//
|
|
nMsgStrID = MSG_DR_SINGLE_SUBJECT_NONAME;
|
|
}
|
|
else
|
|
{
|
|
nMsgStrID = MSG_DR_SINGLE_SUBJECT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Failure line
|
|
// "Fax <subject> failed to send to <name> at <number> (<last error>)."
|
|
//
|
|
//
|
|
// Get error string
|
|
//
|
|
if (!PrepareReceiptErrorString (lpcJobQueue, wstrError))
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("PrepareReceiptErrorString failed. (ec: %ld)"),
|
|
ec);
|
|
return FALSE;
|
|
}
|
|
MsgPtr[3] = (LPDWORD)wstrError.c_str();
|
|
|
|
if (!MsgPtr[1])
|
|
{
|
|
//
|
|
// Name is not mandatory parameter
|
|
//
|
|
nMsgStrID = MSG_NDR_SINGLE_SUBJECT_NONAME;
|
|
}
|
|
else
|
|
{
|
|
nMsgStrID = MSG_NDR_SINGLE_SUBJECT;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Broadcast case
|
|
//
|
|
Assert (JT_BROADCAST == lpcJobQueue->JobType);
|
|
Assert (lpcJobQueue->RecipientJobs.Flink);
|
|
if (bPositive)
|
|
{
|
|
//
|
|
// Compose subject for a broadcast job - success
|
|
// "Fax <subject> successfully sent to <first name> and all other recipients"
|
|
//
|
|
nMsgStrID = MSG_DR_BROADCAST_SUBJECT;
|
|
|
|
MsgPtr[0] = (LPDWORD)(LPCTSTR)wstrSubject.c_str();
|
|
|
|
PLIST_ENTRY lpNext = lpcJobQueue->RecipientJobs.Flink;
|
|
Assert (lpNext);
|
|
PJOB_QUEUE_PTR lpRecipientsGroupMember;
|
|
lpRecipientsGroupMember = CONTAINING_RECORD( lpNext, JOB_QUEUE_PTR, ListEntry );
|
|
Assert (lpRecipientsGroupMember);
|
|
PJOB_QUEUE pFirstRecipient = lpRecipientsGroupMember->lpJob;
|
|
Assert (pFirstRecipient);
|
|
|
|
MsgPtr[1] = (LPDWORD)pFirstRecipient->RecipientProfile.lptstrName;
|
|
if (!MsgPtr[1])
|
|
{
|
|
//
|
|
// Name is not mandatory parameter
|
|
//
|
|
MsgPtr[1] = (LPDWORD)pFirstRecipient->RecipientProfile.lptstrFaxNumber;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Compose subject for a broadcast job - failure
|
|
// "Fax <subject> was not successfully sent to <x> recipients. Canceled: <y> recipient(s). Failed: <z> recipient(s)"
|
|
//
|
|
nMsgStrID = MSG_NDR_BROADCAST_SUBJECT;
|
|
|
|
MsgPtr[0] = (LPDWORD)(LPCTSTR)wstrSubject.c_str();
|
|
Assert (lpcJobQueue->dwRecipientJobsCount ==
|
|
(lpcJobQueue->dwCanceledRecipientJobsCount +
|
|
lpcJobQueue->dwCompletedRecipientJobsCount +
|
|
lpcJobQueue->dwFailedRecipientJobsCount));
|
|
MsgPtr[1] = (LPDWORD) ULongToPtr(lpcJobQueue->dwRecipientJobsCount);
|
|
MsgPtr[2] = (LPDWORD) ULongToPtr(lpcJobQueue->dwCanceledRecipientJobsCount);
|
|
MsgPtr[3] = (LPDWORD) ULongToPtr(lpcJobQueue->dwFailedRecipientJobsCount);
|
|
}
|
|
}
|
|
//
|
|
// Format the subject buffer (system allocates it)
|
|
//
|
|
dwMsgCount = FormatMessage(
|
|
FORMAT_MESSAGE_FROM_HMODULE |
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY |
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
|
g_hResource,
|
|
nMsgStrID,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
|
|
(LPTSTR)pwstrSubject,
|
|
0,
|
|
(va_list *) MsgPtr
|
|
);
|
|
if (!dwMsgCount)
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("FormatMessage failed. (ec: %ld)"),
|
|
ec);
|
|
return FALSE;
|
|
}
|
|
}
|
|
catch (exception &ex)
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("wstring caused exception (%S)"),
|
|
ex.what());
|
|
SetLastError (ERROR_GEN_FAILURE);
|
|
return FALSE;
|
|
}
|
|
|
|
Assert (ERROR_SUCCESS == ec);
|
|
return TRUE;
|
|
} // PrepareReceiptSubject
|
|
|
|
BOOL
|
|
GetNumericResourceValue (
|
|
int iResourceId,
|
|
DWORD &dwValue
|
|
)
|
|
/*++
|
|
|
|
Routine name : GetNumericResourceValue
|
|
|
|
Routine description:
|
|
|
|
Reads a string resource and converts to a numeric value
|
|
|
|
Author:
|
|
|
|
Eran Yariv (EranY), Feb, 2000
|
|
|
|
Arguments:
|
|
|
|
iResourceId [in] - String resource id
|
|
dwValue [out] - Numeric value
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE otherwise.
|
|
In case of failure, call GetLastError() to obtain error code.
|
|
|
|
--*/
|
|
{
|
|
DEBUG_FUNCTION_NAME(TEXT("GetNumericResourceValue"));
|
|
|
|
if (1 != swscanf (GetString (iResourceId), TEXT("%ld"), &dwValue))
|
|
{
|
|
SetLastError (ERROR_GEN_FAILURE);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
} // GetNumericResourceValue
|
|
|
|
BOOL
|
|
AddRecipientLine (
|
|
const JOB_QUEUE *lpcJobQueue,
|
|
BOOL bDisplayError,
|
|
wstring &wstrLine,
|
|
wstring &wstrHTMLLine
|
|
) throw (exception)
|
|
/*++
|
|
|
|
Routine name : AddRecipientLine
|
|
|
|
Routine description:
|
|
|
|
Appends a recipient table line to a plain text string and html string
|
|
|
|
This function may throw STL exceptions in case of string errors.
|
|
|
|
Author:
|
|
|
|
Eran Yariv (EranY), Feb, 2000
|
|
|
|
Arguments:
|
|
|
|
lpcJobQueue [in] - Recipient job.
|
|
If NULL, the table header lines (2 lines) are appended to the string.
|
|
bDisplayError [in] - TRUE if 'last error' column is to be displayed
|
|
wstrLine [out] - String to append to
|
|
wstrHTMLLine [out] - HTML format string to append to
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE otherwise.
|
|
In case of failure, call GetLastError() to obtain error code.
|
|
|
|
--*/
|
|
{
|
|
DWORD ec = ERROR_SUCCESS;
|
|
DEBUG_FUNCTION_NAME(TEXT("AddRecipientLine"));
|
|
|
|
DWORD dwRecNameWidth;
|
|
DWORD dwRecNumberWidth;
|
|
DWORD dwStartTimeWidth;
|
|
DWORD dwEndTimeWidth;
|
|
DWORD dwRetriesWidth;
|
|
DWORD dwErrorWidth;
|
|
|
|
wstring wstrError;
|
|
|
|
if (!GetNumericResourceValue (IDS_RECEIPT_RECIPIENT_NAME_WIDTH, dwRecNameWidth) ||
|
|
!GetNumericResourceValue (IDS_RECEIPT_RECIPIENT_NUMBER_WIDTH, dwRecNumberWidth) ||
|
|
!GetNumericResourceValue (IDS_RECEIPT_START_TIME_WIDTH, dwStartTimeWidth) ||
|
|
!GetNumericResourceValue (IDS_RECEIPT_END_TIME_WIDTH, dwEndTimeWidth) ||
|
|
!GetNumericResourceValue (IDS_RECEIPT_RETRIES_WIDTH, dwRetriesWidth) ||
|
|
!GetNumericResourceValue (IDS_RECEIPT_LAST_ERROR_WIDTH, dwErrorWidth))
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("GetNumericResourceValue failed. (ec: %ld)"),
|
|
ec);
|
|
return FALSE;
|
|
}
|
|
Assert (dwRecNameWidth && dwRecNumberWidth && dwStartTimeWidth && dwEndTimeWidth && dwRetriesWidth && dwErrorWidth);
|
|
if (!lpcJobQueue)
|
|
{
|
|
//
|
|
// Special case - prepare header for table
|
|
//
|
|
WCHAR wszLine[1024]={0};
|
|
LPCWSTR lpcwstrFormat;
|
|
|
|
if (bDisplayError)
|
|
{
|
|
wstrLine.append (GetString (IDS_FAILED_RECP_LIST_HEADER));
|
|
wstrHTMLLine.append (GetString (IDS_FAILED_RECP_LIST_HEADER));
|
|
lpcwstrFormat = TEXT("\n%-*s %-*s %-*s %-*s %-*s %-*s");
|
|
}
|
|
else
|
|
{
|
|
wstrLine.append (GetString (IDS_COMPLETED_RECP_LIST_HEADER));
|
|
wstrHTMLLine.append (GetString (IDS_COMPLETED_RECP_LIST_HEADER));
|
|
lpcwstrFormat = TEXT("\n%-*s %-*s %-*s %-*s %-*s");
|
|
}
|
|
if (0 > _snwprintf (wszLine,
|
|
ARR_SIZE (wszLine) - 1,
|
|
lpcwstrFormat,
|
|
dwRecNameWidth,
|
|
wstring(GetString (IDS_RECEIPT_RECIPIENT_NAME)).substr(0, dwRecNameWidth-1).c_str(),
|
|
dwRecNumberWidth,
|
|
wstring(GetString (IDS_RECEIPT_RECIPIENT_NUMBER)).substr(0, dwRecNumberWidth-1).c_str(),
|
|
dwStartTimeWidth,
|
|
wstring(GetString (IDS_RECEIPT_START_TIME)).substr(0, dwStartTimeWidth-1).c_str(),
|
|
dwEndTimeWidth,
|
|
wstring(GetString (IDS_RECEIPT_END_TIME)).substr(0, dwEndTimeWidth-1).c_str(),
|
|
dwRetriesWidth,
|
|
wstring(GetString (IDS_RECEIPT_RETRIES)).substr(0, dwRetriesWidth-1).c_str(),
|
|
dwErrorWidth,
|
|
wstring(GetString (IDS_RECEIPT_LAST_ERROR)).substr(0, dwErrorWidth-1).c_str()))
|
|
{
|
|
ec = ERROR_BUFFER_OVERFLOW;
|
|
SetLastError (ec);
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("_snwprintf failed. (ec: %ld)"),
|
|
ec);
|
|
return FALSE;
|
|
}
|
|
wstrLine.append (wszLine);
|
|
|
|
wstrHTMLLine.append (HTML_NEW_LINE);
|
|
wstrHTMLLine.append (TEXT("\n"));
|
|
wstrHTMLLine.append (HTML_TABLE_RAW_START);
|
|
wstrHTMLLine.append (HTML_TABLE_HEADER_START);
|
|
wstrHTMLLine.append (GetString(IDS_RECEIPT_RECIPIENT_NAME));
|
|
wstrHTMLLine.append (HTML_TABLE_HEADER_END);
|
|
wstrHTMLLine.append (HTML_TABLE_HEADER_START);
|
|
wstrHTMLLine.append (GetString(IDS_RECEIPT_RECIPIENT_NUMBER));
|
|
wstrHTMLLine.append (HTML_TABLE_HEADER_END);
|
|
wstrHTMLLine.append (HTML_TABLE_HEADER_START);
|
|
wstrHTMLLine.append (GetString (IDS_RECEIPT_START_TIME));
|
|
wstrHTMLLine.append (HTML_TABLE_HEADER_END);
|
|
wstrHTMLLine.append (HTML_TABLE_HEADER_START);
|
|
wstrHTMLLine.append (GetString (IDS_RECEIPT_END_TIME));
|
|
wstrHTMLLine.append (HTML_TABLE_HEADER_END);
|
|
wstrHTMLLine.append (HTML_TABLE_HEADER_START);
|
|
wstrHTMLLine.append (GetString (IDS_RECEIPT_RETRIES));
|
|
wstrHTMLLine.append (HTML_TABLE_HEADER_END);
|
|
if (bDisplayError)
|
|
{
|
|
wstrHTMLLine.append (HTML_TABLE_HEADER_START);
|
|
wstrHTMLLine.append (GetString (IDS_RECEIPT_LAST_ERROR));
|
|
wstrHTMLLine.append (HTML_TABLE_HEADER_END );
|
|
}
|
|
wstrHTMLLine.append (HTML_TABLE_RAW_END);
|
|
wstrHTMLLine.append (TEXT("\n"));
|
|
//
|
|
// Print seperator line
|
|
//
|
|
WCHAR wszSeperator[] =
|
|
TEXT("--------------------------------------------------------------------------------------------------------");
|
|
if (0 > _snwprintf (wszLine,
|
|
sizeof (wszLine) / sizeof (wszLine[0]),
|
|
lpcwstrFormat,
|
|
dwRecNameWidth,
|
|
wstring(wszSeperator).substr(0, dwRecNameWidth-1).c_str(),
|
|
dwRecNumberWidth,
|
|
wstring(wszSeperator).substr(0, dwRecNumberWidth-1).c_str(),
|
|
dwStartTimeWidth,
|
|
wstring(wszSeperator).substr(0, dwStartTimeWidth-1).c_str(),
|
|
dwEndTimeWidth,
|
|
wstring(wszSeperator).substr(0, dwEndTimeWidth-1).c_str(),
|
|
dwRetriesWidth,
|
|
wstring(wszSeperator).substr(0, dwRetriesWidth-1).c_str(),
|
|
dwErrorWidth,
|
|
wstring(wszSeperator).substr(0, dwErrorWidth-1).c_str()))
|
|
{
|
|
ec = ERROR_BUFFER_OVERFLOW;
|
|
SetLastError (ec);
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("_snwprintf failed. (ec: %ld)"),
|
|
ec);
|
|
return FALSE;
|
|
}
|
|
wstrLine.append (wszLine);
|
|
wstrLine.append (TEXT("\n"));
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Prepare recipient line
|
|
//
|
|
WCHAR wszLine[1024]={0};
|
|
WCHAR wszNumber[12]={0};
|
|
LPCWSTR lpcwstrFormat;
|
|
wstring wstrStartTime;
|
|
wstring wstrEndTime;
|
|
|
|
if (!TimeToString ((FILETIME*) &lpcJobQueue->StartTime, wstrStartTime) ||
|
|
!TimeToString ((FILETIME*) &lpcJobQueue->EndTime, wstrEndTime))
|
|
{
|
|
//
|
|
// Some error while converting time to string
|
|
//
|
|
ec = GetLastError ();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("TimeToString failed (ec=%ld)"),
|
|
ec);
|
|
return FALSE;
|
|
}
|
|
|
|
if (bDisplayError)
|
|
{
|
|
lpcwstrFormat = TEXT("%-*s %-*s %-*s %-*s %*d %-*s");
|
|
if (!PrepareReceiptErrorString (lpcJobQueue, wstrError))
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("PrepareReceiptErrorString failed. (ec: %ld)"),
|
|
ec);
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpcwstrFormat = TEXT("%-*s %-*s %-*s %-*s %*d");
|
|
}
|
|
if (0 > _snwprintf (wszLine,
|
|
ARR_SIZE (wszLine) - 1,
|
|
lpcwstrFormat,
|
|
dwRecNameWidth,
|
|
wstring(lpcJobQueue->RecipientProfile.lptstrName ?
|
|
lpcJobQueue->RecipientProfile.lptstrName : EMPTY_STRING
|
|
).substr(0, dwRecNameWidth-1).c_str(),
|
|
dwRecNumberWidth,
|
|
wstring(lpcJobQueue->RecipientProfile.lptstrFaxNumber ?
|
|
lpcJobQueue->RecipientProfile.lptstrFaxNumber : EMPTY_STRING
|
|
).substr(0, dwRecNumberWidth-1).c_str(),
|
|
dwStartTimeWidth,
|
|
wstrStartTime.substr(0, dwStartTimeWidth-1).c_str(),
|
|
dwEndTimeWidth,
|
|
wstrEndTime.substr(0, dwEndTimeWidth-1).c_str(),
|
|
dwRetriesWidth,
|
|
lpcJobQueue->SendRetries,
|
|
dwErrorWidth,
|
|
wstrError.substr(0, dwErrorWidth-1).c_str()))
|
|
{
|
|
ec = ERROR_BUFFER_OVERFLOW;
|
|
SetLastError (ec);
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("_snwprintf failed. (ec: %ld)"),
|
|
ec);
|
|
return FALSE;
|
|
}
|
|
wstrLine.append (wszLine);
|
|
wstrLine.append (TEXT("\n"));
|
|
|
|
wstrHTMLLine.append (HTML_TABLE_RAW_START);
|
|
wstrHTMLLine.append (HTML_TABLE_DATA_START);
|
|
wstrHTMLLine.append (lpcJobQueue->RecipientProfile.lptstrName ?
|
|
lpcJobQueue->RecipientProfile.lptstrName : EMPTY_STRING);
|
|
wstrHTMLLine.append (HTML_TABLE_DATA_END);
|
|
wstrHTMLLine.append (HTML_TABLE_DATA_START);
|
|
wstrHTMLLine.append (lpcJobQueue->RecipientProfile.lptstrFaxNumber ?
|
|
lpcJobQueue->RecipientProfile.lptstrFaxNumber : EMPTY_STRING);
|
|
wstrHTMLLine.append (HTML_TABLE_DATA_END);
|
|
wstrHTMLLine.append (HTML_TABLE_DATA_START);
|
|
wstrHTMLLine.append (wstrStartTime);
|
|
wstrHTMLLine.append (HTML_TABLE_DATA_END);
|
|
wstrHTMLLine.append (HTML_TABLE_DATA_START);
|
|
wstrHTMLLine.append (wstrEndTime);
|
|
wstrHTMLLine.append (HTML_TABLE_DATA_END);
|
|
wstrHTMLLine.append (HTML_TABLE_DATA_START);
|
|
_itow(lpcJobQueue->SendRetries,wszNumber,10);
|
|
wstrHTMLLine.append (wszNumber);
|
|
wstrHTMLLine.append (HTML_TABLE_DATA_END);
|
|
if (bDisplayError)
|
|
{
|
|
wstrHTMLLine.append (HTML_TABLE_DATA_START);
|
|
wstrHTMLLine.append (wstrError);
|
|
wstrHTMLLine.append (HTML_TABLE_DATA_END);
|
|
}
|
|
wstrHTMLLine.append (HTML_TABLE_RAW_END);
|
|
wstrHTMLLine.append (TEXT("\n"));
|
|
}
|
|
return TRUE;
|
|
} // AddRecipientLine
|
|
|
|
|
|
BOOL
|
|
PrepareReceiptErrorString (
|
|
const JOB_QUEUE *lpcJobQueue,
|
|
wstring &wstrError
|
|
) throw (exception)
|
|
/*++
|
|
|
|
Routine name : PrepareReceiptErrorString
|
|
|
|
Routine description:
|
|
|
|
Creates an error string for a failed job queue entry
|
|
|
|
This function may throw STL exceptions in case of string errors.
|
|
|
|
Author:
|
|
|
|
Eran Yariv (EranY), Feb, 2000
|
|
|
|
Arguments:
|
|
|
|
lpcJobQueue [in] - Pointer to failed job queue entry
|
|
wstrError [out] - String output
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE otherwise.
|
|
In case of failure, call GetLastError() to obtain error code.
|
|
|
|
--*/
|
|
{
|
|
DWORD ec = ERROR_SUCCESS;
|
|
TCHAR szErrorDescription[MAX_PATH] = {0};
|
|
|
|
DEBUG_FUNCTION_NAME(TEXT("PrepareReceiptErrorString"));
|
|
|
|
Assert (lpcJobQueue);
|
|
|
|
//
|
|
// Clear the string
|
|
//
|
|
wstrError = TEXT("");
|
|
|
|
Assert( (JS_RETRIES_EXCEEDED == const_cast<PJOB_QUEUE>(lpcJobQueue)->JobStatus) ||
|
|
(JS_CANCELED == const_cast<PJOB_QUEUE>(lpcJobQueue)->JobStatus) );
|
|
|
|
if (JS_CANCELED == const_cast<PJOB_QUEUE>(lpcJobQueue)->JobStatus)
|
|
{
|
|
if (!LoadString(
|
|
g_hResource,
|
|
IDS_JOB_CANCELED_BY_USER,
|
|
szErrorDescription,
|
|
sizeof(szErrorDescription)/sizeof(TCHAR)
|
|
))
|
|
{
|
|
DebugPrintEx(DEBUG_ERR,
|
|
TEXT("Failed to load string"));
|
|
return FALSE;
|
|
}
|
|
|
|
wstrError = szErrorDescription;
|
|
return TRUE;
|
|
}
|
|
|
|
if (lpcJobQueue->ExStatusString[0] != L'\0')
|
|
{
|
|
//
|
|
// FSPI provided extended status string
|
|
//
|
|
wstrError = lpcJobQueue->ExStatusString;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// FSP provided extended status code
|
|
//
|
|
LPTSTR lptstrString = MapFSPIJobExtendedStatusToString(lpcJobQueue->dwLastJobExtendedStatus);
|
|
if (lptstrString)
|
|
{
|
|
wstrError = lptstrString;
|
|
}
|
|
}
|
|
return TRUE;
|
|
} // PrepareReceiptErrorString
|
|
|
|
BOOL
|
|
PrepareReceiptBody(
|
|
BOOL bPositive,
|
|
BOOL bBroadcast,
|
|
const JOB_QUEUE * lpcJobQueue,
|
|
LPCWSTR lpcwstrSubject,
|
|
BOOL bAttachment,
|
|
LPWSTR * ppwstrBody,
|
|
LPWSTR * ppwstrHTMLBody
|
|
) throw (exception)
|
|
/*++
|
|
|
|
Routine name : PrepareReceiptBody
|
|
|
|
Routine description:
|
|
|
|
Prepares the receipts body to be sent out via mail
|
|
|
|
This function may throw STL exceptions in case of string errors.
|
|
|
|
Author:
|
|
|
|
Eran Yariv (EranY), Feb, 2000
|
|
|
|
Arguments:
|
|
|
|
bPositive [in] - Did the job(s) complete successfully?
|
|
bBroadcast [in] - Is this a broadcast job
|
|
lpcJobQueue [in] - Pointer to job (or broadcast parent job)
|
|
lpcwstrSubject [in] - Subject line (as retrieved from call to PrepareReceiptSubject()).
|
|
bAttachment [in] - Should the reciept body contain attachment?
|
|
ppwstrBody [out] - Pointer to receipt body string.
|
|
The string is allocated by this function.
|
|
If the function succeeded, the caller must call LocalFree() to
|
|
deallocate it.
|
|
ppwstrHTMLBody [out] - Pointer to receipt HTML body string.
|
|
The string is allocated by this function.
|
|
If the function succeeded, the caller must call LocalFree() to
|
|
deallocate it.
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE otherwise.
|
|
In case of failure, call GetLastError() to obtain error code.
|
|
|
|
--*/
|
|
{
|
|
DWORD ec = ERROR_SUCCESS;
|
|
DEBUG_FUNCTION_NAME(TEXT("PrepareReceiptBody"));
|
|
|
|
Assert (lpcJobQueue && ppwstrBody && !(bBroadcast && !ppwstrHTMLBody) );
|
|
|
|
DWORD dwMsgCount;
|
|
LPDWORD MsgPtr[8];
|
|
int nMsgStrID;
|
|
int nHTMLMsgStrID;
|
|
wstring wstrDateTime[3]; // Submit time, start time, end time.
|
|
|
|
//
|
|
// Get name of server
|
|
//
|
|
WCHAR wszServerName[MAX_COMPUTERNAME_LENGTH + 1];
|
|
DWORD dwServerNameSize = sizeof (wszServerName) / sizeof (WCHAR);
|
|
if (!GetComputerName (wszServerName, &dwServerNameSize))
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("GetComputerName failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
|
|
if (!bBroadcast)
|
|
{
|
|
//
|
|
// Compose body for single recipient job
|
|
//
|
|
wstring wstrError;
|
|
if (!TimeToString ((FILETIME*) &lpcJobQueue->lpParentJob->SubmissionTime, wstrDateTime[0]) ||
|
|
!TimeToString ((FILETIME*) &lpcJobQueue->StartTime, wstrDateTime[1]) ||
|
|
!TimeToString ((FILETIME*) &lpcJobQueue->EndTime, wstrDateTime[2]))
|
|
{
|
|
//
|
|
// Some error while converting time to string
|
|
//
|
|
ec = GetLastError ();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("TimeToString failed (ec=%ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
if (bPositive)
|
|
{
|
|
//
|
|
// Success case: "
|
|
// <Subject line again>
|
|
// Fax submitted: <date and time>
|
|
// To server: <server name>
|
|
// Transmission started: <data and time>
|
|
// Transmission end: <data and time>
|
|
// Number of retries: <retries>
|
|
// Number of pages: <pages>"
|
|
//
|
|
nMsgStrID = MSG_DR_SINGLE_BODY;
|
|
|
|
MsgPtr[0] = (LPDWORD)lpcwstrSubject;
|
|
MsgPtr[1] = (LPDWORD)(LPCTSTR)(wstrDateTime[0].c_str());
|
|
MsgPtr[2] = (LPDWORD)wszServerName;
|
|
MsgPtr[3] = (LPDWORD)(LPCTSTR)(wstrDateTime[1].c_str());
|
|
MsgPtr[4] = (LPDWORD)(LPCTSTR)(wstrDateTime[2].c_str());
|
|
MsgPtr[5] = (LPDWORD)ULongToPtr(lpcJobQueue->SendRetries);
|
|
MsgPtr[6] = (LPDWORD)ULongToPtr(lpcJobQueue->PageCount);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Failure case: "
|
|
// <Subject line again>
|
|
// Fax submitted: <date and time>
|
|
// To server: <server name>
|
|
// Transmission started: <data and time>
|
|
// Transmission end: <data and time>
|
|
// Number of retries: <retries>
|
|
// Number of pages: <pages>
|
|
// Last error: <last error description>
|
|
//
|
|
nMsgStrID = MSG_NDR_SINGLE_BODY;
|
|
if (!PrepareReceiptErrorString (lpcJobQueue, wstrError))
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("PrepareReceiptErrorString failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
MsgPtr[0] = (LPDWORD)lpcwstrSubject;
|
|
MsgPtr[1] = (LPDWORD)(LPCTSTR)(wstrDateTime[0].c_str());
|
|
MsgPtr[2] = (LPDWORD)wszServerName;
|
|
MsgPtr[3] = (LPDWORD)(LPCTSTR)(wstrDateTime[1].c_str());
|
|
MsgPtr[4] = (LPDWORD)(LPCTSTR)(wstrDateTime[2].c_str());
|
|
MsgPtr[5] = (LPDWORD)ULongToPtr(lpcJobQueue->SendRetries);
|
|
MsgPtr[6] = (LPDWORD)ULongToPtr(lpcJobQueue->PageCount);
|
|
MsgPtr[7] = (LPDWORD)wstrError.c_str();
|
|
}
|
|
//
|
|
// Single recipient is an easy case
|
|
// Format the body string now (system allocates it)
|
|
//
|
|
dwMsgCount = FormatMessage(
|
|
FORMAT_MESSAGE_FROM_HMODULE |
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY |
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
|
g_hResource,
|
|
nMsgStrID,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
|
|
(LPTSTR)ppwstrBody,
|
|
0,
|
|
(va_list *) MsgPtr
|
|
);
|
|
if (!dwMsgCount)
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("FormatMessage failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Broadcast body case
|
|
//
|
|
wstring wstrBody;
|
|
wstring wstrHTMLBody;
|
|
LPWSTR lpwstrStaticPart = NULL;
|
|
LPWSTR lpwstrHTMLStaticPart = NULL;
|
|
//
|
|
// Start with the body's static part
|
|
//
|
|
if (!TimeToString ((FILETIME*) &lpcJobQueue->SubmissionTime, wstrDateTime[0]))
|
|
{
|
|
//
|
|
// Some error while converting time to string
|
|
//
|
|
ec = GetLastError ();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("TimeToString failed (ec=%ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
if (bPositive)
|
|
{
|
|
//
|
|
// Success case: "
|
|
// <Subject line again>
|
|
// Fax submitted: <date and time>
|
|
// To server: <server name>
|
|
// Number of pages: <pages>
|
|
//
|
|
// The fax was successfully sent to the following recipients:
|
|
// Recipient name Recipient number Started Ended Retries
|
|
// -------------- ---------------- ------- ----- -------
|
|
// < ---- data for each recipient goes here ---->"
|
|
//
|
|
nMsgStrID = MSG_DR_BROADCAST_BODY;
|
|
nHTMLMsgStrID = MSG_DR_BROADCAST_HTML_BODY;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Failure case: "
|
|
// <Subject line again>
|
|
// Fax submitted: <date and time>
|
|
// To server: <server name>
|
|
// Number of pages: <pages>
|
|
//
|
|
// The fax was successfully sent to the following recipients:
|
|
// Recipient name Recipient number Started Ended Retries
|
|
// -------------- ---------------- ------- ----- --------
|
|
// < ---------- data for each recipient goes here ---->"
|
|
|
|
// The fax failed to the following recipients:
|
|
// Recipient name Recipient number Started Ended Retries Last error
|
|
// -------------- ---------------- ------- ----- -------- ----------
|
|
// < ---------- data for each recipient goes here ---------->"
|
|
//
|
|
nMsgStrID = MSG_NDR_BROADCAST_BODY;
|
|
nHTMLMsgStrID = MSG_NDR_BROADCAST_HTML_BODY;
|
|
}
|
|
//
|
|
// Start by formatting the static header (system allocates it)
|
|
//
|
|
MsgPtr[0] = (LPDWORD)lpcwstrSubject;
|
|
MsgPtr[1] = (LPDWORD)(wstrDateTime[0].c_str());
|
|
MsgPtr[2] = (LPDWORD)wszServerName;
|
|
MsgPtr[3] = (LPDWORD)ULongToPtr(lpcJobQueue->PageCount);
|
|
|
|
dwMsgCount = FormatMessage(
|
|
FORMAT_MESSAGE_FROM_HMODULE |
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY |
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
|
g_hResource,
|
|
nMsgStrID,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
|
|
(LPTSTR)&lpwstrStaticPart,
|
|
0,
|
|
(va_list *) MsgPtr
|
|
);
|
|
if (!dwMsgCount)
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("FormatMessage failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
//
|
|
// Continue by formatting the HTML static header (system allocates it)
|
|
//
|
|
dwMsgCount = FormatMessage(
|
|
FORMAT_MESSAGE_FROM_HMODULE |
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY |
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
|
g_hResource,
|
|
nHTMLMsgStrID,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
|
|
(LPTSTR)&lpwstrHTMLStaticPart,
|
|
0,
|
|
(va_list *) MsgPtr
|
|
);
|
|
if (!dwMsgCount)
|
|
{
|
|
if (lpwstrStaticPart)
|
|
{
|
|
LocalFree ((HLOCAL)lpwstrStaticPart);
|
|
}
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("FormatMessage failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Add static header to result string
|
|
//
|
|
try
|
|
{
|
|
wstrBody = lpwstrStaticPart;
|
|
wstrHTMLBody.append (HTML_START);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
wstrHTMLBody.append (HTML_HEAD_START);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
wstrHTMLBody.append (HTML_META);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
wstrHTMLBody.append (HTML_TITLE_START);
|
|
wstrHTMLBody.append (GetString(IDS_HTML_RECEIPT_HEADER));
|
|
wstrHTMLBody.append (HTML_TITLE_END);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
wstrHTMLBody.append (HTML_HEAD_END);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
wstrHTMLBody.append (HTML_BODY_START);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
wstrHTMLBody.append (HTML_PARAGRAPH_START);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
wstrHTMLBody.append (lpwstrHTMLStaticPart);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
wstrHTMLBody.append (HTML_PARAGRAPH_END);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
}
|
|
catch (exception &e)
|
|
{
|
|
if (lpwstrStaticPart)
|
|
{
|
|
LocalFree ((HLOCAL)lpwstrStaticPart);
|
|
}
|
|
if (lpwstrHTMLStaticPart)
|
|
{
|
|
LocalFree ((HLOCAL)lpwstrHTMLStaticPart);
|
|
}
|
|
throw e;
|
|
}
|
|
//
|
|
// Free static header
|
|
//
|
|
if (lpwstrStaticPart)
|
|
{
|
|
LocalFree ((HLOCAL)lpwstrStaticPart);
|
|
}
|
|
if (lpwstrHTMLStaticPart)
|
|
{
|
|
LocalFree ((HLOCAL)lpwstrHTMLStaticPart);
|
|
}
|
|
//
|
|
// Start appending table(s) to static body part
|
|
//
|
|
wstrHTMLBody.append (HTML_PARAGRAPH_START);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
if (lpcJobQueue->dwCompletedRecipientJobsCount)
|
|
{
|
|
//
|
|
// Do the recipients lists now (successful recipients)
|
|
//
|
|
wstrHTMLBody.append (HTML_TABLE_START);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
//
|
|
//Creating the header of the succesors table
|
|
//
|
|
if (!AddRecipientLine (NULL, FALSE, wstrBody, wstrHTMLBody))
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("AddRecipientLine (NULL) failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
|
|
PLIST_ENTRY lpNext = lpcJobQueue->RecipientJobs.Flink;
|
|
Assert (lpNext);
|
|
while ((ULONG_PTR)lpNext != (ULONG_PTR)&lpcJobQueue->RecipientJobs)
|
|
{
|
|
PJOB_QUEUE_PTR lpRecipientsGroupMember;
|
|
lpRecipientsGroupMember = CONTAINING_RECORD( lpNext, JOB_QUEUE_PTR, ListEntry );
|
|
Assert (lpRecipientsGroupMember);
|
|
PJOB_QUEUE pRecipient = lpRecipientsGroupMember->lpJob;
|
|
Assert (pRecipient);
|
|
if (JS_COMPLETED == pRecipient->JobStatus)
|
|
{
|
|
//
|
|
// Job successfully completed - adding row of data to the table
|
|
//
|
|
if (!AddRecipientLine (pRecipient, FALSE, wstrBody, wstrHTMLBody))
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("AddRecipientLine failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
}
|
|
lpNext = lpRecipientsGroupMember->ListEntry.Flink;
|
|
}
|
|
wstrBody.append (TEXT("\n"));
|
|
wstrHTMLBody.append (HTML_TABLE_END);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
}
|
|
if (lpcJobQueue->dwFailedRecipientJobsCount)
|
|
{
|
|
//
|
|
// Append negative recipient list
|
|
//
|
|
Assert (!bPositive);
|
|
wstrHTMLBody.append (HTML_NEW_LINE);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
wstrHTMLBody.append (HTML_TABLE_START);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
//
|
|
//Creating the header of the failures table
|
|
//
|
|
if (!AddRecipientLine (NULL, TRUE, wstrBody, wstrHTMLBody))
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("AddRecipientLine (NULL) failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
|
|
PLIST_ENTRY lpNext = lpcJobQueue->RecipientJobs.Flink;
|
|
Assert (lpNext);
|
|
while ((ULONG_PTR)lpNext != (ULONG_PTR)&lpcJobQueue->RecipientJobs)
|
|
{
|
|
PJOB_QUEUE_PTR lpRecipientsGroupMember;
|
|
lpRecipientsGroupMember = CONTAINING_RECORD( lpNext, JOB_QUEUE_PTR, ListEntry );
|
|
Assert (lpRecipientsGroupMember);
|
|
PJOB_QUEUE pRecipient = lpRecipientsGroupMember->lpJob;
|
|
Assert (pRecipient);
|
|
if (JS_RETRIES_EXCEEDED == pRecipient->JobStatus)
|
|
{
|
|
//
|
|
// Job is in failure (JS_RETRIES_EXCEEDED)- adding row of data to the table
|
|
//
|
|
if (!AddRecipientLine (pRecipient, TRUE, wstrBody, wstrHTMLBody))
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("AddRecipientLine failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
}
|
|
lpNext = lpRecipientsGroupMember->ListEntry.Flink;
|
|
}
|
|
wstrHTMLBody.append (HTML_TABLE_END);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
}
|
|
wstrHTMLBody.append (HTML_PARAGRAPH_END);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
|
|
//
|
|
// Check if an attachment was requested
|
|
//
|
|
if (bAttachment &&
|
|
lpcJobQueue->CoverPageEx.lptstrCoverPageFileName)
|
|
{
|
|
//
|
|
// Add remark explaining there is no cover page attachments
|
|
//
|
|
wstrBody.append (TEXT("\n\n"));
|
|
wstrHTMLBody.append (HTML_PARAGRAPH_START);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
if (!lpcJobQueue->FileName)
|
|
{
|
|
//
|
|
// No attachment at all
|
|
//
|
|
wstrBody.append (GetString (IDS_RECEIPT_NO_CP_AND_BODY_ATTACH));
|
|
wstrHTMLBody.append (GetString (IDS_RECEIPT_NO_CP_AND_BODY_ATTACH));
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Attachment contains body file only
|
|
//
|
|
wstrBody.append (GetString (IDS_RECEIPT_NO_CP_ATTACH));
|
|
wstrHTMLBody.append (GetString (IDS_RECEIPT_NO_CP_ATTACH));
|
|
}
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
wstrHTMLBody.append (HTML_PARAGRAPH_END);
|
|
wstrBody.append (TEXT("\n"));
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
}
|
|
|
|
wstrHTMLBody.append (HTML_BODY_END);
|
|
wstrHTMLBody.append (TEXT("\n"));
|
|
wstrHTMLBody.append (HTML_END);
|
|
|
|
//
|
|
// Allocate return buffer
|
|
//
|
|
DWORD dwBufSize = sizeof (WCHAR) * (wstrBody.size() + 1);
|
|
DWORD dwHTMLBufSize = sizeof (WCHAR) * (wstrHTMLBody.size() + 1);
|
|
|
|
*ppwstrBody = (LPTSTR)LocalAlloc (LMEM_FIXED, dwBufSize);
|
|
if (NULL == *ppwstrBody)
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("LocalAlloc failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
|
|
*ppwstrHTMLBody = (LPTSTR)LocalAlloc (LMEM_FIXED, dwHTMLBufSize);
|
|
if (NULL == *ppwstrHTMLBody)
|
|
{
|
|
if (*ppwstrBody)
|
|
{
|
|
LocalFree((HLOCAL)ppwstrBody);
|
|
}
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("LocalAlloc failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
lstrcpy (*ppwstrBody, wstrBody.c_str());
|
|
lstrcpy (*ppwstrHTMLBody, wstrHTMLBody.c_str());
|
|
} // End of broadcast case
|
|
|
|
exit:
|
|
if (ERROR_SUCCESS != ec)
|
|
{
|
|
SetLastError (ec);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
} // PrepareReceiptBody
|
|
|
|
|
|
BOOL
|
|
SendReceipt(
|
|
BOOL bPositive,
|
|
BOOL bBroadcast,
|
|
const JOB_QUEUE * lpcJobQueue,
|
|
LPCTSTR lpctstrTIFF
|
|
)
|
|
/*++
|
|
|
|
Routine name : SendReceipt
|
|
|
|
Routine description:
|
|
|
|
Sends a receipt of a fax delivery / non-delivery
|
|
|
|
Author:
|
|
|
|
Eran Yariv (EranY), Feb, 2000
|
|
|
|
Arguments:
|
|
|
|
bPositive [in] - Did the job(s) complete successfully?
|
|
bBroadcast [in] - Is this a broadcast job
|
|
lpcJobQueue [in] - Pointer to job (or broadcast parent job)
|
|
lpctstrTIFF [in] - TIFF file to attach to receipt (optional, may be NULL)
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE otherwise.
|
|
In case of failure, call GetLastError() to obtain error code.
|
|
|
|
--*/
|
|
{
|
|
DEBUG_FUNCTION_NAME(TEXT("SendReceipt"));
|
|
DWORD ec = ERROR_SUCCESS;
|
|
PFAX_SERVER_RECEIPTS_CONFIGW pServerRecieptConfig = NULL;
|
|
|
|
Assert(lpcJobQueue);
|
|
|
|
LPWSTR lpwstrSubject = NULL;
|
|
LPWSTR lpwstrBody = NULL;
|
|
LPWSTR lpwstrHTMLBody = NULL;
|
|
|
|
//
|
|
// Remove modifiers - leave only the receipt type
|
|
//
|
|
DWORD dwDeliveryType = lpcJobQueue->JobParamsEx.dwReceiptDeliveryType & ~DRT_MODIFIERS;
|
|
|
|
if (DRT_NONE == dwDeliveryType)
|
|
{
|
|
//
|
|
// No receipt requested
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Get server receipts configuration
|
|
//
|
|
ec = GetRecieptsConfiguration (&pServerRecieptConfig, TRUE);
|
|
if (ERROR_SUCCESS != ec)
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("GetRecieptsConfiguration failed. (ec: %ld)"),
|
|
ec);
|
|
SetLastError(ec);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!(dwDeliveryType & pServerRecieptConfig->dwAllowedReceipts))
|
|
{
|
|
//
|
|
// Receipt type is NOT currently supported by the server.
|
|
// This may happen if the supported receipt types has changed since the job
|
|
// was submitted.
|
|
//
|
|
DebugPrintEx(DEBUG_ERR,
|
|
TEXT("dwDeliveryType not supported by the server (%ld)"),
|
|
dwDeliveryType);
|
|
ec = ERROR_UNSUPPORTED_TYPE;
|
|
goto exit;
|
|
}
|
|
|
|
if (!PrepareReceiptSubject (bPositive, bBroadcast, lpcJobQueue, &lpwstrSubject))
|
|
{
|
|
ec = GetLastError ();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("PrepareReceiptSubject failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
|
|
if (DRT_EMAIL & dwDeliveryType)
|
|
{
|
|
//
|
|
// For mail receipts, we create a message body.
|
|
//
|
|
try
|
|
{
|
|
if (!PrepareReceiptBody (bPositive,
|
|
bBroadcast,
|
|
lpcJobQueue,
|
|
lpwstrSubject,
|
|
(lpcJobQueue->JobParamsEx.dwReceiptDeliveryType & DRT_ATTACH_FAX),
|
|
&lpwstrBody,
|
|
&lpwstrHTMLBody) )
|
|
{
|
|
ec = GetLastError ();
|
|
}
|
|
}
|
|
catch (exception &ex)
|
|
{
|
|
ec = ERROR_NOT_ENOUGH_MEMORY;
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("PrepareReceiptBody caused exception (%S)"),
|
|
ex.what());
|
|
}
|
|
if (ERROR_SUCCESS != ec)
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("PrepareReceiptBody failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
switch (dwDeliveryType)
|
|
{
|
|
case DRT_EMAIL:
|
|
{
|
|
HRESULT hr;
|
|
if (!((lpcJobQueue->JobParamsEx.dwReceiptDeliveryType) & DRT_ATTACH_FAX))
|
|
{
|
|
//
|
|
// do not attach tiff file
|
|
//
|
|
lpctstrTIFF = NULL;
|
|
}
|
|
hr = SendMail (
|
|
pServerRecieptConfig->lptstrSMTPFrom, // From
|
|
lpcJobQueue->JobParamsEx.lptstrReceiptDeliveryAddress, // To
|
|
lpwstrSubject, // Subject
|
|
lpwstrBody, // Body
|
|
lpwstrHTMLBody, // HTML Body
|
|
lpctstrTIFF, // Attachment
|
|
GetString ( bPositive ? IDS_DR_FILENAME:IDS_NDR_FILENAME ), // Attachment description
|
|
pServerRecieptConfig->lptstrSMTPServer, // SMTP server
|
|
pServerRecieptConfig->dwSMTPPort, // SMTP port
|
|
(pServerRecieptConfig->SMTPAuthOption == FAX_SMTP_AUTH_ANONYMOUS) ?
|
|
CDO_AUTH_ANONYMOUS : (pServerRecieptConfig->SMTPAuthOption == FAX_SMTP_AUTH_BASIC) ?
|
|
CDO_AUTH_BASIC : CDO_AUTH_NTLM, // Authentication type
|
|
pServerRecieptConfig->lptstrSMTPUserName, // User name
|
|
pServerRecieptConfig->lptstrSMTPPassword, // Password
|
|
pServerRecieptConfig->hLoggedOnUser); // Logged on user token
|
|
if (FAILED(hr))
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("SendMail failed. (hr: 0x%08x)"),
|
|
hr);
|
|
ec = (DWORD)hr;
|
|
goto exit;
|
|
}
|
|
}
|
|
break;
|
|
case DRT_MSGBOX:
|
|
{
|
|
//
|
|
// About to send message box receipt
|
|
//
|
|
DWORD dwMessengerStartupType;
|
|
if (ERROR_SUCCESS == GetServiceStartupType (NULL, MESSENGER_SERVICE_NAME, &dwMessengerStartupType))
|
|
{
|
|
if (SERVICE_DISABLED == dwMessengerStartupType)
|
|
{
|
|
//
|
|
// Ooops. The local Messenger service is disabled. We can't send message boxes.
|
|
//
|
|
g_ReceiptsConfig.dwAllowedReceipts &= ~DRT_MSGBOX;
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("The local Messenger service is disabled. We can't send message boxes."));
|
|
FaxLog( FAXLOG_CATEGORY_OUTBOUND,
|
|
FAXLOG_LEVEL_MIN,
|
|
0,
|
|
MSG_FAX_MESSENGER_SVC_DISABLED_ERR);
|
|
ec = ERROR_SERVICE_DISABLED;
|
|
goto exit;
|
|
}
|
|
}
|
|
ec = NetMessageBufferSend (
|
|
NULL, // Send from this machine
|
|
lpcJobQueue->JobParamsEx.lptstrReceiptDeliveryAddress, // Computer to send to
|
|
NULL, // Sending computer name
|
|
(LPBYTE)lpwstrSubject, // Buffer
|
|
(lstrlen (lpwstrSubject) + 1) * sizeof (WCHAR)); // Buffer size
|
|
if (ERROR_SUCCESS != ec)
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("NetMessageBufferSend failed. (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
default:
|
|
ASSERT_FALSE;
|
|
break;
|
|
}
|
|
Assert( ERROR_SUCCESS == ec);
|
|
|
|
exit:
|
|
if (lpwstrSubject)
|
|
{
|
|
LocalFree ((HLOCAL)lpwstrSubject);
|
|
}
|
|
if (lpwstrBody)
|
|
{
|
|
LocalFree ((HLOCAL)lpwstrBody);
|
|
}
|
|
if (lpwstrHTMLBody)
|
|
{
|
|
LocalFree ((HLOCAL)lpwstrHTMLBody);
|
|
}
|
|
if (ERROR_SUCCESS != ec)
|
|
{
|
|
wstring wstrSubmissionTime;
|
|
SetLastError (ec);
|
|
|
|
//
|
|
// Find Submission Time
|
|
//
|
|
LPCWSTR lpcwstrTime = NULL;
|
|
|
|
try
|
|
{
|
|
if (!TimeToString ((lpcJobQueue->lpParentJob) ?
|
|
((FILETIME*) &lpcJobQueue->lpParentJob->SubmissionTime) :
|
|
((FILETIME*) &lpcJobQueue->SubmissionTime),
|
|
wstrSubmissionTime))
|
|
{
|
|
//
|
|
// Some error while converting time to string
|
|
//
|
|
DebugPrintEx(DEBUG_ERR,
|
|
TEXT("TimeToString failed (ec=%ld)"),
|
|
GetLastError ());
|
|
|
|
lpcwstrTime = L"";
|
|
}
|
|
else
|
|
{
|
|
lpcwstrTime = wstrSubmissionTime.c_str();
|
|
}
|
|
}
|
|
catch (exception &ex)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR,
|
|
TEXT("TimeToString caused exception (%S)"),
|
|
ex.what());
|
|
|
|
lpcwstrTime = L"";
|
|
}
|
|
|
|
switch (dwDeliveryType)
|
|
{
|
|
case DRT_EMAIL:
|
|
|
|
FaxLog(FAXLOG_CATEGORY_OUTBOUND,
|
|
FAXLOG_LEVEL_MIN,
|
|
4,
|
|
((bPositive) ? MSG_FAX_OK_EMAIL_RECEIPT_FAILED : MSG_FAX_ERR_EMAIL_RECEIPT_FAILED),
|
|
DWORD2HEX(ec), // error code
|
|
((lpcJobQueue->lpParentJob) ? lpcJobQueue->lpParentJob->UserName :
|
|
lpcJobQueue->UserName), // sender user name
|
|
lpcJobQueue->SenderProfile.lptstrName, // sender name
|
|
lpcwstrTime // submitted on
|
|
);
|
|
break;
|
|
|
|
case DRT_MSGBOX:
|
|
|
|
FaxLog(FAXLOG_CATEGORY_OUTBOUND,
|
|
FAXLOG_LEVEL_MIN,
|
|
4,
|
|
((bPositive) ? MSG_OK_MSGBOX_RECEIPT_FAILED : MSG_ERR_MSGBOX_RECEIPT_FAILED),
|
|
DWORD2HEX(ec), // error code
|
|
((lpcJobQueue->lpParentJob) ? lpcJobQueue->lpParentJob->UserName :
|
|
lpcJobQueue->UserName), // sender user name
|
|
lpcJobQueue->SenderProfile.lptstrName, // sender name
|
|
lpcwstrTime // submitted on
|
|
);
|
|
break;
|
|
|
|
default:
|
|
ASSERT_FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (NULL != pServerRecieptConfig)
|
|
{
|
|
FreeRecieptsConfiguration (pServerRecieptConfig, TRUE);
|
|
}
|
|
return (ERROR_SUCCESS == ec);
|
|
} // SendReceipt
|
|
|
|
|
|
|