[GDI32][NTGDI][SETUP] Fix font enumeration part 2 (#1492)

Eliminate some bugs about font enumeration. CORE-15755

- Add "Microsoft Sans Serif" font substitution.
- Fix and improve the treatment of the nominal font names.
- Split IntGetFontFamilyInfo function from NtGdiGetFontFamilyInfo.
- Add DoFontSystemUnittest function for font system unittest to GDI32.
- Call DoFontSystemUnittest function at CreateFontIndirectW first call.
This commit is contained in:
Katayama Hirofumi MZ 2019-04-11 11:46:52 +09:00 committed by GitHub
parent cfdf36e442
commit 811faed421
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 252 additions and 96 deletions

View file

@ -11,6 +11,7 @@ MUI_SUBFONT LatinFonts[] =
{ L"Helv", L"Tahoma" },
{ L"Helvetica", L"Liberation Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" },
{ L"Microsoft Sans Serif", L"Tahoma" },
{ L"MS Sans Serif", L"Tahoma" },
{ L"MS Shell Dlg", L"Tahoma" },
{ L"MS Shell Dlg 2", L"Tahoma" },
@ -37,6 +38,7 @@ MUI_SUBFONT CyrillicFonts[] =
{ L"Helv", L"Tahoma" },
{ L"Helvetica", L"Liberation Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" },
{ L"Microsoft Sans Serif", L"Tahoma" },
{ L"MS Sans Serif", L"Tahoma" },
{ L"MS Shell Dlg", L"Tahoma" },
{ L"MS Shell Dlg 2", L"Tahoma" },
@ -63,6 +65,7 @@ MUI_SUBFONT GreekFonts[] =
{ L"Helv", L"DejaVu Sans" },
{ L"Helvetica", L"Liberation Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" },
{ L"Microsoft Sans Serif", L"DejaVu Sans" },
{ L"MS Sans Serif", L"DejaVu Sans" },
{ L"MS Shell Dlg", L"DejaVu Sans" },
{ L"MS Shell Dlg 2", L"DejaVu Sans" },
@ -89,6 +92,7 @@ MUI_SUBFONT HebrewFonts[] =
{ L"Helv", L"Tahoma" },
{ L"Helvetica", L"Tahoma" },
{ L"Lucida Console", L"DejaVu Sans Mono" },
{ L"Microsoft Sans Serif", L"Tahoma" },
{ L"MS Sans Serif", L"Tahoma" },
{ L"MS Shell Dlg", L"Tahoma" },
{ L"MS Shell Dlg 2", L"Tahoma" },
@ -121,6 +125,7 @@ MUI_SUBFONT ChineseSimplifiedFonts[] =
{ L"Helv", L"Droid Sans Fallback" },
{ L"Helvetica", L"Liberation Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" },
{ L"Microsoft Sans Serif", L"Droid Sans Fallback" },
{ L"MS Sans Serif", L"Droid Sans Fallback" },
{ L"MS Shell Dlg", L"Droid Sans Fallback" },
{ L"MS Shell Dlg 2", L"Droid Sans Fallback" },
@ -163,6 +168,7 @@ MUI_SUBFONT ChineseTraditionalFonts[] =
{ L"Helv", L"Droid Sans Fallback" },
{ L"Helvetica", L"Liberation Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" },
{ L"Microsoft Sans Serif", L"Droid Sans Fallback" },
{ L"MS Sans Serif", L"Droid Sans Fallback" },
{ L"MS Shell Dlg", L"Droid Sans Fallback" },
{ L"MS Shell Dlg 2", L"Droid Sans Fallback" },
@ -206,6 +212,7 @@ MUI_SUBFONT JapaneseFonts[] =
{ L"Helv", L"Droid Sans Fallback" },
{ L"Helvetica", L"Liberation Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" },
{ L"Microsoft Sans Serif", L"Droid Sans Fallback" },
{ L"MS Sans Serif", L"Droid Sans Fallback" },
{ L"MS Shell Dlg", L"Droid Sans Fallback" },
{ L"MS Shell Dlg 2", L"Droid Sans Fallback" },
@ -250,6 +257,7 @@ MUI_SUBFONT KoreanFonts[] =
{ L"Helv", L"Droid Sans Fallback" },
{ L"Helvetica", L"Liberation Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" },
{ L"Microsoft Sans Serif", L"Droid Sans Fallback" },
{ L"MS Sans Serif", L"Droid Sans Fallback" },
{ L"MS Shell Dlg", L"Droid Sans Fallback" },
{ L"MS Shell Dlg 2", L"Droid Sans Fallback" },
@ -293,6 +301,7 @@ MUI_SUBFONT UnicodeFonts[] =
{ L"Helv", L"DejaVu Sans" },
{ L"Helvetica", L"DejaVu Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" },
{ L"Microsoft Sans Serif", L"DejaVu Sans" },
{ L"MS Sans Serif", L"DejaVu Sans" },
{ L"MS Shell Dlg", L"DejaVu Sans" },
{ L"MS Shell Dlg 2", L"DejaVu Sans" },
@ -320,6 +329,7 @@ MUI_SUBFONT HindiFonts[] =
{ L"Helv", L"Tahoma" },
{ L"Helvetica", L"Liberation Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" },
{ L"Microsoft Sans Serif", L"FreeSans" },
{ L"MS Sans Serif", L"FreeSans" },
{ L"MS Shell Dlg", L"FreeSans" },
{ L"MS Shell Dlg 2", L"FreeSans" },

View file

@ -50,6 +50,7 @@ HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","Fixedsys",0
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","Helv",0x00000000,"Tahoma"
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","Helvetica",0x00000000,"Liberation Sans"
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","Lucida Console",0x00000000,"DejaVu Sans Mono"
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","Microsoft Sans Serif",0x00000000,"Tahoma"
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","MS Sans Serif",0x00000000,"Tahoma"
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","MS Shell Dlg",0x00000000,"Tahoma"
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","MS Shell Dlg 2",0x00000000,"Tahoma"

View file

@ -218,6 +218,13 @@ IntFontFamilyCompareEx(const FONTFAMILYINFO *ffi1,
int cmp = _wcsicmp(plf1->lfFaceName, plf2->lfFaceName);
if (cmp)
return cmp;
if (dwCompareFlags & IFFCX_CHARSET)
{
if (plf1->lfCharSet < plf2->lfCharSet)
return -1;
if (plf1->lfCharSet > plf2->lfCharSet)
return 1;
}
if (dwCompareFlags & IFFCX_STYLE)
{
WeightDiff1 = labs(plf1->lfWeight - FW_NORMAL);
@ -231,13 +238,6 @@ IntFontFamilyCompareEx(const FONTFAMILYINFO *ffi1,
if (plf1->lfItalic > plf2->lfItalic)
return 1;
}
if (dwCompareFlags & IFFCX_CHARSET)
{
if (plf1->lfCharSet < plf2->lfCharSet)
return -1;
if (plf1->lfCharSet > plf2->lfCharSet)
return 1;
}
return 0;
}
@ -267,7 +267,7 @@ IntFontFamilyListUnique(FONTFAMILYINFO *InfoList, INT nCount,
first = InfoList;
last = &InfoList[nCount];
// std::unique(first, last, IntFontFamilyCompareEx);
/* std::unique(first, last, IntFontFamilyCompareEx); */
if (first == last)
return 0;
@ -285,60 +285,70 @@ IntFontFamilyListUnique(FONTFAMILYINFO *InfoList, INT nCount,
}
static int FASTCALL
IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc, LPARAM lParam,
IntEnumFontFamilies(HDC Dc, const LOGFONTW *LogFont, PVOID EnumProc, LPARAM lParam,
DWORD dwFlags)
{
int FontFamilyCount;
int FontFamilySize;
PFONTFAMILYINFO Info;
int Ret = 1;
int i;
ENUMLOGFONTEXA EnumLogFontExA;
NEWTEXTMETRICEXA NewTextMetricExA;
LOGFONTW lfW;
LONG DataSize, InfoCount;
Info = RtlAllocateHeap(GetProcessHeap(), 0,
INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO));
if (NULL == Info)
DataSize = INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO);
Info = RtlAllocateHeap(GetProcessHeap(), 0, DataSize);
if (Info == NULL)
{
return 1;
}
/* Initialize the LOGFONT structure */
ZeroMemory(&lfW, sizeof(lfW));
if (!LogFont)
{
lfW.lfCharSet = DEFAULT_CHARSET;
lfW.lfPitchAndFamily = 0;
lfW.lfFaceName[0] = 0;
LogFont = &lfW;
}
else
{
lfW.lfCharSet = LogFont->lfCharSet;
lfW.lfPitchAndFamily = LogFont->lfPitchAndFamily;
StringCbCopyW(lfW.lfFaceName, sizeof(lfW.lfFaceName), LogFont->lfFaceName);
}
FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, INITIAL_FAMILY_COUNT);
/* Retrieve the font information */
InfoCount = INITIAL_FAMILY_COUNT;
FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, &lfW, Info, &InfoCount);
if (FontFamilyCount < 0)
{
RtlFreeHeap(GetProcessHeap(), 0, Info);
return 1;
}
if (INITIAL_FAMILY_COUNT < FontFamilyCount)
/* Resize the buffer if the buffer is too small */
if (INITIAL_FAMILY_COUNT < InfoCount)
{
FontFamilySize = FontFamilyCount;
RtlFreeHeap(GetProcessHeap(), 0, Info);
Info = RtlAllocateHeap(GetProcessHeap(), 0,
FontFamilyCount * sizeof(FONTFAMILYINFO));
if (NULL == Info)
DataSize = InfoCount * sizeof(FONTFAMILYINFO);
Info = RtlAllocateHeap(GetProcessHeap(), 0, DataSize);
if (Info == NULL)
{
return 1;
}
FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, FontFamilySize);
if (FontFamilyCount < 0 || FontFamilySize < FontFamilyCount)
FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, &lfW, Info, &InfoCount);
if (FontFamilyCount < 0 || FontFamilyCount < InfoCount)
{
RtlFreeHeap(GetProcessHeap(), 0, Info);
return 1;
}
}
/* Sort and remove redundant information */
qsort(Info, FontFamilyCount, sizeof(*Info), IntFontFamilyCompare);
FontFamilyCount = IntFontFamilyListUnique(Info, FontFamilyCount, LogFont, dwFlags);
FontFamilyCount = IntFontFamilyListUnique(Info, FontFamilyCount, &lfW, dwFlags);
/* call the callback */
for (i = 0; i < FontFamilyCount; i++)
{
if (dwFlags & IEFF_UNICODE)
@ -1693,6 +1703,78 @@ CreateFontIndirectA(
}
#if DBG
VOID DumpFamilyInfo(const FONTFAMILYINFO *Info, LONG Count)
{
LONG i;
const LOGFONTW *plf;
DPRINT1("---\n");
DPRINT1("Count: %d\n", Count);
for (i = 0; i < Count; ++i)
{
plf = &Info[i].EnumLogFontEx.elfLogFont;
DPRINT1("%d: '%S',%u,'%S', %ld:%ld, %ld, %d, %d\n", i,
plf->lfFaceName, plf->lfCharSet, Info[i].EnumLogFontEx.elfFullName,
plf->lfHeight, plf->lfWidth, plf->lfWeight, plf->lfItalic, plf->lfPitchAndFamily);
}
}
VOID DoFontSystemUnittest(VOID)
{
LOGFONTW LogFont;
FONTFAMILYINFO Info[4];
UNICODE_STRING Str1, Str2;
LONG ret, InfoCount;
//DumpFontInfo(TRUE);
/* L"" DEFAULT_CHARSET */
RtlZeroMemory(&LogFont, sizeof(LogFont));
LogFont.lfCharSet = DEFAULT_CHARSET;
InfoCount = RTL_NUMBER_OF(Info);
ret = NtGdiGetFontFamilyInfo(NULL, &LogFont, Info, &InfoCount);
DPRINT1("ret: %ld, InfoCount: %ld\n", ret, InfoCount);
DumpFamilyInfo(Info, ret);
ASSERT(ret == RTL_NUMBER_OF(Info));
ASSERT(InfoCount > 32);
/* L"Microsoft Sans Serif" ANSI_CHARSET */
RtlZeroMemory(&LogFont, sizeof(LogFont));
LogFont.lfCharSet = ANSI_CHARSET;
StringCbCopyW(LogFont.lfFaceName, sizeof(LogFont.lfFaceName), L"Microsoft Sans Serif");
InfoCount = RTL_NUMBER_OF(Info);
ret = NtGdiGetFontFamilyInfo(NULL, &LogFont, Info, &InfoCount);
DPRINT1("ret: %ld, InfoCount: %ld\n", ret, InfoCount);
DumpFamilyInfo(Info, ret);
ASSERT(ret != -1);
ASSERT(InfoCount > 0);
ASSERT(InfoCount < 16);
RtlInitUnicodeString(&Str1, Info[0].EnumLogFontEx.elfLogFont.lfFaceName);
RtlInitUnicodeString(&Str2, L"Microsoft Sans Serif");
ret = RtlCompareUnicodeString(&Str1, &Str2, TRUE);
ASSERT(ret == 0);
RtlInitUnicodeString(&Str1, Info[0].EnumLogFontEx.elfFullName);
RtlInitUnicodeString(&Str2, L"Tahoma");
ret = RtlCompareUnicodeString(&Str1, &Str2, TRUE);
ASSERT(ret == 0);
/* L"Non-Existent" DEFAULT_CHARSET */
RtlZeroMemory(&LogFont, sizeof(LogFont));
LogFont.lfCharSet = ANSI_CHARSET;
StringCbCopyW(LogFont.lfFaceName, sizeof(LogFont.lfFaceName), L"Non-Existent");
InfoCount = RTL_NUMBER_OF(Info);
ret = NtGdiGetFontFamilyInfo(NULL, &LogFont, Info, &InfoCount);
DPRINT1("ret: %ld, InfoCount: %ld\n", ret, InfoCount);
DumpFamilyInfo(Info, ret);
ASSERT(ret == 0);
ASSERT(InfoCount == 0);
}
#endif
/* EOF */
/*
* @implemented
*/
@ -1702,6 +1784,14 @@ CreateFontIndirectW(
CONST LOGFONTW *lplf
)
{
#if DBG
static BOOL bDidTest = FALSE;
if (!bDidTest)
{
DoFontSystemUnittest();
bDidTest = TRUE;
}
#endif
if (lplf)
{
ENUMLOGFONTEXDVW Logfont;

View file

@ -2675,18 +2675,18 @@ FontFamilyFillInfo(PFONTFAMILYINFO Info, LPCWSTR FaceName,
}
static BOOLEAN FASTCALL
GetFontFamilyInfoForList(LPLOGFONTW LogFont,
GetFontFamilyInfoForList(const LOGFONTW *LogFont,
PFONTFAMILYINFO Info,
LPCWSTR NominalName,
DWORD *pCount,
DWORD MaxCount,
LONG *pCount,
LONG MaxCount,
PLIST_ENTRY Head)
{
PLIST_ENTRY Entry;
PFONT_ENTRY CurrentEntry;
FONTGDI *FontGDI;
FONTFAMILYINFO InfoEntry;
DWORD Count = *pCount;
LONG Count = *pCount;
for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
{
@ -2697,29 +2697,15 @@ GetFontFamilyInfoForList(LPLOGFONTW LogFont,
if (LogFont->lfCharSet != DEFAULT_CHARSET &&
LogFont->lfCharSet != FontGDI->CharSet)
{
continue;
continue; /* charset mismatch */
}
if (LogFont->lfFaceName[0] == UNICODE_NULL)
{
if (Count < MaxCount)
{
FontFamilyFillInfo(&Info[Count], NominalName, NULL, FontGDI);
}
Count++;
continue;
}
/* get one info entry */
FontFamilyFillInfo(&InfoEntry, NULL, NULL, FontGDI);
FontFamilyFillInfo(&InfoEntry, NominalName, NULL, FontGDI);
if (NominalName)
{
RtlStringCchCopyW(InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName,
RTL_NUMBER_OF(InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName),
NominalName);
}
else
if (LogFont->lfFaceName[0] != UNICODE_NULL)
{
/* check name */
if (_wcsnicmp(LogFont->lfFaceName,
InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName,
RTL_NUMBER_OF(LogFont->lfFaceName) - 1) != 0 &&
@ -2731,7 +2717,16 @@ GetFontFamilyInfoForList(LPLOGFONTW LogFont,
}
}
if (Count < MaxCount)
if (NominalName)
{
/* store the nominal name */
RtlStringCbCopyW(InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName,
sizeof(InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName),
NominalName);
}
/* store one entry to Info */
if (0 <= Count && Count < MaxCount)
{
RtlCopyMemory(&Info[Count], &InfoEntry, sizeof(InfoEntry));
}
@ -2744,10 +2739,10 @@ GetFontFamilyInfoForList(LPLOGFONTW LogFont,
}
static BOOLEAN FASTCALL
GetFontFamilyInfoForSubstitutes(LPLOGFONTW LogFont,
GetFontFamilyInfoForSubstitutes(const LOGFONTW *LogFont,
PFONTFAMILYINFO Info,
DWORD *pCount,
DWORD MaxCount)
LONG *pCount,
LONG MaxCount)
{
PLIST_ENTRY pEntry, pHead = &g_FontSubstListHead;
PFONTSUBST_ENTRY pCurrentEntry;
@ -2762,6 +2757,7 @@ GetFontFamilyInfoForSubstitutes(LPLOGFONTW LogFont,
pFromW = &pCurrentEntry->FontNames[FONTSUBST_FROM];
if (LogFont->lfFaceName[0] != UNICODE_NULL)
{
/* check name */
if (_wcsicmp(LogFont->lfFaceName, pFromW->Buffer) != 0)
continue; /* mismatch */
}
@ -2771,18 +2767,22 @@ GetFontFamilyInfoForSubstitutes(LPLOGFONTW LogFont,
pCurrentEntry->CharSets[FONTSUBST_FROM] ==
pCurrentEntry->CharSets[FONTSUBST_TO])
{
/* identical mapping */
continue;
}
/* substitute and get the real name */
IntUnicodeStringToBuffer(lf.lfFaceName, sizeof(lf.lfFaceName), pFromW);
SubstituteFontRecurse(&lf);
if (LogFont->lfCharSet != DEFAULT_CHARSET && LogFont->lfCharSet != lf.lfCharSet)
continue;
/* search in global fonts */
IntLockGlobalFonts();
GetFontFamilyInfoForList(&lf, Info, pFromW->Buffer, pCount, MaxCount, &g_FontListHead);
IntUnLockGlobalFonts();
/* search in private fonts */
IntLockProcessPrivateFonts(Win32Process);
GetFontFamilyInfoForList(&lf, Info, pFromW->Buffer, pCount, MaxCount,
&Win32Process->PrivateFontListHead);
@ -5407,41 +5407,22 @@ ftGdiGetKerningPairs( PFONTGDI Font,
// Functions needing sorting.
//
///////////////////////////////////////////////////////////////////////////
int APIENTRY
NtGdiGetFontFamilyInfo(HDC Dc,
LPLOGFONTW UnsafeLogFont,
PFONTFAMILYINFO UnsafeInfo,
DWORD Size)
LONG FASTCALL
IntGetFontFamilyInfo(HDC Dc,
const LOGFONTW *SafeLogFont,
PFONTFAMILYINFO SafeInfo,
LONG InfoCount)
{
NTSTATUS Status;
LOGFONTW LogFont;
PFONTFAMILYINFO Info;
DWORD Count;
LONG AvailCount = 0;
PPROCESSINFO Win32Process;
/* Make a safe copy */
Status = MmCopyFromCaller(&LogFont, UnsafeLogFont, sizeof(LOGFONTW));
if (! NT_SUCCESS(Status))
{
EngSetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
/* Allocate space for a safe copy */
Info = ExAllocatePoolWithTag(PagedPool, Size * sizeof(FONTFAMILYINFO), GDITAG_TEXT);
if (NULL == Info)
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return -1;
}
/* Enumerate font families in the global list */
IntLockGlobalFonts();
Count = 0;
if (! GetFontFamilyInfoForList(&LogFont, Info, NULL, &Count, Size, &g_FontListHead) )
if (!GetFontFamilyInfoForList(SafeLogFont, SafeInfo, NULL, &AvailCount,
InfoCount, &g_FontListHead))
{
IntUnLockGlobalFonts();
ExFreePoolWithTag(Info, GDITAG_TEXT);
return -1;
}
IntUnLockGlobalFonts();
@ -5449,27 +5430,102 @@ NtGdiGetFontFamilyInfo(HDC Dc,
/* Enumerate font families in the process local list */
Win32Process = PsGetCurrentProcessWin32Process();
IntLockProcessPrivateFonts(Win32Process);
if (! GetFontFamilyInfoForList(&LogFont, Info, NULL, &Count, Size,
if (!GetFontFamilyInfoForList(SafeLogFont, SafeInfo, NULL, &AvailCount, InfoCount,
&Win32Process->PrivateFontListHead))
{
IntUnLockProcessPrivateFonts(Win32Process);
ExFreePoolWithTag(Info, GDITAG_TEXT);
return -1;
}
IntUnLockProcessPrivateFonts(Win32Process);
/* Enumerate font families in the registry */
if (! GetFontFamilyInfoForSubstitutes(&LogFont, Info, &Count, Size))
if (!GetFontFamilyInfoForSubstitutes(SafeLogFont, SafeInfo, &AvailCount, InfoCount))
{
ExFreePoolWithTag(Info, GDITAG_TEXT);
return -1;
}
/* Return data to caller */
if (0 != Count)
return AvailCount;
}
LONG NTAPI
NtGdiGetFontFamilyInfo(HDC Dc,
const LOGFONTW *UnsafeLogFont,
PFONTFAMILYINFO UnsafeInfo,
LPLONG UnsafeInfoCount)
{
Status = MmCopyToCaller(UnsafeInfo, Info,
(Count < Size ? Count : Size) * sizeof(FONTFAMILYINFO));
NTSTATUS Status;
LOGFONTW LogFont;
PFONTFAMILYINFO Info;
LONG GotCount, AvailCount, DataSize, SafeInfoCount;
if (UnsafeLogFont == NULL || UnsafeInfo == NULL || UnsafeInfoCount == NULL)
{
EngSetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
Status = MmCopyFromCaller(&SafeInfoCount, UnsafeInfoCount, sizeof(SafeInfoCount));
if (!NT_SUCCESS(Status))
{
EngSetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
GotCount = 0;
Status = MmCopyToCaller(UnsafeInfoCount, &GotCount, sizeof(*UnsafeInfoCount));
if (!NT_SUCCESS(Status))
{
EngSetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
Status = MmCopyFromCaller(&LogFont, UnsafeLogFont, sizeof(LOGFONTW));
if (!NT_SUCCESS(Status))
{
EngSetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
if (SafeInfoCount <= 0)
{
EngSetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
/* Allocate space for a safe copy */
DataSize = SafeInfoCount * sizeof(FONTFAMILYINFO);
if (DataSize <= 0)
{
EngSetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
Info = ExAllocatePoolWithTag(PagedPool, DataSize, GDITAG_TEXT);
if (Info == NULL)
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return -1;
}
/* Retrieve the information */
AvailCount = IntGetFontFamilyInfo(Dc, &LogFont, Info, SafeInfoCount);
GotCount = min(AvailCount, SafeInfoCount);
SafeInfoCount = AvailCount;
/* Return data to caller */
if (GotCount > 0)
{
DataSize = GotCount * sizeof(FONTFAMILYINFO);
if (DataSize <= 0)
{
ExFreePoolWithTag(Info, GDITAG_TEXT);
EngSetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
Status = MmCopyToCaller(UnsafeInfo, Info, DataSize);
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(Info, GDITAG_TEXT);
EngSetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
Status = MmCopyToCaller(UnsafeInfoCount, &SafeInfoCount, sizeof(*UnsafeInfoCount));
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(Info, GDITAG_TEXT);
@ -5480,7 +5536,7 @@ NtGdiGetFontFamilyInfo(HDC Dc,
ExFreePoolWithTag(Info, GDITAG_TEXT);
return Count;
return GotCount;
}
FORCEINLINE

View file

@ -50,14 +50,13 @@ typedef struct tagFONTFAMILYINFO
} FONTFAMILYINFO, *PFONTFAMILYINFO;
/* Should be using NtGdiEnumFontChunk */
INT
LONG
NTAPI
NtGdiGetFontFamilyInfo(
HDC Dc,
LPLOGFONTW LogFont,
const LOGFONTW *LogFont,
PFONTFAMILYINFO Info,
DWORD Size
);
LPLONG UnsafeInfoCount);
/* Use NtGdiGetDCPoint with GdiGetViewPortExt */
BOOL APIENTRY NtGdiGetViewportExtEx(HDC hDC, LPSIZE viewportExt);