Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1361 lines
35 KiB

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
print.c
Abstract:
This module contains the print specific WINFAX API functions.
Author:
Wesley Witt (wesw) 29-Nov-1996
Revision History:
4-Dec-1999 Danl Use fixed GetFaxPrinterName.
--*/
#include "faxapi.h"
#include "faxreg.h"
#include "faxutil.h"
#pragma hdrstop
#include <mbstring.h>
#define NIL _T('\0')
BOOL
WINAPI
FaxStartPrintJob(
IN LPCTSTR PrinterName,
IN const FAX_PRINT_INFO *PrintInfo,
OUT LPDWORD FaxJobId,
OUT PFAX_CONTEXT_INFO FaxContextInfo
)
/*++
Routine Description:
Starts a print job for the specified printer. This
function provides functionality beyond what the caller
can provide by using StartDoc(). This function disables
the display of the fax send wizard and also passes along
the information that would otherwise be gathered by the
fax wizard ui.
Arguments:
PrinterName - Fax printer name (must be a fax printer)
PrintInfo - Fax print information
FaxJobId - Job id of the resulting print job
FaxContextInfo - context information including hdc
Return Value:
TRUE for success.
FALSE for failure.
--*/
{
return FaxStartPrintJob2 ( PrinterName,
PrintInfo,
0, // Default resolution
FaxJobId,
FaxContextInfo);
}
#ifdef UNICODE
BOOL
WINAPI
FaxStartPrintJobA(
IN LPCSTR PrinterName,
IN const FAX_PRINT_INFOA *PrintInfo,
OUT LPDWORD FaxJobId,
OUT FAX_CONTEXT_INFOA *FaxContextInfo
)
/*++
Routine Description:
Starts a print job for the specified printer. This
function provides functionality beyond what the caller
can provide by using StartDoc(). This function disables
the display of the fax send wizard and also passes along
the information that would otherwise be gathered by the
fax wizard ui.
Arguments:
PrinterName - Fax printer name (must be a fax printer)
PrintInfo - Fax print information
FaxJobId - Job id of the resulting print job
FaxContextInfo - device context information (hdc, etc.)
Return Value:
TRUE for success.
FALSE for failure.
--*/
{
return FaxStartPrintJob2A ( PrinterName,
PrintInfo,
0, // Default resolution
FaxJobId,
FaxContextInfo);;
}
#else
BOOL
WINAPI
FaxStartPrintJobW(
IN LPCWSTR PrinterName,
IN const FAX_PRINT_INFOW *PrintInfo,
OUT LPDWORD FaxJobId,
OUT PFAX_CONTEXT_INFOW FaxContextInfo
)
{
UNREFERENCED_PARAMETER(PrinterName);
UNREFERENCED_PARAMETER(PrintInfo);
UNREFERENCED_PARAMETER(FaxJobId);
UNREFERENCED_PARAMETER(FaxContextInfo);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
#endif
PVOID
MyGetJob(
HANDLE hPrinter,
DWORD level,
DWORD jobId
)
/*++
Routine Description:
Wrapper function for spooler API GetJob
Arguments:
hPrinter - Handle to the printer object
level - Level of JOB_INFO structure interested
jobId - Specifies the job ID
Return Value:
Pointer to a JOB_INFO structure, NULL if there is an error
--*/
{
PBYTE pJobInfo = NULL;
DWORD cbNeeded;
if (!GetJob(hPrinter, jobId, level, NULL, 0, &cbNeeded) &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
(pJobInfo = (PBYTE)MemAlloc(cbNeeded)) &&
GetJob(hPrinter, jobId, level, pJobInfo, cbNeeded, &cbNeeded))
{
return pJobInfo;
}
MemFree(pJobInfo);
return NULL;
}
LPTSTR
GetCpField(
HKEY hKey,
LPTSTR SubKey
)
/*++
Routine Description:
Retrieves the data for a coverpage field from
the registry.
Arguments:
hKey - Registry handle
SubKey - Subkey name
Return Value:
Pointer to the coverpage field data.
--*/
{
LONG rVal;
DWORD RegSize=0;
DWORD RegType;
LPBYTE Buffer;
rVal = RegQueryValueEx( hKey, SubKey, 0, &RegType, NULL, &RegSize );
if (rVal != ERROR_SUCCESS) {
return NULL;
}
Buffer = (LPBYTE) MemAlloc( RegSize );
if (!Buffer) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
rVal = RegQueryValueEx( hKey, SubKey, 0, &RegType, Buffer, &RegSize );
if (rVal != ERROR_SUCCESS) {
MemFree( Buffer );
return NULL;
}
return (LPTSTR) Buffer;
}
BOOL
GetCpFields(
PCOVERPAGEFIELDS CpFields
)
/*++
Routine Description:
Initializes the coverpage field structure and
fills in the sender information from the registry.
This function actually loads only the sender fields.
Arguments:
CpFields - Pointer to a coverpage field structure.
Return Value:
TRUE for success.
FALSE for failure.
--*/
{
HKEY hKey;
LONG rVal;
rVal = RegOpenKey(
HKEY_CURRENT_USER,
REGKEY_FAX_USERINFO,
&hKey
);
if (rVal != ERROR_SUCCESS) {
return FALSE;
}
ZeroMemory( CpFields, sizeof(COVERPAGEFIELDS) );
CpFields->ThisStructSize = sizeof(COVERPAGEFIELDS);
//
// sender fields
//
CpFields->SdrName = GetCpField( hKey, REGVAL_FULLNAME );
CpFields->SdrFaxNumber = GetCpField( hKey, REGVAL_FAX_NUMBER );
CpFields->SdrCompany = GetCpField( hKey, REGVAL_COMPANY );
CpFields->SdrAddress = GetCpField( hKey, REGVAL_ADDRESS );
CpFields->SdrTitle = GetCpField( hKey, REGVAL_TITLE );
CpFields->SdrDepartment = GetCpField( hKey, REGVAL_DEPT );
CpFields->SdrOfficeLocation = GetCpField( hKey, REGVAL_OFFICE );
CpFields->SdrHomePhone = GetCpField( hKey, REGVAL_HOME_PHONE );
CpFields->SdrOfficePhone = GetCpField( hKey, REGVAL_OFFICE_PHONE );
CpFields->SdrEmail = GetCpField( hKey, REGVAL_MAILBOX );
RegCloseKey( hKey );
return TRUE;
}
VOID
FreeCpFields(
PCOVERPAGEFIELDS CpFields
)
/*++
Routine Description:
Frees all memory associated with a coverpage field structure.
Arguments:
CpFields - Pointer to a coverpage field structure.
Return Value:
None.
--*/
{
DWORD i;
LPBYTE *p;
for (i = 0; i < NUM_INSERTION_TAGS; i++) {
p = (LPBYTE *) ((ULONG_PTR)CpFields + sizeof(LPTSTR)*(i+1));
if (p && *p) MemFree( *p );
}
}
BOOL
WINAPI
FaxPrintCoverPage(
IN const FAX_CONTEXT_INFO *FaxContextInfo,
IN const FAX_COVERPAGE_INFO *CoverPageInfo
)
/*++
Routine Description:
Prints a coverpage into the printer DC provided.
Arguments:
FaxContextInfo - contains servername, Printer DC
CoverPageInfo - Cover page information
Return Value:
TRUE for success.
FALSE for failure.
--*/
{
TCHAR CpName[MAX_PATH];
TCHAR Buffer[MAX_PATH];
TCHAR TBuffer[MAX_PATH];
COVERPAGEFIELDS CpFields = {0};
COVDOCINFO CovDocInfo;
DWORD dwDateTimeLen;
DWORD cch;
LPTSTR s;
DWORD ec = 0;
LPCTSTR *src;
LPCTSTR *dst;
DWORD i;
LPCTSTR lpctstrCoverPage,lpctstrServerName;
BOOL retVal = TRUE;
DEBUG_FUNCTION_NAME(TEXT("FaxPrintCoverPage"));
//
// do a little argument validation
//
if (CoverPageInfo == NULL || CoverPageInfo->SizeOfStruct != sizeof(FAX_COVERPAGE_INFOW) ||
FaxContextInfo == NULL || FaxContextInfo->hDC == NULL ||
FaxContextInfo->SizeOfStruct != sizeof (FAX_CONTEXT_INFOW) )
{
DebugPrintEx(DEBUG_ERR,
TEXT("CoverPageInfo is NULL or Size mismatch.")
);
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
lpctstrCoverPage = CoverPageInfo->CoverPageName;
lpctstrServerName = FaxContextInfo->ServerName;
if (!ValidateCoverpage(lpctstrCoverPage,
lpctstrServerName,
CoverPageInfo->UseServerCoverPage,
CpName,
ARR_SIZE(CpName)))
{
DebugPrintEx(DEBUG_ERR,
TEXT("ValidateCoverpage failed. ec = %ld"),
GetLastError());
retVal = FALSE;
goto exit;
}
//
// get the coverpage fields
//
// Initialize the sender fields of CpFields with sender information from the registry
GetCpFields( &CpFields );
//
// fixup the recipient name
//
if (CoverPageInfo->RecName)
{
if( _tcsncmp(CoverPageInfo->RecName,TEXT("\'"),1) == 0 )
{
// The recipient name is single quouted. Copy only the string inside the quotes.
_tcsncpy(Buffer, _tcsinc(CoverPageInfo->RecName), ARR_SIZE(Buffer)-1);
TCHAR* eos = _tcsrchr(Buffer,TEXT('\0'));
eos = _tcsdec(Buffer,eos);
if( eos )
{
_tcsnset(eos,TEXT('\0'),1);
}
}
else
{
_tcsncpy(Buffer, CoverPageInfo->RecName, ARR_SIZE(Buffer)-1);
}
}
else
{
Buffer[0] = 0;
}
//
// fill in the coverpage fields with the
// data that the caller passed in
//
CpFields.RecName = StringDup(Buffer);
CpFields.RecFaxNumber = StringDup(CoverPageInfo->RecFaxNumber);
CpFields.Subject = StringDup(CoverPageInfo->Subject);
CpFields.Note = StringDup(CoverPageInfo->Note);
CpFields.NumberOfPages = StringDup(_itot( CoverPageInfo->PageCount, Buffer, 10 ));
for (i = 0;
i <= ((LPBYTE)&CoverPageInfo->SdrOfficePhone -(LPBYTE)&CoverPageInfo->RecCompany)/sizeof(LPCTSTR);
i++)
{
src = (LPCTSTR *) ((LPBYTE)&CoverPageInfo->RecCompany + (i*sizeof(LPCTSTR)));
dst = (LPCTSTR *) ((LPBYTE)&CpFields.RecCompany + (i*sizeof(LPCTSTR)));
if (*dst)
{
MemFree ( (LPBYTE) *dst ) ;
}
*dst = (LPCTSTR) StringDup( *src );
}
//
// the time the fax was sent
//
GetLocalTime((LPSYSTEMTIME)&CoverPageInfo->TimeSent);
//
// dwDataTimeLen is the size of s in characters
//
dwDateTimeLen = sizeof(TBuffer) / sizeof (TCHAR);
s = TBuffer;
//
// Get date into s
//
GetY2KCompliantDate( LOCALE_USER_DEFAULT, 0, &CoverPageInfo->TimeSent, s, dwDateTimeLen );
//
// Advance s past the date string and attempt to append time
//
cch = _tcslen( s );
s += cch;
if (++cch < dwDateTimeLen)
{
*s++ = ' ';
//
// DateTimeLen is the decreased by the size of s in characters
//
dwDateTimeLen -= cch;
//
// Get the time here
//
FaxTimeFormat( LOCALE_USER_DEFAULT, 0, &CoverPageInfo->TimeSent, NULL, s, dwDateTimeLen );
}
CpFields.TimeSent = StringDup( TBuffer );
//
// start the coverpage on a new page
//
StartPage( FaxContextInfo->hDC );
//
// print the cover page
//
ec = PrintCoverPage(
FaxContextInfo->hDC,
&CpFields,
CpName,
&CovDocInfo
);
//
// end the page
//
EndPage( FaxContextInfo->hDC );
FreeCpFields( &CpFields );
if (ec != 0)
{
DebugPrintEx(DEBUG_ERR,
TEXT("PrintCoverPage failed. ec = %ld"),
ec);
SetLastError( ec );
retVal = FALSE;
goto exit;
}
exit:
return retVal;
}
#ifdef UNICODE
BOOL
WINAPI
FaxPrintCoverPageA(
IN const FAX_CONTEXT_INFOA *FaxContextInfo,
IN const FAX_COVERPAGE_INFOA *CoverPageInfo
)
/*++
Routine Description:
Prints a coverpage into the printer DC provided.
Arguments:
FaxContextInfo - fax Printer context info (hdc, etc.)
CoverPageInfo - Cover page information
Return Value:
TRUE for success.
FALSE for failure.
--*/
{
//
// assume all fields between Subject and RecName are LPCTSTR's
//
#define COUNT_CP_FIELDS ((LPBYTE) &CoverPageInfoW.Subject - (LPBYTE)&CoverPageInfoW.RecName)/sizeof(LPCTSTR)
DWORD Rval = ERROR_SUCCESS;
FAX_COVERPAGE_INFOW CoverPageInfoW = {0};
FAX_CONTEXT_INFOW ContextInfoW = {0};
LPWSTR ServerName = NULL;
LPWSTR *d;
LPSTR *s;
DWORD i;
DEBUG_FUNCTION_NAME(TEXT("FaxPrintCoverPageA"));
if (!FaxContextInfo || !CoverPageInfo ||
FaxContextInfo->SizeOfStruct != sizeof(FAX_CONTEXT_INFOA) ||
CoverPageInfo->SizeOfStruct != sizeof(FAX_COVERPAGE_INFOA))
{
DebugPrintEx(DEBUG_ERR,
TEXT("CoverPageInfo is NULL or Size mismatch.")
);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
ContextInfoW.SizeOfStruct = sizeof(FAX_CONTEXT_INFOW);
ContextInfoW.hDC = FaxContextInfo->hDC;
if (FaxContextInfo->ServerName[0] != (CHAR)'\0')
{
ServerName = AnsiStringToUnicodeString( FaxContextInfo->ServerName );
if (!ServerName && FaxContextInfo->ServerName)
{
Rval = ERROR_OUTOFMEMORY;
goto exit;
}
wcscpy(ContextInfoW.ServerName,ServerName);
}
CoverPageInfoW.SizeOfStruct = sizeof(FAX_COVERPAGE_INFOW);
CoverPageInfoW.UseServerCoverPage = CoverPageInfo->UseServerCoverPage;
CoverPageInfoW.PageCount = CoverPageInfo->PageCount;
CoverPageInfoW.CoverPageName = AnsiStringToUnicodeString( CoverPageInfo->CoverPageName );
if (!CoverPageInfoW.CoverPageName && CoverPageInfo->CoverPageName)
{
Rval = ERROR_OUTOFMEMORY;
goto exit;
}
for (i=0;i<=COUNT_CP_FIELDS;i++)
{
d = (LPWSTR*) ((ULONG_PTR)&CoverPageInfoW.RecName + i*sizeof(LPCWSTR));
s = (LPSTR *) ((LPBYTE)&CoverPageInfo->RecName + i*sizeof(LPSTR));
DebugPrint(( TEXT(" source: 0x%08x --> dest: 0x%08x \n"), s, d));
*d = AnsiStringToUnicodeString( *s );
if (!(*d) && (*s))
{
Rval = ERROR_OUTOFMEMORY;
goto exit;
}
}
CoverPageInfoW.TimeSent = CoverPageInfo->TimeSent;
CoverPageInfoW.PageCount = CoverPageInfo->PageCount;
if (!FaxPrintCoverPageW(
&ContextInfoW,
&CoverPageInfoW
))
{
Rval = GetLastError();
goto exit;
}
Assert (ERROR_SUCCESS == Rval);
exit:
if (CoverPageInfoW.CoverPageName)
{
MemFree( (LPBYTE) CoverPageInfoW.CoverPageName );
}
if (ServerName)
{
MemFree( (LPBYTE) ServerName );
}
for (i = 0; i < COUNT_CP_FIELDS; i++)
{
d = (LPWSTR *)((ULONG_PTR)&CoverPageInfoW.RecName + i*sizeof(LPWSTR));
if (d && *d)MemFree( (LPBYTE)*d );
}
if (ERROR_SUCCESS != Rval)
{
SetLastError(Rval);
return FALSE;
}
return TRUE;
}
#else
BOOL
WINAPI
FaxPrintCoverPageW(
IN const FAX_CONTEXT_INFOW *FaxContextInfo,
IN const FAX_COVERPAGE_INFOW *CoverPageInfo
)
{
UNREFERENCED_PARAMETER(FaxContextInfo);
UNREFERENCED_PARAMETER(CoverPageInfo);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
#endif
BOOL
WINAPI
FaxStartPrintJob2(
IN LPCTSTR PrinterName,
IN const FAX_PRINT_INFO *PrintInfo,
IN short TiffRes,
OUT LPDWORD FaxJobId,
OUT PFAX_CONTEXT_INFO FaxContextInfo
)
/*++
Routine Description:
Starts a print job for the specified printer. This
function provides functionality beyond what the caller
can provide by using StartDoc(). This function disables
the display of the fax send wizard and also passes along
the information that would otherwise be gathered by the
fax wizard ui.
Arguments:
PrinterName - Fax printer name (must be a fax printer)
PrintInfo - Fax print information
TiffRes - coverpage resolution. 0 for the printer default
FaxJobId - Job id of the resulting print job
FaxContextInfo - context information including hdc
Return Value:
TRUE for success.
FALSE for failure.
--*/
{
HANDLE hPrinter = NULL;
PDEVMODE DevMode = NULL;
PDMPRIVATE DevModePrivate = NULL;
DOCINFO DocInfo;
PJOB_INFO_2 JobInfo = NULL;
PPRINTER_INFO_2 PrinterInfo = NULL;
DWORD dwNeeded = 0;
HDC hDC = NULL;
INT JobId = 0;
LPTSTR strParameters = NULL;
LONG Size;
LPTSTR lptstrFaxPrinterName = NULL;
DEBUG_FUNCTION_NAME(TEXT("FaxStartPrintJob"));
//
// do a little argument validation
//
Assert (TiffRes == 0 || TiffRes == 98 || TiffRes == 196);
if (PrintInfo == NULL || PrintInfo->SizeOfStruct != sizeof(FAX_PRINT_INFOW) ||
!FaxJobId || !FaxContextInfo)
{
DebugPrintEx(DEBUG_ERR,
TEXT("PrintInfo is NULL or Size mismatch.")
);
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if (PrintInfo->OutputFileName == NULL &&
(PrintInfo->RecipientNumber == NULL || PrintInfo->RecipientNumber[0] == 0))
{
DebugPrintEx(DEBUG_ERR,
TEXT("No valid recipient number.")
);
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if (PrintInfo->Reserved)
{
DebugPrintEx(DEBUG_ERR,
TEXT("Reserved field of FAX_PRINT_INFO should be NULL.")
);
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
//
// if no printer specified, assume they want a local fax printer
//
if (!PrinterName)
{
lptstrFaxPrinterName = GetFaxPrinterName(NULL); // Need to free this pointer
if (!lptstrFaxPrinterName)
{
DebugPrintEx(DEBUG_ERR,
TEXT("GetFaxPrinterName returned NULL.")
);
SetLastError(ERROR_INVALID_PRINTER_NAME);
goto error_exit;
}
}
else
{
lptstrFaxPrinterName = (LPTSTR)PrinterName;
//
// verify that the printer is a fax printer, the only type allowed
//
if (!IsPrinterFaxPrinter( lptstrFaxPrinterName ))
{
DebugPrintEx(DEBUG_ERR,
TEXT("IsPrinterFaxPrinter failed. Printer name = %s"),
lptstrFaxPrinterName
);
SetLastError( ERROR_INVALID_PRINTER_NAME );
goto error_exit;
}
}
//
// open the printer for normal access (this should always work)
//
if (!OpenPrinter( lptstrFaxPrinterName, &hPrinter, NULL ))
{
DebugPrintEx(DEBUG_ERR,
TEXT("OpenPrinter failed. Printer Name = %s , ec = %ld"),
lptstrFaxPrinterName,
GetLastError());
goto error_exit;
}
//
// get the fax server's name if the fax printer isn't local
//
if (!GetPrinter(hPrinter,2,(LPBYTE)PrinterInfo,0,&dwNeeded))
{
PrinterInfo = (PPRINTER_INFO_2)MemAlloc( dwNeeded );
if (!PrinterInfo)
{
DebugPrintEx(DEBUG_ERR,
TEXT("Cant allocate PPRINTER_INFO_2.")
);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto error_exit;
}
}
if (!GetPrinter(hPrinter,2,(LPBYTE)PrinterInfo,dwNeeded,&dwNeeded))
{
DebugPrintEx(DEBUG_ERR,
TEXT("GetPrinter failed. ec = %ld"),
GetLastError());
goto error_exit;
}
if (PrinterInfo->pServerName)
{
if (PrinterInfo->pServerName == _tcsstr (PrinterInfo->pServerName, TEXT("\\\\")))
{
//
// Server name starts with '\\', remove it
//
PrinterInfo->pServerName = _tcsninc (PrinterInfo->pServerName, 2);
}
_tcscpy(FaxContextInfo->ServerName, PrinterInfo->pServerName);
}
else
{
FaxContextInfo->ServerName[0] = NIL;
}
//
// get the required size for the DEVMODE
//
Size = DocumentProperties( NULL, hPrinter, NULL, NULL, NULL, 0 );
if (Size <= 0)
{
DebugPrintEx(DEBUG_ERR,
TEXT("DocumentProperties failed. ec = %ld"),
GetLastError());
goto error_exit;
}
//
// allocate memory for the DEVMODE
//
DevMode = (PDEVMODE) MemAlloc( Size );
if (!DevMode)
{
DebugPrintEx(DEBUG_ERR,
TEXT("Cant allocate DEVMODE.")
);
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
goto error_exit;
}
//
// get the default document properties
//
if (DocumentProperties( NULL, hPrinter, NULL, DevMode, NULL, DM_OUT_BUFFER ) != IDOK)
{
DebugPrintEx(DEBUG_ERR,
TEXT("DocumentProperties failed. ec = %ld"),
GetLastError());
goto error_exit;
}
#ifndef WIN95
//
// be sure we are dealing with the correct DEVMODE
//
if (DevMode->dmDriverExtra < sizeof(DMPRIVATE))
{
DebugPrintEx(DEBUG_ERR,
TEXT("Invalid DEVMODE, wrong private data size. DevMode->dmDriverExtra = %ld, sizeof(DMPRIVATE) = %ld"),
DevMode->dmDriverExtra,
sizeof(DMPRIVATE));
SetLastError(ERROR_INVALID_DATA);
goto error_exit;
}
//
// set the private DEVMODE pointer
//
DevModePrivate = (PDMPRIVATE) ((LPBYTE) DevMode + DevMode->dmSize);
//
// set the necessary stuff in the DEVMODE
//
DevModePrivate->sendCoverPage = FALSE;
DevModePrivate->flags |= FAXDM_NO_WIZARD;
DevModePrivate->flags &= ~FAXDM_DRIVER_DEFAULT;
#endif //#ifndef WIN95
//
// Set the necessary reolution
//
if (0 != TiffRes)
{
//
// Set the coverpage resolution to the same value as the body tiff file
//
DevMode->dmYResolution = TiffRes;
}
//
// create the device context
//
hDC = CreateDC( _T("WINSPOOL"), lptstrFaxPrinterName, NULL, DevMode );
if (!hDC)
{
DebugPrintEx(DEBUG_ERR,
TEXT("CreateDC failed. ec = %ld"),
GetLastError());
goto error_exit;
}
//
// set the document information
//
DocInfo.cbSize = sizeof(DOCINFO);
DocInfo.lpszDocName = PrintInfo->DocName;
DocInfo.lpszOutput = PrintInfo->OutputFileName;
DocInfo.lpszDatatype = NULL;
DocInfo.fwType = 0;
//
// start the print job
//
JobId = StartDoc( hDC, &DocInfo );
if (JobId <= 0)
{
DebugPrintEx(DEBUG_ERR,
TEXT("StartDoc failed. ec = %ld"),
GetLastError());
goto error_exit;
}
if (PrintInfo->OutputFileName == NULL)
{
//
// HACK HACK -> pause the print job
//
if (FaxJobId && *FaxJobId == 0xffffffff)
{
SetJob( hPrinter, JobId, 0, NULL, JOB_CONTROL_PAUSE );
}
//
// set the job tags
// this is how we communicate the information to
// the print driver that would otherwise be
// provided by the fax print wizard
//
JobInfo = (PJOB_INFO_2)MyGetJob( hPrinter, 2, JobId );
if (!JobInfo)
{
DebugPrintEx(DEBUG_ERR,
TEXT("MyGetJob failed. ec = %ld"),
GetLastError());
goto error_exit;
}
DWORD dwReceiptFlag = DRT_NONE;
LPTSTR strReceiptAddress = NULL;
if(PrintInfo->DrEmailAddress)
{
dwReceiptFlag = DRT_EMAIL;
strReceiptAddress = LPTSTR(PrintInfo->DrEmailAddress);
}
TCHAR tszNumericData[10] = {0};
if (0 > _sntprintf (tszNumericData,
ARR_SIZE(tszNumericData) -1,
_T("%d"),
dwReceiptFlag))
{
SetLastError(ERROR_BUFFER_OVERFLOW);
DebugPrintEx(DEBUG_ERR,
TEXT("_sntprintf failed. ec = %ld"),
GetLastError());
goto error_exit;
}
FAX_TAG_MAP_ENTRY tagMap[] =
{
//
// Sender info
//
{ FAXTAG_NEW_RECORD, FAXTAG_NEW_RECORD_VALUE },
{ FAXTAG_BILLING_CODE, LPTSTR(PrintInfo->SenderBillingCode) },
{ FAXTAG_RECEIPT_TYPE, tszNumericData },
{ FAXTAG_RECEIPT_ADDR, strReceiptAddress },
{ FAXTAG_SENDER_NAME, LPTSTR(PrintInfo->SenderName) },
{ FAXTAG_SENDER_COMPANY, LPTSTR(PrintInfo->SenderCompany) },
{ FAXTAG_SENDER_DEPT, LPTSTR(PrintInfo->SenderDept) },
{ FAXTAG_RECIPIENT_COUNT, _T("1") },
//
// Recipient info
//
{ FAXTAG_NEW_RECORD, FAXTAG_NEW_RECORD_VALUE },
{ FAXTAG_RECIPIENT_NAME, LPTSTR(PrintInfo->RecipientName) },
{ FAXTAG_RECIPIENT_NUMBER, LPTSTR(PrintInfo->RecipientNumber) }
};
//
// Call first time to ParamTagToString to find out size of the Parameters string
//
DWORD dwTagCount = sizeof(tagMap)/sizeof(FAX_TAG_MAP_ENTRY);
DWORD dwSize = 0;
ParamTagsToString(tagMap, dwTagCount, NULL, &dwSize);
//
// Allocate the Buffer for the Parameters String
//
strParameters = LPTSTR(MemAlloc(dwSize + sizeof(TCHAR))); // dwSize does not count last NULL
if (!strParameters)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
DebugPrintEx(DEBUG_ERR,
_T("strParameters = MemAlloc(%d) failed. ec = %ld"),
dwSize,
GetLastError());
goto error_exit;
}
//
// Get the Parameters string from the ParamTagToString
//
ParamTagsToString(tagMap, dwTagCount, strParameters, &dwSize);
//
// set these fields or the spooler will
// return ACCESS_DENIED for a non-admin client
//
JobInfo->Position = JOB_POSITION_UNSPECIFIED;
JobInfo->pDevMode = NULL;
//
// set our new fax tags
//
JobInfo->pParameters = strParameters;
if (!SetJob( hPrinter, JobId, 2, (LPBYTE) JobInfo, 0 ))
{
DebugPrintEx(DEBUG_ERR,
TEXT("SetJob failed. ec = %ld"),
GetLastError());
goto error_exit;
}
}
//
// clean up and return to the caller
//
ClosePrinter( hPrinter);
MemFree( PrinterInfo);
MemFree( DevMode );
MemFree( strParameters );
MemFree( JobInfo );
if (!PrinterName)
{
MemFree (lptstrFaxPrinterName);
}
if (FaxJobId)
{
*FaxJobId = JobId;
}
FaxContextInfo->hDC = hDC;
return TRUE;
error_exit:
if (hPrinter) {
ClosePrinter( hPrinter);
}
if (PrinterInfo) {
MemFree( PrinterInfo);
}
if (JobId)
{
if (EndDoc( hDC ) <= 0)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("EndDoc failed. (ec: %ld)"),
GetLastError());
}
}
if (hDC)
{
if (!DeleteDC (hDC))
{
DebugPrintEx(
DEBUG_ERR,
TEXT("DeleteDC failed. (ec: %ld)"),
GetLastError());
}
}
if (DevMode) {
MemFree( DevMode );
}
if (strParameters) {
MemFree( strParameters );
}
if (JobInfo) {
MemFree( JobInfo );
}
if (!PrinterName) {
MemFree (lptstrFaxPrinterName);
}
return FALSE;
}
#ifdef UNICODE
BOOL
WINAPI
FaxStartPrintJob2A(
IN LPCSTR PrinterName,
IN const FAX_PRINT_INFOA *PrintInfo,
IN short TiffRes,
OUT LPDWORD JobId,
OUT FAX_CONTEXT_INFOA *FaxContextInfo
)
/*++
Routine Description:
Starts a print job for the specified printer. This
function provides functionality beyond what the caller
can provide by using StartDoc(). This function disables
the display of the fax send wizard and also passes along
the information that would otherwise be gathered by the
fax wizard ui.
Arguments:
PrinterName - Fax printer name (must be a fax printer)
PrintInfo - Fax print information
TiffRes - coverpage resolution. 0 for the printer default
FaxJobId - Job id of the resulting print job
FaxContextInfo - device context information (hdc, etc.)
Return Value:
TRUE for success.
FALSE for failure.
--*/
{
DWORD Rval = ERROR_SUCCESS;
FAX_PRINT_INFOW PrintInfoW;
FAX_CONTEXT_INFOW ContextInfoW;
LPSTR ServerName = NULL;
LPWSTR PrinterNameW = NULL;
DEBUG_FUNCTION_NAME(TEXT("FaxStartPrintJobA"));
if (!PrintInfo || !JobId || !FaxContextInfo ||
(PrintInfo->SizeOfStruct != sizeof(FAX_PRINT_INFOA)))
{
DebugPrintEx(DEBUG_ERR,
TEXT("PrintInfo is NULL or Size mismatch.")
);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (PrinterName)
{
PrinterNameW = AnsiStringToUnicodeString( PrinterName );
if (!PrinterNameW)
{
SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
}
ZeroMemory( &ContextInfoW, sizeof(FAX_CONTEXT_INFOW) );
ContextInfoW.SizeOfStruct = sizeof(FAX_CONTEXT_INFOW) ;
ZeroMemory( &PrintInfoW, sizeof(FAX_PRINT_INFOW) );
PrintInfoW.SizeOfStruct = sizeof(FAX_PRINT_INFOW);
PrintInfoW.DocName = AnsiStringToUnicodeString( PrintInfo->DocName );
if (!PrintInfoW.DocName && PrintInfo->DocName)
{
Rval = ERROR_OUTOFMEMORY;
goto exit;
}
PrintInfoW.RecipientName = AnsiStringToUnicodeString( PrintInfo->RecipientName );
if (!PrintInfoW.RecipientName && PrintInfo->RecipientName)
{
Rval = ERROR_OUTOFMEMORY;
goto exit;
}
PrintInfoW.RecipientNumber = AnsiStringToUnicodeString( PrintInfo->RecipientNumber );
if (!PrintInfoW.RecipientNumber && PrintInfo->RecipientNumber)
{
Rval = ERROR_OUTOFMEMORY;
goto exit;
}
PrintInfoW.SenderName = AnsiStringToUnicodeString( PrintInfo->SenderName );
if (!PrintInfoW.SenderName && PrintInfo->SenderName)
{
Rval = ERROR_OUTOFMEMORY;
goto exit;
}
PrintInfoW.SenderCompany = AnsiStringToUnicodeString( PrintInfo->SenderCompany );
if (!PrintInfoW.SenderCompany && PrintInfo->SenderCompany)
{
Rval = ERROR_OUTOFMEMORY;
goto exit;
}
PrintInfoW.SenderDept = AnsiStringToUnicodeString( PrintInfo->SenderDept );
if (!PrintInfoW.SenderDept && PrintInfo->SenderDept)
{
Rval = ERROR_OUTOFMEMORY;
goto exit;
}
PrintInfoW.SenderBillingCode = AnsiStringToUnicodeString( PrintInfo->SenderBillingCode );
if (!PrintInfoW.SenderBillingCode && PrintInfo->SenderBillingCode)
{
Rval = ERROR_OUTOFMEMORY;
goto exit;
}
PrintInfoW.Reserved = AnsiStringToUnicodeString( PrintInfo->Reserved );
if (!PrintInfoW.Reserved && PrintInfo->Reserved)
{
Rval = ERROR_OUTOFMEMORY;
goto exit;
}
PrintInfoW.DrEmailAddress = AnsiStringToUnicodeString( PrintInfo->DrEmailAddress );
if (!PrintInfoW.DrEmailAddress && PrintInfo->DrEmailAddress)
{
Rval = ERROR_OUTOFMEMORY;
goto exit;
}
PrintInfoW.OutputFileName = AnsiStringToUnicodeString( PrintInfo->OutputFileName );
if (!PrintInfoW.OutputFileName && PrintInfo->OutputFileName)
{
Rval = ERROR_OUTOFMEMORY;
goto exit;
}
if (!FaxStartPrintJob2W(
(LPWSTR) PrinterNameW,
&PrintInfoW,
TiffRes,
JobId,
&ContextInfoW))
{
Rval = GetLastError();
goto exit;
}
ServerName = UnicodeStringToAnsiString( ContextInfoW.ServerName);
if (ServerName)
{
_mbscpy((PUCHAR)FaxContextInfo->ServerName,(PUCHAR)ServerName);
}
else
{
Rval = ERROR_OUTOFMEMORY;
goto exit;
}
FaxContextInfo->SizeOfStruct = sizeof(FAX_CONTEXT_INFOA);
FaxContextInfo->hDC = ContextInfoW.hDC;
Assert (ERROR_SUCCESS == Rval);
exit:
MemFree( (LPBYTE) PrinterNameW );
MemFree( (LPBYTE) PrintInfoW.DocName );
MemFree( (LPBYTE) PrintInfoW.RecipientName );
MemFree( (LPBYTE) PrintInfoW.RecipientNumber );
MemFree( (LPBYTE) PrintInfoW.SenderName );
MemFree( (LPBYTE) PrintInfoW.SenderCompany );
MemFree( (LPBYTE) PrintInfoW.SenderDept );
MemFree( (LPBYTE) PrintInfoW.SenderBillingCode );
MemFree( (LPBYTE) PrintInfoW.DrEmailAddress );
MemFree( (LPBYTE) PrintInfoW.OutputFileName );
MemFree( (LPBYTE) PrintInfoW.Reserved );
MemFree( (LPBYTE) ServerName );
if (ERROR_SUCCESS != Rval)
{
SetLastError(Rval);
return FALSE;
}
return TRUE;
}
#else
BOOL
WINAPI
FaxStartPrintJob2W(
IN LPCWSTR PrinterName,
IN const FAX_PRINT_INFOW *PrintInfo,
IN DWORD TiffRes,
OUT LPDWORD FaxJobId,
OUT PFAX_CONTEXT_INFOW FaxContextInfo
)
{
UNREFERENCED_PARAMETER(PrinterName);
UNREFERENCED_PARAMETER(PrintInfo);
UNREFERENCED_PARAMETER(TiffRes);
UNREFERENCED_PARAMETER(FaxJobId);
UNREFERENCED_PARAMETER(FaxContextInfo);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
#endif