2381 lines
65 KiB
C
2381 lines
65 KiB
C
|
/*++
|
||
|
|
||
|
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;
|
||
|
}
|