|
|
/*++
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
|