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
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;
|
|
|
|
}
|
|
|
|
|