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.
 
 
 
 
 
 

517 lines
15 KiB

/*++
Copyright (c) 1996-1999 Microsoft Corporation
Module Name:
escape.c
Abstract:
Implementation of escape related DDI entry points:
DrvEscape
Environment:
Windows NT Unidrv driver
Revision History:
10/14/96 -amandan-
Initial framework.
03/31/97 -zhanw-
Added OEM customization support
--*/
#include "unidrv.h"
// define DPRECT if you want to enable DRAWPATTERNRECT escape feature
#define DPRECT
typedef struct _POINTS {
short x;
short y;
} POINTs;
typedef struct _SHORTDRAWPATRECT { // use 16-bit POINT structure
POINTs ptPosition;
POINTs ptSize;
WORD wStyle;
WORD wPattern;
} SHORTDRAWPATRECT, *PSHORTDRAWPATRECT;
ULONG
DrvEscape(
SURFOBJ *pso,
ULONG iEsc,
ULONG cjIn,
PVOID *pvIn,
ULONG cjOut,
PVOID *pvOut
)
/*++
Routine Description:
Implementation of DDI entry point DrvEscape.
Please refer to DDK documentation for more details.
Arguments:
pso - Describes the surface the call is directed to
iEsc - Specifies a query
cjIn - Specifies the size in bytes of the buffer pointed to by pvIn
pvIn - Points to input data buffer
cjOut - Specifies the size in bytes of the buffer pointed to by pvOut
pvOut - Points to the output buffer
Return Value:
Depends on the query specified by iEsc parameter
--*/
{
#define pbIn ((BYTE *)pvIn)
#define pdwIn ((DWORD *)pvIn)
#define pdwOut ((DWORD *)pvOut)
PDEV *pPDev;
ULONG ulRes = 0;
VERBOSE(("Entering DrvEscape: iEsc = %d...\n", iEsc));
ASSERT(pso);
pPDev = (PDEV *) pso->dhpdev;
ASSERT_VALID_PDEV(pPDev);
//
// use driver managed surface
//
if (pPDev->pso)
pso = pPDev->pso;
//
// Handle OEM hooks
//
HANDLE_OEMHOOKS(pPDev,
EP_OEMEscape,
PFN_OEMEscape,
ULONG,
(pso,
iEsc,
cjIn,
pvIn,
cjOut,
pvOut));
HANDLE_VECTORHOOKS(pPDev,
EP_OEMEscape,
VMEscape,
ULONG,
(pso,
iEsc,
cjIn,
pvIn,
cjOut,
pvOut));
switch( iEsc )
{
case QUERYESCSUPPORT:
//
// Check if the specified escape code is supported
//
if (pvIn != NULL || cjIn >= sizeof(DWORD))
{
switch( *pdwIn )
{
case QUERYESCSUPPORT:
case PASSTHROUGH:
//
// Always support these escapes
//
ulRes = 1;
break;
case SETCOPYCOUNT:
ulRes = pPDev->dwMaxCopies > 1;
break;
#ifndef WINNT_40 // NT5
case DRAWPATTERNRECT:
if ((pPDev->fMode & PF_RECT_FILL) &&
(pPDev->dwMinGrayFill < pPDev->dwMaxGrayFill) &&
(pPDev->pdmPrivate->iLayout == ONE_UP) &&
(!(pPDev->pdm->dmFields & DM_TTOPTION) ||
pPDev->pdm->dmTTOption != DMTT_BITMAP) &&
!(pPDev->fMode2 & PF2_MIRRORING_ENABLED) &&
!(pPDev->pdmPrivate->dwFlags & DXF_TEXTASGRAPHICS)) // else, only black fill
{
if (pPDev->fMode & PF_RECTWHITE_FILL)
ulRes = 2;
else
ulRes = 1;
}
break;
#endif // !WINNT_40
}
}
break;
case PASSTHROUGH:
//
// QFE fix: NT4 TTY driver compatibility.
// There is an application that sends FF by itself.
// We don't want to send Form Feed if application calls DrvEscape.
//
if (pPDev->bTTY)
{
pPDev->fMode2 |= PF2_PASSTHROUGH_CALLED_FOR_TTY;
}
if( pvIn == NULL || cjIn < sizeof(WORD) )
{
SetLastError( ERROR_INVALID_PARAMETER );
ERR(("DrvEscape(PASSTHROUGH): Bad input parameters\n"));
}
else
{
//
// Win 3.1 actually uses the first 2 bytes as a count of the
// number of bytes following!!!! So, the following union
// allows us to copy the data to an aligned field that
// we use. And thus we ignore cjIn!
//
union
{
WORD wCount;
BYTE bCount[ 2 ];
} u;
u.bCount[ 0 ] = pbIn[ 0 ];
u.bCount[ 1 ] = pbIn[ 1 ];
if( u.wCount && cjIn >= (ULONG)(u.wCount + sizeof(WORD)) )
{
ulRes = WriteSpoolBuf( pPDev, pbIn + 2, u.wCount );
}
else
{
SetLastError( ERROR_INVALID_DATA );
ERR(("DrvEscape: Bad data in PASSTRHOUGH.\n"));
}
}
break;
case SETCOPYCOUNT:
if( pdwIn && *pdwIn > 0 )
{
pPDev->sCopies = (SHORT)*pdwIn;
//
// Check whether the copy count is in printer range
//
if( pPDev->sCopies > (SHORT)pPDev->dwMaxCopies )
pPDev->sCopies = (SHORT)pPDev->dwMaxCopies;
if( pdwOut )
*pdwOut = pPDev->sCopies;
ulRes = 1;
}
break;
case DRAWPATTERNRECT:
{
#ifndef WINNT_40
typedef struct _DRAWPATRECTP {
DRAWPATRECT DrawPatRect;
XFORMOBJ *pXFormObj;
} DRAWPATRECTP, *PDRAWPATRECTP;
if (pvIn == NULL || (cjIn != sizeof(DRAWPATRECT) && cjIn != sizeof(DRAWPATRECTP)))
#else
if( pvIn == NULL || cjIn != sizeof(DRAWPATRECT))
#endif
{
if (pvIn && cjIn == sizeof(SHORTDRAWPATRECT)) // check for Win3.1 DRAWPATRECT size
{
DRAWPATRECT dpr;
PSHORTDRAWPATRECT psdpr = (PSHORTDRAWPATRECT)pvIn;
if (pPDev->fMode & PF_ENUM_GRXTXT)
{
//
// Some apps (Access 2.0, AmiPro 3.1, etc.) do use the 16-bit
// POINT version of DRAWPATRECT structure. Have to be compatible
// with these apps.
//
dpr.ptPosition.x = (LONG)psdpr->ptPosition.x;
dpr.ptPosition.y = (LONG)psdpr->ptPosition.y;
dpr.ptSize.x = (LONG)psdpr->ptSize.x;
dpr.ptSize.y = (LONG)psdpr->ptSize.y;
dpr.wStyle = psdpr->wStyle;
dpr.wPattern = psdpr->wPattern;
ulRes = DrawPatternRect(pPDev, &dpr);
}
}
else
{
SetLastError( ERROR_INVALID_PARAMETER );
ERR(("DrvEscape(DRAWPATTERNRECT): Bad input parameters.\n"));
}
}
else if (pPDev->fMode & PF_ENUM_GRXTXT)
{
DRAWPATRECT dpr = *(PDRAWPATRECT)pvIn;
#ifndef WINNT_40 // NT 5.0
if (pPDev->pdmPrivate->iLayout != ONE_UP && cjIn == sizeof(DRAWPATRECTP))
{
XFORMOBJ *pXFormObj = ((PDRAWPATRECTP)pvIn)->pXFormObj;
POINTL PTOut[2],PTIn[2];
PTIn[0].x = dpr.ptPosition.x + pPDev->rcClipRgn.left;
PTIn[0].y = dpr.ptPosition.y + pPDev->rcClipRgn.top;
PTIn[1].x = PTIn[0].x + dpr.ptSize.x;
PTIn[1].y = PTIn[0].y + dpr.ptSize.y;
if (!XFORMOBJ_bApplyXform(pXFormObj,
XF_LTOL,
2,
PTIn,
PTOut))
{
ERR (("DrvEscape(DRAWPATTERNRECT): XFORMOBJ_bApplyXform failed.\n"));
break;
}
dpr.ptPosition.x = PTOut[0].x;
dpr.ptSize.x = PTOut[1].x - PTOut[0].x;
if (dpr.ptSize.x < 0)
{
dpr.ptPosition.x += dpr.ptSize.x;
dpr.ptSize.x = -dpr.ptSize.x;
}
else if (dpr.ptSize.x == 0)
dpr.ptSize.x = 1;
dpr.ptPosition.y = PTOut[0].y;
dpr.ptSize.y = PTOut[1].y - PTOut[0].y;
if (dpr.ptSize.y < 0)
{
dpr.ptPosition.y += dpr.ptSize.y;
dpr.ptSize.y = -dpr.ptSize.y;
}
else if (dpr.ptSize.y == 0)
dpr.ptSize.y = 1;
}
#endif // !WINNT_40
// Test whether to force minimum size = 2 pixels
//
if (pPDev->fMode & PF_SINGLEDOT_FILTER)
{
if (dpr.ptSize.y < 2)
dpr.ptSize.y = 2;
if (dpr.ptSize.x < 2)
dpr.ptSize.x = 2;
}
ulRes = DrawPatternRect(pPDev, &dpr);
}
else
ulRes = 1; // no need for GDI to take any action
break; // case DRAWPATTERNRECT
}
default:
SetLastError( ERROR_INVALID_FUNCTION );
break;
}
return ulRes;
}
ULONG
DrawPatternRect(
PDEV *pPDev,
PDRAWPATRECT pPatRect)
/*++
Routine Description:
Implementation of DRAWPATTERNECT escape. Note that it is PCL-specific.
Arguments:
pPDev - the driver's PDEV
pPatRect - the DRAWPATRECT structure from the app
Return Value:
1 if successful. Otherwise, 0.
--*/
{
WORD wPattern, wStyle;
RECTL rcClip;
COMMAND *pCmd;
ULONG ulRes = 0;
if (!(pPDev->fMode & PF_RECT_FILL))
return 0;
wStyle = pPatRect->wStyle;
if (!((wStyle+1) & 3)) // same as (wStyle < 0 || wStyle > 2)
return 0; // we support only solid fill
// Reset the brush, before downloading rule unless we are going to use
// a white rectangle command
if (wStyle != 1)
GSResetBrush(pPDev);
//
// clip to printable region
//
rcClip.left = MAX(0, pPatRect->ptPosition.x);
rcClip.top = MAX(0, pPatRect->ptPosition.y);
rcClip.right = MIN(pPDev->szBand.cx,
pPatRect->ptPosition.x + pPatRect->ptSize.x);
rcClip.bottom = MIN(pPDev->szBand.cy,
pPatRect->ptPosition.y + pPatRect->ptSize.y);
//
// check if we end up with an empty rect. If not, put down the rule.
//
if (rcClip.right > rcClip.left && rcClip.bottom > rcClip.top)
{
DWORD dwXSize,dwYSize;
//
// Move to the starting position. rcClip is in device units to
// which we must add the offset of the band origin
//
XMoveTo(pPDev, rcClip.left+pPDev->rcClipRgn.left, MV_GRAPHICS);
YMoveTo(pPDev, rcClip.top+pPDev->rcClipRgn.top, MV_GRAPHICS);
//
// The RectFill commands expect master units.
//
dwXSize = pPDev->dwRectXSize;
pPDev->dwRectXSize = (rcClip.right - rcClip.left) * pPDev->ptGrxScale.x;
dwYSize = pPDev->dwRectYSize;
pPDev->dwRectYSize = (rcClip.bottom - rcClip.top) * pPDev->ptGrxScale.y;
//
// check whether the rectangle size is different and update if necessary
//
if (dwXSize != pPDev->dwRectXSize ||
(!(COMMANDPTR(pPDev->pDriverInfo,CMD_RECTBLACKFILL)) &&
!(COMMANDPTR(pPDev->pDriverInfo,CMD_RECTGRAYFILL))))
{
WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo,CMD_SETRECTWIDTH));
}
if (dwYSize != pPDev->dwRectYSize ||
(!(COMMANDPTR(pPDev->pDriverInfo,CMD_RECTBLACKFILL)) &&
!(COMMANDPTR(pPDev->pDriverInfo,CMD_RECTGRAYFILL))))
{
WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo,CMD_SETRECTHEIGHT));
}
//
// range-check the pattern based upon the kind of rule.
//
switch (wStyle)
{
case 0:
//
// black fill, which is max gray fill unless CmdRectBlackFill exists
//
if (pCmd = COMMANDPTR(pPDev->pDriverInfo,CMD_RECTBLACKFILL))
WriteChannel(pPDev, pCmd);
else
{
pPDev->dwGrayPercentage = pPDev->dwMaxGrayFill;
WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo,CMD_RECTGRAYFILL));
}
ulRes = 1;
break;
case 1:
//
// White (erase) fill
//
if (pCmd = COMMANDPTR(pPDev->pDriverInfo,CMD_RECTWHITEFILL))
{
WriteChannel(pPDev, pCmd);
ulRes = 1;
}
break;
case 2:
//
// Shaded gray fill.
//
// If 100% black use black rectangle fill anyway
//
if (pPatRect->wPattern == 100 &&
(pCmd = COMMANDPTR(pPDev->pDriverInfo,CMD_RECTBLACKFILL)))
{
WriteChannel(pPDev, pCmd);
}
// If 0% black use white rectangle fill
//
else if (pPatRect->wPattern == 0 &&
(pCmd = COMMANDPTR(pPDev->pDriverInfo,CMD_RECTWHITEFILL)))
{
WriteChannel(pPDev, pCmd);
}
//
// Check for the gray range.
//
else
{
if ((wPattern = pPatRect->wPattern) < (WORD)pPDev->dwMinGrayFill)
wPattern = (WORD)pPDev->dwMinGrayFill;
if (wPattern > (WORD)pPDev->dwMaxGrayFill)
wPattern = (WORD)pPDev->dwMaxGrayFill;
pPDev->dwGrayPercentage = (DWORD)wPattern;
WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo,CMD_RECTGRAYFILL));
}
ulRes = 1;
break;
}
//
// update internal coordinates, if necessary. BUG_BUG, do we really need cx/cyafterfill in PDEV?
//
if (ulRes == 1)
{
if (pPDev->cxafterfill == CXARF_AT_RECT_X_END)
XMoveTo(pPDev, pPatRect->ptSize.x,
MV_GRAPHICS | MV_UPDATE | MV_RELATIVE);
if (pPDev->cyafterfill == CYARF_AT_RECT_Y_END)
YMoveTo(pPDev, pPatRect->ptSize.y,
MV_GRAPHICS | MV_UPDATE | MV_RELATIVE);
if (wStyle != 1)
{
INT i;
BYTE ubMask = BGetMask(pPDev,&rcClip);
for (i = rcClip.top;i < rcClip.bottom;i++)
pPDev->pbScanBuf[i] |= ubMask;
}
}
} // if (!IsRectEmpty(&rcClip))
return ulRes;
}