[WIN32SS] Implement NtGdiAddFontMemResourceEx and NtGdiRemoveFontMemResourceEx. CORE-13046

svn path=/trunk/; revision=74285
This commit is contained in:
Mark Jansen
2017-04-08 17:32:45 +00:00
parent bc6b7e2b35
commit ba121aaf83
7 changed files with 285 additions and 83 deletions
-28
View File
@@ -835,22 +835,6 @@ NtGdiAddRemoteFontToDC(
return 0;
}
/*
* @unimplemented
*/
HANDLE
APIENTRY
NtGdiAddFontMemResourceEx(
IN PVOID pvBuffer,
IN DWORD cjBuffer,
IN DESIGNVECTOR *pdv,
IN ULONG cjDV,
OUT DWORD *pNumFonts)
{
UNIMPLEMENTED;
return NULL;
}
/*
* @unimplemented
*/
@@ -1326,18 +1310,6 @@ NtGdiGetStringBitmapW(
return 0;
}
/*
* @unimplemented
*/
BOOL
APIENTRY
NtGdiRemoveFontMemResourceEx(
IN HANDLE hMMFont)
{
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
+65
View File
@@ -478,6 +478,71 @@ NtGdiAddFontResourceW(
return Ret;
}
HANDLE
APIENTRY
NtGdiAddFontMemResourceEx(
IN PVOID pvBuffer,
IN DWORD cjBuffer,
IN DESIGNVECTOR *pdv,
IN ULONG cjDV,
OUT DWORD *pNumFonts)
{
_SEH2_VOLATILE PVOID Buffer = NULL;
HANDLE Ret;
DWORD NumFonts = 0;
DPRINT("NtGdiAddFontMemResourceEx\n");
DBG_UNREFERENCED_PARAMETER(pdv);
DBG_UNREFERENCED_PARAMETER(cjDV);
if (!pvBuffer || !cjBuffer)
return NULL;
_SEH2_TRY
{
ProbeForRead(pvBuffer, cjBuffer, sizeof(BYTE));
Buffer = ExAllocatePoolWithQuotaTag(PagedPool, cjBuffer, TAG_FONT);
RtlCopyMemory(Buffer, pvBuffer, cjBuffer);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
if (Buffer != NULL)
{
ExFreePoolWithTag(Buffer, TAG_FONT);
}
_SEH2_YIELD(return NULL);
}
_SEH2_END;
Ret = IntGdiAddFontMemResource(Buffer, cjBuffer, &NumFonts);
ExFreePoolWithTag(Buffer, TAG_FONT);
_SEH2_TRY
{
ProbeForWrite(pNumFonts, sizeof(NumFonts), 1);
*pNumFonts = NumFonts;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Leak it? */
_SEH2_YIELD(return NULL);
}
_SEH2_END;
return Ret;
}
BOOL
APIENTRY
NtGdiRemoveFontMemResourceEx(
IN HANDLE hMMFont)
{
return IntGdiRemoveFontMemResource(hMMFont);
}
/*
* @unimplemented
*/
+64
View File
@@ -0,0 +1,64 @@
#pragma once
typedef struct _FONT_ENTRY
{
LIST_ENTRY ListEntry;
FONTGDI *Font;
UNICODE_STRING FaceName;
BYTE NotEnum;
} FONT_ENTRY, *PFONT_ENTRY;
typedef struct _FONT_ENTRY_MEM
{
LIST_ENTRY ListEntry;
FONT_ENTRY *Entry;
} FONT_ENTRY_MEM, *PFONT_ENTRY_MEM;
typedef struct _FONT_ENTRY_COLL_MEM
{
LIST_ENTRY ListEntry;
UINT Handle;
FONT_ENTRY_MEM *Entry;
} FONT_ENTRY_COLL_MEM, *PFONT_ENTRY_COLL_MEM;
typedef struct _FONT_CACHE_ENTRY
{
LIST_ENTRY ListEntry;
int GlyphIndex;
FT_Face Face;
FT_BitmapGlyph BitmapGlyph;
int Height;
MATRIX mxWorldToDevice;
} FONT_CACHE_ENTRY, *PFONT_CACHE_ENTRY;
/*
* FONTSUBST_... --- constants for font substitutes
*/
#define FONTSUBST_FROM 0
#define FONTSUBST_TO 1
#define FONTSUBST_FROM_AND_TO 2
/*
* FONTSUBST_ENTRY --- font substitute entry
*/
typedef struct FONTSUBST_ENTRY
{
LIST_ENTRY ListEntry;
UNICODE_STRING FontNames[FONTSUBST_FROM_AND_TO];
BYTE CharSets[FONTSUBST_FROM_AND_TO];
} FONTSUBST_ENTRY, *PFONTSUBST_ENTRY;
typedef struct GDI_LOAD_FONT
{
PUNICODE_STRING pFileName;
PVOID Buffer;
ULONG BufferSize;
DWORD Characteristics;
UNICODE_STRING RegValueName;
BOOL IsTrueType;
PFONT_ENTRY_MEM PrivateEntry;
} GDI_LOAD_FONT, *PGDI_LOAD_FONT;
+149 -55
View File
@@ -31,6 +31,7 @@
#include FT_INTERNAL_TRUETYPE_TYPES_H
#include <gdi/eng/floatobj.h>
#include "font.h"
#define NDEBUG
#include <debug.h>
@@ -90,13 +91,6 @@ SharedFace_Release(PSHARED_FACE Ptr)
}
}
typedef struct _FONT_ENTRY
{
LIST_ENTRY ListEntry;
FONTGDI *Font;
UNICODE_STRING FaceName;
BYTE NotEnum;
} FONT_ENTRY, *PFONT_ENTRY;
/* The FreeType library is not thread safe, so we have
to serialize access to it */
@@ -120,15 +114,6 @@ static BOOL RenderingEnabled = TRUE;
#define MAX_FONT_CACHE 256
typedef struct _FONT_CACHE_ENTRY
{
LIST_ENTRY ListEntry;
int GlyphIndex;
FT_Face Face;
FT_BitmapGlyph BitmapGlyph;
int Height;
MATRIX mxWorldToDevice;
} FONT_CACHE_ENTRY, *PFONT_CACHE_ENTRY;
static LIST_ENTRY FontCacheListHead;
static UINT FontCacheNumEntries;
@@ -201,23 +186,6 @@ static const CHARSETINFO FontTci[MAXTCIINDEX] =
{ SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
};
/*
* FONTSUBST_... --- constants for font substitutes
*/
#define FONTSUBST_FROM 0
#define FONTSUBST_TO 1
#define FONTSUBST_FROM_AND_TO 2
/*
* FONTSUBST_ENTRY --- font substitute entry
*/
typedef struct FONTSUBST_ENTRY
{
LIST_ENTRY ListEntry;
UNICODE_STRING FontNames[FONTSUBST_FROM_AND_TO];
BYTE CharSets[FONTSUBST_FROM_AND_TO];
} FONTSUBST_ENTRY, *PFONTSUBST_ENTRY;
/* list head */
static RTL_STATIC_LIST_HEAD(FontSubstListHead);
@@ -695,22 +663,13 @@ WeightFromStyle(const char *style_name)
return FW_NORMAL;
}
typedef struct GDI_LOAD_FONT
{
PUNICODE_STRING pFileName;
PVOID Buffer;
ULONG BufferSize;
DWORD Characteristics;
UNICODE_STRING RegValueName;
BOOL IsTrueType;
} GDI_LOAD_FONT, *PGDI_LOAD_FONT;
static INT FASTCALL
IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont,
PSHARED_FACE SharedFace, FT_Long FontIndex, INT CharSetIndex)
{
FT_Error Error;
PFONT_ENTRY Entry;
FONT_ENTRY_MEM* PrivateEntry = NULL;
FONTGDI * FontGDI;
NTSTATUS Status;
FT_Face Face;
@@ -780,19 +739,48 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont,
}
/* set file name */
FontGDI->Filename = ExAllocatePoolWithTag(PagedPool,
pFileName->Length + sizeof(UNICODE_NULL),
GDITAG_PFF);
if (FontGDI->Filename == NULL)
if (pFileName)
{
EngFreeMem(FontGDI);
SharedFace_Release(SharedFace);
ExFreePoolWithTag(Entry, TAG_FONT);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0; /* failure */
FontGDI->Filename = ExAllocatePoolWithTag(PagedPool,
pFileName->Length + sizeof(UNICODE_NULL),
GDITAG_PFF);
if (FontGDI->Filename == NULL)
{
EngFreeMem(FontGDI);
SharedFace_Release(SharedFace);
ExFreePoolWithTag(Entry, TAG_FONT);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0; /* failure */
}
RtlCopyMemory(FontGDI->Filename, pFileName->Buffer, pFileName->Length);
FontGDI->Filename[pFileName->Length / sizeof(WCHAR)] = UNICODE_NULL;
}
else
{
FontGDI->Filename = NULL;
PrivateEntry = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_ENTRY_MEM), TAG_FONT);
if (!PrivateEntry)
{
if (FontGDI->Filename)
ExFreePoolWithTag(FontGDI->Filename, GDITAG_PFF);
EngFreeMem(FontGDI);
SharedFace_Release(SharedFace);
ExFreePoolWithTag(Entry, TAG_FONT);
return 0;
}
PrivateEntry->Entry = Entry;
if (pLoadFont->PrivateEntry)
{
InsertTailList(&pLoadFont->PrivateEntry->ListEntry, &PrivateEntry->ListEntry);
}
else
{
InitializeListHead(&PrivateEntry->ListEntry);
pLoadFont->PrivateEntry = PrivateEntry;
}
}
RtlCopyMemory(FontGDI->Filename, pFileName->Buffer, pFileName->Length);
FontGDI->Filename[pFileName->Length / sizeof(WCHAR)] = UNICODE_NULL;
/* set face */
FontGDI->SharedFace = SharedFace;
@@ -806,7 +794,20 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont,
Status = RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE);
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(FontGDI->Filename, GDITAG_PFF);
if (PrivateEntry)
{
if (pLoadFont->PrivateEntry == PrivateEntry)
{
pLoadFont->PrivateEntry = NULL;
}
else
{
RemoveEntryList(&PrivateEntry->ListEntry);
}
ExFreePoolWithTag(PrivateEntry, TAG_FONT);
}
if (FontGDI->Filename)
ExFreePoolWithTag(FontGDI->Filename, GDITAG_PFF);
EngFreeMem(FontGDI);
SharedFace_Release(SharedFace);
ExFreePoolWithTag(Entry, TAG_FONT);
@@ -1010,6 +1011,7 @@ IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
LoadFont.Characteristics = Characteristics;
RtlInitUnicodeString(&LoadFont.RegValueName, NULL);
LoadFont.IsTrueType = FALSE;
LoadFont.PrivateEntry = NULL;
FontCount = IntGdiLoadFontsFromMemory(&LoadFont, NULL, -1, -1);
ObDereferenceObject(SectionObject);
@@ -1060,8 +1062,100 @@ IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
return FontCount;
}
HANDLE FASTCALL
IntGdiAddFontMemResource(PVOID Buffer, DWORD dwSize, PDWORD pNumAdded)
{
GDI_LOAD_FONT LoadFont;
FONT_ENTRY_COLL_MEM* EntryCollection;
INT FontCount;
HANDLE Ret = 0;
LoadFont.pFileName = NULL;
LoadFont.Buffer = Buffer;
LoadFont.BufferSize = dwSize;
LoadFont.Characteristics = FR_PRIVATE | FR_NOT_ENUM;
RtlInitUnicodeString(&LoadFont.RegValueName, NULL);
LoadFont.IsTrueType = FALSE;
LoadFont.PrivateEntry = NULL;
FontCount = IntGdiLoadFontsFromMemory(&LoadFont, NULL, -1, -1);
RtlFreeUnicodeString(&LoadFont.RegValueName);
*pNumAdded = FontCount;
if (FontCount > 0)
{
EntryCollection = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_ENTRY_COLL_MEM), TAG_FONT);
if (EntryCollection)
{
PPROCESSINFO Win32Process = PsGetCurrentProcessWin32Process();
EntryCollection->Entry = LoadFont.PrivateEntry;
IntLockProcessPrivateFonts(Win32Process);
EntryCollection->Handle = ++Win32Process->PrivateMemFontHandleCount;
InsertTailList(&Win32Process->PrivateMemFontListHead, &EntryCollection->ListEntry);
IntUnLockProcessPrivateFonts(Win32Process);
Ret = (HANDLE)EntryCollection->Handle;
}
}
return Ret;
}
// FIXME: Add RemoveFontResource
VOID FASTCALL
IntGdiCleanupMemEntry(PFONT_ENTRY_MEM Head)
{
PLIST_ENTRY Entry;
PFONT_ENTRY_MEM FontEntry;
while (!IsListEmpty(&Head->ListEntry))
{
Entry = RemoveHeadList(&Head->ListEntry);
FontEntry = CONTAINING_RECORD(Entry, FONT_ENTRY_MEM, ListEntry);
// Delete FontEntry->Entry (FONT_ENTRY*)
ExFreePoolWithTag(FontEntry, TAG_FONT);
}
// Delete Head->Entry (FONT_ENTRY*)
ExFreePoolWithTag(Head, TAG_FONT);
}
BOOL FASTCALL
IntGdiRemoveFontMemResource(HANDLE hMMFont)
{
PLIST_ENTRY Entry;
PFONT_ENTRY_COLL_MEM CurrentEntry;
PFONT_ENTRY_COLL_MEM EntryCollection = NULL;
PPROCESSINFO Win32Process = PsGetCurrentProcessWin32Process();
IntLockProcessPrivateFonts(Win32Process);
Entry = Win32Process->PrivateMemFontListHead.Flink;
while (Entry != &Win32Process->PrivateMemFontListHead)
{
CurrentEntry = CONTAINING_RECORD(Entry, FONT_ENTRY_COLL_MEM, ListEntry);
if (CurrentEntry->Handle == (UINT)hMMFont)
{
EntryCollection = CurrentEntry;
RemoveEntryList(Entry);
break;
}
Entry = Entry->Flink;
}
IntUnLockProcessPrivateFonts(Win32Process);
if (EntryCollection)
{
IntGdiCleanupMemEntry(EntryCollection->Entry);
ExFreePoolWithTag(EntryCollection, TAG_FONT);
return TRUE;
}
return FALSE;
}
BOOL FASTCALL
IntIsFontRenderingEnabled(VOID)
{
+2
View File
@@ -21,6 +21,8 @@ GdiProcessCreate(PEPROCESS Process)
ASSERT(ppiCurrent);
InitializeListHead(&ppiCurrent->PrivateFontListHead);
InitializeListHead(&ppiCurrent->PrivateMemFontListHead);
ppiCurrent->PrivateMemFontHandleCount = 0;
ExInitializeFastMutex(&ppiCurrent->PrivateFontListLock);
InitializeListHead(&ppiCurrent->GDIBrushAttrFreeList);
+2
View File
@@ -113,6 +113,8 @@ VOID FASTCALL IntEnableFontRendering(BOOL Enable);
ULONG FASTCALL FontGetObject(PTEXTOBJ TextObj, ULONG Count, PVOID Buffer);
VOID FASTCALL IntLoadSystemFonts(VOID);
INT FASTCALL IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics);
HANDLE FASTCALL IntGdiAddFontMemResource(PVOID Buffer, DWORD dwSize, PDWORD pNumAdded);
BOOL FASTCALL IntGdiRemoveFontMemResource(HANDLE hMMFont);
ULONG FASTCALL ftGdiGetGlyphOutline(PDC,WCHAR,UINT,LPGLYPHMETRICS,ULONG,PVOID,LPMAT2,BOOL);
INT FASTCALL IntGetOutlineTextMetrics(PFONTGDI,UINT,OUTLINETEXTMETRICW *);
BOOL FASTCALL TextIntUpdateSize(PDC,PTEXTOBJ,PFONTGDI,BOOL);
+3
View File
@@ -273,6 +273,9 @@ typedef struct _PROCESSINFO
/* ReactOS */
FAST_MUTEX PrivateFontListLock;
LIST_ENTRY PrivateFontListHead;
LIST_ENTRY PrivateMemFontListHead;
UINT PrivateMemFontHandleCount;
FAST_MUTEX DriverObjListLock;
LIST_ENTRY DriverObjListHead;
W32HEAP_USER_MAPPING HeapMappings;