Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2380 lines
65 KiB

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
print.c
Abstract:
This module contains the job
specific WINFAX API functions.
Author:
Wesley Witt (wesw) 29-Nov-1996
Revision History:
--*/
#include "faxapi.h"
#pragma hdrstop
#define InchesToCM(_x) (((_x) * 254L + 50) / 100)
#define CMToInches(_x) (((_x) * 100L + 127) / 254)
#define LEFT_MARGIN 1 // ---|
#define RIGHT_MARGIN 1 // |
#define TOP_MARGIN 1 // |---> in inches
#define BOTTOM_MARGIN 1 // ---|
#define FAX_DISPLAY_NAME TEXT("Fax Service")
static int TiffDataWidth[] = {
0, // nothing
1, // TIFF_BYTE
1, // TIFF_ASCII
2, // TIFF_SHORT
4, // TIFF_LONG
8, // TIFF_RATIONAL
1, // TIFF_SBYTE
1, // TIFF_UNDEFINED
2, // TIFF_SSHORT
4, // TIFF_SLONG
8, // TIFF_SRATIONAL
4, // TIFF_FLOAT
8, // TIFF_DOUBLE
};
VOID
LocalSystemTimeToSystemTime(
LPSYSTEMTIME LocalSystemTime,
LPSYSTEMTIME SystemTime
)
{
FILETIME LocalFileTime;
FILETIME UtcFileTime;
SystemTimeToFileTime( LocalSystemTime, &LocalFileTime );
LocalFileTimeToFileTime( &LocalFileTime, &UtcFileTime );
FileTimeToSystemTime( &UtcFileTime, SystemTime );
}
LPWSTR
GetFaxPrinterName(
VOID
)
{
PPRINTER_INFO_2 PrinterInfo;
DWORD i;
DWORD Count;
PrinterInfo = (PPRINTER_INFO_2) MyEnumPrinters( NULL, 2, &Count, PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS );
if (PrinterInfo == NULL) {
return NULL;
}
for (i=0; i<Count; i++) {
if (_wcsicmp( PrinterInfo[i].pDriverName, FAX_DRIVER_NAME ) == 0 &&
_wcsicmp( PrinterInfo[i].pPortName, FAX_PORT_NAME ) == 0)
{
LPWSTR p = (LPWSTR) StringDup( PrinterInfo[i].pPrinterName );
MemFree( PrinterInfo );
return p;
}
}
MemFree( PrinterInfo );
return NULL;
}
BOOL
PrintTextFile(
HDC hDC,
LPWSTR FileName
)
/*++
Routine Description:
Prints a file of plain text into the printer DC provided.
Note: this code was stolen from notepad.
Arguments:
hDC - Printer DC
FileName - Text file name
Return Value:
TRUE for success.
FALSE for failure.
--*/
{
FILE_MAPPING fmText;
LPSTR BodyText = NULL;
LPSTR lpLine;
LPSTR pLineEOL;
LPSTR pNextLine;
HFONT hFont = NULL;
LOGFONT logFont;
BOOL PreferredFont = TRUE;
HFONT hPrevFont = NULL;
TEXTMETRIC tm;
BOOL rVal = TRUE;
INT nLinesPerPage;
INT dyTop; // width of top border (pixels)
INT dyBottom; // width of bottom border
INT dxLeft; // width of left border
INT dxRight; // width of right border
INT yPrintChar; // height of a character
INT tabSize; // Size of a tab for print device in device units
INT yCurpos = 0;
INT xCurpos = 0;
INT nPixelsLeft = 0;
INT guess = 0;
SIZE Size; // to see if text will fit in space left
INT nPrintedLines = 0;
BOOL fPageStarted = FALSE;
INT iPageNum = 0;
INT xPrintRes; // printer resolution in x direction
INT yPrintRes; // printer resolution in y direction
INT yPixInch; // pixels/inch
INT xPixInch; // pixels/inch
INT xPixUnit; // pixels/local measurement unit
INT yPixUnit; // pixels/local measurement unit
BOOL fEnglish;
INT Chars;
INT PrevBkMode = 0;
if (!MapFileOpen( FileName, TRUE, 0, &fmText )) {
return FALSE;
}
Chars = fmText.fSize;
BodyText = fmText.fPtr;
lpLine = BodyText;
fEnglish = GetProfileInt( L"intl", L"iMeasure", 1 );
xPrintRes = GetDeviceCaps( hDC, HORZRES );
yPrintRes = GetDeviceCaps( hDC, VERTRES );
xPixInch = GetDeviceCaps( hDC, LOGPIXELSX );
yPixInch = GetDeviceCaps( hDC, LOGPIXELSY );
//
// compute x and y pixels per local measurement unit
//
if (fEnglish) {
xPixUnit= xPixInch;
yPixUnit= yPixInch;
} else {
xPixUnit= CMToInches( xPixInch );
yPixUnit= CMToInches( yPixInch );
}
SetMapMode( hDC, MM_TEXT );
ZeroMemory(&logFont, sizeof(logFont));
logFont.lfHeight = -22; // scan lines
logFont.lfWeight = FW_NORMAL;
logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
logFont.lfQuality = DEFAULT_QUALITY;
logFont.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
hFont = CreateFontIndirect(&logFont);
if (!hFont) {
hFont = GetStockObject( SYSTEM_FIXED_FONT );
}
hPrevFont = (HFONT) SelectObject( hDC, hFont );
SetBkMode( hDC, TRANSPARENT );
if (!GetTextMetrics( hDC, &tm )) {
rVal = FALSE;
goto exit;
}
yPrintChar = tm.tmHeight + tm.tmExternalLeading;
tabSize = tm.tmAveCharWidth * 8;
//
// compute margins in pixels
//
dxLeft = LEFT_MARGIN * xPixUnit;
dxRight = RIGHT_MARGIN * xPixUnit;
dyTop = TOP_MARGIN * yPixUnit;
dyBottom = BOTTOM_MARGIN * yPixUnit;
//
// Number of lines on a page with margins
//
nLinesPerPage = ((yPrintRes - dyTop - dyBottom) / yPrintChar);
while (*lpLine) {
if (*lpLine == '\r') {
lpLine += 2;
yCurpos += yPrintChar;
nPrintedLines++;
xCurpos= 0;
continue;
}
pLineEOL = lpLine;
while (*pLineEOL && *pLineEOL != '\r') pLineEOL++;
do {
if ((nPrintedLines == 0) && (!fPageStarted)) {
StartPage( hDC );
fPageStarted = TRUE;
yCurpos = 0;
xCurpos = 0;
}
if (*lpLine == '\t') {
//
// round up to the next tab stop
// if the current position is on the tabstop, goto next one
//
xCurpos = ((xCurpos + tabSize) / tabSize ) * tabSize;
lpLine++;
} else {
//
// find end of line or tab
//
pNextLine = lpLine;
while ((pNextLine != pLineEOL) && *pNextLine != '\t') pNextLine++;
//
// find out how many characters will fit on line
//
Chars = (INT)(pNextLine - lpLine);
nPixelsLeft = xPrintRes - dxRight - dxLeft - xCurpos;
GetTextExtentExPointA( hDC, lpLine, Chars, nPixelsLeft, &guess, NULL, &Size );
if (guess) {
//
// at least one character fits - print
//
TextOutA( hDC, dxLeft+xCurpos, yCurpos+dyTop, lpLine, guess );
xCurpos += Size.cx; // account for printing
lpLine += guess; // printed characters
} else {
//
// no characters fit what's left
// no characters will fit in space left
// if none ever will, just print one
// character to keep progressing through
// input file.
//
if (xCurpos == 0) {
if( lpLine != pNextLine ) {
//
// print something if not null line
// could use exttextout here to clip
//
TextOutA( hDC, dxLeft+xCurpos, yCurpos+dyTop, lpLine, 1 );
lpLine++;
}
} else {
//
// perhaps the next line will get it
//
xCurpos = xPrintRes; // force to next line
}
}
//
// move printhead in y-direction
//
if ((xCurpos >= (xPrintRes - dxRight - dxLeft) ) || (lpLine == pLineEOL)) {
yCurpos += yPrintChar;
nPrintedLines++;
xCurpos = 0;
}
if (nPrintedLines >= nLinesPerPage) {
EndPage( hDC );
fPageStarted = FALSE;
nPrintedLines = 0;
xCurpos = 0;
yCurpos = 0;
iPageNum++;
}
}
} while( lpLine != pLineEOL );
if (*lpLine == '\r') {
lpLine += 1;
}
if (*lpLine == '\n') {
lpLine += 1;
}
}
if (fPageStarted) {
EndPage( hDC );
}
exit:
if (fmText.fPtr) {
MapFileClose( &fmText, 0 );
}
if (hPrevFont) {
SelectObject( hDC, hPrevFont );
DeleteObject( hFont );
}
if (PrevBkMode) {
SetBkMode( hDC, PrevBkMode );
}
return rVal;
}
BOOL
PrintRandomDocument(
LPCWSTR FaxPrinterName,
LPCWSTR DocName,
LPWSTR OutputFile
)
/*++
Routine Description:
Prints a document that is attached to a message
Arguments:
FaxPrinterName - name of the printer to print the attachment on
DocName - name of the attachment document
Return Value:
Print job id or zero for failure.
--*/
{
SHELLEXECUTEINFO sei;
WCHAR Args[MAX_PATH];
WCHAR TempPath[MAX_PATH];
HANDLE hMap = NULL;
HANDLE hEvent = NULL;
HANDLE hMutex = NULL;
HANDLE hMutexAttach = NULL;
LPDWORD pJobId = NULL;
DWORD JobId = 0;
BOOL bSuccess = FALSE;
SECURITY_ATTRIBUTES memsa,mutsa,synsa,eventsa;
SECURITY_DESCRIPTOR memsd,mutsd,synsd,eventsd;
//
// get the temp path name and use it for the
// working dir of the launched app
//
if (!GetTempPath( sizeof(TempPath)/sizeof(WCHAR), TempPath )) {
return FALSE;
}
//
// serialize access to this function.
// this is necessary because we have to
// control access to the global shared memory region and mutex
//
//
// serialize access to this function.
// this is necessary because we can't have more than one
// app accessing our shared memory region and mutex
//
hMutexAttach = OpenMutex(MUTEX_ALL_ACCESS,FALSE,FAXRENDER_MUTEX);
if (!hMutexAttach) {
//
// we need to open this mutex with a NULL dacl so that everyone can access this
//
synsa.nLength = sizeof(SECURITY_ATTRIBUTES);
synsa.bInheritHandle = TRUE;
synsa.lpSecurityDescriptor = &synsd;
if(!InitializeSecurityDescriptor(&synsd, SECURITY_DESCRIPTOR_REVISION)) {
goto exit;
}
if(!SetSecurityDescriptorDacl(&synsd, TRUE, (PACL)NULL, FALSE)) {
goto exit;
}
hMutexAttach = CreateMutex(
&synsa,
TRUE,
FAXRENDER_MUTEX
);
if (!hMutexAttach) {
goto exit;
}
} else {
if (WaitForSingleObject( hMutexAttach, 1000* 60 * 5) != WAIT_OBJECT_0) {
//
// something went wrong
//
CloseHandle( hMutexAttach );
goto exit;
}
}
//
// note that this is serialized inside of a critical section.
// we can only have one application setting this at a time or
// we'll stomp on ourselves.
//
//
// since mapispooler might be running under a different security context,
// we must setup a NULL security descriptor
//
memsa.nLength = sizeof(SECURITY_ATTRIBUTES);
memsa.bInheritHandle = TRUE;
memsa.lpSecurityDescriptor = &memsd;
if(!InitializeSecurityDescriptor(&memsd, SECURITY_DESCRIPTOR_REVISION)) {
goto exit;
}
if(!SetSecurityDescriptorDacl(&memsd, TRUE, (PACL)NULL, FALSE)) {
goto exit;
}
mutsa.nLength = sizeof(SECURITY_ATTRIBUTES);
mutsa.bInheritHandle = TRUE;
mutsa.lpSecurityDescriptor = &mutsd;
if(!InitializeSecurityDescriptor(&mutsd, SECURITY_DESCRIPTOR_REVISION)) {
goto exit;
}
if(!SetSecurityDescriptorDacl(&mutsd, TRUE, (PACL)NULL, FALSE)) {
goto exit;
}
eventsa.nLength = sizeof(SECURITY_ATTRIBUTES);
eventsa.bInheritHandle = TRUE;
eventsa.lpSecurityDescriptor = &eventsd;
if(!InitializeSecurityDescriptor(&eventsd, SECURITY_DESCRIPTOR_REVISION)) {
goto exit;
}
if(!SetSecurityDescriptorDacl(&eventsd, TRUE, (PACL)NULL, FALSE)) {
goto exit;
}
//
// create the shared memory region for the print jobid
// the jobid is filled in by the fax printer driver
//
hMap = CreateFileMapping(
INVALID_HANDLE_VALUE,
&memsa,
PAGE_READWRITE | SEC_COMMIT,
0,
4096,
FAXXP_MEM_NAME
);
if (!hMap) {
goto exit;
}
pJobId = (LPDWORD) MapViewOfFile(
hMap,
FILE_MAP_WRITE,
0,
0,
0
);
if (!pJobId) {
goto exit;
}
wcscpy((LPTSTR) pJobId, OutputFile);
//
// set the arguments to the app.
// these arguments are either passed on
// the command line with the /pt switch or
// use as variables for substitution in the
// ddeexec value in the registry.
//
// the values are as follows:
// %1 = file name
// %2 = printer name
// %3 = driver name
// %4 = port name
//
// the first argument does not need to be
// supplied in the args array because it is implied,
// shellexecuteex gets it from the lpFile field.
// arguments 3 & 4 are left blank because they
// are win31 artifacts that are not necessary
// any more. each argument must be enclosed
// in double quotes.
//
wsprintf( Args, L"\"%s\" \"\" \"\"", FaxPrinterName );
//
// fill in the SHELLEXECUTEINFO structure
//
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;
sei.hwnd = NULL;
sei.lpVerb = L"printto";
sei.lpFile = DocName;
sei.lpParameters = Args;
sei.lpDirectory = TempPath;
sei.nShow = SW_SHOWMINNOACTIVE;
sei.hInstApp = NULL;
sei.lpIDList = NULL;
sei.lpClass = NULL;
sei.hkeyClass = NULL;
sei.dwHotKey = 0;
sei.hIcon = NULL;
sei.hProcess = NULL;
//
// create the named mutex for the print driver.
// this is initially unclaimed, and is claimed by the first instance
// of the print driver invoked after this. We do this last in order to
// avoid a situation where we catch the incorrect instance of the print driver
// printing
//
hMutex = CreateMutex(
&mutsa,
FALSE,
FAXXP_MUTEX_NAME
);
if (!hMutex) {
goto exit;
}
//
// create the named event for the print driver.
// this event is signaled when the print driver is finished rendering the document
//
hEvent = CreateEvent(
&eventsa,
FALSE,
FALSE,
FAXXP_EVENT_NAME
);
if (!hEvent) {
goto exit;
}
//
// launch the app
//
if (!ShellExecuteEx( &sei )) {
goto exit;
}
//
// wait for the print driver to finish rendering the document
//
if (WaitForSingleObject( hEvent, 1000 * 60 * 5 ) != WAIT_OBJECT_0) {
//
// something went wrong...
//
goto exit;
}
//
// wait for the print driver to exit so we can get the document
//
if (WaitForSingleObject( hMutex, 1000 * 60 * 5) != WAIT_OBJECT_0) {
//
// something went wrong
//
goto exit;
}
ReleaseMutex(hMutex);
//
// save the print jobid
//
JobId = *pJobId;
bSuccess = TRUE;
exit:
//
// clean up and leave...
//
if (sei.hProcess) CloseHandle( sei.hProcess );
if (hEvent) CloseHandle( hEvent );
if (hMutex) CloseHandle( hMutex );
if (pJobId) UnmapViewOfFile( pJobId );
if (hMap) CloseHandle( hMap );
if (hMutexAttach) {
ReleaseMutex( hMutexAttach );
CloseHandle( hMutexAttach );
}
if (!bSuccess) {
SetLastError(ERROR_INVALID_DATA);
}
return bSuccess;
}
BOOL
CreateCoverpageTiffFile(
IN const FAX_COVERPAGE_INFOW *CoverpageInfo,
OUT LPWSTR CovTiffFile
)
{
WCHAR TempPath[MAX_PATH];
WCHAR TempFile[MAX_PATH];
LPWSTR FaxPrinter;
FAX_PRINT_INFOW PrintInfo;
FAX_CONTEXT_INFOW ContextInfo;
DWORD TmpFaxJobId;
BOOL Rslt;
TempFile[0] = 0;
FaxPrinter = GetFaxPrinterName();
if (FaxPrinter == NULL) {
return FALSE;
}
if (!GetTempPath( sizeof(TempPath)/sizeof(WCHAR), TempPath ) ||
!GetTempFileName( TempPath, L"fax", 0, TempFile ))
{
return FALSE;
}
ZeroMemory( &PrintInfo, sizeof(FAX_PRINT_INFO) );
PrintInfo.SizeOfStruct = sizeof(FAX_PRINT_INFO);
PrintInfo.OutputFileName = TempFile;
ZeroMemory( &ContextInfo, sizeof(FAX_CONTEXT_INFOW) );
ContextInfo.SizeOfStruct = sizeof(FAX_CONTEXT_INFOW);
if (!FaxStartPrintJobW( FaxPrinter, &PrintInfo, &TmpFaxJobId, &ContextInfo )) {
DeleteFile( TempFile );
return FALSE;
}
Rslt = FaxPrintCoverPageW( &ContextInfo, CoverpageInfo );
EndDoc( ContextInfo.hDC );
DeleteDC( ContextInfo.hDC );
if (!Rslt) {
DeleteFile( TempFile );
return FALSE;
}
wcscpy( CovTiffFile, TempFile );
return TRUE;
}
BOOL
CreateFinalTiffFile(
IN LPWSTR FileName,
OUT LPWSTR FinalTiffFile,
IN const FAX_COVERPAGE_INFOW *CoverpageInfo
)
{
WCHAR TempPath[MAX_PATH];
WCHAR FullPath[MAX_PATH];
WCHAR TempFile[MAX_PATH];
WCHAR TiffFile[MAX_PATH];
LPWSTR FaxPrinter = NULL;
FAX_PRINT_INFOW PrintInfo;
DWORD TmpFaxJobId;
FAX_CONTEXT_INFOW ContextInfo;
LPWSTR p;
DWORD Flags = 0;
BOOL Rslt;
//
// make sure that the tiff file passed in is a valid tiff file
//
if (!GetTempPath( sizeof(TempPath)/sizeof(WCHAR), TempPath )) {
return FALSE;
}
if (GetTempFileName( TempPath, L"fax", 0, TempFile ) == 0 ||
GetFullPathName( TempFile, sizeof(FullPath)/sizeof(WCHAR), FullPath, &p ) == 0)
{
return FALSE;
}
if (!ConvertTiffFileToValidFaxFormat( FileName, FullPath, &Flags )) {
if ((Flags & TIFFCF_NOT_TIFF_FILE) == 0) {
Flags = TIFFCF_NOT_TIFF_FILE;
}
}
if (Flags & TIFFCF_NOT_TIFF_FILE) {
//
// try to output the source file into a tiff file,
// by printing to the fax printer in "file" mode
//
FaxPrinter = GetFaxPrinterName();
if (FaxPrinter == NULL) {
DeleteFile( FullPath );
SetLastError( ERROR_INVALID_FUNCTION );
return FALSE;
}
if (!PrintRandomDocument( FaxPrinter, FileName, FullPath )) {
DeleteFile( FullPath );
SetLastError( ERROR_INVALID_FUNCTION );
return FALSE;
}
wcscpy( TiffFile, FullPath );
} else if (Flags & TIFFCF_UNCOMPRESSED_BITS) {
if (FaxPrinter == NULL) {
FaxPrinter = GetFaxPrinterName();
if (FaxPrinter == NULL) {
DeleteFile( FullPath );
SetLastError( ERROR_INVALID_FUNCTION );
return FALSE;
}
}
if (Flags & TIFFCF_ORIGINAL_FILE_GOOD) {
//
// nothing at fullpath, just delete it and use the original source
//
DeleteFile( FullPath );
wcscpy( TiffFile, FileName );
} else {
wcscpy( TiffFile, FullPath );
}
if (GetTempFileName( TempPath, L"fax", 0, TempFile ) == 0 ||
GetFullPathName( TempFile, sizeof(FullPath)/sizeof(WCHAR), FullPath, &p ) == 0)
{
DeleteFile( TiffFile );
return FALSE;
}
ZeroMemory( &PrintInfo, sizeof(FAX_PRINT_INFOW) );
PrintInfo.SizeOfStruct = sizeof(FAX_PRINT_INFOW);
PrintInfo.OutputFileName = FullPath;
ZeroMemory( &ContextInfo, sizeof(FAX_CONTEXT_INFOW) );
ContextInfo.SizeOfStruct = sizeof(FAX_CONTEXT_INFOW);
if (!FaxStartPrintJobW( FaxPrinter, &PrintInfo, &TmpFaxJobId, &ContextInfo )) {
if ((Flags & TIFFCF_ORIGINAL_FILE_GOOD) == 0) DeleteFile( TiffFile );
DeleteFile( FullPath );
SetLastError( ERROR_INVALID_FUNCTION );
return FALSE;
}
Rslt = PrintTiffFile( ContextInfo.hDC, TiffFile );
EndDoc( ContextInfo.hDC );
DeleteDC( ContextInfo.hDC );
if ((Flags & TIFFCF_ORIGINAL_FILE_GOOD) == 0) {
DeleteFile( TiffFile );
}
if (!Rslt) {
DeleteFile( FullPath );
SetLastError( ERROR_INVALID_FUNCTION );
return FALSE;
}
wcscpy( TiffFile, FullPath );
} else if (Flags & TIFFCF_ORIGINAL_FILE_GOOD) {
//
// we didn't create anything at FullPath, just use FileName
//
DeleteFile( FullPath );
wcscpy( TiffFile, FileName );
} else {
//
// should never hit this case
//
DeleteFile( FullPath );
SetLastError( ERROR_INVALID_FUNCTION );
return FALSE;
}
//
// if a coverpage is specified then print the coverpage first
//
if (CoverpageInfo && CoverpageInfo->CoverPageName) {
if (!CreateCoverpageTiffFile( CoverpageInfo, TempFile )) {
if (wcscmp(FileName,TiffFile) != 0) DeleteFile( TiffFile );
DeleteFile( TempFile );
return FALSE;
}
if (!MergeTiffFiles( TempFile, TiffFile )) {
if (wcscmp(FileName,TiffFile) != 0) DeleteFile( TiffFile );
DeleteFile( TempFile );
return FALSE;
}
FileName = TempFile;
} else {
FileName = TiffFile;
}
wcscpy( FinalTiffFile, FileName );
return TRUE;
}
BOOL
CopyFileToServerQueue(
IN const HANDLE FaxHandle,
IN LPCWSTR TiffFile,
IN LPWSTR QueueFileName
)
{
error_status_t ec;
WCHAR FullPath[MAX_PATH];
//
// get a file name from the fax server
//
ec = FAX_GetQueueFileName( FH_FAX_HANDLE(FaxHandle), QueueFileName, MAX_PATH );
if (ec) {
SetLastError( ec );
return FALSE;
}
//
// create the full path to the new file
//
if (!IsLocalFaxConnection(FaxHandle)) {
//
// remote file
//
swprintf( FullPath, FAX_QUEUE_PATH, FH_DATA(FaxHandle)->MachineName, QueueFileName );
} else {
//
// local file
//
if (!GetSpecialPath( CSIDL_COMMON_APPDATA, FullPath )) {
return FALSE;
}
ConcatenatePaths( FullPath, FAX_QUEUE_DIR );
ConcatenatePaths( FullPath, QueueFileName );
}
//
// copy the file to the fax server queue dir
//
if (!CopyFile( TiffFile, FullPath, FALSE )) {
return FALSE;
}
SetFileAttributes( FullPath, (GetFileAttributes( FullPath ) & (0xFFFFFFFF^FILE_ATTRIBUTE_READONLY)) | FILE_ATTRIBUTE_NORMAL );
return TRUE;
}
DWORD
GetLineId(
FARPROC LineGetId,
HCALL CallHandle
)
{
LPVARSTRING DeviceId;
long rslt = 0;
DWORD LineId;
//
// get the deviceID associated with the call handle
//
DeviceId = MemAlloc(sizeof(VARSTRING)+1000);
if (!DeviceId) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
DeviceId->dwTotalSize=sizeof(VARSTRING) +1000;
rslt = (DWORD)LineGetId(NULL,0,(HCALL) CallHandle,LINECALLSELECT_CALL,DeviceId,L"tapi/line");
if (rslt < 0) {
DebugPrint((TEXT("LineGetId() failed, ec = %x\n"),rslt));
MemFree(DeviceId);
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if (DeviceId->dwStringFormat != STRINGFORMAT_BINARY ) {
MemFree(DeviceId);
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
LineId = (DWORD) *((LPBYTE)DeviceId + DeviceId->dwStringOffset);
MemFree(DeviceId);
return LineId;
}
BOOL
WINAPI
FaxSendDocumentW(
IN HANDLE FaxHandle,
IN LPCWSTR FileName,
IN FAX_JOB_PARAMW *JobParams,
IN const FAX_COVERPAGE_INFOW *CoverpageInfo,
OUT LPDWORD FaxJobId
)
/*++
Routine Description:
Sends a FAX document to the specified recipient.
This is an asychronous operation. Use FaxReportStatus
to determine when the send is completed.
Arguments:
FaxHandle - FAX handle obtained from FaxConnectFaxServer.
FileName - File containing the TIFF-F FAX document.
JobParams - pointer to FAX_JOB_PARAM structure with transmission params
CoverpageInfo - optional pointer to FAX_COVERPAGE_INFO structure
FaxJobId - receives the Fax JobId for the job.
Return Value:
TRUE - Success
FALSE - Failure, call GetLastError() for more error information.
--*/
{
error_status_t ec;
WCHAR QueueFileName[MAX_PATH];
WCHAR ExistingFile[MAX_PATH];
DWORD rc;
LPWSTR p;
WCHAR TiffFile[MAX_PATH];
HINSTANCE hTapiLib = NULL;
WCHAR TapiPath[MAX_PATH];
WCHAR MutexName[64];
HANDLE hLineMutex = NULL;
FARPROC LineHandoff;
FARPROC LineGetId;
IUnknown* pDisp=NULL;
ITBasicCallControl* pCallControl;
ITCallInfo* pCallInfo;
ITAddress* pAddressInfo;
ITAddressCapabilities* pAddressCaps;
CALL_STATE CallState;
BSTR FaxSvcName;
HRESULT hr;
DWORD LineId;
DWORD _JobId;
DWORD Event = 0;
long rslt = 0;
//
// argument validation
//
if (!ValidateFaxHandle(FaxHandle, FHT_SERVICE)) {
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (!FileName || !JobParams || JobParams->SizeOfStruct != sizeof(FAX_JOB_PARAMW)) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (JobParams->ScheduleAction != JSA_NOW &&
JobParams->ScheduleAction != JSA_SPECIFIC_TIME &&
JobParams->ScheduleAction != JSA_DISCOUNT_PERIOD) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (JobParams->DeliveryReportType != DRT_NONE &&
JobParams->DeliveryReportType != DRT_EMAIL &&
JobParams->DeliveryReportType != DRT_INBOX ) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
//
// make sure the file is there
//
rc = GetFullPathName(FileName,sizeof(ExistingFile)/sizeof(WCHAR),ExistingFile,&p);
if (rc > MAX_PATH || rc == 0) {
DebugPrint(( TEXT("GetFullPathName failed, ec= %d\n"),GetLastError() ));
SetLastError( (rc > MAX_PATH)
? ERROR_BUFFER_OVERFLOW
: GetLastError() );
return FALSE;
}
if (GetFileAttributes(ExistingFile)==0xFFFFFFFF) {
SetLastError(ERROR_FILE_NOT_FOUND);
return FALSE;
}
//
// if they want a coverpage, try to validate it
//
if (CoverpageInfo &&
!ValidateCoverpage(CoverpageInfo->CoverPageName,
IsLocalFaxConnection(FaxHandle) ? NULL : FH_DATA(FaxHandle)->MachineName,
CoverpageInfo->UseServerCoverPage,
NULL)) {
SetLastError(ERROR_FILE_NOT_FOUND);
return FALSE;
}
if (JobParams->CallHandle != 0 || JobParams->Reserved[0]==0xFFFF1234) {
//
// we don't support call handoff if it's a remote server connection
//
if (!IsLocalFaxConnection(FaxHandle)) {
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
if (JobParams->CallHandle) {
//
// tapi is dynamic
//
ExpandEnvironmentStrings(TAPI_LIBRARY,TapiPath,MAX_PATH);
hTapiLib = LoadLibrary(TapiPath);
if (!hTapiLib) {
SetLastError(ERROR_INVALID_LIBRARY);
return FALSE;
}
LineHandoff = GetProcAddress(hTapiLib,"lineHandoffW");
LineGetId = GetProcAddress(hTapiLib,"lineGetIDW");
if (!LineHandoff || !LineGetId) {
FreeLibrary(hTapiLib);
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
//
// get the line ID
//
LineId = GetLineId(LineGetId,JobParams->CallHandle);
if (LineId) {
JobParams->Reserved[2] = LineId;
} else {
FreeLibrary(hTapiLib);
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
} else if (JobParams->Reserved[1]) {
//
// GetDeviceId from tapi3 dispinterface
//
pDisp = (IUnknown*) JobParams->Reserved[1];
hr = pDisp->lpVtbl->QueryInterface( pDisp, &IID_ITCallInfo, (void**)&pCallInfo );
if (FAILED(hr)) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (FAILED(pCallInfo->lpVtbl->get_CallState(pCallInfo,&CallState))) {
pCallInfo->lpVtbl->Release(pCallInfo);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (CallState != CS_CONNECTED) {
DebugPrint(( TEXT("callstate(%d) is invalid, cannot handoff job\n"),CallState ));
pCallInfo->lpVtbl->Release(pCallInfo);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (FAILED(pCallInfo->lpVtbl->get_Address(pCallInfo,&pAddressInfo))) {
pCallInfo->lpVtbl->Release(pCallInfo);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (FAILED(pAddressInfo->lpVtbl->QueryInterface(pAddressInfo, &IID_ITAddressCapabilities, (void**)&pAddressCaps))) {
pCallInfo->lpVtbl->Release(pCallInfo);
pAddressInfo->lpVtbl->Release(pAddressInfo);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (FAILED(pAddressCaps->lpVtbl->get_AddressCapability( pAddressCaps, AC_LINEID, &LineId ))) {
pCallInfo->lpVtbl->Release(pCallInfo);
pAddressInfo->lpVtbl->Release(pAddressInfo);
pAddressCaps->lpVtbl->Release(pAddressCaps);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (LineId == 0) {
pCallInfo->lpVtbl->Release(pCallInfo);
pAddressInfo->lpVtbl->Release(pAddressInfo);
pAddressCaps->lpVtbl->Release(pAddressCaps);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
JobParams->Reserved[2] = LineId;
pCallInfo->lpVtbl->Release(pCallInfo);
pAddressInfo->lpVtbl->Release(pAddressInfo);
pAddressCaps->lpVtbl->Release(pAddressCaps);
} else {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
DebugPrint((TEXT("device ID = %d\n"),JobParams->Reserved[2]));
//
// we need a mutex to ensure fax service owns the line before calling lineHandoff
//
wsprintf(MutexName,L"FaxLineHandoff%d",JobParams->Reserved[2]);
hLineMutex = CreateMutex(NULL,FALSE,MutexName);
if (!hLineMutex) {
FreeLibrary(hTapiLib);
return FALSE;
}
} else {
//
// this is a normal fax...validate the fax number.
//
if (!JobParams->RecipientNumber) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
}
//
// make sure that the tiff file passed in is a valid tiff file
//
ZeroMemory(TiffFile,sizeof(TiffFile));
if (!CreateFinalTiffFile( (LPWSTR) ExistingFile, TiffFile, CoverpageInfo )) {
DeleteFile( TiffFile );
if (hTapiLib) {
FreeLibrary(hTapiLib);
}
if (hLineMutex) {
CloseHandle(hLineMutex);
}
SetLastError(ERROR_INVALID_DATA);
return FALSE;
}
//
// copy the file to the server's queue dir
//
if (!CopyFileToServerQueue( FaxHandle, TiffFile, QueueFileName )) {
if (hTapiLib) {
FreeLibrary(hTapiLib);
}
if (hLineMutex) {
CloseHandle(hLineMutex);
}
return FALSE;
}
//
// the passed in file should be treated as read-only
// if we created a temp file then delete it
//
if (wcscmp(ExistingFile,TiffFile) != 0) {
DeleteFile( TiffFile );
}
//
// queue the fax to be sent
//
if (JobParams->Reserved[0] != 0xffffffff)
{
JobParams->Reserved[0] = 0;
JobParams->Reserved[1] = 0;
}
if (JobParams->ScheduleAction == JSA_SPECIFIC_TIME) {
//
// convert the system time from local to utc
//
LocalSystemTimeToSystemTime( &JobParams->ScheduleTime, &JobParams->ScheduleTime );
}
ec = FAX_SendDocument( FH_FAX_HANDLE(FaxHandle), QueueFileName, JobParams, &_JobId );
if (ec) {
SetLastError( ec );
if (hTapiLib) {
FreeLibrary(hTapiLib);
}
if (hLineMutex) {
CloseHandle(hLineMutex);
}
return FALSE;
}
if (FaxJobId) {
*FaxJobId = _JobId;
}
//
// we're done if it's a normal call
//
if (JobParams->CallHandle == 0 && !pDisp) {
return TRUE;
}
//
// wait for Mutex to get signalled
//
DebugPrint((TEXT("Waiting for mutex \"FaxLineHandoff%d\""),JobParams->Reserved[2]));
Event = WaitForSingleObject(hLineMutex,INFINITE);
if (Event != WAIT_OBJECT_0 ) {
//
// bail out, we couldn't open the line?
//
}
//
// handoff the call to the fax service, FSP must change media mode appropriately
//
if (JobParams->CallHandle) {
//
// TAPI 2.0 handoff
//
DebugPrint((TEXT("Handing off call %x to faxsvc"),JobParams->CallHandle));
rslt = (long)LineHandoff(JobParams->CallHandle, FAX_DISPLAY_NAME , 0 );
FreeLibrary(hTapiLib);
CloseHandle(hLineMutex);
if (rslt != 0) {
SetLastError(rslt);
return FALSE;
}
} else {
//
// TAPI 3.0 handoff
//
pDisp->lpVtbl->QueryInterface( pDisp, &IID_ITBasicCallControl, (void**)&pCallControl );
if (FAILED(hr)) {
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
FaxSvcName = SysAllocString( FAX_DISPLAY_NAME );
hr = pCallControl->lpVtbl->HandoffDirect(pCallControl,FaxSvcName);
pCallControl->lpVtbl->Release(pCallControl);
SysFreeString( FaxSvcName );
if (FAILED(hr)) {
DebugPrint((TEXT("call handoff failed, ec = %x"),hr));
return FALSE;
}
}
return TRUE;
}
WINFAXAPI
BOOL
WINAPI
FaxSendDocumentForBroadcastW(
IN HANDLE FaxHandle,
IN LPCWSTR FileName,
OUT LPDWORD FaxJobId,
IN PFAX_RECIPIENT_CALLBACKW FaxRecipientCallback,
IN LPVOID Context
)
{
error_status_t ec;
WCHAR TempFile[MAX_PATH];
WCHAR TiffFile[MAX_PATH];
WCHAR CovFileName[MAX_PATH];
WCHAR BodyFileName[MAX_PATH];
WCHAR ExistingFile[MAX_PATH];
DWORD rc;
LPWSTR p;
FAX_JOB_PARAMW JobParams;
FAX_COVERPAGE_INFOW CoverpageInfo;
DWORD TmpFaxJobId;
DWORD BcFaxJobId = 0;
DWORD i = 1;
HANDLE hTiff = NULL;
TIFF_INFO TiffInfo;
DWORD PageCount;
if (!ValidateFaxHandle(FaxHandle, FHT_SERVICE)) {
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (!FileName || !FaxRecipientCallback) {
SetLastError (ERROR_INVALID_PARAMETER);
return FALSE;
}
//
// make sure the file is there
//
rc = GetFullPathName(FileName,sizeof(ExistingFile)/sizeof(WCHAR),ExistingFile,&p);
if (rc > MAX_PATH || rc == 0) {
DebugPrint(( TEXT("GetFullPathName failed, ec= %d\n"),GetLastError() ));
SetLastError( (rc > MAX_PATH)
? ERROR_BUFFER_OVERFLOW
: GetLastError() );
return FALSE;
}
if (GetFileAttributes(ExistingFile)==0xFFFFFFFF) {
SetLastError(ERROR_FILE_NOT_FOUND);
return FALSE;
}
ZeroMemory(TiffFile,sizeof(TiffFile));
if (!CreateFinalTiffFile( (LPWSTR) ExistingFile, TiffFile, NULL)) {
DeleteFile( TiffFile );
SetLastError(ERROR_INVALID_DATA);
return FALSE;
}
hTiff = TiffOpen( TiffFile, &TiffInfo, TRUE, FILLORDER_MSB2LSB );
if (hTiff == NULL) {
DeleteFile( TiffFile );
SetLastError(ERROR_INVALID_DATA);
return FALSE;
}
PageCount = TiffInfo.PageCount;
TiffClose( hTiff );
if (!CopyFileToServerQueue( FaxHandle, TiffFile, BodyFileName )) {
DeleteFile( TiffFile );
return FALSE;
}
//
// the passed in file should be treated as read-only
// if we created a temp file then delete it
//
if (wcscmp(ExistingFile,TiffFile) != 0) {
DeleteFile( TiffFile );
}
ZeroMemory( &JobParams, sizeof(JobParams) );
JobParams.SizeOfStruct = sizeof(JobParams);
JobParams.Reserved[0] = 0xfffffffe;
JobParams.Reserved[1] = 1;
JobParams.Reserved[2] = 0;
ec = FAX_SendDocument( FH_FAX_HANDLE(FaxHandle), BodyFileName, &JobParams, &BcFaxJobId );
if (ec) {
SetLastError( ec );
return FALSE;
}
if (FaxJobId) {
*FaxJobId = BcFaxJobId;
}
while (TRUE) {
ZeroMemory( &JobParams, sizeof(JobParams) );
JobParams.SizeOfStruct = sizeof(JobParams);
ZeroMemory( &CoverpageInfo, sizeof(CoverpageInfo) );
CoverpageInfo.SizeOfStruct = sizeof(CoverpageInfo);
if (!FaxRecipientCallback( FaxHandle, i, Context, &JobParams, &CoverpageInfo )) {
break;
}
if (JobParams.RecipientNumber == NULL) {
continue;
}
JobParams.Reserved[0] = 0xfffffffe;
JobParams.Reserved[1] = 2;
JobParams.Reserved[2] = BcFaxJobId;
CoverpageInfo.PageCount = PageCount + 1;
GetLocalTime( &CoverpageInfo.TimeSent );
if (CreateCoverpageTiffFile( &CoverpageInfo, TempFile )) {
if (CopyFileToServerQueue( FaxHandle, TempFile, CovFileName )) {
ec = FAX_SendDocument( FH_FAX_HANDLE(FaxHandle), CovFileName, &JobParams, &TmpFaxJobId );
if (ec) {
DeleteFile( TempFile );
SetLastError( ec );
return FALSE;
}
}
DeleteFile( TempFile );
} else {
ec = FAX_SendDocument( FH_FAX_HANDLE(FaxHandle), NULL, &JobParams, &TmpFaxJobId );
if (ec) {
SetLastError( ec );
return FALSE;
}
}
i += 1;
}
return TRUE;
}
BOOL
ConvertCoverpageAndJobInfo(PFAX_JOB_PARAMW JobParams,PFAX_COVERPAGE_INFOW CoverpageInfo)
{
#define MyConvertString(TargetString) if (TargetString) { \
TargetString = AnsiStringToUnicodeString((LPCSTR) TargetString); \
}
MyConvertString(JobParams->RecipientNumber);
MyConvertString(JobParams->RecipientName);
MyConvertString(JobParams->Tsid);
MyConvertString(JobParams->SenderName);
MyConvertString(JobParams->SenderDept);
MyConvertString(JobParams->SenderCompany);
MyConvertString(JobParams->BillingCode);
MyConvertString(JobParams->DeliveryReportAddress);
MyConvertString(JobParams->DocumentName);
MyConvertString(CoverpageInfo->CoverPageName);
MyConvertString(CoverpageInfo->RecName);
MyConvertString(CoverpageInfo->RecFaxNumber);
MyConvertString(CoverpageInfo->RecCompany);
MyConvertString(CoverpageInfo->RecStreetAddress);
MyConvertString(CoverpageInfo->RecCity);
MyConvertString(CoverpageInfo->RecState);
MyConvertString(CoverpageInfo->RecZip);
MyConvertString(CoverpageInfo->RecCountry);
MyConvertString(CoverpageInfo->RecTitle);
MyConvertString(CoverpageInfo->RecDepartment);
MyConvertString(CoverpageInfo->RecOfficeLocation);
MyConvertString(CoverpageInfo->RecHomePhone);
MyConvertString(CoverpageInfo->RecOfficePhone);
MyConvertString(CoverpageInfo->SdrName);
MyConvertString(CoverpageInfo->SdrFaxNumber);
MyConvertString(CoverpageInfo->SdrCompany);
MyConvertString(CoverpageInfo->SdrAddress);
MyConvertString(CoverpageInfo->SdrTitle);
MyConvertString(CoverpageInfo->SdrDepartment);
MyConvertString(CoverpageInfo->SdrOfficeLocation);
MyConvertString(CoverpageInfo->SdrHomePhone);
MyConvertString(CoverpageInfo->SdrOfficePhone);
MyConvertString(CoverpageInfo->Note);
MyConvertString(CoverpageInfo->Subject);
return TRUE;
}
BOOL
FreeCoverpageAndJobInfo(PFAX_JOB_PARAMW JobParams,PFAX_COVERPAGE_INFOW CoverpageInfo) {
#define MyFreeString(TargetString) if (TargetString) { \
MemFree( (LPBYTE) TargetString); \
}
MyFreeString(JobParams->RecipientNumber);
MyFreeString(JobParams->RecipientName);
MyFreeString(JobParams->Tsid);
MyFreeString(JobParams->SenderName);
MyFreeString(JobParams->SenderDept);
MyFreeString(JobParams->SenderCompany);
MyFreeString(JobParams->BillingCode);
MyFreeString(JobParams->DeliveryReportAddress);
MyFreeString(JobParams->DocumentName);
MyFreeString(CoverpageInfo->CoverPageName);
MyFreeString(CoverpageInfo->RecName);
MyFreeString(CoverpageInfo->RecFaxNumber);
MyFreeString(CoverpageInfo->RecCompany);
MyFreeString(CoverpageInfo->RecStreetAddress);
MyFreeString(CoverpageInfo->RecCity);
MyFreeString(CoverpageInfo->RecState);
MyFreeString(CoverpageInfo->RecZip);
MyFreeString(CoverpageInfo->RecCountry);
MyFreeString(CoverpageInfo->RecTitle);
MyFreeString(CoverpageInfo->RecDepartment);
MyFreeString(CoverpageInfo->RecOfficeLocation);
MyFreeString(CoverpageInfo->RecHomePhone);
MyFreeString(CoverpageInfo->RecOfficePhone);
MyFreeString(CoverpageInfo->SdrName);
MyFreeString(CoverpageInfo->SdrFaxNumber);
MyFreeString(CoverpageInfo->SdrCompany);
MyFreeString(CoverpageInfo->SdrAddress);
MyFreeString(CoverpageInfo->SdrTitle);
MyFreeString(CoverpageInfo->SdrDepartment);
MyFreeString(CoverpageInfo->SdrOfficeLocation);
MyFreeString(CoverpageInfo->SdrHomePhone);
MyFreeString(CoverpageInfo->SdrOfficePhone);
MyFreeString(CoverpageInfo->Note);
MyFreeString(CoverpageInfo->Subject);
return TRUE;
}
WINFAXAPI
BOOL
WINAPI
FaxSendDocumentForBroadcastA(
IN HANDLE FaxHandle,
IN LPCSTR FileNameA,
OUT LPDWORD FaxJobId,
IN PFAX_RECIPIENT_CALLBACKA FaxRecipientCallbackA,
IN LPVOID Context
)
{
error_status_t ec;
WCHAR TempFile[MAX_PATH];
WCHAR TiffFile[MAX_PATH];
WCHAR CovFileName[MAX_PATH];
WCHAR BodyFileName[MAX_PATH];
FAX_JOB_PARAMW JobParams;
FAX_COVERPAGE_INFOW CoverpageInfo;
DWORD TmpFaxJobId;
DWORD BcFaxJobId = 0;
DWORD i = 1;
HANDLE hTiff = NULL;
TIFF_INFO TiffInfo;
DWORD PageCount;
LPWSTR FileName;
if (!ValidateFaxHandle(FaxHandle, FHT_SERVICE)) {
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (!FileNameA || !FaxRecipientCallbackA) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
FileName = AnsiStringToUnicodeString(FileNameA);
if (!CreateFinalTiffFile( FileName, TiffFile, NULL )) {
DeleteFile( TiffFile );
SetLastError(ERROR_INVALID_DATA);
return FALSE;
}
hTiff = TiffOpen( TiffFile, &TiffInfo, TRUE, FILLORDER_MSB2LSB );
if (hTiff == NULL) {
DeleteFile( TiffFile );
return FALSE;
}
PageCount = TiffInfo.PageCount;
TiffClose( hTiff );
if (!CopyFileToServerQueue( FaxHandle, TiffFile, BodyFileName )) {
DeleteFile( TiffFile );
return FALSE;
}
//
// the passed in file should be treated as read-only
// if we created a temp file then delete it
//
if (wcscmp(FileName,TiffFile) != 0) {
DeleteFile( TiffFile );
}
ZeroMemory( &JobParams, sizeof(JobParams) );
JobParams.SizeOfStruct = sizeof(JobParams);
JobParams.Reserved[0] = 0xfffffffe;
JobParams.Reserved[1] = 1;
JobParams.Reserved[2] = 0;
ec = FAX_SendDocument( FH_FAX_HANDLE(FaxHandle), BodyFileName, &JobParams, &BcFaxJobId );
if (ec) {
SetLastError( ec );
return FALSE;
}
if (FaxJobId) {
*FaxJobId = BcFaxJobId;
}
while (TRUE) {
ZeroMemory( &JobParams, sizeof(JobParams) );
JobParams.SizeOfStruct = sizeof(JobParams);
ZeroMemory( &CoverpageInfo, sizeof(CoverpageInfo) );
CoverpageInfo.SizeOfStruct = sizeof(CoverpageInfo);
if (!FaxRecipientCallbackA( FaxHandle, i, Context, (PFAX_JOB_PARAMA)&JobParams,(PFAX_COVERPAGE_INFOA) &CoverpageInfo )) {
break;
}
if (JobParams.RecipientNumber == NULL) {
continue;
}
ConvertCoverpageAndJobInfo(&JobParams,&CoverpageInfo);
JobParams.Reserved[0] = 0xfffffffe;
JobParams.Reserved[1] = 2;
JobParams.Reserved[2] = BcFaxJobId;
CoverpageInfo.PageCount = PageCount + 1;
GetLocalTime( &CoverpageInfo.TimeSent );
if (CreateCoverpageTiffFile( &CoverpageInfo, TempFile )) {
if (CopyFileToServerQueue( FaxHandle, TempFile, CovFileName )) {
ec = FAX_SendDocument( FH_FAX_HANDLE(FaxHandle), CovFileName, &JobParams, &TmpFaxJobId );
if (ec) {
DeleteFile( TempFile );
SetLastError( ec );
return FALSE;
}
}
DeleteFile( TempFile );
} else {
ec = FAX_SendDocument( FH_FAX_HANDLE(FaxHandle), NULL, &JobParams, &TmpFaxJobId );
if (ec) {
SetLastError( ec );
return FALSE;
}
}
i += 1;
FreeCoverpageAndJobInfo(&JobParams,&CoverpageInfo);
}
return TRUE;
}
BOOL
WINAPI
FaxSendDocumentA(
IN HANDLE FaxHandle,
IN LPCSTR FileName,
IN FAX_JOB_PARAMA *JobParamsA,
IN const FAX_COVERPAGE_INFOA *CoverpageInfoA,
OUT LPDWORD FaxJobId
)
/*++
Routine Description:
Sends a FAX document to the specified recipient.
This is an asychronous operation. Use FaxReportStatus
to determine when the send is completed.
Arguments:
FaxHandle - FAX handle obtained from FaxConnectFaxServer.
FileName - File containing the TIFF-F FAX document.
JobParams - pointer to FAX_JOB_PARAM structure with transmission params
CoverpageInfo - optional pointer to FAX_COVERPAGE_INFO structure
FaxJobId - receives the Fax JobId for the job.
Return Value:
TRUE - Success
FALSE - Failure, call GetLastError() for more error information.
--*/
{
error_status_t ec;
LPWSTR FileNameW;
FAX_JOB_PARAMW JobParamsW;
FAX_COVERPAGE_INFOW CoverpageInfoW;
if (!FileName || !JobParamsA || JobParamsA->SizeOfStruct != sizeof(FAX_JOB_PARAMA)) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (CoverpageInfoA && CoverpageInfoA->SizeOfStruct != sizeof(FAX_COVERPAGE_INFOA)) {
SetLastError(ERROR_INVALID_DATA);
return FALSE;
}
FileNameW = AnsiStringToUnicodeString( FileName );
if (FileNameW == NULL) {
goto exit;
}
CopyMemory(&JobParamsW, JobParamsA, sizeof(FAX_JOB_PARAMA));
JobParamsW.SizeOfStruct = sizeof(FAX_JOB_PARAMW);
JobParamsW.RecipientNumber = AnsiStringToUnicodeString(JobParamsA->RecipientNumber);
JobParamsW.RecipientName = AnsiStringToUnicodeString(JobParamsA->RecipientName);
JobParamsW.Tsid = AnsiStringToUnicodeString(JobParamsA->Tsid);
JobParamsW.SenderName = AnsiStringToUnicodeString(JobParamsA->SenderName);
JobParamsW.SenderCompany = AnsiStringToUnicodeString(JobParamsA->SenderCompany);
JobParamsW.SenderDept = AnsiStringToUnicodeString(JobParamsA->SenderDept);
JobParamsW.BillingCode = AnsiStringToUnicodeString(JobParamsA->BillingCode);
JobParamsW.DeliveryReportAddress = AnsiStringToUnicodeString(JobParamsA->DeliveryReportAddress);
JobParamsW.DocumentName = AnsiStringToUnicodeString(JobParamsA->DocumentName);
if (CoverpageInfoA) {
CoverpageInfoW.SizeOfStruct = sizeof(FAX_COVERPAGE_INFOW);
CoverpageInfoW.UseServerCoverPage = CoverpageInfoA->UseServerCoverPage;
CoverpageInfoW.PageCount = CoverpageInfoA->PageCount;
CoverpageInfoW.TimeSent = CoverpageInfoA->TimeSent;
CoverpageInfoW.CoverPageName = AnsiStringToUnicodeString( CoverpageInfoA->CoverPageName );
CoverpageInfoW.RecName = AnsiStringToUnicodeString( CoverpageInfoA->RecName );
CoverpageInfoW.RecFaxNumber = AnsiStringToUnicodeString( CoverpageInfoA->RecFaxNumber );
CoverpageInfoW.RecCompany = AnsiStringToUnicodeString( CoverpageInfoA->RecCompany );
CoverpageInfoW.RecStreetAddress = AnsiStringToUnicodeString( CoverpageInfoA->RecStreetAddress );
CoverpageInfoW.RecCity = AnsiStringToUnicodeString( CoverpageInfoA->RecCity );
CoverpageInfoW.RecState = AnsiStringToUnicodeString( CoverpageInfoA->RecState );
CoverpageInfoW.RecZip = AnsiStringToUnicodeString( CoverpageInfoA->RecZip );
CoverpageInfoW.RecCountry = AnsiStringToUnicodeString( CoverpageInfoA->RecCountry );
CoverpageInfoW.RecTitle = AnsiStringToUnicodeString( CoverpageInfoA->RecTitle );
CoverpageInfoW.RecDepartment = AnsiStringToUnicodeString( CoverpageInfoA->RecDepartment );
CoverpageInfoW.RecOfficeLocation = AnsiStringToUnicodeString( CoverpageInfoA->RecOfficeLocation );
CoverpageInfoW.RecHomePhone = AnsiStringToUnicodeString( CoverpageInfoA->RecHomePhone );
CoverpageInfoW.RecOfficePhone = AnsiStringToUnicodeString( CoverpageInfoA->RecOfficePhone );
CoverpageInfoW.SdrName = AnsiStringToUnicodeString( CoverpageInfoA->SdrName );
CoverpageInfoW.SdrFaxNumber = AnsiStringToUnicodeString( CoverpageInfoA->SdrFaxNumber );
CoverpageInfoW.SdrCompany = AnsiStringToUnicodeString( CoverpageInfoA->SdrCompany );
CoverpageInfoW.SdrAddress = AnsiStringToUnicodeString( CoverpageInfoA->SdrAddress );
CoverpageInfoW.SdrTitle = AnsiStringToUnicodeString( CoverpageInfoA->SdrTitle );
CoverpageInfoW.SdrDepartment = AnsiStringToUnicodeString( CoverpageInfoA->SdrDepartment );
CoverpageInfoW.SdrOfficeLocation = AnsiStringToUnicodeString( CoverpageInfoA->SdrOfficeLocation );
CoverpageInfoW.SdrHomePhone = AnsiStringToUnicodeString( CoverpageInfoA->SdrHomePhone );
CoverpageInfoW.SdrOfficePhone = AnsiStringToUnicodeString( CoverpageInfoA->SdrOfficePhone );
CoverpageInfoW.Note = AnsiStringToUnicodeString( CoverpageInfoA->Note );
CoverpageInfoW.Subject = AnsiStringToUnicodeString( CoverpageInfoA->Subject );
}
if (FaxSendDocumentW( FaxHandle,
FileNameW,
&JobParamsW,
CoverpageInfoA ? &CoverpageInfoW : NULL,
FaxJobId )) {
ec = 0;
} else {
ec = GetLastError();
}
exit:
MemFree( (LPBYTE) FileNameW );
MemFree( (LPBYTE) JobParamsW.RecipientNumber );
MemFree( (LPBYTE) JobParamsW.RecipientName );
MemFree( (LPBYTE) JobParamsW.Tsid );
MemFree( (LPBYTE) JobParamsW.SenderName );
MemFree( (LPBYTE) JobParamsW.SenderDept );
MemFree( (LPBYTE) JobParamsW.SenderCompany );
MemFree( (LPBYTE) JobParamsW.BillingCode );
MemFree( (LPBYTE) JobParamsW.DeliveryReportAddress );
MemFree( (LPBYTE) JobParamsW.DocumentName );
if (CoverpageInfoA) {
MemFree( (LPBYTE) CoverpageInfoW.CoverPageName );
MemFree( (LPBYTE) CoverpageInfoW.RecName );
MemFree( (LPBYTE) CoverpageInfoW.RecFaxNumber );
MemFree( (LPBYTE) CoverpageInfoW.RecCompany );
MemFree( (LPBYTE) CoverpageInfoW.RecStreetAddress );
MemFree( (LPBYTE) CoverpageInfoW.RecCity );
MemFree( (LPBYTE) CoverpageInfoW.RecState );
MemFree( (LPBYTE) CoverpageInfoW.RecZip );
MemFree( (LPBYTE) CoverpageInfoW.RecCountry );
MemFree( (LPBYTE) CoverpageInfoW.RecTitle );
MemFree( (LPBYTE) CoverpageInfoW.RecDepartment );
MemFree( (LPBYTE) CoverpageInfoW.RecOfficeLocation );
MemFree( (LPBYTE) CoverpageInfoW.RecHomePhone );
MemFree( (LPBYTE) CoverpageInfoW.RecOfficePhone );
MemFree( (LPBYTE) CoverpageInfoW.SdrName );
MemFree( (LPBYTE) CoverpageInfoW.SdrFaxNumber );
MemFree( (LPBYTE) CoverpageInfoW.SdrCompany );
MemFree( (LPBYTE) CoverpageInfoW.SdrAddress );
MemFree( (LPBYTE) CoverpageInfoW.SdrTitle );
MemFree( (LPBYTE) CoverpageInfoW.SdrDepartment );
MemFree( (LPBYTE) CoverpageInfoW.SdrOfficeLocation );
MemFree( (LPBYTE) CoverpageInfoW.SdrHomePhone );
MemFree( (LPBYTE) CoverpageInfoW.SdrOfficePhone );
MemFree( (LPBYTE) CoverpageInfoW.Note );
MemFree( (LPBYTE) CoverpageInfoW.Subject );
}
if (ec) {
SetLastError( ec );
return FALSE;
}
return TRUE;
}
BOOL
WINAPI
FaxAbort(
IN HANDLE FaxHandle,
IN DWORD JobId
)
/*++
Routine Description:
Abort the specified FAX job. All outstanding FAX
operations are terminated.
Arguments:
FaxHandle - FAX Server handle obtained from FaxConnectFaxServer.
JobId - job id.
Return Value:
TRUE - Success
FALSE - Failure, call GetLastError() for more error information.
--*/
{
error_status_t ec;
//
// argument validation
//
if (!ValidateFaxHandle(FaxHandle, FHT_SERVICE)) {
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
ec = FAX_Abort( (handle_t) FH_FAX_HANDLE(FaxHandle),(DWORD) JobId );
if (ec) {
SetLastError( ec );
return FALSE;
}
return TRUE;
}
BOOL
WINAPI
FaxEnumJobsW(
IN HANDLE FaxHandle,
OUT PFAX_JOB_ENTRYW *JobEntryBuffer,
OUT LPDWORD JobsReturned
)
{
PFAX_JOB_ENTRYW JobEntry;
error_status_t ec;
DWORD BufferSize = 0;
DWORD i;
DWORD Size;
if (!ValidateFaxHandle(FaxHandle, FHT_SERVICE)) {
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (!JobEntryBuffer || !JobsReturned) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
*JobEntryBuffer = NULL;
*JobsReturned = 0;
Size = 0;
ec = FAX_EnumJobs( FH_FAX_HANDLE(FaxHandle), (LPBYTE*)JobEntryBuffer, &Size, JobsReturned );
if (ec) {
SetLastError( ec );
return FALSE;
}
JobEntry = (PFAX_JOB_ENTRYW) *JobEntryBuffer;
for (i=0; i<*JobsReturned; i++) {
FixupStringPtr( JobEntryBuffer, JobEntry[i].UserName );
FixupStringPtr( JobEntryBuffer, JobEntry[i].RecipientNumber );
FixupStringPtr( JobEntryBuffer, JobEntry[i].RecipientName );
FixupStringPtr( JobEntryBuffer, JobEntry[i].DocumentName );
FixupStringPtr( JobEntryBuffer, JobEntry[i].Tsid );
FixupStringPtr( JobEntryBuffer, JobEntry[i].SenderName );
FixupStringPtr( JobEntryBuffer, JobEntry[i].SenderCompany );
FixupStringPtr( JobEntryBuffer, JobEntry[i].SenderDept );
FixupStringPtr( JobEntryBuffer, JobEntry[i].BillingCode );
FixupStringPtr( JobEntryBuffer, JobEntry[i].DeliveryReportAddress );
}
return TRUE;
}
BOOL
WINAPI
FaxEnumJobsA(
IN HANDLE FaxHandle,
OUT PFAX_JOB_ENTRYA *JobEntryBuffer,
OUT LPDWORD JobsReturned
)
{
PFAX_JOB_ENTRYW JobEntry;
DWORD i;
if (!FaxEnumJobsW( FaxHandle, (PFAX_JOB_ENTRYW *)JobEntryBuffer, JobsReturned)) {
return FALSE;
}
JobEntry = (PFAX_JOB_ENTRYW) *JobEntryBuffer;
for (i=0; i<*JobsReturned; i++) {
ConvertUnicodeStringInPlace( (LPCWSTR) JobEntry[i].UserName );
ConvertUnicodeStringInPlace( (LPCWSTR) JobEntry[i].RecipientNumber );
ConvertUnicodeStringInPlace( (LPCWSTR) JobEntry[i].RecipientName );
ConvertUnicodeStringInPlace( (LPCWSTR) JobEntry[i].DocumentName );
ConvertUnicodeStringInPlace( (LPCWSTR) JobEntry[i].Tsid );
ConvertUnicodeStringInPlace( (LPCWSTR) JobEntry[i].SenderName );
ConvertUnicodeStringInPlace( (LPCWSTR) JobEntry[i].SenderCompany );
ConvertUnicodeStringInPlace( (LPCWSTR) JobEntry[i].SenderDept );
ConvertUnicodeStringInPlace( (LPCWSTR) JobEntry[i].BillingCode );
ConvertUnicodeStringInPlace( (LPCWSTR) JobEntry[i].DeliveryReportAddress );
}
return TRUE;
}
BOOL
WINAPI
FaxSetJobW(
IN HANDLE FaxHandle,
IN DWORD JobId,
IN DWORD Command,
IN const FAX_JOB_ENTRYW *JobEntry
)
/*++
Routine Description:
set job status information for a requested JobId
Note that this is the fax server JobId, not a spooler job ID.
Arguments:
FaxHandle - FAX handle obtained from FaxConnectFaxServer
JobId - Fax service Job ID
Command - JC_* constant for controlling the job
JobEntry - pointer to Buffer holding the job information
Return Value:
ERROR_SUCCESS for success, otherwise a WIN32 error code.
--*/
{
error_status_t ec;
//
// argument validation
//
//if (!FaxHandle || !JobEntry || Command > JC_RESTART || Command == JC_UNKNOWN || JobId != JobEntry->JobId) {
if (!ValidateFaxHandle(FaxHandle, FHT_SERVICE)) {
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (!JobEntry || Command > JC_RESTART || Command == JC_UNKNOWN) {
SetLastError (ERROR_INVALID_PARAMETER);
return FALSE;
}
ec = FAX_SetJob( FH_FAX_HANDLE(FaxHandle), JobId, Command, JobEntry );
if (ec) {
SetLastError( ec );
return FALSE;
}
return TRUE;
}
BOOL
WINAPI
FaxSetJobA(
IN HANDLE FaxHandle,
IN DWORD JobId,
IN DWORD Command,
IN const FAX_JOB_ENTRYA *JobEntryA
)
/*++
Routine Description:
set job status information for a requested JobId
Note that this is the fax server JobId, not a spooler job ID.
Arguments:
FaxHandle - FAX handle obtained from FaxConnectFaxServer
JobId - Fax service Job ID
Command - JC_* constant for controlling the job
JobEntryA - pointer to Buffer holding the job information
Return Value:
ERROR_SUCCESS for success, otherwise a WIN32 error code.
--*/
{
FAX_JOB_ENTRYW JobEntryW;
error_status_t ec = 0;
if (!JobEntryA) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
JobEntryW.SizeOfStruct = sizeof(FAX_JOB_ENTRYW);
JobEntryW.JobId = JobEntryA->JobId;
JobEntryW.UserName = AnsiStringToUnicodeString(JobEntryA->UserName);
JobEntryW.JobType = JobEntryA->JobType;
JobEntryW.QueueStatus = JobEntryA->QueueStatus;
JobEntryW.Status = JobEntryA->Status;
JobEntryW.PageCount = JobEntryA->PageCount;
JobEntryW.RecipientNumber = AnsiStringToUnicodeString(JobEntryA->RecipientNumber);
JobEntryW.RecipientName = AnsiStringToUnicodeString(JobEntryA->RecipientName);
JobEntryW.Tsid = AnsiStringToUnicodeString(JobEntryA->Tsid);
JobEntryW.SenderName = AnsiStringToUnicodeString(JobEntryA->SenderName);
JobEntryW.SenderCompany = AnsiStringToUnicodeString(JobEntryA->SenderCompany);
JobEntryW.SenderDept = AnsiStringToUnicodeString(JobEntryA->SenderDept);
JobEntryW.BillingCode = AnsiStringToUnicodeString(JobEntryA->BillingCode);
JobEntryW.ScheduleAction = JobEntryA->ScheduleAction;
JobEntryW.ScheduleTime = JobEntryA->ScheduleTime;
JobEntryW.DeliveryReportType = JobEntryA->DeliveryReportType;
JobEntryW.DeliveryReportAddress = AnsiStringToUnicodeString(JobEntryA->DeliveryReportAddress);
JobEntryW.DocumentName = AnsiStringToUnicodeString(JobEntryA->DocumentName);
if (!FaxSetJobW( FaxHandle, JobId, Command, &JobEntryW) ) {
ec = GetLastError();
}
MemFree( (LPBYTE) JobEntryW.UserName);
MemFree( (LPBYTE) JobEntryW.RecipientNumber );
MemFree( (LPBYTE) JobEntryW.RecipientName );
MemFree( (LPBYTE) JobEntryW.Tsid );
MemFree( (LPBYTE) JobEntryW.SenderName );
MemFree( (LPBYTE) JobEntryW.SenderDept );
MemFree( (LPBYTE) JobEntryW.SenderCompany );
MemFree( (LPBYTE) JobEntryW.BillingCode );
MemFree( (LPBYTE) JobEntryW.DeliveryReportAddress );
MemFree( (LPBYTE) JobEntryW.DocumentName );
if (ec != 0) {
SetLastError(ec);
return FALSE;
}
return TRUE;
}
BOOL
WINAPI
FaxGetJobW(
IN HANDLE FaxHandle,
IN DWORD JobId,
IN PFAX_JOB_ENTRYW *JobEntryBuffer
)
/*++
Routine Description:
Returns job status information for a requested JobId
Note that this is the fax server JobId, not a spooler job ID.
Arguments:
FaxHandle - FAX handle obtained from FaxConnectFaxServer
JobId - Fax service Job ID
JobEntryBuffer - Buffer to hold the job information
Return Value:
ERROR_SUCCESS for success, otherwise a WIN32 error code.
--*/
{
error_status_t ec = 0;
PFAX_JOB_ENTRY JobEntry;
DWORD JobEntrySize = 0;
//
// parameter validation
//
if (!ValidateFaxHandle(FaxHandle, FHT_SERVICE)) {
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (!JobEntryBuffer) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
*JobEntryBuffer = NULL;
ec = FAX_GetJob( FH_FAX_HANDLE(FaxHandle), JobId, (char **) JobEntryBuffer , &JobEntrySize );
if (ec) {
SetLastError( ec );
return FALSE;
}
JobEntry = (PFAX_JOB_ENTRY) *JobEntryBuffer;
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntry->UserName);
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntry->RecipientNumber );
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntry->RecipientName );
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntry->Tsid );
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntry->SenderName );
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntry->SenderDept );
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntry->SenderCompany );
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntry->BillingCode );
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntry->DeliveryReportAddress );
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntry->DocumentName );
return TRUE;
}
BOOL
WINAPI
FaxGetJobA(
IN HANDLE FaxHandle,
IN DWORD JobId,
IN PFAX_JOB_ENTRYA *JobEntryBuffer
)
/*++
Routine Description:
Returns job status information for a requested JobId
Note that this is the fax server JobId, not a spooler job ID.
Arguments:
FaxHandle - FAX handle obtained from FaxConnectFaxServer
JobId - Fax service Job ID
JobEntryBuffer - Buffer to hold the job information
Return Value:
ERROR_SUCCESS for success, otherwise a WIN32 error code.
--*/
{
PFAX_JOB_ENTRYW JobEntryW;
DWORD JobEntrySize = 0;
error_status_t ec = 0;
if (!ValidateFaxHandle(FaxHandle, FHT_SERVICE)) {
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (!JobEntryBuffer) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
*JobEntryBuffer = NULL;
ec = FAX_GetJob( FH_FAX_HANDLE(FaxHandle), JobId, (char **) JobEntryBuffer,&JobEntrySize );
if (ec) {
JobEntryBuffer = NULL;
SetLastError(ec);
return FALSE;
}
//
// convert to Ansi
//
JobEntryW = (PFAX_JOB_ENTRYW) *JobEntryBuffer;
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntryW->UserName);
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntryW->RecipientNumber );
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntryW->RecipientName );
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntryW->Tsid );
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntryW->SenderName );
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntryW->SenderDept );
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntryW->SenderCompany );
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntryW->BillingCode );
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntryW->DeliveryReportAddress );
FixupStringPtr (JobEntryBuffer, (LPCWSTR) JobEntryW->DocumentName );
ConvertUnicodeStringInPlace( (LPCWSTR)JobEntryW->UserName);
ConvertUnicodeStringInPlace( (LPCWSTR)JobEntryW->RecipientNumber );
ConvertUnicodeStringInPlace( (LPCWSTR)JobEntryW->RecipientName );
ConvertUnicodeStringInPlace( (LPCWSTR)JobEntryW->Tsid );
ConvertUnicodeStringInPlace( (LPCWSTR)JobEntryW->SenderName );
ConvertUnicodeStringInPlace( (LPCWSTR)JobEntryW->SenderDept );
ConvertUnicodeStringInPlace( (LPCWSTR)JobEntryW->SenderCompany );
ConvertUnicodeStringInPlace( (LPCWSTR)JobEntryW->BillingCode );
ConvertUnicodeStringInPlace( (LPCWSTR)JobEntryW->DeliveryReportAddress );
ConvertUnicodeStringInPlace( (LPCWSTR)JobEntryW->DocumentName );
return TRUE;
}
BOOL
WINAPI
FaxGetPageData(
IN HANDLE FaxHandle,
IN DWORD JobId,
OUT LPBYTE *Buffer,
OUT LPDWORD BufferSize,
OUT LPDWORD ImageWidth,
OUT LPDWORD ImageHeight
)
{
error_status_t ec;
if (!ValidateFaxHandle(FaxHandle, FHT_SERVICE)) {
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (!Buffer || !BufferSize || !ImageWidth || !ImageHeight) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
*Buffer = NULL;
*BufferSize = 0;
*ImageWidth = 0;
*ImageHeight = 0;
ec = FAX_GetPageData( FH_FAX_HANDLE(FaxHandle), JobId, Buffer, BufferSize, ImageWidth, ImageHeight );
if (ec) {
SetLastError( ec );
return FALSE;
}
return TRUE;
}