Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1396 lines
40 KiB

/******************************Module*Header*******************************\
* Module Name: miscgdi.cxx
*
* Misc. GDI routines
*
* Created: 13-Aug-1990 by undead
*
* Copyright (c) 1989 Microsoft Corporation
\**************************************************************************/
#include "precomp.hxx"
extern ULONG gaulConvert[];
/******************************Public*Routine******************************\
* GreSaveScreenBits (hdev,iMode,iIdent,prcl) *
* *
* Passes the call to the device driver, or returns doing nothing. This *
* call is pretty fast, no locks are done. *
* *
* Fri 11-Sep-1992 -by- Patrick Haluptzok [patrickh] *
* Add cursor exclusion. *
* *
* Thu 27-Aug-1992 16:40:42 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
ULONG GreSaveScreenBits(HDEV hdev,ULONG iMode,ULONG iIdent,RECTL *prcl)
{
ULONG ulReturn = 0;
RECTL rcl = {0,0,0,0};
PDEVOBJ po(hdev);
VACQUIREDEVLOCK(po.pDevLock());
if (!po.bDisabled())
{
PFN_DrvSaveScreenBits pfn = PPFNDRV(po,SaveScreenBits);
if (pfn != (PFN_DrvSaveScreenBits) NULL)
{
DEVEXCLUDEOBJ dxo;
if (iMode == SS_FREE)
{
// Make if a very small rectangle.
prcl = &rcl;
}
//
// To Call vExclude directly you must check it's a Display PDEV
// and that cursor exclusion needs to be done.
//
ASSERTGDI(po.bDisplayPDEV(), "ERROR");
if (po.bNeedsSomeExcluding())
{
dxo.vExclude(hdev, prcl, (ECLIPOBJ *) NULL);
}
ulReturn = (*pfn)(po.pSurface()->pSurfobj(),iMode,iIdent,prcl);
}
}
#if DBG
else
{
if (iMode == SS_FREE)
WARNING("GreSaveScreenBits called to free memory in full screen - memory lost\n");
}
#endif
VRELEASEDEVLOCK(po.pDevLock());
return(ulReturn);
}
/******************************Public*Routine******************************\
* GreValidateSurfaceHandle
*
* This allows USER to validate handles passed to it by the client side.
*
* Returns: TRUE if handle is valid and of the correct type,
* FALSE otherwise.
*
* History:
* 06-Sep-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
BOOL GreValidateServerHandle(HANDLE hobj, ULONG ulType)
{
return(HmgValidHandle((HOBJ)hobj, (OBJTYPE) ulType));
}
/******************************Public*Routine******************************\
* GreSetBrushOrg
*
* Set the application defined brush origin into the DC
*
* Returns: Old brush origin
*
* History:
* 30-Oct-1990 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
BOOL GreSetBrushOrg(
HDC hdc,
int x,
int y,
LPPOINT ptl_)
{
DCOBJ dco(hdc);
PPOINTL ptl = (PPOINTL)ptl_;
if (dco.bValid())
{
if (ptl != NULL)
*ptl = dco.pdc->ptlBrushOrigin();
dco.pdc->ptlBrushOrigin((LONG)x,(LONG)y);
return(TRUE);
}
else
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
return(FALSE);
}
}
/******************************Public*Routine******************************\
* GreGetBrushOrg
*
* Returns: Old application brush origin
*
* History:
* 30-Oct-1990 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
BOOL GreGetBrushOrg(HDC hdc,PPOINT ptl_)
{
DCOBJ dco(hdc);
PPOINTL ptl = (PPOINTL)ptl_;
if (dco.bValid())
{
*ptl = dco.pdc->ptlBrushOrigin();
return(TRUE);
}
else
return(FALSE);
}
/******************************Public*Routine******************************\
* NtGdiGetDeviceCapsAll()
*
* Get all the adjustable device caps for the dc. Allows us to cache this
* information on the client side.
*
* NOTE: This function MUST mirror that in GreGetDeviceCaps!
*
* History:
* 09-Jan-1996 -by- Lingyun Wang [lingyunw]
* Made it based on GreGetDeviceCapsAll from the old client\server code.
\**************************************************************************/
BOOL
APIENTRY
NtGdiGetDeviceCapsAll(
HDC hdc,
PDEVCAPS pDevCaps
)
{
BOOL bRet = TRUE;
DEVCAPS devCapsTmp;
// Lock the destination and its transform.
DCOBJ dco(hdc);
// return FALSE if it is a invalid DC
if (!dco.bValid())
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
return(FALSE);
}
// Lock down the pdev
PDEVOBJ po(dco.hdev());
ASSERTGDI(po.bValid(), "Invalid PDEV");
__try
{
ProbeForWrite(pDevCaps, sizeof(DEVCAPS), sizeof(BYTE));
pDevCaps->ulVersion = po.GdiInfo()->ulVersion;
pDevCaps->ulTechnology = po.GdiInfo()->ulTechnology;
// Note that ul*Size fields are now in micrometers
pDevCaps->ulHorzSizeM = (po.GdiInfo()->ulHorzSize+500)/1000;
pDevCaps->ulVertSizeM = (po.GdiInfo()->ulVertSize+500)/1000;
pDevCaps->ulHorzSize = po.GdiInfo()->ulHorzSize;
pDevCaps->ulVertSize = po.GdiInfo()->ulVertSize;
pDevCaps->ulHorzRes = po.GdiInfo()->ulHorzRes;
pDevCaps->ulVertRes = po.GdiInfo()->ulVertRes;
pDevCaps->ulBitsPixel = po.GdiInfo()->cBitsPixel;
if (pDevCaps->ulBitsPixel == 15)
pDevCaps->ulBitsPixel = 16; // Some apps, such as PaintBrush or
// NetScape, break if we return 15bpp
pDevCaps->ulPlanes = po.GdiInfo()->cPlanes;
pDevCaps->ulNumPens = (po.GdiInfo()->ulNumColors == (ULONG)-1) ?
(ULONG)-1 : 5 * po.GdiInfo()->ulNumColors;
pDevCaps->ulNumFonts = po.cFonts();
pDevCaps->ulNumColors = po.GdiInfo()->ulNumColors;
pDevCaps->ulRasterCaps = po.GdiInfo()->flRaster;
pDevCaps->ulAspectX = po.GdiInfo()->ulAspectX;
pDevCaps->ulAspectY = po.GdiInfo()->ulAspectY;
pDevCaps->ulAspectXY = po.GdiInfo()->ulAspectXY;
pDevCaps->ulLogPixelsX = po.GdiInfo()->ulLogPixelsX;
pDevCaps->ulLogPixelsY = po.GdiInfo()->ulLogPixelsY;
pDevCaps->ulSizePalette = po.GdiInfo()->ulNumPalReg;
pDevCaps->ulColorRes = po.GdiInfo()->ulDACRed + po.GdiInfo()->ulDACGreen + po.GdiInfo()->ulDACBlue;
pDevCaps->ulPhysicalWidth = po.GdiInfo()->szlPhysSize.cx;
pDevCaps->ulPhysicalHeight = po.GdiInfo()->szlPhysSize.cy;
pDevCaps->ulPhysicalOffsetX = po.GdiInfo()->ptlPhysOffset.x;
pDevCaps->ulPhysicalOffsetY = po.GdiInfo()->ptlPhysOffset.y;
pDevCaps->ulTextCaps = po.GdiInfo()->flTextCaps;
pDevCaps->ulTextCaps |= (TC_OP_CHARACTER | TC_OP_STROKE | TC_CP_STROKE |
TC_UA_ABLE | TC_SO_ABLE);
if (po.GdiInfo()->ulTechnology != DT_PLOTTER)
pDevCaps->ulTextCaps |= TC_VA_ABLE;
pDevCaps->ulVRefresh = po.GdiInfo()->ulVRefresh;
pDevCaps->ulDesktopHorzRes = po.GdiInfo()->ulHorzRes;
pDevCaps->ulDesktopVertRes = po.GdiInfo()->ulVertRes;
pDevCaps->ulBltAlignment = po.GdiInfo()->ulBltAlignment;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
WARNING ("try-except failed IN NtGdiGetDeviceCapsAll\n");
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
return(bRet);
}
/******************************Public*Routine******************************\
* UpdateSharedDevCaps()
*
* Update the device caps in the shared memory
*
* NOTE: This function MUST mirror that in GreGetDeviceCaps!
*
* History:
* 09-Jan-1996 -by- Lingyun Wang [lingyunw]
* Made it based on GreGetDeviceCapsAll from the old client\server code.
\**************************************************************************/
BOOL
GreUpdateSharedDevCaps(
HDEV hdev
)
{
BOOL bRet = TRUE;
// Lock down the pdev
PDEVOBJ po(hdev);
if (po.bValid())
{
gpGdiDevCaps->ulVersion = po.GdiInfo()->ulVersion;
gpGdiDevCaps->ulTechnology = po.GdiInfo()->ulTechnology;
// Note that ul*Size fields are now in micrometers
gpGdiDevCaps->ulHorzSizeM = (po.GdiInfo()->ulHorzSize+500)/1000;
gpGdiDevCaps->ulVertSizeM = (po.GdiInfo()->ulVertSize+500)/1000;
gpGdiDevCaps->ulHorzSize = po.GdiInfo()->ulHorzSize;
gpGdiDevCaps->ulVertSize = po.GdiInfo()->ulVertSize;
gpGdiDevCaps->ulHorzRes = po.GdiInfo()->ulHorzRes;
gpGdiDevCaps->ulVertRes = po.GdiInfo()->ulVertRes;
gpGdiDevCaps->ulBitsPixel = po.GdiInfo()->cBitsPixel;
if (gpGdiDevCaps->ulBitsPixel == 15)
gpGdiDevCaps->ulBitsPixel = 16; // Some apps, such as PaintBrush or
// NetScape, break if we return 15bpp
gpGdiDevCaps->ulPlanes = po.GdiInfo()->cPlanes;
gpGdiDevCaps->ulNumPens = (po.GdiInfo()->ulNumColors == (ULONG)-1) ?
(ULONG)-1 : 5 * po.GdiInfo()->ulNumColors;
gpGdiDevCaps->ulNumFonts = po.cFonts();
gpGdiDevCaps->ulNumColors = po.GdiInfo()->ulNumColors;
gpGdiDevCaps->ulRasterCaps = po.GdiInfo()->flRaster;
gpGdiDevCaps->ulAspectX = po.GdiInfo()->ulAspectX;
gpGdiDevCaps->ulAspectY = po.GdiInfo()->ulAspectY;
gpGdiDevCaps->ulAspectXY = po.GdiInfo()->ulAspectXY;
gpGdiDevCaps->ulLogPixelsX = po.GdiInfo()->ulLogPixelsX;
gpGdiDevCaps->ulLogPixelsY = po.GdiInfo()->ulLogPixelsY;
gpGdiDevCaps->ulSizePalette = po.GdiInfo()->ulNumPalReg;
gpGdiDevCaps->ulColorRes = po.GdiInfo()->ulDACRed + po.GdiInfo()->ulDACGreen + po.GdiInfo()->ulDACBlue;
gpGdiDevCaps->ulPhysicalWidth = po.GdiInfo()->szlPhysSize.cx;
gpGdiDevCaps->ulPhysicalHeight = po.GdiInfo()->szlPhysSize.cy;
gpGdiDevCaps->ulPhysicalOffsetX = po.GdiInfo()->ptlPhysOffset.x;
gpGdiDevCaps->ulPhysicalOffsetY = po.GdiInfo()->ptlPhysOffset.y;
gpGdiDevCaps->ulTextCaps = po.GdiInfo()->flTextCaps;
gpGdiDevCaps->ulTextCaps |= (TC_OP_CHARACTER | TC_OP_STROKE | TC_CP_STROKE |
TC_UA_ABLE | TC_SO_ABLE);
if (po.GdiInfo()->ulTechnology != DT_PLOTTER)
gpGdiDevCaps->ulTextCaps |= TC_VA_ABLE;
gpGdiDevCaps->ulVRefresh = po.GdiInfo()->ulVRefresh;
gpGdiDevCaps->ulDesktopHorzRes = po.GdiInfo()->ulHorzRes;
gpGdiDevCaps->ulDesktopVertRes = po.GdiInfo()->ulVertRes;
gpGdiDevCaps->ulBltAlignment = po.GdiInfo()->ulBltAlignment;
}
else
{
ASSERTGDI(po.bValid(), "UpdateDevCaps -- Invalid PDEV");
bRet = FALSE;
}
return(bRet);
}
/******************************Public*Routine******************************\
* GreGetDeviceCaps
*
* Returns: device driver specific information
*
* NOTE: This function MUST mirror GreGetDeviceCapsAll and that in
* client\dcquery.c!
*
* History:
* 01-Mar-1992 -by- Donald Sidoroff [donalds]
* Rewritten to corrected GDIINFO structure.
*
* 30-Oct-1990 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
int GreGetDeviceCaps(HDC hdc, int lIndex)
{
// Init return value
int iRet = 0;
// Lock the destination and its transform.
DCOBJ dco(hdc);
if (dco.bValid())
{
// Lock down the pdev
PDEVOBJ po(dco.hdev());
ASSERTGDI(po.bValid(), "Invalid PDEV");
switch (lIndex)
{
case DRIVERVERSION: // Version = 0100h for now
iRet = (po.GdiInfo()->ulVersion);
break;
case TECHNOLOGY: // Device classification
iRet = (po.GdiInfo()->ulTechnology);
break;
case HORZSIZE: // Horizontal size in millimeters
iRet = (po.GdiInfo()->ulHorzSize+500)/1000;
break;
case VERTSIZE: // Vertical size in millimeters
iRet = (po.GdiInfo()->ulVertSize+500)/1000;
break;
case HORZRES: // Horizontal width in pixels
iRet = (po.GdiInfo()->ulHorzRes);
break;
case VERTRES: // Vertical height in pixels
iRet = (po.GdiInfo()->ulVertRes);
break;
case BITSPIXEL: // Number of bits per pixel
iRet = (po.GdiInfo()->cBitsPixel);
if (iRet == 15)
iRet = 16; // Some apps, such as PaintBrush or
// NetScape, break if we return 15bpp
break;
case PLANES: // Number of planes
iRet = (po.GdiInfo()->cPlanes);
break;
case NUMBRUSHES: // Number of brushes the device has
iRet = (-1);
break;
case NUMPENS: // Number of pens the device has
iRet = (po.GdiInfo()->ulNumColors == (ULONG)-1) ?
(ULONG)-1 : 5 * po.GdiInfo()->ulNumColors;
break;
case NUMMARKERS: // Number of markers the device has
iRet = (0);
break;
case NUMFONTS: // Number of fonts the device has
iRet = (po.cFonts());
break;
case NUMCOLORS: // Number of colors in color table
iRet = (po.GdiInfo()->ulNumColors);
break;
case PDEVICESIZE: // Size required for the device descriptor
iRet = (0);
break;
case CURVECAPS: // Curves capabilities
iRet = (CC_CIRCLES |
CC_PIE |
CC_CHORD |
CC_ELLIPSES |
CC_WIDE |
CC_STYLED |
CC_WIDESTYLED |
CC_INTERIORS |
CC_ROUNDRECT);
break;
case LINECAPS: // Line capabilities
iRet = (LC_POLYLINE |
LC_MARKER |
LC_POLYMARKER |
LC_WIDE |
LC_STYLED |
LC_WIDESTYLED |
LC_INTERIORS);
break;
case POLYGONALCAPS: // Polygonal capabilities
iRet = (PC_POLYGON |
PC_RECTANGLE |
PC_WINDPOLYGON |
PC_TRAPEZOID |
PC_SCANLINE |
PC_WIDE |
PC_STYLED |
PC_WIDESTYLED |
PC_INTERIORS);
break;
case TEXTCAPS: // Text capabilities
{
FLONG fl = po.GdiInfo()->flTextCaps;
// Engine will simulate vector fonts on raster devices.
if (po.GdiInfo()->ulTechnology != DT_PLOTTER)
fl |= TC_VA_ABLE;
// Turn underlining, strikeout. Engine will do it for device if needed.
fl |= (TC_UA_ABLE | TC_SO_ABLE);
// Return flag.
iRet = fl;
break;
}
case CLIPCAPS: // Clipping capabilities
iRet = (CP_RECTANGLE);
break;
case RASTERCAPS: // Bitblt capabilities
iRet = (po.GdiInfo()->flRaster);
break;
case ASPECTX: // Length of X leg
iRet = (po.GdiInfo()->ulAspectX);
break;
case ASPECTY: // Length of Y leg
iRet = (po.GdiInfo()->ulAspectY);
break;
case ASPECTXY: // Length of hypotenuse
iRet = (po.GdiInfo()->ulAspectXY);
break;
case LOGPIXELSX: // Logical pixels/inch in X
iRet = (po.GdiInfo()->ulLogPixelsX);
break;
case LOGPIXELSY: // Logical pixels/inch in Y
iRet = (po.GdiInfo()->ulLogPixelsY);
break;
case SIZEPALETTE: // # entries in physical palette
iRet = (po.GdiInfo()->ulNumPalReg);
break;
case NUMRESERVED: // # reserved entries in palette
iRet = (20);
break;
case COLORRES:
iRet = (po.GdiInfo()->ulDACRed + po.GdiInfo()->ulDACGreen + po.GdiInfo()->ulDACBlue);
break;
case PHYSICALWIDTH: // Physical Width in device units
iRet = (po.GdiInfo()->szlPhysSize.cx);
break;
case PHYSICALHEIGHT: // Physical Height in device units
iRet = (po.GdiInfo()->szlPhysSize.cy);
break;
case PHYSICALOFFSETX: // Physical Printable Area x margin
iRet = (po.GdiInfo()->ptlPhysOffset.x);
break;
case PHYSICALOFFSETY: // Physical Printable Area y margin
iRet = (po.GdiInfo()->ptlPhysOffset.y);
break;
case VREFRESH: // Vertical refresh rate of the device
iRet = (po.GdiInfo()->ulVRefresh);
break;
//
// NOTE : temporarily disable this feature for the BETA.
// We will reenable when the engine does it.
//
case DESKTOPHORZRES: // Width of entire virtual desktop
iRet = (po.GdiInfo()->ulHorzRes);
break;
case DESKTOPVERTRES: // Height of entire virtual desktop
iRet = (po.GdiInfo()->ulVertRes);
break;
case BLTALIGNMENT: // Preferred blt alignment
iRet = (po.GdiInfo()->ulBltAlignment);
break;
case HORZSIZEM: // Horizontal size in millimeters/1000
iRet = po.GdiInfo()->ulHorzSize;
break;
case VERTSIZEM: // Vertical size in millimeters/1000
iRet = po.GdiInfo()->ulVertSize;
break;
default:
iRet = 0;
}
}
return(iRet);
}
#if 0
/******************************Public*Routine******************************\
* ULONG GreGetResourceId(HDEV, ULONG, ULONG)
*
* History:
* Fri 10-Dec-1993 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
ULONG GreGetResourceId(HDEV hdev, ULONG ulResId, ULONG ulResType)
{
ULONG ulRet = 0;
PDEVOBJ po(hdev);
PFN_DrvGetResourceId pfn = PPFNDRV(po,GetResourceId);
if (pfn != (PFN_DrvGetResourceId) NULL)
{
ulRet = (*pfn)(ulResId, ulResType);
}
return ulRet;
}
#endif
/******************************Public*Routine******************************\
* BOOL GreDeleteObject(HOBJ)
*
* History:
* Fri 13-Sep-1991 -by- Patrick Haluptzok [patrickh]
* added DC deletion
*
* Tue 27-Nov-1990 -by- Patrick Haluptzok [patrickh]
* added palette deletion, surface deletion, brush deletion.
*
* Wed 22-Aug-1990 Greg Veres [w-gregv]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GreDeleteObject (HANDLE hobj)
{
int ii;
// don't allow deletion of stock objects, just succeed
if (HmgStockObj(hobj))
{
return(TRUE);
}
switch (HmgObjtype(hobj))
{
case RGN_TYPE:
return(bDeleteRegion((HRGN) hobj));
case SURF_TYPE:
return(bDeleteSurface((HSURF)hobj));
case PAL_TYPE:
return(bDeletePalette((HPAL) hobj));
case LFONT_TYPE:
// see if its in cfont list.
for (ii = 0; ii < MAX_PUBLIC_CFONT; ++ii)
{
if (gpGdiSharedMemory->acfPublic[ii].hf == hobj)
{
// just nuke the hfont as this invalidates the whole entry
gpGdiSharedMemory->acfPublic[ii].hf = 0;
break;
}
}
return(bDeleteFont((HLFONT) hobj, FALSE));
case BRUSH_TYPE:
return(bDeleteBrush((HBRUSH) hobj, FALSE));
case DC_TYPE:
return(bDeleteDCInternal((HDC) hobj,TRUE,FALSE));
default:
return(FALSE);
}
}
/******************************Public*Routine******************************\
* NtGdiDeleteObjectApp()
*
* Same as DeleteObject() but doesn't allow public objects to be deleted.
* This should only be called from server.c coming from the client. User
* and console should call the DeleteObject().
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiDeleteObjectApp(
HANDLE hobj
)
{
ULONG objt;
// don't allow deletion of stock objects, just succeed
if (HmgStockObj(hobj))
{
return(TRUE);
}
objt = HmgObjtype(hobj);
// check if it is a public object. If it is, check if it is a public deletable
// surface set by user.
if (GreGetObjectOwner((HOBJ)hobj,objt) == OBJECT_OWNER_PUBLIC)
{
if (objt == SURF_TYPE)
{
WARNING("Trying to delete public surface!");
}
#if 0
BOOL bMsg = TRUE;
if (objt == BRUSH_TYPE)
{
BRUSHSELOBJ bo(hbrush);
if (bo.bValid() || bo.bIsGlobal())
bMsg = FALSE;
}
if (bMsg)
{
DbgPrint("GDI Warning: app trying to delete public object %lx\n",hobj);
}
#endif
//
// return FALSE if hobj == NULL
// otherwise TRUE
//
return(hobj != NULL);
}
switch (objt)
{
case RGN_TYPE:
return(bDeleteRegion((HRGN) hobj));
case SURF_TYPE:
return(bDeleteSurface((HSURF)hobj));
case PAL_TYPE:
return(bDeletePalette((HPAL) hobj));
case LFONT_TYPE:
return(bDeleteFont((HLFONT) hobj, FALSE));
case BRUSH_TYPE:
return(bDeleteBrush((HBRUSH) hobj, FALSE));
case DC_TYPE:
// don't allow deletion of DC's by an app if the undeletable flag is set
return(bDeleteDCInternal((HDC) hobj,FALSE,FALSE));
default:
return(FALSE);
}
}
/******************************Public*Routine******************************\
* cjGetBrushOrPen
*
* Gets brush or pen object data.
*
* For extended pens, some information such as the style array are kept
* only on this, the server side. Most of the brush data is also kept
* on the client side for GetObject.
*
* returns: Number of bytes needed if pvDest == NULL, else bytes copied out.
* For error it returns 0.
*
* History:
* Thu 23-Mar-1992 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
LONG cjGetBrushOrPen(HANDLE hobj, int iCount, LPVOID pvDest)
{
LONG lRet = 0;
BRUSHSELOBJ bro((HBRUSH) hobj);
// NOTE SIZE: Most of this is bunk, since for NT all brush data is kept on the
// client side, and so some of this code path won't even be
// executed. [andrewgo]
//
// And for DOS, we would return some fields as zero, whereas under
// NT we would always return what we were given. [andrewgo]
if (bro.bValid())
{
if (bro.bIsOldStylePen())
{
// Old style pen...
bSyncBrushObj(bro.pbrush());
if (pvDest == (LPVOID) NULL)
{
lRet = sizeof(LOGPEN);
}
else if (iCount >= sizeof(LOGPEN))
{
if ((iCount == (int) sizeof(EXTLOGPEN)) &&
((UINT) bro.flStylePen() == PS_NULL))
{
//moved the NULL extended pen handling from client
//side to server side
PEXTLOGPEN pelp = (PEXTLOGPEN) pvDest;
pelp->elpPenStyle = PS_NULL;
pelp->elpWidth = 0;
pelp->elpBrushStyle = 0;
pelp->elpColor = 0;
pelp->elpHatch = 0;
pelp->elpNumEntries = 0;
lRet = sizeof(EXTLOGPEN);
}
else
{
// Fill in the logical pen.
((LOGPEN *) pvDest)->lopnStyle = (UINT) bro.flStylePen();
((LOGPEN *) pvDest)->lopnWidth.x = (int) bro.lWidthPen();
((LOGPEN *) pvDest)->lopnWidth.y = 0;
((LOGPEN *) pvDest)->lopnColor = bro.clrPen();
lRet = sizeof(LOGPEN);
}
}
}
else if (bro.bIsPen())
{
// Extended pen...
ULONG cstyle = (bro.bIsUserStyled()) ? bro.cstyle() : 0;
int cj = (int) (sizeof(EXTLOGPEN) - sizeof(DWORD) +
sizeof(DWORD) * (SIZE_T) cstyle);
if (pvDest == (LPVOID) NULL)
{
lRet = cj;
}
else if (iCount >= cj)
{
PEXTLOGPEN pelp = (PEXTLOGPEN) pvDest;
pelp->elpPenStyle = (UINT) bro.flStylePen();
pelp->elpWidth = (UINT) bro.lWidthPen();
pelp->elpNumEntries = cstyle;
if (cstyle > 0)
{
// We can't just do a RtlCopyMemory for cosmetics, because
// we don't know how the LONGs are packed in the
// FLOAT_LONG array:
PFLOAT_LONG pelSrc = bro.pstyle();
PLONG plDest = (PLONG) &pelp->elpStyleEntry[0];
for (; cstyle > 0; cstyle--)
{
if (bro.bIsCosmetic())
*plDest = pelSrc->l;
else
{
EFLOATEXT efLength(pelSrc->e);
BOOL b = efLength.bEfToL(*plDest);
ASSERTGDI(b, "Shouldn't have overflowed");
}
plDest++;
pelSrc++;
}
}
// The client side GetObject will fill in the rest of the
// EXTLOGPEN struct. i.e. elpBrushStyle, elpColor, and elpHatch.
// Changed: added these here -30-11-94 -by- Lingyunw
// added lBrushStyle and lHatch to PEN
pelp->elpBrushStyle = bro.lBrushStyle();
pelp->elpColor = bro.crColor();
pelp->elpHatch = (ULONG)bro.lHatch();
lRet = cj;
}
}
else
{
// Brush...
if (pvDest == (LPVOID) NULL)
{
lRet = sizeof(LOGBRUSH);
}
else if (iCount >= sizeof(LOGBRUSH))
{
// make sure the kernel attributes match
bSyncBrushObj(bro.pbrush());
// Fill in logical brush. Figure out what type it is.
// Duplicates of this info is kept on the client side,
// so most calls won't even get here:
if (bro.flAttrs() & BR_IS_SOLID)
{
((LOGBRUSH *) pvDest)->lbStyle = BS_SOLID;
((LOGBRUSH *) pvDest)->lbColor = bro.crColor();
((LOGBRUSH *) pvDest)->lbHatch = 0;
}
else if (bro.flAttrs() & BR_IS_BITMAP)
{
((LOGBRUSH *) pvDest)->lbStyle = BS_PATTERN;
((LOGBRUSH *) pvDest)->lbColor = 0;
((LOGBRUSH *) pvDest)->lbHatch = (LONG)bro.hbmClient();
}
else if (bro.flAttrs() & BR_IS_HATCH)
{
((LOGBRUSH *) pvDest)->lbStyle = BS_HATCHED;
((LOGBRUSH *) pvDest)->lbColor = bro.crColor();
((LOGBRUSH *) pvDest)->lbHatch = bro.ulStyle();
}
else if (bro.flAttrs() & BR_IS_NULL)
{
((LOGBRUSH *) pvDest)->lbStyle = BS_HOLLOW;
((LOGBRUSH *) pvDest)->lbColor = 0;
((LOGBRUSH *) pvDest)->lbHatch = 0;
}
else if (bro.flAttrs() & BR_IS_DIB)
{
// Could be BS_DIBPATTERN or BS_DIBPATTERNPT, but we'll just
// return BS_DIBPATTERN.
((LOGBRUSH *) pvDest)->lbStyle = BS_DIBPATTERN;
((LOGBRUSH *) pvDest)->lbColor = bro.crColor();
((LOGBRUSH *) pvDest)->lbHatch = 0;
}
else
RIP("ERROR GreGetObject invalid brush type");
lRet = sizeof(LOGBRUSH);
}
}
}
else
{
SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
}
return(lRet);
}
/******************************Public*Routine******************************\
* GreGetObject
*
* API function
*
* returns: number of bytes needed if pvDest == NULL, else bytes copied out
* for error it returns 0
*
* in case a log font object is requested, the function will fill the buffer with
* as many bytes of the EXTLOGFONT structure as requested. If a caller
* wants a LOGFONTW structure in the buffer, he should specify
* ulCount == sizeof(LOGFONTW)
* The function will copy the first sizeof(LOGFONTW) bytes of the EXTLOGFONTW
* structure to the buffer, which is precisely the LOGFONTW structure. The rest
* of the EXTLOGFONTW structure will be chopped off.
*
* History:
*
* Thu 30-Jan-1992 -by- J. Andrew Goossen [andrewgo]
* added extended pen support.
*
* Wed 21-Aug-1991 -by- Bodin Dresevic [BodinD]
* update: converted to return EXTLOGFONTW
*
* Fri 24-May-1991 -by- Patrick Haluptzok [patrickh]
* added first pass pen and brush stuff.
*
* Tue 24-Apr-1991 -by- Patrick Haluptzok [patrickh]
* added surface stuff.
*
* 08-Dec-1990 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
int APIENTRY GreExtGetObjectW(HANDLE hobj, int ulCount, LPVOID pvDest)
{
int cRet = 0;
switch (HmgObjtype(hobj))
{
case PAL_TYPE:
cRet = 2;
if (pvDest != NULL)
{
if (ulCount < 2)
{
cRet = 0;
}
else
{
SEMOBJ semo(gpsemPalette);
{
EPALOBJ pal((HPALETTE) hobj);
if (!(pal.bValid()))
cRet = 0;
else
*((PUSHORT) pvDest) = (USHORT) (pal.cEntries());
}
}
}
break;
case LFONT_TYPE:
// The output object is assumed to be
// an EXTLOGFONTW structure.
// client side shall do the translation to LOGFONT if necessary
if (pvDest != (LPVOID) NULL)
{
LFONTOBJ lfo((HLFONT) hobj);
if (!lfo.bValid())
{
WARNING("GreGetObject(): bad handle\n");
}
else
{
SIZE_T cjCopy = MIN((SIZE_T) ulCount, sizeof(EXTLOGFONTW));
RtlCopyMemory((PVOID) pvDest, (PVOID) lfo.plfw(), (UINT) cjCopy);
cRet = (ULONG) cjCopy;
}
}
else
{
cRet = sizeof(EXTLOGFONTW);
}
break;
case SURF_TYPE:
if (pvDest != (LPVOID) NULL)
{
cRet = 0;
if (ulCount >= (int)sizeof(BITMAP))
{
SURFREF SurfBm((HSURF) hobj);
if ((SurfBm.bValid()) &&
((SurfBm.ps->iType() == STYPE_DEVBITMAP) ||
(SurfBm.ps->iType() == STYPE_BITMAP)))
{
BITMAP *pbm = (BITMAP *) pvDest;
pbm->bmType = 0;
pbm->bmWidth = SurfBm.ps->sizl().cx;
pbm->bmHeight = SurfBm.ps->sizl().cy;
pbm->bmBitsPixel = (WORD) gaulConvert[SurfBm.ps->iFormat()];
pbm->bmWidthBytes = ((SurfBm.ps->sizl().cx * pbm->bmBitsPixel + 15) >> 4) << 1;
pbm->bmPlanes = 1;
pbm->bmBits = (LPSTR) NULL;
cRet = sizeof(BITMAP);
// Get the bitmapinfoheader for the dibsection if the buffer
// can hold it.
if (SurfBm.ps->bDIBSection())
{
// Win95 compatability. They fill in the bits even if it
// is not big enough for a full DIBSECTION
pbm->bmBits = (LPSTR) SurfBm.ps->pvBits();
if (ulCount >= sizeof(DIBSECTION))
{
PBITMAPINFOHEADER pbmih = &((DIBSECTION *)pvDest)->dsBmih;
pbmih->biSize = sizeof(BITMAPINFOHEADER);
pbmih->biBitCount = 0;
if (GreGetDIBitsInternal(0,(HBITMAP)hobj,0,0,NULL,
(PBITMAPINFO)pbmih,DIB_RGB_COLORS,0,
sizeof(DIBSECTION)))
{
cRet = sizeof(DIBSECTION);
}
XEPALOBJ pal(SurfBm.ps->ppal());
if ((pal.bValid()) && (pal.bIsBitfields()))
{
((DIBSECTION *)pvDest)->dsBitfields[0] = pal.flRed();
((DIBSECTION *)pvDest)->dsBitfields[1] = pal.flGre();
((DIBSECTION *)pvDest)->dsBitfields[2] = pal.flBlu();
}
else
{
((DIBSECTION *)pvDest)->dsBitfields[0] = 0;
((DIBSECTION *)pvDest)->dsBitfields[1] = 0;
((DIBSECTION *)pvDest)->dsBitfields[2] = 0;
}
((DIBSECTION *)pvDest)->dshSection = SurfBm.ps->hDIBSection();
((DIBSECTION *)pvDest)->dsOffset = SurfBm.ps->dwOffset();
}
}
}
}
}
else
{
cRet = sizeof(BITMAP);
}
break;
case BRUSH_TYPE:
cRet = (int) cjGetBrushOrPen(hobj, ulCount, pvDest);
break;
default:
break;
}
return(cRet);
}
/******************************Public*Routine******************************\
* GreGetStockObject
*
* API function
*
* returns the handle to the stock object requested.
*
* History:
* 08-Dec-1990 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
HANDLE gahStockObjects[PRIV_STOCK_LAST+1] = {0};
HANDLE GreGetStockObject(int ulIndex)
{
if (ulIndex <= PRIV_STOCK_LAST)
{
return(gahStockObjects[ulIndex]);
}
else
{
return(0);
}
}
BOOL bSetStockObject(
HANDLE h,
int iObj
)
{
if (h)
{
gahStockObjects[iObj] = (HANDLE)((ULONG)h | GDISTOCKOBJ);
HmgModifyHandleType((HOBJ) gahStockObjects[iObj]);
}
return(h != NULL);
}
/******************************Public*Routine******************************\
* BOOL GreGetColorAdjustment
*
* Get the color adjustment data of the given DC.
*
* History:
* 25-Aug-1992 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GreGetColorAdjustment(HDC hdc, COLORADJUSTMENT *pca)
{
DCOBJ dco(hdc);
BOOL Status;
if (!dco.bValid())
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
Status = FALSE;
} else {
// Retrieve info from the DC. Mask out the internal flag.
*pca = *dco.pColorAdjustment();
pca->caFlags &= (CA_NEGATIVE | CA_LOG_FILTER);
Status = TRUE;
}
return Status;
}
/******************************Public*Routine******************************\
* BOOL GreSetColorAdjustment
*
* Set the color adjustment data of the given DC.
*
* History:
* 25-Aug-1992 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GreSetColorAdjustment(HDC hdc, COLORADJUSTMENT *pcaNew)
{
DCOBJ dco(hdc);
BOOL Status;
if (!dco.bValid())
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
Status = FALSE;
} else {
// Store info into the DC. Turn off any flags that we don't support.
*dco.pColorAdjustment() = *pcaNew;
dco.pColorAdjustment()->caFlags &= (CA_NEGATIVE | CA_LOG_FILTER);
Status = TRUE;
}
return Status;
}
/******************************Public*Routine******************************\
* HANDLE GreCreateClientObj()
*
* A ClientObj contains no data. It is purly to provide a handle to the
* client for objects such as metafiles that exist only on the client side.
*
* ulType is a client type.
*
* History:
* 17-Jan-1995 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
HANDLE GreCreateClientObj(
ULONG ulType)
{
HANDLE h = NULL;
if(ulType & INDEX_MASK)
{
WARNING("GreCreateClientObj: bad type\n");
return(h);
}
PVOID pv = ALLOCOBJ(sizeof(OBJECT), CLIENTOBJ_TYPE, FALSE);
if (pv)
{
h = HmgInsertObject(pv, 0, CLIENTOBJ_TYPE);
if (!h)
{
WARNING("GreCreateClientObj: HmgInsertObject failed\n");
FREEOBJ(pv, CLIENTOBJ_TYPE);
}
else
{
pv = HmgLock((HOBJ) h,CLIENTOBJ_TYPE);
if (pv != NULL)
{
h = MODIFY_HMGR_TYPE(h,ulType);
HmgModifyHandleType((HOBJ)h);
DEC_EXCLUSIVE_REF_CNT(pv);
}
else
{
RIP("GreCreateClientObj failed lock\n");
}
}
}
else
{
WARNING("GreCreateClientObj(): ALLOCOBJ failed\n");
}
return(h);
}
/******************************Public*Routine******************************\
*
*
* History:
* 17-Jan-1995 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL GreDeleteClientObj(
HANDLE h)
{
PVOID pv = HmgRemoveObject((HOBJ)h, 0, 0, TRUE, CLIENTOBJ_TYPE);
if (pv != NULL)
{
FREEOBJ(pv, CLIENTOBJ_TYPE);
return(TRUE);
}
else
{
WARNING("GreDeleteClientObj: HmgRemoveObject failed\n");
return(FALSE);
}
}
/******************************Public*Routine******************************\
* NtGdiPerf()
*
* routine only here for the purpose of getting performance numbers
*
* Warnings:
*
* History:
* 25-Jul-1995 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL gbEscTouch = 4;
int gxxx;
int
APIENTRY
NtGdiPerf(
HDC hdc,
int iEsc,
PVOID pvIn
)
{
__try
{
if (gbEscTouch & 1)
{
if (iEsc == 5)
gxxx = (*(int *)((PENTRY)pvIn)->pUser);
else
gxxx = (int)((PENTRY)pvIn)->pUser;
}
if (hdc)
{
// Locate the surface.
DCOBJ dco(hdc);
if (!dco.bValid())
return(0);
if (gbEscTouch & 2)
gxxx = dco.pdc->crTextClr();
if (gbEscTouch & 4)
{
if (iEsc == 5)
gxxx = (*(int *)((PENTRY)pvIn)->pUser);
else
gxxx = ((int)((PENTRY)pvIn)->pUser);
}
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
return(1);
}