885 lines
21 KiB
C
885 lines
21 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1996 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
client16.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Support for 16-bit (win31 and win95) fax clients
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Windows NT fax monitor
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
06/02/96 -davidx-
|
|||
|
Created it.
|
|||
|
|
|||
|
mm/dd/yy -author-
|
|||
|
description
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "faxmon.h"
|
|||
|
#include "tiffstub.h"
|
|||
|
#include "prtcovpg.h"
|
|||
|
#include "jobtag.h"
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// File header for the fax data from downlevel client
|
|||
|
//
|
|||
|
|
|||
|
#define FAX16_SIGNATURE 'NF16'
|
|||
|
|
|||
|
typedef struct {
|
|||
|
|
|||
|
WORD Magic; // 'II'
|
|||
|
WORD Magic2; // 0x0042
|
|||
|
DWORD FirstIFDOffset; // offset to the first IFD
|
|||
|
DWORD Fax16Signature; // 'NF16'
|
|||
|
DWORD CodePage; // code page use for converting multibyte strings to Unicode
|
|||
|
|
|||
|
DWORD SenderName; // sender's name string
|
|||
|
DWORD SenderFaxNumber; // sender's fax number string
|
|||
|
DWORD SenderCompany; // sender's company string
|
|||
|
DWORD SenderAddress; // sender's address string
|
|||
|
DWORD SenderTitle; // sender's title string
|
|||
|
DWORD SenderDepartment; // sender's department string
|
|||
|
DWORD SenderOffice; // sender's office location string
|
|||
|
DWORD SenderHomePhone; // sender's home phone number string
|
|||
|
DWORD SenderOfficePhone; // sender's office phone number string
|
|||
|
|
|||
|
DWORD RecName; // recipient's name string
|
|||
|
DWORD RecFaxNumber; // recipient's fax number string
|
|||
|
DWORD RecCompany; // recipient's company string
|
|||
|
DWORD RecAddress; // recipient's address string
|
|||
|
DWORD RecCity; // recipient's city string
|
|||
|
DWORD RecState; // recipient's state string
|
|||
|
DWORD RecZip; // recipient's zip code string
|
|||
|
DWORD RecCountry; // recipient's country string
|
|||
|
DWORD RecTitle; // recipient's title string
|
|||
|
DWORD RecDepartment; // recipient's department string
|
|||
|
DWORD RecOffice; // recipient's office string
|
|||
|
DWORD RecHomePhone; // recipient's home phone number string
|
|||
|
DWORD RecOfficePhone; // recipient's office phone number string
|
|||
|
|
|||
|
DWORD SubjectLine; // subject string
|
|||
|
DWORD NoteMessage; // note string
|
|||
|
DWORD TimeSent; // time-sent string
|
|||
|
DWORD BillingCode; // billing code string
|
|||
|
|
|||
|
DWORD CoverPageFilename; // cover page filename string
|
|||
|
DWORD CoverPageDataSize; // size of embedded cover page file in bytes
|
|||
|
DWORD CoverPageData; // offset to beginning of embedded cover page file
|
|||
|
DWORD NumberOfPages; // number of pages (not including the cover page)
|
|||
|
DWORD EmailNotify; // offset to Email notification address
|
|||
|
DWORD Reserved[7]; // reserved - must be 0 for now
|
|||
|
|
|||
|
//
|
|||
|
// String data and embedded cover page file if any
|
|||
|
//
|
|||
|
|
|||
|
} FAX16_TIFF_HEADER, *PFAX16_TIFF_HEADER;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
LPWSTR
|
|||
|
CopyClientStringToUnicode(
|
|||
|
PFAX16_TIFF_HEADER pFax16Hdr,
|
|||
|
ULONG_PTR offset
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Copy ANSI string from 16-bit clients to Unicode string
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pFax16Hdr - Points to the fax data from downlevel client
|
|||
|
offset - Specifies the starting offset for the ANSI string
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Pointer to the duplicated Unicode string
|
|||
|
NULL if there is an error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LPSTR pAnsiStr;
|
|||
|
INT cch;
|
|||
|
LPWSTR pUnicodeStr = NULL;
|
|||
|
|
|||
|
if (offset != 0) {
|
|||
|
|
|||
|
pAnsiStr = (LPSTR) ((LPBYTE) pFax16Hdr + offset);
|
|||
|
cch = strlen(pAnsiStr);
|
|||
|
|
|||
|
if (pUnicodeStr = MemAllocZ((cch + 1) * sizeof(WCHAR)))
|
|||
|
MultiByteToWideChar(pFax16Hdr->CodePage, 0, pAnsiStr, cch, pUnicodeStr, cch);
|
|||
|
}
|
|||
|
|
|||
|
return pUnicodeStr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
FreeCoverPageFields(
|
|||
|
PCOVERPAGEFIELDS pCPFields
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Dispose of cover page field information
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pCPFields - Points to cover page field information
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
|
|||
|
|
|||
|
if (pCPFields != NULL) {
|
|||
|
|
|||
|
LPTSTR *ppStr;
|
|||
|
LONG_PTR count;
|
|||
|
|
|||
|
//
|
|||
|
// Free individual cover page field strings.
|
|||
|
// HACK: We assume all fields between RecName and ToList are LPTSTRs.
|
|||
|
//
|
|||
|
|
|||
|
ppStr = &pCPFields->RecName;
|
|||
|
count = (offsetof(COVERPAGEFIELDS, ToList) -
|
|||
|
offsetof(COVERPAGEFIELDS, RecName)) / sizeof(LPTSTR);
|
|||
|
|
|||
|
while (count-- > 0) {
|
|||
|
|
|||
|
MemFree(*ppStr);
|
|||
|
ppStr++;
|
|||
|
}
|
|||
|
|
|||
|
MemFree(pCPFields);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
PCOVERPAGEFIELDS
|
|||
|
CollectFax16CoverPageFields(
|
|||
|
PFAX16_TIFF_HEADER pFax16Hdr
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Collect cover page field information from 16bit client fax job
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pFax16Hdr - Points to the fax data from downlevel client
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Pointer to cover page field information
|
|||
|
NULL if there is an error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
//
|
|||
|
// Map fields in FAX16_TIFF_HEADER to fields in COVERPAGEFIELDS.
|
|||
|
// HACK: We assume all fields between RecName and NumberOfPages are LPTSTRs.
|
|||
|
//
|
|||
|
|
|||
|
#define NUM_CPFIELDS ((offsetof(COVERPAGEFIELDS, NumberOfPages) - \
|
|||
|
offsetof(COVERPAGEFIELDS, RecName)) / sizeof(LPTSTR))
|
|||
|
|
|||
|
ULONG_PTR strOffsets[NUM_CPFIELDS] = {
|
|||
|
|
|||
|
pFax16Hdr->RecName,
|
|||
|
pFax16Hdr->RecFaxNumber,
|
|||
|
pFax16Hdr->RecCompany,
|
|||
|
pFax16Hdr->RecAddress,
|
|||
|
pFax16Hdr->RecCity,
|
|||
|
pFax16Hdr->RecState,
|
|||
|
pFax16Hdr->RecZip,
|
|||
|
pFax16Hdr->RecCountry,
|
|||
|
pFax16Hdr->RecTitle,
|
|||
|
pFax16Hdr->RecDepartment,
|
|||
|
pFax16Hdr->RecOffice,
|
|||
|
pFax16Hdr->RecHomePhone,
|
|||
|
pFax16Hdr->RecOfficePhone,
|
|||
|
|
|||
|
pFax16Hdr->SenderName,
|
|||
|
pFax16Hdr->SenderFaxNumber,
|
|||
|
pFax16Hdr->SenderCompany,
|
|||
|
pFax16Hdr->SenderAddress,
|
|||
|
pFax16Hdr->SenderTitle,
|
|||
|
pFax16Hdr->SenderDepartment,
|
|||
|
pFax16Hdr->SenderOffice,
|
|||
|
pFax16Hdr->SenderHomePhone,
|
|||
|
pFax16Hdr->SenderOfficePhone,
|
|||
|
|
|||
|
pFax16Hdr->NoteMessage,
|
|||
|
pFax16Hdr->SubjectLine,
|
|||
|
pFax16Hdr->TimeSent,
|
|||
|
};
|
|||
|
|
|||
|
PCOVERPAGEFIELDS pCPFields;
|
|||
|
LPTSTR *ppStr;
|
|||
|
LONG_PTR index;
|
|||
|
|
|||
|
if ((pCPFields = MemAllocZ(sizeof(COVERPAGEFIELDS))) == NULL)
|
|||
|
return NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Convert individual cover page field from ANSI to Unicode string
|
|||
|
//
|
|||
|
|
|||
|
for (index=0, ppStr = &pCPFields->RecName; index < NUM_CPFIELDS; index++, ppStr++) {
|
|||
|
|
|||
|
if ((strOffsets[index] != 0) &&
|
|||
|
(*ppStr = CopyClientStringToUnicode(pFax16Hdr, strOffsets[index])) == NULL)
|
|||
|
{
|
|||
|
FreeCoverPageFields(pCPFields);
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Number of pages printed
|
|||
|
//
|
|||
|
|
|||
|
if ((pCPFields->NumberOfPages = MemAllocZ(sizeof(TCHAR) * 16)) == NULL) {
|
|||
|
|
|||
|
FreeCoverPageFields(pCPFields);
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
return pCPFields;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
CollectFax16JobParam(
|
|||
|
PFAXPORT pFaxPort,
|
|||
|
PCOVERPAGEFIELDS pCPFields,
|
|||
|
LPTSTR pBillingCode
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Collect 16-bit client fax job parameters
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pFaxPort - Points to a fax port structure
|
|||
|
pCPFields - Points to cover page field information
|
|||
|
pBillingCode - Points to billing code string from 16-bit client
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if successful, FALSE otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
//
|
|||
|
// Cover page fields which are passed fax service as parameters
|
|||
|
//
|
|||
|
|
|||
|
LPTSTR pSrcStr[NUM_JOBPARAM_TAGS] = {
|
|||
|
|
|||
|
pCPFields->RecFaxNumber,
|
|||
|
pCPFields->RecName,
|
|||
|
pCPFields->SdrFaxNumber,
|
|||
|
pCPFields->SdrName,
|
|||
|
pCPFields->SdrCompany,
|
|||
|
pCPFields->SdrDepartment,
|
|||
|
pBillingCode
|
|||
|
};
|
|||
|
|
|||
|
LPTSTR *ppDestStr[NUM_JOBPARAM_TAGS] = {
|
|||
|
|
|||
|
(LPTSTR *)&pFaxPort->jobParam.RecipientNumber,
|
|||
|
(LPTSTR *)&pFaxPort->jobParam.RecipientName,
|
|||
|
(LPTSTR *)&pFaxPort->jobParam.Tsid,
|
|||
|
(LPTSTR *)&pFaxPort->jobParam.SenderName,
|
|||
|
(LPTSTR *)&pFaxPort->jobParam.SenderCompany,
|
|||
|
(LPTSTR *)&pFaxPort->jobParam.SenderDept,
|
|||
|
(LPTSTR *)&pFaxPort->jobParam.BillingCode
|
|||
|
};
|
|||
|
|
|||
|
INT size, index;
|
|||
|
LPTSTR p;
|
|||
|
|
|||
|
//
|
|||
|
// Calculate the total length for all parameters
|
|||
|
//
|
|||
|
|
|||
|
for (index=size=0; index < NUM_JOBPARAM_TAGS; index++) {
|
|||
|
|
|||
|
if (pSrcStr[index])
|
|||
|
size += SizeOfString(pSrcStr[index]);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Concatenate all parameters into a single string
|
|||
|
//
|
|||
|
|
|||
|
if (size > 0 && (p = pFaxPort->pParameters = MemAllocZ(size))) {
|
|||
|
|
|||
|
for (index=0; index < NUM_JOBPARAM_TAGS; index++) {
|
|||
|
|
|||
|
if (pSrcStr[index]) {
|
|||
|
|
|||
|
*ppDestStr[index] = p;
|
|||
|
_tcscpy(p, pSrcStr[index]);
|
|||
|
p += _tcslen(p) + 1;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return (pFaxPort->pParameters != NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
LPTSTR
|
|||
|
GetClientCoverPageFile(
|
|||
|
PFAX16_TIFF_HEADER pFax16Hdr
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Return the cover page file associated with a 16-bit client fax job
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pFax16Hdr - Points to the fax data from downlevel client
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Points to the name of the cover page file
|
|||
|
NULL if there is an error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#define SERVER_CP_DIRECTORY TEXT("\\coverpg\\")
|
|||
|
|
|||
|
{
|
|||
|
LPTSTR pFilename;
|
|||
|
|
|||
|
if (pFax16Hdr->CoverPageFilename) {
|
|||
|
|
|||
|
//
|
|||
|
// Use server-based cover page file
|
|||
|
//
|
|||
|
|
|||
|
if (pFilename = CopyClientStringToUnicode(pFax16Hdr, pFax16Hdr->CoverPageFilename)) {
|
|||
|
|
|||
|
LPTSTR pServerDir = NULL, p;
|
|||
|
DWORD cb, len;
|
|||
|
|
|||
|
len = (_tcslen(SERVER_CP_DIRECTORY) + _tcslen(pFilename) + 1) * sizeof(TCHAR);
|
|||
|
|
|||
|
if (!GetPrinterDriverDirectory(NULL, NULL, 1, NULL, 0, &cb) &&
|
|||
|
GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
|
|||
|
(pServerDir = MemAllocZ(cb + len)) &&
|
|||
|
GetPrinterDriverDirectory(NULL, NULL, 1, (PBYTE) pServerDir, cb, &cb))
|
|||
|
{
|
|||
|
//
|
|||
|
// Strip off the last component of the driver directory
|
|||
|
// which should be w32<arch>.
|
|||
|
//
|
|||
|
|
|||
|
if (p = _tcsrchr(pServerDir, TEXT('\\')))
|
|||
|
*p = NUL;
|
|||
|
|
|||
|
_tcscat(pServerDir, SERVER_CP_DIRECTORY);
|
|||
|
_tcscat(pServerDir, pFilename);
|
|||
|
|
|||
|
MemFree(pFilename);
|
|||
|
pFilename = pServerDir;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
MemFree(pServerDir);
|
|||
|
MemFree(pFilename);
|
|||
|
pFilename = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} else if (pFilename = CreateTempFaxFile()) {
|
|||
|
|
|||
|
//
|
|||
|
// Cover page data is embedded in the cover page job
|
|||
|
// Create a temporary file and copy cover page data into it
|
|||
|
//
|
|||
|
|
|||
|
HANDLE hFile;
|
|||
|
DWORD cbWritten;
|
|||
|
BOOL copied = FALSE;
|
|||
|
|
|||
|
Assert(pFax16Hdr->CoverPageData != 0 && pFax16Hdr->CoverPageDataSize != 0);
|
|||
|
|
|||
|
hFile = CreateFile(pFilename,
|
|||
|
GENERIC_WRITE,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
OPEN_ALWAYS | TRUNCATE_EXISTING,
|
|||
|
FILE_ATTRIBUTE_NORMAL,
|
|||
|
NULL);
|
|||
|
|
|||
|
if (hFile != INVALID_HANDLE_VALUE) {
|
|||
|
|
|||
|
copied = WriteFile(hFile,
|
|||
|
(LPBYTE) pFax16Hdr + pFax16Hdr->CoverPageData,
|
|||
|
pFax16Hdr->CoverPageDataSize,
|
|||
|
&cbWritten,
|
|||
|
NULL);
|
|||
|
|
|||
|
CloseHandle(hFile);
|
|||
|
}
|
|||
|
|
|||
|
if (! copied) {
|
|||
|
|
|||
|
Error(("Failed to copy cover page data to a temporary file\n"));
|
|||
|
DeleteFile(pFilename);
|
|||
|
MemFree(pFilename);
|
|||
|
pFilename = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return pFilename;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
LPTSTR
|
|||
|
GetBaseNoteFilename(
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Get the name of base cover page file in system32 directory
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Pointer to name of base cover page file
|
|||
|
NULL if there is an error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#define BASENOTE_FILENAME TEXT("\\basenote.cov")
|
|||
|
|
|||
|
{
|
|||
|
TCHAR systemDir[MAX_PATH];
|
|||
|
LPTSTR pBaseNoteName = NULL;
|
|||
|
COVDOCINFO covDocInfo;
|
|||
|
|
|||
|
if (GetSystemDirectory(systemDir, MAX_PATH) &&
|
|||
|
(pBaseNoteName = MemAlloc(SizeOfString(systemDir) + SizeOfString(BASENOTE_FILENAME))))
|
|||
|
{
|
|||
|
_tcscpy(pBaseNoteName, systemDir);
|
|||
|
_tcscat(pBaseNoteName, BASENOTE_FILENAME);
|
|||
|
Verbose(("Base cover page filename: %ws\n", pBaseNoteName));
|
|||
|
|
|||
|
if (PrintCoverPage(NULL, NULL, pBaseNoteName, &covDocInfo) ||
|
|||
|
! (covDocInfo.Flags & COVFP_NOTE) ||
|
|||
|
! (covDocInfo.Flags & COVFP_SUBJECT))
|
|||
|
{
|
|||
|
Error(("Invalid base cover page file: %ws\n", pBaseNoteName));
|
|||
|
MemFree(pBaseNoteName);
|
|||
|
pBaseNoteName = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return pBaseNoteName;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
ProcessFax16CoverPage(
|
|||
|
PFAXPORT pFaxPort,
|
|||
|
PFAX16_TIFF_HEADER pFax16Hdr
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Render the cover page for downlevel client into a temporary file
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pFaxPort - Points to a fax port structure
|
|||
|
pFax16Hdr - Pointer to the fax data from downlevel client
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if successful, FALSE if there is an error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PCOVERPAGEFIELDS pCPFields;
|
|||
|
LPTSTR pBillingCode;
|
|||
|
INT result = FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// Make sure the recipient's fax number is specified
|
|||
|
//
|
|||
|
|
|||
|
if (pFax16Hdr->RecFaxNumber == 0) {
|
|||
|
|
|||
|
Error(("No recipient number is specified\n"));
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Collect cover page field information and
|
|||
|
// assemble fax job parameters and
|
|||
|
// create a new temporary file for storing cover page job
|
|||
|
//
|
|||
|
|
|||
|
pBillingCode = CopyClientStringToUnicode(pFax16Hdr, pFax16Hdr->BillingCode);
|
|||
|
|
|||
|
if ((pCPFields = CollectFax16CoverPageFields(pFax16Hdr)) &&
|
|||
|
CollectFax16JobParam(pFaxPort, pCPFields, pBillingCode) &&
|
|||
|
(pFaxPort->pFilename = CreateTempFaxFile()))
|
|||
|
{
|
|||
|
LPTSTR pCPFilename = NULL;
|
|||
|
LPTSTR pBaseNoteName = NULL;
|
|||
|
DWORD pageCount = pFax16Hdr->NumberOfPages;
|
|||
|
BOOL renderCP;
|
|||
|
COVDOCINFO covDocInfo;
|
|||
|
|
|||
|
//
|
|||
|
// Check if cover page is requested - either a server cover page filename
|
|||
|
// is specified or the cover page data is embedded in the file.
|
|||
|
//
|
|||
|
|
|||
|
renderCP = (pFax16Hdr->CoverPageFilename ||
|
|||
|
(pFax16Hdr->CoverPageDataSize && pFax16Hdr->CoverPageData));
|
|||
|
|
|||
|
ZeroMemory(&covDocInfo, sizeof(covDocInfo));
|
|||
|
|
|||
|
if (renderCP) {
|
|||
|
|
|||
|
if (pCPFilename = GetClientCoverPageFile(pFax16Hdr)) {
|
|||
|
|
|||
|
//
|
|||
|
// Find out if the specified cover page contains note/subject fields
|
|||
|
//
|
|||
|
|
|||
|
DWORD ec = PrintCoverPage( NULL, NULL, pCPFilename, &covDocInfo );
|
|||
|
if (ec) {
|
|||
|
Error(( "Cannot examine cover page: %d\n", ec ));
|
|||
|
}
|
|||
|
|
|||
|
result = TRUE;
|
|||
|
pageCount++;
|
|||
|
}
|
|||
|
|
|||
|
} else
|
|||
|
result = TRUE;
|
|||
|
|
|||
|
//
|
|||
|
// Calculate the total number of pages including cover page(s)
|
|||
|
//
|
|||
|
|
|||
|
if (((pCPFields->Note &&
|
|||
|
!IsEmptyString(pCPFields->Note) &&
|
|||
|
!(covDocInfo.Flags & COVFP_NOTE)) ||
|
|||
|
|
|||
|
(pCPFields->Subject &&
|
|||
|
!IsEmptyString(pCPFields->Subject) &&
|
|||
|
!(covDocInfo.Flags & COVFP_SUBJECT))) &&
|
|||
|
|
|||
|
(pBaseNoteName = GetBaseNoteFilename()))
|
|||
|
{
|
|||
|
renderCP = TRUE;
|
|||
|
pageCount++;
|
|||
|
}
|
|||
|
|
|||
|
wsprintf(pCPFields->NumberOfPages, TEXT("%d"), pageCount);
|
|||
|
|
|||
|
//
|
|||
|
// Render the fax cover page(s)
|
|||
|
//
|
|||
|
|
|||
|
if (result && renderCP) {
|
|||
|
|
|||
|
DOCINFO docinfo;
|
|||
|
HDC hdc = NULL;
|
|||
|
DEVMODE devmode, *pDevmode;
|
|||
|
|
|||
|
ZeroMemory(&docinfo, sizeof(docinfo));
|
|||
|
docinfo.cbSize = sizeof(docinfo);
|
|||
|
docinfo.lpszDocName = TEXT("faxmon");
|
|||
|
docinfo.lpszOutput = pFaxPort->pFilename;
|
|||
|
renderCP = FALSE;
|
|||
|
|
|||
|
if (covDocInfo.PaperSize > 0) {
|
|||
|
|
|||
|
ZeroMemory(&devmode, sizeof(devmode));
|
|||
|
_tcsncpy(devmode.dmDeviceName, pFaxPort->pPrinterName, CCHDEVICENAME);
|
|||
|
|
|||
|
devmode.dmSpecVersion = DM_SPECVERSION;
|
|||
|
devmode.dmSize = sizeof(devmode);
|
|||
|
|
|||
|
devmode.dmFields = DM_PAPERSIZE|DM_ORIENTATION;
|
|||
|
devmode.dmPaperSize = covDocInfo.PaperSize;
|
|||
|
devmode.dmOrientation = covDocInfo.Orientation;
|
|||
|
|
|||
|
pDevmode = &devmode;
|
|||
|
|
|||
|
} else
|
|||
|
pDevmode = NULL;
|
|||
|
|
|||
|
if ((hdc = CreateDC(NULL, pFaxPort->pPrinterName, NULL, pDevmode)) &&
|
|||
|
(StartDoc(hdc, &docinfo) > 0))
|
|||
|
{
|
|||
|
//
|
|||
|
// Render the user specified cover page
|
|||
|
//
|
|||
|
|
|||
|
if (pCPFilename) {
|
|||
|
|
|||
|
if (StartPage(hdc) > 0) {
|
|||
|
|
|||
|
renderCP = PrintCoverPage(hdc, pCPFields, pCPFilename, &covDocInfo) == 0 ? TRUE : FALSE;
|
|||
|
EndPage(hdc);
|
|||
|
}
|
|||
|
|
|||
|
} else
|
|||
|
renderCP = TRUE;
|
|||
|
|
|||
|
//
|
|||
|
// Render the extra cover page for note and subject
|
|||
|
//
|
|||
|
|
|||
|
if (pBaseNoteName && renderCP) {
|
|||
|
|
|||
|
if (StartPage(hdc) > 0) {
|
|||
|
|
|||
|
renderCP = PrintCoverPage(hdc, pCPFields, pBaseNoteName, &covDocInfo) == 0 ? TRUE : FALSE;
|
|||
|
EndPage(hdc);
|
|||
|
|
|||
|
} else
|
|||
|
renderCP = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if (renderCP)
|
|||
|
EndDoc(hdc);
|
|||
|
else
|
|||
|
AbortDoc(hdc);
|
|||
|
}
|
|||
|
|
|||
|
result = renderCP;
|
|||
|
|
|||
|
if (hdc)
|
|||
|
DeleteDC(hdc);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// In the embedded cover page data case, we created a temporary
|
|||
|
// cover page file earlier. So delete it here.
|
|||
|
//
|
|||
|
|
|||
|
if (pCPFilename && !pFax16Hdr->CoverPageFilename)
|
|||
|
DeleteFile(pCPFilename);
|
|||
|
|
|||
|
MemFree(pCPFilename);
|
|||
|
MemFree(pBaseNoteName);
|
|||
|
}
|
|||
|
|
|||
|
FreeCoverPageFields(pCPFields);
|
|||
|
MemFree(pBillingCode);
|
|||
|
|
|||
|
//
|
|||
|
// Open the cover page TIFF file if there was no error
|
|||
|
//
|
|||
|
|
|||
|
return result && OpenTempFaxFile(pFaxPort, TRUE);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
ConcatFax16Data(
|
|||
|
PFAXPORT pFaxPort,
|
|||
|
PFAX16_TIFF_HEADER pFax16Hdr,
|
|||
|
DWORD size
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Concatenate the fax data from downlevel client to the end of cover page TIFF file
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pFaxPort - Points to a fax port structure
|
|||
|
pFax16Hdr - Pointer to the fax data from downlevel client
|
|||
|
size - Size of the fax data from downlevel client
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if successful, FALSE otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD bytesWritten;
|
|||
|
|
|||
|
return (pFax16Hdr->NumberOfPages == 0) ||
|
|||
|
(WriteFile(pFaxPort->hFile, pFax16Hdr, size, &bytesWritten, NULL) &&
|
|||
|
bytesWritten == size);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
INT
|
|||
|
ProcessDownlevelFaxJob(
|
|||
|
PFAXPORT pFaxPort
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Process fax jobs sent from win31 and win95 clients
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pFaxPort - Points to a fax port structure
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
error code FAXERR_*
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD fileSize;
|
|||
|
LPVOID pFileView = NULL;
|
|||
|
HANDLE hFileMap = NULL;
|
|||
|
INT result = FAXERR_BAD_DATA16;
|
|||
|
LPTSTR pOrigFilename;
|
|||
|
|
|||
|
//
|
|||
|
// Get the size of fax job file
|
|||
|
//
|
|||
|
|
|||
|
FlushFileBuffers(pFaxPort->hFile);
|
|||
|
|
|||
|
if ((fileSize = GetFileSize(pFaxPort->hFile, NULL)) == 0xffffffff ||
|
|||
|
(fileSize < sizeof(DWORD) * 2))
|
|||
|
{
|
|||
|
return FAXERR_FATAL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Map the fax job data into memory
|
|||
|
//
|
|||
|
|
|||
|
if (hFileMap = CreateFileMapping(pFaxPort->hFile, NULL, PAGE_READONLY, 0, 0, NULL))
|
|||
|
pFileView = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, fileSize);
|
|||
|
|
|||
|
CloseHandle(pFaxPort->hFile);
|
|||
|
pFaxPort->hFile = INVALID_HANDLE_VALUE;
|
|||
|
|
|||
|
pOrigFilename = pFaxPort->pFilename;
|
|||
|
pFaxPort->pFilename = NULL;
|
|||
|
|
|||
|
__try {
|
|||
|
|
|||
|
PFAX16_TIFF_HEADER pFax16Hdr = pFileView;
|
|||
|
|
|||
|
//
|
|||
|
// Validate the fax data from the downlevel client
|
|||
|
//
|
|||
|
|
|||
|
if (hFileMap != NULL &&
|
|||
|
pFileView != NULL &&
|
|||
|
ValidTiffFileHeader(pFileView) &&
|
|||
|
pFax16Hdr->Fax16Signature == FAX16_SIGNATURE)
|
|||
|
{
|
|||
|
//
|
|||
|
// Render the cover page into a temporary TIFF file
|
|||
|
// and concatenate the original TIFF data at the end
|
|||
|
//
|
|||
|
|
|||
|
if (ProcessFax16CoverPage(pFaxPort, pFax16Hdr) &&
|
|||
|
ConcatFax16Data(pFaxPort, pFax16Hdr, fileSize))
|
|||
|
{
|
|||
|
result = FAXERR_NONE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
Error(("Error processing downlevel fax job\n"));
|
|||
|
result = FAXERR_FATAL;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
Error(("Bad TIFF file from downlevel fax client\n"));
|
|||
|
}
|
|||
|
|
|||
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
|
|||
|
Error(("Access violation while reading downlevel fax job\n"));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Perform necessary cleanup before returning to caller
|
|||
|
//
|
|||
|
|
|||
|
if (pFileView)
|
|||
|
UnmapViewOfFile(pFileView);
|
|||
|
|
|||
|
if (hFileMap)
|
|||
|
CloseHandle(hFileMap);
|
|||
|
|
|||
|
DeleteFile(pOrigFilename);
|
|||
|
MemFree(pOrigFilename);
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
|