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.
 
 
 
 
 
 

5150 lines
146 KiB

/******************************Module*Header*******************************\
* Module Name: output.c *
* *
* Client side stubs for graphics output calls. *
* *
* Created: 05-Jun-1991 01:41:18 *
* Author: Charles Whitmer [chuckwh] *
* *
* Copyright (c) 1991-1999 Microsoft Corporation *
\**************************************************************************/
#include "precomp.h"
#pragma hdrstop
// 2 seconds is way way too long for either non-preemptive wow apps or
// an input-synchronized journal situation (like w/mstest). 1/20 a second
// is much better - scottlu
//#define CALLBACK_INTERVAL 2000
// Even better - 1/4 a second
// scottlu
#define CALLBACK_INTERVAL 250
extern BOOL MF_WriteEscape(HDC hdc, int nEscape, int nCount, LPCSTR lpInData, int type );
//
// WINBUG #82877 2-7-2000 bhouse Need to move definition of ETO_NULL_PRCL
//
#define ETO_NULL_PRCL 0x80000000
ULONG GdiBatchLimit = 20;
const XFORM xformIdentity = { 1.00000000f, 0.00000000f, 0.00000000f, 1.00000000f,
0.00000000f, 0.00000000f };
/******************************Public*Routine******************************\
* AngleArc *
* *
* Client side stub. Copies all LDC attributes into the message. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI AngleArc(
HDC hdc,
int x,
int y,
DWORD r,
FLOAT eA,
FLOAT eB
)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return(bRet);
DC_PLDC(hdc,pldc,bRet);
if ((pldc->iType == LO_METADC) &&
!MF_AngleArc(hdc,x,y,r,eA,eB)
)
return(bRet);
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
return(NtGdiAngleArc(hdc,x,y,r,FLOATARG(eA),FLOATARG(eB)));
}
/******************************Public*Routine******************************\
* Arc *
* *
* Client side stub. Copies all LDC attributes into the message. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI Arc
(
HDC hdc,
int x1,
int y1,
int x2,
int y2,
int x3,
int y3,
int x4,
int y4
)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return (MF16_RecordParms9(hdc,x1,y1,x2,y2,x3,y3,x4,y4,META_ARC));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if (!MF_ArcChordPie(hdc,x1,y1,x2,y2,x3,y3,x4,y4,EMR_ARC))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
return(NtGdiArcInternal(ARCTYPE_ARC,hdc,x1,y1,x2,y2,x3,y3,x4,y4));
}
/******************************Public*Routine******************************\
* ArcTo *
* *
* Client side stub. Copies all LDC attributes into the message. *
* *
* 12-Sep-1991 -by- J. Andrew Goossen [andrewgo] *
* Wrote it. Cloned it from Arc. *
\**************************************************************************/
BOOL META WINAPI ArcTo(
HDC hdc,
int x1,
int y1,
int x2,
int y2,
int x3,
int y3,
int x4,
int y4
)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return(bRet);
DC_PLDC(hdc,pldc,bRet);
if ((pldc->iType == LO_METADC) &&
!MF_ArcChordPie(hdc,x1,y1,x2,y2,x3,y3,x4,y4,EMR_ARCTO))
{
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
return(NtGdiArcInternal(ARCTYPE_ARCTO,hdc,x1,y1,x2,y2,x3,y3,x4,y4));
}
/******************************Public*Routine******************************\
* LineTo *
* *
* Client side stub. Copies all LDC attributes into the message. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI LineTo(HDC hdc,int x,int y)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return (MF16_RecordParms3(hdc,x,y,META_LINETO));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if (!MF_SetDD(hdc,(DWORD)x,(DWORD)y,EMR_LINETO))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
return(NtGdiLineTo(hdc,x,y));
}
/******************************Public*Routine******************************\
* Chord *
* *
* Client side stub. Copies all LDC attributes into the message. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI Chord(
HDC hdc,
int x1,
int y1,
int x2,
int y2,
int x3,
int y3,
int x4,
int y4
)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return (MF16_RecordParms9(hdc,x1,y1,x2,y2,x3,y3,x4,y4,META_CHORD));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if (!MF_ArcChordPie(hdc,x1,y1,x2,y2,x3,y3,x4,y4,EMR_CHORD))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
return(NtGdiArcInternal(ARCTYPE_CHORD,hdc,x1,y1,x2,y2,x3,y3,x4,y4));
}
/******************************Public*Routine******************************\
* Ellipse *
* *
* Client side stub. Copies all LDC attributes into the message. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI Ellipse(HDC hdc,int x1,int y1,int x2,int y2)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return (MF16_RecordParms5(hdc,x1,y1,x2,y2,META_ELLIPSE));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if (!MF_EllipseRect(hdc,x1,y1,x2,y2,EMR_ELLIPSE))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
return(NtGdiEllipse(hdc,x1,y1,x2,y2));
}
/******************************Public*Routine******************************\
* Pie *
* *
* Client side stub. Copies all LDC attributes into the message. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI Pie(
HDC hdc,
int x1,
int y1,
int x2,
int y2,
int x3,
int y3,
int x4,
int y4
)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return (MF16_RecordParms9(hdc,x1,y1,x2,y2,x3,y3,x4,y4,META_PIE));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if (!MF_ArcChordPie(hdc,x1,y1,x2,y2,x3,y3,x4,y4,EMR_PIE))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
return(NtGdiArcInternal(ARCTYPE_PIE,hdc,x1,y1,x2,y2,x3,y3,x4,y4));
}
/******************************Public*Routine******************************\
* Rectangle *
* *
* Client side stub. Copies all LDC attributes into the message. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI Rectangle(HDC hdc,int x1,int y1,int x2,int y2)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return (MF16_RecordParms5(hdc,x1,y1,x2,y2,META_RECTANGLE));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if (!MF_EllipseRect(hdc,x1,y1,x2,y2,EMR_RECTANGLE))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
return(NtGdiRectangle(hdc,x1,y1,x2,y2));
}
/******************************Public*Routine******************************\
* RoundRect *
* *
* Client side stub. Copies all LDC attributes into the message. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI RoundRect(
HDC hdc,
int x1,
int y1,
int x2,
int y2,
int x3,
int y3
)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return (MF16_RecordParms7(hdc,x1,y1,x2,y2,x3,y3,META_ROUNDRECT));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if (!MF_RoundRect(hdc,x1,y1,x2,y2,x3,y3))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
return(NtGdiRoundRect(hdc,x1,y1,x2,y2,x3,y3));
}
/******************************Public*Routine******************************\
* PatBlt *
* *
* Client side stub. Copies all LDC attributes into the message. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI PatBlt(
HDC hdc,
int x,
int y,
int cx,
int cy,
DWORD rop
)
{
BOOL bRet = FALSE;
PDC_ATTR pdca;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return(MF16_RecordParmsWWWWD(hdc,(WORD)x,(WORD)y,(WORD)cx,(WORD)cy,rop,META_PATBLT));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if (!MF_AnyBitBlt(hdc,x,y,cx,cy,(LPPOINT)NULL,(HDC)NULL,0,0,0,0,(HBITMAP)NULL,0,0,rop,EMR_BITBLT))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
BEGIN_BATCH_HDC(hdc,pdca,BatchTypePatBlt,BATCHPATBLT);
//
// check DC to see if call can be batched, all DCs in use
// by the client must have a valid dc_attr
//
pBatch->rop4 = rop;
pBatch->x = x;
pBatch->y = y;
pBatch->cx = cx;
pBatch->cy = cy;
pBatch->hbr = pdca->hbrush;
pBatch->TextColor = (ULONG)pdca->crForegroundClr;
pBatch->BackColor = (ULONG)pdca->crBackgroundClr;
pBatch->DCBrushColor = (ULONG)pdca->crDCBrushClr;
pBatch->IcmBrushColor = (ULONG)pdca->IcmBrushColor;
pBatch->ptlViewportOrg = pdca->ptlViewportOrg;
pBatch->ulTextColor = pdca->ulForegroundClr;
pBatch->ulBackColor = pdca->ulBackgroundClr;
pBatch->ulDCBrushColor = pdca->ulDCBrushClr;
COMPLETE_BATCH_COMMAND();
return(TRUE);
UNBATCHED_COMMAND:
return(NtGdiPatBlt(hdc,x,y,cx,cy,rop));
}
/******************************Public*Routine******************************\
* PolyPatBlt
*
* Arguments:
*
* hdc - dest DC
* rop - ROP for all patblt elements
* pPoly - pointer to array of PPOLYPATBLT structures
* Count - number of polypatblts
* Mode - mode for all polypatblts
*
* Return Value:
*
* BOOL Status
*
\**************************************************************************/
BOOL
META WINAPI
PolyPatBlt(
HDC hdc,
DWORD rop,
PPOLYPATBLT pPoly,
DWORD Count,
DWORD Mode
)
{
BOOL bRet = FALSE;
PDC_ATTR pdca;
FIXUP_HANDLE(hdc);
PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
// If ICM is enabled, we need to select the brush onto the DC in
// client side, so that ICM can translate brush color to DC color
// space. thus we can not use Batch, here. because Batch will selet
// the brush onto the DC in kernel side. so, there is no chance to
// ICM will be invoked.
if (IS_ALTDC_TYPE(hdc) || (pdca && IS_ICM_INSIDEDC(pdca->lIcmMode)))
{
ULONG Index;
HBRUSH hOld = 0;
for (Index=0;Index<Count;Index++)
{
//
// select brush, save first to restore
//
if (Index == 0)
{
hOld = SelectObject(hdc,(HBRUSH)pPoly[0].BrClr.hbr);
}
else
{
SelectObject(hdc,(HBRUSH)pPoly[Index].BrClr.hbr);
}
bRet = PatBlt(hdc,
pPoly[Index].x,
pPoly[Index].y,
pPoly[Index].cx,
pPoly[Index].cy,
rop
);
}
//
// restore brush if needed
//
if (hOld)
{
SelectObject(hdc,hOld);
}
}
else
{
RESETUSERPOLLCOUNT();
if ((Count != 0) && (pPoly != NULL) && (Mode == PPB_BRUSH))
{
USHORT uSize;
if (Count > (MAXUSHORT / sizeof(POLYPATBLT)))
goto UNBATCHED_COMMAND;
//
// size of batched structure
//
uSize = (USHORT)(Count * sizeof(POLYPATBLT));
uSize += (USHORT)sizeof(BATCHPOLYPATBLT);
if (uSize < (USHORT)sizeof(BATCHPOLYPATBLT))
goto UNBATCHED_COMMAND;
BEGIN_BATCH_HDC_SIZE(hdc,pdca,BatchTypePolyPatBlt,BATCHPOLYPATBLT,uSize);
pBatch->rop4 = rop;
pBatch->Count = Count;
pBatch->Mode = Mode;
pBatch->TextColor = (ULONG)pdca->crForegroundClr;
pBatch->BackColor = (ULONG)pdca->crBackgroundClr;
pBatch->DCBrushColor = (ULONG)pdca->crDCBrushClr;
pBatch->ptlViewportOrg = pdca->ptlViewportOrg;
pBatch->ulTextColor = pdca->ulForegroundClr;
pBatch->ulBackColor = pdca->ulBackgroundClr;
pBatch->ulDCBrushColor = pdca->ulDCBrushClr;
memcpy(&pBatch->ulBuffer[0],pPoly,Count*sizeof(POLYPATBLT));
//
// if the first hbr entry is NULL, copy in current hbr so
// it is remembered.
//
if (((PPOLYPATBLT)(&pBatch->ulBuffer[0]))->BrClr.hbr == NULL)
{
((PPOLYPATBLT)(&pBatch->ulBuffer[0]))->BrClr.hbr = pdca->hbrush;
}
bRet = TRUE;
COMPLETE_BATCH_COMMAND();
UNBATCHED_COMMAND:
if (!bRet)
{
bRet = NtGdiPolyPatBlt(hdc,rop,pPoly,Count,Mode);
}
}
}
return(bRet);
}
/******************************Public*Routine******************************\
* BitBlt *
* *
* Client side stub. Copies all LDC attributes into the message. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI BitBlt(
HDC hdc,
int x,
int y,
int cx,
int cy,
HDC hdcSrc,
int x1,
int y1,
DWORD rop
)
{
BOOL bRet = FALSE;
//
// if this call redueces to PatBlt, then let PatBlt
// do the metafile and/or output.
//
if ((((rop << 2) ^ rop) & 0x00CC0000) == 0)
{
return(PatBlt(hdc,x,y,cx,cy,rop));
}
//
// Src is required by ROP, do bitblt
//
FIXUP_HANDLE(hdc);
FIXUP_HANDLE(hdcSrc);
if (gbICMEnabledOnceBefore)
{
PDC_ATTR pdcattr, pdcattrSrc;
PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
PSHARED_GET_VALIDATE(pdcattrSrc,hdcSrc,DC_TYPE);
//
// if source DC has DIB section, and destination DC is ICM turned on
// do ICM-aware BitBlt.
//
if (pdcattr && pdcattrSrc)
{
if (IS_ICM_INSIDEDC(pdcattr->lIcmMode) &&
(bDIBSectionSelected(pdcattrSrc) ||
(IS_ICM_LAZY_CORRECTION(pdcattrSrc->lIcmMode) && (GetDCDWord(hdc,DDW_ISMEMDC,FALSE) == FALSE))))
{
if (IcmStretchBlt(hdc,x,y,cx,cy,hdcSrc,x1,y1,cx,cy,rop,pdcattr,pdcattrSrc))
{
return (TRUE);
}
}
}
}
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return (MF16_BitBlt(hdc,x,y,cx,cy,hdcSrc,x1,y1,rop));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if (!MF_AnyBitBlt(hdc,x,y,cx,cy,(LPPOINT)NULL,hdcSrc,x1,y1,cx,cy,(HBITMAP)NULL,0,0,rop,EMR_BITBLT))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
//
// Define _WINDOWBLT_NOTIFICATION_ to turn on Window BLT notification.
// This notification will set a special flag in the SURFOBJ passed to
// drivers when the DrvCopyBits operation is called to move a window.
//
// See also:
// ntgdi\gre\maskblt.cxx
//
#ifdef _WINDOWBLT_NOTIFICATION_
return(NtGdiBitBlt(hdc,x,y,cx,cy,hdcSrc,x1,y1,rop,(COLORREF)-1,0));
#else
return(NtGdiBitBlt(hdc,x,y,cx,cy,hdcSrc,x1,y1,rop,(COLORREF)-1));
#endif
}
/******************************Public*Routine******************************\
* StretchBlt *
* *
* Client side stub. Copies all LDC attributes into the message. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI StretchBlt(
HDC hdc,
int x,
int y,
int cx,
int cy,
HDC hdcSrc,
int x1,
int y1,
int cx1,
int cy1,
DWORD rop
)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
FIXUP_HANDLEZ(hdcSrc);
if (gbICMEnabledOnceBefore)
{
PDC_ATTR pdcattr, pdcattrSrc;
PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
PSHARED_GET_VALIDATE(pdcattrSrc,hdcSrc,DC_TYPE);
//
// if source DC has DIB section, and destination DC is ICM turned on
// do ICM-aware BitBlt.
//
if (pdcattr && pdcattrSrc)
{
if (IS_ICM_INSIDEDC(pdcattr->lIcmMode) &&
(bDIBSectionSelected(pdcattrSrc) ||
(IS_ICM_LAZY_CORRECTION(pdcattrSrc->lIcmMode) && (GetDCDWord(hdc,DDW_ISMEMDC,FALSE) == FALSE))))
{
if (IcmStretchBlt(hdc,x,y,cx,cy,hdcSrc,x1,y1,cx1,cy1,rop,pdcattr,pdcattrSrc))
{
return (TRUE);
}
}
}
}
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return (MF16_StretchBlt(hdc,x,y,cx,cy,hdcSrc,x1,y1,cx1,cy1,rop));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if (!MF_AnyBitBlt(hdc,x,y,cx,cy,(LPPOINT)NULL,hdcSrc,x1,y1,cx1,cy1,(HBITMAP)NULL,0,0,rop,EMR_STRETCHBLT))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
return(NtGdiStretchBlt(hdc,x,y,cx,cy,hdcSrc,x1,y1,cx1,cy1,rop,(COLORREF)-1));
}
/******************************Public*Routine******************************\
* PlgBlt *
* *
* Client side stub. Copies all LDC attributes into the message. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI PlgBlt(
HDC hdc,
CONST POINT *pptl,
HDC hdcSrc,
int x1,
int y1,
int x2,
int y2,
HBITMAP hbm,
int xMask,
int yMask
)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
FIXUP_HANDLEZ(hdcSrc);
FIXUP_HANDLEZ(hbm);
// Check out the source DC and the mask(OPTIONAL).
if (!hdcSrc || IS_METADC16_TYPE(hdcSrc))
return(FALSE);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return(FALSE);
DC_PLDC(hdc,pldc,bRet);
if ((pldc->iType == LO_METADC) &&
!MF_AnyBitBlt(hdc,0,0,0,0,pptl,hdcSrc,x1,y1,x2,y2,hbm,xMask,yMask,0xCCAA0000,EMR_PLGBLT))
{
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
return(NtGdiPlgBlt(hdc,(POINT *)pptl,hdcSrc,x1,y1,x2,y2,hbm,xMask,yMask,
GetBkColor(hdcSrc)));
}
/******************************Public*Routine******************************\
* MaskBlt *
* *
* Client side stub. Copies all LDC attributes into the message. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI MaskBlt(
HDC hdc,
int x,
int y,
int cx,
int cy,
HDC hdcSrc,
int x1,
int y1,
HBITMAP hbm,
int x2,
int y2,
DWORD rop
)
{
BOOL bRet = FALSE;
ULONG crBackColor;
FIXUP_HANDLE(hdc);
FIXUP_HANDLEZ(hdcSrc);
FIXUP_HANDLEZ(hbm);
// Check out the source DC and the mask(OPTIONAL).
if (!hdcSrc || IS_METADC16_TYPE(hdcSrc))
return(FALSE);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return(FALSE);
DC_PLDC(hdc,pldc,bRet);
if ((pldc->iType == LO_METADC) &&
!MF_AnyBitBlt(hdc,x,y,cx,cy,(LPPOINT)NULL,hdcSrc,x1,y1,cx,cy,hbm,x2,y2,rop,EMR_MASKBLT))
{
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
crBackColor = GetBkColor(hdcSrc);
RESETUSERPOLLCOUNT();
// WINBUG #82879 2-7-2000 bhouse Possible bug in MaskBlt
// Old Comment:
// - GetBkColor should be performed in the kernel
// Not a problem. GetBkColor() picks up the color from the PEB DCattr cache.
return(NtGdiMaskBlt(hdc,x,y,cx,cy,hdcSrc,x1,y1,hbm,x2,y2,rop,crBackColor));
}
/******************************Public*Routine******************************\
* ExtFloodFill *
* *
* Client side stub. Copies all LDC attributes into the message. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI ExtFloodFill(
HDC hdc,
int x,
int y,
COLORREF color,
UINT iMode
)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return(MF16_RecordParmsWWDW(hdc,(WORD)x,(WORD)y,(DWORD)color,(WORD)iMode,META_EXTFLOODFILL));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if (!MF_ExtFloodFill(hdc,x,y,color,iMode))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
//
// if the specified COLORREF is not palette index,
// we need to do color conversion, when ICM is enabled.
//
if (!(color & 0x01000000))
{
PDC_ATTR pdcattr;
PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
if (pdcattr && bNeedTranslateColor(pdcattr))
{
COLORREF NewColor;
if (IcmTranslateCOLORREF(hdc,pdcattr,color,&NewColor,ICM_FORWARD))
{
color = NewColor;
}
}
}
return(NtGdiExtFloodFill(hdc,x,y,color,iMode));
}
/******************************Public*Routine******************************\
* FloodFill *
* *
* Just passes the call to the more general ExtFloodFill. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL WINAPI FloodFill(HDC hdc,int x,int y,COLORREF color)
{
return(ExtFloodFill(hdc,x,y,color,FLOODFILLBORDER));
}
/******************************Public*Routine******************************\
* PaintRgn *
* *
* Client side stub. Copies all LDC attributes into the message. *
* *
* 23-11-94 -by- Lingyun Wang [lingyunw]
* Now hrgn is server side handle
*
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI PaintRgn(HDC hdc,HRGN hrgn)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
FIXUP_HANDLE(hrgn);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return(MF16_DrawRgn(hdc,hrgn,(HBRUSH)0,0,0,META_PAINTREGION));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if (!MF_InvertPaintRgn(hdc,hrgn,EMR_PAINTRGN))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
return(NtGdiFillRgn(hdc,hrgn,(HBRUSH)GetDCObject(hdc,LO_BRUSH_TYPE)));
}
/******************************Public*Routine******************************\
* bBatchTextOut
*
* Attempt to batch a textout call on TEB
*
* Arguments:
*
*
*
* Return Value:
*
* TRUE means call is batched, FALSE means call could not be batched
*
* 18-Oct-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
//
// full DWORDS!
//
#define MAX_BATCH_CCHAR ((GDI_BATCH_SIZE - sizeof(BATCHTEXTOUT)) & 0xfffffff0)
#define MAX_BATCH_WCHAR MAX_BATCH_CCHAR / 2
BOOL
bBatchTextOut(
HDC hdc,
LONG x,
LONG y,
UINT fl,
CONST RECT *prcl,
LPCWSTR pwsz,
CONST INT *pdx,
UINT UnicodeCharCount,
UINT ByteCount,
DWORD dwCodePage
)
{
BOOL bRet = FALSE;
ULONG AlignedByteCount;
USHORT usSize;
ULONG cjPdx;
PDC_ATTR pdca;
AlignedByteCount =
(ByteCount + sizeof(PVOID) - 1) & ~(sizeof(PVOID)-1);
if( AlignedByteCount < ByteCount )
goto UNBATCHED_COMMAND; // arithmetic overflow
//
// account for pdx space if needed
//
if (pdx != NULL)
{
cjPdx = UnicodeCharCount * sizeof(INT);
if (fl & ETO_PDY)
cjPdx *= 2;
if ((AlignedByteCount+cjPdx) < AlignedByteCount
|| BALLOC_OVERFLOW1(UnicodeCharCount,INT))
goto UNBATCHED_COMMAND; // arithmetic overflow
AlignedByteCount += cjPdx;
}
usSize = (USHORT)(sizeof(BATCHTEXTOUT) + AlignedByteCount);
if (usSize < AlignedByteCount)
goto UNBATCHED_COMMAND; // arithmetic overflow
PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
BEGIN_BATCH_HDC_SIZE(hdc,pdca,BatchTypeTextOut,BATCHTEXTOUT,usSize);
if (pdca->lTextAlign & TA_UPDATECP)
{
goto UNBATCHED_COMMAND;
}
pBatch->TextColor = (ULONG)pdca->crForegroundClr;
pBatch->BackColor = (ULONG)pdca->crBackgroundClr;
pBatch->BackMode = (ULONG)((pdca->lBkMode == OPAQUE) ? OPAQUE : TRANSPARENT);
pBatch->ulTextColor = pdca->ulForegroundClr;
pBatch->ulBackColor = pdca->ulBackgroundClr;
pBatch->x = x;
pBatch->y = y;
pBatch->fl = fl;
pBatch->cChar = UnicodeCharCount;
pBatch->PdxOffset = 0;
pBatch->dwCodePage = dwCodePage;
pBatch->hlfntNew = pdca->hlfntNew;
pBatch->flTextAlign = pdca->flTextAlign;
pBatch->ptlViewportOrg = pdca->ptlViewportOrg;
//
// copy output RECT if needed
//
if (prcl != NULL)
{
pBatch->rcl.left = prcl->left;
pBatch->rcl.top = prcl->top;
pBatch->rcl.right = prcl->right;
pBatch->rcl.bottom = prcl->bottom;
}
else
{
pBatch->fl |= ETO_NULL_PRCL;
}
//
// copy characters
//
if (ByteCount)
{
RtlCopyMemory((PUCHAR)&pBatch->ulBuffer[0],(PUCHAR)pwsz,ByteCount);
}
//
// copy pdx array
//
if (pdx != NULL)
{
//
// start pdx at INT aligned offset after WCAHR data
//
pBatch->PdxOffset = (ByteCount + 3) & 0xfffffffc;
RtlCopyMemory((PUCHAR)&pBatch->ulBuffer[0] + pBatch->PdxOffset,
(PUCHAR)pdx,
cjPdx);
}
bRet = TRUE;
COMPLETE_BATCH_COMMAND();
UNBATCHED_COMMAND:
return(bRet);
}
/******************************Public*Routine******************************\
*
* BOOL META WINAPI ExtTextOutW
*
* similar to traditional ExtTextOut, except that it takes UNICODE string
*
* History:
* Thu 28-Apr-1994 -by- Patrick Haluptzok [patrickh]
* Special Case 0 char case for Winbench4.0
*
* 05-Aug-1991 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL META WINAPI ExtTextOutW(
HDC hdc,
int x,
int y,
UINT fl,
CONST RECT *prcl,
LPCWSTR pwsz,
UINT c, // count of bytes = 2 * (# of WCHAR's)
CONST INT *pdx
)
{
BOOL bRet = FALSE;
BOOL bEMFDriverComment = FALSE;
if ((fl & ETO_PDY) && !pdx)
return FALSE;
// if we do not know what to do with the rectangle, ignore it.
if (prcl && !(fl & (ETO_OPAQUE | ETO_CLIPPED)))
{
prcl = NULL;
}
if (!prcl)
{
fl &= ~(ETO_CLIPPED | ETO_OPAQUE); // ignore flags if no rect, win95 compat
}
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return (MF16_ExtTextOut(hdc,x,y,fl,prcl,(LPCSTR)pwsz,c,pdx,TRUE));
DC_PLDC(hdc,pldc,bRet);
// if we are EMF spooling then metafile glyph index calls, otherwise don't
// if we are EMF spooling then metafile glyph index calls, otherwise don't
/*
LDC_META_PRINT ETO_GLYPH_INDEX ETO_IGNORELANGUAGE gbLpk MetaFileTheCall
0 0 0 0 1
0 0 0 1 1
0 0 1 0 1
Case1 0 0 1 1 0
Case2 0 1 0 0 0
0 1 0 1 1 <-Win95 Compatability
Case2 0 1 1 0 0
0 1 1 1 1 <-Win95 Compatability
1 0 0 0 1
Case3 1 0 0 1 0
1 0 1 0 1
1 0 1 1 1
1 1 0 0 1
1 1 0 1 1
1 1 1 0 1
1 1 1 1 1
*/
// Now we will metafile the glyph index call (i.e. with ETO_GLYPH_INDEX) for ExtTextOutW.
// This is to support MS OutLook-97/BiDi, since it DEPENDS on this feature!!. Win95/BiDi allowed
// metafiling of GIs on ETOW, but rejects GIs metafiling calls to ETOA.
// This is not neat, but we have to do it to support our Apps.
if (pldc->iType == LO_METADC)
{
BOOL bPrintToEMFDriver = pldc->pUMPD ? pldc->pUMPD->dwFlags & UMPDFLAG_METAFILE_DRIVER : FALSE;
BOOL bLpkEmfCase1 = !(pldc->fl & LDC_META_PRINT) &&
!(fl & ETO_GLYPH_INDEX) &&
(fl & ETO_IGNORELANGUAGE) &&
gbLpk;
BOOL bLpkEmfCase2 = !(pldc->fl & LDC_META_PRINT) &&
(fl & ETO_GLYPH_INDEX) &&
!gbLpk;
BOOL bLpkEmfCase3 = (pldc->fl & LDC_META_PRINT) &&
!(fl & ETO_GLYPH_INDEX) &&
!(fl & ETO_IGNORELANGUAGE) &&
gbLpk;
// Record a special comment containing the original
// Unicode string for the ExtTextOutW call
if (bLpkEmfCase3 && bPrintToEMFDriver)
{
ULONG nSize = 3*sizeof(DWORD) + c*sizeof(WCHAR);
DWORD *lpData;
// double check that we didn't have an arithmetic overflow
// in the calculation of nSize -- if so, lpData can have
// a buffer overflow
if( c >= (MAXIMUM_POOL_ALLOC - 3*sizeof(DWORD) - 3)/sizeof(WCHAR))
{
GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
lpData = LOCALALLOC(ROUNDUP_DWORDALIGN(nSize));
if (lpData)
{
lpData[0] = GDICOMMENT_IDENTIFIER;
lpData[1] = GDICOMMENT_UNICODE_STRING;
lpData[2] = c; // number of wchars in the unicode string
RtlCopyMemory((PBYTE)(lpData+3), pwsz, c*sizeof(WCHAR));
if (!MF_GdiComment(hdc,nSize,(PBYTE)lpData))
{
LOCALFREE(lpData);
return bRet;
}
LOCALFREE(lpData);
bEMFDriverComment = TRUE;
}
}
if (!bLpkEmfCase1 && !bLpkEmfCase2 && !bLpkEmfCase3 &&
!MF_ExtTextOut(hdc,x,y,fl,prcl,(LPCSTR) pwsz,c,pdx,EMR_EXTTEXTOUTW))
{
return(bRet);
}
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
#ifdef LANGPACK
if(gbLpk && !(fl & ETO_GLYPH_INDEX) && !(fl & ETO_IGNORELANGUAGE))
{
bRet = ((*fpLpkExtTextOut)(hdc, x, y, fl, prcl, pwsz, c, pdx, -1));
if (bEMFDriverComment)
{
DWORD lpData[2];
lpData[0] = GDICOMMENT_IDENTIFIER;
lpData[1] = GDICOMMENT_UNICODE_END;
bRet = MF_GdiComment(hdc,2*sizeof(DWORD),(PBYTE)lpData);
ASSERTGDI(bRet, "failed to write the GDICOMMENT_UNICODE_END comment\n");
}
return(bRet);
}
#endif
bRet = FALSE;
if (c <= MAX_BATCH_WCHAR)
{
if ((c == 0) && (prcl != NULL))
{
if (fl & ETO_OPAQUE)
{
//
// attempt to batch the text out rect
//
PDC_ATTR pdca;
PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
if ((pdca != NULL) && !(pdca->lTextAlign & TA_UPDATECP))
{
BEGIN_BATCH_HDC(hdc,pdca,BatchTypeTextOutRect,BATCHTEXTOUTRECT);
pBatch->BackColor = pdca->crBackgroundClr;
pBatch->fl = fl;
pBatch->rcl.left = prcl->left;
pBatch->rcl.top = prcl->top;
pBatch->rcl.right = prcl->right;
pBatch->rcl.bottom = prcl->bottom;
pBatch->ptlViewportOrg = pdca->ptlViewportOrg;
pBatch->ulBackColor = pdca->ulBackgroundClr;
bRet = TRUE;
COMPLETE_BATCH_COMMAND();
}
}
else
{
bRet = TRUE;
}
}
else
{
bRet = bBatchTextOut(hdc,
x,
y,
fl,
(LPRECT)prcl,
(LPWSTR)pwsz,
pdx,
c,
2 * c,
0);
}
}
UNBATCHED_COMMAND:
if (!bRet)
{
bRet = NtGdiExtTextOutW(hdc,
x,
y,
fl,
(LPRECT)prcl,
(LPWSTR)pwsz,
c,
(LPINT)pdx,
0);
}
return(bRet);
}
/******************************Public*Routine******************************\
* PolyTextOutW
*
* Arguments:
*
* hdc - handle to device context
* ppt - pointer to array of POLYTEXTW
* nstrings - length of POLYTEXTW array
*
* Return Value:
*
* status
*
* History:
* 7/31/92 -by- Paul Butzi and Eric Kutter
*
\**************************************************************************/
BOOL META WINAPI PolyTextOutW(HDC hdc,CONST POLYTEXTW *ppt,INT nstrings)
{
BOOL bRet = FALSE;
CONST POLYTEXTW *pp;
FIXUP_HANDLE(hdc);
if (nstrings == 0)
{
bRet = TRUE;
}
else if (nstrings < 0)
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
bRet = FALSE;
}
else
{
//
// Search for error case with string with non-0 length but sting == NULL
//
for ( pp = ppt; pp < (ppt + nstrings); pp += 1 )
{
if ( pp->lpstr == NULL)
{
//
// return failure if they have a non 0 length string with NULL
//
if (pp->n != 0)
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
}
}
//
// If we need to metafile, or print
//
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
{
return (
MF16_PolyTextOut(
hdc,
(CONST POLYTEXTA*) ppt,
nstrings,
TRUE // mrType == EMR_POLYTEXTOUTW
)
);
}
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if
(
!MF_PolyTextOut(
hdc,
(CONST POLYTEXTA*) ppt,
nstrings,
EMR_POLYTEXTOUTW
)
)
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
{
vSAPCallback(pldc);
}
if (pldc->fl & LDC_DOC_CANCELLED)
{
return(bRet);
}
if (pldc->fl & LDC_CALL_STARTPAGE)
{
StartPage(hdc);
}
}
bRet = NtGdiPolyTextOutW(hdc,(POLYTEXTW *)ppt,nstrings, 0);
}
return(bRet);
}
/******************************Public*Routine******************************\
* PolyTextOutA
*
* Arguments:
*
* hdc - handle to device context
* ppt - pointer to array of POLYTEXTA
* nstrings - length of POLYTEXTA array
*
* Return Value:
*
* status
*
* History:
* 7/31/92 -by- Paul Butzi and Eric Kutter
*
\**************************************************************************/
BOOL META WINAPI PolyTextOutA(HDC hdc, CONST POLYTEXTA *ppt, INT nstrings)
{
//
// Convert text to UNICODE and make call
//
POLYTEXTW *pp, *pPolyTextW;
UINT szTotal = 0;
INT cjdx;
BOOL bRet = FALSE;
BOOL bDBCSCodePage;
int i;
PVOID pCharBuffer;
PBYTE pj;
DWORD dwCodePage;
FIXUP_HANDLE(hdc);
if (nstrings == 0)
{
return(TRUE);
}
if (nstrings < 0)
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
//
// Figure out the size needed
//
pPolyTextW = (POLYTEXTW*) ppt;
if( BALLOC_OVERFLOW1(nstrings,POLYTEXTW) )
{
GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
szTotal = sizeof(POLYTEXTW) * nstrings;
for ( pp = pPolyTextW; pp < (pPolyTextW + nstrings); pp ++)
{
if (pp->lpstr != NULL)
{
if( BALLOC_OVERFLOW1(pp->n,WCHAR)
|| (szTotal + pp->n*sizeof(WCHAR)) < szTotal )
{
GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
szTotal += pp->n * sizeof(WCHAR);
if ( pp->pdx != NULL )
{
cjdx = pp->n * sizeof(int);
if (pp->uiFlags & ETO_PDY)
cjdx *= 2;
if( (szTotal + cjdx) < szTotal )
{
GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
szTotal += cjdx;
}
}
else
{
//
// return failure if they have a non 0 length string with NULL
//
if (pp->n != 0)
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
}
}
//
// If we need to metafile, or print
//
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
{
return (
MF16_PolyTextOut(
hdc,
(CONST POLYTEXTA*) pPolyTextW,
nstrings,
FALSE
)
);
}
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if
(
!MF_PolyTextOut(
hdc,
(CONST POLYTEXTA*) pPolyTextW,
nstrings,
EMR_POLYTEXTOUTA
)
)
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
{
vSAPCallback(pldc);
}
if (pldc->fl & LDC_DOC_CANCELLED)
{
return(bRet);
}
if (pldc->fl & LDC_CALL_STARTPAGE)
{
StartPage(hdc);
}
}
//
// alloc memory for WHCAR structures
//
pCharBuffer = LOCALALLOC(szTotal);
if (pCharBuffer == NULL)
{
return(FALSE);
}
RtlCopyMemory(pCharBuffer, (PBYTE) pPolyTextW, nstrings*sizeof(POLYTEXTW));
pp = (POLYTEXTW *)pCharBuffer;
//
// now copy the stuff into the buffer
//
pj = (PBYTE)pCharBuffer + nstrings*sizeof(POLYTEXTW);
dwCodePage = GetCodePage(hdc);
bDBCSCodePage = IS_ANY_DBCS_CODEPAGE(dwCodePage);
for ( i = 0; i < nstrings; i += 1 )
{
if ((pp[i].pdx != NULL) && (pp[i].lpstr != NULL))
{
// patch pdx
cjdx = pp[i].n * sizeof(INT);
if (pp[i].uiFlags & ETO_PDY)
cjdx *= 2;
if(bDBCSCodePage)
{
ConvertDxArray(dwCodePage,
(char*) pp[i].lpstr,
pp[i].pdx,
pp[i].n,
(int*) pj,
pp[i].uiFlags & ETO_PDY
);
}
else
{
RtlCopyMemory(pj,pp[i].pdx,cjdx);
}
pp[i].pdx = (int *)pj;
pj += cjdx;
}
}
for ( i = 0; i < nstrings; i += 1 )
{
if ( pp[i].lpstr != NULL )
{
pp[i].n = MultiByteToWideChar(dwCodePage,
0,
(LPSTR) pp[i].lpstr,
pp[i].n, (LPWSTR) pj,
pp[i].n*sizeof(WCHAR));
// patch lpstr
pp[i].lpstr = (LPWSTR)pj;
pj += pp[i].n * sizeof(WCHAR);
}
}
//
// send off the message and cleanup
//
bRet = NtGdiPolyTextOutW(hdc,(POLYTEXTW *)pCharBuffer,nstrings,dwCodePage);
LOCALFREE(pCharBuffer);
return(bRet);
}
/******************************Public*Routine******************************\
*
* BOOL META WINAPI TextOutW
*
*
*
* History:
* 07-Aug-1991 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL META WINAPI TextOutW(
HDC hdc,
int x,
int y,
LPCWSTR pwsz,
int c
)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if ((c <= 0) || (pwsz == (LPCWSTR) NULL))
{
if (c == 0)
return(TRUE);
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return(MF16_TextOut(hdc,x,y,(LPCSTR) pwsz,c,TRUE));
DC_PLDC(hdc,pldc,bRet);
if((pldc->iType == LO_METADC) &&
(!(pldc->fl & LDC_META_PRINT) || !gbLpk))
{
if (!MF_ExtTextOut(hdc,x,y,0,(LPRECT)NULL,(LPCSTR) pwsz,c,(LPINT)NULL,EMR_EXTTEXTOUTW))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
#ifdef LANGPACK
if(gbLpk)
{
return((*fpLpkExtTextOut)(hdc, x, y, 0, NULL, pwsz, c, 0, -1));
}
#endif
if ((c <= MAX_BATCH_WCHAR) && (GdiBatchLimit > 1))
{
bRet = bBatchTextOut(hdc,
x,
y,
0,
(LPRECT)NULL,
(LPWSTR)pwsz,
NULL,
c,
2 *c,
0);
}
if (!bRet)
{
bRet = NtGdiExtTextOutW(hdc,
x,
y,
0,
0,
(LPWSTR)pwsz,
c,
0,
0);
}
return(bRet);
}
/******************************Public*Routine******************************\
*
* DWORD GetCodePage(HDC hdc)
*
* Effects: returns the code page of the font selected in the dc
*
* History:
* 23-May-1995 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
DWORD GetCodePage(HDC hdc)
{
PDC_ATTR pDcAttr;
FIXUP_HANDLE(hdc);
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (pDcAttr)
{
if (!(pDcAttr->ulDirty_ & DIRTY_CHARSET))
return (0x0000ffff & pDcAttr->iCS_CP); // mask charset
}
else
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return guintAcp; // reasonable default;
}
// we end up here if the code page attributes are dirty so that
// we have to call to the kernel, force the mapping and retrieve
// the code page and char set of the font selected in the dc:
return (0x0000ffff & NtGdiGetCharSet(hdc)); // mask charset
}
/******************************Public*Routine******************************\
*
* BOOL META WINAPI ExtTextOutA
* History:
* 07-Aug-1991 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
#define CAPTURE_STRING_SIZE 130
// not in kernel, it is ok to do this much on the stack
BOOL META WINAPI ExtTextOutInternalA(
HDC hdc,
int x,
int y,
UINT fl,
CONST RECT *prcl,
LPCSTR psz,
UINT c,
CONST INT *pdx,
BOOL bFromTextOut
)
{
BOOL bRet = FALSE;
DWORD dwCodePage;
BOOL bDBCSCodePage;
if ((fl & ETO_PDY) && !pdx)
return FALSE;
// if we do not know what to do with the rectangle, ignore it.
if (prcl && !(fl & (ETO_OPAQUE | ETO_CLIPPED)))
{
prcl = NULL;
}
if (!prcl)
{
fl &= ~(ETO_CLIPPED | ETO_OPAQUE); // ignore flags if no rect, win95 compat
}
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
{
if(bFromTextOut)
{
// yes this matters, some apps rely on TextOutA being metafiled at
// TextOut and not ExtTextOutA
return(MF16_TextOut(hdc,x,y,psz,c,FALSE));
}
else
{
return (MF16_ExtTextOut(hdc,x,y,fl,prcl,psz,c,pdx,FALSE));
}
}
DC_PLDC(hdc,pldc,bRet);
// if we are EMF spooling then metafile glyph index calls, otherwise don't
if((pldc->iType == LO_METADC) &&
(!((!(pldc->fl & LDC_META_PRINT) && (fl & ETO_GLYPH_INDEX)) ||
((pldc->fl & LDC_META_PRINT) && !(fl & ETO_GLYPH_INDEX) && (gbLpk) && !(fl & ETO_IGNORELANGUAGE) && c)) ||
(!(pldc->fl & LDC_META_PRINT) && (!(fl & ETO_GLYPH_INDEX)) && (fl & ETO_IGNORELANGUAGE) && (gbLpk))
)
)
{
DWORD mrType = (fl & ETO_GLYPH_INDEX) ?
EMR_EXTTEXTOUTW :
EMR_EXTTEXTOUTA ;
if (!MF_ExtTextOut(hdc,x,y,fl,prcl,psz,c, pdx, mrType))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
if (fl & ETO_GLYPH_INDEX)
{
bRet = FALSE;
if ((c <= MAX_BATCH_WCHAR) && (GdiBatchLimit > 1))
{
bRet = bBatchTextOut(hdc,
x,
y,
fl,
(LPRECT)prcl,
(LPWSTR)psz,
pdx,
c,
2*c,
0);
}
if (!bRet)
{
bRet = NtGdiExtTextOutW(hdc,
x,y,
fl, (LPRECT)prcl,
(LPWSTR)psz, (int)c,
(LPINT)pdx, 0);
}
return(bRet);
}
// Get code page
dwCodePage = GetCodePage(hdc);
if(fFontAssocStatus)
{
dwCodePage = FontAssocHack(dwCodePage,(char*)psz,c);
}
bDBCSCodePage = IS_ANY_DBCS_CODEPAGE(dwCodePage);
if (c)
{
// get the code page of the font selected in the dc
WCHAR awcCaptureBuffer[CAPTURE_STRING_SIZE];
PWSZ pwszCapt;
INT aiDxCaptureBuffer[CAPTURE_STRING_SIZE*2]; // times 2 for pdy
INT *pDxCapture;
// Allocate the string buffer
if (c <= CAPTURE_STRING_SIZE)
{
pwszCapt = awcCaptureBuffer;
}
else
{
if(bDBCSCodePage)
{
pwszCapt =
((c+1) >= MAXIMUM_POOL_ALLOC/(sizeof(WCHAR)+2*sizeof(INT)))
? (PWSZ) 0
: LOCALALLOC((c+1) * (sizeof(WCHAR)+ 2 * sizeof(INT)));
pDxCapture = (INT*) &pwszCapt[(c+1)&~1]; // ^
} // |
else // for pdy, just in case
{
pwszCapt = BALLOC_OVERFLOW1(c,WCHAR)
? ((PWSZ) 0) : LOCALALLOC(c * sizeof(WCHAR));
}
}
if (pwszCapt)
{
UINT u;
if(bDBCSCodePage && pdx)
{
if(c <= CAPTURE_STRING_SIZE)
{
pDxCapture = aiDxCaptureBuffer;
}
ConvertDxArray(dwCodePage,(char*) psz,(int*) pdx,c,pDxCapture, fl & ETO_PDY);
}
else
{
pDxCapture = (int*) pdx;
}
u = MultiByteToWideChar(
dwCodePage, 0,
psz,c,
pwszCapt, c*sizeof(WCHAR));
if (u)
{
bRet = FALSE;
#ifdef LANGPACK
if (gbLpk && !(fl & ETO_IGNORELANGUAGE))
{
bRet = ((*fpLpkExtTextOut)(hdc, x, y, fl, prcl, pwszCapt,
u, pDxCapture, 0));
if (pwszCapt != awcCaptureBuffer)
LOCALFREE(pwszCapt);
return bRet;
}
#endif
if ((c <= MAX_BATCH_WCHAR) && (GdiBatchLimit > 1))
{
bRet = bBatchTextOut(hdc,
x,
y,
fl,
(LPRECT)prcl,
(LPWSTR)pwszCapt,
pDxCapture,
u,
2 * u,
dwCodePage
);
}
if (!bRet)
{
bRet = NtGdiExtTextOutW(
hdc,
x,y,
fl, (LPRECT)prcl,
(LPWSTR)pwszCapt,(int)u,
pDxCapture,
dwCodePage);
}
}
if (pwszCapt != awcCaptureBuffer)
LOCALFREE(pwszCapt);
}
else
{
GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
}
else
{
bRet = FALSE;
if ((prcl != NULL) && (fl & ETO_OPAQUE))
{
//
// try to batch text out rect
//
PDC_ATTR pdca;
PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
if ((pdca != NULL) && !(pdca->lTextAlign & TA_UPDATECP))
{
BEGIN_BATCH_HDC(hdc,pdca,BatchTypeTextOutRect,BATCHTEXTOUTRECT);
pBatch->BackColor = pdca->crBackgroundClr;
pBatch->fl = fl;
pBatch->rcl.left = prcl->left;
pBatch->rcl.top = prcl->top;
pBatch->rcl.right = prcl->right;
pBatch->rcl.bottom = prcl->bottom;
pBatch->ptlViewportOrg = pdca->ptlViewportOrg;
bRet = TRUE;
COMPLETE_BATCH_COMMAND();
}
}
UNBATCHED_COMMAND:
if (!bRet)
{
bRet = NtGdiExtTextOutW(hdc,
x,y,
fl,
(LPRECT)prcl,
NULL,0,NULL,dwCodePage);
}
}
return(bRet);
}
BOOL META WINAPI ExtTextOutA(
HDC hdc,
int x,
int y,
UINT fl,
CONST RECT *prcl,
LPCSTR psz,
UINT c,
CONST INT *pdx
)
{
return(ExtTextOutInternalA(hdc,x,y,fl,prcl,psz,c,pdx,FALSE));
}
/******************************Public*Routine******************************\
*
* BOOL META WINAPI TextOut
*
* History:
* 07-Aug-1991 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL META WINAPI TextOutA(
HDC hdc,
int x,
int y,
LPCSTR psz,
int c
)
{
BOOL bRet = FALSE;
if ((c <= 0) || (psz == (LPCSTR) NULL))
{
if (c == 0)
return(TRUE);
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
return ExtTextOutInternalA(hdc, x, y, 0, NULL, psz, c, NULL, TRUE);
}
/******************************Public*Routine******************************\
* FillRgn *
* *
* Client side stub. Copies all LDC attributes into the message. *
*
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI FillRgn(HDC hdc,HRGN hrgn,HBRUSH hbrush)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
FIXUP_HANDLE(hrgn);
FIXUP_HANDLE(hbrush);
// validate the region and brush.
if (!hrgn || !hbrush)
return(bRet);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return(MF16_DrawRgn(hdc,hrgn,hbrush,0,0,META_FILLREGION));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if (!MF_FillRgn(hdc,hrgn,hbrush))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
return(NtGdiFillRgn(hdc,hrgn,hbrush));
}
/******************************Public*Routine******************************\
* FrameRgn *
* *
* Client side stub. Copies all LDC attributes into the message. *
*
* 23-11-94 -by- Lingyun Wang [lingyunw]
* Now hrgn and hbrush are server side handles
*
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI FrameRgn(
HDC hdc,
HRGN hrgn,
HBRUSH hbrush,
int cx,
int cy
)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
FIXUP_HANDLE(hrgn);
FIXUP_HANDLE(hbrush);
if (!hrgn || !hbrush)
return(FALSE);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return(MF16_DrawRgn(hdc,hrgn,hbrush,cx,cy,META_FRAMEREGION));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if (!MF_FrameRgn(hdc,hrgn,hbrush,cx,cy))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
return(NtGdiFrameRgn(hdc,hrgn,hbrush,cx,cy));
}
/******************************Public*Routine******************************\
* InvertRgn *
* *
* Client side stub. *
*
* 23-11-94 -by- Lingyun Wang [lingyunw]
* Now hrgn is server side handle
*
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI InvertRgn(HDC hdc,HRGN hrgn)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
FIXUP_HANDLE(hrgn);
if (!hrgn)
return(FALSE);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return(MF16_DrawRgn(hdc,hrgn,(HBRUSH)0,0,0,META_INVERTREGION));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if (!MF_InvertPaintRgn(hdc,hrgn,EMR_INVERTRGN))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
return(NtGdiInvertRgn(hdc,hrgn));
}
/******************************Public*Routine******************************\
* SetPixelV *
* *
* Client side stub. This is a version of SetPixel that does not return a *
* value. This one can be batched for better performance. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL META WINAPI SetPixelV(HDC hdc,int x,int y,COLORREF color)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return(MF16_RecordParmsWWD(hdc,(WORD)x,(WORD)y,(DWORD)color,META_SETPIXEL));
DC_PLDC(hdc,pldc,bRet);
if (pldc->iType == LO_METADC)
{
if (!MF_SetPixelV(hdc,x,y,color))
return(bRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(bRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
//
// ICM conversion (only happen for non-palette index color)
//
if (!(color & 0x01000000))
{
PDC_ATTR pdca;
PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
if (pdca && bNeedTranslateColor(pdca))
{
COLORREF NewColor;
if (IcmTranslateCOLORREF(hdc,pdca,color,&NewColor,ICM_FORWARD))
{
color = NewColor;
}
}
}
return(NtGdiSetPixel(hdc,x,y,color) != CLR_INVALID);
}
/******************************Public*Routine******************************\
* SetPixel *
* *
* Client side stub. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
COLORREF META WINAPI SetPixel(HDC hdc,int x,int y,COLORREF color)
{
ULONG iRet = CLR_INVALID;
COLORREF ColorRet = CLR_INVALID;
COLORREF NewColor;
BOOL bStatus;
PDC_ATTR pdca;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return(MF16_RecordParmsWWD(hdc,(WORD)x,(WORD)y,(DWORD)color,META_SETPIXEL));
DC_PLDC(hdc,pldc,iRet);
if (pldc->iType == LO_METADC)
{
if (!MF_SetPixelV(hdc,x,y,color))
return(iRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(iRet);
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
RESETUSERPOLLCOUNT();
PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
if (pdca)
{
//
// if the color is not a PaletteIndex and ICM is on then translate
//
if (!(color & 0x01000000) && bNeedTranslateColor(pdca))
{
bStatus = IcmTranslateCOLORREF(hdc,
pdca,
color,
&NewColor,
ICM_FORWARD);
if (bStatus)
{
color = NewColor;
}
}
ColorRet = NtGdiSetPixel(hdc,x,y,color);
if ( bNeedTranslateColor(pdca)
&&
( IS_32BITS_COLOR(pdca->lIcmMode)
||
((ColorRet != CLR_INVALID) &&
!(ColorRet & 0x01000000))
)
)
{
//
// Translate back to original color
//
bStatus = IcmTranslateCOLORREF(hdc,
pdca,
ColorRet,
&NewColor,
ICM_BACKWARD);
if (bStatus)
{
ColorRet = NewColor;
}
}
}
else
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
}
return(ColorRet);
}
/******************************Public*Routine******************************\
* UpdateColors *
* *
* Client side stub. *
* *
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL WINAPI UpdateColors(HDC hdc)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
RESETUSERPOLLCOUNT();
return(NtGdiUpdateColors(hdc));
}
/******************************Public*Routine******************************\
* GdiFlush *
* *
* Client side stub. *
* *
* Wed 26-Jun-1991 13:58:00 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL WINAPI GdiFlush(VOID)
{
NtGdiFlush();
return(TRUE);
}
/******************************Public*Routine******************************\
* GdiSetBatchLimit
*
*
* History:
* 31-Jul-1991 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
DWORD WINAPI
GdiSetBatchLimit(
DWORD dwNewBatchLimit
)
{
DWORD OldLimit = 0;
//
// set batch limit (as long as it is (1 <= l <= 20))
// return old limit if successful. A new batch limit of 0
// means set to default (20)
//
if (dwNewBatchLimit == 0)
{
dwNewBatchLimit = 20;
}
if ((dwNewBatchLimit > 0 ) && (dwNewBatchLimit <= 20))
{
GdiFlush();
OldLimit = GdiBatchLimit;
GdiBatchLimit = dwNewBatchLimit;
}
return(OldLimit);
}
/******************************Public*Routine******************************\
* GdiGetBatchLimit
*
* History:
* 7-Apr-1992 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
DWORD WINAPI GdiGetBatchLimit()
{
return(GdiBatchLimit);
}
/******************************Public*Routine******************************\
* EndPage
*
* Client side stub.
*
* History:
* Wed 12-Jun-1991 01:02:25 -by- Charles Whitmer [chuckwh]
* Wrote it.
* 9/16/97 - Ramananthan N. Venkatpathy [RamanV]
* Parameterized End Page to handle Form Pages.
\**************************************************************************/
int InternalEndPage(HDC hdc,
DWORD dwPageType)
{
int iRet = SP_ERROR;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc) && !IS_METADC16_TYPE(hdc))
{
PLDC pldc;
DC_PLDC(hdc,pldc,iRet);
//
// If the EndPage() is already called from
// Escape(NEXTBAND), Just return TRUE here.
//
// This will fixed ...
//
// + The KB Q118873 "PRB: EndPage() Returns -1 When Banding"
// + NTRaid #90099 "T1R: Visio 4.1, 16-bit can't print".
//
if( pldc->fl & LDC_CALLED_ENDPAGE )
{
pldc->fl &= ~LDC_CALLED_ENDPAGE;
return((int)TRUE);
}
if( pldc->fl & LDC_META_PRINT )
{
if (dwPageType == NORMAL_PAGE) {
return(MFP_EndPage( hdc ));
} else if (dwPageType == FORM_PAGE) {
return(MFP_EndFormPage( hdc ));;
}
}
if ((pldc->fl & LDC_DOC_CANCELLED) ||
((pldc->fl & LDC_PAGE_STARTED) == 0))
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(iRet);
}
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
pldc->fl &= ~LDC_PAGE_STARTED;
// now call the drivers UI portion
DocumentEventEx(pldc->pUMPD,
pldc->hSpooler,
hdc,
DOCUMENTEVENT_ENDPAGE,
0,
NULL,
0,
NULL);
RESETUSERPOLLCOUNT();
iRet = NtGdiEndPage(hdc);
// if user mode printer, call EndPagePrinter from user mode
if (iRet && pldc->pUMPD)
iRet = EndPagePrinterEx(pldc->pUMPD, pldc->hSpooler);
// For Win31 compatibility, return SP_ERROR for error.
if (!iRet)
iRet = SP_ERROR;
else
pldc->fl |= LDC_CALL_STARTPAGE;
#if PRINT_TIMER
if( bPrintTimer )
{
DWORD tc;
tc = GetTickCount();
DbgPrint("Page took %d.%d seconds to print\n",
(tc - pldc->msStartPage) / 1000,
(tc - pldc->msStartPage) % 1000 );
}
#endif
}
else
{
GdiSetLastError(ERROR_INVALID_HANDLE);
}
return(iRet);
}
int WINAPI EndPage(HDC hdc)
{
return InternalEndPage(hdc, NORMAL_PAGE);
}
int WINAPI EndFormPage(HDC hdc)
{
return InternalEndPage(hdc, FORM_PAGE);
}
/******************************Public*Routine******************************\
* StartPage
*
* Client side stub.
*
* History:
* 31-Jul-1991 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int WINAPI StartPage(HDC hdc)
{
int iRet = SP_ERROR;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc) && !IS_METADC16_TYPE(hdc))
{
PLDC pldc;
DC_PLDC(hdc,pldc,iRet);
#if PRINT_TIMER
pldc->msStartPage = GetTickCount();
#endif
if( pldc->fl & LDC_META_PRINT )
return(MFP_StartPage( hdc ));
pldc->fl &= ~LDC_CALL_STARTPAGE;
pldc->fl &= ~LDC_CALLED_ENDPAGE;
// Do nothing if page has already been started.
if (pldc->fl & LDC_PAGE_STARTED)
return(1);
// now call the drivers UI portion
if (pldc->hSpooler)
{
if (DocumentEventEx(pldc->pUMPD,
pldc->hSpooler,
hdc,
DOCUMENTEVENT_STARTPAGE,
0,
NULL,
0,
NULL) == -1)
{
return(iRet);
}
}
pldc->fl |= LDC_PAGE_STARTED;
RESETUSERPOLLCOUNT();
// If it is UMPD, call StartPagePrinter from user mode
if (pldc->pUMPD)
iRet = StartPagePrinterEx(pldc->pUMPD, pldc->hSpooler);
if (iRet)
{
iRet = NtGdiStartPage(hdc);
}
// For Win31 compatibility, return SP_ERROR for error.
if (!iRet)
{
pldc->fl &= ~LDC_PAGE_STARTED;
EndDoc(hdc);
iRet = SP_ERROR;
SetLastError(ERROR_INVALID_HANDLE);
}
}
else
{
GdiSetLastError(ERROR_INVALID_HANDLE);
}
return(iRet);
}
/******************************Public*Routine******************************\
* StartFormPage
*
* This interface has been added to support watermarks and forms.
*
* History:
* 7/1/97 -- Ramanathan Venkatapathy [RamanV]
*
\**************************************************************************/
int WINAPI StartFormPage(HDC hdc)
{
// Call StartPage. Recording required for watermarks is done in EndFormPage
return StartPage(hdc);
}
/******************************Public*Routine******************************\
* EndDoc
*
* If a thread is created at StartDoc(), terminate it here.
*
* History:
* 31-Jul-1991 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int WINAPI EndDoc(HDC hdc)
{
int iRet = SP_ERROR;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc) && !IS_METADC16_TYPE(hdc))
{
PLDC pldc;
DC_PLDC(hdc,pldc,iRet);
if( pldc->fl & LDC_META_PRINT )
return(MFP_EndDoc( hdc ));
#if PRINT_TIMER
if( bPrintTimer )
{
DWORD tc;
tc = GetTickCount();
DbgPrint("Document took %d.%d seconds to print\n",
(tc - pldc->msStartDoc) / 1000,
(tc - pldc->msStartDoc) % 1000 );
DbgPrint("Peak temporary spool buffer size: %d\n", PeakTempSpoolBuf);
}
#endif
if ((pldc->fl & LDC_DOC_STARTED) == 0)
return(1);
// Call EndPage if the page has been started.
if (pldc->fl & LDC_PAGE_STARTED)
EndPage(hdc);
// now call the drivers UI portion
DocumentEventEx(pldc->pUMPD,
pldc->hSpooler,
hdc,
DOCUMENTEVENT_ENDDOCPRE,
0,
NULL,
0,
NULL);
RESETUSERPOLLCOUNT();
iRet = NtGdiEndDoc(hdc);
//
// call EndDocPrinter from user mode if it is a User Mode Printer
//
if (pldc->pUMPD)
iRet = EndDocPrinterEx(pldc->pUMPD, pldc->hSpooler);
// For Win31 compatibility, return SP_ERROR for error.
if (!iRet)
{
iRet = SP_ERROR;
}
else
{
DocumentEventEx(pldc->pUMPD,
pldc->hSpooler,
hdc,
DOCUMENTEVENT_ENDDOCPOST,
0,
NULL,
0,
NULL);
}
pldc->fl &= ~(LDC_DOC_STARTED | LDC_CALL_STARTPAGE |
LDC_SAP_CALLBACK | LDC_CALLED_ENDPAGE);
}
else
{
GdiSetLastError(ERROR_INVALID_HANDLE);
}
return(iRet);
}
/******************************Public*Routine******************************\
* AbortDoc
*
* Client side stub.
*
* History:
* 02-Apr-1992 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
int WINAPI AbortDoc(HDC hdc)
{
int iRet = SP_ERROR;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc) && !IS_METADC16_TYPE(hdc))
{
PLDC pldc;
DC_PLDC(hdc,pldc,iRet);
if (!(pldc->fl & LDC_DOC_STARTED))
return(1);
// now call the drivers UI portion
DocumentEventEx(pldc->pUMPD,
pldc->hSpooler,
hdc,
DOCUMENTEVENT_ABORTDOC,
0,
NULL,
0,
NULL);
RESETUSERPOLLCOUNT();
if( pldc->fl & LDC_META_PRINT )
{
DeleteEnhMetaFile(UnassociateEnhMetaFile( hdc, FALSE ));
DeleteEMFSpoolData(pldc);
//
// bug 150446: calling fpAbortPrinter before deleting the
// EMF file might cause EMF file leak.
//
iRet = (*fpAbortPrinter)( pldc->hSpooler );
}
else
{
iRet = NtGdiAbortDoc(hdc);
// call AbortPrinter from user mode if it is UMPD
if (iRet && pldc->pUMPD)
iRet = AbortPrinterEx(pldc, FALSE);
}
// For Win31 compatibility, return SP_ERROR for error.
if (!iRet)
iRet = SP_ERROR;
// turn off the flags
pldc->fl &= ~(LDC_DOC_STARTED | LDC_PAGE_STARTED | LDC_CALL_STARTPAGE |
LDC_SAP_CALLBACK | LDC_META_PRINT | LDC_CALLED_ENDPAGE);
}
else
{
GdiSetLastError(ERROR_INVALID_HANDLE);
}
return(iRet);
}
/******************************Public*Routine******************************\
* StartDocA
*
* Client side stub.
*
* History:
*
* 21-Mar-1995 -by- Mark Enstrom [marke]
* Change to call StartDocW for kmode
*
* 31-Jul-1991 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
ULONG ulToASCII_N(LPSTR psz, DWORD cbAnsi, LPWSTR pwsz, DWORD c);
int WINAPI StartDocA(HDC hdc, CONST DOCINFOA * pDocInfo)
{
DOCINFOW DocInfoW;
WCHAR wDocName[MAX_PATH];
WCHAR wOutput[MAX_PATH];
WCHAR wDataType[MAX_PATH];
int Length;
DocInfoW.cbSize = sizeof(DOCINFOW);
DocInfoW.lpszDocName = NULL;
DocInfoW.lpszOutput = NULL;
DocInfoW.lpszDatatype = NULL;
DocInfoW.fwType = 0;
if (pDocInfo)
{
if (pDocInfo->lpszDocName)
{
Length = strlen(pDocInfo->lpszDocName)+1;
if (Length > MAX_PATH)
{
ERROR_ASSERT(FALSE, "StartDocA lpszDocName Too long");
GdiSetLastError(ERROR_FILENAME_EXCED_RANGE);
return(SP_ERROR);
}
DocInfoW.lpszDocName = &wDocName[0];
vToUnicodeN(DocInfoW.lpszDocName,MAX_PATH,pDocInfo->lpszDocName,Length);
}
if (pDocInfo->lpszOutput)
{
Length = strlen(pDocInfo->lpszOutput)+1;
if (Length > MAX_PATH)
{
ERROR_ASSERT(FALSE, "StartDocA lpszOutput Too long");
GdiSetLastError(ERROR_FILENAME_EXCED_RANGE);
return(SP_ERROR);
}
DocInfoW.lpszOutput = &wOutput[0];
vToUnicodeN(DocInfoW.lpszOutput,MAX_PATH,pDocInfo->lpszOutput,Length);
}
// if the datatype is specified to be raw, and the size is the size of
// the new expanded DOCINFO, make it raw.
// we also verify that the fwType is valid. Otherwise, chances are
// the app left the two new fields unitialized.
try
{
if ((pDocInfo->cbSize == sizeof(DOCINFO)) &&
pDocInfo->lpszDatatype &&
(pDocInfo->fwType <= 1))
{
if (!_stricmp("emf",pDocInfo->lpszDatatype))
{
DocInfoW.lpszDatatype = L"EMF";
}
else
{
Length = strlen(pDocInfo->lpszDatatype)+1;
vToUnicodeN(wDataType,MAX_PATH,pDocInfo->lpszDatatype,Length);
DocInfoW.lpszDatatype = wDataType;
}
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNING("StartDocA an app passed a new DOCINFO structure without initializing it\n");
}
}
return(StartDocW(hdc,&DocInfoW));
}
/******************************Public*Routine******************************\
* StartDocW
*
* Client side stub.
*
* History:
* 31-Jul-1991 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int WINAPI StartDocW(HDC hdc, CONST DOCINFOW * pDocInfo)
{
int iRet = SP_ERROR;
PWSTR pwstr = NULL;
DOCINFOW dio;
BOOL bForceRaw = FALSE;
BOOL bSendStartDocPost = FALSE;
BOOL bCallAbortPrinter = TRUE;
BOOL bEMF = FALSE;
INT iJob;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc) && !IS_METADC16_TYPE(hdc))
{
BOOL bBanding;
PLDC pldc;
DC_PLDC(hdc,pldc,iRet);
// don't allow StartDoc's on info dc's
if (pldc->fl & LDC_INFO)
{
SetLastError(ERROR_INVALID_HANDLE);
return iRet;
}
pldc->fl &= ~LDC_DOC_CANCELLED;
#if PRINT_TIMER
{
DbgPrint("StartDocW: Print Timer is on\n");
pldc->msStartDoc = GetTickCount();
}
#endif
if( pDocInfo )
{
dio = *pDocInfo;
if (dio.cbSize != offsetof(DOCINFOW,lpszDatatype))
{
dio.cbSize = sizeof(DOCINFOW);
dio.lpszDatatype = NULL;
dio.fwType = 0;
try
{
// if it is not NULL and not "emf", go raw
// we also verify that the fwType is valid. Otherwise, chances are
// the app left the two new fields unitialized.
if ((pDocInfo->cbSize == sizeof(DOCINFOW)) &&
pDocInfo->lpszDatatype &&
(pDocInfo->fwType <= 1) &&
_wcsicmp(L"emf",pDocInfo->lpszDatatype))
{
// the app requested non emf
bForceRaw = TRUE;
dio.lpszDatatype = pDocInfo->lpszDatatype;
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNING("StartDocW an app passed a new DOCINFO structure without initializing it\n");
}
}
}
else
{
dio.cbSize = sizeof(DOCINFOW);
dio.lpszDatatype = NULL;
dio.lpszOutput = NULL;
dio.lpszDocName = NULL;
dio.fwType = 0;
}
// if no output port is specified but a port was specified at createDC, use
// that port now
if ((dio.lpszOutput == NULL) && (pldc->pwszPort != NULL))
{
dio.lpszOutput = pldc->pwszPort;
}
// StartDocDlgW returns -1 for error
// -2 for user cancelled
// NULL if there is no string to copy (not file port)
// Non NULL if there is a valid string
if(pldc->hSpooler != (HANDLE)0)
{
ASSERTGDI(ghSpooler,"non null hSpooler with unloaded WINSPOOL W\n");
pwstr = (*fpStartDocDlgW)(pldc->hSpooler, &dio);
if((LONG_PTR)pwstr == -2)
{
pldc->fl |= LDC_DOC_CANCELLED;
return(iRet);
}
if((LONG_PTR)pwstr == -1)
return(iRet);
if(pwstr != NULL)
{
dio.lpszOutput = pwstr;
}
}
// now call the drivers UI portion
if (pldc->hSpooler)
{
PVOID pv = (PVOID)&dio;
iRet = DocumentEventEx(pldc->pUMPD,
pldc->hSpooler,
hdc,
DOCUMENTEVENT_STARTDOCPRE,
sizeof(pv),
(PVOID)&pv,
0,
NULL);
if (iRet == -1)
{
bCallAbortPrinter = FALSE;
goto KMMSGERROR;
}
if(iRet == -2)
{
pldc->fl |= LDC_DOC_CANCELLED;
goto MSGEXIT;
}
}
//
// Check application compatibility
//
if (GetAppCompatFlags(NULL) & GACF_NOEMFSPOOLING)
{
ULONG InData = POSTSCRIPT_PASSTHROUGH;
//
// Disable EMF spooling for postscript printer driver.
//
// Several PS-centric application could not work with EMF spooling.
// This problem is introduced, because application developed for win95
// reley on that win95 does not do EMF spooling with postscript, but
// NT does.
//
if (ExtEscape(hdc,QUERYESCSUPPORT,sizeof(ULONG),(LPCSTR)&InData,0,NULL))
{
bForceRaw = TRUE;
}
}
// Unless the driver has explicitly told us not to spool, we will first try
// to StartDoc with datatype EMF
// we also force to go to EMF if METAFILE_DRIVER is supported by the driver
if ((!bForceRaw && GetDCDWord(hdc, DDW_JOURNAL, 0) &&
RemoteRasterizerCompatible(pldc->hSpooler)) ||
((pldc->pUMPD) && (pldc->pUMPD->dwFlags & UMPDFLAG_METAFILE_DRIVER)))
{
DOC_INFO_3W DocInfo;
DocInfo.pDocName = (LPWSTR) dio.lpszDocName;
DocInfo.pOutputFile = (LPWSTR) dio.lpszOutput;
DocInfo.pDatatype = (LPWSTR) L"NT EMF 1.008";
DocInfo.dwFlags = DI_MEMORYMAP_WRITE;
iJob = (*fpStartDocPrinterW)(pldc->hSpooler, 3, (LPBYTE) &DocInfo);
if( iJob <= 0 )
{
if( GetLastError() != ERROR_INVALID_DATATYPE )
{
WARNING("StartDocW: StartDocPrinter failed w/ error other \
than INVALID_DATA_TYPE\n");
bCallAbortPrinter = FALSE;
goto KMMSGERROR;
}
else
{
// we are going raw so just fall through
}
}
else
{
// the spooler likes the EMF data type so let start metafiling
MFD1("StartDocW calling MFP_StartDocW to do EMF printing\n");
if(MFP_StartDocW( hdc, &dio, FALSE))
{
iRet = iJob;
bSendStartDocPost = TRUE;
goto MSGEXIT;
}
else
{
WARNING("StartDocW: error calling MFP_StartDocW\n");
bEMF = TRUE;
goto KMMSGERROR;
}
}
}
// if it is a UMPD driver, call StartDocPrinter at the client side
if (pldc->pUMPD)
{
DOC_INFO_1W DocInfo;
#define MAX_DOCINFO_DATA_TYPE 80
WCHAR awchDatatype[MAX_DOCINFO_DATA_TYPE];
PFN pfn;
DocInfo.pDocName = (LPWSTR) dio.lpszDocName;
DocInfo.pOutputFile = (LPWSTR) dio.lpszOutput;
DocInfo.pDatatype = NULL;
if (pfn = pldc->pUMPD->apfn[INDEX_DrvQuerySpoolType])
{
awchDatatype[0] = 0;
// did the app specify a data type and will it fit in our buffer
if (dio.lpszDatatype)
{
int cjStr = (wcslen(dio.lpszDatatype) + 1) * sizeof(WCHAR);
if (cjStr < (MAX_DOCINFO_DATA_TYPE * sizeof(WCHAR)))
{
RtlCopyMemory((PVOID)awchDatatype,(PVOID)dio.lpszDatatype,cjStr);
}
}
if (pfn(((PUMDHPDEV)pldc->pUMdhpdev)->dhpdev, awchDatatype))
{
DocInfo.pDatatype = awchDatatype;
}
}
iJob = StartDocPrinterWEx(pldc->pUMPD, pldc->hSpooler, 1, (LPBYTE) &DocInfo);
}
// If we got here it means we are going raw. Mark the DC as type direct
if (pldc->pUMPD && (pldc->pUMPD->dwFlags & UMPDFLAG_METAFILE_DRIVER))
{
// we have to go EMF if METAFILE_DRIVER is on
WARNING("StartDocW failed because EMF failed and METAFILE_DRIVER is on\n");
goto KMMSGERROR;
}
pldc->fl |= LDC_PRINT_DIRECT;
iRet = NtGdiStartDoc(hdc,&dio,&bBanding, iJob);
if (iRet)
{
if (pldc->pfnAbort != NULL)
{
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
goto KMMSGERROR;
pldc->fl |= LDC_SAP_CALLBACK;
pldc->ulLastCallBack = GetTickCount();
}
pldc->fl |= LDC_DOC_STARTED;
if (bBanding)
{
MFD1("StartDocW calling MFP_StartDocW to do banding\n");
iRet = MFP_StartDocW( hdc, NULL, TRUE ) ? iRet : SP_ERROR;
}
else
{
// Only set this when we are not banding since the system will
// get confused and try to call StartPage while playing the
// metafile back during banding.
pldc->fl |= LDC_CALL_STARTPAGE;
}
bSendStartDocPost = TRUE;
}
else
{
KMMSGERROR:
iRet = SP_ERROR;
if (bCallAbortPrinter && pldc->pUMPD)
{
AbortPrinterEx(pldc, bEMF);
}
}
MSGEXIT:
if (bSendStartDocPost)
{
// now see if we need to call the drivers UI portion
{
if (DocumentEventEx(pldc->pUMPD,
pldc->hSpooler,
hdc,
DOCUMENTEVENT_STARTDOCPOST,
sizeof(iRet),
(PVOID)&iRet,
0,
NULL) == -1)
{
AbortDoc(hdc);
iRet = SP_ERROR;
}
}
}
}
if (pwstr != NULL)
{
LocalFree(pwstr);
}
return(iRet);
}
/******************************Public*Routine******************************\
* StartDocEMF
*
* Special version of StartDoc used by the EMF playback code.
*
* History:
* 31-Jul-1991 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int WINAPI StartDocEMF(HDC hdc, CONST DOCINFOW * pDocInfo, BOOL *pbBanding )
{
int iRet = SP_ERROR;
DOCINFOW dio;
INT iJob = 0;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc) && !IS_METADC16_TYPE(hdc))
{
BOOL bBanding;
PLDC pldc;
DC_PLDC(hdc,pldc,iRet);
#if PRINT_TIMER
{
DbgPrint("StartDocW: Print Timer is on\n");
pldc->msStartDoc = GetTickCount();
}
#endif
// if no output port is specified but a port was specified at createDC, use that port now
if (pDocInfo)
{
dio = *pDocInfo;
if (dio.lpszOutput == NULL && pldc->pwszPort != NULL)
dio.lpszOutput = pldc->pwszPort;
}
else
{
ZeroMemory(&dio, sizeof(dio));
dio.cbSize = sizeof(dio);
}
// if it is a UMPD driver, call StartDocPrinter at the client side
if (pldc->pUMPD)
{
DOC_INFO_3W DocInfo;
DocInfo.pDocName = (LPWSTR) dio.lpszDocName;
DocInfo.pOutputFile = (LPWSTR) dio.lpszOutput;
DocInfo.pDatatype = NULL;
DocInfo.dwFlags = DI_MEMORYMAP_WRITE;
iJob = (*fpStartDocPrinterW)( pldc->hSpooler, 3, (LPBYTE) &DocInfo );
}
iRet = NtGdiStartDoc(hdc,(DOCINFOW *)&dio, pbBanding, iJob);
if (iRet)
{
pldc->fl |= LDC_DOC_STARTED;
pldc->fl |= LDC_CALL_STARTPAGE;
}
else
{
// For Win31 compatibility, return SP_ERROR for error.
iRet = SP_ERROR;
if (pldc->pUMPD)
{
(*fpAbortPrinter)(pldc->hSpooler);
}
}
}
return(iRet);
}
/******************************Private*Function****************************\
* vSAPCallback
*
* Call back to applications abort proc.
*
* History:
* 02-May-1992 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
VOID vSAPCallback(PLDC pldc)
{
ULONG ulCurr = GetTickCount();
if (ulCurr - pldc->ulLastCallBack >= CALLBACK_INTERVAL)
{
pldc->ulLastCallBack = ulCurr;
if (!(*pldc->pfnAbort)(pldc->hdc, 0))
{
CancelDC(pldc->hdc);
AbortDoc(pldc->hdc);
}
}
}
/******************************Public*Routine******************************\
* SetAbortProc
*
* Save the application-supplied abort function in the LDC struct.
*
* History:
* 02-Apr-1992 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
int WINAPI SetAbortProc(HDC hdc, ABORTPROC pfnAbort)
{
int iRet = SP_ERROR;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc) && !IS_METADC16_TYPE(hdc))
{
PLDC pldc;
DC_PLDC(hdc,pldc,iRet);
if (pfnAbort != (ABORTPROC)NULL)
{
// PageMaker calls SetAbortProc after StartDoc.
if (pldc->fl & LDC_DOC_STARTED)
{
pldc->fl |= LDC_SAP_CALLBACK;
pldc->ulLastCallBack = GetTickCount();
}
}
else
{
pldc->fl &= ~LDC_SAP_CALLBACK;
}
pldc->pfnAbort = pfnAbort;
iRet = 1;
}
return(iRet);
}
/******************************Public*Routine******************************\
*
* GetPairKernTable
*
* support for GETPAIRKERNTABLE escape, basically reroute the call
* the the regular API
*
* History:
* 17-Jun-1996 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
DWORD GetPairKernTable (
HDC hdc,
DWORD cjSize, // size of buffer in bytes
KERNPAIR * pkp
)
{
DWORD dwRet = GetKerningPairsA(hdc, 0, NULL);
DWORD dwRet1, ikp;
if (pkp && dwRet)
{
// pointer to receiving buffer
KERNINGPAIR *pKernPair = LOCALALLOC(dwRet * sizeof(KERNINGPAIR));
if (pKernPair)
{
dwRet1 = GetKerningPairsA(hdc, dwRet, pKernPair);
if (dwRet1 == dwRet) // paranoid check
{
// now we can copy the data out, get the number of pairs
// that the buffer can hold:
dwRet = cjSize / sizeof (KERNPAIR);
if (dwRet > dwRet1)
dwRet = dwRet1;
for (ikp = 0; ikp < dwRet; ikp++)
{
pkp[ikp].sAmount = (SHORT)pKernPair[ikp].iKernAmount;
pkp[ikp].wBoth = (WORD)
((BYTE)pKernPair[ikp].wFirst |
(BYTE)pKernPair[ikp].wSecond << 8);
}
}
else
{
dwRet = 0;
}
LOCALFREE(pKernPair);
}
else
{
dwRet = 0;
}
}
return dwRet;
}
/******************************Public*Routine******************************\
* Escape *
* *
* Compatibility support for the old 16 bit Escape call. *
* *
* Note that there are some rules to follow here: *
* *
* 1) WOW should map a selected set of old Escape calls to ExtEscape. *
* These should be the calls that we want to support under NT (i.e. the *
* ones we are forced to support), and that make sense (i.e. have well *
* defined output structures, where NULL is well defined). In this *
* mapping, WOW insures 32 bit alignment. It maps directly to ExtEscape *
* just for efficiency. *
* *
* 2) GDI should map ALL the same calls that WOW does. Thus when a 16 bit *
* app that works under WOW gets ported to 32 bits, it will keep *
* working, even if it still calls Escape. (I'm basically assuming that *
* Chicago will also allow this. On the other hand if Chicago forces *
* apps to migrate to ExtEscape, then we can too. But we can't force *
* them by ourselves!) *
* *
* 3) Any data structures passed to Escape must get passed unchanged to *
* ExtEscape. This includes the 16 bit WORD in POSTSCRIPT_PASSTHROUGH. *
* Remember, we *want* Chicago to be able to easily support our *
* ExtEscapes. If we remove that WORD, it will be hard for then *
* to put it back. It's pretty easy for our driver to ignore it. *
* *
* 4) Our Escape entry point should handle QUERYESCSUPPORT in the *
* following way. a) It should require an nCount of 2, not the *
* present 4. b) It should return TRUE for those functions that it *
* handles by mapping onto APIs. c) For any function that it would pass *
* on to ExtEscape, it should also pass the QUERYESCSUPPORT on. (For *
* example, this function can't answer for the support of *
* POSTSCRIPT_PASSTHROUGH.) However, the QUERYESCSUPPORT in ExtEscape *
* *should* expect a DWORD. (It is after all a 32 bit function.) This *
* should not inconvenience Chicago. They can simply reject function *
* numbers >64K. *
* [chuckwh - 5/8/93] *
* *
* History: *
* Mon May 17 13:49:32 1993 -by- Hock San Lee [hockl] *
* Made ENCAPSULATED_POSTSCRIPT call DrawEscape. *
* *
* Sat 08-May-1993 00:03:06 -by- Charles Whitmer [chuckwh] *
* Added support for POSTSCRIPT_PASSTHROUGH, OPENCHANNEL, CLOSECHANNEL, *
* DOWNLOADHEADER, DOWNLOADFACE, GETFACENAME, ENCAPSULATED_POSTSCRIPT. *
* Cleaned up the code and conventions a bit. *
* *
* 02-Apr-1992 -by- Wendy Wu [wendywu] *
* Modified to call the client side GDI functions. *
* *
* 01-Aug-1991 -by- Eric Kutter [erick] *
* Wrote it. *
\**************************************************************************/
int WINAPI Escape(
HDC hdc, // Identifies the device context.
int iEscape, // Specifies the escape function to be performed.
int cjIn, // Number of bytes of data pointed to by pvIn.
LPCSTR pvIn, // Points to the input data.
LPVOID pvOut // Points to the structure to receive output.
)
{
int iRet = 0;
DOCINFOA DocInfo;
PLDC pldc;
ULONG iQuery;
BOOL bFixUp;
FIXUP_HANDLE(hdc);
// Metafile the call.
if(IS_METADC16_TYPE(hdc))
return((int) MF16_Escape(hdc,iEscape,cjIn,pvIn,pvOut));
// handle escapes that don't require a printer
switch (iEscape)
{
case QUERYESCSUPPORT:
switch(*((UNALIGNED USHORT *) pvIn))
{
// Respond OK to the calls we handle inline below.
case QUERYESCSUPPORT:
case PASSTHROUGH:
case STARTDOC:
case ENDDOC:
case NEWFRAME:
case ABORTDOC:
case SETABORTPROC:
case GETPHYSPAGESIZE:
case GETPRINTINGOFFSET:
case GETSCALINGFACTOR:
case NEXTBAND:
case GETCOLORTABLE:
case OPENCHANNEL:
case CLOSECHANNEL:
case DOWNLOADHEADER:
iRet = (IS_ALTDC_TYPE(hdc) ? 1 : 0);
break;
case GETEXTENDEDTEXTMETRICS:
iRet = 1;
break;
// Ask the driver about the few calls we allow to pass through.
case SETCOPYCOUNT:
case GETDEVICEUNITS:
case POSTSCRIPT_PASSTHROUGH:
case POSTSCRIPT_DATA:
case POSTSCRIPT_IGNORE:
case POSTSCRIPT_IDENTIFY:
case POSTSCRIPT_INJECTION:
case DOWNLOADFACE:
case BEGIN_PATH:
case END_PATH:
case CLIP_TO_PATH:
case DRAWPATTERNRECT:
iQuery = (ULONG) (*((UNALIGNED USHORT *) pvIn));
iRet =
(
ExtEscape
(
hdc,
(ULONG) ((USHORT) iEscape),
4,
(LPCSTR) &iQuery,
0,
(LPSTR) NULL
)
);
break;
case ENCAPSULATED_POSTSCRIPT:
iQuery = (ULONG) (*((UNALIGNED USHORT *) pvIn));
iRet =
(
DrawEscape
(
hdc,
(int) (ULONG) ((USHORT) iEscape),
4,
(LPCSTR) &iQuery
)
);
break;
case QUERYDIBSUPPORT:
iRet = 1;
break;
// Otherwise it's no deal. Sorry. If we answer "yes" to some
// call we don't know *everything* about, we may find ourselves
// actually rejecting the call later when the app actually calls
// with some non-NULL pvOut. This would get the app all excited
// about our support for no reason. It would take a path that
// is doomed to failure. [chuckwh]
default:
iRet = 0;
break;
}
return(iRet);
case GETCOLORTABLE:
iRet = GetSystemPaletteEntries(hdc,*((UNALIGNED SHORT *)pvIn),1,pvOut);
if (iRet == 0)
iRet = -1;
return(iRet);
case QUERYDIBSUPPORT:
if ((pvOut != NULL) && (cjIn >= sizeof(BITMAPINFOHEADER)))
{
*((UNALIGNED LONG *)pvOut) = 0;
switch (((UNALIGNED BITMAPINFOHEADER *)pvIn)->biCompression)
{
case BI_RGB:
switch (((UNALIGNED BITMAPINFOHEADER *)pvIn)->biBitCount)
{
case 1:
case 4:
case 8:
case 16:
case 24:
case 32:
*((UNALIGNED LONG *)pvOut) = (QDI_SETDIBITS|QDI_GETDIBITS|
QDI_DIBTOSCREEN|QDI_STRETCHDIB);
break;
default:
break;
}
case BI_RLE4:
if (((UNALIGNED BITMAPINFOHEADER *)pvIn)->biBitCount == 4)
{
*((UNALIGNED LONG *)pvOut) = (QDI_SETDIBITS|QDI_GETDIBITS|
QDI_DIBTOSCREEN|QDI_STRETCHDIB);
}
break;
case BI_RLE8:
if (((UNALIGNED BITMAPINFOHEADER *)pvIn)->biBitCount == 8)
{
*((UNALIGNED LONG *)pvOut) = (QDI_SETDIBITS|QDI_GETDIBITS|
QDI_DIBTOSCREEN|QDI_STRETCHDIB);
}
break;
case BI_BITFIELDS:
switch (((UNALIGNED BITMAPINFOHEADER *)pvIn)->biBitCount)
{
case 16:
case 32:
*((UNALIGNED LONG *)pvOut) = (QDI_SETDIBITS|QDI_GETDIBITS|
QDI_DIBTOSCREEN|QDI_STRETCHDIB);
break;
default:
break;
}
default:
break;
}
return 1;
}
case GETEXTENDEDTEXTMETRICS:
return( GetETM( hdc, pvOut ) ? 1 : 0 );
}
// OK, ones that are related to printing and need the LDC
if (IS_ALTDC_TYPE(hdc))
{
BOOL bFixUp = FALSE;
PLDC pldc;
DC_PLDC(hdc,pldc,iRet);
// Call the appropriate client side APIs.
switch (iEscape)
{
case CLOSECHANNEL:
case ENDDOC:
iRet = EndDoc(hdc);
break;
case ABORTDOC:
iRet = AbortDoc(hdc);
break;
case SETABORTPROC:
iRet = SetAbortProc(hdc, (ABORTPROC)pvIn);
break;
case GETSCALINGFACTOR:
if (pvOut)
{
((UNALIGNED POINT *)pvOut)->x = GetDeviceCaps(hdc, SCALINGFACTORX);
((UNALIGNED POINT *)pvOut)->y = GetDeviceCaps(hdc, SCALINGFACTORY);
}
iRet = 1;
break;
case SETCOPYCOUNT:
iRet =
(
ExtEscape
(
hdc,
(ULONG) ((USHORT) iEscape),
cjIn,
pvIn,
pvOut ? sizeof(int) : 0,
(LPSTR) pvOut
)
);
break;
case GETDEVICEUNITS:
iRet =
(
ExtEscape
(
hdc,
GETDEVICEUNITS,
cjIn,
pvIn,
16,
pvOut
)
);
break;
case POSTSCRIPT_PASSTHROUGH:
iRet =
(
ExtEscape
(
hdc,
POSTSCRIPT_PASSTHROUGH,
(int) (*((UNALIGNED USHORT *) pvIn))+2,
pvIn,
0,
(LPSTR) NULL
)
);
break;
case OPENCHANNEL:
DocInfo.lpszDocName = (LPSTR) NULL;
DocInfo.lpszOutput = (LPSTR) NULL;
DocInfo.lpszDatatype= (LPSTR) "RAW";
DocInfo.fwType = 0;
iRet = StartDocA(hdc,&DocInfo);
break;
case DOWNLOADHEADER:
iRet = 1;
break;
case POSTSCRIPT_DATA:
case POSTSCRIPT_IGNORE:
case POSTSCRIPT_IDENTIFY:
case POSTSCRIPT_INJECTION:
case DOWNLOADFACE:
case BEGIN_PATH:
case END_PATH:
case CLIP_TO_PATH:
case DRAWPATTERNRECT:
iRet =
(
ExtEscape
(
hdc,
(ULONG) ((USHORT) iEscape),
cjIn,
pvIn,
0,
(LPSTR) NULL
)
);
break;
case ENCAPSULATED_POSTSCRIPT:
iRet =
(
DrawEscape
(
hdc,
(int) (ULONG) ((USHORT) iEscape),
cjIn,
pvIn
)
);
break;
case GETPHYSPAGESIZE:
if (pvOut)
{
((UNALIGNED POINT *)pvOut)->x = GetDeviceCaps(hdc, PHYSICALWIDTH);
((UNALIGNED POINT *)pvOut)->y = GetDeviceCaps(hdc, PHYSICALHEIGHT);
}
iRet = 1;
break;
case GETPRINTINGOFFSET:
if (pvOut)
{
((UNALIGNED POINT *)pvOut)->x = GetDeviceCaps(hdc, PHYSICALOFFSETX);
((UNALIGNED POINT *)pvOut)->y = GetDeviceCaps(hdc, PHYSICALOFFSETY);
}
iRet = 1;
break;
case STARTDOC:
DocInfo.lpszDocName = (LPSTR)pvIn;
DocInfo.lpszOutput = (LPSTR)NULL;
DocInfo.lpszDatatype= (LPSTR) NULL;
DocInfo.fwType = 0;
iRet = StartDocA(hdc, &DocInfo);
bFixUp = TRUE;
break;
case PASSTHROUGH:
#if (PASSTHROUGH != DEVICEDATA)
#error PASSTHROUGH != DEVICEDATA
#endif
iRet = ExtEscape
(
hdc,
PASSTHROUGH,
(int) (*((UNALIGNED USHORT *) pvIn))+sizeof(WORD),
pvIn,
0,
(LPSTR) NULL
);
bFixUp = TRUE;
break;
case NEWFRAME:
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
// If no error occured in EndPage, call StartPage next time.
if ((iRet = EndPage(hdc)) > 0)
pldc->fl |= LDC_CALL_STARTPAGE;
bFixUp = TRUE;
break;
case NEXTBAND:
// Win31 compatibility flags.
// GACF_MULTIPLEBANDS: Freelance thinks the first full-page band is
// a text-only band. So it ignores it and waits
// for the next band to print graphics. We'll
// return the full-page band twice for each page.
// The first band will be ignored while the second
// band really contains graphics to print.
// This flag only affects dotmatrix on win31.
// GACF_FORCETEXTBAND: World Perfect and Freelance both have assumptions
// on whether a band is text-only or not. They
// print text and graphics in different bands.
// We'll return two full-page bands for each page.
// One for text and the other for graphics.
// This flag only affects laser jet on win31.
if (pldc->fl & LDC_NEXTBAND)
{
if (GetAppCompatFlags(NULL) & (GACF_FORCETEXTBAND|GACF_MULTIPLEBANDS))
{
if (pldc->fl & LDC_EMPTYBAND)
{
pldc->fl &= ~LDC_EMPTYBAND;
}
else
{
pldc->fl |= LDC_EMPTYBAND;
goto FULLPAGEBAND;
}
}
((UNALIGNED RECT *)pvOut)->left = ((UNALIGNED RECT *)pvOut)->top =
((UNALIGNED RECT *)pvOut)->right = ((UNALIGNED RECT *)pvOut)->bottom = 0;
pldc->fl &= ~LDC_NEXTBAND; // Clear NextBand flag.
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
if ((iRet = EndPage(hdc)) > 0)
{
pldc->fl |= LDC_CALL_STARTPAGE;
//
// Marks application is doing banding by themselves,
// then EndPage() is called when there is no more band.
//
pldc->fl |= LDC_CALLED_ENDPAGE;
}
bFixUp = TRUE;
}
else
{
FULLPAGEBAND:
((UNALIGNED RECT *)pvOut)->left = ((UNALIGNED RECT *)pvOut)->top = 0;
((UNALIGNED RECT *)pvOut)->right = GetDeviceCaps(hdc, HORZRES);
((UNALIGNED RECT *)pvOut)->bottom = GetDeviceCaps(hdc, VERTRES);
pldc->fl |= LDC_NEXTBAND; // Set NextBand flag.
iRet = 1;
}
break;
default:
iRet = 0;
break;
}
// Fix up the return values for STARTDOC and PASSTHROUGH so we're
// win31 compatible.
if (bFixUp && (iRet < 0))
{
if (pldc->fl & LDC_DOC_CANCELLED)
{
iRet = SP_APPABORT;
}
else
{
switch(GetLastError())
{
case ERROR_PRINT_CANCELLED:
iRet = SP_USERABORT;
break;
case ERROR_NOT_ENOUGH_MEMORY:
iRet = SP_OUTOFMEMORY;
break;
case ERROR_DISK_FULL:
iRet = SP_OUTOFDISK;
break;
default:
iRet = SP_ERROR;
break;
}
}
}
}
else
{
// We don't support this escape on this DC, but CorelDRAW expects
// some non-random values back anyway. Zero the output buffer to
// keep it happy.
if ((iEscape == GETSCALINGFACTOR) && pvOut)
{
RtlZeroMemory(pvOut, sizeof(POINT));
}
}
return(iRet);
}
/******************************Public*Routine******************************\
* ExtEscape *
* *
* History: *
* 14-Feb-1992 -by- Dave Snipp [DaveSn] *
* Wrote it. *
\**************************************************************************/
#define BUFSIZE 520
int WINAPI ExtEscape(
HDC hdc, // Identifies the device context.
int iEscape, // Specifies the escape function to be performed.
int cjInput, // Number of bytes of data pointed to by lpInData
LPCSTR lpInData, // Points to the input structure required
int cjOutput, // Number of bytes of data pointed to by lpOutData
LPSTR lpOutData // Points to the structure to receive output from
) // this escape.
{
int iRet = 0;
int cjIn, cjOut, cjData;
PLDC pldc;
XFORM xf;
// We need some extra buffer space for at least one call. I'm going to
// hard code it here. The slickest thing would be to have a separate
// routine that knows how to alloc this space out of the memory window,
// but that would be more complex. I'm rushed. Sorry. [chuckwh]
BYTE jBuffer[BUFSIZE];
// We want to make this escape work just like it does in Windows which means
// that if there is a TrueType font in the DC GDI will compute it otherwise
// we'll pass the escape to the driver. So we call off to GetETM here because
// it does just that.
FIXUP_HANDLE(hdc);
if( iEscape == GETEXTENDEDTEXTMETRICS )
{
if( GetETM( hdc, (EXTTEXTMETRIC*) jBuffer ) )
{
RtlCopyMemory( lpOutData, jBuffer, MIN(cjOutput,sizeof(EXTTEXTMETRIC)) );
return(1);
}
else
{
return(0);
}
}
else if (iEscape == DRAWPATTERNRECT)
{
if (GetAppCompatFlags2(VER40) & GACF2_NODRAWPATRECT)
{
// GACF_NODRAWPATRECT -
//
// Some of application does not work with DrawPatRect escape,
// so that we behave as we don't support it.
//
return (0);
}
if (!cjInput)
{
//
// work around 32 bits Excel (with Ofiice 97) bug.
//
cjInput = sizeof(DRAWPATRECT);
}
}
else if (iEscape == QUERYESCSUPPORT)
{
if (*(ULONG*)lpInData == GETPAIRKERNTABLE)
{
// intercept GETPAIRKERNTABLE escape on the client side where all the work is done
// It is interesting that this "api" works on win95 not only for device fonts but
// also for engine fonts. Therefore this needs to be outside of
// the IS_ALTDC_TYPE(hdc) clause below
return (1);
}
else if (*(ULONG*)lpInData == DRAWPATTERNRECT)
{
if (GetAppCompatFlags2(VER40) & GACF2_NODRAWPATRECT)
{
// GACF_NODRAWPATRECT -
//
// Some of application does not work with DrawPatRect escape,
// so that we behave as we don't support it.
//
return (0);
}
}
}
else if (iEscape == GETPAIRKERNTABLE)
{
return GetPairKernTable(hdc, (DWORD)cjOutput, (KERNPAIR *)lpOutData);
}
// printer specific stuff
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
// don't allow them 16bit metafiles
if (IS_METADC16_TYPE(hdc))
return (0);
DC_PLDC(hdc,pldc,iRet);
MFD2("ExtEscapeCalled %d\n", iEscape );
if (pldc->fl & (LDC_DOC_CANCELLED|LDC_SAP_CALLBACK))
{
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(0);
}
// if it is an output call that requires no return results, better make sure
// we do a start page.
if (( iEscape == DOWNLOADFACE ) ||
( iEscape == GETFACENAME ) ||
( iEscape == POSTSCRIPT_DATA ) ||
( iEscape == BEGIN_PATH ) ||
( iEscape == END_PATH ) ||
( iEscape == CLIP_TO_PATH ) ||
( iEscape == PASSTHROUGH ) ||
( iEscape == DOWNLOADHEADER ))
{
if (pldc->fl & LDC_CALL_STARTPAGE)
StartPage(hdc);
}
if ((pldc->iType == LO_METADC) && (pldc->fl & LDC_META_PRINT))
{
// These two escapes should be called *before* StartDoc, any these escape
// called *after* StartDoc will be failed when EMF is used (see SDK)
if ((iEscape == POSTSCRIPT_IDENTIFY) || (iEscape == POSTSCRIPT_INJECTION))
{
WARNING("GDI32: ExtEscape() PSInjection after StartDoc with EMF, is ignored\n");
SetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
// These escapes will not be recorded into metafile
//
// SETCOPYCOUNT - will be handled in kernel for EMF spooling case.
// and this will be recorded in DEVMODE.dmCopies.
//
// QUERYSUPPORT - will be handled in driver even EMF spooling case,
// since only driver knows which escape support it.
// and this is nothing for drawing, so not nessesary
// to record it.
//
// CHECKJPEGFORMAT & CHECKPNGFORMAT
// - query escapes that do not need to be reocorded
// into metafile.
//
if ((iEscape != SETCOPYCOUNT) && (iEscape != QUERYESCSUPPORT) &&
(iEscape != CHECKJPEGFORMAT) && (iEscape != CHECKPNGFORMAT))
{
BOOL bSetXform = FALSE;
// Write this escape to metafile.
//
// If there's transform set in the hdc by the app
// at the time of DRAWPATRECT, select identity transform in
// once the escape is recorded, select back the original transform
//
if (GetWorldTransform(hdc, &xf))
{
if ((xf.eM11 != 1.0f) || (xf.eM22 != 1.0f) ||
(xf.eM12 != 0.0f) || (xf.eM21 != 0.0f))
{
bSetXform = TRUE;
MF_ModifyWorldTransform(hdc,&xformIdentity,MWT_SET);
}
}
MF_WriteEscape( hdc, iEscape, cjInput, lpInData, EMR_EXTESCAPE );
if (bSetXform)
{
MF_ModifyWorldTransform(hdc,&xf,MWT_SET);
}
if ((lpOutData == (LPSTR) NULL) || (cjOutput == 0))
{
if ((iEscape == PASSTHROUGH) ||
(iEscape == POSTSCRIPT_PASSTHROUGH) ||
(iEscape == POSTSCRIPT_DATA))
{
if ((cjInput < (int)sizeof(WORD)) ||
(cjInput < (int)sizeof(WORD) + *((LPWORD) lpInData)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
cjInput = *((LPWORD) lpInData);
}
return(MAX(cjInput,1));
}
}
MFD2("ExtEscape goes to gre/driver Escape(%d) with EMF printing\n", iEscape);
}
if ((iEscape == DOWNLOADFACE) || (iEscape == GETFACENAME))
{
if (iEscape == DOWNLOADFACE)
{
// Adjust the buffer for the DOWNLOADFACE case. Note that lpOutData
// points at an input word for the mode.
if ((gpwcANSICharSet == (WCHAR *) NULL) && !bGetANSISetMap())
{
return(0);
}
RtlMoveMemory
(
jBuffer + sizeof(WCHAR),
(BYTE *) &gpwcANSICharSet[0],
256*sizeof(WCHAR)
);
if (lpOutData)
*(WCHAR *) jBuffer = *(UNALIGNED WORD *) lpOutData;
else
*(WCHAR *) jBuffer = 0;
cjInput = 257 * sizeof(WCHAR);
lpInData = (LPCSTR) jBuffer;
ASSERTGDI(BUFSIZE >= cjInput,"Buffer too small.\n");
}
}
if ((iEscape == POSTSCRIPT_INJECTION) || (iEscape == POSTSCRIPT_IDENTIFY))
{
// Remember escape data for EMF spooling case. (only BEFORE StartDoc)
if (!(pldc->fl & LDC_DOC_STARTED))
{
PPS_INJECTION_DATA pPSInjection;
ULONG cjCellSize;
if( BROUNDUP_DWORDALIGN_OVERFLOW(
(sizeof(PS_INJECTION_DATA)-1)+cjInput) )
return 0;
cjCellSize =
ROUNDUP_DWORDALIGN((sizeof(PS_INJECTION_DATA)-1)+cjInput);
MFD2("ExtEscape records this Escape(%d) temporary then write EMF later\n",iEscape);
if ((pPSInjection = LOCALALLOC(cjCellSize)) != NULL)
{
cjCellSize -= offsetof(PS_INJECTION_DATA,EmfData);
// Fill up Injection Data.
pPSInjection->EmfData.cjSize = cjCellSize;
pPSInjection->EmfData.nEscape = iEscape;
pPSInjection->EmfData.cjInput = cjInput;
RtlCopyMemory(pPSInjection->EmfData.EscapeData,lpInData,cjInput);
// Put this on list.
InsertTailList(&(pldc->PSDataList),&(pPSInjection->ListEntry));
// Update total data size.
pldc->dwSizeOfPSDataToRecord += cjCellSize;
}
else
{
WARNING("ExtEscape: Failed on LOCALALLOC for POSTSCRIPT_xxxxx\n");
GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return (0);
}
}
}
// now call the drivers UI portion
if (pldc->hSpooler)
{
DOCEVENT_ESCAPE docEvent;
docEvent.iEscape = iEscape;
docEvent.cjInput = cjInput;
docEvent.pvInData = (PVOID)lpInData;
DocumentEventEx(pldc->pUMPD,
pldc->hSpooler,
hdc,
DOCUMENTEVENT_ESCAPE,
sizeof(docEvent),
(PVOID)&docEvent,
cjOutput,
(PVOID)lpOutData);
}
}
cjIn = (lpInData == NULL) ? 0 : cjInput;
cjOut = (lpOutData == NULL) ? 0 : cjOutput;
iRet = NtGdiExtEscape(hdc,NULL,0,iEscape,cjIn,(LPSTR)lpInData,cjOut,lpOutData);
return(iRet);
}
/******************************Public*Routine******************************\
* NamedEscape
*
* History:
* 5-Mar-1996 -by- Gerrit van Wingerden
* Wrote it.
\**************************************************************************/
#define BUFSIZE 520
int WINAPI NamedEscape(
HDC hdc, // Identifies the device context for EMF spooling
LPWSTR pwszDriver, // Identfies the driver
int iEscape, // Specifies the escape function to be performed.
int cjInput, // Number of bytes of data pointed to by lpInData
LPCSTR lpInData, // Points to the input structure required
int cjOutput, // Number of bytes of data pointed to by lpOutData
LPSTR lpOutData // Points to the structure to receive output from
) // this escape.
{
int iRet = 0;
int cjIn, cjOut, cjData;
PLDC pldc;
if(hdc)
{
FIXUP_HANDLE(hdc);
// if we are EMF spooling then we need to record the call here
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
// don't allow them in 16bit metafiles
if (IS_METADC16_TYPE(hdc))
return(0);
DC_PLDC(hdc,pldc,iRet);
MFD2("NamedEscapeCalled %d\n", iEscape );
if (pldc->fl & (LDC_DOC_CANCELLED|LDC_SAP_CALLBACK))
{
if (pldc->fl & LDC_SAP_CALLBACK)
vSAPCallback(pldc);
if (pldc->fl & LDC_DOC_CANCELLED)
return(0);
}
if (pldc->iType == LO_METADC)
{
if(!MF_WriteNamedEscape(hdc,
pwszDriver,
iEscape,
cjInput,
lpInData))
{
WARNING("Error metafiling NameEscape\n");
return(0);
}
}
}
}
cjIn = (lpInData == NULL) ? 0 : cjInput;
cjOut = (lpOutData == NULL) ? 0 : cjOutput;
iRet = NtGdiExtEscape((HDC) 0,
pwszDriver,
wcslen(pwszDriver),
iEscape,cjIn,
(LPSTR)lpInData,
cjOut,lpOutData);
return(iRet);
}
/******************************Public*Routine******************************\
* DrawEscape *
* *
* Client side stub. *
* *
* History: *
* 02-Apr-1992 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
int WINAPI DrawEscape(
HDC hdc, // Identifies the device context.
int iEscape, // Specifies the escape function to be performed.
int cjIn, // Number of bytes of data pointed to by lpIn.
LPCSTR lpIn // Points to the input data.
)
{
int iRet = 0;
int cjInput;
FIXUP_HANDLE(hdc);
// printer specific stuff
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
// don't allow them 16bit metafiles
if (IS_METADC16_TYPE(hdc))
return(0);
DC_PLDC(hdc,pldc,iRet);
MFD2("Calling DrawEscape %d\n", iEscape );
if( ( pldc->fl & LDC_META_PRINT ) && ( iEscape != QUERYESCSUPPORT ) )
{
MF_WriteEscape( hdc, iEscape, cjIn, lpIn, EMR_DRAWESCAPE );
}
}
// Compute the buffer size we need. Since the in and out buffers
// get rounded up to multiples of 4 bytes, we need to simulate that
// here.
cjInput = (lpIn == NULL) ? 0 : ((cjIn+3)&-4);
iRet = NtGdiDrawEscape(hdc,iEscape,cjIn,(LPSTR)lpIn);
return(iRet);
}
/******************************Public*Routine******************************\
* DeviceCapabilitiesExA
*
* This never got implemented. The spooler suports DeviceCapabilities.
*
* History:
* 01-Aug-1991 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int WINAPI DeviceCapabilitiesExA(
LPCSTR pszDriver,
LPCSTR pszDevice,
LPCSTR pszPort,
int iIndex,
LPCSTR pb,
CONST DEVMODEA *pdm)
{
return(GDI_ERROR);
pszDriver;
pszDevice;
pszPort;
iIndex;
pb;
pdm;
}
/**************************************************************************\
*
* New to be implemented Api's for Windows95.
*
\**************************************************************************/
#if 0
WINGDIAPI int WINAPI GetTextCharsetInfo(
HDC hdc,
LPFONTSIGNATURE lpSig,
DWORD dwFlags)
{
return NtGdiGetTextCharsetInfo(hdc, lpSig, dwFlags);
}
#endif
WINGDIAPI int WINAPI GetTextCharset(
HDC hdc)
{
return NtGdiGetTextCharsetInfo(hdc, NULL, 0);
}
/******************************Public*Routine******************************\
*
* WINGDIAPI BOOL WINAPI TranslateCharsetInfo(
*
* client side stub
*
* History:
* 06-Jan-1995 -by- Bodin Dresevic [BodinD]
* Wrote it
\**************************************************************************/
// the definition of this variable is in ntgdi\inc\hmgshare.h
CHARSET_ARRAYS
WINGDIAPI BOOL WINAPI TranslateCharsetInfo(
DWORD *lpSrc,
LPCHARSETINFO lpCs,
DWORD dwFlags)
{
UINT i;
int index;
CHARSETINFO cs;
BOOL bRet = 0;
if (!lpCs)
return 0;
//
// zero these out, we dont support them here.
//
cs.fs.fsUsb[0] =
cs.fs.fsUsb[1] =
cs.fs.fsUsb[2] =
cs.fs.fsUsb[3] =
cs.fs.fsCsb[1] = 0;
switch (dwFlags )
{
case TCI_SRCCHARSET :
{
WORD src ;
src = LOWORD(PtrToUlong(lpSrc));
for ( i=0; i<NCHARSETS; i++ )
{
if ( charsets[i] == src )
{
cs.ciACP = codepages[i];
cs.ciCharset = src;
cs.fs.fsCsb[0] = fs[i];
bRet = 1;
break;
}
}
}
break;
case TCI_SRCCODEPAGE :
{
WORD src ;
src = LOWORD(PtrToUlong(lpSrc));
for ( i=0; i<NCHARSETS; i++ )
{
if ( codepages[i] == src )
{
cs.ciACP = src ;
cs.ciCharset = charsets[i] ;
cs.fs.fsCsb[0] = fs[i];
bRet = 1;
break;
}
}
}
break;
case TCI_SRCLOCALE :
{
// should only come from USER. It's used to find the charset of a
// keyboard layout, and the fonts that it can be used with (fontsigs).
// It is also used to obtain the fontsignature of the system font.
// Used in WM_INPUTLANGCHANGE message, and to determine wParam low-bit
// in WM_INPUTLANGCHANGEREQUEST message.
LOCALESIGNATURE ls;
int iRet;
iRet = GetLocaleInfoW((DWORD)(LOWORD(PtrToUlong(lpSrc))),
LOCALE_FONTSIGNATURE,
(LPWSTR)&ls,
0);
if (GetLocaleInfoW((DWORD)(LOWORD(PtrToUlong(lpSrc))),
LOCALE_FONTSIGNATURE,
(LPWSTR)&ls,
iRet)
)
{
for ( i=0; i<NCHARSETS; i++ )
{
if (fs[i] == ls.lsCsbDefault[0])
{
cs.ciACP = codepages[i];
cs.ciCharset = charsets[i] ;
cs.fs.fsCsb[0] = fs[i]; // a single fontsig
cs.fs.fsCsb[1] = ls.lsCsbSupported[0]; // mask of fontsigs
bRet = 1;
break;
}
}
}
}
break;
case TCI_SRCFONTSIG :
{
DWORD src;
//if(IsBadReadPtr(lpSrc, 8))
// return 0;
try
{
if (!(*(lpSrc+1)))
{
// we dont recognise ANY of the OEM code pages here!
src = *lpSrc;
for ( i=0; i<NCHARSETS; i++ )
{
if ( fs[i] == src )
{
cs.ciACP = codepages[i];
cs.ciCharset = charsets[i] ;
cs.fs.fsCsb[0] = src;
bRet = 1;
break;
}
}
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
break;
default:
GdiSetLastError(ERROR_INVALID_PARAMETER);
break;
}
if (bRet)
{
try
{
*lpCs = cs; // copy out
}
except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
return bRet;
}