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;
|
||
}
|
||
|