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.
 
 
 
 
 
 

1085 lines
27 KiB

#include "procs.hxx"
#pragma hdrstop
/*++
Copyright (c) 1996 Microsoft Corporation
All rights reserved
Module Name:
PrintWrp.c
Abstract:
Wide end to Win95 Ansi printing APIs
Author:
Felix Wong (t-felixw)
Environment:
Revision History:
--*/
#include "dswarn.h"
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <data.h>
typedef struct _SPOOL *PSPOOL;
typedef struct _NOTIFY *PNOTIFY;
typedef struct _NOTIFY {
PNOTIFY pNext;
HANDLE hEvent; // event to trigger on notification
DWORD fdwFlags; // flags to watch for
DWORD fdwOptions; // PRINTER_NOTIFY_*
DWORD dwReturn; // used by WPC when simulating FFPCN
PSPOOL pSpool;
} NOTIFY;
typedef struct _SPOOL {
DWORD signature;
HANDLE hPrinter;
HANDLE hFile;
DWORD JobId;
LPBYTE pBuffer;
DWORD cbBuffer;
DWORD Status;
DWORD fdwFlags;
DWORD cCacheWrite;
DWORD cWritePrinters;
DWORD cFlushBuffers;
DWORD dwTickCount;
DWORD dwCheckJobInterval;
PNOTIFY pNotify;
} SPOOL;
#define SPOOL_STATUS_ANSI 0x00000004
#define MIN_DEVMODE_SIZEW 72
#define MIN_DEVMODE_SIZEA 40
#define NULL_TERMINATED 0
BOOL
ConvertAnsiToUnicodeBuf(
LPBYTE pAnsiBlob,
LPBYTE pUnicodeBlob,
DWORD dwAnsiSize,
DWORD dwUnicodeSize,
PDWORD pOffsets
);
BOOL
bValidDevModeW(
const DEVMODEW *pDevModeW
)
/*++
Routine Description:
Check whether a devmode is valid to be RPC'd across to the spooler.
Arguments:
pDevMode - DevMode to check.
Return Value:
TRUE - Devmode can be RPC'd to spooler.
FALSE - Invalid Devmode.
--*/
{
if( !pDevModeW ){
return FALSE;
}
if( pDevModeW->dmSize < MIN_DEVMODE_SIZEW ){
//
// The only valid case is if pDevModeW is NULL. If it's
// not NULL, then a bad devmode was passed in and the
// app should fix it's code.
//
ASSERT( pDevModeW->dmSize >= MIN_DEVMODE_SIZEW );
return FALSE;
}
return TRUE;
}
LPSTR
AllocateAnsiString(
LPWSTR pPrinterName
)
{
LPSTR pAnsiString;
if (!pPrinterName)
return NULL;
pAnsiString = (LPSTR)LocalAlloc(LPTR, wcslen(pPrinterName)*sizeof(CHAR) +
sizeof(CHAR));
if (pAnsiString)
UnicodeToAnsiString(pPrinterName, pAnsiString, NULL_TERMINATED);
return pAnsiString;
}
LPSTR
FreeAnsiString(
LPSTR pAnsiString
)
{
if (!pAnsiString)
return NULL;
return (LPSTR)LocalFree(pAnsiString);
}
/***************************** Function Header ******************************
* AllocateAnsiDevMode
* Allocate an ANSI version of the DEVMODE structure, and optionally
* copy the contents of the ANSI version passed in.
*
* RETURNS:
* Address of newly allocated structure, 0 if storage not available.
*
* HISTORY:
* 09:23 on 10-Aug-92 -by- Lindsay Harris [lindsayh]
* Made it usable.
*
* Originally "written" by DaveSn.
*
***************************************************************************/
LPDEVMODEA
AllocateAnsiDevMode(
LPDEVMODEW pUNICODEDevMode
)
{
LPDEVMODEA pAnsiDevMode;
LPBYTE p1, p2;
DWORD dwSize;
//
// If the devmode is NULL, then return NULL -- KrishnaG
//
if ( !pUNICODEDevMode || !pUNICODEDevMode->dmSize ) {
return NULL;
}
ASSERT( bValidDevModeW( pUNICODEDevMode ));
//
// Determine output structure size. This has two components: the
// DEVMODEW structure size, plus any private data area. The latter
// is only meaningful when a structure is passed in.
//
dwSize = pUNICODEDevMode->dmSize + pUNICODEDevMode->dmDriverExtra
+ sizeof(DEVMODEA) - sizeof(DEVMODEW);
pAnsiDevMode = (LPDEVMODEA) LocalAlloc(LPTR, dwSize);
if( !pAnsiDevMode ) {
return NULL; /* This is bad news */
}
//
// Copy dmDeviceName which is a string
//
UnicodeToAnsiString(pUNICODEDevMode->dmDeviceName,
(LPSTR)(pAnsiDevMode->dmDeviceName),
ComputeMaxStrlenW(pUNICODEDevMode->dmDeviceName,
sizeof pUNICODEDevMode->dmDeviceName));
//
// Does the devmode we got have a dmFormName? (Windows 3.1 had
// DevMode of size 40 and did not have dmFormName)
//
if ( (LPBYTE)pUNICODEDevMode + pUNICODEDevMode->dmSize >
(LPBYTE) pUNICODEDevMode->dmFormName ) {
//
// Copy everything between dmDeviceName and dmFormName
//
p1 = (LPBYTE) pUNICODEDevMode->dmDeviceName +
sizeof(pUNICODEDevMode->dmDeviceName);
p2 = (LPBYTE) pUNICODEDevMode->dmFormName;
CopyMemory((LPBYTE) pAnsiDevMode->dmDeviceName +
sizeof(pAnsiDevMode->dmDeviceName),
p1,
p2 - p1);
//
// Copy dmFormName which is a string
//
UnicodeToAnsiString(pUNICODEDevMode->dmFormName,
(LPSTR)(pAnsiDevMode->dmFormName),
ComputeMaxStrlenW(pUNICODEDevMode->dmFormName,
sizeof pUNICODEDevMode->dmFormName));
//
// Copy everything after dmFormName
//
p1 = (LPBYTE) pUNICODEDevMode->dmFormName +
sizeof(pUNICODEDevMode->dmFormName);
p2 = (LPBYTE) pUNICODEDevMode + pUNICODEDevMode->dmSize
+ pUNICODEDevMode->dmDriverExtra;
CopyMemory((LPBYTE) pAnsiDevMode->dmFormName +
sizeof(pAnsiDevMode->dmFormName),
p1,
p2 - p1);
pAnsiDevMode->dmSize = pUNICODEDevMode->dmSize + sizeof(DEVMODEA)
- sizeof(DEVMODEW);
} else {
//
// Copy everything after dmDeviceName
//
p1 = (LPBYTE) pUNICODEDevMode->dmDeviceName +
sizeof(pUNICODEDevMode->dmDeviceName);
p2 = (LPBYTE) pUNICODEDevMode + pUNICODEDevMode->dmSize + pUNICODEDevMode->dmDriverExtra;
CopyMemory((LPBYTE) pAnsiDevMode->dmDeviceName +
sizeof(pAnsiDevMode->dmDeviceName),
p1,
p2-p1);
pAnsiDevMode->dmSize = pUNICODEDevMode->dmSize
+ sizeof(pAnsiDevMode->dmDeviceName)
- sizeof(pUNICODEDevMode->dmDeviceName);
}
ASSERT(pAnsiDevMode->dmDriverExtra == pUNICODEDevMode->dmDriverExtra);
return pAnsiDevMode;
}
/************************** Function Header ******************************
* CopyUnicodeDevModeFromAnsiDevMode
* Converts the ANSI version of the DEVMODE to the UNICODE version.
*
* RETURNS:
* Nothing.
*
* HISTORY:
* 09:57 on 10-Aug-92 -by- Lindsay Harris [lindsayh]
* This one actually works!
*
* Originally dreamed up by DaveSn.
*
**************************************************************************/
void
CopyUnicodeDevModeFromAnsiDevMode(
LPDEVMODEW pUNICODEDevMode, /* Filled in by us */
LPDEVMODEA pAnsiDevMode /* Source of data to fill above */
)
{
LPBYTE p1, p2, pExtra;
WORD dmSize, dmDriverExtra;
//
// NOTE: THE TWO INPUT STRUCTURES MAY BE THE SAME.
//
dmSize = pAnsiDevMode->dmSize;
dmDriverExtra = pAnsiDevMode->dmDriverExtra;
pExtra = (LPBYTE) pAnsiDevMode + pAnsiDevMode->dmSize;
//
// Copy dmDeviceName which is a string
//
AnsiToUnicodeString((LPSTR)(pAnsiDevMode->dmDeviceName),
(pUNICODEDevMode->dmDeviceName),
ComputeMaxStrlenA((LPSTR)(pAnsiDevMode->dmDeviceName),
sizeof pUNICODEDevMode->dmDeviceName));
//
// Does the devmode we got have a dmFormName? (Windows 3.1 had
// DevMode of size 40 and did not have dmFormName)
//
if ( (LPBYTE)pAnsiDevMode + dmSize >
(LPBYTE) pAnsiDevMode->dmFormName ) {
//
// Copy everything between dmDeviceName and dmFormName
//
p1 = (LPBYTE) pAnsiDevMode->dmDeviceName +
sizeof(pAnsiDevMode->dmDeviceName);
p2 = (LPBYTE) pAnsiDevMode->dmFormName;
MoveMemory((LPBYTE) pUNICODEDevMode->dmDeviceName +
sizeof(pUNICODEDevMode->dmDeviceName),
p1,
p2 - p1);
//
// Copy dmFormName which is a string
//
AnsiToUnicodeString((LPSTR)(pAnsiDevMode->dmFormName),
pUNICODEDevMode->dmFormName,
ComputeMaxStrlenA((LPSTR)pAnsiDevMode->dmFormName,
sizeof pUNICODEDevMode->dmFormName));
//
// Copy everything after dmFormName
//
p1 = (LPBYTE) pAnsiDevMode->dmFormName +
sizeof(pAnsiDevMode->dmFormName);
p2 = (LPBYTE) pAnsiDevMode + dmSize + dmDriverExtra;
MoveMemory((LPBYTE) pUNICODEDevMode->dmFormName +
sizeof(pUNICODEDevMode->dmFormName),
p1,
p2 - p1);
pUNICODEDevMode->dmSize = dmSize + sizeof(DEVMODEW) - sizeof(DEVMODEA);
} else {
//
// Copy everything after dmDeviceName
//
p1 = (LPBYTE) pAnsiDevMode->dmDeviceName +
sizeof(pAnsiDevMode->dmDeviceName);
p2 = (LPBYTE) pAnsiDevMode + dmSize + dmDriverExtra;
MoveMemory((LPBYTE) pUNICODEDevMode->dmDeviceName +
sizeof(pUNICODEDevMode->dmDeviceName),
p1,
p2 - p1);
pUNICODEDevMode->dmSize = dmSize + sizeof(pUNICODEDevMode->dmDeviceName)
- sizeof(pAnsiDevMode->dmDeviceName);
}
ASSERT(pUNICODEDevMode->dmDriverExtra == dmDriverExtra);
return;
}
void
ConvertAnsiToUnicodeStrings(
LPBYTE pStructure,
LPDWORD pOffsets
)
{
register DWORD i=0;
LPSTR pAnsi;
LPWSTR pUnicode;
while (pOffsets[i] != -1) {
pAnsi = *(LPSTR *)(pStructure+pOffsets[i]);
if (pAnsi) {
pUnicode = (LPWSTR)LocalAlloc( LPTR,
strlen(pAnsi)*sizeof(WCHAR)+
sizeof(WCHAR));
if (pUnicode) {
AnsiToUnicodeString(pAnsi,
pUnicode,
NULL_TERMINATED);
*(LPWSTR *)(pStructure+pOffsets[i]) = pUnicode;
LocalFree(pAnsi);
}
}
i++;
}
}
LPBYTE
AllocateAnsiStructure(
LPBYTE pUnicodeStructure,
DWORD cbStruct,
LPDWORD pOffsets
)
{
DWORD i, j;
LPSTR *ppAnsiString;
LPWSTR *ppUnicodeString;
LPBYTE pAnsiStructure;
if (!pUnicodeStructure) {
return NULL;
}
pAnsiStructure = (LPBYTE)LocalAlloc(LPTR, cbStruct);
if (pAnsiStructure) {
memcpy(pAnsiStructure, pUnicodeStructure, cbStruct);
for (i = 0 ; pOffsets[i] != -1 ; ++i) {
ppUnicodeString = (LPWSTR *)(pUnicodeStructure+pOffsets[i]);
ppAnsiString = (LPSTR *)(pAnsiStructure+pOffsets[i]);
*ppAnsiString = AllocateAnsiString(*ppUnicodeString);
if (*ppUnicodeString && !*ppAnsiString) {
for( j = 0 ; j < i ; ++j) {
ppAnsiString = (LPSTR *)(pAnsiStructure+pOffsets[j]);
FreeAnsiString(*ppAnsiString);
}
LocalFree(pAnsiStructure);
pAnsiStructure = NULL;
break;
}
}
}
return pAnsiStructure;
}
void
FreeAnsiStructure(
LPBYTE pAnsiStructure,
LPDWORD pOffsets
)
{
DWORD i=0;
if ( pAnsiStructure == NULL ) {
return;
}
while (pOffsets[i] != -1) {
FreeAnsiString(*(LPSTR *)(pAnsiStructure+pOffsets[i]));
i++;
}
LocalFree( pAnsiStructure );
}
BOOL
EnumJobsW(
HANDLE hPrinter,
DWORD FirstJob,
DWORD NoJobs,
DWORD Level,
LPBYTE pJob,
DWORD cbBuf,
LPDWORD pcbNeeded,
LPDWORD pcReturned
)
{
DWORD i, cbStruct, *pOffsets;
switch (Level) {
case 1:
pOffsets = JobInfo1StringsA;
cbStruct = sizeof(JOB_INFO_1W);
break;
case 2:
pOffsets = JobInfo2StringsA;
cbStruct = sizeof(JOB_INFO_2W);
break;
case 3:
return EnumJobsA( hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned );
default:
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
if (EnumJobsA(hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded,
pcReturned)) {
i=*pcReturned;
while (i--) {
ConvertAnsiToUnicodeStrings(pJob, pOffsets);
//
// Convert the devmode in place for INFO_2.
//
if( Level == 2 ){
PJOB_INFO_2W pJobInfo2 = (PJOB_INFO_2W)pJob;
if( pJobInfo2->pDevMode ){
CopyUnicodeDevModeFromAnsiDevMode(
(LPDEVMODEW)pJobInfo2->pDevMode,
(LPDEVMODEA)pJobInfo2->pDevMode);
}
}
pJob += cbStruct;
}
return TRUE;
} else
return FALSE;
}
BOOL
GetPrinterW(
HANDLE hPrinter,
DWORD Level,
LPBYTE pPrinter,
DWORD cbBuf,
LPDWORD pcbNeeded
)
{
DWORD *pOffsets;
switch (Level) {
//case STRESSINFOLEVEL:
// pOffsets = PrinterInfoStressOffsetsA;
// break;
case 1:
pOffsets = PrinterInfo1StringsA;
break;
case 2:
pOffsets = PrinterInfo2StringsA;
break;
case 3:
pOffsets = PrinterInfo3StringsA;
break;
case 4:
pOffsets = PrinterInfo4StringsA;
break;
case 5:
pOffsets = PrinterInfo5StringsA;
break;
default:
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
if (GetPrinterA(hPrinter, Level, pPrinter, cbBuf, pcbNeeded)) {
if (pPrinter) {
ConvertAnsiToUnicodeStrings(pPrinter, pOffsets);
if ((Level == 2) && pPrinter) {
PRINTER_INFO_2W *pPrinterInfo2 = (PRINTER_INFO_2W *)pPrinter;
if (pPrinterInfo2->pDevMode)
CopyUnicodeDevModeFromAnsiDevMode(
(LPDEVMODEW)pPrinterInfo2->pDevMode,
(LPDEVMODEA)pPrinterInfo2->pDevMode);
}
}
return TRUE;
}
return FALSE;
}
BOOL
SetPrinterW(
HANDLE hPrinter,
DWORD Level,
LPBYTE pPrinter,
DWORD Command
)
{
LPBYTE pAnsiStructure; /* Ansi version of input data */
DWORD cbStruct; /* Size of the output structure */
DWORD *pOffsets; /* -1 terminated list of addresses */
DWORD ReturnValue=FALSE;
switch (Level) {
case 0:
//
// This could be 2 cases. STRESSINFOLEVEL, or the real 0 level.
// If Command is 0 then it is STRESSINFOLEVEL, else real 0 level
//
/*
if ( !Command ) {
pOffsets = PrinterInfoStressStringsA;
cbStruct = sizeof( PRINTER_INFO_STRESSA );
}
*/
break;
case 1:
pOffsets = PrinterInfo1StringsA;
cbStruct = sizeof( PRINTER_INFO_1W );
break;
case 2:
pOffsets = PrinterInfo2StringsA;
cbStruct = sizeof( PRINTER_INFO_2W );
break;
case 3:
pOffsets = PrinterInfo3StringsA;
cbStruct = sizeof( PRINTER_INFO_3);
break;
case 4:
pOffsets = PrinterInfo4StringsA;
cbStruct = sizeof( PRINTER_INFO_4W );
break;
case 5:
pOffsets = PrinterInfo5StringsA;
cbStruct = sizeof( PRINTER_INFO_5W );
break;
case 6:
break;
default:
SetLastError( ERROR_INVALID_LEVEL );
return FALSE;
}
//
// The structure needs to have its CONTENTS converted from
// ANSI to Unicode. The above switch() statement filled in
// the two important pieces of information needed to accomplish
// this goal. First is the size of the structure, second is
// a list of the offset within the structure to UNICODE
// string pointers. The AllocateUnicodeStructure() call will
// allocate a wide version of the structure, copy its contents
// and convert the strings to Unicode as it goes. That leaves
// us to deal with any other pieces needing conversion.
//
//
// If Level == 0 and Command != 0 then pPrintert is a DWORD
//
if ( Level == 6 || (!Level && Command) ) {
if ( Level == 6 || Command == PRINTER_CONTROL_SET_STATUS )
pAnsiStructure = pPrinter;
else
pAnsiStructure = NULL;
} else {
pAnsiStructure = AllocateAnsiStructure(pPrinter, cbStruct, pOffsets);
if (pPrinter && !pAnsiStructure)
return FALSE;
}
#define pPrinterInfo2A ((LPPRINTER_INFO_2A)pAnsiStructure)
#define pPrinterInfo2W ((LPPRINTER_INFO_2W)pPrinter)
// The Level 2 structure has a DEVMODE struct in it: convert now
if ( Level == 2 &&
pAnsiStructure &&
pPrinterInfo2W->pDevMode ) {
if( bValidDevModeW( pPrinterInfo2W->pDevMode )){
pPrinterInfo2A->pDevMode = AllocateAnsiDevMode(
pPrinterInfo2W->pDevMode );
if( !pPrinterInfo2A->pDevMode) {
FreeAnsiStructure(pAnsiStructure, pOffsets);
return FALSE;
}
}
}
ReturnValue = SetPrinterA( hPrinter, Level, pAnsiStructure, Command );
// Free the DEVMODE we allocated (if we did!), then the
// the Unicode structure and its contents.
if (Level == 2 &&
pAnsiStructure &&
pPrinterInfo2A->pDevMode ) {
LocalFree( pPrinterInfo2A->pDevMode );
}
//
// STRESS_INFO and Levels 1-5
//
if ( Level != 6 && (Level || !Command) )
FreeAnsiStructure( pAnsiStructure, pOffsets );
#undef pPrinterInfo2A
#undef pPrinterInfo2W
return ReturnValue;
}
BOOL
SetJobW(
HANDLE hPrinter,
DWORD JobId,
DWORD Level,
LPBYTE pJob,
DWORD Command
)
{
BOOL ReturnValue=FALSE;
LPBYTE pAnsiStructure=NULL;
LPDEVMODEA pDevModeA = NULL;
DWORD cbStruct;
DWORD *pOffsets;
switch (Level) {
case 0:
break;
case 1:
pOffsets = JobInfo1StringsA;
cbStruct = sizeof(JOB_INFO_1W);
break;
case 2:
pOffsets = JobInfo2StringsA;
cbStruct = sizeof(JOB_INFO_2W);
break;
case 3:
return SetJobA( hPrinter, JobId, Level, pJob, Command );
default:
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
if (Level) {
pAnsiStructure = AllocateAnsiStructure(pJob, cbStruct, pOffsets);
if (pJob && !pAnsiStructure)
return FALSE;
}
if ( Level == 2 && pAnsiStructure && pJob ) {
if( bValidDevModeW( ((LPJOB_INFO_2W)pJob)->pDevMode )){
pDevModeA = AllocateAnsiDevMode(((LPJOB_INFO_2W)pJob)->pDevMode);
if( !pDevModeA ){
ReturnValue = FALSE;
goto Cleanup;
}
((LPJOB_INFO_2A) pAnsiStructure)->pDevMode = pDevModeA;
}
}
ReturnValue = SetJobA(hPrinter, JobId, Level, pAnsiStructure, Command);
if ( pDevModeA ) {
LocalFree(pDevModeA);
}
Cleanup:
FreeAnsiStructure(pAnsiStructure, pOffsets);
return ReturnValue;
}
BOOL
GetJobW(
HANDLE hPrinter,
DWORD JobId,
DWORD Level,
LPBYTE pJob,
DWORD cbBuf,
LPDWORD pcbNeeded
)
{
DWORD *pOffsets;
LPBYTE pJobA = NULL;
DWORD cbNeededA = 0;
DWORD cbBufA = 0;
DWORD dwJobStructSizeW = 0;
DWORD dwJobStructSizeA = 0;
BOOL fRetval;
switch (Level) {
case 1:
pOffsets = JobInfo1StringsA;
dwJobStructSizeW = sizeof(JOB_INFO_1W);
dwJobStructSizeA = sizeof(JOB_INFO_1A);
break;
case 2:
pOffsets = JobInfo2StringsA;
dwJobStructSizeW = sizeof(JOB_INFO_2W);
dwJobStructSizeA = sizeof(JOB_INFO_2A);
break;
case 3:
return GetJobA( hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded );
default:
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
//
// GetJobA is broken. THis is a workaround here which will work
// sometimes. The AV problem however goes away.
//
// Ramv bug fix: The user has passed in a certain amount of
// unicode memory. This has to be appropriately translated into
// equivalent ANSI memory.
//
//
// The translation is to take the entire blob of memory and
// subtract sizeof(JOB_INFO_2W) and then divide the remaining memory
// into 2.
//
// we also have to contend with GetJobA's erroneous return values
// when we pass in a buffer of sixe 0, it gives back wrong results
//
//
//
cbBufA = cbBuf > dwJobStructSizeW ?
(cbBuf-dwJobStructSizeW)/sizeof(WCHAR) + dwJobStructSizeA : 64;
pJobA = (LPBYTE)AllocADsMem( cbBufA);
if (!pJobA){
goto error;
}
fRetval = GetJobA (hPrinter, JobId, Level, pJobA, cbBufA, &cbNeededA);
if ( fRetval) {
//
// RamV bug fix.
// The size that we get back is actually the size of
// the ANSI array needed. We need our array to be larger for
// unicode by an amount = (total lengths of all strings +1)
// times the sizeof(WCHAR)
//
//
// Looks like we have sufficient memory here for our operations
// we need to copy the memory blob from Ansi to Unicode
//
//
// Thanks to win95 returning erroneous values, we are forced
// to fail this call even though it succeeded and send back
// the cbNeededA value converted into the Unicode value
//
if (cbBuf == 0){
*pcbNeeded = 2*cbNeededA; // just being conservative here by
// allocating a little more space than needed
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto error;
}
if (!ConvertAnsiToUnicodeBuf(
pJobA,
pJob,
dwJobStructSizeA,
dwJobStructSizeW,
pOffsets)){
goto error;
}
//
// Convert the devmode in place for INFO_2.
//
if( Level == 2 ){
PJOB_INFO_2W pJobInfo2 = (PJOB_INFO_2W)pJob;
if( pJobInfo2->pDevMode ){
CopyUnicodeDevModeFromAnsiDevMode(
(LPDEVMODEW)pJobInfo2->pDevMode,
(LPDEVMODEA)pJobInfo2->pDevMode);
}
}
return TRUE;
} else {
//
// RamV bug fix.
// The size that we get back is actually the size of
// the ANSI array needed. We need our array to be larger for
// unicode by an amount = (total lengths of all strings +1)
// times the sizeof(WCHAR)
//
if(cbNeededA) {
//
// we need to translate this into unicode terms
//
*pcbNeeded = dwJobStructSizeW +
(cbBufA + cbNeededA - dwJobStructSizeA)*sizeof(WCHAR);
}
return FALSE;
}
error:
if(pJobA) {
FreeADsMem(pJobA);
}
return FALSE;
}
BOOL
ConvertAnsiToUnicodeBuf(
LPBYTE pAnsiBlob,
LPBYTE pUnicodeBlob,
DWORD dwAnsiSize,
DWORD dwUnicodeSize,
PDWORD pOffsets
)
{
DWORD i = 0;
LPSTR pAnsi;
LPBYTE pUnicode;
LPBYTE pszString = pUnicodeBlob + dwUnicodeSize;
LPBYTE pStringPos = NULL;
memcpy(pUnicodeBlob, pAnsiBlob, dwAnsiSize);
pUnicode = pszString;
while (pOffsets[i] != -1) {
pAnsi = *(LPSTR *)(pAnsiBlob + pOffsets[i]);
if (!AnsiToUnicodeString((LPSTR)pAnsi,
(LPWSTR)pUnicode,
NULL_TERMINATED )){
return(FALSE);
}
pStringPos = pUnicodeBlob +pOffsets[i];
*((LPBYTE *)pStringPos) = pUnicode;
pUnicode = pUnicode + (wcslen((LPWSTR)(pUnicode))+1)* sizeof(WCHAR);
i++;
}
return(TRUE);
}
BOOL
OpenPrinterW(
LPWSTR pPrinterName,
LPHANDLE phPrinter,
LPPRINTER_DEFAULTSW pDefault
)
{
BOOL ReturnValue = FALSE;
LPSTR pAnsiPrinterName = NULL;
PRINTER_DEFAULTSA AnsiDefaults={NULL, NULL, 0};
pAnsiPrinterName = AllocateAnsiString(pPrinterName);
if (pPrinterName && !pAnsiPrinterName)
goto Cleanup;
if (pDefault) {
AnsiDefaults.pDatatype = AllocateAnsiString(pDefault->pDatatype);
if (pDefault->pDatatype && !AnsiDefaults.pDatatype)
goto Cleanup;
//
// Milestones etc. 4.5 passes in a bogus devmode in pDefaults.
// Be sure to validate here.
//
if( bValidDevModeW( pDefault->pDevMode )){
AnsiDefaults.pDevMode = AllocateAnsiDevMode(
pDefault->pDevMode );
if( !AnsiDefaults.pDevMode ){
goto Cleanup;
}
}
AnsiDefaults.DesiredAccess = pDefault->DesiredAccess;
}
ReturnValue = OpenPrinterA(pAnsiPrinterName, phPrinter, &AnsiDefaults);
/* Ramv This code below causes AV. I have disabled it
MattRim 1-10-00: Leaving this disabled. phPrinter is an opaque handle
to an undocumented structure. Trying to manipulate it is a surefire way
to cause AVs if a service pack/O.S. upgrade ever changes the implementation
of this Win9x-internal structure.
if (ReturnValue) {
((PSPOOL)*phPrinter)->Status |= SPOOL_STATUS_ANSI;
}
*/
Cleanup:
if (AnsiDefaults.pDevMode)
LocalFree(AnsiDefaults.pDevMode);
FreeAnsiString(AnsiDefaults.pDatatype);
FreeAnsiString(pAnsiPrinterName);
return ReturnValue;
}