/******************************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 Microsoft Corporation * \**************************************************************************/ #include "engine.h" #include "winfont.h" #include "server.h" #include "dciddi.h" #include "limits.h" #ifdef DBGEXCEPT int bStopExcept = FALSE; int bWarnExcept = FALSE; #endif #define DWORD_TO_FLOAT(dw) (*(PFLOAT)(PDWORD)&(dw)) /******************************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; } } 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 (gcpwLocal.lpOrder) { dpOrder = cjW; cjW += cjDword; } if (gcpwLocal.lpDx) { dpDx = cjW; cjW += cjDword; } if (gcpwLocal.lpCaretPos) { dpCaretPos = cjW; cjW += cjDword; } if (gcpwLocal.lpClass) { dpClass = cjW; cjW += ALIGN4(sizeof(char) * nCount); } if (gcpwLocal.lpGlyphs) { dpGlyphs = cjW; cjW += cjWord; } } // alloc mem for gcpw and the string if (pv = PALLOCNOZ(cjW + cjWord,'pmtG')) { 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 { ProbeForRead(pwsz,cjWord,sizeof(BYTE)); RtlCopyMemory(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 ProbeForRead(gcpwLocal.lpDx, cjDword, sizeof(BYTE)); RtlCopyMemory(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) { ProbeForWrite(gcpwLocal.lpOutString, cjWord, sizeof(BYTE)); RtlCopyMemory(gcpwLocal.lpOutString, pgcpwTmp->lpOutString, cjWord); } if (gcpwLocal.lpOrder) { ProbeForWrite(gcpwLocal.lpOrder, cjDword, sizeof(BYTE)); RtlCopyMemory(gcpwLocal.lpOrder, pgcpwTmp->lpOrder, cjDword); } if (gcpwLocal.lpDx) { ProbeForWrite(gcpwLocal.lpDx, cjDword, sizeof(BYTE)); RtlCopyMemory(gcpwLocal.lpDx, pgcpwTmp->lpDx, cjDword); } if (gcpwLocal.lpCaretPos) { ProbeForWrite(gcpwLocal.lpCaretPos, cjDword, sizeof(BYTE)); RtlCopyMemory(gcpwLocal.lpCaretPos, pgcpwTmp->lpCaretPos, cjDword); } if (gcpwLocal.lpClass) { ProbeForWrite(gcpwLocal.lpClass, nCount, sizeof(BYTE)); RtlCopyMemory(gcpwLocal.lpClass, pgcpwTmp->lpClass, nCount); } if (gcpwLocal.lpGlyphs) { ProbeForWrite(gcpwLocal.lpGlyphs, cjWord, sizeof(BYTE)); RtlCopyMemory(gcpwLocal.lpGlyphs, pgcpwTmp->lpGlyphs, cjWord); } } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(3); // SetLastError(GetExceptionCode()); bOk = FALSE; } } } VFREEMEM(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("cjBitmapSize 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); } /******************************Public*Routine******************************\ * INT CaptureDEVMODEW (LPDEVMODEW pdm, LPDEVMODEW *ppdmKm) * Get the size of a DEVMODE * * 01-Jun-1995 -by- Andre Vachon [andreva] * Fixed bugs - out of line try except. * 26-Feb-1995 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/ INT CaptureDEVMODEW ( LPDEVMODEW pdm, LPDEVMODEW *ppdmKm) { INT iRet = 0; ULONG ulSize; INT iExtra; *ppdmKm = NULL; // BUGBUG this routine is incomplete - it does not handle DEVMODEs // that are smaller than sizeof DEVMODEW ulSize = sizeof(DEVMODEW); ProbeForRead (pdm, ulSize, sizeof(BYTE)); iExtra = pdm->dmDriverExtra; if (iExtra) { ProbeForRead (pdm+1, iExtra, sizeof(BYTE)); ulSize += iExtra; } *ppdmKm = PALLOCNOZ(ulSize,'pmtG'); if (*ppdmKm) { RtlCopyMemory(*ppdmKm, pdm, ulSize); // in case dmDriverExtra gets changed (*ppdmKm)->dmDriverExtra = iExtra; } iRet = 1; return iRet; } /******************************Public*Routine******************************\ * cjBitmapSize * * 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] * Wrote it. \**************************************************************************/ ULONG cjBitmapSize(CONST BITMAPINFO *pbmi, ULONG iUsage) { ULONG cjHeader; ULONG cjRGB; ULONG cColorsMax; ULONG cColors; UINT uiBitCount; UINT uiPalUsed; UINT uiCompression; // check for error if (pbmi == (LPBITMAPINFO) NULL) { WARNING("cjBitmapSize failed - NULL pbmi\n"); return(0); } // Check for PM-style DIB if (pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) { cjHeader = sizeof(BITMAPCOREHEADER); cjRGB = sizeof(RGBTRIPLE); uiBitCount = ((LPBITMAPCOREINFO)pbmi)->bmciHeader.bcBitCount; uiPalUsed = 0; uiCompression = (UINT) BI_RGB; } else if (pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) { cjHeader = pbmi->bmiHeader.biSize; 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("cjBitmapSize %lu\n", uiBitCount); #endif WARNING("cjBitmapSize failed for BI_BITFIELDS\n"); return(0); } uiPalUsed = cColorsMax = 3; } 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("cjBitmapSize failed invalid bitcount in bmi BI_RGB\n"); return(0); } } } else if (uiCompression == BI_RLE4) { if (uiBitCount != 4) { // WARNING("cjBitmapSize invalid bitcount BI_RLE4\n"); return(0); } cColorsMax = 16; } else if (uiCompression == BI_RLE8) { if (uiBitCount != 8) { // WARNING("cjBitmapSize invalid bitcount BI_RLE8\n"); return(0); } cColorsMax = 256; } else { WARNING("cjBitmapSize 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; return(((cjHeader + (cjRGB * cColors)) + 3) & ~3); } /******************************Public*Routine******************************\ * cjBitmapBitsSize() * * copied from gdi\client * * History: * 20-Feb-1995 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/ ULONG cjBitmapBitsSize(CONST BITMAPINFO *pbmi) { // Check for PM-style DIB if (pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) { LPBITMAPCOREINFO pbmci; pbmci = (LPBITMAPCOREINFO)pbmi; return(CJSCAN(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)) { return(CJSCAN(pbmi->bmiHeader.biWidth,pbmi->bmiHeader.biPlanes, pbmi->bmiHeader.biBitCount) * ABS(pbmi->bmiHeader.biHeight)); } else { return(pbmi->bmiHeader.biSizeImage); } } /******************************Public*Routine******************************\ * LPBITMAPINFO CaptureBitmapInfo (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. \**************************************************************************/ LPBITMAPINFO pbmiCaptureBitmapInfo (LPBITMAPINFO pbmi, DWORD dwUsage, INT *pcjHeader) { LPBITMAPINFO pbmiTmp; ULONG cjHeader; cjHeader = *pcjHeader; if ((cjHeader == 0) || (pbmi == (LPBITMAPINFO) NULL)) { WARNING("you don't want to Capture a 0 size BITMAPINFO\n"); return NULL; } else { ProbeForRead (pbmi, cjHeader, sizeof(BYTE)); ASSERTGDI (pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER), "bad size\n"); pbmiTmp = PALLOCNOZ(cjHeader,'pmtG'); if (pbmiTmp) { RtlCopyMemory(pbmiTmp,pbmi,cjHeader); // // it'd better still match now that it's safe // if (cjHeader != cjBitmapSize (pbmiTmp, dwUsage)) { WARNING ("CapturebitmapInfo - header size has changed\n"); VFREEMEM (pbmiTmp); pbmiTmp = NULL; } } } return (pbmiTmp); } /******************************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 ) { int iRet = 1; HANDLE hSecure = 0; ULONG cjHeader = 0; LPBITMAPINFO pbmiTmp = NULL; iUsage &= (DIB_PAL_INDICES | DIB_PAL_COLORS | DIB_RGB_COLORS); try { cjHeader = cjBitmapSize(pbmi,iUsage); // // the header size should not be changed // if (cjHeader == cjMaxInfo) { pbmiTmp = pbmiCaptureBitmapInfo(pbmi,iUsage,&cjHeader); if (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; } } 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 ); } 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); ULONG APIENTRY NtGdiPolyPolyDraw( HDC hdc, PPOINT ppt, PULONG pcpt, ULONG ccpt, int iFunc ) { ULONG cpt; PULONG pulCounts; ULONG 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) { ULONG cjAlloc = ccpt * sizeof(ULONG); // // make sure allocation is within reasonable limits // if ((cjAlloc < MAXIMUM_POOL_ALLOC) && (ccpt < 0x8000000)) { pulCounts = PALLOCNOZ(cjAlloc,'pmtG'); } else { EngSetLastError(ERROR_INVALID_PARAMETER); pulCounts = NULL; } } else { pulCounts = &ulCount; } if (pulCounts) { pptTmp = apt; try { UINT i; ProbeForRead(pcpt,ccpt * sizeof(ULONG), sizeof(BYTE)); RtlCopyMemory(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 (cpt >= 0x8000000) { ulRet = 0; } else { ProbeForRead(ppt,cpt * sizeof(POINT), sizeof(BYTE)); if (cpt > 10) { pptTmp = PALLOCNOZ(cpt * sizeof(POINT),'pmtG'); } if (pptTmp) { RtlCopyMemory(pptTmp,ppt,cpt*sizeof(POINT)); } else { ulRet = 0; } } } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(5); // SetLastError(GetExceptionCode()); ulRet = 0; } if (ulRet != 0) { switch(iFunc) { case I_POLYPOLYGON: ulRet = (ULONG) GrePolyPolygonInternal ( hdc, pptTmp, (LPINT)pulCounts, ccpt, cpt ); break; case I_POLYPOLYLINE: ulRet = (ULONG) GrePolyPolylineInternal ( hdc, pptTmp, pulCounts, ccpt, cpt ); break; case I_POLYBEZIER: ulRet = (ULONG) GrePolyBezier ( hdc, pptTmp, ulCount ); break; case I_POLYLINETO: ulRet = (ULONG) GrePolylineTo ( hdc, pptTmp, ulCount ); break; case I_POLYBEZIERTO: ulRet = (ULONG) GrePolyBezierTo ( hdc, pptTmp, ulCount ); break; case I_POLYPOLYRGN: ulRet = (ULONG) GreCreatePolyPolygonRgnInternal ( pptTmp, (LPINT)pulCounts, ccpt, (INT)hdc, // the mode cpt ); break; default: ulRet = 0; } } if (pulCounts != &ulCount) VFREEMEM(pulCounts); if (pptTmp && (pptTmp != apt)) VFREEMEM(pptTmp); } 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 ) { LPBITMAPINFO pbmiTmp = NULL; INT iRet = 1; ULONG cjHeader = cjMaxInfo; ULONG cjBits = cjMaxBits; HANDLE hSecure = 0; if (pjInit && pbmi && cjHeader) { try { pbmiTmp = pbmiCaptureBitmapInfo (pbmi, dwUsage, &cjHeader); if (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 ); 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 = PALLOCNOZ(cjotm,'pmtG'); if (pkmOutlineTextMetricW == (OUTLINETEXTMETRICW *)NULL) { dwRet = (DWORD)-1; } } if (dwRet >= 0) { dwRet = GreGetOutlineTextMetricsInternalW( hdc, cjotm, pkmOutlineTextMetricW, &kmTmDiff); if (dwRet != (DWORD)-1) { try { // // copy TMDIFF structure out // ProbeForWrite(ptmd,sizeof(TMDIFF),sizeof(DWORD)); *ptmd = kmTmDiff; // // copy OTM out if needed // if (cjotm != 0) { ProbeForWrite(potmw,cjotm, sizeof(DWORD)); RtlCopyMemory(potmw,pkmOutlineTextMetricW,cjotm); } } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(7); // SetLastError(GetExceptionCode()); dwRet = (DWORD)-1; } } } if (pkmOutlineTextMetricW != (OUTLINETEXTMETRICW *)NULL) { VFREEMEM(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; dwRet = GreGetBoundsRect(hdc,&rc,f); 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; } try { // bugbug - this would be a prime candidate for a try/except // instead of MmSecureVirtualMemory ProbeForWrite(pjOut,cjMax,sizeof(BYTE)); hSecure = MmSecureVirtualMemory (pjOut, cjMax, PAGE_READWRITE); } 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 //!!! Dunno why this is here -- it's always 0 ) { LPBITMAPINFO pbmiTmp = NULL; ULONG cjHeader = cjMaxInitInfo; ULONG cjBits = cjMaxBits; INT iRet = 1; HANDLE hSecure = 0; if (pbmi && cjHeader) { try { pbmiTmp = pbmiCaptureBitmapInfo (pbmi, iUsage, &cjHeader); if (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 = (INT)GreCreateDIBitmapComp(hdc,cx, cy,fInit,pjInit,pbmiTmp,iUsage, cjHeader,cjBits,0); } else { iRet = (INT)GreCreateDIBitmapReal( hdc, fInit, pjInit, pbmiTmp, iUsage, cjHeader, cjBits, (HANDLE)0, 0, (HANDLE)0, 0); } } //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, OUT PVOID *ppvBits ) { HBITMAP hRet = NULL; BOOL bStatus = FALSE; if (pbmi != NULL) { LPBITMAPINFO pbmiTmp = NULL; PVOID pvBase = NULL; try { pbmiTmp = pbmiCaptureBitmapInfo (pbmi, iUsage, &cjHeader); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(11); // SetLastError(GetExceptionCode()); pbmiTmp = NULL; } if (pbmiTmp) { NTSTATUS Status; ULONG cjBits = cjBitmapBitsSize(pbmiTmp); ULONG cjView = 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; } else { LARGE_INTEGER SectionOffset; 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 = ZwMapViewOfSection( hDIBSection, NtCurrentProcess(), (PVOID *) &pvBase, 0L, cjView, &SectionOffset, &cjView, ViewShare, 0L, PAGE_READWRITE); } // 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_READONLY); if (hSecure) { // // Make the GDI Bitmap // hRet = GreCreateDIBitmapReal( hdc, CBM_CREATEDIB, pDIB, pbmiTmp, iUsage, cjHeader, cjBits, hDIBSection, dwOffset, hSecure, (fl & CDBI_NOPALETTE) | CDBI_DIBSECTION); if (hRet != NULL) { try { ProbeAndWriteStructure(ppvBits,pDIB,PVOID); bStatus = TRUE; } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(12); // SetLastError(GetExceptionCode()); } } } // 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, LONG lHatch, ULONG cstyle, PULONG pulStyle, ULONG cjDIB, BOOL bOldStylePen, HBRUSH hbrush ) { PULONG pulStyleTmp = NULL; PULONG pulDIB = NULL; HPEN hpenRet = (HPEN)1; if (pulStyle) { pulStyleTmp = PALLOCNOZ(cstyle * sizeof(ULONG),'pmtG'); if (!pulStyleTmp) hpenRet = (HPEN)0; } if (iBrushStyle == BS_DIBPATTERNPT) { pulDIB = PALLOCNOZ(cjDIB,'pmtG'); if (!pulDIB) hpenRet = (HPEN)0; } if (hpenRet) { try { if (pulStyle) { ProbeForRead(pulStyle,cstyle * sizeof(ULONG),sizeof(ULONG)); RtlCopyMemory(pulStyleTmp,pulStyle,cstyle * sizeof(ULONG)); } // if it is a DIBPATTERN type, the lHatch is a pointer to the BMI if (iBrushStyle == BS_DIBPATTERNPT) { ProbeForRead((PVOID)lHatch,cjDIB,sizeof(ULONG)); RtlCopyMemory(pulDIB,(PVOID)lHatch,cjDIB); lHatch = (LONG)pulDIB; } } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(13); // SetLastError(GetExceptionCode()); hpenRet = (HPEN)0; } // if all has succeeded if (hpenRet) { hpenRet = GreExtCreatePen( flPenStyle,ulWidth,iBrushStyle, ulColor,lHatch,cstyle, pulStyleTmp,cjDIB,bOldStylePen,hbrush ); } } else { // SetLastError(GetExceptionCode()); } // cleanup if (pulDIB) VFREEMEM(pulDIB); if (pulStyleTmp) VFREEMEM(pulStyleTmp); return(hpenRet); } /******************************Public*Routine******************************\ * NtGdiCreateServerMetaFile() * * History: * 01-Nov-1994 -by- Eric Kutter [erick] * Wrote it. * 22-Mar-1995 -by- Lingyun Wang [lingyunw] * Expanded it. \**************************************************************************/ HANDLE APIENTRY NtGdiCreateServerMetaFile( DWORD iType, ULONG cjData, LPBYTE pjData, DWORD mm, DWORD xExt, DWORD yExt ) { HANDLE hRet = (HANDLE) 1; HANDLE hSecure = 0; if (cjData) { try { //lock up memory ProbeForRead(pjData, cjData, sizeof(DWORD)); hSecure = MmSecureVirtualMemory(pjData, cjData, PAGE_READONLY); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(14); hRet = 0; } } if (hRet) { hRet = GreCreateServerMetaFile(iType,cjData,pjData,mm,xExt,yExt); } //unlock the memory if (hSecure) { MmUnsecureVirtualMemory(hSecure); } return (hRet); } /******************************Public*Routine******************************\ * NtGdiHfontCreate() * * History: * 01-Nov-1994 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/ HFONT APIENTRY NtGdiHfontCreate( LPEXTLOGFONTW pelfw, LFTYPE lft, FLONG fl, PVOID pvCliData ) { INT iRet = 1; // check for bad parameter if (pelfw == (LPEXTLOGFONTW) NULL) { iRet = 0; } else { EXTLOGFONTW elfwTmp; try { elfwTmp = ProbeAndReadStructure(pelfw, EXTLOGFONTW); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(15); // SetLastError(GetExceptionCode()); iRet = 0; } if (iRet) { iRet = (INT)hfontCreate(&elfwTmp, lft, fl, pvCliData); } } 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 != 0) { // do the real work prgnTmp = PALLOCNOZ(cj,'pmtG'); if (prgnTmp) { try { if (px) { xf = ProbeAndReadStructure(px,XFORM); px = &xf; } ProbeForRead(prgn, cj, sizeof(DWORD)); RtlCopyMemory(prgnTmp, prgn, cj); hrgn = (HRGN)1; } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(16); // SetLastError(GetExceptionCode()); } if (hrgn) hrgn = GreExtCreateRegion(px,cj,prgnTmp); VFREEMEM(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 { 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; PBYTE pjBuffer; // // add up size off all arrary elements // try { ProbeForRead(pptw,cStr * sizeof(POLYTEXTW),sizeof(ULONG)); for (ulIndex=0;ulIndex= 0) && (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 { pdxCapt = (PULONG) PALLOCNOZ(cwc * (sizeof(ULONG) + sizeof(WCHAR)), 'pacG'); pwszCapt = (PWSZ) &pdxCapt[cwc]; } if (pdxCapt) { // Capture the string into the buffer. ProbeForRead(lpwsz, cwc*sizeof(WCHAR), sizeof(WCHAR)); RtlCopyMemory(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); } } // 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) { ProbeForWrite(pdxOut, cCh * sizeof(ULONG), sizeof(ULONG)); RtlCopyMemory(pdxOut, pdxCapt, cCh * sizeof(ULONG)); } } } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(25); // SetLastError(GetExceptionCode()); bRet = FALSE; } } if (!UseLocals && pdxCapt) { VFREEMEM(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, BOOL bInteger, PVOID pvBuf ) { BOOL bStatus = FALSE; PVOID pTemp_pvBuf; PWCHAR pTemp_pwc = (PWCHAR)NULL; BOOL bUse_pwc = FALSE; ULONG OutputBufferSize = cwch * (bInteger?sizeof(ABC) : sizeof(ABCFLOAT)); if (pvBuf == NULL) { return(bStatus); } // // allocate memory for buffers, pwch may be NULL // if (pwch != (PWCHAR)NULL) { bUse_pwc = TRUE; pTemp_pwc = (PWCHAR)PALLOCNOZ(cwch * sizeof(WCHAR),'pmtG'); } if ((!bUse_pwc) || (pTemp_pwc != (PWCHAR)NULL)) { pTemp_pvBuf = (PVOID)PALLOCNOZ(OutputBufferSize,'pmtG'); if (pTemp_pvBuf != NULL) { // // copy input data to kernel mode buffer, if needed // if (bUse_pwc) { try { ProbeForRead(pwch,cwch * sizeof(WCHAR), sizeof(WCHAR)); RtlCopyMemory(pTemp_pwc,pwch,cwch * sizeof(WCHAR)); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(26); // SetLastError(GetExceptionCode()); bStatus = FALSE; } } bStatus = GreGetCharABCWidthsW(hdc,wchFirst,cwch,pTemp_pwc,bInteger,pTemp_pvBuf); // // copy results from kernel mode buffer to user buffer // if (bStatus) { try { ProbeForWrite(pvBuf,OutputBufferSize, sizeof(ULONG)); RtlCopyMemory(pvBuf,pTemp_pvBuf,OutputBufferSize); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(27); // SetLastError(GetExceptionCode()); bStatus = FALSE; } } VFREEMEM(pTemp_pvBuf); } if (bUse_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 ) { FLOAT eStartAngle = DWORD_TO_FLOAT(dwStartAngle); FLOAT eSweepAngle = DWORD_TO_FLOAT(dwSweepAngle); return(GreAngleArc(hdc,x,y,dwRadius,eStartAngle,eSweepAngle)); } /******************************Public*Routine******************************\ * NtGdiSetMiterLimit() * * History: * 01-Nov-1994 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/ BOOL APIENTRY NtGdiSetMiterLimit( HDC hdc, DWORD dwNew, PFLOAT peOut ) { BOOL bRet; FLOAT e; FLOAT eNew = DWORD_TO_FLOAT(dwNew); bRet = GreSetMiterLimit(hdc,eNew,&e); if (bRet && peOut) { try { ProbeAndWriteStructure(peOut,e,FLOAT); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(28); // 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 ) { FLOAT exScale = DWORD_TO_FLOAT(dwxScale); FLOAT eyScale = DWORD_TO_FLOAT(dwyScale); return(GreSetFontXform(hdc,exScale,eyScale)); } /******************************Public*Routine******************************\ * NtGdiGetMiterLimit() * * History: * 01-Nov-1994 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/ BOOL APIENTRY NtGdiGetMiterLimit( HDC hdc, PFLOAT peOut ) { BOOL bRet; FLOAT e; bRet = GreGetMiterLimit(hdc,&e); if (bRet) { try { ProbeAndWriteStructure(peOut,e,FLOAT); } 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, UINT fl, PVOID pvBuf ) { BOOL bStatus = FALSE; PVOID pTemp_pvBuf; PWCHAR pTemp_pwc = (PWCHAR)NULL; BOOL bUse_pwc = FALSE; // // allocate memory for buffers, pwc may be NULL // if (pwc != (PWCHAR)NULL) { bUse_pwc = TRUE; pTemp_pwc = (PWCHAR)PALLOCNOZ(cwc * sizeof(WCHAR),'pmtG'); } if ((!bUse_pwc) || (pTemp_pwc != (PWCHAR)NULL)) { pTemp_pvBuf = (PVOID)PALLOCNOZ(cwc * sizeof(ULONG),'pmtG'); if (pTemp_pvBuf != NULL) { // // copy input data to kernel mode buffer, if needed // if (bUse_pwc) { try { ProbeForRead(pwc,cwc * sizeof(WCHAR), sizeof(WCHAR)); RtlCopyMemory(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 { ProbeForWrite(pvBuf,cwc * sizeof(ULONG), sizeof(ULONG)); RtlCopyMemory(pvBuf,pTemp_pvBuf,cwc * sizeof(ULONG)); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(31); // SetLastError(GetExceptionCode()); bStatus = FALSE; } } VFREEMEM(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; // // 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 { ProbeForRead(pjIn,cjIn,sizeof(UCHAR)); RtlCopyMemory(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]; LPSTR pkmInputData = (LPSTR)NULL; LPSTR pkmOutputData = (LPSTR)NULL; PWCHAR pkmDriver = (LPWSTR) NULL; BOOL bStatus = TRUE; BOOL bAllocIn = FALSE; BOOL bAllocOut = FALSE; BOOL bAllocDriver = FALSE; BOOL iRet = -1; // // BUGBUG change bAlloc(in/Out) to bLock(in/Out) // if(pDriver) { if(nDriver <= EXT_STACK_DATA_SIZE-1) { pkmDriver = StackDriver; } else { 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 { ProbeForRead(pDriver,nDriver*sizeof(WCHAR),sizeof(WCHAR)); RtlCopyMemory(pkmDriver,pDriver,nDriver*sizeof(WCHAR)); pkmDriver[nDriver] = 0; // NULL terminate the string } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(94); // SetLastError(GetExceptionCode()); bStatus = FALSE; } } else { bStatus = FALSE; } } if(cjIn != 0 && bStatus) { if (cjIn <= EXT_STACK_DATA_SIZE) { pkmInputData = (LPSTR)StackInputData; } else { // // BUGBUG: or lock user memory // pkmInputData = (LPSTR)PALLOCNOZ(cjIn,'pmtG'); bAllocIn = TRUE; } if (pkmInputData != (LPSTR)NULL) { // // copy data to input kmode buffer // try { ProbeForRead(pjIn,cjIn,sizeof(UCHAR)); RtlCopyMemory(pkmInputData,pjIn,cjIn); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(33); // SetLastError(GetExceptionCode()); bStatus = FALSE; } } else { bStatus = FALSE; } } if (bStatus) { if (cjOut != 0) { if (cjOut <= EXT_STACK_DATA_SIZE) { pkmOutputData = (LPSTR)StackOutputData; } else { // // BUGBUG: or lock user memory // pkmOutputData = (LPSTR)PALLOCNOZ(cjOut,'pmtG'); if (pkmOutputData != (LPSTR)NULL) { bAllocOut = TRUE; } else { bStatus = FALSE; } } } } if (bStatus) { iRet = (pkmDriver) ? GreNamedEscape(pkmDriver,iEsc,cjIn,pkmInputData,cjOut,pkmOutputData) : GreExtEscape(hdc,iEsc,cjIn,pkmInputData,cjOut,pkmOutputData); // // copy data from kmode buffer to user buffer (or not if we lock) // if (cjOut != 0) { try { ProbeForWrite(pjOut,cjOut,sizeof(UCHAR)); RtlCopyMemory(pjOut,pkmOutputData,cjOut); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(34); // SetLastError(GetExceptionCode()); iRet = -1; } } } // // BUGBUG Or unlock // if (bAllocIn && (pkmInputData != (LPSTR)NULL)) { VFREEMEM(pkmInputData); } if (bAllocOut && (pkmOutputData != (LPSTR)NULL)) { VFREEMEM(pkmOutputData); } if (bAllocDriver && (pkmDriver != NULL)) { 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 = PALLOCNOZ(cjBuf,'pmtG'); if (pvkmBuf != NULL) { ReturnBytes = ulGetFontData( hdc, dwTable, dwOffset, pvkmBuf, cjBuf); if (ReturnBytes != GDI_ERROR) { try { ProbeForRead(pvBuf,ReturnBytes,sizeof(BYTE)); RtlCopyMemory(pvBuf,pvkmBuf,ReturnBytes); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(35); // SetLastError(GetExceptionCode()); ReturnBytes = GDI_ERROR; } } VFREEMEM(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) ? PALLOCNOZ(cjBuf,'pmtG') : 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 ) { ProbeForWrite(pvBuf,cjBuf,sizeof(BYTE)); RtlCopyMemory(pvBuf,pvkmBuf,cjBuf); } ProbeAndWriteStructure(pgm,kmGlyphMetrics,GLYPHMETRICS); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(37); // SetLastError(GetExceptionCode()); dwRet = (DWORD)-1; } } } if( pvkmBuf ) { VFREEMEM(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 { ProbeForWrite(praststat, cjBytes, sizeof(DWORD)); RtlCopyMemory(praststat, &tempRasStatus, cjBytes); 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; BOOL bAlloc = FALSE; if (pkpDst != (KERNINGPAIR *)NULL) { pkmKerningPair = PALLOCNOZ(sizeof(KERNINGPAIR) * cPairs,'pmtG'); bAlloc = TRUE; } if (!bAlloc || (pkmKerningPair != (KERNINGPAIR *)NULL)) { cRet = GreGetKerningPairs(hdc,cPairs,pkmKerningPair); // // copy data out if needed // if (bAlloc) { if (cRet != 0) { try { ProbeForWrite(pkpDst,sizeof(KERNINGPAIR) * cRet,sizeof(BYTE)); RtlCopyMemory(pkpDst,pkmKerningPair,sizeof(KERNINGPAIR) * cRet); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(39); // SetLastError(GetExceptionCode()); cRet = 0; } } VFREEMEM(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); 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 ) { LPDEVMODEW pdmTmp = NULL; DWORD dwTmp; INT iRet = 1; INT cj; if (pdm) { try { iRet = CaptureDEVMODEW(pdm, &pdmTmp); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(41); // SetLastError(GetExceptionCode()); iRet = 0; } } if (iRet) { iRet = GreResetDCInternal(hdc,pdmTmp,&dwTmp); if (iRet) { try { ProbeAndWriteUlong(pbBanding,dwTmp); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(42); // SetLastError(GetExceptionCode()); iRet = 0; } } } if (pdmTmp) { VFREEMEM(pdmTmp); } 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 ((pca->caSize != sizeof(COLORADJUSTMENT)) || (pca->caIlluminantIndex > ILLUMINANT_MAX_INDEX) || ((pca->caRedGamma > RGB_GAMMA_MAX) || (pca->caRedGamma < RGB_GAMMA_MIN)) || ((pca->caGreenGamma > RGB_GAMMA_MAX) || (pca->caGreenGamma < RGB_GAMMA_MIN)) || ((pca->caBlueGamma > RGB_GAMMA_MAX) || (pca->caBlueGamma < RGB_GAMMA_MIN)) || ((pca->caReferenceBlack > REFERENCE_BLACK_MAX) || (pca->caReferenceBlack < REFERENCE_BLACK_MIN)) || ((pca->caReferenceWhite > REFERENCE_WHITE_MAX) || (pca->caReferenceWhite < REFERENCE_WHITE_MIN)) || ((pca->caContrast > COLOR_ADJ_MAX) || (pca->caContrast < COLOR_ADJ_MIN)) || ((pca->caBrightness > COLOR_ADJ_MAX) || (pca->caBrightness < COLOR_ADJ_MIN)) || ((pca->caColorfulness > COLOR_ADJ_MAX) || (pca->caColorfulness < COLOR_ADJ_MIN)) || ((pca->caRedGreenTint > COLOR_ADJ_MAX) || (pca->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)); } /******************************Public*Routine******************************\ * NtGdiSetTextCharacterExtra() * * History: * 01-Nov-1994 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/ int APIENTRY NtGdiSetTextCharacterExtra( HDC hdc, int iExtra ) { return(GreSetTextCharacterExtra(hdc,iExtra)); } //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******************************\ * * HFONT APIENTRY NtGdiSelectFont(HDC hdc, HFONT hf) * * 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(GreSelectBitmap(hdc,hbm)); } /******************************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 ) { HDC hdc = NULL; ULONG iRet = 0; PWSZ pwszDevice = NULL; LPDEVMODEW pdmTmp = NULL; INT cjDevice; // // 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); } else { try { ProbeForRead(pustrDevice,sizeof(UNICODE_STRING), sizeof(CHAR)); cjDevice = pustrDevice->Length + sizeof(WCHAR); if (cjDevice) { pwszDevice = PALLOCNOZ(cjDevice,'pmtG'); if (pwszDevice) { ProbeForRead(pustrDevice->Buffer,cjDevice, sizeof(CHAR)); RtlCopyMemory(pwszDevice,pustrDevice->Buffer,cjDevice); pwszDevice[(cjDevice/sizeof(WCHAR))-1] = L'\0'; } } // // pustrLogAddr should always be NULL for now. // iRet = 1; if (pdm) { iRet = CaptureDEVMODEW(pdm, &pdmTmp); } } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(48); // SetLastError(GetExceptionCode()); iRet = 0; } if (iRet) { hdc = hdcOpenDCW(pwszDevice, pdmTmp, iType, NULL, NULL); } if (pwszDevice) VFREEMEM(pwszDevice); if (pdmTmp) VFREEMEM(pdmTmp); } 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 ) { INT iRet = 1; HANDLE hSecure = 0; INT cj; if (pjInit == (VOID *) NULL) { cj = 0; } else { // only needs to word aligned and sized cj = CJSCANW(cx,cPlanes,cBPP)*cy; } 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 = (INT)GreCreateBitmap(cx,cy,cPlanes,cBPP,pjInit); } if (hSecure) { MmUnsecureVirtualMemory(hSecure); } return((HBITMAP)iRet); } /******************************Public*Routine******************************\ * NtGdiCreateHalftonePalette() * * History: * 01-Nov-1994 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/ HPALETTE APIENTRY NtGdiCreateHalftonePalette( HDC hdc ) { return(GreCreateHalftonePalette(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; EXTLOGFONTW elf; } obj; int iType = LO_TYPE(h); int ci = cj; if (cj > sizeof(obj)) { WARNING("cj too big to GetObject\n"); cj = sizeof(obj); } // // 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 { ProbeForWrite(pvOut,MIN(cj,iRet), sizeof(WORD)); RtlCopyMemory(pvOut,&obj,MIN(cj,iRet)); } 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) { bRet = TRUE; try { // // Order the rectangle // if (prcl->left > prcl->right) { rc.left = prcl->right; rc.right = prcl->left; } else { rc.left = prcl->left; rc.right = prcl->right; } if (prcl->top > prcl->bottom) { rc.top = prcl->bottom; rc.bottom = prcl->top; } else { rc.top = prcl->top; rc.bottom = prcl->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. if (pBits == (PVOID) NULL) { ULONG StructureSize = pbmi->bmiHeader.biSize; cScans = 0; iStartScan = 0; cjMaxBits = 0; // // probe the correct structure size // ProbeForRead(pbmi,StructureSize,sizeof(BYTE)); if ((StructureSize == sizeof(BITMAPCOREHEADER)) && (((PBITMAPCOREINFO) pbmi)->bmciHeader.bcBitCount == 0)) { cjHeader = sizeof(BITMAPCOREHEADER); } else if ((StructureSize >= sizeof(BITMAPINFOHEADER)) && (pbmi->bmiHeader.biBitCount == 0)) { cjHeader = sizeof(BITMAPINFOHEADER); } // it is just the header. Copy it } // 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 cjBitmapSize computes // the correct values. biClrUsed is not a input, just output. if (pbmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) { pbmi->bmiHeader.biClrUsed = 0; } // We need more than just the header. This may include bits. // Compute the the full size of the BITMAPINFO cjHeader = cjBitmapSize(pbmi,iUsage); if (cjHeader) { pbmiTmp = PALLOCMEM(cjHeader,'pmtG'); if (pbmiTmp) { RtlCopyMemory(pbmiTmp,pbmi,cjHeader); // Now that it is safe, make sure it hasn't changed if (cjBitmapSize(pbmiTmp,iUsage) != cjHeader) { cjHeader = 0; } else { //BUGBUG - The folowing validation may already be done in Gre... // We need to set biClrUsed to 0 so cjBitmapSize 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) { // 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 = cjBitmapBitsSize(pbmiTmp); 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)) { //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); //BUGBUG - 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 { pwszCapt = (PWSZ) PALLOCNOZ(cwc * sizeof(WCHAR), 'pacG'); } if (pwszCapt) { ProbeForRead(lpwsz, cwc*sizeof(WCHAR), sizeof(WCHAR)); RtlCopyMemory(pwszCapt, lpwsz, cwc*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) { VFREEMEM(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); try { ProbeForWrite(ptm,cj, sizeof(DWORD)); RtlCopyMemory(ptm,&tmw,cj); } 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 ) { int cRet = 0; BOOL bStatus = TRUE; PWCHAR pwsz_km = (PWCHAR)NULL; if ((cChar > 0) && (pszOut)) { pwsz_km = PALLOCNOZ(cChar * sizeof(WCHAR), 'pacG'); if (pwsz_km == (PWCHAR)NULL) { bStatus = FALSE; } } if (bStatus) { cRet = GreGetTextFaceW(hdc,cChar,pwsz_km); if ((cRet > 0) && (pszOut)) { ASSERTGDI(cRet <= cChar, "GreGetTextFaceW, cRet too big\n"); try { ProbeForWrite(pszOut,cRet * sizeof(WCHAR), sizeof(BYTE)); RtlCopyMemory(pszOut,pwsz_km,cRet * sizeof(WCHAR)); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(61); // SetLastError(GetExceptionCode()); cRet = 0; } } if (pwsz_km != (PWCHAR)NULL) { VFREEMEM(pwsz_km); } } return(cRet); } /**************************************************************************** * 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 ) ) { pufi = PALLOCNOZ(nBufferSize * sizeof(UNIVERSAL_FONT_ID),'difG'); if( pufi == NULL ) { iRet = -1 ; } } if( iRet != -1 ) { iRet = GreQueryFonts(pufi, nBufferSize, &TimeStamp ); if( iRet != -1 ) { try { ProbeAndWriteStructure(pTimeStamp,TimeStamp,LARGE_INTEGER); if( pufiFontList ) { ProbeForWrite(pufiFontList, sizeof(UNIVERSAL_FONT_ID)*nBufferSize, sizeof(DWORD) ); RtlCopyMemory(pufiFontList,pufi,sizeof(UNIVERSAL_FONT_ID)*nBufferSize); } } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(62); iRet = -1; } } } if( pufi != NULL ) { VFREEMEM( 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; if(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: // 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 } cj = cjDx + cjStrobj + cjString; if (cj <= TEXT_CAPTURE_BUFFER_SIZE) { pjAlloc = NULL; pjCapture = (BYTE*) &CaptureBuffer; } else { pjAlloc = PVALLOCTEMPBUFFER(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 += cjDx; } pjStrobj = pjCapture; pjCapture += cjStrobj; ASSERTGDI((((ULONG) pjCapture) & 3) == 0, "Buffers should be dword 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******************************\ * * 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; 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 ) { WCHAR awcPath[CWC_PATH]; WCHAR *pwszPath = NULL; // essential initialization int iRet = 0; ULONG iwc; TRACE_FONT(("Entering: NtGdiAddFontResourceW(\"%ws\",%-#x,%-#x,%-#x)\n",pwszFiles, cwc,cFiles,f)); try { if (cwc > 1) { if (cwc <= CWC_PATH) { pwszPath = awcPath; } else { pwszPath = PALLOCNOZ(cwc * sizeof(WCHAR), 'pmtG'); } if (pwszPath) { iRet = (int)bCheckAndCapThePath(pwszPath,pwszFiles,cwc,cFiles); } } } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(95); } if (iRet) iRet = GreAddFontResourceWInternal(pwszPath, cwc, cFiles,f,dwPidTid); if (pwszPath && (pwszPath != awcPath)) VFREEMEM(pwszPath); TRACE_FONT(("Leaving: NtGdiAddFontResourceW")); return iRet; } /******************************Public*Routine******************************\ * BOOL APIENTRY NtGdiRemoveFontResourceW * * History: * 28-Mar-1996 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/ BOOL APIENTRY NtGdiRemoveFontResourceW( WCHAR *pwszFiles, ULONG cwc, ULONG cFiles ) { WCHAR awcPath[CWC_PATH]; WCHAR *pwszPath = NULL; // essential initialization BOOL bRet = FALSE; TRACE_FONT(("Entering: NtGdiRemoveFontResourceW(\"%ws\",%-#x,%-#x)\n",pwszFiles, cwc,cFiles)); try { if (cwc > 1) { if (cwc <= CWC_PATH) { pwszPath = awcPath; } else { pwszPath = PALLOCNOZ(cwc * sizeof(WCHAR), 'pmtG'); } if (pwszPath) { bRet = bCheckAndCapThePath(pwszPath, pwszFiles, cwc, cFiles); } } } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(96); } if (bRet) bRet = GreRemoveFontResourceW(pwszPath, cwc, cFiles); if (pwszPath && (pwszPath != awcPath)) VFREEMEM(pwszPath); TRACE_FONT(("Leaving: NtGdiRemoveFontResourceW")); return bRet; } /******************************Public*Routine******************************\ * NtGdiEnumFontClose() * * History: * 01-Nov-1994 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/ BOOL APIENTRY NtGdiEnumFontClose( ULONG idEnum ) { return(bEnumFontClose(idEnum)); } /******************************Public*Routine******************************\ * NtGdiEnumFontChunk() * * History: * 01-Nov-1994 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/ BOOL APIENTRY NtGdiEnumFontChunk( HDC hdc, ULONG idEnum, ULONG cefdw, ULONG *pcefdw, PENUMFONTDATAW pefdw ) { HANDLE hSecure; BOOL bRet = TRUE; ULONG cefdwRet = 0; try { ProbeForWrite(pefdw, cefdw*sizeof(ENUMFONTDATAW), sizeof(DWORD)); hSecure = MmSecureVirtualMemory(pefdw, cefdw*sizeof(ENUMFONTDATAW), PAGE_READWRITE); if (!hSecure) { bRet = FALSE; } } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(66); // SetLastError(GetExceptionCode()); bRet = FALSE; } if (bRet) { bRet = bEnumFontChunk(hdc,idEnum,cefdw,&cefdwRet,pefdw); ProbeAndWriteUlong(pcefdw,cefdwRet); if (hSecure) { MmUnsecureVirtualMemory(hSecure); } } return (bRet); } /******************************Public*Routine******************************\ * NtGdiEnumFontOpen() * * History: * 08-Mar-1995 Mark Enstrom [marke] * Wrote it. \**************************************************************************/ ULONG APIENTRY NtGdiEnumFontOpen( HDC hdc, ULONG iEnumType, FLONG flWin31Compat, ULONG cwchMax, LPWSTR pwszFaceName, ULONG lfCharSet, ULONG *pulCount ) { ULONG cwchFaceName; PWSTR pwszKmFaceName; ULONG ulRet = 0; BOOL bRet = TRUE; ULONG ulCount = 0; if (pwszFaceName != (PWSZ)NULL) { pwszKmFaceName = (PWSZ)PALLOCNOZ(cwchMax * sizeof(WCHAR), 'pacG'); if (pwszKmFaceName != (PWSZ)NULL) { try { ProbeForRead(pwszFaceName,cwchMax * sizeof(WCHAR), sizeof(WCHAR)); RtlCopyMemory(pwszKmFaceName,pwszFaceName, cwchMax * sizeof(WCHAR)); } 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) { VFREEMEM(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; TRACE_FONT(("Entering: NtGdiGetFontResourceInfoInternalW(\"%ws\",%-#x,%-#x)\n",pwszFiles, cwc,cFiles)); try { if (cwc > 1) { if (cwc <= CWC_PATH) { pwszPath = awcPath; } else { pwszPath = PALLOCNOZ(cwc * sizeof(WCHAR), 'pmtG'); } if (pwszPath) { bRet = bCheckAndCapThePath(pwszPath, pwszFiles, cwc, cFiles); } } } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(97); } if (bRet) bRet = GetFontResourceInfoInternalW(pwszPath,cwc, cFiles, cjIn,pdwBytes,pvBuf,iType); if (pwszPath && (pwszPath != awcPath)) VFREEMEM(pwszPath); TRACE_FONT(("Leaving: NtGdiGetFontResourceInfoInternalW\n")); 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 ) { UNIVERSAL_FONT_ID ufiTmp; BOOL bRet = TRUE; bRet = GreGetUFI(hdc, &ufiTmp); try { if (bRet) { ProbeAndWriteStructure(pufi,ufiTmp,UNIVERSAL_FONT_ID); *pufi = ufiTmp; } } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(68); // SetLastError(GetExceptionCode()); bRet = FALSE; } return (bRet); } /******************************Public*Routine******************************\ * NtGdiGetUFIBits() * * History: * 02-Feb-1995 -by- Andre Vachon [andreva] * Wrote it. * 01-Mar-1995 -by- Lingyun Wang [lingyunw] * Expanded it. \**************************************************************************/ BOOL APIENTRY NtGdiGetUFIBits( PUNIVERSAL_FONT_ID pufi, ULONG cjMaxBytes, PVOID pjBits, PULONG pulFileSize ) { UNIVERSAL_FONT_ID ufiTmp; PVOID pjBitsTmp; ULONG ulFileSizeTmp; BOOL bRet = TRUE; // Get the input data try { ufiTmp = ProbeAndReadStructure(pufi,UNIVERSAL_FONT_ID); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(69); // SetLastError(GetExceptionCode()); bRet = FALSE; } if (bRet) { //alloc temp memory pjBitsTmp = (cjMaxBytes) ? PALLOCNOZ(cjMaxBytes,'pmtG') : NULL; if( pjBitsTmp || ( cjMaxBytes == 0 ) ) { bRet = GreGetUFIBits(&ufiTmp, cjMaxBytes, pjBitsTmp, &ulFileSizeTmp); //if didn't hit error above, retrieve filesize and pjBits back if (bRet) { try { ProbeAndWriteUlong(pulFileSize,ulFileSizeTmp); ProbeForWrite(pjBits,cjMaxBytes, sizeof(DWORD)); RtlCopyMemory(pjBits, pjBitsTmp, cjMaxBytes); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(70); // SetLastError(GetExceptionCode()); bRet = FALSE; } } if( pjBitsTmp ) { VFREEMEM (pjBitsTmp); } } else { //fail to alloc temp memory bRet = FALSE; } } return (bRet); } /******************************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 (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,&xf); 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 = TRUE; XFORM xfSrc1; XFORM xfSrc2; XFORM xfDst; try { xfSrc1 = ProbeAndReadStructure(pxfSrc1,XFORM); xfSrc2 = ProbeAndReadStructure(pxfSrc2,XFORM); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(75); // SetLastError(GetExceptionCode()); bRet = FALSE; } if (bRet) { bRet = GreCombineTransform(&xfDst,&xfSrc1,&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; // // we will just use the the stack if there are less than 10 points // otherwise allocate mem from heap // if (c > 10) { pptTmp = PALLOCNOZ(c * sizeof(POINT),'pmtG'); } // // 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; } } if (bRet) { bRet = GreTransformPoints(hdc,pptTmp,pptTmp,c,iMode); } // // copy pptTmp out to pptOut // if (bRet) { try { ProbeForWrite(pptOut,c * sizeof(POINT), sizeof(BYTE)); RtlCopyMemory(pptOut,pptTmp,c*sizeof(POINT)); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(77); // SetLastError(GetExceptionCode()); bRet = FALSE; } } if (pptTmp && (pptTmp != apt)) VFREEMEM (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; 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) && (pPalEntries != (PALETTEENTRY*)NULL)) { ppalBuffer = (PALETTEENTRY *)PALLOCNOZ(cEntries * sizeof(PALETTEENTRY),'pmtG'); if (ppalBuffer == 0) { bStatus = FALSE; } else { try { ProbeForRead(pPalEntries,cEntries * sizeof(PALETTEENTRY), sizeof(BYTE)); RtlCopyMemory(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 { ppalBuffer = (PALETTEENTRY *)PALLOCNOZ(cEntries * sizeof(PALETTEENTRY),'pmtG'); if (ppalBuffer == 0) { 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 { ProbeForWrite(pPalEntries, lRetEntries * sizeof(PALETTEENTRY), sizeof(BYTE)); RtlCopyMemory(pPalEntries, ppalBuffer, lRetEntries * sizeof(PALETTEENTRY)); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(89); // SetLastError(GetExceptionCode()); lRet = 0; } } } } if (ppalBuffer != (PALETTEENTRY*)NULL) { VFREEMEM(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 ) { BOOL bStatus; ULONG ulRet = 0; SPOOLESC sescHdr; // 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,sizeof(ULONG)); RtlCopyMemory(&sescHdr,psesc,offsetof(SPOOLESC,ajData)); bStatus = TRUE; } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(90); bStatus = FALSE; } if( bStatus ) { ulRet = GreGetSpoolMessage( &sescHdr, psesc->ajData, cjMsg - offsetof(SPOOLESC,ajData), pulOut, cjOut ); if( ulRet ) { try { // probe done above RtlCopyMemory(psesc,&sescHdr,offsetof(SPOOLESC,ajData)); } except(EXCEPTION_EXECUTE_HANDLER) { WARNINGX(91); ulRet = 0; } } } } return(ulRet); } /******************************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; } // 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 { ProbeForWrite(ppfd, cjpfd, sizeof(ULONG)); RtlCopyMemory(ppfd, &pfdLocal, cjpfd); } 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() { } /******************************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 ); try { ProbeForWrite( pChWidthInfo, sizeof(CHWIDTHINFO), sizeof(BYTE) ); RtlCopyMemory( 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 // <= 2 * (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 <= MAX_PATH+1 && cjFontDir >= CJ_FONTDIR ) { ulRet = 1; __try { ProbeForRead( pwszPathname, cjPathname, sizeof(*pwszPathname) ); RtlCopyMemory( awcPathname, pwszPathname, cjPathname ); } __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 { ProbeForWrite( pjFontDir, CJ_FONTDIR, sizeof(BYTE) ); RtlCopyMemory( pjFontDir, ajFontDir, CJ_FONTDIR ); } __except(EXCEPTION_EXECUTE_HANDLER) { WARNING("NtGdiMakeFondDir: bad pjFontDir\n"); ulRet = 0; } } } } return( ulRet ); }