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.
 
 
 
 
 
 

8584 lines
211 KiB

/******************************Module*Header*******************************\
* Module Name: priv.c
* This file contains stubs for calls made by USERSRVL
*
* Created: 01-Nov-1994 07:45:35
* Author: Eric Kutter [erick]
*
* Copyright (c) 1993-1999 Microsoft Corporation
*
\**************************************************************************/
#include "engine.h"
#include "winfont.h"
#include "server.h"
#include "dciddi.h"
#include "limits.h"
#include "drvsup.hxx"
#ifdef DBGEXCEPT
int bStopExcept = FALSE;
int bWarnExcept = FALSE;
#endif
#define DWORD_TO_FLOAT(dw) (*(PFLOAT)(PDWORD)&(dw))
#define DWORD_TO_FLOATL(dw) (*(FLOATL *)(PDWORD)&(dw))
typedef struct {
ULONG uM11;
ULONG uM12;
ULONG uM21;
ULONG uM22;
ULONG uDx;
ULONG uDy;
} ULONGXFORM, *PULONGXFORM;
VOID ProbeAndWriteBuffer(PVOID Dst, PVOID Src, ULONG Length)
{
if (((ULONG_PTR)Dst + Length <= (ULONG_PTR)Dst) ||
((ULONG_PTR)Dst + Length > (ULONG_PTR)MM_USER_PROBE_ADDRESS)) {
*(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;
}
RtlCopyMemory(Dst, Src, Length);
return;
}
VOID ProbeAndWriteAlignedBuffer(PVOID Dst, PVOID Src, ULONG Length, ULONG Alignment)
{
ASSERT(((Alignment) == 1) || ((Alignment) == 2) ||
((Alignment) == 4) || ((Alignment) == 8) ||
((Alignment) == 16));
if (((ULONG_PTR)Dst + Length <= (ULONG_PTR)Dst) ||
((ULONG_PTR)Dst + Length > (ULONG_PTR) MM_USER_PROBE_ADDRESS) ||
((((ULONG_PTR)Dst) & (Alignment - 1)) != 0)) {
*(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;
}
RtlCopyMemory(Dst, Src, Length);
return;
}
/******************************Public*Routine******************************\
* bConvertDwordToFloat
*
* This routine casts a DWORD to a float, and checks whether the float
* is valid (on the Alpha). This is accomplished by doing a floating
* point operation and catching the exception if one is generated.
*
* Arguments:
*
* dword - the float before the cast
* *floatl - a pointer to a float that will receive the value after the
* cast
*
* Return Value:
*
* TRUE for valid floats, FALSE otherwise.
*
* History:
*
* 13-May-1998 -by- Ori Gershony [OriG]
*
\**************************************************************************/
BOOL
bConvertDwordToFloat(
DWORD dword,
FLOATL *floatl
)
{
BOOL bRet=TRUE;
try
{
*floatl = DWORD_TO_FLOATL(dword);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
bRet = FALSE;
}
return bRet;
}
/******************************Public*Routine******************************\
*
* ProbeAndConvertXFORM
*
* This routine probe and copy a user mode xform into kernel mode address,
* At the same time, it checks if the each FLOAT in the XFORM is valid, to prevent
* us to get into a floating point trap on ALPHA. Refer to bConvertDwordToFloat
* for more info.
*
* History:
* 11/24/98 by Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
BOOL
ProbeAndConvertXFORM(
XFORML *kpXform,
XFORML *pXform
)
{
BOOL bRet=TRUE;
try
{
ULONGXFORM *pUXform = (ULONGXFORM *)kpXform;
ProbeForRead(pUXform, sizeof(ULONGXFORM), sizeof(BYTE));
bRet = (bConvertDwordToFloat (pUXform->uM11, &(pXform->eM11))) &&
(bConvertDwordToFloat (pUXform->uM12, &(pXform->eM12))) &&
(bConvertDwordToFloat (pUXform->uM21, &(pXform->eM21))) &&
(bConvertDwordToFloat (pUXform->uM22, &(pXform->eM22))) &&
(bConvertDwordToFloat (pUXform->uDx, &(pXform->eDx))) &&
(bConvertDwordToFloat (pUXform->uDy, &(pXform->eDy)));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
bRet = FALSE;
}
return bRet;
}
/******************************Public*Routine******************************\
*
* NtGdiGetCharacterPlacementW
*
* History:
* 26-Jul-1995 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
#define ALIGN4(X) (((X) + 3) & ~3)
DWORD NtGdiGetCharacterPlacementW(
HDC hdc,
LPWSTR pwsz,
int nCount,
int nMaxExtent,
LPGCP_RESULTSW pgcpw,
DWORD dwFlags
)
{
DWORD dwRet = 0;
BOOL bOk = TRUE; // only change is something goes wrong
LPWSTR pwszTmp = NULL; // probe for read
ULONG cjW = 0;
ULONG dpOutString = 0;
ULONG dpOrder = 0;
ULONG dpDx = 0;
ULONG dpCaretPos = 0;
ULONG dpClass = 0;
ULONG dpGlyphs = 0;
DWORD cjWord, cjDword;
LPGCP_RESULTSW pgcpwTmp = NULL;
VOID *pv = NULL;
// it is much easier to structure the code if we copy pgcpw locally
// at the beginning.
GCP_RESULTSW gcpwLocal;
// valitidy checking
if ((nCount < 0) || ((nMaxExtent < 0) && (nMaxExtent != -1)) || !pwsz)
{
return dwRet;
}
if (pgcpw)
{
try
{
// we are eventually going to want to write to this structure
// so we will do ProbeForWrite now, which will probe the structure
// for both writing and reading. Otherwise, at this time
// ProbeForRead would suffice.
ProbeForWrite(pgcpw, sizeof(GCP_RESULTSW), sizeof(DWORD));
gcpwLocal = *pgcpw;
// take nCount to be the smaller of the nCounts and gcpwLocal.nGlyphs
// Win 95 does the same thing [bodind]
if (nCount > (int)gcpwLocal.nGlyphs)
nCount = (int)gcpwLocal.nGlyphs;
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(1);
return dwRet;
}
}
// Check for overflow of cjByte, cjWord, and cjDword (cjByte is implicit
// in handling of gcpwLocal.lpClass case below).
if (nCount > (MAXIMUM_POOL_ALLOC / sizeof(DWORD)))
{
return dwRet;
}
cjWord = (DWORD)nCount * sizeof(WCHAR);
cjDword = (DWORD)nCount * sizeof(DWORD);
// if pgcpw != NULL, pgcpw may contain some input data and it may
// point to some output data.
if (pgcpw)
{
cjW = sizeof(GCP_RESULTSW);
if (gcpwLocal.lpOutString)
{
dpOutString = cjW;
cjW += ALIGN4(cjWord);
if (cjW < dpOutString)
return dwRet;
}
if (gcpwLocal.lpOrder)
{
dpOrder = cjW;
cjW += cjDword;
if (cjW < dpOrder)
return dwRet;
}
if (gcpwLocal.lpDx)
{
dpDx = cjW;
cjW += cjDword;
if (cjW < dpDx)
return dwRet;
}
if (gcpwLocal.lpCaretPos)
{
dpCaretPos = cjW;
cjW += cjDword;
if (cjW < dpCaretPos)
return dwRet;
}
if (gcpwLocal.lpClass)
{
dpClass = cjW;
cjW += ALIGN4(sizeof(char) * nCount);
if (cjW < dpClass)
return dwRet;
}
if (gcpwLocal.lpGlyphs)
{
dpGlyphs = cjW;
cjW += cjWord;
if (cjW < dpGlyphs)
return dwRet;
}
}
// alloc mem for gcpw and the string
if (cjW <= (MAXIMUM_POOL_ALLOC - cjWord))
pv = AllocFreeTmpBuffer(cjW + cjWord);
if (pv)
{
pwszTmp = (WCHAR*)((BYTE*)pv + cjW);
if (pgcpw)
{
pgcpwTmp = (LPGCP_RESULTSW)pv;
if (gcpwLocal.lpOutString)
pgcpwTmp->lpOutString = (LPWSTR)((BYTE *)pgcpwTmp + dpOutString);
else
pgcpwTmp->lpOutString = NULL;
if (gcpwLocal.lpOrder)
pgcpwTmp->lpOrder = (UINT FAR*)((BYTE *)pgcpwTmp + dpOrder);
else
pgcpwTmp->lpOrder = NULL;
if (gcpwLocal.lpDx)
pgcpwTmp->lpDx = (int FAR *)((BYTE *)pgcpwTmp + dpDx);
else
pgcpwTmp->lpDx = NULL;
if (gcpwLocal.lpCaretPos)
pgcpwTmp->lpCaretPos = (int FAR *)((BYTE *)pgcpwTmp + dpCaretPos);
else
pgcpwTmp->lpCaretPos = NULL;
if (gcpwLocal.lpClass)
pgcpwTmp->lpClass = (LPSTR)((BYTE *)pgcpwTmp + dpClass);
else
pgcpwTmp->lpClass = NULL;
if (gcpwLocal.lpGlyphs)
pgcpwTmp->lpGlyphs = (LPWSTR)((BYTE *)pgcpwTmp + dpGlyphs);
else
pgcpwTmp->lpGlyphs = NULL;
pgcpwTmp->lStructSize = cjW;
pgcpwTmp->nGlyphs = nCount;
}
// check the memory with input data:
try
{
ProbeAndReadBuffer(pwszTmp, pwsz, cjWord);
if ((dwFlags & GCP_JUSTIFYIN) && pgcpw && gcpwLocal.lpDx)
{
// must probe for read, lpDx contains input explaining which glyphs to
// use as spacers for in justifying string
ProbeAndReadBuffer(pgcpwTmp->lpDx,gcpwLocal.lpDx, cjDword);
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(2);
// SetLastError(GetExceptionCode());
bOk = FALSE;
}
if (bOk)
{
dwRet = GreGetCharacterPlacementW(hdc, pwszTmp,(DWORD)nCount,
(DWORD)nMaxExtent,
pgcpwTmp, dwFlags);
if (dwRet && pgcpw) // copy data out
{
try
{
// ProbeForWrite(pgcpw, sizeof(GCP_RESULTSW), sizeof(DWORD));
// we did this above, see the comment
pgcpw->nMaxFit = pgcpwTmp->nMaxFit;
pgcpw->nGlyphs = nCount = pgcpwTmp->nGlyphs;
cjWord = (DWORD)nCount * 2;
cjDword = (DWORD)nCount * 4;
if (gcpwLocal.lpOutString)
{
ProbeAndWriteBuffer(gcpwLocal.lpOutString, pgcpwTmp->lpOutString,
cjWord);
}
if (gcpwLocal.lpOrder)
{
ProbeAndWriteBuffer(gcpwLocal.lpOrder, pgcpwTmp->lpOrder, cjDword);
}
if (gcpwLocal.lpDx)
{
ProbeAndWriteBuffer(gcpwLocal.lpDx, pgcpwTmp->lpDx, cjDword);
}
if (gcpwLocal.lpCaretPos)
{
ProbeAndWriteBuffer(gcpwLocal.lpCaretPos, pgcpwTmp->lpCaretPos,
cjDword);
}
if (gcpwLocal.lpClass)
{
ProbeAndWriteBuffer(gcpwLocal.lpClass, pgcpwTmp->lpClass, nCount);
}
if (gcpwLocal.lpGlyphs)
{
ProbeAndWriteBuffer(gcpwLocal.lpGlyphs, pgcpwTmp->lpGlyphs, cjWord);
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(3);
// SetLastError(GetExceptionCode());
bOk = FALSE;
}
}
}
FreeTmpBuffer(pv);
}
else
{
bOk = FALSE;
}
return (bOk ? dwRet : 0);
}
/*******************************************************************\
* pbmiConvertInfo *
* *
* Converts BITMAPCOREHEADER into BITMAPINFOHEADER *
* copies the the color table *
* *
* 10-1-95 -by- Lingyun Wang [lingyunw] *
\******************************************************************/
LPBITMAPINFO pbmiConvertInfo(CONST BITMAPINFO *pbmi, ULONG iUsage)
{
LPBITMAPINFO pbmiNew;
ULONG cjRGB;
ULONG cColorsMax;
ULONG cColors;
UINT uiBitCount;
ULONG ulSize;
RGBTRIPLE *pTri;
RGBQUAD *pQuad;
ASSERTGDI (pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER), "bad header size\n");
//
// convert COREHEADER and copy color table
//
cjRGB = sizeof(RGBQUAD);
uiBitCount = ((LPBITMAPCOREINFO)pbmi)->bmciHeader.bcBitCount;
//
// figure out the number of entries
//
switch (uiBitCount)
{
case 1:
cColorsMax = 2;
break;
case 4:
cColorsMax = 16;
break;
case 8:
cColorsMax = 256;
break;
default:
if (iUsage == DIB_PAL_COLORS)
{
iUsage = DIB_RGB_COLORS;
}
cColorsMax = 0;
switch (uiBitCount)
{
case 16:
case 24:
case 32:
break;
default:
WARNING("pbmiConvertInfo failed invalid bitcount in bmi BI_RGB\n");
return(0);
}
}
cColors = cColorsMax;
if (iUsage == DIB_PAL_COLORS)
cjRGB = sizeof(USHORT);
else if (iUsage == DIB_PAL_INDICES)
cjRGB = 0;
//
// convert the core header
//
ulSize = sizeof(BITMAPINFOHEADER);
pbmiNew = PALLOCNOZ(ulSize +
cjRGB * cColors,'pmtG');
if (pbmiNew == NULL)
return (0);
pbmiNew->bmiHeader.biSize = ulSize;
//
// copy BITMAPCOREHEADER
//
pbmiNew->bmiHeader.biWidth = ((BITMAPCOREHEADER *)pbmi)->bcWidth;
pbmiNew->bmiHeader.biHeight = ((BITMAPCOREHEADER *)pbmi)->bcHeight;
pbmiNew->bmiHeader.biPlanes = ((BITMAPCOREHEADER *)pbmi)->bcPlanes;
pbmiNew->bmiHeader.biBitCount = ((BITMAPCOREHEADER *)pbmi)->bcBitCount;
pbmiNew->bmiHeader.biCompression = 0;
pbmiNew->bmiHeader.biSizeImage = 0;
pbmiNew->bmiHeader.biXPelsPerMeter = 0;
pbmiNew->bmiHeader.biYPelsPerMeter = 0;
pbmiNew->bmiHeader.biClrUsed = 0;
pbmiNew->bmiHeader.biClrImportant = 0;
//
// copy the color table
//
pTri = (RGBTRIPLE *)((LPBYTE)pbmi + sizeof(BITMAPCOREHEADER));
pQuad = (RGBQUAD *)((LPBYTE)pbmiNew + sizeof(BITMAPINFOHEADER));
//
// copy RGBTRIPLE to RGBQUAD
//
if (iUsage != DIB_PAL_COLORS)
{
INT cj = cColors;
while (cj--)
{
pQuad->rgbRed = pTri->rgbtRed;
pQuad->rgbGreen = pTri->rgbtGreen;
pQuad->rgbBlue = pTri->rgbtBlue;
pQuad->rgbReserved = 0;
pQuad++;
pTri++;
}
}
else
// DIB_PAL_COLORS
{
RtlCopyMemory((LPBYTE)pQuad,(LPBYTE)pTri,cColors * sizeof(USHORT));
}
return(pbmiNew);
}
LPDEVMODEW
CaptureDEVMODEW(
LPDEVMODEW pdm
)
/*++
Routine Description:
Make a kernel-mode copy of a user-mode DEVMODEW structure
Arguments:
pdm - Pointer to user mode DEVMODEW structure to be copied
Return Value:
Pointer to kernel mode copy of DEVMODEW structure
NULL if there is an error
Note:
This function must be called inside try/except.
--*/
{
LPDEVMODEW pdmKm;
WORD dmSize, dmDriverExtra;
ULONG ulSize;
ProbeForRead (pdm, offsetof(DEVMODEW, dmFields), sizeof(BYTE));
dmSize = pdm->dmSize;
dmDriverExtra = pdm->dmDriverExtra;
ulSize = dmSize + dmDriverExtra;
if ((ulSize <= offsetof(DEVMODEW, dmFields)) || BALLOC_OVERFLOW1(ulSize, BYTE))
{
WARNING("bad devmodew size\n");
return NULL;
}
if ((pdmKm = PALLOCTHREADMEMNOZ(ulSize, 'pmtG')) != NULL)
{
try
{
ProbeAndReadBuffer(pdmKm, pdm, ulSize);
pdmKm->dmSize = dmSize;
pdmKm->dmDriverExtra = dmDriverExtra;
}
except(EXCEPTION_EXECUTE_HANDLER)
{
VFREETHREADMEM(pdmKm);
pdmKm = NULL;
}
}
else
{
WARNING("Memory allocation failed in CaptureDEVMODEW\n");
}
return pdmKm;
}
DRIVER_INFO_2W*
CaptureDriverInfo2W(
DRIVER_INFO_2W *pUmDriverInfo2
)
/*++
Routine Description:
Make a kernel-mode copy of a user-mode DRIVER_INFO_2W structure
Arguments:
pUmDriverInfo2 - Pointer to user mode DRIVER_INFO_2W structure
Return Value:
Pointer to copied kernel mode DRIVER_INFO_2W structure
NULL if there is an error
Note:
We're not copying pEnvironment and pConfigFile fields of
DRIVER_INFO_2W structure.
This function must be called inside try/except.
--*/
{
DRIVER_INFO_2W *pKmDriverInfo2;
ULONG NameLen, DriverPathLen, DataFileLen, TotalSize;
PWSTR pName, pDriverPath, pDataFile;
ProbeForRead(pUmDriverInfo2, sizeof(DRIVER_INFO_2W), sizeof(BYTE));
if ((pName = pUmDriverInfo2->pName) == NULL ||
(pDriverPath = pUmDriverInfo2->pDriverPath) == NULL ||
(pDataFile = pUmDriverInfo2->pDataFile) == NULL)
{
WARNING("Missing driver name or driver path\n");
return NULL;
}
NameLen = wcslensafe(pName);
DriverPathLen = wcslensafe(pDriverPath);
TotalSize = sizeof(DRIVER_INFO_2W) +
(NameLen + 1) * sizeof(WCHAR) +
(DriverPathLen + 1) * sizeof(WCHAR);
// pDataFile != NULL
DataFileLen = wcslensafe(pDataFile);
TotalSize += (DataFileLen + 1) * sizeof(WCHAR);
if (BALLOC_OVERFLOW1(TotalSize, BYTE))
return NULL;
// Note: allocated memory is zero-initialized.
pKmDriverInfo2 = (DRIVER_INFO_2W *) PALLOCTHREADMEM(TotalSize, 'pmtG');
if (pKmDriverInfo2 != NULL)
{
__try
{
RtlCopyMemory(pKmDriverInfo2, pUmDriverInfo2, sizeof(DRIVER_INFO_2W));
pKmDriverInfo2->pEnvironment =
pKmDriverInfo2->pConfigFile = NULL;
pKmDriverInfo2->pName = (PWSTR) ((PBYTE) pKmDriverInfo2 + sizeof(DRIVER_INFO_2W));
pKmDriverInfo2->pDriverPath = pKmDriverInfo2->pName + (NameLen + 1);
ProbeAndReadBuffer(pKmDriverInfo2->pName, pName, NameLen * sizeof(WCHAR));
ProbeAndReadBuffer(pKmDriverInfo2->pDriverPath, pDriverPath, DriverPathLen * sizeof(WCHAR));
pKmDriverInfo2->pDataFile = pKmDriverInfo2->pDriverPath + (DriverPathLen + 1);
ProbeAndReadBuffer(pKmDriverInfo2->pDataFile, pDataFile, DataFileLen * sizeof(WCHAR));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
VFREETHREADMEM(pKmDriverInfo2);
pKmDriverInfo2 = NULL;
}
}
else
{
WARNING("Memory allocation failed in CaptureDriverInfo2W\n");
}
return pKmDriverInfo2;
}
__inline VOID
vFreeDriverInfo2(
DRIVER_INFO_2W *pKmDriverInfo2
)
{
if (pKmDriverInfo2 != NULL)
VFREETHREADMEM(pKmDriverInfo2);
}
/******************************Public*Routine******************************\
* GreGetBitmapSize
*
* Returns the size of the header and the color table.
*
* History:
* Wed 19-Aug-1992 -by- Patrick Haluptzok [patrickh]
* add 16 and 32 bit support
*
* Wed 04-Dec-1991 -by- Patrick Haluptzok [patrickh]
* Make it handle DIB_PAL_INDICES.
*
* Tue 08-Oct-1991 -by- Patrick Haluptzok [patrickh]
* Make it handle DIB_PAL_COLORS, calculate max colors based on bpp.
*
* 22-Jul-1991 -by- Eric Kutter [erick]
* 14-Apr-1998 FritzS Convert to Gre function for use by ntuser
* Wrote it.
\**************************************************************************/
ULONG GreGetBitmapSize(CONST BITMAPINFO *pbmi, ULONG iUsage)
{
ULONG cjRet;
ULONG cjHeader;
ULONG cjRGB;
ULONG cColorsMax;
ULONG cColors;
UINT uiBitCount;
UINT uiPalUsed;
UINT uiCompression;
UINT uiHeaderSize;
// check for error
if (pbmi == (LPBITMAPINFO) NULL)
{
WARNING("GreGetBitmapSize failed - NULL pbmi\n");
return(0);
}
uiHeaderSize = pbmi->bmiHeader.biSize;
// Check for PM-style DIB
if (uiHeaderSize == sizeof(BITMAPCOREHEADER))
{
cjHeader = sizeof(BITMAPCOREHEADER);
cjRGB = sizeof(RGBTRIPLE);
uiBitCount = ((LPBITMAPCOREINFO)pbmi)->bmciHeader.bcBitCount;
uiPalUsed = 0;
uiCompression = (UINT) BI_RGB;
}
else if (uiHeaderSize >= sizeof(BITMAPINFOHEADER))
{
cjHeader = uiHeaderSize;
cjRGB = sizeof(RGBQUAD);
uiBitCount = pbmi->bmiHeader.biBitCount;
uiPalUsed = pbmi->bmiHeader.biClrUsed;
uiCompression = (UINT) pbmi->bmiHeader.biCompression;
}
else
{
WARNING("cjBitmapHeaderSize failed - invalid header size\n");
return(0);
}
if (uiCompression == BI_BITFIELDS)
{
// Handle 16 and 32 bit per pel bitmaps.
if (iUsage == DIB_PAL_COLORS)
{
iUsage = DIB_RGB_COLORS;
}
switch (uiBitCount)
{
case 16:
case 32:
break;
default:
#if DBG
DbgPrint("GreGetBitmapSize %lu\n", uiBitCount);
#endif
WARNING("GreGetBitmapSize failed for BI_BITFIELDS\n");
return(0);
}
if (uiHeaderSize <= sizeof(BITMAPINFOHEADER))
{
uiPalUsed = cColorsMax = 3;
}
else
{
//
// masks are imbedded in BITMAPV4 +
//
uiPalUsed = cColorsMax = 0;
}
}
else if (uiCompression == BI_RGB)
{
switch (uiBitCount)
{
case 1:
cColorsMax = 2;
break;
case 4:
cColorsMax = 16;
break;
case 8:
cColorsMax = 256;
break;
default:
if (iUsage == DIB_PAL_COLORS)
{
iUsage = DIB_RGB_COLORS;
}
cColorsMax = 0;
switch (uiBitCount)
{
case 16:
case 24:
case 32:
break;
default:
WARNING("GreGetBitmapSize failed invalid bitcount in bmi BI_RGB\n");
return(0);
}
}
}
else if (uiCompression == BI_CMYK)
{
ASSERTGDI (iUsage == DIB_RGB_COLORS, "BI_CMYK:iUsage should be DIB_RGB_COLORS\n");
switch (uiBitCount)
{
case 1:
cColorsMax = 2;
break;
case 4:
cColorsMax = 16;
break;
case 8:
cColorsMax = 256;
break;
case 32:
cColorsMax = 0;
break;
default:
WARNING("GreGetBitmapSize failed invalid bitcount in bmi BI_CMYK\n");
return(0);
}
}
else if ((uiCompression == BI_RLE4) || (uiCompression == BI_CMYKRLE4))
{
if (uiBitCount != 4)
{
return(0);
}
cColorsMax = 16;
}
else if ((uiCompression == BI_RLE8) || (uiCompression == BI_CMYKRLE8))
{
if (uiBitCount != 8)
{
return(0);
}
cColorsMax = 256;
}
else if ((uiCompression == BI_JPEG) || (uiCompression == BI_PNG))
{
cColorsMax = 0;
}
else
{
WARNING("GreGetBitmapSize failed invalid Compression in header\n");
return(0);
}
if (uiPalUsed != 0)
{
if (uiPalUsed <= cColorsMax)
cColors = uiPalUsed;
else
cColors = cColorsMax;
}
else
cColors = cColorsMax;
if (iUsage == DIB_PAL_COLORS)
cjRGB = sizeof(USHORT);
else if (iUsage == DIB_PAL_INDICES)
cjRGB = 0;
cjRet = ((cjHeader + (cjRGB * cColors)) + 3) & ~3;
// (cjRGB * cColors) has a maximum of 256*sizeof(USHORT) so it will not
// overflow, but we need to check the sum.
if (cjRet < cjHeader)
return 0;
else
return cjRet;
return(((cjHeader + (cjRGB * cColors)) + 3) & ~3);
}
/******************************Public*Routine******************************\
* noOverflowCJSCAN
*
* compute the amount of memory used by a bitmap
*
* Arguments:
*
* ulWidth -- The width of the bitmap
* wPlanes -- The number of color planes
* wBitCount -- The number of bits per color
* ulHeight -- The height of the bitmap
*
* Return Value:
*
* The storage required (assuming each scanline is DWORD aligned) if less than
* ULONG_MAX, 0 otherwise.
*
* History:
*
* 27-Aug-1997 -by- Ori Gershony [orig]
*
\**************************************************************************/
ULONG
noOverflowCJSCAN(
ULONG ulWidth,
WORD wPlanes,
WORD wBitCount,
ULONG ulHeight
)
{
ULONGLONG product;
//
// Note that the following cannot overflow: 32+16+16=64
// (even after adding 31!)
//
product = (((ULONGLONG) ulWidth) * wPlanes * wBitCount);
product = ((product + 31) & ((ULONGLONG) ~31)) / 8;
if (product > MAXULONG)
{
//
// Already too large, final result will not fit in a ULONG
//
return 0; // Overflow
}
product *= ulHeight;
if (product > MAXULONG)
{
return 0; // Overflow
}
else
{
return ((ULONG) product);
}
}
/******************************Public*Routine******************************\
* noOverflowCJSCANW
*
* compute the amount of memory used by a bitmap
*
* Arguments:
*
* ulWidth -- The width of the bitmap
* wPlanes -- The number of color planes
* wBitCount -- The number of bits per color
* ulHeight -- The height of the bitmap
*
* Return Value:
*
* The storage required (assuming each scanline is WORD aligned) if less than
* ULONG_MAX, 0 otherwise.
*
* History:
*
* 27-Aug-1997 -by- Ori Gershony [orig]
*
\**************************************************************************/
ULONG
noOverflowCJSCANW(
ULONG ulWidth,
WORD wPlanes,
WORD wBitCount,
ULONG ulHeight
)
{
ULONGLONG product;
//
// Note that the following cannot overflow: 32+16+16=64
// (even after adding 31!)
//
product = (((ULONGLONG) ulWidth) * wPlanes * wBitCount);
product = ((product + 15) & ((ULONGLONG) ~15)) / 8;
if (product > MAXULONG)
{
//
// Already too large, final result will not fit in a ULONG
//
return 0; // Overflow
}
product *= ulHeight;
if (product > MAXULONG)
{
return 0; // Overflow
}
else
{
return ((ULONG) product);
}
}
/******************************Public*Routine******************************\
* GreGetBitmapBitsSize()
*
* copied from gdi\client
*
* History:
* 20-Feb-1995 -by- Eric Kutter [erick]
* 14-Apr-1998 FritzS make Gre call for use by ntuser
* Wrote it.
\**************************************************************************/
ULONG GreGetBitmapBitsSize(CONST BITMAPINFO *pbmi)
{
// Check for PM-style DIB
if (pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
LPBITMAPCOREINFO pbmci;
pbmci = (LPBITMAPCOREINFO)pbmi;
return(noOverflowCJSCAN(pbmci->bmciHeader.bcWidth,
pbmci->bmciHeader.bcPlanes,
pbmci->bmciHeader.bcBitCount,
pbmci->bmciHeader.bcHeight));
}
// not a core header
if ((pbmi->bmiHeader.biCompression == BI_RGB) ||
(pbmi->bmiHeader.biCompression == BI_BITFIELDS) ||
(pbmi->bmiHeader.biCompression == BI_CMYK)
)
{
return(noOverflowCJSCAN(pbmi->bmiHeader.biWidth,
(WORD) pbmi->bmiHeader.biPlanes,
(WORD) pbmi->bmiHeader.biBitCount,
ABS(pbmi->bmiHeader.biHeight)));
}
else
{
return(pbmi->bmiHeader.biSizeImage);
}
}
/******************************Public*Routine******************************\
* BOOL bCaptureBitmapInfo (LPBITMAPINFO pbmi, INT *pcjHeader)
*
* Capture the Bitmapinfo struct. The header must be a BITMAPINFOHEADER
* or BITMAPV4HEADER
* converted at the client side already.
*
* Note: this has to be called inside a TRY-EXCEPT.
*
* 23-Mar-1995 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
BOOL bCaptureBitmapInfo (
LPBITMAPINFO pbmi,
DWORD dwUsage,
UINT cjHeader,
LPBITMAPINFO *ppbmiTmp)
{
ASSERTGDI(ppbmiTmp != NULL,"bCaptureBitmapInfo(): pbmiTmp == NULL\n");
//
// Make sure we have at least the biSize field of header.
//
if ((cjHeader < sizeof(DWORD)) || (pbmi == (LPBITMAPINFO) NULL))
{
WARNING("bCaptureBitmapInfo - header too small or NULL\n");
return FALSE;
}
else
{
*ppbmiTmp = PALLOCNOZ(cjHeader,'pmtG');
if (*ppbmiTmp)
{
ProbeAndReadBuffer (*ppbmiTmp,pbmi,cjHeader);
//
// First, make sure that cjHeader is at least as
// big as biSize so that the captured header
// has sufficient data for GreGetBitmapSize to use.
// Note that the first thing GreGetBitmapSize does is
// validate biSize, so it isn't necessary for us
// to check cjHeader against BITMAPCOREHEADER, etc.
//
// Next, recompute the header size from the captured
// header: it better still match. Otherwise, we have
// failed to safely capture the entire header (i.e.,
// another thread changed the data changed during
// capture or bogus data was passed to the API).
//
if (((*ppbmiTmp)->bmiHeader.biSize < sizeof(BITMAPINFOHEADER)) ||
(cjHeader < (*ppbmiTmp)->bmiHeader.biSize) ||
(cjHeader != GreGetBitmapSize(*ppbmiTmp, dwUsage)))
{
WARNING("bCapturebitmapInfo - bad header size\n");
VFREEMEM(*ppbmiTmp);
*ppbmiTmp = NULL;
return FALSE;
}
return TRUE;
}
else
{
return FALSE;
}
}
}
/******************************Public*Routine******************************\
* NtGdiSetDIBitsToDeviceInternal()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
* 23-Mar-1995 -by- Lingyun Wang [lingyunw]
* call CaptureBitmapInfo to convert BITMAPCOREINFO if it is so.
\**************************************************************************/
int
APIENTRY
NtGdiSetDIBitsToDeviceInternal(
HDC hdcDest,
int xDst,
int yDst,
DWORD cx,
DWORD cy,
int xSrc,
int ySrc,
DWORD iStartScan,
DWORD cNumScan,
LPBYTE pInitBits,
LPBITMAPINFO pbmi,
DWORD iUsage,
UINT cjMaxBits,
UINT cjMaxInfo,
BOOL bTransformCoordinates,
HANDLE hcmXform
)
{
int iRet = 1;
HANDLE hSecure = 0;
ULONG cjHeader = cjMaxInfo;
LPBITMAPINFO pbmiTmp = NULL;
iUsage &= (DIB_PAL_INDICES | DIB_PAL_COLORS | DIB_RGB_COLORS);
try
{
if (bCaptureBitmapInfo(pbmi,iUsage,cjHeader,&pbmiTmp))
{
if (pInitBits)
{
//
// Use cjMaxBits passed in, this size takes cNumScan
// into account. pInitBits has already been aligned
// in user mode.
//
ProbeForRead(pInitBits,cjMaxBits,sizeof(DWORD));
hSecure = MmSecureVirtualMemory(pInitBits,cjMaxBits, PAGE_READONLY);
if (hSecure == 0)
{
iRet = 0;
}
}
}
else
{
iRet = 0;
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(4);
// SetLastError(GetExceptionCode());
iRet = 0;
}
// if we didn't hit an error above
if (iRet == 1)
{
iRet = GreSetDIBitsToDeviceInternal(
hdcDest,
xDst,
yDst,
cx,
cy,
xSrc,
ySrc,
iStartScan,
cNumScan,
pInitBits,
pbmiTmp,
iUsage,
cjMaxBits,
cjHeader,
bTransformCoordinates,
hcmXform
);
}
if (hSecure)
{
MmUnsecureVirtualMemory(hSecure);
}
if (pbmiTmp)
VFREEMEM(pbmiTmp);
return(iRet);
}
/******************************Public*Routine******************************\
* NtGdiPolyPolyDraw()
*
* History:
* 22-Feb-1995 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL NtGdiFastPolyPolyline(HDC, CONST POINT*, ULONG*, ULONG); // drawgdi.cxx
ULONG_PTR
APIENTRY
NtGdiPolyPolyDraw(
HDC hdc,
PPOINT ppt,
PULONG pcpt,
ULONG ccpt,
int iFunc
)
{
ULONG cpt;
PULONG pulCounts;
ULONG_PTR ulRet = 1;
ULONG ulCount;
POINT apt[10];
PPOINT pptTmp;
if (ccpt > 0)
{
// If a PolyPolyline, first try the fast-path polypolyline code.
if ((iFunc != I_POLYPOLYLINE) ||
(!NtGdiFastPolyPolyline(hdc, ppt, pcpt, ccpt)))
{
if (ccpt > 1)
{
// If ccpt > 1 we cant have I_POLYLINETO/I_POLYBEZIERTO/I_POLYBEZIER
if (iFunc == I_POLYLINETO || iFunc == I_POLYBEZIERTO || iFunc == I_POLYBEZIER)
{
return 0;
}
//
// make sure allocation is within reasonable limits
//
if (!BALLOC_OVERFLOW1(ccpt,ULONG))
{
pulCounts = PALLOCNOZ(ccpt * sizeof(ULONG),'pmtG');
}
else
{
EngSetLastError(ERROR_INVALID_PARAMETER);
pulCounts = NULL;
}
}
else
{
pulCounts = &ulCount;
}
if (pulCounts)
{
pptTmp = apt;
try
{
UINT i;
//
// we did make sure ccpt * sizeof(ULONG) will not overflow
// in above. then here is safe.
//
ProbeAndReadBuffer(pulCounts,pcpt,ccpt * sizeof(ULONG));
cpt = 0;
for (i = 0; i < ccpt; ++i)
cpt += pulCounts[i];
// we need to make sure that the cpt array won't overflow
// a DWORD in terms of number of bytes
if (!BALLOC_OVERFLOW1(cpt,POINT))
{
if (cpt > 10)
{
pptTmp = AllocFreeTmpBuffer(cpt * sizeof(POINT));
}
if (pptTmp)
{
ProbeAndReadBuffer(pptTmp,ppt,cpt*sizeof(POINT));
}
else
{
ulRet = 0;
}
}
else
{
ulRet = 0;
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(5);
// SetLastError(GetExceptionCode());
ulRet = 0;
}
if (ulRet != 0)
{
switch(iFunc)
{
case I_POLYPOLYGON:
ulRet =
(ULONG_PTR) GrePolyPolygonInternal
(
hdc,
pptTmp,
(LPINT)pulCounts,
ccpt,
cpt
);
break;
case I_POLYPOLYLINE:
ulRet =
(ULONG_PTR) GrePolyPolylineInternal
(
hdc,
pptTmp,
pulCounts,
ccpt,
cpt
);
break;
case I_POLYBEZIER:
ulRet =
(ULONG_PTR) GrePolyBezier
(
hdc,
pptTmp,
ulCount
);
break;
case I_POLYLINETO:
ulRet =
(ULONG_PTR) GrePolylineTo
(
hdc,
pptTmp,
ulCount
);
break;
case I_POLYBEZIERTO:
ulRet =
(ULONG_PTR) GrePolyBezierTo
(
hdc,
pptTmp,
ulCount
);
break;
case I_POLYPOLYRGN:
ulRet =
(ULONG_PTR) GreCreatePolyPolygonRgnInternal
(
pptTmp,
(LPINT)pulCounts,
ccpt,
(INT)(ULONG_PTR)hdc, // the mode
cpt
);
break;
default:
ulRet = 0;
}
}
if (pptTmp && (pptTmp != apt))
FreeTmpBuffer(pptTmp);
if (pulCounts != &ulCount)
VFREEMEM(pulCounts);
}
else
{
ulRet = 0;
}
}
}
else
{
ulRet = 0;
}
return(ulRet);
}
/******************************Public*Routine******************************\
* NtGdiStretchDIBitsInternal()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
* 04-MAR-1995 -by- Lingyun Wang [lingyunw]
* Expanded it.
\**************************************************************************/
int
APIENTRY
NtGdiStretchDIBitsInternal(
HDC hdc,
int xDst,
int yDst,
int cxDst,
int cyDst,
int xSrc,
int ySrc,
int cxSrc,
int cySrc,
LPBYTE pjInit,
LPBITMAPINFO pbmi,
DWORD dwUsage,
DWORD dwRop4,
UINT cjMaxInfo,
UINT cjMaxBits,
HANDLE hcmXform
)
{
LPBITMAPINFO pbmiTmp = NULL;
INT iRet = 1;
ULONG cjHeader = cjMaxInfo;
ULONG cjBits = cjMaxBits;
HANDLE hSecure = 0;
if (pjInit && pbmi && cjHeader)
{
try
{
if (bCaptureBitmapInfo(pbmi, dwUsage, cjHeader, &pbmiTmp))
{
if (pjInit)
{
ProbeForRead(pjInit, cjBits, sizeof(DWORD));
hSecure = MmSecureVirtualMemory(pjInit, cjBits, PAGE_READONLY);
if (!hSecure)
{
iRet = 0;
}
}
}
else
{
iRet = 0;
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(6);
// SetLastError(GetExceptionCode());
iRet = 0;
}
}
else
{
// it is completely valid to pass in NULL here if the ROP doesn't use
// a source.
pbmiTmp = NULL;
pjInit = NULL;
pjInit = NULL;
}
if (iRet)
{
iRet = GreStretchDIBitsInternal(
hdc,
xDst,
yDst,
cxDst,
cyDst,
xSrc,
ySrc,
cxSrc,
cySrc,
pjInit,
pbmiTmp,
dwUsage,
dwRop4,
cjHeader,
cjBits,
hcmXform
);
if (hSecure)
{
MmUnsecureVirtualMemory(hSecure);
}
}
if (pbmiTmp)
{
VFREEMEM(pbmiTmp);
}
return (iRet);
}
/******************************Public*Routine******************************\
* NtGdiGetOutlineTextMetricsInternalW
*
* Arguments:
*
* hdc - device context
* cjotm - size of metrics data array
* potmw - pointer to array of OUTLINETEXTMETRICW structures or NULL
* ptmd - pointer to TMDIFF strcture
*
* Return Value:
*
* If potmw is NULL, return size of buffer needed, else TRUE.
* If the function fails, the return value is FALSE;
*
* History:
*
* 15-Mar-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
ULONG
APIENTRY
NtGdiGetOutlineTextMetricsInternalW(
HDC hdc,
ULONG cjotm,
OUTLINETEXTMETRICW *potmw,
TMDIFF *ptmd
)
{
DWORD dwRet = (DWORD)1;
OUTLINETEXTMETRICW *pkmOutlineTextMetricW;
TMDIFF kmTmDiff;
if ((cjotm == 0) || (potmw == (OUTLINETEXTMETRICW *)NULL))
{
cjotm = 0;
pkmOutlineTextMetricW = (OUTLINETEXTMETRICW *)NULL;
}
else
{
pkmOutlineTextMetricW = AllocFreeTmpBuffer(cjotm);
if (pkmOutlineTextMetricW == (OUTLINETEXTMETRICW *)NULL)
{
dwRet = (DWORD)-1;
}
}
if (dwRet != (DWORD)-1)
{
dwRet = GreGetOutlineTextMetricsInternalW(
hdc,
cjotm,
pkmOutlineTextMetricW,
&kmTmDiff);
if (dwRet != (DWORD)-1 && dwRet != (DWORD) 0)
{
try
{
//
// copy TMDIFF structure out
//
ProbeAndWriteAlignedBuffer(ptmd, &kmTmDiff, sizeof(TMDIFF), sizeof(DWORD));
//
// copy OTM out if needed
//
if (cjotm != 0)
{
ProbeAndWriteAlignedBuffer(potmw, pkmOutlineTextMetricW, cjotm, sizeof(DWORD));
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(7);
// SetLastError(GetExceptionCode());
dwRet = (DWORD)-1;
}
}
}
if (pkmOutlineTextMetricW != (OUTLINETEXTMETRICW *)NULL)
{
FreeTmpBuffer(pkmOutlineTextMetricW);
}
return(dwRet);
}
// PUBLIC
/******************************Public*Routine******************************\
* NtGdiGetBoundsRect()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
NtGdiGetBoundsRect(
HDC hdc,
LPRECT prc,
DWORD f
)
{
DWORD dwRet;
RECT rc = {0, 0, 0, 0};
dwRet = GreGetBoundsRect(hdc,&rc,f);
if (dwRet)
{
try
{
ProbeAndWriteStructure(prc,rc,RECT);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(8);
// SetLastError(GetExceptionCode());
dwRet = 0;
}
}
return(dwRet);
}
/******************************Public*Routine******************************\
* NtGdiGetBitmapBits()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
* 03-Mar-1995 -by- Lingyun Wang [lingyunw]
* Expanded it.
\**************************************************************************/
LONG
APIENTRY
NtGdiGetBitmapBits(
HBITMAP hbm,
ULONG cjMax,
PBYTE pjOut
)
{
LONG lRet = 1;
HANDLE hSecure = 0;
LONG lOffset = 0;
ULONG cjBmSize = 0;
//
// get the bitmap size, just in case they pass
// in a cjMax greater than the bitmap size
//
cjBmSize = GreGetBitmapBits(hbm,0,NULL,&lOffset);
if (cjMax > cjBmSize)
{
cjMax = cjBmSize;
}
if (pjOut)
{
try
{
// WINBUG #83051 2-8-2000 bhouse Investigate possible stale comment
// The below old comment mentions how this is ideal for try execept block ...
// hmmm ... but we are in a try except block... this needs verifying that
// it is just an old stale comment.
// Old Comment:
// - this would be a prime candidate for a try/except
// instead of MmSecureVirtualMemory
ProbeForWrite(pjOut,cjMax,sizeof(BYTE));
hSecure = MmSecureVirtualMemory (pjOut, cjMax, PAGE_READWRITE);
if (hSecure == 0)
{
lRet = 0;
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(9);
// SetLastError(GetExceptionCode());
lRet = 0;
}
}
if (lRet)
{
lRet = GreGetBitmapBits(hbm,cjMax,pjOut,&lOffset);
}
if (hSecure)
{
MmUnsecureVirtualMemory(hSecure);
}
return (lRet);
}
/******************************Public*Routine******************************\
* NtGdiCreateDIBitmapInternal()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
*
* History:
* 03-Mar-1995 -by- Lingyun Wang [lingyunw]
* Expanded it.
*
* Difference from NtGdiCreateDIBitmapInternal():
* Takes in cx, cy
*
\**************************************************************************/
HBITMAP
APIENTRY
NtGdiCreateDIBitmapInternal(
HDC hdc,
INT cx, //Bitmap width
INT cy, //Bitmap Height
DWORD fInit,
LPBYTE pjInit,
LPBITMAPINFO pbmi,
DWORD iUsage,
UINT cjMaxInitInfo,
UINT cjMaxBits,
FLONG f,
HANDLE hcmXform
)
{
LPBITMAPINFO pbmiTmp = NULL;
ULONG cjHeader = cjMaxInitInfo;
ULONG cjBits = cjMaxBits;
ULONG_PTR iRet = 1;
HANDLE hSecure = 0;
if (pbmi && cjHeader)
{
try
{
if (bCaptureBitmapInfo(pbmi, iUsage, cjHeader, &pbmiTmp))
{
if (pjInit)
{
ProbeForRead(pjInit,cjBits,sizeof(DWORD));
hSecure = MmSecureVirtualMemory(pjInit, cjBits, PAGE_READONLY);
if (!hSecure)
{
iRet = 0;
}
}
}
else
{
iRet = 0;
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(10);
// SetLastError(GetExceptionCode());
iRet = 0;
}
}
// if we didn't hit an error above
if (iRet == 1)
{
if (!(fInit & CBM_CREATEDIB))
{
//create an compatible bitmap
iRet = (ULONG_PTR)GreCreateDIBitmapComp(
hdc,
cx,
cy,
fInit,
pjInit,
pbmiTmp,
iUsage,
cjHeader,
cjBits,
0,
hcmXform);
}
else
{
iRet = (ULONG_PTR)GreCreateDIBitmapReal(
hdc,
fInit,
pjInit,
pbmiTmp,
iUsage,
cjHeader,
cjBits,
(HANDLE)0,
0,
(HANDLE)0,
0,
0,
NULL);
}
}
//free up
if (pbmiTmp)
{
VFREEMEM(pbmiTmp);
}
if (hSecure)
{
MmUnsecureVirtualMemory(hSecure);
}
return((HBITMAP)iRet);
}
/******************************Public*Routine******************************\
* NtGdiCreateDIBSection
*
* Arguments:
*
* hdc - Handle to a device context. If the value of iUsage is
* DIB_PAL_COLORS, the function uses this device context's logical
* palette to initialize the device-independent bitmap's colors.
*
*
* hSection - Handle to a file mapping object that the function will use to
* create the device-independent bitmap. This parameter can be
* NULL. If hSection is not NULL, it must be a handle to a file
* mapping object created by calling the CreateFileMapping
* function. Handles created by other means will cause
* CreateDIBSection to fail. If hSection is not NULL, the
* CreateDIBSection function locates the bitmap's bit values at
* offset dwOffset in the file mapping object referred to by
* hSection. An application can later retrieve the hSection
* handle by calling the GetObject function with the HBITMAP
* returned by CreateDIBSection.
*
*
*
* dwOffset - Specifies the offset from the beginning of the file mapping
* object referenced by hSection where storage for the bitmap's
* bit values is to begin. This value is ignored if hSection is
* NULL. The bitmap's bit values are aligned on doubleword
* boundaries, so dwOffset must be a multiple of the size of a
* DWORD.
*
* If hSection is NULL, the operating system allocates memory for
* the device-independent bitmap. In this case, the
* CreateDIBSection function ignores the dwOffset parameter. An
* application cannot later obtain a handle to this memory: the
* dshSection member of the DIBSECTION structure filled in by
* calling the GetObject function will be NULL.
*
*
* pbmi - Points to a BITMAPINFO structure that specifies various
* attributes of the device-independent bitmap, including the
* bitmap's dimensions and colors.iUsage
*
* iUsage - Specifies the type of data contained in the bmiColors array
* member of the BITMAPINFO structure pointed to by pbmi: logical
* palette indices or literal RGB values.
*
* cjMaxInfo - Maximum size of pbmi
*
* cjMaxBits - Maximum size of bitamp
*
*
* Return Value:
*
* handle of bitmap or NULL
*
* History:
*
* 28-Mar-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
HBITMAP
APIENTRY
NtGdiCreateDIBSection(
IN HDC hdc,
IN HANDLE hSectionApp,
IN DWORD dwOffset,
IN LPBITMAPINFO pbmi,
IN DWORD iUsage,
IN UINT cjHeader,
IN FLONG fl,
IN ULONG_PTR dwColorSpace,
OUT PVOID *ppvBits
)
{
HBITMAP hRet = NULL;
BOOL bStatus = FALSE;
if (pbmi != NULL)
{
LPBITMAPINFO pbmiTmp = NULL;
PVOID pvBase = NULL;
try
{
bCaptureBitmapInfo(pbmi, iUsage, cjHeader, &pbmiTmp);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(11);
EngSetLastError(ERROR_INVALID_PARAMETER);
if (pbmiTmp != NULL)
{
VFREEMEM(pbmiTmp);
pbmiTmp = NULL;
}
}
if (pbmiTmp)
{
NTSTATUS Status;
ULONG cjBits = GreGetBitmapBitsSize(pbmiTmp);
SIZE_T cjView = (SIZE_T)cjBits;
if (cjBits)
{
HANDLE hDIBSection = hSectionApp;
//
// if the app's hsection is NULL, then just
// allocate the proper range of virtual memory
//
if (hDIBSection == NULL)
{
Status = ZwAllocateVirtualMemory(
NtCurrentProcess(),
&pvBase,
0L,
&cjView,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE
);
dwOffset = 0;
if (!NT_SUCCESS(Status))
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
}
else
{
LARGE_INTEGER SectionOffset;
PVOID pObj;
SectionOffset.LowPart = dwOffset & 0xFFFF0000;
SectionOffset.HighPart = 0;
//
// Notice, header is not included in section as it is
// in client-server. We do need to leave room for
// the offset, however.
//
cjView += (dwOffset & 0x0000FFFF);
Status = ObReferenceObjectByHandle(hDIBSection,
SECTION_MAP_READ|SECTION_MAP_WRITE,
*(POBJECT_TYPE *)MmSectionObjectType,
PsGetCurrentThreadPreviousMode(),
&pObj,
0L);
if(NT_SUCCESS(Status))
{
Status = MmMapViewOfSection(
pObj,
PsGetCurrentProcess(),
(PVOID *) &pvBase,
0L,
cjView,
&SectionOffset,
&cjView,
ViewShare,
0L,
PAGE_READWRITE);
if (!NT_SUCCESS(Status))
{
EngSetLastError(ERROR_INVALID_PARAMETER);
}
//
// we're not going to use this again
//
ObDereferenceObject(pObj);
}
else
{
WARNING("NtGdiCreateDIBSection: ObReferenceObjectByHandle failed\n");
EngSetLastError(ERROR_INVALID_PARAMETER);
//
//This will now fall through to the cleanup code at the end of the routine
//to free pbmiTmp
//
}
}
// set the pointer to the beginning of the bits
if (NT_SUCCESS(Status))
{
HANDLE hSecure = NULL;
PBYTE pDIB = NULL;
pDIB = (PBYTE)pvBase + (dwOffset & 0x0000FFFF);
//
// try to secure memory, keep secure until bitmap
// is deleted
//
hSecure = MmSecureVirtualMemory(
pvBase,
cjView,
PAGE_READWRITE);
if (hSecure)
{
//
// Make the GDI Bitmap
//
hRet = GreCreateDIBitmapReal(
hdc,
CBM_CREATEDIB,
pDIB,
pbmiTmp,
iUsage,
cjHeader,
cjBits,
hDIBSection,
dwOffset,
hSecure,
(fl & CDBI_NOPALETTE) | CDBI_DIBSECTION,
dwColorSpace,
NULL);
if (hRet != NULL)
{
try
{
ProbeAndWriteStructure(ppvBits,pDIB,PVOID);
bStatus = TRUE;
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(12);
EngSetLastError(ERROR_INVALID_PARAMETER);
}
}
else
{
EngSetLastError(ERROR_INVALID_PARAMETER);
}
}
else
{
EngSetLastError(ERROR_INVALID_PARAMETER);
}
// if we failed, we need to do cleanup.
if (!bStatus)
{
//
// The bDeleteSurface call will free DIBSection memory,
// only do cleanup if MmSecureVirtualMemory or GreCreateDIBitmapReal
// failed
//
if (hRet)
{
bDeleteSurface((HSURF)hRet);
hRet = NULL;
}
else
{
// do we need to unsecure the memory?
if (hSecure)
{
MmUnsecureVirtualMemory(hSecure);
}
// free the memory based on allocation
if (hSectionApp == NULL)
{
cjView = 0;
ZwFreeVirtualMemory(
NtCurrentProcess(),
&pDIB,
&cjView,
MEM_RELEASE);
}
else
{
//
// unmap view of section
//
ZwUnmapViewOfSection(
NtCurrentProcess(),
pvBase);
}
}
}
}
}
// the only way to have gotten here is if we did allocate the pbmiTmp
VFREEMEM(pbmiTmp);
}
}
return(hRet);
}
/******************************Public*Routine******************************\
* NtGdiExtCreatePen()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
HPEN
APIENTRY
NtGdiExtCreatePen(
ULONG flPenStyle,
ULONG ulWidth,
ULONG iBrushStyle,
ULONG ulColor,
ULONG_PTR lClientHatch,
ULONG_PTR lHatch,
ULONG cstyle,
PULONG pulStyle,
ULONG cjDIB,
BOOL bOldStylePen,
HBRUSH hbrush
)
{
PULONG pulStyleTmp = NULL;
PULONG pulDIB = NULL;
HPEN hpenRet = (HPEN)1;
if (pulStyle)
{
if (!BALLOC_OVERFLOW1(cstyle,ULONG))
{
pulStyleTmp = PALLOCNOZ(cstyle * sizeof(ULONG),'pmtG');
}
if (!pulStyleTmp)
hpenRet = (HPEN)0;
}
if (iBrushStyle == BS_DIBPATTERNPT)
{
pulDIB = AllocFreeTmpBuffer(cjDIB);
if (!pulDIB)
hpenRet = (HPEN)0;
}
if (hpenRet)
{
try
{
if (pulStyle)
{
ProbeAndReadAlignedBuffer(pulStyleTmp,pulStyle,cstyle * sizeof(ULONG), sizeof(ULONG));
}
// if it is a DIBPATTERN type, the lHatch is a pointer to the BMI
if (iBrushStyle == BS_DIBPATTERNPT)
{
ProbeAndReadAlignedBuffer(pulDIB,(PVOID)lHatch,cjDIB,sizeof(ULONG));
lHatch = (ULONG_PTR)pulDIB;
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(13);
// SetLastError(GetExceptionCode());
hpenRet = (HPEN)0;
}
// if all has succeeded
if (hpenRet)
{
hpenRet = GreExtCreatePen(
flPenStyle,ulWidth,iBrushStyle,
ulColor,lClientHatch,lHatch,cstyle,
pulStyleTmp,cjDIB,bOldStylePen,hbrush
);
}
}
else
{
// SetLastError(GetExceptionCode());
}
// cleanup
if (pulDIB)
FreeTmpBuffer(pulDIB);
if (pulStyleTmp)
VFREEMEM(pulStyleTmp);
return(hpenRet);
}
/******************************Public*Routine******************************\
* NtGdiHfontCreate()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
HFONT
APIENTRY
NtGdiHfontCreate(
ENUMLOGFONTEXDVW * plfw,
ULONG cjElfw,
LFTYPE lft,
FLONG fl,
PVOID pvCliData
)
{
ULONG_PTR iRet = 1;
// check for bad parameter
if (plfw && cjElfw && (cjElfw <= sizeof(ENUMLOGFONTEXDVW)))
{
ENUMLOGFONTEXDVW elfwTmp; // too big a structure on the stack?
try
{
ProbeAndReadBuffer(&elfwTmp, plfw, cjElfw);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(15);
// SetLastError(GetExceptionCode());
iRet = 0;
}
// Ignore the DV because adobe said they will never ship a mm otf font
// This is a hack to avoid changing lot of code to remove mm support from the system
elfwTmp.elfDesignVector.dvNumAxes = 0;
if (iRet)
{
iRet = (ULONG_PTR)hfontCreate(&elfwTmp, lft, fl, pvCliData);
}
}
else
{
iRet = 0;
}
return ((HFONT)iRet);
}
/******************************Public*Routine******************************\
* NtGdiExtCreateRegion()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
* 24-Feb-1995 -by- Lingyun Wang [lingyunw]
* expanded it.
\**************************************************************************/
HRGN
APIENTRY
NtGdiExtCreateRegion(
LPXFORM px,
DWORD cj,
LPRGNDATA prgn
)
{
LPRGNDATA prgnTmp;
XFORM xf;
HRGN hrgn = (HRGN)NULL;
// check for bad parameter
if (cj >= sizeof(RGNDATAHEADER))
{
// do the real work
prgnTmp = AllocFreeTmpBuffer(cj);
if (prgnTmp)
{
BOOL bConvert = TRUE;
if (px)
{
bConvert = ProbeAndConvertXFORM ((XFORML *)px, (XFORML *)&xf);
px = &xf;
}
if (bConvert)
{
try
{
ProbeAndReadBuffer(prgnTmp, prgn, cj);
hrgn = (HRGN)1;
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(16);
// SetLastError(GetExceptionCode());
}
}
if (hrgn)
hrgn = GreExtCreateRegion((XFORML *)px,cj,prgnTmp);
FreeTmpBuffer(prgnTmp);
}
else
{
// fail to allocate memory
// SetLastError();
}
}
return(hrgn);
}
/******************************Public*Routine******************************\
* NtGdiPolyDraw()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiPolyDraw(
HDC hdc,
LPPOINT ppt,
LPBYTE pjAttr,
ULONG cpt
)
{
BOOL bRet = TRUE;
BOOL bLocked = FALSE;
HANDLE hSecure1 = 0;
HANDLE hSecure2 = 0;
try
{
// Make sure lengths do not overflow.
//
// Note: sizeof(BYTE) < sizeof(POINT), so the single test
// suffices for both lengths
//
// Note: using MAXULONG instead of MAXIMUM_POOL_ALLOC (or the
// BALLOC_ macros) because we are not allocating memory.
if (cpt <= (MAXULONG / sizeof(POINT)))
{
ProbeForRead(ppt, cpt * sizeof(POINT), sizeof(DWORD));
ProbeForRead(pjAttr,cpt * sizeof(BYTE), sizeof(BYTE));
hSecure1 = MmSecureVirtualMemory(ppt, cpt * sizeof(POINT), PAGE_READONLY);
hSecure2 = MmSecureVirtualMemory(pjAttr, cpt * sizeof(BYTE), PAGE_READONLY);
}
if (!hSecure1 || !hSecure2)
{
bRet = FALSE;
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(17);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
if (bRet)
{
bRet = GrePolyDraw(hdc,ppt,pjAttr,cpt);
}
if (hSecure1)
{
MmUnsecureVirtualMemory(hSecure1);
}
if (hSecure2)
{
MmUnsecureVirtualMemory(hSecure2);
}
return(bRet);
}
/******************************Public*Routine******************************\
* NtGdiPolyTextOutW
*
* Arguments:
*
* hdc - Handle to device context
* pptw - pointer to array of POLYTEXTW
* cStr - number of POLYTEXTW
*
* Return Value:
*
* Status
*
* History:
*
* 24-Mar-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
BOOL
APIENTRY
NtGdiPolyTextOutW(
HDC hdc,
POLYTEXTW *pptw,
UINT cStr,
DWORD dwCodePage
)
{
BOOL bStatus = TRUE;
ULONG ulSize = sizeof(POLYTEXTW) * cStr;
ULONG ulIndex;
PPOLYTEXTW pPoly = NULL;
PBYTE pjBuffer;
PBYTE pjBufferEnd;
ULONG cjdx;
//
// Check for overflow
//
if (!BALLOC_OVERFLOW1(cStr,POLYTEXTW))
{
//
// add up size off all array elements
//
try
{
ProbeForRead(pptw,cStr * sizeof(POLYTEXTW),sizeof(ULONG));
for (ulIndex=0;ulIndex<cStr;ulIndex++)
{
int n = pptw[ulIndex].n;
ULONG ulTmp; // used to check for
// overflow of ulSize
//
// Pull count from each, also check for
// non-zero length and NULL string
//
ulTmp = ulSize;
ulSize += n * sizeof(WCHAR);
if (BALLOC_OVERFLOW1(n, WCHAR) || (ulSize < ulTmp))
{
bStatus = FALSE;
break;
}
if (pptw[ulIndex].pdx != (int *)NULL)
{
cjdx = n * sizeof(int);
if (pptw[ulIndex].uiFlags & ETO_PDY)
{
if (BALLOC_OVERFLOW1(n*2,int))
bStatus = FALSE;
cjdx *= 2;
}
else
{
if (BALLOC_OVERFLOW1(n,int))
bStatus = FALSE;
}
ulTmp = ulSize;
ulSize += cjdx;
if (!bStatus || (ulSize < ulTmp))
{
bStatus = FALSE;
break;
}
}
if (n != 0)
{
if (pptw[ulIndex].lpstr == NULL)
{
bStatus = FALSE;
break;
}
}
}
} except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(18);
// SetLastError(GetExceptionCode());
bStatus = FALSE;
}
}
else
{
bStatus = FALSE;
}
if (bStatus && ulSize)
{
pPoly = (PPOLYTEXTW)AllocFreeTmpBuffer(ulSize);
if (pPoly != (POLYTEXTW *)NULL)
{
try
{
// Note: pptw already read probed
RtlCopyMemory(pPoly,pptw,sizeof(POLYTEXTW) * cStr);
pjBuffer = ((PBYTE)pPoly) + sizeof(POLYTEXTW) * cStr;
pjBufferEnd = ((PBYTE)pPoly) + ulSize;
//
// copy strings and pdx into kernel mode
// buffer and update pointers. Copy all pdx
// values first, then copy strings to avoid
// unaligned accesses due to odd length strings...
//
for (ulIndex=0;ulIndex<cStr;ulIndex++)
{
//
// Pull count from each, also check for
// non-zero length and NULL string
//
if (pPoly[ulIndex].n != 0)
{
if (pPoly[ulIndex].pdx != (int *)NULL)
{
cjdx = pPoly[ulIndex].n * sizeof(int);
if (pPoly[ulIndex].uiFlags & ETO_PDY)
{
typedef struct _TWOINT
{
int i1;
int i2;
} TWOINT;
if (BALLOC_OVERFLOW1(pPoly[ulIndex].n,TWOINT))
{
bStatus = FALSE;
}
cjdx *= 2;
}
else
{
if (BALLOC_OVERFLOW1(pPoly[ulIndex].n,int))
{
bStatus = FALSE;
}
}
//
// Check for cjdx overflow and check that kernel
// mode buffer still has space.
//
if (!bStatus || ((pjBuffer + cjdx) > pjBufferEnd))
{
bStatus = FALSE; // need set if past end of
// KM buffer but compuation // overflowed but computa
// of cjdx didn't overflow
break;
}
ProbeAndReadAlignedBuffer(
pjBuffer,
pPoly[ulIndex].pdx,
cjdx, sizeof(int));
pPoly[ulIndex].pdx = (int *)pjBuffer;
pjBuffer += cjdx;
}
}
}
//
// now copy strings
//
if (bStatus)
{
for (ulIndex=0;ulIndex<cStr;ulIndex++)
{
//
// Pull count from each, also check for
// non-zero length and NULL string
//
if (pPoly[ulIndex].n != 0)
{
if (pPoly[ulIndex].lpstr != NULL)
{
ULONG StrSize = pPoly[ulIndex].n * sizeof(WCHAR);
//
// Check for overflow of StrSize and check
// that kernel mode buffer has space.
//
if (BALLOC_OVERFLOW1(pPoly[ulIndex].n, WCHAR) ||
((pjBuffer + StrSize) > pjBufferEnd))
{
bStatus = FALSE;
break;
}
ProbeAndReadAlignedBuffer(
pjBuffer,
(PVOID)pPoly[ulIndex].lpstr,
StrSize,
sizeof(WCHAR));
pPoly[ulIndex].lpstr = (LPWSTR)pjBuffer;
pjBuffer += StrSize;
}
else
{
//
// data error, n != 0 but lpstr = NULL
//
bStatus = FALSE;
break;
}
}
}
}
} except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(19);
// SetLastError(GetExceptionCode());
bStatus = FALSE;
}
if (bStatus)
{
//
// Finally ready to call gre function
//
bStatus = GrePolyTextOutW(hdc,pPoly,cStr,dwCodePage);
}
FreeTmpBuffer(pPoly);
}
else
{
WARNING("NtGdiPolyTextOut failed to allocate memory\n");
bStatus = FALSE;
}
}
return(bStatus);
}
/******************************Public*Routine******************************\
* NtGdiRectVisible()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
* 24-Feb-1995 -by- Lingyun Wang [lingyunw]
* Expanded it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiRectVisible(
HDC hdc,
LPRECT prc
)
{
DWORD dwRet;
RECT rc;
try
{
rc = ProbeAndReadStructure(prc,RECT);
dwRet = 1;
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(22);
// SetLastError(GetExceptionCode());
dwRet = 0;
}
if (dwRet)
{
dwRet = GreRectVisible(hdc,&rc);
}
return(dwRet);
}
/******************************Public*Routine******************************\
* NtGdiSetMetaRgn()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int
APIENTRY
NtGdiSetMetaRgn(
HDC hdc
)
{
return(GreSetMetaRgn(hdc));
}
/******************************Public*Routine******************************\
* NtGdiGetAppClipBox()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int
APIENTRY
NtGdiGetAppClipBox(
HDC hdc,
LPRECT prc
)
{
int iRet;
RECT rc;
iRet = GreGetAppClipBox(hdc,&rc);
if (iRet != ERROR)
{
try
{
ProbeAndWriteStructure(prc,rc,RECT);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(23);
// SetLastError(GetExceptionCode());
iRet = 0;
}
}
return(iRet);
}
/******************************Public*Routine******************************\
* NtGdiGetTextExtentEx()
*
* History:
* Fri 06-Oct-1995 -by- Bodin Dresevic [BodinD]
* Rewrote it.
* 07-Feb-1995 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
#define LOCAL_CWC_MAX 16
BOOL
APIENTRY
NtGdiGetTextExtentExW(
HDC hdc,
LPWSTR lpwsz,
ULONG cwc,
ULONG dxMax,
ULONG *pcCh,
PULONG pdxOut,
LPSIZE psize,
FLONG fl
)
{
SIZE size;
ULONG cCh = 0;
ULONG Localpdx[LOCAL_CWC_MAX];
WCHAR Localpwsz[LOCAL_CWC_MAX];
PWSZ pwszCapt = NULL;
PULONG pdxCapt = NULL;
BOOL UseLocals = FALSE;
BOOL bRet = FALSE;
BOOL b;
if ( (b = (psize != NULL)) )
{
if (cwc == 0)
{
cCh = 0;
size.cx = 0;
size.cy = 0;
bRet = TRUE;
}
else
{
// capture the string
// NULL string causes failiure.
if ( cwc > LOCAL_CWC_MAX ) {
UseLocals = FALSE;
} else {
UseLocals = TRUE;
}
if (lpwsz != NULL)
{
try
{
if ( UseLocals ) {
pwszCapt = Localpwsz;
pdxCapt = Localpdx;
} else {
if (cwc && !BALLOC_OVERFLOW2(cwc,ULONG,WCHAR))
{
pdxCapt = (PULONG) AllocFreeTmpBuffer(cwc * (sizeof(ULONG) + sizeof(WCHAR)));
}
pwszCapt = (PWSZ) &pdxCapt[cwc];
}
if (pdxCapt)
{
// Capture the string into the buffer.
ProbeAndReadBuffer(pwszCapt, lpwsz, cwc*sizeof(WCHAR));
bRet = TRUE;
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(24);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
}
if (bRet)
{
bRet = GreGetTextExtentExW(hdc,
pwszCapt,
cwc,
pcCh ? dxMax : ULONG_MAX,
&cCh,
pdxOut ? pdxCapt : NULL,
&size, fl);
}
}
// Write the value back into the user mode buffer if the call succeded
if (bRet)
{
try
{
ProbeAndWriteStructure(psize,size,SIZE);
if (pcCh)
{
ProbeAndWriteUlong(pcCh,cCh);
}
// We will only try to copy the data if pcCh is not zero,
// and it is set to zero if cwc is zero.
if (cCh)
{
// only copy if the caller requested the data, and the
// data is present.
if (pdxOut && pdxCapt)
{
ProbeAndWriteAlignedBuffer(pdxOut, pdxCapt, cCh * sizeof(ULONG), sizeof(ULONG));
}
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(25);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
}
if (!UseLocals && pdxCapt)
{
FreeTmpBuffer(pdxCapt);
}
}
return (bRet);
}
/******************************Public*Routine******************************\
* NtGdiGetCharABCWidthsW()
*
* Arguments:
*
* hdc - handle to device context
* wchFirst - first char (if pwch is NULL)
* cwch - Number of chars to get ABC widths for
* pwch - array of WCHARs (mat be NULL)
* bInteger - return int or float ABC values
* pvBuf - results buffer
*
* Return Value:
*
* BOOL Status
*
* History:
*
* 14-Mar-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
BOOL
APIENTRY
NtGdiGetCharABCWidthsW(
HDC hdc,
UINT wchFirst,
ULONG cwch,
PWCHAR pwch,
FLONG fl,
PVOID pvBuf
)
{
BOOL bStatus = FALSE;
PVOID pTemp_pvBuf = NULL;
PWCHAR pTemp_pwc = (PWCHAR)NULL;
BOOL bUse_pwc = FALSE;
ULONG OutputBufferSize = 0;
if (pvBuf == NULL)
{
return(bStatus);
}
//
// allocate memory for buffers, pwch may be NULL
//
if (pwch != (PWCHAR)NULL)
{
bUse_pwc = TRUE;
if (cwch && !BALLOC_OVERFLOW1(cwch,WCHAR))
{
pTemp_pwc = (PWCHAR)PALLOCNOZ(cwch * sizeof(WCHAR),'pmtG');
}
}
if ((!bUse_pwc) || (pTemp_pwc != (PWCHAR)NULL))
{
if (fl & GCABCW_INT)
{
if (!BALLOC_OVERFLOW1(cwch,ABC))
{
pTemp_pvBuf = (PVOID)AllocFreeTmpBuffer(cwch * sizeof(ABC));
OutputBufferSize = cwch * sizeof(ABC);
}
}
else
{
if (!BALLOC_OVERFLOW1(cwch,ABCFLOAT))
{
pTemp_pvBuf = (PVOID)AllocFreeTmpBuffer(cwch * sizeof(ABCFLOAT));
OutputBufferSize = cwch * sizeof(ABCFLOAT);
}
}
if (pTemp_pvBuf != NULL)
{
BOOL bErr = FALSE;
//
// copy input data to kernel mode buffer, if needed
//
if (bUse_pwc)
{
try
{
ProbeAndReadBuffer(pTemp_pwc,pwch,cwch * sizeof(WCHAR));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(26);
// SetLastError(GetExceptionCode());
bErr = TRUE;
}
}
if (!bErr)
{
bStatus = GreGetCharABCWidthsW(hdc,wchFirst,cwch,pTemp_pwc,fl,pTemp_pvBuf);
//
// copy results from kernel mode buffer to user buffer
//
if (bStatus)
{
try
{
ProbeAndWriteBuffer(pvBuf,pTemp_pvBuf,OutputBufferSize);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(27);
// SetLastError(GetExceptionCode());
bStatus = FALSE;
}
}
}
FreeTmpBuffer(pTemp_pvBuf);
}
if (bUse_pwc)
{
if (pTemp_pwc)
VFREEMEM(pTemp_pwc);
}
}
return(bStatus);
}
/******************************Public*Routine******************************\
* NtGdiAngleArc()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiAngleArc(
HDC hdc,
int x,
int y,
DWORD dwRadius,
DWORD dwStartAngle,
DWORD dwSweepAngle
)
{
FLOATL l_eStartAngle;
FLOATL l_eSweepAngle;
// Validate arguments and cast to floats
BOOL bRet = (bConvertDwordToFloat(dwStartAngle, &l_eStartAngle) &&
bConvertDwordToFloat(dwSweepAngle ,&l_eSweepAngle));
if (bRet)
{
bRet = GreAngleArc(hdc,x,y,dwRadius,l_eStartAngle,l_eSweepAngle);
}
return bRet;
}
/******************************Public*Routine******************************\
* NtGdiSetMiterLimit()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiSetMiterLimit(
HDC hdc,
DWORD dwNew,
PDWORD pdwOut
)
{
BOOL bRet = TRUE;
FLOATL l_e;
FLOATL l_eNew;
ASSERTGDI(sizeof(FLOATL) == sizeof(DWORD),"sizeof(FLOATL) != sizeof(DWORD)\n");
// Validate argument and cast to float
bRet = bConvertDwordToFloat(dwNew, &l_eNew);
if (bRet)
{
bRet = GreSetMiterLimit(hdc,l_eNew,&l_e);
}
if (bRet && pdwOut)
{
try
{
ProbeAndWriteAlignedBuffer(pdwOut, &l_e, sizeof(DWORD), sizeof(DWORD));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(113);
// SetLastError(GetExceptionCode());
bRet = 0;
}
}
return(bRet);
}
/******************************Public*Routine******************************\
* NtGdiSetFontXform()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiSetFontXform(
HDC hdc,
DWORD dwxScale,
DWORD dwyScale
)
{
FLOATL l_exScale;
FLOATL l_eyScale;
// Validate arguments and cast to floats
BOOL bRet = (bConvertDwordToFloat (dwxScale, &l_exScale) &&
bConvertDwordToFloat (dwyScale, &l_eyScale));
if (bRet)
{
bRet = GreSetFontXform(hdc,l_exScale,l_eyScale);
}
return bRet;
}
/******************************Public*Routine******************************\
* NtGdiGetMiterLimit()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiGetMiterLimit(
HDC hdc,
PDWORD pdwOut
)
{
BOOL bRet;
FLOATL l_e;
bRet = GreGetMiterLimit(hdc,&l_e);
if (bRet)
{
try
{
ProbeAndWriteAlignedBuffer(pdwOut, &l_e, sizeof(DWORD), sizeof(DWORD));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(29);
// SetLastError(GetExceptionCode());
bRet = 0;
}
}
return(bRet);
}
/******************************Public*Routine******************************\
* NtGdiMaskBlt()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiMaskBlt(
HDC hdc,
int xDst,
int yDst,
int cx,
int cy,
HDC hdcSrc,
int xSrc,
int ySrc,
HBITMAP hbmMask,
int xMask,
int yMask,
DWORD dwRop4,
DWORD crBackColor
)
{
return(GreMaskBlt(
hdc,xDst,yDst,cx,cy,
hdcSrc,xSrc,ySrc,
hbmMask,xMask,yMask,
dwRop4,crBackColor
));
}
/******************************Public*Routine******************************\
* NtGdiGetCharWidthW
*
* History:
*
* 10-Mar-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
BOOL
APIENTRY
NtGdiGetCharWidthW(
HDC hdc,
UINT wcFirst,
UINT cwc,
PWCHAR pwc,
FLONG fl,
PVOID pvBuf
)
{
BOOL bStatus = FALSE;
PVOID pTemp_pvBuf = NULL;
PWCHAR pTemp_pwc = (PWCHAR)NULL;
BOOL bUse_pwc = FALSE;
//
// allocate memory for buffers, pwc may be NULL
//
if (!cwc)
{
return(FALSE);
}
if (pwc != (PWCHAR)NULL)
{
bUse_pwc = TRUE;
if (!BALLOC_OVERFLOW1(cwc,WCHAR))
{
pTemp_pwc = (PWCHAR)PALLOCNOZ(cwc * sizeof(WCHAR),'pmtG');
}
}
if ((!bUse_pwc) || (pTemp_pwc != (PWCHAR)NULL))
{
if (!BALLOC_OVERFLOW1(cwc,ULONG))
{
pTemp_pvBuf = (PVOID)AllocFreeTmpBuffer(cwc * sizeof(ULONG));
}
if (pTemp_pvBuf != NULL)
{
//
// copy input data to kernel mode buffer, if needed
//
if (bUse_pwc)
{
try
{
ProbeAndReadBuffer(pTemp_pwc,pwc,cwc * sizeof(WCHAR));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(30);
// SetLastError(GetExceptionCode());
bStatus = FALSE;
}
}
bStatus = GreGetCharWidthW(hdc,wcFirst,cwc,pTemp_pwc,fl,pTemp_pvBuf);
//
// copy results from kernel mode buffer to user buffer
//
if (bStatus)
{
try
{
ProbeAndWriteBuffer(pvBuf,pTemp_pvBuf,cwc * sizeof(ULONG));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(31);
// SetLastError(GetExceptionCode());
bStatus = FALSE;
}
}
FreeTmpBuffer(pTemp_pvBuf);
}
if (bUse_pwc)
{
VFREEMEM(pTemp_pwc);
}
}
return(bStatus);
}
/******************************Public*Routine******************************\
* NtGdiDrawEscape
*
* Arguments:
*
* hdc - handle of device context
* iEsc - specifies escape function
* cjIn - size of structure for input
* pjIn - address of structure for input
*
* Return Value:
*
* > 0 if successful
* == 0 if function not supported
* < 0 if error
*
* History:
*
* 16-Mar-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
#define DRAWESCAPE_BUFFER_SIZE 64
int
APIENTRY
NtGdiDrawEscape(
HDC hdc,
int iEsc,
int cjIn,
LPSTR pjIn
)
{
int cRet = 0;
ULONG AllocSize;
UCHAR StackBuffer[DRAWESCAPE_BUFFER_SIZE];
LPSTR pCallBuffer = pjIn;
HANDLE hSecure = 0;
//
// Validate.
//
if (cjIn < 0)
{
return -1;
}
//
// Check cjIn is 0 for NULL pjIn
//
if (pjIn == (LPSTR)NULL)
{
if (cjIn != 0)
{
cRet = -1;
}
else
{
cRet = GreDrawEscape(hdc,iEsc,0,(LPSTR)NULL);
}
}
else
{
//
// Try to alloc off stack, otherwise lock buffer
//
AllocSize = (cjIn + 3) & ~0x03;
if (AllocSize <= DRAWESCAPE_BUFFER_SIZE)
{
pCallBuffer = (LPSTR)StackBuffer;
//
// copy data into buffer
//
try
{
ProbeAndReadBuffer(pCallBuffer,pjIn,cjIn);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(32);
// SetLastError(GetExceptionCode());
cRet = -1;
}
}
else
{
hSecure = MmSecureVirtualMemory(pjIn, cjIn, PAGE_READONLY);
if (hSecure == 0)
{
cRet = -1;
}
}
if (cRet >= 0)
{
cRet = GreDrawEscape(hdc,iEsc,cjIn,pCallBuffer);
}
if (hSecure)
{
MmUnsecureVirtualMemory(hSecure);
}
}
return(cRet);
}
/******************************Public*Routine******************************\
* NtGdiExtEscape
*
* Arguments:
*
* hdc - handle of device context
* pDriver - buffer containing name of font driver
* nDriver - length of driver name
* iEsc - escape function
* cjIn - size, in bytes, of input data structure
* pjIn - address of input structure
* cjOut - size, in bytes, of output data structure
* pjOut - address of output structure
*
* Return Value:
*
* > 0 : success
* == 0 : escape not implemented
* < 0 : error
*
* History:
*
* 17-Mar-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
#define EXT_STACK_DATA_SIZE 32
int
APIENTRY
NtGdiExtEscape(
HDC hdc,
PWCHAR pDriver, // only used for NamedEscape call
int nDriver, // only used for NamedEscape call
int iEsc,
int cjIn,
LPSTR pjIn,
int cjOut,
LPSTR pjOut
)
{
UCHAR StackInputData[EXT_STACK_DATA_SIZE];
UCHAR StackOutputData[EXT_STACK_DATA_SIZE];
WCHAR StackDriver[EXT_STACK_DATA_SIZE];
HANDLE hSecureIn;
LPSTR pkmIn, pkmOut;
BOOL bAllocOut, bAllocIn, bAllocDriver;
PWCHAR pkmDriver = NULL;
BOOL bStatus = TRUE;
BOOL iRet = -1;
bAllocOut = bAllocIn = bAllocDriver = FALSE;
hSecureIn = NULL;
pkmIn = pkmOut = NULL;
if ((cjIn < 0) || (cjOut < 0) || (nDriver < 0))
{
WARNING("NtGdiExtEscape: negative count passed in\n");
bStatus = FALSE;
}
if (pDriver && bStatus)
{
if (nDriver <= EXT_STACK_DATA_SIZE-1)
{
pkmDriver = StackDriver;
}
else
{
if (!BALLOC_OVERFLOW1((nDriver+1),WCHAR))
{
pkmDriver = (WCHAR*)PALLOCNOZ((nDriver+1) * sizeof(WCHAR),'pmtG');
}
// even if we fail this is okay because we check for NULL before FREE
bAllocDriver = TRUE;
}
if (pkmDriver != NULL)
{
try
{
ProbeAndReadAlignedBuffer(pkmDriver,pDriver,nDriver*sizeof(WCHAR), sizeof(WCHAR));
pkmDriver[nDriver] = 0; // NULL terminate the string
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(94);
bStatus = FALSE;
}
}
else
{
bStatus = FALSE;
}
}
if ((cjIn != 0) && bStatus)
{
try
{
if (cjIn <= EXT_STACK_DATA_SIZE)
{
pkmIn = (LPSTR) StackInputData;
ProbeAndReadBuffer(pkmIn, pjIn, cjIn);
}
else if (pkmDriver != NULL)
{
//
// make kernel copies for the fontdrv
// otherwise just secure the memory
//
pkmIn = (LPSTR)PALLOCNOZ(cjIn,'pmtG');
if (pkmIn != (LPSTR)NULL)
{
bAllocIn = TRUE;
try
{
ProbeAndReadBuffer(pkmIn,pjIn,cjIn);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(33);
// SetLastError(GetExceptionCode());
bStatus = FALSE;
}
}
else
{
bStatus = FALSE;
}
}
else
{
ProbeForRead(pjIn,cjIn,sizeof(BYTE));
if (hSecureIn = MmSecureVirtualMemory(pjIn, cjIn, PAGE_READONLY))
{
pkmIn = pjIn;
}
else
{
bStatus = FALSE;
}
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(33);
bStatus = FALSE;
}
}
if ((cjOut != 0) && bStatus)
{
if (cjOut <= EXT_STACK_DATA_SIZE)
pkmOut = (LPSTR) StackOutputData;
else if (pkmOut = (LPSTR) PALLOCNOZ(cjOut, 'pmtG'))
bAllocOut = TRUE;
else
bStatus = FALSE;
// Security: zero initialize the return buffer or we may open
// a hole that returns old pool data or old kernel stack data.
if (pkmOut)
{
RtlZeroMemory((PVOID) pkmOut, cjOut);
}
}
if (bStatus)
{
iRet = (pkmDriver) ?
GreNamedEscape(pkmDriver, iEsc, cjIn, pkmIn, cjOut, pkmOut) :
GreExtEscape(hdc, iEsc, cjIn, pkmIn, cjOut, pkmOut);
if (cjOut != 0)
{
try
{
ProbeAndWriteBuffer(pjOut, pkmOut, cjOut);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(34);
iRet = -1;
}
}
}
if (hSecureIn)
MmUnsecureVirtualMemory(hSecureIn);
if (bAllocOut && pkmOut)
VFREEMEM(pkmOut);
if (bAllocIn && pkmIn)
VFREEMEM(pkmIn);
if (bAllocDriver && pkmDriver)
VFREEMEM(pkmDriver);
return(iRet);
}
/******************************Public*Routine******************************\
* NtGdiGetFontData()
*
* Arguments:
*
* hdc - handle to device context
* dwTable - name of a font metric table
* dwOffset - ffset from the beginning of the font metric table
* pvBuf - buffer to receive the font information
* cjBuf - length, in bytes, of the information to be retrieved
*
* Return Value:
*
* Count of byte written to buffer, of GDI_ERROR for failure
*
* History:
*
* 14-Mar-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
ULONG
APIENTRY
NtGdiGetFontData(
HDC hdc,
DWORD dwTable,
DWORD dwOffset,
PVOID pvBuf,
ULONG cjBuf
)
{
PVOID pvkmBuf = NULL;
ULONG ReturnBytes = GDI_ERROR;
if (cjBuf == 0)
{
ReturnBytes = ulGetFontData(
hdc,
dwTable,
dwOffset,
pvkmBuf,
cjBuf);
}
else
{
pvkmBuf = AllocFreeTmpBuffer(cjBuf);
if (pvkmBuf != NULL)
{
ReturnBytes = ulGetFontData(
hdc,
dwTable,
dwOffset,
pvkmBuf,
cjBuf);
if (ReturnBytes != GDI_ERROR)
{
try
{
ProbeAndWriteBuffer(pvBuf,pvkmBuf,ReturnBytes);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(35);
// SetLastError(GetExceptionCode());
ReturnBytes = GDI_ERROR;
}
}
FreeTmpBuffer(pvkmBuf);
}
}
return(ReturnBytes);
}
/******************************Public*Routine******************************\
* NtGdiGetGlyphOutline
*
* Arguments:
*
* hdc - device context
* wch - character to query
* iFormat - format of data to return
* pgm - address of structure for metrics
* cjBuf - size of buffer for data
* pvBuf - address of buffer for data
* pmat2 - address of transformation matrix structure
* bIgnoreRotation - internal rotation flag
*
* Return Value:
*
* If the function succeeds, and GGO_BITMAP or GGO_NATIVE is specified,
* then return value is greater than zero.
* If the function succeeds, and GGO_METRICS is specified,
* then return value is zero.
* If GGO_BITMAP or GGO_NATIVE is specified,
* and the buffer size or address is zero,
* then return value specifies the required buffer size.
* If GGO_BITMAP or GGO_NATIVE is specified,
* and the function fails for other reasons,
* then return value is GDI_ERROR.
* If GGO_METRICS is specified, and the function fails,
* then return value is GDI_ERROR.
*
* History:
*
* 15-Mar-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
ULONG
APIENTRY
NtGdiGetGlyphOutline(
HDC hdc,
WCHAR wch,
UINT iFormat,
LPGLYPHMETRICS pgm,
ULONG cjBuf,
PVOID pvBuf,
LPMAT2 pmat2,
BOOL bIgnoreRotation
)
{
// error return value of -1 from server.inc
DWORD dwRet = (DWORD)-1;
PVOID pvkmBuf;
MAT2 kmMat2;
GLYPHMETRICS kmGlyphMetrics;
// try to allocate buffer
pvkmBuf = (cjBuf) ? AllocFreeTmpBuffer(cjBuf) : NULL;
if ((pvkmBuf != NULL) || !cjBuf)
{
BOOL bStatus = TRUE;
// copy input structures
try
{
kmMat2 = ProbeAndReadStructure(pmat2,MAT2);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(36);
// SetLastError(GetExceptionCode());
bStatus = FALSE;
}
if (bStatus)
{
dwRet = GreGetGlyphOutlineInternal(
hdc,
wch,
iFormat,
&kmGlyphMetrics,
cjBuf,
pvkmBuf,
&kmMat2,
bIgnoreRotation);
if (dwRet != (DWORD)-1)
{
try
{
if( pvkmBuf )
{
ProbeAndWriteBuffer(pvBuf,pvkmBuf,cjBuf);
}
ProbeAndWriteStructure(pgm,kmGlyphMetrics,GLYPHMETRICS);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(37);
// SetLastError(GetExceptionCode());
dwRet = (DWORD)-1;
}
}
}
if( pvkmBuf )
{
FreeTmpBuffer(pvkmBuf);
}
}
return(dwRet);
}
/******************************Public*Routine******************************\
* NtGdiGetRasterizerCaps()
*
* History:
* 08-Mar-1995 -by- Mark Enstrom [marke]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiGetRasterizerCaps(
LPRASTERIZER_STATUS praststat,
ULONG cjBytes
)
{
BOOL bStatus = FALSE;
RASTERIZER_STATUS tempRasStatus;
if (praststat && cjBytes)
{
cjBytes = min(cjBytes, sizeof(RASTERIZER_STATUS));
if (GreGetRasterizerCaps(&tempRasStatus))
{
try
{
ProbeAndWriteAlignedBuffer(praststat, &tempRasStatus, cjBytes, sizeof(DWORD));
bStatus = TRUE;
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(38);
// SetLastError(GetExceptionCode());
}
}
}
return(bStatus);
}
/******************************Public*Routine******************************\
* NtGdiGetKerningPairs
*
* Arguments:
*
* hdc - device context
* cPairs - number of pairs to retrieve
* pkpDst - Pointer to buffer to recieve kerning pairs data or NULL
*
* Return Value:
*
* If pkpDst is NULL, return number of Kerning pairs in font,
* otherwise return number of kerning pairs written to buffer.
* If failure, return 0
*
* History:
*
* 15-Mar-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
ULONG
APIENTRY
NtGdiGetKerningPairs(
HDC hdc,
ULONG cPairs,
KERNINGPAIR *pkpDst
)
{
ULONG cRet = 0;
KERNINGPAIR *pkmKerningPair = (KERNINGPAIR *)NULL;
if (pkpDst != (KERNINGPAIR *)NULL)
{
if (!BALLOC_OVERFLOW1(cPairs,KERNINGPAIR))
{
pkmKerningPair = AllocFreeTmpBuffer(sizeof(KERNINGPAIR) * cPairs);
}
}
if ((pkpDst == (KERNINGPAIR *)NULL) ||
(pkmKerningPair != (KERNINGPAIR *)NULL))
{
cRet = GreGetKerningPairs(hdc,cPairs,pkmKerningPair);
//
// copy data out if needed
//
if (pkpDst != (KERNINGPAIR *)NULL)
{
if (cRet != 0)
{
try
{
ProbeAndWriteBuffer(pkpDst,pkmKerningPair,sizeof(KERNINGPAIR) * cRet);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(39);
// SetLastError(GetExceptionCode());
cRet = 0;
}
}
FreeTmpBuffer(pkmKerningPair);
}
}
return(cRet);
}
/******************************Public*Routine******************************\
* NtGdiGetObjectBitmapHandle()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
HBITMAP
APIENTRY
NtGdiGetObjectBitmapHandle(
HBRUSH hbr,
UINT *piUsage
)
{
UINT iUsage;
HBITMAP hbitmap = (HBITMAP)1;
// error checking
int iType = LO_TYPE(hbr);
if ((iType != LO_BRUSH_TYPE) &&
(iType != LO_EXTPEN_TYPE))
{
return((HBITMAP)hbr);
}
hbitmap = GreGetObjectBitmapHandle(hbr,&iUsage);
if (hbitmap)
{
try
{
ProbeAndWriteUlong(piUsage,iUsage);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(40);
// SetLastError(GetExceptionCode());
hbitmap = (HBITMAP)0;
}
}
return (hbitmap);
}
/******************************Public*Routine******************************\
* NtGdiResetDC()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
* 26-Feb-1995 -by- Lingyun Wang [lingyunw]
* Expanded it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiResetDC(
HDC hdc,
LPDEVMODEW pdm,
BOOL *pbBanding,
DRIVER_INFO_2W *pDriverInfo2,
PVOID ppUMdhpdev
)
{
LPDEVMODEW pdmTmp = NULL;
DWORD dwTmp;
INT iRet = 1;
INT cj;
DRIVER_INFO_2W *pKmDriverInfo2 = NULL;
try
{
// Make a kernel mode copy of DEVMODEW structure
iRet = (pdm == NULL) ||
(pdmTmp = CaptureDEVMODEW(pdm)) != NULL;
// Make a kernel mode copy of DRIVER_INFO_2W structure
iRet = iRet &&
((pDriverInfo2 == NULL) ||
(pKmDriverInfo2 = CaptureDriverInfo2W(pDriverInfo2)) != NULL);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(41);
iRet = 0;
}
if (iRet)
{
iRet = GreResetDCInternal(hdc,pdmTmp,&dwTmp, pKmDriverInfo2, ppUMdhpdev);
if (iRet)
{
try
{
ProbeAndWriteUlong(pbBanding,dwTmp);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(42);
// SetLastError(GetExceptionCode());
iRet = 0;
}
}
}
if (pdmTmp)
{
VFREETHREADMEM(pdmTmp);
}
vFreeDriverInfo2(pKmDriverInfo2);
return (iRet);
}
/******************************Public*Routine******************************\
* NtGdiSetBoundsRect()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
NtGdiSetBoundsRect(
HDC hdc,
LPRECT prc,
DWORD f
)
{
DWORD dwRet=0;
RECT rc;
if (prc)
{
try
{
rc = ProbeAndReadStructure(prc,RECT);
prc = &rc;
dwRet = 1;
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(43);
// SetLastError(GetExceptionCode());
dwRet = 0;
}
}
else
{
// can't use the DCB_ACCUMULATE without a rectangle
f &= ~DCB_ACCUMULATE;
dwRet = 1;
}
if (dwRet)
dwRet = GreSetBoundsRect(hdc,prc,f);
return(dwRet);
}
/******************************Public*Routine******************************\
* NtGdiGetColorAdjustment()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiGetColorAdjustment(
HDC hdc,
PCOLORADJUSTMENT pcaOut
)
{
BOOL bRet;
COLORADJUSTMENT ca;
bRet = GreGetColorAdjustment(hdc,&ca);
if (bRet)
{
try
{
ProbeAndWriteStructure(pcaOut,ca,COLORADJUSTMENT);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(44);
// SetLastError(GetExceptionCode());
bRet = 0;
}
}
return(bRet);
}
/******************************Public*Routine******************************\
* NtGdiSetColorAdjustment()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiSetColorAdjustment(
HDC hdc,
PCOLORADJUSTMENT pca
)
{
BOOL bRet;
COLORADJUSTMENT ca;
try
{
ca = ProbeAndReadStructure(pca,COLORADJUSTMENT);
bRet = 1;
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(45);
// SetLastError(GetExceptionCode());
bRet = 0;
}
if (bRet)
{
// Range check all the adjustment values. Return FALSE if any of them
// is out of range.
if ((ca.caSize != sizeof(COLORADJUSTMENT)) ||
(ca.caIlluminantIndex > ILLUMINANT_MAX_INDEX) ||
((ca.caRedGamma > RGB_GAMMA_MAX) ||
(ca.caRedGamma < RGB_GAMMA_MIN)) ||
((ca.caGreenGamma > RGB_GAMMA_MAX) ||
(ca.caGreenGamma < RGB_GAMMA_MIN)) ||
((ca.caBlueGamma > RGB_GAMMA_MAX) ||
(ca.caBlueGamma < RGB_GAMMA_MIN)) ||
((ca.caReferenceBlack > REFERENCE_BLACK_MAX) ||
(ca.caReferenceBlack < REFERENCE_BLACK_MIN)) ||
((ca.caReferenceWhite > REFERENCE_WHITE_MAX) ||
(ca.caReferenceWhite < REFERENCE_WHITE_MIN)) ||
((ca.caContrast > COLOR_ADJ_MAX) ||
(ca.caContrast < COLOR_ADJ_MIN)) ||
((ca.caBrightness > COLOR_ADJ_MAX) ||
(ca.caBrightness < COLOR_ADJ_MIN)) ||
((ca.caColorfulness > COLOR_ADJ_MAX) ||
(ca.caColorfulness < COLOR_ADJ_MIN)) ||
((ca.caRedGreenTint > COLOR_ADJ_MAX) ||
(ca.caRedGreenTint < COLOR_ADJ_MIN)))
{
bRet = 0;
}
else
{
bRet = GreSetColorAdjustment(hdc,&ca);
}
}
return(bRet);
}
/******************************Public*Routine******************************\
* NtGdiCancelDC()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiCancelDC(
HDC hdc
)
{
return(GreCancelDC(hdc));
}
//API's used by USER
/******************************Public*Routine******************************\
* NtGdiSelectBrush()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
HBRUSH
APIENTRY
NtGdiSelectBrush(
HDC hdc,
HBRUSH hbrush
)
{
return(GreSelectBrush(hdc,(HANDLE)hbrush));
}
/******************************Public*Routine******************************\
* NtGdiSelectPen()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
HPEN
APIENTRY
NtGdiSelectPen(
HDC hdc,
HPEN hpen
)
{
return(GreSelectPen(hdc,hpen));
}
/******************************Public*Routine******************************\
* NtGdiSelectFont()
*
* History:
* 18-Mar-1996 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
HFONT
APIENTRY
NtGdiSelectFont(HDC hdc, HFONT hf)
{
return(GreSelectFont(hdc, hf));
}
/******************************Public*Routine******************************\
* NtGdiSelectBitmap()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
HBITMAP
APIENTRY
NtGdiSelectBitmap(
HDC hdc,
HBITMAP hbm
)
{
return(hbmSelectBitmap(hdc,hbm,FALSE));
}
/******************************Public*Routine******************************\
* NtGdiExtSelectClipRgn()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int
APIENTRY
NtGdiExtSelectClipRgn(
HDC hdc,
HRGN hrgn,
int iMode
)
{
return(GreExtSelectClipRgn(hdc,hrgn,iMode));
}
/******************************Public*Routine******************************\
* NtGdiCreatePen()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
HPEN
APIENTRY
NtGdiCreatePen(
int iPenStyle,
int iPenWidth,
COLORREF cr,
HBRUSH hbr
)
{
return(GreCreatePen(iPenStyle,iPenWidth,cr,hbr));
}
/******************************Public*Routine******************************\
*
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiStretchBlt(
HDC hdcDst,
int xDst,
int yDst,
int cxDst,
int cyDst,
HDC hdcSrc,
int xSrc,
int ySrc,
int cxSrc,
int cySrc,
DWORD dwRop,
DWORD dwBackColor
)
{
return(GreStretchBlt(
hdcDst,xDst,yDst,cxDst,cyDst,
hdcSrc,xSrc,ySrc,cxSrc,cySrc,
dwRop,dwBackColor));
}
/******************************Public*Routine******************************\
* NtGdiMoveTo()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiMoveTo(
HDC hdc,
int x,
int y,
LPPOINT pptOut
)
{
BOOL bRet;
POINT pt;
bRet = GreMoveTo(hdc,x,y,&pt);
if (bRet && pptOut)
{
try
{
ProbeAndWriteStructure(pptOut,pt,POINT);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(47);
// SetLastError(GetExceptionCode());
bRet = 0;
}
}
return(bRet);
}
/******************************Public*Routine******************************\
* NtGdiGetDeviceCaps()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int
APIENTRY
NtGdiGetDeviceCaps(
HDC hdc,
int i
)
{
return(GreGetDeviceCaps(hdc,i));
}
/******************************Public*Routine******************************\
* NtGdiSaveDC()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int
APIENTRY
NtGdiSaveDC(
HDC hdc
)
{
return(GreSaveDC(hdc));
}
/******************************Public*Routine******************************\
* NtGdiRestoreDC()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiRestoreDC(
HDC hdc,
int iLevel
)
{
return(GreRestoreDC(hdc,iLevel));
}
/******************************Public*Routine******************************\
* NtGdiGetNearestColor()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
COLORREF
APIENTRY
NtGdiGetNearestColor(
HDC hdc,
COLORREF cr
)
{
return(GreGetNearestColor(hdc,cr));
}
/******************************Public*Routine******************************\
* NtGdiGetSystemPaletteUse()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
UINT
APIENTRY
NtGdiGetSystemPaletteUse(
HDC hdc
)
{
return(GreGetSystemPaletteUse(hdc));
}
/******************************Public*Routine******************************\
* NtGdiSetSystemPaletteUse()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
UINT
APIENTRY
NtGdiSetSystemPaletteUse(
HDC hdc,
UINT ui
)
{
return(GreSetSystemPaletteUse(hdc,ui));
}
/******************************Public*Routine******************************\
* NtGdiGetRandomRgn()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int
APIENTRY
NtGdiGetRandomRgn(
HDC hdc,
HRGN hrgn,
int iRgn
)
{
return(GreGetRandomRgn(hdc,hrgn,iRgn));
}
/******************************Public*Routine******************************\
* NtGdiIntersectClipRect()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int
APIENTRY
NtGdiIntersectClipRect(
HDC hdc,
int xLeft,
int yTop,
int xRight,
int yBottom
)
{
return(GreIntersectClipRect(hdc,xLeft,yTop,xRight,yBottom));
}
/******************************Public*Routine******************************\
* NtGdiExcludeClipRect()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int
APIENTRY
NtGdiExcludeClipRect(
HDC hdc,
int xLeft,
int yTop,
int xRight,
int yBottom
)
{
return(GreExcludeClipRect(hdc,xLeft,yTop,xRight,yBottom));
}
/******************************Public*Routine******************************\
* NtGdiOpenDCW()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
* 27-Feb-1995 -by- Lingyun Wang [lingyunw]
* Expanded it.
\**************************************************************************/
HDC
APIENTRY
NtGdiOpenDCW(
PUNICODE_STRING pustrDevice,
DEVMODEW * pdm,
PUNICODE_STRING pustrLogAddr,
ULONG iType,
HANDLE hspool,
DRIVER_INFO_2W *pDriverInfo2,
PVOID ppUMdhpdev
)
{
HDC hdc = NULL;
ULONG iRet = 0;
PWSZ pwszDevice = NULL;
LPDEVMODEW pdmTmp = NULL;
INT cjDevice;
PWSTR pwstrDevice;
DRIVER_INFO_2W *pKmDriverInfo2 = NULL;
//
// This API overloads the pwszDevice parameter.
//
// If pustrDevice is NULL, it is equivalent to calling with "DISPLAY"
// which means to get a DC on the current device, which is done by
// calling USER
//
if (pustrDevice == NULL)
{
hdc = UserGetDesktopDC(iType, FALSE, TRUE);
}
else
{
try
{
ProbeForRead(pustrDevice,sizeof(UNICODE_STRING), sizeof(CHAR));
cjDevice = pustrDevice->Length;
pwstrDevice = pustrDevice->Buffer;
if (cjDevice)
{
if (cjDevice <= (MAXIMUM_POOL_ALLOC - sizeof(WCHAR)))
{
pwszDevice = AllocFreeTmpBuffer(cjDevice + sizeof(WCHAR));
}
if (pwszDevice)
{
ProbeAndReadBuffer(pwszDevice,pwstrDevice,cjDevice);
pwszDevice[(cjDevice/sizeof(WCHAR))] = L'\0';
}
}
// Make a kernel copy of DEVMODEW structure
iRet = (pdm == NULL) ||
(pdmTmp = CaptureDEVMODEW(pdm)) != NULL;
// Make a kernel copy of DRIVER_INFO_2W structure
iRet = iRet &&
((pDriverInfo2 == NULL) ||
(pKmDriverInfo2 = CaptureDriverInfo2W(pDriverInfo2)) != NULL);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(48);
// SetLastError(GetExceptionCode());
iRet = 0;
}
if (iRet)
{
hdc = hdcOpenDCW(pwszDevice,
pdmTmp,
iType,
hspool,
NULL,
pKmDriverInfo2,
ppUMdhpdev);
}
if (pwszDevice)
FreeTmpBuffer(pwszDevice);
if (pdmTmp)
VFREETHREADMEM(pdmTmp);
vFreeDriverInfo2(pKmDriverInfo2);
}
return (hdc);
}
/******************************Public*Routine******************************\
* NtGdiCreateCompatibleBitmap()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
HBITMAP
APIENTRY
NtGdiCreateCompatibleBitmap(
HDC hdc,
int cx,
int cy
)
{
return(GreCreateCompatibleBitmap(hdc,cx,cy));
}
/******************************Public*Routine******************************\
* NtGdiCreateBitmap()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
* 04-MAR-1995 -by- Lingyun Wang [lingyunw]
* Expanded it.
\**************************************************************************/
HBITMAP
APIENTRY
NtGdiCreateBitmap(
int cx,
int cy,
UINT cPlanes,
UINT cBPP,
LPBYTE pjInit
)
{
ULONG_PTR iRet = 1;
HANDLE hSecure = 0;
INT cj;
if (pjInit == (VOID *) NULL)
{
cj = 0;
}
else
{
// only needs to word aligned and sized
cj = noOverflowCJSCANW(cx,(WORD) cPlanes,(WORD) cBPP,cy);
if (cj == 0)
iRet = 0;
}
if (cj)
{
try
{
ProbeForRead(pjInit,cj,sizeof(BYTE));
hSecure = MmSecureVirtualMemory(pjInit, cj, PAGE_READONLY);
if (hSecure == 0)
{
iRet = 0;
}
}
except (EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(49);
iRet = 0;
}
}
// if we didn't hit an error above
if (iRet)
{
iRet = (ULONG_PTR)GreCreateBitmap(cx,cy,cPlanes,cBPP,pjInit);
}
if (hSecure)
{
MmUnsecureVirtualMemory(hSecure);
}
return((HBITMAP)iRet);
}
/******************************Public*Routine******************************\
* NtGdiSetBitmapAttributes()
*
* History:
* 27-Oct-2000 -by- Pravin Santiago [pravins]
* Wrote it.
\**************************************************************************/
HBITMAP
APIENTRY
NtGdiSetBitmapAttributes(
HBITMAP hbm,
DWORD dwFlags
)
{
if (dwFlags & SBA_STOCK)
return(GreMakeBitmapStock(hbm));
return (HBITMAP)0;
}
/******************************Public*Routine******************************\
* NtGdiClearBitmapAttributes()
*
* History:
* 27-Oct-2000 -by- Pravin Santiago [pravins]
* Wrote it.
\**************************************************************************/
HBITMAP
APIENTRY
NtGdiClearBitmapAttributes(
HBITMAP hbm,
DWORD dwFlags
)
{
if (dwFlags & SBA_STOCK)
return(GreMakeBitmapNonStock(hbm));
return (HBITMAP)0;
}
/******************************Public*Routine******************************\
* NtGdiSetBrushAttributes()
*
* History:
* 27-Oct-2000 -by- Pravin Santiago [pravins]
* Wrote it.
\**************************************************************************/
HBRUSH
APIENTRY
NtGdiSetBrushAttributes(
HBRUSH hbr,
DWORD dwFlags
)
{
if (dwFlags & SBA_STOCK)
return(GreMakeBrushStock(hbr));
return (HBRUSH)0;
}
/******************************Public*Routine******************************\
* NtGdiClearBrushAttributes()
*
* History:
* 27-Oct-2000 -by- Pravin Santiago [pravins]
* Wrote it.
\**************************************************************************/
HBRUSH
APIENTRY
NtGdiClearBrushAttributes(
HBRUSH hbr,
DWORD dwFlags
)
{
if (dwFlags & SBA_STOCK)
return(GreMakeBrushNonStock(hbr));
return (HBRUSH)0;
}
/******************************Public*Routine******************************\
* NtGdiCreateHalftonePalette()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
HPALETTE
APIENTRY
NtGdiCreateHalftonePalette(
HDC hdc
)
{
return(GreCreateCompatibleHalftonePalette(hdc));
}
/******************************Public*Routine******************************\
* NtGdiGetStockObject()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
HANDLE
APIENTRY
NtGdiGetStockObject(
int iObject
)
{
return(GreGetStockObject(iObject));
}
/******************************Public*Routine******************************\
* NtGdiExtGetObjectW()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int
APIENTRY
NtGdiExtGetObjectW(
HANDLE h,
int cj,
LPVOID pvOut
)
{
int iRet = 0;
union
{
BITMAP bm;
DIBSECTION ds;
EXTLOGPEN elp;
LOGPEN l;
LOGBRUSH lb;
LOGFONTW lf;
ENUMLOGFONTEXDVW elf;
LOGCOLORSPACEEXW lcsp;
} obj;
int iType = LO_TYPE(h);
int ci;
if ((cj < 0) || (cj > sizeof(obj)))
{
WARNING("GetObject size too big\n");
cj = sizeof(obj);
}
ci = cj;
//
// make the getobject call on brush
// still work even the app passes in
// a cj < sizeof(LOGBRUSH)
//
if (iType == LO_BRUSH_TYPE)
{
cj = sizeof(LOGBRUSH);
}
iRet = GreExtGetObjectW(h,cj,pvOut ? &obj : NULL);
if (iType == LO_BRUSH_TYPE)
{
cj = min(cj, ci);
}
if (iRet && pvOut)
{
try
{
ProbeAndWriteAlignedBuffer(pvOut,&obj,MIN(cj,iRet), sizeof(WORD));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(50);
// SetLastError(GetExceptionCode());
iRet = 0;
}
}
return(iRet);
}
/******************************Public*Routine******************************\
* NtGdiSetBrushOrg()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiSetBrushOrg(
HDC hdc,
int x,
int y,
LPPOINT pptOut
)
{
BOOL bRet;
POINT pt;
bRet = GreSetBrushOrg(hdc,x,y,&pt);
if (bRet && pptOut)
{
try
{
ProbeAndWriteStructure(pptOut,pt,POINT);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(51);
// SetLastError(GetExceptionCode());
bRet = 0;
}
}
return(bRet);
}
/******************************Public*Routine******************************\
* NtGdiUnrealizeObject()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiUnrealizeObject(
HANDLE h
)
{
return(GreUnrealizeObject(h));
}
/******************************Public*Routine******************************\
*
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int
APIENTRY
NtGdiCombineRgn(
HRGN hrgnDst,
HRGN hrgnSrc1,
HRGN hrgnSrc2,
int iMode
)
{
return(GreCombineRgn(hrgnDst,hrgnSrc1,hrgnSrc2,iMode));
}
/******************************Public*Routine******************************\
* NtGdiSetRectRgn()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiSetRectRgn(
HRGN hrgn,
int xLeft,
int yTop,
int xRight,
int yBottom
)
{
return(GreSetRectRgn(hrgn,xLeft,yTop,xRight,yBottom));
}
/******************************Public*Routine******************************\
* NtGdiSetBitmapBits()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
LONG
APIENTRY
NtGdiSetBitmapBits(
HBITMAP hbm,
ULONG cj,
PBYTE pjInit
)
{
LONG lRet = 1;
LONG lOffset = 0;
HANDLE hSecure = 0;
try
{
// Each scan is copied seperately
ProbeForRead(pjInit,cj,sizeof(BYTE));
hSecure = MmSecureVirtualMemory(pjInit, cj, PAGE_READONLY);
if (hSecure == 0)
{
lRet = 0;
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(52);
// SetLastError(GetExceptionCode());
lRet = 0;
}
if (lRet)
lRet = GreSetBitmapBits(hbm,cj,pjInit,&lOffset);
if (hSecure)
{
MmUnsecureVirtualMemory(hSecure);
}
return (lRet);
}
/******************************Public*Routine******************************\
* NtGdiOffsetRgn()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int
APIENTRY
NtGdiOffsetRgn(
HRGN hrgn,
int cx,
int cy
)
{
return(GreOffsetRgn(hrgn,cx,cy));
}
/******************************Public*Routine******************************\
* NtGdiGetRgnBox()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
* 24-Feb-1995 -by- Lingyun Wang [lingyunw]
* expanded it.
\**************************************************************************/
int
APIENTRY
NtGdiGetRgnBox(
HRGN hrgn,
LPRECT prcOut
)
{
RECT rc;
int iRet;
iRet = GreGetRgnBox(hrgn,&rc);
if (iRet)
{
try
{
ProbeAndWriteStructure(prcOut,rc,RECT);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(53);
// SetLastError(GetExceptionCode());
iRet = 0;
}
}
return(iRet);
}
/******************************Public*Routine******************************\
* NtGdiRectInRegion()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiRectInRegion(
HRGN hrgn,
LPRECT prcl
)
{
RECT rc;
BOOL bRet;
if (prcl)
{
RECT rclTmp;
bRet = TRUE;
try
{
rclTmp = ProbeAndReadStructure(prcl,RECT);
//
// Order the rectangle
//
if (rclTmp.left > rclTmp.right)
{
rc.left = rclTmp.right;
rc.right = rclTmp.left;
}
else
{
rc.left = rclTmp.left;
rc.right = rclTmp.right;
}
if (rclTmp.top > rclTmp.bottom)
{
rc.top = rclTmp.bottom;
rc.bottom = rclTmp.top;
}
else
{
rc.top = rclTmp.top;
rc.bottom = rclTmp.bottom;
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(54);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
if (bRet)
{
bRet = GreRectInRegion(hrgn,&rc);
if (bRet)
{
try
{
ProbeAndWriteStructure(prcl,rc,RECT);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(55);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
}
}
}
else
{
bRet = FALSE;
}
return bRet;
}
/******************************Public*Routine******************************\
* NtGdiPtInRegion()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiPtInRegion(
HRGN hrgn,
int x,
int y
)
{
return(GrePtInRegion(hrgn,x,y));
}
/******************************Public*Routine******************************\
* NtGdiGetDIBitsInternal()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int
APIENTRY
NtGdiGetDIBitsInternal(
HDC hdc,
HBITMAP hbm,
UINT iStartScan,
UINT cScans,
LPBYTE pBits,
LPBITMAPINFO pbmi,
UINT iUsage,
UINT cjMaxBits,
UINT cjMaxInfo
)
{
int iRet = 0;
ULONG cjHeader = 0;
BOOL bNullWidth = TRUE;
HANDLE hSecure = 0;
union
{
BITMAPINFOHEADER bmih;
BITMAPCOREHEADER bmch;
} bmihTmp;
PBITMAPINFO pbmiTmp = (PBITMAPINFO)&bmihTmp.bmih;
// do some up front validation
if (((iUsage != DIB_RGB_COLORS) &&
(iUsage != DIB_PAL_COLORS) &&
(iUsage != DIB_PAL_INDICES)) ||
(pbmi == NULL) ||
(hbm == NULL))
{
return(0);
}
if (cScans == 0)
pBits = (PVOID) NULL;
try
{
//
// pbmi might not be aligned.
// First probe to get the size of the structure
// located in the first DWORD. Later, probe the
// actual structure size
//
ProbeForRead(pbmi,sizeof(DWORD),sizeof(BYTE));
// If the bitcount is zero, we will return only the bitmap info or core
// header without the color table. Otherwise, we always return the bitmap
// info with the color table.
{
ULONG StructureSize = pbmi->bmiHeader.biSize;
//
// probe the correct structure size,
// so that we can read/write entire of bitmap header.
//
ProbeForWrite(pbmi,StructureSize,sizeof(BYTE));
if (pBits == (PVOID) NULL)
{
if ((StructureSize == sizeof(BITMAPCOREHEADER)) &&
(((PBITMAPCOREINFO) pbmi)->bmciHeader.bcBitCount == 0))
{
cjHeader = sizeof(BITMAPCOREHEADER);
}
else if ((StructureSize >= sizeof(BITMAPINFOHEADER)) &&
(pbmi->bmiHeader.biBitCount == 0))
{
cjHeader = sizeof(BITMAPINFOHEADER);
}
}
}
// we just need the header so copy it.
if (cjHeader)
{
RtlCopyMemory(pbmiTmp,pbmi,cjHeader);
pbmiTmp->bmiHeader.biSize = cjHeader;
}
else
{
// We need to set biClrUsed to 0 so GreGetBitmapSize computes
// the correct values. biClrUsed is not a input, just output.
if (pbmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
{
// NOTE: We are going to modify bitmap header
// in user mode memory here
// that's why we need to do ProbeWrite()
pbmi->bmiHeader.biClrUsed = 0;
}
// We need more than just the header. This may include bits.
// Compute the the full size of the BITMAPINFO
cjHeader = GreGetBitmapSize(pbmi,iUsage);
if (cjHeader)
{
pbmiTmp = PALLOCMEM(cjHeader,'pmtG');
if (pbmiTmp)
{
// The earlier write probe does not probe all of the
// memory we might read in this case.
ProbeAndReadBuffer(pbmiTmp,pbmi,cjHeader);
// Now that it is safe, make sure it hasn't changed
if (GreGetBitmapSize(pbmiTmp,iUsage) != cjHeader)
{
cjHeader = 0;
}
else
{
// We need to set biClrUsed to 0 so GreGetBitmapSize computes
// the correct values. biClrUsed is not a input, just output.
if (pbmiTmp->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
{
pbmiTmp->bmiHeader.biClrUsed = 0;
}
// Get iStartScan and cNumScan in a valid range.
if (cScans)
{
if (pbmiTmp->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
{
ULONG ulHeight = ABS(pbmiTmp->bmiHeader.biHeight);
iStartScan = MIN(ulHeight, iStartScan);
cScans = MIN((ulHeight - iStartScan), cScans);
bNullWidth = (pbmiTmp->bmiHeader.biWidth == 0) ||
(pbmiTmp->bmiHeader.biPlanes == 0) ||
(pbmiTmp->bmiHeader.biBitCount == 0);
}
else
{
LPBITMAPCOREHEADER pbmc = (LPBITMAPCOREHEADER)pbmiTmp;
iStartScan = MIN((UINT)pbmc->bcHeight, iStartScan);
cScans = MIN((UINT)(pbmc->bcHeight - iStartScan), cScans);
bNullWidth = (pbmc->bcWidth == 0) ||
(pbmc->bcPlanes == 0) ||
(pbmc->bcBitCount == 0);
}
}
}
}
}
}
if (cjHeader && pBits && pbmiTmp)
{
// if they passed a buffer and it isn't BI_RGB,
// they must supply buffer size, 0 is an illegal value
if ((pbmiTmp->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
((pbmiTmp->bmiHeader.biCompression == BI_RLE8) ||
(pbmiTmp->bmiHeader.biCompression == BI_RLE4)) &&
(pbmiTmp->bmiHeader.biSizeImage == 0))
{
cjHeader = 0;
}
else
{
if (cjMaxBits == 0)
cjMaxBits = GreGetBitmapBitsSize(pbmiTmp);
if (cjMaxBits)
{
ProbeForWrite(pBits,cjMaxBits,sizeof(DWORD));
hSecure = MmSecureVirtualMemory(pBits, cjMaxBits, PAGE_READWRITE);
}
if (hSecure == 0)
{
cjHeader = 0;
}
}
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(56);
cjHeader = 0;
}
// did we have an error
if ((pBits && bNullWidth) || (cjHeader == 0) || (pbmiTmp == NULL))
{
//GdiSetLastError(ERROR_INVALID_PARAMETER);
iRet = 0;
}
else
{
// do the work
iRet = GreGetDIBitsInternal(
hdc,hbm,
iStartScan,cScans,
pBits,pbmiTmp,
iUsage,cjMaxBits,cjHeader
);
// copy out the header
if (iRet)
{
try
{
RtlCopyMemory(pbmi,pbmiTmp,cjHeader);
// WINBUG #83055 2-7-2000 bhouse Investigate need to unlock bits
// Old Comment:
// - we also need to unlock the bits
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(57);
// SetLastError(GetExceptionCode());
iRet = 0;
}
}
}
if (hSecure)
{
MmUnsecureVirtualMemory(hSecure);
}
if (pbmiTmp && (pbmiTmp != (PBITMAPINFO)&bmihTmp.bmih))
VFREEMEM(pbmiTmp);
return(iRet);
}
/******************************Public*Routine******************************\
* NtGdiGetTextExtent(
*
* History:
* 07-Feb-1995 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiGetTextExtent(
HDC hdc,
LPWSTR lpwsz,
int cwc,
LPSIZE psize,
UINT flOpts
)
{
SIZE size;
PWSZ pwszCapt = NULL;
WCHAR Localpwsz[LOCAL_CWC_MAX];
BOOL UseLocals;
BOOL bRet = FALSE;
if (cwc >= 0)
{
if (cwc == 0)
{
size.cx = 0;
size.cy = 0;
bRet = TRUE;
}
else
{
if ( cwc > LOCAL_CWC_MAX ) {
UseLocals = FALSE;
} else {
UseLocals = TRUE;
}
//
// capture the string
//
if (lpwsz != NULL)
{
try
{
if ( UseLocals )
{
pwszCapt = Localpwsz;
}
else
{
if (!BALLOC_OVERFLOW1(cwc,WCHAR))
{
pwszCapt = (PWSZ) AllocFreeTmpBuffer(cwc * sizeof(WCHAR));
}
}
if (pwszCapt)
{
ProbeAndReadAlignedBuffer(pwszCapt, lpwsz, cwc*sizeof(WCHAR), sizeof(WCHAR));
bRet = TRUE;
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(58);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
}
if (bRet)
{
bRet = GreGetTextExtentW(hdc, pwszCapt, cwc, &size, flOpts);
}
if (!UseLocals && pwszCapt)
{
FreeTmpBuffer(pwszCapt);
}
}
//
// Write the value back into the user mode buffer
//
if (bRet)
{
try
{
ProbeAndWriteStructure(psize,size,SIZE);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(59);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
}
}
return (bRet);
}
/******************************Public*Routine******************************\
* NtGdiGetTextMetricsW()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiGetTextMetricsW(
HDC hdc,
TMW_INTERNAL * ptm,
ULONG cj
)
{
BOOL bRet = FALSE;
TMW_INTERNAL tmw;
if (cj <= sizeof(tmw))
{
bRet = GreGetTextMetricsW(hdc,&tmw);
if (bRet)
{
try
{
ProbeAndWriteAlignedBuffer(ptm,&tmw,cj, sizeof(DWORD));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(60);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
}
}
return(bRet);
}
/******************************Public*Routine******************************\
* NtGdiGetTextFaceW()
*
* History:
* 10-Mar-1995 -by- Mark Enstrom [marke]
* Wrote it.
\**************************************************************************/
int
APIENTRY
NtGdiGetTextFaceW(
HDC hdc,
int cChar,
LPWSTR pszOut,
BOOL bAliasName
)
{
int cRet = 0;
BOOL bStatus = TRUE;
PWCHAR pwsz_km = (PWCHAR)NULL;
if ((cChar > 0) && (pszOut))
{
if (!BALLOC_OVERFLOW1(cChar,WCHAR))
{
pwsz_km = AllocFreeTmpBuffer(cChar * sizeof(WCHAR));
}
if (pwsz_km == (PWCHAR)NULL)
{
bStatus = FALSE;
}
}
if (bStatus)
{
cRet = GreGetTextFaceW(hdc,cChar,pwsz_km, bAliasName);
if ((cRet > 0) && (pszOut))
{
ASSERTGDI(cRet <= cChar, "GreGetTextFaceW, cRet too big\n");
try
{
ProbeAndWriteBuffer(pszOut,pwsz_km,cRet * sizeof(WCHAR));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(61);
// SetLastError(GetExceptionCode());
cRet = 0;
}
}
if (pwsz_km != (PWCHAR)NULL)
{
FreeTmpBuffer(pwsz_km);
}
}
return(cRet);
}
/******************************Public*Routine******************************\
* NtGdiFontIsLinked()
*
* History:
* 9-July-1998 -by- Yung-Jen Tony Tsai [marke]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiFontIsLinked(
HDC hdc
)
{
return GreFontIsLinked(hdc);
}
/****************************************************************************
* NtGdiQueryFonts
*
* History:
* 5/24/1995 by Gerrit van Wingerden [gerritv]
* Wrote it.
*****************************************************************************/
INT NtGdiQueryFonts(
PUNIVERSAL_FONT_ID pufiFontList,
ULONG nBufferSize,
PLARGE_INTEGER pTimeStamp
)
{
INT iRet = 0;
PUNIVERSAL_FONT_ID pufi = NULL;
LARGE_INTEGER TimeStamp;
if( ( nBufferSize > 0 ) && ( pufiFontList != NULL ) )
{
if (!BALLOC_OVERFLOW1(nBufferSize,UNIVERSAL_FONT_ID))
{
pufi = AllocFreeTmpBuffer(nBufferSize * sizeof(UNIVERSAL_FONT_ID));
}
if( pufi == NULL )
{
iRet = -1 ;
}
}
if( iRet != -1 )
{
iRet = GreQueryFonts(pufi, nBufferSize, &TimeStamp );
if( iRet != -1 )
{
try
{
ProbeAndWriteStructure(pTimeStamp,TimeStamp,LARGE_INTEGER);
if( pufiFontList )
{
ProbeAndWriteAlignedBuffer(pufiFontList,pufi,
sizeof(UNIVERSAL_FONT_ID)*nBufferSize, sizeof(DWORD));
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(62);
iRet = -1;
}
}
}
if( pufi != NULL )
{
FreeTmpBuffer( pufi );
}
if( iRet == -1 )
{
// We need to set the last error here to something because the spooler
// code that calls this relies on there being a non-zero error code
// in the case of failure. Since we really have no idea I will just
// set this to ERROR_NOT_ENOUGH_MEMORY which would be the most likely
// reason for a failure
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
return(iRet);
}
BOOL
GreExtTextOutRect(
HDC hdc,
LPRECT prcl
);
/******************************Public*Routine******************************\
* NtGdiExtTextOutW()
*
* History:
* 06-Feb-1995 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
BOOL NtGdiExtTextOutW
(
HDC hdc,
int x, // Initial x position
int y, // Initial y position
UINT flOpts, // Options
LPRECT prcl, // Clipping rectangle
LPWSTR pwsz, // UNICODE Character array
int cwc, // char count
LPINT pdx, // Character spacing
DWORD dwCodePage // Code page
)
{
RECT newRect;
BOOL bRet;
BYTE CaptureBuffer[TEXT_CAPTURE_BUFFER_SIZE];
BYTE *pjAlloc;
BYTE *pjCapture;
BYTE *pjStrobj;
LONG cjDx;
LONG cjStrobj;
LONG cjString;
LONG cj;
// huge values of cwc will lead to an overflow below causing the system to
// crash
if ((cwc < 0) || (cwc > 0xffff))
{
return(FALSE);
}
if (prcl)
{
if (flOpts & (ETO_OPAQUE | ETO_CLIPPED))
{
try
{
newRect = ProbeAndReadStructure(prcl,RECT);
prcl = &newRect;
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(63);
// SetLastError(GetExceptionCode());
return FALSE;
}
}
else
prcl = NULL;
}
// 0 char case, pass off to special case code.
if (cwc == 0)
{
if ((prcl != NULL) && (flOpts & ETO_OPAQUE))
{
bRet = GreExtTextOutRect(hdc, prcl);
}
else
{
// Bug fix, we have to return TRUE here, MS Publisher
// doesn't work otherwise. Not really that bad, we
// did succeed to draw nothing.
bRet = TRUE;
}
}
else
{
//
// Make sure there is a rectangle or a string if we need them:
//
if ( ((flOpts & (ETO_CLIPPED | ETO_OPAQUE)) && (prcl == NULL)) ||
(pwsz == NULL) )
{
bRet = FALSE;
}
else
{
bRet = TRUE;
//
// We allocate a single buffer to hold the captured copy of
// the pdx array (if there is one), room for the STROBJ,
// and to hold the captured copy of the string (in that
// order).
//
// NOTE: With the appropriate exception handling in the
// body of ExtTextOutW, we might not need to copy
// these buffers:
//
//
// see if it is for a user mode printer driver
//
cjDx = 0; // dword sized
cjStrobj = SIZEOF_STROBJ_BUFFER(cwc); // dword sized
cjString = cwc * sizeof(WCHAR); // not dword sized
if (pdx)
{
cjDx = cwc * sizeof(INT); // dword sized
if (flOpts & ETO_PDY)
cjDx *= 2; // space for pdy array
}
cj = ALIGN_PTR(cjDx) + cjStrobj + cjString;
if (cj <= TEXT_CAPTURE_BUFFER_SIZE)
{
pjAlloc = NULL;
pjCapture = CaptureBuffer;
}
else
{
pjAlloc = AllocFreeTmpBuffer(cj);
pjCapture = pjAlloc;
if (pjAlloc == NULL)
return(FALSE);
}
if (pdx)
{
try
{
// NOTE: Works95 passes byte aligned pointers for
// this. Since we copy it any ways, this is not
// really a problem and it is compatible with NT 3.51.
ProbeForRead(pdx, cjDx, sizeof(BYTE));
RtlCopyMemory(pjCapture, pdx, cjDx);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(64);
bRet = FALSE;
}
pdx = (INT*) pjCapture;
pjCapture += ALIGN_PTR(cjDx);
}
pjStrobj = pjCapture;
pjCapture += cjStrobj;
ASSERTGDI((((ULONG_PTR) pjCapture) & (sizeof(PVOID)-1)) == 0,
"Buffers should be ptr aligned");
try
{
ProbeForRead(pwsz, cwc*sizeof(WCHAR), sizeof(WCHAR));
RtlCopyMemory(pjCapture, pwsz, cwc*sizeof(WCHAR));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(65);
bRet = FALSE;
}
if (bRet)
{
bRet = GreExtTextOutWInternal(hdc,
x,
y,
flOpts,
prcl,
(LPWSTR) pjCapture,
cwc,
pdx,
pjStrobj,
dwCodePage);
}
if (pjAlloc)
{
FREEALLOCTEMPBUFFER(pjAlloc);
}
}
}
return bRet;
}
/************************Public*Routine**************************\
* NtGdiConsoleTextOut()
*
* History:
* 23-Mar-1998 -by- Xudong Wu [TessieW]
* Wrote it.
\****************************************************************/
#define CONSOLE_BUFFER 128
BOOL NtGdiConsoleTextOut(
HDC hdc,
POLYTEXTW *lpto, // Ptr to array of polytext structures
UINT nStrings, // number of polytext structures
RECTL *prclBounds
)
{
BOOL bStatus = TRUE;
ULONG ulSize = nStrings * sizeof(POLYTEXTW);
POLYTEXTW *lptoTmp = NULL, *ppt;
RECTL rclBoundsTmp;
PBYTE pjBuffer, pjBufferEnd;
ULONG aulTmp[CONSOLE_BUFFER];
if (nStrings == 0)
return TRUE;
if (!lpto)
return FALSE;
if (prclBounds)
{
try
{
rclBoundsTmp = ProbeAndReadStructure(prclBounds, RECTL);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNING("NtGdiConsoleTextOut invalid prclBounds\n");
return FALSE;
}
}
if (!BALLOC_OVERFLOW1(nStrings,POLYTEXTW))
{
try
{
ProbeForRead(lpto, nStrings * sizeof(POLYTEXTW), sizeof(ULONG));
for (ppt = lpto; ppt < lpto + nStrings; ppt++)
{
int n = ppt->n;
ULONG ulTmp; // used to check for
// overflow of ulSize
//
// Pull count from each, also check for
// non-zero length and NULL string
//
ulTmp = ulSize;
ulSize += n * sizeof(WCHAR);
if (BALLOC_OVERFLOW1(n, WCHAR) ||
(ulSize < ulTmp) ||
(ppt->pdx != (int *)NULL) ||
((n != 0) && (ppt->lpstr == NULL)))
{
bStatus = FALSE;
break;
}
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
bStatus = FALSE;
WARNING("NtGdiConsoleTextOut invalid lpto\n");
}
}
else
{
bStatus = FALSE;
}
if (bStatus)
{
if (ulSize > (CONSOLE_BUFFER * sizeof(ULONG)))
{
lptoTmp = AllocFreeTmpBuffer(ulSize);
}
else
{
lptoTmp = (POLYTEXTW *)aulTmp;
}
if (lptoTmp)
{
try
{
ProbeAndReadBuffer(lptoTmp, lpto, nStrings * sizeof(POLYTEXTW));
pjBuffer = ((BYTE*)lptoTmp) + nStrings * sizeof(POLYTEXTW);
pjBufferEnd = pjBuffer + ulSize;
for (ppt = lptoTmp; ppt < lptoTmp + nStrings; ppt++)
{
if (ppt->n)
{
ULONG StrSize = ppt->n * sizeof(WCHAR);
if (ppt->pdx || (ppt->lpstr == NULL))
{
bStatus = FALSE;
break;
}
if (BALLOC_OVERFLOW1(ppt->n, WCHAR) || ((pjBuffer + StrSize) > pjBufferEnd))
{
bStatus = FALSE;
break;
}
ProbeAndReadAlignedBuffer(pjBuffer, ppt->lpstr, StrSize, sizeof(WCHAR));
ppt->lpstr = (LPWSTR)pjBuffer;
pjBuffer += StrSize;
}
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
bStatus = FALSE;
WARNING("NtGdiConsoleTextOut() failed to copy lpto\n");
}
if (bStatus)
{
bStatus = GreConsoleTextOut(hdc, lptoTmp, nStrings, prclBounds ? &rclBoundsTmp : NULL);
}
if (lptoTmp != (POLYTEXTW *)aulTmp)
FreeTmpBuffer(lptoTmp);
}
else
{
WARNING("NtGdiConsoleTextOut() failed to alloc mem\n");
}
}
return bStatus;
}
/******************************Public*Routine******************************\
*
* BOOL bCheckAndCapThePath, used in add/remove font resoruce
*
* History:
* 11-Apr-1996 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL bCheckAndCapThePath (
WCHAR *pwszUcPath, // output
WCHAR *pwszFiles, // input
ULONG cwc,
ULONG cFiles
)
{
ULONG cFiles1 = 1; // for consistency checking
BOOL bRet = TRUE;
ULONG iwc;
ASSERTGDI(!BALLOC_OVERFLOW1(cwc,WCHAR),
"caller should check for overflow\n");
ProbeForRead(pwszFiles, cwc * sizeof(WCHAR), sizeof(CHAR));
if (pwszFiles[cwc - 1] == L'\0')
{
// this used to be done later, in gdi code which now expects capped string
cCapString(pwszUcPath, pwszFiles, cwc);
// replace separators by zeros, want zero terminated strings in
// the engine
for (iwc = 0; iwc < cwc; iwc++)
{
if (pwszUcPath[iwc] == PATH_SEPARATOR)
{
pwszUcPath[iwc] = L'\0';
cFiles1++;
}
}
// check consistency
if (cFiles != cFiles1)
bRet = FALSE;
}
else
{
bRet = FALSE;
}
return bRet;
}
// MISC FONT API's
/******************************Public*Routine******************************\
* NtGdiAddFontResourceW()
*
* History:
* Wed 11-Oct-1995 -by- Bodin Dresevic [BodinD]
* Rewrote it
\**************************************************************************/
#define CWC_PATH 80
int
APIENTRY
NtGdiAddFontResourceW(
WCHAR *pwszFiles,
ULONG cwc,
ULONG cFiles,
FLONG f,
DWORD dwPidTid,
DESIGNVECTOR *pdv
)
{
WCHAR awcPath[CWC_PATH];
WCHAR *pwszPath = NULL; // essential initialization
int iRet = 0;
ULONG iwc;
DESIGNVECTOR dvTmp;
DWORD cjDV = 0;
DWORD dvNumAxes = 0;
try
{
if (cwc > 1)
{
if (cwc <= CWC_PATH)
{
pwszPath = awcPath;
}
else if (cwc <= 4 * (MAX_PATH + 1))
{
pwszPath = AllocFreeTmpBuffer(cwc * sizeof(WCHAR));
}
else
{
iRet = 0;
WARNING("NtGdiAddFontResourceW: pwszFiles longer than 4*(MAX_PATH+1)\n");
}
if (pwszPath)
{
// RtlUpcaseUnicodeString() doesn't initialize the buffer
// if it is bigger than 0x7FFF
iRet = (int)bCheckAndCapThePath(pwszPath,pwszFiles,cwc,cFiles);
}
}
if (iRet && pdv)
{
// get the dvNumAxes first
ProbeForRead(pdv, offsetof(DESIGNVECTOR,dvValues) , sizeof(BYTE));
dvNumAxes = pdv->dvNumAxes;
if ((dvNumAxes > 0) && (dvNumAxes <= MM_MAX_NUMAXES))
{
cjDV = SIZEOFDV(dvNumAxes);
if (!BALLOC_OVERFLOW1(cjDV, BYTE))
{
ProbeAndReadBuffer(&dvTmp, pdv, cjDV);
pdv = &dvTmp;
}
else
iRet = 0;
}
else if (dvNumAxes == 0)
{
pdv = 0;
}
else
{
iRet = 0;
}
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
iRet = 0;
WARNINGX(95);
}
if (iRet)
iRet = GreAddFontResourceWInternal(pwszPath, cwc, cFiles,f,dwPidTid, pdv, cjDV);
if (iRet) //Increase global time stamp for realization info
(gpGdiSharedMemory->timeStamp)++;
if (pwszPath && (pwszPath != awcPath))
FreeTmpBuffer(pwszPath);
TRACE_FONT(("Leaving: NtGdiAddFontResourceW"));
return iRet;
}
/*************Public*Routine***************************\
* BOOL APIENTRY NtGdiUnmapMemFont *
* *
* History: *
* Jul-03-1996 -by- Xudong Wu [TessieW] *
* *
* Wrote it. *
*******************************************************/
BOOL APIENTRY NtGdiUnmapMemFont(PVOID pvView)
{
// we may need this if we ever figure out how to map the memory font to
// the application's address space
return 1;
}
/***************Public*Routine**************************\
* HANDLE NtGdiAddFontMemResourceEx() *
* *
* History: *
* 09-Jun-1996 -by- Xudong Wu [TessieW] *
* *
* Wrote it. *
********************************************************/
HANDLE APIENTRY NtGdiAddFontMemResourceEx
(
PVOID pvBuffer,
ULONG cjBuffer,
DESIGNVECTOR *pdv,
DWORD cjDV,
DWORD *pNumFonts
)
{
BOOL bOK = TRUE;
HANDLE hMMFont = 0;
DESIGNVECTOR dvTmp;
// check the size and pointer
if ((cjBuffer == 0) || (pvBuffer == NULL) || (pNumFonts == NULL))
{
return 0;
}
__try
{
if (cjDV)
{
if (cjDV <= SIZEOFDV(MM_MAX_NUMAXES))
{
ProbeAndReadBuffer(&dvTmp, pdv, cjDV);
pdv = &dvTmp;
}
else
{
bOK = FALSE;
}
}
else
{
pdv = NULL;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
bOK = FALSE;
WARNING("NtGdiAddFontMemResource() try-except\n");
}
if (bOK)
{
DWORD cFonts;
if (hMMFont = GreAddFontMemResourceEx(pvBuffer, cjBuffer, pdv, cjDV, &cFonts))
{
__try
{
ProbeAndWriteUlong(pNumFonts, cFonts);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
GreRemoveFontMemResourceEx(hMMFont);
hMMFont = 0;
}
}
}
return hMMFont;
}
/******************************Public*Routine******************************\
* BOOL APIENTRY NtGdiRemoveFontResourceW
*
* History:
* 28-Mar-1996 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiRemoveFontResourceW(
WCHAR *pwszFiles,
ULONG cwc,
ULONG cFiles,
ULONG fl,
DWORD dwPidTid,
DESIGNVECTOR *pdv
)
{
WCHAR awcPath[CWC_PATH];
WCHAR *pwszPath = NULL; // essential initialization
BOOL bRet = FALSE;
DESIGNVECTOR dvTmp;
DWORD cjDV = 0, dvNumAxes = 0;
TRACE_FONT(("Entering: NtGdiRemoveFontResourceW(\"%ws\",%-#x,%-#x)\n",pwszFiles, cwc,cFiles));
try
{
if (cwc > 1)
{
if (cwc <= CWC_PATH)
{
pwszPath = awcPath;
}
else if (!BALLOC_OVERFLOW1(cwc,WCHAR))
{
pwszPath = AllocFreeTmpBuffer(cwc * sizeof(WCHAR));
}
if (pwszPath)
{
bRet = bCheckAndCapThePath(pwszPath, pwszFiles, cwc, cFiles);
}
}
if (bRet && pdv)
{
// get the dvNumAxes first
ProbeForRead(pdv, offsetof(DESIGNVECTOR,dvValues) , sizeof(BYTE));
dvNumAxes = pdv->dvNumAxes;
if ((dvNumAxes > 0) && (dvNumAxes <= MM_MAX_NUMAXES))
{
cjDV = SIZEOFDV(dvNumAxes);
if (!BALLOC_OVERFLOW1(cjDV, BYTE))
{
ProbeAndReadBuffer(&dvTmp, pdv, cjDV);
pdv = &dvTmp;
}
else
bRet = FALSE;
}
else if (dvNumAxes == 0)
{
pdv = 0;
}
else
{
bRet = FALSE;
}
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
bRet = FALSE;
WARNINGX(96);
}
if (bRet)
bRet = GreRemoveFontResourceW(pwszPath, cwc, cFiles, fl, dwPidTid, pdv, cjDV);
if (bRet) //Increase global time stamp for realization info
(gpGdiSharedMemory->timeStamp)++;
if (pwszPath && (pwszPath != awcPath))
FreeTmpBuffer(pwszPath);
TRACE_FONT(("Leaving: NtGdiRemoveFontResourceW"));
return bRet;
}
/***************Public*Routine**************************\
* NtGdiRemoveFontMemResourceEx() *
* *
* History: *
* 09-Jun-1996 -by- Xudong Wu [TessieW] *
* *
* Wrote it. *
********************************************************/
BOOL
APIENTRY
NtGdiRemoveFontMemResourceEx(HANDLE hMMFont)
{
BOOL bRet = TRUE;
if (hMMFont == 0)
{
return FALSE;
}
if (bRet)
{
bRet = GreRemoveFontMemResourceEx(hMMFont);
}
return bRet;
}
/******************************Public*Routine******************************\
* NtGdiEnumFontClose()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiEnumFontClose(
ULONG_PTR idEnum
)
{
return(bEnumFontClose(idEnum));
}
/******************************Public*Routine******************************\
* NtGdiEnumFontChunk()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiEnumFontChunk(
HDC hdc,
ULONG_PTR idEnum,
ULONG cjEfdw,
ULONG *pcjEfdw,
PENUMFONTDATAW pefdw
)
{
HANDLE hSecure;
BOOL bRet = TRUE;
ULONG cjEfdwRet = 0;
try
{
ProbeForWrite(pefdw, cjEfdw, sizeof(DWORD));
hSecure = MmSecureVirtualMemory(pefdw, cjEfdw, PAGE_READWRITE);
if (!hSecure)
{
bRet = FALSE;
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(66);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
if (bRet)
{
try
{
bRet = bEnumFontChunk(hdc,idEnum,cjEfdw,&cjEfdwRet,pefdw);
ProbeAndWriteUlong(pcjEfdw,cjEfdwRet);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(105);
bRet = FALSE;
}
MmUnsecureVirtualMemory(hSecure);
}
return (bRet);
}
/******************************Public*Routine******************************\
* NtGdiEnumFontOpen()
*
* History:
* 08-Mar-1995 Mark Enstrom [marke]
* Wrote it.
\**************************************************************************/
ULONG_PTR
APIENTRY
NtGdiEnumFontOpen(
HDC hdc,
ULONG iEnumType,
FLONG flWin31Compat,
ULONG cwchMax,
LPWSTR pwszFaceName,
ULONG lfCharSet,
ULONG *pulCount
)
{
ULONG cwchFaceName;
PWSTR pwszKmFaceName = NULL;
ULONG_PTR ulRet = 0;
BOOL bRet = TRUE;
ULONG ulCount = 0;
if (pwszFaceName != (PWSZ)NULL)
{
if ((cwchMax == 0) || (cwchMax > LF_FACESIZE))
return FALSE;
if (!BALLOC_OVERFLOW1(cwchMax,WCHAR))
{
pwszKmFaceName = (PWSZ)AllocFreeTmpBuffer(cwchMax * sizeof(WCHAR));
}
if (pwszKmFaceName != (PWSZ)NULL)
{
try
{
ProbeAndReadAlignedBuffer(pwszKmFaceName,pwszFaceName, cwchMax * sizeof(WCHAR), sizeof(WCHAR));
// GreEnumFontOpen expects zero terminated sting
pwszKmFaceName[cwchMax-1] = 0;
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(66);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
}
else
{
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
}
else
{
pwszKmFaceName = (PWSZ)NULL;
cwchMax = 0;
}
if (bRet)
{
ulRet = GreEnumFontOpen(hdc,iEnumType,flWin31Compat,cwchMax,
(PWSZ)pwszKmFaceName, lfCharSet,&ulCount);
if (ulRet)
{
try
{
ProbeAndWriteUlong(pulCount,ulCount);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(67);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
}
}
if (pwszKmFaceName != (PWSTR)NULL)
{
FreeTmpBuffer(pwszKmFaceName);
}
return(ulRet);
}
/******************************Public*Routine******************************\
* NtGdiGetFontResourceInfoInternalW()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiGetFontResourceInfoInternalW(
LPWSTR pwszFiles,
ULONG cwc,
ULONG cFiles,
UINT cjIn,
LPDWORD pdwBytes,
LPVOID pvBuf,
DWORD iType
)
{
WCHAR awcPath[CWC_PATH];
WCHAR *pwszPath = NULL; // essential initialization
BOOL bRet = FALSE;
SIZE_T dwBytesTmp;
LOGFONTW lfw;
LPVOID pvBufTmp = NULL;
TRACE_FONT(("Entering: NtGdiGetFontResourceInfoInternalW(\"%ws\",%-#x,%-#x)\n",pwszFiles, cwc,cFiles));
try
{
if (cwc > 1)
{
if (cwc <= CWC_PATH)
{
pwszPath = awcPath;
}
else if (!BALLOC_OVERFLOW1(cwc,WCHAR))
{
pwszPath = AllocFreeTmpBuffer(cwc * sizeof(WCHAR));
}
if (pwszPath)
{
bRet = bCheckAndCapThePath(pwszPath, pwszFiles, cwc, cFiles);
}
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(97);
}
if (cjIn > sizeof(LOGFONTW))
{
if (!BALLOC_OVERFLOW1(cjIn, BYTE))
{
pvBufTmp = PALLOCMEM(cjIn, 'pmtG');
if (!pvBufTmp)
{
WARNING("NtGdiGetFontResourceInfoInternalW: failed to allocate memory\n");
bRet = FALSE;
}
}
}
else
{
pvBufTmp = (PVOID)&lfw;
}
if (bRet && (bRet = GetFontResourceInfoInternalW(pwszPath,cwc, cFiles, cjIn,
&dwBytesTmp, pvBufTmp, iType)))
{
try
{
ProbeAndWriteUlong(pdwBytes, (ULONG) dwBytesTmp);
if (cjIn)
{
ProbeAndWriteBuffer(pvBuf, pvBufTmp, cjIn);
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(110);
}
}
if (pwszPath && (pwszPath != awcPath))
FreeTmpBuffer(pwszPath);
if (pvBufTmp && (pvBufTmp != (PVOID)&lfw))
{
VFREEMEM(pvBufTmp);
}
TRACE_FONT(("Leaving: NtGdiGetFontResourceInfoInternalW\n"));
return bRet;
}
ULONG
APIENTRY
NtGdiGetEmbedFonts()
{
return GreGetEmbedFonts();
}
BOOL
APIENTRY
NtGdiChangeGhostFont(KERNEL_PVOID *pfontID, BOOL bLoad)
{
BOOL bRet = TRUE;
VOID *fontID;
try
{
ProbeAndReadBuffer(&fontID, pfontID, sizeof(VOID*));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(68);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
bRet = bRet && GreChangeGhostFont(fontID, bLoad);
return bRet;
}
/******************************Public*Routine******************************\
* NtGdiGetUFI()
*
* History:
* 02-Feb-1995 -by- Andre Vachon [andreva]
* Wrote it.
* 01-Mar-1995 -by- Lingyun Wang [lingyunw]
* Expanded it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiGetUFI(
HDC hdc,
PUNIVERSAL_FONT_ID pufi,
DESIGNVECTOR *pdv, ULONG *pcjDV, ULONG *pulBaseCheckSum,
FLONG *pfl
)
{
UNIVERSAL_FONT_ID ufiTmp;
BOOL bRet = TRUE;
FLONG flTmp;
DESIGNVECTOR dvTmp;
ULONG cjDVTmp;
ULONG ulBaseCheckSum = 0;
bRet = GreGetUFI(hdc, &ufiTmp, &dvTmp, &cjDVTmp, &ulBaseCheckSum, &flTmp, NULL);
try
{
if (bRet)
{
ProbeAndWriteStructure(pufi,ufiTmp,UNIVERSAL_FONT_ID);
ProbeAndWriteUlong(pfl, flTmp);
if ((flTmp & FL_UFI_DESIGNVECTOR_PFF) && pdv)
{
ProbeAndWriteBuffer(pdv, &dvTmp, cjDVTmp);
ProbeAndWriteUlong(pcjDV, cjDVTmp);
ProbeAndWriteUlong(pulBaseCheckSum, ulBaseCheckSum);
}
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(68);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
return (bRet);
}
BOOL
APIENTRY
NtGdiGetEmbUFI(
HDC hdc,
PUNIVERSAL_FONT_ID pufi,
DESIGNVECTOR *pdv, ULONG *pcjDV, ULONG *pulBaseCheckSum,
FLONG *pfl,
KERNEL_PVOID *pEmbFontID
)
{
UNIVERSAL_FONT_ID ufiTmp;
BOOL bRet = TRUE;
FLONG flTmp;
DESIGNVECTOR dvTmp;
ULONG cjDVTmp;
ULONG ulBaseCheckSum = 0;
VOID *fontID;
bRet = GreGetUFI(hdc, &ufiTmp, &dvTmp, &cjDVTmp, &ulBaseCheckSum, &flTmp, &fontID);
try
{
if (bRet)
{
ProbeAndWriteStructure(pufi,ufiTmp,UNIVERSAL_FONT_ID);
ProbeAndWriteUlong(pfl, flTmp);
ProbeAndWriteBuffer(pEmbFontID, &fontID, sizeof(VOID*));
if ((flTmp & FL_UFI_DESIGNVECTOR_PFF) && pdv)
{
ProbeAndWriteBuffer(pdv, &dvTmp, cjDVTmp);
ProbeAndWriteUlong(pcjDV, cjDVTmp);
ProbeAndWriteUlong(pulBaseCheckSum, ulBaseCheckSum);
}
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(68);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
return (bRet);
}
/**************************Public*Routine**************************\
* NtGdiGetUFIPathname()
*
* Return the font file path name according to the input ufi.
*
* History:
* Feb-04-1997 Xudong Wu [tessiew]
* Wrote it.
*
\*******************************************************************/
BOOL
APIENTRY
NtGdiGetUFIPathname
(
PUNIVERSAL_FONT_ID pufi,
ULONG* pcwc,
LPWSTR pwszPathname,
ULONG* pcNumFiles,
FLONG fl,
BOOL *pbMemFont,
ULONG *pcjView,
PVOID pvView,
BOOL *pbTTC,
ULONG *piTTC
)
{
UNIVERSAL_FONT_ID ufiTmp;
WCHAR awszTmp[MAX_PATH], *pwszTmp = NULL;
COUNT cwcTmp, cNumFilesTmp;
BOOL bRet = TRUE;
BOOL bMemFontTmp;
PVOID pvViewTmp = pvView;
ULONG cjViewTmp;
BOOL bTTC;
ULONG iTTC;
try
{
ufiTmp = ProbeAndReadStructure(pufi, UNIVERSAL_FONT_ID);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(105);
bRet = FALSE;
}
if (bRet && (bRet = GreGetUFIPathname(&ufiTmp,
&cwcTmp,
NULL, // just ask for the size
&cNumFilesTmp,
fl,
&bMemFontTmp,
&cjViewTmp,
pvViewTmp,
pbTTC ? &bTTC : NULL,
piTTC ? &iTTC : NULL)))
{
if (cwcTmp <= MAX_PATH)
{
pwszTmp = awszTmp;
}
else
{
if (!BALLOC_OVERFLOW1(cwcTmp,WCHAR))
{
pwszTmp = AllocFreeTmpBuffer(cwcTmp * sizeof(WCHAR));
}
if (!pwszTmp)
bRet = FALSE;
}
}
if (bRet && (!bMemFontTmp) && pwszTmp)
{
bRet = GreGetUFIPathname(&ufiTmp,
&cwcTmp,
pwszTmp,
&cNumFilesTmp,
fl,
NULL,
NULL,
NULL,
pbTTC ? &bTTC : NULL,
piTTC ? &iTTC : NULL
);
}
if (bRet)
{
try
{
if (pcwc)
{
ProbeAndWriteStructure(pcwc, cwcTmp, ULONG);
}
if (pwszPathname)
{
ProbeAndWriteBuffer(pwszPathname, pwszTmp, cwcTmp * sizeof(WCHAR));
}
if (pcNumFiles)
{
ProbeAndWriteStructure(pcNumFiles, cNumFilesTmp, ULONG);
}
if (bMemFontTmp)
{
if (pbMemFont)
{
ProbeAndWriteStructure(pbMemFont, bMemFontTmp, BOOL);
}
if (pcjView)
{
ProbeAndWriteUlong(pcjView, cjViewTmp);
}
}
if (pbTTC)
{
ProbeAndWriteStructure(pbTTC, bTTC, BOOL);
}
if (piTTC)
{
ProbeAndWriteUlong(piTTC, iTTC);
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(107);
bRet = FALSE;
}
}
if (pwszTmp && (pwszTmp != awszTmp))
{
FreeTmpBuffer(pwszTmp);
}
return (bRet);
}
/******************************Public*Routine******************************\
* NtGdiSetLayout
*
* History:
* 29-Oct-1997 -by- Mohamed Hassanin [mhamid]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
NtGdiSetLayout(
HDC hdc,
LONG wox,
DWORD dwLayout)
{
return GreSetLayout(hdc, wox, dwLayout);
}
BOOL
APIENTRY
NtGdiMirrorWindowOrg(
HDC hdc)
{
return GreMirrorWindowOrg(hdc);
}
LONG
APIENTRY
NtGdiGetDeviceWidth(
HDC hdc)
{
return GreGetDeviceWidth(hdc);
}
/******************************Public*Routine******************************\
* NtGdiGetDCPoint()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiGetDCPoint(
HDC hdc,
UINT iPoint,
PPOINTL pptOut
)
{
BOOL bRet;
POINTL pt;
if (bRet = GreGetDCPoint(hdc,iPoint,&pt))
{
// modify *pptOut only if successful
try
{
ProbeAndWriteStructure(pptOut,pt,POINT);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(71);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
}
return(bRet);
}
/******************************Public*Routine******************************\
* NtGdiScaleWindowExtEx()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiScaleWindowExtEx(
HDC hdc,
int xNum,
int xDenom,
int yNum,
int yDenom,
LPSIZE pszOut
)
{
BOOL bRet;
SIZE sz;
bRet = GreScaleWindowExtEx(hdc,xNum,xDenom,yNum,yDenom,&sz);
if (bRet && pszOut)
{
try
{
ProbeAndWriteStructure(pszOut,sz,SIZE);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(73);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
}
return(bRet);
}
/******************************Public*Routine******************************\
* NtGdiGetTransform()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiGetTransform(
HDC hdc,
DWORD iXform,
LPXFORM pxf
)
{
BOOL bRet;
XFORM xf;
bRet = GreGetTransform(hdc,iXform,(XFORML *)&xf);
if (bRet)
{
try
{
ProbeAndWriteStructure(pxf,xf,XFORM);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(74);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
}
return(bRet);
}
/******************************Public*Routine******************************\
* NtGdiCombineTransform()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiCombineTransform(
LPXFORM pxfDst,
LPXFORM pxfSrc1,
LPXFORM pxfSrc2
)
{
BOOL bRet;
XFORM xfSrc1;
XFORM xfSrc2;
XFORM xfDst;
bRet = ProbeAndConvertXFORM ((XFORML *)pxfSrc1, (XFORML *)&xfSrc1)
&& ProbeAndConvertXFORM ((XFORML *)pxfSrc2, (XFORML *)&xfSrc2);
if (bRet)
{
bRet = GreCombineTransform((XFORML *)&xfDst,(XFORML *)&xfSrc1,(XFORML *)&xfSrc2);
if (bRet)
{
try
{
ProbeAndWriteStructure(pxfDst,xfDst,XFORM);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(76);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
}
}
return(bRet);
}
/******************************Public*Routine******************************\
* NtGdiTransformPoints()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiTransformPoints(
HDC hdc,
PPOINT pptIn,
PPOINT pptOut,
int c,
int iMode
)
{
BOOL bRet = TRUE;
POINT apt[10];
PPOINT pptTmp = apt;
//
// validate
//
if (c <= 0)
{
//
// GetTransformPoints returns TRUE for this condition, as does
// the DPtoLP and LPtoDP APIs.
//
return bRet;
}
//
// we will just use the the stack if there are less than 10 points
// otherwise allocate mem from heap
//
if (c > 10)
{
//
// local stack is not enough, invalidate pointer and try to allocate.
//
pptTmp = NULL;
if (!BALLOC_OVERFLOW1(c,POINT))
{
pptTmp = AllocFreeTmpBuffer(c * sizeof(POINT));
}
}
//
// copy pptIn into pptTmp
//
if (pptTmp)
{
try
{
ProbeForRead(pptIn,c * sizeof(POINT), sizeof(BYTE));
RtlCopyMemory(pptTmp,pptIn,c*sizeof(POINT));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(77);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
}
else
{
bRet = FALSE;
}
if (bRet)
{
bRet = GreTransformPoints(hdc,pptTmp,pptTmp,c,iMode);
}
//
// copy pptTmp out to pptOut
//
if (bRet)
{
try
{
ProbeAndWriteBuffer(pptOut,pptTmp,c*sizeof(POINT));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(77);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
}
if (pptTmp && (pptTmp != apt))
FreeTmpBuffer(pptTmp);
return(bRet);
}
/******************************Public*Routine******************************\
* NtGdiGetTextCharsetInfo()
*
* History:
* Thu 23-Mar-1995 -by- Bodin Dresevic [BodinD]
* update: fixed it.
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int
APIENTRY
NtGdiGetTextCharsetInfo(
HDC hdc,
LPFONTSIGNATURE lpSig,
DWORD dwFlags
)
{
FONTSIGNATURE fsig;
int iRet = GDI_ERROR;
fsig.fsUsb[0] = 0;
fsig.fsUsb[1] = 0;
fsig.fsUsb[2] = 0;
fsig.fsUsb[3] = 0;
fsig.fsCsb[0] = 0;
fsig.fsCsb[1] = 0;
iRet = GreGetTextCharsetInfo(hdc, lpSig ? &fsig : NULL , dwFlags);
if (iRet != GDI_ERROR)
{
if (lpSig)
{
try
{
ProbeAndWriteStructure(lpSig, fsig, FONTSIGNATURE);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(78);
// SetLastError(GetExceptionCode());
// look into gtc.c win95 source file, this is what they return
// in case of bad write pointer [bodind],
// cant return 0 - that's ANSI_CHARSET!
iRet = DEFAULT_CHARSET;
}
}
}
return iRet;
}
/******************************Public*Routine******************************\
* NtGdiGetBitmapDimension()
*
* History:
* 23-Feb-1995 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiGetBitmapDimension(
HBITMAP hbm,
LPSIZE psize
)
{
BOOL bRet;
SIZE tmpsize;
// check for null handle
if (hbm == 0)
{
bRet = FALSE;
}
// do the real work
else
{
bRet = GreGetBitmapDimension(hbm,&tmpsize);
// if Gre call is successful do this, otherwise
// we don't bother
if (bRet)
{
try
{
ProbeAndWriteStructure(psize,tmpsize,SIZE);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(81);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
}
}
return (bRet);
}
/******************************Public*Routine******************************\
* NtGdiSetBitmapDimension()
*
* History:
* 23-Feb-1995 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
BOOL
APIENTRY
NtGdiSetBitmapDimension(
HBITMAP hbm,
int cx,
int cy,
LPSIZE psizeOut
)
{
BOOL bRet;
SIZE tmpsize;
// check for null handle
if (hbm == 0)
{
bRet = FALSE;
}
// do the real work
else
{
bRet = GreSetBitmapDimension(hbm,cx, cy, &tmpsize);
// if the Gre call is successful, we copy out
// the original size
if (bRet && psizeOut)
{
try
{
ProbeAndWriteStructure(psizeOut,tmpsize,SIZE);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(82);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
}
}
return (bRet);
}
BOOL
APIENTRY
NtGdiForceUFIMapping(
HDC hdc,
PUNIVERSAL_FONT_ID pufi
)
{
BOOL bRet = FALSE;
if( pufi )
{
try
{
UNIVERSAL_FONT_ID ufi;
ufi = ProbeAndReadStructure( pufi, UNIVERSAL_FONT_ID);
bRet = GreForceUFIMapping( hdc, &ufi);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(87);
bRet = FALSE;
}
}
return bRet;
}
typedef LONG (*NTGDIPALFUN)(HPALETTE,UINT,UINT,PPALETTEENTRY);
NTGDIPALFUN palfun[] =
{
(NTGDIPALFUN)GreAnimatePalette,
(NTGDIPALFUN)GreSetPaletteEntries,
(NTGDIPALFUN)GreGetPaletteEntries,
(NTGDIPALFUN)GreGetSystemPaletteEntries,
(NTGDIPALFUN)GreGetDIBColorTable,
(NTGDIPALFUN)GreSetDIBColorTable
};
/******************************Public*Routine******************************\
* NtGdiDoPalette
*
* History:
* 08-Mar-1995 Mark Enstrom [marke]
* Wrote it.
\**************************************************************************/
LONG
APIENTRY
NtGdiDoPalette(
HPALETTE hpal,
WORD iStart,
WORD cEntries,
PALETTEENTRY *pPalEntries,
DWORD iFunc,
BOOL bInbound)
{
LONG lRet = 0;
BOOL bStatus = TRUE;
PALETTEENTRY *ppalBuffer = (PALETTEENTRY*)NULL;
if (iFunc <= 5)
{
if (bInbound)
{
//
// copy pal entries to temp buffer if needed
//
if ((cEntries > 0))
{
if (!BALLOC_OVERFLOW1(cEntries,PALETTEENTRY))
{
ppalBuffer = (PALETTEENTRY *)AllocFreeTmpBuffer(cEntries * sizeof(PALETTEENTRY));
}
if (ppalBuffer == NULL)
{
bStatus = FALSE;
}
else
{
try
{
ProbeAndReadBuffer(ppalBuffer,pPalEntries,cEntries * sizeof(PALETTEENTRY));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(88);
bStatus = FALSE;
//SetLastError(GetExceptionCode());
}
}
}
if (bStatus)
{
lRet = (*palfun[iFunc])(
hpal,
iStart,
cEntries,
ppalBuffer);
}
}
else
{
LONG lRetEntries;
//
// Query of palette information
//
if (pPalEntries != (PALETTEENTRY*)NULL)
{
if (cEntries == 0)
{
// if there is a buffer but no entries, we're done.
bStatus = FALSE;
lRet = 0;
}
else
{
if (!BALLOC_OVERFLOW1(cEntries,PALETTEENTRY))
{
ppalBuffer = (PALETTEENTRY *)AllocFreeTmpBuffer(cEntries * sizeof(PALETTEENTRY));
}
if (ppalBuffer == NULL)
{
bStatus = FALSE;
}
}
}
if (bStatus)
{
lRet = (*palfun[iFunc])(
hpal,
iStart,
cEntries,
ppalBuffer);
//
// copy data back (if there is a buffer)
//
lRetEntries = min((LONG)cEntries,lRet);
if ((lRetEntries > 0) && (pPalEntries != (PALETTEENTRY*)NULL))
{
try
{
ProbeAndWriteBuffer(pPalEntries, ppalBuffer, lRetEntries * sizeof(PALETTEENTRY));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(89);
// SetLastError(GetExceptionCode());
lRet = 0;
}
}
}
}
if (ppalBuffer != (PALETTEENTRY*)NULL)
{
FreeTmpBuffer(ppalBuffer);
}
}
return(lRet);
}
/******************************Public*Routine******************************\
* NtGdiGetSpoolMessage()
*
* History:
* 21-Feb-1995 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
ULONG NtGdiGetSpoolMessage(
PSPOOLESC psesc,
ULONG cjMsg,
PULONG pulOut,
ULONG cjOut
)
{
ULONG ulRet = 0;
HANDLE hSecure = 0;
// psesc contains two pieces. The header which includes data going
// in and out and the variable length data which is only output. We
// divide the message into two pieces here since we only need to validate
// the header up front. We just put a try/except around the output buffer
// when we copy it in later.
if (psesc && (cjMsg >= offsetof(SPOOLESC,ajData)))
{
try
{
ProbeForWrite(psesc,cjMsg,PROBE_ALIGNMENT(SPOOLESC));
hSecure = MmSecureVirtualMemory (psesc, cjMsg, PAGE_READWRITE);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(90);
}
if (hSecure)
{
ulRet = GreGetSpoolMessage(
psesc,
psesc->ajData,
cjMsg - offsetof(SPOOLESC,ajData),
pulOut,
cjOut );
MmUnsecureVirtualMemory (hSecure);
}
}
return(ulRet);
}
/******************************Public*Routine******************************\
* NtGdiUnloadPrinterDriver()
*
* This function is called by the spooler when the printer driver has to be
* unloaded for upgrade purposes. The driver will be marked to be unloaded when
* the DC count goes to zero.
*
* History:
* 11/18/97 Ramanathan Venkatapathy
* Wrote it.
\**************************************************************************/
BOOL APIENTRY NtGdiUnloadPrinterDriver(
LPWSTR pDriverName,
ULONG cbDriverName)
{
BOOL bReturn = FALSE;
WCHAR pDriverFile[MAX_PATH + 1];
RtlZeroMemory(pDriverFile, (MAX_PATH + 1) * sizeof(WCHAR));
// Check for invalid driver name.
if (cbDriverName > (MAX_PATH * sizeof(WCHAR)))
{
return bReturn;
}
__try
{
ProbeAndReadAlignedBuffer(pDriverFile, pDriverName, cbDriverName, sizeof(WCHAR) );
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
WARNING("NtGdiUnloadPrinterDriver: bad driver file name.\n");
return bReturn;
}
bReturn = ldevArtificialDecrement(pDriverFile);
return bReturn;
}
/******************************Public*Routine******************************\
*
* NtGdiDescribePixelFormat
*
* Returns information about pixel formats for driver-managed surfaces
*
* History:
* Thu Nov 02 18:16:26 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
int NtGdiDescribePixelFormat(HDC hdc, int ipfd, UINT cjpfd,
PPIXELFORMATDESCRIPTOR ppfd)
{
PIXELFORMATDESCRIPTOR pfdLocal;
int iRet;
if (cjpfd > 0 && ppfd == NULL)
{
return 0;
}
// Make sure we cannot overrun our local structure.
cjpfd = min(cjpfd, sizeof(pfdLocal));
// Retrieve information into a local copy because the
// devlock is held when the driver fills it in. If there
// was an access violation then the lock wouldn't be cleaned
// up
iRet = GreDescribePixelFormat(hdc, ipfd, cjpfd, &pfdLocal);
// Copy data back if necessary
if (iRet != 0 && cjpfd > 0)
{
try
{
ProbeAndWriteAlignedBuffer(ppfd, &pfdLocal, cjpfd, sizeof(ULONG));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(92);
iRet = 0;
}
}
return iRet;
}
/******************************Public*Routine******************************\
* NtGdiFlush: Stub onle
*
* Arguments:
*
* None
*
* Return Value:
*
* None
*
* History:
*
* 1-Nov-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
VOID
NtGdiFlush()
{
GreFlush();
}
/******************************Public*Routine*****************************\
* NtGdiGetCharWidthInfo
*
* Get the lMaxNegA lMaxNegC and lMinWidthD
*
* History:
* 14-Feb-1996 -by- Xudong Wu [tessiew]
* Wrote it.
\*************************************************************************/
BOOL
APIENTRY
NtGdiGetCharWidthInfo(
HDC hdc,
PCHWIDTHINFO pChWidthInfo
)
{
BOOL bRet = FALSE;
CHWIDTHINFO tempChWidthInfo;
bRet = GreGetCharWidthInfo( hdc, &tempChWidthInfo );
if (bRet)
{
try
{
ProbeAndWriteBuffer( pChWidthInfo, &tempChWidthInfo, sizeof(CHWIDTHINFO) );
}
except( EXCEPTION_EXECUTE_HANDLER )
{
WARNINGX(93);
bRet = FALSE;
}
}
return ( bRet );
}
ULONG
APIENTRY
NtGdiMakeFontDir(
FLONG flEmbed, // mark file as "hidden"
PBYTE pjFontDir, // pointer to structure to fill
unsigned cjFontDir, // >= CJ_FONTDIR
PWSZ pwszPathname, // path of font file to use
unsigned cjPathname // <= sizeof(WCHAR) * (MAX_PATH+1)
)
{
ULONG ulRet;
WCHAR awcPathname[MAX_PATH+1]; // safe buffer for path name
BYTE ajFontDir[CJ_FONTDIR]; // safe buffer for return data
ulRet = 0;
if ( (cjPathname <= (sizeof(WCHAR) * (MAX_PATH+1))) &&
(cjFontDir >= CJ_FONTDIR) )
{
ulRet = 1;
__try
{
ProbeAndReadAlignedBuffer( awcPathname, pwszPathname, cjPathname, sizeof(*pwszPathname));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
WARNING("NtGdiMakeFondDir: bad pwszPathname\n");
ulRet = 0;
}
if ( ulRet )
{
awcPathname[MAX_PATH] = 0;
ulRet = GreMakeFontDir( flEmbed, ajFontDir, awcPathname );
if ( ulRet )
{
__try
{
ProbeAndWriteBuffer( pjFontDir, ajFontDir, CJ_FONTDIR );
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
WARNING("NtGdiMakeFondDir: bad pjFontDir\n");
ulRet = 0;
}
}
}
}
return( ulRet );
}
DWORD APIENTRY NtGdiGetGlyphIndicesWInternal(
HDC hdc,
LPWSTR pwc,
int cwc,
LPWORD pgi,
DWORD iMode,
BOOL bSubset
)
{
WORD awBuffer[2*LOCAL_CWC_MAX];
LPWSTR pwcTmp;
LPWORD pgiTmp = NULL;
DWORD dwRet = GDI_ERROR;
if (cwc < 0)
return dwRet;
// test for important special case
if ((cwc == 0) && (pwc == NULL) && (pgi == NULL) && (iMode == 0))
return GreGetGlyphIndicesW(hdc, NULL, 0, NULL, 0, bSubset);
if (cwc <= LOCAL_CWC_MAX)
{
pgiTmp = awBuffer;
}
else
{
if (!BALLOC_OVERFLOW2(cwc,WORD,WCHAR))
{
pgiTmp = (LPWORD)AllocFreeTmpBuffer(cwc * (sizeof(WORD)+sizeof(WCHAR)));
}
}
if (pgiTmp)
{
// make a temp buffer for the string in the same buffer, after the indices
pwcTmp = &pgiTmp[cwc];
try
{
ProbeAndReadBuffer(pwcTmp, pwc, cwc * sizeof(WCHAR));
dwRet = cwc; // indicate that we did not hit the exception
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(98);
dwRet = GDI_ERROR;
}
if (dwRet != GDI_ERROR)
dwRet = GreGetGlyphIndicesW(hdc, pwcTmp, cwc, pgiTmp, iMode, bSubset);
if (dwRet != GDI_ERROR)
{
try
{
ProbeAndWriteBuffer(pgi, pgiTmp, cwc * sizeof(WORD));
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(99);
dwRet = GDI_ERROR;
}
}
if (pgiTmp != awBuffer)
FreeTmpBuffer(pgiTmp);
}
return dwRet;
}
DWORD APIENTRY NtGdiGetGlyphIndicesW(
HDC hdc,
LPWSTR pwc,
int cwc,
LPWORD pgi,
DWORD iMode
)
{
return NtGdiGetGlyphIndicesWInternal(hdc, pwc, cwc, pgi, iMode, FALSE);
}
/******************************Public*Routine******************************\
*
* NtGdi stub for GetFontUnicodeRanges
*
* History:
* 09-Sep-1996 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
DWORD NtGdiGetFontUnicodeRanges(HDC hdc, LPGLYPHSET pgs)
{
DWORD dwRet, dwRet1;
LPGLYPHSET pgsTmp = NULL;
dwRet = GreGetFontUnicodeRanges(hdc, NULL);
if (dwRet && pgs)
{
if (pgsTmp = (LPGLYPHSET)AllocFreeTmpBuffer(dwRet))
{
dwRet1 = GreGetFontUnicodeRanges(hdc, pgsTmp);
if (dwRet1 && (dwRet == dwRet1)) // consistency check
{
try
{
ProbeAndWriteBuffer(pgs, pgsTmp, dwRet);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(102);
dwRet = 0;
}
}
else
{
WARNINGX(101);
dwRet = 0;
}
FreeTmpBuffer(pgsTmp);
}
else
{
WARNINGX(100);
dwRet = 0;
}
}
return dwRet;
}
#ifdef LANGPACK
BOOL
APIENTRY
NtGdiGetRealizationInfo(
HDC hdc,
PREALIZATION_INFO pri,
KHFONT hf
)
{
REALIZATION_INFO riTmp;
BOOL bRet = TRUE;
int ii;
bRet = GreGetRealizationInfo(hdc, &riTmp);
try
{
if (bRet)
{
ProbeAndWriteStructure(pri,riTmp,REALIZATION_INFO);
}
if (bRet)
{
if (hf)
{
// Find CFONT Location
for (ii = 0; ii < MAX_PUBLIC_CFONT; ++ii)
if (gpGdiSharedMemory->acfPublic[ii].hf == (HFONT)hf)
break;
if (ii < MAX_PUBLIC_CFONT){
CFONT* pcf = &gpGdiSharedMemory->acfPublic[ii];
pcf->ri = riTmp;
pcf->fl |= CFONT_CACHED_RI;
pcf->timeStamp = gpGdiSharedMemory->timeStamp;
}
}
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(104);
// SetLastError(GetExceptionCode());
bRet = FALSE;
}
return (bRet);
}
#endif
/******************************Public*Routine******************************\
* NtGdiDrawStream
*
* Arguments:
*
* hdc - handle to primary destination device context
* cjIn - size, in bytes, of input draw stream
* pjIn - address of input draw stream
*
* Return Value:
*
* TRUE : success
* FALSE : faiure
*
* History:
*
* 3-19-2001 bhouse Created it
*
\**************************************************************************/
#define DS_STACKBUFLENGTH 256
BOOL
APIENTRY
NtGdiDrawStream(
HDC hdcDst,
ULONG cjIn,
PVOID pvIn
)
{
BYTE pbScratchBuf[DS_STACKBUFLENGTH];
BOOL bRet = FALSE;
PVOID pvScratch = NULL;
if(cjIn > sizeof(pbScratchBuf))
{
if (BALLOC_OVERFLOW1(cjIn,BYTE))
{
WARNING("NtGdiDrawStream: input stream is too large\n");
goto exit;
}
pvScratch = AllocFreeTmpBuffer(cjIn);
if (pvScratch == NULL)
{
WARNING("NtGdiDrawStream: unable to allocate temp buffer\n");
goto exit;
}
}
else
{
pvScratch = (PVOID) pbScratchBuf;
}
// copy the stream from user mode
// NOTE: we can get rid of the copy if we try/except in all appropriate
// places during the handling of the stream.
try
{
ProbeAndReadBuffer(pvScratch, pvIn,cjIn);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
WARNING("NtGdiDrawStream: exception occured reading stream\n");
goto exit;
}
bRet = GreDrawStream(hdcDst, cjIn, pvScratch);
exit:
if(pvScratch != NULL && pvScratch != pbScratchBuf)
{
FreeTmpBuffer(pvScratch);
}
return bRet;
}