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

1104 lines
26 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:
--*/
#include "faxapi.h"
#pragma hdrstop
LPWSTR Platforms[] =
{
L"Windows NT x86",
L"Windows NT R4000",
L"Windows NT Alpha_AXP",
L"Windows NT PowerPC"
};
LPWSTR
AddFaxTag(
LPWSTR TagStr,
LPCWSTR FaxTag,
LPCWSTR Value
)
{
if (!Value) {
return TagStr;
}
wcscat( TagStr, FaxTag );
wcscat( TagStr, Value );
return TagStr;
}
BOOL
IsPrinterFaxPrinter(
LPWSTR PrinterName
)
{
HANDLE hPrinter = NULL;
PRINTER_DEFAULTS PrinterDefaults;
SYSTEM_INFO SystemInfo;
DWORD Size;
DWORD Rval = FALSE;
LPDRIVER_INFO_2 DriverInfo = NULL;
PrinterDefaults.pDatatype = NULL;
PrinterDefaults.pDevMode = NULL;
PrinterDefaults.DesiredAccess = PRINTER_READ;
if (!OpenPrinter( PrinterName, &hPrinter, &PrinterDefaults )) {
DebugPrint(( L"OpenPrinter() failed, ec=%d", GetLastError() ));
return FALSE;
}
GetSystemInfo( &SystemInfo );
Size = 4096;
DriverInfo = (LPDRIVER_INFO_2) MemAlloc( Size );
if (!DriverInfo) {
DebugPrint(( L"Memory allocation failed, size=%d", Size ));
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto exit;
}
Rval = GetPrinterDriver(
hPrinter,
Platforms[SystemInfo.wProcessorArchitecture],
2,
(LPBYTE) DriverInfo,
Size,
&Size
);
if (!Rval) {
DebugPrint(( L"GetPrinterDriver() failed, ec=%d", GetLastError() ));
goto exit;
}
if (_tcscmp( DriverInfo->pName, FAX_DRIVER_NAME ) == 0) {
Rval = TRUE;
} else {
Rval = FALSE;
}
exit:
MemFree( DriverInfo );
ClosePrinter( hPrinter );
return Rval;
}
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 = MemAlloc(cbNeeded)) &&
GetJob(hPrinter, jobId, level, pJobInfo, cbNeeded, &cbNeeded))
{
return pJobInfo;
}
MemFree(pJobInfo);
return NULL;
}
LPWSTR
GetCpField(
HKEY hKey,
LPWSTR 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;
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 (LPWSTR) Buffer;
}
BOOL
GetCpFields(
PCOVERPAGEFIELDS CpFields
)
/*++
Routine Description:
Initializes the coverpage field structure and
fills in the sender information from the registry.
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 );
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
FaxPrintCoverPageW(
IN const FAX_CONTEXT_INFO *FaxContextInfo,
IN const FAX_COVERPAGE_INFOW *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.
--*/
{
WCHAR CpName[MAX_PATH];
WCHAR Buffer[MAX_PATH];
LPWSTR p;
COVERPAGEFIELDS CpFields = {0};
COVDOCINFO CovDocInfo;
DWORD DateTimeLen;
DWORD cch;
LPWSTR s;
DWORD ec = 0;
LPCWSTR *src;
LPCWSTR *dst;
DWORD i;
//
// 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) )
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if (!ValidateCoverpage(CoverPageInfo->CoverPageName,
FaxContextInfo->ServerName,
CoverPageInfo->UseServerCoverPage,
CpName)) {
return FALSE;
}
//
// get the coverpage fields
//
GetCpFields( &CpFields );
//
// fixup the recipient name
//
if (CoverPageInfo->RecName) {
if (CoverPageInfo->RecName[0] == '\'') {
wcscpy( Buffer, &CoverPageInfo->RecName[1] );
Buffer[wcslen(Buffer)-1] = 0;
} else {
wcscpy( Buffer, CoverPageInfo->RecName );
}
} 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 );
if (CpFields.RecFaxNumber) {
p = wcsrchr( (LPWSTR) CpFields.RecFaxNumber, L'@' );
if (p) {
wcscpy( (LPWSTR) CpFields.RecFaxNumber, p+1 );
}
}
CpFields.Subject = StringDup( CoverPageInfo->Subject );
CpFields.Note = StringDup( CoverPageInfo->Note ? CoverPageInfo->Note : L"" );
CpFields.NumberOfPages = StringDup( _itow( CoverPageInfo->PageCount, Buffer, 10 ) );
for (i = 0;
i <= ((LPBYTE)&CoverPageInfo->SdrOfficePhone-(LPBYTE)&CoverPageInfo->RecCompany)/sizeof(LPCWSTR);
i++) {
src = (LPCWSTR *) ((LPBYTE)&CoverPageInfo->RecCompany + (i*sizeof(LPCWSTR)));
dst = (LPCWSTR *) ((LPBYTE)&CpFields.RecCompany + (i*sizeof(LPCWSTR)));
if (*dst) {
MemFree ( (LPBYTE) *dst ) ;
}
*dst = (LPCWSTR) StringDup( *src );
}
//
// the time the fax was sent
//
GetLocalTime((LPSYSTEMTIME)&CoverPageInfo->TimeSent);
DateTimeLen = sizeof(Buffer);
s = Buffer;
GetDateFormat( LOCALE_USER_DEFAULT, 0, &CoverPageInfo->TimeSent, NULL, s, DateTimeLen );
cch = wcslen( s );
s += cch;
if (++cch < DateTimeLen) {
*s++ = ' ';
DateTimeLen -= cch;
GetTimeFormat( LOCALE_USER_DEFAULT, 0, &CoverPageInfo->TimeSent, NULL, s, DateTimeLen );
}
CpFields.TimeSent = StringDup( Buffer );
//
// 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) {
SetLastError( ec );
return FALSE;
}
return TRUE;
}
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)
BOOL Rval;
FAX_COVERPAGE_INFOW CoverPageInfoW = {0};
FAX_CONTEXT_INFOW ContextInfoW = {0};
LPWSTR ServerName = NULL;
LPWSTR *d;
LPSTR *s;
DWORD i;
if (!FaxContextInfo || !CoverPageInfo ||
FaxContextInfo->SizeOfStruct != sizeof(FAX_CONTEXT_INFOA) ||
CoverPageInfo->SizeOfStruct != sizeof(FAX_COVERPAGE_INFOA)) {
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 );
wcscpy(ContextInfoW.ServerName,ServerName);
}
CoverPageInfoW.SizeOfStruct = sizeof(FAX_COVERPAGE_INFOW);
CoverPageInfoW.UseServerCoverPage = CoverPageInfo->UseServerCoverPage;
CoverPageInfoW.PageCount = CoverPageInfo->PageCount;
CoverPageInfoW.CoverPageName = AnsiStringToUnicodeString( CoverPageInfo->CoverPageName );
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 );
}
CoverPageInfoW.TimeSent = CoverPageInfo->TimeSent;
CoverPageInfoW.PageCount = CoverPageInfo->PageCount;
Rval = FaxPrintCoverPageW(
&ContextInfoW,
&CoverPageInfoW
);
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 );
}
return Rval;
}
BOOL
WINAPI
FaxStartPrintJobW(
IN LPCWSTR PrinterName,
IN const FAX_PRINT_INFOW *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.
--*/
{
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;
LPWSTR FaxTags = NULL;
LONG Size;
LPWSTR FaxPrinterName;
//
// do a little argument validation
//
if (PrintInfo == NULL || PrintInfo->SizeOfStruct != sizeof(FAX_PRINT_INFOW) ||
!FaxJobId || !FaxContextInfo)
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if (PrintInfo->OutputFileName == NULL &&
(PrintInfo->RecipientNumber == NULL || PrintInfo->RecipientNumber[0] == 0))
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if (PrintInfo->DrProfileName && PrintInfo->DrEmailAddress) {
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
//
// if no printer specified, assume they want a local fax printer
//
if (!PrinterName) {
FaxPrinterName = GetFaxPrinterName();
if (!FaxPrinterName) {
SetLastError(ERROR_INVALID_PRINTER_NAME);
return FALSE;
}
} else {
FaxPrinterName = (LPWSTR) PrinterName;
}
//
// verify that the printer is a fax printer, the only type allowed
//
if (!IsPrinterFaxPrinter( FaxPrinterName )) {
SetLastError( ERROR_INVALID_PRINTER_NAME );
return FALSE;
}
//
// open the printer for normal access (this should always work)
//
if (!OpenPrinter( FaxPrinterName, &hPrinter, NULL )) {
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 = MemAlloc( dwNeeded );
if (!PrinterInfo) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto error_exit;
}
}
if (!GetPrinter(hPrinter,2,(LPBYTE)PrinterInfo,dwNeeded,&dwNeeded)) {
goto error_exit;
}
if (PrinterInfo->pServerName)
wcscpy(FaxContextInfo->ServerName,PrinterInfo->pServerName);
else
FaxContextInfo->ServerName[0] = 0;
//
// get the required size for the DEVMODE
//
Size = DocumentProperties( NULL, hPrinter, NULL, NULL, NULL, 0 );
if (Size <= 0) {
goto error_exit;
}
//
// allocate memory for the DEVMODE
//
DevMode = (PDEVMODE) MemAlloc( Size );
if (!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) {
goto error_exit;
}
//
// be sure we are dealing with the correct DEVMODE
//
if (DevMode->dmDriverExtra < sizeof(DMPRIVATE)) {
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;
//
// create the device context
//
hDC = CreateDC( L"WINSPOOL", FaxPrinterName, NULL, DevMode );
if (!hDC) {
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) {
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 );
}
//
// allocate memory for the fax tags
//
FaxTags = (LPWSTR) MemAlloc( 4096 );
if (!FaxTags) {
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
//
// 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 = MyGetJob( hPrinter, 2, JobId );
if (!JobInfo) {
goto error_exit;
}
AddFaxTag( FaxTags, FAXTAG_RECIPIENT_NUMBER, PrintInfo->RecipientNumber );
AddFaxTag( FaxTags, FAXTAG_RECIPIENT_NAME, PrintInfo->RecipientName );
AddFaxTag( FaxTags, FAXTAG_SENDER_NAME, PrintInfo->SenderName );
AddFaxTag( FaxTags, FAXTAG_SENDER_NAME, PrintInfo->SenderName );
AddFaxTag( FaxTags, FAXTAG_SENDER_COMPANY, PrintInfo->SenderCompany );
AddFaxTag( FaxTags, FAXTAG_SENDER_DEPT, PrintInfo->SenderDept );
AddFaxTag( FaxTags, FAXTAG_BILLING_CODE, PrintInfo->SenderBillingCode );
if (PrintInfo->DrProfileName) {
AddFaxTag( FaxTags, FAXTAG_PROFILE_NAME, PrintInfo->DrProfileName );
AddFaxTag( FaxTags, FAXTAG_EMAIL_NAME, L"inbox" );
} else if (PrintInfo->DrEmailAddress) {
AddFaxTag( FaxTags, FAXTAG_PROFILE_NAME, PrintInfo->DrEmailAddress );
AddFaxTag( FaxTags, FAXTAG_EMAIL_NAME, L"email" );
}
//
// 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 = FaxTags;
if (!SetJob( hPrinter, JobId, 2, (LPBYTE) JobInfo, 0 )) {
goto error_exit;
}
}
//
// clean up and return to the caller
//
ClosePrinter( hPrinter);
MemFree( PrinterInfo);
MemFree( DevMode );
MemFree( FaxTags );
MemFree( JobInfo );
if (!PrinterName) {
MemFree (FaxPrinterName);
}
if (FaxJobId) {
*FaxJobId = JobId;
}
FaxContextInfo->hDC = hDC;
return TRUE;
error_exit:
if (hPrinter) {
ClosePrinter( hPrinter);
}
if (PrinterInfo) {
MemFree( PrinterInfo);
}
if (JobId) {
EndDoc( hDC );
}
if (hDC) {
DeleteDC( hDC );
}
if (DevMode) {
MemFree( DevMode );
}
if (FaxTags) {
MemFree( FaxTags );
}
if (JobInfo) {
MemFree( JobInfo );
}
if (!PrinterName) {
MemFree (FaxPrinterName);
}
return FALSE;
}
BOOL
WINAPI
FaxStartPrintJobA(
IN LPCSTR PrinterName,
IN const FAX_PRINT_INFOA *PrintInfo,
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
FaxJobId - Job id of the resulting print job
FaxContextInfo - device context information (hdc, etc.)
Return Value:
TRUE for success.
FALSE for failure.
--*/
{
BOOL Rval;
FAX_PRINT_INFOW PrintInfoW;
FAX_CONTEXT_INFOW ContextInfoW;
LPSTR ServerName;
LPWSTR PrinterNameW = NULL;
if (!PrintInfo || !JobId || !FaxContextInfo ||
(PrintInfo->SizeOfStruct != sizeof(FAX_PRINT_INFOA))) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (PrinterName) {
PrinterNameW = AnsiStringToUnicodeString( PrinterName );
}
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 );
PrintInfoW.RecipientName = AnsiStringToUnicodeString( PrintInfo->RecipientName );
PrintInfoW.RecipientNumber = AnsiStringToUnicodeString( PrintInfo->RecipientNumber );
PrintInfoW.SenderName = AnsiStringToUnicodeString( PrintInfo->SenderName );
PrintInfoW.SenderCompany = AnsiStringToUnicodeString( PrintInfo->SenderCompany );
PrintInfoW.SenderDept = AnsiStringToUnicodeString( PrintInfo->SenderDept );
PrintInfoW.SenderBillingCode = AnsiStringToUnicodeString( PrintInfo->SenderBillingCode );
PrintInfoW.DrProfileName = AnsiStringToUnicodeString( PrintInfo->DrProfileName );
PrintInfoW.DrEmailAddress = AnsiStringToUnicodeString( PrintInfo->DrEmailAddress );
PrintInfoW.OutputFileName = AnsiStringToUnicodeString( PrintInfo->OutputFileName );
Rval = FaxStartPrintJobW(
(LPWSTR) PrinterNameW,
&PrintInfoW,
JobId,
&ContextInfoW
);
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 );
ServerName = UnicodeStringToAnsiString( ContextInfoW.ServerName);
if (ServerName) {
strcpy(FaxContextInfo->ServerName,ServerName);
}
else
FaxContextInfo->ServerName[0] = 0;
FaxContextInfo->SizeOfStruct = sizeof(FAX_CONTEXT_INFOA);
FaxContextInfo->hDC = ContextInfoW.hDC;
MemFree( (LPBYTE) ServerName );
return Rval;
}
BOOL
ValidateCoverpage(
LPCWSTR CoverPageName,
LPCWSTR ServerName,
BOOL ServerCoverpage,
LPWSTR ResolvedName
)
/*++
Routine Description:
This routine tries to validate that that coverpage specified by the user actually exists where
they say it does, and that it is indeed a coverpage (or a resolvable link to one)
Please see the SDK for documentation on the rules for how server coverpages work, etc.
Arguments:
CoverpageName - contains name of coverpage
ServerName - name of the server, if any (can be null)
ServerCoverpage - indicates if this coverpage is on the server, or in the server location for
coverpages locally
ResolvedName - a pointer to buffer (should be MAX_PATH large at least) to receive the
resolved coverpage name. If NULL, then this param is ignored
Return Value:
TRUE if coverpage can be used.
FALSE if the coverpage is invalid or cannot be used.
--*/
{
LPWSTR p;
DWORD ec = 0;
WCHAR CpDir[MAX_PATH];
WCHAR Buffer[MAX_PATH];
if (!CoverPageName) {
ec = ERROR_INVALID_PARAMETER;
goto exit;
}
wcsncpy(CpDir,CoverPageName,MAX_PATH);
p = wcschr(CpDir, L'\\' );
if (p) {
//
// the coverpage file name contains a path so just use it.
//
if (GetFileAttributes( CpDir ) == 0xffffffff) {
ec = ERROR_FILE_NOT_FOUND;
goto exit;
}
} else {
//
// the coverpage file name does not contain
// a path so we must construct a full path name
//
if (ServerCoverpage) {
if (!ServerName || ServerName[0] == 0)
ec = GetServerCpDir( NULL, CpDir, sizeof(CpDir) );
else
ec = GetServerCpDir( ServerName, CpDir, sizeof(CpDir) );
} else {
ec = GetClientCpDir( CpDir, sizeof(CpDir) );
}
if (!ec) {
ec = ERROR_FILE_NOT_FOUND;
goto exit;
}
ec = 0;
ConcatenatePaths(CpDir, CoverPageName);
if (wcschr( CpDir, '.' ) == NULL) {
wcscat( CpDir, CP_FILENAME_EXT );
}
if (GetFileAttributes( CpDir ) == 0xffffffff) {
p = wcschr( CpDir, '.' );
if (p) {
wcscpy( p, CP_SHORTCUT_EXT );
if (GetFileAttributes( CpDir ) == 0xffffffff) {
ec = ERROR_FILE_NOT_FOUND;
goto exit;
}
} else {
ec = ERROR_FILE_NOT_FOUND;
goto exit;
}
}
}
//
// if the file is really a shortcut, then resolve it
//
if (IsCoverPageShortcut( CpDir )) {
if (!ResolveShortcut( CpDir, Buffer )) {
DebugPrint(( TEXT("Cover page file is really a link, but resolution is not possible") ));
ec = ERROR_FILE_NOT_FOUND;
goto exit;
} else {
if (ResolvedName) {
wcscpy(ResolvedName,Buffer);
}
}
} else {
if (ResolvedName) {
wcscpy( ResolvedName, CpDir );
}
}
exit:
if (ec) {
SetLastError(ec);
return FALSE;
}
return TRUE;
}