mirror of
https://github.com/reactos/reactos.git
synced 2024-10-30 11:35:58 +00:00
88c9e7c6e8
svn path=/branches/reactos-yarotows/; revision=47117
984 lines
21 KiB
C
984 lines
21 KiB
C
/*
|
|
* PROJECT: ReactOS win32 kernel mode subsystem
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: subsystems/win32/win32k/objects/font.c
|
|
* PURPOSE: Font
|
|
* PROGRAMMER:
|
|
*/
|
|
|
|
/** Includes ******************************************************************/
|
|
|
|
#include <win32k.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
DWORD FASTCALL GreGetGlyphIndicesW(HDC,LPWSTR,INT,LPWORD,DWORD,DWORD);
|
|
|
|
/** Internal ******************************************************************/
|
|
|
|
DWORD
|
|
FASTCALL
|
|
GreGetKerningPairs(
|
|
HDC hDC,
|
|
ULONG NumPairs,
|
|
LPKERNINGPAIR krnpair)
|
|
{
|
|
PDC dc;
|
|
PDC_ATTR pdcattr;
|
|
PTEXTOBJ TextObj;
|
|
PFONTGDI FontGDI;
|
|
DWORD Count;
|
|
KERNINGPAIR *pKP;
|
|
|
|
dc = DC_LockDc(hDC);
|
|
if (!dc)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
|
return 0;
|
|
}
|
|
|
|
pdcattr = dc->pdcattr;
|
|
TextObj = RealizeFontInit(pdcattr->hlfntNew);
|
|
DC_UnlockDc(dc);
|
|
|
|
if (!TextObj)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
|
return 0;
|
|
}
|
|
|
|
FontGDI = ObjToGDI(TextObj->Font, FONT);
|
|
TEXTOBJ_UnlockText(TextObj);
|
|
|
|
Count = ftGdiGetKerningPairs(FontGDI,0,NULL);
|
|
|
|
if ( Count && krnpair )
|
|
{
|
|
if (Count > NumPairs)
|
|
{
|
|
SetLastWin32Error(ERROR_INSUFFICIENT_BUFFER);
|
|
return 0;
|
|
}
|
|
pKP = ExAllocatePoolWithTag(PagedPool, Count * sizeof(KERNINGPAIR), TAG_GDITEXT);
|
|
if (!pKP)
|
|
{
|
|
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
|
|
return 0;
|
|
}
|
|
ftGdiGetKerningPairs(FontGDI,Count,pKP);
|
|
|
|
RtlCopyMemory(krnpair, pKP, Count * sizeof(KERNINGPAIR));
|
|
|
|
ExFreePoolWithTag(pKP,TAG_GDITEXT);
|
|
}
|
|
return Count;
|
|
}
|
|
|
|
|
|
DWORD
|
|
FASTCALL
|
|
GreGetCharacterPlacementW(
|
|
HDC hdc,
|
|
LPWSTR pwsz,
|
|
INT nCount,
|
|
INT nMaxExtent,
|
|
LPGCP_RESULTSW pgcpw,
|
|
DWORD dwFlags)
|
|
{
|
|
SIZE Size = {0,0};
|
|
|
|
if (!pgcpw)
|
|
{
|
|
if (GreGetTextExtentW( hdc, pwsz, nCount, &Size, 1))
|
|
return MAKELONG(Size.cx, Size.cy);
|
|
return 0;
|
|
}
|
|
UNIMPLEMENTED;
|
|
return 0;
|
|
}
|
|
|
|
INT
|
|
FASTCALL
|
|
FontGetObject(PTEXTOBJ TFont, INT Count, PVOID Buffer)
|
|
{
|
|
if( Buffer == NULL ) return sizeof(LOGFONTW);
|
|
|
|
switch (Count)
|
|
{
|
|
case sizeof(ENUMLOGFONTEXDVW):
|
|
RtlCopyMemory( (LPENUMLOGFONTEXDVW) Buffer,
|
|
&TFont->logfont,
|
|
sizeof(ENUMLOGFONTEXDVW));
|
|
break;
|
|
case sizeof(ENUMLOGFONTEXW):
|
|
RtlCopyMemory( (LPENUMLOGFONTEXW) Buffer,
|
|
&TFont->logfont.elfEnumLogfontEx,
|
|
sizeof(ENUMLOGFONTEXW));
|
|
break;
|
|
|
|
case sizeof(EXTLOGFONTW):
|
|
case sizeof(ENUMLOGFONTW):
|
|
RtlCopyMemory((LPENUMLOGFONTW) Buffer,
|
|
&TFont->logfont.elfEnumLogfontEx.elfLogFont,
|
|
sizeof(ENUMLOGFONTW));
|
|
break;
|
|
|
|
case sizeof(LOGFONTW):
|
|
RtlCopyMemory((LPLOGFONTW) Buffer,
|
|
&TFont->logfont.elfEnumLogfontEx.elfLogFont,
|
|
sizeof(LOGFONTW));
|
|
break;
|
|
|
|
default:
|
|
SetLastWin32Error(ERROR_BUFFER_OVERFLOW);
|
|
return 0;
|
|
}
|
|
return Count;
|
|
}
|
|
|
|
DWORD
|
|
FASTCALL
|
|
IntGetCharDimensions(HDC hdc, PTEXTMETRICW ptm, PDWORD height)
|
|
{
|
|
PDC pdc;
|
|
PDC_ATTR pdcattr;
|
|
PTEXTOBJ TextObj;
|
|
SIZE sz;
|
|
TMW_INTERNAL tmwi;
|
|
BOOL Good;
|
|
|
|
static const WCHAR alphabet[] = {
|
|
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
|
|
'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
|
|
'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
|
|
|
|
if(!ftGdiGetTextMetricsW(hdc, &tmwi)) return 0;
|
|
|
|
pdc = DC_LockDc(hdc);
|
|
|
|
if (!pdc) return 0;
|
|
|
|
pdcattr = pdc->pdcattr;
|
|
|
|
TextObj = RealizeFontInit(pdcattr->hlfntNew);
|
|
if ( !TextObj )
|
|
{
|
|
DC_UnlockDc(pdc);
|
|
return 0;
|
|
}
|
|
Good = TextIntGetTextExtentPoint(pdc, TextObj, alphabet, 52, 0, NULL, 0, &sz);
|
|
TEXTOBJ_UnlockText(TextObj);
|
|
DC_UnlockDc(pdc);
|
|
|
|
if (!Good) return 0;
|
|
if (ptm) *ptm = tmwi.TextMetric;
|
|
if (height) *height = tmwi.TextMetric.tmHeight;
|
|
|
|
return (sz.cx / 26 + 1) / 2;
|
|
}
|
|
|
|
|
|
DWORD
|
|
FASTCALL
|
|
IntGetFontLanguageInfo(PDC Dc)
|
|
{
|
|
PDC_ATTR pdcattr;
|
|
FONTSIGNATURE fontsig;
|
|
static const DWORD GCP_DBCS_MASK=0x003F0000,
|
|
GCP_DIACRITIC_MASK=0x00000000,
|
|
FLI_GLYPHS_MASK=0x00000000,
|
|
GCP_GLYPHSHAPE_MASK=0x00000040,
|
|
GCP_KASHIDA_MASK=0x00000000,
|
|
GCP_LIGATE_MASK=0x00000000,
|
|
GCP_USEKERNING_MASK=0x00000000,
|
|
GCP_REORDER_MASK=0x00000060;
|
|
|
|
DWORD result=0;
|
|
|
|
ftGdiGetTextCharsetInfo( Dc, &fontsig, 0 );
|
|
|
|
/* We detect each flag we return using a bitmask on the Codepage Bitfields */
|
|
if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
|
|
result|=GCP_DBCS;
|
|
|
|
if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
|
|
result|=GCP_DIACRITIC;
|
|
|
|
if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
|
|
result|=FLI_GLYPHS;
|
|
|
|
if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
|
|
result|=GCP_GLYPHSHAPE;
|
|
|
|
if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
|
|
result|=GCP_KASHIDA;
|
|
|
|
if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
|
|
result|=GCP_LIGATE;
|
|
|
|
if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
|
|
result|=GCP_USEKERNING;
|
|
|
|
pdcattr = Dc->pdcattr;
|
|
|
|
/* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
|
|
if ( pdcattr->lTextAlign & TA_RTLREADING )
|
|
if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
|
|
result|=GCP_REORDER;
|
|
|
|
return result;
|
|
}
|
|
|
|
PTEXTOBJ
|
|
FASTCALL
|
|
RealizeFontInit(HFONT hFont)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PTEXTOBJ pTextObj;
|
|
|
|
pTextObj = TEXTOBJ_LockText(hFont);
|
|
|
|
if ( pTextObj && !(pTextObj->fl & TEXTOBJECT_INIT))
|
|
{
|
|
Status = TextIntRealizeFont(hFont, pTextObj);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TEXTOBJ_UnlockText(pTextObj);
|
|
return NULL;
|
|
}
|
|
}
|
|
return pTextObj;
|
|
}
|
|
|
|
HFONT
|
|
FASTCALL
|
|
GreSelectFont( HDC hDC, HFONT hFont)
|
|
{
|
|
PDC pdc;
|
|
PDC_ATTR pdcattr;
|
|
PTEXTOBJ pOrgFnt, pNewFnt = NULL;
|
|
HFONT hOrgFont = NULL;
|
|
|
|
if (!hDC || !hFont) return NULL;
|
|
|
|
pdc = DC_LockDc(hDC);
|
|
if (!pdc)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (NT_SUCCESS(TextIntRealizeFont((HFONT)hFont,NULL)))
|
|
{
|
|
/* LFONTOBJ use share and locking. */
|
|
pNewFnt = TEXTOBJ_LockText(hFont);
|
|
pdcattr = pdc->pdcattr;
|
|
pOrgFnt = pdc->dclevel.plfnt;
|
|
if (pOrgFnt)
|
|
{
|
|
hOrgFont = pOrgFnt->BaseObject.hHmgr;
|
|
}
|
|
else
|
|
{
|
|
hOrgFont = pdcattr->hlfntNew;
|
|
}
|
|
pdc->dclevel.plfnt = pNewFnt;
|
|
pdc->hlfntCur = hFont;
|
|
pdcattr->hlfntNew = hFont;
|
|
pdcattr->ulDirty_ |= DIRTY_CHARSET;
|
|
pdcattr->ulDirty_ &= ~SLOW_WIDTHS;
|
|
}
|
|
|
|
if (pNewFnt) TEXTOBJ_UnlockText(pNewFnt);
|
|
DC_UnlockDc(pdc);
|
|
return hOrgFont;
|
|
}
|
|
|
|
/** Functions ******************************************************************/
|
|
|
|
INT
|
|
APIENTRY
|
|
NtGdiAddFontResourceW(
|
|
IN WCHAR *pwszFiles,
|
|
IN ULONG cwc,
|
|
IN ULONG cFiles,
|
|
IN FLONG fl,
|
|
IN DWORD dwPidTid,
|
|
IN OPTIONAL DESIGNVECTOR *pdv)
|
|
{
|
|
UNICODE_STRING SafeFileName;
|
|
PWSTR src;
|
|
NTSTATUS Status;
|
|
int Ret;
|
|
|
|
/* FIXME - Protect with SEH? */
|
|
RtlInitUnicodeString(&SafeFileName, pwszFiles);
|
|
|
|
/* Reserve for prepending '\??\' */
|
|
SafeFileName.Length += 4 * sizeof(WCHAR);
|
|
SafeFileName.MaximumLength += 4 * sizeof(WCHAR);
|
|
|
|
src = SafeFileName.Buffer;
|
|
SafeFileName.Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, SafeFileName.MaximumLength, TAG_STRING);
|
|
if(!SafeFileName.Buffer)
|
|
{
|
|
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
|
|
return 0;
|
|
}
|
|
|
|
/* Prepend '\??\' */
|
|
RtlCopyMemory(SafeFileName.Buffer, L"\\??\\", 4 * sizeof(WCHAR));
|
|
|
|
Status = MmCopyFromCaller(SafeFileName.Buffer + 4, src, SafeFileName.MaximumLength - (4 * sizeof(WCHAR)));
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING);
|
|
SetLastNtError(Status);
|
|
return 0;
|
|
}
|
|
|
|
Ret = IntGdiAddFontResource(&SafeFileName, (DWORD)fl);
|
|
|
|
ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING);
|
|
return Ret;
|
|
}
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
DWORD
|
|
APIENTRY
|
|
NtGdiGetCharacterPlacementW(
|
|
IN HDC hdc,
|
|
IN LPWSTR pwsz,
|
|
IN INT nCount,
|
|
IN INT nMaxExtent,
|
|
IN OUT LPGCP_RESULTSW pgcpw,
|
|
IN DWORD dwFlags)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtGdiGetFontData(
|
|
HDC hDC,
|
|
DWORD Table,
|
|
DWORD Offset,
|
|
LPVOID Buffer,
|
|
DWORD Size)
|
|
{
|
|
PDC Dc;
|
|
PDC_ATTR pdcattr;
|
|
HFONT hFont;
|
|
PTEXTOBJ TextObj;
|
|
PFONTGDI FontGdi;
|
|
DWORD Result = GDI_ERROR;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
if (Buffer && Size)
|
|
{
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForRead(Buffer, Size, 1);
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status)) return Result;
|
|
|
|
Dc = DC_LockDc(hDC);
|
|
if (Dc == NULL)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
|
return GDI_ERROR;
|
|
}
|
|
pdcattr = Dc->pdcattr;
|
|
|
|
hFont = pdcattr->hlfntNew;
|
|
TextObj = RealizeFontInit(hFont);
|
|
DC_UnlockDc(Dc);
|
|
|
|
if (TextObj == NULL)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
|
return GDI_ERROR;
|
|
}
|
|
|
|
FontGdi = ObjToGDI(TextObj->Font, FONT);
|
|
|
|
Result = ftGdiGetFontData(FontGdi, Table, Offset, Buffer, Size);
|
|
|
|
TEXTOBJ_UnlockText(TextObj);
|
|
|
|
return Result;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
DWORD
|
|
APIENTRY
|
|
NtGdiGetFontUnicodeRanges(
|
|
IN HDC hdc,
|
|
OUT OPTIONAL LPGLYPHSET pgs)
|
|
{
|
|
PDC pDc;
|
|
PDC_ATTR pdcattr;
|
|
HFONT hFont;
|
|
PTEXTOBJ TextObj;
|
|
PFONTGDI FontGdi;
|
|
DWORD Size = 0;
|
|
PGLYPHSET pgsSafe;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
pDc = DC_LockDc(hdc);
|
|
if (!pDc)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
|
return 0;
|
|
}
|
|
|
|
pdcattr = pDc->pdcattr;
|
|
|
|
hFont = pdcattr->hlfntNew;
|
|
TextObj = RealizeFontInit(hFont);
|
|
|
|
if ( TextObj == NULL)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
|
goto Exit;
|
|
}
|
|
FontGdi = ObjToGDI(TextObj->Font, FONT);
|
|
|
|
Size = ftGetFontUnicodeRanges( FontGdi, NULL);
|
|
|
|
if (Size && pgs)
|
|
{
|
|
pgsSafe = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
|
|
if (!pgsSafe)
|
|
{
|
|
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
|
|
Size = 0;
|
|
goto Exit;
|
|
}
|
|
|
|
Size = ftGetFontUnicodeRanges( FontGdi, pgsSafe);
|
|
|
|
if (Size)
|
|
{
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForWrite(pgs, Size, 1);
|
|
RtlCopyMemory(pgs, pgsSafe, Size);
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END
|
|
|
|
if (!NT_SUCCESS(Status)) Size = 0;
|
|
}
|
|
ExFreePoolWithTag(pgsSafe, TAG_GDITEXT);
|
|
}
|
|
Exit:
|
|
TEXTOBJ_UnlockText(TextObj);
|
|
DC_UnlockDc(pDc);
|
|
return Size;
|
|
}
|
|
|
|
ULONG
|
|
APIENTRY
|
|
NtGdiGetGlyphOutline(
|
|
IN HDC hdc,
|
|
IN WCHAR wch,
|
|
IN UINT iFormat,
|
|
OUT LPGLYPHMETRICS pgm,
|
|
IN ULONG cjBuf,
|
|
OUT OPTIONAL PVOID UnsafeBuf,
|
|
IN LPMAT2 pmat2,
|
|
IN BOOL bIgnoreRotation)
|
|
{
|
|
ULONG Ret = GDI_ERROR;
|
|
PDC dc;
|
|
PVOID pvBuf = NULL;
|
|
GLYPHMETRICS gm;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
dc = DC_LockDc(hdc);
|
|
if (!dc)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
|
return GDI_ERROR;
|
|
}
|
|
|
|
if (UnsafeBuf && cjBuf)
|
|
{
|
|
pvBuf = ExAllocatePoolWithTag(PagedPool, cjBuf, TAG_GDITEXT);
|
|
if (!pvBuf)
|
|
{
|
|
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Ret = ftGdiGetGlyphOutline( dc,
|
|
wch,
|
|
iFormat,
|
|
pgm ? &gm : NULL,
|
|
cjBuf,
|
|
pvBuf,
|
|
pmat2,
|
|
bIgnoreRotation);
|
|
|
|
if (pvBuf)
|
|
{
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForWrite(UnsafeBuf, cjBuf, 1);
|
|
RtlCopyMemory(UnsafeBuf, pvBuf, cjBuf);
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END
|
|
|
|
ExFreePoolWithTag(pvBuf, TAG_GDITEXT);
|
|
}
|
|
|
|
if (pgm)
|
|
{
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForWrite(pgm, sizeof(GLYPHMETRICS), 1);
|
|
RtlCopyMemory(pgm, &gm, sizeof(GLYPHMETRICS));
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END
|
|
}
|
|
|
|
if (! NT_SUCCESS(Status))
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
|
Ret = GDI_ERROR;
|
|
}
|
|
|
|
Exit:
|
|
DC_UnlockDc(dc);
|
|
return Ret;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtGdiGetKerningPairs(HDC hDC,
|
|
ULONG NumPairs,
|
|
LPKERNINGPAIR krnpair)
|
|
{
|
|
PDC dc;
|
|
PDC_ATTR pdcattr;
|
|
PTEXTOBJ TextObj;
|
|
PFONTGDI FontGDI;
|
|
DWORD Count;
|
|
KERNINGPAIR *pKP;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
dc = DC_LockDc(hDC);
|
|
if (!dc)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
|
return 0;
|
|
}
|
|
|
|
pdcattr = dc->pdcattr;
|
|
TextObj = RealizeFontInit(pdcattr->hlfntNew);
|
|
DC_UnlockDc(dc);
|
|
|
|
if (!TextObj)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
|
return 0;
|
|
}
|
|
|
|
FontGDI = ObjToGDI(TextObj->Font, FONT);
|
|
TEXTOBJ_UnlockText(TextObj);
|
|
|
|
Count = ftGdiGetKerningPairs(FontGDI,0,NULL);
|
|
|
|
if ( Count && krnpair )
|
|
{
|
|
if (Count > NumPairs)
|
|
{
|
|
SetLastWin32Error(ERROR_INSUFFICIENT_BUFFER);
|
|
return 0;
|
|
}
|
|
pKP = ExAllocatePoolWithTag(PagedPool, Count * sizeof(KERNINGPAIR), TAG_GDITEXT);
|
|
if (!pKP)
|
|
{
|
|
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
|
|
return 0;
|
|
}
|
|
ftGdiGetKerningPairs(FontGDI,Count,pKP);
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForWrite(krnpair, Count * sizeof(KERNINGPAIR), 1);
|
|
RtlCopyMemory(krnpair, pKP, Count * sizeof(KERNINGPAIR));
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
|
Count = 0;
|
|
}
|
|
ExFreePoolWithTag(pKP,TAG_GDITEXT);
|
|
}
|
|
return Count;
|
|
}
|
|
|
|
/*
|
|
From "Undocumented Windows 2000 Secrets" Appendix B, Table B-2, page
|
|
472, this is NtGdiGetOutlineTextMetricsInternalW.
|
|
*/
|
|
ULONG
|
|
APIENTRY
|
|
NtGdiGetOutlineTextMetricsInternalW (HDC hDC,
|
|
ULONG Data,
|
|
OUTLINETEXTMETRICW *otm,
|
|
TMDIFF *Tmd)
|
|
{
|
|
PDC dc;
|
|
PDC_ATTR pdcattr;
|
|
PTEXTOBJ TextObj;
|
|
PFONTGDI FontGDI;
|
|
HFONT hFont = 0;
|
|
ULONG Size;
|
|
OUTLINETEXTMETRICW *potm;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
dc = DC_LockDc(hDC);
|
|
if (!dc)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
|
return 0;
|
|
}
|
|
pdcattr = dc->pdcattr;
|
|
hFont = pdcattr->hlfntNew;
|
|
TextObj = RealizeFontInit(hFont);
|
|
DC_UnlockDc(dc);
|
|
if (!TextObj)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
|
return 0;
|
|
}
|
|
FontGDI = ObjToGDI(TextObj->Font, FONT);
|
|
TEXTOBJ_UnlockText(TextObj);
|
|
Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
|
|
if (!otm) return Size;
|
|
if (Size > Data)
|
|
{
|
|
SetLastWin32Error(ERROR_INSUFFICIENT_BUFFER);
|
|
return 0;
|
|
}
|
|
potm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
|
|
if (!potm)
|
|
{
|
|
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
|
|
return 0;
|
|
}
|
|
IntGetOutlineTextMetrics(FontGDI, Size, potm);
|
|
if (otm)
|
|
{
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForWrite(otm, Size, 1);
|
|
RtlCopyMemory(otm, potm, Size);
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
|
Size = 0;
|
|
}
|
|
}
|
|
ExFreePoolWithTag(potm,TAG_GDITEXT);
|
|
return Size;
|
|
}
|
|
|
|
W32KAPI
|
|
BOOL
|
|
APIENTRY
|
|
NtGdiGetFontResourceInfoInternalW(
|
|
IN LPWSTR pwszFiles,
|
|
IN ULONG cwc,
|
|
IN ULONG cFiles,
|
|
IN UINT cjIn,
|
|
OUT LPDWORD pdwBytes,
|
|
OUT LPVOID pvBuf,
|
|
IN DWORD dwType)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
DWORD dwBytes;
|
|
UNICODE_STRING SafeFileNames;
|
|
BOOL bRet = FALSE;
|
|
ULONG cbStringSize;
|
|
|
|
union
|
|
{
|
|
LOGFONTW logfontw;
|
|
WCHAR FullName[LF_FULLFACESIZE];
|
|
} Buffer;
|
|
|
|
/* FIXME: handle cFiles > 0 */
|
|
|
|
/* Check for valid dwType values
|
|
dwType == 4 seems to be handled by gdi32 only */
|
|
if (dwType == 4 || dwType > 5)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Allocate a safe unicode string buffer */
|
|
cbStringSize = cwc * sizeof(WCHAR);
|
|
SafeFileNames.MaximumLength = SafeFileNames.Length = cbStringSize - sizeof(WCHAR);
|
|
SafeFileNames.Buffer = ExAllocatePoolWithTag(PagedPool,
|
|
cbStringSize,
|
|
'RTSU');
|
|
if (!SafeFileNames.Buffer)
|
|
{
|
|
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Check buffers and copy pwszFiles to safe unicode string */
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForRead(pwszFiles, cbStringSize, 1);
|
|
ProbeForWrite(pdwBytes, sizeof(DWORD), 1);
|
|
ProbeForWrite(pvBuf, cjIn, 1);
|
|
|
|
RtlCopyMemory(SafeFileNames.Buffer, pwszFiles, cbStringSize);
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
SetLastNtError(Status);
|
|
/* Free the string buffer for the safe filename */
|
|
ExFreePoolWithTag(SafeFileNames.Buffer,'RTSU');
|
|
return FALSE;
|
|
}
|
|
|
|
/* Do the actual call */
|
|
bRet = IntGdiGetFontResourceInfo(&SafeFileNames, &Buffer, &dwBytes, dwType);
|
|
|
|
/* Check if succeeded and the buffer is big enough */
|
|
if (bRet && cjIn >= dwBytes)
|
|
{
|
|
/* Copy the data back to caller */
|
|
_SEH2_TRY
|
|
{
|
|
/* Buffers are already probed */
|
|
RtlCopyMemory(pvBuf, &Buffer, dwBytes);
|
|
*pdwBytes = dwBytes;
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
SetLastNtError(Status);
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
|
|
/* Free the string for the safe filenames */
|
|
ExFreePoolWithTag(SafeFileNames.Buffer,'RTSU');
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
BOOL
|
|
APIENTRY
|
|
NtGdiGetRealizationInfo(
|
|
IN HDC hdc,
|
|
OUT PREALIZATION_INFO pri,
|
|
IN HFONT hf)
|
|
{
|
|
PDC pDc;
|
|
PTEXTOBJ pTextObj;
|
|
PFONTGDI pFontGdi;
|
|
PDC_ATTR pdcattr;
|
|
BOOL Ret = FALSE;
|
|
INT i = 0;
|
|
REALIZATION_INFO ri;
|
|
|
|
pDc = DC_LockDc(hdc);
|
|
if (!pDc)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
|
return 0;
|
|
}
|
|
pdcattr = pDc->pdcattr;
|
|
pTextObj = RealizeFontInit(pdcattr->hlfntNew);
|
|
pFontGdi = ObjToGDI(pTextObj->Font, FONT);
|
|
TEXTOBJ_UnlockText(pTextObj);
|
|
DC_UnlockDc(pDc);
|
|
|
|
Ret = ftGdiRealizationInfo(pFontGdi, &ri);
|
|
if (Ret)
|
|
{
|
|
if (pri)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForWrite(pri, sizeof(REALIZATION_INFO), 1);
|
|
RtlCopyMemory(pri, &ri, sizeof(REALIZATION_INFO));
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
SetLastNtError(Status);
|
|
return FALSE;
|
|
}
|
|
}
|
|
do
|
|
{
|
|
if (GdiHandleTable->cfPublic[i].hf == hf)
|
|
{
|
|
GdiHandleTable->cfPublic[i].iTechnology = ri.iTechnology;
|
|
GdiHandleTable->cfPublic[i].iUniq = ri.iUniq;
|
|
GdiHandleTable->cfPublic[i].dwUnknown = ri.dwUnknown;
|
|
GdiHandleTable->cfPublic[i].dwCFCount = GdiHandleTable->dwCFCount;
|
|
GdiHandleTable->cfPublic[i].fl |= CFONT_REALIZATION;
|
|
}
|
|
i++;
|
|
}
|
|
while ( i < GDI_CFONT_MAX );
|
|
}
|
|
return Ret;
|
|
}
|
|
|
|
HFONT
|
|
APIENTRY
|
|
NtGdiHfontCreate(
|
|
IN PENUMLOGFONTEXDVW pelfw,
|
|
IN ULONG cjElfw,
|
|
IN LFTYPE lft,
|
|
IN FLONG fl,
|
|
IN PVOID pvCliData )
|
|
{
|
|
ENUMLOGFONTEXDVW SafeLogfont;
|
|
HFONT hNewFont;
|
|
PTEXTOBJ TextObj;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
/* Silence GCC warnings */
|
|
SafeLogfont.elfEnumLogfontEx.elfLogFont.lfEscapement = 0;
|
|
SafeLogfont.elfEnumLogfontEx.elfLogFont.lfOrientation = 0;
|
|
|
|
if (!pelfw)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForRead(pelfw, sizeof(ENUMLOGFONTEXDVW), 1);
|
|
RtlCopyMemory(&SafeLogfont, pelfw, sizeof(ENUMLOGFONTEXDVW));
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
TextObj = TEXTOBJ_AllocTextWithHandle();
|
|
if (!TextObj)
|
|
{
|
|
return NULL;
|
|
}
|
|
hNewFont = TextObj->BaseObject.hHmgr;
|
|
|
|
TextObj->lft = lft;
|
|
TextObj->fl = fl;
|
|
RtlCopyMemory (&TextObj->logfont, &SafeLogfont, sizeof(ENUMLOGFONTEXDVW));
|
|
|
|
if (SafeLogfont.elfEnumLogfontEx.elfLogFont.lfEscapement !=
|
|
SafeLogfont.elfEnumLogfontEx.elfLogFont.lfOrientation)
|
|
{
|
|
/* this should really depend on whether GM_ADVANCED is set */
|
|
TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation =
|
|
TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfEscapement;
|
|
}
|
|
TEXTOBJ_UnlockText(TextObj);
|
|
|
|
if (pvCliData && hNewFont)
|
|
{
|
|
// FIXME: use GDIOBJ_InsertUserData
|
|
KeEnterCriticalRegion();
|
|
{
|
|
INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)hNewFont);
|
|
PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
|
|
Entry->UserData = pvCliData;
|
|
}
|
|
KeLeaveCriticalRegion();
|
|
}
|
|
|
|
return hNewFont;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
HFONT
|
|
APIENTRY
|
|
NtGdiSelectFont(
|
|
IN HDC hDC,
|
|
IN HFONT hFont)
|
|
{
|
|
return GreSelectFont(hDC, hFont);
|
|
}
|
|
|
|
|
|
/* EOF */
|