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.
 
 
 
 
 
 

1834 lines
49 KiB

/*++
Copyright (c) 1997-1999 Microsoft Corporation
--*/
// NTRAID#NTBUG9-553877-2002/02/28-yasuho-: Security: mandatory changes
// NTRAID#NTBUG9-576656-2002/03/14-yasuho-: Possible buffer overrun
// NTRAID#NTBUG9-576658-2002/03/14-yasuho-: Possible divide by zero
// NTRAID#NTBUG9-576660-2002/03/14-yasuho-: Need impersonate for file access
// NTRAID#NTBUG9-576661-2002/03/14-yasuho-: Remove the dead codes
#include "pdev.h"
#include "alpsres.h"
#include "dither.h"
#include <stdio.h>
// #include <winsplp.h>
INT iCompTIFF( BYTE *, int, BYTE *, int );
HANDLE RevertToPrinterSelf( VOID );
BOOL ImpersonatePrinterClient( HANDLE );
BOOL bTextQuality(
PDEVOBJ pdevobj);
BOOL IsAsfOkMedia(
PDEVOBJ pdevobj);
BOOL
bDataSpool(
PDEVOBJ pdevobj,
HANDLE hFile,
LPSTR pBuf,
DWORD dwLen);
BOOL
bSpoolOut(
PDEVOBJ pdevobj);
#define DATASPOOL(p, f, s, n) \
if (TRUE != bDataSpool((p), (f), (s), (n))) \
return FALSE;
#define SPOOLOUT(p) \
if (TRUE != bSpoolOut(p)) \
return FALSE;
//
// Decision table for media type/paper
// source selection. To avoid hardware damage,
// we will select "manual feed" whenever ASF is
// not appropriate to specified media.
//
static struct {
BOOL bAsfOk; // Can print on ASF
// Add new attributes here
} gMediaType[MAX_MEDIATYPES] = {
{1}, // PPC (Normal)
{1}, // PPC (Fine)
{1}, // OHP (Normal)
{1}, // OHP (Fine)
{1}, // ExcOHP (Normal)
{1}, // ExcOHP (Fine)
{0}, // Iron (PPC)
{0}, // Iron (OHP)
{0}, // Thick Paper
{1}, // Postcard
{1}, // High Grade Paper
{0}, // Back Print Film
{0}, // Labeca Sheet
{0}, // CD Master
{1}, // Dye-sub Paper
{1}, // Dye-sub Label
{0}, // Glossy Paper
{1}, // VD Photo Film
{1}, // VD Photo Postcard
// Add new media type here
};
static
PAPERSIZE
gPaperSize[] = {
{2, 4800 * 2, 5960 * 2, 0, 0, 0, 1}, // Letter
{3, 4800 * 2, 7755 * 2, 0, 0, 0, 1}, // Legal
{1, 4190 * 2, 5663 * 2, 0, 0, 0, 1}, // Exective
{4, 4800 * 2, 6372 * 2, 0, 0, 0, 1}, // A4
{5, 4138 * 2, 5430 * 2, 0, 0, 0, 1}, // B5
{6, 2202 * 2, 2856 * 2, 0, 0, 0, 1}, // Postcard
{6, 4564 * 2, 2856 * 2, 0, 0, 0, 1}, // Double Postcard
{7, 2202 * 2, 3114 * 2, 0, 0, 0, 1}, // Photo Color Label
{7, 2202 * 2, 2740 * 2, 0, 0, 0, 1}, // Glossy Label
{0, 2030 * 2, 3164 * 2, 0, 0, 0, 1}, // CD Master
{6, 2202 * 2, 3365 * 2, 0, 0, 0, 1}, // VD Photo Postcard
/* Add new paper sizes here */
};
#define PAPER_SIZE_LETTER 0
#define PAPER_SIZE_LEGAL 1
#define PAPER_SIZE_EXECTIVE 2
#define PAPER_SIZE_A4 3
#define PAPER_SIZE_B5 4
#define PAPER_SIZE_POSTCARD 5
#define PAPER_SIZE_DOUBLE_POSTCARD 6
#define PAPER_PHOTO_COLOR_LABEL 7
#define PAPER_GLOSSY_LABEL 8
#define PAPER_CD_MASTER 9
#define PAPER_VD_PHOTO_POSTCARD 10
/* Add new paper sizes here */
#define MAX_PAPERS (sizeof(gPaperSize)/sizeof(gPaperSize[0]))
//
// ---- F U N C T I O N S ----
//
//////////////////////////////////////////////////////////////////////////
// Function: OEMEnablePDEV
//
// Description: OEM callback for DrvEnablePDEV;
// allocate OEM specific memory block
//
// Parameters:
//
// pdevobj Pointer to the DEVOBJ. pdevobj->pdevOEM is undefined.
// pPrinterName name of the current printer.
// cPatterns, phsurfPatterns, cjGdiInfo, pGdiInfo, cjDevInfo, pDevInfo:
// These parameters are identical to what's passed
// into DrvEnablePDEV.
// pded points to a function table which contains the
// system driver's implementation of DDI entrypoints.
//
// Returns:
// Pointer to the PDEVOEM
//
// Comments:
//
//
// History:
//
//////////////////////////////////////////////////////////////////////////
PDEVOEM APIENTRY
OEMEnablePDEV(
PDEVOBJ pdevobj,
PWSTR pPrinterName,
ULONG cPatterns,
HSURF *phsurfPatterns,
ULONG cjGdiInfo,
GDIINFO* pGdiInfo,
ULONG cjDevInfo,
DEVINFO* pDevInfo,
DRVENABLEDATA *pded)
{
PCURRENTSTATUS pTemp = NULL;
VERBOSE((DLLTEXT("OEMEnablePDEV() entry.\n")));
pdevobj->pdevOEM = NULL;
// Allocate minidriver private PDEV block.
pTemp = (PCURRENTSTATUS)MemAllocZ(sizeof(CURRENTSTATUS));
if (NULL == pTemp) {
ERR(("Memory allocation failure.\n"));
goto FAIL_NO_MEMORY;
}
#define MAX_RASTER_PIXELS 5100
// In worstcase, Photo color printing mode use 4 bits par pixel
#define MAX_RASTER_BYTES (MAX_RASTER_PIXELS + 1 / 2)
// Buffers for four plane rasters and one for the
// the scratch work enough for worstcase compression
// overhead.
// The 1st one byte is used for On/Off flag.
#define MAX_RASTER_BUFFER_BYTES \
(4 + MAX_RASTER_BYTES * 5 + (MAX_RASTER_BYTES >> 4))
pTemp->pData = (PBYTE)MemAllocZ(MAX_RASTER_BUFFER_BYTES);
if (NULL == pTemp->pData) {
ERR(("Memory allocation failure.\n"));
goto FAIL_NO_MEMORY;
}
pTemp->pRaster[0] = pTemp->pData;
pTemp->pRaster[1] = pTemp->pRaster[0] + (1 + MAX_RASTER_BYTES);
pTemp->pRaster[2] = pTemp->pRaster[1] + (1 + MAX_RASTER_BYTES);
pTemp->pRaster[3] = pTemp->pRaster[2] + (1 + MAX_RASTER_BYTES);
pTemp->pData2 = pTemp->pRaster[3] + (1 + MAX_RASTER_BYTES);
pTemp->pPaperSize = (PAPERSIZE *)MemAllocZ(
sizeof (gPaperSize));
if (NULL == pTemp->pPaperSize) {
ERR(("Memory allocation failure.\n"));
goto FAIL_NO_MEMORY;
}
CopyMemory(pTemp->pPaperSize, gPaperSize,
sizeof (gPaperSize));
// Set minidriver PDEV address.
pdevobj->pdevOEM = (MINIDEV *)MemAllocZ(sizeof(MINIDEV));
if (NULL == pdevobj->pdevOEM) {
ERR(("Memory allocation failure.\n"));
goto FAIL_NO_MEMORY;
}
MINIDEV_DATA(pdevobj) = pTemp;
return pdevobj->pdevOEM;
FAIL_NO_MEMORY:
if (NULL != pTemp) {
if (NULL != pTemp->pData) {
MemFree(pTemp->pData);
}
if (NULL != pTemp->pPaperSize) {
MemFree(pTemp->pPaperSize);
}
MemFree(pTemp);
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////
// Function: OEMDisablePDEV
//
// Description: OEM callback for DrvDisablePDEV;
// free all allocated OEM specific memory block(s)
//
// Parameters:
//
// pdevobj Pointer to the DEVOBJ.
//
// Returns:
// None
//
// Comments:
//
//
// History:
//
//////////////////////////////////////////////////////////////////////////
VOID APIENTRY
OEMDisablePDEV(
PDEVOBJ pdevobj)
{
PCURRENTSTATUS pTemp;
VERBOSE((DLLTEXT("OEMDisablePDEV() entry.\n")));
if ( NULL != pdevobj->pdevOEM ) {
pTemp = (PCURRENTSTATUS)MINIDEV_DATA(pdevobj);
if (NULL != pTemp) {
if (NULL != pTemp->pData) {
MemFree(pTemp->pData);
}
if (NULL != pTemp->pPaperSize) {
MemFree(pTemp->pPaperSize);
}
MemFree( pTemp );
}
MemFree( pdevobj->pdevOEM );
pdevobj->pdevOEM = NULL;
}
}
BOOL APIENTRY
OEMResetPDEV(
PDEVOBJ pdevobjOld,
PDEVOBJ pdevobjNew )
{
PCURRENTSTATUS pTempOld, pTempNew;
PBYTE pTemp;
VERBOSE((DLLTEXT("OEMResetPDEV entry.\n")));
// Do some verificatin on PDEV data passed in.
pTempOld = (PCURRENTSTATUS)MINIDEV_DATA(pdevobjOld);
pTempNew = (PCURRENTSTATUS)MINIDEV_DATA(pdevobjNew);
// Copy mindiriver specific part of PDEV
if (NULL != pTempNew && NULL != pTempOld) {
// NTRAID#NTBUG9-279876-2002/03/14-yasuho-: Should implement OEMResetPDEV().
// NTRAID#NTBUG9-249133-2002/03/14-yasuho-: 2nd page is distorted with duplex.
// This printer doesn't have duplex but we should copy them.
pTempNew->iCurrentResolution = pTempOld->iCurrentResolution;
pTempNew->iPaperQuality = pTempOld->iPaperQuality;
pTempNew->iPaperSize = pTempOld->iPaperSize;
pTempNew->iPaperSource = pTempOld->iPaperSource;
pTempNew->iTextQuality = pTempOld->iTextQuality;
pTempNew->iModel = pTempOld->iModel;
pTempNew->iDither = pTempOld->iDither;
pTempNew->fRequestColor = pTempOld->fRequestColor;
pTempNew->iUnitScale = pTempOld->iUnitScale;
pTempNew->iEmulState = pTempOld->iEmulState;
pTempNew->bXflip = pTempOld->bXflip;
}
return TRUE;
}
VOID
XFlip(
PDEVOBJ pdevobjOld,
PCURRENTSTATUS pdevOEM,
PBYTE pBuf,
DWORD dwLen)
{
INT i, j, k;
BYTE jTemp, jTemp2;
#define SWAP_3BYTES(p, q) { \
jTemp = *(PBYTE)(p); \
*(PBYTE)(p) = *(PBYTE)(q); \
*(PBYTE)(q) = jTemp; \
jTemp = *((PBYTE)(p) + 1); \
*((PBYTE)(p) + 1) = *((PBYTE)(q) + 1); \
*((PBYTE)(q) + 1) = jTemp; \
jTemp = *((PBYTE)(p) + 2); \
*((PBYTE)(p) + 2) = *((PBYTE)(q) + 2); \
*((PBYTE)(q) + 2) = jTemp; }
if (pdevOEM->fRequestColor) {
j = (dwLen / 3) * 3 - 3;
for (i = 0; i < j; i += 3, j -= 3) {
SWAP_3BYTES(pBuf + i, pBuf + j);
}
}
else {
j = dwLen - 1;
for (i = 0; i < j; i++, j--) {
jTemp = pBuf[j];
jTemp2 = 0;
for (k = 0; k < 8; k++) {
if ((jTemp >> k) & 1) {
jTemp2 |= (1 << (7 - k));
}
}
if (i == j) {
pBuf[j] = jTemp2;
continue;
}
jTemp = pBuf[i];
pBuf[i] = jTemp2;
jTemp2 = 0;
for (k = 0; k < 8; k++) {
if ((jTemp >> k) & 1) {
jTemp2 |= (1 << (7 - k));
}
}
pBuf[j] = jTemp2;
}
}
}
BOOL APIENTRY
OEMFilterGraphics(
PDEVOBJ pdevobj,
PBYTE pBuf,
DWORD dwLen)
{
PCURRENTSTATUS lpnp;
int i, x;
WORD wByteLen, wDataSize;
BYTE bRed, bGreen, bBlue;
BYTE py, pm, pc, pk, rm;
BYTE by, bm, bc, bk;
BYTE bCmd[128];
LONG iTemp;
INT iColor, iPlane;
BYTE *pTemp;
BOOL bLast = FALSE;
WORD wTemp;
PBYTE pCmd;
lpnp = (PCURRENTSTATUS)MINIDEV_DATA(pdevobj);
VERBOSE(("%d lines left in logical page.\n",
lpnp->wRasterCount));
// We clip off any raster lines exceeding the
// harware margins since it will feed paper too
// much and we cannot back feed the paper
// for 2nd plane and aftter. This result as
// "only cyan (1st plane) image is printed on
// paper."
if (lpnp->wRasterCount <= 0) {
WARNING(("Line beyond page length.\n"));
// We discard this line silently.
return TRUE;
}
else if (lpnp->wRasterCount <= 1) {
// The last raster in logical page,
// Need special handling.
bLast = TRUE;
}
lpnp->wRasterCount--;
// Do x-flip when requested.
if (lpnp->bXflip) {
XFlip(pdevobj, MINIDEV_DATA(pdevobj), pBuf, dwLen);
}
// Get resulting buffer length in bytes.
if ( lpnp->fRequestColor ) {
if ((dwLen / 3) > MAX_RASTER_BYTES) {
ERR((DLLTEXT("dwLen is too big (%d).\n"), dwLen));
return FALSE;
}
// NTRAID#NTBUG9-644657-2002/04/09-yasuho-: AV occured on OEMFilterGraphics()
// The pointer(s) will be not valid if the MDP_StartPage() has been failed.
if (!lpnp->pRaster)
return FALSE;
wByteLen = (WORD)(dwLen / 3);
memset(lpnp->pRaster[0], 0, wByteLen+1);
memset(lpnp->pRaster[1], 0, wByteLen+1);
memset(lpnp->pRaster[2], 0, wByteLen+1);
memset(lpnp->pRaster[3], 0, wByteLen+1);
}
else {
if (dwLen > MAX_RASTER_BYTES) {
ERR((DLLTEXT("dwLen is too big (%d).\n"), dwLen));
return FALSE;
}
wByteLen = (WORD)dwLen;
}
// Check if we have K ribbon
if (NULL != lpnp->pRasterK) {
// NTRAID#NTBUG9-644657-2002/04/09-yasuho-: AV occured on OEMFilterGraphics()
// The pointer(s) will be not valid if the MDP_StartPage() has been failed.
if (!lpnp->pRasterK)
return FALSE;
lpnp->pRasterK[0] = 0;
}
if ( lpnp->fRequestColor ) {
// NTRAID#NTBUG9-644657-2002/04/09-yasuho-: AV occured on OEMFilterGraphics()
// The pointer(s) will be not valid if the MDP_StartPage() has been failed.
if (!lpnp->pRasterC || !lpnp->pRasterM || !lpnp->pRasterY)
return FALSE;
lpnp->pRasterC[0] = 0;
lpnp->pRasterM[0] = 0;
lpnp->pRasterY[0] = 0;
for ( i = 0, x = 0; i+2 < (INT)dwLen ; i+=3, x++ ) {
bRed = pBuf[i];
bGreen = pBuf[i+1];
bBlue = pBuf[i+2];
// RGB -> YMCK
// DITHER_OHP: No longer used.
switch ( lpnp->iTextQuality ) {
case CMDID_TEXTQUALITY_PHOTO:
bPhotoConvert(pdevobj, bRed, bGreen, bBlue, &py, &pm, &pc, &pk);
// Processing dither
bDitherProcess(pdevobj, x, py, pm, pc, pk, &by, &bm, &bc, &bk);
break;
case CMDID_TEXTQUALITY_GRAPHIC:
bBusinessConvert(pdevobj, bRed, bGreen, bBlue, &py, &pm, &pc, &pk);
// Processing dither
bDitherProcess(pdevobj, x, py, pm, pc, pk, &by, &bm, &bc, &bk);
break;
case CMDID_TEXTQUALITY_CHARACTER:
bCharacterConvert(pdevobj, bRed, bGreen, bBlue, &py, &pm, &pc, &pk);
// Processing dither
bDitherProcess(pdevobj, x, py, pm, pc, pk, &by, &bm, &bc, &bk);
break;
//case CMDID_TEXTQUALITY_GRAY: dead code
}
if ((lpnp->iDither == DITHER_DYE) || (lpnp->iDither == DITHER_VD)) {
if ( bc ) {
lpnp->pRasterC[0] = 1;
lpnp->pRasterC[1 + x / 2] |= (BYTE)(bc << ((x % 2) ? 0 : 4));
}
if ( bm ) {
lpnp->pRasterM[0] = 1;
lpnp->pRasterM[1 + x / 2] |= (BYTE)(bm << ((x % 2) ? 0 : 4));
}
if ( by ) {
lpnp->pRasterY[0] = 1;
lpnp->pRasterY[1 + x / 2] |= (BYTE)(by << ((x % 2) ? 0 : 4));
}
// K make sure we have K ribbon
if ( bk && (lpnp->iDither == DITHER_VD) ) {
lpnp->pRasterK[0] = 1;
lpnp->pRasterK[1 + x / 2] |= (BYTE)(bk << ((x % 2) ? 0 : 4));
}
} else {
if ( bc ) {
lpnp->pRasterC[0] = 1;
lpnp->pRasterC[1 + x / 8] |= (BYTE)(0x80 >> (x % 8));
}
if ( bm ) {
lpnp->pRasterM[0] = 1;
lpnp->pRasterM[1 + x / 8] |= (BYTE)(0x80 >> (x % 8));
}
if ( by ) {
lpnp->pRasterY[0] = 1;
lpnp->pRasterY[1 + x / 8] |= (BYTE)(0x80 >> (x % 8));
}
// K make sure we have K ribbon
if ( bk && lpnp->pRasterK ) {
lpnp->pRasterK[0] = 1;
lpnp->pRasterK[1 + x / 8] |= (BYTE)(0x80 >> (x % 8));
}
}
}
}
else {
// Monochrome.
pTemp = pBuf;
for (i = 0; i < wByteLen; i++, pTemp++) {
if (*pTemp) {
lpnp->pRasterK[0] = 1;
break;
}
}
}
// Loop process for each color start here.
for ( iPlane = 0; iPlane < 4; iPlane++ ) {
if (NONE == lpnp->PlaneColor[iPlane]) {
// No more plane to process.
break;
}
if (!lpnp->fRequestColor) {
pTemp = pBuf;
}
else {
// Color rasters
pTemp = lpnp->pRaster[iPlane] + 1;
}
// If we do not have ink on this raster line,
// skip this line, just move cursor to the next one.
if (0 == lpnp->pRaster[iPlane][0]) {
lpnp->wRasterOffset[iPlane]++;
continue;
}
// We have ink, output data.
iColor = lpnp->PlaneColor[iPlane];
if (0 > iColor) {
iColor *= -1;
lpnp->PlaneColor[iPlane] = iColor;
// Ink selection commands
switch (iColor) {
case CYAN:
DATASPOOL(pdevobj, lpnp->TempFile[iPlane],
"\x1B\x1A\x01\x00\x72", 5);
break;
case MAGENTA:
DATASPOOL(pdevobj, lpnp->TempFile[iPlane],
"\x1B\x1A\x02\x00\x72", 5);
break;
case YELLOW:
DATASPOOL(pdevobj, lpnp->TempFile[iPlane],
"\x1B\x1A\x03\x00\x72", 5);
break;
case BLACK:
DATASPOOL(pdevobj, lpnp->TempFile[iPlane],
"\x1B\x1A\x00\x01\x72", 5);
break;
default:
ERR((DLLTEXT("Invalid color or plane IDs (%d, %d).\n"),
lpnp->PlaneColor[iPlane], iPlane));
return FALSE;
}
}
// First we move cursor to the correct raster offset.
if (0 < lpnp->wRasterOffset[iPlane]) {
// Send Y cursor move command
if (FAILED(StringCchPrintfExA(bCmd, sizeof bCmd, &pCmd, NULL, 0,
"\x1B\x2A\x62%c%c\x59",
LOBYTE(lpnp->wRasterOffset[iPlane]),
HIBYTE(lpnp->wRasterOffset[iPlane]))))
return FALSE;
DATASPOOL(pdevobj, lpnp->TempFile[iPlane], bCmd, (DWORD)(pCmd - bCmd));
// Reset Y position index.
lpnp->wRasterOffset[iPlane] = 0;
}
// Decide if we want to do compress
if ((lpnp->iDither == DITHER_DYE) || (lpnp->iDither == DITHER_VD))
wDataSize = ( wByteLen + 1 ) / 2; // 2 pixels par byte
else
wDataSize = ( wByteLen + 7 ) / 8; // 8 pixels par byte
if ((lpnp->iDither != DITHER_DYE) && (lpnp->iDither != DITHER_VD)) {
// NTRAID#NTBUG9-24281-2002/03/14-yasuho-:
// large bitmap does not printed on 1200dpi.
// Unnecessary data were sent to printer.
wTemp = bPlaneSendOrderCMY(lpnp) ? wDataSize : wByteLen;
if ((iTemp = iCompTIFF(lpnp->pData2,
MAX_RASTER_BUFFER_BYTES - (1 + MAX_RASTER_BYTES)*4,
pTemp, wTemp)) > 0 && iTemp < wTemp) {
pTemp = lpnp->pData2;
wDataSize = (WORD)iTemp;
// Turn on compression mode.
if (lpnp->iCompMode[iPlane] != COMP_TIFF4) {
DATASPOOL(pdevobj, lpnp->TempFile[iPlane], "\x1B*b\x02\x00M", 6);
lpnp->iCompMode[iPlane] = COMP_TIFF4;
}
}
else if (lpnp->iCompMode[iPlane] != COMP_NONE) {
// Turn off compression mode.
DATASPOOL(pdevobj, lpnp->TempFile[iPlane], "\x1B*b\x00\x00M", 6);
lpnp->iCompMode[iPlane] = COMP_NONE;
}
} // not DITHER_DYE
//
// a) ESC * xx V - one raster output, mo move.
// b) ESC * xx W - one raster output, move to next raster.
//
// Use a) on the last raster to avoid page eject. For the
// other rasters use b).
// Send one raster data
if (FAILED(StringCchPrintfExA(bCmd, sizeof bCmd, &pCmd, NULL, 0,
"\x1B\x2A\x62%c%c%c",
LOBYTE(wDataSize), HIBYTE(wDataSize),
(BYTE)(bLast ? 0x56 : 0x57))))
return FALSE;
DATASPOOL(pdevobj, lpnp->TempFile[iPlane], bCmd, (DWORD)(pCmd - bCmd));
DATASPOOL(pdevobj, lpnp->TempFile[iPlane], pTemp, wDataSize);
} // end of Color loop
lpnp->y++;
return TRUE;
}
INT
GetPlaneColor(
PDEVOBJ pdevobj,
PCURRENTSTATUS lpnp,
INT iPlane)
{
INT iColor;
iColor = NONE;
if (!lpnp->fRequestColor) {
if (0 == iPlane) {
iColor = BLACK;
}
return iColor;
}
// Color
// NTRAID#NTBUG9-24281-2002/03/14-yasuho-:
// large bitmap does not printed on 1200dpi.
// Do not use black plane (K) on the 1200dpi with color mode.
if (bPlaneSendOrderCMY(lpnp)) {
switch (iPlane) {
case 0:
iColor = CYAN;
break;
case 1:
iColor = MAGENTA;
break;
case 2:
iColor = YELLOW;
break;
}
}
else if (bPlaneSendOrderMCY(lpnp)) {
switch (iPlane) {
case 0:
iColor = MAGENTA;
break;
case 1:
iColor = CYAN;
break;
case 2:
iColor = YELLOW;
break;
}
}
else if (bPlaneSendOrderYMC(lpnp)) {
switch (iPlane) {
case 0:
iColor = YELLOW;
break;
case 1:
iColor = MAGENTA;
break;
case 2:
iColor = CYAN;
break;
}
}
else if (bPlaneSendOrderCMYK(lpnp)) {
switch (iPlane) {
case 0:
iColor = CYAN;
break;
case 1:
iColor = MAGENTA;
break;
case 2:
iColor = YELLOW;
break;
case 3:
iColor = BLACK;
break;
}
}
return iColor;
}
VOID
MDP_StartDoc(
PDEVOBJ pdevobj,
PCURRENTSTATUS pdevOEM)
{
VERBOSE(("MDP_StartDoc called.\n"));
WRITESPOOLBUF(pdevobj, "\x1B\x65\x1B\x25\x80\x41", 6);
}
VOID
MDP_EndDoc(
PDEVOBJ pdevobj,
PCURRENTSTATUS pdevOEM)
{
WRITESPOOLBUF(pdevobj, "\x1B\x25\x00\x58", 4);
}
BOOL
MDP_CreateTempFile(
PDEVOBJ pdevobj,
PCURRENTSTATUS pdevOEM,
INT iPlane)
{
HANDLE hFile;
BOOL bRet = FALSE;
HANDLE hToken = NULL;
PBYTE pBuf = NULL;
DWORD dwSize, dwNeeded = 0;
pdevOEM->TempName[iPlane][0] = __TEXT('\0');
pdevOEM->TempFile[iPlane] = INVALID_HANDLE_VALUE;
dwSize = (MAX_PATH + 1) * sizeof(WCHAR);
for (;;) {
if ((pBuf = MemAlloc(dwSize)) == NULL)
goto out;
if (GetPrinterData(pdevobj->hPrinter, SPLREG_DEFAULT_SPOOL_DIRECTORY,
NULL, pBuf, dwSize, &dwNeeded) == ERROR_SUCCESS)
break;
if (dwNeeded < dwSize || GetLastError() != ERROR_MORE_DATA)
goto out;
MemFree(pBuf);
dwSize = dwNeeded;
}
if (!(hToken = RevertToPrinterSelf()))
goto out;
if (!GetTempFileName((LPWSTR)pBuf, TEMP_NAME_PREFIX, 0,
pdevOEM->TempName[iPlane])) {
ERR((DLLTEXT("GetTempFileName failed (%d).\n"), GetLastError()))
goto out;
}
hFile = CreateFile(pdevOEM->TempName[iPlane],
(GENERIC_READ | GENERIC_WRITE), 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
ERR((DLLTEXT("CreateFile failed.\n")))
DeleteFile(pdevOEM->TempName[iPlane]);
goto out;
}
pdevOEM->TempFile[iPlane] = hFile;
bRet = TRUE;
out:
if (pBuf) MemFree(pBuf);
if (hToken) (void)ImpersonatePrinterClient(hToken);
return bRet;
}
BOOL
MDP_StartPage(
PDEVOBJ pdevobj,
PCURRENTSTATUS pdevOEM)
{
LONG iPageLength;
INT iPaperSizeID;
BYTE bCmd[128];
INT iColor, iPlane;
PBYTE pCmd;
// Set resolution
switch (pdevOEM->iCurrentResolution) {
case DPI1200:
WRITESPOOLBUF(pdevobj, "\x1B\x2A\x74\x04\x52", 5);
break;
case DPI600:
WRITESPOOLBUF(pdevobj, "\x1B\x2A\x74\x03\x52", 5);
break;
case DPI300:
WRITESPOOLBUF(pdevobj, "\x1B\x2A\x74\x02\x52", 5);
break;
}
// Set Paper Dimentions
// Make sure top margin is 0 and we are at top.
WRITESPOOLBUF(pdevobj, "\x1B\x26\x6C\x00\x00\x45", 6);
WRITESPOOLBUF(pdevobj, "\x1B\x1A\x00\x00\x0C", 5);
if (pdevOEM->iPaperSize < 0 || pdevOEM->iPaperSize >= MAX_PAPERS)
return FALSE;
if (!(pdevOEM->iUnitScale))
return FALSE;
iPaperSizeID
= pdevOEM->pPaperSize[pdevOEM->iPaperSize].iPaperSizeID;
if (FAILED(StringCchPrintfExA(bCmd, sizeof bCmd, &pCmd, NULL, 0,
"\x1B\x26\x6C%c%c\x41",
LOBYTE(iPaperSizeID), HIBYTE(iPaperSizeID))))
return FALSE;
WRITESPOOLBUF(pdevobj, bCmd, (DWORD)(pCmd - bCmd));
iPageLength
= pdevOEM->pPaperSize[pdevOEM->iPaperSize].iLogicalPageHeight;
iPageLength /= pdevOEM->iUnitScale;
if (FAILED(StringCchPrintfExA(bCmd, sizeof bCmd, &pCmd, NULL, 0,
"\x1B\x26\x6C%c%c\x50",
LOBYTE(iPageLength), HIBYTE(iPageLength))))
return FALSE;
WRITESPOOLBUF(pdevobj, bCmd, (DWORD)(pCmd - bCmd));
// # of raster lines in logical page.
pdevOEM->wRasterCount = (WORD)iPageLength;
// Determine dither methods.
pdevOEM->iDither = DITHER_HIGH_DIV2;
if (!(pdevOEM->fRequestColor)) {
pdevOEM->iTextQuality = CMDID_TEXTQUALITY_GRAY;
}
else {
if (!(bTextQuality(pdevobj))){
ERR((DLLTEXT("bTextQuality failed\n")));
return FALSE;
}
}
// Initialize dither tables
if (!(bInitialDither(pdevobj))){
ERR((DLLTEXT("bInitialDither failed\n")));
return FALSE;
}
// Pre-processing of color conversion. needed only photo.
if (pdevOEM->iTextQuality == CMDID_TEXTQUALITY_PHOTO ) {
if (!(bInitialColorConvert(pdevobj)) ){
ERR((DLLTEXT("bInitialColorConvert failed\n")));
return FALSE;
}
}
// Start Raster Data Transfer
WRITESPOOLBUF(pdevobj, "\x1B\x2A\x72\x00\x41", 5);
if ( pdevOEM->fRequestColor ) {
// Open temporary files. One file per one plain.
for (iPlane = 0; iPlane < 4; iPlane++) {
#if !CACHE_FIRST_PLANE
// We do not spool 1st plane
if (0 == iPlane) {
pdevOEM->TempFile[iPlane] = INVALID_HANDLE_VALUE;
continue;
}
#endif // !CACHE_FIRST_PLANE
if (!MDP_CreateTempFile(pdevobj, pdevOEM, iPlane))
return FALSE;
}
}
else {
for (iPlane = 0; iPlane < 4; iPlane++) {
pdevOEM->TempFile[iPlane] = INVALID_HANDLE_VALUE;
}
}
// Change printer emulation state.
pdevOEM->iEmulState = EMUL_DATA_TRANSFER;
pdevOEM->iCompMode[0] = pdevOEM->iCompMode[1] = pdevOEM->iCompMode[2]
= pdevOEM->iCompMode[3] = COMP_NONE;
// Misc setup.
pdevOEM->y = 0;
if (!pdevOEM->fRequestColor) {
WRITESPOOLBUF(pdevobj, "\x1B\x1A\x00\x01\x72", 5);
}
pdevOEM->pRasterC = NULL;
pdevOEM->pRasterM = NULL;
pdevOEM->pRasterY = NULL;
pdevOEM->pRasterK = NULL;
for (iPlane = 0; iPlane < 4; iPlane++) {
pdevOEM->wRasterOffset[iPlane] = 0;
// Set color ID for each plane.
// Negative value = Has no ink so do not have to ouput
// Positive value = Has ink on the plane. Have to output.
//
iColor = GetPlaneColor(pdevobj, pdevOEM, iPlane);
pdevOEM->PlaneColor[iPlane] = (-iColor);
switch (iColor) {
// NTRAID#NTBUG9-644657-2002/04/09-yasuho-: AV occured on OEMFilterGraphics()
// If the GetPlaneColor() failed, this function must return as failure.
default:
return FALSE;
case CYAN:
pdevOEM->pRasterC = pdevOEM->pRaster[iPlane];
break;
case MAGENTA:
pdevOEM->pRasterM = pdevOEM->pRaster[iPlane];
break;
case YELLOW:
pdevOEM->pRasterY = pdevOEM->pRaster[iPlane];
break;
case BLACK:
pdevOEM->pRasterK = pdevOEM->pRaster[iPlane];
break;
}
}
return TRUE;
}
BOOL
MDP_EndPage(
PDEVOBJ pdevobj,
PCURRENTSTATUS pdevOEM)
{
INT i;
HANDLE hToken = NULL;
BOOL bRet = FALSE;
// Spooled data transfer
if ( pdevOEM->fRequestColor )
SPOOLOUT(pdevobj);
// End Raster Transfer, FF.
WRITESPOOLBUF(pdevobj, "\x1B\x2A\x72\x43\x0C", 5);
// Change printer emulation state.
pdevOEM->iEmulState = EMUL_RGL;
// Close cache files.
for (i = 0; i < 4; i++) {
if (INVALID_HANDLE_VALUE != pdevOEM->TempFile[i]) {
if (0 == CloseHandle(pdevOEM->TempFile[i])) {
ERR((DLLTEXT("CloseHandle error %d\n"),
GetLastError()));
goto out;
}
pdevOEM->TempFile[i] = INVALID_HANDLE_VALUE;
if (!(hToken = RevertToPrinterSelf()))
goto out;
if (0 == DeleteFile(pdevOEM->TempName[i])) {
ERR((DLLTEXT("DeleteName error %d\n"),
GetLastError()));
goto out;
}
pdevOEM->TempName[i][0] = __TEXT('\0');
(void)ImpersonatePrinterClient(hToken);
hToken = NULL;
}
}
bRet = TRUE;
out:
if (hToken) (void)ImpersonatePrinterClient(hToken);
return bRet;
}
INT APIENTRY
OEMCommandCallback(
PDEVOBJ pdevobj,
DWORD dwCmdCbID,
DWORD dwCount,
PDWORD pdwParams)
{
PCURRENTSTATUS lpnp;
WORD len;
WORD wPageLength;
WORD wVerticalOffset;
WORD wRealOffset;
INT iRet;
VERBOSE((DLLTEXT("OEMCommandCallback(%d) entry.\n"),dwCmdCbID));
lpnp = (PCURRENTSTATUS)MINIDEV_DATA(pdevobj);
iRet = 0;
switch ( dwCmdCbID ){
case CMDID_PAPERSOURCE_CSF:
// \x1B&l\x03\x00H
lpnp->iPaperSource = CMDID_PAPERSOURCE_CSF;
break;
case CMDID_PAPERSOURCE_MANUAL:
// \x1B&l\x02\x00H
lpnp->iPaperSource = CMDID_PAPERSOURCE_MANUAL;
break;
case CMDID_PAPERQUALITY_PPC_NORMAL:
case CMDID_PAPERQUALITY_PPC_FINE:
case CMDID_PAPERQUALITY_OHP_NORMAL:
case CMDID_PAPERQUALITY_OHP_FINE:
case CMDID_PAPERQUALITY_OHP_EXCL_NORMAL:
case CMDID_PAPERQUALITY_OHP_EXCL_FINE:
case CMDID_PAPERQUALITY_IRON_PPC:
case CMDID_PAPERQUALITY_IRON_OHP:
case CMDID_PAPERQUALITY_THICK:
case CMDID_PAPERQUALITY_POSTCARD:
case CMDID_PAPERQUALITY_HIGRADE:
case CMDID_PAPERQUALITY_BACKPRINTFILM:
case CMDID_PAPERQUALITY_LABECA_SHEET:
case CMDID_PAPERQUALITY_CD_MASTER:
case CMDID_PAPERQUALITY_DYE_SUB_PAPER:
case CMDID_PAPERQUALITY_DYE_SUB_LABEL:
case CMDID_PAPERQUALITY_GLOSSY_PAPER:
case CMDID_PAPERQUALITY_VD_PHOTO_FILM:
case CMDID_PAPERQUALITY_VD_PHOTO_CARD:
{
switch ( dwCmdCbID ){
case CMDID_PAPERQUALITY_PPC_NORMAL:
WRITESPOOLBUF(pdevobj, "\x1B&l\x00\x00M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_PPC_NORMAL;
break;
case CMDID_PAPERQUALITY_PPC_FINE: // only mono color
if( lpnp->fRequestColor ){
// If user selects color, then we selects PPC NORMAL
// because, PPC FINE is not accepted color
WRITESPOOLBUF(pdevobj, "\x1B&l\x00\x00M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_PPC_NORMAL;
}else{
WRITESPOOLBUF(pdevobj, "\x1B&l\x00\x02M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_PPC_FINE;
}
break;
case CMDID_PAPERQUALITY_OHP_NORMAL:
WRITESPOOLBUF(pdevobj, "\x1B&l\x08\x01M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_OHP_NORMAL;
break;
case CMDID_PAPERQUALITY_OHP_FINE:
WRITESPOOLBUF(pdevobj, "\x1B&l\x08\x02M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_OHP_FINE;
break;
case CMDID_PAPERQUALITY_OHP_EXCL_NORMAL:
WRITESPOOLBUF(pdevobj, "\x1B&l\x01\x01M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_OHP_EXCL_NORMAL;
break;
case CMDID_PAPERQUALITY_OHP_EXCL_FINE:
WRITESPOOLBUF(pdevobj, "\x1B&l\x01\x02M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_OHP_EXCL_FINE;
break;
case CMDID_PAPERQUALITY_IRON_PPC:
WRITESPOOLBUF(pdevobj, "\x1B&l\x02\x02M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_IRON_PPC;
break;
case CMDID_PAPERQUALITY_IRON_OHP:
WRITESPOOLBUF(pdevobj, "\x1B&l\x02\x01M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_IRON_OHP;
break;
case CMDID_PAPERQUALITY_THICK:
WRITESPOOLBUF(pdevobj, "\x1B&l\x05\x00M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_THICK;
break;
case CMDID_PAPERQUALITY_POSTCARD:
WRITESPOOLBUF(pdevobj, "\x1B&l\x06\x00M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_POSTCARD;
break;
case CMDID_PAPERQUALITY_HIGRADE:
WRITESPOOLBUF(pdevobj, "\x1B&l\x07\x00M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_HIGRADE;
break;
case CMDID_PAPERQUALITY_BACKPRINTFILM:
WRITESPOOLBUF(pdevobj, "\x1B&l\x09\x00M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_BACKPRINTFILM;
break;
case CMDID_PAPERQUALITY_LABECA_SHEET:
WRITESPOOLBUF(pdevobj, "\x1B&l\x03\x00M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_LABECA_SHEET;
break;
case CMDID_PAPERQUALITY_CD_MASTER:
WRITESPOOLBUF(pdevobj, "\x1B&l\x04\x01M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_CD_MASTER;
break;
case CMDID_PAPERQUALITY_DYE_SUB_PAPER:
WRITESPOOLBUF(pdevobj, "\x1B&l\x0A\x00M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_DYE_SUB_PAPER;
break;
case CMDID_PAPERQUALITY_DYE_SUB_LABEL:
WRITESPOOLBUF(pdevobj, "\x1B&l\x0C\x00M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_DYE_SUB_LABEL;
break;
case CMDID_PAPERQUALITY_GLOSSY_PAPER:
WRITESPOOLBUF(pdevobj, "\x1B&l\x0F\x00M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_GLOSSY_PAPER;
break;
case CMDID_PAPERQUALITY_VD_PHOTO_FILM:
WRITESPOOLBUF(pdevobj, "\x1B&l\x10\x00M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_VD_PHOTO_FILM;
break;
case CMDID_PAPERQUALITY_VD_PHOTO_CARD:
WRITESPOOLBUF(pdevobj, "\x1B&l\x11\x00M", 6);
lpnp->iPaperQuality = CMDID_PAPERQUALITY_VD_PHOTO_CARD;
break;
}
if (lpnp->iPaperSource == CMDID_PAPERSOURCE_MANUAL){
WRITESPOOLBUF(pdevobj, "\x1B&l\x02\x00H", 6);
} else {
// Check if this media ( PAPERQUALITY ) and this
// paper size is printable on CSF.
if (IsAsfOkMedia(pdevobj)){
WRITESPOOLBUF(pdevobj, "\x1B&l\x03\x00H", 6);
}else{
WRITESPOOLBUF(pdevobj, "\x1B&l\x02\x00H", 6);
}
}
if( lpnp->fRequestColor ){
// YMCK Page Plane
WRITESPOOLBUF(pdevobj, "\x1B\x2A\x72\x04\x55", 5);
}else{
// Black Raster Plane
WRITESPOOLBUF( pdevobj, "\x1B\x2A\x72\x00\x55", 5);
}
}
break;
case CMDID_TEXTQUALITY_PHOTO:
case CMDID_TEXTQUALITY_GRAPHIC:
case CMDID_TEXTQUALITY_CHARACTER:
lpnp->iTextQuality = dwCmdCbID;
break;
// ####
case CMDID_MIRROR_ON:
lpnp->bXflip = TRUE;
break;
case CMDID_MIRROR_OFF:
lpnp->bXflip = FALSE;
break;
case CMDID_CURSOR_RELATIVE:
if (dwCount < 1 || !pdwParams)
break;
if (!lpnp->iUnitScale)
break;
// this printer's linespacing cmd is influenced with current resolution.
wVerticalOffset = (WORD)(pdwParams[0]);
wVerticalOffset /= (WORD)lpnp->iUnitScale;
lpnp->wRasterOffset[0] += wVerticalOffset;
lpnp->wRasterOffset[1] += wVerticalOffset;
lpnp->wRasterOffset[2] += wVerticalOffset;
lpnp->wRasterOffset[3] += wVerticalOffset;
lpnp->wRasterCount -= wVerticalOffset;
// Return offset change in device's units
iRet = wVerticalOffset;
break;
case CMDID_RESOLUTION_1200_MONO:
lpnp->iCurrentResolution = DPI1200;
lpnp->iUnitScale = 2;
break;
case CMDID_RESOLUTION_600:
lpnp->iCurrentResolution = DPI600;
lpnp->iUnitScale = 2;
break;
case CMDID_RESOLUTION_300:
lpnp->iCurrentResolution = DPI300;
lpnp->iUnitScale = 4;
break;
case CMDID_PSIZE_LETTER:
lpnp->iPaperSize = PAPER_SIZE_LETTER;
break;
case CMDID_PSIZE_LEGAL:
lpnp->iPaperSize = PAPER_SIZE_LEGAL;
break;
case CMDID_PSIZE_EXECTIVE:
lpnp->iPaperSize = PAPER_SIZE_EXECTIVE;
break;
case CMDID_PSIZE_A4:
lpnp->iPaperSize = PAPER_SIZE_A4;
break;
case CMDID_PSIZE_B5:
lpnp->iPaperSize = PAPER_SIZE_B5;
break;
case CMDID_PSIZE_POSTCARD:
lpnp->iPaperSize = PAPER_SIZE_POSTCARD;
break;
case CMDID_PSIZE_POSTCARD_DOUBLE:
lpnp->iPaperSize = PAPER_SIZE_DOUBLE_POSTCARD;
break;
case CMDID_PSIZE_PHOTO_COLOR_LABEL:
lpnp->iPaperSize = PAPER_PHOTO_COLOR_LABEL;
break;
case CMDID_PSIZE_GLOSSY_LABEL:
lpnp->iPaperSize = PAPER_GLOSSY_LABEL;
break;
case CMDID_PSIZE_CD_MASTER:
lpnp->iPaperSize = PAPER_CD_MASTER;
break;
case CMDID_PSIZE_VD_PHOTO_POSTCARD:
lpnp->iPaperSize = PAPER_VD_PHOTO_POSTCARD;
break;
case CMDID_COLORMODE_COLOR:
case CMDID_COLORMODE_MONO:
lpnp->fRequestColor = (dwCmdCbID == CMDID_COLORMODE_COLOR);
break;
case CMDID_BEGINDOC_MD5000: // Postcard printable area is expantioned on MD-5000
lpnp->pPaperSize[PAPER_SIZE_POSTCARD].iLogicalPageHeight
= 3082 * 2;
lpnp->pPaperSize[PAPER_SIZE_DOUBLE_POSTCARD].iLogicalPageHeight
= 3082 * 2;
case CMDID_BEGINDOC_MD2000:
case CMDID_BEGINDOC_MD2010:
lpnp->iModel = dwCmdCbID;
MDP_StartDoc(pdevobj, MINIDEV_DATA(pdevobj));
break;
case CMDID_ENDDOC:
MDP_EndDoc(pdevobj, MINIDEV_DATA(pdevobj));
break;
case CMDID_BEGINPAGE:
MDP_StartPage(pdevobj, MINIDEV_DATA(pdevobj));
break;
case CMDID_ENDPAGE:
MDP_EndPage(pdevobj, MINIDEV_DATA(pdevobj));
break;
default:
ERR((DLLTEXT("Unknown CallbackID = %d\n"), dwCmdCbID));
}
return iRet;
}
/*************************** Function Header *******************************
* IsAsfOkMedia
*
* Check if the media and the paper size is printable on Cut Sheet Feeder.
*
* HISTORY:
* 24 Sep 1996 -by- Sueya Sugihara [sueyas]
* Created.
*
***************************************************************************/
BOOL IsAsfOkMedia(
PDEVOBJ pdevobj)
{
PCURRENTSTATUS lpnp;
lpnp = (PCURRENTSTATUS)(MINIDEV_DATA(pdevobj));
if (lpnp->iPaperQuality < CMDID_PAPERQUALITY_FIRST ||
lpnp->iPaperQuality > CMDID_PAPERQUALITY_LAST)
return FALSE;
if (lpnp->iPaperSize < 0 || lpnp->iPaperSize > MAX_PAPERS)
return FALSE;
// ASF enabled only with ASF-allowed paper size AND
// ASF-allowed media type
if (gMediaType[lpnp->iPaperQuality - CMDID_PAPERQUALITY_FIRST].bAsfOk
&& lpnp->pPaperSize[lpnp->iPaperSize].bAsfOk) {
return TRUE;
}
return FALSE;
}
/*************************** Function Header *******************************
* bTextQuality
*
* Select dither table according to the paper quality(Media Type) and
* resolution and the requested halftoning type.
* If appropriate halftoning type is not selected, then this function
* selects halftoning type.
*
* HISTORY:
* 24 Sep 1996 -by- Sueya Sugihara [sueyas]
* Created.
*
***************************************************************************/
BOOL bTextQuality(
PDEVOBJ pdevobj)
{
PCURRENTSTATUS lpnp;
lpnp = (PCURRENTSTATUS)(MINIDEV_DATA(pdevobj));
switch ( lpnp->iPaperQuality ){
case CMDID_PAPERQUALITY_PPC_NORMAL:
case CMDID_PAPERQUALITY_OHP_NORMAL:
case CMDID_PAPERQUALITY_OHP_EXCL_NORMAL:
case CMDID_PAPERQUALITY_OHP_EXCL_FINE:
case CMDID_PAPERQUALITY_IRON_PPC:
case CMDID_PAPERQUALITY_IRON_OHP:
case CMDID_PAPERQUALITY_THICK:
case CMDID_PAPERQUALITY_POSTCARD:
case CMDID_PAPERQUALITY_HIGRADE:
case CMDID_PAPERQUALITY_BACKPRINTFILM:
case CMDID_PAPERQUALITY_LABECA_SHEET:
case CMDID_PAPERQUALITY_CD_MASTER:
case CMDID_PAPERQUALITY_GLOSSY_PAPER:
if ( lpnp->iTextQuality == CMDID_TEXTQUALITY_PHOTO ){
lpnp->iDither = DITHER_HIGH; // 145LPI
}else if ( lpnp->iTextQuality == CMDID_TEXTQUALITY_GRAPHIC ){
lpnp->iDither = DITHER_LOW; // 95LPI
}else{
lpnp->iDither = DITHER_HIGH_DIV2; // 145/2LPI
}
break;
case CMDID_PAPERQUALITY_DYE_SUB_PAPER:
case CMDID_PAPERQUALITY_DYE_SUB_LABEL:
lpnp->iDither = DITHER_DYE; // Dye-sub Media dither
break;
case CMDID_PAPERQUALITY_VD_PHOTO_FILM:
case CMDID_PAPERQUALITY_VD_PHOTO_CARD:
lpnp->iDither = DITHER_VD; // Dye-sub Media dither
break;
default:
return FALSE;
}
return TRUE;
}
BOOL
bDataSpool(
PDEVOBJ pdevobj,
HANDLE hFile,
LPSTR lpBuf,
DWORD dwLen)
{
DWORD dwTemp, dwTemp2;
BYTE *pTemp;
if (hFile != INVALID_HANDLE_VALUE) {
pTemp = lpBuf;
dwTemp = dwLen;
while (dwTemp > 0) {
if (0 == WriteFile(hFile, pTemp, dwTemp, &dwTemp2, NULL)) {
ERR((DLLTEXT("Writing cache faild, WriteFile() error %d.\n"),
GetLastError()));
return FALSE;
}
pTemp += dwTemp2;
dwTemp -= dwTemp2;
}
}
else {
WRITESPOOLBUF(pdevobj, lpBuf, dwLen);
}
return TRUE;
}
BOOL
bSpoolOut(
PDEVOBJ pdevobj)
{
PCURRENTSTATUS lpnp;
INT iPlane, iColor, iFile;
DWORD dwSize, dwTemp, dwTemp2;
HANDLE hFile;
#define BUF_SIZE 1024
BYTE Buf[BUF_SIZE];
lpnp = (PCURRENTSTATUS)(MINIDEV_DATA(pdevobj));
VERBOSE((DLLTEXT("bSpoolOut entry.\n")));
for (iPlane = 0; iPlane < 4; iPlane++) {
// CMDID_PAPERQUALITY_OHP_EXCL_NORMAL : MCY
// CMDID_PAPERQUALITY_OHP_EXCL_FINE : MCY
// CMDID_PAPERQUALITY_IRON_OHP : YMC
// Except above : CMYK
VERBOSE((DLLTEXT("About to send plane %d.\n"), iPlane));
// Check if we have ink in this plane.
iColor = lpnp->PlaneColor[iPlane];
// Exit loop if no remaining plane to print
if (iColor == NONE) {
VERBOSE((DLLTEXT("No remaining plane left.\n")));
break;
}
else if (0 > iColor) {
VERBOSE((DLLTEXT("No ink on this plane.\n")));
continue;
}
// If it is 2nd plane and after, send Back Feed.
if (0 < iPlane) {
WRITESPOOLBUF(pdevobj, "\x1B\x1A\x00\x00\x0C", 5);
}
VERBOSE((DLLTEXT("Cached data Plane=%d Color=%d\n"),
iPlane, iColor));
// Get file handle.
hFile = lpnp->TempFile[iPlane];
if (INVALID_HANDLE_VALUE == hFile) {
#if CACHE_FIRST_PLANE
ERR((DLLTEXT("file handle NULL in SendCachedData.\n")));
return FALSE;
#endif // CACHE_FIRST_PLANE
// Allow fp to be NULL for the case where we
// immediately send data to printer.
continue;
}
dwSize = SetFilePointer(hFile, 0L, NULL, FILE_CURRENT);
if (0xffffffff == dwSize) {
ERR((DLLTEXT("SetFilePointer failed %d\n"),
GetLastError()));
return FALSE;
}
// Output cached data.
if (0L != SetFilePointer(hFile, 0L, NULL, FILE_BEGIN)) {
ERR((DLLTEXT("SetFilePointer failed %d\n"),
GetLastError()));
return FALSE;
}
VERBOSE((DLLTEXT("Size of data to be read and sent = %ld\n"), dwSize));
for ( ; dwSize > 0; dwSize -= dwTemp2) {
dwTemp = ((BUF_SIZE < dwSize) ? BUF_SIZE : dwSize);
if (0 == ReadFile(hFile, Buf, dwTemp, &dwTemp2, NULL)) {
ERR((DLLTEXT("ReadFile error in SendCachedData.\n")));
return FALSE;
}
if (dwTemp2 > 0) {
WRITESPOOLBUF(pdevobj, Buf, dwTemp2);
}
}
}
return TRUE;
}
/*++
Routine Name
ImpersonationToken
Routine Description:
This routine checks if a token is a primary token or an impersonation
token.
Arguments:
hToken - impersonation token or primary token of the process
Return Value:
TRUE, if the token is an impersonation token
FALSE, otherwise.
--*/
BOOL
ImpersonationToken(
IN HANDLE hToken
)
{
BOOL bRet = TRUE;
TOKEN_TYPE eTokenType;
DWORD cbNeeded;
DWORD LastError;
//
// Preserve the last error. Some callers of ImpersonatePrinterClient (which
// calls ImpersonationToken) rely on the fact that ImpersonatePrinterClient
// does not alter the last error.
//
LastError = GetLastError();
//
// Get the token type from the thread token. The token comes
// from RevertToPrinterSelf. An impersonation token cannot be
// queried, because RevertToPRinterSelf doesn't open it with
// TOKEN_QUERY access. That's why we assume that hToken is
// an impersonation token by default
//
if (GetTokenInformation(hToken,
TokenType,
&eTokenType,
sizeof(eTokenType),
&cbNeeded))
{
bRet = eTokenType == TokenImpersonation;
}
SetLastError(LastError);
return bRet;
}
/*++
Routine Name
RevertToPrinterSelf
Routine Description:
This routine will revert to the local system. It returns the token that
ImpersonatePrinterClient then uses to imersonate the client again. If the
current thread doesn't impersonate, then the function merely returns the
primary token of the process. (instead of returning NULL) Thus we honor
a request for reverting to printer self, even if the thread is not impersonating.
Arguments:
None.
Return Value:
NULL, if the function failed
HANDLE to token, otherwise.
--*/
HANDLE
RevertToPrinterSelf(
VOID
)
{
HANDLE NewToken, OldToken, cToken;
BOOL Status;
NewToken = NULL;
Status = OpenThreadToken(GetCurrentThread(),
TOKEN_IMPERSONATE,
TRUE,
&OldToken);
if (Status)
{
//
// We are currently impersonating
//
cToken = GetCurrentThread();
Status = SetThreadToken(&cToken,
NewToken);
if (!Status) {
return NULL;
}
}
else if (GetLastError() == ERROR_NO_TOKEN)
{
//
// We are not impersonating
//
Status = OpenProcessToken(GetCurrentProcess(),
TOKEN_QUERY,
&OldToken);
if (!Status) {
return NULL;
}
}
return OldToken;
}
/*++
Routine Name
ImpersonatePrinterClient
Routine Description:
This routine attempts to set the passed in hToken as the token for the
current thread. If hToken is not an impersonation token, then the routine
will simply close the token.
Arguments:
hToken - impersonation token or primary token of the process
Return Value:
TRUE, if the function succeeds in setting hToken
FALSE, otherwise.
--*/
BOOL
ImpersonatePrinterClient(
HANDLE hToken)
{
BOOL Status;
HANDLE cToken;
//
// Check if we have an impersonation token
//
if (ImpersonationToken(hToken))
{
cToken = GetCurrentThread();
Status = SetThreadToken(&cToken,
hToken);
if (!Status)
{
return FALSE;
}
}
CloseHandle(hToken);
return TRUE;
}