[WIN32K:NTGDI] Improve allocated resources cleanup in failure paths of IntGdiLoadFontsFromMemory().

- Use an auxiliary list where we add the new enumerated faces, for easy
  roll-back in case a failure happens during font loading. Only at the
  very end when font loading has been successfully done, the auxiliary
  list is appended to the corresponding global or per-proceess font list.

- Perform actual cleanup in case of failures.

- Introduce CleanupFontEntryEx() helper to simplify cleanup in
  IntGdiLoadFontsFromMemory() in failure paths; implement
  CleanupFontEntry() around it.

Additions:

- Perform string buffer NULL check in IntGdiAddFontResource().
- Reorder memory unmapping and section object dereferencing in
  IntGdiAddFontResource().
- Move DuplicateUnicodeString() upwards.
- Mark explicitly the Marlett font handling hacks.
This commit is contained in:
Hermès Bélusca-Maïto 2019-07-21 00:47:58 +02:00
parent eab73ad1a4
commit 3de67cec24
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0

View file

@ -5,7 +5,7 @@
* PURPOSE: FreeType font engine interface * PURPOSE: FreeType font engine interface
* PROGRAMMERS: Copyright 2001 Huw D M Davies for CodeWeavers. * PROGRAMMERS: Copyright 2001 Huw D M Davies for CodeWeavers.
* Copyright 2006 Dmitry Timoshkov for CodeWeavers. * Copyright 2006 Dmitry Timoshkov for CodeWeavers.
* Copyright 2016-2018 Katayama Hirofumi MZ. * Copyright 2016-2019 Katayama Hirofumi MZ.
*/ */
/** Includes ******************************************************************/ /** Includes ******************************************************************/
@ -52,6 +52,7 @@ FT_Library g_FreeTypeLibrary;
/* special font names */ /* special font names */
static const UNICODE_STRING g_MarlettW = RTL_CONSTANT_STRING(L"Marlett"); static const UNICODE_STRING g_MarlettW = RTL_CONSTANT_STRING(L"Marlett");
#define MARLETT_HACK_CHARSET
/* registry */ /* registry */
static UNICODE_STRING g_FontRegPath = static UNICODE_STRING g_FontRegPath =
@ -337,6 +338,33 @@ SharedFace_Release(PSHARED_FACE Ptr)
} }
static VOID FASTCALL
CleanupFontEntryEx(PFONT_ENTRY FontEntry, PFONTGDI FontGDI)
{
// PFONTGDI FontGDI = FontEntry->Font;
PSHARED_FACE SharedFace = FontGDI->SharedFace;
if (FontGDI->Filename)
ExFreePoolWithTag(FontGDI->Filename, GDITAG_PFF);
if (FontEntry->StyleName.Buffer)
RtlFreeUnicodeString(&FontEntry->StyleName);
if (FontEntry->FaceName.Buffer)
RtlFreeUnicodeString(&FontEntry->FaceName);
EngFreeMem(FontGDI);
SharedFace_Release(SharedFace);
ExFreePoolWithTag(FontEntry, TAG_FONT);
}
static __inline VOID FASTCALL
CleanupFontEntry(PFONT_ENTRY FontEntry)
{
CleanupFontEntryEx(FontEntry, FontEntry->Font);
}
static __inline void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt) static __inline void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
{ {
pt->x.value = vec->x >> 6; pt->x.value = vec->x >> 6;
@ -832,9 +860,9 @@ SubstituteFontByList(PLIST_ENTRY pHead,
} }
static VOID static VOID
IntUnicodeStringToBuffer(LPWSTR pszBuffer, USHORT cbBuffer, const UNICODE_STRING *pString) IntUnicodeStringToBuffer(LPWSTR pszBuffer, SIZE_T cbBuffer, const UNICODE_STRING *pString)
{ {
USHORT cbLength = pString->Length; SIZE_T cbLength = pString->Length;
if (cbBuffer < sizeof(UNICODE_NULL)) if (cbBuffer < sizeof(UNICODE_NULL))
return; return;
@ -846,6 +874,29 @@ IntUnicodeStringToBuffer(LPWSTR pszBuffer, USHORT cbBuffer, const UNICODE_STRING
pszBuffer[cbLength / sizeof(WCHAR)] = UNICODE_NULL; pszBuffer[cbLength / sizeof(WCHAR)] = UNICODE_NULL;
} }
static NTSTATUS
DuplicateUnicodeString(PUNICODE_STRING Source, PUNICODE_STRING Destination)
{
NTSTATUS Status = STATUS_NO_MEMORY;
UNICODE_STRING Tmp;
Tmp.Buffer = ExAllocatePoolWithTag(PagedPool, Source->MaximumLength, TAG_USTR);
if (Tmp.Buffer)
{
Tmp.MaximumLength = Source->MaximumLength;
Tmp.Length = 0;
RtlCopyUnicodeString(&Tmp, Source);
Destination->MaximumLength = Tmp.MaximumLength;
Destination->Length = Tmp.Length;
Destination->Buffer = Tmp.Buffer;
Status = STATUS_SUCCESS;
}
return Status;
}
static BOOL static BOOL
SubstituteFontRecurse(LOGFONTW* pLogFont) SubstituteFontRecurse(LOGFONTW* pLogFont)
{ {
@ -1083,9 +1134,10 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont)
{ {
FT_Error Error; FT_Error Error;
PFONT_ENTRY Entry; PFONT_ENTRY Entry;
FONT_ENTRY_MEM* PrivateEntry; PFONT_ENTRY_MEM PrivateEntry;
FONTGDI * FontGDI; PFONTGDI FontGDI;
FT_Face Face; FT_Face Face;
NTSTATUS Status;
ANSI_STRING AnsiString; ANSI_STRING AnsiString;
FT_WinFNT_HeaderRec WinFNT; FT_WinFNT_HeaderRec WinFNT;
PUNICODE_STRING pFileName = pLoadFont->pFileName; PUNICODE_STRING pFileName = pLoadFont->pFileName;
@ -1096,12 +1148,14 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont)
PSHARED_FACE SharedFace; PSHARED_FACE SharedFace;
INT iCharSet, CharSetCount; INT iCharSet, CharSetCount;
FT_Long iFace, FaceCount; FT_Long iFace, FaceCount;
LIST_ENTRY LoadedFontList;
USHORT NameLength; USHORT NameLength;
WCHAR szSize[32]; SIZE_T Length;
PWCHAR pszBuffer;
UNICODE_STRING NewString; UNICODE_STRING NewString;
USHORT Length; WCHAR szSize[32];
/* get num_faces */ /* Retrieve the number of faces */
IntLockFreeType(); IntLockFreeType();
Error = FT_New_Memory_Face(g_FreeTypeLibrary, Error = FT_New_Memory_Face(g_FreeTypeLibrary,
pLoadFont->Memory->Buffer, pLoadFont->Memory->Buffer,
@ -1121,6 +1175,17 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont)
return 0; /* failure */ return 0; /* failure */
} }
/*
* Initialize the temporary font list that needs to be appended to the
* global or per-process font table, in case font enumeration successes.
* If an error happens while loading and enumerating the fonts, this list
* is used to cleanup the allocated resources.
*/
InitializeListHead(&LoadedFontList);
/*
* Enumerate each typeface in the font.
*/
for (iFace = 0; iFace < FaceCount; ++iFace) for (iFace = 0; iFace < FaceCount; ++iFace)
{ {
Face = NULL; Face = NULL;
@ -1141,7 +1206,7 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont)
if (Error || !SharedFace) if (Error || !SharedFace)
{ {
DPRINT1("Error reading font (FT_Error: %d)\n", Error); DPRINT1("Error reading font (FT_Error: %d)\n", Error);
return 0; goto Finish; /* failure */
} }
/* os2_ulCodePageRange1 and CharSetCount and IsTrueType */ /* os2_ulCodePageRange1 and CharSetCount and IsTrueType */
@ -1165,8 +1230,16 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont)
pLoadFont->IsTrueType = FALSE; pLoadFont->IsTrueType = FALSE;
} }
/*
* Enumerate all supported character sets for the selected typeface.
*/
for (iCharSet = 0; iCharSet < CharSetCount; ++iCharSet) for (iCharSet = 0; iCharSet < CharSetCount; ++iCharSet)
{ {
/*
* Add a reference to SharedFace only when iCharSet is > 0,
* since the first reference has been already done by the
* SharedFace_Create() call above.
*/
if (iCharSet > 0) if (iCharSet > 0)
{ {
IntLockFreeType(); IntLockFreeType();
@ -1174,28 +1247,28 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont)
IntUnLockFreeType(); IntUnLockFreeType();
} }
/* allocate a FONT_ENTRY */ /* Allocate a FONT_ENTRY */
Entry = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_ENTRY), TAG_FONT); Entry = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_ENTRY), TAG_FONT);
if (!Entry) if (!Entry)
{ {
DPRINT1("Failed to allocate FONT_ENTRY\n");
SharedFace_Release(SharedFace); SharedFace_Release(SharedFace);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
DPRINT1("ERROR_NOT_ENOUGH_MEMORY\n"); goto Finish; /* failure */
return 0; /* failure */
} }
/* allocate a FONTGDI */ /* Allocate a FONTGDI */
FontGDI = EngAllocMem(FL_ZERO_MEMORY, sizeof(FONTGDI), GDITAG_RFONT); FontGDI = EngAllocMem(FL_ZERO_MEMORY, sizeof(FONTGDI), GDITAG_RFONT);
if (!FontGDI) if (!FontGDI)
{ {
DPRINT1("Failed to allocate FontGDI\n");
SharedFace_Release(SharedFace); SharedFace_Release(SharedFace);
ExFreePoolWithTag(Entry, TAG_FONT); ExFreePoolWithTag(Entry, TAG_FONT);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
DPRINT1("ERROR_NOT_ENOUGH_MEMORY\n"); goto Finish; /* failure */
return 0; /* failure */
} }
/* set face */ /* Set face */
FontGDI->SharedFace = SharedFace; FontGDI->SharedFace = SharedFace;
FontGDI->CharSet = ANSI_CHARSET; FontGDI->CharSet = ANSI_CHARSET;
FontGDI->OriginalItalic = ItalicFromStyle(Face->style_name); FontGDI->OriginalItalic = ItalicFromStyle(Face->style_name);
@ -1205,18 +1278,29 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont)
/* Entry->FaceName */ /* Entry->FaceName */
RtlInitAnsiString(&AnsiString, Face->family_name); RtlInitAnsiString(&AnsiString, Face->family_name);
RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiString, TRUE); Status = RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiString, TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to allocate Entry->FaceName\n");
CleanupFontEntryEx(Entry, FontGDI);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Finish; /* failure */
}
/* Entry->StyleName */ /* Entry->StyleName */
RtlInitUnicodeString(&Entry->StyleName, NULL);
if (Face->style_name && Face->style_name[0] && if (Face->style_name && Face->style_name[0] &&
strcmp(Face->style_name, "Regular") != 0) strcmp(Face->style_name, "Regular") != 0)
{ {
RtlInitAnsiString(&AnsiString, Face->style_name); RtlInitAnsiString(&AnsiString, Face->style_name);
RtlAnsiStringToUnicodeString(&Entry->StyleName, &AnsiString, TRUE); Status = RtlAnsiStringToUnicodeString(&Entry->StyleName, &AnsiString, TRUE);
} if (!NT_SUCCESS(Status))
else {
{ DPRINT1("Failed to allocate Entry->StyleName\n");
RtlInitUnicodeString(&Entry->StyleName, NULL); CleanupFontEntryEx(Entry, FontGDI);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Finish; /* failure */
}
} }
/* FontGDI->CharSet */ /* FontGDI->CharSet */
@ -1224,11 +1308,13 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont)
{ {
FontGDI->CharSet = IntGetCharSet(iCharSet, os2_ulCodePageRange1); FontGDI->CharSet = IntGetCharSet(iCharSet, os2_ulCodePageRange1);
#ifdef MARLETT_HACK_CHARSET
/* FIXME: CharSet is invalid on our Marlett */ /* FIXME: CharSet is invalid on our Marlett */
if (RtlEqualUnicodeString(&Entry->FaceName, &g_MarlettW, TRUE)) if (RtlEqualUnicodeString(&Entry->FaceName, &g_MarlettW, TRUE))
{ {
FontGDI->CharSet = SYMBOL_CHARSET; FontGDI->CharSet = SYMBOL_CHARSET;
} }
#endif
} }
else else
{ {
@ -1241,40 +1327,37 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont)
IntUnLockFreeType(); IntUnLockFreeType();
} }
/* set file name */ /* Set the file name */
if (pFileName) if (pFileName)
{ {
FontGDI->Filename = ExAllocatePoolWithTag(PagedPool, // TODO: Since this Filename is common to all the faces+charsets
pFileName->Length + sizeof(UNICODE_NULL), // inside the given font, it may be worth to somehow cache it
GDITAG_PFF); // only once and share it amongst all these faces+charsets.
Length = pFileName->Length + sizeof(UNICODE_NULL);
FontGDI->Filename = ExAllocatePoolWithTag(PagedPool, Length, GDITAG_PFF);
if (FontGDI->Filename == NULL) if (FontGDI->Filename == NULL)
{ {
EngFreeMem(FontGDI); DPRINT1("Failed to allocate FontGDI->Filename\n");
SharedFace_Release(SharedFace); CleanupFontEntryEx(Entry, FontGDI);
ExFreePoolWithTag(Entry, TAG_FONT);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
DPRINT1("ERROR_NOT_ENOUGH_MEMORY\n"); goto Finish; /* failure */
return 0; /* failure */
} }
IntUnicodeStringToBuffer(FontGDI->Filename, Length, pFileName);
RtlCopyMemory(FontGDI->Filename, pFileName->Buffer, pFileName->Length);
FontGDI->Filename[pFileName->Length / sizeof(WCHAR)] = UNICODE_NULL;
} }
else else
{ {
/* This is a memory font, initialize a suitable entry */
FontGDI->Filename = NULL; FontGDI->Filename = NULL;
PrivateEntry = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_ENTRY_MEM), TAG_FONT); PrivateEntry = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_ENTRY_MEM), TAG_FONT);
if (!PrivateEntry) if (!PrivateEntry)
{ {
if (FontGDI->Filename) DPRINT1("Failed to allocate PrivateEntry\n");
ExFreePoolWithTag(FontGDI->Filename, GDITAG_PFF); CleanupFontEntryEx(Entry, FontGDI);
EngFreeMem(FontGDI);
SharedFace_Release(SharedFace);
ExFreePoolWithTag(Entry, TAG_FONT);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
DPRINT1("ERROR_NOT_ENOUGH_MEMORY\n"); goto Finish; /* failure */
return 0;
} }
PrivateEntry->Entry = Entry; PrivateEntry->Entry = Entry;
@ -1292,22 +1375,7 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont)
/* Add this font resource to the font table */ /* Add this font resource to the font table */
Entry->Font = FontGDI; Entry->Font = FontGDI;
Entry->NotEnum = (Characteristics & FR_NOT_ENUM); Entry->NotEnum = (Characteristics & FR_NOT_ENUM);
InsertTailList(&LoadedFontList, &Entry->ListEntry);
if (Characteristics & FR_PRIVATE)
{
/* private font */
PPROCESSINFO Win32Process = PsGetCurrentProcessWin32Process();
IntLockProcessPrivateFonts(Win32Process);
InsertTailList(&Win32Process->PrivateFontListHead, &Entry->ListEntry);
IntUnLockProcessPrivateFonts(Win32Process);
}
else
{
/* global font */
IntLockGlobalFonts();
InsertTailList(&g_FontListHead, &Entry->ListEntry);
IntUnLockGlobalFonts();
}
DPRINT("Font loaded: %s (%s)\n", DPRINT("Font loaded: %s (%s)\n",
Face->family_name ? Face->family_name : "<NULL>", Face->family_name ? Face->family_name : "<NULL>",
@ -1317,62 +1385,77 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont)
} }
IntLockFreeType(); IntLockFreeType();
IntRequestFontSize(NULL, FontGDI, 0, 0); /* Error = */ IntRequestFontSize(NULL, FontGDI, 0, 0);
IntUnLockFreeType(); IntUnLockFreeType();
/*
* Initialize and build the registry font value entry,
* only in the case we load fonts from a file and not from memory.
*/
if (!pFileName)
continue;
NameLength = Entry->FaceName.Length; NameLength = Entry->FaceName.Length;
if (pLoadFont->RegValueName.Length == 0) if (pValueName->Length == 0)
{ {
if (FT_IS_SFNT(Face)) if (FT_IS_SFNT(Face))
{ {
RtlCreateUnicodeString(pValueName, Entry->FaceName.Buffer); Status = DuplicateUnicodeString(&Entry->FaceName, pValueName);
// TODO: Check return value
} }
else else
{ {
szSize[0] = L' '; szSize[0] = L' ';
_itow(PX2PT(FontGDI->EmHeight), &szSize[1], 10); _itow(PX2PT(FontGDI->EmHeight), szSize+1, 10);
Length = NameLength + wcslen(szSize) * sizeof(WCHAR); Length = NameLength + (wcslen(szSize) + 1) * sizeof(WCHAR);
pValueName->Length = 0; pszBuffer = ExAllocatePoolWithTag(PagedPool, Length, TAG_USTR);
pValueName->MaximumLength = Length + sizeof(WCHAR); if (pszBuffer)
pValueName->Buffer = ExAllocatePoolWithTag(PagedPool, {
pValueName->MaximumLength, RtlInitEmptyUnicodeString(pValueName, pszBuffer, (USHORT)Length);
TAG_USTR); RtlCopyUnicodeString(pValueName, &Entry->FaceName);
pValueName->Buffer[0] = UNICODE_NULL; RtlAppendUnicodeToString(pValueName, szSize);
RtlAppendUnicodeStringToString(pValueName, &Entry->FaceName); }
RtlAppendUnicodeToString(pValueName, szSize); else
{
// FIXME!
}
} }
} }
else else
{ {
if (FT_IS_SFNT(Face)) if (FT_IS_SFNT(Face))
{ {
Length = pValueName->Length + 3 * sizeof(WCHAR) + NameLength; Length = pValueName->Length + 3 * sizeof(WCHAR) + NameLength + sizeof(UNICODE_NULL);
NewString.Length = 0; pszBuffer = ExAllocatePoolWithTag(PagedPool, Length, TAG_USTR);
NewString.MaximumLength = Length + sizeof(WCHAR); if (pszBuffer)
NewString.Buffer = ExAllocatePoolWithTag(PagedPool, {
NewString.MaximumLength, RtlInitEmptyUnicodeString(&NewString, pszBuffer, (USHORT)Length);
TAG_USTR); RtlCopyUnicodeString(&NewString, pValueName);
NewString.Buffer[0] = UNICODE_NULL; RtlAppendUnicodeToString(&NewString, L" & ");
RtlAppendUnicodeStringToString(&NewString, pValueName); RtlAppendUnicodeStringToString(&NewString, &Entry->FaceName);
RtlAppendUnicodeToString(&NewString, L" & "); }
RtlAppendUnicodeStringToString(&NewString, &Entry->FaceName); else
{
// FIXME!
}
} }
else else
{ {
szSize[0] = L','; szSize[0] = L',';
szSize[1] = L' '; _itow(PX2PT(FontGDI->EmHeight), szSize+1, 10);
_itow(PX2PT(FontGDI->EmHeight), &szSize[2], 10);
Length = pValueName->Length + wcslen(szSize) * sizeof(WCHAR); Length = pValueName->Length + (wcslen(szSize) + 1) * sizeof(WCHAR);
NewString.Length = 0; pszBuffer = ExAllocatePoolWithTag(PagedPool, Length, TAG_USTR);
NewString.MaximumLength = Length + sizeof(WCHAR); if (pszBuffer)
NewString.Buffer = ExAllocatePoolWithTag(PagedPool, {
NewString.MaximumLength, RtlInitEmptyUnicodeString(&NewString, pszBuffer, (USHORT)Length);
TAG_USTR); RtlCopyUnicodeString(&NewString, pValueName);
NewString.Buffer[0] = UNICODE_NULL; RtlAppendUnicodeToString(&NewString, szSize);
RtlAppendUnicodeStringToString(&NewString, pValueName); }
RtlAppendUnicodeToString(&NewString, szSize); else
{
// FIXME!
}
} }
RtlFreeUnicodeString(pValueName); RtlFreeUnicodeString(pValueName);
@ -1380,7 +1463,77 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont)
} }
} }
return FaceCount; /* number of loaded faces */ Finish:
if (iFace == FaceCount)
{
/*
* We succeeded, append the created font entries into the correct font table.
*/
PLIST_ENTRY ListToAppend;
/* No typefaces were present */
if (FaceCount == 0)
{
ASSERT(IsListEmpty(&LoadedFontList));
return 0;
}
ASSERT(!IsListEmpty(&LoadedFontList));
/*
* Remove the temporary font list' head and reinitialize it.
* This effectively empties the list and at the same time transforms
* 'ListToAppend' into a headless list, ready to be appended to the
* suitable font table.
*/
ListToAppend = LoadedFontList.Flink;
RemoveEntryList(&LoadedFontList);
InitializeListHead(&LoadedFontList);
if (Characteristics & FR_PRIVATE)
{
/* Private font */
PPROCESSINFO Win32Process = PsGetCurrentProcessWin32Process();
IntLockProcessPrivateFonts(Win32Process);
AppendTailList(&Win32Process->PrivateFontListHead, ListToAppend);
IntUnLockProcessPrivateFonts(Win32Process);
}
else
{
/* Global font */
IntLockGlobalFonts();
AppendTailList(&g_FontListHead, ListToAppend);
IntUnLockGlobalFonts();
}
return FaceCount; /* Number of loaded faces */
}
else
{
/* We failed, cleanup the resources */
PLIST_ENTRY ListEntry;
if (pLoadFont->PrivateEntry)
{
while (!IsListEmpty(&pLoadFont->PrivateEntry->ListEntry))
{
ListEntry = RemoveHeadList(&pLoadFont->PrivateEntry->ListEntry);
PrivateEntry = CONTAINING_RECORD(ListEntry, FONT_ENTRY_MEM, ListEntry);
ExFreePoolWithTag(PrivateEntry, TAG_FONT);
}
ExFreePoolWithTag(pLoadFont->PrivateEntry, TAG_FONT);
pLoadFont->PrivateEntry = NULL;
}
while (!IsListEmpty(&LoadedFontList))
{
ListEntry = RemoveHeadList(&LoadedFontList);
Entry = CONTAINING_RECORD(ListEntry, FONT_ENTRY, ListEntry);
CleanupFontEntry(Entry);
}
return 0; /* No faces have been added */
}
} }
/* /*
@ -1400,7 +1553,7 @@ IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
SIZE_T ViewSize = 0; SIZE_T ViewSize = 0;
LARGE_INTEGER SectionSize; LARGE_INTEGER SectionSize;
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
GDI_LOAD_FONT LoadFont; GDI_LOAD_FONT LoadFont;
INT FontCount; INT FontCount;
HANDLE KeyHandle; HANDLE KeyHandle;
static const UNICODE_STRING TrueTypePostfix = RTL_CONSTANT_STRING(L" (TrueType)"); static const UNICODE_STRING TrueTypePostfix = RTL_CONSTANT_STRING(L" (TrueType)");
@ -1448,36 +1601,40 @@ IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
LoadFont.PrivateEntry = NULL; LoadFont.PrivateEntry = NULL;
FontCount = IntGdiLoadFontsFromMemory(&LoadFont); FontCount = IntGdiLoadFontsFromMemory(&LoadFont);
ObDereferenceObject(SectionObject);
/* Release our copy */ /* Release our copy */
IntLockFreeType(); IntLockFreeType();
SharedMem_Release(LoadFont.Memory); SharedMem_Release(LoadFont.Memory);
IntUnLockFreeType(); IntUnLockFreeType();
ObDereferenceObject(SectionObject);
/* Save the loaded font name into the registry */
if (FontCount > 0) if (FontCount > 0)
{ {
if (LoadFont.IsTrueType) if (LoadFont.IsTrueType)
{ {
/* append " (TrueType)" */ /* Append " (TrueType)" */
UNICODE_STRING NewString; UNICODE_STRING NewString;
USHORT Length; SIZE_T Length;
PWCHAR pszBuffer;
Length = LoadFont.RegValueName.Length + TrueTypePostfix.Length; Length = LoadFont.RegValueName.Length + TrueTypePostfix.Length + sizeof(UNICODE_NULL);
NewString.Length = 0; pszBuffer = ExAllocatePoolWithTag(PagedPool, Length, TAG_USTR);
NewString.MaximumLength = Length + sizeof(WCHAR); if (pszBuffer)
NewString.Buffer = ExAllocatePoolWithTag(PagedPool, {
NewString.MaximumLength, RtlInitEmptyUnicodeString(&NewString, pszBuffer, (USHORT)Length);
TAG_USTR); NewString.Buffer[0] = UNICODE_NULL;
NewString.Buffer[0] = UNICODE_NULL; RtlAppendUnicodeStringToString(&NewString, &LoadFont.RegValueName);
RtlAppendUnicodeStringToString(&NewString, &TrueTypePostfix);
RtlAppendUnicodeStringToString(&NewString, &LoadFont.RegValueName); RtlFreeUnicodeString(&LoadFont.RegValueName);
RtlAppendUnicodeStringToString(&NewString, &TrueTypePostfix); LoadFont.RegValueName = NewString;
RtlFreeUnicodeString(&LoadFont.RegValueName); }
LoadFont.RegValueName = NewString; else
{
// FIXME!
}
} }
/* registry */
InitializeObjectAttributes(&ObjectAttributes, &g_FontRegPath, InitializeObjectAttributes(&ObjectAttributes, &g_FontRegPath,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL, NULL); NULL, NULL);
@ -1504,26 +1661,25 @@ IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
HANDLE FASTCALL HANDLE FASTCALL
IntGdiAddFontMemResource(PVOID Buffer, DWORD dwSize, PDWORD pNumAdded) IntGdiAddFontMemResource(PVOID Buffer, DWORD dwSize, PDWORD pNumAdded)
{ {
HANDLE Ret = NULL;
GDI_LOAD_FONT LoadFont; GDI_LOAD_FONT LoadFont;
FONT_ENTRY_COLL_MEM* EntryCollection; PFONT_ENTRY_COLL_MEM EntryCollection;
INT FaceCount; INT FaceCount;
HANDLE Ret = 0;
PVOID BufferCopy = ExAllocatePoolWithTag(PagedPool, dwSize, TAG_FONT); PVOID BufferCopy = ExAllocatePoolWithTag(PagedPool, dwSize, TAG_FONT);
if (!BufferCopy) if (!BufferCopy)
{ {
*pNumAdded = 0; *pNumAdded = 0;
return NULL; return NULL;
} }
memcpy(BufferCopy, Buffer, dwSize); RtlCopyMemory(BufferCopy, Buffer, dwSize);
LoadFont.pFileName = NULL; LoadFont.pFileName = NULL;
LoadFont.Memory = SharedMem_Create(BufferCopy, dwSize, FALSE); LoadFont.Memory = SharedMem_Create(BufferCopy, dwSize, FALSE);
LoadFont.Characteristics = FR_PRIVATE | FR_NOT_ENUM; LoadFont.Characteristics = FR_PRIVATE | FR_NOT_ENUM;
RtlInitUnicodeString(&LoadFont.RegValueName, NULL); RtlInitUnicodeString(&LoadFont.RegValueName, NULL);
LoadFont.IsTrueType = FALSE; LoadFont.IsTrueType = FALSE;
LoadFont.PrivateEntry = NULL; LoadFont.PrivateEntry = NULL;
FaceCount = IntGdiLoadFontsFromMemory(&LoadFont); FaceCount = IntGdiLoadFontsFromMemory(&LoadFont);
RtlFreeUnicodeString(&LoadFont.RegValueName); RtlFreeUnicodeString(&LoadFont.RegValueName);
@ -1554,20 +1710,6 @@ IntGdiAddFontMemResource(PVOID Buffer, DWORD dwSize, PDWORD pNumAdded)
// FIXME: Add RemoveFontResource // FIXME: Add RemoveFontResource
static VOID FASTCALL
CleanupFontEntry(PFONT_ENTRY FontEntry)
{
PFONTGDI FontGDI = FontEntry->Font;
PSHARED_FACE SharedFace = FontGDI->SharedFace;
if (FontGDI->Filename)
ExFreePoolWithTag(FontGDI->Filename, GDITAG_PFF);
EngFreeMem(FontGDI);
SharedFace_Release(SharedFace);
ExFreePoolWithTag(FontEntry, TAG_FONT);
}
VOID FASTCALL VOID FASTCALL
IntGdiCleanupMemEntry(PFONT_ENTRY_MEM Head) IntGdiCleanupMemEntry(PFONT_ENTRY_MEM Head)
{ {
@ -2352,29 +2494,6 @@ SwapEndian(LPVOID pvData, DWORD Size)
} }
} }
static NTSTATUS
DuplicateUnicodeString(PUNICODE_STRING Source, PUNICODE_STRING Destination)
{
NTSTATUS Status = STATUS_NO_MEMORY;
UNICODE_STRING Tmp;
Tmp.Buffer = ExAllocatePoolWithTag(PagedPool, Source->MaximumLength, TAG_USTR);
if (Tmp.Buffer)
{
Tmp.MaximumLength = Source->MaximumLength;
Tmp.Length = 0;
RtlCopyUnicodeString(&Tmp, Source);
Destination->MaximumLength = Tmp.MaximumLength;
Destination->Length = Tmp.Length;
Destination->Buffer = Tmp.Buffer;
Status = STATUS_SUCCESS;
}
return Status;
}
static NTSTATUS static NTSTATUS
IntGetFontLocalizedName(PUNICODE_STRING pNameW, PSHARED_FACE SharedFace, IntGetFontLocalizedName(PUNICODE_STRING pNameW, PSHARED_FACE SharedFace,
FT_UShort NameID, FT_UShort LangID) FT_UShort NameID, FT_UShort LangID)
@ -4429,6 +4548,8 @@ GetFontPenalty(const LOGFONTW * LogFont,
/* FIXME: FaceNameSubst Penalty 500 */ /* FIXME: FaceNameSubst Penalty 500 */
Byte = LogFont->lfCharSet; Byte = LogFont->lfCharSet;
#ifdef MARLETT_HACK_CHARSET
if (Byte == DEFAULT_CHARSET) if (Byte == DEFAULT_CHARSET)
{ {
if (_wcsicmp(LogFont->lfFaceName, L"Marlett") == 0) if (_wcsicmp(LogFont->lfFaceName, L"Marlett") == 0)
@ -4441,6 +4562,7 @@ GetFontPenalty(const LOGFONTW * LogFont,
Byte = SYMBOL_CHARSET; Byte = SYMBOL_CHARSET;
} }
} }
#endif
if (Byte != TM->tmCharSet) if (Byte != TM->tmCharSet)
{ {
@ -6442,7 +6564,7 @@ NtGdiExtTextOutW(
/* Probe and copy the string */ /* Probe and copy the string */
ProbeForRead(UnsafeString, StringSize, 1); ProbeForRead(UnsafeString, StringSize, 1);
memcpy((PVOID)SafeString, UnsafeString, StringSize); RtlCopyMemory((PVOID)SafeString, UnsafeString, StringSize);
/* If we have Dx values... */ /* If we have Dx values... */
if (UnsafeDx) if (UnsafeDx)
@ -6450,7 +6572,7 @@ NtGdiExtTextOutW(
/* ... probe and copy them */ /* ... probe and copy them */
SafeDx = Buffer; SafeDx = Buffer;
ProbeForRead(UnsafeDx, DxSize, 1); ProbeForRead(UnsafeDx, DxSize, 1);
memcpy(SafeDx, UnsafeDx, DxSize); RtlCopyMemory(SafeDx, UnsafeDx, DxSize);
} }
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)