[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"Helv", L"Tahoma" },
{ L"Helvetica", L"Liberation Sans" }, { L"Helvetica", L"Liberation Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" }, { L"Lucida Console", L"DejaVu Sans Mono" },
{ L"Microsoft Sans Serif", L"Tahoma" },
{ L"MS Sans Serif", L"Tahoma" }, { L"MS Sans Serif", L"Tahoma" },
{ L"MS Shell Dlg", L"Tahoma" }, { L"MS Shell Dlg", L"Tahoma" },
{ L"MS Shell Dlg 2", L"Tahoma" }, { L"MS Shell Dlg 2", L"Tahoma" },
@ -37,6 +38,7 @@ MUI_SUBFONT CyrillicFonts[] =
{ L"Helv", L"Tahoma" }, { L"Helv", L"Tahoma" },
{ L"Helvetica", L"Liberation Sans" }, { L"Helvetica", L"Liberation Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" }, { L"Lucida Console", L"DejaVu Sans Mono" },
{ L"Microsoft Sans Serif", L"Tahoma" },
{ L"MS Sans Serif", L"Tahoma" }, { L"MS Sans Serif", L"Tahoma" },
{ L"MS Shell Dlg", L"Tahoma" }, { L"MS Shell Dlg", L"Tahoma" },
{ L"MS Shell Dlg 2", L"Tahoma" }, { L"MS Shell Dlg 2", L"Tahoma" },
@ -63,6 +65,7 @@ MUI_SUBFONT GreekFonts[] =
{ L"Helv", L"DejaVu Sans" }, { L"Helv", L"DejaVu Sans" },
{ L"Helvetica", L"Liberation Sans" }, { L"Helvetica", L"Liberation Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" }, { L"Lucida Console", L"DejaVu Sans Mono" },
{ L"Microsoft Sans Serif", L"DejaVu Sans" },
{ L"MS Sans Serif", L"DejaVu Sans" }, { L"MS Sans Serif", L"DejaVu Sans" },
{ L"MS Shell Dlg", L"DejaVu Sans" }, { L"MS Shell Dlg", L"DejaVu Sans" },
{ L"MS Shell Dlg 2", L"DejaVu Sans" }, { L"MS Shell Dlg 2", L"DejaVu Sans" },
@ -89,6 +92,7 @@ MUI_SUBFONT HebrewFonts[] =
{ L"Helv", L"Tahoma" }, { L"Helv", L"Tahoma" },
{ L"Helvetica", L"Tahoma" }, { L"Helvetica", L"Tahoma" },
{ L"Lucida Console", L"DejaVu Sans Mono" }, { L"Lucida Console", L"DejaVu Sans Mono" },
{ L"Microsoft Sans Serif", L"Tahoma" },
{ L"MS Sans Serif", L"Tahoma" }, { L"MS Sans Serif", L"Tahoma" },
{ L"MS Shell Dlg", L"Tahoma" }, { L"MS Shell Dlg", L"Tahoma" },
{ L"MS Shell Dlg 2", L"Tahoma" }, { L"MS Shell Dlg 2", L"Tahoma" },
@ -121,6 +125,7 @@ MUI_SUBFONT ChineseSimplifiedFonts[] =
{ L"Helv", L"Droid Sans Fallback" }, { L"Helv", L"Droid Sans Fallback" },
{ L"Helvetica", L"Liberation Sans" }, { L"Helvetica", L"Liberation Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" }, { 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 Sans Serif", L"Droid Sans Fallback" },
{ L"MS Shell Dlg", L"Droid Sans Fallback" }, { L"MS Shell Dlg", L"Droid Sans Fallback" },
{ L"MS Shell Dlg 2", 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"Helv", L"Droid Sans Fallback" },
{ L"Helvetica", L"Liberation Sans" }, { L"Helvetica", L"Liberation Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" }, { 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 Sans Serif", L"Droid Sans Fallback" },
{ L"MS Shell Dlg", L"Droid Sans Fallback" }, { L"MS Shell Dlg", L"Droid Sans Fallback" },
{ L"MS Shell Dlg 2", 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"Helv", L"Droid Sans Fallback" },
{ L"Helvetica", L"Liberation Sans" }, { L"Helvetica", L"Liberation Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" }, { 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 Sans Serif", L"Droid Sans Fallback" },
{ L"MS Shell Dlg", L"Droid Sans Fallback" }, { L"MS Shell Dlg", L"Droid Sans Fallback" },
{ L"MS Shell Dlg 2", 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"Helv", L"Droid Sans Fallback" },
{ L"Helvetica", L"Liberation Sans" }, { L"Helvetica", L"Liberation Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" }, { 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 Sans Serif", L"Droid Sans Fallback" },
{ L"MS Shell Dlg", L"Droid Sans Fallback" }, { L"MS Shell Dlg", L"Droid Sans Fallback" },
{ L"MS Shell Dlg 2", 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"Helv", L"DejaVu Sans" },
{ L"Helvetica", L"DejaVu Sans" }, { L"Helvetica", L"DejaVu Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" }, { L"Lucida Console", L"DejaVu Sans Mono" },
{ L"Microsoft Sans Serif", L"DejaVu Sans" },
{ L"MS Sans Serif", L"DejaVu Sans" }, { L"MS Sans Serif", L"DejaVu Sans" },
{ L"MS Shell Dlg", L"DejaVu Sans" }, { L"MS Shell Dlg", L"DejaVu Sans" },
{ L"MS Shell Dlg 2", L"DejaVu Sans" }, { L"MS Shell Dlg 2", L"DejaVu Sans" },
@ -320,6 +329,7 @@ MUI_SUBFONT HindiFonts[] =
{ L"Helv", L"Tahoma" }, { L"Helv", L"Tahoma" },
{ L"Helvetica", L"Liberation Sans" }, { L"Helvetica", L"Liberation Sans" },
{ L"Lucida Console", L"DejaVu Sans Mono" }, { L"Lucida Console", L"DejaVu Sans Mono" },
{ L"Microsoft Sans Serif", L"FreeSans" },
{ L"MS Sans Serif", L"FreeSans" }, { L"MS Sans Serif", L"FreeSans" },
{ L"MS Shell Dlg", L"FreeSans" }, { L"MS Shell Dlg", L"FreeSans" },
{ L"MS Shell Dlg 2", 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","Helv",0x00000000,"Tahoma"
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","Helvetica",0x00000000,"Liberation Sans" 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","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 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",0x00000000,"Tahoma"
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","MS Shell Dlg 2",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); int cmp = _wcsicmp(plf1->lfFaceName, plf2->lfFaceName);
if (cmp) if (cmp)
return 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) if (dwCompareFlags & IFFCX_STYLE)
{ {
WeightDiff1 = labs(plf1->lfWeight - FW_NORMAL); WeightDiff1 = labs(plf1->lfWeight - FW_NORMAL);
@ -231,13 +238,6 @@ IntFontFamilyCompareEx(const FONTFAMILYINFO *ffi1,
if (plf1->lfItalic > plf2->lfItalic) if (plf1->lfItalic > plf2->lfItalic)
return 1; return 1;
} }
if (dwCompareFlags & IFFCX_CHARSET)
{
if (plf1->lfCharSet < plf2->lfCharSet)
return -1;
if (plf1->lfCharSet > plf2->lfCharSet)
return 1;
}
return 0; return 0;
} }
@ -267,7 +267,7 @@ IntFontFamilyListUnique(FONTFAMILYINFO *InfoList, INT nCount,
first = InfoList; first = InfoList;
last = &InfoList[nCount]; last = &InfoList[nCount];
// std::unique(first, last, IntFontFamilyCompareEx); /* std::unique(first, last, IntFontFamilyCompareEx); */
if (first == last) if (first == last)
return 0; return 0;
@ -285,60 +285,70 @@ IntFontFamilyListUnique(FONTFAMILYINFO *InfoList, INT nCount,
} }
static int FASTCALL static int FASTCALL
IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc, LPARAM lParam, IntEnumFontFamilies(HDC Dc, const LOGFONTW *LogFont, PVOID EnumProc, LPARAM lParam,
DWORD dwFlags) DWORD dwFlags)
{ {
int FontFamilyCount; int FontFamilyCount;
int FontFamilySize;
PFONTFAMILYINFO Info; PFONTFAMILYINFO Info;
int Ret = 1; int Ret = 1;
int i; int i;
ENUMLOGFONTEXA EnumLogFontExA; ENUMLOGFONTEXA EnumLogFontExA;
NEWTEXTMETRICEXA NewTextMetricExA; NEWTEXTMETRICEXA NewTextMetricExA;
LOGFONTW lfW; LOGFONTW lfW;
LONG DataSize, InfoCount;
Info = RtlAllocateHeap(GetProcessHeap(), 0, DataSize = INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO);
INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO)); Info = RtlAllocateHeap(GetProcessHeap(), 0, DataSize);
if (NULL == Info) if (Info == NULL)
{ {
return 1; return 1;
} }
/* Initialize the LOGFONT structure */
ZeroMemory(&lfW, sizeof(lfW));
if (!LogFont) if (!LogFont)
{ {
lfW.lfCharSet = DEFAULT_CHARSET; lfW.lfCharSet = DEFAULT_CHARSET;
lfW.lfPitchAndFamily = 0; }
lfW.lfFaceName[0] = 0; else
LogFont = &lfW; {
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) if (FontFamilyCount < 0)
{ {
RtlFreeHeap(GetProcessHeap(), 0, Info); RtlFreeHeap(GetProcessHeap(), 0, Info);
return 1; 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); RtlFreeHeap(GetProcessHeap(), 0, Info);
Info = RtlAllocateHeap(GetProcessHeap(), 0, DataSize = InfoCount * sizeof(FONTFAMILYINFO);
FontFamilyCount * sizeof(FONTFAMILYINFO)); Info = RtlAllocateHeap(GetProcessHeap(), 0, DataSize);
if (NULL == Info) if (Info == NULL)
{ {
return 1; return 1;
} }
FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, FontFamilySize); FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, &lfW, Info, &InfoCount);
if (FontFamilyCount < 0 || FontFamilySize < FontFamilyCount) if (FontFamilyCount < 0 || FontFamilyCount < InfoCount)
{ {
RtlFreeHeap(GetProcessHeap(), 0, Info); RtlFreeHeap(GetProcessHeap(), 0, Info);
return 1; return 1;
} }
} }
/* Sort and remove redundant information */
qsort(Info, FontFamilyCount, sizeof(*Info), IntFontFamilyCompare); 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++) for (i = 0; i < FontFamilyCount; i++)
{ {
if (dwFlags & IEFF_UNICODE) 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 * @implemented
*/ */
@ -1702,6 +1784,14 @@ CreateFontIndirectW(
CONST LOGFONTW *lplf CONST LOGFONTW *lplf
) )
{ {
#if DBG
static BOOL bDidTest = FALSE;
if (!bDidTest)
{
DoFontSystemUnittest();
bDidTest = TRUE;
}
#endif
if (lplf) if (lplf)
{ {
ENUMLOGFONTEXDVW Logfont; ENUMLOGFONTEXDVW Logfont;

View file

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

View file

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